summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/ffmpeg/COPYING504
-rw-r--r--contrib/ffmpeg/CREDITS47
-rw-r--r--contrib/ffmpeg/Changelog389
-rw-r--r--contrib/ffmpeg/Doxyfile1038
-rw-r--r--contrib/ffmpeg/INSTALL14
-rw-r--r--contrib/ffmpeg/MAINTAINERS243
-rw-r--r--contrib/ffmpeg/Makefile241
-rw-r--r--contrib/ffmpeg/README19
-rw-r--r--contrib/ffmpeg/berrno.h44
-rwxr-xr-xcontrib/ffmpeg/build_avopt9
-rwxr-xr-xcontrib/ffmpeg/clean-diff11
-rw-r--r--contrib/ffmpeg/cmdutils.c141
-rw-r--r--contrib/ffmpeg/cmdutils.h34
-rw-r--r--contrib/ffmpeg/common.mak100
-rwxr-xr-xcontrib/ffmpeg/configure2186
-rw-r--r--contrib/ffmpeg/cws2fws.c127
-rw-r--r--contrib/ffmpeg/doc/Makefile20
-rw-r--r--contrib/ffmpeg/doc/TODO82
-rw-r--r--contrib/ffmpeg/doc/faq.texi312
-rw-r--r--contrib/ffmpeg/doc/ffmpeg-doc.texi1607
-rw-r--r--contrib/ffmpeg/doc/ffmpeg_powerpc_performance_evaluation_howto.txt172
-rw-r--r--contrib/ffmpeg/doc/ffplay-doc.texi104
-rw-r--r--contrib/ffmpeg/doc/ffserver-doc.texi224
-rw-r--r--contrib/ffmpeg/doc/ffserver.conf349
-rw-r--r--contrib/ffmpeg/doc/hooks.texi113
-rw-r--r--contrib/ffmpeg/doc/optimization.txt158
-rw-r--r--contrib/ffmpeg/doc/soc.txt24
-rwxr-xr-xcontrib/ffmpeg/doc/texi2pod.pl427
-rw-r--r--contrib/ffmpeg/ffinstall.nsi75
-rw-r--r--contrib/ffmpeg/ffmpeg.c3973
-rw-r--r--contrib/ffmpeg/ffplay.c2488
-rw-r--r--contrib/ffmpeg/ffserver.c4602
-rw-r--r--contrib/ffmpeg/ffserver.h8
-rw-r--r--contrib/ffmpeg/libavcodec/4xm.c759
-rw-r--r--contrib/ffmpeg/libavcodec/8bps.c236
-rw-r--r--contrib/ffmpeg/libavcodec/Makefile456
-rw-r--r--contrib/ffmpeg/libavcodec/a52dec.c257
-rw-r--r--contrib/ffmpeg/libavcodec/aasc.c176
-rw-r--r--contrib/ffmpeg/libavcodec/ac3.h65
-rw-r--r--contrib/ffmpeg/libavcodec/ac3dec.c184
-rw-r--r--contrib/ffmpeg/libavcodec/ac3enc.c1557
-rw-r--r--contrib/ffmpeg/libavcodec/ac3tab.h205
-rw-r--r--contrib/ffmpeg/libavcodec/adpcm.c1370
-rw-r--r--contrib/ffmpeg/libavcodec/adx.c412
-rw-r--r--contrib/ffmpeg/libavcodec/alac.c859
-rw-r--r--contrib/ffmpeg/libavcodec/allcodecs.c289
-rw-r--r--contrib/ffmpeg/libavcodec/alpha/asm.h191
-rw-r--r--contrib/ffmpeg/libavcodec/alpha/dsputil_alpha.c362
-rw-r--r--contrib/ffmpeg/libavcodec/alpha/dsputil_alpha_asm.S285
-rw-r--r--contrib/ffmpeg/libavcodec/alpha/motion_est_alpha.c345
-rw-r--r--contrib/ffmpeg/libavcodec/alpha/motion_est_mvi_asm.S185
-rw-r--r--contrib/ffmpeg/libavcodec/alpha/mpegvideo_alpha.c147
-rw-r--r--contrib/ffmpeg/libavcodec/alpha/regdef.h66
-rw-r--r--contrib/ffmpeg/libavcodec/alpha/simple_idct_alpha.c308
-rw-r--r--contrib/ffmpeg/libavcodec/amr.c715
-rw-r--r--contrib/ffmpeg/libavcodec/apiexample.c457
-rw-r--r--contrib/ffmpeg/libavcodec/armv4l/dsputil_arm.c262
-rw-r--r--contrib/ffmpeg/libavcodec/armv4l/dsputil_arm_s.S696
-rw-r--r--contrib/ffmpeg/libavcodec/armv4l/dsputil_iwmmxt.c188
-rw-r--r--contrib/ffmpeg/libavcodec/armv4l/dsputil_iwmmxt_rnd.h1114
-rw-r--r--contrib/ffmpeg/libavcodec/armv4l/jrevdct_arm.S386
-rw-r--r--contrib/ffmpeg/libavcodec/armv4l/mathops.h49
-rw-r--r--contrib/ffmpeg/libavcodec/armv4l/mpegvideo_arm.c33
-rw-r--r--contrib/ffmpeg/libavcodec/armv4l/mpegvideo_iwmmxt.c119
-rw-r--r--contrib/ffmpeg/libavcodec/armv4l/simple_idct_arm.S487
-rw-r--r--contrib/ffmpeg/libavcodec/armv4l/simple_idct_armv5te.S718
-rw-r--r--contrib/ffmpeg/libavcodec/asv1.c655
-rw-r--r--contrib/ffmpeg/libavcodec/audioconvert.c79
-rw-r--r--contrib/ffmpeg/libavcodec/avcodec.h2707
-rw-r--r--contrib/ffmpeg/libavcodec/avs.c160
-rw-r--r--contrib/ffmpeg/libavcodec/beosthread.c182
-rw-r--r--contrib/ffmpeg/libavcodec/bfin/dsputil_bfin.c55
-rw-r--r--contrib/ffmpeg/libavcodec/bitstream.c254
-rw-r--r--contrib/ffmpeg/libavcodec/bitstream.h956
-rw-r--r--contrib/ffmpeg/libavcodec/bitstream_filter.c284
-rw-r--r--contrib/ffmpeg/libavcodec/bmp.c254
-rw-r--r--contrib/ffmpeg/libavcodec/bytestream.h89
-rw-r--r--contrib/ffmpeg/libavcodec/cabac.c265
-rw-r--r--contrib/ffmpeg/libavcodec/cabac.h859
-rw-r--r--contrib/ffmpeg/libavcodec/cavs.c1540
-rw-r--r--contrib/ffmpeg/libavcodec/cavsdata.h643
-rw-r--r--contrib/ffmpeg/libavcodec/cavsdsp.c546
-rw-r--r--contrib/ffmpeg/libavcodec/cinepak.c453
-rw-r--r--contrib/ffmpeg/libavcodec/cljr.c158
-rw-r--r--contrib/ffmpeg/libavcodec/cook.c1312
-rw-r--r--contrib/ffmpeg/libavcodec/cookdata.h559
-rw-r--r--contrib/ffmpeg/libavcodec/cscd.c264
-rw-r--r--contrib/ffmpeg/libavcodec/cyuv.c190
-rw-r--r--contrib/ffmpeg/libavcodec/dct-test.c535
-rw-r--r--contrib/ffmpeg/libavcodec/dpcm.c335
-rw-r--r--contrib/ffmpeg/libavcodec/dsicinav.c362
-rw-r--r--contrib/ffmpeg/libavcodec/dsputil.c4156
-rw-r--r--contrib/ffmpeg/libavcodec/dsputil.h778
-rw-r--r--contrib/ffmpeg/libavcodec/dtsdec.c320
-rw-r--r--contrib/ffmpeg/libavcodec/dv.c1265
-rw-r--r--contrib/ffmpeg/libavcodec/dvbsub.c445
-rw-r--r--contrib/ffmpeg/libavcodec/dvbsubdec.c1633
-rw-r--r--contrib/ffmpeg/libavcodec/dvdata.h2724
-rw-r--r--contrib/ffmpeg/libavcodec/dvdsubdec.c477
-rw-r--r--contrib/ffmpeg/libavcodec/dvdsubenc.c247
-rw-r--r--contrib/ffmpeg/libavcodec/error_resilience.c1030
-rw-r--r--contrib/ffmpeg/libavcodec/eval.c466
-rw-r--r--contrib/ffmpeg/libavcodec/eval.h84
-rw-r--r--contrib/ffmpeg/libavcodec/faac.c133
-rw-r--r--contrib/ffmpeg/libavcodec/faad.c334
-rw-r--r--contrib/ffmpeg/libavcodec/faandct.c220
-rw-r--r--contrib/ffmpeg/libavcodec/faandct.h33
-rw-r--r--contrib/ffmpeg/libavcodec/fdctref.c158
-rw-r--r--contrib/ffmpeg/libavcodec/fft-test.c297
-rw-r--r--contrib/ffmpeg/libavcodec/fft.c262
-rw-r--r--contrib/ffmpeg/libavcodec/ffv1.c1040
-rw-r--r--contrib/ffmpeg/libavcodec/flac.c752
-rw-r--r--contrib/ffmpeg/libavcodec/flacenc.c1371
-rw-r--r--contrib/ffmpeg/libavcodec/flashsv.c276
-rw-r--r--contrib/ffmpeg/libavcodec/flicvideo.c754
-rw-r--r--contrib/ffmpeg/libavcodec/fraps.c398
-rw-r--r--contrib/ffmpeg/libavcodec/g726.c429
-rw-r--r--contrib/ffmpeg/libavcodec/gif.c350
-rw-r--r--contrib/ffmpeg/libavcodec/gifdec.c339
-rw-r--r--contrib/ffmpeg/libavcodec/golomb.c156
-rw-r--r--contrib/ffmpeg/libavcodec/golomb.h479
-rw-r--r--contrib/ffmpeg/libavcodec/h261.c1055
-rw-r--r--contrib/ffmpeg/libavcodec/h261data.h157
-rw-r--r--contrib/ffmpeg/libavcodec/h263.c6294
-rw-r--r--contrib/ffmpeg/libavcodec/h263data.h308
-rw-r--r--contrib/ffmpeg/libavcodec/h263dec.c913
-rw-r--r--contrib/ffmpeg/libavcodec/h264.c8655
-rw-r--r--contrib/ffmpeg/libavcodec/h264data.h1314
-rw-r--r--contrib/ffmpeg/libavcodec/h264idct.c168
-rw-r--r--contrib/ffmpeg/libavcodec/huffyuv.c1290
-rw-r--r--contrib/ffmpeg/libavcodec/i386/cavsdsp_mmx.c518
-rw-r--r--contrib/ffmpeg/libavcodec/i386/cputest.c126
-rw-r--r--contrib/ffmpeg/libavcodec/i386/dsputil_h264_template_mmx.c326
-rw-r--r--contrib/ffmpeg/libavcodec/i386/dsputil_mmx.c3534
-rw-r--r--contrib/ffmpeg/libavcodec/i386/dsputil_mmx_avg.h870
-rw-r--r--contrib/ffmpeg/libavcodec/i386/dsputil_mmx_rnd.h592
-rw-r--r--contrib/ffmpeg/libavcodec/i386/fdct_mmx.c566
-rw-r--r--contrib/ffmpeg/libavcodec/i386/fft_3dn.c125
-rw-r--r--contrib/ffmpeg/libavcodec/i386/fft_3dn2.c210
-rw-r--r--contrib/ffmpeg/libavcodec/i386/fft_sse.c247
-rw-r--r--contrib/ffmpeg/libavcodec/i386/h264dsp_mmx.c1513
-rw-r--r--contrib/ffmpeg/libavcodec/i386/idct_mmx.c597
-rw-r--r--contrib/ffmpeg/libavcodec/i386/idct_mmx_xvid.c535
-rw-r--r--contrib/ffmpeg/libavcodec/i386/mathops.h41
-rw-r--r--contrib/ffmpeg/libavcodec/i386/mmx.h283
-rw-r--r--contrib/ffmpeg/libavcodec/i386/motion_est_mmx.c408
-rw-r--r--contrib/ffmpeg/libavcodec/i386/mpegvideo_mmx.c725
-rw-r--r--contrib/ffmpeg/libavcodec/i386/mpegvideo_mmx_template.c348
-rw-r--r--contrib/ffmpeg/libavcodec/i386/simple_idct_mmx.c1294
-rw-r--r--contrib/ffmpeg/libavcodec/i386/snowdsp_mmx.c921
-rw-r--r--contrib/ffmpeg/libavcodec/i386/vp3dsp_mmx.c324
-rw-r--r--contrib/ffmpeg/libavcodec/i386/vp3dsp_sse2.c827
-rw-r--r--contrib/ffmpeg/libavcodec/idcinvideo.c272
-rw-r--r--contrib/ffmpeg/libavcodec/imc.c813
-rw-r--r--contrib/ffmpeg/libavcodec/imcdata.h164
-rw-r--r--contrib/ffmpeg/libavcodec/imgconvert.c2842
-rw-r--r--contrib/ffmpeg/libavcodec/imgconvert_template.h875
-rw-r--r--contrib/ffmpeg/libavcodec/imgresample.c947
-rw-r--r--contrib/ffmpeg/libavcodec/indeo2.c221
-rw-r--r--contrib/ffmpeg/libavcodec/indeo2data.h134
-rw-r--r--contrib/ffmpeg/libavcodec/indeo3.c1153
-rw-r--r--contrib/ffmpeg/libavcodec/indeo3data.h2335
-rw-r--r--contrib/ffmpeg/libavcodec/interplayvideo.c964
-rw-r--r--contrib/ffmpeg/libavcodec/jfdctfst.c338
-rw-r--r--contrib/ffmpeg/libavcodec/jfdctint.c406
-rw-r--r--contrib/ffmpeg/libavcodec/jpeg_ls.c855
-rw-r--r--contrib/ffmpeg/libavcodec/jrevdct.c1159
-rw-r--r--contrib/ffmpeg/libavcodec/kmvc.c417
-rw-r--r--contrib/ffmpeg/libavcodec/lcl.c928
-rw-r--r--contrib/ffmpeg/libavcodec/liba52/a52.h73
-rw-r--r--contrib/ffmpeg/libavcodec/liba52/a52_internal.h162
-rw-r--r--contrib/ffmpeg/libavcodec/liba52/a52_util.h32
-rw-r--r--contrib/ffmpeg/libavcodec/liba52/bit_allocate.c260
-rw-r--r--contrib/ffmpeg/libavcodec/liba52/bitstream.c91
-rw-r--r--contrib/ffmpeg/libavcodec/liba52/bitstream.h77
-rw-r--r--contrib/ffmpeg/libavcodec/liba52/crc.c73
-rw-r--r--contrib/ffmpeg/libavcodec/liba52/downmix.c679
-rw-r--r--contrib/ffmpeg/libavcodec/liba52/imdct.c411
-rw-r--r--contrib/ffmpeg/libavcodec/liba52/mm_accel.h42
-rw-r--r--contrib/ffmpeg/libavcodec/liba52/parse.c939
-rw-r--r--contrib/ffmpeg/libavcodec/liba52/resample.c63
-rw-r--r--contrib/ffmpeg/libavcodec/liba52/resample_c.c203
-rw-r--r--contrib/ffmpeg/libavcodec/liba52/resample_mmx.c537
-rw-r--r--contrib/ffmpeg/libavcodec/liba52/tables.h246
-rw-r--r--contrib/ffmpeg/libavcodec/libgsm.c97
-rw-r--r--contrib/ffmpeg/libavcodec/loco.c287
-rw-r--r--contrib/ffmpeg/libavcodec/lzo.c226
-rw-r--r--contrib/ffmpeg/libavcodec/lzo.h35
-rw-r--r--contrib/ffmpeg/libavcodec/lzw.c262
-rw-r--r--contrib/ffmpeg/libavcodec/lzw.h49
-rw-r--r--contrib/ffmpeg/libavcodec/mace.c456
-rw-r--r--contrib/ffmpeg/libavcodec/mathops.h69
-rw-r--r--contrib/ffmpeg/libavcodec/mdct.c177
-rw-r--r--contrib/ffmpeg/libavcodec/mdec.c270
-rw-r--r--contrib/ffmpeg/libavcodec/mjpeg.c2625
-rw-r--r--contrib/ffmpeg/libavcodec/mlib/dsputil_mlib.c464
-rw-r--r--contrib/ffmpeg/libavcodec/mmvideo.c206
-rw-r--r--contrib/ffmpeg/libavcodec/motion_est.c2114
-rw-r--r--contrib/ffmpeg/libavcodec/motion_est_template.c1166
-rw-r--r--contrib/ffmpeg/libavcodec/motion_test.c159
-rw-r--r--contrib/ffmpeg/libavcodec/mp3lameaudio.c221
-rw-r--r--contrib/ffmpeg/libavcodec/mpeg12.c3493
-rw-r--r--contrib/ffmpeg/libavcodec/mpeg12data.h469
-rw-r--r--contrib/ffmpeg/libavcodec/mpeg4data.h423
-rw-r--r--contrib/ffmpeg/libavcodec/mpegaudio.c801
-rw-r--r--contrib/ffmpeg/libavcodec/mpegaudio.h106
-rw-r--r--contrib/ffmpeg/libavcodec/mpegaudiodec.c2879
-rw-r--r--contrib/ffmpeg/libavcodec/mpegaudiodectab.h795
-rw-r--r--contrib/ffmpeg/libavcodec/mpegaudiotab.h111
-rw-r--r--contrib/ffmpeg/libavcodec/mpegvideo.c6903
-rw-r--r--contrib/ffmpeg/libavcodec/mpegvideo.h928
-rw-r--r--contrib/ffmpeg/libavcodec/msmpeg4.c1938
-rw-r--r--contrib/ffmpeg/libavcodec/msmpeg4data.h2028
-rw-r--r--contrib/ffmpeg/libavcodec/msrle.c309
-rw-r--r--contrib/ffmpeg/libavcodec/msvideo1.c349
-rw-r--r--contrib/ffmpeg/libavcodec/nuv.c216
-rw-r--r--contrib/ffmpeg/libavcodec/oggvorbis.c381
-rw-r--r--contrib/ffmpeg/libavcodec/opt.c381
-rw-r--r--contrib/ffmpeg/libavcodec/opt.h83
-rw-r--r--contrib/ffmpeg/libavcodec/os2thread.c147
-rw-r--r--contrib/ffmpeg/libavcodec/parser.c860
-rw-r--r--contrib/ffmpeg/libavcodec/parser.h63
-rw-r--r--contrib/ffmpeg/libavcodec/pcm.c548
-rw-r--r--contrib/ffmpeg/libavcodec/png.c968
-rw-r--r--contrib/ffmpeg/libavcodec/pnm.c606
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/dsputil_altivec.c1591
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/dsputil_altivec.h106
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/dsputil_ppc.c325
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/dsputil_ppc.h155
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/fdct_altivec.c493
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/fft_altivec.c166
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/float_altivec.c194
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/gcc_fixes.h119
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/gmc_altivec.c146
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/h264_altivec.c438
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/h264_template_altivec.c719
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/idct_altivec.c237
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/mathops.h33
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/mpegvideo_altivec.c603
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/mpegvideo_ppc.c87
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/snow_altivec.c788
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/types_altivec.h41
-rw-r--r--contrib/ffmpeg/libavcodec/ppc/vc1dsp_altivec.c338
-rw-r--r--contrib/ffmpeg/libavcodec/ps2/dsputil_mmi.c163
-rw-r--r--contrib/ffmpeg/libavcodec/ps2/idct_mmi.c363
-rw-r--r--contrib/ffmpeg/libavcodec/ps2/mmi.h172
-rw-r--r--contrib/ffmpeg/libavcodec/ps2/mpegvideo_mmi.c89
-rw-r--r--contrib/ffmpeg/libavcodec/pthread.c170
-rw-r--r--contrib/ffmpeg/libavcodec/qdm2.c2042
-rw-r--r--contrib/ffmpeg/libavcodec/qdm2data.h530
-rw-r--r--contrib/ffmpeg/libavcodec/qdrw.c160
-rw-r--r--contrib/ffmpeg/libavcodec/qpeg.c324
-rw-r--r--contrib/ffmpeg/libavcodec/qtrle.c630
-rw-r--r--contrib/ffmpeg/libavcodec/ra144.c519
-rw-r--r--contrib/ffmpeg/libavcodec/ra144.h2428
-rw-r--r--contrib/ffmpeg/libavcodec/ra288.c258
-rw-r--r--contrib/ffmpeg/libavcodec/ra288.h205
-rw-r--r--contrib/ffmpeg/libavcodec/rangecoder.c181
-rw-r--r--contrib/ffmpeg/libavcodec/rangecoder.h127
-rw-r--r--contrib/ffmpeg/libavcodec/ratecontrol.c944
-rw-r--r--contrib/ffmpeg/libavcodec/ratecontrol.h103
-rw-r--r--contrib/ffmpeg/libavcodec/raw.c210
-rw-r--r--contrib/ffmpeg/libavcodec/resample.c249
-rw-r--r--contrib/ffmpeg/libavcodec/resample2.c274
-rw-r--r--contrib/ffmpeg/libavcodec/roqvideo.c474
-rw-r--r--contrib/ffmpeg/libavcodec/rpza.c292
-rw-r--r--contrib/ffmpeg/libavcodec/rtjpeg.c165
-rw-r--r--contrib/ffmpeg/libavcodec/rtjpeg.h39
-rw-r--r--contrib/ffmpeg/libavcodec/rv10.c803
-rw-r--r--contrib/ffmpeg/libavcodec/sh4/dsputil_align.c430
-rw-r--r--contrib/ffmpeg/libavcodec/sh4/dsputil_sh4.c120
-rw-r--r--contrib/ffmpeg/libavcodec/sh4/idct_sh4.c366
-rw-r--r--contrib/ffmpeg/libavcodec/sh4/qpel.c1600
-rw-r--r--contrib/ffmpeg/libavcodec/shorten.c533
-rw-r--r--contrib/ffmpeg/libavcodec/simple_idct.c587
-rw-r--r--contrib/ffmpeg/libavcodec/simple_idct.h38
-rw-r--r--contrib/ffmpeg/libavcodec/smacker.c723
-rw-r--r--contrib/ffmpeg/libavcodec/smc.c493
-rw-r--r--contrib/ffmpeg/libavcodec/snow.c4686
-rw-r--r--contrib/ffmpeg/libavcodec/snow.h176
-rw-r--r--contrib/ffmpeg/libavcodec/sonic.c981
-rw-r--r--contrib/ffmpeg/libavcodec/sp5x.h332
-rw-r--r--contrib/ffmpeg/libavcodec/sparc/dsputil_vis.c4090
-rw-r--r--contrib/ffmpeg/libavcodec/sparc/vis.h327
-rw-r--r--contrib/ffmpeg/libavcodec/svq1.c1431
-rw-r--r--contrib/ffmpeg/libavcodec/svq1_cb.h1580
-rw-r--r--contrib/ffmpeg/libavcodec/svq1_vlc.h281
-rw-r--r--contrib/ffmpeg/libavcodec/svq3.c1014
-rw-r--r--contrib/ffmpeg/libavcodec/targa.c254
-rw-r--r--contrib/ffmpeg/libavcodec/tiertexseqv.c232
-rw-r--r--contrib/ffmpeg/libavcodec/tiff.c531
-rw-r--r--contrib/ffmpeg/libavcodec/truemotion1.c923
-rw-r--r--contrib/ffmpeg/libavcodec/truemotion1data.h829
-rw-r--r--contrib/ffmpeg/libavcodec/truemotion2.c893
-rw-r--r--contrib/ffmpeg/libavcodec/truespeech.c381
-rw-r--r--contrib/ffmpeg/libavcodec/truespeech_data.h157
-rw-r--r--contrib/ffmpeg/libavcodec/tscc.c348
-rw-r--r--contrib/ffmpeg/libavcodec/tta.c446
-rw-r--r--contrib/ffmpeg/libavcodec/ulti.c428
-rw-r--r--contrib/ffmpeg/libavcodec/ulti_cb.h4119
-rw-r--r--contrib/ffmpeg/libavcodec/utils.c1331
-rw-r--r--contrib/ffmpeg/libavcodec/vc1.c4370
-rw-r--r--contrib/ffmpeg/libavcodec/vc1acdata.h585
-rw-r--r--contrib/ffmpeg/libavcodec/vc1data.h652
-rw-r--r--contrib/ffmpeg/libavcodec/vc1dsp.c463
-rw-r--r--contrib/ffmpeg/libavcodec/vcr1.c190
-rw-r--r--contrib/ffmpeg/libavcodec/vmdav.c572
-rw-r--r--contrib/ffmpeg/libavcodec/vmnc.c525
-rw-r--r--contrib/ffmpeg/libavcodec/vorbis.c1814
-rw-r--r--contrib/ffmpeg/libavcodec/vorbis.h43
-rw-r--r--contrib/ffmpeg/libavcodec/vorbis_data.c2155
-rw-r--r--contrib/ffmpeg/libavcodec/vorbis_enc.c1087
-rw-r--r--contrib/ffmpeg/libavcodec/vorbis_enc_data.h498
-rw-r--r--contrib/ffmpeg/libavcodec/vp3.c2659
-rw-r--r--contrib/ffmpeg/libavcodec/vp3data.h3178
-rw-r--r--contrib/ffmpeg/libavcodec/vp3dsp.c225
-rw-r--r--contrib/ffmpeg/libavcodec/vp5.c290
-rw-r--r--contrib/ffmpeg/libavcodec/vp56.c665
-rw-r--r--contrib/ffmpeg/libavcodec/vp56.h248
-rw-r--r--contrib/ffmpeg/libavcodec/vp56data.c66
-rw-r--r--contrib/ffmpeg/libavcodec/vp56data.h248
-rw-r--r--contrib/ffmpeg/libavcodec/vp5data.h173
-rw-r--r--contrib/ffmpeg/libavcodec/vp6.c522
-rw-r--r--contrib/ffmpeg/libavcodec/vp6data.h292
-rw-r--r--contrib/ffmpeg/libavcodec/vqavideo.c625
-rw-r--r--contrib/ffmpeg/libavcodec/w32thread.c136
-rw-r--r--contrib/ffmpeg/libavcodec/wavpack.c556
-rw-r--r--contrib/ffmpeg/libavcodec/wmadata.h1433
-rw-r--r--contrib/ffmpeg/libavcodec/wmadec.c1337
-rw-r--r--contrib/ffmpeg/libavcodec/wmv2.c855
-rw-r--r--contrib/ffmpeg/libavcodec/wnv1.c146
-rw-r--r--contrib/ffmpeg/libavcodec/ws-snd1.c144
-rw-r--r--contrib/ffmpeg/libavcodec/x264.c299
-rw-r--r--contrib/ffmpeg/libavcodec/xan.c492
-rw-r--r--contrib/ffmpeg/libavcodec/xl.c140
-rw-r--r--contrib/ffmpeg/libavcodec/xvid_internal.h32
-rw-r--r--contrib/ffmpeg/libavcodec/xvid_rc.c148
-rw-r--r--contrib/ffmpeg/libavcodec/xvidff.c768
-rw-r--r--contrib/ffmpeg/libavcodec/xvmcvideo.c318
-rw-r--r--contrib/ffmpeg/libavcodec/zmbv.c692
-rw-r--r--contrib/ffmpeg/libavformat/4xm.c331
-rw-r--r--contrib/ffmpeg/libavformat/Makefile197
-rw-r--r--contrib/ffmpeg/libavformat/adtsenc.c123
-rw-r--r--contrib/ffmpeg/libavformat/aiff.c436
-rw-r--r--contrib/ffmpeg/libavformat/allformats.c182
-rw-r--r--contrib/ffmpeg/libavformat/allformats.h176
-rw-r--r--contrib/ffmpeg/libavformat/amr.c201
-rw-r--r--contrib/ffmpeg/libavformat/asf-enc.c866
-rw-r--r--contrib/ffmpeg/libavformat/asf.c951
-rw-r--r--contrib/ffmpeg/libavformat/asf.h285
-rw-r--r--contrib/ffmpeg/libavformat/au.c209
-rw-r--r--contrib/ffmpeg/libavformat/audio.c352
-rw-r--r--contrib/ffmpeg/libavformat/avformat.h539
-rw-r--r--contrib/ffmpeg/libavformat/avi.h39
-rw-r--r--contrib/ffmpeg/libavformat/avidec.c989
-rw-r--r--contrib/ffmpeg/libavformat/avienc.c580
-rw-r--r--contrib/ffmpeg/libavformat/avio.c192
-rw-r--r--contrib/ffmpeg/libavformat/avio.h201
-rw-r--r--contrib/ffmpeg/libavformat/aviobuf.c790
-rw-r--r--contrib/ffmpeg/libavformat/avisynth.c222
-rw-r--r--contrib/ffmpeg/libavformat/avs.c227
-rw-r--r--contrib/ffmpeg/libavformat/barpainet.h45
-rw-r--r--contrib/ffmpeg/libavformat/base64.c231
-rw-r--r--contrib/ffmpeg/libavformat/base64.h24
-rw-r--r--contrib/ffmpeg/libavformat/beosaudio.cpp465
-rw-r--r--contrib/ffmpeg/libavformat/crc.c98
-rw-r--r--contrib/ffmpeg/libavformat/cutils.c275
-rw-r--r--contrib/ffmpeg/libavformat/daud.c58
-rw-r--r--contrib/ffmpeg/libavformat/dc1394.c193
-rw-r--r--contrib/ffmpeg/libavformat/dsicin.c224
-rw-r--r--contrib/ffmpeg/libavformat/dv.c451
-rw-r--r--contrib/ffmpeg/libavformat/dv.h37
-rw-r--r--contrib/ffmpeg/libavformat/dv1394.c240
-rw-r--r--contrib/ffmpeg/libavformat/dv1394.h357
-rw-r--r--contrib/ffmpeg/libavformat/dvenc.c407
-rw-r--r--contrib/ffmpeg/libavformat/electronicarts.c291
-rw-r--r--contrib/ffmpeg/libavformat/ffm.c792
-rw-r--r--contrib/ffmpeg/libavformat/file.c140
-rw-r--r--contrib/ffmpeg/libavformat/flic.c221
-rw-r--r--contrib/ffmpeg/libavformat/flvdec.c259
-rw-r--r--contrib/ffmpeg/libavformat/flvenc.c284
-rw-r--r--contrib/ffmpeg/libavformat/framehook.c121
-rw-r--r--contrib/ffmpeg/libavformat/framehook.h50
-rw-r--r--contrib/ffmpeg/libavformat/gif.c419
-rw-r--r--contrib/ffmpeg/libavformat/gifdec.c593
-rw-r--r--contrib/ffmpeg/libavformat/grab.c860
-rw-r--r--contrib/ffmpeg/libavformat/grab_bktr.c330
-rw-r--r--contrib/ffmpeg/libavformat/gxf.c525
-rw-r--r--contrib/ffmpeg/libavformat/gxf.h34
-rw-r--r--contrib/ffmpeg/libavformat/gxfenc.c829
-rw-r--r--contrib/ffmpeg/libavformat/http.c289
-rw-r--r--contrib/ffmpeg/libavformat/idcin.c301
-rw-r--r--contrib/ffmpeg/libavformat/idroq.c291
-rw-r--r--contrib/ffmpeg/libavformat/img.c400
-rw-r--r--contrib/ffmpeg/libavformat/img2.c425
-rw-r--r--contrib/ffmpeg/libavformat/ipmovie.c625
-rw-r--r--contrib/ffmpeg/libavformat/isom.c131
-rw-r--r--contrib/ffmpeg/libavformat/isom.h38
-rw-r--r--contrib/ffmpeg/libavformat/jpeg.c240
-rw-r--r--contrib/ffmpeg/libavformat/libnut.c283
-rw-r--r--contrib/ffmpeg/libavformat/matroska.c2767
-rw-r--r--contrib/ffmpeg/libavformat/mm.c212
-rw-r--r--contrib/ffmpeg/libavformat/mmf.c331
-rw-r--r--contrib/ffmpeg/libavformat/mov.c1798
-rw-r--r--contrib/ffmpeg/libavformat/movenc.c1724
-rw-r--r--contrib/ffmpeg/libavformat/mp3.c430
-rw-r--r--contrib/ffmpeg/libavformat/mpeg.c1824
-rw-r--r--contrib/ffmpeg/libavformat/mpegts.c1527
-rw-r--r--contrib/ffmpeg/libavformat/mpegts.h63
-rw-r--r--contrib/ffmpeg/libavformat/mpegtsenc.c676
-rw-r--r--contrib/ffmpeg/libavformat/mpjpeg.c67
-rw-r--r--contrib/ffmpeg/libavformat/mtv.c187
-rw-r--r--contrib/ffmpeg/libavformat/mxf.c1082
-rw-r--r--contrib/ffmpeg/libavformat/nsvdec.c763
-rw-r--r--contrib/ffmpeg/libavformat/nut.c1457
-rw-r--r--contrib/ffmpeg/libavformat/nut.h97
-rw-r--r--contrib/ffmpeg/libavformat/nutdec.c889
-rw-r--r--contrib/ffmpeg/libavformat/nuv.c241
-rw-r--r--contrib/ffmpeg/libavformat/ogg.c283
-rw-r--r--contrib/ffmpeg/libavformat/ogg2.c697
-rw-r--r--contrib/ffmpeg/libavformat/ogg2.h85
-rw-r--r--contrib/ffmpeg/libavformat/oggparseflac.c82
-rw-r--r--contrib/ffmpeg/libavformat/oggparseogm.c166
-rw-r--r--contrib/ffmpeg/libavformat/oggparsetheora.c129
-rw-r--r--contrib/ffmpeg/libavformat/oggparsevorbis.c205
-rw-r--r--contrib/ffmpeg/libavformat/os_support.c96
-rw-r--r--contrib/ffmpeg/libavformat/os_support.h53
-rw-r--r--contrib/ffmpeg/libavformat/png.c889
-rw-r--r--contrib/ffmpeg/libavformat/pnm.c478
-rw-r--r--contrib/ffmpeg/libavformat/psxstr.c364
-rw-r--r--contrib/ffmpeg/libavformat/qtpalette.h295
-rw-r--r--contrib/ffmpeg/libavformat/raw.c843
-rw-r--r--contrib/ffmpeg/libavformat/riff.c468
-rw-r--r--contrib/ffmpeg/libavformat/riff.h51
-rw-r--r--contrib/ffmpeg/libavformat/rm.c1146
-rw-r--r--contrib/ffmpeg/libavformat/rtp.c1099
-rw-r--r--contrib/ffmpeg/libavformat/rtp.h118
-rw-r--r--contrib/ffmpeg/libavformat/rtp_h264.c419
-rw-r--r--contrib/ffmpeg/libavformat/rtp_h264.h26
-rw-r--r--contrib/ffmpeg/libavformat/rtp_internal.h110
-rw-r--r--contrib/ffmpeg/libavformat/rtpproto.c303
-rw-r--r--contrib/ffmpeg/libavformat/rtsp.c1493
-rw-r--r--contrib/ffmpeg/libavformat/rtsp.h98
-rw-r--r--contrib/ffmpeg/libavformat/rtspcodes.h31
-rw-r--r--contrib/ffmpeg/libavformat/segafilm.c310
-rw-r--r--contrib/ffmpeg/libavformat/sgi.c460
-rw-r--r--contrib/ffmpeg/libavformat/sierravmd.c302
-rw-r--r--contrib/ffmpeg/libavformat/smacker.c345
-rw-r--r--contrib/ffmpeg/libavformat/sol.c160
-rw-r--r--contrib/ffmpeg/libavformat/swf.c944
-rw-r--r--contrib/ffmpeg/libavformat/tcp.c232
-rw-r--r--contrib/ffmpeg/libavformat/tiertexseq.c310
-rw-r--r--contrib/ffmpeg/libavformat/tta.c152
-rw-r--r--contrib/ffmpeg/libavformat/udp.c512
-rw-r--r--contrib/ffmpeg/libavformat/utils.c3108
-rw-r--r--contrib/ffmpeg/libavformat/v4l2.c541
-rw-r--r--contrib/ffmpeg/libavformat/voc.c36
-rw-r--r--contrib/ffmpeg/libavformat/voc.h51
-rw-r--r--contrib/ffmpeg/libavformat/vocdec.c155
-rw-r--r--contrib/ffmpeg/libavformat/vocenc.c104
-rw-r--r--contrib/ffmpeg/libavformat/wav.c253
-rw-r--r--contrib/ffmpeg/libavformat/wc3movie.c394
-rw-r--r--contrib/ffmpeg/libavformat/westwood.c414
-rw-r--r--contrib/ffmpeg/libavformat/wv.c202
-rw-r--r--contrib/ffmpeg/libavformat/yuv.c161
-rw-r--r--contrib/ffmpeg/libavformat/yuv4mpeg.c408
-rw-r--r--contrib/ffmpeg/libavutil/Makefile29
-rw-r--r--contrib/ffmpeg/libavutil/adler32.c71
-rw-r--r--contrib/ffmpeg/libavutil/adler32.h27
-rw-r--r--contrib/ffmpeg/libavutil/avutil.h137
-rw-r--r--contrib/ffmpeg/libavutil/bswap.h175
-rw-r--r--contrib/ffmpeg/libavutil/common.h449
-rw-r--r--contrib/ffmpeg/libavutil/crc.c104
-rw-r--r--contrib/ffmpeg/libavutil/crc.h35
-rw-r--r--contrib/ffmpeg/libavutil/fifo.c137
-rw-r--r--contrib/ffmpeg/libavutil/fifo.h25
-rw-r--r--contrib/ffmpeg/libavutil/integer.c223
-rw-r--r--contrib/ffmpeg/libavutil/integer.h49
-rw-r--r--contrib/ffmpeg/libavutil/internal.h235
-rw-r--r--contrib/ffmpeg/libavutil/intfloat_readwrite.c97
-rw-r--r--contrib/ffmpeg/libavutil/intfloat_readwrite.h39
-rw-r--r--contrib/ffmpeg/libavutil/lls.c151
-rw-r--r--contrib/ffmpeg/libavutil/lls.h45
-rw-r--r--contrib/ffmpeg/libavutil/log.c82
-rw-r--r--contrib/ffmpeg/libavutil/log.h62
-rw-r--r--contrib/ffmpeg/libavutil/mathematics.c139
-rw-r--r--contrib/ffmpeg/libavutil/mathematics.h51
-rw-r--r--contrib/ffmpeg/libavutil/md5.c186
-rw-r--r--contrib/ffmpeg/libavutil/md5.h34
-rw-r--r--contrib/ffmpeg/libavutil/mem.c171
-rw-r--r--contrib/ffmpeg/libavutil/rational.c118
-rw-r--r--contrib/ffmpeg/libavutil/rational.h71
-rw-r--r--contrib/ffmpeg/libavutil/softfloat.c72
-rw-r--r--contrib/ffmpeg/libavutil/softfloat.h122
-rw-r--r--contrib/ffmpeg/libavutil/tree.c151
-rw-r--r--contrib/ffmpeg/libavutil/tree.h52
-rw-r--r--contrib/ffmpeg/libavutil/x86_cpu.h60
-rw-r--r--contrib/ffmpeg/libpostproc/Makefile26
-rw-r--r--contrib/ffmpeg/libpostproc/mangle.h47
-rw-r--r--contrib/ffmpeg/libpostproc/postprocess.c1144
-rw-r--r--contrib/ffmpeg/libpostproc/postprocess.h84
-rw-r--r--contrib/ffmpeg/libpostproc/postprocess_altivec_template.c1191
-rw-r--r--contrib/ffmpeg/libpostproc/postprocess_internal.h183
-rw-r--r--contrib/ffmpeg/libpostproc/postprocess_template.c3843
-rw-r--r--contrib/ffmpeg/libswscale/Makefile26
-rw-r--r--contrib/ffmpeg/libswscale/cs_test.c306
-rw-r--r--contrib/ffmpeg/libswscale/rgb2rgb.c665
-rw-r--r--contrib/ffmpeg/libswscale/rgb2rgb.h147
-rw-r--r--contrib/ffmpeg/libswscale/rgb2rgb_template.c2688
-rw-r--r--contrib/ffmpeg/libswscale/swscale-example.c229
-rw-r--r--contrib/ffmpeg/libswscale/swscale.c2864
-rw-r--r--contrib/ffmpeg/libswscale/swscale.h146
-rw-r--r--contrib/ffmpeg/libswscale/swscale_altivec_template.c548
-rw-r--r--contrib/ffmpeg/libswscale/swscale_internal.h226
-rw-r--r--contrib/ffmpeg/libswscale/swscale_template.c3241
-rw-r--r--contrib/ffmpeg/libswscale/yuv2rgb.c844
-rw-r--r--contrib/ffmpeg/libswscale/yuv2rgb_altivec.c963
-rw-r--r--contrib/ffmpeg/libswscale/yuv2rgb_mlib.c87
-rw-r--r--contrib/ffmpeg/libswscale/yuv2rgb_template.c540
-rw-r--r--contrib/ffmpeg/makefile.xine.in30
-rw-r--r--contrib/ffmpeg/output_example.c546
-rw-r--r--contrib/ffmpeg/pktdumper.c97
-rw-r--r--contrib/ffmpeg/qt-faststart.c311
-rw-r--r--contrib/ffmpeg/tests/Makefile91
-rw-r--r--contrib/ffmpeg/tests/audiogen.c168
-rw-r--r--contrib/ffmpeg/tests/dsptest.c178
-rw-r--r--contrib/ffmpeg/tests/ffmpeg.regression.ref182
-rw-r--r--contrib/ffmpeg/tests/ffserver.regression.ref10
-rw-r--r--contrib/ffmpeg/tests/lena.pnm109
-rw-r--r--contrib/ffmpeg/tests/libav.regression.ref106
-rwxr-xr-xcontrib/ffmpeg/tests/regression.sh785
-rw-r--r--contrib/ffmpeg/tests/rotozoom.c289
-rw-r--r--contrib/ffmpeg/tests/rotozoom.regression.ref182
-rwxr-xr-xcontrib/ffmpeg/tests/server-regression.sh50
-rw-r--r--contrib/ffmpeg/tests/test.conf306
-rw-r--r--contrib/ffmpeg/tests/tiny_psnr.c154
-rw-r--r--contrib/ffmpeg/tests/videogen.c278
-rwxr-xr-xcontrib/ffmpeg/unwrap-diff2
-rwxr-xr-xcontrib/ffmpeg/version.sh14
-rw-r--r--contrib/ffmpeg/vhook/Makefile51
-rw-r--r--contrib/ffmpeg/vhook/drawtext.c531
-rw-r--r--contrib/ffmpeg/vhook/fish.c380
-rw-r--r--contrib/ffmpeg/vhook/imlib2.c450
-rw-r--r--contrib/ffmpeg/vhook/null.c116
-rw-r--r--contrib/ffmpeg/vhook/ppm.c367
-rw-r--r--contrib/ffmpeg/vhook/watermark.c661
-rw-r--r--contrib/ffmpeg/xvmc_render.h47
547 files changed, 321790 insertions, 0 deletions
diff --git a/contrib/ffmpeg/COPYING b/contrib/ffmpeg/COPYING
new file mode 100644
index 000000000..1e0991447
--- /dev/null
+++ b/contrib/ffmpeg/COPYING
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/contrib/ffmpeg/CREDITS b/contrib/ffmpeg/CREDITS
new file mode 100644
index 000000000..f7f086a3c
--- /dev/null
+++ b/contrib/ffmpeg/CREDITS
@@ -0,0 +1,47 @@
+This file contains the name of the people who have contributed to
+FFmpeg. The names are sorted alphabetically by last name.
+
+Michel Bardiaux
+Fabrice Bellard
+Patrice Bensoussan
+Alex Beregszaszi
+BERO
+Mario Brito
+Ronald Bultje
+Maarten Daniels
+Reimar Doeffinger
+Tim Ferguson
+Brian Foley
+Arpad Gereoffy
+Philip Gladstone
+Vladimir Gneushev
+Roine Gustafsson
+David Hammerton
+Wolfgang Hesseler
+Falk Hueffner
+Steven Johnson
+Zdenek Kabelac
+Robin Kay
+Todd Kirby
+Nick Kurshev
+Benjamin Larsson
+Loïc Le Loarer
+Daniel Maas
+Mike Melanson
+Loren Merritt
+Jeff Muizelaar
+Michael Niedermayer
+François Revol
+Peter Ross
+Måns Rullgård
+Roman Shaposhnik
+Oded Shimon
+Dieter Shirley
+Konstantin Shishkov
+Juan J. Sierralta
+Ewald Snel
+Sascha Sommer
+Leon van Stuivenberg
+Roberto Togni
+Lionel Ulmer
+Reynaldo Verdejo
diff --git a/contrib/ffmpeg/Changelog b/contrib/ffmpeg/Changelog
new file mode 100644
index 000000000..5267b5321
--- /dev/null
+++ b/contrib/ffmpeg/Changelog
@@ -0,0 +1,389 @@
+version <next>
+- DV50 AKA DVCPRO50 encoder, decoder, muxer and demuxer
+- TechSmith Camtasia (TSCC) video decoder
+- IBM Ultimotion (ULTI) video decoder
+- Sierra Online audio file demuxer and decoder
+- Apple QuickDraw (qdrw) video decoder
+- Creative ADPCM audio decoder (16 bits as well as 8 bits schemes)
+- Electronic Arts Multimedia (WVE/UV2/etc.) file demuxer
+- Miro VideoXL (VIXL) video decoder
+- H.261 video encoder
+- QPEG video decoder
+- Nullsoft Video (NSV) file demuxer
+- Shorten audio decoder
+- LOCO video decoder
+- Apple Lossless Audio Codec (ALAC) decoder
+- Winnov WNV1 video decoder
+- Autodesk Animator Studio Codec (AASC) decoder
+- Indeo 2 video decoder
+- Fraps FPS1 video decoder
+- Snow video encoder/decoder
+- Sonic audio encoder/decoder
+- Vorbis audio encoder/decoder
+- Macromedia ADPCM decoder
+- Duck TrueMotion 2 video decoder
+- support for decoding FLX and DTA extensions in FLIC files
+- H.264 custom quantization matrices support
+- ffserver fixed, it should now be usable again
+- QDM2 audio decoder
+- Real Cooker audio decoder
+- TrueSpeech audio decoder
+- WMA2 audio decoder fixed, now all files should play correctly
+- RealAudio 14.4 and 28.8 decoders fixed
+- JPEG-LS encoder and decoder
+- CamStudio video decoder
+- build system improvements
+- tabs and trailing whitespace removed from the codebase
+- AIFF/AIFF-C audio format, encoding and decoding
+- ADTS AAC file reading and writing
+- Creative VOC file reading and writing
+- American Laser Games multimedia (*.mm) playback system
+- Zip Blocks Motion Video decoder
+- Improved Theora/VP3 decoder
+- True Audio (TTA) decoder
+- AVS demuxer and video decoder
+- Smacker demuxer and decoder
+- NuppelVideo/MythTV demuxer and RTjpeg decoder
+- KMVC decoder
+- MPEG-2 intra vlc support
+- MPEG-2 4:2:2 encoder
+- Flash Screen Video decoder
+- GXF demuxer
+- Chinese AVS decoder
+- GXF muxer
+- MXF demuxer
+- VC-1/WMV3/WMV9 video decoder
+- MacIntel support
+- AVISynth support
+- VMware video decoder
+- VP5 video decoder
+- VP6 video decoder
+- WavPack lossless audio decoder
+- Targa (.TGA) picture decoder
+- Delphine Software .cin demuxer/audio and video decoder
+- Tiertex .seq demuxer/video decoder
+- MTV demuxer
+- TIFF picture decoder
+- GIF picture decoder
+- Intel Music decoder
+
+version 0.4.9-pre1:
+
+- DV encoder, DV muxer
+- Microsoft RLE video decoder
+- Microsoft Video-1 decoder
+- Apple Animation (RLE) decoder
+- Apple Graphics (SMC) decoder
+- Apple Video (RPZA) decoder
+- Cinepak decoder
+- Sega FILM (CPK) file demuxer
+- Westwood multimedia support (VQA & AUD files)
+- Id Quake II CIN playback support
+- 8BPS video decoder
+- FLIC playback support
+- RealVideo 2.0 (RV20) decoder
+- Duck TrueMotion v1 (DUCK) video decoder
+- Sierra VMD demuxer and video decoder
+- MSZH and ZLIB decoder support
+- SVQ1 video encoder
+- AMR-WB support
+- PPC optimizations
+- rate distortion optimal cbp support
+- rate distorted optimal ac prediction for MPEG-4
+- rate distorted optimal lambda->qp support
+- AAC encoding with libfaac
+- Sunplus JPEG codec (SP5X) support
+- use Lagrange multipler instead of QP for ratecontrol
+- Theora/VP3 decoding support
+- XA and ADX ADPCM codecs
+- export MPEG-2 active display area / pan scan
+- Add support for configuring with IBM XLC
+- floating point AAN DCT
+- initial support for zygo video (not complete)
+- RGB ffv1 support
+- new audio/video parser API
+- av_log() system
+- av_read_frame() and av_seek_frame() support
+- missing last frame fixes
+- seek by mouse in ffplay
+- noise reduction of DCT coefficients
+- H.263 OBMC & 4MV support
+- H.263 alternative inter vlc support
+- H.263 loop filter
+- H.263 slice structured mode
+- interlaced DCT support for MPEG-2 encoding
+- stuffing to stay above min_bitrate
+- MB type & QP visualization
+- frame stepping for ffplay
+- interlaced motion estimation
+- alternate scantable support
+- SVCD scan offset support
+- closed GOP support
+- SSE2 FDCT
+- quantizer noise shaping
+- G.726 ADPCM audio codec
+- MS ADPCM encoding
+- multithreaded/SMP motion estimation
+- multithreaded/SMP encoding for MPEG-1/MPEG-2/MPEG-4/H.263
+- multithreaded/SMP decoding for MPEG-2
+- FLAC decoder
+- Metrowerks CodeWarrior suppport
+- H.263+ custom pcf support
+- nicer output for 'ffmpeg -formats'
+- Matroska demuxer
+- SGI image format, encoding and decoding
+- H.264 loop filter support
+- H.264 CABAC support
+- nicer looking arrows for the motion vector vissualization
+- improved VCD support
+- audio timestamp drift compensation
+- MPEG-2 YUV 422/444 support
+- polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample
+- better image scaling
+- H.261 support
+- correctly interleave packets during encoding
+- VIS optimized motion compensation
+- intra_dc_precision>0 encoding support
+- support reuse of motion vectors/MB types/field select values of the source video
+- more accurate deblock filter
+- padding support
+- many optimizations and bugfixes
+
+version 0.4.8:
+
+- MPEG-2 video encoding (Michael)
+- Id RoQ playback subsystem (Mike Melanson and Tim Ferguson)
+- Wing Commander III Movie (.mve) file playback subsystem (Mike Melanson
+ and Mario Brito)
+- Xan DPCM audio decoder (Mario Brito)
+- Interplay MVE playback subsystem (Mike Melanson)
+- Duck DK3 and DK4 ADPCM audio decoders (Mike Melanson)
+
+version 0.4.7:
+
+- RealAudio 1.0 (14_4) and 2.0 (28_8) native decoders. Author unknown, code from mplayerhq
+ (originally from public domain player for Amiga at http://www.honeypot.net/audio)
+- current version now also compiles with older GCC (Fabrice)
+- 4X multimedia playback system including 4xm file demuxer (Mike
+ Melanson), and 4X video and audio codecs (Michael)
+- Creative YUV (CYUV) decoder (Mike Melanson)
+- FFV1 codec (our very simple lossless intra only codec, compresses much better
+ than HuffYUV) (Michael)
+- ASV1 (Asus), H.264, Intel indeo3 codecs have been added (various)
+- tiny PNG encoder and decoder, tiny GIF decoder, PAM decoder (PPM with
+ alpha support), JPEG YUV colorspace support. (Fabrice Bellard)
+- ffplay has been replaced with a newer version which uses SDL (optionally)
+ for multiplatform support (Fabrice)
+- Sorenson Version 3 codec (SVQ3) support has been added (decoding only) - donated
+ by anonymous
+- AMR format has been added (Johannes Carlsson)
+- 3GP support has been added (Johannes Carlsson)
+- VP3 codec has been added (Mike Melanson)
+- more MPEG-1/2 fixes
+- better multiplatform support, MS Visual Studio fixes (various)
+- AltiVec optimizations (Magnus Damn and others)
+- SH4 processor support has been added (BERO)
+- new public interfaces (avcodec_get_pix_fmt) (Roman Shaposhnick)
+- VOB streaming support (Brian Foley)
+- better MP3 autodetection (Andriy Rysin)
+- qpel encoding (Michael)
+- 4mv+b frames encoding finally fixed (Michael)
+- chroma ME (Michael)
+- 5 comparison functions for ME (Michael)
+- B-frame encoding speedup (Michael)
+- WMV2 codec (unfinished - Michael)
+- user specified diamond size for EPZS (Michael)
+- Playstation STR playback subsystem, still experimental (Mike and Michael)
+- ASV2 codec (Michael)
+- CLJR decoder (Alex)
+
+.. And lots more new enhancements and fixes.
+
+version 0.4.6:
+
+- completely new integer only MPEG audio layer 1/2/3 decoder rewritten
+ from scratch
+- Recoded DCT and motion vector search with gcc (no longer depends on nasm)
+- fix quantization bug in AC3 encoder
+- added PCM codecs and format. Corrected WAV/AVI/ASF PCM issues
+- added prototype ffplay program
+- added GOB header parsing on H.263/H.263+ decoder (Juanjo)
+- bug fix on MCBPC tables of H.263 (Juanjo)
+- bug fix on DC coefficients of H.263 (Juanjo)
+- added Advanced Prediction Mode on H.263/H.263+ decoder (Juanjo)
+- now we can decode H.263 streams found in QuickTime files (Juanjo)
+- now we can decode H.263 streams found in VIVO v1 files(Juanjo)
+- preliminary RTP "friendly" mode for H.263/H.263+ coding. (Juanjo)
+- added GOB header for H.263/H.263+ coding on RTP mode (Juanjo)
+- now H.263 picture size is returned on the first decoded frame (Juanjo)
+- added first regression tests
+- added MPEG-2 TS demuxer
+- new demux API for libav
+- more accurate and faster IDCT (Michael)
+- faster and entropy-controlled motion search (Michael)
+- two pass video encoding (Michael)
+- new video rate control (Michael)
+- added MSMPEG4V1, MSMPEGV2 and WMV1 support (Michael)
+- great performance improvement of video encoders and decoders (Michael)
+- new and faster bit readers and vlc parsers (Michael)
+- high quality encoding mode: tries all macroblock/VLC types (Michael)
+- added DV video decoder
+- preliminary RTP/RTSP support in ffserver and libavformat
+- H.263+ AIC decoding/encoding support (Juanjo)
+- VCD MPEG-PS mode (Juanjo)
+- PSNR stuff (Juanjo)
+- simple stats output (Juanjo)
+- 16-bit and 15-bit RGB/BGR/GBR support (Bisqwit)
+
+version 0.4.5:
+
+- some header fixes (Zdenek Kabelac <kabi@informatics.muni.cz>)
+- many MMX optimizations (Nick Kurshev <nickols_k@mail.ru>)
+- added configure system (actually a small shell script)
+- added MPEG audio layer 1/2/3 decoding using LGPL'ed mpglib by
+ Michael Hipp (temporary solution - waiting for integer only
+ decoder)
+- fixed VIDIOCSYNC interrupt
+- added Intel H.263 decoding support ('I263' AVI fourCC)
+- added Real Video 1.0 decoding (needs further testing)
+- simplified image formats again. Added PGM format (=grey
+ pgm). Renamed old PGM to PGMYUV.
+- fixed msmpeg4 slice issues (tell me if you still find problems)
+- fixed OpenDivX bugs with newer versions (added VOL header decoding)
+- added support for MPlayer interface
+- added macroblock skip optimization
+- added MJPEG decoder
+- added mmx/mmxext IDCT from libmpeg2
+- added pgmyuvpipe, ppm, and ppm_pipe formats (original patch by Celer
+ <celer@shell.scrypt.net>)
+- added pixel format conversion layer (e.g. for MJPEG or PPM)
+- added deinterlacing option
+- MPEG-1/2 fixes
+- MPEG-4 vol header fixes (Jonathan Marsden <snmjbm@pacbell.net>)
+- ARM optimizations (Lionel Ulmer <lionel.ulmer@free.fr>).
+- Windows porting of file converter
+- added MJPEG raw format (input/ouput)
+- added JPEG image format support (input/output)
+
+version 0.4.4:
+
+- fixed some std header definitions (Bjorn Lindgren
+ <bjorn.e.lindgren@telia.com>).
+- added MPEG demuxer (MPEG-1 and 2 compatible).
+- added ASF demuxer
+- added prototype RM demuxer
+- added AC3 decoding (done with libac3 by Aaron Holtzman)
+- added decoding codec parameter guessing (.e.g. for MPEG, because the
+ header does not include them)
+- fixed header generation in MPEG-1, AVI and ASF muxer: wmplayer can now
+ play them (only tested video)
+- fixed H.263 white bug
+- fixed phase rounding in img resample filter
+- add MMX code for polyphase img resample filter
+- added CPU autodetection
+- added generic title/author/copyright/comment string handling (ASF and RM
+ use them)
+- added SWF demux to extract MP3 track (not usable yet because no MP3
+ decoder)
+- added fractional frame rate support
+- codecs are no longer searched by read_header() (should fix ffserver
+ segfault)
+
+version 0.4.3:
+
+- BGR24 patch (initial patch by Jeroen Vreeken <pe1rxq@amsat.org>)
+- fixed raw yuv output
+- added motion rounding support in MPEG-4
+- fixed motion bug rounding in MSMPEG4
+- added B-frame handling in video core
+- added full MPEG-1 decoding support
+- added partial (frame only) MPEG-2 support
+- changed the FOURCC code for H.263 to "U263" to be able to see the
+ +AVI/H.263 file with the UB Video H.263+ decoder. MPlayer works with
+ this +codec ;) (JuanJo).
+- Halfpel motion estimation after MB type selection (JuanJo)
+- added pgm and .Y.U.V output format
+- suppressed 'img:' protocol. Simply use: /tmp/test%d.[pgm|Y] as input or
+ output.
+- added pgmpipe I/O format (original patch from Martin Aumueller
+ <lists@reserv.at>, but changed completely since we use a format
+ instead of a protocol)
+
+version 0.4.2:
+
+- added H.263/MPEG-4/MSMPEG4 decoding support. MPEG-4 decoding support
+ (for OpenDivX) is almost complete: 8x8 MVs and rounding are
+ missing. MSMPEG4 support is complete.
+- added prototype MPEG-1 decoder. Only I- and P-frames handled yet (it
+ can decode ffmpeg MPEGs :-)).
+- added libavcodec API documentation (see apiexample.c).
+- fixed image polyphase bug (the bottom of some images could be
+ greenish)
+- added support for non clipped motion vectors (decoding only)
+ and image sizes non-multiple of 16
+- added support for AC prediction (decoding only)
+- added file overwrite confirmation (can be disabled with -y)
+- added custom size picture to H.263 using H.263+ (Juanjo)
+
+version 0.4.1:
+
+- added MSMPEG4 (aka DivX) compatible encoder. Changed default codec
+ of AVI and ASF to DIV3.
+- added -me option to set motion estimation method
+ (default=log). suppressed redundant -hq option.
+- added options -acodec and -vcodec to force a given codec (useful for
+ AVI for example)
+- fixed -an option
+- improved dct_quantize speed
+- factorized some motion estimation code
+
+version 0.4.0:
+
+- removing grab code from ffserver and moved it to ffmpeg. Added
+ multistream support to ffmpeg.
+- added timeshifting support for live feeds (option ?date=xxx in the
+ URL)
+- added high quality image resize code with polyphase filter (need
+ mmx/see optimisation). Enable multiple image size support in ffserver.
+- added multi live feed support in ffserver
+- suppressed master feature from ffserver (it should be done with an
+ external program which opens the .ffm url and writes it to another
+ ffserver)
+- added preliminary support for video stream parsing (WAV and AVI half
+ done). Added proper support for audio/video file conversion in
+ ffmpeg.
+- added preliminary support for video file sending from ffserver
+- redesigning I/O subsystem: now using URL based input and output
+ (see avio.h)
+- added WAV format support
+- added "tty user interface" to ffmpeg to stop grabbing gracefully
+- added MMX/SSE optimizations to SAD (Sums of Absolutes Differences)
+ (Juan J. Sierralta P. a.k.a. "Juanjo" <juanjo@atmlab.utfsm.cl>)
+- added MMX DCT from mpeg2_movie 1.5 (Juanjo)
+- added new motion estimation algorithms, log and phods (Juanjo)
+- changed directories: libav for format handling, libavcodec for
+ codecs
+
+version 0.3.4:
+
+- added stereo in MPEG audio encoder
+
+version 0.3.3:
+
+- added 'high quality' mode which use motion vectors. It can be used in
+ real time at low resolution.
+- fixed rounding problems which caused quality problems at high
+ bitrates and large GOP size
+
+version 0.3.2: small fixes
+
+- ASF fixes
+- put_seek bug fix
+
+version 0.3.1: added avi/divx support
+
+- added AVI support
+- added MPEG-4 codec compatible with OpenDivX. It is based on the H.263 codec
+- added sound for flash format (not tested)
+
+version 0.3: initial public release
diff --git a/contrib/ffmpeg/Doxyfile b/contrib/ffmpeg/Doxyfile
new file mode 100644
index 000000000..9e4fdcdd0
--- /dev/null
+++ b/contrib/ffmpeg/Doxyfile
@@ -0,0 +1,1038 @@
+# Doxyfile 1.3-rc1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = ffmpeg
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = doxy
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch,
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en
+# (Japanese with english messages), Korean, Norwegian, Polish, Portuguese,
+# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these class will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
+# members of a class in the documentation of that class as if those members were
+# ordinary class members. Constructors, destructors and assignment operators of
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH = .
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower case letters. If set to YES upper case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# users are adviced to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explict @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# reimplements.
+
+INHERIT_DOCS = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consist of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT =
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
+# *.h++ *.idl *.odl
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+
+INPUT_FILTER =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output dir.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non empty doxygen will try to run
+# the html help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the Html help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+,
+# or Internet explorer 4.0+). Note that for large projects the tree generation
+# can take a very long time. In such cases it is better to disable this feature.
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimised for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assigments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_XML = NO
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed.
+
+PREDEFINED = __attribute__(x)="" "RENAME(x)=x ## _TMPL" "DEF(x)=x ## _TMPL" \
+ HAVE_AV_CONFIG_H HAVE_MMX HAVE_MMX2 HAVE_3DNOW \
+ ATTR_ALIGN(x)=""
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+#EXPAND_AS_DEFINED = FF_COMMON_FRAME
+EXPAND_AS_DEFINED = declare_idct(idct, table, idct_row_head, idct_row, idct_row_tail, idct_row_mid)
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse the
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tagfiles.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off. Note that this
+# option is superceded by the HAVE_DOT option below. This is only a fallback. It is
+# recommended to install and use dot, since it yield more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermedate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
+
+# The CGI_NAME tag should be the name of the CGI script that
+# starts the search engine (doxysearch) with the correct parameters.
+# A script with this name will be generated by doxygen.
+
+CGI_NAME = search.cgi
+
+# The CGI_URL tag should be the absolute URL to the directory where the
+# cgi binaries are located. See the documentation of your http daemon for
+# details.
+
+CGI_URL =
+
+# The DOC_URL tag should be the absolute URL to the directory where the
+# documentation is located. If left blank the absolute path to the
+# documentation, with file:// prepended to it, will be used.
+
+DOC_URL =
+
+# The DOC_ABSPATH tag should be the absolute path to the directory where the
+# documentation is located. If left blank the directory on the local machine
+# will be used.
+
+DOC_ABSPATH =
+
+# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
+# is installed.
+
+BIN_ABSPATH = /usr/local/bin/
+
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to
+# documentation generated for other projects. This allows doxysearch to search
+# the documentation for these projects as well.
+
+EXT_DOC_PATHS =
diff --git a/contrib/ffmpeg/INSTALL b/contrib/ffmpeg/INSTALL
new file mode 100644
index 000000000..a636c5367
--- /dev/null
+++ b/contrib/ffmpeg/INSTALL
@@ -0,0 +1,14 @@
+
+1) Type './configure' create the configuration (use './configure
+--help' to have the configure options).
+
+'configure' can be launched from another directory than the ffmpeg
+sources to put the objects at that place. In that case, use an
+absolute path when launching 'configure',
+e.g. /ffmpegdir/ffmpeg/configure.
+
+2) Then type 'make' to build ffmpeg. On BSD systems, type 'gmake'
+instead of 'make'. You may need to install GNU make first.
+
+3) Type 'make install' to install ffmpeg and ffserver in
+/usr/local/bin.
diff --git a/contrib/ffmpeg/MAINTAINERS b/contrib/ffmpeg/MAINTAINERS
new file mode 100644
index 000000000..410523390
--- /dev/null
+++ b/contrib/ffmpeg/MAINTAINERS
@@ -0,0 +1,243 @@
+FFmpeg maintainers
+==================
+
+Below is a list of the people maintaining different parts of the
+FFmpeg code.
+
+
+Project Leader
+==============
+
+Michael Niedermayer
+ final design decisions
+
+
+Applications
+============
+
+ffmpeg:
+ ffmpeg.c Michael Niedermayer
+
+ Video Hooks:
+ vhook
+ vhook/watermark.c Marcus Engene
+ vhook/ppm.c
+ vhook/drawtext.c
+ vhook/fish.c
+ vhook/null.c
+ vhook/imlib2.c
+
+ffplay:
+ ffplay.c
+
+ffserver:
+ ffserver.c, ffserver.h
+
+Commandline utility code:
+ cmdutils.c, cmdutils.h
+
+QuickTime faststart:
+ qt-faststart.c Mike Melanson
+
+
+Miscellaneous Areas
+===================
+
+documentation Mike Melanson, Diego Biurrun
+website Mike Melanson, Diego Biurrun
+build system (configure,Makefiles) Diego Biurrun, Mans Rullgard
+project server Diego Biurrun, Mans Rullgard
+mailinglists Michael Niedermayer, Baptiste Coudurier
+
+
+libavutil
+=========
+
+External Interfaces:
+ libavutil/avutil.h
+Internal Interfaces:
+ libavutil/common.h
+
+Other:
+ intfloat* Michael Niedermayer
+ rational.c, rational.h Michael Niedermayer
+ mathematics.c, mathematics.h Michael Niedermayer
+ integer.c, integer.h Michael Niedermayer
+ bswap.h
+
+
+libavcodec
+==========
+
+Generic Parts:
+ External Interfaces:
+ avcodec.h Michael Niedermayer
+ utility code:
+ utils.c
+ mem.c
+ opt.c, opt.h
+ arithmetic expression evaluator:
+ eval.c Michael Niedermayer
+ audio and video frame extraction:
+ parser.c
+ bitsream reading:
+ bitstream.c, bitstream.h Michael Niedermayer
+ CABAC:
+ cabac.h, cabac.c Michael Niedermayer
+ DSP utilities:
+ dsputils.c, dsputils.h Michael Niedermayer
+ entropy coding:
+ rangecoder.c, rangecoder.h Michael Niedermayer
+ floating point AAN DCT:
+ faandct.c, faandct.h Michael Niedermayer
+ Golomb coding:
+ golomb.c, golomb.h Michael Niedermayer
+ motion estimation:
+ motion* Michael Niedermayer
+ rate control:
+ ratecontrol.c
+ xvid_rc.c Michael Niedermayer
+ simple IDCT:
+ simple_idct.c, simple_idct.h Michael Niedermayer
+ postprocessing:
+ libpostproc/* Michael Niedermayer
+
+Codecs:
+ 4xm.c Michael Niedermayer
+ 8bps.c Roberto Togni
+ aasc.c Kostya Shishkov
+ asv* Michael Niedermayer
+ bmp.c Mans Rullgard
+ cavs* Stefan Gehrer
+ cinepak.c Roberto Togni
+ cljr Alex Beregszaszi
+ cook.c, cookdata.h Benjamin Larsson
+ cscd.c Reimar Doeffinger
+ dpcm.c Mike Melanson
+ dv.c Roman Shaposhnik
+ ffv1.c Michael Niedermayer
+ flac.c Alex Beregszaszi
+ flacenc.c Justin Ruggles
+ flashsv.c Benjamin Larsson
+ flicvideo.c Mike Melanson
+ g726.c Roman Shaposhnik
+ gifdec.c Baptiste Coudurier
+ h264* Loren Merritt, Michael Niedermayer
+ h261* Michael Niedermayer
+ h263* Michael Niedermayer
+ huffyuv.c Michael Niedermayer
+ idcinvideo.c Mike Melanson
+ imc* Benjamin Larsson
+ indeo2* Kostya Shishkov
+ interplayvideo.c Mike Melanson
+ jpeg_ls.c Kostya Shishkov
+ kmvc.c Kostya Shishkov
+ lcl.c Roberto Togni
+ loco.c Kostya Shishkov
+ lzo.h, lzo.c Reimar Doeffinger
+ mdec.c Michael Niedermayer
+ mjpeg.c Michael Niedermayer
+ mpeg12.c, mpeg12data.h Michael Niedermayer
+ mpegvideo.c, mpegvideo.h Michael Niedermayer
+ msmpeg4.c, msmpeg4data.h Michael Niedermayer
+ msrle.c Mike Melanson
+ msvideo1.c Mike Melanson
+ nuv.c Reimar Doeffinger
+ oggtheora.c Mans Rullgard
+ qdm2.c, qdm2data.h Roberto Togni
+ qdrw.c Kostya Shishkov
+ qpeg.c Kostya Shishkov
+ qtrle.c Mike Melanson
+ ra144.c, ra144.h, ra288.c, ra288.h Roberto Togni
+ resample2.c Michael Niedermayer
+ rpza.c Roberto Togni
+ rtjpeg.c, rtjpeg.h Reimar Doeffinger
+ rv10.c Michael Niedermayer
+ smc.c Mike Melanson
+ snow.c Michael Niedermayer, Loren Merritt
+ sonic.c Alex Beregszaszi
+ svq3.c Michael Niedermayer
+ targa.c Kostya Shishkov
+ tiff.c Kostya Shishkov
+ truemotion1* Mike Melanson
+ truemotion2* Kostya Shishkov
+ truespeech.c Kostya Shishkov
+ tscc.c Kostya Shishkov
+ ulti* Kostya Shishkov
+ vc1* Kostya Shishkov
+ vcr1.c Michael Niedermayer
+ vmnc.c Kostya Shishkov
+ vorbis_enc.c Oded Shimon
+ vp3* Mike Melanson
+ vp5 Aurelien Jacobs
+ vp6 Aurelien Jacobs
+ vqavideo.c Mike Melanson
+ wavpack.c Kostya Shishkov
+ wmv2.c Michael Niedermayer
+ wnv1.c Kostya Shishkov
+ x264.c Mans Rullgard
+ xan.c Mike Melanson
+ xl.c Kostya Shishkov
+ xvmcvideo.c Ivan Kalvachev
+ zmbv.c Kostya Shishkov
+
+
+libavformat
+===========
+
+Generic parts:
+ External Interface:
+ libavformat/avformat.h
+ Utility Code:
+ libavformat/utils.c
+
+
+Muxers/Demuxers:
+ 4xm.c Mike Melanson
+ adtsenc.c Mans Rullgard
+ aiff.c Baptiste Coudurier
+ avi* Michael Niedermayer
+ crc.c Michael Niedermayer
+ daud.c Reimar Doeffinger
+ dc1394.c, dv.c Roman Shaposhnik
+ flic.c Mike Melanson
+ flvdec.c, flvenc.c Michael Niedermayer
+ gxf.c Reimar Doeffinger
+ gxfenc.c Baptiste Coudurier
+ idcin.c Mike Melanson
+ idroq.c Mike Melanson
+ ipmovie.c Mike Melanson
+ img2.c Michael Niedermayer
+ matroska.c Aurelien Jacobs
+ mov.c Francois Revol, Michael Niedermayer
+ movenc.c Michael Niedermayer, Baptiste Coudurier
+ mpegts* Mans Rullgard
+ mtv.c Reynaldo H. Verdejo Pinochet
+ mxf.c Baptiste Coudurier
+ nsvdec.c Francois Revol
+ nut.c Alex Beregszaszi
+ nuv.c Reimar Doeffinger
+ ogg2.c, ogg2.h Mans Rullgard
+ oggparsevorbis.c Mans Rullgard
+ oggparseogm.c Mans Rullgard
+ psxstr.c Mike Melanson
+ raw.c Michael Niedermayer
+ rm.c Roberto Togni
+ segafilm.c Mike Melanson
+ v4l2.c Luca Abeni
+ voc.c Aurelien Jacobs
+ wav.c Michael Niedermayer
+ wc3movie.c Mike Melanson
+ westwood.c Mike Melanson
+ wv.c Kostya Shishkov
+
+
+Operating systems / CPU architectures
+=====================================
+
+Alpha Mans Rullgard, Falk Hueffner
+BeOS Francois Revol
+i386 Michael Niedermayer
+Mac OS X / PowerPC Romain Dolbeau
+Amiga / PowerPC Colin Ward
+Linux / PowerPC Luca Barbato
diff --git a/contrib/ffmpeg/Makefile b/contrib/ffmpeg/Makefile
new file mode 100644
index 000000000..929522c3b
--- /dev/null
+++ b/contrib/ffmpeg/Makefile
@@ -0,0 +1,241 @@
+#
+# Main ffmpeg Makefile
+# (c) 2000-2004 Fabrice Bellard
+#
+include config.mak
+
+VPATH=$(SRC_PATH_BARE)
+
+CFLAGS=$(OPTFLAGS) -I$(BUILD_ROOT) -I$(SRC_PATH) -I$(SRC_PATH)/libavutil \
+ -I$(SRC_PATH)/libavcodec -I$(SRC_PATH)/libavformat -I$(SRC_PATH)/libswscale \
+ -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_ISOC9X_SOURCE
+LDFLAGS+= -g
+
+ifeq ($(CONFIG_FFMPEG),yes)
+MANPAGES=doc/ffmpeg.1
+PROGS_G+=ffmpeg_g$(EXESUF)
+PROGS+=ffmpeg$(EXESUF)
+endif
+
+ifeq ($(CONFIG_FFSERVER),yes)
+MANPAGES+=doc/ffserver.1
+PROGS+=ffserver$(EXESUF)
+endif
+
+ifeq ($(CONFIG_FFPLAY),yes)
+MANPAGES+=doc/ffplay.1
+PROGS_G+=ffplay_g$(EXESUF)
+PROGS+=ffplay$(EXESUF)
+endif
+
+BASENAMES=ffmpeg ffplay ffserver
+ALLPROGS=$(addsuffix $(EXESUF), $(BASENAMES))
+ALLPROGS_G=$(addsuffix _g$(EXESUF), $(BASENAMES))
+ALLMANPAGES=$(addsuffix .1, $(BASENAMES))
+
+ifeq ($(BUILD_SHARED),yes)
+DEP_LIBS=libavcodec/$(SLIBPREF)avcodec$(SLIBSUF) libavformat/$(SLIBPREF)avformat$(SLIBSUF)
+else
+DEP_LIBS=libavcodec/$(LIBPREF)avcodec$(LIBSUF) libavformat/$(LIBPREF)avformat$(LIBSUF)
+endif
+
+ifeq ($(CONFIG_VHOOK),yes)
+VHOOK=videohook
+INSTALLVHOOK=install-vhook
+endif
+
+ifeq ($(BUILD_DOC),yes)
+DOC=documentation
+INSTALLMAN=install-man
+endif
+
+OBJS = ffmpeg.o ffserver.o cmdutils.o ffplay.o
+SRCS = $(OBJS:.o=.c) $(ASM_OBJS:.o=.s)
+LDFLAGS := -L$(BUILD_ROOT)/libavformat -L$(BUILD_ROOT)/libavcodec -L$(BUILD_ROOT)/libavutil $(LDFLAGS)
+EXTRALIBS := -lavformat$(BUILDSUF) -lavcodec$(BUILDSUF) -lavutil$(BUILDSUF) $(EXTRALIBS)
+
+ifeq ($(CONFIG_SWSCALER),yes)
+LDFLAGS+=-L./libswscale
+EXTRALIBS+=-lswscale$(BUILDSUF)
+endif
+
+all: lib $(PROGS_G) $(PROGS) $(VHOOK) $(DOC)
+
+lib:
+ $(MAKE) -C libavutil all
+ $(MAKE) -C libavcodec all
+ $(MAKE) -C libavformat all
+ifeq ($(CONFIG_PP),yes)
+ $(MAKE) -C libpostproc all
+endif
+ifeq ($(CONFIG_SWSCALER),yes)
+ $(MAKE) -C libswscale all
+endif
+
+ffmpeg_g$(EXESUF): ffmpeg.o cmdutils.o .libs
+ $(CC) $(LDFLAGS) -o $@ ffmpeg.o cmdutils.o $(EXTRALIBS)
+
+ffserver$(EXESUF): ffserver.o .libs
+ $(CC) $(LDFLAGS) $(FFSERVERLDFLAGS) -o $@ ffserver.o $(EXTRALIBS)
+
+ffplay_g$(EXESUF): ffplay.o cmdutils.o .libs
+ $(CC) $(LDFLAGS) -o $@ ffplay.o cmdutils.o $(EXTRALIBS) $(SDL_LIBS)
+
+%$(EXESUF): %_g$(EXESUF)
+ cp -p $< $@
+ $(STRIP) $@
+
+version.h:
+ $(SRC_PATH)/version.sh $(SRC_PATH)
+
+output_example$(EXESUF): output_example.o .libs
+ $(CC) $(LDFLAGS) -o $@ output_example.o $(EXTRALIBS)
+
+qt-faststart$(EXESUF): qt-faststart.c
+ $(CC) $(CFLAGS) $< -o $@
+
+cws2fws$(EXESUF): cws2fws.c
+ $(CC) $< -o $@ -lz
+
+ffplay.o: ffplay.c
+ $(CC) $(CFLAGS) $(SDL_CFLAGS) -c -o $@ $<
+
+ffmpeg.o ffplay.o ffserver.o: version.h
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+videohook: .libs
+ $(MAKE) -C vhook all
+
+documentation:
+ $(MAKE) -C doc all
+
+install: install-progs install-libs install-headers $(INSTALLMAN) $(INSTALLVHOOK)
+
+ifeq ($(BUILD_SHARED),yes)
+install-progs: $(PROGS) install-libs
+else
+install-progs: $(PROGS)
+endif
+ install -d "$(bindir)"
+ install -c $(INSTALLSTRIP) -m 755 $(PROGS) "$(bindir)"
+
+# create the window installer
+wininstaller: all install
+ makensis ffinstall.nsi
+
+install-man:
+ install -d "$(mandir)/man1"
+ install -m 644 $(MANPAGES) "$(mandir)/man1"
+
+install-vhook:
+ $(MAKE) -C vhook install
+
+install-libs:
+ $(MAKE) -C libavutil install-libs
+ $(MAKE) -C libavcodec install-libs
+ $(MAKE) -C libavformat install-libs
+ifeq ($(CONFIG_PP),yes)
+ $(MAKE) -C libpostproc install-libs
+endif
+ifeq ($(CONFIG_SWSCALER),yes)
+ $(MAKE) -C libswscale install-libs
+endif
+
+ifeq ($(BUILD_SHARED),yes)
+ -$(LDCONFIG)
+endif
+
+install-headers:
+ $(MAKE) -C libavutil install-headers
+ $(MAKE) -C libavcodec install-headers
+ $(MAKE) -C libavformat install-headers
+ifeq ($(CONFIG_PP),yes)
+ $(MAKE) -C libpostproc install-headers
+endif
+ $(MAKE) -C libswscale install-headers
+
+uninstall: uninstall-progs uninstall-libs uninstall-headers uninstall-man uninstall-vhook
+
+uninstall-progs:
+ rm -f $(addprefix $(bindir)/, $(ALLPROGS))
+
+uninstall-man:
+ rm -f $(addprefix $(mandir)/man1/,$(ALLMANPAGES))
+
+uninstall-vhook:
+ $(MAKE) -C vhook uninstall
+
+uninstall-libs:
+ $(MAKE) -C libavutil uninstall-libs
+ $(MAKE) -C libavcodec uninstall-libs
+ $(MAKE) -C libavformat uninstall-libs
+ $(MAKE) -C libpostproc uninstall-libs
+
+uninstall-headers:
+ $(MAKE) -C libavutil uninstall-headers
+ $(MAKE) -C libavcodec uninstall-headers
+ $(MAKE) -C libavformat uninstall-headers
+ $(MAKE) -C libpostproc uninstall-headers
+ -rmdir "$(incdir)"
+ -rmdir "$(prefix)/include/postproc"
+
+depend dep: .depend
+ $(MAKE) -C libavutil depend
+ $(MAKE) -C libavcodec depend
+ $(MAKE) -C libavformat depend
+ifeq ($(CONFIG_PP),yes)
+ $(MAKE) -C libpostproc depend
+endif
+ifeq ($(CONFIG_SWSCALER),yes)
+ $(MAKE) -C libswscale depend
+endif
+ifeq ($(CONFIG_VHOOK),yes)
+ $(MAKE) -C vhook depend
+endif
+
+.depend: $(SRCS) version.h
+ $(CC) -MM $(CFLAGS) $(SDL_CFLAGS) $(filter-out %.h,$^) 1>.depend
+
+.libs: lib
+ @test -f .libs || touch .libs
+ @for i in $(DEP_LIBS) ; do if test $$i -nt .libs ; then touch .libs; fi ; done
+
+clean:
+ $(MAKE) -C libavutil clean
+ $(MAKE) -C libavcodec clean
+ $(MAKE) -C libavformat clean
+ $(MAKE) -C libpostproc clean
+ $(MAKE) -C libswscale clean
+ $(MAKE) -C tests clean
+ $(MAKE) -C vhook clean
+ $(MAKE) -C doc clean
+ rm -f *.o *.d *~ .libs gmon.out TAGS $(ALLPROGS) $(ALLPROGS_G) \
+ output_example$(EXESUF) qt-faststart$(EXESUF) cws2fws$(EXESUF)
+
+distclean: clean
+ $(MAKE) -C libavutil distclean
+ $(MAKE) -C libavcodec distclean
+ $(MAKE) -C libavformat distclean
+ $(MAKE) -C libpostproc distclean
+ $(MAKE) -C libswscale distclean
+ $(MAKE) -C tests distclean
+ $(MAKE) -C vhook distclean
+ rm -f .depend version.h config.* *.pc
+
+TAGS:
+ etags *.[ch] libavformat/*.[ch] libavcodec/*.[ch]
+
+# regression tests
+
+codectest libavtest test-server fulltest test mpeg4 mpeg: $(PROGS)
+ $(MAKE) -C tests $@
+
+.PHONY: all lib videohook documentation install* wininstaller uninstall*
+.PHONY: dep depend clean distclean TAGS
+.PHONY: codectest libavtest test-server fulltest test mpeg4 mpeg
+
+ifneq ($(wildcard .depend),)
+include .depend
+endif
diff --git a/contrib/ffmpeg/README b/contrib/ffmpeg/README
new file mode 100644
index 000000000..ad98fc645
--- /dev/null
+++ b/contrib/ffmpeg/README
@@ -0,0 +1,19 @@
+FFmpeg README
+-------------
+
+1) Documentation
+----------------
+
+* Read the documentation in the doc/ directory.
+
+2) Licensing
+------------
+
+* Read the file COPYING. ffmpeg and the associated libraries EXCEPT
+ liba52 and libpostproc are licensed under the Lesser GNU General
+ Public License.
+
+* liba52 and libpostproc are distributed under the GNU General Public
+ License and their compilation and use is optional in ffmpeg.
+
+Fabrice Bellard.
diff --git a/contrib/ffmpeg/berrno.h b/contrib/ffmpeg/berrno.h
new file mode 100644
index 000000000..eb3bd0cd4
--- /dev/null
+++ b/contrib/ffmpeg/berrno.h
@@ -0,0 +1,44 @@
+#ifndef BERRNO_H
+#define BERRNO_H
+
+#include <Errors.h>
+
+// mmu_man: this is needed for http.c (defined errno)
+#include <errno.h>
+
+#ifdef ENOENT
+#undef ENOENT
+#endif
+#define ENOENT 2
+
+#ifdef EINTR
+#undef EINTR
+#endif
+#define EINTR 4
+
+#ifdef EIO
+#undef EIO
+#endif
+#define EIO 5
+
+#ifdef EAGAIN
+#undef EAGAIN
+#endif
+#define EAGAIN 11
+
+#ifdef ENOMEM
+#undef ENOMEM
+#endif
+#define ENOMEM 12
+
+#ifdef EINVAL
+#undef EINVAL
+#endif
+#define EINVAL 22
+
+#ifdef EPIPE
+#undef EPIPE
+#endif
+#define EPIPE 32
+
+#endif /* BERRNO_H */
diff --git a/contrib/ffmpeg/build_avopt b/contrib/ffmpeg/build_avopt
new file mode 100755
index 000000000..fcf165765
--- /dev/null
+++ b/contrib/ffmpeg/build_avopt
@@ -0,0 +1,9 @@
+#!/bin/sh
+sed 's/unsigned//g' |\
+ sed 's/enum//g' |\
+ egrep '^ *(int|float|double|AVRational|char *\*) *[a-zA-Z_0-9]* *;' |\
+ sed 's/^ *\([^ ]*\)[ *]*\([^;]*\);.*$/{"\2", NULL, OFFSET(\2), FF_OPT_TYPE_\U\1, DEFAULT, \1_MIN, \1_MAX},/' |\
+ sed 's/AVRATIONAL_M/INT_M/g'|\
+ sed 's/TYPE_AVRATIONAL/TYPE_RATIONAL/g'|\
+ sed 's/FLOAT_M/FLT_M/g'|\
+ sed 's/FF_OPT_TYPE_CHAR/FF_OPT_TYPE_STRING/g'
diff --git a/contrib/ffmpeg/clean-diff b/contrib/ffmpeg/clean-diff
new file mode 100755
index 000000000..98e26a79f
--- /dev/null
+++ b/contrib/ffmpeg/clean-diff
@@ -0,0 +1,11 @@
+#!/bin/sh
+sed '/^+[^+]/!s/ /TaBBaT/g' |\
+ expand -t `seq -s , 9 8 200` |\
+ sed 's/TaBBaT/ /g' |\
+ sed '/^+[^+]/s/ * $//' |\
+ tr -d '\015' |\
+ tr '\n' '°' |\
+ sed 's/\(@@[^@]*@@°[^@]*\)/\n\1/g' |\
+ egrep -v '@@[^@]*@@°(( [^°]*°)|([+-][[:space:]]*°)|(-[[:space:]]*([^°]*)°\+[[:space:]]*\5°))*$' |\
+ tr -d '\n' |\
+ tr '°' '\n'
diff --git a/contrib/ffmpeg/cmdutils.c b/contrib/ffmpeg/cmdutils.c
new file mode 100644
index 000000000..2c53d90da
--- /dev/null
+++ b/contrib/ffmpeg/cmdutils.c
@@ -0,0 +1,141 @@
+/*
+ * Various utilities for command line tools
+ * Copyright (c) 2000-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 HAVE_AV_CONFIG_H
+#include "avformat.h"
+#include "common.h"
+
+#include "cmdutils.h"
+
+void show_help_options(const OptionDef *options, const char *msg, int mask, int value)
+{
+ const OptionDef *po;
+ int first;
+
+ first = 1;
+ for(po = options; po->name != NULL; po++) {
+ char buf[64];
+ if ((po->flags & mask) == value) {
+ if (first) {
+ printf("%s", msg);
+ first = 0;
+ }
+ pstrcpy(buf, sizeof(buf), po->name);
+ if (po->flags & HAS_ARG) {
+ pstrcat(buf, sizeof(buf), " ");
+ pstrcat(buf, sizeof(buf), po->argname);
+ }
+ printf("-%-17s %s\n", buf, po->help);
+ }
+ }
+}
+
+static const OptionDef* find_option(const OptionDef *po, const char *name){
+ while (po->name != NULL) {
+ if (!strcmp(name, po->name))
+ break;
+ po++;
+ }
+ return po;
+}
+
+void parse_options(int argc, char **argv, const OptionDef *options)
+{
+ const char *opt, *arg;
+ int optindex, handleoptions=1;
+ const OptionDef *po;
+
+ /* parse options */
+ optindex = 1;
+ while (optindex < argc) {
+ opt = argv[optindex++];
+
+ if (handleoptions && opt[0] == '-' && opt[1] != '\0') {
+ if (opt[1] == '-' && opt[2] == '\0') {
+ handleoptions = 0;
+ continue;
+ }
+ po= find_option(options, opt + 1);
+ if (!po->name)
+ po= find_option(options, "default");
+ if (!po->name) {
+unknown_opt:
+ fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], opt);
+ exit(1);
+ }
+ arg = NULL;
+ if (po->flags & HAS_ARG) {
+ arg = argv[optindex++];
+ if (!arg) {
+ fprintf(stderr, "%s: missing argument for option '%s'\n", argv[0], opt);
+ exit(1);
+ }
+ }
+ if (po->flags & OPT_STRING) {
+ char *str;
+ str = av_strdup(arg);
+ *po->u.str_arg = str;
+ } else if (po->flags & OPT_BOOL) {
+ *po->u.int_arg = 1;
+ } else if (po->flags & OPT_INT) {
+ *po->u.int_arg = atoi(arg);
+ } else if (po->flags & OPT_FLOAT) {
+ *po->u.float_arg = atof(arg);
+ } else if (po->flags & OPT_FUNC2) {
+ if(po->u.func2_arg(opt+1, arg)<0)
+ goto unknown_opt;
+ } else {
+ po->u.func_arg(arg);
+ }
+ } else {
+ parse_arg_file(opt);
+ }
+ }
+}
+
+void print_error(const char *filename, int err)
+{
+ switch(err) {
+ case AVERROR_NUMEXPECTED:
+ fprintf(stderr, "%s: Incorrect image filename syntax.\n"
+ "Use '%%d' to specify the image number:\n"
+ " for img1.jpg, img2.jpg, ..., use 'img%%d.jpg';\n"
+ " for img001.jpg, img002.jpg, ..., use 'img%%03d.jpg'.\n",
+ filename);
+ break;
+ case AVERROR_INVALIDDATA:
+ fprintf(stderr, "%s: Error while parsing header\n", filename);
+ break;
+ case AVERROR_NOFMT:
+ fprintf(stderr, "%s: Unknown format\n", filename);
+ break;
+ case AVERROR_IO:
+ fprintf(stderr, "%s: I/O error occured\n"
+ "Usually that means that input file is truncated and/or corrupted.\n",
+ filename);
+ break;
+ case AVERROR_NOMEM:
+ fprintf(stderr, "%s: memory allocation error occured\n", filename);
+ break;
+ default:
+ fprintf(stderr, "%s: Error while opening file\n", filename);
+ break;
+ }
+}
diff --git a/contrib/ffmpeg/cmdutils.h b/contrib/ffmpeg/cmdutils.h
new file mode 100644
index 000000000..d9c66f015
--- /dev/null
+++ b/contrib/ffmpeg/cmdutils.h
@@ -0,0 +1,34 @@
+#ifndef _CMD_UTILS_H
+#define _CMD_UTILS_H
+
+typedef struct {
+ const char *name;
+ int flags;
+#define HAS_ARG 0x0001
+#define OPT_BOOL 0x0002
+#define OPT_EXPERT 0x0004
+#define OPT_STRING 0x0008
+#define OPT_VIDEO 0x0010
+#define OPT_AUDIO 0x0020
+#define OPT_GRAB 0x0040
+#define OPT_INT 0x0080
+#define OPT_FLOAT 0x0100
+#define OPT_SUBTITLE 0x0200
+#define OPT_FUNC2 0x0400
+ union {
+ void (*func_arg)(const char *); //FIXME passing error code as int return would be nicer then exit() in the func
+ int *int_arg;
+ char **str_arg;
+ float *float_arg;
+ int (*func2_arg)(const char *, const char *);
+ } u;
+ const char *help;
+ const char *argname;
+} OptionDef;
+
+void show_help_options(const OptionDef *options, const char *msg, int mask, int value);
+void parse_options(int argc, char **argv, const OptionDef *options);
+void parse_arg_file(const char *filename);
+void print_error(const char *filename, int err);
+
+#endif /* _CMD_UTILS_H */
diff --git a/contrib/ffmpeg/common.mak b/contrib/ffmpeg/common.mak
new file mode 100644
index 000000000..d4a8dca41
--- /dev/null
+++ b/contrib/ffmpeg/common.mak
@@ -0,0 +1,100 @@
+#
+# common bits used by all libraries
+#
+
+VPATH = $(SRC_PATH_BARE)/lib$(NAME)
+SRC_DIR = "$(VPATH)"
+
+CFLAGS += -DHAVE_AV_CONFIG_H -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \
+ -D_ISOC9X_SOURCE -I$(BUILD_ROOT) -I$(SRC_PATH) \
+ -I$(SRC_PATH)/libavutil $(OPTFLAGS)
+SRCS := $(OBJS:.o=.c) $(ASM_OBJS:.o=.S) $(CPPOBJS:.o=.cpp)
+OBJS := $(OBJS) $(ASM_OBJS) $(CPPOBJS)
+STATIC_OBJS := $(OBJS) $(STATIC_OBJS)
+SHARED_OBJS := $(OBJS) $(SHARED_OBJS)
+
+all: $(EXTRADEPS) $(LIB) $(SLIBNAME)
+
+$(LIB): $(STATIC_OBJS)
+ rm -f $@
+ $(AR) rc $@ $^ $(EXTRAOBJS)
+ $(RANLIB) $@
+
+$(SLIBNAME): $(SLIBNAME_WITH_MAJOR)
+ ln -sf $^ $@
+
+$(SLIBNAME_WITH_MAJOR): $(SHARED_OBJS)
+ $(CC) $(SHFLAGS) $(LDFLAGS) -o $@ $^ $(EXTRALIBS) $(EXTRAOBJS)
+ $(SLIB_EXTRA_CMD)
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(LIBOBJFLAGS) -c -o $@ $<
+
+%.o: %.S
+ $(CC) $(CFLAGS) $(LIBOBJFLAGS) -c -o $@ $<
+
+# BeOS: remove -Wall to get rid of all the "multibyte constant" warnings
+%.o: %.cpp
+ g++ $(subst -Wall,,$(CFLAGS)) -c -o $@ $<
+
+%: %.o $(LIB)
+ $(CC) $(LDFLAGS) -o $@ $^ $(EXTRALIBS)
+
+depend dep: $(SRCS)
+ $(CC) -MM $(CFLAGS) $^ 1>.depend
+
+clean::
+ rm -f *.o *.d *~ *.a *.lib *.so *.so.* *.dylib *.dll \
+ *.def *.dll.a *.exp
+
+distclean: clean
+ rm -f .depend
+
+ifeq ($(BUILD_SHARED),yes)
+INSTLIBTARGETS += install-lib-shared
+endif
+ifeq ($(BUILD_STATIC),yes)
+INSTLIBTARGETS += install-lib-static
+endif
+
+install: install-libs install-headers
+
+install-libs: $(INSTLIBTARGETS)
+
+install-lib-shared: $(SLIBNAME)
+ install -d "$(shlibdir)"
+ install $(INSTALLSTRIP) -m 755 $(SLIBNAME) \
+ "$(shlibdir)/$(SLIBNAME_WITH_VERSION)"
+ cd "$(shlibdir)" && \
+ ln -sf $(SLIBNAME_WITH_VERSION) $(SLIBNAME_WITH_MAJOR)
+ cd "$(shlibdir)" && \
+ ln -sf $(SLIBNAME_WITH_VERSION) $(SLIBNAME)
+
+install-lib-static: $(LIB)
+ install -d "$(libdir)"
+ install -m 644 $(LIB) "$(libdir)"
+ $(LIB_INSTALL_EXTRA_CMD)
+
+install-headers:
+ install -d "$(incdir)"
+ install -d "$(libdir)/pkgconfig"
+ install -m 644 $(addprefix $(SRC_DIR)/,$(HEADERS)) "$(incdir)"
+ install -m 644 $(BUILD_ROOT)/lib$(NAME).pc "$(libdir)/pkgconfig"
+
+uninstall: uninstall-libs uninstall-headers
+
+uninstall-libs:
+ -rm -f "$(shlibdir)/$(SLIBNAME_WITH_MAJOR)" \
+ "$(shlibdir)/$(SLIBNAME)" \
+ "$(shlibdir)/$(SLIBNAME_WITH_VERSION)"
+ -rm -f "$(libdir)/$(LIB)"
+
+uninstall-headers:
+ rm -f $(addprefix "$(incdir)/",$(HEADERS))
+ rm -f "$(libdir)/pkgconfig/lib$(NAME).pc"
+
+.PHONY: all depend dep clean distclean install* uninstall*
+
+ifneq ($(wildcard .depend),)
+include .depend
+endif
diff --git a/contrib/ffmpeg/configure b/contrib/ffmpeg/configure
new file mode 100755
index 000000000..8da8f0916
--- /dev/null
+++ b/contrib/ffmpeg/configure
@@ -0,0 +1,2186 @@
+#!/bin/sh
+#
+# FFmpeg configure script
+#
+# Copyright (c) 2000, 2001, 2002 Fabrice Bellard
+# Copyright (c) 2005-2006 Diego Biurrun
+# Copyright (c) 2005-2006 Mans Rullgard
+#
+
+# make sure we are running under a compatible shell
+# try to make this part work with most shells
+
+try_exec(){
+ type "$1" >/dev/null 2>&1 && exec "$@"
+}
+
+unset foo
+(: ${foo%%bar}) 2>/dev/null && ! (: ${foo?}) 2>/dev/null
+if test "$?" != 0; then
+ export FF_CONF_EXEC
+ if test "0$FF_CONF_EXEC" -lt 1; then
+ FF_CONF_EXEC=1
+ try_exec bash "$0" "$@"
+ fi
+ if test "0$FF_CONF_EXEC" -lt 2; then
+ FF_CONF_EXEC=2
+ try_exec ksh "$0" "$@"
+ fi
+ if test "0$FF_CONF_EXEC" -lt 3; then
+ FF_CONF_EXEC=3
+ try_exec /usr/xpg4/bin/sh "$0" "$@"
+ fi
+ echo "No compatible shell script interpreter found."
+ echo "This configure script requires a POSIX compatible shell"
+ echo "such as bash or ksh."
+ if test "$BASH_VERSION" = '2.04.0(1)-release'; then
+ echo "This bash version ($BASH_VERSION) is broken on your platform."
+ echo "Upgrade to a later version if available."
+ fi
+ exit 1
+fi
+
+show_help(){
+ echo "Usage: configure [options]"
+ echo "Options: [defaults in brackets after descriptions]"
+ echo
+ echo "Standard options:"
+ echo " --help print this message"
+ echo " --log[=FILE|yes|no] log tests and output to FILE [config.err]"
+ echo " --prefix=PREFIX install in PREFIX [$PREFIX]"
+ echo " --libdir=DIR install libs in DIR [PREFIX/lib]"
+ echo " --shlibdir=DIR install shared libs in DIR [PREFIX/lib]"
+ echo " --incdir=DIR install includes in DIR [PREFIX/include/ffmpeg]"
+ echo " --mandir=DIR install man page in DIR [PREFIX/man]"
+ echo " --enable-mp3lame enable MP3 encoding via libmp3lame [default=no]"
+ echo " --enable-libnut enable NUT support via libnut [default=no]"
+ echo " --enable-libogg enable Ogg support via libogg [default=no]"
+ echo " --enable-vorbis enable Vorbis support via libvorbis [default=no]"
+ echo " --enable-faad enable FAAD support via libfaad [default=no]"
+ echo " --enable-faadbin build FAAD support with runtime linking [default=no]"
+ echo " --enable-faac enable FAAC support via libfaac [default=no]"
+ echo " --enable-libgsm enable GSM support via libgsm [default=no]"
+ echo " --enable-xvid enable XviD support via xvidcore [default=no]"
+ echo " --enable-x264 enable H.264 encoding via x264 [default=no]"
+ echo " --enable-mingw32 enable MinGW native/cross Windows compile"
+ echo " --enable-mingwce enable MinGW native/cross WinCE compile"
+ echo " --enable-a52 enable GPLed A52 support [default=no]"
+ echo " --enable-a52bin open liba52.so.0 at runtime [default=no]"
+ echo " --enable-dts enable GPLed DTS support [default=no]"
+ echo " --enable-pp enable GPLed postprocessing support [default=no]"
+ echo " --enable-static build static libraries [default=yes]"
+ echo " --disable-static do not build static libraries [default=no]"
+ echo " --enable-shared build shared libraries [default=no]"
+ echo " --disable-shared do not build shared libraries [default=yes]"
+ echo " --enable-amr_nb enable amr_nb float audio codec"
+ echo " --enable-amr_nb-fixed use fixed point for amr-nb codec"
+ echo " --enable-amr_wb enable amr_wb float audio codec"
+ echo " --enable-amr_if2 enable amr_wb IF2 audio codec"
+ echo " --enable-sunmlib use Sun medialib [default=no]"
+ echo " --enable-pthreads use pthreads [default=no]"
+ echo " --enable-dc1394 enable IIDC-1394 grabbing using libdc1394"
+ echo " and libraw1394 [default=no]"
+ echo " --enable-swscaler software scaler support [default=no]"
+ echo " --enable-avisynth allow reading AVISynth script files [default=no]"
+ echo " --enable-gpl allow use of GPL code, the resulting libav*"
+ echo " and ffmpeg will be under GPL [default=no]"
+ echo ""
+ echo "Advanced options (experts only):"
+ echo " --source-path=PATH path to source code [$source_path]"
+ echo " --build-path=PATH path to build directory [.]"
+ echo " --cross-prefix=PREFIX use PREFIX for compilation tools [$cross_prefix]"
+ echo " --cross-compile assume a cross-compiler is used"
+ echo " --cc=CC use C compiler CC [$cc]"
+ echo " --make=MAKE use specified make [$make]"
+ echo " --extra-cflags=ECFLAGS add ECFLAGS to CFLAGS [$CFLAGS]"
+ echo " --extra-ldflags=ELDFLAGS add ELDFLAGS to LDFLAGS [$LDFLAGS]"
+ echo " --extra-libs=ELIBS add ELIBS [$ELIBS]"
+ echo " --build-suffix=SUFFIX suffix for application specific build []"
+ echo " --arch=ARCH select architecture [$arch]"
+ echo " --cpu=CPU selects the minimum cpu required (affects
+ instruction selection, may crash on older CPUs)"
+ echo " --powerpc-perf-enable enable performance report on PPC"
+ echo " (requires enabling PMC)"
+ echo " --disable-mmx disable MMX usage"
+ echo " --disable-armv5te disable armv5te usage"
+ echo " --disable-iwmmxt disable iwmmxt usage"
+ echo " --disable-altivec disable AltiVec usage"
+ echo " --disable-audio-oss disable OSS audio support [default=no]"
+ echo " --disable-audio-beos disable BeOS audio support [default=no]"
+ echo " --disable-v4l disable video4linux grabbing [default=no]"
+ echo " --disable-v4l2 disable video4linux2 grabbing [default=no]"
+ echo " --disable-bktr disable bktr video grabbing [default=no]"
+ echo " --disable-dv1394 disable DV1394 grabbing [default=no]"
+ echo " --disable-network disable network support [default=no]"
+ echo " --disable-ipv6 disable ipv6 support [default=no]"
+ echo " --disable-zlib disable zlib [default=no]"
+ echo " --disable-vhook disable video hooking support"
+ echo " --enable-gprof enable profiling with gprof [$gprof]"
+ echo " --disable-debug disable debugging symbols"
+ echo " --disable-opts disable compiler optimizations"
+ echo " --enable-extra-warnings enable more compiler warnings"
+ echo " --disable-mpegaudio-hp faster (but less accurate)"
+ echo " MPEG audio decoding [default=no]"
+ echo " --disable-protocols disable I/O protocols support [default=no]"
+ echo " --disable-ffmpeg disable ffmpeg build"
+ echo " --disable-ffserver disable ffserver build"
+ echo " --disable-ffplay disable ffplay build"
+ echo " --enable-small optimize for size instead of speed"
+ echo " --enable-memalign-hack emulate memalign, interferes with memory debuggers"
+ echo " --disable-strip disable stripping of executables and shared libraries"
+ echo " --disable-encoder=NAME disables encoder NAME"
+ echo " --enable-encoder=NAME enables encoder NAME"
+ echo " --disable-decoder=NAME disables decoder NAME"
+ echo " --enable-decoder=NAME enables decoder NAME"
+ echo " --disable-encoders disables all encoders"
+ echo " --disable-decoders disables all decoders"
+ echo " --disable-muxer=NAME disables muxer NAME"
+ echo " --enable-muxer=NAME enables muxer NAME"
+ echo " --disable-muxers disables all muxers"
+ echo " --disable-demuxer=NAME disables demuxer NAME"
+ echo " --enable-demuxer=NAME enables demuxer NAME"
+ echo " --disable-demuxers disables all demuxers"
+ echo " --enable-parser=NAME enables parser NAME"
+ echo " --disable-parser=NAME disables parser NAME"
+ echo " --disable-parsers disables all parsers"
+ echo ""
+ echo "NOTE: Object files are built at the place where configure is launched."
+ exit 1
+}
+
+log(){
+ echo "$@" >>$logfile
+}
+
+log_file(){
+ log BEGIN $1
+ cat -n $1 >>$logfile
+ log END $1
+}
+
+echolog(){
+ log "$@"
+ echo "$@"
+}
+
+die(){
+ echolog "$@"
+ cat <<EOF
+If you think configure made a mistake, make sure you are using the latest
+version from SVN. If the latest version fails, report the problem to the
+ffmpeg-devel@mplayerhq.hu mailing list or IRC #ffmpeg on irc.freenode.net.
+EOF
+ if enabled logging; then
+ cat <<EOF
+Include the log file "$logfile" produced by configure as this will help
+solving the problem.
+EOF
+ else
+cat <<EOF
+Rerun configure with logging enabled (do not use --log=no), and include the
+log this produces with your report.
+EOF
+ fi
+ rm -f $TMPC $TMPO $TMPE $TMPS $TMPH
+ exit 1
+}
+
+# "tr '[a-z]' '[A-Z]'" is a workaround for Solaris tr not grokking "tr a-z A-Z"
+toupper(){
+ echo "$@" | tr '[a-z]' '[A-Z]'
+}
+
+set_all(){
+ value=$1
+ shift
+ for var in $*; do
+ eval $var=$value
+ done
+}
+
+enable(){
+ set_all yes $*
+}
+
+disable(){
+ set_all no $*
+}
+
+enabled(){
+ eval test "x\$$1" = "xyes"
+}
+
+enabled_all(){
+ for opt; do
+ enabled $opt || return 1
+ done
+}
+
+enabled_any(){
+ for opt; do
+ enabled $opt && return 0
+ done
+}
+
+print_config(){
+ pfx=$1
+ header=$2
+ makefile=$3
+ shift 3
+ for cfg; do
+ if enabled $cfg; then
+ ucname="${pfx}`toupper $cfg`"
+ echo "#define ${ucname} 1" >> $header
+ echo "${ucname}=yes" >> $makefile
+ fi
+ done
+}
+
+flags_saved(){
+ (: ${SAVE_CFLAGS?}) 2>/dev/null
+}
+
+save_flags(){
+ flags_saved && return
+ SAVE_CFLAGS="$CFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+ SAVE_extralibs="$extralibs"
+}
+
+restore_flags(){
+ CFLAGS="$SAVE_CFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
+ extralibs="$SAVE_extralibs"
+ unset SAVE_CFLAGS
+ unset SAVE_LDFLAGS
+ unset SAVE_extralibs
+}
+
+temp_cflags(){
+ save_flags
+ CFLAGS="$CFLAGS $*"
+}
+
+temp_ldflags(){
+ save_flags
+ LDFLAGS="$LDFLAGS $*"
+}
+
+temp_extralibs(){
+ save_flags
+ extralibs="$extralibs $*"
+}
+
+append(){
+ var=$1
+ shift
+ flags_saved && eval "SAVE_$var=\"\$SAVE_$var $*\""
+ eval "$var=\"\$$var $*\""
+}
+
+add_cflags(){
+ append CFLAGS "$@"
+}
+
+add_ldflags(){
+ append LDFLAGS "$@"
+}
+
+add_extralibs(){
+ append extralibs "$@"
+}
+
+check_cmd(){
+ log "$@"
+ "$@" >>$logfile 2>&1
+}
+
+check_cc(){
+ log check_cc "$@"
+ cat >$TMPC
+ log_file $TMPC
+ check_cmd $cc $CFLAGS "$@" -c -o $TMPO $TMPC
+}
+
+check_cpp(){
+ log check_cpp "$@"
+ cat >$TMPC
+ log_file $TMPC
+ check_cmd $cc $CFLAGS "$@" -E -o $TMPO $TMPC
+}
+
+check_ld(){
+ log check_ld "$@"
+ check_cc || return
+ check_cmd $cc $LDFLAGS "$@" -o $TMPE $TMPO $extralibs
+}
+
+check_cflags(){
+ log check_cflags "$@"
+ check_cc "$@" <<EOF && add_cflags "$@"
+int x;
+EOF
+}
+
+check_ldflags(){
+ log check_ldflags "$@"
+ check_ld "$@" <<EOF && add_ldflags "$@"
+int main(){
+ return 0;
+}
+EOF
+}
+
+check_header(){
+ log check_header "$@"
+ header=$1
+ shift
+ check_cpp "$@" <<EOF
+#include <$header>
+int x;
+EOF
+ err=$?
+ var=`echo $header | sed 's/[^[:alnum:]]/_/g'`
+ test "$err" = 0 && enable $var || disable $var
+ return $err
+}
+
+check_func(){
+ log check_func "$@"
+ func=$1
+ shift
+ check_ld "$@" <<EOF
+extern int $func();
+int main(){
+ $func();
+}
+EOF
+ err=$?
+ test "$err" = 0 && enable $func || disable $func
+ return $err
+}
+
+check_lib(){
+ log check_lib "$@"
+ header="$1"
+ func="$2"
+ shift 2
+ temp_extralibs "$@"
+ check_header $header && check_func $func && add_extralibs "$@"
+ err=$?
+ restore_flags
+ return $err
+}
+
+check_exec(){
+ check_ld "$@" && { test "$cross_compile" = yes || $TMPE >>$logfile 2>&1; }
+}
+
+require(){
+ name="$1"
+ header="$2"
+ func="$3"
+ shift 3
+ check_lib $header $func "$@" || die "ERROR: $name not found"
+}
+
+CONFIG_LIST='
+ encoders
+ decoders
+ parsers
+ muxers
+ demuxers
+ a52
+ a52bin
+ amr
+ amr_nb
+ amr_nb_fixed
+ amr_wb
+ audio_beos
+ audio_oss
+ avisynth
+ beos_netserver
+ bktr
+ dc1394
+ dts
+ dv1394
+ faac
+ faad
+ faadbin
+ ffmpeg
+ ffplay
+ ffserver
+ gpl
+ ipv6
+ libgsm
+ libnut
+ libogg
+ libvorbis
+ memalign_hack
+ mp3lame
+ mpegaudio_hp
+ network
+ pp
+ protocols
+ swscaler
+ vhook
+ video4linux
+ video4linux2
+ wince
+ x264
+ xvid
+ zlib
+'
+
+HAVE_LIST='
+ altivec_h
+ beosthreads
+ byteswap_h
+ dcbzl
+ dlfcn_h
+ dlopen
+ freetype2
+ gprof
+ imlib2
+ inet_aton
+ localtime_r
+ lrintf
+ malloc_h
+ memalign
+ mlib
+ os2
+ os2threads
+ pthreads
+ sdl
+ sdl_video_size
+ threads
+ w32threads
+'
+
+# set temporary file name
+if test ! -z "$TMPDIR" ; then
+ TMPDIR1="${TMPDIR}"
+elif test ! -z "$TEMPDIR" ; then
+ TMPDIR1="${TEMPDIR}"
+else
+ TMPDIR1="/tmp"
+fi
+
+TMPC="${TMPDIR1}/ffmpeg-conf-${RANDOM}-$$-${RANDOM}.c"
+TMPO="${TMPDIR1}/ffmpeg-conf-${RANDOM}-$$-${RANDOM}.o"
+TMPE="${TMPDIR1}/ffmpeg-conf-${RANDOM}-$$-${RANDOM}"
+TMPS="${TMPDIR1}/ffmpeg-conf-${RANDOM}-$$-${RANDOM}.S"
+TMPH="${TMPDIR1}/ffmpeg-conf-${RANDOM}-$$-${RANDOM}.h"
+
+# default parameters
+logging="yes"
+logfile="config.err"
+PREFIX="/usr/local"
+libdir='${PREFIX}/lib'
+shlibdir="$libdir"
+incdir='${PREFIX}/include/ffmpeg'
+mandir='${PREFIX}/man'
+bindir='${PREFIX}/bin'
+cross_prefix=""
+cross_compile="no"
+cc="gcc"
+ar="ar"
+ranlib="ranlib"
+make="make"
+strip="strip"
+arch=`uname -m`
+cpu="generic"
+powerpc_perf="no"
+mmx="default"
+cmov="no"
+cmov_is_fast="no"
+armv5te="default"
+iwmmxt="default"
+altivec="default"
+dcbzl="no"
+mmi="default"
+case "$arch" in
+ i386|i486|i586|i686|i86pc|BePC)
+ arch="x86_32"
+ ;;
+ x86_64|amd64)
+ arch="x86_32"
+ canon_arch="`$cc -dumpmachine | sed -e 's,\([^-]*\)-.*,\1,'`"
+ if [ x"$canon_arch" = x"x86_64" -o x"$canon_arch" = x"amd64" ]; then
+ if [ -z "`echo $CFLAGS | grep -- -m32`" ]; then
+ arch="x86_64"
+ fi
+ fi
+ ;;
+ # armv4l is a subset of armv[567]*l
+ arm|armv[4567]*l)
+ arch="armv4l"
+ ;;
+ alpha)
+ arch="alpha"
+ ;;
+ "Power Macintosh"|ppc|ppc64|powerpc)
+ arch="powerpc"
+ ;;
+ mips|mipsel|IP*)
+ arch="mips"
+ ;;
+ sun4u|sparc64)
+ arch="sparc64"
+ ;;
+ sparc)
+ arch="sparc"
+ ;;
+ sh4)
+ arch="sh4"
+ ;;
+ parisc|parisc64)
+ arch="parisc"
+ ;;
+ s390|s390x)
+ arch="s390"
+ ;;
+ m68k)
+ arch="m68k"
+ ;;
+ ia64)
+ arch="ia64"
+ ;;
+ bfin)
+ arch="bfin"
+ ;;
+ *)
+ arch="unknown"
+ ;;
+esac
+gprof="no"
+video4linux="yes"
+video4linux2="yes"
+bktr="no"
+audio_oss="yes"
+audio_beos="no"
+dv1394="yes"
+dc1394="no"
+network="yes"
+ipv6="yes"
+zlib="yes"
+libgsm="no"
+mp3lame="no"
+libnut="no"
+libogg="no"
+libvorbis="no"
+faad="no"
+faadbin="no"
+faac="no"
+xvid="no"
+x264="no"
+a52="no"
+a52bin="no"
+dts="no"
+pp="no"
+mingw32="no"
+wince="no"
+os2="no"
+lstatic="yes"
+lshared="no"
+optimize="yes"
+debug="yes"
+extrawarnings="no"
+dostrip="yes"
+installstrip="-s"
+extralibs="-lm"
+bigendian="no"
+vhook="default"
+avisynth="no"
+dlfcn_h="no"
+dlopen="no"
+mpegaudio_hp="yes"
+SHFLAGS='-shared -Wl,-soname,$@'
+VHOOKSHFLAGS='$(SHFLAGS)'
+beos_netserver="no"
+protocols="yes"
+ffmpeg="yes"
+ffserver="yes"
+ffplay="yes"
+LIBOBJFLAGS=""
+FFLDFLAGS=-Wl,--warn-common
+LDLATEFLAGS='-Wl,-rpath-link,\$(BUILD_ROOT)/libavcodec -Wl,-rpath-link,\$(BUILD_ROOT)/libavformat -Wl,-rpath-link,\$(BUILD_ROOT)/libavutil'
+FFSERVERLDFLAGS=-Wl,-E
+LDCONFIG="ldconfig"
+LIBPREF="lib"
+LIBSUF=".a"
+LIB='$(LIBPREF)$(NAME)$(LIBSUF)'
+SLIBPREF="lib"
+SLIBSUF=".so"
+SLIBNAME='$(SLIBPREF)$(NAME)$(SLIBSUF)'
+SLIBNAME_WITH_VERSION='$(SLIBNAME).$(LIBVERSION)'
+SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
+EXESUF=""
+BUILDSUF=""
+amr_nb="no"
+amr_wb="no"
+amr_nb_fixed="no"
+amr_if2="no"
+mlib="no"
+pthreads="no"
+swscaler="no"
+gpl="no"
+memalign_hack="no"
+asmalign_pot="unknown"
+LIB_INSTALL_EXTRA_CMD='$(RANLIB) "$(libdir)/$(LIB)"'
+
+# OS specific
+targetos=`uname -s`
+case $targetos in
+BeOS)
+PREFIX="/boot/home/config"
+# helps building libavcodec
+add_cflags "-DPIC -fomit-frame-pointer"
+# 3 gcc releases known for BeOS, each with ugly bugs
+gcc_version="`$cc -v 2>&1 | grep version | cut -d ' ' -f3-`"
+case "$gcc_version" in
+2.9-beos-991026*|2.9-beos-000224*) echo "R5/GG gcc"
+mmx="no"
+;;
+*20010315*) echo "BeBits gcc"
+add_cflags "-fno-expensive-optimizations"
+;;
+esac
+SHFLAGS=-nostart
+# disable Linux things
+audio_oss="no"
+video4linux="no"
+video4linux2="no"
+dv1394="no"
+# enable BeOS things
+audio_beos="yes"
+beosthreads="yes"
+# no need for libm, but the inet stuff
+# Check for BONE
+if (echo $BEINCLUDES|grep 'headers/be/bone' >/dev/null); then
+extralibs="-lbind -lsocket"
+else
+beos_netserver="yes"
+extralibs="-lnet"
+fi ;;
+SunOS)
+video4linux="no"
+video4linux2="no"
+audio_oss="no"
+dv1394="no"
+make="gmake"
+FFLDFLAGS=""
+FFSERVERLDFLAGS=""
+SHFLAGS="-shared -Wl,-h,\$@"
+add_extralibs "-lsocket -lnsl"
+;;
+NetBSD)
+video4linux="no"
+video4linux2="no"
+bktr="yes"
+audio_oss="yes"
+dv1394="no"
+make="gmake"
+add_extralibs "-lossaudio"
+;;
+OpenBSD)
+video4linux="no"
+video4linux2="no"
+bktr="yes"
+audio_oss="yes"
+dv1394="no"
+make="gmake"
+LIBOBJFLAGS="\$(PIC)"
+LDCONFIG="ldconfig -m \$(shlibdir)"
+add_extralibs "-lossaudio"
+;;
+FreeBSD)
+video4linux="no"
+video4linux2="no"
+bktr="yes"
+audio_oss="yes"
+dv1394="no"
+make="gmake"
+add_cflags "-pthread"
+;;
+GNU/kFreeBSD)
+video4linux="no"
+video4linux2="no"
+bktr="yes"
+audio_oss="yes"
+dv1394="no"
+add_cflags "-pthread"
+;;
+BSD/OS)
+video4linux="no"
+video4linux2="no"
+bktr="yes"
+audio_oss="yes"
+dv1394="no"
+extralibs="-lpoll -lgnugetopt -lm"
+make="gmake"
+strip="strip -d"
+installstrip=""
+;;
+Darwin)
+cc="cc"
+video4linux="no"
+video4linux2="no"
+audio_oss="no"
+dv1394="no"
+SHFLAGS="-dynamiclib -Wl,-single_module -Wl,-install_name,\$(shlibdir)/\$(SLIBNAME),-current_version,\$(SPPVERSION),-compatibility_version,\$(SPPVERSION)"
+VHOOKSHFLAGS='-dynamiclib -Wl,-single_module -flat_namespace -undefined suppress -Wl,-install_name,$(shlibdir)/vhook/$@'
+extralibs=""
+strip="strip -x"
+installstrip=""
+FFLDFLAGS="-Wl,-dynamic,-search_paths_first"
+SLIBSUF=".dylib"
+SLIBNAME_WITH_FULLVERSION='$(SLIBPREF)$(NAME).$(LIBVERSION)$(SLIBSUF)'
+SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(NAME).$(LIBMAJOR)$(SLIBSUF)'
+FFSERVERLDFLAGS=-Wl,-bind_at_load
+LIB_INSTALL_EXTRA_CMD='$(RANLIB) "$(libdir)/$(LIB)"'
+;;
+MINGW32*)
+# Note: the rest of the mingw32 config is done afterwards as mingw32
+# can be forced on the command line for Linux cross compilation.
+mingw32="yes"
+;;
+CYGWIN*)
+targetos=CYGWIN
+shlibdir='${PREFIX}/bin'
+video4linux="no"
+video4linux2="no"
+audio_oss="yes"
+dv1394="no"
+VHOOKSHFLAGS='-shared -L$(BUILD_ROOT)/libavformat -L$(BUILD_ROOT)/libavcodec -L$(BUILD_ROOT)/libavutil'
+VHOOKLIBS='-lavformat$(BUILDSUF) -lavcodec$(BUILDSUF) -lavutil$(BUILDSUF) $(EXTRALIBS)'
+extralibs=""
+EXESUF=".exe"
+SLIBPREF="cyg"
+SLIBSUF=".dll"
+SLIBNAME_WITH_VERSION='$(SLIBPREF)$(NAME)-$(LIBVERSION)$(SLIBSUF)'
+SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(NAME)-$(LIBMAJOR)$(SLIBSUF)'
+SHFLAGS='-shared -Wl,--out-implib=lib$(NAME).dll.a'
+;;
+Linux)
+LDLATEFLAGS="-Wl,--as-needed $LDLATEFLAGS"
+;;
+IRIX*)
+targetos=IRIX
+ranlib="echo ignoring ranlib"
+video4linux="no"
+video4linux2="no"
+audio_oss="no"
+make="gmake"
+;;
+OS/2)
+TMPE=$TMPE".exe"
+ar="emxomfar -p128"
+ranlib="echo ignoring ranlib"
+strip="echo ignoring strip"
+add_cflags "-Zomf"
+FFLDFLAGS="-Zomf -Zstack 16384 -s"
+SHFLAGS="-Zdll -Zomf"
+FFSERVERLDFLAGS=""
+LIBPREF=""
+LIBSUF=".lib"
+SLIBPREF=""
+SLIBSUF=".dll"
+EXESUF=".exe"
+extralibs=""
+pkg_requires=""
+video4linux="no"
+video4linux2="no"
+audio_oss="no"
+dv1394="no"
+ffserver="no"
+vhook="no"
+os2="yes"
+os2threads="yes"
+;;
+*)
+targetos="${targetos}-UNKNOWN"
+;;
+esac
+
+# find source path
+source_path="`dirname \"$0\"`"
+source_path_used="yes"
+if test -z "$source_path" -o "$source_path" = "." ; then
+ source_path="`pwd`"
+ source_path_used="no"
+else
+ source_path="`cd \"$source_path\"; pwd`"
+ echo "$source_path" | grep -q '[[:blank:]]' &&
+ die "Out of tree builds are impossible with whitespace in source path."
+fi
+
+if test x"$1" = x"-h" -o x"$1" = x"--help" ; then
+ show_help
+fi
+
+FFMPEG_CONFIGURATION=" "
+for opt do
+ FFMPEG_CONFIGURATION="$FFMPEG_CONFIGURATION""$opt "
+done
+
+ENCODER_LIST=`sed -n 's/^[^#]*ENC.*, *\(.*\)).*/\1_encoder/p' "$source_path/libavcodec/allcodecs.c"`
+DECODER_LIST=`sed -n 's/^[^#]*DEC.*, *\(.*\)).*/\1_decoder/p' "$source_path/libavcodec/allcodecs.c"`
+PARSER_LIST=`sed -n 's/^[^#]*PARSER.*, *\(.*\)).*/\1_parser/p' "$source_path/libavcodec/allcodecs.c"`
+MUXER_LIST=`sed -n 's/^[^#]*_MUX.*, *\(.*\)).*/\1_muxer/p' "$source_path/libavformat/allformats.c"`
+DEMUXER_LIST=`sed -n 's/^[^#]*DEMUX.*, *\(.*\)).*/\1_demuxer/p' "$source_path/libavformat/allformats.c"`
+
+enable $ENCODER_LIST $DECODER_LIST $PARSER_LIST $MUXER_LIST $DEMUXER_LIST
+
+for opt do
+ optval="${opt#*=}"
+ case "$opt" in
+ --log)
+ ;;
+ --log=*) logging="$optval"
+ ;;
+ --prefix=*) PREFIX="$optval"; force_prefix=yes
+ ;;
+ --libdir=*) libdir="$optval"; force_libdir=yes
+ ;;
+ --shlibdir=*) shlibdir="$optval"
+ ;;
+ --incdir=*) incdir="$optval"
+ ;;
+ --mandir=*) mandir="$optval"
+ ;;
+ --source-path=*) source_path="$optval"
+ ;;
+ --build-path=*) build_path="$optval"
+ ;;
+ --cross-prefix=*) cross_prefix="$optval"
+ ;;
+ --cross-compile) cross_compile=yes
+ ;;
+ --cc=*) cc="$optval"
+ ;;
+ --make=*) make="$optval"
+ ;;
+ --extra-cflags=*) add_cflags "$optval"
+ ;;
+ --extra-ldflags=*) add_ldflags "$optval"
+ ;;
+ --extra-libs=*) add_extralibs "$optval"
+ ;;
+ --build-suffix=*) BUILDSUF="$optval"
+ ;;
+ --arch=*) arch="$optval"
+ ;;
+ --cpu=*) cpu="$optval"
+ ;;
+ --powerpc-perf-enable) powerpc_perf="yes"
+ ;;
+ --disable-mmx) mmx="no"
+ ;;
+ --disable-armv5te) armv5te="no"
+ ;;
+ --disable-iwmmxt) iwmmxt="no"
+ ;;
+ --disable-altivec) altivec="no"
+ ;;
+ --enable-gprof) gprof="yes"
+ ;;
+ --disable-v4l) video4linux="no"
+ ;;
+ --disable-v4l2) video4linux2="no"
+ ;;
+ --disable-bktr) bktr="no"
+ ;;
+ --disable-audio-oss) audio_oss="no"
+ ;;
+ --disable-audio-beos) audio_beos="no"
+ ;;
+ --disable-dv1394) dv1394="no"
+ ;;
+ --disable-network) network="no"; ffserver="no"
+ ;;
+ --disable-ipv6) ipv6="no";
+ ;;
+ --disable-zlib) zlib="no"
+ ;;
+ --enable-a52) a52="yes"
+ ;;
+ --enable-a52bin) a52bin="yes"
+ ;;
+ --enable-dts) dts="yes"
+ ;;
+ --enable-pp) pp="yes"
+ ;;
+ --enable-libgsm) libgsm="yes"
+ ;;
+ --enable-mp3lame) mp3lame="yes"
+ ;;
+ --enable-libnut) libnut="yes"
+ ;;
+ --enable-libogg) libogg="yes"
+ pkg_requires="$pkg_requires ogg >= 1.1"
+ ;;
+ --enable-vorbis) libvorbis="yes"
+ pkg_requires="$pkg_requires vorbis vorbisenc"
+ ;;
+ --enable-faad) faad="yes"
+ ;;
+ --enable-faadbin) faadbin="yes"
+ ;;
+ --enable-faac) faac="yes"
+ ;;
+ --enable-xvid) xvid="yes"
+ ;;
+ --enable-x264) x264="yes"
+ ;;
+ --enable-avisynth) avisynth="yes";
+ ;;
+ --enable-dc1394) dc1394="yes"
+ pkg_requires="$pkg_requires libraw1394"
+ ;;
+ --disable-vhook) vhook="no"
+ ;;
+ --enable-mingw32) mingw32="yes"
+ ;;
+ --enable-mingwce) wince="yes"
+ ;;
+ --enable-static) lstatic="yes"
+ ;;
+ --disable-static) lstatic="no"
+ ;;
+ --enable-shared) lshared="yes"
+ ;;
+ --disable-shared) lshared="no"
+ ;;
+ --disable-debug) debug="no"
+ ;;
+ --disable-opts) optimize="no"
+ ;;
+ --enable-extra-warnings) extrawarnings="yes"
+ ;;
+ --disable-mpegaudio-hp) mpegaudio_hp="no"
+ ;;
+ --disable-protocols) protocols="no"; network="no"; ffserver="no"
+ ;;
+ --disable-ffmpeg) ffmpeg="no"
+ ;;
+ --disable-ffserver) ffserver="no"
+ ;;
+ --disable-ffplay) ffplay="no"
+ ;;
+ --enable-small) optimize="small"
+ ;;
+ --enable-amr_nb) amr="yes"; amr_nb="yes"; amr_nb_fixed="no"
+ ;;
+ --enable-amr_nb-fixed) amr="yes"; amr_nb_fixed="yes"; amr_nb="no"
+ ;;
+ --enable-amr_wb) amr="yes"; amr_wb="yes"
+ ;;
+ --enable-amr_if2) amr="yes"; amr_if2="yes"
+ ;;
+ --enable-sunmlib) mlib="yes"
+ ;;
+ --enable-pthreads) pthreads="yes"
+ ;;
+ --enable-swscaler) swscaler="yes"
+ ;;
+ --enable-gpl) gpl="yes"
+ ;;
+ --enable-memalign-hack) memalign_hack="yes"
+ ;;
+ --disable-strip) dostrip="no"
+ ;;
+ --enable-encoder=*) enable ${optval}_encoder
+ ;;
+ --enable-decoder=*) enable ${optval}_decoder
+ ;;
+ --disable-encoder=*) disable ${optval}_encoder
+ ;;
+ --disable-decoder=*) disable ${optval}_decoder
+ ;;
+ --disable-encoders) disable $ENCODER_LIST
+ ;;
+ --disable-decoders) disable $DECODER_LIST
+ ;;
+ --enable-muxer=*) enable ${optval}_muxer
+ ;;
+ --disable-muxer=*) disable ${optval}_muxer
+ ;;
+ --disable-muxers) disable $MUXER_LIST; ffserver="no"
+ ;;
+ --enable-demuxer=*) enable ${optval}_demuxer
+ ;;
+ --disable-demuxer=*) disable ${optval}_demuxer
+ ;;
+ --disable-demuxers) disable $DEMUXER_LIST
+ ;;
+ --enable-parser=*) enable ${optval}_parser
+ ;;
+ --disable-parser=*) disable ${optval}_parser
+ ;;
+ --disable-parsers) disable $PARSER_LIST
+ ;;
+ --help) show_help
+ ;;
+ *)
+ echo "Unknown option \"$opt\"."
+ echo "See $0 --help for available options."
+ exit 1
+ ;;
+ esac
+done
+
+cd "$build_path"
+
+if test "$logging" != no; then
+ test "$logging" = yes || logfile="$logging"
+ echo "# $0 $@" >$logfile
+ set >>$logfile
+else
+ logfile=/dev/null
+fi
+
+if test "$mingw32" = "yes" -o "$wince" = "yes"; then
+ if test "$lshared" = "yes" && test "$lstatic" = "yes" ; then
+ cat <<EOF
+You can only build one library type at once on MinGW.
+Specify --disable-static --enable-shared to only build
+the shared libraries. To build only the static libraries
+you do not need to pass additional options.
+EOF
+ exit 1
+ fi
+ video4linux="no"
+ video4linux2="no"
+ bktr="no"
+ audio_oss="no"
+ dv1394="no"
+ dc1394="no"
+ ffserver="no"
+ network="no"
+ if enabled mingw32; then
+ w32threads="yes"
+ fi
+ if test "$wince" = "yes"; then
+ protocols="no"
+ fi
+ SLIBPREF=""
+ SLIBSUF=".dll"
+ EXESUF=".exe"
+ SLIBNAME_WITH_VERSION='$(SLIBPREF)$(NAME)-$(LIBVERSION)$(SLIBSUF)'
+ SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(NAME)-$(LIBMAJOR)$(SLIBSUF)'
+ SLIB_EXTRA_CMD="-lib /machine:i386 /def:\$(@:${SLIBSUF}=.def)"
+ SHFLAGS="-shared -Wl,--output-def,\$(@:${SLIBSUF}=.def),--out-implib,lib\$(SLIBNAME:\$(SLIBSUF)=.dll.a)"
+ if test "$force_prefix" != yes; then PREFIX="$PROGRAMFILES/FFmpeg"; fi
+ if test "$force_libdir" != yes; then bindir='${PREFIX}'; fi
+ shlibdir='${PREFIX}'
+fi
+
+# Combine FFLDFLAGS and the LDFLAGS environment variable.
+LDFLAGS="$FFLDFLAGS $LDFLAGS"
+
+test -n "$cross_prefix" && cross_compile=yes
+cc="${cross_prefix}${cc}"
+ar="${cross_prefix}${ar}"
+ranlib="${cross_prefix}${ranlib}"
+strip="${cross_prefix}${strip}"
+
+# we need to build at least one lib type
+if test "$lstatic" = "no" && test "$lshared" = "no" ; then
+ cat <<EOF
+At least one library type must be built.
+Specify --enable-static to build the static libraries or --enable-shared to
+build the shared libraries as well. To only build the shared libraries specify
+--disable-static in addition to --enable-shared.
+EOF
+ exit 1;
+fi
+
+if test "$libvorbis" = "yes" ; then
+ if test "$libogg" = "no"; then
+ echo "libogg must be enabled to enable Vorbis."
+ fail="yes"
+ fi
+fi
+
+if test "$gpl" != "yes"; then
+ if test "$pp" != "no"; then
+ echo "The Postprocessing code is under GPL and --enable-gpl is not specified."
+ fail="yes"
+ fi
+
+ if test "$a52" != "no" -o "$a52bin" != "no"; then
+ echo "liba52 is under GPL and --enable-gpl is not specified."
+ fail="yes"
+ fi
+
+ if test "$xvid" != "no"; then
+ echo "libxvidcore is under GPL and --enable-gpl is not specified."
+ fail="yes"
+ fi
+
+ if test "$x264" != "no"; then
+ echo "x264 is under GPL and --enable-gpl is not specified."
+ fail="yes"
+ fi
+
+ if test "$dts" != "no"; then
+ echo "libdts is under GPL and --enable-gpl is not specified."
+ fail="yes"
+ fi
+
+ if test "$faad" != "no" -o "$faadbin" != "no"; then
+ if check_header faad.h; then
+ check_cc << EOF
+ #include <faad.h>
+ #ifndef FAAD2_VERSION
+ ok faad1
+ #endif
+ int main( void ) { return 0; }
+EOF
+ if test $? = 0 ; then
+ echo "FAAD2 is under GPL and --enable-gpl is not specified."
+ fail="yes"
+ fi
+ else
+ faad="no"
+ faadbin="no"
+ echo "FAAD test failed."
+ fi
+ fi
+
+ if test "$swscaler" != "no"; then
+ echo "The software scaler is under GPL and --enable-gpl is not specified."
+ fail="yes"
+ fi
+fi
+
+if test "$fail" = "yes"; then
+ exit 1
+fi
+
+# compute MMX state
+if test $mmx = "default"; then
+ if test $arch = "x86_32" -o $arch = "x86_64"; then
+ mmx="yes"
+ else
+ mmx="no"
+ fi
+fi
+
+#Darwin CC versions
+needmdynamicnopic="no"
+if test $targetos = Darwin; then
+ if test -n "`$cc -v 2>&1 | grep xlc`"; then
+ add_cflags "-qpdf2 -qlanglvl=extc99 -qmaxmem=-1 -qarch=auto -qtune=auto"
+ else
+ gcc_version="`$cc -v 2>&1 | grep version | cut -d ' ' -f3-`"
+ case "$gcc_version" in
+ *2.95*)
+ add_cflags "-no-cpp-precomp -pipe"
+ ;;
+ *[34].*)
+ add_cflags "-no-cpp-precomp -pipe -force_cpusubtype_ALL -Wno-sign-compare"
+ if test "$lshared" = no; then
+ needmdynamicnopic="yes"
+ fi
+ ;;
+ *)
+ add_cflags "-no-cpp-precomp -pipe"
+ if test "$lshared" = no; then
+ needmdynamicnopic="yes"
+ fi
+ ;;
+ esac
+ fi
+fi
+
+if test $optimize != "no"; then
+ add_cflags "-fomit-frame-pointer"
+fi
+
+# Can only do AltiVec on PowerPC
+if test $altivec = "default"; then
+ if test $arch = "powerpc"; then
+ altivec="yes"
+ else
+ altivec="no"
+ fi
+fi
+
+# Add processor-specific flags
+POWERPCMODE="32bits"
+if test $cpu != "generic"; then
+ case $cpu in
+ 601|ppc601|PowerPC601)
+ add_cflags "-mcpu=601"
+ if test $altivec = "yes"; then
+ echo "WARNING: Tuning for PPC601 but AltiVec enabled!";
+ fi
+ ;;
+ 603*|ppc603*|PowerPC603*)
+ add_cflags "-mcpu=603"
+ if test $altivec = "yes"; then
+ echo "WARNING: Tuning for PPC603 but AltiVec enabled!";
+ fi
+ ;;
+ 604*|ppc604*|PowerPC604*)
+ add_cflags "-mcpu=604"
+ if test $altivec = "yes"; then
+ echo "WARNING: Tuning for PPC604 but AltiVec enabled!";
+ fi
+ ;;
+ G3|g3|75*|ppc75*|PowerPC75*)
+ add_cflags "-mcpu=750 -mpowerpc-gfxopt"
+ if test $altivec = "yes"; then
+ echo "WARNING: Tuning for PPC75x but AltiVec enabled!";
+ fi
+ ;;
+ G4|g4|745*|ppc745*|PowerPC745*)
+ add_cflags "-mcpu=7450 -mpowerpc-gfxopt"
+ if test $altivec = "no"; then
+ echo "WARNING: Tuning for PPC745x but AltiVec disabled!";
+ fi
+ ;;
+ 74*|ppc74*|PowerPC74*)
+ add_cflags "-mcpu=7400 -mpowerpc-gfxopt"
+ if test $altivec = "no"; then
+ echo "WARNING: Tuning for PPC74xx but AltiVec disabled!";
+ fi
+ ;;
+ G5|g5|970|ppc970|PowerPC970|power4*|Power4*)
+ add_cflags "-mcpu=970 -mpowerpc-gfxopt -mpowerpc64"
+ if test $altivec = "no"; then
+ echo "WARNING: Tuning for PPC970 but AltiVec disabled!";
+ fi
+ POWERPCMODE="64bits"
+ ;;
+ # targets that do NOT support conditional mov (cmov)
+ i[345]86|pentium|pentium-mmx|k6|k6-[23]|winchip-c6|winchip2|c3)
+ add_cflags "-march=$cpu"
+ cmov="no"
+ ;;
+ # targets that do support conditional mov (cmov)
+ i686|pentiumpro|pentium[23]|pentium-m|athlon|athlon-tbird|athlon-4|athlon-[mx]p|athlon64|k8|opteron|athlon-fx)
+ add_cflags "-march=$cpu"
+ cmov="yes"
+ cmov_is_fast="yes"
+ ;;
+ # targets that do support conditional mov but on which it's slow
+ pentium4|prescott|nocona)
+ add_cflags "-march=$cpu"
+ cmov="yes"
+ cmov_is_fast="no"
+ ;;
+ sparc64)
+ add_cflags "-mcpu=v9"
+ ;;
+ *)
+ echo "WARNING: Unknown CPU \"$cpu\", ignored."
+ ;;
+ esac
+fi
+
+# make sure we can execute files in $TMPDIR
+cat >$TMPE 2>>$logfile <<EOF
+#! /bin/sh
+EOF
+chmod +x $TMPE >>$logfile 2>&1
+if ! $TMPE >>$logfile 2>&1; then
+ cat <<EOF
+Unable to create and execute files in $TMPDIR1. Set the TMPDIR environment
+variable to another directory and make sure that $TMPDIR1 is not mounted
+noexec.
+EOF
+ die "Sanity test failed."
+fi
+rm $TMPE
+
+# compiler sanity check
+check_exec <<EOF
+int main(){
+ return 0;
+}
+EOF
+if test "$?" != 0; then
+ echo "$cc is unable to create an executable file."
+ if test -z "$cross_prefix" -a "$cross_compile" = no; then
+ echo "If $cc is a cross-compiler, use the --cross-compile option."
+ echo "Only do this if you know what cross compiling means."
+ fi
+ die "C compiler test failed."
+fi
+
+# check for assembler specific support
+
+if test $arch = "powerpc"; then
+check_cc <<EOF && dcbzl=yes
+int main(void) {
+ register long zero = 0;
+ char data[1024];
+ asm volatile("dcbzl %0, %1" : : "b" (data), "r" (zero));
+return 0;
+}
+EOF
+fi
+
+# check for SIMD availability
+
+# AltiVec flags: The FSF version of GCC differs from the Apple version
+if test $arch = "powerpc"; then
+ if test $altivec = "yes"; then
+ if test -n "`$cc -v 2>&1 | grep version | grep Apple`"; then
+ add_cflags "-faltivec"
+ else
+ add_cflags "-maltivec -mabi=altivec"
+ fi
+ fi
+fi
+
+check_header altivec.h
+
+# check if our compiler supports Motorola AltiVec C API
+if test $altivec = "yes"; then
+ if test $altivec_h = "yes"; then
+ inc_altivec_h="#include <altivec.h>"
+ else
+ inc_altivec_h=
+ fi
+ check_cc <<EOF || altivec=no
+$inc_altivec_h
+int main(void) {
+ vector signed int v1, v2, v3;
+ v1 = vec_add(v2,v3);
+ return 0;
+}
+EOF
+fi
+
+# check armv5te instructions support
+if test $armv5te = "default" -a $arch = "armv4l"; then
+ armv5te=no
+ check_cc <<EOF && armv5te=yes
+ int main(void) {
+ __asm__ __volatile__ ("qadd r0, r0, r0");
+ }
+EOF
+fi
+
+# check iwmmxt support
+if test $iwmmxt = "default" -a $arch = "armv4l"; then
+ iwmmxt=no
+ check_cc <<EOF && iwmmxt=yes
+ int main(void) {
+ __asm__ __volatile__ ("wunpckelub wr6, wr4");
+ }
+EOF
+fi
+
+# mmi only available on mips
+if test $mmi = "default"; then
+ if test $arch = "mips"; then
+ mmi="yes"
+ else
+ mmi="no"
+ fi
+fi
+
+# check if our compiler supports mmi
+enabled mmi && check_cc <<EOF || mmi="no"
+int main(void) {
+ __asm__ ("lq \$2, 0(\$2)");
+ return 0;
+}
+EOF
+
+# ---
+# big/little-endian test
+if test "$cross_compile" = "no"; then
+ check_ld <<EOF || die "endian test failed" && $TMPE && bigendian="yes"
+#include <inttypes.h>
+int main(int argc, char ** argv){
+ volatile uint32_t i=0x01234567;
+ return (*((uint8_t*)(&i))) == 0x67;
+}
+EOF
+else
+ # programs cannot be launched if cross compiling, so make a static guess
+ if test "$arch" = "powerpc" -o "$arch" = "mips" ; then
+ bigendian="yes"
+ fi
+fi
+
+# ---
+# check availability of some header files
+
+check_header malloc.h
+check_func memalign
+
+if test "$memalign" = "no" -a "$mmx" = "yes" -a \
+ "$memalign_hack" != "yes" -a "$targetos" != "Darwin" -a \
+ "$targetos" != "FreeBSD" ; then
+ die "Error, no memalign() but SSE enabled, disable it or use --enable-memalign-hack."
+fi
+
+check_header byteswap.h
+
+check_func inet_aton
+check_func localtime_r
+enabled zlib && check_lib zlib.h zlibVersion -lz || zlib="no"
+
+# check for some common methods of building with pthread support
+# do this before the optional library checks as some of them require pthreads
+if enabled pthreads; then
+ if check_func pthread_create; then
+ :
+ elif check_func pthread_create -pthread; then
+ add_cflags -pthread
+ add_ldflags -pthread
+ elif check_func pthread_create -pthreads; then
+ add_cflags -pthreads
+ add_ldflags -pthreads
+ elif ! check_lib pthread.h pthread_create -lpthread; then
+ die "ERROR: can't find pthreads library"
+ fi
+fi
+
+# these are off by default, so fail if requested and not available
+enabled dts && require libdts dts.h dts_init -ldts -lm
+enabled libgsm && require libgsm gsm.h gsm_create -lgsm
+enabled mp3lame && require LAME lame/lame.h lame_init -lmp3lame -lm
+enabled libvorbis && require libvorbis vorbis/vorbisenc.h vorbis_info_init -lvorbis -lvorbisenc -logg
+enabled libogg && require libogg ogg/ogg.h ogg_sync_init -logg
+enabled libnut && require libnut libnut.h nut_demuxer_init -lnut
+enabled xvid && require XviD xvid.h xvid_global -lxvidcore
+enabled x264 && require x264 x264.h x264_encoder_open -lx264
+enabled dc1394 && require libdc1394 libdc1394/dc1394_control.h dc1394_create_handle -ldc1394_control -lraw1394
+enabled mlib && require mediaLib mlib_types.h mlib_VectorSub_S16_U8_Mod -lmlib
+
+# Ugh, faac uses stdcall calling convention on win32 so we can't use
+# the generic test functions
+if enabled faac; then
+ save_flags
+ temp_extralibs -lfaac
+ check_ld <<EOF && add_extralibs -lfaac || die "ERROR: libfaac not found"
+#include <stdint.h>
+#include <faac.h>
+int main(){
+ char *id, *cpr;
+ faacEncGetVersion(&id, &cpr);
+ return 0;
+}
+EOF
+ restore_flags
+fi
+
+# Ugh, recent faad2 versions have renamed all functions and #define the
+# old names in faad.h. Generic tests won't work.
+if enabled faad; then
+ save_flags
+ temp_extralibs -lfaad
+ check_ld <<EOF && add_extralibs -lfaad || die "ERROR: libfaad not found"
+#include <faad.h>
+int main(){
+ faacDecOpen();
+ return 0;
+}
+EOF
+ restore_flags
+fi
+
+# Ugh, avisynth uses WINAPI calls. Generic tests won't work.
+if enabled avisynth; then
+ save_flags
+ temp_extralibs -lvfw32
+ check_ld <<EOF && add_extralibs -lvfw32 || die "ERROR: vfw32 not found"
+#include <windows.h>
+#include <vfw.h>
+int main(){
+ AVIFileInit();
+ return 0;
+}
+EOF
+ restore_flags
+fi
+
+
+# test for lrintf in math.h
+check_exec <<EOF && lrintf=yes || lrintf=no
+#define _ISOC9X_SOURCE 1
+#include <math.h>
+int main( void ) { return (lrintf(3.999f) > 0)?0:1; }
+EOF
+
+_restrict=
+for restrict_keyword in restrict __restrict__ __restrict; do
+ check_cc <<EOF && _restrict=$restrict_keyword && break
+void foo(char * $restrict_keyword p);
+EOF
+done
+
+# dlopen/dlfcn.h probing
+
+check_header dlfcn.h
+
+if check_func dlopen; then
+ ldl=
+elif check_func dlopen -ldl; then
+ ldl=-ldl
+fi
+
+if test "$vhook" = "default"; then
+ vhook="$dlopen"
+fi
+
+if enabled_any vhook a52bin faadbin; then
+ add_extralibs $ldl
+fi
+
+if test "$targetos" = "CYGWIN" -a "$lstatic" = "yes" ; then
+ vhook="no"
+ echo
+ echo "At the moment vhooks don't work on Cygwin static builds."
+ echo "Patches welcome."
+ echo
+fi
+
+if enabled vhook; then
+ check_ldflags -rdynamic
+ check_ldflags -export-dynamic
+fi
+
+if enabled audio_beos; then
+ add_extralibs "-lmedia -lbe"
+fi
+
+##########################################
+# imlib check
+
+temp_extralibs -lImlib2
+check_ld <<EOF && imlib2=yes || imlib2=no
+#include <X11/Xlib.h>
+#include <Imlib2.h>
+int main( void ) { return (int) imlib_load_font("foo"); }
+EOF
+restore_flags
+
+##########################################
+# FreeType check
+
+freetype2=no
+if test "x$targetos" != "xBeOS"; then
+ if (freetype-config --version) >/dev/null 2>&1 ; then
+ temp_cflags `freetype-config --cflags`
+ temp_extralibs `freetype-config --libs`
+ check_ld <<EOF && freetype2=yes
+#include <ft2build.h>
+int main( void ) { return (int) FT_Init_FreeType(0); }
+EOF
+ restore_flags
+ fi
+fi
+
+##########################################
+# SDL check
+
+sdl_too_old=no
+sdl=no
+SDL_CONFIG="${cross_prefix}sdl-config"
+if ("${SDL_CONFIG}" --version) >/dev/null 2>&1 ; then
+ temp_cflags `"${SDL_CONFIG}" --cflags`
+ temp_extralibs `"${SDL_CONFIG}" --libs`
+ check_ld <<EOF
+#include <SDL.h>
+#undef main /* We don't want SDL to override our main() */
+int main( void ) { return SDL_Init (SDL_INIT_VIDEO); }
+EOF
+ if test $? = 0; then
+ _sdlversion=`"${SDL_CONFIG}" --version | sed 's/[^0-9]//g'`
+ if test "$_sdlversion" -lt 121 ; then
+ sdl_too_old=yes
+ else
+ sdl=yes
+ check_cc <<EOF && sdl_video_size=yes || sdl_video_size=no
+#include <SDL.h>
+int main(void){
+ const SDL_VideoInfo *vi = SDL_GetVideoInfo();
+ int w = vi->current_w;
+ return 0;
+}
+EOF
+ fi
+ fi
+ restore_flags
+fi
+
+enabled sdl || ffplay=no
+
+##########################################
+# texi2html check
+
+texi2html=no
+if (texi2html -version) >/dev/null 2>&1; then
+texi2html=yes
+fi
+
+##########################################
+# IPv6 check
+
+enabled network && enabled ipv6 && check_ld <<EOF && ipv6=yes || ipv6=no
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+int main( void ) {
+ struct sockaddr_storage saddr;
+ struct ipv6_mreq mreq6;
+ getaddrinfo(0,0,0,0);
+ getnameinfo(0,0,0,0,0,0,0);
+ IN6_IS_ADDR_MULTICAST((const struct in6_addr *)0);
+}
+EOF
+
+# check for video4linux2 --- V4L2_PIX_FMT_YUV420
+enabled video4linux2 && check_cc <<EOF || video4linux2="no"
+#include <sys/time.h>
+#include <asm/types.h>
+#include <linux/videodev2.h>
+int dummy = V4L2_PIX_FMT_YUV420;
+struct v4l2_buffer dummy1;
+EOF
+
+enabled debug && add_cflags -g
+
+# add some useful compiler flags if supported
+check_cflags -Wdeclaration-after-statement
+check_cflags -Wall
+check_cflags -Wno-switch
+check_cflags -Wdisabled-optimization
+check_cflags -Wpointer-arith
+check_cflags -Wredundant-decls
+enabled extrawarnings && check_cflags -Winline
+
+# add some linker flags
+check_ldflags $LDLATEFLAGS
+
+# not all compilers support -Os
+test "$optimize" = "small" && check_cflags -Os
+
+if enabled optimize; then
+ if test -n "`$cc -v 2>&1 | grep xlc`"; then
+ add_cflags "-O5"
+ add_ldflags "-O5"
+ else
+ add_cflags "-O3"
+ fi
+fi
+
+# PIC flags for shared library objects where they are needed
+if test "$lshared" = "yes" ; then
+ # LIBOBJFLAGS may have already been set in the OS configuration
+ if test -z "$LIBOBJFLAGS" ; then
+ case "$arch" in
+ x86_64|ia64|alpha|sparc*) LIBOBJFLAGS="\$(PIC)" ;;
+ esac
+ fi
+fi
+
+if test "$gprof" = "yes" ; then
+ add_cflags "-p"
+ add_ldflags "-p"
+fi
+
+VHOOKCFLAGS="-fPIC $CFLAGS"
+test "$needmdynamicnopic" = yes && add_cflags -mdynamic-no-pic
+
+# find if .align arg is power-of-two or not
+if test $asmalign_pot = "unknown"; then
+ asmalign_pot="no"
+ echo 'asm (".align 3");' | check_cc && asmalign_pot="yes"
+fi
+
+echo "install prefix $PREFIX"
+echo "source path $source_path"
+echo "C compiler $cc"
+echo "make $make"
+echo "ARCH $arch ($cpu)"
+if test "$BUILDSUF" != ""; then
+ echo "build suffix $BUILDSUF"
+fi
+echo "big-endian $bigendian"
+if test $arch = "x86_32" -o $arch = "x86_64"; then
+ echo "MMX enabled $mmx"
+ echo "CMOV enabled $cmov"
+ echo "CMOV is fast $cmov_is_fast"
+fi
+if test $arch = "armv4l"; then
+ echo "ARMv5TE enabled $armv5te"
+ echo "IWMMXT enabled $iwmmxt"
+fi
+if test $arch = "mips"; then
+ echo "MMI enabled $mmi"
+fi
+if test $arch = "powerpc"; then
+ echo "AltiVec enabled $altivec"
+ echo "dcbzl available $dcbzl"
+fi
+echo "gprof enabled $gprof"
+echo "zlib enabled $zlib"
+echo "libgsm enabled $libgsm"
+echo "mp3lame enabled $mp3lame"
+echo "libnut enabled $libnut"
+echo "libogg enabled $libogg"
+echo "Vorbis enabled $libvorbis"
+echo "FAAD enabled $faad"
+echo "faadbin enabled $faadbin"
+echo "FAAC enabled $faac"
+echo "XviD enabled $xvid"
+echo "x264 enabled $x264"
+echo "a52 support $a52"
+echo "a52 dlopened $a52bin"
+echo "DTS support $dts"
+echo "pp support $pp"
+echo "Software Scaler enabled $swscaler"
+echo "AVISynth enabled $avisynth"
+echo "debug symbols $debug"
+echo "strip symbols $dostrip"
+echo "optimize $optimize"
+echo "static $lstatic"
+echo "shared $lshared"
+echo "video hooking $vhook"
+echo "SDL support $sdl"
+if test $sdl_too_old = "yes"; then
+ echo "-> Your SDL version is too old - please upgrade to have FFplay/SDL support."
+fi
+
+if test "$vhook" = "yes"; then
+ echo "Imlib2 support $imlib2"
+ echo "FreeType support $freetype2"
+fi
+echo "Sun medialib support" $mlib
+echo "pthreads support" $pthreads
+echo "AMR-NB float support" $amr_nb
+echo "AMR-NB fixed support" $amr_nb_fixed
+echo "AMR-WB float support" $amr_wb
+echo "AMR-WB IF2 support" $amr_if2
+echo "network support $network"
+if test "$network" = "yes" ; then
+ echo "IPv6 support $ipv6"
+fi
+echo ".align is power-of-two" $asmalign_pot
+if test "$gpl" = "no" ; then
+ echo "License: LGPL"
+else
+ echo "License: GPL"
+fi
+
+echo "Creating config.mak and config.h..."
+
+echo "# Automatically generated by configure - do not modify!" > config.mak
+echo "/* Automatically generated by configure - do not modify! */" > $TMPH
+echo "#define FFMPEG_CONFIGURATION "'"'"$FFMPEG_CONFIGURATION"'"' >> $TMPH
+
+echo "PREFIX=$PREFIX" >> config.mak
+echo "prefix=\$(DESTDIR)\${PREFIX}" >> config.mak
+echo "libdir=\$(DESTDIR)$libdir" >> config.mak
+echo "shlibdir=\$(DESTDIR)$shlibdir" >> config.mak
+echo "incdir=\$(DESTDIR)$incdir" >> config.mak
+echo "bindir=\$(DESTDIR)$bindir" >> config.mak
+echo "mandir=\$(DESTDIR)$mandir" >> config.mak
+echo "MAKE=$make" >> config.mak
+echo "CC=$cc" >> config.mak
+echo "AR=$ar" >> config.mak
+echo "RANLIB=$ranlib" >> config.mak
+if test "$dostrip" = "yes" ; then
+ echo "STRIP=$strip" >> config.mak
+ echo "INSTALLSTRIP=$installstrip" >> config.mak
+else
+ echo "STRIP=echo ignoring strip" >> config.mak
+ echo "INSTALLSTRIP=" >> config.mak
+fi
+
+echo "OPTFLAGS=$CFLAGS" >> config.mak
+echo "VHOOKCFLAGS=$VHOOKCFLAGS">>config.mak
+echo "LDFLAGS=$LDFLAGS" >> config.mak
+echo "LDCONFIG=$LDCONFIG" >> config.mak
+echo "FFSERVERLDFLAGS=$FFSERVERLDFLAGS" >> config.mak
+echo "SHFLAGS=$SHFLAGS" >> config.mak
+echo "VHOOKSHFLAGS=$VHOOKSHFLAGS" >> config.mak
+echo "VHOOKLIBS=$VHOOKLIBS" >> config.mak
+echo "LIBOBJFLAGS=$LIBOBJFLAGS" >> config.mak
+echo "BUILD_STATIC=$lstatic" >> config.mak
+echo "BUILDSUF=$BUILDSUF" >> config.mak
+echo "LIBPREF=$LIBPREF" >> config.mak
+echo "LIBSUF=\${BUILDSUF}$LIBSUF" >> config.mak
+if test "$lstatic" = "yes" ; then
+ echo "LIB=$LIB" >> config.mak
+else # Some Make complain if this variable does not exist.
+ echo "LIB=" >> config.mak
+fi
+echo "SLIBPREF=$SLIBPREF" >> config.mak
+echo "SLIBSUF=\${BUILDSUF}$SLIBSUF" >> config.mak
+echo "EXESUF=\${BUILDSUF}$EXESUF" >> config.mak
+echo "TARGET_OS=$targetos" >> config.mak
+
+ucarch=`toupper $arch`
+echo "TARGET_ARCH_${ucarch}=yes" >> config.mak
+echo "#define ARCH_${ucarch} 1" >> $TMPH
+
+# special cases
+case "$arch" in
+ x86_32|x86_64)
+ echo "TARGET_ARCH_X86=yes" >> config.mak
+ echo "#define ARCH_X86 1" >> $TMPH
+ ;;
+ powerpc)
+ if test "$POWERPCMODE" = "64bits"; then
+ echo "#define POWERPC_MODE_64BITS 1" >> $TMPH
+ fi
+ if test "$powerpc_perf" = "yes"; then
+ echo "#define POWERPC_PERFORMANCE_REPORT 1" >> $TMPH
+ fi
+ ;;
+ sparc64)
+ echo "TARGET_ARCH_SPARC=yes" >> config.mak
+ echo "#define ARCH_SPARC 1" >> $TMPH
+ ;;
+esac
+
+if test "$bigendian" = "yes" ; then
+ echo "WORDS_BIGENDIAN=yes" >> config.mak
+ echo "#define WORDS_BIGENDIAN 1" >> $TMPH
+fi
+if test "$mmx" = "yes" ; then
+ echo "TARGET_MMX=yes" >> config.mak
+ echo "#define HAVE_MMX 1" >> $TMPH
+ echo "#define __CPU__ 586" >> $TMPH
+fi
+if test "$cmov" = "yes" ; then
+ echo "TARGET_CMOV=yes" >> config.mak
+ echo "#define HAVE_CMOV 1" >> $TMPH
+fi
+if test "$cmov_is_fast" = "yes" ; then
+ echo "TARGET_CMOV_IS_FAST=yes" >> config.mak
+ echo "#define CMOV_IS_FAST 1" >> $TMPH
+fi
+if test "$armv5te" = "yes" ; then
+ echo "TARGET_ARMV5TE=yes" >> config.mak
+ echo "#define HAVE_ARMV5TE 1" >> $TMPH
+fi
+if test "$iwmmxt" = "yes" ; then
+ echo "TARGET_IWMMXT=yes" >> config.mak
+ echo "#define HAVE_IWMMXT 1" >> $TMPH
+fi
+if test "$mmi" = "yes" ; then
+ echo "TARGET_MMI=yes" >> config.mak
+ echo "#define HAVE_MMI 1" >> $TMPH
+fi
+
+if test "$altivec" = "yes" ; then
+ echo "TARGET_ALTIVEC=yes" >> config.mak
+ echo "#define HAVE_ALTIVEC 1" >> $TMPH
+fi
+
+if test "$sdl" = "yes" ; then
+ echo "SDL_LIBS=`"${SDL_CONFIG}" --libs`" >> config.mak
+ echo "SDL_CFLAGS=`"${SDL_CONFIG}" --cflags`" >> config.mak
+fi
+if test "$texi2html" = "yes"; then
+ echo "BUILD_DOC=yes" >> config.mak
+fi
+
+sws_version=`grep '#define LIBSWSCALE_VERSION ' "$source_path/libswscale/swscale.h" | sed 's/[^0-9\.]//g'`
+pp_version=`grep '#define LIBPOSTPROC_VERSION ' "$source_path/libpostproc/postprocess.h" | sed 's/[^0-9\.]//g'`
+lavc_version=`grep '#define LIBAVCODEC_VERSION ' "$source_path/libavcodec/avcodec.h" | sed 's/[^0-9\.]//g'`
+lavf_version=`grep '#define LIBAVFORMAT_VERSION ' "$source_path/libavformat/avformat.h" | sed 's/[^0-9\.]//g'`
+lavu_version=`grep '#define LIBAVUTIL_VERSION ' "$source_path/libavutil/avutil.h" | sed 's/[^0-9\.]//g'`
+
+
+
+if test "$lshared" = "yes" ; then
+ echo "#define BUILD_SHARED_AV 1" >> $TMPH
+ echo "BUILD_SHARED=yes" >> config.mak
+ echo "PIC=-fPIC -DPIC" >> config.mak
+ echo "SPPMAJOR=${lavc_version%%.*}" >> config.mak
+ echo "SPPVERSION=$lavc_version" >> config.mak
+ echo "LAVCMAJOR=${lavc_version%%.*}" >> config.mak
+ echo "LAVCVERSION=$lavc_version" >> config.mak
+ echo "LAVFMAJOR=${lavf_version%%.*}" >> config.mak
+ echo "LAVFVERSION=$lavf_version" >> config.mak
+ echo "LAVUMAJOR=${lavu_version%%.*}" >> config.mak
+ echo "LAVUVERSION=$lavu_version" >> config.mak
+ echo "SWSMAJOR=${sws_version%%.*}" >> config.mak
+ echo "SWSVERSION=$sws_version" >> config.mak
+ echo "SLIBNAME=${SLIBNAME}" >> config.mak
+ echo "SLIBNAME_WITH_VERSION=${SLIBNAME_WITH_VERSION}" >> config.mak
+ echo "SLIBNAME_WITH_MAJOR=${SLIBNAME_WITH_MAJOR}" >> config.mak
+ echo "SLIB_EXTRA_CMD=${SLIB_EXTRA_CMD}" >> config.mak
+fi
+echo "LIB_INSTALL_EXTRA_CMD=${LIB_INSTALL_EXTRA_CMD}" >> config.mak
+echo "EXTRALIBS=$extralibs" >> config.mak
+
+enabled_any $ENCODER_LIST && enable encoders
+enabled_any $DECODER_LIST && enable decoders
+enabled_any $MUXER_LIST && enable muxers
+enabled_any $DEMUXER_LIST && enable demuxers
+
+enabled_any pthreads beosthreads os2threads w32threads && enable threads
+
+print_config HAVE_ $TMPH config.mak $HAVE_LIST
+print_config CONFIG_ $TMPH config.mak $CONFIG_LIST
+
+if test "$targetos" = "Darwin"; then
+ echo "#define CONFIG_DARWIN 1" >> $TMPH
+fi
+
+echo "#define restrict $_restrict" >> $TMPH
+
+if test "$optimize" = "small"; then
+ echo "#define always_inline" >> $TMPH
+ echo "#define CONFIG_SMALL 1" >> $TMPH
+fi
+
+echo "SRC_PATH=\"$source_path\"" >> config.mak
+echo "SRC_PATH_BARE=$source_path" >> config.mak
+echo "BUILD_ROOT=\"$PWD\"" >> config.mak
+
+if test "$amr_if2" = "yes" ; then
+ echo "AMR_CFLAGS=-DIF2=1" >> config.mak
+fi
+
+# Apparently it's not possible to portably echo a backslash.
+if test "$asmalign_pot" = "yes" ; then
+ printf '#define ASMALIGN(ZEROBITS) ".align " #ZEROBITS "\\n\\t"\n' >> $TMPH
+else
+ printf '#define ASMALIGN(ZEROBITS) ".align 1<<" #ZEROBITS "\\n\\t"\n' >> $TMPH
+fi
+
+
+for codec in $DECODER_LIST $ENCODER_LIST $PARSER_LIST $DEMUXER_LIST $MUXER_LIST; do
+ ucname="`toupper $codec`"
+ config_name="CONFIG_$ucname"
+ enabled_name="ENABLE_$ucname"
+ if enabled $codec; then
+ echo "#define $config_name 1" >> $TMPH
+ echo "#define $enabled_name 1" >> $TMPH
+ echo "$config_name=yes" >> config.mak
+ else
+ echo "#define $enabled_name 0" >> $TMPH
+ fi
+done
+
+# Do not overwrite config.h if unchanged to avoid superfluous rebuilds.
+if ! cmp -s $TMPH config.h; then
+ mv -f $TMPH config.h
+else
+ echo "config.h is unchanged"
+fi
+
+rm -f $TMPO $TMPC $TMPE $TMPS $TMPH
+
+# build tree in object directory if source path is different from current one
+if test "$source_path_used" = "yes" ; then
+ DIRS="\
+ doc \
+ libavformat \
+ libavcodec \
+ libavcodec/alpha \
+ libavcodec/armv4l \
+ libavcodec/bfin \
+ libavcodec/i386 \
+ libavcodec/sparc \
+ libavcodec/mlib \
+ libavcodec/ppc \
+ libavcodec/liba52 \
+ libpostproc \
+ libavutil \
+ libswscale \
+ tests \
+ vhook \
+ "
+ FILES="\
+ Makefile \
+ common.mak \
+ libavformat/Makefile \
+ libavcodec/Makefile \
+ libpostproc/Makefile \
+ libavutil/Makefile \
+ libswscale/Makefile \
+ tests/Makefile \
+ vhook/Makefile \
+ doc/Makefile \
+ doc/texi2pod.pl \
+ "
+ for dir in $DIRS ; do
+ mkdir -p $dir
+ done
+ for f in $FILES ; do
+ ln -sf "$source_path/$f" $f
+ done
+fi
+
+# build pkg-config files libav*.pc and libpostproc.pc
+# libavutil.pc
+cat <<EOF >libavutil.pc
+prefix=$PREFIX
+exec_prefix=\${prefix}
+libdir=\${exec_prefix}/lib
+includedir=\${prefix}/include
+
+Name: libavutil
+Description: FFmpeg utility library
+Version: $lavu_version
+Requires:
+Conflicts:
+Libs: -L\${libdir} -lavutil
+Cflags: -I\${includedir} -I\${includedir}/ffmpeg
+EOF
+
+cat <<EOF >libavutil-uninstalled.pc
+prefix=
+exec_prefix=
+libdir=\${pcfiledir}/libavutil
+includedir=\${pcfiledir}/libavutil
+
+Name: libavutil
+Description: FFmpeg utility library
+Version: $lavu_version
+Requires:
+Conflicts:
+Libs: \${libdir}/${LIBPREF}avutil${LIBSUF}
+Cflags: -I\${includedir}
+EOF
+
+# libavcodec.pc
+cat <<EOF >libavcodec.pc
+prefix=$PREFIX
+exec_prefix=\${prefix}
+libdir=\${exec_prefix}/lib
+includedir=\${prefix}/include
+
+Name: libavcodec
+Description: FFmpeg codec library
+Version: $lavc_version
+Requires: $pkg_requires libavutil = $lavu_version
+Conflicts:
+Libs: -L\${libdir} -lavcodec $extralibs
+Cflags: -I\${includedir} -I\${includedir}/ffmpeg
+EOF
+
+cat <<EOF >libavcodec-uninstalled.pc
+prefix=
+exec_prefix=
+libdir=\${pcfiledir}/libavcodec
+includedir=\${pcfiledir}/libavcodec
+
+Name: libavcodec
+Description: FFmpeg codec library
+Version: $lavc_version
+Requires: $pkg_requires libavutil = $lavu_version
+Conflicts:
+Libs: \${libdir}/${LIBPREF}avcodec${LIBSUF} $extralibs
+Cflags: -I\${includedir}
+EOF
+
+# libavformat.pc
+cat <<EOF >libavformat.pc
+prefix=$PREFIX
+exec_prefix=\${prefix}
+libdir=\${exec_prefix}/lib
+includedir=\${prefix}/include
+
+Name: libavformat
+Description: FFmpeg container format library
+Version: $lavf_version
+Requires: $pkg_requires libavcodec = $lavc_version
+Conflicts:
+Libs: -L\${libdir} -lavformat $extralibs
+Cflags: -I\${includedir} -I\${includedir}/ffmpeg
+EOF
+
+cat <<EOF >libavformat-uninstalled.pc
+prefix=
+exec_prefix=
+libdir=\${pcfiledir}/libavformat
+includedir=\${pcfiledir}/libavformat
+
+Name: libavformat
+Description: FFmpeg container format library
+Version: $lavf_version
+Requires: $pkg_requires libavcodec = $lavc_version
+Conflicts:
+Libs: \${libdir}/${LIBPREF}avformat${LIBSUF} $extralibs
+Cflags: -I\${includedir}
+EOF
+
+
+# libpostproc.pc
+cat <<EOF >libpostproc.pc
+prefix=$PREFIX
+exec_prefix=\${prefix}
+libdir=\${exec_prefix}/lib
+includedir=\${prefix}/include
+
+Name: libpostproc
+Description: FFmpeg post processing library
+Version: $lavc_version
+Requires:
+Conflicts:
+Libs: -L\${libdir} -lpostproc
+Cflags: -I\${includedir} -I\${includedir}/postproc
+EOF
+
+cat <<EOF >libpostproc-uninstalled.pc
+prefix=
+exec_prefix=
+libdir=\${pcfiledir}/libpostproc
+includedir=\${pcfiledir}/libpostproc
+
+Name: libpostproc
+Description: FFmpeg post processing library
+Version: $lavc_version
+Requires:
+Conflicts:
+Libs: \${libdir}/${LIBPREF}postproc${LIBSUF}
+Cflags: -I\${includedir}
+EOF
+
+if test "$swscaler" != "no"; then
+ sws_pc_libs="-L\${libdir} -lswscale"
+ sws_pc_uninstalled_libs="\${libdir}/${LIBPREF}swscale${LIBSUF}"
+ sws_pc_requires="$pkg_requires libavutil = $lavu_version"
+else
+ sws_pc_libs=""
+ sws_pc_uninstalled_libs=""
+ sws_pc_requires="$pkg_requires libavcodec = $lavc_version"
+fi
+# libswscale.pc
+cat <<EOF >libswscale.pc
+prefix=$PREFIX
+exec_prefix=\${prefix}
+libdir=\${exec_prefix}/lib
+includedir=\${prefix}/include
+
+Name: libswscale
+Description: FFmpeg image rescaling library
+Version: $sws_version
+Requires: $sws_pc_requires
+Conflicts:
+Libs: $sws_pc_libs
+Cflags: -I\${includedir} -I\${includedir}/swscale
+EOF
+
+cat <<EOF >libswscale-uninstalled.pc
+prefix=
+exec_prefix=
+libdir=\${pcfiledir}/libswscale
+includedir=\${pcfiledir}/libswscale
+
+Name: libswscale
+Description: FFmpeg image rescaling library
+Version: $sws_version
+Requires: $sws_pc_requires
+Conflicts:
+Libs: $sws_pc_uninstalled_libs
+Cflags: -I\${includedir}
+EOF
diff --git a/contrib/ffmpeg/cws2fws.c b/contrib/ffmpeg/cws2fws.c
new file mode 100644
index 000000000..2e70c6618
--- /dev/null
+++ b/contrib/ffmpeg/cws2fws.c
@@ -0,0 +1,127 @@
+/*
+ * cws2fws by Alex Beregszaszi <alex@fsn.hu>
+ * Public domain.
+ *
+ * This utility converts compressed Macromedia Flash files to uncompressed ones.
+ *
+ */
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <zlib.h>
+
+#ifdef DEBUG
+#define dbgprintf printf
+#else
+#define dbgprintf
+#endif
+
+main(int argc, char *argv[])
+{
+ int fd_in, fd_out, comp_len, uncomp_len, tag, i, last_out;
+ char buf_in[1024], buf_out[65536];
+ z_stream zstream;
+ struct stat statbuf;
+
+ if (argc < 3)
+ {
+ printf("Usage: %s <infile.swf> <outfile.swf>\n", argv[0]);
+ exit(1);
+ }
+
+ fd_in = open(argv[1], O_RDONLY);
+ if (fd_in < 0)
+ {
+ perror("Error while opening: ");
+ exit(1);
+ }
+
+ fd_out = open(argv[2], O_WRONLY|O_CREAT, 00644);
+ if (fd_out < 0)
+ {
+ perror("Error while opening: ");
+ close(fd_in);
+ exit(1);
+ }
+
+ if (read(fd_in, &buf_in, 8) != 8)
+ {
+ printf("Header error\n");
+ close(fd_in);
+ close(fd_out);
+ exit(1);
+ }
+
+ if (buf_in[0] != 'C' || buf_in[1] != 'W' || buf_in[2] != 'S')
+ {
+ printf("Not a compressed flash file\n");
+ exit(1);
+ }
+
+ fstat(fd_in, &statbuf);
+ comp_len = statbuf.st_size;
+ uncomp_len = buf_in[4] | (buf_in[5] << 8) | (buf_in[6] << 16) | (buf_in[7] << 24);
+
+ printf("Compressed size: %d Uncompressed size: %d\n", comp_len-4, uncomp_len-4);
+
+ // write out modified header
+ buf_in[0] = 'F';
+ write(fd_out, &buf_in, 8);
+
+ zstream.zalloc = NULL;
+ zstream.zfree = NULL;
+ zstream.opaque = NULL;
+ inflateInit(&zstream);
+
+ for (i = 0; i < comp_len-8;)
+ {
+ int ret, len = read(fd_in, &buf_in, 1024);
+
+ dbgprintf("read %d bytes\n", len);
+
+ last_out = zstream.total_out;
+
+ zstream.next_in = &buf_in[0];
+ zstream.avail_in = len;
+ zstream.next_out = &buf_out[0];
+ zstream.avail_out = 65536;
+
+ ret = inflate(&zstream, Z_SYNC_FLUSH);
+ if (ret != Z_STREAM_END && ret != Z_OK)
+ {
+ printf("Error while decompressing: %d\n", ret);
+ inflateEnd(&zstream);
+ exit(1);
+ }
+
+ dbgprintf("a_in: %d t_in: %d a_out: %d t_out: %d -- %d out\n",
+ zstream.avail_in, zstream.total_in, zstream.avail_out, zstream.total_out,
+ zstream.total_out-last_out);
+
+ write(fd_out, &buf_out, zstream.total_out-last_out);
+
+ i += len;
+
+ if (ret == Z_STREAM_END || ret == Z_BUF_ERROR)
+ break;
+ }
+
+ if (zstream.total_out != uncomp_len-8)
+ {
+ printf("Size mismatch (%d != %d), updating header...\n",
+ zstream.total_out, uncomp_len-8);
+
+ buf_in[0] = (zstream.total_out+8) & 0xff;
+ buf_in[1] = (zstream.total_out+8 >> 8) & 0xff;
+ buf_in[2] = (zstream.total_out+8 >> 16) & 0xff;
+ buf_in[3] = (zstream.total_out+8 >> 24) & 0xff;
+
+ lseek(fd_out, 4, SEEK_SET);
+ write(fd_out, &buf_in, 4);
+ }
+
+ inflateEnd(&zstream);
+ close(fd_in);
+ close(fd_out);
+}
diff --git a/contrib/ffmpeg/doc/Makefile b/contrib/ffmpeg/doc/Makefile
new file mode 100644
index 000000000..4fc9dfb8f
--- /dev/null
+++ b/contrib/ffmpeg/doc/Makefile
@@ -0,0 +1,20 @@
+-include ../config.mak
+
+VPATH=$(SRC_PATH_BARE)/doc
+
+all: ffmpeg-doc.html faq.html ffserver-doc.html ffplay-doc.html hooks.html \
+ ffmpeg.1 ffserver.1 ffplay.1
+
+%.html: %.texi Makefile
+ texi2html -monolithic -number $<
+
+%.pod: %-doc.texi
+ ./texi2pod.pl $< $@
+
+%.1: %.pod
+ pod2man --section=1 --center=" " --release=" " $< > $@
+
+clean:
+ rm -f *.html *.pod *.1
+
+.PHONY: all clean
diff --git a/contrib/ffmpeg/doc/TODO b/contrib/ffmpeg/doc/TODO
new file mode 100644
index 000000000..8271659d2
--- /dev/null
+++ b/contrib/ffmpeg/doc/TODO
@@ -0,0 +1,82 @@
+ffmpeg TODO list:
+----------------
+
+Fabrice's TODO list: (unordered)
+-------------------
+Short term:
+
+- seeking API and example in ffplay
+- use AVFMTCTX_DISCARD_PKT in ffplay so that DV has a chance to work
+- add RTSP regression test (both client and server)
+- make ffserver allocate AVFormatContext
+- clean up (incompatible change, for 0.5.0):
+ * AVStream -> AVComponent
+ * AVFormatContext -> AVInputStream/AVOutputStream
+ * suppress rate_emu from AVCodecContext
+- add new float/integer audio filterting and conversion : suppress
+ CODEC_ID_PCM_xxc and use CODEC_ID_RAWAUDIO.
+- fix telecine and frame rate conversion
+
+Long term (ask me if you want to help):
+
+- commit new imgconvert API and new PIX_FMT_xxx alpha formats
+- commit new LGPL'ed float and integer-only AC3 decoder
+- add WMA integer-only decoder
+- add new MPEG4-AAC audio decoder (both integer-only and float version)
+
+Michael's TODO list: (unordered) (if anyone wanna help with sth, just ask)
+-------------------
+- optimize H264 CABAC
+- more optimizations
+- simper rate control
+
+Francois' TODO list: (unordered, without any timeframe)
+-------------------
+- test MACE decoder against the openquicktime one as suggested by A'rpi
+- BeOS audio input grabbing backend
+- BeOS video input grabbing backend
+- have a REAL BeOS errno fix (return MKERROR(EXXX);), not a hack
+- publish my BeOS libposix on BeBits so I can officially support ffserver :)
+- check the whole code for thread-safety (global and init stuff)
+
+Philip'a TODO list: (alphabetically ordered) (please help)
+------------------
+- Add a multi-ffm filetype so that feeds can be recorded into multiple files rather
+ than one big file.
+- Authenticated users support -- where the authentication is in the URL
+- Change ASF files so that the embedded timestamp in the frames is right rather
+ than being an offset from the start of the stream
+- Make ffm files more resilient to changes in the codec structures so that you
+ can play old ffm files.
+
+unassigned TODO: (unordered)
+---------------
+- use AVFrame for audio codecs too
+- rework aviobuf.c buffering strategy and fix url_fskip
+- generate optimal huffman tables for mjpeg encoding
+- fix ffserver regression tests
+- support xvids motion estimation
+- support x264s motion estimation
+- support x264s rate control
+- SNOW: non translational motion compensation
+- SNOW: more optimal quantization
+- SNOW: 4x4 block support
+- SNOW: 1/8 pel motion compensation support
+- SNOW: iterative motion estimation based on subsampled images
+- FLAC: lossy encoding (viterbi and naive scalar quantization)
+- libavfilter
+- JPEG2000 decoder & encoder
+- MPEG4 GMC encoding support
+- macroblock based pixel format (better cache locality, somewhat complex, one paper claimed it faster for high res)
+- finish NUT implementation
+- seeking regression test
+- regression tests for codecs which dont have an encoder (I+P frame bitstream in svn)
+- add support for using mplayers video filters to ffmpeg
+- reverse engeneer RV30/RV40
+- finish implementation of WMV2 j-picture
+- H264 encoder
+- per MB ratecontrol (so VCD and such do work better)
+- replace/rewrite libavcodec/fdctref.c
+- write a script which iteratively changes all functions between always_inline and noinline and benchmarks the result to find the best set of inlined functions
+- set up roundup bugtracker somewhere with (newBug, reproduced, analyzed, fixed, worksForMe, duplicate, wontFix, invalid, needMoreInfo, newPatch, ok, applied, rejected, needChanges, newRequest, implemented, wontImplement, invalidReq) states and a checked integer
+- convert all the non SIMD asm into small asm vs. C testcases and submit them to the gcc devels so they can improve gcc
diff --git a/contrib/ffmpeg/doc/faq.texi b/contrib/ffmpeg/doc/faq.texi
new file mode 100644
index 000000000..9f1e8ec2d
--- /dev/null
+++ b/contrib/ffmpeg/doc/faq.texi
@@ -0,0 +1,312 @@
+\input texinfo @c -*- texinfo -*-
+
+@settitle FFmpeg FAQ
+@titlepage
+@sp 7
+@center @titlefont{FFmpeg FAQ}
+@sp 3
+@end titlepage
+
+
+@chapter General Problems
+
+@section I cannot read this file although this format seems to be supported by ffmpeg.
+
+Even if ffmpeg can read the file format, it may not support all its
+codecs. Please consult the supported codec list in the ffmpeg
+documentation.
+
+@section How do I encode JPEGs to another format ?
+
+If the JPEGs are named img1.jpg, img2.jpg, img3.jpg,..., use:
+
+@example
+ ffmpeg -f image2 -i img%d.jpg /tmp/a.mpg
+@end example
+
+@samp{%d} is replaced by the image number.
+
+@file{img%03d.jpg} generates @file{img001.jpg}, @file{img002.jpg}, etc...
+
+The same system is used for the other image formats.
+
+@section How do I encode movie to single pictures ?
+
+Use:
+
+@example
+ ffmpeg -i movie.mpg movie%d.jpg
+@end example
+
+The @file{movie.mpg} used as input will be converted to
+@file{movie1.jpg}, @file{movie2.jpg}, etc...
+
+Instead of relying on file format self-recognition, you may also use
+@table @option
+@item -vcodec ppm
+@item -vcodec png
+@item -vcodec mjpeg
+@end table
+to force the encoding.
+
+Applying that to the previous example:
+@example
+ ffmpeg -i movie.mpg -f image2 -vcodec mjpeg menu%d.jpg
+@end example
+
+Beware that there is no "jpeg" codec. Use "mjpeg" instead.
+
+@section FFmpeg does not support codec XXX. Can you include a Windows DLL loader to support it ?
+
+No. FFmpeg only supports open source codecs. Windows DLLs are not
+portable, bloated and often slow.
+
+@section I get "Unsupported codec (id=86043) for input stream #0.1". What is the problem ?
+
+This is the Qcelp codec, FFmpeg has no support for that codec currently. Try mencoder/mplayer it might work.
+
+@section Why do I see a slight quality degradation with multithreaded MPEG* encoding ?
+
+For multithreaded MPEG* encoding, the encoded slices must be independent,
+otherwise thread n would practically have to wait for n-1 to finish, so it's
+quite logical that there is a small reduction of quality. This is not a bug.
+
+@section How can I read from the standard input or write to the standard output ?
+
+Use @file{-} as filename.
+
+@section Why does ffmpeg not decode audio in VOB files ?
+
+The audio is AC3 (a.k.a. A/52). AC3 decoding is an optional component in ffmpeg
+as the component that handles AC3 decoding (liba52) is currently released under
+the GPL. If you have liba52 installed on your system, enable AC3 decoding
+with @code{./configure --enable-a52}. Take care: by
+enabling AC3, you automatically change the license of libavcodec from
+LGPL to GPL.
+
+@section Which codecs are supported by Windows ?
+
+Windows does not support standard formats like MPEG very well, unless you
+install some additional codecs
+
+The following list of video codecs should work on most Windows systems:
+@table @option
+@item msmpeg4v2
+.avi/.asf
+@item msmpeg4
+.asf only
+@item wmv1
+.asf only
+@item wmv2
+.asf only
+@item mpeg4
+only if you have some MPEG-4 codec installed like ffdshow or XviD
+@item mpeg1
+.mpg only
+@end table
+Note, ASF files often have .wmv or .wma extensions in Windows. It should also
+be mentioned that Microsoft claims a patent on the ASF format, and may sue
+or threaten users who create ASF files with non-Microsoft software. It is
+strongly advised to avoid ASF where possible.
+
+The following list of audio codecs should work on most Windows systems:
+@table @option
+@item adpcm_ima_wav
+@item adpcm_ms
+@item pcm
+@item mp3
+if some MP3 codec like LAME is installed
+@end table
+
+@section Why does the chrominance data seem to be sampled at a different time from the luminance data on bt8x8 captures on Linux?
+
+This is a well-known bug in the bt8x8 driver. For 2.4.26 there is a patch at
+(@url{http://mplayerhq.hu/~michael/bttv-420-2.4.26.patch}). This may also
+apply cleanly to other 2.4-series kernels.
+
+@section How do I avoid the ugly aliasing artifacts in bt8x8 captures on Linux?
+
+Pass 'combfilter=1 lumafilter=1' to the bttv driver. Note though that 'combfilter=1'
+will cause somewhat too strong filtering. A fix is to apply (@url{http://mplayerhq.hu/~michael/bttv-comb-2.4.26.patch})
+or (@url{http://mplayerhq.hu/~michael/bttv-comb-2.6.6.patch})
+and pass 'combfilter=2'.
+
+@section I have a problem with an old version of ffmpeg; where should I report it?
+Nowhere. Upgrade to the latest release or if there is no recent release upgrade
+to Subversion HEAD. You could also try to report it. Maybe you will get lucky and
+become the first person in history to get an answer different from "upgrade
+to Subversion HEAD".
+
+@section -f jpeg doesn't work.
+
+Try '-f image2 test%d.jpg'.
+
+@section Why can I not change the framerate?
+
+Some codecs, like MPEG-1/2, only allow a small number of fixed framerates.
+Choose a different codec with the -vcodec command line option.
+
+@section ffmpeg does not work; What is wrong?
+
+Try a 'make distclean' in the ffmpeg source directory. If this does not help see
+(@url{http://ffmpeg.org/bugreports.php}).
+
+@section How do I encode XviD or DivX video with ffmpeg?
+
+Both XviD and DivX (version 4+) are implementations of the ISO MPEG-4
+standard (note that there are many other coding formats that use this
+same standard). Thus, use '-vcodec mpeg4' to encode these formats. The
+default fourcc stored in an MPEG-4-coded file will be 'FMP4'. If you want
+a different fourcc, use the '-vtag' option. E.g., '-vtag xvid' will
+force the fourcc 'xvid' to be stored as the video fourcc rather than the
+default.
+
+@section How do I encode videos which play on the iPod?
+
+@table @option
+@item needed stuff
+-acodec aac -vcodec mpeg4 width<=320 height<=240
+@item working stuff
+4mv, title
+@item non-working stuff
+B-frames
+@item example command line
+ffmpeg -i input -acodec aac -ab 128 -vcodec mpeg4 -b 1200kb -mbd 2 -flags +4mv+trell -aic 2 -cmp 2 -subcmp 2 -s 320x180 -title X output.mp4
+@end table
+
+@section How do I encode videos which play on the PSP?
+
+@table @option
+@item needed stuff
+-acodec aac -vcodec mpeg4 width*height<=76800 width%16=0 height%16=0 -ar 24000 -r 30000/1001 or 15000/1001 -f psp
+@item working stuff
+4mv, title
+@item non-working stuff
+B-frames
+@item example command line
+ffmpeg -i input -acodec aac -ab 128 -vcodec mpeg4 -b 1200kb -ar 24000 -mbd 2 -flags +4mv+trell -aic 2 -cmp 2 -subcmp 2 -s 368x192 -r 30000/1001 -title X -f psp output.mp4
+@item needed stuff for H.264
+-acodec aac -vcodec h264 width*height<=76800 width%16=0? height%16=0? -ar 48000 -coder 1 -r 30000/1001 or 15000/1001 -f psp
+@item working stuff for H.264
+title, loop filter
+@item non-working stuff for H.264
+CAVLC
+@item example command line
+ffmpeg -i input -acodec aac -ab 128 -vcodec h264 -b 1200kb -ar 48000 -mbd 2 -coder 1 -cmp 2 -subcmp 2 -s 368x192 -r 30000/1001 -title X -f psp -flags loop -trellis 2 -partitions parti4x4+parti8x8+partp4x4+partp8x8+partb8x8 output.mp4
+@end table
+
+@section How can I read DirectShow files?
+
+If you have built FFmpeg with @code{./configure --enable-avisynth}
+(only possible on MinGW/Cygwin platforms),
+then you may use any file that DirectShow can read as input.
+(Be aware that this feature has been recently added,
+so you will need to help yourself in case of problems.)
+
+Just create an "input.avs" text file with this single line ...
+@example
+ DirectShowSource("C:\path to your file\yourfile.asf")
+@end example
+... and then feed that text file to FFmpeg:
+@example
+ ffmpeg -i input.avs
+@end example
+
+For ANY other help on Avisynth, please visit @url{http://www.avisynth.org/}.
+
+@chapter Development
+
+@section When will the next FFmpeg version be released? / Why are FFmpeg releases so few and far between?
+
+Like most open source projects FFmpeg suffers from a certain lack of
+manpower. For this reason the developers have to prioritize the work
+they do and putting out releases is not at the top of the list, fixing
+bugs and reviewing patches takes precedence. Please don't complain or
+request more timely and/or frequent releases unless you are willing to
+help out creating them.
+
+@section Why doesn't FFmpeg support feature [xyz]?
+
+Because no one has taken on that task yet. FFmpeg development is
+driven by the tasks that are important to the individual developers.
+If there is a feature that is important to you, the best way to get
+it implemented is to undertake the task yourself.
+
+
+@section Are there examples illustrating how to use the FFmpeg libraries, particularly libavcodec and libavformat ?
+
+Yes. Read the Developers Guide of the FFmpeg documentation. Alternatively,
+examine the source code for one of the many open source projects that
+already incorporate ffmpeg at (@url{projects.php}).
+
+@section Can you support my C compiler XXX ?
+
+No. Only GCC is supported. GCC is ported to most systems available and there
+is no need to pollute the source code with @code{#ifdef}s
+related to the compiler.
+
+@section Can I use FFmpeg or libavcodec under Windows ?
+
+Yes, but the MinGW tools @emph{must} be used to compile FFmpeg. You
+can link the resulting DLLs with any other Windows program. Read the
+@emph{Native Windows Compilation} and @emph{Visual C++ compatibility}
+sections in the FFmpeg documentation to find more information.
+
+@section Can you add automake, libtool or autoconf support ?
+
+No. These tools are too bloated and they complicate the build. Moreover,
+since only @samp{gcc} is supported they would add little advantages in
+terms of portability.
+
+@section Why not rewrite ffmpeg in object-oriented C++ ?
+
+ffmpeg is already organized in a highly modular manner and does not need to
+be rewritten in a formal object language. Further, many of the developers
+favor straight C; it works for them. For more arguments on this matter,
+read "Programming Religion" at (@url{http://lkml.org/faq/lkmlfaq-15.html}).
+
+@section Why are the ffmpeg programs devoid of debugging symbols ?
+
+The build process creates ffmpeg_g, ffplay_g, etc. which contain full debug
+information. Those binaries are strip'd to create ffmpeg, ffplay, etc. If
+you need the debug information, used the *_g versions.
+
+@section I do not like the LGPL, can I contribute code under the GPL instead ?
+
+Yes, as long as the code is optional and can easily and cleanly be placed
+under #ifdef CONFIG_GPL without breaking anything. So for example a new codec
+or filter would be OK under GPL while a bugfix to LGPL code would not.
+
+@section I want to compile xyz.c alone but my compiler produced many errors.
+
+Common code is in its own files in libav* and is used by the individual
+codecs. They will not work without the common parts, you have to compile
+the whole libav*. If you wish, disable some parts with configure switches.
+You can also try to hack it and remove more, but if you had problems fixing
+the compilation failure then you are probably not qualified for this.
+
+@section Visual C++ produces many errors.
+
+Visual C++ is not compliant to the C standard and does not support
+the inline assembly used in FFmpeg.
+If you wish - for whatever weird reason - to use Visual C++ for your
+project then you can link the Visual C++ code with libav* as long as
+you compile the latter with a working C compiler. For more information, see
+the @emph{Visual C++ compatibility} section in the FFmpeg documentation.
+
+There have been efforts to make FFmpeg compatible with Visual C++ in the
+past. However, they have all been rejected as too intrusive, especially
+since MinGW does the job perfectly adequately. None of the core developers
+work with Visual C++ and thus this item is low priority. Should you find
+the silver bullet that solves this problem, feel free to shoot it at us.
+
+@section I have a file in memory / a API different from *open/*read/ libc how do i use it with libavformat ?
+
+You have to implement a URLProtocol, see libavformat/file.c in FFmpeg
+and libmpdemux/demux_lavf.c in MPlayer sources.
+
+@section I get "No compatible shell script interpreter found." in MSys.
+
+The standard MSys bash (2.04) is broken. You need to install 2.05 or later.
+
+@bye
diff --git a/contrib/ffmpeg/doc/ffmpeg-doc.texi b/contrib/ffmpeg/doc/ffmpeg-doc.texi
new file mode 100644
index 000000000..2d814c0fb
--- /dev/null
+++ b/contrib/ffmpeg/doc/ffmpeg-doc.texi
@@ -0,0 +1,1607 @@
+\input texinfo @c -*- texinfo -*-
+
+@settitle FFmpeg Documentation
+@titlepage
+@sp 7
+@center @titlefont{FFmpeg Documentation}
+@sp 3
+@end titlepage
+
+
+@chapter Introduction
+
+FFmpeg is a very fast video and audio converter. It can also grab from
+a live audio/video source.
+
+The command line interface is designed to be intuitive, in the sense
+that FFmpeg tries to figure out all parameters that can possibly be
+derived automatically. You usually only have to specify the target
+bitrate you want.
+
+FFmpeg can also convert from any sample rate to any other, and resize
+video on the fly with a high quality polyphase filter.
+
+@chapter Quick Start
+
+@c man begin EXAMPLES
+@section Video and Audio grabbing
+
+FFmpeg can use a video4linux compatible video source and any Open Sound
+System audio source:
+
+@example
+ffmpeg /tmp/out.mpg
+@end example
+
+Note that you must activate the right video source and channel before
+launching FFmpeg with any TV viewer such as xawtv
+(@url{http://bytesex.org/xawtv/}) by Gerd Knorr. You also
+have to set the audio recording levels correctly with a
+standard mixer.
+
+@section Video and Audio file format conversion
+
+* FFmpeg can use any supported file format and protocol as input:
+
+Examples:
+
+* You can use YUV files as input:
+
+@example
+ffmpeg -i /tmp/test%d.Y /tmp/out.mpg
+@end example
+
+It will use the files:
+@example
+/tmp/test0.Y, /tmp/test0.U, /tmp/test0.V,
+/tmp/test1.Y, /tmp/test1.U, /tmp/test1.V, etc...
+@end example
+
+The Y files use twice the resolution of the U and V files. They are
+raw files, without header. They can be generated by all decent video
+decoders. You must specify the size of the image with the @option{-s} option
+if FFmpeg cannot guess it.
+
+* You can input from a raw YUV420P file:
+
+@example
+ffmpeg -i /tmp/test.yuv /tmp/out.avi
+@end example
+
+test.yuv is a file containing raw YUV planar data. Each frame is composed
+of the Y plane followed by the U and V planes at half vertical and
+horizontal resolution.
+
+* You can output to a raw YUV420P file:
+
+@example
+ffmpeg -i mydivx.avi hugefile.yuv
+@end example
+
+* You can set several input files and output files:
+
+@example
+ffmpeg -i /tmp/a.wav -s 640x480 -i /tmp/a.yuv /tmp/a.mpg
+@end example
+
+Converts the audio file a.wav and the raw YUV video file a.yuv
+to MPEG file a.mpg.
+
+* You can also do audio and video conversions at the same time:
+
+@example
+ffmpeg -i /tmp/a.wav -ar 22050 /tmp/a.mp2
+@end example
+
+Converts a.wav to MPEG audio at 22050Hz sample rate.
+
+* You can encode to several formats at the same time and define a
+mapping from input stream to output streams:
+
+@example
+ffmpeg -i /tmp/a.wav -ab 64 /tmp/a.mp2 -ab 128 /tmp/b.mp2 -map 0:0 -map 0:0
+@end example
+
+Converts a.wav to a.mp2 at 64 kbits and to b.mp2 at 128 kbits. '-map
+file:index' specifies which input stream is used for each output
+stream, in the order of the definition of output streams.
+
+* You can transcode decrypted VOBs
+
+@example
+ffmpeg -i snatch_1.vob -f avi -vcodec mpeg4 -b 800k -g 300 -bf 2 -acodec mp3 -ab 128 snatch.avi
+@end example
+
+This is a typical DVD ripping example; the input is a VOB file, the
+output an AVI file with MPEG-4 video and MP3 audio. Note that in this
+command we use B-frames so the MPEG-4 stream is DivX5 compatible, and
+GOP size is 300 which means one intra frame every 10 seconds for 29.97fps
+input video. Furthermore, the audio stream is MP3-encoded so you need
+to enable LAME support by passing @code{--enable-mp3lame} to configure.
+The mapping is particularly useful for DVD transcoding
+to get the desired audio language.
+
+NOTE: To see the supported input formats, use @code{ffmpeg -formats}.
+@c man end
+
+@chapter Invocation
+
+@section Syntax
+
+The generic syntax is:
+
+@example
+@c man begin SYNOPSIS
+ffmpeg [[infile options][@option{-i} @var{infile}]]... @{[outfile options] @var{outfile}@}...
+@c man end
+@end example
+@c man begin DESCRIPTION
+If no input file is given, audio/video grabbing is done.
+
+As a general rule, options are applied to the next specified
+file. Therefore, order is important, and you can have the same
+option on the command line multiple times. Each occurrence is
+then applied to the next input or output file.
+
+* To set the video bitrate of the output file to 64kbit/s:
+@example
+ffmpeg -i input.avi -b 64k output.avi
+@end example
+
+* To force the frame rate of the input and output file to 24 fps:
+@example
+ffmpeg -r 24 -i input.avi output.avi
+@end example
+
+* To force the frame rate of the output file to 24 fps:
+@example
+ffmpeg -i input.avi -r 24 output.avi
+@end example
+
+* To force the frame rate of input file to 1 fps and the output file to 24 fps:
+@example
+ffmpeg -r 1 -i input.avi -r 24 output.avi
+@end example
+
+The format option may be needed for raw input files.
+
+By default, FFmpeg tries to convert as losslessly as possible: It
+uses the same audio and video parameters for the outputs as the one
+specified for the inputs.
+@c man end
+
+@c man begin OPTIONS
+@section Main options
+
+@table @option
+@item -L
+Show license.
+
+@item -h
+Show help.
+
+@item -version
+Show version.
+
+@item -formats
+Show available formats, codecs, protocols, ...
+
+@item -f fmt
+Force format.
+
+@item -i filename
+input filename
+
+@item -y
+Overwrite output files.
+
+@item -t duration
+Set the recording time in seconds.
+@code{hh:mm:ss[.xxx]} syntax is also supported.
+
+@item -fs limit_size
+Set the file size limit.
+
+@item -ss position
+Seek to given time position in seconds.
+@code{hh:mm:ss[.xxx]} syntax is also supported.
+
+@item -itsoffset offset
+Set the input time offset in seconds.
+@code{[-]hh:mm:ss[.xxx]} syntax is also supported.
+This option affects all the input files that follow it.
+The offset is added to the timestamps of the input files.
+Specifying a positive offset means that the corresponding
+streams are delayed by 'offset' seconds.
+
+@item -title string
+Set the title.
+
+@item -timestamp time
+Set the timestamp.
+
+@item -author string
+Set the author.
+
+@item -copyright string
+Set the copyright.
+
+@item -comment string
+Set the comment.
+
+@item -album string
+Set the album.
+
+@item -track number
+Set the track.
+
+@item -year number
+Set the year.
+
+@item -v verbose
+Control amount of logging.
+
+@item -target type
+Specify target file type ("vcd", "svcd", "dvd", "dv", "dv50", "pal-vcd",
+"ntsc-svcd", ... ). All the format options (bitrate, codecs,
+buffer sizes) are then set automatically. You can just type:
+
+@example
+ffmpeg -i myfile.avi -target vcd /tmp/vcd.mpg
+@end example
+
+Nevertheless you can specify additional options as long as you know
+they do not conflict with the standard, as in:
+
+@example
+ffmpeg -i myfile.avi -target vcd -bf 2 /tmp/vcd.mpg
+@end example
+
+@item -dframes number
+Set the number of data frames to record.
+
+@item -scodec codec
+Force subtitle codec ('copy' to copy stream).
+
+@item -newsubtitle
+Add a new subtitle stream to the current output stream.
+
+@item -slang code
+Set the ISO 639 language code (3 letters) of the current subtitle stream.
+
+@end table
+
+@section Video Options
+
+@table @option
+@item -b bitrate
+Set the video bitrate in bit/s (default = 200 kb/s).
+@item -vframes number
+Set the number of video frames to record.
+@item -r fps
+Set frame rate (Hz value, fraction or abbreviation), (default = 25).
+@item -s size
+Set frame size. The format is @samp{wxh} (default = 160x128).
+The following abbreviations are recognized:
+@table @samp
+@item sqcif
+128x96
+@item qcif
+176x144
+@item cif
+352x288
+@item 4cif
+704x576
+@end table
+
+@item -aspect aspect
+Set aspect ratio (4:3, 16:9 or 1.3333, 1.7777).
+@item -croptop size
+Set top crop band size (in pixels).
+@item -cropbottom size
+Set bottom crop band size (in pixels).
+@item -cropleft size
+Set left crop band size (in pixels).
+@item -cropright size
+Set right crop band size (in pixels).
+@item -padtop size
+Set top pad band size (in pixels).
+@item -padbottom size
+Set bottom pad band size (in pixels).
+@item -padleft size
+Set left pad band size (in pixels).
+@item -padright size
+Set right pad band size (in pixels).
+@item -padcolor (hex color)
+Set color of padded bands. The value for padcolor is expressed
+as a six digit hexadecimal number where the first two digits
+represent red, the middle two digits green and last two digits
+blue (default = 000000 (black)).
+@item -vn
+Disable video recording.
+@item -bt tolerance
+Set video bitrate tolerance (in bit/s).
+@item -maxrate bitrate
+Set max video bitrate tolerance (in bit/s).
+@item -minrate bitrate
+Set min video bitrate tolerance (in bit/s).
+@item -bufsize size
+Set rate control buffer size (in bits).
+@item -vcodec codec
+Force video codec to @var{codec}. Use the @code{copy} special value to
+tell that the raw codec data must be copied as is.
+@item -sameq
+Use same video quality as source (implies VBR).
+
+@item -pass n
+Select the pass number (1 or 2). It is useful to do two pass
+encoding. The statistics of the video are recorded in the first
+pass and the video is generated at the exact requested bitrate
+in the second pass.
+
+@item -passlogfile file
+Set two pass logfile name to @var{file}.
+
+@item -newvideo
+Add a new video stream to the current output stream.
+
+@end table
+
+@section Advanced Video Options
+
+@table @option
+@item -pix_fmt format
+Set pixel format.
+@item -g gop_size
+Set the group of pictures size.
+@item -intra
+Use only intra frames.
+@item -vdt n
+Discard threshold.
+@item -qscale q
+Use fixed video quantizer scale (VBR).
+@item -qmin q
+minimum video quantizer scale (VBR)
+@item -qmax q
+maximum video quantizer scale (VBR)
+@item -qdiff q
+maximum difference between the quantizer scales (VBR)
+@item -qblur blur
+video quantizer scale blur (VBR)
+@item -qcomp compression
+video quantizer scale compression (VBR)
+
+@item -lmin lambda
+minimum video lagrange factor (VBR)
+@item -lmax lambda
+max video lagrange factor (VBR)
+@item -mblmin lambda
+minimum macroblock quantizer scale (VBR)
+@item -mblmax lambda
+maximum macroblock quantizer scale (VBR)
+
+These four options (lmin, lmax, mblmin, mblmax) use 'lambda' units,
+but you may use the QP2LAMBDA constant to easily convert from 'q' units:
+@example
+ffmpeg -i src.ext -lmax 21*QP2LAMBDA dst.ext
+@end example
+
+@item -rc_init_cplx complexity
+initial complexity for single pass encoding
+@item -b_qfactor factor
+qp factor between P- and B-frames
+@item -i_qfactor factor
+qp factor between P- and I-frames
+@item -b_qoffset offset
+qp offset between P- and B-frames
+@item -i_qoffset offset
+qp offset between P- and I-frames
+@item -rc_eq equation
+Set rate control equation (@pxref{FFmpeg formula
+evaluator}) (default = @code{tex^qComp}).
+@item -rc_override override
+rate control override for specific intervals
+@item -me method
+Set motion estimation method to @var{method}.
+Available methods are (from lowest to best quality):
+@table @samp
+@item zero
+Try just the (0, 0) vector.
+@item phods
+@item log
+@item x1
+@item epzs
+(default method)
+@item full
+exhaustive search (slow and marginally better than epzs)
+@end table
+
+@item -dct_algo algo
+Set DCT algorithm to @var{algo}. Available values are:
+@table @samp
+@item 0
+FF_DCT_AUTO (default)
+@item 1
+FF_DCT_FASTINT
+@item 2
+FF_DCT_INT
+@item 3
+FF_DCT_MMX
+@item 4
+FF_DCT_MLIB
+@item 5
+FF_DCT_ALTIVEC
+@end table
+
+@item -idct_algo algo
+Set IDCT algorithm to @var{algo}. Available values are:
+@table @samp
+@item 0
+FF_IDCT_AUTO (default)
+@item 1
+FF_IDCT_INT
+@item 2
+FF_IDCT_SIMPLE
+@item 3
+FF_IDCT_SIMPLEMMX
+@item 4
+FF_IDCT_LIBMPEG2MMX
+@item 5
+FF_IDCT_PS2
+@item 6
+FF_IDCT_MLIB
+@item 7
+FF_IDCT_ARM
+@item 8
+FF_IDCT_ALTIVEC
+@item 9
+FF_IDCT_SH4
+@item 10
+FF_IDCT_SIMPLEARM
+@end table
+
+@item -er n
+Set error resilience to @var{n}.
+@table @samp
+@item 1
+FF_ER_CAREFUL (default)
+@item 2
+FF_ER_COMPLIANT
+@item 3
+FF_ER_AGGRESSIVE
+@item 4
+FF_ER_VERY_AGGRESSIVE
+@end table
+
+@item -ec bit_mask
+Set error concealment to @var{bit_mask}. @var{bit_mask} is a bit mask of
+the following values:
+@table @samp
+@item 1
+FF_EC_GUESS_MVS (default = enabled)
+@item 2
+FF_EC_DEBLOCK (default = enabled)
+@end table
+
+@item -bf frames
+Use 'frames' B-frames (supported for MPEG-1, MPEG-2 and MPEG-4).
+@item -mbd mode
+macroblock decision
+@table @samp
+@item 0
+FF_MB_DECISION_SIMPLE: Use mb_cmp (cannot change it yet in FFmpeg).
+@item 1
+FF_MB_DECISION_BITS: Choose the one which needs the fewest bits.
+@item 2
+FF_MB_DECISION_RD: rate distortion
+@end table
+
+@item -4mv
+Use four motion vector by macroblock (MPEG-4 only).
+@item -part
+Use data partitioning (MPEG-4 only).
+@item -bug param
+Work around encoder bugs that are not auto-detected.
+@item -strict strictness
+How strictly to follow the standards.
+@item -aic
+Enable Advanced intra coding (h263+).
+@item -umv
+Enable Unlimited Motion Vector (h263+)
+
+@item -deinterlace
+Deinterlace pictures.
+@item -ilme
+Force interlacing support in encoder (MPEG-2 and MPEG-4 only).
+Use this option if your input file is interlaced and you want
+to keep the interlaced format for minimum losses.
+The alternative is to deinterlace the input stream with
+@option{-deinterlace}, but deinterlacing introduces losses.
+@item -psnr
+Calculate PSNR of compressed frames.
+@item -vstats
+Dump video coding statistics to @file{vstats_HHMMSS.log}.
+@item -vhook module
+Insert video processing @var{module}. @var{module} contains the module
+name and its parameters separated by spaces.
+@item -top n
+top=1/bottom=0/auto=-1 field first
+@item -dc precision
+Intra_dc_precision.
+@item -vtag fourcc/tag
+Force video tag/fourcc.
+@item -qphist
+Show QP histogram.
+@item -vbsf bitstream filter
+Bitstream filters available are "dump_extra", "remove_extra", "noise".
+@end table
+
+@section Audio Options
+
+@table @option
+@item -aframes number
+Set the number of audio frames to record.
+@item -ar freq
+Set the audio sampling frequency (default = 44100 Hz).
+@item -ab bitrate
+Set the audio bitrate in kbit/s (default = 64).
+@item -ac channels
+Set the number of audio channels (default = 1).
+@item -an
+Disable audio recording.
+@item -acodec codec
+Force audio codec to @var{codec}. Use the @code{copy} special value to
+specify that the raw codec data must be copied as is.
+@item -newaudio
+Add a new audio track to the output file. If you want to specify parameters,
+do so before @code{-newaudio} (@code{-acodec}, @code{-ab}, etc..).
+
+Mapping will be done automatically, if the number of output streams is equal to
+the number of input streams, else it will pick the first one that matches. You
+can override the mapping using @code{-map} as usual.
+
+Example:
+@example
+ffmpeg -i file.mpg -vcodec copy -acodec ac3 -ab 384 test.mpg -acodec mp2 -ab 192 -newaudio
+@end example
+@item -alang code
+Set the ISO 639 language code (3 letters) of the current audio stream.
+@end table
+
+@section Advanced Audio options:
+
+@table @option
+@item -atag fourcc/tag
+Force audio tag/fourcc.
+@item -absf bitstream filter
+Bitstream filters available are "dump_extra", "remove_extra", "noise", "mp3comp", "mp3decomp".
+@end table
+
+@section Subtitle options:
+
+@table @option
+@item -scodec codec
+Force subtitle codec ('copy' to copy stream).
+@item -newsubtitle
+Add a new subtitle stream to the current output stream.
+@item -slang code
+Set the ISO 639 language code (3 letters) of the current subtitle stream.
+@end table
+
+@section Audio/Video grab options
+
+@table @option
+@item -vd device
+sEt video grab device (e.g. @file{/dev/video0}).
+@item -vc channel
+Set video grab channel (DV1394 only).
+@item -tvstd standard
+Set television standard (NTSC, PAL (SECAM)).
+@item -dv1394
+Set DV1394 grab.
+@item -ad device
+Set audio device (e.g. @file{/dev/dsp}).
+@item -grab format
+Request grabbing using.
+@item -gd device
+Set grab device.
+@end table
+
+@section Advanced options
+
+@table @option
+@item -map input stream id[:input stream id]
+Set stream mapping from input streams to output streams.
+Just enumerate the input streams in the order you want them in the output.
+[input stream id] sets the (input) stream to sync against.
+@item -map_meta_data outfile:infile
+Set meta data information of outfile from infile.
+@item -debug
+Print specific debug info.
+@item -benchmark
+Add timings for benchmarking.
+@item -dump
+Dump each input packet.
+@item -hex
+When dumping packets, also dump the payload.
+@item -bitexact
+Only use bit exact algorithms (for codec testing).
+@item -ps size
+Set packet size in bits.
+@item -re
+Read input at native frame rate. Mainly used to simulate a grab device.
+@item -loop_input
+Loop over the input stream. Currently it works only for image
+streams. This option is used for automatic FFserver testing.
+@item -loop_output number_of_times
+Repeatedly loop output for formats that support looping such as animated GIF
+(0 will loop the output infinitely).
+@item -threads count
+Thread count.
+@item -vsync parameter
+Video sync method. Video will be stretched/squeezed to match the timestamps,
+it is done by duplicating and dropping frames. With -map you can select from
+which stream the timestamps should be taken. You can leave either video or
+audio unchanged and sync the remaining stream(s) to the unchanged one.
+@item -async samples_per_second
+Audio sync method. "Stretches/squeezes" the audio stream to match the timestamps,
+the parameter is the maximum samples per second by which the audio is changed.
+-async 1 is a special case where only the start of the audio stream is corrected
+without any later correction.
+@end table
+
+@node FFmpeg formula evaluator
+@section FFmpeg formula evaluator
+
+When evaluating a rate control string, FFmpeg uses an internal formula
+evaluator.
+
+The following binary operators are available: @code{+}, @code{-},
+@code{*}, @code{/}, @code{^}.
+
+The following unary operators are available: @code{+}, @code{-},
+@code{(...)}.
+
+The following functions are available:
+@table @var
+@item sinh(x)
+@item cosh(x)
+@item tanh(x)
+@item sin(x)
+@item cos(x)
+@item tan(x)
+@item exp(x)
+@item log(x)
+@item squish(x)
+@item gauss(x)
+@item abs(x)
+@item max(x, y)
+@item min(x, y)
+@item gt(x, y)
+@item lt(x, y)
+@item eq(x, y)
+@item bits2qp(bits)
+@item qp2bits(qp)
+@end table
+
+The following constants are available:
+@table @var
+@item PI
+@item E
+@item iTex
+@item pTex
+@item tex
+@item mv
+@item fCode
+@item iCount
+@item mcVar
+@item var
+@item isI
+@item isP
+@item isB
+@item avgQP
+@item qComp
+@item avgIITex
+@item avgPITex
+@item avgPPTex
+@item avgBPTex
+@item avgTex
+@end table
+
+@c man end
+
+@ignore
+
+@setfilename ffmpeg
+@settitle FFmpeg video converter
+
+@c man begin SEEALSO
+ffserver(1), ffplay(1) and the HTML documentation of @file{ffmpeg}.
+@c man end
+
+@c man begin AUTHOR
+Fabrice Bellard
+@c man end
+
+@end ignore
+
+@section Protocols
+
+The filename can be @file{-} to read from standard input or to write
+to standard output.
+
+FFmpeg also handles many protocols specified with an URL syntax.
+
+Use 'ffmpeg -formats' to see a list of the supported protocols.
+
+The protocol @code{http:} is currently used only to communicate with
+FFserver (see the FFserver documentation). When FFmpeg will be a
+video player it will also be used for streaming :-)
+
+@chapter Tips
+
+@itemize
+@item For streaming at very low bitrate application, use a low frame rate
+and a small GOP size. This is especially true for RealVideo where
+the Linux player does not seem to be very fast, so it can miss
+frames. An example is:
+
+@example
+ffmpeg -g 3 -r 3 -t 10 -b 50k -s qcif -f rv10 /tmp/b.rm
+@end example
+
+@item The parameter 'q' which is displayed while encoding is the current
+quantizer. The value 1 indicates that a very good quality could
+be achieved. The value 31 indicates the worst quality. If q=31 appears
+too often, it means that the encoder cannot compress enough to meet
+your bitrate. You must either increase the bitrate, decrease the
+frame rate or decrease the frame size.
+
+@item If your computer is not fast enough, you can speed up the
+compression at the expense of the compression ratio. You can use
+'-me zero' to speed up motion estimation, and '-intra' to disable
+motion estimation completely (you have only I-frames, which means it
+is about as good as JPEG compression).
+
+@item To have very low audio bitrates, reduce the sampling frequency
+(down to 22050 kHz for MPEG audio, 22050 or 11025 for AC3).
+
+@item To have a constant quality (but a variable bitrate), use the option
+'-qscale n' when 'n' is between 1 (excellent quality) and 31 (worst
+quality).
+
+@item When converting video files, you can use the '-sameq' option which
+uses the same quality factor in the encoder as in the decoder.
+It allows almost lossless encoding.
+
+@end itemize
+
+
+@chapter external libraries
+
+FFmpeg can be hooked up with a number of external libraries to add support
+for more formats.
+
+@section AMR
+
+AMR comes in two different flavors, WB and NB. FFmpeg can make use of the
+AMR WB (floating-point mode) and the AMR NB (both floating-point and
+fixed-point mode) reference decoders and encoders.
+
+@itemize
+
+@item For AMR WB floating-point download TS26.204 V5.1.0 from
+@url{http://www.3gpp.org/ftp/Specs/archive/26_series/26.204/26204-510.zip}
+and extract the source to @file{libavcodec/amrwb_float/}.
+
+@item For AMR NB floating-point download TS26.104 REL-5 V5.1.0 from
+@url{http://www.3gpp.org/ftp/Specs/archive/26_series/26.104/26104-510.zip}
+and extract the source to @file{libavcodec/amr_float/}.
+If you try this on Alpha, you may need to change @code{Word32} to
+@code{int} in @file{amr/typedef.h}.
+
+@item For AMR NB fixed-point download TS26.073 REL-5 V5.1.0 from
+@url{http://www.3gpp.org/ftp/Specs/archive/26_series/26.073/26073-510.zip}
+and extract the source to @file{libavcodec/amr}.
+You must also add @code{-DMMS_IO} and remove @code{-pedantic-errors}
+to/from @code{CFLAGS} in @file{libavcodec/amr/makefile}, i.e.
+``@code{CFLAGS = -Wall -I. \$(CFLAGS_\$(MODE)) -D\$(VAD) -DMMS_IO}''.
+
+@end itemize
+
+
+@chapter Supported File Formats and Codecs
+
+You can use the @code{-formats} option to have an exhaustive list.
+
+@section File Formats
+
+FFmpeg supports the following file formats through the @code{libavformat}
+library:
+
+@multitable @columnfractions .4 .1 .1 .4
+@item Supported File Format @tab Encoding @tab Decoding @tab Comments
+@item MPEG audio @tab X @tab X
+@item MPEG-1 systems @tab X @tab X
+@tab muxed audio and video
+@item MPEG-2 PS @tab X @tab X
+@tab also known as @code{VOB} file
+@item MPEG-2 TS @tab @tab X
+@tab also known as DVB Transport Stream
+@item ASF@tab X @tab X
+@item AVI@tab X @tab X
+@item WAV@tab X @tab X
+@item Macromedia Flash@tab X @tab X
+@tab Only embedded audio is decoded.
+@item FLV @tab X @tab X
+@tab Macromedia Flash video files
+@item Real Audio and Video @tab X @tab X
+@item Raw AC3 @tab X @tab X
+@item Raw MJPEG @tab X @tab X
+@item Raw MPEG video @tab X @tab X
+@item Raw PCM8/16 bits, mulaw/Alaw@tab X @tab X
+@item Raw CRI ADX audio @tab X @tab X
+@item Raw Shorten audio @tab @tab X
+@item SUN AU format @tab X @tab X
+@item NUT @tab X @tab X @tab NUT Open Container Format
+@item QuickTime @tab X @tab X
+@item MPEG-4 @tab X @tab X
+@tab MPEG-4 is a variant of QuickTime.
+@item Raw MPEG4 video @tab X @tab X
+@item DV @tab X @tab X
+@item 4xm @tab @tab X
+@tab 4X Technologies format, used in some games.
+@item Playstation STR @tab @tab X
+@item Id RoQ @tab @tab X
+@tab Used in Quake III, Jedi Knight 2, other computer games.
+@item Interplay MVE @tab @tab X
+@tab Format used in various Interplay computer games.
+@item WC3 Movie @tab @tab X
+@tab Multimedia format used in Origin's Wing Commander III computer game.
+@item Sega FILM/CPK @tab @tab X
+@tab Used in many Sega Saturn console games.
+@item Westwood Studios VQA/AUD @tab @tab X
+@tab Multimedia formats used in Westwood Studios games.
+@item Id Cinematic (.cin) @tab @tab X
+@tab Used in Quake II.
+@item FLIC format @tab @tab X
+@tab .fli/.flc files
+@item Sierra VMD @tab @tab X
+@tab Used in Sierra CD-ROM games.
+@item Sierra Online @tab @tab X
+@tab .sol files used in Sierra Online games.
+@item Matroska @tab @tab X
+@item Electronic Arts Multimedia @tab @tab X
+@tab Used in various EA games; files have extensions like WVE and UV2.
+@item Nullsoft Video (NSV) format @tab @tab X
+@item ADTS AAC audio @tab X @tab X
+@item Creative VOC @tab X @tab X @tab Created for the Sound Blaster Pro.
+@item American Laser Games MM @tab @tab X
+@tab Multimedia format used in games like Mad Dog McCree
+@item AVS @tab @tab X
+@tab Multimedia format used by the Creature Shock game.
+@item Smacker @tab @tab X
+@tab Multimedia format used by many games.
+@item GXF @tab X @tab X
+@tab General eXchange Format SMPTE 360M, used by Thomson Grass Valley playout servers.
+@item CIN @tab @tab X
+@tab Multimedia format used by Delphine Software games.
+@item MXF @tab @tab X
+@tab Material eXchange Format SMPTE 377M, used by D-Cinema, broadcast industry.
+@item SEQ @tab @tab X
+@tab Tiertex .seq files used in the DOS CDROM version of the game Flashback.
+@end multitable
+
+@code{X} means that encoding (resp. decoding) is supported.
+
+@section Image Formats
+
+FFmpeg can read and write images for each frame of a video sequence. The
+following image formats are supported:
+
+@multitable @columnfractions .4 .1 .1 .4
+@item Supported Image Format @tab Encoding @tab Decoding @tab Comments
+@item PGM, PPM @tab X @tab X
+@item PAM @tab X @tab X @tab PAM is a PNM extension with alpha support.
+@item PGMYUV @tab X @tab X @tab PGM with U and V components in YUV 4:2:0
+@item JPEG @tab X @tab X @tab Progressive JPEG is not supported.
+@item .Y.U.V @tab X @tab X @tab one raw file per component
+@item animated GIF @tab X @tab X @tab Only uncompressed GIFs are generated.
+@item PNG @tab X @tab X @tab 2 bit and 4 bit/pixel not supported yet.
+@item Targa @tab @tab X @tab Targa (.TGA) image format.
+@item TIFF @tab @tab X @tab Only 24 bit/pixel images are supported.
+@item SGI @tab X @tab X @tab SGI RGB image format
+@end multitable
+
+@code{X} means that encoding (resp. decoding) is supported.
+
+@section Video Codecs
+
+@multitable @columnfractions .4 .1 .1 .4
+@item Supported Codec @tab Encoding @tab Decoding @tab Comments
+@item MPEG-1 video @tab X @tab X
+@item MPEG-2 video @tab X @tab X
+@item MPEG-4 @tab X @tab X
+@item MSMPEG4 V1 @tab X @tab X
+@item MSMPEG4 V2 @tab X @tab X
+@item MSMPEG4 V3 @tab X @tab X
+@item WMV7 @tab X @tab X
+@item WMV8 @tab X @tab X @tab not completely working
+@item WMV9 @tab @tab X @tab not completely working
+@item VC1 @tab @tab X
+@item H.261 @tab X @tab X
+@item H.263(+) @tab X @tab X @tab also known as RealVideo 1.0
+@item H.264 @tab @tab X
+@item RealVideo 1.0 @tab X @tab X
+@item RealVideo 2.0 @tab X @tab X
+@item MJPEG @tab X @tab X
+@item lossless MJPEG @tab X @tab X
+@item JPEG-LS @tab X @tab X @tab fourcc: MJLS, lossless and near-lossless is supported
+@item Apple MJPEG-B @tab @tab X
+@item Sunplus MJPEG @tab @tab X @tab fourcc: SP5X
+@item DV @tab X @tab X
+@item HuffYUV @tab X @tab X
+@item FFmpeg Video 1 @tab X @tab X @tab experimental lossless codec (fourcc: FFV1)
+@item FFmpeg Snow @tab X @tab X @tab experimental wavelet codec (fourcc: SNOW)
+@item Asus v1 @tab X @tab X @tab fourcc: ASV1
+@item Asus v2 @tab X @tab X @tab fourcc: ASV2
+@item Creative YUV @tab @tab X @tab fourcc: CYUV
+@item Sorenson Video 1 @tab X @tab X @tab fourcc: SVQ1
+@item Sorenson Video 3 @tab @tab X @tab fourcc: SVQ3
+@item On2 VP3 @tab @tab X @tab still experimental
+@item On2 VP5 @tab @tab X @tab fourcc: VP50
+@item On2 VP6 @tab @tab X @tab fourcc: VP62
+@item Theora @tab @tab X @tab still experimental
+@item Intel Indeo 3 @tab @tab X
+@item FLV @tab X @tab X @tab Sorenson H.263 used in Flash
+@item Flash Screen Video @tab @tab X @tab fourcc: FSV1
+@item ATI VCR1 @tab @tab X @tab fourcc: VCR1
+@item ATI VCR2 @tab @tab X @tab fourcc: VCR2
+@item Cirrus Logic AccuPak @tab @tab X @tab fourcc: CLJR
+@item 4X Video @tab @tab X @tab Used in certain computer games.
+@item Sony Playstation MDEC @tab @tab X
+@item Id RoQ @tab @tab X @tab Used in Quake III, Jedi Knight 2, other computer games.
+@item Xan/WC3 @tab @tab X @tab Used in Wing Commander III .MVE files.
+@item Interplay Video @tab @tab X @tab Used in Interplay .MVE files.
+@item Apple Animation @tab @tab X @tab fourcc: 'rle '
+@item Apple Graphics @tab @tab X @tab fourcc: 'smc '
+@item Apple Video @tab @tab X @tab fourcc: rpza
+@item Apple QuickDraw @tab @tab X @tab fourcc: qdrw
+@item Cinepak @tab @tab X
+@item Microsoft RLE @tab @tab X
+@item Microsoft Video-1 @tab @tab X
+@item Westwood VQA @tab @tab X
+@item Id Cinematic Video @tab @tab X @tab Used in Quake II.
+@item Planar RGB @tab @tab X @tab fourcc: 8BPS
+@item FLIC video @tab @tab X
+@item Duck TrueMotion v1 @tab @tab X @tab fourcc: DUCK
+@item Duck TrueMotion v2 @tab @tab X @tab fourcc: TM20
+@item VMD Video @tab @tab X @tab Used in Sierra VMD files.
+@item MSZH @tab @tab X @tab Part of LCL
+@item ZLIB @tab X @tab X @tab Part of LCL, encoder experimental
+@item TechSmith Camtasia @tab @tab X @tab fourcc: TSCC
+@item IBM Ultimotion @tab @tab X @tab fourcc: ULTI
+@item Miro VideoXL @tab @tab X @tab fourcc: VIXL
+@item QPEG @tab @tab X @tab fourccs: QPEG, Q1.0, Q1.1
+@item LOCO @tab @tab X @tab
+@item Winnov WNV1 @tab @tab X @tab
+@item Autodesk Animator Studio Codec @tab @tab X @tab fourcc: AASC
+@item Fraps FPS1 @tab @tab X @tab
+@item CamStudio @tab @tab X @tab fourcc: CSCD
+@item American Laser Games Video @tab @tab X @tab Used in games like Mad Dog McCree
+@item ZMBV @tab @tab X @tab
+@item AVS Video @tab @tab X @tab Video encoding used by the Creature Shock game.
+@item Smacker Video @tab @tab X @tab Video encoding used in Smacker.
+@item RTjpeg @tab @tab X @tab Video encoding used in NuppelVideo files.
+@item KMVC @tab @tab X @tab Codec used in Worms games.
+@item VMware Video @tab @tab X @tab Codec used in videos captured by VMware.
+@item Cin Video @tab @tab X @tab Codec used in Delphine Software games.
+@item Tiertex Seq Video @tab @tab X @tab Codec used in DOS CDROM FlashBack game.
+@end multitable
+
+@code{X} means that encoding (resp. decoding) is supported.
+
+@section Audio Codecs
+
+@multitable @columnfractions .4 .1 .1 .1 .7
+@item Supported Codec @tab Encoding @tab Decoding @tab Comments
+@item MPEG audio layer 2 @tab IX @tab IX
+@item MPEG audio layer 1/3 @tab IX @tab IX
+@tab MP3 encoding is supported through the external library LAME.
+@item AC3 @tab IX @tab IX
+@tab liba52 is used internally for decoding.
+@item Vorbis @tab X @tab X
+@item WMA V1/V2 @tab @tab X
+@item AAC @tab X @tab X
+@tab Supported through the external library libfaac/libfaad.
+@item Microsoft ADPCM @tab X @tab X
+@item MS IMA ADPCM @tab X @tab X
+@item QT IMA ADPCM @tab @tab X
+@item 4X IMA ADPCM @tab @tab X
+@item G.726 ADPCM @tab X @tab X
+@item Duck DK3 IMA ADPCM @tab @tab X
+@tab Used in some Sega Saturn console games.
+@item Duck DK4 IMA ADPCM @tab @tab X
+@tab Used in some Sega Saturn console games.
+@item Westwood Studios IMA ADPCM @tab @tab X
+@tab Used in Westwood Studios games like Command and Conquer.
+@item SMJPEG IMA ADPCM @tab @tab X
+@tab Used in certain Loki game ports.
+@item CD-ROM XA ADPCM @tab @tab X
+@item CRI ADX ADPCM @tab X @tab X
+@tab Used in Sega Dreamcast games.
+@item Electronic Arts ADPCM @tab @tab X
+@tab Used in various EA titles.
+@item Creative ADPCM @tab @tab X
+@tab 16 -> 4, 8 -> 4, 8 -> 3, 8 -> 2
+@item RA144 @tab @tab X
+@tab Real 14400 bit/s codec
+@item RA288 @tab @tab X
+@tab Real 28800 bit/s codec
+@item RADnet @tab X @tab IX
+@tab Real low bitrate AC3 codec, liba52 is used for decoding.
+@item AMR-NB @tab X @tab X
+@tab Supported through an external library.
+@item AMR-WB @tab X @tab X
+@tab Supported through an external library.
+@item DV audio @tab @tab X
+@item Id RoQ DPCM @tab @tab X
+@tab Used in Quake III, Jedi Knight 2, other computer games.
+@item Interplay MVE DPCM @tab @tab X
+@tab Used in various Interplay computer games.
+@item Xan DPCM @tab @tab X
+@tab Used in Origin's Wing Commander IV AVI files.
+@item Sierra Online DPCM @tab @tab X
+@tab Used in Sierra Online game audio files.
+@item Apple MACE 3 @tab @tab X
+@item Apple MACE 6 @tab @tab X
+@item FLAC lossless audio @tab @tab X
+@item Shorten lossless audio @tab @tab X
+@item Apple lossless audio @tab @tab X
+@tab QuickTime fourcc 'alac'
+@item FFmpeg Sonic @tab X @tab X
+@tab experimental lossy/lossless codec
+@item Qdesign QDM2 @tab @tab X
+@tab there are still some distortions
+@item Real COOK @tab @tab X
+@tab All versions except 5.1 are supported
+@item DSP Group TrueSpeech @tab @tab X
+@item True Audio (TTA) @tab @tab X
+@item Smacker Audio @tab @tab X
+@item WavPack Audio @tab @tab X
+@item Cin Audio @tab @tab X
+@tab Codec used in Delphine Software games.
+@item Intel Music Coder @tab @tab X
+@end multitable
+
+@code{X} means that encoding (resp. decoding) is supported.
+
+@code{I} means that an integer-only version is available, too (ensures high
+performance on systems without hardware floating point support).
+
+@chapter Platform Specific information
+
+@section Linux
+
+FFmpeg should be compiled with at least GCC 2.95.3. GCC 3.2 is the
+preferred compiler now for FFmpeg. All future optimizations will depend on
+features only found in GCC 3.2.
+
+@section BSD
+
+BSD make will not build FFmpeg, you need to install and use GNU Make
+(@file{gmake}).
+
+@section Windows
+
+@subsection Native Windows compilation
+
+@itemize
+@item Install the current versions of MSYS and MinGW from
+@url{http://www.mingw.org/}. You can find detailed installation
+instructions in the download section and the FAQ.
+
+@item If you want to test the FFplay, also download
+the MinGW development library of SDL 1.2.x
+(@file{SDL-devel-1.2.x-mingw32.tar.gz}) from
+@url{http://www.libsdl.org}. Unpack it in a temporary directory, and
+unpack the archive @file{i386-mingw32msvc.tar.gz} in the MinGW tool
+directory. Edit the @file{sdl-config} script so that it gives the
+correct SDL directory when invoked.
+
+@item Extract the current version of FFmpeg.
+
+@item Start the MSYS shell (file @file{msys.bat}).
+
+@item Change to the FFmpeg directory and follow
+ the instructions of how to compile FFmpeg (file
+@file{INSTALL}). Usually, launching @file{./configure} and @file{make}
+suffices. If you have problems using SDL, verify that
+@file{sdl-config} can be launched from the MSYS command line.
+
+@item You can install FFmpeg in @file{Program Files/FFmpeg} by typing
+@file{make install}. Don't forget to copy @file{SDL.dll} to the place
+you launch @file{ffplay} from.
+
+@end itemize
+
+Notes:
+@itemize
+
+@item The target @file{make wininstaller} can be used to create a
+Nullsoft based Windows installer for FFmpeg and FFplay. @file{SDL.dll}
+must be copied to the FFmpeg directory in order to build the
+installer.
+
+@item By using @code{./configure --enable-shared} when configuring FFmpeg,
+you can build @file{avcodec.dll} and @file{avformat.dll}. With
+@code{make install} you install the FFmpeg DLLs and the associated
+headers in @file{Program Files/FFmpeg}.
+
+@item Visual C++ compatibility: If you used @code{./configure --enable-shared}
+when configuring FFmpeg, FFmpeg tries to use the Microsoft Visual
+C++ @code{lib} tool to build @code{avcodec.lib} and
+@code{avformat.lib}. With these libraries you can link your Visual C++
+code directly with the FFmpeg DLLs (see below).
+
+@end itemize
+
+@subsection Visual C++ compatibility
+
+FFmpeg will not compile under Visual C++ -- and it has too many
+dependencies on the GCC compiler to make a port viable. However,
+if you want to use the FFmpeg libraries in your own applications,
+you can still compile those applications using Visual C++. An
+important restriction to this is that you have to use the
+dynamically linked versions of the FFmpeg libraries (i.e. the
+DLLs), and you have to make sure that Visual-C++-compatible
+import libraries are created during the FFmpeg build process.
+
+This description of how to use the FFmpeg libraries with Visual C++ is
+based on Visual C++ 2005 Express Edition Beta 2. If you have a different
+version, you might have to modify the procedures slightly.
+
+Here are the step-by-step instructions for building the FFmpeg libraries
+so they can be used with Visual C++:
+
+@enumerate
+
+@item Install Visual C++ (if you haven't done so already).
+
+@item Install MinGW and MSYS as described above.
+
+@item Add a call to @file{vcvars32.bat} (which sets up the environment
+variables for the Visual C++ tools) as the first line of
+@file{msys.bat}. The standard location for @file{vcvars32.bat} is
+@file{C:\Program Files\Microsoft Visual Studio 8\VC\bin\vcvars32.bat},
+and the standard location for @file{msys.bat} is
+@file{C:\msys\1.0\msys.bat}. If this corresponds to your setup, add the
+following line as the first line of @file{msys.bat}:
+
+@code{call "C:\Program Files\Microsoft Visual Studio 8\VC\bin\vcvars32.bat"}
+
+@item Start the MSYS shell (file @file{msys.bat}) and type @code{link.exe}.
+If you get a help message with the command line options of @code{link.exe},
+this means your environment variables are set up correctly, the
+Microsoft linker is on the path and will be used by FFmpeg to
+create Visual-C++-compatible import libraries.
+
+@item Extract the current version of FFmpeg and change to the FFmpeg directory.
+
+@item Type the command
+@code{./configure --enable-shared --disable-static --enable-memalign-hack}
+to configure and, if that didn't produce any errors,
+type @code{make} to build FFmpeg.
+
+@item The subdirectories @file{libavformat}, @file{libavcodec}, and
+@file{libavutil} should now contain the files @file{avformat.dll},
+@file{avformat.lib}, @file{avcodec.dll}, @file{avcodec.lib},
+@file{avutil.dll}, and @file{avutil.lib}, respectively. Copy the three
+DLLs to your System32 directory (typically @file{C:\Windows\System32}).
+
+@end enumerate
+
+And here is how to use these libraries with Visual C++:
+
+@enumerate
+
+@item Create a new console application ("File / New / Project") and then
+select "Win32 Console Application". On the appropriate page of the
+Application Wizard, uncheck the "Precompiled headers" option.
+
+@item Write the source code for your application, or, for testing, just
+copy the code from an existing sample application into the source file
+that Visual C++ has already created for you. (Note that your source
+filehas to have a @code{.cpp} extension; otherwise, Visual C++ won't
+compile the FFmpeg headers correctly because in C mode, it doesn't
+recognize the @code{inline} keyword.) For example, you can copy
+@file{output_example.c} from the FFmpeg distribution (but you will
+have to make minor modifications so the code will compile under
+C++, see below).
+
+@item Open the "Project / Properties" dialog box. In the "Configuration"
+combo box, select "All Configurations" so that the changes you make will
+affect both debug and release builds. In the tree view on the left hand
+side, select "C/C++ / General", then edit the "Additional Include
+Directories" setting to contain the complete paths to the
+@file{libavformat}, @file{libavcodec}, and @file{libavutil}
+subdirectories of your FFmpeg directory. Note that the directories have
+to be separated using semicolons. Now select "Linker / General" from the
+tree view and edit the "Additional Library Directories" setting to
+contain the same three directories.
+
+@item Still in the "Project / Properties" dialog box, select "Linker / Input"
+from the tree view, then add the files @file{avformat.lib},
+@file{avcodec.lib}, and @file{avutil.lib} to the end of the "Additional
+Dependencies". Note that the names of the libraries have to be separated
+using spaces.
+
+@item Now, select "C/C++ / Code Generation" from the tree view. Select
+"Debug" in the "Configuration" combo box. Make sure that "Runtime
+Library" is set to "Multi-threaded Debug DLL". Then, select "Release" in
+the "Configuration" combo box and make sure that "Runtime Library" is
+set to "Multi-threaded DLL".
+
+@item Click "OK" to close the "Project / Properties" dialog box and build
+the application. Hopefully, it should compile and run cleanly. If you
+used @file{output_example.c} as your sample application, you will get a
+few compiler errors, but they are easy to fix. The first type of error
+occurs because Visual C++ doesn't allow an @code{int} to be converted to
+an @code{enum} without a cast. To solve the problem, insert the required
+casts (this error occurs once for a @code{CodecID} and once for a
+@code{CodecType}). The second type of error occurs because C++ requires
+the return value of @code{malloc} to be cast to the exact type of the
+pointer it is being assigned to. Visual C++ will complain that, for
+example, @code{(void *)} is being assigned to @code{(uint8_t *)} without
+an explicit cast. So insert an explicit cast in these places to silence
+the compiler. The third type of error occurs because the @code{snprintf}
+library function is called @code{_snprintf} under Visual C++. So just
+add an underscore to fix the problem. With these changes,
+@file{output_example.c} should compile under Visual C++, and the
+resulting executable should produce valid video files.
+
+@end enumerate
+
+@subsection Cross compilation for Windows with Linux
+
+You must use the MinGW cross compilation tools available at
+@url{http://www.mingw.org/}.
+
+Then configure FFmpeg with the following options:
+@example
+./configure --enable-mingw32 --cross-prefix=i386-mingw32msvc-
+@end example
+(you can change the cross-prefix according to the prefix chosen for the
+MinGW tools).
+
+Then you can easily test FFmpeg with Wine
+(@url{http://www.winehq.com/}).
+
+@subsection Compilation under Cygwin
+
+Cygwin works very much like Unix.
+
+Just install your Cygwin with all the "Base" packages, plus the
+following "Devel" ones:
+@example
+binutils, gcc-core, make, subversion
+@end example
+
+Do not install binutils-20060709-1 (they are buggy on shared builds);
+use binutils-20050610-1 instead.
+
+Then run
+
+@example
+./configure --enable-static --disable-shared
+@end example
+
+to make a static build or
+
+@example
+./configure --enable-shared --disable-static
+@end example
+
+to build shared libraries.
+
+If you want to build FFmpeg with additional libraries, download Cygwin
+"Devel" packages for Ogg and Vorbis from any Cygwin packages repository
+and/or SDL, xvid, faac, faad2 packages from Cygwin Ports,
+(@url{http://cygwinports.dotsrc.org/}).
+
+@subsection Crosscompilation for Windows under Cygwin
+
+With Cygwin you can create Windows binaries that don't need the cygwin1.dll.
+
+Just install your Cygwin as explained before, plus these additional
+"Devel" packages:
+@example
+gcc-mingw-core, mingw-runtime, mingw-zlib
+@end example
+
+and add some special flags to your configure invocation.
+
+For a static build run
+@example
+./configure --enable-mingw32 --enable-memalign-hack --enable-static --disable-shared --extra-cflags=-mno-cygwin --extra-libs=-mno-cygwin
+@end example
+
+and for a build with shared libraries
+@example
+./configure --enable-mingw32 --enable-memalign-hack --enable-shared --disable-static --extra-cflags=-mno-cygwin --extra-libs=-mno-cygwin
+@end example
+
+@section BeOS
+
+The configure script should guess the configuration itself.
+Networking support is currently not finished.
+errno issues fixed by Andrew Bachmann.
+
+Old stuff:
+
+François Revol - revol at free dot fr - April 2002
+
+The configure script should guess the configuration itself,
+however I still didn't test building on the net_server version of BeOS.
+
+FFserver is broken (needs poll() implementation).
+
+There are still issues with errno codes, which are negative in BeOS, and
+that FFmpeg negates when returning. This ends up turning errors into
+valid results, then crashes.
+(To be fixed)
+
+@chapter Developers Guide
+
+@section API
+@itemize @bullet
+@item libavcodec is the library containing the codecs (both encoding and
+decoding). Look at @file{libavcodec/apiexample.c} to see how to use it.
+
+@item libavformat is the library containing the file format handling (mux and
+demux code for several formats). Look at @file{ffplay.c} to use it in a
+player. See @file{output_example.c} to use it to generate audio or video
+streams.
+
+@end itemize
+
+@section Integrating libavcodec or libavformat in your program
+
+You can integrate all the source code of the libraries to link them
+statically to avoid any version problem. All you need is to provide a
+'config.mak' and a 'config.h' in the parent directory. See the defines
+generated by ./configure to understand what is needed.
+
+You can use libavcodec or libavformat in your commercial program, but
+@emph{any patch you make must be published}. The best way to proceed is
+to send your patches to the FFmpeg mailing list.
+
+@node Coding Rules
+@section Coding Rules
+
+FFmpeg is programmed in the ISO C90 language with a few additional
+features from ISO C99, namely:
+@itemize @bullet
+@item
+the @samp{inline} keyword;
+@item
+@samp{//} comments;
+@item
+designated struct initializers (@samp{struct s x = @{ .i = 17 @};})
+@item
+compound literals (@samp{x = (struct s) @{ 17, 23 @};})
+@end itemize
+
+These features are supported by all compilers we care about, so we won't
+accept patches to remove their use unless they absolutely don't impair
+clarity and performance.
+
+All code must compile with GCC 2.95 and GCC 3.3. Currently, FFmpeg also
+compiles with several other compilers, such as the Compaq ccc compiler
+or Sun Studio 9, and we would like to keep it that way unless it would
+be exceedingly involved. To ensure compatibility, please don't use any
+additional C99 features or GCC extensions. Especially watch out for:
+@itemize @bullet
+@item
+mixing statements and declarations;
+@item
+@samp{long long} (use @samp{int64_t} instead);
+@item
+@samp{__attribute__} not protected by @samp{#ifdef __GNUC__} or similar;
+@item
+GCC statement expressions (@samp{(x = (@{ int y = 4; y; @})}).
+@end itemize
+
+Indent size is 4.
+The presentation is the one specified by 'indent -i4 -kr -nut'.
+The TAB character is forbidden outside of Makefiles as is any
+form of trailing whitespace. Commits containing either will be
+rejected by the Subversion repository.
+
+Main priority in FFmpeg is simplicity and small code size (=less
+bugs).
+
+Comments: Use the JavaDoc/Doxygen
+format (see examples below) so that code documentation
+can be generated automatically. All nontrivial functions should have a comment
+above them explaining what the function does, even if it's just one sentence.
+All structures and their member variables should be documented, too.
+@example
+/**
+ * @@file mpeg.c
+ * MPEG codec.
+ * @@author ...
+ */
+
+/**
+ * Summary sentence.
+ * more text ...
+ * ...
+ */
+typedef struct Foobar@{
+ int var1; /**< var1 description */
+ int var2; ///< var2 description
+ /** var3 description */
+ int var3;
+@} Foobar;
+
+/**
+ * Summary sentence.
+ * more text ...
+ * ...
+ * @@param my_parameter description of my_parameter
+ * @@return return value description
+ */
+int myfunc(int my_parameter)
+...
+@end example
+
+fprintf and printf are forbidden in libavformat and libavcodec,
+please use av_log() instead.
+
+@section Development Policy
+
+@enumerate
+@item
+ You must not commit code which breaks FFmpeg! (Meaning unfinished but
+ enabled code which breaks compilation or compiles but does not work or
+ breaks the regression tests)
+ You can commit unfinished stuff (for testing etc), but it must be disabled
+ (#ifdef etc) by default so it does not interfere with other developers'
+ work.
+@item
+ You don't have to over-test things. If it works for you, and you think it
+ should work for others, then commit. If your code has problems
+ (portability, triggers compiler bugs, unusual environment etc) they will be
+ reported and eventually fixed.
+@item
+ Do not commit unrelated changes together, split them into self-contained
+ pieces.
+@item
+ Do not change behavior of the program (renaming options etc) without
+ first discussing it on the ffmpeg-devel mailing list. Do not remove
+ functionality from the code. Just improve!
+
+ Note: Redundant code can be removed.
+@item
+ Do not commit changes to the build system (Makefiles, configure script)
+ which change behavior, defaults etc, without asking first. The same
+ applies to compiler warning fixes, trivial looking fixes and to code
+ maintained by other developers. We usually have a reason for doing things
+ the way we do. Send your changes as patches to the ffmpeg-devel mailing
+ list, and if the code maintainers say OK, you may commit. This does not
+ apply to files you wrote and/or maintain.
+@item
+ We refuse source indentation and other cosmetic changes if they are mixed
+ with functional changes, such commits will be rejected and removed. Every
+ developer has his own indentation style, you should not change it. Of course
+ if you (re)write something, you can use your own style, even though we would
+ prefer if the indentation throughout FFmpeg was consistent (Many projects
+ force a given indentation style - we don't.). If you really need to make
+ indentation changes (try to avoid this), separate them strictly from real
+ changes.
+
+ NOTE: If you had to put if()@{ .. @} over a large (> 5 lines) chunk of code,
+ then either do NOT change the indentation of the inner part within (don't
+ move it to the right)! or do so in a separate commit
+@item
+ Always fill out the commit log message. Describe in a few lines what you
+ changed and why. You can refer to mailing list postings if you fix a
+ particular bug. Comments such as "fixed!" or "Changed it." are unacceptable.
+@item
+ If you apply a patch by someone else, include the name and email address in
+ the log message. Since the ffmpeg-cvslog mailing list is publicly
+ archived you should add some SPAM protection to the email address. Send an
+ answer to ffmpeg-devel (or wherever you got the patch from) saying that
+ you applied the patch.
+@item
+ Do NOT commit to code actively maintained by others without permission.
+ Send a patch to ffmpeg-devel instead. If noone answers within a reasonable
+ timeframe (12h for build failures and security fixes, 3 days small changes,
+ 1 week for big patches) then commit your patch if you think it's OK.
+ Also note, the maintainer can simply ask for more time to review!
+@item
+ Subscribe to the ffmpeg-cvslog mailing list. The diffs of all commits
+ are sent there and reviewed by all the other developers. Bugs and possible
+ improvements or general questions regarding commits are discussed there. We
+ expect you to react if problems with your code are uncovered.
+@item
+ Update the documentation if you change behavior or add features. If you are
+ unsure how best to do this, send a patch to ffmpeg-devel, the documentation
+ maintainer(s) will review and commit your stuff.
+@item
+ Never write to unallocated memory, never write over the end of arrays,
+ always check values read from some untrusted source before using them
+ as array index or other risky things.
+@item
+ Remember to check if you need to bump versions for the specific libav
+ parts (libavutil, libavcodec, libavformat) you are changing. You need
+ to change the version integer and the version string.
+ Incrementing the first component means no backward compatibility to
+ previous versions (e.g. removal of a function from the public API).
+ Incrementing the second component means backward compatible change
+ (e.g. addition of a function to the public API).
+ Incrementing the third component means a noteworthy binary compatible
+ change (e.g. encoder bug fix that matters for the decoder).
+@item
+ If you add a new codec, remember to update the changelog, add it to
+ the supported codecs table in the documentation and bump the second
+ component of the @file{libavcodec} version number appropriately. If
+ it has a fourcc, add it to @file{libavformat/avienc.c}, even if it
+ is only a decoder.
+@end enumerate
+
+We think our rules are not too hard. If you have comments, contact us.
+
+Note, these rules are mostly borrowed from the MPlayer project.
+
+@section Submitting patches
+
+First, (@pxref{Coding Rules}) above if you didn't yet.
+
+When you submit your patch, try to send a unified diff (diff '-up'
+option). I cannot read other diffs :-)
+
+Also please do not submit patches which contain several unrelated changes.
+Split them into individual self-contained patches; this makes reviewing
+them much easier.
+
+Run the regression tests before submitting a patch so that you can
+verify that there are no big problems.
+
+Patches should be posted as base64 encoded attachments (or any other
+encoding which ensures that the patch won't be trashed during
+transmission) to the ffmpeg-devel mailing list, see
+@url{http://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-devel}
+
+It also helps quite a bit if you tell us what the patch does (for example
+'replaces lrint by lrintf'), and why (for example '*BSD isn't C99 compliant
+and has no lrint()')
+
+We reply to all submitted patches and either apply or reject with some
+explanation why, but sometimes we are quite busy so it can take a week or two.
+
+@section Regression tests
+
+Before submitting a patch (or committing to the repository), you should at least
+test that you did not break anything.
+
+The regression tests build a synthetic video stream and a synthetic
+audio stream. These are then encoded and decoded with all codecs or
+formats. The CRC (or MD5) of each generated file is recorded in a
+result file. A 'diff' is launched to compare the reference results and
+the result file.
+
+The regression tests then go on to test the FFserver code with a
+limited set of streams. It is important that this step runs correctly
+as well.
+
+Run 'make test' to test all the codecs and formats.
+
+Run 'make fulltest' to test all the codecs, formats and FFserver.
+
+[Of course, some patches may change the results of the regression tests. In
+this case, the reference results of the regression tests shall be modified
+accordingly].
+
+@bye
diff --git a/contrib/ffmpeg/doc/ffmpeg_powerpc_performance_evaluation_howto.txt b/contrib/ffmpeg/doc/ffmpeg_powerpc_performance_evaluation_howto.txt
new file mode 100644
index 000000000..2eb4ee71a
--- /dev/null
+++ b/contrib/ffmpeg/doc/ffmpeg_powerpc_performance_evaluation_howto.txt
@@ -0,0 +1,172 @@
+FFmpeg & evaluating performance on the PowerPC Architecture HOWTO
+
+(c) 2003-2004 Romain Dolbeau <romain@dolbeau.org>
+
+
+
+I - Introduction
+
+The PowerPC architecture and its SIMD extension AltiVec offer some
+interesting tools to evaluate performance and improve the code.
+This document tries to explain how to use those tools with FFmpeg.
+
+The architecture itself offers two ways to evaluate the performance of
+a given piece of code:
+
+1) The Time Base Registers (TBL)
+2) The Performance Monitor Counter Registers (PMC)
+
+The first ones are always available, always active, but they're not very
+accurate: the registers increment by one every four *bus* cycles. On
+my 667 Mhz tiBook (ppc7450), this means once every twenty *processor*
+cycles. So we won't use that.
+
+The PMC are much more useful: not only can they report cycle-accurate
+timing, but they can also be used to monitor many other parameters,
+such as the number of AltiVec stalls for every kind of instruction,
+or instruction cache misses. The downside is that not all processors
+support the PMC (all G3, all G4 and the 970 do support them), and
+they're inactive by default - you need to activate them with a
+dedicated tool. Also, the number of available PMC depends on the
+procesor: the various 604 have 2, the various 75x (aka. G3) have 4,
+and the various 74xx (aka G4) have 6.
+
+*WARNING*: The PowerPC 970 is not very well documented, and its PMC
+registers are 64 bits wide. To properly notify the code, you *must*
+tune for the 970 (using --tune=970), or the code will assume 32 bit
+registers.
+
+
+II - Enabling FFmpeg PowerPC performance support
+
+This needs to be done by hand. First, you need to configure FFmpeg as
+usual, but add the "--powerpc-perf-enable" option. For instance:
+
+#####
+./configure --prefix=/usr/local/ffmpeg-svn --cc=gcc-3.3 --tune=7450 --powerpc-perf-enable
+#####
+
+This will configure FFmpeg to install inside /usr/local/ffmpeg-svn,
+compiling with gcc-3.3 (you should try to use this one or a newer
+gcc), and tuning for the PowerPC 7450 (i.e. the newer G4; as a rule of
+thumb, those at 550Mhz and more). It will also enable the PMC.
+
+You may also edit the file "config.h" to enable the following line:
+
+#####
+// #define ALTIVEC_USE_REFERENCE_C_CODE 1
+#####
+
+If you enable this line, then the code will not make use of AltiVec,
+but will use the reference C code instead. This is useful to compare
+performance between two versions of the code.
+
+Also, the number of enabled PMC is defined in "libavcodec/ppc/dsputil_ppc.h":
+
+#####
+#define POWERPC_NUM_PMC_ENABLED 4
+#####
+
+If you have a G4 CPU, you can enable all 6 PMC. DO NOT enable more
+PMC than available on your CPU!
+
+Then, simply compile FFmpeg as usual (make && make install).
+
+
+
+III - Using FFmpeg PowerPC performance support
+
+This FFmeg can be used exactly as usual. But before exiting, FFmpeg
+will dump a per-function report that looks like this:
+
+#####
+PowerPC performance report
+ Values are from the PMC registers, and represent whatever the
+ registers are set to record.
+ Function "gmc1_altivec" (pmc1):
+ min: 231
+ max: 1339867
+ avg: 558.25 (255302)
+ Function "gmc1_altivec" (pmc2):
+ min: 93
+ max: 2164
+ avg: 267.31 (255302)
+ Function "gmc1_altivec" (pmc3):
+ min: 72
+ max: 1987
+ avg: 276.20 (255302)
+(...)
+#####
+
+In this example, PMC1 was set to record CPU cycles, PMC2 was set to
+record AltiVec Permute Stall Cycles, and PMC3 was set to record AltiVec
+Issue Stalls.
+
+The function "gmc1_altivec" was monitored 255302 times, and the
+minimum execution time was 231 processor cycles. The max and average
+aren't much use, as it's very likely the OS interrupted execution for
+reasons of its own :-(
+
+With the exact same settings and source file, but using the reference C
+code we get:
+
+#####
+PowerPC performance report
+ Values are from the PMC registers, and represent whatever the
+ registers are set to record.
+ Function "gmc1_altivec" (pmc1):
+ min: 592
+ max: 2532235
+ avg: 962.88 (255302)
+ Function "gmc1_altivec" (pmc2):
+ min: 0
+ max: 33
+ avg: 0.00 (255302)
+ Function "gmc1_altivec" (pmc3):
+ min: 0
+ max: 350
+ avg: 0.03 (255302)
+(...)
+#####
+
+592 cycles, so the fastest AltiVec execution is about 2.5x faster than
+the fastest C execution in this example. It's not perfect but it's not
+bad (well I wrote this function so I can't say otherwise :-).
+
+Once you have that kind of report, you can try to improve things by
+finding what goes wrong and fixing it; in the example above, one
+should try to diminish the number of AltiVec stalls, as this *may*
+improve performance.
+
+
+
+IV) Enabling the PMC in Mac OS X
+
+This is easy. Use "Monster" and "monster". Those tools come from
+Apple's CHUD package, and can be found hidden in the developer web
+site & FTP site. "MONster" is the graphical application, use it to
+generate a config file specifying what each register should
+monitor. Then use the command-line application "monster" to use that
+config file, and enjoy the results.
+
+Note that "MONster" can be used for many other things, but it's
+documented by Apple, it's not my subject.
+
+If you are using CHUD 4.4.2 or later, you'll notice that MONster is
+no longer available. It's been superseeded by Shark, where
+configuration of PMCs is available as a plugin.
+
+
+
+V) Enabling the PMC on Linux
+
+On linux you may use oprofile from http://oprofile.sf.net, depending on the
+version and the cpu you may need to apply a patch[1] to access a set of the
+possibile counters from the userspace application. You can always define them
+using the kernel interface /dev/oprofile/* .
+
+[1] http://dev.gentoo.org/~lu_zero/development/oprofile-g4-20060423.patch
+
+--
+Romain Dolbeau <romain@dolbeau.org>
+Luca Barbato <lu_zero@gentoo.org>
diff --git a/contrib/ffmpeg/doc/ffplay-doc.texi b/contrib/ffmpeg/doc/ffplay-doc.texi
new file mode 100644
index 000000000..db08eb38f
--- /dev/null
+++ b/contrib/ffmpeg/doc/ffplay-doc.texi
@@ -0,0 +1,104 @@
+\input texinfo @c -*- texinfo -*-
+
+@settitle FFplay Documentation
+@titlepage
+@sp 7
+@center @titlefont{FFplay Documentation}
+@sp 3
+@end titlepage
+
+
+@chapter Introduction
+
+@c man begin DESCRIPTION
+FFplay is a very simple and portable media player using the FFmpeg
+libraries and the SDL library. It is mostly used as a testbed for the
+various FFmpeg APIs.
+@c man end
+
+@chapter Invocation
+
+@section Syntax
+@example
+@c man begin SYNOPSIS
+ffplay [options] @file{input_file}
+@c man end
+@end example
+
+@c man begin OPTIONS
+@section Main options
+
+@table @option
+@item -h
+show help
+@item -x width
+force displayed width
+@item -y height
+force displayed height
+@item -an
+disable audio
+@item -vn
+disable video
+@item -nodisp
+disable graphical display
+@item -f fmt
+force format
+@end table
+
+@section Advanced options
+@table @option
+@item -stats
+Show the stream duration, the codec parameters, the current position in
+the stream and the audio/video synchronisation drift.
+@item -rtp_tcp
+Force RTP/TCP protocol usage instead of RTP/UDP. It is only meaningful
+if you are streaming with the RTSP protocol.
+@item -sync type
+Set the master clock to audio (@code{type=audio}), video
+(@code{type=video}) or external (@code{type=ext}). Default is audio. The
+master clock is used to control audio-video synchronization. Most media
+players use audio as master clock, but in some cases (streaming or high
+quality broadcast) it is necessary to change that. This option is mainly
+used for debugging purposes.
+@end table
+
+@section While playing
+
+@table @key
+@item q, ESC
+quit
+
+@item f
+toggle full screen
+
+@item p, SPC
+pause
+
+@item a
+cycle audio channel
+
+@item v
+cycle video channel
+
+@item w
+show audio waves
+@end table
+
+@c man end
+
+@ignore
+
+@setfilename ffplay
+@settitle FFplay media player
+
+@c man begin SEEALSO
+ffmpeg(1), ffserver(1) and the html documentation of @file{ffmpeg}.
+@c man end
+
+@c man begin AUTHOR
+Fabrice Bellard
+@c man end
+
+@end ignore
+
+@bye
diff --git a/contrib/ffmpeg/doc/ffserver-doc.texi b/contrib/ffmpeg/doc/ffserver-doc.texi
new file mode 100644
index 000000000..ed67bb6c0
--- /dev/null
+++ b/contrib/ffmpeg/doc/ffserver-doc.texi
@@ -0,0 +1,224 @@
+\input texinfo @c -*- texinfo -*-
+
+@settitle FFserver Documentation
+@titlepage
+@sp 7
+@center @titlefont{FFserver Documentation}
+@sp 3
+@end titlepage
+
+
+@chapter Introduction
+
+@c man begin DESCRIPTION
+FFserver is a streaming server for both audio and video. It supports
+several live feeds, streaming from files and time shifting on live feeds
+(you can seek to positions in the past on each live feed, provided you
+specify a big enough feed storage in ffserver.conf).
+
+This documentation covers only the streaming aspects of ffserver /
+ffmpeg. All questions about parameters for ffmpeg, codec questions,
+etc. are not covered here. Read @file{ffmpeg-doc.html} for more
+information.
+@c man end
+
+@chapter QuickStart
+
+[Contributed by Philip Gladstone, philip-ffserver at gladstonefamily dot net]
+
+@section What can this do?
+
+When properly configured and running, you can capture video and audio in real
+time from a suitable capture card, and stream it out over the Internet to
+either Windows Media Player or RealAudio player (with some restrictions).
+
+It can also stream from files, though that is currently broken. Very often, a
+web server can be used to serve up the files just as well.
+
+It can stream prerecorded video from .ffm files, though it is somewhat tricky
+to make it work correctly.
+
+@section What do I need?
+
+I use Linux on a 900MHz Duron with a cheapo Bt848 based TV capture card. I'm
+using stock Linux 2.4.17 with the stock drivers. [Actually that isn't true,
+I needed some special drivers for my motherboard-based sound card.]
+
+I understand that FreeBSD systems work just fine as well.
+
+@section How do I make it work?
+
+First, build the kit. It *really* helps to have installed LAME first. Then when
+you run the ffserver ./configure, make sure that you have the --enable-mp3lame
+flag turned on.
+
+LAME is important as it allows for streaming audio to Windows Media Player.
+Don't ask why the other audio types do not work.
+
+As a simple test, just run the following two command lines (assuming that you
+have a V4L video capture card):
+
+@example
+./ffserver -f doc/ffserver.conf &
+./ffmpeg http://localhost:8090/feed1.ffm
+@end example
+
+At this point you should be able to go to your Windows machine and fire up
+Windows Media Player (WMP). Go to Open URL and enter
+
+@example
+ http://<linuxbox>:8090/test.asf
+@end example
+
+You should (after a short delay) see video and hear audio.
+
+WARNING: trying to stream test1.mpg doesn't work with WMP as it tries to
+transfer the entire file before starting to play.
+The same is true of AVI files.
+
+@section What happens next?
+
+You should edit the ffserver.conf file to suit your needs (in terms of
+frame rates etc). Then install ffserver and ffmpeg, write a script to start
+them up, and off you go.
+
+@section Troubleshooting
+
+@subsection I don't hear any audio, but video is fine.
+
+Maybe you didn't install LAME, or got your ./configure statement wrong. Check
+the ffmpeg output to see if a line referring to MP3 is present. If not, then
+your configuration was incorrect. If it is, then maybe your wiring is not
+set up correctly. Maybe the sound card is not getting data from the right
+input source. Maybe you have a really awful audio interface (like I do)
+that only captures in stereo and also requires that one channel be flipped.
+If you are one of these people, then export 'AUDIO_FLIP_LEFT=1' before
+starting ffmpeg.
+
+@subsection The audio and video loose sync after a while.
+
+Yes, they do.
+
+@subsection After a long while, the video update rate goes way down in WMP.
+
+Yes, it does. Who knows why?
+
+@subsection WMP 6.4 behaves differently to WMP 7.
+
+Yes, it does. Any thoughts on this would be gratefully received. These
+differences extend to embedding WMP into a web page. [There are two
+object IDs that you can use: The old one, which does not play well, and
+the new one, which does (both tested on the same system). However,
+I suspect that the new one is not available unless you have installed WMP 7].
+
+@section What else can it do?
+
+You can replay video from .ffm files that was recorded earlier.
+However, there are a number of caveats, including the fact that the
+ffserver parameters must match the original parameters used to record the
+file. If they do not, then ffserver deletes the file before recording into it.
+(Now that I write this, it seems broken).
+
+You can fiddle with many of the codec choices and encoding parameters, and
+there are a bunch more parameters that you cannot control. Post a message
+to the mailing list if there are some 'must have' parameters. Look in
+ffserver.conf for a list of the currently available controls.
+
+It will automatically generate the ASX or RAM files that are often used
+in browsers. These files are actually redirections to the underlying ASF
+or RM file. The reason for this is that the browser often fetches the
+entire file before starting up the external viewer. The redirection files
+are very small and can be transferred quickly. [The stream itself is
+often 'infinite' and thus the browser tries to download it and never
+finishes.]
+
+@section Tips
+
+* When you connect to a live stream, most players (WMP, RA, etc) want to
+buffer a certain number of seconds of material so that they can display the
+signal continuously. However, ffserver (by default) starts sending data
+in realtime. This means that there is a pause of a few seconds while the
+buffering is being done by the player. The good news is that this can be
+cured by adding a '?buffer=5' to the end of the URL. This means that the
+stream should start 5 seconds in the past -- and so the first 5 seconds
+of the stream are sent as fast as the network will allow. It will then
+slow down to real time. This noticeably improves the startup experience.
+
+You can also add a 'Preroll 15' statement into the ffserver.conf that will
+add the 15 second prebuffering on all requests that do not otherwise
+specify a time. In addition, ffserver will skip frames until a key_frame
+is found. This further reduces the startup delay by not transferring data
+that will be discarded.
+
+* You may want to adjust the MaxBandwidth in the ffserver.conf to limit
+the amount of bandwidth consumed by live streams.
+
+@section Why does the ?buffer / Preroll stop working after a time?
+
+It turns out that (on my machine at least) the number of frames successfully
+grabbed is marginally less than the number that ought to be grabbed. This
+means that the timestamp in the encoded data stream gets behind realtime.
+This means that if you say 'Preroll 10', then when the stream gets 10
+or more seconds behind, there is no Preroll left.
+
+Fixing this requires a change in the internals of how timestamps are
+handled.
+
+@section Does the @code{?date=} stuff work.
+
+Yes (subject to the limitation outlined above). Also note that whenever you
+start ffserver, it deletes the ffm file (if any parameters have changed),
+thus wiping out what you had recorded before.
+
+The format of the @code{?date=xxxxxx} is fairly flexible. You should use one
+of the following formats (the 'T' is literal):
+
+@example
+* YYYY-MM-DDTHH:MM:SS (localtime)
+* YYYY-MM-DDTHH:MM:SSZ (UTC)
+@end example
+
+You can omit the YYYY-MM-DD, and then it refers to the current day. However
+note that @samp{?date=16:00:00} refers to 16:00 on the current day -- this
+may be in the future and so is unlikely to be useful.
+
+You use this by adding the ?date= to the end of the URL for the stream.
+For example: @samp{http://localhost:8080/test.asf?date=2002-07-26T23:05:00}.
+
+@chapter Invocation
+@section Syntax
+@example
+@c man begin SYNOPSIS
+ffserver [options]
+@c man end
+@end example
+
+@section Options
+@c man begin OPTIONS
+@table @option
+@item -L
+Print the license.
+@item -h
+Print the help.
+@item -f configfile
+Use @file{configfile} instead of @file{/etc/ffserver.conf}.
+@end table
+@c man end
+
+@ignore
+
+@setfilename ffsserver
+@settitle FFserver video server
+
+@c man begin SEEALSO
+ffmpeg(1), ffplay(1), the @file{ffmpeg/doc/ffserver.conf} example and
+the HTML documentation of @file{ffmpeg}.
+@c man end
+
+@c man begin AUTHOR
+Fabrice Bellard
+@c man end
+
+@end ignore
+
+@bye
diff --git a/contrib/ffmpeg/doc/ffserver.conf b/contrib/ffmpeg/doc/ffserver.conf
new file mode 100644
index 000000000..a3b3ff412
--- /dev/null
+++ b/contrib/ffmpeg/doc/ffserver.conf
@@ -0,0 +1,349 @@
+# Port on which the server is listening. You must select a different
+# port from your standard HTTP web server if it is running on the same
+# computer.
+Port 8090
+
+# Address on which the server is bound. Only useful if you have
+# several network interfaces.
+BindAddress 0.0.0.0
+
+# Number of simultaneous requests that can be handled. Since FFServer
+# is very fast, it is more likely that you will want to leave this high
+# and use MaxBandwidth, below.
+MaxClients 1000
+
+# This the maximum amount of kbit/sec that you are prepared to
+# consume when streaming to clients.
+MaxBandwidth 1000
+
+# Access log file (uses standard Apache log file format)
+# '-' is the standard output.
+CustomLog -
+
+# Suppress that if you want to launch ffserver as a daemon.
+NoDaemon
+
+
+##################################################################
+# Definition of the live feeds. Each live feed contains one video
+# and/or audio sequence coming from an ffmpeg encoder or another
+# ffserver. This sequence may be encoded simultaneously with several
+# codecs at several resolutions.
+
+<Feed feed1.ffm>
+
+# You must use 'ffmpeg' to send a live feed to ffserver. In this
+# example, you can type:
+#
+# ffmpeg http://localhost:8090/feed1.ffm
+
+# ffserver can also do time shifting. It means that it can stream any
+# previously recorded live stream. The request should contain:
+# "http://xxxx?date=[YYYY-MM-DDT][[HH:]MM:]SS[.m...]".You must specify
+# a path where the feed is stored on disk. You also specify the
+# maximum size of the feed, where zero means unlimited. Default:
+# File=/tmp/feed_name.ffm FileMaxSize=5M
+File /tmp/feed1.ffm
+FileMaxSize 200K
+
+# You could specify
+# ReadOnlyFile /saved/specialvideo.ffm
+# This marks the file as readonly and it will not be deleted or updated.
+
+# Specify launch in order to start ffmpeg automatically.
+# First ffmpeg must be defined with an appropriate path if needed,
+# after that options can follow, but avoid adding the http:// field
+#Launch ffmpeg
+
+# Only allow connections from localhost to the feed.
+ACL allow 127.0.0.1
+
+</Feed>
+
+
+##################################################################
+# Now you can define each stream which will be generated from the
+# original audio and video stream. Each format has a filename (here
+# 'test1.mpg'). FFServer will send this stream when answering a
+# request containing this filename.
+
+<Stream test1.mpg>
+
+# coming from live feed 'feed1'
+Feed feed1.ffm
+
+# Format of the stream : you can choose among:
+# mpeg : MPEG-1 multiplexed video and audio
+# mpegvideo : only MPEG-1 video
+# mp2 : MPEG-2 audio (use AudioCodec to select layer 2 and 3 codec)
+# ogg : Ogg format (Vorbis audio codec)
+# rm : RealNetworks-compatible stream. Multiplexed audio and video.
+# ra : RealNetworks-compatible stream. Audio only.
+# mpjpeg : Multipart JPEG (works with Netscape without any plugin)
+# jpeg : Generate a single JPEG image.
+# asf : ASF compatible streaming (Windows Media Player format).
+# swf : Macromedia Flash compatible stream
+# avi : AVI format (MPEG-4 video, MPEG audio sound)
+# master : special ffmpeg stream used to duplicate a server
+Format mpeg
+
+# Bitrate for the audio stream. Codecs usually support only a few
+# different bitrates.
+AudioBitRate 32
+
+# Number of audio channels: 1 = mono, 2 = stereo
+AudioChannels 1
+
+# Sampling frequency for audio. When using low bitrates, you should
+# lower this frequency to 22050 or 11025. The supported frequencies
+# depend on the selected audio codec.
+AudioSampleRate 44100
+
+# Bitrate for the video stream
+VideoBitRate 64
+
+# Ratecontrol buffer size
+VideoBufferSize 40
+
+# Number of frames per second
+VideoFrameRate 3
+
+# Size of the video frame: WxH (default: 160x128)
+# The following abbreviations are defined: sqcif, qcif, cif, 4cif
+VideoSize 160x128
+
+# Transmit only intra frames (useful for low bitrates, but kills frame rate).
+#VideoIntraOnly
+
+# If non-intra only, an intra frame is transmitted every VideoGopSize
+# frames. Video synchronization can only begin at an intra frame.
+VideoGopSize 12
+
+# More MPEG-4 parameters
+# VideoHighQuality
+# Video4MotionVector
+
+# Choose your codecs:
+#AudioCodec mp2
+#VideoCodec mpeg1video
+
+# Suppress audio
+#NoAudio
+
+# Suppress video
+#NoVideo
+
+#VideoQMin 3
+#VideoQMax 31
+
+# Set this to the number of seconds backwards in time to start. Note that
+# most players will buffer 5-10 seconds of video, and also you need to allow
+# for a keyframe to appear in the data stream.
+#Preroll 15
+
+# ACL:
+
+# You can allow ranges of addresses (or single addresses)
+#ACL ALLOW <first address> <last address>
+
+# You can deny ranges of addresses (or single addresses)
+#ACL DENY <first address> <last address>
+
+# You can repeat the ACL allow/deny as often as you like. It is on a per
+# stream basis. The first match defines the action. If there are no matches,
+# then the default is the inverse of the last ACL statement.
+#
+# Thus 'ACL allow localhost' only allows access from localhost.
+# 'ACL deny 1.0.0.0 1.255.255.255' would deny the whole of network 1 and
+# allow everybody else.
+
+</Stream>
+
+
+##################################################################
+# Example streams
+
+
+# Multipart JPEG
+
+#<Stream test.mjpg>
+#Feed feed1.ffm
+#Format mpjpeg
+#VideoFrameRate 2
+#VideoIntraOnly
+#NoAudio
+#Strict -1
+#</Stream>
+
+
+# Single JPEG
+
+#<Stream test.jpg>
+#Feed feed1.ffm
+#Format jpeg
+#VideoFrameRate 2
+#VideoIntraOnly
+##VideoSize 352x240
+#NoAudio
+#Strict -1
+#</Stream>
+
+
+# Flash
+
+#<Stream test.swf>
+#Feed feed1.ffm
+#Format swf
+#VideoFrameRate 2
+#VideoIntraOnly
+#NoAudio
+#</Stream>
+
+
+# ASF compatible
+
+<Stream test.asf>
+Feed feed1.ffm
+Format asf
+VideoFrameRate 15
+VideoSize 352x240
+VideoBitRate 256
+VideoBufferSize 40
+VideoGopSize 30
+AudioBitRate 64
+StartSendOnKey
+</Stream>
+
+
+# MP3 audio
+
+#<Stream test.mp3>
+#Feed feed1.ffm
+#Format mp2
+#AudioCodec mp3
+#AudioBitRate 64
+#AudioChannels 1
+#AudioSampleRate 44100
+#NoVideo
+#</Stream>
+
+
+# Ogg Vorbis audio
+
+#<Stream test.ogg>
+#Feed feed1.ffm
+#Title "Stream title"
+#AudioBitRate 64
+#AudioChannels 2
+#AudioSampleRate 44100
+#NoVideo
+#</Stream>
+
+
+# Real with audio only at 32 kbits
+
+#<Stream test.ra>
+#Feed feed1.ffm
+#Format rm
+#AudioBitRate 32
+#NoVideo
+#NoAudio
+#</Stream>
+
+
+# Real with audio and video at 64 kbits
+
+#<Stream test.rm>
+#Feed feed1.ffm
+#Format rm
+#AudioBitRate 32
+#VideoBitRate 128
+#VideoFrameRate 25
+#VideoGopSize 25
+#NoAudio
+#</Stream>
+
+
+##################################################################
+# A stream coming from a file: you only need to set the input
+# filename and optionally a new format. Supported conversions:
+# AVI -> ASF
+
+#<Stream file.rm>
+#File "/usr/local/httpd/htdocs/tlive.rm"
+#NoAudio
+#</Stream>
+
+#<Stream file.asf>
+#File "/usr/local/httpd/htdocs/test.asf"
+#NoAudio
+#Author "Me"
+#Copyright "Super MegaCorp"
+#Title "Test stream from disk"
+#Comment "Test comment"
+#</Stream>
+
+
+##################################################################
+# RTSP examples
+#
+# You can access this stream with the RTSP URL:
+# rtsp://localhost:5454/test1-rtsp.mpg
+#
+# A non-standard RTSP redirector is also created. Its URL is:
+# http://localhost:8090/test1-rtsp.rtsp
+
+#<Stream test1-rtsp.mpg>
+#Format rtp
+#File "/usr/local/httpd/htdocs/test1.mpg"
+#</Stream>
+
+
+##################################################################
+# SDP/multicast examples
+#
+# If you want to send your stream in multicast, you must set the
+# multicast address with MulticastAddress. The port and the TTL can
+# also be set.
+#
+# An SDP file is automatically generated by ffserver by adding the
+# 'sdp' extension to the stream name (here
+# http://localhost:8090/test1-sdp.sdp). You should usually give this
+# file to your player to play the stream.
+#
+# The 'NoLoop' option can be used to avoid looping when the stream is
+# terminated.
+
+#<Stream test1-sdp.mpg>
+#Format rtp
+#File "/usr/local/httpd/htdocs/test1.mpg"
+#MulticastAddress 224.124.0.1
+#MulticastPort 5000
+#MulticastTTL 16
+#NoLoop
+#</Stream>
+
+
+##################################################################
+# Special streams
+
+# Server status
+
+<Stream stat.html>
+Format status
+
+# Only allow local people to get the status
+ACL allow localhost
+ACL allow 192.168.0.0 192.168.255.255
+
+#FaviconURL http://pond1.gladstonefamily.net:8080/favicon.ico
+</Stream>
+
+
+# Redirect index.html to the appropriate site
+
+<Redirect index.html>
+URL http://www.ffmpeg.org/
+</Redirect>
+
+
diff --git a/contrib/ffmpeg/doc/hooks.texi b/contrib/ffmpeg/doc/hooks.texi
new file mode 100644
index 000000000..15013547c
--- /dev/null
+++ b/contrib/ffmpeg/doc/hooks.texi
@@ -0,0 +1,113 @@
+\input texinfo @c -*- texinfo -*-
+
+@settitle Video Hook Documentation
+@titlepage
+@sp 7
+@center @titlefont{Video Hook Documentation}
+@sp 3
+@end titlepage
+
+
+@chapter Introduction
+
+
+The video hook functionality is designed (mostly) for live video. It allows
+the video to be modified or examined between the decoder and the encoder.
+
+Any number of hook modules can be placed inline, and they are run in the
+order that they were specified on the ffmpeg command line.
+
+Three modules are provided and are described below. They are all intended to
+be used as a base for your own modules.
+
+Modules are loaded using the -vhook option to ffmpeg. The value of this parameter
+is a space separated list of arguments. The first is the module name, and the rest
+are passed as arguments to the Configure function of the module.
+
+@section null.c
+
+This does nothing. Actually it converts the input image to RGB24 and then converts
+it back again. This is meant as a sample that you can use to test your setup.
+
+@section fish.c
+
+This implements a 'fish detector'. Essentially it converts the image into HSV
+space and tests whether more than a certain percentage of the pixels fall into
+a specific HSV cuboid. If so, then the image is saved into a file for processing
+by other bits of code.
+
+Why use HSV? It turns out that HSV cuboids represent a more compact range of
+colors than would an RGB cuboid.
+
+@section imlib2.c
+
+This module implements a text overlay for a video image. Currently it
+supports a fixed overlay or reading the text from a file. The string
+is passed through strftime so that it is easy to imprint the date and
+time onto the image.
+
+You may also overlay an image (even semi-transparent) like TV stations do.
+You may move either the text or the image around your video to create
+scrolling credits, for example.
+
+Text fonts are being looked for in a FONTPATH environment variable.
+
+Options:
+@multitable @columnfractions .2 .8
+@item @option{-c <color>} @tab The color of the text
+@item @option{-F <fontname>} @tab The font face and size
+@item @option{-t <text>} @tab The text
+@item @option{-f <filename>} @tab The filename to read text from
+@item @option{-x <expresion>} @tab X coordinate of text or image
+@item @option{-y <expresion>} @tab Y coordinate of text or image
+@item @option{-i <filename>} @tab The filename to read a image from
+@end multitable
+
+Expresions are functions of these variables:
+@multitable @columnfractions .2 .8
+@item @var{N} @tab frame number (starting at zero)
+@item @var{H} @tab frame height
+@item @var{W} @tab frame width
+@item @var{h} @tab image height
+@item @var{w} @tab image width
+@item @var{X} @tab previous x coordinate of text or image
+@item @var{Y} @tab previous y coordinate of text or image
+@end multitable
+
+You may also use the constants @var{PI}, @var{E}, and the math functions available at the
+FFmpeg formula evaluator at (@url{ffmpeg-doc.html#SEC13}), except @var{bits2qp(bits)}
+and @var{qp2bits(qp)}.
+
+Usage examples:
+
+@example
+ # Remember to set the path to your fonts
+ FONTPATH="/cygdrive/c/WINDOWS/Fonts/"
+ FONTPATH="$FONTPATH:/usr/share/imlib2/data/fonts/"
+ FONTPATH="$FONTPATH:/usr/X11R6/lib/X11/fonts/TTF/"
+ export FONTPATH
+
+ # Bulb dancing in a Lissajous pattern
+ ffmpeg -i input.avi -vhook \
+ 'vhook/imlib2.dll -x W*(0.5+0.25*sin(N/47*PI))-w/2 -y H*(0.5+0.50*cos(N/97*PI))-h/2 -i /usr/share/imlib2/data/images/bulb.png' \
+ -acodec copy -sameq output.avi
+
+ # Text scrolling
+ ffmpeg -i input.avi -vhook \
+ 'vhook/imlib2.dll -c red -F Vera.ttf/20 -x 150+0.5*N -y 70+0.25*N -t Hello' \
+ -acodec copy -sameq output.avi
+@end example
+
+@section ppm.c
+
+It's basically a launch point for a PPM pipe, so you can use any
+executable (or script) which consumes a PPM on stdin and produces a PPM
+on stdout (and flushes each frame).
+
+Usage example:
+
+@example
+ffmpeg -i input -vhook "/path/to/ppm.so some-ppm-filter args" output
+@end example
+
+@bye
diff --git a/contrib/ffmpeg/doc/optimization.txt b/contrib/ffmpeg/doc/optimization.txt
new file mode 100644
index 000000000..26c5ae64c
--- /dev/null
+++ b/contrib/ffmpeg/doc/optimization.txt
@@ -0,0 +1,158 @@
+optimization Tips (for libavcodec):
+
+What to optimize:
+If you plan to do non-x86 architecture specific optimizations (SIMD normally),
+then take a look in the i386/ directory, as most important functions are
+already optimized for MMX.
+
+If you want to do x86 optimizations then you can either try to finetune the
+stuff in the i386 directory or find some other functions in the C source to
+optimize, but there aren't many left.
+
+Understanding these overoptimized functions:
+As many functions tend to be a bit difficult to understand because
+of optimizations, it can be hard to optimize them further, or write
+architecture-specific versions. It is recommened to look at older
+revisions of the interesting files (for a web frontend try ViewVC at
+http://svn.mplayerhq.hu/ffmpeg/trunk/).
+Alternatively, look into the other architecture-specific versions in
+the i386/, ppc/, alpha/ subdirectories. Even if you don't exactly
+comprehend the instructions, it could help understanding the functions
+and how they can be optimized.
+
+NOTE: If you still don't understand some function, ask at our mailing list!!!
+(http://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-devel)
+
+
+
+WTF is that function good for ....:
+The primary purpose of that list is to avoid wasting time to optimize functions
+which are rarely used
+
+put(_no_rnd)_pixels{,_x2,_y2,_xy2}
+ Used in motion compensation (en/decoding).
+
+avg_pixels{,_x2,_y2,_xy2}
+ Used in motion compensation of B-frames.
+ These are less important than the put*pixels functions.
+
+avg_no_rnd_pixels*
+ unused
+
+pix_abs16x16{,_x2,_y2,_xy2}
+ Used in motion estimation (encoding) with SAD.
+
+pix_abs8x8{,_x2,_y2,_xy2}
+ Used in motion estimation (encoding) with SAD of MPEG-4 4MV only.
+ These are less important than the pix_abs16x16* functions.
+
+put_mspel8_mc* / wmv2_mspel8*
+ Used only in WMV2.
+ it is not recommended that you waste your time with these, as WMV2
+ is an ugly and relatively useless codec.
+
+mpeg4_qpel* / *qpel_mc*
+ Used in MPEG-4 qpel motion compensation (encoding & decoding).
+ The qpel8 functions are used only for 4mv,
+ the avg_* functions are used only for B-frames.
+ Optimizing them should have a significant impact on qpel
+ encoding & decoding.
+
+qpel{8,16}_mc??_old_c / *pixels{8,16}_l4
+ Just used to work around a bug in an old libavcodec encoder version.
+ Don't optimize them.
+
+tpel_mc_func {put,avg}_tpel_pixels_tab
+ Used only for SVQ3, so only optimize them if you need fast SVQ3 decoding.
+
+add_bytes/diff_bytes
+ For huffyuv only, optimize if you want a faster ffhuffyuv codec.
+
+get_pixels / diff_pixels
+ Used for encoding, easy.
+
+clear_blocks
+ easiest to optimize
+
+gmc
+ Used for MPEG-4 gmc.
+ Optimizing this should have a significant effect on the gmc decoding
+ speed but it's very likely impossible to write in SIMD.
+
+gmc1
+ Used for chroma blocks in MPEG-4 gmc with 1 warp point
+ (there are 4 luma & 2 chroma blocks per macroblock, so
+ only 1/3 of the gmc blocks use this, the other 2/3
+ use the normal put_pixel* code, but only if there is
+ just 1 warp point).
+ Note: DivX5 gmc always uses just 1 warp point.
+
+pix_sum
+ Used for encoding.
+
+hadamard8_diff / sse / sad == pix_norm1 / dct_sad / quant_psnr / rd / bit
+ Specific compare functions used in encoding, it depends upon the
+ command line switches which of these are used.
+ Don't waste your time with dct_sad & quant_psnr, they aren't
+ really useful.
+
+put_pixels_clamped / add_pixels_clamped
+ Used for en/decoding in the IDCT, easy.
+ Note, some optimized IDCTs have the add/put clamped code included and
+ then put_pixels_clamped / add_pixels_clamped will be unused.
+
+idct/fdct
+ idct (encoding & decoding)
+ fdct (encoding)
+ difficult to optimize
+
+dct_quantize_trellis
+ Used for encoding with trellis quantization.
+ difficult to optimize
+
+dct_quantize
+ Used for encoding.
+
+dct_unquantize_mpeg1
+ Used in MPEG-1 en/decoding.
+
+dct_unquantize_mpeg2
+ Used in MPEG-2 en/decoding.
+
+dct_unquantize_h263
+ Used in MPEG-4/H.263 en/decoding.
+
+FIXME remaining functions?
+BTW, most of these functions are in dsputil.c/.h, some are in mpegvideo.c/.h.
+
+
+
+Alignment:
+Some instructions on some architectures have strict alignment restrictions,
+for example most SSE/SSE2 instructions on x86.
+The minimum guaranteed alignment is written in the .h files, for example:
+ void (*put_pixels_clamped)(const DCTELEM *block/*align 16*/, UINT8 *pixels/*align 8*/, int line_size);
+
+
+
+Links:
+http://www.aggregate.org/MAGIC/
+
+x86-specific:
+http://developer.intel.com/design/pentium4/manuals/248966.htm
+
+The IA-32 Intel Architecture Software Developer's Manual, Volume 2:
+Instruction Set Reference
+http://developer.intel.com/design/pentium4/manuals/245471.htm
+
+http://www.agner.org/assem/
+
+AMD Athlon Processor x86 Code Optimization Guide:
+http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/22007.pdf
+
+GCC asm links:
+official doc but quite ugly
+http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
+
+a bit old (note "+" is valid for input-output, even though the next disagrees)
+http://www.cs.virginia.edu/~clc5q/gcc-inline-asm.pdf
diff --git a/contrib/ffmpeg/doc/soc.txt b/contrib/ffmpeg/doc/soc.txt
new file mode 100644
index 000000000..8b4a86db8
--- /dev/null
+++ b/contrib/ffmpeg/doc/soc.txt
@@ -0,0 +1,24 @@
+Google Summer of Code and similar project guidelines
+
+Summer of Code is a project by Google in which students are paid to implement
+some nice new features for various participating open source projects ...
+
+This text is a collection of things to take care of for the next soc as
+it's a little late for this year's soc (2006).
+
+The Goal:
+Our goal in respect to soc is and must be of course exactly one thing and
+that is to improve FFmpeg, to reach this goal, code must
+* conform to the svn policy and patch submission guidelines
+* must improve FFmpeg somehow (faster, smaller, "better",
+ more codecs supported, fewer bugs, cleaner, ...)
+
+for mentors and other developers to help students to reach that goal it is
+essential that changes to their codebase are publicly visible, clean and
+easy reviewable that again leads us to:
+* use of a revision control system like svn
+* separation of cosmetic from non-cosmetic changes (this is almost entirely
+ ignored by mentors and students in soc 2006 which might lead to a suprise
+ when the code will be reviewed at the end before a possible inclusion in
+ FFmpeg, individual changes were generally not reviewable due to cosmetics).
+* frequent commits, so that comments can be provided early
diff --git a/contrib/ffmpeg/doc/texi2pod.pl b/contrib/ffmpeg/doc/texi2pod.pl
new file mode 100755
index 000000000..c414ffcc6
--- /dev/null
+++ b/contrib/ffmpeg/doc/texi2pod.pl
@@ -0,0 +1,427 @@
+#! /usr/bin/perl -w
+
+# Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+
+# This file is part of GNU CC.
+
+# GNU CC 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; either version 2, or (at your option)
+# any later version.
+
+# GNU CC is distributed in the hope that 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 GNU CC; see the file COPYING. If not, write to
+# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+
+# This does trivial (and I mean _trivial_) conversion of Texinfo
+# markup to Perl POD format. It's intended to be used to extract
+# something suitable for a manpage from a Texinfo document.
+
+$output = 0;
+$skipping = 0;
+%sects = ();
+$section = "";
+@icstack = ();
+@endwstack = ();
+@skstack = ();
+@instack = ();
+$shift = "";
+%defs = ();
+$fnno = 1;
+$inf = "";
+$ibase = "";
+
+while ($_ = shift) {
+ if (/^-D(.*)$/) {
+ if ($1 ne "") {
+ $flag = $1;
+ } else {
+ $flag = shift;
+ }
+ $value = "";
+ ($flag, $value) = ($flag =~ /^([^=]+)(?:=(.+))?/);
+ die "no flag specified for -D\n"
+ unless $flag ne "";
+ die "flags may only contain letters, digits, hyphens, dashes and underscores\n"
+ unless $flag =~ /^[a-zA-Z0-9_-]+$/;
+ $defs{$flag} = $value;
+ } elsif (/^-/) {
+ usage();
+ } else {
+ $in = $_, next unless defined $in;
+ $out = $_, next unless defined $out;
+ usage();
+ }
+}
+
+if (defined $in) {
+ $inf = gensym();
+ open($inf, "<$in") or die "opening \"$in\": $!\n";
+ $ibase = $1 if $in =~ m|^(.+)/[^/]+$|;
+} else {
+ $inf = \*STDIN;
+}
+
+if (defined $out) {
+ open(STDOUT, ">$out") or die "opening \"$out\": $!\n";
+}
+
+while(defined $inf) {
+while(<$inf>) {
+ # Certain commands are discarded without further processing.
+ /^\@(?:
+ [a-z]+index # @*index: useful only in complete manual
+ |need # @need: useful only in printed manual
+ |(?:end\s+)?group # @group .. @end group: ditto
+ |page # @page: ditto
+ |node # @node: useful only in .info file
+ |(?:end\s+)?ifnottex # @ifnottex .. @end ifnottex: use contents
+ )\b/x and next;
+
+ chomp;
+
+ # Look for filename and title markers.
+ /^\@setfilename\s+([^.]+)/ and $fn = $1, next;
+ /^\@settitle\s+([^.]+)/ and $tl = postprocess($1), next;
+
+ # Identify a man title but keep only the one we are interested in.
+ /^\@c\s+man\s+title\s+([A-Za-z0-9-]+)\s+(.+)/ and do {
+ if (exists $defs{$1}) {
+ $fn = $1;
+ $tl = postprocess($2);
+ }
+ next;
+ };
+
+ # Look for blocks surrounded by @c man begin SECTION ... @c man end.
+ # This really oughta be @ifman ... @end ifman and the like, but such
+ # would require rev'ing all other Texinfo translators.
+ /^\@c\s+man\s+begin\s+([A-Z]+)\s+([A-Za-z0-9-]+)/ and do {
+ $output = 1 if exists $defs{$2};
+ $sect = $1;
+ next;
+ };
+ /^\@c\s+man\s+begin\s+([A-Z]+)/ and $sect = $1, $output = 1, next;
+ /^\@c\s+man\s+end/ and do {
+ $sects{$sect} = "" unless exists $sects{$sect};
+ $sects{$sect} .= postprocess($section);
+ $section = "";
+ $output = 0;
+ next;
+ };
+
+ # handle variables
+ /^\@set\s+([a-zA-Z0-9_-]+)\s*(.*)$/ and do {
+ $defs{$1} = $2;
+ next;
+ };
+ /^\@clear\s+([a-zA-Z0-9_-]+)/ and do {
+ delete $defs{$1};
+ next;
+ };
+
+ next unless $output;
+
+ # Discard comments. (Can't do it above, because then we'd never see
+ # @c man lines.)
+ /^\@c\b/ and next;
+
+ # End-block handler goes up here because it needs to operate even
+ # if we are skipping.
+ /^\@end\s+([a-z]+)/ and do {
+ # Ignore @end foo, where foo is not an operation which may
+ # cause us to skip, if we are presently skipping.
+ my $ended = $1;
+ next if $skipping && $ended !~ /^(?:ifset|ifclear|ignore|menu|iftex)$/;
+
+ die "\@end $ended without \@$ended at line $.\n" unless defined $endw;
+ die "\@$endw ended by \@end $ended at line $.\n" unless $ended eq $endw;
+
+ $endw = pop @endwstack;
+
+ if ($ended =~ /^(?:ifset|ifclear|ignore|menu|iftex)$/) {
+ $skipping = pop @skstack;
+ next;
+ } elsif ($ended =~ /^(?:example|smallexample|display)$/) {
+ $shift = "";
+ $_ = ""; # need a paragraph break
+ } elsif ($ended =~ /^(?:itemize|enumerate|[fv]?table)$/) {
+ $_ = "\n=back\n";
+ $ic = pop @icstack;
+ } else {
+ die "unknown command \@end $ended at line $.\n";
+ }
+ };
+
+ # We must handle commands which can cause skipping even while we
+ # are skipping, otherwise we will not process nested conditionals
+ # correctly.
+ /^\@ifset\s+([a-zA-Z0-9_-]+)/ and do {
+ push @endwstack, $endw;
+ push @skstack, $skipping;
+ $endw = "ifset";
+ $skipping = 1 unless exists $defs{$1};
+ next;
+ };
+
+ /^\@ifclear\s+([a-zA-Z0-9_-]+)/ and do {
+ push @endwstack, $endw;
+ push @skstack, $skipping;
+ $endw = "ifclear";
+ $skipping = 1 if exists $defs{$1};
+ next;
+ };
+
+ /^\@(ignore|menu|iftex)\b/ and do {
+ push @endwstack, $endw;
+ push @skstack, $skipping;
+ $endw = $1;
+ $skipping = 1;
+ next;
+ };
+
+ next if $skipping;
+
+ # Character entities. First the ones that can be replaced by raw text
+ # or discarded outright:
+ s/\@copyright\{\}/(c)/g;
+ s/\@dots\{\}/.../g;
+ s/\@enddots\{\}/..../g;
+ s/\@([.!? ])/$1/g;
+ s/\@[:-]//g;
+ s/\@bullet(?:\{\})?/*/g;
+ s/\@TeX\{\}/TeX/g;
+ s/\@pounds\{\}/\#/g;
+ s/\@minus(?:\{\})?/-/g;
+ s/\\,/,/g;
+
+ # Now the ones that have to be replaced by special escapes
+ # (which will be turned back into text by unmunge())
+ s/&/&amp;/g;
+ s/\@\{/&lbrace;/g;
+ s/\@\}/&rbrace;/g;
+ s/\@\@/&at;/g;
+
+ # Inside a verbatim block, handle @var specially.
+ if ($shift ne "") {
+ s/\@var\{([^\}]*)\}/<$1>/g;
+ }
+
+ # POD doesn't interpret E<> inside a verbatim block.
+ if ($shift eq "") {
+ s/</&lt;/g;
+ s/>/&gt;/g;
+ } else {
+ s/</&LT;/g;
+ s/>/&GT;/g;
+ }
+
+ # Single line command handlers.
+
+ /^\@include\s+(.+)$/ and do {
+ push @instack, $inf;
+ $inf = gensym();
+
+ # Try cwd and $ibase.
+ open($inf, "<" . $1)
+ or open($inf, "<" . $ibase . "/" . $1)
+ or die "cannot open $1 or $ibase/$1: $!\n";
+ next;
+ };
+
+ /^\@(?:section|unnumbered|unnumberedsec|center)\s+(.+)$/
+ and $_ = "\n=head2 $1\n";
+ /^\@subsection\s+(.+)$/
+ and $_ = "\n=head3 $1\n";
+
+ # Block command handlers:
+ /^\@itemize\s+(\@[a-z]+|\*|-)/ and do {
+ push @endwstack, $endw;
+ push @icstack, $ic;
+ $ic = $1;
+ $_ = "\n=over 4\n";
+ $endw = "itemize";
+ };
+
+ /^\@enumerate(?:\s+([a-zA-Z0-9]+))?/ and do {
+ push @endwstack, $endw;
+ push @icstack, $ic;
+ if (defined $1) {
+ $ic = $1 . ".";
+ } else {
+ $ic = "1.";
+ }
+ $_ = "\n=over 4\n";
+ $endw = "enumerate";
+ };
+
+ /^\@([fv]?table)\s+(\@[a-z]+)/ and do {
+ push @endwstack, $endw;
+ push @icstack, $ic;
+ $endw = $1;
+ $ic = $2;
+ $ic =~ s/\@(?:samp|strong|key|gcctabopt|option|env)/B/;
+ $ic =~ s/\@(?:code|kbd)/C/;
+ $ic =~ s/\@(?:dfn|var|emph|cite|i)/I/;
+ $ic =~ s/\@(?:file)/F/;
+ $_ = "\n=over 4\n";
+ };
+
+ /^\@((?:small)?example|display)/ and do {
+ push @endwstack, $endw;
+ $endw = $1;
+ $shift = "\t";
+ $_ = ""; # need a paragraph break
+ };
+
+ /^\@itemx?\s*(.+)?$/ and do {
+ if (defined $1) {
+ # Entity escapes prevent munging by the <> processing below.
+ $_ = "\n=item $ic\&LT;$1\&GT;\n";
+ } else {
+ $_ = "\n=item $ic\n";
+ $ic =~ y/A-Ya-y/B-Zb-z/;
+ $ic =~ s/(\d+)/$1 + 1/eg;
+ }
+ };
+
+ $section .= $shift.$_."\n";
+}
+# End of current file.
+close($inf);
+$inf = pop @instack;
+}
+
+die "No filename or title\n" unless defined $fn && defined $tl;
+
+$sects{NAME} = "$fn \- $tl\n";
+$sects{FOOTNOTES} .= "=back\n" if exists $sects{FOOTNOTES};
+
+for $sect (qw(NAME SYNOPSIS DESCRIPTION OPTIONS EXAMPLES ENVIRONMENT FILES
+ BUGS NOTES FOOTNOTES SEEALSO AUTHOR COPYRIGHT)) {
+ if(exists $sects{$sect}) {
+ $head = $sect;
+ $head =~ s/SEEALSO/SEE ALSO/;
+ print "=head1 $head\n\n";
+ print scalar unmunge ($sects{$sect});
+ print "\n";
+ }
+}
+
+sub usage
+{
+ die "usage: $0 [-D toggle...] [infile [outfile]]\n";
+}
+
+sub postprocess
+{
+ local $_ = $_[0];
+
+ # @value{foo} is replaced by whatever 'foo' is defined as.
+ while (m/(\@value\{([a-zA-Z0-9_-]+)\})/g) {
+ if (! exists $defs{$2}) {
+ print STDERR "Option $2 not defined\n";
+ s/\Q$1\E//;
+ } else {
+ $value = $defs{$2};
+ s/\Q$1\E/$value/;
+ }
+ }
+
+ # Formatting commands.
+ # Temporary escape for @r.
+ s/\@r\{([^\}]*)\}/R<$1>/g;
+ s/\@(?:dfn|var|emph|cite|i)\{([^\}]*)\}/I<$1>/g;
+ s/\@(?:code|kbd)\{([^\}]*)\}/C<$1>/g;
+ s/\@(?:gccoptlist|samp|strong|key|option|env|command|b)\{([^\}]*)\}/B<$1>/g;
+ s/\@sc\{([^\}]*)\}/\U$1/g;
+ s/\@file\{([^\}]*)\}/F<$1>/g;
+ s/\@w\{([^\}]*)\}/S<$1>/g;
+ s/\@(?:dmn|math)\{([^\}]*)\}/$1/g;
+
+ # Cross references are thrown away, as are @noindent and @refill.
+ # (@noindent is impossible in .pod, and @refill is unnecessary.)
+ # @* is also impossible in .pod; we discard it and any newline that
+ # follows it. Similarly, our macro @gol must be discarded.
+
+ s/\(?\@xref\{(?:[^\}]*)\}(?:[^.<]|(?:<[^<>]*>))*\.\)?//g;
+ s/\s+\(\@pxref\{(?:[^\}]*)\}\)//g;
+ s/;\s+\@pxref\{(?:[^\}]*)\}//g;
+ s/\@noindent\s*//g;
+ s/\@refill//g;
+ s/\@gol//g;
+ s/\@\*\s*\n?//g;
+
+ # @uref can take one, two, or three arguments, with different
+ # semantics each time. @url and @email are just like @uref with
+ # one argument, for our purposes.
+ s/\@(?:uref|url|email)\{([^\},]*)\}/&lt;B<$1>&gt;/g;
+ s/\@uref\{([^\},]*),([^\},]*)\}/$2 (C<$1>)/g;
+ s/\@uref\{([^\},]*),([^\},]*),([^\},]*)\}/$3/g;
+
+ # Turn B<blah I<blah> blah> into B<blah> I<blah> B<blah> to
+ # match Texinfo semantics of @emph inside @samp. Also handle @r
+ # inside bold.
+ s/&LT;/</g;
+ s/&GT;/>/g;
+ 1 while s/B<((?:[^<>]|I<[^<>]*>)*)R<([^>]*)>/B<$1>${2}B</g;
+ 1 while (s/B<([^<>]*)I<([^>]+)>/B<$1>I<$2>B</g);
+ 1 while (s/I<([^<>]*)B<([^>]+)>/I<$1>B<$2>I</g);
+ s/[BI]<>//g;
+ s/([BI])<(\s+)([^>]+)>/$2$1<$3>/g;
+ s/([BI])<([^>]+?)(\s+)>/$1<$2>$3/g;
+
+ # Extract footnotes. This has to be done after all other
+ # processing because otherwise the regexp will choke on formatting
+ # inside @footnote.
+ while (/\@footnote/g) {
+ s/\@footnote\{([^\}]+)\}/[$fnno]/;
+ add_footnote($1, $fnno);
+ $fnno++;
+ }
+
+ return $_;
+}
+
+sub unmunge
+{
+ # Replace escaped symbols with their equivalents.
+ local $_ = $_[0];
+
+ s/&lt;/E<lt>/g;
+ s/&gt;/E<gt>/g;
+ s/&lbrace;/\{/g;
+ s/&rbrace;/\}/g;
+ s/&at;/\@/g;
+ s/&amp;/&/g;
+ return $_;
+}
+
+sub add_footnote
+{
+ unless (exists $sects{FOOTNOTES}) {
+ $sects{FOOTNOTES} = "\n=over 4\n\n";
+ }
+
+ $sects{FOOTNOTES} .= "=item $fnno.\n\n"; $fnno++;
+ $sects{FOOTNOTES} .= $_[0];
+ $sects{FOOTNOTES} .= "\n\n";
+}
+
+# stolen from Symbol.pm
+{
+ my $genseq = 0;
+ sub gensym
+ {
+ my $name = "GEN" . $genseq++;
+ my $ref = \*{$name};
+ delete $::{$name};
+ return $ref;
+ }
+}
diff --git a/contrib/ffmpeg/ffinstall.nsi b/contrib/ffmpeg/ffinstall.nsi
new file mode 100644
index 000000000..f483b0174
--- /dev/null
+++ b/contrib/ffmpeg/ffinstall.nsi
@@ -0,0 +1,75 @@
+;NSIS Script For FFmpeg
+
+;Title Of Your Application
+Name "FFmpeg"
+CompletedText "FFmpeg install completed! Enjoy your meal!"
+
+; do a CRC check
+CRCCheck On
+
+; output file name
+OutFile "FFinstall.exe"
+
+; license page introduction
+LicenseText "You must agree to this license before installing."
+
+; license data
+LicenseData ".\COPYING"
+
+; the default installation directory
+InstallDir "$PROGRAMFILES\FFmpeg"
+
+;The text to prompt the user to enter a directory
+DirText "Please select the folder below"
+
+Section "Install"
+ ;Install Files
+ SetOutPath $INSTDIR
+ SetCompress Auto
+ SetOverwrite IfNewer
+ File ".\ffmpeg.exe"
+ File ".\SDL.dll"
+ File ".\ffplay.exe"
+ File ".\COPYING"
+ File ".\CREDITS"
+
+ ; documentation
+ SetOutPath $INSTDIR\doc
+ File ".\doc\faq.html"
+ File ".\doc\ffmpeg-doc.html"
+ File ".\doc\ffplay-doc.html"
+
+ ; Write the uninstall keys for Windows
+ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\FFmpeg" "DisplayName" "FFmpeg (remove only)"
+ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\FFmpeg" "UninstallString" "$INSTDIR\Uninst.exe"
+WriteUninstaller "Uninst.exe"
+SectionEnd
+
+Section "Shortcuts"
+ ;Add Shortcuts
+SectionEnd
+
+UninstallText "This will uninstall FFmpeg from your system"
+
+Section Uninstall
+ ; delete files
+ Delete "$INSTDIR\ffmpeg.exe"
+ Delete "$INSTDIR\SDL.dll"
+ Delete "$INSTDIR\ffplay.exe"
+ Delete "$INSTDIR\COPYING"
+ Delete "$INSTDIR\CREDITS"
+
+ ; delete documentation
+ Delete "$INSTDIR\doc\faq.html"
+ Delete "$INSTDIR\ffmpeg-doc.html"
+ Delete "$INSTDIR\doc\ffplay-doc.html"
+
+ RMDir /r $INSTDIR\doc
+
+ ; delete uninstaller and unistall registry entries
+ Delete "$INSTDIR\Uninst.exe"
+ DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\FFmpeg"
+ DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\FFmpeg"
+ RMDir "$INSTDIR"
+SectionEnd
+
diff --git a/contrib/ffmpeg/ffmpeg.c b/contrib/ffmpeg/ffmpeg.c
new file mode 100644
index 000000000..ab0b689a6
--- /dev/null
+++ b/contrib/ffmpeg/ffmpeg.c
@@ -0,0 +1,3973 @@
+/*
+ * FFmpeg main
+ * Copyright (c) 2000-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 HAVE_AV_CONFIG_H
+#include <signal.h>
+#include <limits.h>
+#include "avformat.h"
+#include "swscale.h"
+#include "framehook.h"
+#include "dsputil.h"
+#include "opt.h"
+#include "fifo.h"
+
+#ifdef __MINGW32__
+#include <conio.h>
+#else
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <termios.h>
+#include <sys/resource.h>
+#endif
+#ifdef CONFIG_OS2
+#include <sys/types.h>
+#include <sys/select.h>
+#include <stdlib.h>
+#endif
+#undef time //needed because HAVE_AV_CONFIG_H is defined on top
+#include <time.h>
+
+#include "version.h"
+#include "cmdutils.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+#if !defined(INFINITY) && defined(HUGE_VAL)
+#define INFINITY HUGE_VAL
+#endif
+
+/* select an input stream for an output stream */
+typedef struct AVStreamMap {
+ int file_index;
+ int stream_index;
+ int sync_file_index;
+ int sync_stream_index;
+} AVStreamMap;
+
+/** select an input file for an output file */
+typedef struct AVMetaDataMap {
+ int out_file;
+ int in_file;
+} AVMetaDataMap;
+
+extern const OptionDef options[];
+
+static void show_help(void);
+static void show_license(void);
+static int opt_default(const char *opt, const char *arg);
+
+#define MAX_FILES 20
+
+static AVFormatContext *input_files[MAX_FILES];
+static int64_t input_files_ts_offset[MAX_FILES];
+static int nb_input_files = 0;
+
+static AVFormatContext *output_files[MAX_FILES];
+static int nb_output_files = 0;
+
+static AVStreamMap stream_maps[MAX_FILES];
+static int nb_stream_maps;
+
+static AVMetaDataMap meta_data_maps[MAX_FILES];
+static int nb_meta_data_maps;
+
+static AVInputFormat *file_iformat;
+static AVOutputFormat *file_oformat;
+static int frame_width = 0;
+static int frame_height = 0;
+static float frame_aspect_ratio = 0;
+static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
+static int frame_padtop = 0;
+static int frame_padbottom = 0;
+static int frame_padleft = 0;
+static int frame_padright = 0;
+static int padcolor[3] = {16,128,128}; /* default to black */
+static int frame_topBand = 0;
+static int frame_bottomBand = 0;
+static int frame_leftBand = 0;
+static int frame_rightBand = 0;
+static int max_frames[4] = {INT_MAX, INT_MAX, INT_MAX, INT_MAX};
+static int frame_rate = 25;
+static int frame_rate_base = 1;
+static float video_qscale = 0;
+static int video_qdiff = 3;
+static uint16_t *intra_matrix = NULL;
+static uint16_t *inter_matrix = NULL;
+#if 0 //experimental, (can be removed)
+static float video_rc_qsquish=1.0;
+static float video_rc_qmod_amp=0;
+static int video_rc_qmod_freq=0;
+#endif
+static char *video_rc_override_string=NULL;
+static char *video_rc_eq="tex^qComp";
+static int me_method = ME_EPZS;
+static int video_disable = 0;
+static int video_discard = 0;
+static int video_codec_id = CODEC_ID_NONE;
+static int video_codec_tag = 0;
+static int same_quality = 0;
+static int do_deinterlace = 0;
+static int packet_size = 0;
+static int strict = 0;
+static int top_field_first = -1;
+static int me_threshold = 0;
+static int intra_dc_precision = 8;
+static int loop_input = 0;
+static int loop_output = AVFMT_NOOUTPUTLOOP;
+static int qp_hist = 0;
+
+static int intra_only = 0;
+static int audio_sample_rate = 44100;
+static int audio_bit_rate = 64000;
+#define QSCALE_NONE -99999
+static float audio_qscale = QSCALE_NONE;
+static int audio_disable = 0;
+static int audio_channels = 1;
+static int audio_codec_id = CODEC_ID_NONE;
+static int audio_codec_tag = 0;
+static char *audio_language = NULL;
+
+static int subtitle_codec_id = CODEC_ID_NONE;
+static char *subtitle_language = NULL;
+
+static float mux_preload= 0.5;
+static float mux_max_delay= 0.7;
+
+static int64_t recording_time = 0;
+static int64_t start_time = 0;
+static int64_t rec_timestamp = 0;
+static int64_t input_ts_offset = 0;
+static int file_overwrite = 0;
+static char *str_title = NULL;
+static char *str_author = NULL;
+static char *str_copyright = NULL;
+static char *str_comment = NULL;
+static char *str_album = NULL;
+static int do_benchmark = 0;
+static int do_hex_dump = 0;
+static int do_pkt_dump = 0;
+static int do_psnr = 0;
+static int do_vstats = 0;
+static int do_pass = 0;
+static char *pass_logfilename = NULL;
+static int audio_stream_copy = 0;
+static int video_stream_copy = 0;
+static int subtitle_stream_copy = 0;
+static int video_sync_method= 1;
+static int audio_sync_method= 0;
+static int copy_ts= 0;
+static int opt_shortest = 0; //
+static int video_global_header = 0;
+
+static int rate_emu = 0;
+
+#ifdef CONFIG_BKTR
+static const char *video_grab_format = "bktr";
+#else
+#ifdef CONFIG_VIDEO4LINUX2
+static const char *video_grab_format = "video4linux2";
+#else
+static const char *video_grab_format = "video4linux";
+#endif
+#endif
+static char *video_device = NULL;
+static char *grab_device = NULL;
+static int video_channel = 0;
+static char *video_standard = "ntsc";
+
+static const char *audio_grab_format = "audio_device";
+static char *audio_device = NULL;
+static int audio_volume = 256;
+
+static int using_stdin = 0;
+static int using_vhook = 0;
+static int verbose = 1;
+static int thread_count= 1;
+static int q_pressed = 0;
+static int64_t video_size = 0;
+static int64_t audio_size = 0;
+static int64_t extra_size = 0;
+static int nb_frames_dup = 0;
+static int nb_frames_drop = 0;
+static int input_sync;
+static int limit_filesize = 0; //
+
+static int pgmyuv_compatibility_hack=0;
+static int dts_delta_threshold = 10;
+
+static int sws_flags = SWS_BICUBIC;
+
+const char **opt_names=NULL;
+int opt_name_count=0;
+AVCodecContext *avctx_opts;
+AVFormatContext *avformat_opts;
+
+static AVBitStreamFilterContext *video_bitstream_filters=NULL;
+static AVBitStreamFilterContext *audio_bitstream_filters=NULL;
+static AVBitStreamFilterContext *bitstream_filters[MAX_FILES][MAX_STREAMS];
+
+#define DEFAULT_PASS_LOGFILENAME "ffmpeg2pass"
+
+struct AVInputStream;
+
+typedef struct AVOutputStream {
+ int file_index; /* file index */
+ int index; /* stream index in the output file */
+ int source_index; /* AVInputStream index */
+ AVStream *st; /* stream in the output file */
+ int encoding_needed; /* true if encoding needed for this stream */
+ int frame_number;
+ /* input pts and corresponding output pts
+ for A/V sync */
+ //double sync_ipts; /* dts from the AVPacket of the demuxer in second units */
+ struct AVInputStream *sync_ist; /* input stream to sync against */
+ int64_t sync_opts; /* output frame counter, could be changed to some true timestamp */ //FIXME look at frame_number
+ /* video only */
+ int video_resample;
+ AVFrame pict_tmp; /* temporary image for resampling */
+ struct SwsContext *img_resample_ctx; /* for image resampling */
+ int resample_height;
+
+ int video_crop;
+ int topBand; /* cropping area sizes */
+ int leftBand;
+
+ int video_pad;
+ int padtop; /* padding area sizes */
+ int padbottom;
+ int padleft;
+ int padright;
+
+ /* audio only */
+ int audio_resample;
+ ReSampleContext *resample; /* for audio resampling */
+ AVFifoBuffer fifo; /* for compression: one audio fifo per codec */
+ FILE *logfile;
+} AVOutputStream;
+
+typedef struct AVInputStream {
+ int file_index;
+ int index;
+ AVStream *st;
+ int discard; /* true if stream data should be discarded */
+ int decoding_needed; /* true if the packets must be decoded in 'raw_fifo' */
+ int64_t sample_index; /* current sample */
+
+ int64_t start; /* time when read started */
+ unsigned long frame; /* current frame */
+ int64_t next_pts; /* synthetic pts for cases where pkt.pts
+ is not defined */
+ int64_t pts; /* current pts */
+ int is_start; /* is 1 at the start and after a discontinuity */
+} AVInputStream;
+
+typedef struct AVInputFile {
+ int eof_reached; /* true if eof reached */
+ int ist_index; /* index of first stream in ist_table */
+ int buffer_size; /* current total buffer size */
+ int buffer_size_max; /* buffer size at which we consider we can stop
+ buffering */
+ int nb_streams; /* nb streams we are aware of */
+} AVInputFile;
+
+#ifndef __MINGW32__
+
+/* init terminal so that we can grab keys */
+static struct termios oldtty;
+#endif
+
+static void term_exit(void)
+{
+#ifndef __MINGW32__
+ tcsetattr (0, TCSANOW, &oldtty);
+#endif
+}
+
+static volatile sig_atomic_t received_sigterm = 0;
+
+static void
+sigterm_handler(int sig)
+{
+ received_sigterm = sig;
+ term_exit();
+}
+
+static void term_init(void)
+{
+#ifndef __MINGW32__
+ struct termios tty;
+
+ tcgetattr (0, &tty);
+ oldtty = tty;
+
+ tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
+ |INLCR|IGNCR|ICRNL|IXON);
+ tty.c_oflag |= OPOST;
+ tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
+ tty.c_cflag &= ~(CSIZE|PARENB);
+ tty.c_cflag |= CS8;
+ tty.c_cc[VMIN] = 1;
+ tty.c_cc[VTIME] = 0;
+
+ tcsetattr (0, TCSANOW, &tty);
+ signal(SIGQUIT, sigterm_handler); /* Quit (POSIX). */
+#endif
+
+ signal(SIGINT , sigterm_handler); /* Interrupt (ANSI). */
+ signal(SIGTERM, sigterm_handler); /* Termination (ANSI). */
+ /*
+ register a function to be called at normal program termination
+ */
+ atexit(term_exit);
+#ifdef CONFIG_BEOS_NETSERVER
+ fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);
+#endif
+}
+
+/* read a key without blocking */
+static int read_key(void)
+{
+#ifdef __MINGW32__
+ if(kbhit())
+ return(getch());
+#else
+ int n = 1;
+ unsigned char ch;
+#ifndef CONFIG_BEOS_NETSERVER
+ struct timeval tv;
+ fd_set rfds;
+
+ FD_ZERO(&rfds);
+ FD_SET(0, &rfds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ n = select(1, &rfds, NULL, NULL, &tv);
+#endif
+ if (n > 0) {
+ n = read(0, &ch, 1);
+ if (n == 1)
+ return ch;
+
+ return n;
+ }
+#endif
+ return -1;
+}
+
+static int decode_interrupt_cb(void)
+{
+ return q_pressed || (q_pressed = read_key() == 'q');
+}
+
+static int read_ffserver_streams(AVFormatContext *s, const char *filename)
+{
+ int i, err;
+ AVFormatContext *ic;
+
+ err = av_open_input_file(&ic, filename, NULL, FFM_PACKET_SIZE, NULL);
+ if (err < 0)
+ return err;
+ /* copy stream format */
+ s->nb_streams = ic->nb_streams;
+ for(i=0;i<ic->nb_streams;i++) {
+ AVStream *st;
+
+ // FIXME: a more elegant solution is needed
+ st = av_mallocz(sizeof(AVStream));
+ memcpy(st, ic->streams[i], sizeof(AVStream));
+ st->codec = avcodec_alloc_context();
+ memcpy(st->codec, ic->streams[i]->codec, sizeof(AVCodecContext));
+ s->streams[i] = st;
+ }
+
+ av_close_input_file(ic);
+ return 0;
+}
+
+static double
+get_sync_ipts(const AVOutputStream *ost)
+{
+ const AVInputStream *ist = ost->sync_ist;
+ return (double)(ist->pts + input_files_ts_offset[ist->file_index] - start_time)/AV_TIME_BASE;
+}
+
+static void write_frame(AVFormatContext *s, AVPacket *pkt, AVCodecContext *avctx, AVBitStreamFilterContext *bsfc){
+ while(bsfc){
+ AVPacket new_pkt= *pkt;
+ int a= av_bitstream_filter_filter(bsfc, avctx, NULL,
+ &new_pkt.data, &new_pkt.size,
+ pkt->data, pkt->size,
+ pkt->flags & PKT_FLAG_KEY);
+ if(a){
+ av_free_packet(pkt);
+ new_pkt.destruct= av_destruct_packet;
+ }
+ *pkt= new_pkt;
+
+ bsfc= bsfc->next;
+ }
+
+ av_interleaved_write_frame(s, pkt);
+}
+
+#define MAX_AUDIO_PACKET_SIZE (128 * 1024)
+
+static void do_audio_out(AVFormatContext *s,
+ AVOutputStream *ost,
+ AVInputStream *ist,
+ unsigned char *buf, int size)
+{
+ uint8_t *buftmp;
+ static uint8_t *audio_buf = NULL;
+ static uint8_t *audio_out = NULL;
+ const int audio_out_size= 4*MAX_AUDIO_PACKET_SIZE;
+
+ int size_out, frame_bytes, ret;
+ AVCodecContext *enc= ost->st->codec;
+
+ /* SC: dynamic allocation of buffers */
+ if (!audio_buf)
+ audio_buf = av_malloc(2*MAX_AUDIO_PACKET_SIZE);
+ if (!audio_out)
+ audio_out = av_malloc(audio_out_size);
+ if (!audio_buf || !audio_out)
+ return; /* Should signal an error ! */
+
+ if(audio_sync_method){
+ double delta = get_sync_ipts(ost) * enc->sample_rate - ost->sync_opts
+ - av_fifo_size(&ost->fifo)/(ost->st->codec->channels * 2);
+ double idelta= delta*ist->st->codec->sample_rate / enc->sample_rate;
+ int byte_delta= ((int)idelta)*2*ist->st->codec->channels;
+
+ //FIXME resample delay
+ if(fabs(delta) > 50){
+ if(ist->is_start){
+ if(byte_delta < 0){
+ byte_delta= FFMAX(byte_delta, -size);
+ size += byte_delta;
+ buf -= byte_delta;
+ if(verbose > 2)
+ fprintf(stderr, "discarding %d audio samples\n", (int)-delta);
+ if(!size)
+ return;
+ ist->is_start=0;
+ }else{
+ static uint8_t *input_tmp= NULL;
+ input_tmp= av_realloc(input_tmp, byte_delta + size);
+
+ if(byte_delta + size <= MAX_AUDIO_PACKET_SIZE)
+ ist->is_start=0;
+ else
+ byte_delta= MAX_AUDIO_PACKET_SIZE - size;
+
+ memset(input_tmp, 0, byte_delta);
+ memcpy(input_tmp + byte_delta, buf, size);
+ buf= input_tmp;
+ size += byte_delta;
+ if(verbose > 2)
+ fprintf(stderr, "adding %d audio samples of silence\n", (int)delta);
+ }
+ }else if(audio_sync_method>1){
+ int comp= clip(delta, -audio_sync_method, audio_sync_method);
+ assert(ost->audio_resample);
+ if(verbose > 2)
+ fprintf(stderr, "compensating audio timestamp drift:%f compensation:%d in:%d\n", delta, comp, enc->sample_rate);
+// fprintf(stderr, "drift:%f len:%d opts:%"PRId64" ipts:%"PRId64" fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(&ost->fifo)/(ost->st->codec->channels * 2));
+ av_resample_compensate(*(struct AVResampleContext**)ost->resample, comp, enc->sample_rate);
+ }
+ }
+ }else
+ ost->sync_opts= lrintf(get_sync_ipts(ost) * enc->sample_rate)
+ - av_fifo_size(&ost->fifo)/(ost->st->codec->channels * 2); //FIXME wrong
+
+ if (ost->audio_resample) {
+ buftmp = audio_buf;
+ size_out = audio_resample(ost->resample,
+ (short *)buftmp, (short *)buf,
+ size / (ist->st->codec->channels * 2));
+ size_out = size_out * enc->channels * 2;
+ } else {
+ buftmp = buf;
+ size_out = size;
+ }
+
+ /* now encode as many frames as possible */
+ if (enc->frame_size > 1) {
+ /* output resampled raw samples */
+ av_fifo_write(&ost->fifo, buftmp, size_out);
+
+ frame_bytes = enc->frame_size * 2 * enc->channels;
+
+ while (av_fifo_read(&ost->fifo, audio_buf, frame_bytes) == 0) {
+ AVPacket pkt;
+ av_init_packet(&pkt);
+
+ ret = avcodec_encode_audio(enc, audio_out, audio_out_size,
+ (short *)audio_buf);
+ audio_size += ret;
+ pkt.stream_index= ost->index;
+ pkt.data= audio_out;
+ pkt.size= ret;
+ if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
+ pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
+ pkt.flags |= PKT_FLAG_KEY;
+ write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
+
+ ost->sync_opts += enc->frame_size;
+ }
+ } else {
+ AVPacket pkt;
+ av_init_packet(&pkt);
+
+ ost->sync_opts += size_out / (2 * enc->channels);
+
+ /* output a pcm frame */
+ /* XXX: change encoding codec API to avoid this ? */
+ switch(enc->codec->id) {
+ case CODEC_ID_PCM_S32LE:
+ case CODEC_ID_PCM_S32BE:
+ case CODEC_ID_PCM_U32LE:
+ case CODEC_ID_PCM_U32BE:
+ size_out = size_out << 1;
+ break;
+ case CODEC_ID_PCM_S24LE:
+ case CODEC_ID_PCM_S24BE:
+ case CODEC_ID_PCM_U24LE:
+ case CODEC_ID_PCM_U24BE:
+ case CODEC_ID_PCM_S24DAUD:
+ size_out = size_out / 2 * 3;
+ break;
+ case CODEC_ID_PCM_S16LE:
+ case CODEC_ID_PCM_S16BE:
+ case CODEC_ID_PCM_U16LE:
+ case CODEC_ID_PCM_U16BE:
+ break;
+ default:
+ size_out = size_out >> 1;
+ break;
+ }
+ ret = avcodec_encode_audio(enc, audio_out, size_out,
+ (short *)buftmp);
+ audio_size += ret;
+ pkt.stream_index= ost->index;
+ pkt.data= audio_out;
+ pkt.size= ret;
+ if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
+ pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
+ pkt.flags |= PKT_FLAG_KEY;
+ write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
+ }
+}
+
+static void pre_process_video_frame(AVInputStream *ist, AVPicture *picture, void **bufp)
+{
+ AVCodecContext *dec;
+ AVPicture *picture2;
+ AVPicture picture_tmp;
+ uint8_t *buf = 0;
+
+ dec = ist->st->codec;
+
+ /* deinterlace : must be done before any resize */
+ if (do_deinterlace || using_vhook) {
+ int size;
+
+ /* create temporary picture */
+ size = avpicture_get_size(dec->pix_fmt, dec->width, dec->height);
+ buf = av_malloc(size);
+ if (!buf)
+ return;
+
+ picture2 = &picture_tmp;
+ avpicture_fill(picture2, buf, dec->pix_fmt, dec->width, dec->height);
+
+ if (do_deinterlace){
+ if(avpicture_deinterlace(picture2, picture,
+ dec->pix_fmt, dec->width, dec->height) < 0) {
+ /* if error, do not deinterlace */
+ av_free(buf);
+ buf = NULL;
+ picture2 = picture;
+ }
+ } else {
+ img_copy(picture2, picture, dec->pix_fmt, dec->width, dec->height);
+ }
+ } else {
+ picture2 = picture;
+ }
+
+ frame_hook_process(picture2, dec->pix_fmt, dec->width, dec->height);
+
+ if (picture != picture2)
+ *picture = *picture2;
+ *bufp = buf;
+}
+
+/* we begin to correct av delay at this threshold */
+#define AV_DELAY_MAX 0.100
+
+static void do_subtitle_out(AVFormatContext *s,
+ AVOutputStream *ost,
+ AVInputStream *ist,
+ AVSubtitle *sub,
+ int64_t pts)
+{
+ static uint8_t *subtitle_out = NULL;
+ int subtitle_out_max_size = 65536;
+ int subtitle_out_size, nb, i;
+ AVCodecContext *enc;
+ AVPacket pkt;
+
+ if (pts == AV_NOPTS_VALUE) {
+ fprintf(stderr, "Subtitle packets must have a pts\n");
+ return;
+ }
+
+ enc = ost->st->codec;
+
+ if (!subtitle_out) {
+ subtitle_out = av_malloc(subtitle_out_max_size);
+ }
+
+ /* Note: DVB subtitle need one packet to draw them and one other
+ packet to clear them */
+ /* XXX: signal it in the codec context ? */
+ if (enc->codec_id == CODEC_ID_DVB_SUBTITLE)
+ nb = 2;
+ else
+ nb = 1;
+
+ for(i = 0; i < nb; i++) {
+ subtitle_out_size = avcodec_encode_subtitle(enc, subtitle_out,
+ subtitle_out_max_size, sub);
+
+ av_init_packet(&pkt);
+ pkt.stream_index = ost->index;
+ pkt.data = subtitle_out;
+ pkt.size = subtitle_out_size;
+ pkt.pts = av_rescale_q(av_rescale_q(pts, ist->st->time_base, AV_TIME_BASE_Q) + input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ost->st->time_base);
+ if (enc->codec_id == CODEC_ID_DVB_SUBTITLE) {
+ /* XXX: the pts correction is handled here. Maybe handling
+ it in the codec would be better */
+ if (i == 0)
+ pkt.pts += 90 * sub->start_display_time;
+ else
+ pkt.pts += 90 * sub->end_display_time;
+ }
+ write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
+ }
+}
+
+static int bit_buffer_size= 1024*256;
+static uint8_t *bit_buffer= NULL;
+
+static void do_video_out(AVFormatContext *s,
+ AVOutputStream *ost,
+ AVInputStream *ist,
+ AVFrame *in_picture,
+ int *frame_size)
+{
+ int nb_frames, i, ret;
+ AVFrame *final_picture, *formatted_picture, *resampling_dst, *padding_src;
+ AVFrame picture_crop_temp, picture_pad_temp;
+ uint8_t *buf = NULL, *buf1 = NULL;
+ AVCodecContext *enc, *dec;
+
+ avcodec_get_frame_defaults(&picture_crop_temp);
+ avcodec_get_frame_defaults(&picture_pad_temp);
+
+ enc = ost->st->codec;
+ dec = ist->st->codec;
+
+ /* by default, we output a single frame */
+ nb_frames = 1;
+
+ *frame_size = 0;
+
+ if(video_sync_method){
+ double vdelta;
+ vdelta = get_sync_ipts(ost) / av_q2d(enc->time_base) - ost->sync_opts;
+ //FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
+ if (vdelta < -1.1)
+ nb_frames = 0;
+ else if (vdelta > 1.1)
+ nb_frames = lrintf(vdelta);
+//fprintf(stderr, "vdelta:%f, ost->sync_opts:%"PRId64", ost->sync_ipts:%f nb_frames:%d\n", vdelta, ost->sync_opts, ost->sync_ipts, nb_frames);
+ if (nb_frames == 0){
+ ++nb_frames_drop;
+ if (verbose>2)
+ fprintf(stderr, "*** drop!\n");
+ }else if (nb_frames > 1) {
+ nb_frames_dup += nb_frames;
+ if (verbose>2)
+ fprintf(stderr, "*** %d dup!\n", nb_frames-1);
+ }
+ }else
+ ost->sync_opts= lrintf(get_sync_ipts(ost) / av_q2d(enc->time_base));
+
+ nb_frames= FFMIN(nb_frames, max_frames[CODEC_TYPE_VIDEO] - ost->frame_number);
+ if (nb_frames <= 0)
+ return;
+
+ if (ost->video_crop) {
+ if (img_crop((AVPicture *)&picture_crop_temp, (AVPicture *)in_picture, dec->pix_fmt, ost->topBand, ost->leftBand) < 0) {
+ av_log(NULL, AV_LOG_ERROR, "error cropping picture\n");
+ goto the_end;
+ }
+ formatted_picture = &picture_crop_temp;
+ } else {
+ formatted_picture = in_picture;
+ }
+
+ final_picture = formatted_picture;
+ padding_src = formatted_picture;
+ resampling_dst = &ost->pict_tmp;
+ if (ost->video_pad) {
+ final_picture = &ost->pict_tmp;
+ if (ost->video_resample) {
+ if (img_crop((AVPicture *)&picture_pad_temp, (AVPicture *)final_picture, enc->pix_fmt, ost->padtop, ost->padleft) < 0) {
+ av_log(NULL, AV_LOG_ERROR, "error padding picture\n");
+ goto the_end;
+ }
+ resampling_dst = &picture_pad_temp;
+ }
+ }
+
+ if (ost->video_resample) {
+ padding_src = NULL;
+ final_picture = &ost->pict_tmp;
+ sws_scale(ost->img_resample_ctx, formatted_picture->data, formatted_picture->linesize,
+ 0, ost->resample_height, resampling_dst->data, resampling_dst->linesize);
+ }
+
+ if (ost->video_pad) {
+ img_pad((AVPicture*)final_picture, (AVPicture *)padding_src,
+ enc->height, enc->width, enc->pix_fmt,
+ ost->padtop, ost->padbottom, ost->padleft, ost->padright, padcolor);
+ }
+
+ /* duplicates frame if needed */
+ for(i=0;i<nb_frames;i++) {
+ AVPacket pkt;
+ av_init_packet(&pkt);
+ pkt.stream_index= ost->index;
+
+ if (s->oformat->flags & AVFMT_RAWPICTURE) {
+ /* raw pictures are written as AVPicture structure to
+ avoid any copies. We support temorarily the older
+ method. */
+ AVFrame* old_frame = enc->coded_frame;
+ enc->coded_frame = dec->coded_frame; //FIXME/XXX remove this hack
+ pkt.data= (uint8_t *)final_picture;
+ pkt.size= sizeof(AVPicture);
+ if(dec->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
+ pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
+ if(dec->coded_frame && dec->coded_frame->key_frame)
+ pkt.flags |= PKT_FLAG_KEY;
+
+ write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
+ enc->coded_frame = old_frame;
+ } else {
+ AVFrame big_picture;
+
+ big_picture= *final_picture;
+ /* better than nothing: use input picture interlaced
+ settings */
+ big_picture.interlaced_frame = in_picture->interlaced_frame;
+ if(avctx_opts->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)){
+ if(top_field_first == -1)
+ big_picture.top_field_first = in_picture->top_field_first;
+ else
+ big_picture.top_field_first = top_field_first;
+ }
+
+ /* handles sameq here. This is not correct because it may
+ not be a global option */
+ if (same_quality) {
+ big_picture.quality = ist->st->quality;
+ }else
+ big_picture.quality = ost->st->quality;
+ if(!me_threshold)
+ big_picture.pict_type = 0;
+// big_picture.pts = AV_NOPTS_VALUE;
+ big_picture.pts= ost->sync_opts;
+// big_picture.pts= av_rescale(ost->sync_opts, AV_TIME_BASE*(int64_t)enc->time_base.num, enc->time_base.den);
+//av_log(NULL, AV_LOG_DEBUG, "%"PRId64" -> encoder\n", ost->sync_opts);
+ ret = avcodec_encode_video(enc,
+ bit_buffer, bit_buffer_size,
+ &big_picture);
+ if (ret == -1) {
+ fprintf(stderr, "Video encoding failed\n");
+ exit(1);
+ }
+ //enc->frame_number = enc->real_pict_num;
+ if(ret>0){
+ pkt.data= bit_buffer;
+ pkt.size= ret;
+ if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
+ pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
+/*av_log(NULL, AV_LOG_DEBUG, "encoder -> %"PRId64"/%"PRId64"\n",
+ pkt.pts != AV_NOPTS_VALUE ? av_rescale(pkt.pts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1,
+ pkt.dts != AV_NOPTS_VALUE ? av_rescale(pkt.dts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1);*/
+
+ if(enc->coded_frame && enc->coded_frame->key_frame)
+ pkt.flags |= PKT_FLAG_KEY;
+ write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
+ *frame_size = ret;
+ //fprintf(stderr,"\nFrame: %3d %3d size: %5d type: %d",
+ // enc->frame_number-1, enc->real_pict_num, ret,
+ // enc->pict_type);
+ /* if two pass, output log */
+ if (ost->logfile && enc->stats_out) {
+ fprintf(ost->logfile, "%s", enc->stats_out);
+ }
+ }
+ }
+ ost->sync_opts++;
+ ost->frame_number++;
+ }
+ the_end:
+ av_free(buf);
+ av_free(buf1);
+}
+
+static double psnr(double d){
+ if(d==0) return INFINITY;
+ return -10.0*log(d)/log(10.0);
+}
+
+static void do_video_stats(AVFormatContext *os, AVOutputStream *ost,
+ int frame_size)
+{
+ static FILE *fvstats=NULL;
+ char filename[40];
+ time_t today2;
+ struct tm *today;
+ AVCodecContext *enc;
+ int frame_number;
+ int64_t ti;
+ double ti1, bitrate, avg_bitrate;
+
+ if (!fvstats) {
+ today2 = time(NULL);
+ today = localtime(&today2);
+ snprintf(filename, sizeof(filename), "vstats_%02d%02d%02d.log", today->tm_hour,
+ today->tm_min,
+ today->tm_sec);
+ fvstats = fopen(filename,"w");
+ if (!fvstats) {
+ perror("fopen");
+ exit(1);
+ }
+ }
+
+ ti = MAXINT64;
+ enc = ost->st->codec;
+ if (enc->codec_type == CODEC_TYPE_VIDEO) {
+ frame_number = ost->frame_number;
+ fprintf(fvstats, "frame= %5d q= %2.1f ", frame_number, enc->coded_frame->quality/(float)FF_QP2LAMBDA);
+ if (enc->flags&CODEC_FLAG_PSNR)
+ fprintf(fvstats, "PSNR= %6.2f ", psnr(enc->coded_frame->error[0]/(enc->width*enc->height*255.0*255.0)));
+
+ fprintf(fvstats,"f_size= %6d ", frame_size);
+ /* compute pts value */
+ ti1 = ost->sync_opts * av_q2d(enc->time_base);
+ if (ti1 < 0.01)
+ ti1 = 0.01;
+
+ bitrate = (frame_size * 8) / av_q2d(enc->time_base) / 1000.0;
+ avg_bitrate = (double)(video_size * 8) / ti1 / 1000.0;
+ fprintf(fvstats, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
+ (double)video_size / 1024, ti1, bitrate, avg_bitrate);
+ fprintf(fvstats,"type= %c\n", av_get_pict_type_char(enc->coded_frame->pict_type));
+ }
+}
+
+static void print_report(AVFormatContext **output_files,
+ AVOutputStream **ost_table, int nb_ostreams,
+ int is_last_report)
+{
+ char buf[1024];
+ AVOutputStream *ost;
+ AVFormatContext *oc, *os;
+ int64_t total_size;
+ AVCodecContext *enc;
+ int frame_number, vid, i;
+ double bitrate, ti1, pts;
+ static int64_t last_time = -1;
+ static int qp_histogram[52];
+
+ if (!is_last_report) {
+ int64_t cur_time;
+ /* display the report every 0.5 seconds */
+ cur_time = av_gettime();
+ if (last_time == -1) {
+ last_time = cur_time;
+ return;
+ }
+ if ((cur_time - last_time) < 500000)
+ return;
+ last_time = cur_time;
+ }
+
+
+ oc = output_files[0];
+
+ total_size = url_ftell(&oc->pb);
+
+ buf[0] = '\0';
+ ti1 = 1e10;
+ vid = 0;
+ for(i=0;i<nb_ostreams;i++) {
+ ost = ost_table[i];
+ os = output_files[ost->file_index];
+ enc = ost->st->codec;
+ if (vid && enc->codec_type == CODEC_TYPE_VIDEO) {
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ",
+ enc->coded_frame->quality/(float)FF_QP2LAMBDA);
+ }
+ if (!vid && enc->codec_type == CODEC_TYPE_VIDEO) {
+ frame_number = ost->frame_number;
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d q=%3.1f ",
+ frame_number, enc->coded_frame ? enc->coded_frame->quality/(float)FF_QP2LAMBDA : -1);
+ if(is_last_report)
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "L");
+ if(qp_hist && enc->coded_frame){
+ int j;
+ int qp= lrintf(enc->coded_frame->quality/(float)FF_QP2LAMBDA);
+ if(qp>=0 && qp<sizeof(qp_histogram)/sizeof(int))
+ qp_histogram[qp]++;
+ for(j=0; j<32; j++)
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%X", (int)lrintf(log(qp_histogram[j]+1)/log(2)));
+ }
+ if (enc->flags&CODEC_FLAG_PSNR){
+ int j;
+ double error, error_sum=0;
+ double scale, scale_sum=0;
+ char type[3]= {'Y','U','V'};
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "PSNR=");
+ for(j=0; j<3; j++){
+ if(is_last_report){
+ error= enc->error[j];
+ scale= enc->width*enc->height*255.0*255.0*frame_number;
+ }else{
+ error= enc->coded_frame->error[j];
+ scale= enc->width*enc->height*255.0*255.0;
+ }
+ if(j) scale/=4;
+ error_sum += error;
+ scale_sum += scale;
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%c:%2.2f ", type[j], psnr(error/scale));
+ }
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "*:%2.2f ", psnr(error_sum/scale_sum));
+ }
+ vid = 1;
+ }
+ /* compute min output value */
+ pts = (double)ost->st->pts.val * ost->st->time_base.num / ost->st->time_base.den;
+ if ((pts < ti1) && (pts > 0))
+ ti1 = pts;
+ }
+ if (ti1 < 0.01)
+ ti1 = 0.01;
+
+ if (verbose || is_last_report) {
+ bitrate = (double)(total_size * 8) / ti1 / 1000.0;
+
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+ "size=%8.0fkB time=%0.1f bitrate=%6.1fkbits/s",
+ (double)total_size / 1024, ti1, bitrate);
+
+ if (verbose > 1)
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " dup=%d drop=%d",
+ nb_frames_dup, nb_frames_drop);
+
+ if (verbose >= 0)
+ fprintf(stderr, "%s \r", buf);
+
+ fflush(stderr);
+ }
+
+ if (is_last_report && verbose >= 0){
+ int64_t raw= audio_size + video_size + extra_size;
+ fprintf(stderr, "\n");
+ fprintf(stderr, "video:%1.0fkB audio:%1.0fkB global headers:%1.0fkB muxing overhead %f%%\n",
+ video_size/1024.0,
+ audio_size/1024.0,
+ extra_size/1024.0,
+ 100.0*(total_size - raw)/raw
+ );
+ }
+}
+
+/* pkt = NULL means EOF (needed to flush decoder buffers) */
+static int output_packet(AVInputStream *ist, int ist_index,
+ AVOutputStream **ost_table, int nb_ostreams,
+ const AVPacket *pkt)
+{
+ AVFormatContext *os;
+ AVOutputStream *ost;
+ uint8_t *ptr;
+ int len, ret, i;
+ uint8_t *data_buf;
+ int data_size, got_picture;
+ AVFrame picture;
+ void *buffer_to_free;
+ static unsigned int samples_size= 0;
+ static short *samples= NULL;
+ AVSubtitle subtitle, *subtitle_to_free;
+ int got_subtitle;
+
+ if(!pkt){
+ ist->pts= ist->next_pts; // needed for last packet if vsync=0
+ } else if (pkt->dts != AV_NOPTS_VALUE) { //FIXME seems redundant, as libavformat does this too
+ ist->next_pts = ist->pts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
+ } else {
+// assert(ist->pts == ist->next_pts);
+ }
+
+ if (pkt == NULL) {
+ /* EOF handling */
+ ptr = NULL;
+ len = 0;
+ goto handle_eof;
+ }
+
+ len = pkt->size;
+ ptr = pkt->data;
+ while (len > 0) {
+ handle_eof:
+ /* decode the packet if needed */
+ data_buf = NULL; /* fail safe */
+ data_size = 0;
+ subtitle_to_free = NULL;
+ if (ist->decoding_needed) {
+ switch(ist->st->codec->codec_type) {
+ case CODEC_TYPE_AUDIO:{
+ if(pkt)
+ samples= av_fast_realloc(samples, &samples_size, FFMAX(pkt->size, AVCODEC_MAX_AUDIO_FRAME_SIZE));
+ /* XXX: could avoid copy if PCM 16 bits with same
+ endianness as CPU */
+ ret = avcodec_decode_audio(ist->st->codec, samples, &data_size,
+ ptr, len);
+ if (ret < 0)
+ goto fail_decode;
+ ptr += ret;
+ len -= ret;
+ /* Some bug in mpeg audio decoder gives */
+ /* data_size < 0, it seems they are overflows */
+ if (data_size <= 0) {
+ /* no audio frame */
+ continue;
+ }
+ data_buf = (uint8_t *)samples;
+ ist->next_pts += ((int64_t)AV_TIME_BASE/2 * data_size) /
+ (ist->st->codec->sample_rate * ist->st->codec->channels);
+ break;}
+ case CODEC_TYPE_VIDEO:
+ data_size = (ist->st->codec->width * ist->st->codec->height * 3) / 2;
+ /* XXX: allocate picture correctly */
+ avcodec_get_frame_defaults(&picture);
+
+ ret = avcodec_decode_video(ist->st->codec,
+ &picture, &got_picture, ptr, len);
+ ist->st->quality= picture.quality;
+ if (ret < 0)
+ goto fail_decode;
+ if (!got_picture) {
+ /* no picture yet */
+ goto discard_packet;
+ }
+ if (ist->st->codec->time_base.num != 0) {
+ ist->next_pts += ((int64_t)AV_TIME_BASE *
+ ist->st->codec->time_base.num) /
+ ist->st->codec->time_base.den;
+ }
+ len = 0;
+ break;
+ case CODEC_TYPE_SUBTITLE:
+ ret = avcodec_decode_subtitle(ist->st->codec,
+ &subtitle, &got_subtitle, ptr, len);
+ if (ret < 0)
+ goto fail_decode;
+ if (!got_subtitle) {
+ goto discard_packet;
+ }
+ subtitle_to_free = &subtitle;
+ len = 0;
+ break;
+ default:
+ goto fail_decode;
+ }
+ } else {
+ switch(ist->st->codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ ist->next_pts += ((int64_t)AV_TIME_BASE * ist->st->codec->frame_size) /
+ (ist->st->codec->sample_rate * ist->st->codec->channels);
+ break;
+ case CODEC_TYPE_VIDEO:
+ if (ist->st->codec->time_base.num != 0) {
+ ist->next_pts += ((int64_t)AV_TIME_BASE *
+ ist->st->codec->time_base.num) /
+ ist->st->codec->time_base.den;
+ }
+ break;
+ }
+ data_buf = ptr;
+ data_size = len;
+ ret = len;
+ len = 0;
+ }
+
+ buffer_to_free = NULL;
+ if (ist->st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ pre_process_video_frame(ist, (AVPicture *)&picture,
+ &buffer_to_free);
+ }
+
+ // preprocess audio (volume)
+ if (ist->st->codec->codec_type == CODEC_TYPE_AUDIO) {
+ if (audio_volume != 256) {
+ short *volp;
+ volp = samples;
+ for(i=0;i<(data_size / sizeof(short));i++) {
+ int v = ((*volp) * audio_volume + 128) >> 8;
+ if (v < -32768) v = -32768;
+ if (v > 32767) v = 32767;
+ *volp++ = v;
+ }
+ }
+ }
+
+ /* frame rate emulation */
+ if (ist->st->codec->rate_emu) {
+ int64_t pts = av_rescale((int64_t) ist->frame * ist->st->codec->time_base.num, 1000000, ist->st->codec->time_base.den);
+ int64_t now = av_gettime() - ist->start;
+ if (pts > now)
+ usleep(pts - now);
+
+ ist->frame++;
+ }
+
+#if 0
+ /* mpeg PTS deordering : if it is a P or I frame, the PTS
+ is the one of the next displayed one */
+ /* XXX: add mpeg4 too ? */
+ if (ist->st->codec->codec_id == CODEC_ID_MPEG1VIDEO) {
+ if (ist->st->codec->pict_type != B_TYPE) {
+ int64_t tmp;
+ tmp = ist->last_ip_pts;
+ ist->last_ip_pts = ist->frac_pts.val;
+ ist->frac_pts.val = tmp;
+ }
+ }
+#endif
+ /* if output time reached then transcode raw format,
+ encode packets and output them */
+ if (start_time == 0 || ist->pts >= start_time)
+ for(i=0;i<nb_ostreams;i++) {
+ int frame_size;
+
+ ost = ost_table[i];
+ if (ost->source_index == ist_index) {
+ os = output_files[ost->file_index];
+
+#if 0
+ printf("%d: got pts=%0.3f %0.3f\n", i,
+ (double)pkt->pts / AV_TIME_BASE,
+ ((double)ist->pts / AV_TIME_BASE) -
+ ((double)ost->st->pts.val * ost->st->time_base.num / ost->st->time_base.den));
+#endif
+ /* set the input output pts pairs */
+ //ost->sync_ipts = (double)(ist->pts + input_files_ts_offset[ist->file_index] - start_time)/ AV_TIME_BASE;
+
+ if (ost->encoding_needed) {
+ switch(ost->st->codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ do_audio_out(os, ost, ist, data_buf, data_size);
+ break;
+ case CODEC_TYPE_VIDEO:
+ do_video_out(os, ost, ist, &picture, &frame_size);
+ video_size += frame_size;
+ if (do_vstats && frame_size)
+ do_video_stats(os, ost, frame_size);
+ break;
+ case CODEC_TYPE_SUBTITLE:
+ do_subtitle_out(os, ost, ist, &subtitle,
+ pkt->pts);
+ break;
+ default:
+ av_abort();
+ }
+ } else {
+ AVFrame avframe; //FIXME/XXX remove this
+ AVPacket opkt;
+ av_init_packet(&opkt);
+
+ /* no reencoding needed : output the packet directly */
+ /* force the input stream PTS */
+
+ avcodec_get_frame_defaults(&avframe);
+ ost->st->codec->coded_frame= &avframe;
+ avframe.key_frame = pkt->flags & PKT_FLAG_KEY;
+
+ if(ost->st->codec->codec_type == CODEC_TYPE_AUDIO)
+ audio_size += data_size;
+ else if (ost->st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ video_size += data_size;
+ ost->sync_opts++;
+ }
+
+ opkt.stream_index= ost->index;
+ if(pkt->pts != AV_NOPTS_VALUE)
+ opkt.pts= av_rescale_q(av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q) + input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ost->st->time_base);
+ else
+ opkt.pts= AV_NOPTS_VALUE;
+
+ {
+ int64_t dts;
+ if (pkt->dts == AV_NOPTS_VALUE)
+ dts = ist->next_pts;
+ else
+ dts= av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
+ opkt.dts= av_rescale_q(dts + input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ost->st->time_base);
+ }
+ opkt.flags= pkt->flags;
+
+ //FIXME remove the following 2 lines they shall be replaced by the bitstream filters
+ if(av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & PKT_FLAG_KEY))
+ opkt.destruct= av_destruct_packet;
+
+ write_frame(os, &opkt, ost->st->codec, bitstream_filters[ost->file_index][pkt->stream_index]);
+ ost->st->codec->frame_number++;
+ ost->frame_number++;
+ av_free_packet(&opkt);
+ }
+ }
+ }
+ av_free(buffer_to_free);
+ /* XXX: allocate the subtitles in the codec ? */
+ if (subtitle_to_free) {
+ if (subtitle_to_free->rects != NULL) {
+ for (i = 0; i < subtitle_to_free->num_rects; i++) {
+ av_free(subtitle_to_free->rects[i].bitmap);
+ av_free(subtitle_to_free->rects[i].rgba_palette);
+ }
+ av_freep(&subtitle_to_free->rects);
+ }
+ subtitle_to_free->num_rects = 0;
+ subtitle_to_free = NULL;
+ }
+ }
+ discard_packet:
+ if (pkt == NULL) {
+ /* EOF handling */
+
+ for(i=0;i<nb_ostreams;i++) {
+ ost = ost_table[i];
+ if (ost->source_index == ist_index) {
+ AVCodecContext *enc= ost->st->codec;
+ os = output_files[ost->file_index];
+
+ if(ost->st->codec->codec_type == CODEC_TYPE_AUDIO && enc->frame_size <=1)
+ continue;
+ if(ost->st->codec->codec_type == CODEC_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE))
+ continue;
+
+ if (ost->encoding_needed) {
+ for(;;) {
+ AVPacket pkt;
+ int fifo_bytes;
+ av_init_packet(&pkt);
+ pkt.stream_index= ost->index;
+
+ switch(ost->st->codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ fifo_bytes = av_fifo_size(&ost->fifo);
+ ret = 0;
+ /* encode any samples remaining in fifo */
+ if(fifo_bytes > 0 && enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) {
+ int fs_tmp = enc->frame_size;
+ enc->frame_size = fifo_bytes / (2 * enc->channels);
+ if(av_fifo_read(&ost->fifo, (uint8_t *)samples, fifo_bytes) == 0) {
+ ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, samples);
+ }
+ enc->frame_size = fs_tmp;
+ }
+ if(ret <= 0) {
+ ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, NULL);
+ }
+ audio_size += ret;
+ pkt.flags |= PKT_FLAG_KEY;
+ break;
+ case CODEC_TYPE_VIDEO:
+ ret = avcodec_encode_video(enc, bit_buffer, bit_buffer_size, NULL);
+ video_size += ret;
+ if(enc->coded_frame && enc->coded_frame->key_frame)
+ pkt.flags |= PKT_FLAG_KEY;
+ if (ost->logfile && enc->stats_out) {
+ fprintf(ost->logfile, "%s", enc->stats_out);
+ }
+ break;
+ default:
+ ret=-1;
+ }
+
+ if(ret<=0)
+ break;
+ pkt.data= bit_buffer;
+ pkt.size= ret;
+ if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
+ pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
+ write_frame(os, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+ fail_decode:
+ return -1;
+}
+
+
+/*
+ * The following code is the main loop of the file converter
+ */
+static int av_encode(AVFormatContext **output_files,
+ int nb_output_files,
+ AVFormatContext **input_files,
+ int nb_input_files,
+ AVStreamMap *stream_maps, int nb_stream_maps)
+{
+ int ret, i, j, k, n, nb_istreams = 0, nb_ostreams = 0;
+ AVFormatContext *is, *os;
+ AVCodecContext *codec, *icodec;
+ AVOutputStream *ost, **ost_table = NULL;
+ AVInputStream *ist, **ist_table = NULL;
+ AVInputFile *file_table;
+ AVFormatContext *stream_no_data;
+ int key;
+
+ file_table= (AVInputFile*) av_mallocz(nb_input_files * sizeof(AVInputFile));
+ if (!file_table)
+ goto fail;
+
+ /* input stream init */
+ j = 0;
+ for(i=0;i<nb_input_files;i++) {
+ is = input_files[i];
+ file_table[i].ist_index = j;
+ file_table[i].nb_streams = is->nb_streams;
+ j += is->nb_streams;
+ }
+ nb_istreams = j;
+
+ ist_table = av_mallocz(nb_istreams * sizeof(AVInputStream *));
+ if (!ist_table)
+ goto fail;
+
+ for(i=0;i<nb_istreams;i++) {
+ ist = av_mallocz(sizeof(AVInputStream));
+ if (!ist)
+ goto fail;
+ ist_table[i] = ist;
+ }
+ j = 0;
+ for(i=0;i<nb_input_files;i++) {
+ is = input_files[i];
+ for(k=0;k<is->nb_streams;k++) {
+ ist = ist_table[j++];
+ ist->st = is->streams[k];
+ ist->file_index = i;
+ ist->index = k;
+ ist->discard = 1; /* the stream is discarded by default
+ (changed later) */
+
+ if (ist->st->codec->rate_emu) {
+ ist->start = av_gettime();
+ ist->frame = 0;
+ }
+ }
+ }
+
+ /* output stream init */
+ nb_ostreams = 0;
+ for(i=0;i<nb_output_files;i++) {
+ os = output_files[i];
+ if (!os->nb_streams) {
+ fprintf(stderr, "Output file does not contain any stream\n");
+ exit(1);
+ }
+ nb_ostreams += os->nb_streams;
+ }
+ if (nb_stream_maps > 0 && nb_stream_maps != nb_ostreams) {
+ fprintf(stderr, "Number of stream maps must match number of output streams\n");
+ exit(1);
+ }
+
+ /* Sanity check the mapping args -- do the input files & streams exist? */
+ for(i=0;i<nb_stream_maps;i++) {
+ int fi = stream_maps[i].file_index;
+ int si = stream_maps[i].stream_index;
+
+ if (fi < 0 || fi > nb_input_files - 1 ||
+ si < 0 || si > file_table[fi].nb_streams - 1) {
+ fprintf(stderr,"Could not find input stream #%d.%d\n", fi, si);
+ exit(1);
+ }
+ fi = stream_maps[i].sync_file_index;
+ si = stream_maps[i].sync_stream_index;
+ if (fi < 0 || fi > nb_input_files - 1 ||
+ si < 0 || si > file_table[fi].nb_streams - 1) {
+ fprintf(stderr,"Could not find sync stream #%d.%d\n", fi, si);
+ exit(1);
+ }
+ }
+
+ ost_table = av_mallocz(sizeof(AVOutputStream *) * nb_ostreams);
+ if (!ost_table)
+ goto fail;
+ for(i=0;i<nb_ostreams;i++) {
+ ost = av_mallocz(sizeof(AVOutputStream));
+ if (!ost)
+ goto fail;
+ ost_table[i] = ost;
+ }
+
+ n = 0;
+ for(k=0;k<nb_output_files;k++) {
+ os = output_files[k];
+ for(i=0;i<os->nb_streams;i++) {
+ int found;
+ ost = ost_table[n++];
+ ost->file_index = k;
+ ost->index = i;
+ ost->st = os->streams[i];
+ if (nb_stream_maps > 0) {
+ ost->source_index = file_table[stream_maps[n-1].file_index].ist_index +
+ stream_maps[n-1].stream_index;
+
+ /* Sanity check that the stream types match */
+ if (ist_table[ost->source_index]->st->codec->codec_type != ost->st->codec->codec_type) {
+ fprintf(stderr, "Codec type mismatch for mapping #%d.%d -> #%d.%d\n",
+ stream_maps[n-1].file_index, stream_maps[n-1].stream_index,
+ ost->file_index, ost->index);
+ exit(1);
+ }
+
+ } else {
+ /* get corresponding input stream index : we select the first one with the right type */
+ found = 0;
+ for(j=0;j<nb_istreams;j++) {
+ ist = ist_table[j];
+ if (ist->discard &&
+ ist->st->codec->codec_type == ost->st->codec->codec_type) {
+ ost->source_index = j;
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ /* try again and reuse existing stream */
+ for(j=0;j<nb_istreams;j++) {
+ ist = ist_table[j];
+ if (ist->st->codec->codec_type == ost->st->codec->codec_type) {
+ ost->source_index = j;
+ found = 1;
+ }
+ }
+ if (!found) {
+ fprintf(stderr, "Could not find input stream matching output stream #%d.%d\n",
+ ost->file_index, ost->index);
+ exit(1);
+ }
+ }
+ }
+ ist = ist_table[ost->source_index];
+ ist->discard = 0;
+ ost->sync_ist = (nb_stream_maps > 0) ?
+ ist_table[file_table[stream_maps[n-1].sync_file_index].ist_index +
+ stream_maps[n-1].sync_stream_index] : ist;
+ }
+ }
+
+ /* for each output stream, we compute the right encoding parameters */
+ for(i=0;i<nb_ostreams;i++) {
+ ost = ost_table[i];
+ ist = ist_table[ost->source_index];
+
+ codec = ost->st->codec;
+ icodec = ist->st->codec;
+
+ if (ost->st->stream_copy) {
+ /* if stream_copy is selected, no need to decode or encode */
+ codec->codec_id = icodec->codec_id;
+ codec->codec_type = icodec->codec_type;
+ if(!codec->codec_tag) codec->codec_tag = icodec->codec_tag;
+ codec->bit_rate = icodec->bit_rate;
+ codec->extradata= icodec->extradata;
+ codec->extradata_size= icodec->extradata_size;
+ if(av_q2d(icodec->time_base) > av_q2d(ist->st->time_base) && av_q2d(ist->st->time_base) < 1.0/1000)
+ codec->time_base = icodec->time_base;
+ else
+ codec->time_base = ist->st->time_base;
+ switch(codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ codec->sample_rate = icodec->sample_rate;
+ codec->channels = icodec->channels;
+ codec->frame_size = icodec->frame_size;
+ codec->block_align= icodec->block_align;
+ break;
+ case CODEC_TYPE_VIDEO:
+ codec->pix_fmt = icodec->pix_fmt;
+ codec->width = icodec->width;
+ codec->height = icodec->height;
+ codec->has_b_frames = icodec->has_b_frames;
+ break;
+ case CODEC_TYPE_SUBTITLE:
+ break;
+ default:
+ av_abort();
+ }
+ } else {
+ switch(codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ if (av_fifo_init(&ost->fifo, 2 * MAX_AUDIO_PACKET_SIZE))
+ goto fail;
+
+ if (codec->channels == icodec->channels &&
+ codec->sample_rate == icodec->sample_rate) {
+ ost->audio_resample = 0;
+ } else {
+ if (codec->channels != icodec->channels &&
+ (icodec->codec_id == CODEC_ID_AC3 ||
+ icodec->codec_id == CODEC_ID_DTS)) {
+ /* Special case for 5:1 AC3 and DTS input */
+ /* and mono or stereo output */
+ /* Request specific number of channels */
+ icodec->channels = codec->channels;
+ if (codec->sample_rate == icodec->sample_rate)
+ ost->audio_resample = 0;
+ else {
+ ost->audio_resample = 1;
+ }
+ } else {
+ ost->audio_resample = 1;
+ }
+ }
+ if(audio_sync_method>1)
+ ost->audio_resample = 1;
+
+ if(ost->audio_resample){
+ ost->resample = audio_resample_init(codec->channels, icodec->channels,
+ codec->sample_rate, icodec->sample_rate);
+ if(!ost->resample){
+ printf("Can't resample. Aborting.\n");
+ av_abort();
+ }
+ }
+ ist->decoding_needed = 1;
+ ost->encoding_needed = 1;
+ break;
+ case CODEC_TYPE_VIDEO:
+ ost->video_crop = ((frame_leftBand + frame_rightBand + frame_topBand + frame_bottomBand) != 0);
+ ost->video_pad = ((frame_padleft + frame_padright + frame_padtop + frame_padbottom) != 0);
+ ost->video_resample = ((codec->width != icodec->width -
+ (frame_leftBand + frame_rightBand) +
+ (frame_padleft + frame_padright)) ||
+ (codec->height != icodec->height -
+ (frame_topBand + frame_bottomBand) +
+ (frame_padtop + frame_padbottom)) ||
+ (codec->pix_fmt != icodec->pix_fmt));
+ if (ost->video_crop) {
+ ost->topBand = frame_topBand;
+ ost->leftBand = frame_leftBand;
+ }
+ if (ost->video_pad) {
+ ost->padtop = frame_padtop;
+ ost->padleft = frame_padleft;
+ ost->padbottom = frame_padbottom;
+ ost->padright = frame_padright;
+ if (!ost->video_resample) {
+ avcodec_get_frame_defaults(&ost->pict_tmp);
+ if( avpicture_alloc( (AVPicture*)&ost->pict_tmp, codec->pix_fmt,
+ codec->width, codec->height ) )
+ goto fail;
+ }
+ }
+ if (ost->video_resample) {
+ avcodec_get_frame_defaults(&ost->pict_tmp);
+ if( avpicture_alloc( (AVPicture*)&ost->pict_tmp, codec->pix_fmt,
+ codec->width, codec->height ) )
+ goto fail;
+
+ ost->img_resample_ctx = sws_getContext(
+ icodec->width - (frame_leftBand + frame_rightBand),
+ icodec->height - (frame_topBand + frame_bottomBand),
+ icodec->pix_fmt,
+ codec->width - (frame_padleft + frame_padright),
+ codec->height - (frame_padtop + frame_padbottom),
+ codec->pix_fmt,
+ sws_flags, NULL, NULL, NULL);
+ if (ost->img_resample_ctx == NULL) {
+ fprintf(stderr, "Cannot get resampling context\n");
+ exit(1);
+ }
+ ost->resample_height = icodec->height - (frame_topBand + frame_bottomBand);
+ }
+ ost->encoding_needed = 1;
+ ist->decoding_needed = 1;
+ break;
+ case CODEC_TYPE_SUBTITLE:
+ ost->encoding_needed = 1;
+ ist->decoding_needed = 1;
+ break;
+ default:
+ av_abort();
+ break;
+ }
+ /* two pass mode */
+ if (ost->encoding_needed &&
+ (codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2))) {
+ char logfilename[1024];
+ FILE *f;
+ int size;
+ char *logbuffer;
+
+ snprintf(logfilename, sizeof(logfilename), "%s-%d.log",
+ pass_logfilename ?
+ pass_logfilename : DEFAULT_PASS_LOGFILENAME, i);
+ if (codec->flags & CODEC_FLAG_PASS1) {
+ f = fopen(logfilename, "w");
+ if (!f) {
+ perror(logfilename);
+ exit(1);
+ }
+ ost->logfile = f;
+ } else {
+ /* read the log file */
+ f = fopen(logfilename, "r");
+ if (!f) {
+ perror(logfilename);
+ exit(1);
+ }
+ fseek(f, 0, SEEK_END);
+ size = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ logbuffer = av_malloc(size + 1);
+ if (!logbuffer) {
+ fprintf(stderr, "Could not allocate log buffer\n");
+ exit(1);
+ }
+ size = fread(logbuffer, 1, size, f);
+ fclose(f);
+ logbuffer[size] = '\0';
+ codec->stats_in = logbuffer;
+ }
+ }
+ }
+ if(codec->codec_type == CODEC_TYPE_VIDEO){
+ int size= codec->width * codec->height;
+ bit_buffer_size= FFMAX(bit_buffer_size, 4*size);
+ }
+ }
+
+ if (!bit_buffer)
+ bit_buffer = av_malloc(bit_buffer_size);
+ if (!bit_buffer)
+ goto fail;
+
+ /* dump the file output parameters - cannot be done before in case
+ of stream copy */
+ for(i=0;i<nb_output_files;i++) {
+ dump_format(output_files[i], i, output_files[i]->filename, 1);
+ }
+
+ /* dump the stream mapping */
+ if (verbose >= 0) {
+ fprintf(stderr, "Stream mapping:\n");
+ for(i=0;i<nb_ostreams;i++) {
+ ost = ost_table[i];
+ fprintf(stderr, " Stream #%d.%d -> #%d.%d",
+ ist_table[ost->source_index]->file_index,
+ ist_table[ost->source_index]->index,
+ ost->file_index,
+ ost->index);
+ if (ost->sync_ist != ist_table[ost->source_index])
+ fprintf(stderr, " [sync #%d.%d]",
+ ost->sync_ist->file_index,
+ ost->sync_ist->index);
+ fprintf(stderr, "\n");
+ }
+ }
+
+ /* open each encoder */
+ for(i=0;i<nb_ostreams;i++) {
+ ost = ost_table[i];
+ if (ost->encoding_needed) {
+ AVCodec *codec;
+ codec = avcodec_find_encoder(ost->st->codec->codec_id);
+ if (!codec) {
+ fprintf(stderr, "Unsupported codec for output stream #%d.%d\n",
+ ost->file_index, ost->index);
+ exit(1);
+ }
+ if (avcodec_open(ost->st->codec, codec) < 0) {
+ fprintf(stderr, "Error while opening codec for output stream #%d.%d - maybe incorrect parameters such as bit_rate, rate, width or height\n",
+ ost->file_index, ost->index);
+ exit(1);
+ }
+ extra_size += ost->st->codec->extradata_size;
+ }
+ }
+
+ /* open each decoder */
+ for(i=0;i<nb_istreams;i++) {
+ ist = ist_table[i];
+ if (ist->decoding_needed) {
+ AVCodec *codec;
+ codec = avcodec_find_decoder(ist->st->codec->codec_id);
+ if (!codec) {
+ fprintf(stderr, "Unsupported codec (id=%d) for input stream #%d.%d\n",
+ ist->st->codec->codec_id, ist->file_index, ist->index);
+ exit(1);
+ }
+ if (avcodec_open(ist->st->codec, codec) < 0) {
+ fprintf(stderr, "Error while opening codec for input stream #%d.%d\n",
+ ist->file_index, ist->index);
+ exit(1);
+ }
+ //if (ist->st->codec->codec_type == CODEC_TYPE_VIDEO)
+ // ist->st->codec->flags |= CODEC_FLAG_REPEAT_FIELD;
+ }
+ }
+
+ /* init pts */
+ for(i=0;i<nb_istreams;i++) {
+ ist = ist_table[i];
+ is = input_files[ist->file_index];
+ ist->pts = 0;
+ ist->next_pts = av_rescale_q(ist->st->start_time, ist->st->time_base, AV_TIME_BASE_Q);
+ if(ist->st->start_time == AV_NOPTS_VALUE)
+ ist->next_pts=0;
+ if(input_files_ts_offset[ist->file_index])
+ ist->next_pts= AV_NOPTS_VALUE;
+ ist->is_start = 1;
+ }
+
+ /* compute buffer size max (should use a complete heuristic) */
+ for(i=0;i<nb_input_files;i++) {
+ file_table[i].buffer_size_max = 2048;
+ }
+
+ /* set meta data information from input file if required */
+ for (i=0;i<nb_meta_data_maps;i++) {
+ AVFormatContext *out_file;
+ AVFormatContext *in_file;
+
+ int out_file_index = meta_data_maps[i].out_file;
+ int in_file_index = meta_data_maps[i].in_file;
+ if ( out_file_index < 0 || out_file_index >= nb_output_files ) {
+ fprintf(stderr, "Invalid output file index %d map_meta_data(%d,%d)\n", out_file_index, out_file_index, in_file_index);
+ ret = -EINVAL;
+ goto fail;
+ }
+ if ( in_file_index < 0 || in_file_index >= nb_input_files ) {
+ fprintf(stderr, "Invalid input file index %d map_meta_data(%d,%d)\n", in_file_index, out_file_index, in_file_index);
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ out_file = output_files[out_file_index];
+ in_file = input_files[in_file_index];
+
+ strcpy(out_file->title, in_file->title);
+ strcpy(out_file->author, in_file->author);
+ strcpy(out_file->copyright, in_file->copyright);
+ strcpy(out_file->comment, in_file->comment);
+ strcpy(out_file->album, in_file->album);
+ out_file->year = in_file->year;
+ out_file->track = in_file->track;
+ strcpy(out_file->genre, in_file->genre);
+ }
+
+ /* open files and write file headers */
+ for(i=0;i<nb_output_files;i++) {
+ os = output_files[i];
+ if (av_write_header(os) < 0) {
+ fprintf(stderr, "Could not write header for output file #%d (incorrect codec parameters ?)\n", i);
+ ret = -EINVAL;
+ goto fail;
+ }
+ }
+
+ if ( !using_stdin && verbose >= 0) {
+ fprintf(stderr, "Press [q] to stop encoding\n");
+ url_set_interrupt_cb(decode_interrupt_cb);
+ }
+ term_init();
+
+ stream_no_data = 0;
+ key = -1;
+
+ for(; received_sigterm == 0;) {
+ int file_index, ist_index;
+ AVPacket pkt;
+ double ipts_min;
+ double opts_min;
+
+ redo:
+ ipts_min= 1e100;
+ opts_min= 1e100;
+ /* if 'q' pressed, exits */
+ if (!using_stdin) {
+ if (q_pressed)
+ break;
+ /* read_key() returns 0 on EOF */
+ key = read_key();
+ if (key == 'q')
+ break;
+ }
+
+ /* select the stream that we must read now by looking at the
+ smallest output pts */
+ file_index = -1;
+ for(i=0;i<nb_ostreams;i++) {
+ double ipts, opts;
+ ost = ost_table[i];
+ os = output_files[ost->file_index];
+ ist = ist_table[ost->source_index];
+ if(ost->st->codec->codec_type == CODEC_TYPE_VIDEO)
+ opts = ost->sync_opts * av_q2d(ost->st->codec->time_base);
+ else
+ opts = ost->st->pts.val * av_q2d(ost->st->time_base);
+ ipts = (double)ist->pts;
+ if (!file_table[ist->file_index].eof_reached){
+ if(ipts < ipts_min) {
+ ipts_min = ipts;
+ if(input_sync ) file_index = ist->file_index;
+ }
+ if(opts < opts_min) {
+ opts_min = opts;
+ if(!input_sync) file_index = ist->file_index;
+ }
+ }
+ if(ost->frame_number >= max_frames[ost->st->codec->codec_type]){
+ file_index= -1;
+ break;
+ }
+ }
+ /* if none, if is finished */
+ if (file_index < 0) {
+ break;
+ }
+
+ /* finish if recording time exhausted */
+ if (recording_time > 0 && opts_min >= (recording_time / 1000000.0))
+ break;
+
+ /* finish if limit size exhausted */
+ if (limit_filesize != 0 && (limit_filesize * 1024) < url_ftell(&output_files[0]->pb))
+ break;
+
+ /* read a frame from it and output it in the fifo */
+ is = input_files[file_index];
+ if (av_read_frame(is, &pkt) < 0) {
+ file_table[file_index].eof_reached = 1;
+ if (opt_shortest) break; else continue; //
+ }
+
+ if (!pkt.size) {
+ stream_no_data = is;
+ } else {
+ stream_no_data = 0;
+ }
+ if (do_pkt_dump) {
+ av_pkt_dump(stdout, &pkt, do_hex_dump);
+ }
+ /* the following test is needed in case new streams appear
+ dynamically in stream : we ignore them */
+ if (pkt.stream_index >= file_table[file_index].nb_streams)
+ goto discard_packet;
+ ist_index = file_table[file_index].ist_index + pkt.stream_index;
+ ist = ist_table[ist_index];
+ if (ist->discard)
+ goto discard_packet;
+
+// fprintf(stderr, "next:%"PRId64" dts:%"PRId64" off:%"PRId64" %d\n", ist->next_pts, pkt.dts, input_files_ts_offset[ist->file_index], ist->st->codec->codec_type);
+ if (pkt.dts != AV_NOPTS_VALUE && ist->next_pts != AV_NOPTS_VALUE) {
+ int64_t delta= av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q) - ist->next_pts;
+ if(FFABS(delta) > 1LL*dts_delta_threshold*AV_TIME_BASE && !copy_ts){
+ input_files_ts_offset[ist->file_index]-= delta;
+ if (verbose > 2)
+ fprintf(stderr, "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", delta, input_files_ts_offset[ist->file_index]);
+ for(i=0; i<file_table[file_index].nb_streams; i++){
+ int index= file_table[file_index].ist_index + i;
+ ist_table[index]->next_pts += delta;
+ ist_table[index]->is_start=1;
+ }
+ }
+ }
+
+ //fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->index, pkt.size);
+ if (output_packet(ist, ist_index, ost_table, nb_ostreams, &pkt) < 0) {
+
+ if (verbose >= 0)
+ fprintf(stderr, "Error while decoding stream #%d.%d\n",
+ ist->file_index, ist->index);
+
+ av_free_packet(&pkt);
+ goto redo;
+ }
+
+ discard_packet:
+ av_free_packet(&pkt);
+
+ /* dump report by using the output first video and audio streams */
+ print_report(output_files, ost_table, nb_ostreams, 0);
+ }
+
+ /* at the end of stream, we must flush the decoder buffers */
+ for(i=0;i<nb_istreams;i++) {
+ ist = ist_table[i];
+ if (ist->decoding_needed) {
+ output_packet(ist, i, ost_table, nb_ostreams, NULL);
+ }
+ }
+
+ term_exit();
+
+ /* write the trailer if needed and close file */
+ for(i=0;i<nb_output_files;i++) {
+ os = output_files[i];
+ av_write_trailer(os);
+ }
+
+ /* dump report by using the first video and audio streams */
+ print_report(output_files, ost_table, nb_ostreams, 1);
+
+ /* close each encoder */
+ for(i=0;i<nb_ostreams;i++) {
+ ost = ost_table[i];
+ if (ost->encoding_needed) {
+ av_freep(&ost->st->codec->stats_in);
+ avcodec_close(ost->st->codec);
+ }
+ }
+
+ /* close each decoder */
+ for(i=0;i<nb_istreams;i++) {
+ ist = ist_table[i];
+ if (ist->decoding_needed) {
+ avcodec_close(ist->st->codec);
+ }
+ }
+
+ /* finished ! */
+
+ ret = 0;
+ fail1:
+ av_freep(&bit_buffer);
+ av_free(file_table);
+
+ if (ist_table) {
+ for(i=0;i<nb_istreams;i++) {
+ ist = ist_table[i];
+ av_free(ist);
+ }
+ av_free(ist_table);
+ }
+ if (ost_table) {
+ for(i=0;i<nb_ostreams;i++) {
+ ost = ost_table[i];
+ if (ost) {
+ if (ost->logfile) {
+ fclose(ost->logfile);
+ ost->logfile = NULL;
+ }
+ av_fifo_free(&ost->fifo); /* works even if fifo is not
+ initialized but set to zero */
+ av_free(ost->pict_tmp.data[0]);
+ if (ost->video_resample)
+ sws_freeContext(ost->img_resample_ctx);
+ if (ost->audio_resample)
+ audio_resample_close(ost->resample);
+ av_free(ost);
+ }
+ }
+ av_free(ost_table);
+ }
+ return ret;
+ fail:
+ ret = -ENOMEM;
+ goto fail1;
+}
+
+#if 0
+int file_read(const char *filename)
+{
+ URLContext *h;
+ unsigned char buffer[1024];
+ int len, i;
+
+ if (url_open(&h, filename, O_RDONLY) < 0) {
+ printf("could not open '%s'\n", filename);
+ return -1;
+ }
+ for(;;) {
+ len = url_read(h, buffer, sizeof(buffer));
+ if (len <= 0)
+ break;
+ for(i=0;i<len;i++) putchar(buffer[i]);
+ }
+ url_close(h);
+ return 0;
+}
+#endif
+
+static void opt_format(const char *arg)
+{
+ /* compatibility stuff for pgmyuv */
+ if (!strcmp(arg, "pgmyuv")) {
+ pgmyuv_compatibility_hack=1;
+// opt_image_format(arg);
+ arg = "image2";
+ }
+
+ file_iformat = av_find_input_format(arg);
+ file_oformat = guess_format(arg, NULL, NULL);
+ if (!file_iformat && !file_oformat) {
+ fprintf(stderr, "Unknown input or output format: %s\n", arg);
+ exit(1);
+ }
+}
+
+static void opt_video_rc_eq(char *arg)
+{
+ video_rc_eq = arg;
+}
+
+static void opt_video_rc_override_string(char *arg)
+{
+ video_rc_override_string = arg;
+}
+
+static void opt_me_threshold(const char *arg)
+{
+ me_threshold = atoi(arg);
+}
+
+static void opt_verbose(const char *arg)
+{
+ verbose = atoi(arg);
+ av_log_set_level(atoi(arg));
+}
+
+static void opt_frame_rate(const char *arg)
+{
+ if (parse_frame_rate(&frame_rate, &frame_rate_base, arg) < 0) {
+ fprintf(stderr, "Incorrect frame rate\n");
+ exit(1);
+ }
+}
+
+static void opt_frame_crop_top(const char *arg)
+{
+ frame_topBand = atoi(arg);
+ if (frame_topBand < 0) {
+ fprintf(stderr, "Incorrect top crop size\n");
+ exit(1);
+ }
+ if ((frame_topBand % 2) != 0) {
+ fprintf(stderr, "Top crop size must be a multiple of 2\n");
+ exit(1);
+ }
+ if ((frame_topBand) >= frame_height){
+ fprintf(stderr, "Vertical crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
+ exit(1);
+ }
+ frame_height -= frame_topBand;
+}
+
+static void opt_frame_crop_bottom(const char *arg)
+{
+ frame_bottomBand = atoi(arg);
+ if (frame_bottomBand < 0) {
+ fprintf(stderr, "Incorrect bottom crop size\n");
+ exit(1);
+ }
+ if ((frame_bottomBand % 2) != 0) {
+ fprintf(stderr, "Bottom crop size must be a multiple of 2\n");
+ exit(1);
+ }
+ if ((frame_bottomBand) >= frame_height){
+ fprintf(stderr, "Vertical crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
+ exit(1);
+ }
+ frame_height -= frame_bottomBand;
+}
+
+static void opt_frame_crop_left(const char *arg)
+{
+ frame_leftBand = atoi(arg);
+ if (frame_leftBand < 0) {
+ fprintf(stderr, "Incorrect left crop size\n");
+ exit(1);
+ }
+ if ((frame_leftBand % 2) != 0) {
+ fprintf(stderr, "Left crop size must be a multiple of 2\n");
+ exit(1);
+ }
+ if ((frame_leftBand) >= frame_width){
+ fprintf(stderr, "Horizontal crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
+ exit(1);
+ }
+ frame_width -= frame_leftBand;
+}
+
+static void opt_frame_crop_right(const char *arg)
+{
+ frame_rightBand = atoi(arg);
+ if (frame_rightBand < 0) {
+ fprintf(stderr, "Incorrect right crop size\n");
+ exit(1);
+ }
+ if ((frame_rightBand % 2) != 0) {
+ fprintf(stderr, "Right crop size must be a multiple of 2\n");
+ exit(1);
+ }
+ if ((frame_rightBand) >= frame_width){
+ fprintf(stderr, "Horizontal crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
+ exit(1);
+ }
+ frame_width -= frame_rightBand;
+}
+
+static void opt_frame_size(const char *arg)
+{
+ if (parse_image_size(&frame_width, &frame_height, arg) < 0) {
+ fprintf(stderr, "Incorrect frame size\n");
+ exit(1);
+ }
+ if ((frame_width % 2) != 0 || (frame_height % 2) != 0) {
+ fprintf(stderr, "Frame size must be a multiple of 2\n");
+ exit(1);
+ }
+}
+
+
+#define SCALEBITS 10
+#define ONE_HALF (1 << (SCALEBITS - 1))
+#define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
+
+#define RGB_TO_Y(r, g, b) \
+((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \
+ FIX(0.11400) * (b) + ONE_HALF) >> SCALEBITS)
+
+#define RGB_TO_U(r1, g1, b1, shift)\
+(((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \
+ FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
+
+#define RGB_TO_V(r1, g1, b1, shift)\
+(((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \
+ FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
+
+static void opt_pad_color(const char *arg) {
+ /* Input is expected to be six hex digits similar to
+ how colors are expressed in html tags (but without the #) */
+ int rgb = strtol(arg, NULL, 16);
+ int r,g,b;
+
+ r = (rgb >> 16);
+ g = ((rgb >> 8) & 255);
+ b = (rgb & 255);
+
+ padcolor[0] = RGB_TO_Y(r,g,b);
+ padcolor[1] = RGB_TO_U(r,g,b,0);
+ padcolor[2] = RGB_TO_V(r,g,b,0);
+}
+
+static void opt_frame_pad_top(const char *arg)
+{
+ frame_padtop = atoi(arg);
+ if (frame_padtop < 0) {
+ fprintf(stderr, "Incorrect top pad size\n");
+ exit(1);
+ }
+ if ((frame_padtop % 2) != 0) {
+ fprintf(stderr, "Top pad size must be a multiple of 2\n");
+ exit(1);
+ }
+}
+
+static void opt_frame_pad_bottom(const char *arg)
+{
+ frame_padbottom = atoi(arg);
+ if (frame_padbottom < 0) {
+ fprintf(stderr, "Incorrect bottom pad size\n");
+ exit(1);
+ }
+ if ((frame_padbottom % 2) != 0) {
+ fprintf(stderr, "Bottom pad size must be a multiple of 2\n");
+ exit(1);
+ }
+}
+
+
+static void opt_frame_pad_left(const char *arg)
+{
+ frame_padleft = atoi(arg);
+ if (frame_padleft < 0) {
+ fprintf(stderr, "Incorrect left pad size\n");
+ exit(1);
+ }
+ if ((frame_padleft % 2) != 0) {
+ fprintf(stderr, "Left pad size must be a multiple of 2\n");
+ exit(1);
+ }
+}
+
+
+static void opt_frame_pad_right(const char *arg)
+{
+ frame_padright = atoi(arg);
+ if (frame_padright < 0) {
+ fprintf(stderr, "Incorrect right pad size\n");
+ exit(1);
+ }
+ if ((frame_padright % 2) != 0) {
+ fprintf(stderr, "Right pad size must be a multiple of 2\n");
+ exit(1);
+ }
+}
+
+
+static void opt_frame_pix_fmt(const char *arg)
+{
+ frame_pix_fmt = avcodec_get_pix_fmt(arg);
+}
+
+static void opt_frame_aspect_ratio(const char *arg)
+{
+ int x = 0, y = 0;
+ double ar = 0;
+ const char *p;
+
+ p = strchr(arg, ':');
+ if (p) {
+ x = strtol(arg, (char **)&arg, 10);
+ if (arg == p)
+ y = strtol(arg+1, (char **)&arg, 10);
+ if (x > 0 && y > 0)
+ ar = (double)x / (double)y;
+ } else
+ ar = strtod(arg, (char **)&arg);
+
+ if (!ar) {
+ fprintf(stderr, "Incorrect aspect ratio specification.\n");
+ exit(1);
+ }
+ frame_aspect_ratio = ar;
+}
+
+static void opt_qscale(const char *arg)
+{
+ video_qscale = atof(arg);
+ if (video_qscale <= 0 ||
+ video_qscale > 255) {
+ fprintf(stderr, "qscale must be > 0.0 and <= 255\n");
+ exit(1);
+ }
+}
+
+static void opt_qdiff(const char *arg)
+{
+ video_qdiff = atoi(arg);
+ if (video_qdiff < 0 ||
+ video_qdiff > 31) {
+ fprintf(stderr, "qdiff must be >= 1 and <= 31\n");
+ exit(1);
+ }
+}
+
+static void opt_packet_size(const char *arg)
+{
+ packet_size= atoi(arg);
+}
+
+static void opt_strict(const char *arg)
+{
+ strict= atoi(arg);
+}
+
+static void opt_top_field_first(const char *arg)
+{
+ top_field_first= atoi(arg);
+}
+
+static void opt_thread_count(const char *arg)
+{
+ thread_count= atoi(arg);
+#if !defined(HAVE_THREADS)
+ if (verbose >= 0)
+ fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
+#endif
+}
+
+static void opt_audio_bitrate(const char *arg)
+{
+ audio_bit_rate = atoi(arg) * 1000;
+}
+
+static void opt_audio_rate(const char *arg)
+{
+ audio_sample_rate = atoi(arg);
+}
+
+static void opt_audio_channels(const char *arg)
+{
+ audio_channels = atoi(arg);
+}
+
+static void opt_video_device(const char *arg)
+{
+ video_device = av_strdup(arg);
+}
+
+static void opt_grab_device(const char *arg)
+{
+ grab_device = av_strdup(arg);
+}
+
+static void opt_video_channel(const char *arg)
+{
+ video_channel = strtol(arg, NULL, 0);
+}
+
+static void opt_video_standard(const char *arg)
+{
+ video_standard = av_strdup(arg);
+}
+
+static void opt_audio_device(const char *arg)
+{
+ audio_device = av_strdup(arg);
+}
+
+static void opt_codec(int *pstream_copy, int *pcodec_id,
+ int codec_type, const char *arg)
+{
+ AVCodec *p;
+
+ if (!strcmp(arg, "copy")) {
+ *pstream_copy = 1;
+ } else {
+ p = first_avcodec;
+ while (p) {
+ if (!strcmp(p->name, arg) && p->type == codec_type)
+ break;
+ p = p->next;
+ }
+ if (p == NULL) {
+ fprintf(stderr, "Unknown codec '%s'\n", arg);
+ exit(1);
+ } else {
+ *pcodec_id = p->id;
+ }
+ }
+}
+
+static void opt_audio_codec(const char *arg)
+{
+ opt_codec(&audio_stream_copy, &audio_codec_id, CODEC_TYPE_AUDIO, arg);
+}
+
+static void opt_audio_tag(const char *arg)
+{
+ char *tail;
+ audio_codec_tag= strtol(arg, &tail, 0);
+
+ if(!tail || *tail)
+ audio_codec_tag= arg[0] + (arg[1]<<8) + (arg[2]<<16) + (arg[3]<<24);
+}
+
+static void opt_video_tag(const char *arg)
+{
+ char *tail;
+ video_codec_tag= strtol(arg, &tail, 0);
+
+ if(!tail || *tail)
+ video_codec_tag= arg[0] + (arg[1]<<8) + (arg[2]<<16) + (arg[3]<<24);
+}
+
+static void add_frame_hooker(const char *arg)
+{
+ int argc = 0;
+ char *argv[64];
+ int i;
+ char *args = av_strdup(arg);
+
+ using_vhook = 1;
+
+ argv[0] = strtok(args, " ");
+ while (argc < 62 && (argv[++argc] = strtok(NULL, " "))) {
+ }
+
+ i = frame_hook_add(argc, argv);
+
+ if (i != 0) {
+ fprintf(stderr, "Failed to add video hook function: %s\n", arg);
+ exit(1);
+ }
+}
+
+const char *motion_str[] = {
+ "zero",
+ "full",
+ "log",
+ "phods",
+ "epzs",
+ "x1",
+ "hex",
+ "umh",
+ "iter",
+ NULL,
+};
+
+static void opt_motion_estimation(const char *arg)
+{
+ const char **p;
+ p = motion_str;
+ for(;;) {
+ if (!*p) {
+ fprintf(stderr, "Unknown motion estimation method '%s'\n", arg);
+ exit(1);
+ }
+ if (!strcmp(*p, arg))
+ break;
+ p++;
+ }
+ me_method = (p - motion_str) + 1;
+}
+
+static void opt_video_codec(const char *arg)
+{
+ opt_codec(&video_stream_copy, &video_codec_id, CODEC_TYPE_VIDEO, arg);
+}
+
+static void opt_subtitle_codec(const char *arg)
+{
+ opt_codec(&subtitle_stream_copy, &subtitle_codec_id, CODEC_TYPE_SUBTITLE, arg);
+}
+
+static void opt_map(const char *arg)
+{
+ AVStreamMap *m;
+ const char *p;
+
+ p = arg;
+ m = &stream_maps[nb_stream_maps++];
+
+ m->file_index = strtol(arg, (char **)&p, 0);
+ if (*p)
+ p++;
+
+ m->stream_index = strtol(p, (char **)&p, 0);
+ if (*p) {
+ p++;
+ m->sync_file_index = strtol(p, (char **)&p, 0);
+ if (*p)
+ p++;
+ m->sync_stream_index = strtol(p, (char **)&p, 0);
+ } else {
+ m->sync_file_index = m->file_index;
+ m->sync_stream_index = m->stream_index;
+ }
+}
+
+static void opt_map_meta_data(const char *arg)
+{
+ AVMetaDataMap *m;
+ const char *p;
+
+ p = arg;
+ m = &meta_data_maps[nb_meta_data_maps++];
+
+ m->out_file = strtol(arg, (char **)&p, 0);
+ if (*p)
+ p++;
+
+ m->in_file = strtol(p, (char **)&p, 0);
+}
+
+static void opt_recording_time(const char *arg)
+{
+ recording_time = parse_date(arg, 1);
+}
+
+static void opt_start_time(const char *arg)
+{
+ start_time = parse_date(arg, 1);
+}
+
+static void opt_rec_timestamp(const char *arg)
+{
+ rec_timestamp = parse_date(arg, 0) / 1000000;
+}
+
+static void opt_input_ts_offset(const char *arg)
+{
+ input_ts_offset = parse_date(arg, 1);
+}
+
+static void opt_input_file(const char *filename)
+{
+ AVFormatContext *ic;
+ AVFormatParameters params, *ap = &params;
+ int err, i, ret, rfps, rfps_base;
+ int64_t timestamp;
+
+ if (!strcmp(filename, "-"))
+ filename = "pipe:";
+
+ using_stdin |= !strncmp(filename, "pipe:", 5) ||
+ !strcmp( filename, "/dev/stdin" );
+
+ /* get default parameters from command line */
+ ic = av_alloc_format_context();
+
+ memset(ap, 0, sizeof(*ap));
+ ap->prealloced_context = 1;
+ ap->sample_rate = audio_sample_rate;
+ ap->channels = audio_channels;
+ ap->time_base.den = frame_rate;
+ ap->time_base.num = frame_rate_base;
+ ap->width = frame_width + frame_padleft + frame_padright;
+ ap->height = frame_height + frame_padtop + frame_padbottom;
+ ap->pix_fmt = frame_pix_fmt;
+ ap->device = grab_device;
+ ap->channel = video_channel;
+ ap->standard = video_standard;
+ ap->video_codec_id = video_codec_id;
+ ap->audio_codec_id = audio_codec_id;
+ if(pgmyuv_compatibility_hack)
+ ap->video_codec_id= CODEC_ID_PGMYUV;
+
+ for(i=0; i<opt_name_count; i++){
+ AVOption *opt;
+ double d= av_get_double(avformat_opts, opt_names[i], &opt);
+ if(d==d && (opt->flags&AV_OPT_FLAG_DECODING_PARAM))
+ av_set_double(ic, opt_names[i], d);
+ }
+ /* open the input file with generic libav function */
+ err = av_open_input_file(&ic, filename, file_iformat, 0, ap);
+ if (err < 0) {
+ print_error(filename, err);
+ exit(1);
+ }
+
+ ic->loop_input = loop_input;
+
+ /* If not enough info to get the stream parameters, we decode the
+ first frames to get it. (used in mpeg case for example) */
+ ret = av_find_stream_info(ic);
+ if (ret < 0 && verbose >= 0) {
+ fprintf(stderr, "%s: could not find codec parameters\n", filename);
+ exit(1);
+ }
+
+ timestamp = start_time;
+ /* add the stream start time */
+ if (ic->start_time != AV_NOPTS_VALUE)
+ timestamp += ic->start_time;
+
+ /* if seeking requested, we execute it */
+ if (start_time != 0) {
+ ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
+ if (ret < 0) {
+ fprintf(stderr, "%s: could not seek to position %0.3f\n",
+ filename, (double)timestamp / AV_TIME_BASE);
+ }
+ /* reset seek info */
+ start_time = 0;
+ }
+
+ /* update the current parameters so that they match the one of the input stream */
+ for(i=0;i<ic->nb_streams;i++) {
+ int j;
+ AVCodecContext *enc = ic->streams[i]->codec;
+#if defined(HAVE_THREADS)
+ if(thread_count>1)
+ avcodec_thread_init(enc, thread_count);
+#endif
+ enc->thread_count= thread_count;
+ switch(enc->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ for(j=0; j<opt_name_count; j++){
+ AVOption *opt;
+ double d= av_get_double(avctx_opts, opt_names[j], &opt);
+ if(d==d && (opt->flags&AV_OPT_FLAG_AUDIO_PARAM) && (opt->flags&AV_OPT_FLAG_DECODING_PARAM))
+ av_set_double(enc, opt_names[j], d);
+ }
+ //fprintf(stderr, "\nInput Audio channels: %d", enc->channels);
+ audio_channels = enc->channels;
+ audio_sample_rate = enc->sample_rate;
+ if(audio_disable)
+ ic->streams[i]->discard= AVDISCARD_ALL;
+ break;
+ case CODEC_TYPE_VIDEO:
+ for(j=0; j<opt_name_count; j++){
+ AVOption *opt;
+ double d= av_get_double(avctx_opts, opt_names[j], &opt);
+ if(d==d && (opt->flags&AV_OPT_FLAG_VIDEO_PARAM) && (opt->flags&AV_OPT_FLAG_DECODING_PARAM))
+ av_set_double(enc, opt_names[j], d);
+ }
+ frame_height = enc->height;
+ frame_width = enc->width;
+ frame_aspect_ratio = av_q2d(enc->sample_aspect_ratio) * enc->width / enc->height;
+ frame_pix_fmt = enc->pix_fmt;
+ rfps = ic->streams[i]->r_frame_rate.num;
+ rfps_base = ic->streams[i]->r_frame_rate.den;
+ if(enc->lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
+ if(me_threshold)
+ enc->debug |= FF_DEBUG_MV;
+
+ if (enc->time_base.den != rfps || enc->time_base.num != rfps_base) {
+
+ if (verbose >= 0)
+ fprintf(stderr,"\nSeems that stream %d comes from film source: %2.2f (%d/%d) -> %2.2f (%d/%d)\n",
+ i, (float)enc->time_base.den / enc->time_base.num, enc->time_base.den, enc->time_base.num,
+
+ (float)rfps / rfps_base, rfps, rfps_base);
+ }
+ /* update the current frame rate to match the stream frame rate */
+ frame_rate = rfps;
+ frame_rate_base = rfps_base;
+
+ enc->rate_emu = rate_emu;
+ if(video_disable)
+ ic->streams[i]->discard= AVDISCARD_ALL;
+ else if(video_discard)
+ ic->streams[i]->discard= video_discard;
+ break;
+ case CODEC_TYPE_DATA:
+ break;
+ case CODEC_TYPE_SUBTITLE:
+ break;
+ case CODEC_TYPE_UNKNOWN:
+ break;
+ default:
+ av_abort();
+ }
+ }
+
+ input_files[nb_input_files] = ic;
+ input_files_ts_offset[nb_input_files] = input_ts_offset - (copy_ts ? 0 : timestamp);
+ /* dump the file content */
+ if (verbose >= 0)
+ dump_format(ic, nb_input_files, filename, 0);
+
+ nb_input_files++;
+ file_iformat = NULL;
+ file_oformat = NULL;
+
+ grab_device = NULL;
+ video_channel = 0;
+
+ rate_emu = 0;
+}
+
+static void opt_grab(const char *arg)
+{
+ file_iformat = av_find_input_format(arg);
+ opt_input_file("");
+}
+
+static void check_audio_video_inputs(int *has_video_ptr, int *has_audio_ptr)
+{
+ int has_video, has_audio, i, j;
+ AVFormatContext *ic;
+
+ has_video = 0;
+ has_audio = 0;
+ for(j=0;j<nb_input_files;j++) {
+ ic = input_files[j];
+ for(i=0;i<ic->nb_streams;i++) {
+ AVCodecContext *enc = ic->streams[i]->codec;
+ switch(enc->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ has_audio = 1;
+ break;
+ case CODEC_TYPE_VIDEO:
+ has_video = 1;
+ break;
+ case CODEC_TYPE_DATA:
+ case CODEC_TYPE_UNKNOWN:
+ case CODEC_TYPE_SUBTITLE:
+ break;
+ default:
+ av_abort();
+ }
+ }
+ }
+ *has_video_ptr = has_video;
+ *has_audio_ptr = has_audio;
+}
+
+static void new_video_stream(AVFormatContext *oc)
+{
+ AVStream *st;
+ AVCodecContext *video_enc;
+ int codec_id;
+
+ st = av_new_stream(oc, oc->nb_streams);
+ if (!st) {
+ fprintf(stderr, "Could not alloc stream\n");
+ exit(1);
+ }
+ bitstream_filters[nb_output_files][oc->nb_streams - 1]= video_bitstream_filters;
+ video_bitstream_filters= NULL;
+
+#if defined(HAVE_THREADS)
+ if(thread_count>1)
+ avcodec_thread_init(st->codec, thread_count);
+#endif
+
+ video_enc = st->codec;
+
+ if(video_codec_tag)
+ video_enc->codec_tag= video_codec_tag;
+
+ if( (video_global_header&1)
+ || (video_global_header==0 && (oc->oformat->flags & AVFMT_GLOBALHEADER))){
+ video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
+ avctx_opts->flags|= CODEC_FLAG_GLOBAL_HEADER;
+ }
+ if(video_global_header&2){
+ video_enc->flags2 |= CODEC_FLAG2_LOCAL_HEADER;
+ avctx_opts->flags2|= CODEC_FLAG2_LOCAL_HEADER;
+ }
+
+ if (video_stream_copy) {
+ st->stream_copy = 1;
+ video_enc->codec_type = CODEC_TYPE_VIDEO;
+ } else {
+ char *p;
+ int i;
+ AVCodec *codec;
+
+ codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, CODEC_TYPE_VIDEO);
+ if (video_codec_id != CODEC_ID_NONE)
+ codec_id = video_codec_id;
+
+ video_enc->codec_id = codec_id;
+ codec = avcodec_find_encoder(codec_id);
+
+ for(i=0; i<opt_name_count; i++){
+ AVOption *opt;
+ double d= av_get_double(avctx_opts, opt_names[i], &opt);
+ if(d==d && (opt->flags&AV_OPT_FLAG_VIDEO_PARAM) && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
+ av_set_double(video_enc, opt_names[i], d);
+ }
+
+ video_enc->time_base.den = frame_rate;
+ video_enc->time_base.num = frame_rate_base;
+ if(codec && codec->supported_framerates){
+ const AVRational *p= codec->supported_framerates;
+ AVRational req= (AVRational){frame_rate, frame_rate_base};
+ const AVRational *best=NULL;
+ AVRational best_error= (AVRational){INT_MAX, 1};
+ for(; p->den!=0; p++){
+ AVRational error= av_sub_q(req, *p);
+ if(error.num <0) error.num *= -1;
+ if(av_cmp_q(error, best_error) < 0){
+ best_error= error;
+ best= p;
+ }
+ }
+ video_enc->time_base.den= best->num;
+ video_enc->time_base.num= best->den;
+ }
+
+ video_enc->width = frame_width + frame_padright + frame_padleft;
+ video_enc->height = frame_height + frame_padtop + frame_padbottom;
+ video_enc->sample_aspect_ratio = av_d2q(frame_aspect_ratio*video_enc->height/video_enc->width, 255);
+ video_enc->pix_fmt = frame_pix_fmt;
+
+ if(codec && codec->pix_fmts){
+ const enum PixelFormat *p= codec->pix_fmts;
+ for(; *p!=-1; p++){
+ if(*p == video_enc->pix_fmt)
+ break;
+ }
+ if(*p == -1)
+ video_enc->pix_fmt = codec->pix_fmts[0];
+ }
+
+ if (intra_only)
+ video_enc->gop_size = 0;
+ if (video_qscale || same_quality) {
+ video_enc->flags |= CODEC_FLAG_QSCALE;
+ video_enc->global_quality=
+ st->quality = FF_QP2LAMBDA * video_qscale;
+ }
+
+ if(intra_matrix)
+ video_enc->intra_matrix = intra_matrix;
+ if(inter_matrix)
+ video_enc->inter_matrix = inter_matrix;
+
+ video_enc->max_qdiff = video_qdiff;
+ video_enc->rc_eq = video_rc_eq;
+ video_enc->thread_count = thread_count;
+ p= video_rc_override_string;
+ for(i=0; p; i++){
+ int start, end, q;
+ int e=sscanf(p, "%d,%d,%d", &start, &end, &q);
+ if(e!=3){
+ fprintf(stderr, "error parsing rc_override\n");
+ exit(1);
+ }
+ video_enc->rc_override=
+ av_realloc(video_enc->rc_override,
+ sizeof(RcOverride)*(i+1));
+ video_enc->rc_override[i].start_frame= start;
+ video_enc->rc_override[i].end_frame = end;
+ if(q>0){
+ video_enc->rc_override[i].qscale= q;
+ video_enc->rc_override[i].quality_factor= 1.0;
+ }
+ else{
+ video_enc->rc_override[i].qscale= 0;
+ video_enc->rc_override[i].quality_factor= -q/100.0;
+ }
+ p= strchr(p, '/');
+ if(p) p++;
+ }
+ video_enc->rc_override_count=i;
+ video_enc->rc_initial_buffer_occupancy = video_enc->rc_buffer_size*3/4;
+ video_enc->me_threshold= me_threshold;
+ video_enc->intra_dc_precision= intra_dc_precision - 8;
+ video_enc->strict_std_compliance = strict;
+
+ if(packet_size){
+ video_enc->rtp_mode= 1;
+ video_enc->rtp_payload_size= packet_size;
+ }
+
+ if (do_psnr)
+ video_enc->flags|= CODEC_FLAG_PSNR;
+
+ video_enc->me_method = me_method;
+
+ /* two pass mode */
+ if (do_pass) {
+ if (do_pass == 1) {
+ video_enc->flags |= CODEC_FLAG_PASS1;
+ } else {
+ video_enc->flags |= CODEC_FLAG_PASS2;
+ }
+ }
+ }
+
+ /* reset some key parameters */
+ video_disable = 0;
+ video_codec_id = CODEC_ID_NONE;
+ video_stream_copy = 0;
+}
+
+static void new_audio_stream(AVFormatContext *oc)
+{
+ AVStream *st;
+ AVCodecContext *audio_enc;
+ int codec_id, i;
+
+ st = av_new_stream(oc, oc->nb_streams);
+ if (!st) {
+ fprintf(stderr, "Could not alloc stream\n");
+ exit(1);
+ }
+
+ bitstream_filters[nb_output_files][oc->nb_streams - 1]= audio_bitstream_filters;
+ audio_bitstream_filters= NULL;
+
+#if defined(HAVE_THREADS)
+ if(thread_count>1)
+ avcodec_thread_init(st->codec, thread_count);
+#endif
+
+ audio_enc = st->codec;
+ audio_enc->codec_type = CODEC_TYPE_AUDIO;
+ audio_enc->strict_std_compliance = strict;
+
+ if(audio_codec_tag)
+ audio_enc->codec_tag= audio_codec_tag;
+
+ if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
+ audio_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
+ avctx_opts->flags|= CODEC_FLAG_GLOBAL_HEADER;
+ }
+ if (audio_stream_copy) {
+ st->stream_copy = 1;
+ audio_enc->channels = audio_channels;
+ } else {
+ codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, CODEC_TYPE_AUDIO);
+
+ for(i=0; i<opt_name_count; i++){
+ AVOption *opt;
+ double d= av_get_double(avctx_opts, opt_names[i], &opt);
+ if(d==d && (opt->flags&AV_OPT_FLAG_AUDIO_PARAM) && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
+ av_set_double(audio_enc, opt_names[i], d);
+ }
+
+ if (audio_codec_id != CODEC_ID_NONE)
+ codec_id = audio_codec_id;
+ audio_enc->codec_id = codec_id;
+
+ audio_enc->bit_rate = audio_bit_rate;
+ if (audio_qscale > QSCALE_NONE) {
+ audio_enc->flags |= CODEC_FLAG_QSCALE;
+ audio_enc->global_quality = st->quality = FF_QP2LAMBDA * audio_qscale;
+ }
+ audio_enc->thread_count = thread_count;
+ /* For audio codecs other than AC3 or DTS we limit */
+ /* the number of coded channels to stereo */
+ if (audio_channels > 2 && codec_id != CODEC_ID_AC3
+ && codec_id != CODEC_ID_DTS) {
+ audio_enc->channels = 2;
+ } else
+ audio_enc->channels = audio_channels;
+ }
+ audio_enc->sample_rate = audio_sample_rate;
+ audio_enc->time_base= (AVRational){1, audio_sample_rate};
+ if (audio_language) {
+ pstrcpy(st->language, sizeof(st->language), audio_language);
+ av_free(audio_language);
+ audio_language = NULL;
+ }
+
+ /* reset some key parameters */
+ audio_disable = 0;
+ audio_codec_id = CODEC_ID_NONE;
+ audio_stream_copy = 0;
+}
+
+static void opt_new_subtitle_stream(void)
+{
+ AVFormatContext *oc;
+ AVStream *st;
+ AVCodecContext *subtitle_enc;
+ int i;
+
+ if (nb_output_files <= 0) {
+ fprintf(stderr, "At least one output file must be specified\n");
+ exit(1);
+ }
+ oc = output_files[nb_output_files - 1];
+
+ st = av_new_stream(oc, oc->nb_streams);
+ if (!st) {
+ fprintf(stderr, "Could not alloc stream\n");
+ exit(1);
+ }
+
+ subtitle_enc = st->codec;
+ subtitle_enc->codec_type = CODEC_TYPE_SUBTITLE;
+ if (subtitle_stream_copy) {
+ st->stream_copy = 1;
+ } else {
+ for(i=0; i<opt_name_count; i++){
+ AVOption *opt;
+ double d= av_get_double(avctx_opts, opt_names[i], &opt);
+ if(d==d && (opt->flags&AV_OPT_FLAG_SUBTITLE_PARAM) && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
+ av_set_double(subtitle_enc, opt_names[i], d);
+ }
+ subtitle_enc->codec_id = subtitle_codec_id;
+ }
+
+ if (subtitle_language) {
+ pstrcpy(st->language, sizeof(st->language), subtitle_language);
+ av_free(subtitle_language);
+ subtitle_language = NULL;
+ }
+
+ subtitle_codec_id = CODEC_ID_NONE;
+ subtitle_stream_copy = 0;
+}
+
+static void opt_new_audio_stream(void)
+{
+ AVFormatContext *oc;
+ if (nb_output_files <= 0) {
+ fprintf(stderr, "At least one output file must be specified\n");
+ exit(1);
+ }
+ oc = output_files[nb_output_files - 1];
+ new_audio_stream(oc);
+}
+
+static void opt_new_video_stream(void)
+{
+ AVFormatContext *oc;
+ if (nb_output_files <= 0) {
+ fprintf(stderr, "At least one output file must be specified\n");
+ exit(1);
+ }
+ oc = output_files[nb_output_files - 1];
+ new_video_stream(oc);
+}
+
+static void opt_output_file(const char *filename)
+{
+ AVFormatContext *oc;
+ int use_video, use_audio, input_has_video, input_has_audio, i;
+ AVFormatParameters params, *ap = &params;
+
+ if (!strcmp(filename, "-"))
+ filename = "pipe:";
+
+ oc = av_alloc_format_context();
+
+ if (!file_oformat) {
+ file_oformat = guess_format(NULL, filename, NULL);
+ if (!file_oformat) {
+ fprintf(stderr, "Unable for find a suitable output format for '%s'\n",
+ filename);
+ exit(1);
+ }
+ }
+
+ oc->oformat = file_oformat;
+ pstrcpy(oc->filename, sizeof(oc->filename), filename);
+
+ if (!strcmp(file_oformat->name, "ffm") &&
+ strstart(filename, "http:", NULL)) {
+ /* special case for files sent to ffserver: we get the stream
+ parameters from ffserver */
+ if (read_ffserver_streams(oc, filename) < 0) {
+ fprintf(stderr, "Could not read stream parameters from '%s'\n", filename);
+ exit(1);
+ }
+ } else {
+ use_video = file_oformat->video_codec != CODEC_ID_NONE || video_stream_copy || video_codec_id != CODEC_ID_NONE;
+ use_audio = file_oformat->audio_codec != CODEC_ID_NONE || audio_stream_copy || audio_codec_id != CODEC_ID_NONE;
+
+ /* disable if no corresponding type found and at least one
+ input file */
+ if (nb_input_files > 0) {
+ check_audio_video_inputs(&input_has_video, &input_has_audio);
+ if (!input_has_video)
+ use_video = 0;
+ if (!input_has_audio)
+ use_audio = 0;
+ }
+
+ /* manual disable */
+ if (audio_disable) {
+ use_audio = 0;
+ }
+ if (video_disable) {
+ use_video = 0;
+ }
+
+ if (use_video) {
+ new_video_stream(oc);
+ }
+
+ if (use_audio) {
+ new_audio_stream(oc);
+ }
+
+ oc->timestamp = rec_timestamp;
+
+ if (str_title)
+ pstrcpy(oc->title, sizeof(oc->title), str_title);
+ if (str_author)
+ pstrcpy(oc->author, sizeof(oc->author), str_author);
+ if (str_copyright)
+ pstrcpy(oc->copyright, sizeof(oc->copyright), str_copyright);
+ if (str_comment)
+ pstrcpy(oc->comment, sizeof(oc->comment), str_comment);
+ if (str_album)
+ pstrcpy(oc->album, sizeof(oc->album), str_album);
+ }
+
+ output_files[nb_output_files++] = oc;
+
+ /* check filename in case of an image number is expected */
+ if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
+ if (!av_filename_number_test(oc->filename)) {
+ print_error(oc->filename, AVERROR_NUMEXPECTED);
+ exit(1);
+ }
+ }
+
+ if (!(oc->oformat->flags & AVFMT_NOFILE)) {
+ /* test if it already exists to avoid loosing precious files */
+ if (!file_overwrite &&
+ (strchr(filename, ':') == NULL ||
+ strstart(filename, "file:", NULL))) {
+ if (url_exist(filename)) {
+ int c;
+
+ if ( !using_stdin ) {
+ fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename);
+ fflush(stderr);
+ c = getchar();
+ if (toupper(c) != 'Y') {
+ fprintf(stderr, "Not overwriting - exiting\n");
+ exit(1);
+ }
+ }
+ else {
+ fprintf(stderr,"File '%s' already exists. Exiting.\n", filename);
+ exit(1);
+ }
+ }
+ }
+
+ /* open the file */
+ if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {
+ fprintf(stderr, "Could not open '%s'\n", filename);
+ exit(1);
+ }
+ }
+
+ memset(ap, 0, sizeof(*ap));
+ if (av_set_parameters(oc, ap) < 0) {
+ fprintf(stderr, "%s: Invalid encoding parameters\n",
+ oc->filename);
+ exit(1);
+ }
+
+ oc->preload= (int)(mux_preload*AV_TIME_BASE);
+ oc->max_delay= (int)(mux_max_delay*AV_TIME_BASE);
+ oc->loop_output = loop_output;
+
+ for(i=0; i<opt_name_count; i++){
+ AVOption *opt;
+ double d = av_get_double(avformat_opts, opt_names[i], &opt);
+ if(d==d && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
+ av_set_double(oc, opt_names[i], d);
+ }
+
+ /* reset some options */
+ file_oformat = NULL;
+ file_iformat = NULL;
+}
+
+/* prepare dummy protocols for grab */
+static void prepare_grab(void)
+{
+ int has_video, has_audio, i, j;
+ AVFormatContext *oc;
+ AVFormatContext *ic;
+ AVFormatParameters vp1, *vp = &vp1;
+ AVFormatParameters ap1, *ap = &ap1;
+
+ /* see if audio/video inputs are needed */
+ has_video = 0;
+ has_audio = 0;
+ memset(ap, 0, sizeof(*ap));
+ memset(vp, 0, sizeof(*vp));
+ vp->time_base.num= 1;
+ for(j=0;j<nb_output_files;j++) {
+ oc = output_files[j];
+ for(i=0;i<oc->nb_streams;i++) {
+ AVCodecContext *enc = oc->streams[i]->codec;
+ switch(enc->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ if (enc->sample_rate > ap->sample_rate)
+ ap->sample_rate = enc->sample_rate;
+ if (enc->channels > ap->channels)
+ ap->channels = enc->channels;
+ has_audio = 1;
+ break;
+ case CODEC_TYPE_VIDEO:
+ if (enc->width > vp->width)
+ vp->width = enc->width;
+ if (enc->height > vp->height)
+ vp->height = enc->height;
+
+ if (vp->time_base.num*(int64_t)enc->time_base.den > enc->time_base.num*(int64_t)vp->time_base.den){
+ vp->time_base = enc->time_base;
+ vp->width += frame_leftBand + frame_rightBand;
+ vp->width -= (frame_padleft + frame_padright);
+ vp->height += frame_topBand + frame_bottomBand;
+ vp->height -= (frame_padtop + frame_padbottom);
+ }
+ has_video = 1;
+ break;
+ default:
+ av_abort();
+ }
+ }
+ }
+
+ if (has_video == 0 && has_audio == 0) {
+ fprintf(stderr, "Output file must have at least one audio or video stream\n");
+ exit(1);
+ }
+
+ if (has_video) {
+ AVInputFormat *fmt1;
+ fmt1 = av_find_input_format(video_grab_format);
+ vp->device = video_device;
+ vp->channel = video_channel;
+ vp->standard = video_standard;
+ vp->pix_fmt = frame_pix_fmt;
+ if (av_open_input_file(&ic, "", fmt1, 0, vp) < 0) {
+ fprintf(stderr, "Could not find video grab device\n");
+ exit(1);
+ }
+ /* If not enough info to get the stream parameters, we decode the
+ first frames to get it. */
+ if ((ic->ctx_flags & AVFMTCTX_NOHEADER) && av_find_stream_info(ic) < 0) {
+ fprintf(stderr, "Could not find video grab parameters\n");
+ exit(1);
+ }
+ /* by now video grab has one stream */
+ ic->streams[0]->r_frame_rate.num = vp->time_base.den;
+ ic->streams[0]->r_frame_rate.den = vp->time_base.num;
+ input_files[nb_input_files] = ic;
+
+ if (verbose >= 0)
+ dump_format(ic, nb_input_files, "", 0);
+
+ nb_input_files++;
+ }
+ if (has_audio && audio_grab_format) {
+ AVInputFormat *fmt1;
+ fmt1 = av_find_input_format(audio_grab_format);
+ ap->device = audio_device;
+ if (av_open_input_file(&ic, "", fmt1, 0, ap) < 0) {
+ fprintf(stderr, "Could not find audio grab device\n");
+ exit(1);
+ }
+ input_files[nb_input_files] = ic;
+
+ if (verbose >= 0)
+ dump_format(ic, nb_input_files, "", 0);
+
+ nb_input_files++;
+ }
+}
+
+/* same option as mencoder */
+static void opt_pass(const char *pass_str)
+{
+ int pass;
+ pass = atoi(pass_str);
+ if (pass != 1 && pass != 2) {
+ fprintf(stderr, "pass number can be only 1 or 2\n");
+ exit(1);
+ }
+ do_pass = pass;
+}
+
+#if defined(__MINGW32__) || defined(CONFIG_OS2)
+static int64_t getutime(void)
+{
+ return av_gettime();
+}
+#else
+static int64_t getutime(void)
+{
+ struct rusage rusage;
+
+ getrusage(RUSAGE_SELF, &rusage);
+ return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
+}
+#endif
+
+#if defined(CONFIG_FFM_DEMUXER) || defined(CONFIG_FFM_MUXER)
+extern int ffm_nopts;
+#endif
+
+static void show_formats(void)
+{
+ AVInputFormat *ifmt;
+ AVOutputFormat *ofmt;
+ URLProtocol *up;
+ AVCodec *p, *p2;
+ const char **pp, *last_name;
+
+ printf("File formats:\n");
+ last_name= "000";
+ for(;;){
+ int decode=0;
+ int encode=0;
+ const char *name=NULL;
+ const char *long_name=NULL;
+
+ for(ofmt = first_oformat; ofmt != NULL; ofmt = ofmt->next) {
+ if((name == NULL || strcmp(ofmt->name, name)<0) &&
+ strcmp(ofmt->name, last_name)>0){
+ name= ofmt->name;
+ long_name= ofmt->long_name;
+ encode=1;
+ }
+ }
+ for(ifmt = first_iformat; ifmt != NULL; ifmt = ifmt->next) {
+ if((name == NULL || strcmp(ifmt->name, name)<0) &&
+ strcmp(ifmt->name, last_name)>0){
+ name= ifmt->name;
+ long_name= ifmt->long_name;
+ encode=0;
+ }
+ if(name && strcmp(ifmt->name, name)==0)
+ decode=1;
+ }
+ if(name==NULL)
+ break;
+ last_name= name;
+
+ printf(
+ " %s%s %-15s %s\n",
+ decode ? "D":" ",
+ encode ? "E":" ",
+ name,
+ long_name ? long_name:" ");
+ }
+ printf("\n");
+
+ printf("Codecs:\n");
+ last_name= "000";
+ for(;;){
+ int decode=0;
+ int encode=0;
+ int cap=0;
+ const char *type_str;
+
+ p2=NULL;
+ for(p = first_avcodec; p != NULL; p = p->next) {
+ if((p2==NULL || strcmp(p->name, p2->name)<0) &&
+ strcmp(p->name, last_name)>0){
+ p2= p;
+ decode= encode= cap=0;
+ }
+ if(p2 && strcmp(p->name, p2->name)==0){
+ if(p->decode) decode=1;
+ if(p->encode) encode=1;
+ cap |= p->capabilities;
+ }
+ }
+ if(p2==NULL)
+ break;
+ last_name= p2->name;
+
+ switch(p2->type) {
+ case CODEC_TYPE_VIDEO:
+ type_str = "V";
+ break;
+ case CODEC_TYPE_AUDIO:
+ type_str = "A";
+ break;
+ case CODEC_TYPE_SUBTITLE:
+ type_str = "S";
+ break;
+ default:
+ type_str = "?";
+ break;
+ }
+ printf(
+ " %s%s%s%s%s%s %s",
+ decode ? "D": (/*p2->decoder ? "d":*/" "),
+ encode ? "E":" ",
+ type_str,
+ cap & CODEC_CAP_DRAW_HORIZ_BAND ? "S":" ",
+ cap & CODEC_CAP_DR1 ? "D":" ",
+ cap & CODEC_CAP_TRUNCATED ? "T":" ",
+ p2->name);
+ /* if(p2->decoder && decode==0)
+ printf(" use %s for decoding", p2->decoder->name);*/
+ printf("\n");
+ }
+ printf("\n");
+
+ printf("Supported file protocols:\n");
+ for(up = first_protocol; up != NULL; up = up->next)
+ printf(" %s:", up->name);
+ printf("\n");
+
+ printf("Frame size, frame rate abbreviations:\n ntsc pal qntsc qpal sntsc spal film ntsc-film sqcif qcif cif 4cif\n");
+ printf("Motion estimation methods:\n");
+ pp = motion_str;
+ while (*pp) {
+ printf(" %s", *pp);
+ if ((pp - motion_str + 1) == ME_ZERO)
+ printf("(fastest)");
+ else if ((pp - motion_str + 1) == ME_FULL)
+ printf("(slowest)");
+ else if ((pp - motion_str + 1) == ME_EPZS)
+ printf("(default)");
+ pp++;
+ }
+ printf("\n\n");
+ printf(
+"Note, the names of encoders and decoders dont always match, so there are\n"
+"several cases where the above table shows encoder only or decoder only entries\n"
+"even though both encoding and decoding are supported for example, the h263\n"
+"decoder corresponds to the h263 and h263p encoders, for file formats its even\n"
+"worse\n");
+ exit(1);
+}
+
+static void parse_matrix_coeffs(uint16_t *dest, const char *str)
+{
+ int i;
+ const char *p = str;
+ for(i = 0;; i++) {
+ dest[i] = atoi(p);
+ if(i == 63)
+ break;
+ p = strchr(p, ',');
+ if(!p) {
+ fprintf(stderr, "Syntax error in matrix \"%s\" at coeff %d\n", str, i);
+ exit(1);
+ }
+ p++;
+ }
+}
+
+static void opt_inter_matrix(const char *arg)
+{
+ inter_matrix = av_mallocz(sizeof(uint16_t) * 64);
+ parse_matrix_coeffs(inter_matrix, arg);
+}
+
+static void opt_intra_matrix(const char *arg)
+{
+ intra_matrix = av_mallocz(sizeof(uint16_t) * 64);
+ parse_matrix_coeffs(intra_matrix, arg);
+}
+
+static void opt_target(const char *arg)
+{
+ int norm = -1;
+ static const char *const frame_rates[] = {"25", "30000/1001", "24000/1001"};
+
+ if(!strncmp(arg, "pal-", 4)) {
+ norm = 0;
+ arg += 4;
+ } else if(!strncmp(arg, "ntsc-", 5)) {
+ norm = 1;
+ arg += 5;
+ } else if(!strncmp(arg, "film-", 5)) {
+ norm = 2;
+ arg += 5;
+ } else {
+ int fr;
+ /* Calculate FR via float to avoid int overflow */
+ fr = (int)(frame_rate * 1000.0 / frame_rate_base);
+ if(fr == 25000) {
+ norm = 0;
+ } else if((fr == 29970) || (fr == 23976)) {
+ norm = 1;
+ } else {
+ /* Try to determine PAL/NTSC by peeking in the input files */
+ if(nb_input_files) {
+ int i, j;
+ for(j = 0; j < nb_input_files; j++) {
+ for(i = 0; i < input_files[j]->nb_streams; i++) {
+ AVCodecContext *c = input_files[j]->streams[i]->codec;
+ if(c->codec_type != CODEC_TYPE_VIDEO)
+ continue;
+ fr = c->time_base.den * 1000 / c->time_base.num;
+ if(fr == 25000) {
+ norm = 0;
+ break;
+ } else if((fr == 29970) || (fr == 23976)) {
+ norm = 1;
+ break;
+ }
+ }
+ if(norm >= 0)
+ break;
+ }
+ }
+ }
+ if(verbose && norm >= 0)
+ fprintf(stderr, "Assuming %s for target.\n", norm ? "NTSC" : "PAL");
+ }
+
+ if(norm < 0) {
+ fprintf(stderr, "Could not determine norm (PAL/NTSC/NTSC-Film) for target.\n");
+ fprintf(stderr, "Please prefix target with \"pal-\", \"ntsc-\" or \"film-\",\n");
+ fprintf(stderr, "or set a framerate with \"-r xxx\".\n");
+ exit(1);
+ }
+
+ if(!strcmp(arg, "vcd")) {
+
+ opt_video_codec("mpeg1video");
+ opt_audio_codec("mp2");
+ opt_format("vcd");
+
+ opt_frame_size(norm ? "352x240" : "352x288");
+ opt_frame_rate(frame_rates[norm]);
+ opt_default("gop", norm ? "18" : "15");
+
+ opt_default("b", "1150000");
+ opt_default("maxrate", "1150000");
+ opt_default("minrate", "1150000");
+ opt_default("bufsize", "327680"); // 40*1024*8;
+
+ audio_bit_rate = 224000;
+ audio_sample_rate = 44100;
+
+ opt_default("packetsize", "2324");
+ opt_default("muxrate", "1411200"); // 2352 * 75 * 8;
+
+ /* We have to offset the PTS, so that it is consistent with the SCR.
+ SCR starts at 36000, but the first two packs contain only padding
+ and the first pack from the other stream, respectively, may also have
+ been written before.
+ So the real data starts at SCR 36000+3*1200. */
+ mux_preload= (36000+3*1200) / 90000.0; //0.44
+ } else if(!strcmp(arg, "svcd")) {
+
+ opt_video_codec("mpeg2video");
+ opt_audio_codec("mp2");
+ opt_format("svcd");
+
+ opt_frame_size(norm ? "480x480" : "480x576");
+ opt_frame_rate(frame_rates[norm]);
+ opt_default("gop", norm ? "18" : "15");
+
+ opt_default("b", "2040000");
+ opt_default("maxrate", "2516000");
+ opt_default("minrate", "0"); //1145000;
+ opt_default("bufsize", "1835008"); //224*1024*8;
+ opt_default("flags", "+SCAN_OFFSET");
+
+
+ audio_bit_rate = 224000;
+ audio_sample_rate = 44100;
+
+ opt_default("packetsize", "2324");
+
+ } else if(!strcmp(arg, "dvd")) {
+
+ opt_video_codec("mpeg2video");
+ opt_audio_codec("ac3");
+ opt_format("dvd");
+
+ opt_frame_size(norm ? "720x480" : "720x576");
+ opt_frame_rate(frame_rates[norm]);
+ opt_default("gop", norm ? "18" : "15");
+
+ opt_default("b", "6000000");
+ opt_default("maxrate", "9000000");
+ opt_default("minrate", "0"); //1500000;
+ opt_default("bufsize", "1835008"); //224*1024*8;
+
+ opt_default("packetsize", "2048"); // from www.mpucoder.com: DVD sectors contain 2048 bytes of data, this is also the size of one pack.
+ opt_default("muxrate", "10080000"); // from mplex project: data_rate = 1260000. mux_rate = data_rate * 8
+
+ audio_bit_rate = 448000;
+ audio_sample_rate = 48000;
+
+ } else if(!strncmp(arg, "dv", 2)) {
+
+ opt_format("dv");
+
+ opt_frame_size(norm ? "720x480" : "720x576");
+ opt_frame_pix_fmt(!strncmp(arg, "dv50", 4) ? "yuv422p" :
+ (norm ? "yuv411p" : "yuv420p"));
+ opt_frame_rate(frame_rates[norm]);
+
+ audio_sample_rate = 48000;
+ audio_channels = 2;
+
+ } else {
+ fprintf(stderr, "Unknown target: %s\n", arg);
+ exit(1);
+ }
+}
+
+static void opt_video_bsf(const char *arg)
+{
+ AVBitStreamFilterContext *bsfc= av_bitstream_filter_init(arg); //FIXME split name and args for filter at '='
+ AVBitStreamFilterContext **bsfp;
+
+ if(!bsfc){
+ fprintf(stderr, "Unkown bitstream filter %s\n", arg);
+ exit(1);
+ }
+
+ bsfp= &video_bitstream_filters;
+ while(*bsfp)
+ bsfp= &(*bsfp)->next;
+
+ *bsfp= bsfc;
+}
+
+//FIXME avoid audio - video code duplication
+static void opt_audio_bsf(const char *arg)
+{
+ AVBitStreamFilterContext *bsfc= av_bitstream_filter_init(arg); //FIXME split name and args for filter at '='
+ AVBitStreamFilterContext **bsfp;
+
+ if(!bsfc){
+ fprintf(stderr, "Unkown bitstream filter %s\n", arg);
+ exit(1);
+ }
+
+ bsfp= &audio_bitstream_filters;
+ while(*bsfp)
+ bsfp= &(*bsfp)->next;
+
+ *bsfp= bsfc;
+}
+
+static void show_version(void)
+{
+ /* TODO: add function interface to avutil and avformat */
+ fprintf(stderr, "ffmpeg " FFMPEG_VERSION "\n"
+ "libavutil %d\n"
+ "libavcodec %d\n"
+ "libavformat %d\n",
+ LIBAVUTIL_BUILD, avcodec_build(), LIBAVFORMAT_BUILD);
+ exit(1);
+}
+
+static int opt_default(const char *opt, const char *arg){
+ AVOption *o= av_set_string(avctx_opts, opt, arg);
+ if(!o)
+ o = av_set_string(avformat_opts, opt, arg);
+ if(!o)
+ return -1;
+
+// av_log(NULL, AV_LOG_ERROR, "%s:%s: %f 0x%0X\n", opt, arg, av_get_double(avctx_opts, opt, NULL), (int)av_get_int(avctx_opts, opt, NULL));
+
+ //FIXME we should always use avctx_opts, ... for storing options so there wont be any need to keep track of whats set over this
+ opt_names= av_realloc(opt_names, sizeof(void*)*(opt_name_count+1));
+ opt_names[opt_name_count++]= o->name;
+
+#if defined(CONFIG_FFM_DEMUXER) || defined(CONFIG_FFM_MUXER)
+ /* disable generate of real time pts in ffm (need to be supressed anyway) */
+ if(avctx_opts->flags & CODEC_FLAG_BITEXACT)
+ ffm_nopts = 1;
+#endif
+
+ if(avctx_opts->debug)
+ av_log_set_level(AV_LOG_DEBUG);
+ return 0;
+}
+
+const OptionDef options[] = {
+ /* main options */
+ { "L", 0, {(void*)show_license}, "show license" },
+ { "h", 0, {(void*)show_help}, "show help" },
+ { "version", 0, {(void*)show_version}, "show version" },
+ { "formats", 0, {(void*)show_formats}, "show available formats, codecs, protocols, ..." },
+ { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
+ { "i", HAS_ARG, {(void*)opt_input_file}, "input file name", "filename" },
+ { "y", OPT_BOOL, {(void*)&file_overwrite}, "overwrite output files" },
+ { "map", HAS_ARG | OPT_EXPERT, {(void*)opt_map}, "set input stream mapping", "file:stream[:syncfile:syncstream]" },
+ { "map_meta_data", HAS_ARG | OPT_EXPERT, {(void*)opt_map_meta_data}, "set meta data information of outfile from infile", "outfile:infile" },
+ { "t", HAS_ARG, {(void*)opt_recording_time}, "set the recording time", "duration" },
+ { "fs", HAS_ARG | OPT_INT, {(void*)&limit_filesize}, "set the limit file size", "limit_size" }, //
+ { "ss", HAS_ARG, {(void*)opt_start_time}, "set the start time offset", "time_off" },
+ { "itsoffset", HAS_ARG, {(void*)opt_input_ts_offset}, "set the input ts offset", "time_off" },
+ { "title", HAS_ARG | OPT_STRING, {(void*)&str_title}, "set the title", "string" },
+ { "timestamp", HAS_ARG, {(void*)&opt_rec_timestamp}, "set the timestamp", "time" },
+ { "author", HAS_ARG | OPT_STRING, {(void*)&str_author}, "set the author", "string" },
+ { "copyright", HAS_ARG | OPT_STRING, {(void*)&str_copyright}, "set the copyright", "string" },
+ { "comment", HAS_ARG | OPT_STRING, {(void*)&str_comment}, "set the comment", "string" },
+ { "album", HAS_ARG | OPT_STRING, {(void*)&str_album}, "set the album", "string" },
+ { "benchmark", OPT_BOOL | OPT_EXPERT, {(void*)&do_benchmark},
+ "add timings for benchmarking" },
+ { "dump", OPT_BOOL | OPT_EXPERT, {(void*)&do_pkt_dump},
+ "dump each input packet" },
+ { "hex", OPT_BOOL | OPT_EXPERT, {(void*)&do_hex_dump},
+ "when dumping packets, also dump the payload" },
+ { "re", OPT_BOOL | OPT_EXPERT, {(void*)&rate_emu}, "read input at native frame rate", "" },
+ { "loop_input", OPT_BOOL | OPT_EXPERT, {(void*)&loop_input}, "loop (current only works with images)" },
+ { "loop_output", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&loop_output}, "number of times to loop output in formats that support looping (0 loops forever)", "" },
+ { "v", HAS_ARG, {(void*)opt_verbose}, "control amount of logging", "verbose" },
+ { "target", HAS_ARG, {(void*)opt_target}, "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\", \"dv50\", \"pal-vcd\", \"ntsc-svcd\", ...)", "type" },
+ { "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
+ { "vsync", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_sync_method}, "video sync method", "" },
+ { "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" },
+ { "vglobal", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_global_header}, "video global header storage type", "" },
+ { "copyts", OPT_BOOL | OPT_EXPERT, {(void*)&copy_ts}, "copy timestamps" },
+ { "shortest", OPT_BOOL | OPT_EXPERT, {(void*)&opt_shortest}, "finish encoding within shortest input" }, //
+ { "dts_delta_threshold", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&dts_delta_threshold}, "timestamp discontinuity delta threshold", "" },
+
+ /* video options */
+ { "vframes", OPT_INT | HAS_ARG | OPT_VIDEO, {(void*)&max_frames[CODEC_TYPE_VIDEO]}, "set the number of video frames to record", "number" },
+ { "aframes", OPT_INT | HAS_ARG | OPT_AUDIO, {(void*)&max_frames[CODEC_TYPE_AUDIO]}, "set the number of audio frames to record", "number" },
+ { "dframes", OPT_INT | HAS_ARG, {(void*)&max_frames[CODEC_TYPE_DATA]}, "set the number of data frames to record", "number" },
+ { "r", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_rate}, "set frame rate (Hz value, fraction or abbreviation)", "rate" },
+ { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
+ { "aspect", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_aspect_ratio}, "set aspect ratio (4:3, 16:9 or 1.3333, 1.7777)", "aspect" },
+ { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format", "format" },
+ { "croptop", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_top}, "set top crop band size (in pixels)", "size" },
+ { "cropbottom", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_bottom}, "set bottom crop band size (in pixels)", "size" },
+ { "cropleft", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_left}, "set left crop band size (in pixels)", "size" },
+ { "cropright", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_right}, "set right crop band size (in pixels)", "size" },
+ { "padtop", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_top}, "set top pad band size (in pixels)", "size" },
+ { "padbottom", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_bottom}, "set bottom pad band size (in pixels)", "size" },
+ { "padleft", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_left}, "set left pad band size (in pixels)", "size" },
+ { "padright", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_right}, "set right pad band size (in pixels)", "size" },
+ { "padcolor", HAS_ARG | OPT_VIDEO, {(void*)opt_pad_color}, "set color of pad bands (Hex 000000 thru FFFFFF)", "color" },
+ { "intra", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_only}, "use only intra frames"},
+ { "vn", OPT_BOOL | OPT_VIDEO, {(void*)&video_disable}, "disable video" },
+ { "vdt", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&video_discard}, "discard threshold", "n" },
+ { "qscale", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qscale}, "use fixed video quantizer scale (VBR)", "q" },
+ { "qdiff", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qdiff}, "max difference between the quantizer scale (VBR)", "q" },
+ { "rc_eq", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_rc_eq}, "set rate control equation", "equation" },
+ { "rc_override", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_rc_override_string}, "rate control override for specific intervals", "override" },
+ { "vcodec", HAS_ARG | OPT_VIDEO, {(void*)opt_video_codec}, "force video codec ('copy' to copy stream)", "codec" },
+ { "me", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_motion_estimation}, "set motion estimation method",
+ "method" },
+ { "me_threshold", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_me_threshold}, "motion estimaton threshold", "" },
+ { "ps", HAS_ARG | OPT_EXPERT, {(void*)opt_packet_size}, "set packet size in bits", "size" },
+ { "strict", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_strict}, "how strictly to follow the standards", "strictness" },
+ { "sameq", OPT_BOOL | OPT_VIDEO, {(void*)&same_quality},
+ "use same video quality as source (implies VBR)" },
+ { "pass", HAS_ARG | OPT_VIDEO, {(void*)&opt_pass}, "select the pass number (1 or 2)", "n" },
+ { "passlogfile", HAS_ARG | OPT_STRING | OPT_VIDEO, {(void*)&pass_logfilename}, "select two pass log file name", "file" },
+ { "deinterlace", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_deinterlace},
+ "deinterlace pictures" },
+ { "psnr", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_psnr}, "calculate PSNR of compressed frames" },
+ { "vstats", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_vstats}, "dump video coding statistics to file" },
+ { "vhook", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)add_frame_hooker}, "insert video processing module", "module" },
+ { "intra_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_intra_matrix}, "specify intra matrix coeffs", "matrix" },
+ { "inter_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_inter_matrix}, "specify inter matrix coeffs", "matrix" },
+ { "top", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_top_field_first}, "top=1/bottom=0/auto=-1 field first", "" },
+ { "dc", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_dc_precision}, "intra_dc_precision", "precision" },
+ { "vtag", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_tag}, "force video tag/fourcc", "fourcc/tag" },
+ { "newvideo", OPT_VIDEO, {(void*)opt_new_video_stream}, "add a new video stream to the current output stream" },
+ { "qphist", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, { (void *)&qp_hist }, "show QP histogram" },
+
+ /* audio options */
+ { "ab", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_bitrate}, "set audio bitrate (in kbit/s)", "bitrate", },
+ { "aq", OPT_FLOAT | HAS_ARG | OPT_AUDIO, {(void*)&audio_qscale}, "set audio quality (codec-specific)", "quality", },
+ { "ar", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_rate}, "set audio sampling rate (in Hz)", "rate" },
+ { "ac", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_channels}, "set number of audio channels", "channels" },
+ { "an", OPT_BOOL | OPT_AUDIO, {(void*)&audio_disable}, "disable audio" },
+ { "acodec", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_codec}, "force audio codec ('copy' to copy stream)", "codec" },
+ { "atag", HAS_ARG | OPT_EXPERT | OPT_AUDIO, {(void*)opt_audio_tag}, "force audio tag/fourcc", "fourcc/tag" },
+ { "vol", OPT_INT | HAS_ARG | OPT_AUDIO, {(void*)&audio_volume}, "change audio volume (256=normal)" , "volume" }, //
+ { "newaudio", OPT_AUDIO, {(void*)opt_new_audio_stream}, "add a new audio stream to the current output stream" },
+ { "alang", HAS_ARG | OPT_STRING | OPT_AUDIO, {(void *)&audio_language}, "set the ISO 639 language code (3 letters) of the current audio stream" , "code" },
+
+ /* subtitle options */
+ { "scodec", HAS_ARG | OPT_SUBTITLE, {(void*)opt_subtitle_codec}, "force subtitle codec ('copy' to copy stream)", "codec" },
+ { "newsubtitle", OPT_SUBTITLE, {(void*)opt_new_subtitle_stream}, "add a new subtitle stream to the current output stream" },
+ { "slang", HAS_ARG | OPT_STRING | OPT_SUBTITLE, {(void *)&subtitle_language}, "set the ISO 639 language code (3 letters) of the current subtitle stream" , "code" },
+
+ /* grab options */
+ { "vd", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_device}, "set video grab device", "device" },
+ { "vc", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_channel}, "set video grab channel (DV1394 only)", "channel" },
+ { "tvstd", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_standard}, "set television standard (NTSC, PAL (SECAM))", "standard" },
+ { "ad", HAS_ARG | OPT_EXPERT | OPT_AUDIO | OPT_GRAB, {(void*)opt_audio_device}, "set audio device", "device" },
+
+ /* G.2 grab options */
+ { "grab", HAS_ARG | OPT_EXPERT | OPT_GRAB, {(void*)opt_grab}, "request grabbing using", "format" },
+ { "gd", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_grab_device}, "set grab device", "device" },
+
+ /* muxer options */
+ { "muxdelay", OPT_FLOAT | HAS_ARG | OPT_EXPERT, {(void*)&mux_max_delay}, "set the maximum demux-decode delay", "seconds" },
+ { "muxpreload", OPT_FLOAT | HAS_ARG | OPT_EXPERT, {(void*)&mux_preload}, "set the initial demux-decode delay", "seconds" },
+
+ { "absf", HAS_ARG | OPT_AUDIO | OPT_EXPERT, {(void*)opt_audio_bsf}, "", "bitstream filter" },
+ { "vbsf", HAS_ARG | OPT_VIDEO | OPT_EXPERT, {(void*)opt_video_bsf}, "", "bitstream filter" },
+
+ { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
+ { NULL, },
+};
+
+static void show_banner(void)
+{
+ fprintf(stderr, "FFmpeg version " FFMPEG_VERSION ", Copyright (c) 2000-2006 Fabrice Bellard, et al.\n");
+ fprintf(stderr, " configuration: " FFMPEG_CONFIGURATION "\n");
+ fprintf(stderr, " libavutil version: " AV_STRINGIFY(LIBAVUTIL_VERSION) "\n");
+ fprintf(stderr, " libavcodec version: " AV_STRINGIFY(LIBAVCODEC_VERSION) "\n");
+ fprintf(stderr, " libavformat version: " AV_STRINGIFY(LIBAVFORMAT_VERSION) "\n");
+ fprintf(stderr, " built on " __DATE__ " " __TIME__);
+#ifdef __GNUC__
+ fprintf(stderr, ", gcc: " __VERSION__ "\n");
+#else
+ fprintf(stderr, ", using a non-gcc compiler\n");
+#endif
+}
+
+static void show_license(void)
+{
+ show_banner();
+#ifdef CONFIG_GPL
+ printf(
+ "FFmpeg is free software; you can redistribute it and/or modify\n"
+ "it under the terms of the GNU General Public License as published by\n"
+ "the Free Software Foundation; either version 2 of the License, or\n"
+ "(at your option) any later version.\n"
+ "\n"
+ "FFmpeg is distributed in the hope that it will be useful,\n"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+ "GNU General Public License for more details.\n"
+ "\n"
+ "You should have received a copy of the GNU General Public License\n"
+ "along with FFmpeg; if not, write to the Free Software\n"
+ "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
+ );
+#else
+ printf(
+ "FFmpeg is free software; you can redistribute it and/or\n"
+ "modify it under the terms of the GNU Lesser General Public\n"
+ "License as published by the Free Software Foundation; either\n"
+ "version 2.1 of the License, or (at your option) any later version.\n"
+ "\n"
+ "FFmpeg is distributed in the hope that it will be useful,\n"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
+ "Lesser General Public License for more details.\n"
+ "\n"
+ "You should have received a copy of the GNU Lesser General Public\n"
+ "License along with FFmpeg; if not, write to the Free Software\n"
+ "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n"
+ );
+#endif
+ exit(1);
+}
+
+static void show_help(void)
+{
+ show_banner();
+ printf("usage: ffmpeg [[infile options] -i infile]... {[outfile options] outfile}...\n"
+ "Hyper fast Audio and Video encoder\n");
+ printf("\n");
+ show_help_options(options, "Main options:\n",
+ OPT_EXPERT | OPT_AUDIO | OPT_VIDEO, 0);
+ show_help_options(options, "\nVideo options:\n",
+ OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
+ OPT_VIDEO);
+ show_help_options(options, "\nAdvanced Video options:\n",
+ OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
+ OPT_VIDEO | OPT_EXPERT);
+ show_help_options(options, "\nAudio options:\n",
+ OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
+ OPT_AUDIO);
+ show_help_options(options, "\nAdvanced Audio options:\n",
+ OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
+ OPT_AUDIO | OPT_EXPERT);
+ show_help_options(options, "\nSubtitle options:\n",
+ OPT_SUBTITLE | OPT_GRAB,
+ OPT_SUBTITLE);
+ show_help_options(options, "\nAudio/Video grab options:\n",
+ OPT_GRAB,
+ OPT_GRAB);
+ show_help_options(options, "\nAdvanced options:\n",
+ OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
+ OPT_EXPERT);
+ av_opt_show(avctx_opts, NULL);
+ av_opt_show(avformat_opts, NULL);
+
+ exit(1);
+}
+
+void parse_arg_file(const char *filename)
+{
+ opt_output_file(filename);
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+ int64_t ti;
+
+ av_register_all();
+
+ avctx_opts= avcodec_alloc_context();
+ avformat_opts = av_alloc_format_context();
+
+ if (argc <= 1)
+ show_help();
+ else
+ show_banner();
+
+ /* parse options */
+ parse_options(argc, argv, options);
+
+ /* file converter / grab */
+ if (nb_output_files <= 0) {
+ fprintf(stderr, "Must supply at least one output file\n");
+ exit(1);
+ }
+
+ if (nb_input_files == 0) {
+ input_sync = 1;
+ prepare_grab();
+ }
+
+ ti = getutime();
+ av_encode(output_files, nb_output_files, input_files, nb_input_files,
+ stream_maps, nb_stream_maps);
+ ti = getutime() - ti;
+ if (do_benchmark) {
+ printf("bench: utime=%0.3fs\n", ti / 1000000.0);
+ }
+
+ /* close files */
+ for(i=0;i<nb_output_files;i++) {
+ /* maybe av_close_output_file ??? */
+ AVFormatContext *s = output_files[i];
+ int j;
+ if (!(s->oformat->flags & AVFMT_NOFILE))
+ url_fclose(&s->pb);
+ for(j=0;j<s->nb_streams;j++)
+ av_free(s->streams[j]);
+ av_free(s);
+ }
+ for(i=0;i<nb_input_files;i++)
+ av_close_input_file(input_files[i]);
+
+ av_free_static();
+
+ if(intra_matrix)
+ av_free(intra_matrix);
+ if(inter_matrix)
+ av_free(inter_matrix);
+
+#ifdef POWERPC_PERFORMANCE_REPORT
+ extern void powerpc_display_perf_report(void);
+ powerpc_display_perf_report();
+#endif /* POWERPC_PERFORMANCE_REPORT */
+
+ if (received_sigterm) {
+ fprintf(stderr,
+ "Received signal %d: terminating.\n",
+ (int) received_sigterm);
+ exit (255);
+ }
+
+ exit(0); /* not all OS-es handle main() return value */
+ return 0;
+}
diff --git a/contrib/ffmpeg/ffplay.c b/contrib/ffmpeg/ffplay.c
new file mode 100644
index 000000000..f80a43548
--- /dev/null
+++ b/contrib/ffmpeg/ffplay.c
@@ -0,0 +1,2488 @@
+/*
+ * FFplay : Simple Media Player based on the ffmpeg libraries
+ * 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 HAVE_AV_CONFIG_H
+#include "avformat.h"
+#include "swscale.h"
+
+#include "version.h"
+#include "cmdutils.h"
+
+#include <SDL.h>
+#include <SDL_thread.h>
+
+#ifdef __MINGW32__
+#undef main /* We don't want SDL to override our main() */
+#endif
+
+#ifdef CONFIG_OS2
+#define INCL_DOS
+ #include <os2.h>
+ #include <stdio.h>
+
+ void MorphToPM()
+ {
+ PPIB pib;
+ PTIB tib;
+
+ DosGetInfoBlocks(&tib, &pib);
+
+ // Change flag from VIO to PM:
+ if (pib->pib_ultype==2) pib->pib_ultype = 3;
+ }
+#endif
+
+//#define DEBUG_SYNC
+
+#define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
+#define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
+#define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
+
+/* SDL audio buffer size, in samples. Should be small to have precise
+ A/V sync as SDL does not have hardware buffer fullness info. */
+#define SDL_AUDIO_BUFFER_SIZE 1024
+
+/* no AV sync correction is done if below the AV sync threshold */
+#define AV_SYNC_THRESHOLD 0.01
+/* no AV correction is done if too big error */
+#define AV_NOSYNC_THRESHOLD 10.0
+
+/* maximum audio speed change to get correct sync */
+#define SAMPLE_CORRECTION_PERCENT_MAX 10
+
+/* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
+#define AUDIO_DIFF_AVG_NB 20
+
+/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
+#define SAMPLE_ARRAY_SIZE (2*65536)
+
+static int sws_flags = SWS_BICUBIC;
+
+typedef struct PacketQueue {
+ AVPacketList *first_pkt, *last_pkt;
+ int nb_packets;
+ int size;
+ int abort_request;
+ SDL_mutex *mutex;
+ SDL_cond *cond;
+} PacketQueue;
+
+#define VIDEO_PICTURE_QUEUE_SIZE 1
+#define SUBPICTURE_QUEUE_SIZE 4
+
+typedef struct VideoPicture {
+ double pts; ///<presentation time stamp for this picture
+ SDL_Overlay *bmp;
+ int width, height; /* source height & width */
+ int allocated;
+} VideoPicture;
+
+typedef struct SubPicture {
+ double pts; /* presentation time stamp for this picture */
+ AVSubtitle sub;
+} SubPicture;
+
+enum {
+ AV_SYNC_AUDIO_MASTER, /* default choice */
+ AV_SYNC_VIDEO_MASTER,
+ AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
+};
+
+typedef struct VideoState {
+ SDL_Thread *parse_tid;
+ SDL_Thread *video_tid;
+ AVInputFormat *iformat;
+ int no_background;
+ int abort_request;
+ int paused;
+ int last_paused;
+ int seek_req;
+ int seek_flags;
+ int64_t seek_pos;
+ AVFormatContext *ic;
+ int dtg_active_format;
+
+ int audio_stream;
+
+ int av_sync_type;
+ double external_clock; /* external clock base */
+ int64_t external_clock_time;
+
+ double audio_clock;
+ double audio_diff_cum; /* used for AV difference average computation */
+ double audio_diff_avg_coef;
+ double audio_diff_threshold;
+ int audio_diff_avg_count;
+ AVStream *audio_st;
+ PacketQueue audioq;
+ int audio_hw_buf_size;
+ /* samples output by the codec. we reserve more space for avsync
+ compensation */
+ DECLARE_ALIGNED(16,uint8_t,audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]);
+ unsigned int audio_buf_size; /* in bytes */
+ int audio_buf_index; /* in bytes */
+ AVPacket audio_pkt;
+ uint8_t *audio_pkt_data;
+ int audio_pkt_size;
+
+ int show_audio; /* if true, display audio samples */
+ int16_t sample_array[SAMPLE_ARRAY_SIZE];
+ int sample_array_index;
+ int last_i_start;
+
+ SDL_Thread *subtitle_tid;
+ int subtitle_stream;
+ int subtitle_stream_changed;
+ AVStream *subtitle_st;
+ PacketQueue subtitleq;
+ SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
+ int subpq_size, subpq_rindex, subpq_windex;
+ SDL_mutex *subpq_mutex;
+ SDL_cond *subpq_cond;
+
+ double frame_timer;
+ double frame_last_pts;
+ double frame_last_delay;
+ double video_clock; ///<pts of last decoded frame / predicted pts of next decoded frame
+ int video_stream;
+ AVStream *video_st;
+ PacketQueue videoq;
+ double video_current_pts; ///<current displayed pts (different from video_clock if frame fifos are used)
+ int64_t video_current_pts_time; ///<time (av_gettime) at which we updated video_current_pts - used to have running video pts
+ VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
+ int pictq_size, pictq_rindex, pictq_windex;
+ SDL_mutex *pictq_mutex;
+ SDL_cond *pictq_cond;
+
+ // QETimer *video_timer;
+ char filename[1024];
+ int width, height, xleft, ytop;
+} VideoState;
+
+void show_help(void);
+static int audio_write_get_buf_size(VideoState *is);
+
+/* options specified by the user */
+static AVInputFormat *file_iformat;
+static const char *input_filename;
+static int fs_screen_width;
+static int fs_screen_height;
+static int screen_width = 640;
+static int screen_height = 480;
+static int audio_disable;
+static int video_disable;
+static int seek_by_bytes;
+static int display_disable;
+static int show_status;
+static int av_sync_type = AV_SYNC_AUDIO_MASTER;
+static int64_t start_time = AV_NOPTS_VALUE;
+static int debug = 0;
+static int debug_mv = 0;
+static int step = 0;
+static int thread_count = 1;
+static int workaround_bugs = 1;
+static int fast = 0;
+static int genpts = 0;
+static int lowres = 0;
+static int idct = FF_IDCT_AUTO;
+static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
+static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
+static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
+static int error_resilience = FF_ER_CAREFUL;
+static int error_concealment = 3;
+
+/* current context */
+static int is_full_screen;
+static VideoState *cur_stream;
+static int64_t audio_callback_time;
+
+AVPacket flush_pkt;
+
+#define FF_ALLOC_EVENT (SDL_USEREVENT)
+#define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
+#define FF_QUIT_EVENT (SDL_USEREVENT + 2)
+
+SDL_Surface *screen;
+
+/* packet queue handling */
+static void packet_queue_init(PacketQueue *q)
+{
+ memset(q, 0, sizeof(PacketQueue));
+ q->mutex = SDL_CreateMutex();
+ q->cond = SDL_CreateCond();
+}
+
+static void packet_queue_flush(PacketQueue *q)
+{
+ AVPacketList *pkt, *pkt1;
+
+ SDL_LockMutex(q->mutex);
+ for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
+ pkt1 = pkt->next;
+ av_free_packet(&pkt->pkt);
+ av_freep(&pkt);
+ }
+ q->last_pkt = NULL;
+ q->first_pkt = NULL;
+ q->nb_packets = 0;
+ q->size = 0;
+ SDL_UnlockMutex(q->mutex);
+}
+
+static void packet_queue_end(PacketQueue *q)
+{
+ packet_queue_flush(q);
+ SDL_DestroyMutex(q->mutex);
+ SDL_DestroyCond(q->cond);
+}
+
+static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
+{
+ AVPacketList *pkt1;
+
+ /* duplicate the packet */
+ if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
+ return -1;
+
+ pkt1 = av_malloc(sizeof(AVPacketList));
+ if (!pkt1)
+ return -1;
+ pkt1->pkt = *pkt;
+ pkt1->next = NULL;
+
+
+ SDL_LockMutex(q->mutex);
+
+ if (!q->last_pkt)
+
+ q->first_pkt = pkt1;
+ else
+ q->last_pkt->next = pkt1;
+ q->last_pkt = pkt1;
+ q->nb_packets++;
+ q->size += pkt1->pkt.size;
+ /* XXX: should duplicate packet data in DV case */
+ SDL_CondSignal(q->cond);
+
+ SDL_UnlockMutex(q->mutex);
+ return 0;
+}
+
+static void packet_queue_abort(PacketQueue *q)
+{
+ SDL_LockMutex(q->mutex);
+
+ q->abort_request = 1;
+
+ SDL_CondSignal(q->cond);
+
+ SDL_UnlockMutex(q->mutex);
+}
+
+/* return < 0 if aborted, 0 if no packet and > 0 if packet. */
+static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
+{
+ AVPacketList *pkt1;
+ int ret;
+
+ SDL_LockMutex(q->mutex);
+
+ for(;;) {
+ if (q->abort_request) {
+ ret = -1;
+ break;
+ }
+
+ pkt1 = q->first_pkt;
+ if (pkt1) {
+ q->first_pkt = pkt1->next;
+ if (!q->first_pkt)
+ q->last_pkt = NULL;
+ q->nb_packets--;
+ q->size -= pkt1->pkt.size;
+ *pkt = pkt1->pkt;
+ av_free(pkt1);
+ ret = 1;
+ break;
+ } else if (!block) {
+ ret = 0;
+ break;
+ } else {
+ SDL_CondWait(q->cond, q->mutex);
+ }
+ }
+ SDL_UnlockMutex(q->mutex);
+ return ret;
+}
+
+static inline void fill_rectangle(SDL_Surface *screen,
+ int x, int y, int w, int h, int color)
+{
+ SDL_Rect rect;
+ rect.x = x;
+ rect.y = y;
+ rect.w = w;
+ rect.h = h;
+ SDL_FillRect(screen, &rect, color);
+}
+
+#if 0
+/* draw only the border of a rectangle */
+void fill_border(VideoState *s, int x, int y, int w, int h, int color)
+{
+ int w1, w2, h1, h2;
+
+ /* fill the background */
+ w1 = x;
+ if (w1 < 0)
+ w1 = 0;
+ w2 = s->width - (x + w);
+ if (w2 < 0)
+ w2 = 0;
+ h1 = y;
+ if (h1 < 0)
+ h1 = 0;
+ h2 = s->height - (y + h);
+ if (h2 < 0)
+ h2 = 0;
+ fill_rectangle(screen,
+ s->xleft, s->ytop,
+ w1, s->height,
+ color);
+ fill_rectangle(screen,
+ s->xleft + s->width - w2, s->ytop,
+ w2, s->height,
+ color);
+ fill_rectangle(screen,
+ s->xleft + w1, s->ytop,
+ s->width - w1 - w2, h1,
+ color);
+ fill_rectangle(screen,
+ s->xleft + w1, s->ytop + s->height - h2,
+ s->width - w1 - w2, h2,
+ color);
+}
+#endif
+
+
+
+#define SCALEBITS 10
+#define ONE_HALF (1 << (SCALEBITS - 1))
+#define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
+
+#define RGB_TO_Y_CCIR(r, g, b) \
+((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
+ FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
+
+#define RGB_TO_U_CCIR(r1, g1, b1, shift)\
+(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \
+ FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
+
+#define RGB_TO_V_CCIR(r1, g1, b1, shift)\
+(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \
+ FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
+
+#define ALPHA_BLEND(a, oldp, newp, s)\
+((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
+
+#define RGBA_IN(r, g, b, a, s)\
+{\
+ unsigned int v = ((const uint32_t *)(s))[0];\
+ a = (v >> 24) & 0xff;\
+ r = (v >> 16) & 0xff;\
+ g = (v >> 8) & 0xff;\
+ b = v & 0xff;\
+}
+
+#define YUVA_IN(y, u, v, a, s, pal)\
+{\
+ unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)s];\
+ a = (val >> 24) & 0xff;\
+ y = (val >> 16) & 0xff;\
+ u = (val >> 8) & 0xff;\
+ v = val & 0xff;\
+}
+
+#define YUVA_OUT(d, y, u, v, a)\
+{\
+ ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
+}
+
+
+#define BPP 1
+
+static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect)
+{
+ int wrap, wrap3, width2, skip2;
+ int y, u, v, a, u1, v1, a1, w, h;
+ uint8_t *lum, *cb, *cr;
+ const uint8_t *p;
+ const uint32_t *pal;
+
+ lum = dst->data[0] + rect->y * dst->linesize[0];
+ cb = dst->data[1] + (rect->y >> 1) * dst->linesize[1];
+ cr = dst->data[2] + (rect->y >> 1) * dst->linesize[2];
+
+ width2 = (rect->w + 1) >> 1;
+ skip2 = rect->x >> 1;
+ wrap = dst->linesize[0];
+ wrap3 = rect->linesize;
+ p = rect->bitmap;
+ pal = rect->rgba_palette; /* Now in YCrCb! */
+
+ if (rect->y & 1) {
+ lum += rect->x;
+ cb += skip2;
+ cr += skip2;
+
+ if (rect->x & 1) {
+ YUVA_IN(y, u, v, a, p, pal);
+ lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
+ cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
+ cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
+ cb++;
+ cr++;
+ lum++;
+ p += BPP;
+ }
+ for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
+ YUVA_IN(y, u, v, a, p, pal);
+ u1 = u;
+ v1 = v;
+ a1 = a;
+ lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
+
+ YUVA_IN(y, u, v, a, p + BPP, pal);
+ u1 += u;
+ v1 += v;
+ a1 += a;
+ lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
+ cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
+ cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
+ cb++;
+ cr++;
+ p += 2 * BPP;
+ lum += 2;
+ }
+ if (w) {
+ YUVA_IN(y, u, v, a, p, pal);
+ lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
+ cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
+ cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
+ }
+ p += wrap3 + (wrap3 - rect->w * BPP);
+ lum += wrap + (wrap - rect->w - rect->x);
+ cb += dst->linesize[1] - width2 - skip2;
+ cr += dst->linesize[2] - width2 - skip2;
+ }
+ for(h = rect->h - (rect->y & 1); h >= 2; h -= 2) {
+ lum += rect->x;
+ cb += skip2;
+ cr += skip2;
+
+ if (rect->x & 1) {
+ YUVA_IN(y, u, v, a, p, pal);
+ u1 = u;
+ v1 = v;
+ a1 = a;
+ lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
+ p += wrap3;
+ lum += wrap;
+ YUVA_IN(y, u, v, a, p, pal);
+ u1 += u;
+ v1 += v;
+ a1 += a;
+ lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
+ cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
+ cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
+ cb++;
+ cr++;
+ p += -wrap3 + BPP;
+ lum += -wrap + 1;
+ }
+ for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
+ YUVA_IN(y, u, v, a, p, pal);
+ u1 = u;
+ v1 = v;
+ a1 = a;
+ lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
+
+ YUVA_IN(y, u, v, a, p, pal);
+ u1 += u;
+ v1 += v;
+ a1 += a;
+ lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
+ p += wrap3;
+ lum += wrap;
+
+ YUVA_IN(y, u, v, a, p, pal);
+ u1 += u;
+ v1 += v;
+ a1 += a;
+ lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
+
+ YUVA_IN(y, u, v, a, p, pal);
+ u1 += u;
+ v1 += v;
+ a1 += a;
+ lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
+
+ cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2);
+ cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2);
+
+ cb++;
+ cr++;
+ p += -wrap3 + 2 * BPP;
+ lum += -wrap + 2;
+ }
+ if (w) {
+ YUVA_IN(y, u, v, a, p, pal);
+ u1 = u;
+ v1 = v;
+ a1 = a;
+ lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
+ p += wrap3;
+ lum += wrap;
+ YUVA_IN(y, u, v, a, p, pal);
+ u1 += u;
+ v1 += v;
+ a1 += a;
+ lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
+ cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
+ cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
+ cb++;
+ cr++;
+ p += -wrap3 + BPP;
+ lum += -wrap + 1;
+ }
+ p += wrap3 + (wrap3 - rect->w * BPP);
+ lum += wrap + (wrap - rect->w - rect->x);
+ cb += dst->linesize[1] - width2 - skip2;
+ cr += dst->linesize[2] - width2 - skip2;
+ }
+ /* handle odd height */
+ if (h) {
+ lum += rect->x;
+ cb += skip2;
+ cr += skip2;
+
+ if (rect->x & 1) {
+ YUVA_IN(y, u, v, a, p, pal);
+ lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
+ cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
+ cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
+ cb++;
+ cr++;
+ lum++;
+ p += BPP;
+ }
+ for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
+ YUVA_IN(y, u, v, a, p, pal);
+ u1 = u;
+ v1 = v;
+ a1 = a;
+ lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
+
+ YUVA_IN(y, u, v, a, p + BPP, pal);
+ u1 += u;
+ v1 += v;
+ a1 += a;
+ lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
+ cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
+ cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
+ cb++;
+ cr++;
+ p += 2 * BPP;
+ lum += 2;
+ }
+ if (w) {
+ YUVA_IN(y, u, v, a, p, pal);
+ lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
+ cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
+ cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
+ }
+ }
+}
+
+static void free_subpicture(SubPicture *sp)
+{
+ int i;
+
+ for (i = 0; i < sp->sub.num_rects; i++)
+ {
+ av_free(sp->sub.rects[i].bitmap);
+ av_free(sp->sub.rects[i].rgba_palette);
+ }
+
+ av_free(sp->sub.rects);
+
+ memset(&sp->sub, 0, sizeof(AVSubtitle));
+}
+
+static void video_image_display(VideoState *is)
+{
+ VideoPicture *vp;
+ SubPicture *sp;
+ AVPicture pict;
+ float aspect_ratio;
+ int width, height, x, y;
+ SDL_Rect rect;
+ int i;
+
+ vp = &is->pictq[is->pictq_rindex];
+ if (vp->bmp) {
+ /* XXX: use variable in the frame */
+ if (is->video_st->codec->sample_aspect_ratio.num == 0)
+ aspect_ratio = 0;
+ else
+ aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio)
+ * is->video_st->codec->width / is->video_st->codec->height;;
+ if (aspect_ratio <= 0.0)
+ aspect_ratio = (float)is->video_st->codec->width /
+ (float)is->video_st->codec->height;
+ /* if an active format is indicated, then it overrides the
+ mpeg format */
+#if 0
+ if (is->video_st->codec->dtg_active_format != is->dtg_active_format) {
+ is->dtg_active_format = is->video_st->codec->dtg_active_format;
+ printf("dtg_active_format=%d\n", is->dtg_active_format);
+ }
+#endif
+#if 0
+ switch(is->video_st->codec->dtg_active_format) {
+ case FF_DTG_AFD_SAME:
+ default:
+ /* nothing to do */
+ break;
+ case FF_DTG_AFD_4_3:
+ aspect_ratio = 4.0 / 3.0;
+ break;
+ case FF_DTG_AFD_16_9:
+ aspect_ratio = 16.0 / 9.0;
+ break;
+ case FF_DTG_AFD_14_9:
+ aspect_ratio = 14.0 / 9.0;
+ break;
+ case FF_DTG_AFD_4_3_SP_14_9:
+ aspect_ratio = 14.0 / 9.0;
+ break;
+ case FF_DTG_AFD_16_9_SP_14_9:
+ aspect_ratio = 14.0 / 9.0;
+ break;
+ case FF_DTG_AFD_SP_4_3:
+ aspect_ratio = 4.0 / 3.0;
+ break;
+ }
+#endif
+
+ if (is->subtitle_st)
+ {
+ if (is->subpq_size > 0)
+ {
+ sp = &is->subpq[is->subpq_rindex];
+
+ if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000))
+ {
+ SDL_LockYUVOverlay (vp->bmp);
+
+ pict.data[0] = vp->bmp->pixels[0];
+ pict.data[1] = vp->bmp->pixels[2];
+ pict.data[2] = vp->bmp->pixels[1];
+
+ pict.linesize[0] = vp->bmp->pitches[0];
+ pict.linesize[1] = vp->bmp->pitches[2];
+ pict.linesize[2] = vp->bmp->pitches[1];
+
+ for (i = 0; i < sp->sub.num_rects; i++)
+ blend_subrect(&pict, &sp->sub.rects[i]);
+
+ SDL_UnlockYUVOverlay (vp->bmp);
+ }
+ }
+ }
+
+
+ /* XXX: we suppose the screen has a 1.0 pixel ratio */
+ height = is->height;
+ width = ((int)rint(height * aspect_ratio)) & -3;
+ if (width > is->width) {
+ width = is->width;
+ height = ((int)rint(width / aspect_ratio)) & -3;
+ }
+ x = (is->width - width) / 2;
+ y = (is->height - height) / 2;
+ if (!is->no_background) {
+ /* fill the background */
+ // fill_border(is, x, y, width, height, QERGB(0x00, 0x00, 0x00));
+ } else {
+ is->no_background = 0;
+ }
+ rect.x = is->xleft + x;
+ rect.y = is->xleft + y;
+ rect.w = width;
+ rect.h = height;
+ SDL_DisplayYUVOverlay(vp->bmp, &rect);
+ } else {
+#if 0
+ fill_rectangle(screen,
+ is->xleft, is->ytop, is->width, is->height,
+ QERGB(0x00, 0x00, 0x00));
+#endif
+ }
+}
+
+static inline int compute_mod(int a, int b)
+{
+ a = a % b;
+ if (a >= 0)
+ return a;
+ else
+ return a + b;
+}
+
+static void video_audio_display(VideoState *s)
+{
+ int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
+ int ch, channels, h, h2, bgcolor, fgcolor;
+ int16_t time_diff;
+
+ /* compute display index : center on currently output samples */
+ channels = s->audio_st->codec->channels;
+ nb_display_channels = channels;
+ if (!s->paused) {
+ n = 2 * channels;
+ delay = audio_write_get_buf_size(s);
+ delay /= n;
+
+ /* to be more precise, we take into account the time spent since
+ the last buffer computation */
+ if (audio_callback_time) {
+ time_diff = av_gettime() - audio_callback_time;
+ delay += (time_diff * s->audio_st->codec->sample_rate) / 1000000;
+ }
+
+ delay -= s->width / 2;
+ if (delay < s->width)
+ delay = s->width;
+ i_start = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
+ s->last_i_start = i_start;
+ } else {
+ i_start = s->last_i_start;
+ }
+
+ bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
+ fill_rectangle(screen,
+ s->xleft, s->ytop, s->width, s->height,
+ bgcolor);
+
+ fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
+
+ /* total height for one channel */
+ h = s->height / nb_display_channels;
+ /* graph height / 2 */
+ h2 = (h * 9) / 20;
+ for(ch = 0;ch < nb_display_channels; ch++) {
+ i = i_start + ch;
+ y1 = s->ytop + ch * h + (h / 2); /* position of center line */
+ for(x = 0; x < s->width; x++) {
+ y = (s->sample_array[i] * h2) >> 15;
+ if (y < 0) {
+ y = -y;
+ ys = y1 - y;
+ } else {
+ ys = y1;
+ }
+ fill_rectangle(screen,
+ s->xleft + x, ys, 1, y,
+ fgcolor);
+ i += channels;
+ if (i >= SAMPLE_ARRAY_SIZE)
+ i -= SAMPLE_ARRAY_SIZE;
+ }
+ }
+
+ fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
+
+ for(ch = 1;ch < nb_display_channels; ch++) {
+ y = s->ytop + ch * h;
+ fill_rectangle(screen,
+ s->xleft, y, s->width, 1,
+ fgcolor);
+ }
+ SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
+}
+
+/* display the current picture, if any */
+static void video_display(VideoState *is)
+{
+ if (is->audio_st && is->show_audio)
+ video_audio_display(is);
+ else if (is->video_st)
+ video_image_display(is);
+}
+
+static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque)
+{
+ SDL_Event event;
+ event.type = FF_REFRESH_EVENT;
+ event.user.data1 = opaque;
+ SDL_PushEvent(&event);
+ return 0; /* 0 means stop timer */
+}
+
+/* schedule a video refresh in 'delay' ms */
+static void schedule_refresh(VideoState *is, int delay)
+{
+ SDL_AddTimer(delay, sdl_refresh_timer_cb, is);
+}
+
+/* get the current audio clock value */
+static double get_audio_clock(VideoState *is)
+{
+ double pts;
+ int hw_buf_size, bytes_per_sec;
+ pts = is->audio_clock;
+ hw_buf_size = audio_write_get_buf_size(is);
+ bytes_per_sec = 0;
+ if (is->audio_st) {
+ bytes_per_sec = is->audio_st->codec->sample_rate *
+ 2 * is->audio_st->codec->channels;
+ }
+ if (bytes_per_sec)
+ pts -= (double)hw_buf_size / bytes_per_sec;
+ return pts;
+}
+
+/* get the current video clock value */
+static double get_video_clock(VideoState *is)
+{
+ double delta;
+ if (is->paused) {
+ delta = 0;
+ } else {
+ delta = (av_gettime() - is->video_current_pts_time) / 1000000.0;
+ }
+ return is->video_current_pts + delta;
+}
+
+/* get the current external clock value */
+static double get_external_clock(VideoState *is)
+{
+ int64_t ti;
+ ti = av_gettime();
+ return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
+}
+
+/* get the current master clock value */
+static double get_master_clock(VideoState *is)
+{
+ double val;
+
+ if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
+ if (is->video_st)
+ val = get_video_clock(is);
+ else
+ val = get_audio_clock(is);
+ } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
+ if (is->audio_st)
+ val = get_audio_clock(is);
+ else
+ val = get_video_clock(is);
+ } else {
+ val = get_external_clock(is);
+ }
+ return val;
+}
+
+/* seek in the stream */
+static void stream_seek(VideoState *is, int64_t pos, int rel)
+{
+ if (!is->seek_req) {
+ is->seek_pos = pos;
+ is->seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0;
+ if (seek_by_bytes)
+ is->seek_flags |= AVSEEK_FLAG_BYTE;
+ is->seek_req = 1;
+ }
+}
+
+/* pause or resume the video */
+static void stream_pause(VideoState *is)
+{
+ is->paused = !is->paused;
+ if (is->paused) {
+ is->video_current_pts = get_video_clock(is);
+ }
+}
+
+/* called to display each frame */
+static void video_refresh_timer(void *opaque)
+{
+ VideoState *is = opaque;
+ VideoPicture *vp;
+ double actual_delay, delay, sync_threshold, ref_clock, diff;
+
+ SubPicture *sp, *sp2;
+
+ if (is->video_st) {
+ if (is->pictq_size == 0) {
+ /* if no picture, need to wait */
+ schedule_refresh(is, 1);
+ } else {
+ /* dequeue the picture */
+ vp = &is->pictq[is->pictq_rindex];
+
+ /* update current video pts */
+ is->video_current_pts = vp->pts;
+ is->video_current_pts_time = av_gettime();
+
+ /* compute nominal delay */
+ delay = vp->pts - is->frame_last_pts;
+ if (delay <= 0 || delay >= 1.0) {
+ /* if incorrect delay, use previous one */
+ delay = is->frame_last_delay;
+ }
+ is->frame_last_delay = delay;
+ is->frame_last_pts = vp->pts;
+
+ /* update delay to follow master synchronisation source */
+ if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
+ is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
+ /* if video is slave, we try to correct big delays by
+ duplicating or deleting a frame */
+ ref_clock = get_master_clock(is);
+ diff = vp->pts - ref_clock;
+
+ /* skip or repeat frame. We take into account the
+ delay to compute the threshold. I still don't know
+ if it is the best guess */
+ sync_threshold = AV_SYNC_THRESHOLD;
+ if (delay > sync_threshold)
+ sync_threshold = delay;
+ if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
+ if (diff <= -sync_threshold)
+ delay = 0;
+ else if (diff >= sync_threshold)
+ delay = 2 * delay;
+ }
+ }
+
+ is->frame_timer += delay;
+ /* compute the REAL delay (we need to do that to avoid
+ long term errors */
+ actual_delay = is->frame_timer - (av_gettime() / 1000000.0);
+ if (actual_delay < 0.010) {
+ /* XXX: should skip picture */
+ actual_delay = 0.010;
+ }
+ /* launch timer for next picture */
+ schedule_refresh(is, (int)(actual_delay * 1000 + 0.5));
+
+#if defined(DEBUG_SYNC)
+ printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
+ delay, actual_delay, vp->pts, -diff);
+#endif
+
+ if(is->subtitle_st) {
+ if (is->subtitle_stream_changed) {
+ SDL_LockMutex(is->subpq_mutex);
+
+ while (is->subpq_size) {
+ free_subpicture(&is->subpq[is->subpq_rindex]);
+
+ /* update queue size and signal for next picture */
+ if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
+ is->subpq_rindex = 0;
+
+ is->subpq_size--;
+ }
+ is->subtitle_stream_changed = 0;
+
+ SDL_CondSignal(is->subpq_cond);
+ SDL_UnlockMutex(is->subpq_mutex);
+ } else {
+ if (is->subpq_size > 0) {
+ sp = &is->subpq[is->subpq_rindex];
+
+ if (is->subpq_size > 1)
+ sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE];
+ else
+ sp2 = NULL;
+
+ if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
+ || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
+ {
+ free_subpicture(sp);
+
+ /* update queue size and signal for next picture */
+ if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
+ is->subpq_rindex = 0;
+
+ SDL_LockMutex(is->subpq_mutex);
+ is->subpq_size--;
+ SDL_CondSignal(is->subpq_cond);
+ SDL_UnlockMutex(is->subpq_mutex);
+ }
+ }
+ }
+ }
+
+ /* display picture */
+ video_display(is);
+
+ /* update queue size and signal for next picture */
+ if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
+ is->pictq_rindex = 0;
+
+ SDL_LockMutex(is->pictq_mutex);
+ is->pictq_size--;
+ SDL_CondSignal(is->pictq_cond);
+ SDL_UnlockMutex(is->pictq_mutex);
+ }
+ } else if (is->audio_st) {
+ /* draw the next audio frame */
+
+ schedule_refresh(is, 40);
+
+ /* if only audio stream, then display the audio bars (better
+ than nothing, just to test the implementation */
+
+ /* display picture */
+ video_display(is);
+ } else {
+ schedule_refresh(is, 100);
+ }
+ if (show_status) {
+ static int64_t last_time;
+ int64_t cur_time;
+ int aqsize, vqsize, sqsize;
+ double av_diff;
+
+ cur_time = av_gettime();
+ if (!last_time || (cur_time - last_time) >= 500 * 1000) {
+ aqsize = 0;
+ vqsize = 0;
+ sqsize = 0;
+ if (is->audio_st)
+ aqsize = is->audioq.size;
+ if (is->video_st)
+ vqsize = is->videoq.size;
+ if (is->subtitle_st)
+ sqsize = is->subtitleq.size;
+ av_diff = 0;
+ if (is->audio_st && is->video_st)
+ av_diff = get_audio_clock(is) - get_video_clock(is);
+ printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB sq=%5dB \r",
+ get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024, sqsize);
+ fflush(stdout);
+ last_time = cur_time;
+ }
+ }
+}
+
+/* allocate a picture (needs to do that in main thread to avoid
+ potential locking problems */
+static void alloc_picture(void *opaque)
+{
+ VideoState *is = opaque;
+ VideoPicture *vp;
+
+ vp = &is->pictq[is->pictq_windex];
+
+ if (vp->bmp)
+ SDL_FreeYUVOverlay(vp->bmp);
+
+#if 0
+ /* XXX: use generic function */
+ /* XXX: disable overlay if no hardware acceleration or if RGB format */
+ switch(is->video_st->codec->pix_fmt) {
+ case PIX_FMT_YUV420P:
+ case PIX_FMT_YUV422P:
+ case PIX_FMT_YUV444P:
+ case PIX_FMT_YUV422:
+ case PIX_FMT_YUV410P:
+ case PIX_FMT_YUV411P:
+ is_yuv = 1;
+ break;
+ default:
+ is_yuv = 0;
+ break;
+ }
+#endif
+ vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec->width,
+ is->video_st->codec->height,
+ SDL_YV12_OVERLAY,
+ screen);
+ vp->width = is->video_st->codec->width;
+ vp->height = is->video_st->codec->height;
+
+ SDL_LockMutex(is->pictq_mutex);
+ vp->allocated = 1;
+ SDL_CondSignal(is->pictq_cond);
+ SDL_UnlockMutex(is->pictq_mutex);
+}
+
+/**
+ *
+ * @param pts the dts of the pkt / pts of the frame and guessed if not known
+ */
+static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
+{
+ VideoPicture *vp;
+ int dst_pix_fmt;
+ AVPicture pict;
+ static struct SwsContext *img_convert_ctx;
+
+ /* wait until we have space to put a new picture */
+ SDL_LockMutex(is->pictq_mutex);
+ while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
+ !is->videoq.abort_request) {
+ SDL_CondWait(is->pictq_cond, is->pictq_mutex);
+ }
+ SDL_UnlockMutex(is->pictq_mutex);
+
+ if (is->videoq.abort_request)
+ return -1;
+
+ vp = &is->pictq[is->pictq_windex];
+
+ /* alloc or resize hardware picture buffer */
+ if (!vp->bmp ||
+ vp->width != is->video_st->codec->width ||
+ vp->height != is->video_st->codec->height) {
+ SDL_Event event;
+
+ vp->allocated = 0;
+
+ /* the allocation must be done in the main thread to avoid
+ locking problems */
+ event.type = FF_ALLOC_EVENT;
+ event.user.data1 = is;
+ SDL_PushEvent(&event);
+
+ /* wait until the picture is allocated */
+ SDL_LockMutex(is->pictq_mutex);
+ while (!vp->allocated && !is->videoq.abort_request) {
+ SDL_CondWait(is->pictq_cond, is->pictq_mutex);
+ }
+ SDL_UnlockMutex(is->pictq_mutex);
+
+ if (is->videoq.abort_request)
+ return -1;
+ }
+
+ /* if the frame is not skipped, then display it */
+ if (vp->bmp) {
+ /* get a pointer on the bitmap */
+ SDL_LockYUVOverlay (vp->bmp);
+
+ dst_pix_fmt = PIX_FMT_YUV420P;
+ pict.data[0] = vp->bmp->pixels[0];
+ pict.data[1] = vp->bmp->pixels[2];
+ pict.data[2] = vp->bmp->pixels[1];
+
+ pict.linesize[0] = vp->bmp->pitches[0];
+ pict.linesize[1] = vp->bmp->pitches[2];
+ pict.linesize[2] = vp->bmp->pitches[1];
+ if (img_convert_ctx == NULL) {
+ img_convert_ctx = sws_getContext(is->video_st->codec->width,
+ is->video_st->codec->height, is->video_st->codec->pix_fmt,
+ is->video_st->codec->width, is->video_st->codec->height,
+ dst_pix_fmt, sws_flags, NULL, NULL, NULL);
+ if (img_convert_ctx == NULL) {
+ fprintf(stderr, "Cannot initialize the conversion context\n");
+ exit(1);
+ }
+ }
+ sws_scale(img_convert_ctx, src_frame->data, src_frame->linesize,
+ 0, is->video_st->codec->height, pict.data, pict.linesize);
+ /* update the bitmap content */
+ SDL_UnlockYUVOverlay(vp->bmp);
+
+ vp->pts = pts;
+
+ /* now we can update the picture count */
+ if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
+ is->pictq_windex = 0;
+ SDL_LockMutex(is->pictq_mutex);
+ is->pictq_size++;
+ SDL_UnlockMutex(is->pictq_mutex);
+ }
+ return 0;
+}
+
+/**
+ * compute the exact PTS for the picture if it is omitted in the stream
+ * @param pts1 the dts of the pkt / pts of the frame
+ */
+static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1)
+{
+ double frame_delay, pts;
+
+ pts = pts1;
+
+ if (pts != 0) {
+ /* update video clock with pts, if present */
+ is->video_clock = pts;
+ } else {
+ pts = is->video_clock;
+ }
+ /* update video clock for next frame */
+ frame_delay = av_q2d(is->video_st->codec->time_base);
+ /* for MPEG2, the frame can be repeated, so we update the
+ clock accordingly */
+ frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
+ is->video_clock += frame_delay;
+
+#if defined(DEBUG_SYNC) && 0
+ {
+ int ftype;
+ if (src_frame->pict_type == FF_B_TYPE)
+ ftype = 'B';
+ else if (src_frame->pict_type == FF_I_TYPE)
+ ftype = 'I';
+ else
+ ftype = 'P';
+ printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
+ ftype, pts, pts1);
+ }
+#endif
+ return queue_picture(is, src_frame, pts);
+}
+
+static int video_thread(void *arg)
+{
+ VideoState *is = arg;
+ AVPacket pkt1, *pkt = &pkt1;
+ int len1, got_picture;
+ AVFrame *frame= avcodec_alloc_frame();
+ double pts;
+
+ for(;;) {
+ while (is->paused && !is->videoq.abort_request) {
+ SDL_Delay(10);
+ }
+ if (packet_queue_get(&is->videoq, pkt, 1) < 0)
+ break;
+
+ if(pkt->data == flush_pkt.data){
+ avcodec_flush_buffers(is->video_st->codec);
+ continue;
+ }
+
+ /* NOTE: ipts is the PTS of the _first_ picture beginning in
+ this packet, if any */
+ pts = 0;
+ if (pkt->dts != AV_NOPTS_VALUE)
+ pts = av_q2d(is->video_st->time_base)*pkt->dts;
+
+ len1 = avcodec_decode_video(is->video_st->codec,
+ frame, &got_picture,
+ pkt->data, pkt->size);
+// if (len1 < 0)
+// break;
+ if (got_picture) {
+ if (output_picture2(is, frame, pts) < 0)
+ goto the_end;
+ }
+ av_free_packet(pkt);
+ if (step)
+ if (cur_stream)
+ stream_pause(cur_stream);
+ }
+ the_end:
+ av_free(frame);
+ return 0;
+}
+
+static int subtitle_thread(void *arg)
+{
+ VideoState *is = arg;
+ SubPicture *sp;
+ AVPacket pkt1, *pkt = &pkt1;
+ int len1, got_subtitle;
+ double pts;
+ int i, j;
+ int r, g, b, y, u, v, a;
+
+ for(;;) {
+ while (is->paused && !is->subtitleq.abort_request) {
+ SDL_Delay(10);
+ }
+ if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
+ break;
+
+ if(pkt->data == flush_pkt.data){
+ avcodec_flush_buffers(is->subtitle_st->codec);
+ continue;
+ }
+ SDL_LockMutex(is->subpq_mutex);
+ while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
+ !is->subtitleq.abort_request) {
+ SDL_CondWait(is->subpq_cond, is->subpq_mutex);
+ }
+ SDL_UnlockMutex(is->subpq_mutex);
+
+ if (is->subtitleq.abort_request)
+ goto the_end;
+
+ sp = &is->subpq[is->subpq_windex];
+
+ /* NOTE: ipts is the PTS of the _first_ picture beginning in
+ this packet, if any */
+ pts = 0;
+ if (pkt->pts != AV_NOPTS_VALUE)
+ pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
+
+ len1 = avcodec_decode_subtitle(is->subtitle_st->codec,
+ &sp->sub, &got_subtitle,
+ pkt->data, pkt->size);
+// if (len1 < 0)
+// break;
+ if (got_subtitle && sp->sub.format == 0) {
+ sp->pts = pts;
+
+ for (i = 0; i < sp->sub.num_rects; i++)
+ {
+ for (j = 0; j < sp->sub.rects[i].nb_colors; j++)
+ {
+ RGBA_IN(r, g, b, a, sp->sub.rects[i].rgba_palette + j);
+ y = RGB_TO_Y_CCIR(r, g, b);
+ u = RGB_TO_U_CCIR(r, g, b, 0);
+ v = RGB_TO_V_CCIR(r, g, b, 0);
+ YUVA_OUT(sp->sub.rects[i].rgba_palette + j, y, u, v, a);
+ }
+ }
+
+ /* now we can update the picture count */
+ if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
+ is->subpq_windex = 0;
+ SDL_LockMutex(is->subpq_mutex);
+ is->subpq_size++;
+ SDL_UnlockMutex(is->subpq_mutex);
+ }
+ av_free_packet(pkt);
+// if (step)
+// if (cur_stream)
+// stream_pause(cur_stream);
+ }
+ the_end:
+ return 0;
+}
+
+/* copy samples for viewing in editor window */
+static void update_sample_display(VideoState *is, short *samples, int samples_size)
+{
+ int size, len, channels;
+
+ channels = is->audio_st->codec->channels;
+
+ size = samples_size / sizeof(short);
+ while (size > 0) {
+ len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
+ if (len > size)
+ len = size;
+ memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
+ samples += len;
+ is->sample_array_index += len;
+ if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
+ is->sample_array_index = 0;
+ size -= len;
+ }
+}
+
+/* return the new audio buffer size (samples can be added or deleted
+ to get better sync if video or external master clock) */
+static int synchronize_audio(VideoState *is, short *samples,
+ int samples_size1, double pts)
+{
+ int n, samples_size;
+ double ref_clock;
+
+ n = 2 * is->audio_st->codec->channels;
+ samples_size = samples_size1;
+
+ /* if not master, then we try to remove or add samples to correct the clock */
+ if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
+ is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
+ double diff, avg_diff;
+ int wanted_size, min_size, max_size, nb_samples;
+
+ ref_clock = get_master_clock(is);
+ diff = get_audio_clock(is) - ref_clock;
+
+ if (diff < AV_NOSYNC_THRESHOLD) {
+ is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
+ if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
+ /* not enough measures to have a correct estimate */
+ is->audio_diff_avg_count++;
+ } else {
+ /* estimate the A-V difference */
+ avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
+
+ if (fabs(avg_diff) >= is->audio_diff_threshold) {
+ wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
+ nb_samples = samples_size / n;
+
+ min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
+ max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
+ if (wanted_size < min_size)
+ wanted_size = min_size;
+ else if (wanted_size > max_size)
+ wanted_size = max_size;
+
+ /* add or remove samples to correction the synchro */
+ if (wanted_size < samples_size) {
+ /* remove samples */
+ samples_size = wanted_size;
+ } else if (wanted_size > samples_size) {
+ uint8_t *samples_end, *q;
+ int nb;
+
+ /* add samples */
+ nb = (samples_size - wanted_size);
+ samples_end = (uint8_t *)samples + samples_size - n;
+ q = samples_end + n;
+ while (nb > 0) {
+ memcpy(q, samples_end, n);
+ q += n;
+ nb -= n;
+ }
+ samples_size = wanted_size;
+ }
+ }
+#if 0
+ printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
+ diff, avg_diff, samples_size - samples_size1,
+ is->audio_clock, is->video_clock, is->audio_diff_threshold);
+#endif
+ }
+ } else {
+ /* too big difference : may be initial PTS errors, so
+ reset A-V filter */
+ is->audio_diff_avg_count = 0;
+ is->audio_diff_cum = 0;
+ }
+ }
+
+ return samples_size;
+}
+
+/* decode one audio frame and returns its uncompressed size */
+static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, double *pts_ptr)
+{
+ AVPacket *pkt = &is->audio_pkt;
+ int n, len1, data_size;
+ double pts;
+
+ for(;;) {
+ /* NOTE: the audio packet can contain several frames */
+ while (is->audio_pkt_size > 0) {
+ len1 = avcodec_decode_audio(is->audio_st->codec,
+ (int16_t *)audio_buf, &data_size,
+ is->audio_pkt_data, is->audio_pkt_size);
+ if (len1 < 0) {
+ /* if error, we skip the frame */
+ is->audio_pkt_size = 0;
+ break;
+ }
+
+ is->audio_pkt_data += len1;
+ is->audio_pkt_size -= len1;
+ if (data_size <= 0)
+ continue;
+ /* if no pts, then compute it */
+ pts = is->audio_clock;
+ *pts_ptr = pts;
+ n = 2 * is->audio_st->codec->channels;
+ is->audio_clock += (double)data_size /
+ (double)(n * is->audio_st->codec->sample_rate);
+#if defined(DEBUG_SYNC)
+ {
+ static double last_clock;
+ printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
+ is->audio_clock - last_clock,
+ is->audio_clock, pts);
+ last_clock = is->audio_clock;
+ }
+#endif
+ return data_size;
+ }
+
+ /* free the current packet */
+ if (pkt->data)
+ av_free_packet(pkt);
+
+ if (is->paused || is->audioq.abort_request) {
+ return -1;
+ }
+
+ /* read next packet */
+ if (packet_queue_get(&is->audioq, pkt, 1) < 0)
+ return -1;
+ if(pkt->data == flush_pkt.data){
+ avcodec_flush_buffers(is->audio_st->codec);
+ continue;
+ }
+
+ is->audio_pkt_data = pkt->data;
+ is->audio_pkt_size = pkt->size;
+
+ /* if update the audio clock with the pts */
+ if (pkt->pts != AV_NOPTS_VALUE) {
+ is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
+ }
+ }
+}
+
+/* get the current audio output buffer size, in samples. With SDL, we
+ cannot have a precise information */
+static int audio_write_get_buf_size(VideoState *is)
+{
+ return is->audio_hw_buf_size - is->audio_buf_index;
+}
+
+
+/* prepare a new audio buffer */
+void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
+{
+ VideoState *is = opaque;
+ int audio_size, len1;
+ double pts;
+
+ audio_callback_time = av_gettime();
+
+ while (len > 0) {
+ if (is->audio_buf_index >= is->audio_buf_size) {
+ audio_size = audio_decode_frame(is, is->audio_buf, &pts);
+ if (audio_size < 0) {
+ /* if error, just output silence */
+ is->audio_buf_size = 1024;
+ memset(is->audio_buf, 0, is->audio_buf_size);
+ } else {
+ if (is->show_audio)
+ update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
+ audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
+ pts);
+ is->audio_buf_size = audio_size;
+ }
+ is->audio_buf_index = 0;
+ }
+ len1 = is->audio_buf_size - is->audio_buf_index;
+ if (len1 > len)
+ len1 = len;
+ memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
+ len -= len1;
+ stream += len1;
+ is->audio_buf_index += len1;
+ }
+}
+
+
+/* open a given stream. Return 0 if OK */
+static int stream_component_open(VideoState *is, int stream_index)
+{
+ AVFormatContext *ic = is->ic;
+ AVCodecContext *enc;
+ AVCodec *codec;
+ SDL_AudioSpec wanted_spec, spec;
+
+ if (stream_index < 0 || stream_index >= ic->nb_streams)
+ return -1;
+ enc = ic->streams[stream_index]->codec;
+
+ /* prepare audio output */
+ if (enc->codec_type == CODEC_TYPE_AUDIO) {
+ wanted_spec.freq = enc->sample_rate;
+ wanted_spec.format = AUDIO_S16SYS;
+ /* hack for AC3. XXX: suppress that */
+ if (enc->channels > 2)
+ enc->channels = 2;
+ wanted_spec.channels = enc->channels;
+ wanted_spec.silence = 0;
+ wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
+ wanted_spec.callback = sdl_audio_callback;
+ wanted_spec.userdata = is;
+ if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
+ fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
+ return -1;
+ }
+ is->audio_hw_buf_size = spec.size;
+ }
+
+ codec = avcodec_find_decoder(enc->codec_id);
+ enc->debug_mv = debug_mv;
+ enc->debug = debug;
+ enc->workaround_bugs = workaround_bugs;
+ enc->lowres = lowres;
+ if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
+ enc->idct_algo= idct;
+ if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
+ enc->skip_frame= skip_frame;
+ enc->skip_idct= skip_idct;
+ enc->skip_loop_filter= skip_loop_filter;
+ enc->error_resilience= error_resilience;
+ enc->error_concealment= error_concealment;
+ if (!codec ||
+ avcodec_open(enc, codec) < 0)
+ return -1;
+#if defined(HAVE_THREADS)
+ if(thread_count>1)
+ avcodec_thread_init(enc, thread_count);
+#endif
+ enc->thread_count= thread_count;
+ switch(enc->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ is->audio_stream = stream_index;
+ is->audio_st = ic->streams[stream_index];
+ is->audio_buf_size = 0;
+ is->audio_buf_index = 0;
+
+ /* init averaging filter */
+ is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
+ is->audio_diff_avg_count = 0;
+ /* since we do not have a precise anough audio fifo fullness,
+ we correct audio sync only if larger than this threshold */
+ is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
+
+ memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
+ packet_queue_init(&is->audioq);
+ SDL_PauseAudio(0);
+ break;
+ case CODEC_TYPE_VIDEO:
+ is->video_stream = stream_index;
+ is->video_st = ic->streams[stream_index];
+
+ is->frame_last_delay = 40e-3;
+ is->frame_timer = (double)av_gettime() / 1000000.0;
+ is->video_current_pts_time = av_gettime();
+
+ packet_queue_init(&is->videoq);
+ is->video_tid = SDL_CreateThread(video_thread, is);
+ break;
+ case CODEC_TYPE_SUBTITLE:
+ is->subtitle_stream = stream_index;
+ is->subtitle_st = ic->streams[stream_index];
+ packet_queue_init(&is->subtitleq);
+
+ is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static void stream_component_close(VideoState *is, int stream_index)
+{
+ AVFormatContext *ic = is->ic;
+ AVCodecContext *enc;
+
+ if (stream_index < 0 || stream_index >= ic->nb_streams)
+ return;
+ enc = ic->streams[stream_index]->codec;
+
+ switch(enc->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ packet_queue_abort(&is->audioq);
+
+ SDL_CloseAudio();
+
+ packet_queue_end(&is->audioq);
+ break;
+ case CODEC_TYPE_VIDEO:
+ packet_queue_abort(&is->videoq);
+
+ /* note: we also signal this mutex to make sure we deblock the
+ video thread in all cases */
+ SDL_LockMutex(is->pictq_mutex);
+ SDL_CondSignal(is->pictq_cond);
+ SDL_UnlockMutex(is->pictq_mutex);
+
+ SDL_WaitThread(is->video_tid, NULL);
+
+ packet_queue_end(&is->videoq);
+ break;
+ case CODEC_TYPE_SUBTITLE:
+ packet_queue_abort(&is->subtitleq);
+
+ /* note: we also signal this mutex to make sure we deblock the
+ video thread in all cases */
+ SDL_LockMutex(is->subpq_mutex);
+ is->subtitle_stream_changed = 1;
+
+ SDL_CondSignal(is->subpq_cond);
+ SDL_UnlockMutex(is->subpq_mutex);
+
+ SDL_WaitThread(is->subtitle_tid, NULL);
+
+ packet_queue_end(&is->subtitleq);
+ break;
+ default:
+ break;
+ }
+
+ avcodec_close(enc);
+ switch(enc->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ is->audio_st = NULL;
+ is->audio_stream = -1;
+ break;
+ case CODEC_TYPE_VIDEO:
+ is->video_st = NULL;
+ is->video_stream = -1;
+ break;
+ case CODEC_TYPE_SUBTITLE:
+ is->subtitle_st = NULL;
+ is->subtitle_stream = -1;
+ break;
+ default:
+ break;
+ }
+}
+
+static void dump_stream_info(const AVFormatContext *s)
+{
+ if (s->track != 0)
+ fprintf(stderr, "Track: %d\n", s->track);
+ if (s->title[0] != '\0')
+ fprintf(stderr, "Title: %s\n", s->title);
+ if (s->author[0] != '\0')
+ fprintf(stderr, "Author: %s\n", s->author);
+ if (s->copyright[0] != '\0')
+ fprintf(stderr, "Copyright: %s\n", s->copyright);
+ if (s->comment[0] != '\0')
+ fprintf(stderr, "Comment: %s\n", s->comment);
+ if (s->album[0] != '\0')
+ fprintf(stderr, "Album: %s\n", s->album);
+ if (s->year != 0)
+ fprintf(stderr, "Year: %d\n", s->year);
+ if (s->genre[0] != '\0')
+ fprintf(stderr, "Genre: %s\n", s->genre);
+}
+
+/* since we have only one decoding thread, we can use a global
+ variable instead of a thread local variable */
+static VideoState *global_video_state;
+
+static int decode_interrupt_cb(void)
+{
+ return (global_video_state && global_video_state->abort_request);
+}
+
+/* this thread gets the stream from the disk or the network */
+static int decode_thread(void *arg)
+{
+ VideoState *is = arg;
+ AVFormatContext *ic;
+ int err, i, ret, video_index, audio_index, use_play;
+ AVPacket pkt1, *pkt = &pkt1;
+ AVFormatParameters params, *ap = &params;
+
+ video_index = -1;
+ audio_index = -1;
+ is->video_stream = -1;
+ is->audio_stream = -1;
+ is->subtitle_stream = -1;
+
+ global_video_state = is;
+ url_set_interrupt_cb(decode_interrupt_cb);
+
+ memset(ap, 0, sizeof(*ap));
+ ap->initial_pause = 1; /* we force a pause when starting an RTSP
+ stream */
+
+ err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
+ if (err < 0) {
+ print_error(is->filename, err);
+ ret = -1;
+ goto fail;
+ }
+ is->ic = ic;
+#ifdef CONFIG_NETWORK
+ use_play = (ic->iformat == &rtsp_demuxer);
+#else
+ use_play = 0;
+#endif
+
+ if(genpts)
+ ic->flags |= AVFMT_FLAG_GENPTS;
+
+ if (!use_play) {
+ err = av_find_stream_info(ic);
+ if (err < 0) {
+ fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
+ ret = -1;
+ goto fail;
+ }
+ ic->pb.eof_reached= 0; //FIXME hack, ffplay maybe shouldnt use url_feof() to test for the end
+ }
+
+ /* if seeking requested, we execute it */
+ if (start_time != AV_NOPTS_VALUE) {
+ int64_t timestamp;
+
+ timestamp = start_time;
+ /* add the stream start time */
+ if (ic->start_time != AV_NOPTS_VALUE)
+ timestamp += ic->start_time;
+ ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
+ if (ret < 0) {
+ fprintf(stderr, "%s: could not seek to position %0.3f\n",
+ is->filename, (double)timestamp / AV_TIME_BASE);
+ }
+ }
+
+ /* now we can begin to play (RTSP stream only) */
+ av_read_play(ic);
+
+ if (use_play) {
+ err = av_find_stream_info(ic);
+ if (err < 0) {
+ fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
+ ret = -1;
+ goto fail;
+ }
+ }
+
+ for(i = 0; i < ic->nb_streams; i++) {
+ AVCodecContext *enc = ic->streams[i]->codec;
+ switch(enc->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ if (audio_index < 0 && !audio_disable)
+ audio_index = i;
+ break;
+ case CODEC_TYPE_VIDEO:
+ if (video_index < 0 && !video_disable)
+ video_index = i;
+ break;
+ default:
+ break;
+ }
+ }
+ if (show_status) {
+ dump_format(ic, 0, is->filename, 0);
+ dump_stream_info(ic);
+ }
+
+ /* open the streams */
+ if (audio_index >= 0) {
+ stream_component_open(is, audio_index);
+ }
+
+ if (video_index >= 0) {
+ stream_component_open(is, video_index);
+ } else {
+ if (!display_disable)
+ is->show_audio = 1;
+ }
+
+ if (is->video_stream < 0 && is->audio_stream < 0) {
+ fprintf(stderr, "%s: could not open codecs\n", is->filename);
+ ret = -1;
+ goto fail;
+ }
+
+ for(;;) {
+ if (is->abort_request)
+ break;
+#ifdef CONFIG_NETWORK
+ if (is->paused != is->last_paused) {
+ is->last_paused = is->paused;
+ if (is->paused)
+ av_read_pause(ic);
+ else
+ av_read_play(ic);
+ }
+ if (is->paused && ic->iformat == &rtsp_demuxer) {
+ /* wait 10 ms to avoid trying to get another packet */
+ /* XXX: horrible */
+ SDL_Delay(10);
+ continue;
+ }
+#endif
+ if (is->seek_req) {
+ ret = av_seek_frame(is->ic, -1, is->seek_pos, is->seek_flags);
+ if (ret < 0) {
+ fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
+ }else{
+ if (is->audio_stream >= 0) {
+ packet_queue_flush(&is->audioq);
+ packet_queue_put(&is->audioq, &flush_pkt);
+ }
+ if (is->subtitle_stream >= 0) {
+ packet_queue_flush(&is->subtitleq);
+ packet_queue_put(&is->subtitleq, &flush_pkt);
+ }
+ if (is->video_stream >= 0) {
+ packet_queue_flush(&is->videoq);
+ packet_queue_put(&is->videoq, &flush_pkt);
+ }
+ }
+ is->seek_req = 0;
+ }
+
+ /* if the queue are full, no need to read more */
+ if (is->audioq.size > MAX_AUDIOQ_SIZE ||
+ is->videoq.size > MAX_VIDEOQ_SIZE ||
+ is->subtitleq.size > MAX_SUBTITLEQ_SIZE ||
+ url_feof(&ic->pb)) {
+ /* wait 10 ms */
+ SDL_Delay(10);
+ continue;
+ }
+ ret = av_read_frame(ic, pkt);
+ if (ret < 0) {
+ if (url_ferror(&ic->pb) == 0) {
+ SDL_Delay(100); /* wait for user event */
+ continue;
+ } else
+ break;
+ }
+ if (pkt->stream_index == is->audio_stream) {
+ packet_queue_put(&is->audioq, pkt);
+ } else if (pkt->stream_index == is->video_stream) {
+ packet_queue_put(&is->videoq, pkt);
+ } else if (pkt->stream_index == is->subtitle_stream) {
+ packet_queue_put(&is->subtitleq, pkt);
+ } else {
+ av_free_packet(pkt);
+ }
+ }
+ /* wait until the end */
+ while (!is->abort_request) {
+ SDL_Delay(100);
+ }
+
+ ret = 0;
+ fail:
+ /* disable interrupting */
+ global_video_state = NULL;
+
+ /* close each stream */
+ if (is->audio_stream >= 0)
+ stream_component_close(is, is->audio_stream);
+ if (is->video_stream >= 0)
+ stream_component_close(is, is->video_stream);
+ if (is->subtitle_stream >= 0)
+ stream_component_close(is, is->subtitle_stream);
+ if (is->ic) {
+ av_close_input_file(is->ic);
+ is->ic = NULL; /* safety */
+ }
+ url_set_interrupt_cb(NULL);
+
+ if (ret != 0) {
+ SDL_Event event;
+
+ event.type = FF_QUIT_EVENT;
+ event.user.data1 = is;
+ SDL_PushEvent(&event);
+ }
+ return 0;
+}
+
+static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
+{
+ VideoState *is;
+
+ is = av_mallocz(sizeof(VideoState));
+ if (!is)
+ return NULL;
+ pstrcpy(is->filename, sizeof(is->filename), filename);
+ is->iformat = iformat;
+ if (screen) {
+ is->width = screen->w;
+ is->height = screen->h;
+ }
+ is->ytop = 0;
+ is->xleft = 0;
+
+ /* start video display */
+ is->pictq_mutex = SDL_CreateMutex();
+ is->pictq_cond = SDL_CreateCond();
+
+ is->subpq_mutex = SDL_CreateMutex();
+ is->subpq_cond = SDL_CreateCond();
+
+ /* add the refresh timer to draw the picture */
+ schedule_refresh(is, 40);
+
+ is->av_sync_type = av_sync_type;
+ is->parse_tid = SDL_CreateThread(decode_thread, is);
+ if (!is->parse_tid) {
+ av_free(is);
+ return NULL;
+ }
+ return is;
+}
+
+static void stream_close(VideoState *is)
+{
+ VideoPicture *vp;
+ int i;
+ /* XXX: use a special url_shutdown call to abort parse cleanly */
+ is->abort_request = 1;
+ SDL_WaitThread(is->parse_tid, NULL);
+
+ /* free all pictures */
+ for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
+ vp = &is->pictq[i];
+ if (vp->bmp) {
+ SDL_FreeYUVOverlay(vp->bmp);
+ vp->bmp = NULL;
+ }
+ }
+ SDL_DestroyMutex(is->pictq_mutex);
+ SDL_DestroyCond(is->pictq_cond);
+ SDL_DestroyMutex(is->subpq_mutex);
+ SDL_DestroyCond(is->subpq_cond);
+}
+
+static void stream_cycle_channel(VideoState *is, int codec_type)
+{
+ AVFormatContext *ic = is->ic;
+ int start_index, stream_index;
+ AVStream *st;
+
+ if (codec_type == CODEC_TYPE_VIDEO)
+ start_index = is->video_stream;
+ else if (codec_type == CODEC_TYPE_AUDIO)
+ start_index = is->audio_stream;
+ else
+ start_index = is->subtitle_stream;
+ if (start_index < (codec_type == CODEC_TYPE_SUBTITLE ? -1 : 0))
+ return;
+ stream_index = start_index;
+ for(;;) {
+ if (++stream_index >= is->ic->nb_streams)
+ {
+ if (codec_type == CODEC_TYPE_SUBTITLE)
+ {
+ stream_index = -1;
+ goto the_end;
+ } else
+ stream_index = 0;
+ }
+ if (stream_index == start_index)
+ return;
+ st = ic->streams[stream_index];
+ if (st->codec->codec_type == codec_type) {
+ /* check that parameters are OK */
+ switch(codec_type) {
+ case CODEC_TYPE_AUDIO:
+ if (st->codec->sample_rate != 0 &&
+ st->codec->channels != 0)
+ goto the_end;
+ break;
+ case CODEC_TYPE_VIDEO:
+ case CODEC_TYPE_SUBTITLE:
+ goto the_end;
+ default:
+ break;
+ }
+ }
+ }
+ the_end:
+ stream_component_close(is, start_index);
+ stream_component_open(is, stream_index);
+}
+
+
+static void toggle_full_screen(void)
+{
+ int w, h, flags;
+ is_full_screen = !is_full_screen;
+ if (!fs_screen_width) {
+ /* use default SDL method */
+ SDL_WM_ToggleFullScreen(screen);
+ } else {
+ /* use the recorded resolution */
+ flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
+ if (is_full_screen) {
+ w = fs_screen_width;
+ h = fs_screen_height;
+ flags |= SDL_FULLSCREEN;
+ } else {
+ w = screen_width;
+ h = screen_height;
+ flags |= SDL_RESIZABLE;
+ }
+ screen = SDL_SetVideoMode(w, h, 0, flags);
+ cur_stream->width = w;
+ cur_stream->height = h;
+ }
+}
+
+static void toggle_pause(void)
+{
+ if (cur_stream)
+ stream_pause(cur_stream);
+ step = 0;
+}
+
+static void step_to_next_frame(void)
+{
+ if (cur_stream) {
+ if (cur_stream->paused)
+ cur_stream->paused=0;
+ cur_stream->video_current_pts = get_video_clock(cur_stream);
+ }
+ step = 1;
+}
+
+static void do_exit(void)
+{
+ if (cur_stream) {
+ stream_close(cur_stream);
+ cur_stream = NULL;
+ }
+ if (show_status)
+ printf("\n");
+ SDL_Quit();
+ exit(0);
+}
+
+static void toggle_audio_display(void)
+{
+ if (cur_stream) {
+ cur_stream->show_audio = !cur_stream->show_audio;
+ }
+}
+
+/* handle an event sent by the GUI */
+static void event_loop(void)
+{
+ SDL_Event event;
+ double incr, pos, frac;
+
+ for(;;) {
+ SDL_WaitEvent(&event);
+ switch(event.type) {
+ case SDL_KEYDOWN:
+ switch(event.key.keysym.sym) {
+ case SDLK_ESCAPE:
+ case SDLK_q:
+ do_exit();
+ break;
+ case SDLK_f:
+ toggle_full_screen();
+ break;
+ case SDLK_p:
+ case SDLK_SPACE:
+ toggle_pause();
+ break;
+ case SDLK_s: //S: Step to next frame
+ step_to_next_frame();
+ break;
+ case SDLK_a:
+ if (cur_stream)
+ stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
+ break;
+ case SDLK_v:
+ if (cur_stream)
+ stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
+ break;
+ case SDLK_t:
+ if (cur_stream)
+ stream_cycle_channel(cur_stream, CODEC_TYPE_SUBTITLE);
+ break;
+ case SDLK_w:
+ toggle_audio_display();
+ break;
+ case SDLK_LEFT:
+ incr = -10.0;
+ goto do_seek;
+ case SDLK_RIGHT:
+ incr = 10.0;
+ goto do_seek;
+ case SDLK_UP:
+ incr = 60.0;
+ goto do_seek;
+ case SDLK_DOWN:
+ incr = -60.0;
+ do_seek:
+ if (cur_stream) {
+ if (seek_by_bytes) {
+ pos = url_ftell(&cur_stream->ic->pb);
+ if (cur_stream->ic->bit_rate)
+ incr *= cur_stream->ic->bit_rate / 60.0;
+ else
+ incr *= 180000.0;
+ pos += incr;
+ stream_seek(cur_stream, pos, incr);
+ } else {
+ pos = get_master_clock(cur_stream);
+ pos += incr;
+ stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), incr);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case SDL_MOUSEBUTTONDOWN:
+ if (cur_stream) {
+ int ns, hh, mm, ss;
+ int tns, thh, tmm, tss;
+ tns = cur_stream->ic->duration/1000000LL;
+ thh = tns/3600;
+ tmm = (tns%3600)/60;
+ tss = (tns%60);
+ frac = (double)event.button.x/(double)cur_stream->width;
+ ns = frac*tns;
+ hh = ns/3600;
+ mm = (ns%3600)/60;
+ ss = (ns%60);
+ fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
+ hh, mm, ss, thh, tmm, tss);
+ stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0);
+ }
+ break;
+ case SDL_VIDEORESIZE:
+ if (cur_stream) {
+ screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
+ SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
+ cur_stream->width = event.resize.w;
+ cur_stream->height = event.resize.h;
+ }
+ break;
+ case SDL_QUIT:
+ case FF_QUIT_EVENT:
+ do_exit();
+ break;
+ case FF_ALLOC_EVENT:
+ alloc_picture(event.user.data1);
+ break;
+ case FF_REFRESH_EVENT:
+ video_refresh_timer(event.user.data1);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void opt_width(const char *arg)
+{
+ screen_width = atoi(arg);
+}
+
+void opt_height(const char *arg)
+{
+ screen_height = atoi(arg);
+}
+
+static void opt_format(const char *arg)
+{
+ file_iformat = av_find_input_format(arg);
+ if (!file_iformat) {
+ fprintf(stderr, "Unknown input format: %s\n", arg);
+ exit(1);
+ }
+}
+
+#ifdef CONFIG_NETWORK
+void opt_rtp_tcp(void)
+{
+ /* only tcp protocol */
+ rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP);
+}
+#endif
+
+void opt_sync(const char *arg)
+{
+ if (!strcmp(arg, "audio"))
+ av_sync_type = AV_SYNC_AUDIO_MASTER;
+ else if (!strcmp(arg, "video"))
+ av_sync_type = AV_SYNC_VIDEO_MASTER;
+ else if (!strcmp(arg, "ext"))
+ av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
+ else
+ show_help();
+}
+
+void opt_seek(const char *arg)
+{
+ start_time = parse_date(arg, 1);
+}
+
+static void opt_debug(const char *arg)
+{
+ av_log_set_level(99);
+ debug = atoi(arg);
+}
+
+static void opt_vismv(const char *arg)
+{
+ debug_mv = atoi(arg);
+}
+
+static void opt_thread_count(const char *arg)
+{
+ thread_count= atoi(arg);
+#if !defined(HAVE_THREADS)
+ fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
+#endif
+}
+
+const OptionDef options[] = {
+ { "h", 0, {(void*)show_help}, "show help" },
+ { "x", HAS_ARG, {(void*)opt_width}, "force displayed width", "width" },
+ { "y", HAS_ARG, {(void*)opt_height}, "force displayed height", "height" },
+ { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
+ { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
+ { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
+ { "ss", HAS_ARG, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
+ { "bytes", OPT_BOOL, {(void*)&seek_by_bytes}, "seek by bytes" },
+ { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
+ { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
+ { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
+ { "debug", HAS_ARG | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
+ { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
+ { "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
+ { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
+ { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
+ { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
+ { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
+ { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
+ { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
+ { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
+ { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_resilience}, "set error detection threshold (0-4)", "threshold" },
+ { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options", "bit_mask" },
+#ifdef CONFIG_NETWORK
+ { "rtp_tcp", OPT_EXPERT, {(void*)&opt_rtp_tcp}, "force RTP/TCP protocol usage", "" },
+#endif
+ { "sync", HAS_ARG | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
+ { "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
+ { NULL, },
+};
+
+void show_help(void)
+{
+ printf("ffplay version " FFMPEG_VERSION ", Copyright (c) 2003-2006 Fabrice Bellard, et al.\n"
+ "usage: ffplay [options] input_file\n"
+ "Simple media player\n");
+ printf("\n");
+ show_help_options(options, "Main options:\n",
+ OPT_EXPERT, 0);
+ show_help_options(options, "\nAdvanced options:\n",
+ OPT_EXPERT, OPT_EXPERT);
+ printf("\nWhile playing:\n"
+ "q, ESC quit\n"
+ "f toggle full screen\n"
+ "p, SPC pause\n"
+ "a cycle audio channel\n"
+ "v cycle video channel\n"
+ "t cycle subtitle channel\n"
+ "w show audio waves\n"
+ "left/right seek backward/forward 10 seconds\n"
+ "down/up seek backward/forward 1 minute\n"
+ "mouse click seek to percentage in file corresponding to fraction of width\n"
+ );
+ exit(1);
+}
+
+void parse_arg_file(const char *filename)
+{
+ if (!strcmp(filename, "-"))
+ filename = "pipe:";
+ input_filename = filename;
+}
+
+/* Called from the main */
+int main(int argc, char **argv)
+{
+ int flags, w, h;
+
+ /* register all codecs, demux and protocols */
+ av_register_all();
+
+ #ifdef CONFIG_OS2
+ MorphToPM(); // Morph the VIO application to a PM one to be able to use Win* functions
+
+ // Make stdout and stderr unbuffered
+ setbuf( stdout, NULL );
+ setbuf( stderr, NULL );
+ #endif
+
+ parse_options(argc, argv, options);
+
+ if (!input_filename)
+ show_help();
+
+ if (display_disable) {
+ video_disable = 1;
+ }
+ flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
+#if !defined(__MINGW32__) && !defined(CONFIG_DARWIN)
+ flags |= SDL_INIT_EVENTTHREAD; /* Not supported on win32 or darwin */
+#endif
+ if (SDL_Init (flags)) {
+ fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
+ exit(1);
+ }
+
+ if (!display_disable) {
+#ifdef HAVE_SDL_VIDEO_SIZE
+ const SDL_VideoInfo *vi = SDL_GetVideoInfo();
+ fs_screen_width = vi->current_w;
+ fs_screen_height = vi->current_h;
+#endif
+ flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
+ if (is_full_screen && fs_screen_width) {
+ w = fs_screen_width;
+ h = fs_screen_height;
+ flags |= SDL_FULLSCREEN;
+ } else {
+ w = screen_width;
+ h = screen_height;
+ flags |= SDL_RESIZABLE;
+ }
+#ifndef CONFIG_DARWIN
+ screen = SDL_SetVideoMode(w, h, 0, flags);
+#else
+ /* setting bits_per_pixel = 0 or 32 causes blank video on OS X */
+ screen = SDL_SetVideoMode(w, h, 24, flags);
+#endif
+ if (!screen) {
+ fprintf(stderr, "SDL: could not set video mode - exiting\n");
+ exit(1);
+ }
+ SDL_WM_SetCaption("FFplay", "FFplay");
+ }
+
+ SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
+ SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
+ SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
+ SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
+
+ av_init_packet(&flush_pkt);
+ flush_pkt.data= "FLUSH";
+
+ cur_stream = stream_open(input_filename, file_iformat);
+
+ event_loop();
+
+ /* never returns */
+
+ return 0;
+}
diff --git a/contrib/ffmpeg/ffserver.c b/contrib/ffmpeg/ffserver.c
new file mode 100644
index 000000000..138e607ed
--- /dev/null
+++ b/contrib/ffmpeg/ffserver.c
@@ -0,0 +1,4602 @@
+/*
+ * Multiple format streaming server
+ * 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
+ */
+#define HAVE_AV_CONFIG_H
+#include "avformat.h"
+
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <errno.h>
+#include <sys/time.h>
+#undef time //needed because HAVE_AV_CONFIG_H is defined on top
+#include <time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <signal.h>
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include "version.h"
+#include "ffserver.h"
+
+/* maximum number of simultaneous HTTP connections */
+#define HTTP_MAX_CONNECTIONS 2000
+
+enum HTTPState {
+ HTTPSTATE_WAIT_REQUEST,
+ HTTPSTATE_SEND_HEADER,
+ HTTPSTATE_SEND_DATA_HEADER,
+ HTTPSTATE_SEND_DATA, /* sending TCP or UDP data */
+ HTTPSTATE_SEND_DATA_TRAILER,
+ HTTPSTATE_RECEIVE_DATA,
+ HTTPSTATE_WAIT_FEED, /* wait for data from the feed */
+ HTTPSTATE_READY,
+
+ RTSPSTATE_WAIT_REQUEST,
+ RTSPSTATE_SEND_REPLY,
+ RTSPSTATE_SEND_PACKET,
+};
+
+const char *http_state[] = {
+ "HTTP_WAIT_REQUEST",
+ "HTTP_SEND_HEADER",
+
+ "SEND_DATA_HEADER",
+ "SEND_DATA",
+ "SEND_DATA_TRAILER",
+ "RECEIVE_DATA",
+ "WAIT_FEED",
+ "READY",
+
+ "RTSP_WAIT_REQUEST",
+ "RTSP_SEND_REPLY",
+ "RTSP_SEND_PACKET",
+};
+
+#define IOBUFFER_INIT_SIZE 8192
+
+/* coef for exponential mean for bitrate estimation in statistics */
+#define AVG_COEF 0.9
+
+/* timeouts are in ms */
+#define HTTP_REQUEST_TIMEOUT (15 * 1000)
+#define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
+
+#define SYNC_TIMEOUT (10 * 1000)
+
+typedef struct {
+ int64_t count1, count2;
+ long time1, time2;
+} DataRateData;
+
+/* context associated with one connection */
+typedef struct HTTPContext {
+ enum HTTPState state;
+ int fd; /* socket file descriptor */
+ struct sockaddr_in from_addr; /* origin */
+ struct pollfd *poll_entry; /* used when polling */
+ long timeout;
+ uint8_t *buffer_ptr, *buffer_end;
+ int http_error;
+ int post;
+ struct HTTPContext *next;
+ int got_key_frame; /* stream 0 => 1, stream 1 => 2, stream 2=> 4 */
+ int64_t data_count;
+ /* feed input */
+ int feed_fd;
+ /* input format handling */
+ AVFormatContext *fmt_in;
+ long start_time; /* In milliseconds - this wraps fairly often */
+ int64_t first_pts; /* initial pts value */
+ int64_t cur_pts; /* current pts value from the stream in us */
+ int64_t cur_frame_duration; /* duration of the current frame in us */
+ int cur_frame_bytes; /* output frame size, needed to compute
+ the time at which we send each
+ packet */
+ int pts_stream_index; /* stream we choose as clock reference */
+ int64_t cur_clock; /* current clock reference value in us */
+ /* output format handling */
+ struct FFStream *stream;
+ /* -1 is invalid stream */
+ int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
+ int switch_feed_streams[MAX_STREAMS]; /* index of streams in the feed */
+ int switch_pending;
+ AVFormatContext fmt_ctx; /* instance of FFStream for one user */
+ int last_packet_sent; /* true if last data packet was sent */
+ int suppress_log;
+ DataRateData datarate;
+ int wmp_client_id;
+ char protocol[16];
+ char method[16];
+ char url[128];
+ int buffer_size;
+ uint8_t *buffer;
+ int is_packetized; /* if true, the stream is packetized */
+ int packet_stream_index; /* current stream for output in state machine */
+
+ /* RTSP state specific */
+ uint8_t *pb_buffer; /* XXX: use that in all the code */
+ ByteIOContext *pb;
+ int seq; /* RTSP sequence number */
+
+ /* RTP state specific */
+ enum RTSPProtocol rtp_protocol;
+ char session_id[32]; /* session id */
+ AVFormatContext *rtp_ctx[MAX_STREAMS];
+
+ /* RTP/UDP specific */
+ URLContext *rtp_handles[MAX_STREAMS];
+
+ /* RTP/TCP specific */
+ struct HTTPContext *rtsp_c;
+ uint8_t *packet_buffer, *packet_buffer_ptr, *packet_buffer_end;
+} HTTPContext;
+
+static AVFrame dummy_frame;
+
+/* each generated stream is described here */
+enum StreamType {
+ STREAM_TYPE_LIVE,
+ STREAM_TYPE_STATUS,
+ STREAM_TYPE_REDIRECT,
+};
+
+enum IPAddressAction {
+ IP_ALLOW = 1,
+ IP_DENY,
+};
+
+typedef struct IPAddressACL {
+ struct IPAddressACL *next;
+ enum IPAddressAction action;
+ /* These are in host order */
+ struct in_addr first;
+ struct in_addr last;
+} IPAddressACL;
+
+/* description of each stream of the ffserver.conf file */
+typedef struct FFStream {
+ enum StreamType stream_type;
+ char filename[1024]; /* stream filename */
+ struct FFStream *feed; /* feed we are using (can be null if
+ coming from file) */
+ AVFormatParameters *ap_in; /* input parameters */
+ AVInputFormat *ifmt; /* if non NULL, force input format */
+ AVOutputFormat *fmt;
+ IPAddressACL *acl;
+ int nb_streams;
+ int prebuffer; /* Number of millseconds early to start */
+ long max_time; /* Number of milliseconds to run */
+ int send_on_key;
+ AVStream *streams[MAX_STREAMS];
+ int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
+ char feed_filename[1024]; /* file name of the feed storage, or
+ input file name for a stream */
+ char author[512];
+ char title[512];
+ char copyright[512];
+ char comment[512];
+ pid_t pid; /* Of ffmpeg process */
+ time_t pid_start; /* Of ffmpeg process */
+ char **child_argv;
+ struct FFStream *next;
+ int bandwidth; /* bandwidth, in kbits/s */
+ /* RTSP options */
+ char *rtsp_option;
+ /* multicast specific */
+ int is_multicast;
+ struct in_addr multicast_ip;
+ int multicast_port; /* first port used for multicast */
+ int multicast_ttl;
+ int loop; /* if true, send the stream in loops (only meaningful if file) */
+
+ /* feed specific */
+ int feed_opened; /* true if someone is writing to the feed */
+ int is_feed; /* true if it is a feed */
+ int readonly; /* True if writing is prohibited to the file */
+ int conns_served;
+ int64_t bytes_served;
+ int64_t feed_max_size; /* maximum storage size, zero means unlimited */
+ int64_t feed_write_index; /* current write position in feed (it wraps round) */
+ int64_t feed_size; /* current size of feed */
+ struct FFStream *next_feed;
+} FFStream;
+
+typedef struct FeedData {
+ long long data_count;
+ float avg_frame_size; /* frame size averraged over last frames with exponential mean */
+} FeedData;
+
+struct sockaddr_in my_http_addr;
+struct sockaddr_in my_rtsp_addr;
+
+static char logfilename[1024];
+static HTTPContext *first_http_ctx;
+static FFStream *first_feed; /* contains only feeds */
+static FFStream *first_stream; /* contains all streams, including feeds */
+
+static void new_connection(int server_fd, int is_rtsp);
+static void close_connection(HTTPContext *c);
+
+/* HTTP handling */
+static int handle_connection(HTTPContext *c);
+static int http_parse_request(HTTPContext *c);
+static int http_send_data(HTTPContext *c);
+static void compute_stats(HTTPContext *c);
+static int open_input_stream(HTTPContext *c, const char *info);
+static int http_start_receive_data(HTTPContext *c);
+static int http_receive_data(HTTPContext *c);
+
+/* RTSP handling */
+static int rtsp_parse_request(HTTPContext *c);
+static void rtsp_cmd_describe(HTTPContext *c, const char *url);
+static void rtsp_cmd_options(HTTPContext *c, const char *url);
+static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPHeader *h);
+static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPHeader *h);
+static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPHeader *h);
+static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPHeader *h);
+
+/* SDP handling */
+static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
+ struct in_addr my_ip);
+
+/* RTP handling */
+static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
+ FFStream *stream, const char *session_id,
+ enum RTSPProtocol rtp_protocol);
+static int rtp_new_av_stream(HTTPContext *c,
+ int stream_index, struct sockaddr_in *dest_addr,
+ HTTPContext *rtsp_c);
+
+static const char *my_program_name;
+static const char *my_program_dir;
+
+static int ffserver_debug;
+static int ffserver_daemon;
+static int no_launch;
+static int need_to_start_children;
+
+static int nb_max_connections;
+static int nb_connections;
+
+static int max_bandwidth;
+static int current_bandwidth;
+
+static long cur_time; // Making this global saves on passing it around everywhere
+
+static long gettime_ms(void)
+{
+ struct timeval tv;
+
+ gettimeofday(&tv,NULL);
+ return (long long)tv.tv_sec * 1000 + (tv.tv_usec / 1000);
+}
+
+static FILE *logfile = NULL;
+
+static void __attribute__ ((format (printf, 1, 2))) http_log(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+
+ if (logfile) {
+ vfprintf(logfile, fmt, ap);
+ fflush(logfile);
+ }
+ va_end(ap);
+}
+
+static char *ctime1(char *buf2)
+{
+ time_t ti;
+ char *p;
+
+ ti = time(NULL);
+ p = ctime(&ti);
+ strcpy(buf2, p);
+ p = buf2 + strlen(p) - 1;
+ if (*p == '\n')
+ *p = '\0';
+ return buf2;
+}
+
+static void log_connection(HTTPContext *c)
+{
+ char buf2[32];
+
+ if (c->suppress_log)
+ return;
+
+ http_log("%s - - [%s] \"%s %s %s\" %d %"PRId64"\n",
+ inet_ntoa(c->from_addr.sin_addr),
+ ctime1(buf2), c->method, c->url,
+ c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
+}
+
+static void update_datarate(DataRateData *drd, int64_t count)
+{
+ if (!drd->time1 && !drd->count1) {
+ drd->time1 = drd->time2 = cur_time;
+ drd->count1 = drd->count2 = count;
+ } else {
+ if (cur_time - drd->time2 > 5000) {
+ drd->time1 = drd->time2;
+ drd->count1 = drd->count2;
+ drd->time2 = cur_time;
+ drd->count2 = count;
+ }
+ }
+}
+
+/* In bytes per second */
+static int compute_datarate(DataRateData *drd, int64_t count)
+{
+ if (cur_time == drd->time1)
+ return 0;
+
+ return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
+}
+
+
+static void start_children(FFStream *feed)
+{
+ if (no_launch)
+ return;
+
+ for (; feed; feed = feed->next) {
+ if (feed->child_argv && !feed->pid) {
+ feed->pid_start = time(0);
+
+ feed->pid = fork();
+
+ if (feed->pid < 0) {
+ fprintf(stderr, "Unable to create children\n");
+ exit(1);
+ }
+ if (!feed->pid) {
+ /* In child */
+ char pathname[1024];
+ char *slash;
+ int i;
+
+ for (i = 3; i < 256; i++) {
+ close(i);
+ }
+
+ if (!ffserver_debug) {
+ i = open("/dev/null", O_RDWR);
+ if (i)
+ dup2(i, 0);
+ dup2(i, 1);
+ dup2(i, 2);
+ if (i)
+ close(i);
+ }
+
+ pstrcpy(pathname, sizeof(pathname), my_program_name);
+
+ slash = strrchr(pathname, '/');
+ if (!slash) {
+ slash = pathname;
+ } else {
+ slash++;
+ }
+ strcpy(slash, "ffmpeg");
+
+ /* This is needed to make relative pathnames work */
+ chdir(my_program_dir);
+
+ signal(SIGPIPE, SIG_DFL);
+
+ execvp(pathname, feed->child_argv);
+
+ _exit(1);
+ }
+ }
+ }
+}
+
+/* open a listening socket */
+static int socket_open_listen(struct sockaddr_in *my_addr)
+{
+ int server_fd, tmp;
+
+ server_fd = socket(AF_INET,SOCK_STREAM,0);
+ if (server_fd < 0) {
+ perror ("socket");
+ return -1;
+ }
+
+ tmp = 1;
+ setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));
+
+ if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
+ char bindmsg[32];
+ snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", ntohs(my_addr->sin_port));
+ perror (bindmsg);
+ close(server_fd);
+ return -1;
+ }
+
+ if (listen (server_fd, 5) < 0) {
+ perror ("listen");
+ close(server_fd);
+ return -1;
+ }
+ fcntl(server_fd, F_SETFL, O_NONBLOCK);
+
+ return server_fd;
+}
+
+/* start all multicast streams */
+static void start_multicast(void)
+{
+ FFStream *stream;
+ char session_id[32];
+ HTTPContext *rtp_c;
+ struct sockaddr_in dest_addr;
+ int default_port, stream_index;
+
+ default_port = 6000;
+ for(stream = first_stream; stream != NULL; stream = stream->next) {
+ if (stream->is_multicast) {
+ /* open the RTP connection */
+ snprintf(session_id, sizeof(session_id),
+ "%08x%08x", (int)random(), (int)random());
+
+ /* choose a port if none given */
+ if (stream->multicast_port == 0) {
+ stream->multicast_port = default_port;
+ default_port += 100;
+ }
+
+ dest_addr.sin_family = AF_INET;
+ dest_addr.sin_addr = stream->multicast_ip;
+ dest_addr.sin_port = htons(stream->multicast_port);
+
+ rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
+ RTSP_PROTOCOL_RTP_UDP_MULTICAST);
+ if (!rtp_c) {
+ continue;
+ }
+ if (open_input_stream(rtp_c, "") < 0) {
+ fprintf(stderr, "Could not open input stream for stream '%s'\n",
+ stream->filename);
+ continue;
+ }
+
+ /* open each RTP stream */
+ for(stream_index = 0; stream_index < stream->nb_streams;
+ stream_index++) {
+ dest_addr.sin_port = htons(stream->multicast_port +
+ 2 * stream_index);
+ if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {
+ fprintf(stderr, "Could not open output stream '%s/streamid=%d'\n",
+ stream->filename, stream_index);
+ exit(1);
+ }
+ }
+
+ /* change state to send data */
+ rtp_c->state = HTTPSTATE_SEND_DATA;
+ }
+ }
+}
+
+/* main loop of the http server */
+static int http_server(void)
+{
+ int server_fd, ret, rtsp_server_fd, delay, delay1;
+ struct pollfd poll_table[HTTP_MAX_CONNECTIONS + 2], *poll_entry;
+ HTTPContext *c, *c_next;
+
+ server_fd = socket_open_listen(&my_http_addr);
+ if (server_fd < 0)
+ return -1;
+
+ rtsp_server_fd = socket_open_listen(&my_rtsp_addr);
+ if (rtsp_server_fd < 0)
+ return -1;
+
+ http_log("ffserver started.\n");
+
+ start_children(first_feed);
+
+ first_http_ctx = NULL;
+ nb_connections = 0;
+
+ start_multicast();
+
+ for(;;) {
+ poll_entry = poll_table;
+ poll_entry->fd = server_fd;
+ poll_entry->events = POLLIN;
+ poll_entry++;
+
+ poll_entry->fd = rtsp_server_fd;
+ poll_entry->events = POLLIN;
+ poll_entry++;
+
+ /* wait for events on each HTTP handle */
+ c = first_http_ctx;
+ delay = 1000;
+ while (c != NULL) {
+ int fd;
+ fd = c->fd;
+ switch(c->state) {
+ case HTTPSTATE_SEND_HEADER:
+ case RTSPSTATE_SEND_REPLY:
+ case RTSPSTATE_SEND_PACKET:
+ c->poll_entry = poll_entry;
+ poll_entry->fd = fd;
+ poll_entry->events = POLLOUT;
+ poll_entry++;
+ break;
+ case HTTPSTATE_SEND_DATA_HEADER:
+ case HTTPSTATE_SEND_DATA:
+ case HTTPSTATE_SEND_DATA_TRAILER:
+ if (!c->is_packetized) {
+ /* for TCP, we output as much as we can (may need to put a limit) */
+ c->poll_entry = poll_entry;
+ poll_entry->fd = fd;
+ poll_entry->events = POLLOUT;
+ poll_entry++;
+ } else {
+ /* when ffserver is doing the timing, we work by
+ looking at which packet need to be sent every
+ 10 ms */
+ delay1 = 10; /* one tick wait XXX: 10 ms assumed */
+ if (delay1 < delay)
+ delay = delay1;
+ }
+ break;
+ case HTTPSTATE_WAIT_REQUEST:
+ case HTTPSTATE_RECEIVE_DATA:
+ case HTTPSTATE_WAIT_FEED:
+ case RTSPSTATE_WAIT_REQUEST:
+ /* need to catch errors */
+ c->poll_entry = poll_entry;
+ poll_entry->fd = fd;
+ poll_entry->events = POLLIN;/* Maybe this will work */
+ poll_entry++;
+ break;
+ default:
+ c->poll_entry = NULL;
+ break;
+ }
+ c = c->next;
+ }
+
+ /* wait for an event on one connection. We poll at least every
+ second to handle timeouts */
+ do {
+ ret = poll(poll_table, poll_entry - poll_table, delay);
+ if (ret < 0 && errno != EAGAIN && errno != EINTR)
+ return -1;
+ } while (ret <= 0);
+
+ cur_time = gettime_ms();
+
+ if (need_to_start_children) {
+ need_to_start_children = 0;
+ start_children(first_feed);
+ }
+
+ /* now handle the events */
+ for(c = first_http_ctx; c != NULL; c = c_next) {
+ c_next = c->next;
+ if (handle_connection(c) < 0) {
+ /* close and free the connection */
+ log_connection(c);
+ close_connection(c);
+ }
+ }
+
+ poll_entry = poll_table;
+ /* new HTTP connection request ? */
+ if (poll_entry->revents & POLLIN) {
+ new_connection(server_fd, 0);
+ }
+ poll_entry++;
+ /* new RTSP connection request ? */
+ if (poll_entry->revents & POLLIN) {
+ new_connection(rtsp_server_fd, 1);
+ }
+ }
+}
+
+/* start waiting for a new HTTP/RTSP request */
+static void start_wait_request(HTTPContext *c, int is_rtsp)
+{
+ c->buffer_ptr = c->buffer;
+ c->buffer_end = c->buffer + c->buffer_size - 1; /* leave room for '\0' */
+
+ if (is_rtsp) {
+ c->timeout = cur_time + RTSP_REQUEST_TIMEOUT;
+ c->state = RTSPSTATE_WAIT_REQUEST;
+ } else {
+ c->timeout = cur_time + HTTP_REQUEST_TIMEOUT;
+ c->state = HTTPSTATE_WAIT_REQUEST;
+ }
+}
+
+static void new_connection(int server_fd, int is_rtsp)
+{
+ struct sockaddr_in from_addr;
+ int fd, len;
+ HTTPContext *c = NULL;
+
+ len = sizeof(from_addr);
+ fd = accept(server_fd, (struct sockaddr *)&from_addr,
+ &len);
+ if (fd < 0)
+ return;
+ fcntl(fd, F_SETFL, O_NONBLOCK);
+
+ /* XXX: should output a warning page when coming
+ close to the connection limit */
+ if (nb_connections >= nb_max_connections)
+ goto fail;
+
+ /* add a new connection */
+ c = av_mallocz(sizeof(HTTPContext));
+ if (!c)
+ goto fail;
+
+ c->fd = fd;
+ c->poll_entry = NULL;
+ c->from_addr = from_addr;
+ c->buffer_size = IOBUFFER_INIT_SIZE;
+ c->buffer = av_malloc(c->buffer_size);
+ if (!c->buffer)
+ goto fail;
+
+ c->next = first_http_ctx;
+ first_http_ctx = c;
+ nb_connections++;
+
+ start_wait_request(c, is_rtsp);
+
+ return;
+
+ fail:
+ if (c) {
+ av_free(c->buffer);
+ av_free(c);
+ }
+ close(fd);
+}
+
+static void close_connection(HTTPContext *c)
+{
+ HTTPContext **cp, *c1;
+ int i, nb_streams;
+ AVFormatContext *ctx;
+ URLContext *h;
+ AVStream *st;
+
+ /* remove connection from list */
+ cp = &first_http_ctx;
+ while ((*cp) != NULL) {
+ c1 = *cp;
+ if (c1 == c) {
+ *cp = c->next;
+ } else {
+ cp = &c1->next;
+ }
+ }
+
+ /* remove references, if any (XXX: do it faster) */
+ for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
+ if (c1->rtsp_c == c)
+ c1->rtsp_c = NULL;
+ }
+
+ /* remove connection associated resources */
+ if (c->fd >= 0)
+ close(c->fd);
+ if (c->fmt_in) {
+ /* close each frame parser */
+ for(i=0;i<c->fmt_in->nb_streams;i++) {
+ st = c->fmt_in->streams[i];
+ if (st->codec->codec) {
+ avcodec_close(st->codec);
+ }
+ }
+ av_close_input_file(c->fmt_in);
+ }
+
+ /* free RTP output streams if any */
+ nb_streams = 0;
+ if (c->stream)
+ nb_streams = c->stream->nb_streams;
+
+ for(i=0;i<nb_streams;i++) {
+ ctx = c->rtp_ctx[i];
+ if (ctx) {
+ av_write_trailer(ctx);
+ av_free(ctx);
+ }
+ h = c->rtp_handles[i];
+ if (h) {
+ url_close(h);
+ }
+ }
+
+ ctx = &c->fmt_ctx;
+
+ if (!c->last_packet_sent) {
+ if (ctx->oformat) {
+ /* prepare header */
+ if (url_open_dyn_buf(&ctx->pb) >= 0) {
+ av_write_trailer(ctx);
+ url_close_dyn_buf(&ctx->pb, &c->pb_buffer);
+ }
+ }
+ }
+
+ for(i=0; i<ctx->nb_streams; i++)
+ av_free(ctx->streams[i]) ;
+
+ if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
+ current_bandwidth -= c->stream->bandwidth;
+ av_freep(&c->pb_buffer);
+ av_freep(&c->packet_buffer);
+ av_free(c->buffer);
+ av_free(c);
+ nb_connections--;
+}
+
+static int handle_connection(HTTPContext *c)
+{
+ int len, ret;
+
+ switch(c->state) {
+ case HTTPSTATE_WAIT_REQUEST:
+ case RTSPSTATE_WAIT_REQUEST:
+ /* timeout ? */
+ if ((c->timeout - cur_time) < 0)
+ return -1;
+ if (c->poll_entry->revents & (POLLERR | POLLHUP))
+ return -1;
+
+ /* no need to read if no events */
+ if (!(c->poll_entry->revents & POLLIN))
+ return 0;
+ /* read the data */
+ read_loop:
+ len = read(c->fd, c->buffer_ptr, 1);
+ if (len < 0) {
+ if (errno != EAGAIN && errno != EINTR)
+ return -1;
+ } else if (len == 0) {
+ return -1;
+ } else {
+ /* search for end of request. */
+ uint8_t *ptr;
+ c->buffer_ptr += len;
+ ptr = c->buffer_ptr;
+ if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
+ (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
+ /* request found : parse it and reply */
+ if (c->state == HTTPSTATE_WAIT_REQUEST) {
+ ret = http_parse_request(c);
+ } else {
+ ret = rtsp_parse_request(c);
+ }
+ if (ret < 0)
+ return -1;
+ } else if (ptr >= c->buffer_end) {
+ /* request too long: cannot do anything */
+ return -1;
+ } else goto read_loop;
+ }
+ break;
+
+ case HTTPSTATE_SEND_HEADER:
+ if (c->poll_entry->revents & (POLLERR | POLLHUP))
+ return -1;
+
+ /* no need to write if no events */
+ if (!(c->poll_entry->revents & POLLOUT))
+ return 0;
+ len = write(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr);
+ if (len < 0) {
+ if (errno != EAGAIN && errno != EINTR) {
+ /* error : close connection */
+ av_freep(&c->pb_buffer);
+ return -1;
+ }
+ } else {
+ c->buffer_ptr += len;
+ if (c->stream)
+ c->stream->bytes_served += len;
+ c->data_count += len;
+ if (c->buffer_ptr >= c->buffer_end) {
+ av_freep(&c->pb_buffer);
+ /* if error, exit */
+ if (c->http_error) {
+ return -1;
+ }
+ /* all the buffer was sent : synchronize to the incoming stream */
+ c->state = HTTPSTATE_SEND_DATA_HEADER;
+ c->buffer_ptr = c->buffer_end = c->buffer;
+ }
+ }
+ break;
+
+ case HTTPSTATE_SEND_DATA:
+ case HTTPSTATE_SEND_DATA_HEADER:
+ case HTTPSTATE_SEND_DATA_TRAILER:
+ /* for packetized output, we consider we can always write (the
+ input streams sets the speed). It may be better to verify
+ that we do not rely too much on the kernel queues */
+ if (!c->is_packetized) {
+ if (c->poll_entry->revents & (POLLERR | POLLHUP))
+ return -1;
+
+ /* no need to read if no events */
+ if (!(c->poll_entry->revents & POLLOUT))
+ return 0;
+ }
+ if (http_send_data(c) < 0)
+ return -1;
+ break;
+ case HTTPSTATE_RECEIVE_DATA:
+ /* no need to read if no events */
+ if (c->poll_entry->revents & (POLLERR | POLLHUP))
+ return -1;
+ if (!(c->poll_entry->revents & POLLIN))
+ return 0;
+ if (http_receive_data(c) < 0)
+ return -1;
+ break;
+ case HTTPSTATE_WAIT_FEED:
+ /* no need to read if no events */
+ if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
+ return -1;
+
+ /* nothing to do, we'll be waken up by incoming feed packets */
+ break;
+
+ case RTSPSTATE_SEND_REPLY:
+ if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
+ av_freep(&c->pb_buffer);
+ return -1;
+ }
+ /* no need to write if no events */
+ if (!(c->poll_entry->revents & POLLOUT))
+ return 0;
+ len = write(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr);
+ if (len < 0) {
+ if (errno != EAGAIN && errno != EINTR) {
+ /* error : close connection */
+ av_freep(&c->pb_buffer);
+ return -1;
+ }
+ } else {
+ c->buffer_ptr += len;
+ c->data_count += len;
+ if (c->buffer_ptr >= c->buffer_end) {
+ /* all the buffer was sent : wait for a new request */
+ av_freep(&c->pb_buffer);
+ start_wait_request(c, 1);
+ }
+ }
+ break;
+ case RTSPSTATE_SEND_PACKET:
+ if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
+ av_freep(&c->packet_buffer);
+ return -1;
+ }
+ /* no need to write if no events */
+ if (!(c->poll_entry->revents & POLLOUT))
+ return 0;
+ len = write(c->fd, c->packet_buffer_ptr,
+ c->packet_buffer_end - c->packet_buffer_ptr);
+ if (len < 0) {
+ if (errno != EAGAIN && errno != EINTR) {
+ /* error : close connection */
+ av_freep(&c->packet_buffer);
+ return -1;
+ }
+ } else {
+ c->packet_buffer_ptr += len;
+ if (c->packet_buffer_ptr >= c->packet_buffer_end) {
+ /* all the buffer was sent : wait for a new request */
+ av_freep(&c->packet_buffer);
+ c->state = RTSPSTATE_WAIT_REQUEST;
+ }
+ }
+ break;
+ case HTTPSTATE_READY:
+ /* nothing to do */
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int extract_rates(char *rates, int ratelen, const char *request)
+{
+ const char *p;
+
+ for (p = request; *p && *p != '\r' && *p != '\n'; ) {
+ if (strncasecmp(p, "Pragma:", 7) == 0) {
+ const char *q = p + 7;
+
+ while (*q && *q != '\n' && isspace(*q))
+ q++;
+
+ if (strncasecmp(q, "stream-switch-entry=", 20) == 0) {
+ int stream_no;
+ int rate_no;
+
+ q += 20;
+
+ memset(rates, 0xff, ratelen);
+
+ while (1) {
+ while (*q && *q != '\n' && *q != ':')
+ q++;
+
+ if (sscanf(q, ":%d:%d", &stream_no, &rate_no) != 2) {
+ break;
+ }
+ stream_no--;
+ if (stream_no < ratelen && stream_no >= 0) {
+ rates[stream_no] = rate_no;
+ }
+
+ while (*q && *q != '\n' && !isspace(*q))
+ q++;
+ }
+
+ return 1;
+ }
+ }
+ p = strchr(p, '\n');
+ if (!p)
+ break;
+
+ p++;
+ }
+
+ return 0;
+}
+
+static int find_stream_in_feed(FFStream *feed, AVCodecContext *codec, int bit_rate)
+{
+ int i;
+ int best_bitrate = 100000000;
+ int best = -1;
+
+ for (i = 0; i < feed->nb_streams; i++) {
+ AVCodecContext *feed_codec = feed->streams[i]->codec;
+
+ if (feed_codec->codec_id != codec->codec_id ||
+ feed_codec->sample_rate != codec->sample_rate ||
+ feed_codec->width != codec->width ||
+ feed_codec->height != codec->height) {
+ continue;
+ }
+
+ /* Potential stream */
+
+ /* We want the fastest stream less than bit_rate, or the slowest
+ * faster than bit_rate
+ */
+
+ if (feed_codec->bit_rate <= bit_rate) {
+ if (best_bitrate > bit_rate || feed_codec->bit_rate > best_bitrate) {
+ best_bitrate = feed_codec->bit_rate;
+ best = i;
+ }
+ } else {
+ if (feed_codec->bit_rate < best_bitrate) {
+ best_bitrate = feed_codec->bit_rate;
+ best = i;
+ }
+ }
+ }
+
+ return best;
+}
+
+static int modify_current_stream(HTTPContext *c, char *rates)
+{
+ int i;
+ FFStream *req = c->stream;
+ int action_required = 0;
+
+ /* Not much we can do for a feed */
+ if (!req->feed)
+ return 0;
+
+ for (i = 0; i < req->nb_streams; i++) {
+ AVCodecContext *codec = req->streams[i]->codec;
+
+ switch(rates[i]) {
+ case 0:
+ c->switch_feed_streams[i] = req->feed_streams[i];
+ break;
+ case 1:
+ c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 2);
+ break;
+ case 2:
+ /* Wants off or slow */
+ c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 4);
+#ifdef WANTS_OFF
+ /* This doesn't work well when it turns off the only stream! */
+ c->switch_feed_streams[i] = -2;
+ c->feed_streams[i] = -2;
+#endif
+ break;
+ }
+
+ if (c->switch_feed_streams[i] >= 0 && c->switch_feed_streams[i] != c->feed_streams[i])
+ action_required = 1;
+ }
+
+ return action_required;
+}
+
+
+static void do_switch_stream(HTTPContext *c, int i)
+{
+ if (c->switch_feed_streams[i] >= 0) {
+#ifdef PHILIP
+ c->feed_streams[i] = c->switch_feed_streams[i];
+#endif
+
+ /* Now update the stream */
+ }
+ c->switch_feed_streams[i] = -1;
+}
+
+/* XXX: factorize in utils.c ? */
+/* XXX: take care with different space meaning */
+static void skip_spaces(const char **pp)
+{
+ const char *p;
+ p = *pp;
+ while (*p == ' ' || *p == '\t')
+ p++;
+ *pp = p;
+}
+
+static void get_word(char *buf, int buf_size, const char **pp)
+{
+ const char *p;
+ char *q;
+
+ p = *pp;
+ skip_spaces(&p);
+ q = buf;
+ while (!isspace(*p) && *p != '\0') {
+ if ((q - buf) < buf_size - 1)
+ *q++ = *p;
+ p++;
+ }
+ if (buf_size > 0)
+ *q = '\0';
+ *pp = p;
+}
+
+static int validate_acl(FFStream *stream, HTTPContext *c)
+{
+ enum IPAddressAction last_action = IP_DENY;
+ IPAddressACL *acl;
+ struct in_addr *src = &c->from_addr.sin_addr;
+ unsigned long src_addr = ntohl(src->s_addr);
+
+ for (acl = stream->acl; acl; acl = acl->next) {
+ if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr) {
+ return (acl->action == IP_ALLOW) ? 1 : 0;
+ }
+ last_action = acl->action;
+ }
+
+ /* Nothing matched, so return not the last action */
+ return (last_action == IP_DENY) ? 1 : 0;
+}
+
+/* compute the real filename of a file by matching it without its
+ extensions to all the stream filenames */
+static void compute_real_filename(char *filename, int max_size)
+{
+ char file1[1024];
+ char file2[1024];
+ char *p;
+ FFStream *stream;
+
+ /* compute filename by matching without the file extensions */
+ pstrcpy(file1, sizeof(file1), filename);
+ p = strrchr(file1, '.');
+ if (p)
+ *p = '\0';
+ for(stream = first_stream; stream != NULL; stream = stream->next) {
+ pstrcpy(file2, sizeof(file2), stream->filename);
+ p = strrchr(file2, '.');
+ if (p)
+ *p = '\0';
+ if (!strcmp(file1, file2)) {
+ pstrcpy(filename, max_size, stream->filename);
+ break;
+ }
+ }
+}
+
+enum RedirType {
+ REDIR_NONE,
+ REDIR_ASX,
+ REDIR_RAM,
+ REDIR_ASF,
+ REDIR_RTSP,
+ REDIR_SDP,
+};
+
+/* parse http request and prepare header */
+static int http_parse_request(HTTPContext *c)
+{
+ char *p;
+ enum RedirType redir_type;
+ char cmd[32];
+ char info[1024], *filename;
+ char url[1024], *q;
+ char protocol[32];
+ char msg[1024];
+ const char *mime_type;
+ FFStream *stream;
+ int i;
+ char ratebuf[32];
+ char *useragent = 0;
+
+ p = c->buffer;
+ get_word(cmd, sizeof(cmd), (const char **)&p);
+ pstrcpy(c->method, sizeof(c->method), cmd);
+
+ if (!strcmp(cmd, "GET"))
+ c->post = 0;
+ else if (!strcmp(cmd, "POST"))
+ c->post = 1;
+ else
+ return -1;
+
+ get_word(url, sizeof(url), (const char **)&p);
+ pstrcpy(c->url, sizeof(c->url), url);
+
+ get_word(protocol, sizeof(protocol), (const char **)&p);
+ if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
+ return -1;
+
+ pstrcpy(c->protocol, sizeof(c->protocol), protocol);
+
+ if (ffserver_debug)
+ http_log("New connection: %s %s\n", cmd, url);
+
+ /* find the filename and the optional info string in the request */
+ p = url;
+ if (*p == '/')
+ p++;
+ filename = p;
+ p = strchr(p, '?');
+ if (p) {
+ pstrcpy(info, sizeof(info), p);
+ *p = '\0';
+ } else {
+ info[0] = '\0';
+ }
+
+ for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
+ if (strncasecmp(p, "User-Agent:", 11) == 0) {
+ useragent = p + 11;
+ if (*useragent && *useragent != '\n' && isspace(*useragent))
+ useragent++;
+ break;
+ }
+ p = strchr(p, '\n');
+ if (!p)
+ break;
+
+ p++;
+ }
+
+ redir_type = REDIR_NONE;
+ if (match_ext(filename, "asx")) {
+ redir_type = REDIR_ASX;
+ filename[strlen(filename)-1] = 'f';
+ } else if (match_ext(filename, "asf") &&
+ (!useragent || strncasecmp(useragent, "NSPlayer", 8) != 0)) {
+ /* if this isn't WMP or lookalike, return the redirector file */
+ redir_type = REDIR_ASF;
+ } else if (match_ext(filename, "rpm,ram")) {
+ redir_type = REDIR_RAM;
+ strcpy(filename + strlen(filename)-2, "m");
+ } else if (match_ext(filename, "rtsp")) {
+ redir_type = REDIR_RTSP;
+ compute_real_filename(filename, sizeof(url) - 1);
+ } else if (match_ext(filename, "sdp")) {
+ redir_type = REDIR_SDP;
+ compute_real_filename(filename, sizeof(url) - 1);
+ }
+
+ stream = first_stream;
+ while (stream != NULL) {
+ if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
+ break;
+ stream = stream->next;
+ }
+ if (stream == NULL) {
+ snprintf(msg, sizeof(msg), "File '%s' not found", url);
+ goto send_error;
+ }
+
+ c->stream = stream;
+ memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams));
+ memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams));
+
+ if (stream->stream_type == STREAM_TYPE_REDIRECT) {
+ c->http_error = 301;
+ q = c->buffer;
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 301 Moved\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Location: %s\r\n", stream->feed_filename);
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: text/html\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<html><head><title>Moved</title></head><body>\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "You should be <a href=\"%s\">redirected</a>.\r\n", stream->feed_filename);
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</body></html>\r\n");
+
+ /* prepare output buffer */
+ c->buffer_ptr = c->buffer;
+ c->buffer_end = q;
+ c->state = HTTPSTATE_SEND_HEADER;
+ return 0;
+ }
+
+ /* If this is WMP, get the rate information */
+ if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
+ if (modify_current_stream(c, ratebuf)) {
+ for (i = 0; i < sizeof(c->feed_streams) / sizeof(c->feed_streams[0]); i++) {
+ if (c->switch_feed_streams[i] >= 0)
+ do_switch_stream(c, i);
+ }
+ }
+ }
+
+ if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE) {
+ current_bandwidth += stream->bandwidth;
+ }
+
+ if (c->post == 0 && max_bandwidth < current_bandwidth) {
+ c->http_error = 200;
+ q = c->buffer;
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 Server too busy\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: text/html\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<html><head><title>Too busy</title></head><body>\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<p>The server is too busy to serve your request at this time.</p>\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<p>The bandwidth being served (including your stream) is %dkbit/sec, and this exceeds the limit of %dkbit/sec.</p>\r\n",
+ current_bandwidth, max_bandwidth);
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</body></html>\r\n");
+
+ /* prepare output buffer */
+ c->buffer_ptr = c->buffer;
+ c->buffer_end = q;
+ c->state = HTTPSTATE_SEND_HEADER;
+ return 0;
+ }
+
+ if (redir_type != REDIR_NONE) {
+ char *hostinfo = 0;
+
+ for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
+ if (strncasecmp(p, "Host:", 5) == 0) {
+ hostinfo = p + 5;
+ break;
+ }
+ p = strchr(p, '\n');
+ if (!p)
+ break;
+
+ p++;
+ }
+
+ if (hostinfo) {
+ char *eoh;
+ char hostbuf[260];
+
+ while (isspace(*hostinfo))
+ hostinfo++;
+
+ eoh = strchr(hostinfo, '\n');
+ if (eoh) {
+ if (eoh[-1] == '\r')
+ eoh--;
+
+ if (eoh - hostinfo < sizeof(hostbuf) - 1) {
+ memcpy(hostbuf, hostinfo, eoh - hostinfo);
+ hostbuf[eoh - hostinfo] = 0;
+
+ c->http_error = 200;
+ q = c->buffer;
+ switch(redir_type) {
+ case REDIR_ASX:
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 ASX Follows\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: video/x-ms-asf\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<ASX Version=\"3\">\r\n");
+ //q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<!-- Autogenerated by ffserver -->\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n",
+ hostbuf, filename, info);
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</ASX>\r\n");
+ break;
+ case REDIR_RAM:
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 RAM Follows\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: audio/x-pn-realaudio\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "# Autogenerated by ffserver\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "http://%s/%s%s\r\n",
+ hostbuf, filename, info);
+ break;
+ case REDIR_ASF:
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 ASF Redirect follows\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: video/x-ms-asf\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "[Reference]\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Ref1=http://%s/%s%s\r\n",
+ hostbuf, filename, info);
+ break;
+ case REDIR_RTSP:
+ {
+ char hostname[256], *p;
+ /* extract only hostname */
+ pstrcpy(hostname, sizeof(hostname), hostbuf);
+ p = strrchr(hostname, ':');
+ if (p)
+ *p = '\0';
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 RTSP Redirect follows\r\n");
+ /* XXX: incorrect mime type ? */
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: application/x-rtsp\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "rtsp://%s:%d/%s\r\n",
+ hostname, ntohs(my_rtsp_addr.sin_port),
+ filename);
+ }
+ break;
+ case REDIR_SDP:
+ {
+ uint8_t *sdp_data;
+ int sdp_data_size, len;
+ struct sockaddr_in my_addr;
+
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: application/sdp\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
+
+ len = sizeof(my_addr);
+ getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
+
+ /* XXX: should use a dynamic buffer */
+ sdp_data_size = prepare_sdp_description(stream,
+ &sdp_data,
+ my_addr.sin_addr);
+ if (sdp_data_size > 0) {
+ memcpy(q, sdp_data, sdp_data_size);
+ q += sdp_data_size;
+ *q = '\0';
+ av_free(sdp_data);
+ }
+ }
+ break;
+ default:
+ av_abort();
+ break;
+ }
+
+ /* prepare output buffer */
+ c->buffer_ptr = c->buffer;
+ c->buffer_end = q;
+ c->state = HTTPSTATE_SEND_HEADER;
+ return 0;
+ }
+ }
+ }
+
+ snprintf(msg, sizeof(msg), "ASX/RAM file not handled");
+ goto send_error;
+ }
+
+ stream->conns_served++;
+
+ /* XXX: add there authenticate and IP match */
+
+ if (c->post) {
+ /* if post, it means a feed is being sent */
+ if (!stream->is_feed) {
+ /* However it might be a status report from WMP! Lets log the data
+ * as it might come in handy one day
+ */
+ char *logline = 0;
+ int client_id = 0;
+
+ for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
+ if (strncasecmp(p, "Pragma: log-line=", 17) == 0) {
+ logline = p;
+ break;
+ }
+ if (strncasecmp(p, "Pragma: client-id=", 18) == 0) {
+ client_id = strtol(p + 18, 0, 10);
+ }
+ p = strchr(p, '\n');
+ if (!p)
+ break;
+
+ p++;
+ }
+
+ if (logline) {
+ char *eol = strchr(logline, '\n');
+
+ logline += 17;
+
+ if (eol) {
+ if (eol[-1] == '\r')
+ eol--;
+ http_log("%.*s\n", (int) (eol - logline), logline);
+ c->suppress_log = 1;
+ }
+ }
+
+#ifdef DEBUG_WMP
+ http_log("\nGot request:\n%s\n", c->buffer);
+#endif
+
+ if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
+ HTTPContext *wmpc;
+
+ /* Now we have to find the client_id */
+ for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) {
+ if (wmpc->wmp_client_id == client_id)
+ break;
+ }
+
+ if (wmpc) {
+ if (modify_current_stream(wmpc, ratebuf)) {
+ wmpc->switch_pending = 1;
+ }
+ }
+ }
+
+ snprintf(msg, sizeof(msg), "POST command not handled");
+ c->stream = 0;
+ goto send_error;
+ }
+ if (http_start_receive_data(c) < 0) {
+ snprintf(msg, sizeof(msg), "could not open feed");
+ goto send_error;
+ }
+ c->http_error = 0;
+ c->state = HTTPSTATE_RECEIVE_DATA;
+ return 0;
+ }
+
+#ifdef DEBUG_WMP
+ if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0) {
+ http_log("\nGot request:\n%s\n", c->buffer);
+ }
+#endif
+
+ if (c->stream->stream_type == STREAM_TYPE_STATUS)
+ goto send_stats;
+
+ /* open input stream */
+ if (open_input_stream(c, info) < 0) {
+ snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url);
+ goto send_error;
+ }
+
+ /* prepare http header */
+ q = c->buffer;
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n");
+ mime_type = c->stream->fmt->mime_type;
+ if (!mime_type)
+ mime_type = "application/x-octet_stream";
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Pragma: no-cache\r\n");
+
+ /* for asf, we need extra headers */
+ if (!strcmp(c->stream->fmt->name,"asf_stream")) {
+ /* Need to allocate a client id */
+
+ c->wmp_client_id = random() & 0x7fffffff;
+
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Server: Cougar 4.1.0.3923\r\nCache-Control: no-cache\r\nPragma: client-id=%d\r\nPragma: features=\"broadcast\"\r\n", c->wmp_client_id);
+ }
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-Type: %s\r\n", mime_type);
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
+
+ /* prepare output buffer */
+ c->http_error = 0;
+ c->buffer_ptr = c->buffer;
+ c->buffer_end = q;
+ c->state = HTTPSTATE_SEND_HEADER;
+ return 0;
+ send_error:
+ c->http_error = 404;
+ q = c->buffer;
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 404 Not Found\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: %s\r\n", "text/html");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<HTML>\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<HEAD><TITLE>404 Not Found</TITLE></HEAD>\n");
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<BODY>%s</BODY>\n", msg);
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</HTML>\n");
+
+ /* prepare output buffer */
+ c->buffer_ptr = c->buffer;
+ c->buffer_end = q;
+ c->state = HTTPSTATE_SEND_HEADER;
+ return 0;
+ send_stats:
+ compute_stats(c);
+ c->http_error = 200; /* horrible : we use this value to avoid
+ going to the send data state */
+ c->state = HTTPSTATE_SEND_HEADER;
+ return 0;
+}
+
+static void fmt_bytecount(ByteIOContext *pb, int64_t count)
+{
+ static const char *suffix = " kMGTP";
+ const char *s;
+
+ for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++) {
+ }
+
+ url_fprintf(pb, "%"PRId64"%c", count, *s);
+}
+
+static void compute_stats(HTTPContext *c)
+{
+ HTTPContext *c1;
+ FFStream *stream;
+ char *p;
+ time_t ti;
+ int i, len;
+ ByteIOContext pb1, *pb = &pb1;
+
+ if (url_open_dyn_buf(pb) < 0) {
+ /* XXX: return an error ? */
+ c->buffer_ptr = c->buffer;
+ c->buffer_end = c->buffer;
+ return;
+ }
+
+ url_fprintf(pb, "HTTP/1.0 200 OK\r\n");
+ url_fprintf(pb, "Content-type: %s\r\n", "text/html");
+ url_fprintf(pb, "Pragma: no-cache\r\n");
+ url_fprintf(pb, "\r\n");
+
+ url_fprintf(pb, "<HEAD><TITLE>FFServer Status</TITLE>\n");
+ if (c->stream->feed_filename) {
+ url_fprintf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
+ }
+ url_fprintf(pb, "</HEAD>\n<BODY>");
+ url_fprintf(pb, "<H1>FFServer Status</H1>\n");
+ /* format status */
+ url_fprintf(pb, "<H2>Available Streams</H2>\n");
+ url_fprintf(pb, "<TABLE cellspacing=0 cellpadding=4>\n");
+ url_fprintf(pb, "<TR><Th valign=top>Path<th align=left>Served<br>Conns<Th><br>bytes<Th valign=top>Format<Th>Bit rate<br>kbits/s<Th align=left>Video<br>kbits/s<th><br>Codec<Th align=left>Audio<br>kbits/s<th><br>Codec<Th align=left valign=top>Feed\n");
+ stream = first_stream;
+ while (stream != NULL) {
+ char sfilename[1024];
+ char *eosf;
+
+ if (stream->feed != stream) {
+ pstrcpy(sfilename, sizeof(sfilename) - 10, stream->filename);
+ eosf = sfilename + strlen(sfilename);
+ if (eosf - sfilename >= 4) {
+ if (strcmp(eosf - 4, ".asf") == 0) {
+ strcpy(eosf - 4, ".asx");
+ } else if (strcmp(eosf - 3, ".rm") == 0) {
+ strcpy(eosf - 3, ".ram");
+ } else if (stream->fmt == &rtp_muxer) {
+ /* generate a sample RTSP director if
+ unicast. Generate an SDP redirector if
+ multicast */
+ eosf = strrchr(sfilename, '.');
+ if (!eosf)
+ eosf = sfilename + strlen(sfilename);
+ if (stream->is_multicast)
+ strcpy(eosf, ".sdp");
+ else
+ strcpy(eosf, ".rtsp");
+ }
+ }
+
+ url_fprintf(pb, "<TR><TD><A HREF=\"/%s\">%s</A> ",
+ sfilename, stream->filename);
+ url_fprintf(pb, "<td align=right> %d <td align=right> ",
+ stream->conns_served);
+ fmt_bytecount(pb, stream->bytes_served);
+ switch(stream->stream_type) {
+ case STREAM_TYPE_LIVE:
+ {
+ int audio_bit_rate = 0;
+ int video_bit_rate = 0;
+ const char *audio_codec_name = "";
+ const char *video_codec_name = "";
+ const char *audio_codec_name_extra = "";
+ const char *video_codec_name_extra = "";
+
+ for(i=0;i<stream->nb_streams;i++) {
+ AVStream *st = stream->streams[i];
+ AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
+ switch(st->codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ audio_bit_rate += st->codec->bit_rate;
+ if (codec) {
+ if (*audio_codec_name)
+ audio_codec_name_extra = "...";
+ audio_codec_name = codec->name;
+ }
+ break;
+ case CODEC_TYPE_VIDEO:
+ video_bit_rate += st->codec->bit_rate;
+ if (codec) {
+ if (*video_codec_name)
+ video_codec_name_extra = "...";
+ video_codec_name = codec->name;
+ }
+ break;
+ case CODEC_TYPE_DATA:
+ video_bit_rate += st->codec->bit_rate;
+ break;
+ default:
+ av_abort();
+ }
+ }
+ url_fprintf(pb, "<TD align=center> %s <TD align=right> %d <TD align=right> %d <TD> %s %s <TD align=right> %d <TD> %s %s",
+ stream->fmt->name,
+ stream->bandwidth,
+ video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
+ audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
+ if (stream->feed) {
+ url_fprintf(pb, "<TD>%s", stream->feed->filename);
+ } else {
+ url_fprintf(pb, "<TD>%s", stream->feed_filename);
+ }
+ url_fprintf(pb, "\n");
+ }
+ break;
+ default:
+ url_fprintf(pb, "<TD align=center> - <TD align=right> - <TD align=right> - <td><td align=right> - <TD>\n");
+ break;
+ }
+ }
+ stream = stream->next;
+ }
+ url_fprintf(pb, "</TABLE>\n");
+
+ stream = first_stream;
+ while (stream != NULL) {
+ if (stream->feed == stream) {
+ url_fprintf(pb, "<h2>Feed %s</h2>", stream->filename);
+ if (stream->pid) {
+ url_fprintf(pb, "Running as pid %d.\n", stream->pid);
+
+#if defined(linux) && !defined(CONFIG_NOCUTILS)
+ {
+ FILE *pid_stat;
+ char ps_cmd[64];
+
+ /* This is somewhat linux specific I guess */
+ snprintf(ps_cmd, sizeof(ps_cmd),
+ "ps -o \"%%cpu,cputime\" --no-headers %d",
+ stream->pid);
+
+ pid_stat = popen(ps_cmd, "r");
+ if (pid_stat) {
+ char cpuperc[10];
+ char cpuused[64];
+
+ if (fscanf(pid_stat, "%10s %64s", cpuperc,
+ cpuused) == 2) {
+ url_fprintf(pb, "Currently using %s%% of the cpu. Total time used %s.\n",
+ cpuperc, cpuused);
+ }
+ fclose(pid_stat);
+ }
+ }
+#endif
+
+ url_fprintf(pb, "<p>");
+ }
+ url_fprintf(pb, "<table cellspacing=0 cellpadding=4><tr><th>Stream<th>type<th>kbits/s<th align=left>codec<th align=left>Parameters\n");
+
+ for (i = 0; i < stream->nb_streams; i++) {
+ AVStream *st = stream->streams[i];
+ AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
+ const char *type = "unknown";
+ char parameters[64];
+
+ parameters[0] = 0;
+
+ switch(st->codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ type = "audio";
+ break;
+ case CODEC_TYPE_VIDEO:
+ type = "video";
+ snprintf(parameters, sizeof(parameters), "%dx%d, q=%d-%d, fps=%d", st->codec->width, st->codec->height,
+ st->codec->qmin, st->codec->qmax, st->codec->time_base.den / st->codec->time_base.num);
+ break;
+ default:
+ av_abort();
+ }
+ url_fprintf(pb, "<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
+ i, type, st->codec->bit_rate/1000, codec ? codec->name : "", parameters);
+ }
+ url_fprintf(pb, "</table>\n");
+
+ }
+ stream = stream->next;
+ }
+
+#if 0
+ {
+ float avg;
+ AVCodecContext *enc;
+ char buf[1024];
+
+ /* feed status */
+ stream = first_feed;
+ while (stream != NULL) {
+ url_fprintf(pb, "<H1>Feed '%s'</H1>\n", stream->filename);
+ url_fprintf(pb, "<TABLE>\n");
+ url_fprintf(pb, "<TR><TD>Parameters<TD>Frame count<TD>Size<TD>Avg bitrate (kbits/s)\n");
+ for(i=0;i<stream->nb_streams;i++) {
+ AVStream *st = stream->streams[i];
+ FeedData *fdata = st->priv_data;
+ enc = st->codec;
+
+ avcodec_string(buf, sizeof(buf), enc);
+ avg = fdata->avg_frame_size * (float)enc->rate * 8.0;
+ if (enc->codec->type == CODEC_TYPE_AUDIO && enc->frame_size > 0)
+ avg /= enc->frame_size;
+ url_fprintf(pb, "<TR><TD>%s <TD> %d <TD> %"PRId64" <TD> %0.1f\n",
+ buf, enc->frame_number, fdata->data_count, avg / 1000.0);
+ }
+ url_fprintf(pb, "</TABLE>\n");
+ stream = stream->next_feed;
+ }
+ }
+#endif
+
+ /* connection status */
+ url_fprintf(pb, "<H2>Connection Status</H2>\n");
+
+ url_fprintf(pb, "Number of connections: %d / %d<BR>\n",
+ nb_connections, nb_max_connections);
+
+ url_fprintf(pb, "Bandwidth in use: %dk / %dk<BR>\n",
+ current_bandwidth, max_bandwidth);
+
+ url_fprintf(pb, "<TABLE>\n");
+ url_fprintf(pb, "<TR><th>#<th>File<th>IP<th>Proto<th>State<th>Target bits/sec<th>Actual bits/sec<th>Bytes transferred\n");
+ c1 = first_http_ctx;
+ i = 0;
+ while (c1 != NULL) {
+ int bitrate;
+ int j;
+
+ bitrate = 0;
+ if (c1->stream) {
+ for (j = 0; j < c1->stream->nb_streams; j++) {
+ if (!c1->stream->feed) {
+ bitrate += c1->stream->streams[j]->codec->bit_rate;
+ } else {
+ if (c1->feed_streams[j] >= 0) {
+ bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codec->bit_rate;
+ }
+ }
+ }
+ }
+
+ i++;
+ p = inet_ntoa(c1->from_addr.sin_addr);
+ url_fprintf(pb, "<TR><TD><B>%d</B><TD>%s%s<TD>%s<TD>%s<TD>%s<td align=right>",
+ i,
+ c1->stream ? c1->stream->filename : "",
+ c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
+ p,
+ c1->protocol,
+ http_state[c1->state]);
+ fmt_bytecount(pb, bitrate);
+ url_fprintf(pb, "<td align=right>");
+ fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8);
+ url_fprintf(pb, "<td align=right>");
+ fmt_bytecount(pb, c1->data_count);
+ url_fprintf(pb, "\n");
+ c1 = c1->next;
+ }
+ url_fprintf(pb, "</TABLE>\n");
+
+ /* date */
+ ti = time(NULL);
+ p = ctime(&ti);
+ url_fprintf(pb, "<HR size=1 noshade>Generated at %s", p);
+ url_fprintf(pb, "</BODY>\n</HTML>\n");
+
+ len = url_close_dyn_buf(pb, &c->pb_buffer);
+ c->buffer_ptr = c->pb_buffer;
+ c->buffer_end = c->pb_buffer + len;
+}
+
+/* check if the parser needs to be opened for stream i */
+static void open_parser(AVFormatContext *s, int i)
+{
+ AVStream *st = s->streams[i];
+ AVCodec *codec;
+
+ if (!st->codec->codec) {
+ codec = avcodec_find_decoder(st->codec->codec_id);
+ if (codec && (codec->capabilities & CODEC_CAP_PARSE_ONLY)) {
+ st->codec->parse_only = 1;
+ if (avcodec_open(st->codec, codec) < 0) {
+ st->codec->parse_only = 0;
+ }
+ }
+ }
+}
+
+static int open_input_stream(HTTPContext *c, const char *info)
+{
+ char buf[128];
+ char input_filename[1024];
+ AVFormatContext *s;
+ int buf_size, i;
+ int64_t stream_pos;
+
+ /* find file name */
+ if (c->stream->feed) {
+ strcpy(input_filename, c->stream->feed->feed_filename);
+ buf_size = FFM_PACKET_SIZE;
+ /* compute position (absolute time) */
+ if (find_info_tag(buf, sizeof(buf), "date", info)) {
+ stream_pos = parse_date(buf, 0);
+ } else if (find_info_tag(buf, sizeof(buf), "buffer", info)) {
+ int prebuffer = strtol(buf, 0, 10);
+ stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
+ } else {
+ stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
+ }
+ } else {
+ strcpy(input_filename, c->stream->feed_filename);
+ buf_size = 0;
+ /* compute position (relative time) */
+ if (find_info_tag(buf, sizeof(buf), "date", info)) {
+ stream_pos = parse_date(buf, 1);
+ } else {
+ stream_pos = 0;
+ }
+ }
+ if (input_filename[0] == '\0')
+ return -1;
+
+#if 0
+ { time_t when = stream_pos / 1000000;
+ http_log("Stream pos = %"PRId64", time=%s", stream_pos, ctime(&when));
+ }
+#endif
+
+ /* open stream */
+ if (av_open_input_file(&s, input_filename, c->stream->ifmt,
+ buf_size, c->stream->ap_in) < 0) {
+ http_log("%s not found", input_filename);
+ return -1;
+ }
+ c->fmt_in = s;
+
+ /* open each parser */
+ for(i=0;i<s->nb_streams;i++)
+ open_parser(s, i);
+
+ /* choose stream as clock source (we favorize video stream if
+ present) for packet sending */
+ c->pts_stream_index = 0;
+ for(i=0;i<c->stream->nb_streams;i++) {
+ if (c->pts_stream_index == 0 &&
+ c->stream->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) {
+ c->pts_stream_index = i;
+ }
+ }
+
+#if 1
+ if (c->fmt_in->iformat->read_seek) {
+ c->fmt_in->iformat->read_seek(c->fmt_in, 0, stream_pos, 0);
+ }
+#endif
+ /* set the start time (needed for maxtime and RTP packet timing) */
+ c->start_time = cur_time;
+ c->first_pts = AV_NOPTS_VALUE;
+ return 0;
+}
+
+/* return the server clock (in us) */
+static int64_t get_server_clock(HTTPContext *c)
+{
+ /* compute current pts value from system time */
+ return (int64_t)(cur_time - c->start_time) * 1000LL;
+}
+
+/* return the estimated time at which the current packet must be sent
+ (in us) */
+static int64_t get_packet_send_clock(HTTPContext *c)
+{
+ int bytes_left, bytes_sent, frame_bytes;
+
+ frame_bytes = c->cur_frame_bytes;
+ if (frame_bytes <= 0) {
+ return c->cur_pts;
+ } else {
+ bytes_left = c->buffer_end - c->buffer_ptr;
+ bytes_sent = frame_bytes - bytes_left;
+ return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
+ }
+}
+
+
+static int http_prepare_data(HTTPContext *c)
+{
+ int i, len, ret;
+ AVFormatContext *ctx;
+
+ av_freep(&c->pb_buffer);
+ switch(c->state) {
+ case HTTPSTATE_SEND_DATA_HEADER:
+ memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
+ pstrcpy(c->fmt_ctx.author, sizeof(c->fmt_ctx.author),
+ c->stream->author);
+ pstrcpy(c->fmt_ctx.comment, sizeof(c->fmt_ctx.comment),
+ c->stream->comment);
+ pstrcpy(c->fmt_ctx.copyright, sizeof(c->fmt_ctx.copyright),
+ c->stream->copyright);
+ pstrcpy(c->fmt_ctx.title, sizeof(c->fmt_ctx.title),
+ c->stream->title);
+
+ /* open output stream by using specified codecs */
+ c->fmt_ctx.oformat = c->stream->fmt;
+ c->fmt_ctx.nb_streams = c->stream->nb_streams;
+ for(i=0;i<c->fmt_ctx.nb_streams;i++) {
+ AVStream *st;
+ AVStream *src;
+ st = av_mallocz(sizeof(AVStream));
+ st->codec= avcodec_alloc_context();
+ c->fmt_ctx.streams[i] = st;
+ /* if file or feed, then just take streams from FFStream struct */
+ if (!c->stream->feed ||
+ c->stream->feed == c->stream)
+ src = c->stream->streams[i];
+ else
+ src = c->stream->feed->streams[c->stream->feed_streams[i]];
+
+ *st = *src;
+ st->priv_data = 0;
+ st->codec->frame_number = 0; /* XXX: should be done in
+ AVStream, not in codec */
+ /* I'm pretty sure that this is not correct...
+ * However, without it, we crash
+ */
+ st->codec->coded_frame = &dummy_frame;
+ }
+ c->got_key_frame = 0;
+
+ /* prepare header and save header data in a stream */
+ if (url_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
+ /* XXX: potential leak */
+ return -1;
+ }
+ c->fmt_ctx.pb.is_streamed = 1;
+
+ av_set_parameters(&c->fmt_ctx, NULL);
+ av_write_header(&c->fmt_ctx);
+
+ len = url_close_dyn_buf(&c->fmt_ctx.pb, &c->pb_buffer);
+ c->buffer_ptr = c->pb_buffer;
+ c->buffer_end = c->pb_buffer + len;
+
+ c->state = HTTPSTATE_SEND_DATA;
+ c->last_packet_sent = 0;
+ break;
+ case HTTPSTATE_SEND_DATA:
+ /* find a new packet */
+ {
+ AVPacket pkt;
+
+ /* read a packet from the input stream */
+ if (c->stream->feed) {
+ ffm_set_write_index(c->fmt_in,
+ c->stream->feed->feed_write_index,
+ c->stream->feed->feed_size);
+ }
+
+ if (c->stream->max_time &&
+ c->stream->max_time + c->start_time - cur_time < 0) {
+ /* We have timed out */
+ c->state = HTTPSTATE_SEND_DATA_TRAILER;
+ } else {
+ redo:
+ if (av_read_frame(c->fmt_in, &pkt) < 0) {
+ if (c->stream->feed && c->stream->feed->feed_opened) {
+ /* if coming from feed, it means we reached the end of the
+ ffm file, so must wait for more data */
+ c->state = HTTPSTATE_WAIT_FEED;
+ return 1; /* state changed */
+ } else {
+ if (c->stream->loop) {
+ av_close_input_file(c->fmt_in);
+ c->fmt_in = NULL;
+ if (open_input_stream(c, "") < 0)
+ goto no_loop;
+ goto redo;
+ } else {
+ no_loop:
+ /* must send trailer now because eof or error */
+ c->state = HTTPSTATE_SEND_DATA_TRAILER;
+ }
+ }
+ } else {
+ /* update first pts if needed */
+ if (c->first_pts == AV_NOPTS_VALUE) {
+ c->first_pts = av_rescale_q(pkt.dts, c->fmt_in->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
+ c->start_time = cur_time;
+ }
+ /* send it to the appropriate stream */
+ if (c->stream->feed) {
+ /* if coming from a feed, select the right stream */
+ if (c->switch_pending) {
+ c->switch_pending = 0;
+ for(i=0;i<c->stream->nb_streams;i++) {
+ if (c->switch_feed_streams[i] == pkt.stream_index) {
+ if (pkt.flags & PKT_FLAG_KEY) {
+ do_switch_stream(c, i);
+ }
+ }
+ if (c->switch_feed_streams[i] >= 0) {
+ c->switch_pending = 1;
+ }
+ }
+ }
+ for(i=0;i<c->stream->nb_streams;i++) {
+ if (c->feed_streams[i] == pkt.stream_index) {
+ pkt.stream_index = i;
+ if (pkt.flags & PKT_FLAG_KEY) {
+ c->got_key_frame |= 1 << i;
+ }
+ /* See if we have all the key frames, then
+ * we start to send. This logic is not quite
+ * right, but it works for the case of a
+ * single video stream with one or more
+ * audio streams (for which every frame is
+ * typically a key frame).
+ */
+ if (!c->stream->send_on_key ||
+ ((c->got_key_frame + 1) >> c->stream->nb_streams)) {
+ goto send_it;
+ }
+ }
+ }
+ } else {
+ AVCodecContext *codec;
+
+ send_it:
+ /* specific handling for RTP: we use several
+ output stream (one for each RTP
+ connection). XXX: need more abstract handling */
+ if (c->is_packetized) {
+ AVStream *st;
+ /* compute send time and duration */
+ st = c->fmt_in->streams[pkt.stream_index];
+ c->cur_pts = av_rescale_q(pkt.dts, st->time_base, AV_TIME_BASE_Q);
+ if (st->start_time != AV_NOPTS_VALUE)
+ c->cur_pts -= av_rescale_q(st->start_time, st->time_base, AV_TIME_BASE_Q);
+ c->cur_frame_duration = av_rescale_q(pkt.duration, st->time_base, AV_TIME_BASE_Q);
+#if 0
+ printf("index=%d pts=%0.3f duration=%0.6f\n",
+ pkt.stream_index,
+ (double)c->cur_pts /
+ AV_TIME_BASE,
+ (double)c->cur_frame_duration /
+ AV_TIME_BASE);
+#endif
+ /* find RTP context */
+ c->packet_stream_index = pkt.stream_index;
+ ctx = c->rtp_ctx[c->packet_stream_index];
+ if(!ctx) {
+ av_free_packet(&pkt);
+ break;
+ }
+ codec = ctx->streams[0]->codec;
+ /* only one stream per RTP connection */
+ pkt.stream_index = 0;
+ } else {
+ ctx = &c->fmt_ctx;
+ /* Fudge here */
+ codec = ctx->streams[pkt.stream_index]->codec;
+ }
+
+ codec->coded_frame->key_frame = ((pkt.flags & PKT_FLAG_KEY) != 0);
+ if (c->is_packetized) {
+ int max_packet_size;
+ if (c->rtp_protocol == RTSP_PROTOCOL_RTP_TCP)
+ max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
+ else
+ max_packet_size = url_get_max_packet_size(c->rtp_handles[c->packet_stream_index]);
+ ret = url_open_dyn_packet_buf(&ctx->pb, max_packet_size);
+ } else {
+ ret = url_open_dyn_buf(&ctx->pb);
+ }
+ if (ret < 0) {
+ /* XXX: potential leak */
+ return -1;
+ }
+ if (av_write_frame(ctx, &pkt)) {
+ c->state = HTTPSTATE_SEND_DATA_TRAILER;
+ }
+
+ len = url_close_dyn_buf(&ctx->pb, &c->pb_buffer);
+ c->cur_frame_bytes = len;
+ c->buffer_ptr = c->pb_buffer;
+ c->buffer_end = c->pb_buffer + len;
+
+ codec->frame_number++;
+ if (len == 0)
+ goto redo;
+ }
+ av_free_packet(&pkt);
+ }
+ }
+ }
+ break;
+ default:
+ case HTTPSTATE_SEND_DATA_TRAILER:
+ /* last packet test ? */
+ if (c->last_packet_sent || c->is_packetized)
+ return -1;
+ ctx = &c->fmt_ctx;
+ /* prepare header */
+ if (url_open_dyn_buf(&ctx->pb) < 0) {
+ /* XXX: potential leak */
+ return -1;
+ }
+ av_write_trailer(ctx);
+ len = url_close_dyn_buf(&ctx->pb, &c->pb_buffer);
+ c->buffer_ptr = c->pb_buffer;
+ c->buffer_end = c->pb_buffer + len;
+
+ c->last_packet_sent = 1;
+ break;
+ }
+ return 0;
+}
+
+/* in bit/s */
+#define SHORT_TERM_BANDWIDTH 8000000
+
+/* should convert the format at the same time */
+/* send data starting at c->buffer_ptr to the output connection
+ (either UDP or TCP connection) */
+static int http_send_data(HTTPContext *c)
+{
+ int len, ret;
+
+ for(;;) {
+ if (c->buffer_ptr >= c->buffer_end) {
+ ret = http_prepare_data(c);
+ if (ret < 0)
+ return -1;
+ else if (ret != 0) {
+ /* state change requested */
+ break;
+ }
+ } else {
+ if (c->is_packetized) {
+ /* RTP data output */
+ len = c->buffer_end - c->buffer_ptr;
+ if (len < 4) {
+ /* fail safe - should never happen */
+ fail1:
+ c->buffer_ptr = c->buffer_end;
+ return 0;
+ }
+ len = (c->buffer_ptr[0] << 24) |
+ (c->buffer_ptr[1] << 16) |
+ (c->buffer_ptr[2] << 8) |
+ (c->buffer_ptr[3]);
+ if (len > (c->buffer_end - c->buffer_ptr))
+ goto fail1;
+ if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
+ /* nothing to send yet: we can wait */
+ return 0;
+ }
+
+ c->data_count += len;
+ update_datarate(&c->datarate, c->data_count);
+ if (c->stream)
+ c->stream->bytes_served += len;
+
+ if (c->rtp_protocol == RTSP_PROTOCOL_RTP_TCP) {
+ /* RTP packets are sent inside the RTSP TCP connection */
+ ByteIOContext pb1, *pb = &pb1;
+ int interleaved_index, size;
+ uint8_t header[4];
+ HTTPContext *rtsp_c;
+
+ rtsp_c = c->rtsp_c;
+ /* if no RTSP connection left, error */
+ if (!rtsp_c)
+ return -1;
+ /* if already sending something, then wait. */
+ if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST) {
+ break;
+ }
+ if (url_open_dyn_buf(pb) < 0)
+ goto fail1;
+ interleaved_index = c->packet_stream_index * 2;
+ /* RTCP packets are sent at odd indexes */
+ if (c->buffer_ptr[1] == 200)
+ interleaved_index++;
+ /* write RTSP TCP header */
+ header[0] = '$';
+ header[1] = interleaved_index;
+ header[2] = len >> 8;
+ header[3] = len;
+ put_buffer(pb, header, 4);
+ /* write RTP packet data */
+ c->buffer_ptr += 4;
+ put_buffer(pb, c->buffer_ptr, len);
+ size = url_close_dyn_buf(pb, &c->packet_buffer);
+ /* prepare asynchronous TCP sending */
+ rtsp_c->packet_buffer_ptr = c->packet_buffer;
+ rtsp_c->packet_buffer_end = c->packet_buffer + size;
+ c->buffer_ptr += len;
+
+ /* send everything we can NOW */
+ len = write(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
+ rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr);
+ if (len > 0) {
+ rtsp_c->packet_buffer_ptr += len;
+ }
+ if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
+ /* if we could not send all the data, we will
+ send it later, so a new state is needed to
+ "lock" the RTSP TCP connection */
+ rtsp_c->state = RTSPSTATE_SEND_PACKET;
+ break;
+ } else {
+ /* all data has been sent */
+ av_freep(&c->packet_buffer);
+ }
+ } else {
+ /* send RTP packet directly in UDP */
+ c->buffer_ptr += 4;
+ url_write(c->rtp_handles[c->packet_stream_index],
+ c->buffer_ptr, len);
+ c->buffer_ptr += len;
+ /* here we continue as we can send several packets per 10 ms slot */
+ }
+ } else {
+ /* TCP data output */
+ len = write(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr);
+ if (len < 0) {
+ if (errno != EAGAIN && errno != EINTR) {
+ /* error : close connection */
+ return -1;
+ } else {
+ return 0;
+ }
+ } else {
+ c->buffer_ptr += len;
+ }
+ c->data_count += len;
+ update_datarate(&c->datarate, c->data_count);
+ if (c->stream)
+ c->stream->bytes_served += len;
+ break;
+ }
+ }
+ } /* for(;;) */
+ return 0;
+}
+
+static int http_start_receive_data(HTTPContext *c)
+{
+ int fd;
+
+ if (c->stream->feed_opened)
+ return -1;
+
+ /* Don't permit writing to this one */
+ if (c->stream->readonly)
+ return -1;
+
+ /* open feed */
+ fd = open(c->stream->feed_filename, O_RDWR);
+ if (fd < 0)
+ return -1;
+ c->feed_fd = fd;
+
+ c->stream->feed_write_index = ffm_read_write_index(fd);
+ c->stream->feed_size = lseek(fd, 0, SEEK_END);
+ lseek(fd, 0, SEEK_SET);
+
+ /* init buffer input */
+ c->buffer_ptr = c->buffer;
+ c->buffer_end = c->buffer + FFM_PACKET_SIZE;
+ c->stream->feed_opened = 1;
+ return 0;
+}
+
+static int http_receive_data(HTTPContext *c)
+{
+ HTTPContext *c1;
+
+ if (c->buffer_end > c->buffer_ptr) {
+ int len;
+
+ len = read(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr);
+ if (len < 0) {
+ if (errno != EAGAIN && errno != EINTR) {
+ /* error : close connection */
+ goto fail;
+ }
+ } else if (len == 0) {
+ /* end of connection : close it */
+ goto fail;
+ } else {
+ c->buffer_ptr += len;
+ c->data_count += len;
+ update_datarate(&c->datarate, c->data_count);
+ }
+ }
+
+ if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
+ if (c->buffer[0] != 'f' ||
+ c->buffer[1] != 'm') {
+ http_log("Feed stream has become desynchronized -- disconnecting\n");
+ goto fail;
+ }
+ }
+
+ if (c->buffer_ptr >= c->buffer_end) {
+ FFStream *feed = c->stream;
+ /* a packet has been received : write it in the store, except
+ if header */
+ if (c->data_count > FFM_PACKET_SIZE) {
+
+ // printf("writing pos=0x%"PRIx64" size=0x%"PRIx64"\n", feed->feed_write_index, feed->feed_size);
+ /* XXX: use llseek or url_seek */
+ lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
+ write(c->feed_fd, c->buffer, FFM_PACKET_SIZE);
+
+ feed->feed_write_index += FFM_PACKET_SIZE;
+ /* update file size */
+ if (feed->feed_write_index > c->stream->feed_size)
+ feed->feed_size = feed->feed_write_index;
+
+ /* handle wrap around if max file size reached */
+ if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
+ feed->feed_write_index = FFM_PACKET_SIZE;
+
+ /* write index */
+ ffm_write_write_index(c->feed_fd, feed->feed_write_index);
+
+ /* wake up any waiting connections */
+ for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
+ if (c1->state == HTTPSTATE_WAIT_FEED &&
+ c1->stream->feed == c->stream->feed) {
+ c1->state = HTTPSTATE_SEND_DATA;
+ }
+ }
+ } else {
+ /* We have a header in our hands that contains useful data */
+ AVFormatContext s;
+ AVInputFormat *fmt_in;
+ ByteIOContext *pb = &s.pb;
+ int i;
+
+ memset(&s, 0, sizeof(s));
+
+ url_open_buf(pb, c->buffer, c->buffer_end - c->buffer, URL_RDONLY);
+ pb->buf_end = c->buffer_end; /* ?? */
+ pb->is_streamed = 1;
+
+ /* use feed output format name to find corresponding input format */
+ fmt_in = av_find_input_format(feed->fmt->name);
+ if (!fmt_in)
+ goto fail;
+
+ if (fmt_in->priv_data_size > 0) {
+ s.priv_data = av_mallocz(fmt_in->priv_data_size);
+ if (!s.priv_data)
+ goto fail;
+ } else
+ s.priv_data = NULL;
+
+ if (fmt_in->read_header(&s, 0) < 0) {
+ av_freep(&s.priv_data);
+ goto fail;
+ }
+
+ /* Now we have the actual streams */
+ if (s.nb_streams != feed->nb_streams) {
+ av_freep(&s.priv_data);
+ goto fail;
+ }
+ for (i = 0; i < s.nb_streams; i++) {
+ memcpy(feed->streams[i]->codec,
+ s.streams[i]->codec, sizeof(AVCodecContext));
+ }
+ av_freep(&s.priv_data);
+ }
+ c->buffer_ptr = c->buffer;
+ }
+
+ return 0;
+ fail:
+ c->stream->feed_opened = 0;
+ close(c->feed_fd);
+ return -1;
+}
+
+/********************************************************************/
+/* RTSP handling */
+
+static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
+{
+ const char *str;
+ time_t ti;
+ char *p;
+ char buf2[32];
+
+ switch(error_number) {
+#define DEF(n, c, s) case c: str = s; break;
+#include "rtspcodes.h"
+#undef DEF
+ default:
+ str = "Unknown Error";
+ break;
+ }
+
+ url_fprintf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
+ url_fprintf(c->pb, "CSeq: %d\r\n", c->seq);
+
+ /* output GMT time */
+ ti = time(NULL);
+ p = ctime(&ti);
+ strcpy(buf2, p);
+ p = buf2 + strlen(p) - 1;
+ if (*p == '\n')
+ *p = '\0';
+ url_fprintf(c->pb, "Date: %s GMT\r\n", buf2);
+}
+
+static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
+{
+ rtsp_reply_header(c, error_number);
+ url_fprintf(c->pb, "\r\n");
+}
+
+static int rtsp_parse_request(HTTPContext *c)
+{
+ const char *p, *p1, *p2;
+ char cmd[32];
+ char url[1024];
+ char protocol[32];
+ char line[1024];
+ ByteIOContext pb1;
+ int len;
+ RTSPHeader header1, *header = &header1;
+
+ c->buffer_ptr[0] = '\0';
+ p = c->buffer;
+
+ get_word(cmd, sizeof(cmd), &p);
+ get_word(url, sizeof(url), &p);
+ get_word(protocol, sizeof(protocol), &p);
+
+ pstrcpy(c->method, sizeof(c->method), cmd);
+ pstrcpy(c->url, sizeof(c->url), url);
+ pstrcpy(c->protocol, sizeof(c->protocol), protocol);
+
+ c->pb = &pb1;
+ if (url_open_dyn_buf(c->pb) < 0) {
+ /* XXX: cannot do more */
+ c->pb = NULL; /* safety */
+ return -1;
+ }
+
+ /* check version name */
+ if (strcmp(protocol, "RTSP/1.0") != 0) {
+ rtsp_reply_error(c, RTSP_STATUS_VERSION);
+ goto the_end;
+ }
+
+ /* parse each header line */
+ memset(header, 0, sizeof(RTSPHeader));
+ /* skip to next line */
+ while (*p != '\n' && *p != '\0')
+ p++;
+ if (*p == '\n')
+ p++;
+ while (*p != '\0') {
+ p1 = strchr(p, '\n');
+ if (!p1)
+ break;
+ p2 = p1;
+ if (p2 > p && p2[-1] == '\r')
+ p2--;
+ /* skip empty line */
+ if (p2 == p)
+ break;
+ len = p2 - p;
+ if (len > sizeof(line) - 1)
+ len = sizeof(line) - 1;
+ memcpy(line, p, len);
+ line[len] = '\0';
+ rtsp_parse_line(header, line);
+ p = p1 + 1;
+ }
+
+ /* handle sequence number */
+ c->seq = header->seq;
+
+ if (!strcmp(cmd, "DESCRIBE")) {
+ rtsp_cmd_describe(c, url);
+ } else if (!strcmp(cmd, "OPTIONS")) {
+ rtsp_cmd_options(c, url);
+ } else if (!strcmp(cmd, "SETUP")) {
+ rtsp_cmd_setup(c, url, header);
+ } else if (!strcmp(cmd, "PLAY")) {
+ rtsp_cmd_play(c, url, header);
+ } else if (!strcmp(cmd, "PAUSE")) {
+ rtsp_cmd_pause(c, url, header);
+ } else if (!strcmp(cmd, "TEARDOWN")) {
+ rtsp_cmd_teardown(c, url, header);
+ } else {
+ rtsp_reply_error(c, RTSP_STATUS_METHOD);
+ }
+ the_end:
+ len = url_close_dyn_buf(c->pb, &c->pb_buffer);
+ c->pb = NULL; /* safety */
+ if (len < 0) {
+ /* XXX: cannot do more */
+ return -1;
+ }
+ c->buffer_ptr = c->pb_buffer;
+ c->buffer_end = c->pb_buffer + len;
+ c->state = RTSPSTATE_SEND_REPLY;
+ return 0;
+}
+
+/* XXX: move that to rtsp.c, but would need to replace FFStream by
+ AVFormatContext */
+static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
+ struct in_addr my_ip)
+{
+ ByteIOContext pb1, *pb = &pb1;
+ int i, payload_type, port, private_payload_type, j;
+ const char *ipstr, *title, *mediatype;
+ AVStream *st;
+
+ if (url_open_dyn_buf(pb) < 0)
+ return -1;
+
+ /* general media info */
+
+ url_fprintf(pb, "v=0\n");
+ ipstr = inet_ntoa(my_ip);
+ url_fprintf(pb, "o=- 0 0 IN IP4 %s\n", ipstr);
+ title = stream->title;
+ if (title[0] == '\0')
+ title = "No Title";
+ url_fprintf(pb, "s=%s\n", title);
+ if (stream->comment[0] != '\0')
+ url_fprintf(pb, "i=%s\n", stream->comment);
+ if (stream->is_multicast) {
+ url_fprintf(pb, "c=IN IP4 %s\n", inet_ntoa(stream->multicast_ip));
+ }
+ /* for each stream, we output the necessary info */
+ private_payload_type = RTP_PT_PRIVATE;
+ for(i = 0; i < stream->nb_streams; i++) {
+ st = stream->streams[i];
+ if (st->codec->codec_id == CODEC_ID_MPEG2TS) {
+ mediatype = "video";
+ } else {
+ switch(st->codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ mediatype = "audio";
+ break;
+ case CODEC_TYPE_VIDEO:
+ mediatype = "video";
+ break;
+ default:
+ mediatype = "application";
+ break;
+ }
+ }
+ /* NOTE: the port indication is not correct in case of
+ unicast. It is not an issue because RTSP gives it */
+ payload_type = rtp_get_payload_type(st->codec);
+ if (payload_type < 0)
+ payload_type = private_payload_type++;
+ if (stream->is_multicast) {
+ port = stream->multicast_port + 2 * i;
+ } else {
+ port = 0;
+ }
+ url_fprintf(pb, "m=%s %d RTP/AVP %d\n",
+ mediatype, port, payload_type);
+ if (payload_type >= RTP_PT_PRIVATE) {
+ /* for private payload type, we need to give more info */
+ switch(st->codec->codec_id) {
+ case CODEC_ID_MPEG4:
+ {
+ uint8_t *data;
+ url_fprintf(pb, "a=rtpmap:%d MP4V-ES/%d\n",
+ payload_type, 90000);
+ /* we must also add the mpeg4 header */
+ data = st->codec->extradata;
+ if (data) {
+ url_fprintf(pb, "a=fmtp:%d config=", payload_type);
+ for(j=0;j<st->codec->extradata_size;j++) {
+ url_fprintf(pb, "%02x", data[j]);
+ }
+ url_fprintf(pb, "\n");
+ }
+ }
+ break;
+ default:
+ /* XXX: add other codecs ? */
+ goto fail;
+ }
+ }
+ url_fprintf(pb, "a=control:streamid=%d\n", i);
+ }
+ return url_close_dyn_buf(pb, pbuffer);
+ fail:
+ url_close_dyn_buf(pb, pbuffer);
+ av_free(*pbuffer);
+ return -1;
+}
+
+static void rtsp_cmd_options(HTTPContext *c, const char *url)
+{
+// rtsp_reply_header(c, RTSP_STATUS_OK);
+ url_fprintf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
+ url_fprintf(c->pb, "CSeq: %d\r\n", c->seq);
+ url_fprintf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
+ url_fprintf(c->pb, "\r\n");
+}
+
+static void rtsp_cmd_describe(HTTPContext *c, const char *url)
+{
+ FFStream *stream;
+ char path1[1024];
+ const char *path;
+ uint8_t *content;
+ int content_length, len;
+ struct sockaddr_in my_addr;
+
+ /* find which url is asked */
+ url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
+ path = path1;
+ if (*path == '/')
+ path++;
+
+ for(stream = first_stream; stream != NULL; stream = stream->next) {
+ if (!stream->is_feed && stream->fmt == &rtp_muxer &&
+ !strcmp(path, stream->filename)) {
+ goto found;
+ }
+ }
+ /* no stream found */
+ rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
+ return;
+
+ found:
+ /* prepare the media description in sdp format */
+
+ /* get the host IP */
+ len = sizeof(my_addr);
+ getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
+ content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
+ if (content_length < 0) {
+ rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
+ return;
+ }
+ rtsp_reply_header(c, RTSP_STATUS_OK);
+ url_fprintf(c->pb, "Content-Type: application/sdp\r\n");
+ url_fprintf(c->pb, "Content-Length: %d\r\n", content_length);
+ url_fprintf(c->pb, "\r\n");
+ put_buffer(c->pb, content, content_length);
+}
+
+static HTTPContext *find_rtp_session(const char *session_id)
+{
+ HTTPContext *c;
+
+ if (session_id[0] == '\0')
+ return NULL;
+
+ for(c = first_http_ctx; c != NULL; c = c->next) {
+ if (!strcmp(c->session_id, session_id))
+ return c;
+ }
+ return NULL;
+}
+
+static RTSPTransportField *find_transport(RTSPHeader *h, enum RTSPProtocol protocol)
+{
+ RTSPTransportField *th;
+ int i;
+
+ for(i=0;i<h->nb_transports;i++) {
+ th = &h->transports[i];
+ if (th->protocol == protocol)
+ return th;
+ }
+ return NULL;
+}
+
+static void rtsp_cmd_setup(HTTPContext *c, const char *url,
+ RTSPHeader *h)
+{
+ FFStream *stream;
+ int stream_index, port;
+ char buf[1024];
+ char path1[1024];
+ const char *path;
+ HTTPContext *rtp_c;
+ RTSPTransportField *th;
+ struct sockaddr_in dest_addr;
+ RTSPActionServerSetup setup;
+
+ /* find which url is asked */
+ url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
+ path = path1;
+ if (*path == '/')
+ path++;
+
+ /* now check each stream */
+ for(stream = first_stream; stream != NULL; stream = stream->next) {
+ if (!stream->is_feed && stream->fmt == &rtp_muxer) {
+ /* accept aggregate filenames only if single stream */
+ if (!strcmp(path, stream->filename)) {
+ if (stream->nb_streams != 1) {
+ rtsp_reply_error(c, RTSP_STATUS_AGGREGATE);
+ return;
+ }
+ stream_index = 0;
+ goto found;
+ }
+
+ for(stream_index = 0; stream_index < stream->nb_streams;
+ stream_index++) {
+ snprintf(buf, sizeof(buf), "%s/streamid=%d",
+ stream->filename, stream_index);
+ if (!strcmp(path, buf))
+ goto found;
+ }
+ }
+ }
+ /* no stream found */
+ rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
+ return;
+ found:
+
+ /* generate session id if needed */
+ if (h->session_id[0] == '\0') {
+ snprintf(h->session_id, sizeof(h->session_id),
+ "%08x%08x", (int)random(), (int)random());
+ }
+
+ /* find rtp session, and create it if none found */
+ rtp_c = find_rtp_session(h->session_id);
+ if (!rtp_c) {
+ /* always prefer UDP */
+ th = find_transport(h, RTSP_PROTOCOL_RTP_UDP);
+ if (!th) {
+ th = find_transport(h, RTSP_PROTOCOL_RTP_TCP);
+ if (!th) {
+ rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
+ return;
+ }
+ }
+
+ rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
+ th->protocol);
+ if (!rtp_c) {
+ rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH);
+ return;
+ }
+
+ /* open input stream */
+ if (open_input_stream(rtp_c, "") < 0) {
+ rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
+ return;
+ }
+ }
+
+ /* test if stream is OK (test needed because several SETUP needs
+ to be done for a given file) */
+ if (rtp_c->stream != stream) {
+ rtsp_reply_error(c, RTSP_STATUS_SERVICE);
+ return;
+ }
+
+ /* test if stream is already set up */
+ if (rtp_c->rtp_ctx[stream_index]) {
+ rtsp_reply_error(c, RTSP_STATUS_STATE);
+ return;
+ }
+
+ /* check transport */
+ th = find_transport(h, rtp_c->rtp_protocol);
+ if (!th || (th->protocol == RTSP_PROTOCOL_RTP_UDP &&
+ th->client_port_min <= 0)) {
+ rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
+ return;
+ }
+
+ /* setup default options */
+ setup.transport_option[0] = '\0';
+ dest_addr = rtp_c->from_addr;
+ dest_addr.sin_port = htons(th->client_port_min);
+
+ /* add transport option if needed */
+ if (ff_rtsp_callback) {
+ setup.ipaddr = ntohl(dest_addr.sin_addr.s_addr);
+ if (ff_rtsp_callback(RTSP_ACTION_SERVER_SETUP, rtp_c->session_id,
+ (char *)&setup, sizeof(setup),
+ stream->rtsp_option) < 0) {
+ rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
+ return;
+ }
+ dest_addr.sin_addr.s_addr = htonl(setup.ipaddr);
+ }
+
+ /* setup stream */
+ if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
+ rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
+ return;
+ }
+
+ /* now everything is OK, so we can send the connection parameters */
+ rtsp_reply_header(c, RTSP_STATUS_OK);
+ /* session ID */
+ url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
+
+ switch(rtp_c->rtp_protocol) {
+ case RTSP_PROTOCOL_RTP_UDP:
+ port = rtp_get_local_port(rtp_c->rtp_handles[stream_index]);
+ url_fprintf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
+ "client_port=%d-%d;server_port=%d-%d",
+ th->client_port_min, th->client_port_min + 1,
+ port, port + 1);
+ break;
+ case RTSP_PROTOCOL_RTP_TCP:
+ url_fprintf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
+ stream_index * 2, stream_index * 2 + 1);
+ break;
+ default:
+ break;
+ }
+ if (setup.transport_option[0] != '\0') {
+ url_fprintf(c->pb, ";%s", setup.transport_option);
+ }
+ url_fprintf(c->pb, "\r\n");
+
+
+ url_fprintf(c->pb, "\r\n");
+}
+
+
+/* find an rtp connection by using the session ID. Check consistency
+ with filename */
+static HTTPContext *find_rtp_session_with_url(const char *url,
+ const char *session_id)
+{
+ HTTPContext *rtp_c;
+ char path1[1024];
+ const char *path;
+ char buf[1024];
+ int s;
+
+ rtp_c = find_rtp_session(session_id);
+ if (!rtp_c)
+ return NULL;
+
+ /* find which url is asked */
+ url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
+ path = path1;
+ if (*path == '/')
+ path++;
+ if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
+ for(s=0; s<rtp_c->stream->nb_streams; ++s) {
+ snprintf(buf, sizeof(buf), "%s/streamid=%d",
+ rtp_c->stream->filename, s);
+ if(!strncmp(path, buf, sizeof(buf))) {
+ // XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE if nb_streams>1?
+ return rtp_c;
+ }
+ }
+ return NULL;
+}
+
+static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPHeader *h)
+{
+ HTTPContext *rtp_c;
+
+ rtp_c = find_rtp_session_with_url(url, h->session_id);
+ if (!rtp_c) {
+ rtsp_reply_error(c, RTSP_STATUS_SESSION);
+ return;
+ }
+
+ if (rtp_c->state != HTTPSTATE_SEND_DATA &&
+ rtp_c->state != HTTPSTATE_WAIT_FEED &&
+ rtp_c->state != HTTPSTATE_READY) {
+ rtsp_reply_error(c, RTSP_STATUS_STATE);
+ return;
+ }
+
+#if 0
+ /* XXX: seek in stream */
+ if (h->range_start != AV_NOPTS_VALUE) {
+ printf("range_start=%0.3f\n", (double)h->range_start / AV_TIME_BASE);
+ av_seek_frame(rtp_c->fmt_in, -1, h->range_start);
+ }
+#endif
+
+ rtp_c->state = HTTPSTATE_SEND_DATA;
+
+ /* now everything is OK, so we can send the connection parameters */
+ rtsp_reply_header(c, RTSP_STATUS_OK);
+ /* session ID */
+ url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
+ url_fprintf(c->pb, "\r\n");
+}
+
+static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPHeader *h)
+{
+ HTTPContext *rtp_c;
+
+ rtp_c = find_rtp_session_with_url(url, h->session_id);
+ if (!rtp_c) {
+ rtsp_reply_error(c, RTSP_STATUS_SESSION);
+ return;
+ }
+
+ if (rtp_c->state != HTTPSTATE_SEND_DATA &&
+ rtp_c->state != HTTPSTATE_WAIT_FEED) {
+ rtsp_reply_error(c, RTSP_STATUS_STATE);
+ return;
+ }
+
+ rtp_c->state = HTTPSTATE_READY;
+ rtp_c->first_pts = AV_NOPTS_VALUE;
+ /* now everything is OK, so we can send the connection parameters */
+ rtsp_reply_header(c, RTSP_STATUS_OK);
+ /* session ID */
+ url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
+ url_fprintf(c->pb, "\r\n");
+}
+
+static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPHeader *h)
+{
+ HTTPContext *rtp_c;
+
+ rtp_c = find_rtp_session_with_url(url, h->session_id);
+ if (!rtp_c) {
+ rtsp_reply_error(c, RTSP_STATUS_SESSION);
+ return;
+ }
+
+ /* abort the session */
+ close_connection(rtp_c);
+
+ if (ff_rtsp_callback) {
+ ff_rtsp_callback(RTSP_ACTION_SERVER_TEARDOWN, rtp_c->session_id,
+ NULL, 0,
+ rtp_c->stream->rtsp_option);
+ }
+
+ /* now everything is OK, so we can send the connection parameters */
+ rtsp_reply_header(c, RTSP_STATUS_OK);
+ /* session ID */
+ url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
+ url_fprintf(c->pb, "\r\n");
+}
+
+
+/********************************************************************/
+/* RTP handling */
+
+static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
+ FFStream *stream, const char *session_id,
+ enum RTSPProtocol rtp_protocol)
+{
+ HTTPContext *c = NULL;
+ const char *proto_str;
+
+ /* XXX: should output a warning page when coming
+ close to the connection limit */
+ if (nb_connections >= nb_max_connections)
+ goto fail;
+
+ /* add a new connection */
+ c = av_mallocz(sizeof(HTTPContext));
+ if (!c)
+ goto fail;
+
+ c->fd = -1;
+ c->poll_entry = NULL;
+ c->from_addr = *from_addr;
+ c->buffer_size = IOBUFFER_INIT_SIZE;
+ c->buffer = av_malloc(c->buffer_size);
+ if (!c->buffer)
+ goto fail;
+ nb_connections++;
+ c->stream = stream;
+ pstrcpy(c->session_id, sizeof(c->session_id), session_id);
+ c->state = HTTPSTATE_READY;
+ c->is_packetized = 1;
+ c->rtp_protocol = rtp_protocol;
+
+ /* protocol is shown in statistics */
+ switch(c->rtp_protocol) {
+ case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
+ proto_str = "MCAST";
+ break;
+ case RTSP_PROTOCOL_RTP_UDP:
+ proto_str = "UDP";
+ break;
+ case RTSP_PROTOCOL_RTP_TCP:
+ proto_str = "TCP";
+ break;
+ default:
+ proto_str = "???";
+ break;
+ }
+ pstrcpy(c->protocol, sizeof(c->protocol), "RTP/");
+ pstrcat(c->protocol, sizeof(c->protocol), proto_str);
+
+ current_bandwidth += stream->bandwidth;
+
+ c->next = first_http_ctx;
+ first_http_ctx = c;
+ return c;
+
+ fail:
+ if (c) {
+ av_free(c->buffer);
+ av_free(c);
+ }
+ return NULL;
+}
+
+/* add a new RTP stream in an RTP connection (used in RTSP SETUP
+ command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
+ used. */
+static int rtp_new_av_stream(HTTPContext *c,
+ int stream_index, struct sockaddr_in *dest_addr,
+ HTTPContext *rtsp_c)
+{
+ AVFormatContext *ctx;
+ AVStream *st;
+ char *ipaddr;
+ URLContext *h;
+ uint8_t *dummy_buf;
+ char buf2[32];
+ int max_packet_size;
+
+ /* now we can open the relevant output stream */
+ ctx = av_alloc_format_context();
+ if (!ctx)
+ return -1;
+ ctx->oformat = &rtp_muxer;
+
+ st = av_mallocz(sizeof(AVStream));
+ if (!st)
+ goto fail;
+ st->codec= avcodec_alloc_context();
+ ctx->nb_streams = 1;
+ ctx->streams[0] = st;
+
+ if (!c->stream->feed ||
+ c->stream->feed == c->stream) {
+ memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
+ } else {
+ memcpy(st,
+ c->stream->feed->streams[c->stream->feed_streams[stream_index]],
+ sizeof(AVStream));
+ }
+
+ /* build destination RTP address */
+ ipaddr = inet_ntoa(dest_addr->sin_addr);
+
+ switch(c->rtp_protocol) {
+ case RTSP_PROTOCOL_RTP_UDP:
+ case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
+ /* RTP/UDP case */
+
+ /* XXX: also pass as parameter to function ? */
+ if (c->stream->is_multicast) {
+ int ttl;
+ ttl = c->stream->multicast_ttl;
+ if (!ttl)
+ ttl = 16;
+ snprintf(ctx->filename, sizeof(ctx->filename),
+ "rtp://%s:%d?multicast=1&ttl=%d",
+ ipaddr, ntohs(dest_addr->sin_port), ttl);
+ } else {
+ snprintf(ctx->filename, sizeof(ctx->filename),
+ "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
+ }
+
+ if (url_open(&h, ctx->filename, URL_WRONLY) < 0)
+ goto fail;
+ c->rtp_handles[stream_index] = h;
+ max_packet_size = url_get_max_packet_size(h);
+ break;
+ case RTSP_PROTOCOL_RTP_TCP:
+ /* RTP/TCP case */
+ c->rtsp_c = rtsp_c;
+ max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
+ break;
+ default:
+ goto fail;
+ }
+
+ http_log("%s:%d - - [%s] \"PLAY %s/streamid=%d %s\"\n",
+ ipaddr, ntohs(dest_addr->sin_port),
+ ctime1(buf2),
+ c->stream->filename, stream_index, c->protocol);
+
+ /* normally, no packets should be output here, but the packet size may be checked */
+ if (url_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
+ /* XXX: close stream */
+ goto fail;
+ }
+ av_set_parameters(ctx, NULL);
+ if (av_write_header(ctx) < 0) {
+ fail:
+ if (h)
+ url_close(h);
+ av_free(ctx);
+ return -1;
+ }
+ url_close_dyn_buf(&ctx->pb, &dummy_buf);
+ av_free(dummy_buf);
+
+ c->rtp_ctx[stream_index] = ctx;
+ return 0;
+}
+
+/********************************************************************/
+/* ffserver initialization */
+
+static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec)
+{
+ AVStream *fst;
+
+ fst = av_mallocz(sizeof(AVStream));
+ if (!fst)
+ return NULL;
+ fst->codec= avcodec_alloc_context();
+ fst->priv_data = av_mallocz(sizeof(FeedData));
+ memcpy(fst->codec, codec, sizeof(AVCodecContext));
+ fst->codec->coded_frame = &dummy_frame;
+ fst->index = stream->nb_streams;
+ av_set_pts_info(fst, 33, 1, 90000);
+ stream->streams[stream->nb_streams++] = fst;
+ return fst;
+}
+
+/* return the stream number in the feed */
+static int add_av_stream(FFStream *feed, AVStream *st)
+{
+ AVStream *fst;
+ AVCodecContext *av, *av1;
+ int i;
+
+ av = st->codec;
+ for(i=0;i<feed->nb_streams;i++) {
+ st = feed->streams[i];
+ av1 = st->codec;
+ if (av1->codec_id == av->codec_id &&
+ av1->codec_type == av->codec_type &&
+ av1->bit_rate == av->bit_rate) {
+
+ switch(av->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ if (av1->channels == av->channels &&
+ av1->sample_rate == av->sample_rate)
+ goto found;
+ break;
+ case CODEC_TYPE_VIDEO:
+ if (av1->width == av->width &&
+ av1->height == av->height &&
+ av1->time_base.den == av->time_base.den &&
+ av1->time_base.num == av->time_base.num &&
+ av1->gop_size == av->gop_size)
+ goto found;
+ break;
+ default:
+ av_abort();
+ }
+ }
+ }
+
+ fst = add_av_stream1(feed, av);
+ if (!fst)
+ return -1;
+ return feed->nb_streams - 1;
+ found:
+ return i;
+}
+
+static void remove_stream(FFStream *stream)
+{
+ FFStream **ps;
+ ps = &first_stream;
+ while (*ps != NULL) {
+ if (*ps == stream) {
+ *ps = (*ps)->next;
+ } else {
+ ps = &(*ps)->next;
+ }
+ }
+}
+
+/* specific mpeg4 handling : we extract the raw parameters */
+static void extract_mpeg4_header(AVFormatContext *infile)
+{
+ int mpeg4_count, i, size;
+ AVPacket pkt;
+ AVStream *st;
+ const uint8_t *p;
+
+ mpeg4_count = 0;
+ for(i=0;i<infile->nb_streams;i++) {
+ st = infile->streams[i];
+ if (st->codec->codec_id == CODEC_ID_MPEG4 &&
+ st->codec->extradata_size == 0) {
+ mpeg4_count++;
+ }
+ }
+ if (!mpeg4_count)
+ return;
+
+ printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
+ while (mpeg4_count > 0) {
+ if (av_read_packet(infile, &pkt) < 0)
+ break;
+ st = infile->streams[pkt.stream_index];
+ if (st->codec->codec_id == CODEC_ID_MPEG4 &&
+ st->codec->extradata_size == 0) {
+ av_freep(&st->codec->extradata);
+ /* fill extradata with the header */
+ /* XXX: we make hard suppositions here ! */
+ p = pkt.data;
+ while (p < pkt.data + pkt.size - 4) {
+ /* stop when vop header is found */
+ if (p[0] == 0x00 && p[1] == 0x00 &&
+ p[2] == 0x01 && p[3] == 0xb6) {
+ size = p - pkt.data;
+ // av_hex_dump(pkt.data, size);
+ st->codec->extradata = av_malloc(size);
+ st->codec->extradata_size = size;
+ memcpy(st->codec->extradata, pkt.data, size);
+ break;
+ }
+ p++;
+ }
+ mpeg4_count--;
+ }
+ av_free_packet(&pkt);
+ }
+}
+
+/* compute the needed AVStream for each file */
+static void build_file_streams(void)
+{
+ FFStream *stream, *stream_next;
+ AVFormatContext *infile;
+ int i;
+
+ /* gather all streams */
+ for(stream = first_stream; stream != NULL; stream = stream_next) {
+ stream_next = stream->next;
+ if (stream->stream_type == STREAM_TYPE_LIVE &&
+ !stream->feed) {
+ /* the stream comes from a file */
+ /* try to open the file */
+ /* open stream */
+ stream->ap_in = av_mallocz(sizeof(AVFormatParameters));
+ if (stream->fmt == &rtp_muxer) {
+ /* specific case : if transport stream output to RTP,
+ we use a raw transport stream reader */
+ stream->ap_in->mpeg2ts_raw = 1;
+ stream->ap_in->mpeg2ts_compute_pcr = 1;
+ }
+
+ if (av_open_input_file(&infile, stream->feed_filename,
+ stream->ifmt, 0, stream->ap_in) < 0) {
+ http_log("%s not found", stream->feed_filename);
+ /* remove stream (no need to spend more time on it) */
+ fail:
+ remove_stream(stream);
+ } else {
+ /* find all the AVStreams inside and reference them in
+ 'stream' */
+ if (av_find_stream_info(infile) < 0) {
+ http_log("Could not find codec parameters from '%s'",
+ stream->feed_filename);
+ av_close_input_file(infile);
+ goto fail;
+ }
+ extract_mpeg4_header(infile);
+
+ for(i=0;i<infile->nb_streams;i++) {
+ add_av_stream1(stream, infile->streams[i]->codec);
+ }
+ av_close_input_file(infile);
+ }
+ }
+ }
+}
+
+/* compute the needed AVStream for each feed */
+static void build_feed_streams(void)
+{
+ FFStream *stream, *feed;
+ int i;
+
+ /* gather all streams */
+ for(stream = first_stream; stream != NULL; stream = stream->next) {
+ feed = stream->feed;
+ if (feed) {
+ if (!stream->is_feed) {
+ /* we handle a stream coming from a feed */
+ for(i=0;i<stream->nb_streams;i++) {
+ stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
+ }
+ }
+ }
+ }
+
+ /* gather all streams */
+ for(stream = first_stream; stream != NULL; stream = stream->next) {
+ feed = stream->feed;
+ if (feed) {
+ if (stream->is_feed) {
+ for(i=0;i<stream->nb_streams;i++) {
+ stream->feed_streams[i] = i;
+ }
+ }
+ }
+ }
+
+ /* create feed files if needed */
+ for(feed = first_feed; feed != NULL; feed = feed->next_feed) {
+ int fd;
+
+ if (url_exist(feed->feed_filename)) {
+ /* See if it matches */
+ AVFormatContext *s;
+ int matches = 0;
+
+ if (av_open_input_file(&s, feed->feed_filename, NULL, FFM_PACKET_SIZE, NULL) >= 0) {
+ /* Now see if it matches */
+ if (s->nb_streams == feed->nb_streams) {
+ matches = 1;
+ for(i=0;i<s->nb_streams;i++) {
+ AVStream *sf, *ss;
+ sf = feed->streams[i];
+ ss = s->streams[i];
+
+ if (sf->index != ss->index ||
+ sf->id != ss->id) {
+ printf("Index & Id do not match for stream %d (%s)\n",
+ i, feed->feed_filename);
+ matches = 0;
+ } else {
+ AVCodecContext *ccf, *ccs;
+
+ ccf = sf->codec;
+ ccs = ss->codec;
+#define CHECK_CODEC(x) (ccf->x != ccs->x)
+
+ if (CHECK_CODEC(codec) || CHECK_CODEC(codec_type)) {
+ printf("Codecs do not match for stream %d\n", i);
+ matches = 0;
+ } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
+ printf("Codec bitrates do not match for stream %d\n", i);
+ matches = 0;
+ } else if (ccf->codec_type == CODEC_TYPE_VIDEO) {
+ if (CHECK_CODEC(time_base.den) ||
+ CHECK_CODEC(time_base.num) ||
+ CHECK_CODEC(width) ||
+ CHECK_CODEC(height)) {
+ printf("Codec width, height and framerate do not match for stream %d\n", i);
+ matches = 0;
+ }
+ } else if (ccf->codec_type == CODEC_TYPE_AUDIO) {
+ if (CHECK_CODEC(sample_rate) ||
+ CHECK_CODEC(channels) ||
+ CHECK_CODEC(frame_size)) {
+ printf("Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
+ matches = 0;
+ }
+ } else {
+ printf("Unknown codec type\n");
+ matches = 0;
+ }
+ }
+ if (!matches) {
+ break;
+ }
+ }
+ } else {
+ printf("Deleting feed file '%s' as stream counts differ (%d != %d)\n",
+ feed->feed_filename, s->nb_streams, feed->nb_streams);
+ }
+
+ av_close_input_file(s);
+ } else {
+ printf("Deleting feed file '%s' as it appears to be corrupt\n",
+ feed->feed_filename);
+ }
+ if (!matches) {
+ if (feed->readonly) {
+ printf("Unable to delete feed file '%s' as it is marked readonly\n",
+ feed->feed_filename);
+ exit(1);
+ }
+ unlink(feed->feed_filename);
+ }
+ }
+ if (!url_exist(feed->feed_filename)) {
+ AVFormatContext s1, *s = &s1;
+
+ if (feed->readonly) {
+ printf("Unable to create feed file '%s' as it is marked readonly\n",
+ feed->feed_filename);
+ exit(1);
+ }
+
+ /* only write the header of the ffm file */
+ if (url_fopen(&s->pb, feed->feed_filename, URL_WRONLY) < 0) {
+ fprintf(stderr, "Could not open output feed file '%s'\n",
+ feed->feed_filename);
+ exit(1);
+ }
+ s->oformat = feed->fmt;
+ s->nb_streams = feed->nb_streams;
+ for(i=0;i<s->nb_streams;i++) {
+ AVStream *st;
+ st = feed->streams[i];
+ s->streams[i] = st;
+ }
+ av_set_parameters(s, NULL);
+ av_write_header(s);
+ /* XXX: need better api */
+ av_freep(&s->priv_data);
+ url_fclose(&s->pb);
+ }
+ /* get feed size and write index */
+ fd = open(feed->feed_filename, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Could not open output feed file '%s'\n",
+ feed->feed_filename);
+ exit(1);
+ }
+
+ feed->feed_write_index = ffm_read_write_index(fd);
+ feed->feed_size = lseek(fd, 0, SEEK_END);
+ /* ensure that we do not wrap before the end of file */
+ if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
+ feed->feed_max_size = feed->feed_size;
+
+ close(fd);
+ }
+}
+
+/* compute the bandwidth used by each stream */
+static void compute_bandwidth(void)
+{
+ int bandwidth, i;
+ FFStream *stream;
+
+ for(stream = first_stream; stream != NULL; stream = stream->next) {
+ bandwidth = 0;
+ for(i=0;i<stream->nb_streams;i++) {
+ AVStream *st = stream->streams[i];
+ switch(st->codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ case CODEC_TYPE_VIDEO:
+ bandwidth += st->codec->bit_rate;
+ break;
+ default:
+ break;
+ }
+ }
+ stream->bandwidth = (bandwidth + 999) / 1000;
+ }
+}
+
+static void get_arg(char *buf, int buf_size, const char **pp)
+{
+ const char *p;
+ char *q;
+ int quote;
+
+ p = *pp;
+ while (isspace(*p)) p++;
+ q = buf;
+ quote = 0;
+ if (*p == '\"' || *p == '\'')
+ quote = *p++;
+ for(;;) {
+ if (quote) {
+ if (*p == quote)
+ break;
+ } else {
+ if (isspace(*p))
+ break;
+ }
+ if (*p == '\0')
+ break;
+ if ((q - buf) < buf_size - 1)
+ *q++ = *p;
+ p++;
+ }
+ *q = '\0';
+ if (quote && *p == quote)
+ p++;
+ *pp = p;
+}
+
+/* add a codec and set the default parameters */
+static void add_codec(FFStream *stream, AVCodecContext *av)
+{
+ AVStream *st;
+
+ /* compute default parameters */
+ switch(av->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ if (av->bit_rate == 0)
+ av->bit_rate = 64000;
+ if (av->sample_rate == 0)
+ av->sample_rate = 22050;
+ if (av->channels == 0)
+ av->channels = 1;
+ break;
+ case CODEC_TYPE_VIDEO:
+ if (av->bit_rate == 0)
+ av->bit_rate = 64000;
+ if (av->time_base.num == 0){
+ av->time_base.den = 5;
+ av->time_base.num = 1;
+ }
+ if (av->width == 0 || av->height == 0) {
+ av->width = 160;
+ av->height = 128;
+ }
+ /* Bitrate tolerance is less for streaming */
+ if (av->bit_rate_tolerance == 0)
+ av->bit_rate_tolerance = av->bit_rate / 4;
+ if (av->qmin == 0)
+ av->qmin = 3;
+ if (av->qmax == 0)
+ av->qmax = 31;
+ if (av->max_qdiff == 0)
+ av->max_qdiff = 3;
+ av->qcompress = 0.5;
+ av->qblur = 0.5;
+
+ if (!av->nsse_weight)
+ av->nsse_weight = 8;
+
+ av->frame_skip_cmp = FF_CMP_DCTMAX;
+ av->me_method = ME_EPZS;
+ av->rc_buffer_aggressivity = 1.0;
+
+ if (!av->rc_eq)
+ av->rc_eq = "tex^qComp";
+ if (!av->i_quant_factor)
+ av->i_quant_factor = -0.8;
+ if (!av->b_quant_factor)
+ av->b_quant_factor = 1.25;
+ if (!av->b_quant_offset)
+ av->b_quant_offset = 1.25;
+ if (!av->rc_max_rate)
+ av->rc_max_rate = av->bit_rate * 2;
+
+ if (av->rc_max_rate && !av->rc_buffer_size) {
+ av->rc_buffer_size = av->rc_max_rate;
+ }
+
+
+ break;
+ default:
+ av_abort();
+ }
+
+ st = av_mallocz(sizeof(AVStream));
+ if (!st)
+ return;
+ st->codec = avcodec_alloc_context();
+ stream->streams[stream->nb_streams++] = st;
+ memcpy(st->codec, av, sizeof(AVCodecContext));
+}
+
+static int opt_audio_codec(const char *arg)
+{
+ AVCodec *p;
+
+ p = first_avcodec;
+ while (p) {
+ if (!strcmp(p->name, arg) && p->type == CODEC_TYPE_AUDIO)
+ break;
+ p = p->next;
+ }
+ if (p == NULL) {
+ return CODEC_ID_NONE;
+ }
+
+ return p->id;
+}
+
+static int opt_video_codec(const char *arg)
+{
+ AVCodec *p;
+
+ p = first_avcodec;
+ while (p) {
+ if (!strcmp(p->name, arg) && p->type == CODEC_TYPE_VIDEO)
+ break;
+ p = p->next;
+ }
+ if (p == NULL) {
+ return CODEC_ID_NONE;
+ }
+
+ return p->id;
+}
+
+/* simplistic plugin support */
+
+#ifdef HAVE_DLOPEN
+static void load_module(const char *filename)
+{
+ void *dll;
+ void (*init_func)(void);
+ dll = dlopen(filename, RTLD_NOW);
+ if (!dll) {
+ fprintf(stderr, "Could not load module '%s' - %s\n",
+ filename, dlerror());
+ return;
+ }
+
+ init_func = dlsym(dll, "ffserver_module_init");
+ if (!init_func) {
+ fprintf(stderr,
+ "%s: init function 'ffserver_module_init()' not found\n",
+ filename);
+ dlclose(dll);
+ }
+
+ init_func();
+}
+#endif
+
+static int parse_ffconfig(const char *filename)
+{
+ FILE *f;
+ char line[1024];
+ char cmd[64];
+ char arg[1024];
+ const char *p;
+ int val, errors, line_num;
+ FFStream **last_stream, *stream, *redirect;
+ FFStream **last_feed, *feed;
+ AVCodecContext audio_enc, video_enc;
+ int audio_id, video_id;
+
+ f = fopen(filename, "r");
+ if (!f) {
+ perror(filename);
+ return -1;
+ }
+
+ errors = 0;
+ line_num = 0;
+ first_stream = NULL;
+ last_stream = &first_stream;
+ first_feed = NULL;
+ last_feed = &first_feed;
+ stream = NULL;
+ feed = NULL;
+ redirect = NULL;
+ audio_id = CODEC_ID_NONE;
+ video_id = CODEC_ID_NONE;
+ for(;;) {
+ if (fgets(line, sizeof(line), f) == NULL)
+ break;
+ line_num++;
+ p = line;
+ while (isspace(*p))
+ p++;
+ if (*p == '\0' || *p == '#')
+ continue;
+
+ get_arg(cmd, sizeof(cmd), &p);
+
+ if (!strcasecmp(cmd, "Port")) {
+ get_arg(arg, sizeof(arg), &p);
+ my_http_addr.sin_port = htons (atoi(arg));
+ } else if (!strcasecmp(cmd, "BindAddress")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (!inet_aton(arg, &my_http_addr.sin_addr)) {
+ fprintf(stderr, "%s:%d: Invalid IP address: %s\n",
+ filename, line_num, arg);
+ errors++;
+ }
+ } else if (!strcasecmp(cmd, "NoDaemon")) {
+ ffserver_daemon = 0;
+ } else if (!strcasecmp(cmd, "RTSPPort")) {
+ get_arg(arg, sizeof(arg), &p);
+ my_rtsp_addr.sin_port = htons (atoi(arg));
+ } else if (!strcasecmp(cmd, "RTSPBindAddress")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (!inet_aton(arg, &my_rtsp_addr.sin_addr)) {
+ fprintf(stderr, "%s:%d: Invalid IP address: %s\n",
+ filename, line_num, arg);
+ errors++;
+ }
+ } else if (!strcasecmp(cmd, "MaxClients")) {
+ get_arg(arg, sizeof(arg), &p);
+ val = atoi(arg);
+ if (val < 1 || val > HTTP_MAX_CONNECTIONS) {
+ fprintf(stderr, "%s:%d: Invalid MaxClients: %s\n",
+ filename, line_num, arg);
+ errors++;
+ } else {
+ nb_max_connections = val;
+ }
+ } else if (!strcasecmp(cmd, "MaxBandwidth")) {
+ get_arg(arg, sizeof(arg), &p);
+ val = atoi(arg);
+ if (val < 10 || val > 100000) {
+ fprintf(stderr, "%s:%d: Invalid MaxBandwidth: %s\n",
+ filename, line_num, arg);
+ errors++;
+ } else {
+ max_bandwidth = val;
+ }
+ } else if (!strcasecmp(cmd, "CustomLog")) {
+ get_arg(logfilename, sizeof(logfilename), &p);
+ } else if (!strcasecmp(cmd, "<Feed")) {
+ /*********************************************/
+ /* Feed related options */
+ char *q;
+ if (stream || feed) {
+ fprintf(stderr, "%s:%d: Already in a tag\n",
+ filename, line_num);
+ } else {
+ feed = av_mallocz(sizeof(FFStream));
+ /* add in stream list */
+ *last_stream = feed;
+ last_stream = &feed->next;
+ /* add in feed list */
+ *last_feed = feed;
+ last_feed = &feed->next_feed;
+
+ get_arg(feed->filename, sizeof(feed->filename), &p);
+ q = strrchr(feed->filename, '>');
+ if (*q)
+ *q = '\0';
+ feed->fmt = guess_format("ffm", NULL, NULL);
+ /* defaut feed file */
+ snprintf(feed->feed_filename, sizeof(feed->feed_filename),
+ "/tmp/%s.ffm", feed->filename);
+ feed->feed_max_size = 5 * 1024 * 1024;
+ feed->is_feed = 1;
+ feed->feed = feed; /* self feeding :-) */
+ }
+ } else if (!strcasecmp(cmd, "Launch")) {
+ if (feed) {
+ int i;
+
+ feed->child_argv = (char **) av_mallocz(64 * sizeof(char *));
+
+ for (i = 0; i < 62; i++) {
+ char argbuf[256];
+
+ get_arg(argbuf, sizeof(argbuf), &p);
+ if (!argbuf[0])
+ break;
+
+ feed->child_argv[i] = av_malloc(strlen(argbuf) + 1);
+ strcpy(feed->child_argv[i], argbuf);
+ }
+
+ feed->child_argv[i] = av_malloc(30 + strlen(feed->filename));
+
+ snprintf(feed->child_argv[i], 30+strlen(feed->filename),
+ "http://%s:%d/%s",
+ (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
+ inet_ntoa(my_http_addr.sin_addr),
+ ntohs(my_http_addr.sin_port), feed->filename);
+
+ if (ffserver_debug)
+ {
+ int j;
+ fprintf(stdout, "Launch commandline: ");
+ for (j = 0; j <= i; j++)
+ fprintf(stdout, "%s ", feed->child_argv[j]);
+ fprintf(stdout, "\n");
+ }
+ }
+ } else if (!strcasecmp(cmd, "ReadOnlyFile")) {
+ if (feed) {
+ get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
+ feed->readonly = 1;
+ } else if (stream) {
+ get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
+ }
+ } else if (!strcasecmp(cmd, "File")) {
+ if (feed) {
+ get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
+ } else if (stream) {
+ get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
+ }
+ } else if (!strcasecmp(cmd, "FileMaxSize")) {
+ if (feed) {
+ const char *p1;
+ double fsize;
+
+ get_arg(arg, sizeof(arg), &p);
+ p1 = arg;
+ fsize = strtod(p1, (char **)&p1);
+ switch(toupper(*p1)) {
+ case 'K':
+ fsize *= 1024;
+ break;
+ case 'M':
+ fsize *= 1024 * 1024;
+ break;
+ case 'G':
+ fsize *= 1024 * 1024 * 1024;
+ break;
+ }
+ feed->feed_max_size = (int64_t)fsize;
+ }
+ } else if (!strcasecmp(cmd, "</Feed>")) {
+ if (!feed) {
+ fprintf(stderr, "%s:%d: No corresponding <Feed> for </Feed>\n",
+ filename, line_num);
+ errors++;
+#if 0
+ } else {
+ /* Make sure that we start out clean */
+ if (unlink(feed->feed_filename) < 0
+ && errno != ENOENT) {
+ fprintf(stderr, "%s:%d: Unable to clean old feed file '%s': %s\n",
+ filename, line_num, feed->feed_filename, strerror(errno));
+ errors++;
+ }
+#endif
+ }
+ feed = NULL;
+ } else if (!strcasecmp(cmd, "<Stream")) {
+ /*********************************************/
+ /* Stream related options */
+ char *q;
+ if (stream || feed) {
+ fprintf(stderr, "%s:%d: Already in a tag\n",
+ filename, line_num);
+ } else {
+ stream = av_mallocz(sizeof(FFStream));
+ *last_stream = stream;
+ last_stream = &stream->next;
+
+ get_arg(stream->filename, sizeof(stream->filename), &p);
+ q = strrchr(stream->filename, '>');
+ if (*q)
+ *q = '\0';
+ stream->fmt = guess_stream_format(NULL, stream->filename, NULL);
+ memset(&audio_enc, 0, sizeof(AVCodecContext));
+ memset(&video_enc, 0, sizeof(AVCodecContext));
+ audio_id = CODEC_ID_NONE;
+ video_id = CODEC_ID_NONE;
+ if (stream->fmt) {
+ audio_id = stream->fmt->audio_codec;
+ video_id = stream->fmt->video_codec;
+ }
+ }
+ } else if (!strcasecmp(cmd, "Feed")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ FFStream *sfeed;
+
+ sfeed = first_feed;
+ while (sfeed != NULL) {
+ if (!strcmp(sfeed->filename, arg))
+ break;
+ sfeed = sfeed->next_feed;
+ }
+ if (!sfeed) {
+ fprintf(stderr, "%s:%d: feed '%s' not defined\n",
+ filename, line_num, arg);
+ } else {
+ stream->feed = sfeed;
+ }
+ }
+ } else if (!strcasecmp(cmd, "Format")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (!strcmp(arg, "status")) {
+ stream->stream_type = STREAM_TYPE_STATUS;
+ stream->fmt = NULL;
+ } else {
+ stream->stream_type = STREAM_TYPE_LIVE;
+ /* jpeg cannot be used here, so use single frame jpeg */
+ if (!strcmp(arg, "jpeg"))
+ strcpy(arg, "mjpeg");
+ stream->fmt = guess_stream_format(arg, NULL, NULL);
+ if (!stream->fmt) {
+ fprintf(stderr, "%s:%d: Unknown Format: %s\n",
+ filename, line_num, arg);
+ errors++;
+ }
+ }
+ if (stream->fmt) {
+ audio_id = stream->fmt->audio_codec;
+ video_id = stream->fmt->video_codec;
+ }
+ } else if (!strcasecmp(cmd, "InputFormat")) {
+ stream->ifmt = av_find_input_format(arg);
+ if (!stream->ifmt) {
+ fprintf(stderr, "%s:%d: Unknown input format: %s\n",
+ filename, line_num, arg);
+ }
+ } else if (!strcasecmp(cmd, "FaviconURL")) {
+ if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
+ get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
+ } else {
+ fprintf(stderr, "%s:%d: FaviconURL only permitted for status streams\n",
+ filename, line_num);
+ errors++;
+ }
+ } else if (!strcasecmp(cmd, "Author")) {
+ if (stream) {
+ get_arg(stream->author, sizeof(stream->author), &p);
+ }
+ } else if (!strcasecmp(cmd, "Comment")) {
+ if (stream) {
+ get_arg(stream->comment, sizeof(stream->comment), &p);
+ }
+ } else if (!strcasecmp(cmd, "Copyright")) {
+ if (stream) {
+ get_arg(stream->copyright, sizeof(stream->copyright), &p);
+ }
+ } else if (!strcasecmp(cmd, "Title")) {
+ if (stream) {
+ get_arg(stream->title, sizeof(stream->title), &p);
+ }
+ } else if (!strcasecmp(cmd, "Preroll")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ stream->prebuffer = atof(arg) * 1000;
+ }
+ } else if (!strcasecmp(cmd, "StartSendOnKey")) {
+ if (stream) {
+ stream->send_on_key = 1;
+ }
+ } else if (!strcasecmp(cmd, "AudioCodec")) {
+ get_arg(arg, sizeof(arg), &p);
+ audio_id = opt_audio_codec(arg);
+ if (audio_id == CODEC_ID_NONE) {
+ fprintf(stderr, "%s:%d: Unknown AudioCodec: %s\n",
+ filename, line_num, arg);
+ errors++;
+ }
+ } else if (!strcasecmp(cmd, "VideoCodec")) {
+ get_arg(arg, sizeof(arg), &p);
+ video_id = opt_video_codec(arg);
+ if (video_id == CODEC_ID_NONE) {
+ fprintf(stderr, "%s:%d: Unknown VideoCodec: %s\n",
+ filename, line_num, arg);
+ errors++;
+ }
+ } else if (!strcasecmp(cmd, "MaxTime")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ stream->max_time = atof(arg) * 1000;
+ }
+ } else if (!strcasecmp(cmd, "AudioBitRate")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ audio_enc.bit_rate = atoi(arg) * 1000;
+ }
+ } else if (!strcasecmp(cmd, "AudioChannels")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ audio_enc.channels = atoi(arg);
+ }
+ } else if (!strcasecmp(cmd, "AudioSampleRate")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ audio_enc.sample_rate = atoi(arg);
+ }
+ } else if (!strcasecmp(cmd, "AudioQuality")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+// audio_enc.quality = atof(arg) * 1000;
+ }
+ } else if (!strcasecmp(cmd, "VideoBitRateRange")) {
+ if (stream) {
+ int minrate, maxrate;
+
+ get_arg(arg, sizeof(arg), &p);
+
+ if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
+ video_enc.rc_min_rate = minrate * 1000;
+ video_enc.rc_max_rate = maxrate * 1000;
+ } else {
+ fprintf(stderr, "%s:%d: Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n",
+ filename, line_num, arg);
+ errors++;
+ }
+ }
+ } else if (!strcasecmp(cmd, "Debug")) {
+ if (stream) {
+ get_arg(arg, sizeof(arg), &p);
+ video_enc.debug = strtol(arg,0,0);
+ }
+ } else if (!strcasecmp(cmd, "Strict")) {
+ if (stream) {
+ get_arg(arg, sizeof(arg), &p);
+ video_enc.strict_std_compliance = atoi(arg);
+ }
+ } else if (!strcasecmp(cmd, "VideoBufferSize")) {
+ if (stream) {
+ get_arg(arg, sizeof(arg), &p);
+ video_enc.rc_buffer_size = atoi(arg) * 8*1024;
+ }
+ } else if (!strcasecmp(cmd, "VideoBitRateTolerance")) {
+ if (stream) {
+ get_arg(arg, sizeof(arg), &p);
+ video_enc.bit_rate_tolerance = atoi(arg) * 1000;
+ }
+ } else if (!strcasecmp(cmd, "VideoBitRate")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ video_enc.bit_rate = atoi(arg) * 1000;
+ }
+ } else if (!strcasecmp(cmd, "VideoSize")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ parse_image_size(&video_enc.width, &video_enc.height, arg);
+ if ((video_enc.width % 16) != 0 ||
+ (video_enc.height % 16) != 0) {
+ fprintf(stderr, "%s:%d: Image size must be a multiple of 16\n",
+ filename, line_num);
+ errors++;
+ }
+ }
+ } else if (!strcasecmp(cmd, "VideoFrameRate")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ video_enc.time_base.num= DEFAULT_FRAME_RATE_BASE;
+ video_enc.time_base.den = (int)(strtod(arg, NULL) * video_enc.time_base.num);
+ }
+ } else if (!strcasecmp(cmd, "VideoGopSize")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ video_enc.gop_size = atoi(arg);
+ }
+ } else if (!strcasecmp(cmd, "VideoIntraOnly")) {
+ if (stream) {
+ video_enc.gop_size = 1;
+ }
+ } else if (!strcasecmp(cmd, "VideoHighQuality")) {
+ if (stream) {
+ video_enc.mb_decision = FF_MB_DECISION_BITS;
+ }
+ } else if (!strcasecmp(cmd, "Video4MotionVector")) {
+ if (stream) {
+ video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
+ video_enc.flags |= CODEC_FLAG_4MV;
+ }
+ } else if (!strcasecmp(cmd, "BitExact")) {
+ if (stream) {
+ video_enc.flags |= CODEC_FLAG_BITEXACT;
+ }
+ } else if (!strcasecmp(cmd, "DctFastint")) {
+ if (stream) {
+ video_enc.dct_algo = FF_DCT_FASTINT;
+ }
+ } else if (!strcasecmp(cmd, "IdctSimple")) {
+ if (stream) {
+ video_enc.idct_algo = FF_IDCT_SIMPLE;
+ }
+ } else if (!strcasecmp(cmd, "Qscale")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ video_enc.flags |= CODEC_FLAG_QSCALE;
+ video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
+ }
+ } else if (!strcasecmp(cmd, "VideoQDiff")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ video_enc.max_qdiff = atoi(arg);
+ if (video_enc.max_qdiff < 1 || video_enc.max_qdiff > 31) {
+ fprintf(stderr, "%s:%d: VideoQDiff out of range\n",
+ filename, line_num);
+ errors++;
+ }
+ }
+ } else if (!strcasecmp(cmd, "VideoQMax")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ video_enc.qmax = atoi(arg);
+ if (video_enc.qmax < 1 || video_enc.qmax > 31) {
+ fprintf(stderr, "%s:%d: VideoQMax out of range\n",
+ filename, line_num);
+ errors++;
+ }
+ }
+ } else if (!strcasecmp(cmd, "VideoQMin")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ video_enc.qmin = atoi(arg);
+ if (video_enc.qmin < 1 || video_enc.qmin > 31) {
+ fprintf(stderr, "%s:%d: VideoQMin out of range\n",
+ filename, line_num);
+ errors++;
+ }
+ }
+ } else if (!strcasecmp(cmd, "LumaElim")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ video_enc.luma_elim_threshold = atoi(arg);
+ }
+ } else if (!strcasecmp(cmd, "ChromaElim")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ video_enc.chroma_elim_threshold = atoi(arg);
+ }
+ } else if (!strcasecmp(cmd, "LumiMask")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ video_enc.lumi_masking = atof(arg);
+ }
+ } else if (!strcasecmp(cmd, "DarkMask")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ video_enc.dark_masking = atof(arg);
+ }
+ } else if (!strcasecmp(cmd, "NoVideo")) {
+ video_id = CODEC_ID_NONE;
+ } else if (!strcasecmp(cmd, "NoAudio")) {
+ audio_id = CODEC_ID_NONE;
+ } else if (!strcasecmp(cmd, "ACL")) {
+ IPAddressACL acl;
+ struct hostent *he;
+
+ get_arg(arg, sizeof(arg), &p);
+ if (strcasecmp(arg, "allow") == 0) {
+ acl.action = IP_ALLOW;
+ } else if (strcasecmp(arg, "deny") == 0) {
+ acl.action = IP_DENY;
+ } else {
+ fprintf(stderr, "%s:%d: ACL action '%s' is not ALLOW or DENY\n",
+ filename, line_num, arg);
+ errors++;
+ }
+
+ get_arg(arg, sizeof(arg), &p);
+
+ he = gethostbyname(arg);
+ if (!he) {
+ fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
+ filename, line_num, arg);
+ errors++;
+ } else {
+ /* Only take the first */
+ acl.first.s_addr = ntohl(((struct in_addr *) he->h_addr_list[0])->s_addr);
+ acl.last = acl.first;
+ }
+
+ get_arg(arg, sizeof(arg), &p);
+
+ if (arg[0]) {
+ he = gethostbyname(arg);
+ if (!he) {
+ fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
+ filename, line_num, arg);
+ errors++;
+ } else {
+ /* Only take the first */
+ acl.last.s_addr = ntohl(((struct in_addr *) he->h_addr_list[0])->s_addr);
+ }
+ }
+
+ if (!errors) {
+ IPAddressACL *nacl = (IPAddressACL *) av_mallocz(sizeof(*nacl));
+ IPAddressACL **naclp = 0;
+
+ *nacl = acl;
+ nacl->next = 0;
+
+ if (stream) {
+ naclp = &stream->acl;
+ } else if (feed) {
+ naclp = &feed->acl;
+ } else {
+ fprintf(stderr, "%s:%d: ACL found not in <stream> or <feed>\n",
+ filename, line_num);
+ errors++;
+ }
+
+ if (naclp) {
+ while (*naclp)
+ naclp = &(*naclp)->next;
+
+ *naclp = nacl;
+ }
+ }
+ } else if (!strcasecmp(cmd, "RTSPOption")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ av_freep(&stream->rtsp_option);
+ /* XXX: av_strdup ? */
+ stream->rtsp_option = av_malloc(strlen(arg) + 1);
+ if (stream->rtsp_option) {
+ strcpy(stream->rtsp_option, arg);
+ }
+ }
+ } else if (!strcasecmp(cmd, "MulticastAddress")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ if (!inet_aton(arg, &stream->multicast_ip)) {
+ fprintf(stderr, "%s:%d: Invalid IP address: %s\n",
+ filename, line_num, arg);
+ errors++;
+ }
+ stream->is_multicast = 1;
+ stream->loop = 1; /* default is looping */
+ }
+ } else if (!strcasecmp(cmd, "MulticastPort")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ stream->multicast_port = atoi(arg);
+ }
+ } else if (!strcasecmp(cmd, "MulticastTTL")) {
+ get_arg(arg, sizeof(arg), &p);
+ if (stream) {
+ stream->multicast_ttl = atoi(arg);
+ }
+ } else if (!strcasecmp(cmd, "NoLoop")) {
+ if (stream) {
+ stream->loop = 0;
+ }
+ } else if (!strcasecmp(cmd, "</Stream>")) {
+ if (!stream) {
+ fprintf(stderr, "%s:%d: No corresponding <Stream> for </Stream>\n",
+ filename, line_num);
+ errors++;
+ }
+ if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
+ if (audio_id != CODEC_ID_NONE) {
+ audio_enc.codec_type = CODEC_TYPE_AUDIO;
+ audio_enc.codec_id = audio_id;
+ add_codec(stream, &audio_enc);
+ }
+ if (video_id != CODEC_ID_NONE) {
+ video_enc.codec_type = CODEC_TYPE_VIDEO;
+ video_enc.codec_id = video_id;
+ add_codec(stream, &video_enc);
+ }
+ }
+ stream = NULL;
+ } else if (!strcasecmp(cmd, "<Redirect")) {
+ /*********************************************/
+ char *q;
+ if (stream || feed || redirect) {
+ fprintf(stderr, "%s:%d: Already in a tag\n",
+ filename, line_num);
+ errors++;
+ } else {
+ redirect = av_mallocz(sizeof(FFStream));
+ *last_stream = redirect;
+ last_stream = &redirect->next;
+
+ get_arg(redirect->filename, sizeof(redirect->filename), &p);
+ q = strrchr(redirect->filename, '>');
+ if (*q)
+ *q = '\0';
+ redirect->stream_type = STREAM_TYPE_REDIRECT;
+ }
+ } else if (!strcasecmp(cmd, "URL")) {
+ if (redirect) {
+ get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
+ }
+ } else if (!strcasecmp(cmd, "</Redirect>")) {
+ if (!redirect) {
+ fprintf(stderr, "%s:%d: No corresponding <Redirect> for </Redirect>\n",
+ filename, line_num);
+ errors++;
+ }
+ if (!redirect->feed_filename[0]) {
+ fprintf(stderr, "%s:%d: No URL found for <Redirect>\n",
+ filename, line_num);
+ errors++;
+ }
+ redirect = NULL;
+ } else if (!strcasecmp(cmd, "LoadModule")) {
+ get_arg(arg, sizeof(arg), &p);
+#ifdef HAVE_DLOPEN
+ load_module(arg);
+#else
+ fprintf(stderr, "%s:%d: Module support not compiled into this version: '%s'\n",
+ filename, line_num, arg);
+ errors++;
+#endif
+ } else {
+ fprintf(stderr, "%s:%d: Incorrect keyword: '%s'\n",
+ filename, line_num, cmd);
+ errors++;
+ }
+ }
+
+ fclose(f);
+ if (errors)
+ return -1;
+ else
+ return 0;
+}
+
+
+#if 0
+static void write_packet(FFCodec *ffenc,
+ uint8_t *buf, int size)
+{
+ PacketHeader hdr;
+ AVCodecContext *enc = &ffenc->enc;
+ uint8_t *wptr;
+ mk_header(&hdr, enc, size);
+ wptr = http_fifo.wptr;
+ fifo_write(&http_fifo, (uint8_t *)&hdr, sizeof(hdr), &wptr);
+ fifo_write(&http_fifo, buf, size, &wptr);
+ /* atomic modification of wptr */
+ http_fifo.wptr = wptr;
+ ffenc->data_count += size;
+ ffenc->avg_frame_size = ffenc->avg_frame_size * AVG_COEF + size * (1.0 - AVG_COEF);
+}
+#endif
+
+static void show_banner(void)
+{
+ printf("ffserver version " FFMPEG_VERSION ", Copyright (c) 2000-2006 Fabrice Bellard, et al.\n");
+}
+
+static void show_help(void)
+{
+ show_banner();
+ printf("usage: ffserver [-L] [-h] [-f configfile]\n"
+ "Hyper fast multi format Audio/Video streaming server\n"
+ "\n"
+ "-L : print the LICENSE\n"
+ "-h : this help\n"
+ "-f configfile : use configfile instead of /etc/ffserver.conf\n"
+ );
+}
+
+static void show_license(void)
+{
+ show_banner();
+ printf(
+ "FFmpeg is free software; you can redistribute it and/or\n"
+ "modify it under the terms of the GNU Lesser General Public\n"
+ "License as published by the Free Software Foundation; either\n"
+ "version 2.1 of the License, or (at your option) any later version.\n"
+ "\n"
+ "FFmpeg is distributed in the hope that it will be useful,\n"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
+ "Lesser General Public License for more details.\n"
+ "\n"
+ "You should have received a copy of the GNU Lesser General Public\n"
+ "License along with FFmpeg; if not, write to the Free Software\n"
+ "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
+ );
+}
+
+static void handle_child_exit(int sig)
+{
+ pid_t pid;
+ int status;
+
+ while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+ FFStream *feed;
+
+ for (feed = first_feed; feed; feed = feed->next) {
+ if (feed->pid == pid) {
+ int uptime = time(0) - feed->pid_start;
+
+ feed->pid = 0;
+ fprintf(stderr, "%s: Pid %d exited with status %d after %d seconds\n", feed->filename, pid, status, uptime);
+
+ if (uptime < 30) {
+ /* Turn off any more restarts */
+ feed->child_argv = 0;
+ }
+ }
+ }
+ }
+
+ need_to_start_children = 1;
+}
+
+int main(int argc, char **argv)
+{
+ const char *config_filename;
+ int c;
+ struct sigaction sigact;
+
+ av_register_all();
+
+ config_filename = "/etc/ffserver.conf";
+
+ my_program_name = argv[0];
+ my_program_dir = getcwd(0, 0);
+ ffserver_daemon = 1;
+
+ for(;;) {
+ c = getopt(argc, argv, "ndLh?f:");
+ if (c == -1)
+ break;
+ switch(c) {
+ case 'L':
+ show_license();
+ exit(1);
+ case '?':
+ case 'h':
+ show_help();
+ exit(1);
+ case 'n':
+ no_launch = 1;
+ break;
+ case 'd':
+ ffserver_debug = 1;
+ ffserver_daemon = 0;
+ break;
+ case 'f':
+ config_filename = optarg;
+ break;
+ default:
+ exit(2);
+ }
+ }
+
+ putenv("http_proxy"); /* Kill the http_proxy */
+
+ srandom(gettime_ms() + (getpid() << 16));
+
+ /* address on which the server will handle HTTP connections */
+ my_http_addr.sin_family = AF_INET;
+ my_http_addr.sin_port = htons (8080);
+ my_http_addr.sin_addr.s_addr = htonl (INADDR_ANY);
+
+ /* address on which the server will handle RTSP connections */
+ my_rtsp_addr.sin_family = AF_INET;
+ my_rtsp_addr.sin_port = htons (5454);
+ my_rtsp_addr.sin_addr.s_addr = htonl (INADDR_ANY);
+
+ nb_max_connections = 5;
+ max_bandwidth = 1000;
+ first_stream = NULL;
+ logfilename[0] = '\0';
+
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_handler = handle_child_exit;
+ sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
+ sigaction(SIGCHLD, &sigact, 0);
+
+ if (parse_ffconfig(config_filename) < 0) {
+ fprintf(stderr, "Incorrect config file - exiting.\n");
+ exit(1);
+ }
+
+ build_file_streams();
+
+ build_feed_streams();
+
+ compute_bandwidth();
+
+ /* put the process in background and detach it from its TTY */
+ if (ffserver_daemon) {
+ int pid;
+
+ pid = fork();
+ if (pid < 0) {
+ perror("fork");
+ exit(1);
+ } else if (pid > 0) {
+ /* parent : exit */
+ exit(0);
+ } else {
+ /* child */
+ setsid();
+ chdir("/");
+ close(0);
+ open("/dev/null", O_RDWR);
+ if (strcmp(logfilename, "-") != 0) {
+ close(1);
+ dup(0);
+ }
+ close(2);
+ dup(0);
+ }
+ }
+
+ /* signal init */
+ signal(SIGPIPE, SIG_IGN);
+
+ /* open log file if needed */
+ if (logfilename[0] != '\0') {
+ if (!strcmp(logfilename, "-"))
+ logfile = stdout;
+ else
+ logfile = fopen(logfilename, "w");
+ }
+
+ if (http_server() < 0) {
+ fprintf(stderr, "Could not start server\n");
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/contrib/ffmpeg/ffserver.h b/contrib/ffmpeg/ffserver.h
new file mode 100644
index 000000000..868e4cd9b
--- /dev/null
+++ b/contrib/ffmpeg/ffserver.h
@@ -0,0 +1,8 @@
+#ifndef FFSERVER_H
+#define FFSERVER_H
+
+/* interface between ffserver and modules */
+
+void ffserver_module_init(void);
+
+#endif
diff --git a/contrib/ffmpeg/libavcodec/4xm.c b/contrib/ffmpeg/libavcodec/4xm.c
new file mode 100644
index 000000000..ea60e9bf2
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/4xm.c
@@ -0,0 +1,759 @@
+/*
+ * 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.c
+ * 4XM codec.
+ */
+
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+//#undef NDEBUG
+//#include <assert.h>
+
+#define BLOCK_TYPE_VLC_BITS 5
+#define ACDC_VLC_BITS 9
+
+#define CFRAME_BUFFER_COUNT 100
+
+static const uint8_t block_type_tab[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}x1
+ { 0,1}, { 0,0}, { 2,2}, { 6,3}, {14,4}, {15,4}, { 0,0}
+ },{ //1x{8,4}
+ { 0,1}, { 2,2}, { 0,0}, { 6,3}, {14,4}, {15,4}, { 0,0}
+ },{ //1x2, 2x1
+ { 0,1}, { 0,0}, { 0,0}, { 2,2}, { 6,3}, {14,4}, {15,4}
+ }
+};
+
+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[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;
+ uint8_t *bytestream;
+ uint16_t *wordstream;
+ int mv[256];
+ VLC pre_vlc;
+ int last_dc;
+ DECLARE_ALIGNED_8(DCTELEM, block[6][64]);
+ uint8_t *bitstream_buffer;
+ unsigned int bitstream_buffer_size;
+ 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(DCTELEM 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 void init_vlcs(FourXContext *f){
+ int i;
+
+ for(i=0; i<4; i++){
+ init_vlc(&block_type_vlc[i], BLOCK_TYPE_VLC_BITS, 7,
+ &block_type_tab[i][0][1], 2, 1,
+ &block_type_tab[i][0][0], 2, 1, 1);
+ }
+}
+
+static void init_mv(FourXContext *f){
+ int i;
+
+ for(i=0; i<256; i++){
+ f->mv[i] = mv[i][0] + mv[i][1]*f->current_picture.linesize[0]/2;
+ }
+}
+
+static inline void mcdc(uint16_t *dst, uint16_t *src, int log2w, int h, int stride, int scale, int 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++){
+ ((uint32_t*)dst)[0] = scale*((uint32_t*)src)[0] + dc;
+ if(scale) src += stride;
+ dst += stride;
+ }
+ break;
+ case 2:
+ for(i=0; i<h; i++){
+ ((uint32_t*)dst)[0] = scale*((uint32_t*)src)[0] + dc;
+ ((uint32_t*)dst)[1] = scale*((uint32_t*)src)[1] + dc;
+ if(scale) src += stride;
+ dst += stride;
+ }
+ break;
+ case 3:
+ for(i=0; i<h; i++){
+ ((uint32_t*)dst)[0] = scale*((uint32_t*)src)[0] + dc;
+ ((uint32_t*)dst)[1] = scale*((uint32_t*)src)[1] + dc;
+ ((uint32_t*)dst)[2] = scale*((uint32_t*)src)[2] + dc;
+ ((uint32_t*)dst)[3] = scale*((uint32_t*)src)[3] + dc;
+ if(scale) src += stride;
+ dst += stride;
+ }
+ break;
+ default: assert(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[index].table, BLOCK_TYPE_VLC_BITS, 1);
+
+ assert(code>=0 && code<=6);
+
+ if(code == 0){
+ src += f->mv[ *f->bytestream++ ];
+ 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 == 4){
+ src += f->mv[ *f->bytestream++ ];
+ mcdc(dst, src, log2w, h, stride, 1, le2me_16(*f->wordstream++));
+ }else if(code == 5){
+ mcdc(dst, src, log2w, h, stride, 0, le2me_16(*f->wordstream++));
+ }else if(code == 6){
+ if(log2w){
+ dst[0] = le2me_16(*f->wordstream++);
+ dst[1] = le2me_16(*f->wordstream++);
+ }else{
+ dst[0 ] = le2me_16(*f->wordstream++);
+ dst[stride] = le2me_16(*f->wordstream++);
+ }
+ }
+}
+
+static int get32(void *p){
+ return le2me_32(*(uint32_t*)p);
+}
+
+static int decode_p_frame(FourXContext *f, 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*)f->current_picture.data[0];
+ const int stride= f->current_picture.linesize[0]>>1;
+ const unsigned int bitstream_size= get32(buf+8);
+ const unsigned int bytestream_size= get32(buf+16);
+ const unsigned int wordstream_size= get32(buf+12);
+
+ if(bitstream_size+ bytestream_size+ wordstream_size + 20 != length
+ || bitstream_size > (1<<26)
+ || bytestream_size > (1<<26)
+ || wordstream_size > (1<<26)
+ ){
+ 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 -1;
+ }
+
+ f->bitstream_buffer= av_fast_realloc(f->bitstream_buffer, &f->bitstream_buffer_size, bitstream_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ f->dsp.bswap_buf((uint32_t*)f->bitstream_buffer, (uint32_t*)(buf + 20), bitstream_size/4);
+ init_get_bits(&f->gb, f->bitstream_buffer, 8*bitstream_size);
+
+ f->wordstream= (uint16_t*)(buf + 20 + bitstream_size);
+ f->bytestream= buf + 20 + bitstream_size + wordstream_size;
+
+ init_mv(f);
+
+ 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;
+ }
+
+ if(bitstream_size != (get_bits_count(&f->gb)+31)/32*4)
+ av_log(f->avctx, AV_LOG_ERROR, " %d %td %td bytes left\n",
+ bitstream_size - (get_bits_count(&f->gb)+31)/32*4,
+ bytestream_size - (f->bytestream - (buf + 20 + bitstream_size + wordstream_size)),
+ wordstream_size - (((uint8_t*)f->wordstream) - (buf + 20 + bitstream_size))
+ );
+
+ return 0;
+}
+
+/**
+ * decode block and dequantize.
+ * Note this is allmost identical to mjpeg
+ */
+static int decode_i_block(FourXContext *f, DCTELEM *block){
+ int code, i, j, level, val;
+
+ /* 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, int x, int y){
+ DCTELEM (*block)[64]= f->block;
+ int stride= f->current_picture.linesize[0]>>1;
+ int i;
+ uint16_t *dst = ((uint16_t*)f->current_picture.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++){
+ DCTELEM *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 i;
+
+ f->dsp.clear_blocks(f->block[0]);
+
+ for(i=0; i<6; i++){
+ if(decode_i_block(f, f->block[i]) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+static uint8_t *read_huffman_tables(FourXContext *f, uint8_t * const buf){
+ int frequency[512];
+ uint8_t flag[512];
+ int up[512];
+ uint8_t len_tab[257];
+ int bits_tab[257];
+ int start, end;
+ uint8_t *ptr= buf;
+ int j;
+
+ memset(frequency, 0, sizeof(frequency));
+ memset(up, -1, sizeof(up));
+
+ start= *ptr++;
+ end= *ptr++;
+ for(;;){
+ int i;
+
+ for(i=start; i<=end; i++){
+ frequency[i]= *ptr++;
+// printf("%d %d %d\n", start, end, frequency[i]);
+ }
+ start= *ptr++;
+ if(start==0) break;
+
+ end= *ptr++;
+ }
+ frequency[256]=1;
+
+ while((ptr - buf)&3) ptr++; // 4byte align
+
+// for(j=0; j<16; j++)
+// printf("%2X", ptr[j]);
+
+ 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;
+ int len=0;
+ int bits=0;
+
+ for(node= j; up[node] != -1; node= up[node]){
+ bits += flag[node]<<len;
+ len++;
+ if(len > 31) av_log(f->avctx, AV_LOG_ERROR, "vlc length overflow\n"); //can this happen at all ?
+ }
+
+ bits_tab[j]= bits;
+ len_tab[j]= len;
+ }
+
+ init_vlc(&f->pre_vlc, ACDC_VLC_BITS, 257,
+ len_tab , 1, 1,
+ bits_tab, 4, 4, 0);
+
+ return ptr;
+}
+
+static int decode_i_frame(FourXContext *f, uint8_t *buf, int length){
+ int x, y;
+ const int width= f->avctx->width;
+ const int height= f->avctx->height;
+ uint16_t *dst= (uint16_t*)f->current_picture.data[0];
+ const int stride= f->current_picture.linesize[0]>>1;
+ const unsigned int bitstream_size= get32(buf);
+ const int token_count __attribute__((unused)) = get32(buf + bitstream_size + 8);
+ unsigned int prestream_size= 4*get32(buf + bitstream_size + 4);
+ uint8_t *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 -1;
+ }
+
+ prestream= read_huffman_tables(f, prestream);
+
+ init_get_bits(&f->gb, buf + 4, 8*bitstream_size);
+
+ prestream_size= length + buf - prestream;
+
+ f->bitstream_buffer= av_fast_realloc(f->bitstream_buffer, &f->bitstream_buffer_size, prestream_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ f->dsp.bswap_buf((uint32_t*)f->bitstream_buffer, (uint32_t*)prestream, prestream_size/4);
+ 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(decode_i_mb(f) < 0)
+ return -1;
+
+ idct_put(f, x, y);
+ }
+ dst += 16*stride;
+ }
+
+ 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 *data_size,
+ uint8_t *buf, int buf_size)
+{
+ FourXContext * const f = avctx->priv_data;
+ AVFrame *picture = data;
+ AVFrame *p, temp;
+ int i, frame_4cc, frame_size;
+
+ frame_4cc= get32(buf);
+ if(buf_size != get32(buf+4)+8 || buf_size < 20){
+ av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %d\n", buf_size, get32(buf+4));
+ }
+
+ if(frame_4cc == ff_get_fourcc("cfrm")){
+ int free_index=-1;
+ const int data_size= buf_size - 20;
+ const int id= get32(buf+12);
+ const int whole_size= get32(buf+16);
+ CFrameBuffer *cfrm;
+
+ 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];
+
+ cfrm->data= av_fast_realloc(cfrm->data, &cfrm->allocated_size, cfrm->size + data_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ if(!cfrm->data){ //explicit check needed as memcpy below might not catch a NULL
+ av_log(f->avctx, AV_LOG_ERROR, "realloc falure");
+ return -1;
+ }
+
+ 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= ff_get_fourcc("pfrm");
+ }else
+ return buf_size;
+ }else{
+ buf= buf + 12;
+ frame_size= buf_size - 12;
+ }
+
+ temp= f->current_picture;
+ f->current_picture= f->last_picture;
+ f->last_picture= temp;
+
+ p= &f->current_picture;
+ avctx->coded_frame= p;
+
+ avctx->flags |= CODEC_FLAG_EMU_EDGE; // alternatively we would have to use our own buffer management
+
+ if(p->data[0])
+ avctx->release_buffer(avctx, p);
+
+ p->reference= 1;
+ if(avctx->get_buffer(avctx, p) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ if(frame_4cc == ff_get_fourcc("ifrm")){
+ p->pict_type= I_TYPE;
+ if(decode_i_frame(f, buf, frame_size) < 0)
+ return -1;
+ }else if(frame_4cc == ff_get_fourcc("pfrm")){
+ p->pict_type= P_TYPE;
+ if(decode_p_frame(f, buf, frame_size) < 0)
+ return -1;
+ }else if(frame_4cc == ff_get_fourcc("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);
+ }
+
+#if 0
+for(i=0; i<20; i++){
+ printf("%2X %c ", buf[i], clip(buf[i],16,126));
+}
+#endif
+
+ p->key_frame= p->pict_type == I_TYPE;
+
+ *picture= *p;
+ *data_size = sizeof(AVPicture);
+
+ emms_c();
+
+ return buf_size;
+}
+
+
+static void common_init(AVCodecContext *avctx){
+ FourXContext * const f = avctx->priv_data;
+
+ dsputil_init(&f->dsp, avctx);
+
+ f->avctx= avctx;
+}
+
+static int decode_init(AVCodecContext *avctx){
+ FourXContext * const f = avctx->priv_data;
+
+ common_init(avctx);
+ init_vlcs(f);
+
+ avctx->pix_fmt= PIX_FMT_RGB565;
+
+ return 0;
+}
+
+
+static 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;
+ }
+ free_vlc(&f->pre_vlc);
+
+ return 0;
+}
+
+AVCodec fourxm_decoder = {
+ "4xm",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_4XM,
+ sizeof(FourXContext),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame,
+ /*CODEC_CAP_DR1,*/
+};
+
diff --git a/contrib/ffmpeg/libavcodec/8bps.c b/contrib/ffmpeg/libavcodec/8bps.c
new file mode 100644
index 000000000..297465043
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/8bps.c
@@ -0,0 +1,236 @@
+/*
+ * 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 8bps.c
+ * QT 8BPS Video Decoder by Roberto Togni <rtogni at bresciaonline dot it>
+ * 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 RGBA32)
+ * : RGBA32 (RGB 32bpp, 4th plane is probably alpha and it's ignored)
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "common.h"
+#include "avcodec.h"
+
+
+static const enum PixelFormat pixfmt_rgb24[] = {PIX_FMT_BGR24, PIX_FMT_RGBA32, -1};
+
+/*
+ * Decoder context
+ */
+typedef struct EightBpsContext {
+
+ AVCodecContext *avctx;
+ AVFrame pic;
+
+ unsigned char planes;
+ unsigned char planemap[4];
+} EightBpsContext;
+
+
+/*
+ *
+ * Decode a frame
+ *
+ */
+static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size)
+{
+ EightBpsContext * const c = (EightBpsContext *)avctx->priv_data;
+ unsigned char *encoded = (unsigned char *)buf;
+ unsigned char *pixptr, *pixptr_end;
+ unsigned int height = avctx->height; // Real image height
+ unsigned int dlen, p, row;
+ unsigned char *lp, *dp;
+ unsigned char count;
+ unsigned int px_inc;
+ unsigned int planes = c->planes;
+ unsigned char *planemap = c->planemap;
+
+ if(c->pic.data[0])
+ avctx->release_buffer(avctx, &c->pic);
+
+ c->pic.reference = 0;
+ c->pic.buffer_hints = FF_BUFFER_HINTS_VALID;
+ if(avctx->get_buffer(avctx, &c->pic) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ /* Set data pointer after line lengths */
+ dp = encoded + planes * (height << 1);
+
+ /* Ignore alpha plane, don't know what to do with it */
+ if (planes == 4)
+ planes--;
+
+ px_inc = planes + (avctx->pix_fmt == PIX_FMT_RGBA32);
+
+ 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 = c->pic.data[0] + row * c->pic.linesize[0] + planemap[p];
+ pixptr_end = pixptr + c->pic.linesize[0];
+ dlen = be2me_16(*(unsigned short *)(lp+row*2));
+ /* Decode a row of this plane */
+ while(dlen > 0) {
+ if(dp + 1 >= buf+buf_size) return -1;
+ if ((count = *dp++) <= 127) {
+ count++;
+ dlen -= count + 1;
+ if (pixptr + count * px_inc > pixptr_end)
+ break;
+ if(dp + count > buf+buf_size) return -1;
+ while(count--) {
+ *pixptr = *dp++;
+ pixptr += px_inc;
+ }
+ } else {
+ count = 257 - count;
+ if (pixptr + count * px_inc > pixptr_end)
+ break;
+ while(count--) {
+ *pixptr = *dp;
+ pixptr += px_inc;
+ }
+ dp++;
+ dlen -= 2;
+ }
+ }
+ }
+ }
+
+ if (avctx->palctrl) {
+ memcpy (c->pic.data[1], avctx->palctrl->palette, AVPALETTE_SIZE);
+ if (avctx->palctrl->palette_changed) {
+ c->pic.palette_has_changed = 1;
+ avctx->palctrl->palette_changed = 0;
+ } else
+ c->pic.palette_has_changed = 0;
+ }
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = c->pic;
+
+ /* always report that the buffer was completely consumed */
+ return buf_size;
+}
+
+
+/*
+ *
+ * Init 8BPS decoder
+ *
+ */
+static int decode_init(AVCodecContext *avctx)
+{
+ EightBpsContext * const c = (EightBpsContext *)avctx->priv_data;
+
+ c->avctx = avctx;
+ avctx->has_b_frames = 0;
+
+ c->pic.data[0] = NULL;
+
+ if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
+ return 1;
+ }
+
+ switch (avctx->bits_per_sample) {
+ case 8:
+ avctx->pix_fmt = PIX_FMT_PAL8;
+ c->planes = 1;
+ c->planemap[0] = 0; // 1st plane is palette indexes
+ if (avctx->palctrl == NULL) {
+ av_log(avctx, AV_LOG_ERROR, "Error: PAL8 format but no palette from demuxer.\n");
+ return -1;
+ }
+ 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 = PIX_FMT_RGBA32;
+ c->planes = 4;
+#ifdef WORDS_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_sample);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+
+/*
+ *
+ * Uninit 8BPS decoder
+ *
+ */
+static int decode_end(AVCodecContext *avctx)
+{
+ EightBpsContext * const c = (EightBpsContext *)avctx->priv_data;
+
+ if (c->pic.data[0])
+ avctx->release_buffer(avctx, &c->pic);
+
+ return 0;
+}
+
+
+
+AVCodec eightbps_decoder = {
+ "8bps",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_8BPS,
+ sizeof(EightBpsContext),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/Makefile b/contrib/ffmpeg/libavcodec/Makefile
new file mode 100644
index 000000000..03c1ae43d
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/Makefile
@@ -0,0 +1,456 @@
+#
+# libavcodec Makefile
+# (c) 2000-2005 Fabrice Bellard
+#
+include ../config.mak
+
+CFLAGS+=-I$(SRC_PATH)/libswscale $(AMR_CFLAGS)
+
+OBJS= bitstream.o \
+ utils.o \
+ allcodecs.o \
+ mpegvideo.o \
+ jrevdct.o \
+ jfdctfst.o \
+ jfdctint.o\
+ mjpeg.o \
+ resample.o \
+ resample2.o \
+ dsputil.o \
+ motion_est.o \
+ imgconvert.o \
+ mpeg12.o \
+ mpegaudiodec.o \
+ simple_idct.o \
+ ratecontrol.o \
+ eval.o \
+ error_resilience.o \
+ fft.o \
+ mdct.o \
+ raw.o \
+ golomb.o \
+ cabac.o\
+ faandct.o \
+ parser.o \
+ vp3dsp.o \
+ h264idct.o \
+ rangecoder.o \
+ pnm.o \
+ h263.o \
+ msmpeg4.o \
+ h263dec.o \
+ opt.o \
+ bitstream_filter.o \
+ audioconvert.o \
+
+
+HEADERS = avcodec.h opt.h
+
+OBJS-$(CONFIG_AASC_DECODER) += aasc.o
+OBJS-$(CONFIG_AC3_ENCODER) += ac3enc.o
+OBJS-$(CONFIG_ALAC_DECODER) += alac.o
+OBJS-$(CONFIG_ASV1_DECODER) += asv1.o
+OBJS-$(CONFIG_ASV1_ENCODER) += asv1.o
+OBJS-$(CONFIG_ASV2_DECODER) += asv1.o
+OBJS-$(CONFIG_ASV2_ENCODER) += asv1.o
+OBJS-$(CONFIG_AVS_DECODER) += avs.o
+OBJS-$(CONFIG_BMP_DECODER) += bmp.o
+OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdsp.o
+OBJS-$(CONFIG_CINEPAK_DECODER) += cinepak.o
+OBJS-$(CONFIG_CLJR_DECODER) += cljr.o
+OBJS-$(CONFIG_CLJR_ENCODER) += cljr.o
+OBJS-$(CONFIG_COOK_DECODER) += cook.o
+OBJS-$(CONFIG_CSCD_DECODER) += cscd.o lzo.o
+OBJS-$(CONFIG_CYUV_DECODER) += cyuv.o
+OBJS-$(CONFIG_DSICINVIDEO_DECODER) += dsicinav.o
+OBJS-$(CONFIG_DSICINAUDIO_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) += dv.o
+OBJS-$(CONFIG_DVVIDEO_ENCODER) += dv.o
+OBJS-$(CONFIG_EIGHTBPS_DECODER) += 8bps.o
+OBJS-$(CONFIG_FFV1_DECODER) += ffv1.o
+OBJS-$(CONFIG_FFV1_ENCODER) += ffv1.o
+OBJS-$(CONFIG_FFVHUFF_DECODER) += huffyuv.o
+OBJS-$(CONFIG_FFVHUFF_ENCODER) += huffyuv.o
+OBJS-$(CONFIG_FLAC_DECODER) += flac.o
+OBJS-$(CONFIG_FLAC_ENCODER) += flacenc.o
+OBJS-$(CONFIG_FLASHSV_DECODER) += flashsv.o
+OBJS-$(CONFIG_FLIC_DECODER) += flicvideo.o
+OBJS-$(CONFIG_FOURXM_DECODER) += 4xm.o
+OBJS-$(CONFIG_FRAPS_DECODER) += fraps.o
+OBJS-$(CONFIG_GIF_DECODER) += gifdec.o lzw.o
+OBJS-$(CONFIG_GIF_ENCODER) += gif.o
+OBJS-$(CONFIG_H261_DECODER) += h261.o
+OBJS-$(CONFIG_H261_ENCODER) += h261.o
+OBJS-$(CONFIG_H264_DECODER) += h264.o
+OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o
+OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o
+OBJS-$(CONFIG_IDCIN_DECODER) += idcinvideo.o
+OBJS-$(CONFIG_IMC_DECODER) += imc.o
+OBJS-$(CONFIG_INDEO2_DECODER) += indeo2.o
+OBJS-$(CONFIG_INDEO3_DECODER) += indeo3.o
+OBJS-$(CONFIG_INTERPLAY_VIDEO_DECODER) += interplayvideo.o
+OBJS-$(CONFIG_INTERPLAY_DPCM_DECODER) += dpcm.o
+OBJS-$(CONFIG_KMVC_DECODER) += kmvc.o
+OBJS-$(CONFIG_LOCO_DECODER) += loco.o
+OBJS-$(CONFIG_MACE3_DECODER) += mace.o
+OBJS-$(CONFIG_MACE6_DECODER) += mace.o
+OBJS-$(CONFIG_MMVIDEO_DECODER) += mmvideo.o
+OBJS-$(CONFIG_MP2_ENCODER) += mpegaudio.o
+OBJS-$(CONFIG_MSRLE_DECODER) += msrle.o
+OBJS-$(CONFIG_MSVIDEO1_DECODER) += msvideo1.o
+OBJS-$(CONFIG_MSZH_DECODER) += lcl.o
+OBJS-$(CONFIG_NUV_DECODER) += nuv.o rtjpeg.o lzo.o
+OBJS-$(CONFIG_PNG_DECODER) += png.o
+OBJS-$(CONFIG_PNG_ENCODER) += png.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_RA_144_DECODER) += ra144.o
+OBJS-$(CONFIG_RA_288_DECODER) += ra288.o
+OBJS-$(CONFIG_ROQ_DECODER) += roqvideo.o
+OBJS-$(CONFIG_ROQ_DPCM_DECODER) += dpcm.o
+OBJS-$(CONFIG_RPZA_DECODER) += rpza.o
+OBJS-$(CONFIG_RV10_DECODER) += rv10.o
+OBJS-$(CONFIG_RV10_ENCODER) += rv10.o
+OBJS-$(CONFIG_RV20_DECODER) += rv10.o
+OBJS-$(CONFIG_RV20_ENCODER) += rv10.o
+OBJS-$(CONFIG_SHORTEN_DECODER) += shorten.o
+OBJS-$(CONFIG_SMACKAUD_DECODER) += smacker.o
+OBJS-$(CONFIG_SMACKER_DECODER) += smacker.o
+OBJS-$(CONFIG_SMC_DECODER) += smc.o
+OBJS-$(CONFIG_SNOW_DECODER) += snow.o
+OBJS-$(CONFIG_SNOW_ENCODER) += snow.o
+OBJS-$(CONFIG_SOL_DPCM_DECODER) += dpcm.o
+OBJS-$(CONFIG_SONIC_DECODER) += sonic.o
+OBJS-$(CONFIG_SONIC_ENCODER) += sonic.o
+OBJS-$(CONFIG_SONIC_LS_DECODER) += sonic.o
+OBJS-$(CONFIG_SVQ1_DECODER) += svq1.o
+OBJS-$(CONFIG_SVQ1_ENCODER) += svq1.o
+OBJS-$(CONFIG_SVQ3_DECODER) += h264.o
+OBJS-$(CONFIG_TARGA_DECODER) += targa.o
+OBJS-$(CONFIG_THEORA_DECODER) += vp3.o
+OBJS-$(CONFIG_TIERTEXSEQVIDEO_DECODER) += tiertexseqv.o
+OBJS-$(CONFIG_TIFF_DECODER) += tiff.o lzw.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
+OBJS-$(CONFIG_TTA_DECODER) += tta.o
+OBJS-$(CONFIG_ULTI_DECODER) += ulti.o
+OBJS-$(CONFIG_VC1_DECODER) += vc1.o vc1dsp.o
+OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o
+OBJS-$(CONFIG_VCR1_ENCODER) += vcr1.o
+OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o
+OBJS-$(CONFIG_VMDVIDEO_DECODER) += vmdav.o
+OBJS-$(CONFIG_VMNC_DECODER) += vmnc.o
+OBJS-$(CONFIG_VORBIS_DECODER) += vorbis.o vorbis_data.o
+OBJS-$(CONFIG_VORBIS_ENCODER) += vorbis_enc.o vorbis.o vorbis_data.o
+OBJS-$(CONFIG_VP3_DECODER) += vp3.o
+OBJS-$(CONFIG_VP5_DECODER) += vp5.o vp56.o vp56data.o
+OBJS-$(CONFIG_VP6_DECODER) += vp6.o vp56.o vp56data.o
+OBJS-$(CONFIG_VQA_DECODER) += vqavideo.o
+OBJS-$(CONFIG_WAVPACK_DECODER) += wavpack.o
+OBJS-$(CONFIG_WMAV1_DECODER) += wmadec.o
+OBJS-$(CONFIG_WMAV2_DECODER) += wmadec.o
+OBJS-$(CONFIG_WMV3_DECODER) += vc1.o vc1dsp.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) += xan.o
+OBJS-$(CONFIG_XL_DECODER) += xl.o
+OBJS-$(CONFIG_ZLIB_DECODER) += lcl.o
+OBJS-$(CONFIG_ZLIB_ENCODER) += lcl.o
+OBJS-$(CONFIG_ZMBV_DECODER) += zmbv.o
+
+OBJS-$(CONFIG_PCM_S32LE_DECODER) += pcm.o
+OBJS-$(CONFIG_PCM_S32LE_ENCODER) += pcm.o
+OBJS-$(CONFIG_PCM_S32BE_DECODER) += pcm.o
+OBJS-$(CONFIG_PCM_S32BE_ENCODER) += pcm.o
+OBJS-$(CONFIG_PCM_U32LE_DECODER) += pcm.o
+OBJS-$(CONFIG_PCM_U32LE_ENCODER) += pcm.o
+OBJS-$(CONFIG_PCM_U32BE_DECODER) += pcm.o
+OBJS-$(CONFIG_PCM_U32BE_ENCODER) += pcm.o
+OBJS-$(CONFIG_PCM_S24LE_DECODER) += pcm.o
+OBJS-$(CONFIG_PCM_S24LE_ENCODER) += pcm.o
+OBJS-$(CONFIG_PCM_S24BE_DECODER) += pcm.o
+OBJS-$(CONFIG_PCM_S24BE_ENCODER) += pcm.o
+OBJS-$(CONFIG_PCM_U24LE_DECODER) += pcm.o
+OBJS-$(CONFIG_PCM_U24LE_ENCODER) += pcm.o
+OBJS-$(CONFIG_PCM_U24BE_DECODER) += pcm.o
+OBJS-$(CONFIG_PCM_U24BE_ENCODER) += pcm.o
+OBJS-$(CONFIG_PCM_S24DAUD_DECODER) += pcm.o
+OBJS-$(CONFIG_PCM_S24DAUD_ENCODER) += pcm.o
+OBJS-$(CONFIG_PCM_S16LE_DECODER) += pcm.o
+OBJS-$(CONFIG_PCM_S16LE_ENCODER) += pcm.o
+OBJS-$(CONFIG_PCM_S16BE_DECODER) += pcm.o
+OBJS-$(CONFIG_PCM_S16BE_ENCODER) += pcm.o
+OBJS-$(CONFIG_PCM_U16LE_DECODER) += pcm.o
+OBJS-$(CONFIG_PCM_U16LE_ENCODER) += pcm.o
+OBJS-$(CONFIG_PCM_U16BE_DECODER) += pcm.o
+OBJS-$(CONFIG_PCM_U16BE_ENCODER) += pcm.o
+OBJS-$(CONFIG_PCM_S8_DECODER) += pcm.o
+OBJS-$(CONFIG_PCM_S8_ENCODER) += pcm.o
+OBJS-$(CONFIG_PCM_U8_DECODER) += pcm.o
+OBJS-$(CONFIG_PCM_U8_ENCODER) += pcm.o
+OBJS-$(CONFIG_PCM_ALAW_DECODER) += pcm.o
+OBJS-$(CONFIG_PCM_ALAW_ENCODER) += pcm.o
+OBJS-$(CONFIG_PCM_MULAW_DECODER) += pcm.o
+OBJS-$(CONFIG_PCM_MULAW_ENCODER) += pcm.o
+
+OBJS-$(CONFIG_ADPCM_4XM_DECODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_4XM_ENCODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_ADX_DECODER) += adx.o
+OBJS-$(CONFIG_ADPCM_ADX_ENCODER) += adx.o
+OBJS-$(CONFIG_ADPCM_CT_DECODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_CT_ENCODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_EA_DECODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_EA_ENCODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_G726_DECODER) += g726.o
+OBJS-$(CONFIG_ADPCM_G726_ENCODER) += g726.o
+OBJS-$(CONFIG_ADPCM_IMA_DK3_DECODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_IMA_DK3_ENCODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_IMA_DK4_DECODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_IMA_DK4_ENCODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_IMA_QT_DECODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_IMA_QT_ENCODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_IMA_SMJPEG_DECODER)+= adpcm.o
+OBJS-$(CONFIG_ADPCM_IMA_SMJPEG_ENCODER)+= adpcm.o
+OBJS-$(CONFIG_ADPCM_IMA_WAV_DECODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_IMA_WAV_ENCODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_IMA_WS_DECODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_IMA_WS_ENCODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_MS_DECODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_MS_ENCODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_SBPRO_2_DECODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_SBPRO_2_ENCODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_SBPRO_3_DECODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_SBPRO_3_ENCODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_SBPRO_4_DECODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_SBPRO_4_ENCODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_SWF_DECODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_SWF_ENCODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_XA_DECODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_XA_ENCODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_YAMAHA_DECODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER) += adpcm.o
+
+OBJS-$(CONFIG_FAAD) += faad.o
+OBJS-$(CONFIG_FAAC) += faac.o
+OBJS-$(CONFIG_XVID) += xvidff.o xvid_rc.o
+OBJS-$(CONFIG_X264) += x264.o
+OBJS-$(CONFIG_MP3LAME) += mp3lameaudio.o
+OBJS-$(CONFIG_LIBVORBIS) += oggvorbis.o
+OBJS-$(CONFIG_LIBGSM) += libgsm.o
+
+# currently using liba52 for ac3 decoding
+OBJS-$(CONFIG_A52) += a52dec.o
+
+# using builtin liba52 or runtime linked liba52.so.0
+OBJS-$(CONFIG_A52)$(CONFIG_A52BIN) += liba52/bit_allocate.o \
+ liba52/bitstream.o \
+ liba52/downmix.o \
+ liba52/imdct.o \
+ liba52/parse.o \
+ liba52/crc.o \
+ liba52/resample.o
+
+# currently using libdts for dts decoding
+OBJS-$(CONFIG_DTS) += dtsdec.o
+
+OBJS-$(CONFIG_AMR) += amr.o
+OBJS-$(CONFIG_AMR_NB) += amr_float/sp_dec.o \
+ amr_float/sp_enc.o \
+ amr_float/interf_dec.o \
+ amr_float/interf_enc.o
+
+ifeq ($(CONFIG_AMR_NB_FIXED),yes)
+EXTRAOBJS += amr/*.o
+EXTRADEPS=amrlibs
+endif
+
+OBJS-$(CONFIG_AMR_WB) += amrwb_float/dec_acelp.o \
+ amrwb_float/dec_dtx.o \
+ amrwb_float/dec_gain.o \
+ amrwb_float/dec_if.o \
+ amrwb_float/dec_lpc.o \
+ amrwb_float/dec_main.o \
+ amrwb_float/dec_rom.o \
+ amrwb_float/dec_util.o \
+ amrwb_float/enc_acelp.o \
+ amrwb_float/enc_dtx.o \
+ amrwb_float/enc_gain.o \
+ amrwb_float/enc_if.o \
+ amrwb_float/enc_lpc.o \
+ amrwb_float/enc_main.o \
+ amrwb_float/enc_rom.o \
+ amrwb_float/enc_util.o \
+ amrwb_float/if_rom.o
+
+OBJS-$(CONFIG_AAC_PARSER) += parser.o
+OBJS-$(CONFIG_AC3_PARSER) += parser.o
+OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs.o parser.o
+OBJS-$(CONFIG_DVBSUB_PARSER) += dvbsubdec.o
+OBJS-$(CONFIG_DVDSUB_PARSER) += dvdsubdec.o
+OBJS-$(CONFIG_H261_PARSER) += h261.o
+OBJS-$(CONFIG_H263_PARSER) += h263dec.o
+OBJS-$(CONFIG_H264_PARSER) += h264.o
+OBJS-$(CONFIG_MJPEG_PARSER) += mjpeg.o
+OBJS-$(CONFIG_MPEG4VIDEO_PARSER) += parser.o
+OBJS-$(CONFIG_MPEGAUDIO_PARSER) += parser.o
+OBJS-$(CONFIG_MPEGVIDEO_PARSER) += parser.o
+OBJS-$(CONFIG_PNM_PARSER) += pnm.o
+
+OBJS-$(HAVE_PTHREADS) += pthread.o
+OBJS-$(HAVE_W32THREADS) += w32thread.o
+OBJS-$(HAVE_OS2THREADS) += os2thread.o
+OBJS-$(HAVE_BEOSTHREADS) += beosthread.o
+
+OBJS-$(HAVE_XVMC_ACCEL) += xvmcvideo.o
+
+ifneq ($(CONFIG_SWSCALER),yes)
+OBJS += imgresample.o
+endif
+
+# i386 mmx specific stuff
+ifeq ($(TARGET_MMX),yes)
+OBJS += i386/fdct_mmx.o \
+ i386/cputest.o \
+ i386/dsputil_mmx.o \
+ i386/mpegvideo_mmx.o \
+ i386/motion_est_mmx.o \
+ i386/simple_idct_mmx.o \
+ i386/idct_mmx_xvid.o \
+ i386/fft_sse.o \
+ i386/vp3dsp_mmx.o \
+ i386/vp3dsp_sse2.o \
+ i386/fft_3dn.o \
+ i386/fft_3dn2.o \
+ i386/snowdsp_mmx.o \
+
+ifeq ($(CONFIG_GPL),yes)
+OBJS += i386/idct_mmx.o
+endif
+ifeq ($(CONFIG_CAVS_DECODER),yes)
+OBJS += i386/cavsdsp_mmx.o
+endif
+endif
+
+# armv4l specific stuff
+ASM_OBJS-$(TARGET_ARCH_ARMV4L) += armv4l/jrevdct_arm.o \
+ armv4l/simple_idct_arm.o \
+ armv4l/dsputil_arm_s.o \
+
+OBJS-$(TARGET_ARCH_ARMV4L) += armv4l/dsputil_arm.o \
+ armv4l/mpegvideo_arm.o \
+
+OBJS-$(TARGET_IWMMXT) += armv4l/dsputil_iwmmxt.o \
+ armv4l/mpegvideo_iwmmxt.o \
+
+ASM_OBJS-$(TARGET_ARMV5TE) += armv4l/simple_idct_armv5te.o \
+
+# sun sparc
+OBJS-$(TARGET_ARCH_SPARC) += sparc/dsputil_vis.o \
+
+sparc/dsputil_vis.o: CFLAGS += -mcpu=ultrasparc -mtune=ultrasparc
+
+# sun mediaLib specific stuff
+OBJS-$(HAVE_MLIB) += mlib/dsputil_mlib.o \
+
+# alpha specific stuff
+OBJS-$(TARGET_ARCH_ALPHA) += alpha/dsputil_alpha.o \
+ alpha/mpegvideo_alpha.o \
+ alpha/simple_idct_alpha.o \
+ alpha/motion_est_alpha.o \
+
+ASM_OBJS-$(TARGET_ARCH_ALPHA) += alpha/dsputil_alpha_asm.o \
+ alpha/motion_est_mvi_asm.o \
+
+OBJS-$(TARGET_ARCH_POWERPC) += ppc/dsputil_ppc.o \
+ ppc/mpegvideo_ppc.o \
+
+OBJS-$(TARGET_MMI) += ps2/dsputil_mmi.o \
+ ps2/idct_mmi.o \
+ ps2/mpegvideo_mmi.o \
+
+OBJS-$(TARGET_ARCH_SH4) += sh4/idct_sh4.o \
+ sh4/dsputil_sh4.o \
+ sh4/dsputil_align.o \
+
+OBJS-$(TARGET_ALTIVEC) += ppc/dsputil_altivec.o \
+ ppc/mpegvideo_altivec.o \
+ ppc/idct_altivec.o \
+ ppc/fft_altivec.o \
+ ppc/gmc_altivec.o \
+ ppc/fdct_altivec.o \
+ ppc/float_altivec.o \
+
+ifeq ($(TARGET_ALTIVEC),yes)
+OBJS-$(CONFIG_H264_DECODER) += ppc/h264_altivec.o
+OBJS-$(CONFIG_SNOW_DECODER) += ppc/snow_altivec.o
+OBJS-$(CONFIG_VC1_DECODER) += ppc/vc1dsp_altivec.o
+OBJS-$(CONFIG_WMV3_DECODER) += ppc/vc1dsp_altivec.o
+endif
+
+OBJS-$(TARGET_ARCH_BFIN) += bfin/dsputil_bfin.o \
+
+CFLAGS += $(CFLAGS-yes)
+OBJS += $(OBJS-yes)
+ASM_OBJS += $(ASM_OBJS-yes)
+
+EXTRALIBS := -L$(BUILD_ROOT)/libavutil -lavutil$(BUILDSUF) $(EXTRALIBS)
+
+NAME=avcodec
+ifeq ($(BUILD_SHARED),yes)
+LIBVERSION=$(LAVCVERSION)
+LIBMAJOR=$(LAVCMAJOR)
+endif
+
+TESTS= imgresample-test fft-test
+ifeq ($(TARGET_ARCH_X86),yes)
+TESTS+= cpuid_test dct-test motion-test
+endif
+
+include ../common.mak
+
+amrlibs:
+ $(MAKE) -C amr spclib fipoplib
+
+tests: apiexample $(TESTS)
+
+clean::
+ rm -f \
+ i386/*.o i386/*~ \
+ armv4l/*.o armv4l/*~ \
+ mlib/*.o mlib/*~ \
+ alpha/*.o alpha/*~ \
+ ppc/*.o ppc/*~ \
+ ps2/*.o ps2/*~ \
+ sh4/*.o sh4/*~ \
+ sparc/*.o sparc/*~ \
+ liba52/*.o liba52/*~ \
+ amr_float/*.o \
+ apiexample $(TESTS)
+ -$(MAKE) -C amr clean
+ -$(MAKE) -C amrwb_float -f makefile.gcc clean
+
+apiexample: apiexample.o $(LIB)
+
+cpuid_test: i386/cputest.c
+ $(CC) $(CFLAGS) -D__TEST__ -o $@ $<
+
+imgresample-test: imgresample.c $(LIB)
+ $(CC) $(CFLAGS) -DTEST -o $@ $^ $(EXTRALIBS)
+
+dct-test: dct-test.o fdctref.o $(LIB)
+
+motion-test: motion_test.o $(LIB)
+
+fft-test: fft-test.o $(LIB)
+
+.PHONY: amrlibs tests
diff --git a/contrib/ffmpeg/libavcodec/a52dec.c b/contrib/ffmpeg/libavcodec/a52dec.c
new file mode 100644
index 000000000..dec25138e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/a52dec.c
@@ -0,0 +1,257 @@
+/*
+ * A52 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 a52dec.c
+ * A52 decoder.
+ */
+
+#include "avcodec.h"
+#include "liba52/a52.h"
+
+#ifdef CONFIG_A52BIN
+#include <dlfcn.h>
+static const char* liba52name = "liba52.so.0";
+#endif
+
+/**
+ * liba52 - Copyright (C) Aaron Holtzman
+ * released under the GPL license.
+ */
+typedef struct AC3DecodeState {
+ uint8_t inbuf[4096]; /* input buffer */
+ uint8_t *inbuf_ptr;
+ int frame_size;
+ int flags;
+ int channels;
+ a52_state_t* state;
+ sample_t* samples;
+
+ /*
+ * virtual method table
+ *
+ * using this function table so the liba52 doesn't
+ * have to be really linked together with ffmpeg
+ * and might be linked in runtime - this allows binary
+ * distribution of ffmpeg library which doens't depend
+ * on liba52 library - but if user has it installed
+ * it will be used - user might install such library
+ * separately
+ */
+ void* handle;
+ a52_state_t* (*a52_init)(uint32_t mm_accel);
+ sample_t* (*a52_samples)(a52_state_t * state);
+ int (*a52_syncinfo)(uint8_t * buf, int * flags,
+ int * sample_rate, int * bit_rate);
+ int (*a52_frame)(a52_state_t * state, uint8_t * buf, int * flags,
+ sample_t * level, sample_t bias);
+ void (*a52_dynrng)(a52_state_t * state,
+ sample_t (* call) (sample_t, void *), void * data);
+ int (*a52_block)(a52_state_t * state);
+ void (*a52_free)(a52_state_t * state);
+
+} AC3DecodeState;
+
+#ifdef CONFIG_A52BIN
+static void* dlsymm(void* handle, const char* symbol)
+{
+ void* f = dlsym(handle, symbol);
+ if (!f)
+ av_log( NULL, AV_LOG_ERROR, "A52 Decoder - function '%s' can't be resolved\n", symbol);
+ return f;
+}
+#endif
+
+static int a52_decode_init(AVCodecContext *avctx)
+{
+ AC3DecodeState *s = avctx->priv_data;
+
+#ifdef CONFIG_A52BIN
+ s->handle = dlopen(liba52name, RTLD_LAZY);
+ if (!s->handle)
+ {
+ av_log( avctx, AV_LOG_ERROR, "A52 library %s could not be opened! \n%s\n", liba52name, dlerror());
+ return -1;
+ }
+ s->a52_init = (a52_state_t* (*)(uint32_t)) dlsymm(s->handle, "a52_init");
+ s->a52_samples = (sample_t* (*)(a52_state_t*)) dlsymm(s->handle, "a52_samples");
+ s->a52_syncinfo = (int (*)(uint8_t*, int*, int*, int*)) dlsymm(s->handle, "a52_syncinfo");
+ s->a52_frame = (int (*)(a52_state_t*, uint8_t*, int*, sample_t*, sample_t)) dlsymm(s->handle, "a52_frame");
+ s->a52_block = (int (*)(a52_state_t*)) dlsymm(s->handle, "a52_block");
+ s->a52_free = (void (*)(a52_state_t*)) dlsymm(s->handle, "a52_free");
+ if (!s->a52_init || !s->a52_samples || !s->a52_syncinfo
+ || !s->a52_frame || !s->a52_block || !s->a52_free)
+ {
+ dlclose(s->handle);
+ return -1;
+ }
+#else
+ /* static linked version */
+ s->handle = 0;
+ s->a52_init = a52_init;
+ s->a52_samples = a52_samples;
+ s->a52_syncinfo = a52_syncinfo;
+ s->a52_frame = a52_frame;
+ s->a52_block = a52_block;
+ s->a52_free = a52_free;
+#endif
+ s->state = s->a52_init(0); /* later use CPU flags */
+ s->samples = s->a52_samples(s->state);
+ s->inbuf_ptr = s->inbuf;
+ s->frame_size = 0;
+
+ return 0;
+}
+
+/**** the following two functions comes from a52dec */
+static inline int blah (int32_t i)
+{
+ if (i > 0x43c07fff)
+ return 32767;
+ else if (i < 0x43bf8000)
+ return -32768;
+ return i - 0x43c00000;
+}
+
+static inline void float_to_int (float * _f, int16_t * s16, int nchannels)
+{
+ int i, j, c;
+ int32_t * f = (int32_t *) _f; // XXX assumes IEEE float format
+
+ j = 0;
+ nchannels *= 256;
+ for (i = 0; i < 256; i++) {
+ for (c = 0; c < nchannels; c += 256)
+ s16[j++] = blah (f[i + c]);
+ }
+}
+
+/**** end */
+
+#define HEADER_SIZE 7
+
+static int a52_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ AC3DecodeState *s = avctx->priv_data;
+ uint8_t *buf_ptr;
+ int flags, i, len;
+ int sample_rate, bit_rate;
+ short *out_samples = data;
+ float level;
+ static const int ac3_channels[8] = {
+ 2, 1, 2, 3, 3, 4, 4, 5
+ };
+
+ buf_ptr = buf;
+ while (buf_size > 0) {
+ len = s->inbuf_ptr - s->inbuf;
+ if (s->frame_size == 0) {
+ /* no header seen : find one. We need at least 7 bytes to parse it */
+ len = HEADER_SIZE - len;
+ if (len > buf_size)
+ len = buf_size;
+ memcpy(s->inbuf_ptr, buf_ptr, len);
+ buf_ptr += len;
+ s->inbuf_ptr += len;
+ buf_size -= len;
+ if ((s->inbuf_ptr - s->inbuf) == HEADER_SIZE) {
+ len = s->a52_syncinfo(s->inbuf, &s->flags, &sample_rate, &bit_rate);
+ if (len == 0) {
+ /* no sync found : move by one byte (inefficient, but simple!) */
+ memcpy(s->inbuf, s->inbuf + 1, HEADER_SIZE - 1);
+ s->inbuf_ptr--;
+ } else {
+ s->frame_size = len;
+ /* update codec info */
+ avctx->sample_rate = sample_rate;
+ s->channels = ac3_channels[s->flags & 7];
+ if (s->flags & A52_LFE)
+ s->channels++;
+ if (avctx->channels == 0)
+ /* No specific number of channel requested */
+ avctx->channels = s->channels;
+ else if (s->channels < avctx->channels) {
+ av_log(avctx, AV_LOG_ERROR, "ac3dec: AC3 Source channels are less than specified: output to %d channels.. (frmsize: %d)\n", s->channels, len);
+ avctx->channels = s->channels;
+ }
+ avctx->bit_rate = bit_rate;
+ }
+ }
+ } else if (len < s->frame_size) {
+ len = s->frame_size - len;
+ if (len > buf_size)
+ len = buf_size;
+
+ memcpy(s->inbuf_ptr, buf_ptr, len);
+ buf_ptr += len;
+ s->inbuf_ptr += len;
+ buf_size -= len;
+ } else {
+ flags = s->flags;
+ if (avctx->channels == 1)
+ flags = A52_MONO;
+ else if (avctx->channels == 2)
+ flags = A52_STEREO;
+ else
+ flags |= A52_ADJUST_LEVEL;
+ level = 1;
+ if (s->a52_frame(s->state, s->inbuf, &flags, &level, 384)) {
+ fail:
+ s->inbuf_ptr = s->inbuf;
+ s->frame_size = 0;
+ continue;
+ }
+ for (i = 0; i < 6; i++) {
+ if (s->a52_block(s->state))
+ goto fail;
+ float_to_int(s->samples, out_samples + i * 256 * avctx->channels, avctx->channels);
+ }
+ s->inbuf_ptr = s->inbuf;
+ s->frame_size = 0;
+ *data_size = 6 * avctx->channels * 256 * sizeof(int16_t);
+ break;
+ }
+ }
+ return buf_ptr - buf;
+}
+
+static int a52_decode_end(AVCodecContext *avctx)
+{
+ AC3DecodeState *s = avctx->priv_data;
+ s->a52_free(s->state);
+#ifdef CONFIG_A52BIN
+ dlclose(s->handle);
+#endif
+ return 0;
+}
+
+AVCodec ac3_decoder = {
+ "ac3",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_AC3,
+ sizeof(AC3DecodeState),
+ a52_decode_init,
+ NULL,
+ a52_decode_end,
+ a52_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/aasc.c b/contrib/ffmpeg/libavcodec/aasc.c
new file mode 100644
index 000000000..6c8e3166e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/aasc.c
@@ -0,0 +1,176 @@
+/*
+ * Autodesc 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 aasc.c
+ * Autodesc RLE Video Decoder by Konstantin Shishkov
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.h"
+
+typedef struct AascContext {
+ AVCodecContext *avctx;
+ AVFrame frame;
+} AascContext;
+
+#define FETCH_NEXT_STREAM_BYTE() \
+ if (stream_ptr >= buf_size) \
+ { \
+ av_log(s->avctx, AV_LOG_ERROR, " AASC: stream ptr just went out of bounds (fetch)\n"); \
+ break; \
+ } \
+ stream_byte = buf[stream_ptr++];
+
+static int aasc_decode_init(AVCodecContext *avctx)
+{
+ AascContext *s = (AascContext *)avctx->priv_data;
+
+ s->avctx = avctx;
+
+ avctx->pix_fmt = PIX_FMT_BGR24;
+ avctx->has_b_frames = 0;
+ s->frame.data[0] = NULL;
+
+ return 0;
+}
+
+static int aasc_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ AascContext *s = (AascContext *)avctx->priv_data;
+ int stream_ptr = 4;
+ unsigned char rle_code;
+ unsigned char stream_byte;
+ int pixel_ptr = 0;
+ int row_dec, row_ptr;
+ int frame_size;
+ int i;
+
+ s->frame.reference = 1;
+ s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
+ if (avctx->reget_buffer(avctx, &s->frame)) {
+ av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+ return -1;
+ }
+
+ row_dec = s->frame.linesize[0];
+ row_ptr = (s->avctx->height - 1) * row_dec;
+ frame_size = row_dec * s->avctx->height;
+
+ while (row_ptr >= 0) {
+ FETCH_NEXT_STREAM_BYTE();
+ rle_code = stream_byte;
+ if (rle_code == 0) {
+ /* fetch the next byte to see how to handle escape code */
+ FETCH_NEXT_STREAM_BYTE();
+ 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 */
+ break;
+ } else if (stream_byte == 2) {
+ /* reposition frame decode coordinates */
+ FETCH_NEXT_STREAM_BYTE();
+ pixel_ptr += stream_byte;
+ FETCH_NEXT_STREAM_BYTE();
+ row_ptr -= stream_byte * row_dec;
+ } else {
+ /* copy pixels from encoded stream */
+ if ((pixel_ptr + stream_byte > avctx->width * 3) ||
+ (row_ptr < 0)) {
+ av_log(s->avctx, AV_LOG_ERROR, " AASC: frame ptr just went out of bounds (copy1)\n");
+ break;
+ }
+
+ rle_code = stream_byte;
+ if (stream_ptr + rle_code > buf_size) {
+ av_log(s->avctx, AV_LOG_ERROR, " AASC: stream ptr just went out of bounds (copy2)\n");
+ break;
+ }
+
+ for (i = 0; i < rle_code; i++) {
+ FETCH_NEXT_STREAM_BYTE();
+ s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
+ pixel_ptr++;
+ }
+ if (rle_code & 1)
+ stream_ptr++;
+ }
+ } else {
+ /* decode a run of data */
+ if ((pixel_ptr + rle_code > avctx->width * 3) ||
+ (row_ptr < 0)) {
+ av_log(s->avctx, AV_LOG_ERROR, " AASC: frame ptr just went out of bounds (run1)\n");
+ break;
+ }
+
+ FETCH_NEXT_STREAM_BYTE();
+
+ while(rle_code--) {
+ s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
+ pixel_ptr++;
+ }
+ }
+ }
+
+ /* one last sanity check on the way out */
+ if (stream_ptr < buf_size)
+ av_log(s->avctx, AV_LOG_ERROR, " AASC: ended frame decode with bytes left over (%d < %d)\n",
+ stream_ptr, buf_size);
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = s->frame;
+
+ /* report that the buffer was completely consumed */
+ return buf_size;
+}
+
+static int aasc_decode_end(AVCodecContext *avctx)
+{
+ AascContext *s = (AascContext *)avctx->priv_data;
+
+ /* release the last frame */
+ if (s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ return 0;
+}
+
+AVCodec aasc_decoder = {
+ "aasc",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_AASC,
+ sizeof(AascContext),
+ aasc_decode_init,
+ NULL,
+ aasc_decode_end,
+ aasc_decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/ac3.h b/contrib/ffmpeg/libavcodec/ac3.h
new file mode 100644
index 000000000..5daa9750f
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ac3.h
@@ -0,0 +1,65 @@
+/*
+ * Common code between AC3 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 ac3.h
+ * Common code between AC3 encoder and decoder.
+ */
+
+#define AC3_MAX_CODED_FRAME_SIZE 3840 /* in bytes */
+#define AC3_MAX_CHANNELS 6 /* including LFE channel */
+
+#define NB_BLOCKS 6 /* number of PCM blocks inside an AC3 frame */
+#define AC3_FRAME_SIZE (NB_BLOCKS * 256)
+
+/* exponent encoding strategy */
+#define EXP_REUSE 0
+#define EXP_NEW 1
+
+#define EXP_D15 1
+#define EXP_D25 2
+#define EXP_D45 3
+
+typedef struct AC3BitAllocParameters {
+ int fscod; /* frequency */
+ int halfratecod;
+ int sgain, sdecay, fdecay, dbknee, floor;
+ int cplfleak, cplsleak;
+} AC3BitAllocParameters;
+
+#if 0
+extern const uint16_t ac3_freqs[3];
+extern const uint16_t ac3_bitratetab[19];
+extern const int16_t ac3_window[256];
+extern const uint8_t sdecaytab[4];
+extern const uint8_t fdecaytab[4];
+extern const uint16_t sgaintab[4];
+extern const uint16_t dbkneetab[4];
+extern const uint16_t floortab[8];
+extern const uint16_t fgaintab[8];
+#endif
+
+void ac3_common_init(void);
+void ac3_parametric_bit_allocation(AC3BitAllocParameters *s, uint8_t *bap,
+ int8_t *exp, int start, int end,
+ int snroffset, int fgain, int is_lfe,
+ int deltbae,int deltnseg,
+ uint8_t *deltoffst, uint8_t *deltlen, uint8_t *deltba);
diff --git a/contrib/ffmpeg/libavcodec/ac3dec.c b/contrib/ffmpeg/libavcodec/ac3dec.c
new file mode 100644
index 000000000..b6bebfb59
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ac3dec.c
@@ -0,0 +1,184 @@
+/*
+ * AC3 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 ac3dec.c
+ * AC3 decoder.
+ */
+
+//#define DEBUG
+
+#include "avcodec.h"
+#include "libac3/ac3.h"
+
+/* currently, I use libac3 which is Copyright (C) Aaron Holtzman and
+ released under the GPL license. I may reimplement it someday... */
+typedef struct AC3DecodeState {
+ uint8_t inbuf[4096]; /* input buffer */
+ uint8_t *inbuf_ptr;
+ int frame_size;
+ int flags;
+ int channels;
+ ac3_state_t state;
+} AC3DecodeState;
+
+static int ac3_decode_init(AVCodecContext *avctx)
+{
+ AC3DecodeState *s = avctx->priv_data;
+
+ ac3_init ();
+ s->inbuf_ptr = s->inbuf;
+ s->frame_size = 0;
+ return 0;
+}
+
+stream_samples_t samples;
+
+/**** the following two functions comes from ac3dec */
+static inline int blah (int32_t i)
+{
+ if (i > 0x43c07fff)
+ return 32767;
+ else if (i < 0x43bf8000)
+ return -32768;
+ else
+ return i - 0x43c00000;
+}
+
+static inline void float_to_int (float * _f, int16_t * s16, int nchannels)
+{
+ int i, j, c;
+ int32_t * f = (int32_t *) _f; // XXX assumes IEEE float format
+
+ j = 0;
+ nchannels *= 256;
+ for (i = 0; i < 256; i++) {
+ for (c = 0; c < nchannels; c += 256)
+ s16[j++] = blah (f[i + c]);
+ }
+}
+
+/**** end */
+
+#define HEADER_SIZE 7
+
+static int ac3_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ AC3DecodeState *s = avctx->priv_data;
+ uint8_t *buf_ptr;
+ int flags, i, len;
+ int sample_rate, bit_rate;
+ short *out_samples = data;
+ float level;
+ static const int ac3_channels[8] = {
+ 2, 1, 2, 3, 3, 4, 4, 5
+ };
+
+ buf_ptr = buf;
+ while (buf_size > 0) {
+ len = s->inbuf_ptr - s->inbuf;
+ if (s->frame_size == 0) {
+ /* no header seen : find one. We need at least 7 bytes to parse it */
+ len = HEADER_SIZE - len;
+ if (len > buf_size)
+ len = buf_size;
+ memcpy(s->inbuf_ptr, buf_ptr, len);
+ buf_ptr += len;
+ s->inbuf_ptr += len;
+ buf_size -= len;
+ if ((s->inbuf_ptr - s->inbuf) == HEADER_SIZE) {
+ len = ac3_syncinfo (s->inbuf, &s->flags, &sample_rate, &bit_rate);
+ if (len == 0) {
+ /* no sync found : move by one byte (inefficient, but simple!) */
+ memcpy(s->inbuf, s->inbuf + 1, HEADER_SIZE - 1);
+ s->inbuf_ptr--;
+ } else {
+ s->frame_size = len;
+ /* update codec info */
+ avctx->sample_rate = sample_rate;
+ s->channels = ac3_channels[s->flags & 7];
+ if (s->flags & AC3_LFE)
+ s->channels++;
+ if (avctx->channels == 0)
+ /* No specific number of channel requested */
+ avctx->channels = s->channels;
+ else if (s->channels < avctx->channels) {
+ av_log( avctx, AV_LOG_INFO, "ac3dec: AC3 Source channels are less than specified: output to %d channels.. (frmsize: %d)\n", s->channels, len);
+ avctx->channels = s->channels;
+ }
+ avctx->bit_rate = bit_rate;
+ }
+ }
+ } else if (len < s->frame_size) {
+ len = s->frame_size - len;
+ if (len > buf_size)
+ len = buf_size;
+
+ memcpy(s->inbuf_ptr, buf_ptr, len);
+ buf_ptr += len;
+ s->inbuf_ptr += len;
+ buf_size -= len;
+ } else {
+ flags = s->flags;
+ if (avctx->channels == 1)
+ flags = AC3_MONO;
+ else if (avctx->channels == 2)
+ flags = AC3_STEREO;
+ else
+ flags |= AC3_ADJUST_LEVEL;
+ level = 1;
+ if (ac3_frame (&s->state, s->inbuf, &flags, &level, 384)) {
+ fail:
+ s->inbuf_ptr = s->inbuf;
+ s->frame_size = 0;
+ continue;
+ }
+ for (i = 0; i < 6; i++) {
+ if (ac3_block (&s->state))
+ goto fail;
+ float_to_int (*samples, out_samples + i * 256 * avctx->channels, avctx->channels);
+ }
+ s->inbuf_ptr = s->inbuf;
+ s->frame_size = 0;
+ *data_size = 6 * avctx->channels * 256 * sizeof(int16_t);
+ break;
+ }
+ }
+ return buf_ptr - buf;
+}
+
+static int ac3_decode_end(AVCodecContext *s)
+{
+ return 0;
+}
+
+AVCodec ac3_decoder = {
+ "ac3",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_AC3,
+ sizeof(AC3DecodeState),
+ ac3_decode_init,
+ NULL,
+ ac3_decode_end,
+ ac3_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/ac3enc.c b/contrib/ffmpeg/libavcodec/ac3enc.c
new file mode 100644
index 000000000..c8c8920ed
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ac3enc.c
@@ -0,0 +1,1557 @@
+/*
+ * The simplest AC3 encoder
+ * 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 ac3enc.c
+ * The simplest AC3 encoder.
+ */
+//#define DEBUG
+//#define DEBUG_BITALLOC
+#include "avcodec.h"
+#include "bitstream.h"
+#include "crc.h"
+#include "ac3.h"
+
+typedef struct AC3EncodeContext {
+ PutBitContext pb;
+ int nb_channels;
+ int nb_all_channels;
+ int lfe_channel;
+ int bit_rate;
+ unsigned int sample_rate;
+ unsigned int bsid;
+ unsigned int frame_size_min; /* minimum frame size in case rounding is necessary */
+ unsigned int frame_size; /* current frame size in words */
+ unsigned int bits_written;
+ unsigned int samples_written;
+ int halfratecod;
+ unsigned int frmsizecod;
+ unsigned int fscod; /* frequency */
+ unsigned int acmod;
+ int lfe;
+ unsigned int bsmod;
+ short last_samples[AC3_MAX_CHANNELS][256];
+ unsigned int chbwcod[AC3_MAX_CHANNELS];
+ int nb_coefs[AC3_MAX_CHANNELS];
+
+ /* bitrate allocation control */
+ int sgaincod, sdecaycod, fdecaycod, dbkneecod, floorcod;
+ AC3BitAllocParameters bit_alloc;
+ int csnroffst;
+ int fgaincod[AC3_MAX_CHANNELS];
+ int fsnroffst[AC3_MAX_CHANNELS];
+ /* mantissa encoding */
+ int mant1_cnt, mant2_cnt, mant4_cnt;
+} AC3EncodeContext;
+
+#include "ac3tab.h"
+
+#define MDCT_NBITS 9
+#define N (1 << MDCT_NBITS)
+
+/* new exponents are sent if their Norm 1 exceed this number */
+#define EXP_DIFF_THRESHOLD 1000
+
+static void fft_init(int ln);
+
+static inline int16_t fix15(float a)
+{
+ int v;
+ v = (int)(a * (float)(1 << 15));
+ if (v < -32767)
+ v = -32767;
+ else if (v > 32767)
+ v = 32767;
+ return v;
+}
+
+static inline int calc_lowcomp1(int a, int b0, int b1)
+{
+ if ((b0 + 256) == b1) {
+ a = 384 ;
+ } else if (b0 > b1) {
+ a = a - 64;
+ if (a < 0) a=0;
+ }
+ return a;
+}
+
+static inline int calc_lowcomp(int a, int b0, int b1, int bin)
+{
+ if (bin < 7) {
+ if ((b0 + 256) == b1) {
+ a = 384 ;
+ } else if (b0 > b1) {
+ a = a - 64;
+ if (a < 0) a=0;
+ }
+ } else if (bin < 20) {
+ if ((b0 + 256) == b1) {
+ a = 320 ;
+ } else if (b0 > b1) {
+ a= a - 64;
+ if (a < 0) a=0;
+ }
+ } else {
+ a = a - 128;
+ if (a < 0) a=0;
+ }
+ return a;
+}
+
+/* AC3 bit allocation. The algorithm is the one described in the AC3
+ spec. */
+void ac3_parametric_bit_allocation(AC3BitAllocParameters *s, uint8_t *bap,
+ int8_t *exp, int start, int end,
+ int snroffset, int fgain, int is_lfe,
+ int deltbae,int deltnseg,
+ uint8_t *deltoffst, uint8_t *deltlen, uint8_t *deltba)
+{
+ int bin,i,j,k,end1,v,v1,bndstrt,bndend,lowcomp,begin;
+ int fastleak,slowleak,address,tmp;
+ int16_t psd[256]; /* scaled exponents */
+ int16_t bndpsd[50]; /* interpolated exponents */
+ int16_t excite[50]; /* excitation */
+ int16_t mask[50]; /* masking value */
+
+ /* exponent mapping to PSD */
+ for(bin=start;bin<end;bin++) {
+ psd[bin]=(3072 - (exp[bin] << 7));
+ }
+
+ /* PSD integration */
+ j=start;
+ k=masktab[start];
+ do {
+ v=psd[j];
+ j++;
+ end1=bndtab[k+1];
+ if (end1 > end) end1=end;
+ for(i=j;i<end1;i++) {
+ int c,adr;
+ /* logadd */
+ v1=psd[j];
+ c=v-v1;
+ if (c >= 0) {
+ adr=c >> 1;
+ if (adr > 255) adr=255;
+ v=v + latab[adr];
+ } else {
+ adr=(-c) >> 1;
+ if (adr > 255) adr=255;
+ v=v1 + latab[adr];
+ }
+ j++;
+ }
+ bndpsd[k]=v;
+ k++;
+ } while (end > bndtab[k]);
+
+ /* excitation function */
+ bndstrt = masktab[start];
+ bndend = masktab[end-1] + 1;
+
+ if (bndstrt == 0) {
+ lowcomp = 0;
+ lowcomp = calc_lowcomp1(lowcomp, bndpsd[0], bndpsd[1]) ;
+ excite[0] = bndpsd[0] - fgain - lowcomp ;
+ lowcomp = calc_lowcomp1(lowcomp, bndpsd[1], bndpsd[2]) ;
+ excite[1] = bndpsd[1] - fgain - lowcomp ;
+ begin = 7 ;
+ for (bin = 2; bin < 7; bin++) {
+ if (!(is_lfe && bin == 6))
+ lowcomp = calc_lowcomp1(lowcomp, bndpsd[bin], bndpsd[bin+1]) ;
+ fastleak = bndpsd[bin] - fgain ;
+ slowleak = bndpsd[bin] - s->sgain ;
+ excite[bin] = fastleak - lowcomp ;
+ if (!(is_lfe && bin == 6)) {
+ if (bndpsd[bin] <= bndpsd[bin+1]) {
+ begin = bin + 1 ;
+ break ;
+ }
+ }
+ }
+
+ end1=bndend;
+ if (end1 > 22) end1=22;
+
+ for (bin = begin; bin < end1; bin++) {
+ if (!(is_lfe && bin == 6))
+ lowcomp = calc_lowcomp(lowcomp, bndpsd[bin], bndpsd[bin+1], bin) ;
+
+ fastleak -= s->fdecay ;
+ v = bndpsd[bin] - fgain;
+ if (fastleak < v) fastleak = v;
+
+ slowleak -= s->sdecay ;
+ v = bndpsd[bin] - s->sgain;
+ if (slowleak < v) slowleak = v;
+
+ v=fastleak - lowcomp;
+ if (slowleak > v) v=slowleak;
+
+ excite[bin] = v;
+ }
+ begin = 22;
+ } else {
+ /* coupling channel */
+ begin = bndstrt;
+
+ fastleak = (s->cplfleak << 8) + 768;
+ slowleak = (s->cplsleak << 8) + 768;
+ }
+
+ for (bin = begin; bin < bndend; bin++) {
+ fastleak -= s->fdecay ;
+ v = bndpsd[bin] - fgain;
+ if (fastleak < v) fastleak = v;
+ slowleak -= s->sdecay ;
+ v = bndpsd[bin] - s->sgain;
+ if (slowleak < v) slowleak = v;
+
+ v=fastleak;
+ if (slowleak > v) v = slowleak;
+ excite[bin] = v;
+ }
+
+ /* compute masking curve */
+
+ for (bin = bndstrt; bin < bndend; bin++) {
+ v1 = excite[bin];
+ tmp = s->dbknee - bndpsd[bin];
+ if (tmp > 0) {
+ v1 += tmp >> 2;
+ }
+ v=hth[bin >> s->halfratecod][s->fscod];
+ if (v1 > v) v=v1;
+ mask[bin] = v;
+ }
+
+ /* delta bit allocation */
+
+ if (deltbae == 0 || deltbae == 1) {
+ int band, seg, delta;
+ band = 0 ;
+ for (seg = 0; seg < deltnseg; seg++) {
+ band += deltoffst[seg] ;
+ if (deltba[seg] >= 4) {
+ delta = (deltba[seg] - 3) << 7;
+ } else {
+ delta = (deltba[seg] - 4) << 7;
+ }
+ for (k = 0; k < deltlen[seg]; k++) {
+ mask[band] += delta ;
+ band++ ;
+ }
+ }
+ }
+
+ /* compute bit allocation */
+
+ i = start ;
+ j = masktab[start] ;
+ do {
+ v=mask[j];
+ v -= snroffset ;
+ v -= s->floor ;
+ if (v < 0) v = 0;
+ v &= 0x1fe0 ;
+ v += s->floor ;
+
+ end1=bndtab[j] + bndsz[j];
+ if (end1 > end) end1=end;
+
+ for (k = i; k < end1; k++) {
+ address = (psd[i] - v) >> 5 ;
+ if (address < 0) address=0;
+ else if (address > 63) address=63;
+ bap[i] = baptab[address];
+ i++;
+ }
+ } while (end > bndtab[j++]) ;
+}
+
+typedef struct IComplex {
+ short re,im;
+} IComplex;
+
+static void fft_init(int ln)
+{
+ int i, j, m, n;
+ float alpha;
+
+ n = 1 << ln;
+
+ for(i=0;i<(n/2);i++) {
+ alpha = 2 * M_PI * (float)i / (float)n;
+ costab[i] = fix15(cos(alpha));
+ sintab[i] = fix15(sin(alpha));
+ }
+
+ for(i=0;i<n;i++) {
+ m=0;
+ for(j=0;j<ln;j++) {
+ m |= ((i >> j) & 1) << (ln-j-1);
+ }
+ fft_rev[i]=m;
+ }
+}
+
+/* butter fly op */
+#define BF(pre, pim, qre, qim, pre1, pim1, qre1, qim1) \
+{\
+ int ax, ay, bx, by;\
+ bx=pre1;\
+ by=pim1;\
+ ax=qre1;\
+ ay=qim1;\
+ pre = (bx + ax) >> 1;\
+ pim = (by + ay) >> 1;\
+ qre = (bx - ax) >> 1;\
+ qim = (by - ay) >> 1;\
+}
+
+#define MUL16(a,b) ((a) * (b))
+
+#define CMUL(pre, pim, are, aim, bre, bim) \
+{\
+ pre = (MUL16(are, bre) - MUL16(aim, bim)) >> 15;\
+ pim = (MUL16(are, bim) + MUL16(bre, aim)) >> 15;\
+}
+
+
+/* do a 2^n point complex fft on 2^ln points. */
+static void fft(IComplex *z, int ln)
+{
+ int j, l, np, np2;
+ int nblocks, nloops;
+ register IComplex *p,*q;
+ int tmp_re, tmp_im;
+
+ np = 1 << ln;
+
+ /* reverse */
+ for(j=0;j<np;j++) {
+ int k;
+ IComplex tmp;
+ k = fft_rev[j];
+ if (k < j) {
+ tmp = z[k];
+ z[k] = z[j];
+ z[j] = tmp;
+ }
+ }
+
+ /* pass 0 */
+
+ p=&z[0];
+ j=(np >> 1);
+ do {
+ BF(p[0].re, p[0].im, p[1].re, p[1].im,
+ p[0].re, p[0].im, p[1].re, p[1].im);
+ p+=2;
+ } while (--j != 0);
+
+ /* pass 1 */
+
+ p=&z[0];
+ j=np >> 2;
+ do {
+ BF(p[0].re, p[0].im, p[2].re, p[2].im,
+ p[0].re, p[0].im, p[2].re, p[2].im);
+ BF(p[1].re, p[1].im, p[3].re, p[3].im,
+ p[1].re, p[1].im, p[3].im, -p[3].re);
+ p+=4;
+ } while (--j != 0);
+
+ /* pass 2 .. ln-1 */
+
+ nblocks = np >> 3;
+ nloops = 1 << 2;
+ np2 = np >> 1;
+ do {
+ p = z;
+ q = z + nloops;
+ for (j = 0; j < nblocks; ++j) {
+
+ BF(p->re, p->im, q->re, q->im,
+ p->re, p->im, q->re, q->im);
+
+ p++;
+ q++;
+ for(l = nblocks; l < np2; l += nblocks) {
+ CMUL(tmp_re, tmp_im, costab[l], -sintab[l], q->re, q->im);
+ BF(p->re, p->im, q->re, q->im,
+ p->re, p->im, tmp_re, tmp_im);
+ p++;
+ q++;
+ }
+ p += nloops;
+ q += nloops;
+ }
+ nblocks = nblocks >> 1;
+ nloops = nloops << 1;
+ } while (nblocks != 0);
+}
+
+/* do a 512 point mdct */
+static void mdct512(int32_t *out, int16_t *in)
+{
+ int i, re, im, re1, im1;
+ int16_t rot[N];
+ IComplex x[N/4];
+
+ /* shift to simplify computations */
+ for(i=0;i<N/4;i++)
+ rot[i] = -in[i + 3*N/4];
+ for(i=N/4;i<N;i++)
+ rot[i] = in[i - N/4];
+
+ /* pre rotation */
+ for(i=0;i<N/4;i++) {
+ re = ((int)rot[2*i] - (int)rot[N-1-2*i]) >> 1;
+ im = -((int)rot[N/2+2*i] - (int)rot[N/2-1-2*i]) >> 1;
+ CMUL(x[i].re, x[i].im, re, im, -xcos1[i], xsin1[i]);
+ }
+
+ fft(x, MDCT_NBITS - 2);
+
+ /* post rotation */
+ for(i=0;i<N/4;i++) {
+ re = x[i].re;
+ im = x[i].im;
+ CMUL(re1, im1, re, im, xsin1[i], xcos1[i]);
+ out[2*i] = im1;
+ out[N/2-1-2*i] = re1;
+ }
+}
+
+/* XXX: use another norm ? */
+static int calc_exp_diff(uint8_t *exp1, uint8_t *exp2, int n)
+{
+ int sum, i;
+ sum = 0;
+ for(i=0;i<n;i++) {
+ sum += abs(exp1[i] - exp2[i]);
+ }
+ return sum;
+}
+
+static void compute_exp_strategy(uint8_t exp_strategy[NB_BLOCKS][AC3_MAX_CHANNELS],
+ uint8_t exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2],
+ int ch, int is_lfe)
+{
+ int i, j;
+ int exp_diff;
+
+ /* estimate if the exponent variation & decide if they should be
+ reused in the next frame */
+ exp_strategy[0][ch] = EXP_NEW;
+ for(i=1;i<NB_BLOCKS;i++) {
+ exp_diff = calc_exp_diff(exp[i][ch], exp[i-1][ch], N/2);
+#ifdef DEBUG
+ av_log(NULL, AV_LOG_DEBUG, "exp_diff=%d\n", exp_diff);
+#endif
+ if (exp_diff > EXP_DIFF_THRESHOLD)
+ exp_strategy[i][ch] = EXP_NEW;
+ else
+ exp_strategy[i][ch] = EXP_REUSE;
+ }
+ if (is_lfe)
+ return;
+
+ /* now select the encoding strategy type : if exponents are often
+ recoded, we use a coarse encoding */
+ i = 0;
+ while (i < NB_BLOCKS) {
+ j = i + 1;
+ while (j < NB_BLOCKS && exp_strategy[j][ch] == EXP_REUSE)
+ j++;
+ switch(j - i) {
+ case 1:
+ exp_strategy[i][ch] = EXP_D45;
+ break;
+ case 2:
+ case 3:
+ exp_strategy[i][ch] = EXP_D25;
+ break;
+ default:
+ exp_strategy[i][ch] = EXP_D15;
+ break;
+ }
+ i = j;
+ }
+}
+
+/* set exp[i] to min(exp[i], exp1[i]) */
+static void exponent_min(uint8_t exp[N/2], uint8_t exp1[N/2], int n)
+{
+ int i;
+
+ for(i=0;i<n;i++) {
+ if (exp1[i] < exp[i])
+ exp[i] = exp1[i];
+ }
+}
+
+/* update the exponents so that they are the ones the decoder will
+ decode. Return the number of bits used to code the exponents */
+static int encode_exp(uint8_t encoded_exp[N/2],
+ uint8_t exp[N/2],
+ int nb_exps,
+ int exp_strategy)
+{
+ int group_size, nb_groups, i, j, k, exp_min;
+ uint8_t exp1[N/2];
+
+ switch(exp_strategy) {
+ case EXP_D15:
+ group_size = 1;
+ break;
+ case EXP_D25:
+ group_size = 2;
+ break;
+ default:
+ case EXP_D45:
+ group_size = 4;
+ break;
+ }
+ nb_groups = ((nb_exps + (group_size * 3) - 4) / (3 * group_size)) * 3;
+
+ /* for each group, compute the minimum exponent */
+ exp1[0] = exp[0]; /* DC exponent is handled separately */
+ k = 1;
+ for(i=1;i<=nb_groups;i++) {
+ exp_min = exp[k];
+ assert(exp_min >= 0 && exp_min <= 24);
+ for(j=1;j<group_size;j++) {
+ if (exp[k+j] < exp_min)
+ exp_min = exp[k+j];
+ }
+ exp1[i] = exp_min;
+ k += group_size;
+ }
+
+ /* constraint for DC exponent */
+ if (exp1[0] > 15)
+ exp1[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++)
+ exp1[i] = FFMIN(exp1[i], exp1[i-1] + 2);
+ for (i=nb_groups-1;i>=0;i--)
+ exp1[i] = FFMIN(exp1[i], exp1[i+1] + 2);
+
+ /* now we have the exponent values the decoder will see */
+ encoded_exp[0] = exp1[0];
+ k = 1;
+ for(i=1;i<=nb_groups;i++) {
+ for(j=0;j<group_size;j++) {
+ encoded_exp[k+j] = exp1[i];
+ }
+ k += group_size;
+ }
+
+#if defined(DEBUG)
+ av_log(NULL, AV_LOG_DEBUG, "exponents: strategy=%d\n", exp_strategy);
+ for(i=0;i<=nb_groups * group_size;i++) {
+ av_log(NULL, AV_LOG_DEBUG, "%d ", encoded_exp[i]);
+ }
+ av_log(NULL, AV_LOG_DEBUG, "\n");
+#endif
+
+ return 4 + (nb_groups / 3) * 7;
+}
+
+/* return the size in bits taken by the mantissa */
+static int compute_mantissa_size(AC3EncodeContext *s, uint8_t *m, int nb_coefs)
+{
+ int bits, mant, i;
+
+ bits = 0;
+ for(i=0;i<nb_coefs;i++) {
+ mant = m[i];
+ switch(mant) {
+ case 0:
+ /* nothing */
+ break;
+ case 1:
+ /* 3 mantissa in 5 bits */
+ if (s->mant1_cnt == 0)
+ bits += 5;
+ if (++s->mant1_cnt == 3)
+ s->mant1_cnt = 0;
+ break;
+ case 2:
+ /* 3 mantissa in 7 bits */
+ if (s->mant2_cnt == 0)
+ bits += 7;
+ if (++s->mant2_cnt == 3)
+ s->mant2_cnt = 0;
+ break;
+ case 3:
+ bits += 3;
+ break;
+ case 4:
+ /* 2 mantissa in 7 bits */
+ if (s->mant4_cnt == 0)
+ bits += 7;
+ if (++s->mant4_cnt == 2)
+ s->mant4_cnt = 0;
+ break;
+ case 14:
+ bits += 14;
+ break;
+ case 15:
+ bits += 16;
+ break;
+ default:
+ bits += mant - 1;
+ break;
+ }
+ }
+ return bits;
+}
+
+
+static int bit_alloc(AC3EncodeContext *s,
+ uint8_t bap[NB_BLOCKS][AC3_MAX_CHANNELS][N/2],
+ uint8_t encoded_exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2],
+ uint8_t exp_strategy[NB_BLOCKS][AC3_MAX_CHANNELS],
+ int frame_bits, int csnroffst, int fsnroffst)
+{
+ int i, ch;
+
+ /* compute size */
+ for(i=0;i<NB_BLOCKS;i++) {
+ s->mant1_cnt = 0;
+ s->mant2_cnt = 0;
+ s->mant4_cnt = 0;
+ for(ch=0;ch<s->nb_all_channels;ch++) {
+ ac3_parametric_bit_allocation(&s->bit_alloc,
+ bap[i][ch], (int8_t *)encoded_exp[i][ch],
+ 0, s->nb_coefs[ch],
+ (((csnroffst-15) << 4) +
+ fsnroffst) << 2,
+ fgaintab[s->fgaincod[ch]],
+ ch == s->lfe_channel,
+ 2, 0, NULL, NULL, NULL);
+ frame_bits += compute_mantissa_size(s, bap[i][ch],
+ s->nb_coefs[ch]);
+ }
+ }
+#if 0
+ printf("csnr=%d fsnr=%d frame_bits=%d diff=%d\n",
+ csnroffst, fsnroffst, frame_bits,
+ 16 * s->frame_size - ((frame_bits + 7) & ~7));
+#endif
+ return 16 * s->frame_size - frame_bits;
+}
+
+#define SNR_INC1 4
+
+static int compute_bit_allocation(AC3EncodeContext *s,
+ uint8_t bap[NB_BLOCKS][AC3_MAX_CHANNELS][N/2],
+ uint8_t encoded_exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2],
+ uint8_t exp_strategy[NB_BLOCKS][AC3_MAX_CHANNELS],
+ int frame_bits)
+{
+ int i, ch;
+ int csnroffst, fsnroffst;
+ uint8_t bap1[NB_BLOCKS][AC3_MAX_CHANNELS][N/2];
+ static int frame_bits_inc[8] = { 0, 0, 2, 2, 2, 4, 2, 4 };
+
+ /* init default parameters */
+ s->sdecaycod = 2;
+ s->fdecaycod = 1;
+ s->sgaincod = 1;
+ s->dbkneecod = 2;
+ s->floorcod = 4;
+ for(ch=0;ch<s->nb_all_channels;ch++)
+ s->fgaincod[ch] = 4;
+
+ /* compute real values */
+ s->bit_alloc.fscod = s->fscod;
+ s->bit_alloc.halfratecod = s->halfratecod;
+ s->bit_alloc.sdecay = sdecaytab[s->sdecaycod] >> s->halfratecod;
+ s->bit_alloc.fdecay = fdecaytab[s->fdecaycod] >> s->halfratecod;
+ s->bit_alloc.sgain = sgaintab[s->sgaincod];
+ s->bit_alloc.dbknee = dbkneetab[s->dbkneecod];
+ s->bit_alloc.floor = floortab[s->floorcod];
+
+ /* header size */
+ frame_bits += 65;
+ // if (s->acmod == 2)
+ // frame_bits += 2;
+ frame_bits += frame_bits_inc[s->acmod];
+
+ /* audio blocks */
+ for(i=0;i<NB_BLOCKS;i++) {
+ frame_bits += s->nb_channels * 2 + 2; /* blksw * c, dithflag * c, dynrnge, cplstre */
+ if (s->acmod == 2) {
+ frame_bits++; /* rematstr */
+ if(i==0) frame_bits += 4;
+ }
+ frame_bits += 2 * s->nb_channels; /* chexpstr[2] * c */
+ if (s->lfe)
+ frame_bits++; /* lfeexpstr */
+ for(ch=0;ch<s->nb_channels;ch++) {
+ if (exp_strategy[i][ch] != EXP_REUSE)
+ frame_bits += 6 + 2; /* chbwcod[6], gainrng[2] */
+ }
+ frame_bits++; /* baie */
+ frame_bits++; /* snr */
+ frame_bits += 2; /* delta / skip */
+ }
+ frame_bits++; /* cplinu for block 0 */
+ /* bit alloc info */
+ /* sdcycod[2], fdcycod[2], sgaincod[2], dbpbcod[2], floorcod[3] */
+ /* csnroffset[6] */
+ /* (fsnoffset[4] + fgaincod[4]) * c */
+ frame_bits += 2*4 + 3 + 6 + s->nb_all_channels * (4 + 3);
+
+ /* auxdatae, crcrsv */
+ frame_bits += 2;
+
+ /* CRC */
+ frame_bits += 16;
+
+ /* now the big work begins : do the bit allocation. Modify the snr
+ offset until we can pack everything in the requested frame size */
+
+ csnroffst = s->csnroffst;
+ while (csnroffst >= 0 &&
+ bit_alloc(s, bap, encoded_exp, exp_strategy, frame_bits, csnroffst, 0) < 0)
+ csnroffst -= SNR_INC1;
+ if (csnroffst < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Bit allocation failed, try increasing the bitrate, -ab 384 for example!\n");
+ return -1;
+ }
+ while ((csnroffst + SNR_INC1) <= 63 &&
+ bit_alloc(s, bap1, encoded_exp, exp_strategy, frame_bits,
+ csnroffst + SNR_INC1, 0) >= 0) {
+ csnroffst += SNR_INC1;
+ memcpy(bap, bap1, sizeof(bap1));
+ }
+ while ((csnroffst + 1) <= 63 &&
+ bit_alloc(s, bap1, encoded_exp, exp_strategy, frame_bits, csnroffst + 1, 0) >= 0) {
+ csnroffst++;
+ memcpy(bap, bap1, sizeof(bap1));
+ }
+
+ fsnroffst = 0;
+ while ((fsnroffst + SNR_INC1) <= 15 &&
+ bit_alloc(s, bap1, encoded_exp, exp_strategy, frame_bits,
+ csnroffst, fsnroffst + SNR_INC1) >= 0) {
+ fsnroffst += SNR_INC1;
+ memcpy(bap, bap1, sizeof(bap1));
+ }
+ while ((fsnroffst + 1) <= 15 &&
+ bit_alloc(s, bap1, encoded_exp, exp_strategy, frame_bits,
+ csnroffst, fsnroffst + 1) >= 0) {
+ fsnroffst++;
+ memcpy(bap, bap1, sizeof(bap1));
+ }
+
+ s->csnroffst = csnroffst;
+ for(ch=0;ch<s->nb_all_channels;ch++)
+ s->fsnroffst[ch] = fsnroffst;
+#if defined(DEBUG_BITALLOC)
+ {
+ int j;
+
+ for(i=0;i<6;i++) {
+ for(ch=0;ch<s->nb_all_channels;ch++) {
+ printf("Block #%d Ch%d:\n", i, ch);
+ printf("bap=");
+ for(j=0;j<s->nb_coefs[ch];j++) {
+ printf("%d ",bap[i][ch][j]);
+ }
+ printf("\n");
+ }
+ }
+ }
+#endif
+ return 0;
+}
+
+void ac3_common_init(void)
+{
+ int i, j, k, l, v;
+ /* compute bndtab and masktab from bandsz */
+ k = 0;
+ l = 0;
+ for(i=0;i<50;i++) {
+ bndtab[i] = l;
+ v = bndsz[i];
+ for(j=0;j<v;j++) masktab[k++]=i;
+ l += v;
+ }
+ bndtab[50] = l;
+}
+
+
+static int AC3_encode_init(AVCodecContext *avctx)
+{
+ int freq = avctx->sample_rate;
+ int bitrate = avctx->bit_rate;
+ int channels = avctx->channels;
+ AC3EncodeContext *s = avctx->priv_data;
+ int i, j, ch;
+ float alpha;
+ static const uint8_t acmod_defs[6] = {
+ 0x01, /* C */
+ 0x02, /* L R */
+ 0x03, /* L C R */
+ 0x06, /* L R SL SR */
+ 0x07, /* L C R SL SR */
+ 0x07, /* L C R SL SR (+LFE) */
+ };
+
+ avctx->frame_size = AC3_FRAME_SIZE;
+
+ /* number of channels */
+ if (channels < 1 || channels > 6)
+ return -1;
+ s->acmod = acmod_defs[channels - 1];
+ s->lfe = (channels == 6) ? 1 : 0;
+ s->nb_all_channels = channels;
+ s->nb_channels = channels > 5 ? 5 : channels;
+ s->lfe_channel = s->lfe ? 5 : -1;
+
+ /* frequency */
+ for(i=0;i<3;i++) {
+ for(j=0;j<3;j++)
+ if ((ac3_freqs[j] >> i) == freq)
+ goto found;
+ }
+ return -1;
+ found:
+ s->sample_rate = freq;
+ s->halfratecod = i;
+ s->fscod = j;
+ s->bsid = 8 + s->halfratecod;
+ s->bsmod = 0; /* complete main audio service */
+
+ /* bitrate & frame size */
+ bitrate /= 1000;
+ for(i=0;i<19;i++) {
+ if ((ac3_bitratetab[i] >> s->halfratecod) == bitrate)
+ break;
+ }
+ if (i == 19)
+ return -1;
+ s->bit_rate = bitrate;
+ s->frmsizecod = i << 1;
+ s->frame_size_min = (bitrate * 1000 * AC3_FRAME_SIZE) / (freq * 16);
+ s->bits_written = 0;
+ s->samples_written = 0;
+ s->frame_size = s->frame_size_min;
+
+ /* bit allocation init */
+ for(ch=0;ch<s->nb_channels;ch++) {
+ /* bandwidth for each channel */
+ /* XXX: should compute the bandwidth according to the frame
+ size, so that we avoid anoying high freq artefacts */
+ s->chbwcod[ch] = 50; /* sample bandwidth as mpeg audio layer 2 table 0 */
+ s->nb_coefs[ch] = ((s->chbwcod[ch] + 12) * 3) + 37;
+ }
+ if (s->lfe) {
+ s->nb_coefs[s->lfe_channel] = 7; /* fixed */
+ }
+ /* initial snr offset */
+ s->csnroffst = 40;
+
+ ac3_common_init();
+
+ /* mdct init */
+ fft_init(MDCT_NBITS - 2);
+ for(i=0;i<N/4;i++) {
+ alpha = 2 * M_PI * (i + 1.0 / 8.0) / (float)N;
+ xcos1[i] = fix15(-cos(alpha));
+ xsin1[i] = fix15(-sin(alpha));
+ }
+
+ avctx->coded_frame= avcodec_alloc_frame();
+ avctx->coded_frame->key_frame= 1;
+
+ return 0;
+}
+
+/* output the AC3 frame header */
+static void output_frame_header(AC3EncodeContext *s, unsigned char *frame)
+{
+ init_put_bits(&s->pb, frame, AC3_MAX_CODED_FRAME_SIZE);
+
+ 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->fscod);
+ put_bits(&s->pb, 6, s->frmsizecod + (s->frame_size - s->frame_size_min));
+ put_bits(&s->pb, 5, s->bsid);
+ put_bits(&s->pb, 3, s->bsmod);
+ put_bits(&s->pb, 3, s->acmod);
+ if ((s->acmod & 0x01) && s->acmod != 0x01)
+ put_bits(&s->pb, 2, 1); /* XXX -4.5 dB */
+ if (s->acmod & 0x04)
+ put_bits(&s->pb, 2, 1); /* XXX -6 dB */
+ if (s->acmod == 0x02)
+ put_bits(&s->pb, 2, 0); /* surround not indicated */
+ put_bits(&s->pb, 1, s->lfe); /* LFE */
+ put_bits(&s->pb, 5, 31); /* dialog norm: -31 db */
+ put_bits(&s->pb, 1, 0); /* no compression control word */
+ put_bits(&s->pb, 1, 0); /* no lang code */
+ put_bits(&s->pb, 1, 0); /* no audio production info */
+ put_bits(&s->pb, 1, 0); /* no copyright */
+ put_bits(&s->pb, 1, 1); /* original bitstream */
+ 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 addtional bit stream info */
+}
+
+/* symetric quantization on 'levels' levels */
+static inline int sym_quant(int c, int e, int levels)
+{
+ int v;
+
+ if (c >= 0) {
+ v = (levels * (c << e)) >> 24;
+ v = (v + 1) >> 1;
+ v = (levels >> 1) + v;
+ } else {
+ v = (levels * ((-c) << e)) >> 24;
+ v = (v + 1) >> 1;
+ v = (levels >> 1) - v;
+ }
+ assert (v >= 0 && v < levels);
+ return v;
+}
+
+/* asymetric quantization on 2^qbits levels */
+static inline int asym_quant(int c, int e, int qbits)
+{
+ int lshift, m, v;
+
+ lshift = e + qbits - 24;
+ if (lshift >= 0)
+ v = c << lshift;
+ else
+ v = c >> (-lshift);
+ /* rounding */
+ v = (v + 1) >> 1;
+ m = (1 << (qbits-1));
+ if (v >= m)
+ v = m - 1;
+ assert(v >= -m);
+ return v & ((1 << qbits)-1);
+}
+
+/* Output one audio block. There are NB_BLOCKS audio blocks in one AC3
+ frame */
+static void output_audio_block(AC3EncodeContext *s,
+ uint8_t exp_strategy[AC3_MAX_CHANNELS],
+ uint8_t encoded_exp[AC3_MAX_CHANNELS][N/2],
+ uint8_t bap[AC3_MAX_CHANNELS][N/2],
+ int32_t mdct_coefs[AC3_MAX_CHANNELS][N/2],
+ int8_t global_exp[AC3_MAX_CHANNELS],
+ int block_num)
+{
+ int ch, nb_groups, group_size, i, baie, rbnd;
+ uint8_t *p;
+ uint16_t qmant[AC3_MAX_CHANNELS][N/2];
+ int exp0, exp1;
+ int mant1_cnt, mant2_cnt, mant4_cnt;
+ uint16_t *qmant1_ptr, *qmant2_ptr, *qmant4_ptr;
+ int delta0, delta1, delta2;
+
+ for(ch=0;ch<s->nb_channels;ch++)
+ put_bits(&s->pb, 1, 0); /* 512 point MDCT */
+ for(ch=0;ch<s->nb_channels;ch++)
+ put_bits(&s->pb, 1, 1); /* no dither */
+ put_bits(&s->pb, 1, 0); /* no dynamic range */
+ if (block_num == 0) {
+ /* for block 0, even if no coupling, we must say it. This is a
+ waste of bit :-) */
+ put_bits(&s->pb, 1, 1); /* coupling strategy present */
+ put_bits(&s->pb, 1, 0); /* no coupling strategy */
+ } else {
+ put_bits(&s->pb, 1, 0); /* no new coupling strategy */
+ }
+
+ if (s->acmod == 2)
+ {
+ if(block_num==0)
+ {
+ /* first block must define rematrixing (rematstr) */
+ put_bits(&s->pb, 1, 1);
+
+ /* dummy rematrixing rematflg(1:4)=0 */
+ for (rbnd=0;rbnd<4;rbnd++)
+ put_bits(&s->pb, 1, 0);
+ }
+ else
+ {
+ /* no matrixing (but should be used in the future) */
+ put_bits(&s->pb, 1, 0);
+ }
+ }
+
+#if defined(DEBUG)
+ {
+ static int count = 0;
+ av_log(NULL, AV_LOG_DEBUG, "Block #%d (%d)\n", block_num, count++);
+ }
+#endif
+ /* exponent strategy */
+ for(ch=0;ch<s->nb_channels;ch++) {
+ put_bits(&s->pb, 2, exp_strategy[ch]);
+ }
+
+ if (s->lfe) {
+ put_bits(&s->pb, 1, exp_strategy[s->lfe_channel]);
+ }
+
+ for(ch=0;ch<s->nb_channels;ch++) {
+ if (exp_strategy[ch] != EXP_REUSE)
+ put_bits(&s->pb, 6, s->chbwcod[ch]);
+ }
+
+ /* exponents */
+ for (ch = 0; ch < s->nb_all_channels; ch++) {
+ switch(exp_strategy[ch]) {
+ case EXP_REUSE:
+ continue;
+ case EXP_D15:
+ group_size = 1;
+ break;
+ case EXP_D25:
+ group_size = 2;
+ break;
+ default:
+ case EXP_D45:
+ group_size = 4;
+ break;
+ }
+ nb_groups = (s->nb_coefs[ch] + (group_size * 3) - 4) / (3 * group_size);
+ p = encoded_exp[ch];
+
+ /* first exponent */
+ exp1 = *p++;
+ put_bits(&s->pb, 4, exp1);
+
+ /* next ones are delta encoded */
+ for(i=0;i<nb_groups;i++) {
+ /* merge three delta in one code */
+ exp0 = exp1;
+ exp1 = p[0];
+ p += group_size;
+ delta0 = exp1 - exp0 + 2;
+
+ exp0 = exp1;
+ exp1 = p[0];
+ p += group_size;
+ delta1 = exp1 - exp0 + 2;
+
+ exp0 = exp1;
+ exp1 = p[0];
+ p += group_size;
+ delta2 = exp1 - exp0 + 2;
+
+ put_bits(&s->pb, 7, ((delta0 * 5 + delta1) * 5) + delta2);
+ }
+
+ if (ch != s->lfe_channel)
+ put_bits(&s->pb, 2, 0); /* no gain range info */
+ }
+
+ /* bit allocation info */
+ baie = (block_num == 0);
+ put_bits(&s->pb, 1, baie);
+ if (baie) {
+ put_bits(&s->pb, 2, s->sdecaycod);
+ put_bits(&s->pb, 2, s->fdecaycod);
+ put_bits(&s->pb, 2, s->sgaincod);
+ put_bits(&s->pb, 2, s->dbkneecod);
+ put_bits(&s->pb, 3, s->floorcod);
+ }
+
+ /* snr offset */
+ put_bits(&s->pb, 1, baie); /* always present with bai */
+ if (baie) {
+ put_bits(&s->pb, 6, s->csnroffst);
+ for(ch=0;ch<s->nb_all_channels;ch++) {
+ put_bits(&s->pb, 4, s->fsnroffst[ch]);
+ put_bits(&s->pb, 3, s->fgaincod[ch]);
+ }
+ }
+
+ put_bits(&s->pb, 1, 0); /* no delta bit allocation */
+ put_bits(&s->pb, 1, 0); /* no data to skip */
+
+ /* mantissa encoding : we use two passes to handle the grouping. A
+ one pass method may be faster, but it would necessitate to
+ modify the output stream. */
+
+ /* first pass: quantize */
+ mant1_cnt = mant2_cnt = mant4_cnt = 0;
+ qmant1_ptr = qmant2_ptr = qmant4_ptr = NULL;
+
+ for (ch = 0; ch < s->nb_all_channels; ch++) {
+ int b, c, e, v;
+
+ for(i=0;i<s->nb_coefs[ch];i++) {
+ c = mdct_coefs[ch][i];
+ e = encoded_exp[ch][i] - global_exp[ch];
+ b = bap[ch][i];
+ switch(b) {
+ case 0:
+ v = 0;
+ break;
+ case 1:
+ v = sym_quant(c, e, 3);
+ switch(mant1_cnt) {
+ case 0:
+ qmant1_ptr = &qmant[ch][i];
+ v = 9 * v;
+ mant1_cnt = 1;
+ break;
+ case 1:
+ *qmant1_ptr += 3 * v;
+ mant1_cnt = 2;
+ v = 128;
+ break;
+ default:
+ *qmant1_ptr += v;
+ mant1_cnt = 0;
+ v = 128;
+ break;
+ }
+ break;
+ case 2:
+ v = sym_quant(c, e, 5);
+ switch(mant2_cnt) {
+ case 0:
+ qmant2_ptr = &qmant[ch][i];
+ v = 25 * v;
+ mant2_cnt = 1;
+ break;
+ case 1:
+ *qmant2_ptr += 5 * v;
+ mant2_cnt = 2;
+ v = 128;
+ break;
+ default:
+ *qmant2_ptr += v;
+ 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(mant4_cnt) {
+ case 0:
+ qmant4_ptr = &qmant[ch][i];
+ v = 11 * v;
+ mant4_cnt = 1;
+ break;
+ default:
+ *qmant4_ptr += v;
+ 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, b - 1);
+ break;
+ }
+ qmant[ch][i] = v;
+ }
+ }
+
+ /* second pass : output the values */
+ for (ch = 0; ch < s->nb_all_channels; ch++) {
+ int b, q;
+
+ for(i=0;i<s->nb_coefs[ch];i++) {
+ q = qmant[ch][i];
+ b = bap[ch][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_bits(&s->pb, 3, q);
+ break;
+ case 4:
+ if (q != 128)
+ put_bits(&s->pb, 7, q);
+ break;
+ case 14:
+ put_bits(&s->pb, 14, q);
+ break;
+ case 15:
+ put_bits(&s->pb, 16, q);
+ break;
+ default:
+ put_bits(&s->pb, b - 1, q);
+ break;
+ }
+ }
+ }
+}
+
+#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;
+}
+
+
+/* compute log2(max(abs(tab[]))) */
+static int log2_tab(int16_t *tab, int n)
+{
+ int i, v;
+
+ v = 0;
+ for(i=0;i<n;i++) {
+ v |= abs(tab[i]);
+ }
+ return av_log2(v);
+}
+
+static void lshift_tab(int16_t *tab, int n, int lshift)
+{
+ int i;
+
+ if (lshift > 0) {
+ for(i=0;i<n;i++) {
+ tab[i] <<= lshift;
+ }
+ } else if (lshift < 0) {
+ lshift = -lshift;
+ for(i=0;i<n;i++) {
+ tab[i] >>= lshift;
+ }
+ }
+}
+
+/* fill the end of the frame and compute the two crcs */
+static int output_frame_end(AC3EncodeContext *s)
+{
+ int frame_size, frame_size_58, n, crc1, crc2, crc_inv;
+ uint8_t *frame;
+
+ frame_size = s->frame_size; /* frame size in words */
+ /* align to 8 bits */
+ flush_put_bits(&s->pb);
+ /* add zero bytes to reach the frame size */
+ frame = s->pb.buf;
+ n = 2 * s->frame_size - (pbBufPtr(&s->pb) - frame) - 2;
+ assert(n >= 0);
+ if(n>0)
+ memset(pbBufPtr(&s->pb), 0, n);
+
+ /* Now we must compute both crcs : this is not so easy for crc1
+ because it is at the beginning of the data... */
+ frame_size_58 = (frame_size >> 1) + (frame_size >> 3);
+ crc1 = bswap_16(av_crc(av_crc8005, 0, frame + 4, 2 * frame_size_58 - 4));
+ /* XXX: could precompute crc_inv */
+ crc_inv = pow_poly((CRC16_POLY >> 1), (16 * frame_size_58) - 16, CRC16_POLY);
+ crc1 = mul_poly(crc_inv, crc1, CRC16_POLY);
+ frame[2] = crc1 >> 8;
+ frame[3] = crc1;
+
+ crc2 = bswap_16(av_crc(av_crc8005, 0, frame + 2 * frame_size_58, (frame_size - frame_size_58) * 2 - 2));
+ frame[2*frame_size - 2] = crc2 >> 8;
+ frame[2*frame_size - 1] = crc2;
+
+ // printf("n=%d frame_size=%d\n", n, frame_size);
+ return frame_size * 2;
+}
+
+static int AC3_encode_frame(AVCodecContext *avctx,
+ unsigned char *frame, int buf_size, void *data)
+{
+ AC3EncodeContext *s = avctx->priv_data;
+ int16_t *samples = data;
+ int i, j, k, v, ch;
+ int16_t input_samples[N];
+ int32_t mdct_coef[NB_BLOCKS][AC3_MAX_CHANNELS][N/2];
+ uint8_t exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2];
+ uint8_t exp_strategy[NB_BLOCKS][AC3_MAX_CHANNELS];
+ uint8_t encoded_exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2];
+ uint8_t bap[NB_BLOCKS][AC3_MAX_CHANNELS][N/2];
+ int8_t exp_samples[NB_BLOCKS][AC3_MAX_CHANNELS];
+ int frame_bits;
+
+ frame_bits = 0;
+ for(ch=0;ch<s->nb_all_channels;ch++) {
+ /* fixed mdct to the six sub blocks & exponent computation */
+ for(i=0;i<NB_BLOCKS;i++) {
+ int16_t *sptr;
+ int sinc;
+
+ /* compute input samples */
+ memcpy(input_samples, s->last_samples[ch], N/2 * sizeof(int16_t));
+ sinc = s->nb_all_channels;
+ sptr = samples + (sinc * (N/2) * i) + ch;
+ for(j=0;j<N/2;j++) {
+ v = *sptr;
+ input_samples[j + N/2] = v;
+ s->last_samples[ch][j] = v;
+ sptr += sinc;
+ }
+
+ /* apply the MDCT window */
+ for(j=0;j<N/2;j++) {
+ input_samples[j] = MUL16(input_samples[j],
+ ac3_window[j]) >> 15;
+ input_samples[N-j-1] = MUL16(input_samples[N-j-1],
+ ac3_window[j]) >> 15;
+ }
+
+ /* Normalize the samples to use the maximum available
+ precision */
+ v = 14 - log2_tab(input_samples, N);
+ if (v < 0)
+ v = 0;
+ exp_samples[i][ch] = v - 10;
+ lshift_tab(input_samples, N, v);
+
+ /* do the MDCT */
+ mdct512(mdct_coef[i][ch], input_samples);
+
+ /* compute "exponents". We take into account the
+ normalization there */
+ for(j=0;j<N/2;j++) {
+ int e;
+ v = abs(mdct_coef[i][ch][j]);
+ if (v == 0)
+ e = 24;
+ else {
+ e = 23 - av_log2(v) + exp_samples[i][ch];
+ if (e >= 24) {
+ e = 24;
+ mdct_coef[i][ch][j] = 0;
+ }
+ }
+ exp[i][ch][j] = e;
+ }
+ }
+
+ compute_exp_strategy(exp_strategy, exp, ch, ch == s->lfe_channel);
+
+ /* compute the exponents as the decoder will see them. The
+ EXP_REUSE case must be handled carefully : we select the
+ min of the exponents */
+ i = 0;
+ while (i < NB_BLOCKS) {
+ j = i + 1;
+ while (j < NB_BLOCKS && exp_strategy[j][ch] == EXP_REUSE) {
+ exponent_min(exp[i][ch], exp[j][ch], s->nb_coefs[ch]);
+ j++;
+ }
+ frame_bits += encode_exp(encoded_exp[i][ch],
+ exp[i][ch], s->nb_coefs[ch],
+ exp_strategy[i][ch]);
+ /* copy encoded exponents for reuse case */
+ for(k=i+1;k<j;k++) {
+ memcpy(encoded_exp[k][ch], encoded_exp[i][ch],
+ s->nb_coefs[ch] * sizeof(uint8_t));
+ }
+ i = j;
+ }
+ }
+
+ /* adjust for fractional frame sizes */
+ while(s->bits_written >= s->bit_rate*1000 && s->samples_written >= s->sample_rate) {
+ s->bits_written -= s->bit_rate*1000;
+ s->samples_written -= s->sample_rate;
+ }
+ s->frame_size = s->frame_size_min + (s->bits_written * s->sample_rate < s->samples_written * s->bit_rate*1000);
+ s->bits_written += s->frame_size * 16;
+ s->samples_written += AC3_FRAME_SIZE;
+
+ compute_bit_allocation(s, bap, encoded_exp, exp_strategy, frame_bits);
+ /* everything is known... let's output the frame */
+ output_frame_header(s, frame);
+
+ for(i=0;i<NB_BLOCKS;i++) {
+ output_audio_block(s, exp_strategy[i], encoded_exp[i],
+ bap[i], mdct_coef[i], exp_samples[i], i);
+ }
+ return output_frame_end(s);
+}
+
+static int AC3_encode_close(AVCodecContext *avctx)
+{
+ av_freep(&avctx->coded_frame);
+ return 0;
+}
+
+#if 0
+/*************************************************************************/
+/* TEST */
+
+#define FN (N/4)
+
+void fft_test(void)
+{
+ IComplex in[FN], in1[FN];
+ int k, n, i;
+ float sum_re, sum_im, a;
+
+ /* FFT test */
+
+ for(i=0;i<FN;i++) {
+ in[i].re = random() % 65535 - 32767;
+ in[i].im = random() % 65535 - 32767;
+ in1[i] = in[i];
+ }
+ fft(in, 7);
+
+ /* do it by hand */
+ for(k=0;k<FN;k++) {
+ sum_re = 0;
+ sum_im = 0;
+ for(n=0;n<FN;n++) {
+ a = -2 * M_PI * (n * k) / FN;
+ sum_re += in1[n].re * cos(a) - in1[n].im * sin(a);
+ sum_im += in1[n].re * sin(a) + in1[n].im * cos(a);
+ }
+ printf("%3d: %6d,%6d %6.0f,%6.0f\n",
+ k, in[k].re, in[k].im, sum_re / FN, sum_im / FN);
+ }
+}
+
+void mdct_test(void)
+{
+ int16_t input[N];
+ int32_t output[N/2];
+ float input1[N];
+ float output1[N/2];
+ float s, a, err, e, emax;
+ int i, k, n;
+
+ for(i=0;i<N;i++) {
+ input[i] = (random() % 65535 - 32767) * 9 / 10;
+ input1[i] = input[i];
+ }
+
+ mdct512(output, input);
+
+ /* do it by hand */
+ for(k=0;k<N/2;k++) {
+ s = 0;
+ for(n=0;n<N;n++) {
+ a = (2*M_PI*(2*n+1+N/2)*(2*k+1) / (4 * N));
+ s += input1[n] * cos(a);
+ }
+ output1[k] = -2 * s / N;
+ }
+
+ err = 0;
+ emax = 0;
+ for(i=0;i<N/2;i++) {
+ printf("%3d: %7d %7.0f\n", i, output[i], output1[i]);
+ e = output[i] - output1[i];
+ if (e > emax)
+ emax = e;
+ err += e * e;
+ }
+ printf("err2=%f emax=%f\n", err / (N/2), emax);
+}
+
+void test_ac3(void)
+{
+ AC3EncodeContext ctx;
+ unsigned char frame[AC3_MAX_CODED_FRAME_SIZE];
+ short samples[AC3_FRAME_SIZE];
+ int ret, i;
+
+ AC3_encode_init(&ctx, 44100, 64000, 1);
+
+ fft_test();
+ mdct_test();
+
+ for(i=0;i<AC3_FRAME_SIZE;i++)
+ samples[i] = (int)(sin(2*M_PI*i*1000.0/44100) * 10000);
+ ret = AC3_encode_frame(&ctx, frame, samples);
+ printf("ret=%d\n", ret);
+}
+#endif
+
+AVCodec ac3_encoder = {
+ "ac3",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_AC3,
+ sizeof(AC3EncodeContext),
+ AC3_encode_init,
+ AC3_encode_frame,
+ AC3_encode_close,
+ NULL,
+};
diff --git a/contrib/ffmpeg/libavcodec/ac3tab.h b/contrib/ffmpeg/libavcodec/ac3tab.h
new file mode 100644
index 000000000..9f90ae95c
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ac3tab.h
@@ -0,0 +1,205 @@
+/*
+ * AC3 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 ac3tab.h
+ * tables taken directly from AC3 spec.
+ */
+
+/* possible frequencies */
+static const uint16_t ac3_freqs[3] = { 48000, 44100, 32000 };
+
+/* possible bitrates */
+static const uint16_t ac3_bitratetab[19] = {
+ 32, 40, 48, 56, 64, 80, 96, 112, 128,
+ 160, 192, 224, 256, 320, 384, 448, 512, 576, 640
+};
+
+/* AC3 MDCT window */
+
+/* MDCT window */
+static const int16_t ac3_window[256] = {
+ 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,
+};
+
+static uint8_t masktab[253];
+
+static const uint8_t latab[260]= {
+0x0040,0x003f,0x003e,0x003d,0x003c,0x003b,0x003a,0x0039,0x0038,0x0037,
+0x0036,0x0035,0x0034,0x0034,0x0033,0x0032,0x0031,0x0030,0x002f,0x002f,
+0x002e,0x002d,0x002c,0x002c,0x002b,0x002a,0x0029,0x0029,0x0028,0x0027,
+0x0026,0x0026,0x0025,0x0024,0x0024,0x0023,0x0023,0x0022,0x0021,0x0021,
+0x0020,0x0020,0x001f,0x001e,0x001e,0x001d,0x001d,0x001c,0x001c,0x001b,
+0x001b,0x001a,0x001a,0x0019,0x0019,0x0018,0x0018,0x0017,0x0017,0x0016,
+0x0016,0x0015,0x0015,0x0015,0x0014,0x0014,0x0013,0x0013,0x0013,0x0012,
+0x0012,0x0012,0x0011,0x0011,0x0011,0x0010,0x0010,0x0010,0x000f,0x000f,
+0x000f,0x000e,0x000e,0x000e,0x000d,0x000d,0x000d,0x000d,0x000c,0x000c,
+0x000c,0x000c,0x000b,0x000b,0x000b,0x000b,0x000a,0x000a,0x000a,0x000a,
+0x000a,0x0009,0x0009,0x0009,0x0009,0x0009,0x0008,0x0008,0x0008,0x0008,
+0x0008,0x0008,0x0007,0x0007,0x0007,0x0007,0x0007,0x0007,0x0006,0x0006,
+0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0005,0x0005,0x0005,0x0005,
+0x0005,0x0005,0x0005,0x0005,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,
+0x0004,0x0004,0x0004,0x0004,0x0004,0x0003,0x0003,0x0003,0x0003,0x0003,
+0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0002,
+0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,
+0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,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,0x0001,0x0001,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+};
+
+static const uint16_t hth[50][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 },
+};
+
+static const uint8_t baptab[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,
+};
+
+static const uint8_t sdecaytab[4]={
+ 0x0f, 0x11, 0x13, 0x15,
+};
+
+static const uint8_t fdecaytab[4]={
+ 0x3f, 0x53, 0x67, 0x7b,
+};
+
+static const uint16_t sgaintab[4]= {
+ 0x540, 0x4d8, 0x478, 0x410,
+};
+
+static const uint16_t dbkneetab[4]= {
+ 0x000, 0x700, 0x900, 0xb00,
+};
+
+static const int16_t floortab[8]= {
+ 0x2f0, 0x2b0, 0x270, 0x230, 0x1f0, 0x170, 0x0f0, 0xf800,
+};
+
+static const uint16_t fgaintab[8]= {
+ 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, 0x400,
+};
+
+static const uint8_t bndsz[50]={
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, 6, 6, 6, 6, 6, 6, 12, 12, 12, 12, 24, 24, 24, 24, 24
+};
+
+static uint8_t bndtab[51];
+
+/* fft & mdct sin cos tables */
+static int16_t costab[64];
+static int16_t sintab[64];
+static int16_t fft_rev[512];
+static int16_t xcos1[128];
+static int16_t xsin1[128];
diff --git a/contrib/ffmpeg/libavcodec/adpcm.c b/contrib/ffmpeg/libavcodec/adpcm.c
new file mode 100644
index 000000000..ec3fe6f6e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/adpcm.c
@@ -0,0 +1,1370 @@
+/*
+ * ADPCM codecs
+ * 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 "bitstream.h"
+
+/**
+ * @file adpcm.c
+ * ADPCM codecs.
+ * 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)
+ *
+ * Features and limitations:
+ *
+ * Reference documents:
+ * http://www.pcisys.net/~melanson/codecs/simpleaudio.html
+ * http://www.geocities.com/SiliconValley/8682/aud3.txt
+ * http://openquicktime.sourceforge.net/plugins.htm
+ * XAnim sources (xa_codec.c) http://www.rasnaimaging.com/people/lapus/download.html
+ * http://www.cs.ucla.edu/~leec/mediabench/applications.html
+ * SoX source code http://home.sprynet.com/~cbagwell/sox.html
+ *
+ * CD-ROM XA:
+ * http://ku-www.ss.titech.ac.jp/~yatsushi/xaadpcm.html
+ * vagpack & depack http://homepages.compuserve.de/bITmASTER32/psx-index.html
+ * readstr http://www.geocities.co.jp/Playtown/2004/
+ */
+
+#define BLKSIZE 1024
+
+#define CLAMP_TO_SHORT(value) \
+if (value > 32767) \
+ value = 32767; \
+else if (value < -32768) \
+ value = -32768; \
+
+/* step_table[] and index_table[] are from the ADPCM reference source */
+/* This is the index table: */
+static const int 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:
+ */
+static const int 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
+};
+
+/* These are for MS-ADPCM */
+/* AdaptationTable[], AdaptCoeff1[], and AdaptCoeff2[] are from libsndfile */
+static const int AdaptationTable[] = {
+ 230, 230, 230, 230, 307, 409, 512, 614,
+ 768, 614, 512, 409, 307, 230, 230, 230
+};
+
+static const int AdaptCoeff1[] = {
+ 256, 512, 0, 192, 240, 460, 392
+};
+
+static const int AdaptCoeff2[] = {
+ 0, -256, 0, 64, 0, -208, -232
+};
+
+/* 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
+};
+
+static const int ct_adpcm_table[8] = {
+ 0x00E6, 0x00E6, 0x00E6, 0x00E6,
+ 0x0133, 0x0199, 0x0200, 0x0266
+};
+
+// 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 }
+};
+
+static const int yamaha_indexscale[] = {
+ 230, 230, 230, 230, 307, 409, 512, 614,
+ 230, 230, 230, 230, 307, 409, 512, 614
+};
+
+static const int yamaha_difflookup[] = {
+ 1, 3, 5, 7, 9, 11, 13, 15,
+ -1, -3, -5, -7, -9, -11, -13, -15
+};
+
+/* end of tables */
+
+typedef struct ADPCMChannelStatus {
+ int predictor;
+ short int step_index;
+ int step;
+ /* for encoding */
+ int prev_sample;
+
+ /* MS version */
+ short sample1;
+ short sample2;
+ int coeff1;
+ int coeff2;
+ int idelta;
+} ADPCMChannelStatus;
+
+typedef struct ADPCMContext {
+ int channel; /* for stereo MOVs, decode left, then decode right, then tell it's decoded */
+ ADPCMChannelStatus status[2];
+ short sample_buffer[32]; /* hold left samples while waiting for right samples */
+
+ /* SWF only */
+ int nb_bits;
+ int nb_samples;
+} ADPCMContext;
+
+/* XXX: implement encoding */
+
+#ifdef CONFIG_ENCODERS
+static int adpcm_encode_init(AVCodecContext *avctx)
+{
+ if (avctx->channels > 2)
+ return -1; /* only stereo or mono =) */
+ switch(avctx->codec->id) {
+ case CODEC_ID_ADPCM_IMA_QT:
+ av_log(avctx, AV_LOG_ERROR, "ADPCM: codec adpcm_ima_qt unsupported for encoding !\n");
+ avctx->frame_size = 64; /* XXX: can multiple of avctx->channels * 64 (left and right blocks are interleaved) */
+ return -1;
+ break;
+ case CODEC_ID_ADPCM_IMA_WAV:
+ avctx->frame_size = (BLKSIZE - 4 * avctx->channels) * 8 / (4 * avctx->channels) + 1; /* each 16 bits sample gives one nibble */
+ /* and we have 4 bytes per channel overhead */
+ avctx->block_align = BLKSIZE;
+ /* seems frame_size isn't taken into account... have to buffer the samples :-( */
+ break;
+ case CODEC_ID_ADPCM_MS:
+ avctx->frame_size = (BLKSIZE - 7 * avctx->channels) * 2 / avctx->channels + 2; /* each 16 bits sample gives one nibble */
+ /* and we have 7 bytes per channel overhead */
+ avctx->block_align = BLKSIZE;
+ break;
+ case CODEC_ID_ADPCM_YAMAHA:
+ avctx->frame_size = BLKSIZE * avctx->channels;
+ avctx->block_align = BLKSIZE;
+ break;
+ default:
+ return -1;
+ break;
+ }
+
+ avctx->coded_frame= avcodec_alloc_frame();
+ avctx->coded_frame->key_frame= 1;
+
+ return 0;
+}
+
+static int adpcm_encode_close(AVCodecContext *avctx)
+{
+ av_freep(&avctx->coded_frame);
+
+ return 0;
+}
+
+
+static inline unsigned char adpcm_ima_compress_sample(ADPCMChannelStatus *c, short sample)
+{
+ int delta = sample - c->prev_sample;
+ int nibble = FFMIN(7, abs(delta)*4/step_table[c->step_index]) + (delta<0)*8;
+ c->prev_sample = c->prev_sample + ((step_table[c->step_index] * yamaha_difflookup[nibble]) / 8);
+ CLAMP_TO_SHORT(c->prev_sample);
+ c->step_index = clip(c->step_index + index_table[nibble], 0, 88);
+ return nibble;
+}
+
+static inline unsigned char adpcm_ms_compress_sample(ADPCMChannelStatus *c, short sample)
+{
+ int predictor, nibble, bias;
+
+ predictor = (((c->sample1) * (c->coeff1)) + ((c->sample2) * (c->coeff2))) / 256;
+
+ nibble= sample - predictor;
+ if(nibble>=0) bias= c->idelta/2;
+ else bias=-c->idelta/2;
+
+ nibble= (nibble + bias) / c->idelta;
+ nibble= clip(nibble, -8, 7)&0x0F;
+
+ predictor += (signed)((nibble & 0x08)?(nibble - 0x10):(nibble)) * c->idelta;
+ CLAMP_TO_SHORT(predictor);
+
+ c->sample2 = c->sample1;
+ c->sample1 = predictor;
+
+ c->idelta = (AdaptationTable[(int)nibble] * c->idelta) >> 8;
+ if (c->idelta < 16) c->idelta = 16;
+
+ return nibble;
+}
+
+static inline unsigned char adpcm_yamaha_compress_sample(ADPCMChannelStatus *c, short 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->predictor + ((c->step * yamaha_difflookup[nibble]) / 8);
+ CLAMP_TO_SHORT(c->predictor);
+ c->step = (c->step * yamaha_indexscale[nibble]) >> 8;
+ c->step = clip(c->step, 127, 24567);
+
+ return nibble;
+}
+
+typedef struct TrellisPath {
+ int nibble;
+ int prev;
+} TrellisPath;
+
+typedef struct TrellisNode {
+ uint32_t ssd;
+ int path;
+ int sample1;
+ int sample2;
+ int step;
+} TrellisNode;
+
+static void adpcm_compress_trellis(AVCodecContext *avctx, const short *samples,
+ uint8_t *dst, ADPCMChannelStatus *c, int n)
+{
+#define FREEZE_INTERVAL 128
+ //FIXME 6% faster if frontier is a compile-time constant
+ const int frontier = 1 << avctx->trellis;
+ const int stride = avctx->channels;
+ const int version = avctx->codec->id;
+ const int max_paths = frontier*FREEZE_INTERVAL;
+ TrellisPath paths[max_paths], *p;
+ TrellisNode node_buf[2][frontier];
+ TrellisNode *nodep_buf[2][frontier];
+ TrellisNode **nodes = nodep_buf[0]; // nodes[] is always sorted by .ssd
+ TrellisNode **nodes_next = nodep_buf[1];
+ int pathn = 0, froze = -1, i, j, k;
+
+ assert(!(max_paths&(max_paths-1)));
+
+ memset(nodep_buf, 0, sizeof(nodep_buf));
+ nodes[0] = &node_buf[1][0];
+ 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 == CODEC_ID_ADPCM_IMA_WAV)
+ nodes[0]->sample1 = c->prev_sample;
+ if(version == CODEC_ID_ADPCM_MS)
+ nodes[0]->step = c->idelta;
+ if(version == 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[i&1];
+ TrellisNode **u;
+ int sample = samples[i*stride];
+ memset(nodes_next, 0, frontier*sizeof(TrellisNode*));
+ for(j=0; j<frontier && nodes[j]; j++) {
+ // higher j have higher ssd already, so they're unlikely to use a suboptimal next sample too
+ const int range = (j < frontier/2) ? 1 : 0;
+ const int step = nodes[j]->step;
+ int nidx;
+ if(version == CODEC_ID_ADPCM_MS) {
+ const int predictor = ((nodes[j]->sample1 * c->coeff1) + (nodes[j]->sample2 * c->coeff2)) / 256;
+ const int div = (sample - predictor) / step;
+ const int nmin = clip(div-range, -8, 6);
+ const int nmax = 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;\
+ CLAMP_TO_SHORT(dec_sample);\
+ d = sample - dec_sample;\
+ ssd = nodes[j]->ssd + d*d;\
+ if(nodes_next[frontier-1] && ssd >= nodes_next[frontier-1]->ssd)\
+ continue;\
+ /* 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. */\
+ for(k=0; k<frontier && nodes_next[k]; k++) {\
+ if(dec_sample == nodes_next[k]->sample1) {\
+ assert(ssd >= nodes_next[k]->ssd);\
+ goto next_##NAME;\
+ }\
+ }\
+ for(k=0; k<frontier; k++) {\
+ if(!nodes_next[k] || ssd < nodes_next[k]->ssd) {\
+ TrellisNode *u = nodes_next[frontier-1];\
+ if(!u) {\
+ assert(pathn < max_paths);\
+ u = t++;\
+ 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;\
+ memmove(&nodes_next[k+1], &nodes_next[k], (frontier-k-1)*sizeof(TrellisNode*));\
+ nodes_next[k] = u;\
+ break;\
+ }\
+ }\
+ next_##NAME:;
+ STORE_NODE(ms, FFMAX(16, (AdaptationTable[nibble] * step) >> 8));
+ }
+ } else if(version == CODEC_ID_ADPCM_IMA_WAV) {
+#define LOOP_NODES(NAME, STEP_TABLE, STEP_INDEX)\
+ const int predictor = nodes[j]->sample1;\
+ const int div = (sample - predictor) * 4 / STEP_TABLE;\
+ int nmin = clip(div-range, -7, 6);\
+ int nmax = 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 * yamaha_difflookup[nibble]) / 8;\
+ STORE_NODE(NAME, STEP_INDEX);\
+ }
+ LOOP_NODES(ima, step_table[step], clip(step + index_table[nibble], 0, 88));
+ } else { //CODEC_ID_ADPCM_YAMAHA
+ LOOP_NODES(yamaha, step, clip((step * yamaha_indexscale[nibble]) >> 8, 127, 24567));
+#undef LOOP_NODES
+#undef STORE_NODE
+ }
+ }
+
+ u = nodes;
+ nodes = nodes_next;
+ nodes_next = u;
+
+ // 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,
+ unsigned char *frame, int buf_size, void *data)
+{
+ int n, i, st;
+ short *samples;
+ unsigned char *dst;
+ ADPCMContext *c = avctx->priv_data;
+
+ dst = frame;
+ samples = (short *)data;
+ st= avctx->channels == 2;
+/* n = (BLKSIZE - 4 * avctx->channels) / (2 * 8 * avctx->channels); */
+
+ switch(avctx->codec->id) {
+ case CODEC_ID_ADPCM_IMA_QT: /* XXX: can't test until we get .mov writer */
+ break;
+ case CODEC_ID_ADPCM_IMA_WAV:
+ n = avctx->frame_size / 8;
+ c->status[0].prev_sample = (signed short)samples[0]; /* XXX */
+/* c->status[0].step_index = 0; *//* XXX: not sure how to init the state machine */
+ *dst++ = (c->status[0].prev_sample) & 0xFF; /* little endian */
+ *dst++ = (c->status[0].prev_sample >> 8) & 0xFF;
+ *dst++ = (unsigned char)c->status[0].step_index;
+ *dst++ = 0; /* unknown */
+ samples++;
+ if (avctx->channels == 2) {
+ c->status[1].prev_sample = (signed short)samples[1];
+/* c->status[1].step_index = 0; */
+ *dst++ = (c->status[1].prev_sample) & 0xFF;
+ *dst++ = (c->status[1].prev_sample >> 8) & 0xFF;
+ *dst++ = (unsigned char)c->status[1].step_index;
+ *dst++ = 0;
+ samples++;
+ }
+
+ /* stereo: 4 bytes (8 samples) for left, 4 bytes for right, 4 bytes left, ... */
+ if(avctx->trellis > 0) {
+ uint8_t buf[2][n*8];
+ adpcm_compress_trellis(avctx, samples, buf[0], &c->status[0], n*8);
+ if(avctx->channels == 2)
+ adpcm_compress_trellis(avctx, samples+1, buf[1], &c->status[1], n*8);
+ for(i=0; i<n; i++) {
+ *dst++ = buf[0][8*i+0] | (buf[0][8*i+1] << 4);
+ *dst++ = buf[0][8*i+2] | (buf[0][8*i+3] << 4);
+ *dst++ = buf[0][8*i+4] | (buf[0][8*i+5] << 4);
+ *dst++ = buf[0][8*i+6] | (buf[0][8*i+7] << 4);
+ if (avctx->channels == 2) {
+ *dst++ = buf[1][8*i+0] | (buf[1][8*i+1] << 4);
+ *dst++ = buf[1][8*i+2] | (buf[1][8*i+3] << 4);
+ *dst++ = buf[1][8*i+4] | (buf[1][8*i+5] << 4);
+ *dst++ = buf[1][8*i+6] | (buf[1][8*i+7] << 4);
+ }
+ }
+ } else
+ for (; n>0; n--) {
+ *dst = adpcm_ima_compress_sample(&c->status[0], samples[0]) & 0x0F;
+ *dst |= (adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels]) << 4) & 0xF0;
+ dst++;
+ *dst = adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 2]) & 0x0F;
+ *dst |= (adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 3]) << 4) & 0xF0;
+ dst++;
+ *dst = adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 4]) & 0x0F;
+ *dst |= (adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 5]) << 4) & 0xF0;
+ dst++;
+ *dst = adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 6]) & 0x0F;
+ *dst |= (adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 7]) << 4) & 0xF0;
+ dst++;
+ /* right channel */
+ if (avctx->channels == 2) {
+ *dst = adpcm_ima_compress_sample(&c->status[1], samples[1]);
+ *dst |= adpcm_ima_compress_sample(&c->status[1], samples[3]) << 4;
+ dst++;
+ *dst = adpcm_ima_compress_sample(&c->status[1], samples[5]);
+ *dst |= adpcm_ima_compress_sample(&c->status[1], samples[7]) << 4;
+ dst++;
+ *dst = adpcm_ima_compress_sample(&c->status[1], samples[9]);
+ *dst |= adpcm_ima_compress_sample(&c->status[1], samples[11]) << 4;
+ dst++;
+ *dst = adpcm_ima_compress_sample(&c->status[1], samples[13]);
+ *dst |= adpcm_ima_compress_sample(&c->status[1], samples[15]) << 4;
+ dst++;
+ }
+ samples += 8 * avctx->channels;
+ }
+ break;
+ case CODEC_ID_ADPCM_MS:
+ for(i=0; i<avctx->channels; i++){
+ int predictor=0;
+
+ *dst++ = predictor;
+ c->status[i].coeff1 = AdaptCoeff1[predictor];
+ c->status[i].coeff2 = AdaptCoeff2[predictor];
+ }
+ for(i=0; i<avctx->channels; i++){
+ if (c->status[i].idelta < 16)
+ c->status[i].idelta = 16;
+
+ *dst++ = c->status[i].idelta & 0xFF;
+ *dst++ = c->status[i].idelta >> 8;
+ }
+ for(i=0; i<avctx->channels; i++){
+ c->status[i].sample1= *samples++;
+
+ *dst++ = c->status[i].sample1 & 0xFF;
+ *dst++ = c->status[i].sample1 >> 8;
+ }
+ for(i=0; i<avctx->channels; i++){
+ c->status[i].sample2= *samples++;
+
+ *dst++ = c->status[i].sample2 & 0xFF;
+ *dst++ = c->status[i].sample2 >> 8;
+ }
+
+ if(avctx->trellis > 0) {
+ int n = avctx->block_align - 7*avctx->channels;
+ uint8_t buf[2][n];
+ if(avctx->channels == 1) {
+ n *= 2;
+ adpcm_compress_trellis(avctx, samples, buf[0], &c->status[0], n);
+ for(i=0; i<n; i+=2)
+ *dst++ = (buf[0][i] << 4) | buf[0][i+1];
+ } else {
+ adpcm_compress_trellis(avctx, samples, buf[0], &c->status[0], n);
+ adpcm_compress_trellis(avctx, samples+1, buf[1], &c->status[1], n);
+ for(i=0; i<n; i++)
+ *dst++ = (buf[0][i] << 4) | buf[1][i];
+ }
+ } 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 CODEC_ID_ADPCM_YAMAHA:
+ n = avctx->frame_size / 2;
+ if(avctx->trellis > 0) {
+ uint8_t buf[2][n*2];
+ n *= 2;
+ if(avctx->channels == 1) {
+ adpcm_compress_trellis(avctx, samples, buf[0], &c->status[0], n);
+ for(i=0; i<n; i+=2)
+ *dst++ = buf[0][i] | (buf[0][i+1] << 4);
+ } else {
+ adpcm_compress_trellis(avctx, samples, buf[0], &c->status[0], n);
+ adpcm_compress_trellis(avctx, samples+1, buf[1], &c->status[1], n);
+ for(i=0; i<n; i++)
+ *dst++ = buf[0][i] | (buf[1][i] << 4);
+ }
+ } else
+ for (; n>0; n--) {
+ for(i = 0; i < avctx->channels; i++) {
+ int nibble;
+ nibble = adpcm_yamaha_compress_sample(&c->status[i], samples[i]);
+ nibble |= adpcm_yamaha_compress_sample(&c->status[i], samples[i+avctx->channels]) << 4;
+ *dst++ = nibble;
+ }
+ samples += 2 * avctx->channels;
+ }
+ break;
+ default:
+ return -1;
+ }
+ return dst - frame;
+}
+#endif //CONFIG_ENCODERS
+
+static int adpcm_decode_init(AVCodecContext * avctx)
+{
+ ADPCMContext *c = avctx->priv_data;
+
+ c->channel = 0;
+ c->status[0].predictor = c->status[1].predictor = 0;
+ c->status[0].step_index = c->status[1].step_index = 0;
+ c->status[0].step = c->status[1].step = 0;
+
+ switch(avctx->codec->id) {
+ case CODEC_ID_ADPCM_CT:
+ c->status[0].step = c->status[1].step = 511;
+ break;
+ default:
+ break;
+ }
+ 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 = step_table[c->step_index];
+ step_index = c->step_index + index_table[(unsigned)nibble];
+ if (step_index < 0) step_index = 0;
+ else if (step_index > 88) step_index = 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;
+
+ CLAMP_TO_SHORT(predictor);
+ c->predictor = predictor;
+ c->step_index = step_index;
+
+ return (short)predictor;
+}
+
+static inline short adpcm_ms_expand_nibble(ADPCMChannelStatus *c, char nibble)
+{
+ int predictor;
+
+ predictor = (((c->sample1) * (c->coeff1)) + ((c->sample2) * (c->coeff2))) / 256;
+ predictor += (signed)((nibble & 0x08)?(nibble - 0x10):(nibble)) * c->idelta;
+ CLAMP_TO_SHORT(predictor);
+
+ c->sample2 = c->sample1;
+ c->sample1 = predictor;
+ c->idelta = (AdaptationTable[(int)nibble] * c->idelta) >> 8;
+ if (c->idelta < 16) c->idelta = 16;
+
+ return (short)predictor;
+}
+
+static inline short adpcm_ct_expand_nibble(ADPCMChannelStatus *c, char nibble)
+{
+ int predictor;
+ 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 = c->predictor;
+ /* predictor update is not so trivial: predictor is multiplied on 254/256 before updating */
+ if(sign)
+ predictor = ((predictor * 254) >> 8) - diff;
+ else
+ predictor = ((predictor * 254) >> 8) + diff;
+ /* calculate new step and clamp it to range 511..32767 */
+ new_step = (ct_adpcm_table[nibble & 7] * c->step) >> 8;
+ c->step = new_step;
+ if(c->step < 511)
+ c->step = 511;
+ if(c->step > 32767)
+ c->step = 32767;
+
+ CLAMP_TO_SHORT(predictor);
+ c->predictor = predictor;
+ return (short)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);
+
+ if (sign)
+ c->predictor -= diff;
+ else
+ c->predictor += diff;
+
+ /* clamp result */
+ if (c->predictor > 16256)
+ c->predictor = 16256;
+ else if (c->predictor < -16384)
+ c->predictor = -16384;
+
+ /* 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 * yamaha_difflookup[nibble]) / 8;
+ CLAMP_TO_SHORT(c->predictor);
+ c->step = (c->step * yamaha_indexscale[nibble]) >> 8;
+ c->step = clip(c->step, 127, 24567);
+ return c->predictor;
+}
+
+static void xa_decode(short *out, const unsigned char *in,
+ ADPCMChannelStatus *left, ADPCMChannelStatus *right, int inc)
+{
+ int i, j;
+ int shift,filter,f0,f1;
+ int s_1,s_2;
+ int d,s,t;
+
+ for(i=0;i<4;i++) {
+
+ shift = 12 - (in[4+i*2] & 15);
+ filter = in[4+i*2] >> 4;
+ 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 = (signed char)(d<<4)>>4;
+ s = ( t<<shift ) + ((s_1*f0 + s_2*f1+32)>>6);
+ CLAMP_TO_SHORT(s);
+ *out = s;
+ out += inc;
+ s_2 = s_1;
+ s_1 = s;
+ }
+
+ if (inc==2) { /* stereo */
+ left->sample1 = s_1;
+ left->sample2 = s_2;
+ s_1 = right->sample1;
+ s_2 = right->sample2;
+ out = out + 1 - 28*2;
+ }
+
+ shift = 12 - (in[5+i*2] & 15);
+ filter = in[5+i*2] >> 4;
+
+ 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 = (signed char)d >> 4;
+ s = ( t<<shift ) + ((s_1*f0 + s_2*f1+32)>>6);
+ CLAMP_TO_SHORT(s);
+ *out = s;
+ out += inc;
+ s_2 = s_1;
+ s_1 = s;
+ }
+
+ if (inc==2) { /* stereo */
+ right->sample1 = s_1;
+ right->sample2 = s_2;
+ out -= 1;
+ } else {
+ left->sample1 = s_1;
+ left->sample2 = s_2;
+ }
+ }
+}
+
+
+/* DK3 ADPCM support macro */
+#define DK3_GET_NEXT_NIBBLE() \
+ if (decode_top_nibble_next) \
+ { \
+ nibble = (last_byte >> 4) & 0x0F; \
+ decode_top_nibble_next = 0; \
+ } \
+ else \
+ { \
+ last_byte = *src++; \
+ if (src >= buf + buf_size) break; \
+ nibble = last_byte & 0x0F; \
+ decode_top_nibble_next = 1; \
+ }
+
+static int adpcm_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ ADPCMContext *c = avctx->priv_data;
+ ADPCMChannelStatus *cs;
+ int n, m, channel, i;
+ int block_predictor[2];
+ short *samples;
+ uint8_t *src;
+ int st; /* stereo */
+
+ /* DK3 ADPCM accounting variables */
+ unsigned char last_byte = 0;
+ unsigned char nibble;
+ int decode_top_nibble_next = 0;
+ int diff_channel;
+
+ /* EA ADPCM state variables */
+ uint32_t samples_in_chunk;
+ int32_t previous_left_sample, previous_right_sample;
+ int32_t current_left_sample, current_right_sample;
+ int32_t next_left_sample, next_right_sample;
+ int32_t coeff1l, coeff2l, coeff1r, coeff2r;
+ uint8_t shift_left, shift_right;
+ int count1, count2;
+
+ if (!buf_size)
+ return 0;
+
+ samples = data;
+ src = buf;
+
+ st = avctx->channels == 2 ? 1 : 0;
+
+ switch(avctx->codec->id) {
+ case CODEC_ID_ADPCM_IMA_QT:
+ n = (buf_size - 2);/* >> 2*avctx->channels;*/
+ channel = c->channel;
+ cs = &(c->status[channel]);
+ /* (pppppp) (piiiiiii) */
+
+ /* Bits 15-7 are the _top_ 9 bits of the 16-bit initial predictor value */
+ cs->predictor = (*src++) << 8;
+ cs->predictor |= (*src & 0x80);
+ cs->predictor &= 0xFF80;
+
+ /* sign extension */
+ if(cs->predictor & 0x8000)
+ cs->predictor -= 0x10000;
+
+ CLAMP_TO_SHORT(cs->predictor);
+
+ cs->step_index = (*src++) & 0x7F;
+
+ if (cs->step_index > 88){
+ av_log(avctx, AV_LOG_ERROR, "ERROR: step_index = %i\n", cs->step_index);
+ cs->step_index = 88;
+ }
+
+ cs->step = step_table[cs->step_index];
+
+ if (st && channel)
+ samples++;
+
+ for(m=32; n>0 && m>0; n--, m--) { /* in QuickTime, IMA is encoded by chuncks of 34 bytes (=64 samples) */
+ *samples = adpcm_ima_expand_nibble(cs, src[0] & 0x0F, 3);
+ samples += avctx->channels;
+ *samples = adpcm_ima_expand_nibble(cs, (src[0] >> 4) & 0x0F, 3);
+ samples += avctx->channels;
+ src ++;
+ }
+
+ if(st) { /* handle stereo interlacing */
+ c->channel = (channel + 1) % 2; /* we get one packet for left, then one for right data */
+ if(channel == 1) { /* wait for the other packet before outputing anything */
+ return src - buf;
+ }
+ }
+ break;
+ case CODEC_ID_ADPCM_IMA_WAV:
+ if (avctx->block_align != 0 && buf_size > avctx->block_align)
+ buf_size = avctx->block_align;
+
+// samples_per_block= (block_align-4*chanels)*8 / (bits_per_sample * chanels) + 1;
+
+ for(i=0; i<avctx->channels; i++){
+ cs = &(c->status[i]);
+ cs->predictor = (int16_t)(src[0] + (src[1]<<8));
+ src+=2;
+
+ // XXX: is this correct ??: *samples++ = cs->predictor;
+
+ cs->step_index = *src++;
+ if (cs->step_index > 88){
+ av_log(avctx, AV_LOG_ERROR, "ERROR: step_index = %i\n", cs->step_index);
+ cs->step_index = 88;
+ }
+ if (*src++) av_log(avctx, AV_LOG_ERROR, "unused byte should be null but is %d!!\n", src[-1]); /* unused */
+ }
+
+ while(src < buf + buf_size){
+ for(m=0; m<4; m++){
+ for(i=0; i<=st; i++)
+ *samples++ = adpcm_ima_expand_nibble(&c->status[i], src[4*i] & 0x0F, 3);
+ for(i=0; i<=st; i++)
+ *samples++ = adpcm_ima_expand_nibble(&c->status[i], src[4*i] >> 4 , 3);
+ src++;
+ }
+ src += 4*st;
+ }
+ break;
+ case CODEC_ID_ADPCM_4XM:
+ cs = &(c->status[0]);
+ c->status[0].predictor= (int16_t)(src[0] + (src[1]<<8)); src+=2;
+ if(st){
+ c->status[1].predictor= (int16_t)(src[0] + (src[1]<<8)); src+=2;
+ }
+ c->status[0].step_index= (int16_t)(src[0] + (src[1]<<8)); src+=2;
+ if(st){
+ c->status[1].step_index= (int16_t)(src[0] + (src[1]<<8)); src+=2;
+ }
+ if (cs->step_index < 0) cs->step_index = 0;
+ if (cs->step_index > 88) cs->step_index = 88;
+
+ m= (buf_size - (src - buf))>>st;
+ for(i=0; i<m; i++) {
+ *samples++ = adpcm_ima_expand_nibble(&c->status[0], src[i] & 0x0F, 4);
+ if (st)
+ *samples++ = adpcm_ima_expand_nibble(&c->status[1], src[i+m] & 0x0F, 4);
+ *samples++ = adpcm_ima_expand_nibble(&c->status[0], src[i] >> 4, 4);
+ if (st)
+ *samples++ = adpcm_ima_expand_nibble(&c->status[1], src[i+m] >> 4, 4);
+ }
+
+ src += m<<st;
+
+ break;
+ case CODEC_ID_ADPCM_MS:
+ if (avctx->block_align != 0 && buf_size > avctx->block_align)
+ buf_size = avctx->block_align;
+ n = buf_size - 7 * avctx->channels;
+ if (n < 0)
+ return -1;
+ block_predictor[0] = clip(*src++, 0, 7);
+ block_predictor[1] = 0;
+ if (st)
+ block_predictor[1] = clip(*src++, 0, 7);
+ c->status[0].idelta = (int16_t)((*src & 0xFF) | ((src[1] << 8) & 0xFF00));
+ src+=2;
+ if (st){
+ c->status[1].idelta = (int16_t)((*src & 0xFF) | ((src[1] << 8) & 0xFF00));
+ src+=2;
+ }
+ c->status[0].coeff1 = AdaptCoeff1[block_predictor[0]];
+ c->status[0].coeff2 = AdaptCoeff2[block_predictor[0]];
+ c->status[1].coeff1 = AdaptCoeff1[block_predictor[1]];
+ c->status[1].coeff2 = AdaptCoeff2[block_predictor[1]];
+
+ c->status[0].sample1 = ((*src & 0xFF) | ((src[1] << 8) & 0xFF00));
+ src+=2;
+ if (st) c->status[1].sample1 = ((*src & 0xFF) | ((src[1] << 8) & 0xFF00));
+ if (st) src+=2;
+ c->status[0].sample2 = ((*src & 0xFF) | ((src[1] << 8) & 0xFF00));
+ src+=2;
+ if (st) c->status[1].sample2 = ((*src & 0xFF) | ((src[1] << 8) & 0xFF00));
+ if (st) src+=2;
+
+ *samples++ = c->status[0].sample1;
+ if (st) *samples++ = c->status[1].sample1;
+ *samples++ = c->status[0].sample2;
+ if (st) *samples++ = c->status[1].sample2;
+ for(;n>0;n--) {
+ *samples++ = adpcm_ms_expand_nibble(&c->status[0], (src[0] >> 4) & 0x0F);
+ *samples++ = adpcm_ms_expand_nibble(&c->status[st], src[0] & 0x0F);
+ src ++;
+ }
+ break;
+ case CODEC_ID_ADPCM_IMA_DK4:
+ if (avctx->block_align != 0 && buf_size > avctx->block_align)
+ buf_size = avctx->block_align;
+
+ c->status[0].predictor = (int16_t)(src[0] | (src[1] << 8));
+ c->status[0].step_index = src[2];
+ src += 4;
+ *samples++ = c->status[0].predictor;
+ if (st) {
+ c->status[1].predictor = (int16_t)(src[0] | (src[1] << 8));
+ c->status[1].step_index = src[2];
+ src += 4;
+ *samples++ = c->status[1].predictor;
+ }
+ while (src < buf + buf_size) {
+
+ /* take care of the top nibble (always left or mono channel) */
+ *samples++ = adpcm_ima_expand_nibble(&c->status[0],
+ (src[0] >> 4) & 0x0F, 3);
+
+ /* take care of the bottom nibble, which is right sample for
+ * stereo, or another mono sample */
+ if (st)
+ *samples++ = adpcm_ima_expand_nibble(&c->status[1],
+ src[0] & 0x0F, 3);
+ else
+ *samples++ = adpcm_ima_expand_nibble(&c->status[0],
+ src[0] & 0x0F, 3);
+
+ src++;
+ }
+ break;
+ case CODEC_ID_ADPCM_IMA_DK3:
+ if (avctx->block_align != 0 && buf_size > avctx->block_align)
+ buf_size = avctx->block_align;
+
+ c->status[0].predictor = (int16_t)(src[10] | (src[11] << 8));
+ c->status[1].predictor = (int16_t)(src[12] | (src[13] << 8));
+ c->status[0].step_index = src[14];
+ c->status[1].step_index = src[15];
+ /* sign extend the predictors */
+ src += 16;
+ diff_channel = c->status[1].predictor;
+
+ /* the DK3_GET_NEXT_NIBBLE macro issues the break statement when
+ * the buffer is consumed */
+ while (1) {
+
+ /* 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 CODEC_ID_ADPCM_IMA_WS:
+ /* no per-block initialization; just start decoding the data */
+ while (src < buf + buf_size) {
+
+ if (st) {
+ *samples++ = adpcm_ima_expand_nibble(&c->status[0],
+ (src[0] >> 4) & 0x0F, 3);
+ *samples++ = adpcm_ima_expand_nibble(&c->status[1],
+ src[0] & 0x0F, 3);
+ } else {
+ *samples++ = adpcm_ima_expand_nibble(&c->status[0],
+ (src[0] >> 4) & 0x0F, 3);
+ *samples++ = adpcm_ima_expand_nibble(&c->status[0],
+ src[0] & 0x0F, 3);
+ }
+
+ src++;
+ }
+ break;
+ case CODEC_ID_ADPCM_XA:
+ c->status[0].sample1 = c->status[0].sample2 =
+ c->status[1].sample1 = c->status[1].sample2 = 0;
+ while (buf_size >= 128) {
+ xa_decode(samples, src, &c->status[0], &c->status[1],
+ avctx->channels);
+ src += 128;
+ samples += 28 * 8;
+ buf_size -= 128;
+ }
+ break;
+ case CODEC_ID_ADPCM_EA:
+ samples_in_chunk = LE_32(src);
+ if (samples_in_chunk >= ((buf_size - 12) * 2)) {
+ src += buf_size;
+ break;
+ }
+ src += 4;
+ current_left_sample = (int16_t)LE_16(src);
+ src += 2;
+ previous_left_sample = (int16_t)LE_16(src);
+ src += 2;
+ current_right_sample = (int16_t)LE_16(src);
+ src += 2;
+ previous_right_sample = (int16_t)LE_16(src);
+ src += 2;
+
+ for (count1 = 0; count1 < samples_in_chunk/28;count1++) {
+ coeff1l = ea_adpcm_table[(*src >> 4) & 0x0F];
+ coeff2l = ea_adpcm_table[((*src >> 4) & 0x0F) + 4];
+ coeff1r = ea_adpcm_table[*src & 0x0F];
+ coeff2r = ea_adpcm_table[(*src & 0x0F) + 4];
+ src++;
+
+ shift_left = ((*src >> 4) & 0x0F) + 8;
+ shift_right = (*src & 0x0F) + 8;
+ src++;
+
+ for (count2 = 0; count2 < 28; count2++) {
+ next_left_sample = (((*src & 0xF0) << 24) >> shift_left);
+ next_right_sample = (((*src & 0x0F) << 28) >> shift_right);
+ src++;
+
+ 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;
+ CLAMP_TO_SHORT(next_left_sample);
+ CLAMP_TO_SHORT(next_right_sample);
+
+ previous_left_sample = current_left_sample;
+ current_left_sample = next_left_sample;
+ previous_right_sample = current_right_sample;
+ current_right_sample = next_right_sample;
+ *samples++ = (unsigned short)current_left_sample;
+ *samples++ = (unsigned short)current_right_sample;
+ }
+ }
+ break;
+ case CODEC_ID_ADPCM_IMA_SMJPEG:
+ c->status[0].predictor = *src;
+ src += 2;
+ c->status[0].step_index = *src++;
+ src++; /* skip another byte before getting to the meat */
+ while (src < buf + buf_size) {
+ *samples++ = adpcm_ima_expand_nibble(&c->status[0],
+ *src & 0x0F, 3);
+ *samples++ = adpcm_ima_expand_nibble(&c->status[0],
+ (*src >> 4) & 0x0F, 3);
+ src++;
+ }
+ break;
+ case CODEC_ID_ADPCM_CT:
+ while (src < buf + buf_size) {
+ if (st) {
+ *samples++ = adpcm_ct_expand_nibble(&c->status[0],
+ (src[0] >> 4) & 0x0F);
+ *samples++ = adpcm_ct_expand_nibble(&c->status[1],
+ src[0] & 0x0F);
+ } else {
+ *samples++ = adpcm_ct_expand_nibble(&c->status[0],
+ (src[0] >> 4) & 0x0F);
+ *samples++ = adpcm_ct_expand_nibble(&c->status[0],
+ src[0] & 0x0F);
+ }
+ src++;
+ }
+ break;
+ case CODEC_ID_ADPCM_SBPRO_4:
+ case CODEC_ID_ADPCM_SBPRO_3:
+ case CODEC_ID_ADPCM_SBPRO_2:
+ if (!c->status[0].step_index) {
+ /* the first byte is a raw sample */
+ *samples++ = 128 * (*src++ - 0x80);
+ if (st)
+ *samples++ = 128 * (*src++ - 0x80);
+ c->status[0].step_index = 1;
+ }
+ if (avctx->codec->id == CODEC_ID_ADPCM_SBPRO_4) {
+ while (src < buf + buf_size) {
+ *samples++ = adpcm_sbpro_expand_nibble(&c->status[0],
+ (src[0] >> 4) & 0x0F, 4, 0);
+ *samples++ = adpcm_sbpro_expand_nibble(&c->status[st],
+ src[0] & 0x0F, 4, 0);
+ src++;
+ }
+ } else if (avctx->codec->id == CODEC_ID_ADPCM_SBPRO_3) {
+ while (src < buf + buf_size) {
+ *samples++ = adpcm_sbpro_expand_nibble(&c->status[0],
+ (src[0] >> 5) & 0x07, 3, 0);
+ *samples++ = adpcm_sbpro_expand_nibble(&c->status[0],
+ (src[0] >> 2) & 0x07, 3, 0);
+ *samples++ = adpcm_sbpro_expand_nibble(&c->status[0],
+ src[0] & 0x03, 2, 0);
+ src++;
+ }
+ } else {
+ while (src < buf + buf_size) {
+ *samples++ = adpcm_sbpro_expand_nibble(&c->status[0],
+ (src[0] >> 6) & 0x03, 2, 2);
+ *samples++ = adpcm_sbpro_expand_nibble(&c->status[st],
+ (src[0] >> 4) & 0x03, 2, 2);
+ *samples++ = adpcm_sbpro_expand_nibble(&c->status[0],
+ (src[0] >> 2) & 0x03, 2, 2);
+ *samples++ = adpcm_sbpro_expand_nibble(&c->status[st],
+ src[0] & 0x03, 2, 2);
+ src++;
+ }
+ }
+ break;
+ case CODEC_ID_ADPCM_SWF:
+ {
+ GetBitContext gb;
+ const int *table;
+ int k0, signmask;
+ int size = buf_size*8;
+
+ init_get_bits(&gb, buf, size);
+
+ // first frame, read bits & inital values
+ if (!c->nb_bits)
+ {
+ c->nb_bits = get_bits(&gb, 2)+2;
+// av_log(NULL,AV_LOG_INFO,"nb_bits: %d\n", c->nb_bits);
+ }
+
+ table = swf_index_tables[c->nb_bits-2];
+ k0 = 1 << (c->nb_bits-2);
+ signmask = 1 << (c->nb_bits-1);
+
+ while (get_bits_count(&gb) <= size)
+ {
+ int i;
+
+ c->nb_samples++;
+ // wrap around at every 4096 samples...
+ if ((c->nb_samples & 0xfff) == 1)
+ {
+ for (i = 0; i <= st; i++)
+ {
+ *samples++ = c->status[i].predictor = get_sbits(&gb, 16);
+ c->status[i].step_index = get_bits(&gb, 6);
+ }
+ }
+
+ // similar to IMA adpcm
+ for (i = 0; i <= st; i++)
+ {
+ int delta = get_bits(&gb, c->nb_bits);
+ int step = 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 = clip(c->status[i].step_index, 0, 88);
+ c->status[i].predictor = clip(c->status[i].predictor, -32768, 32767);
+
+ *samples++ = c->status[i].predictor;
+ }
+ }
+
+// src += get_bits_count(&gb)*8;
+ src += size;
+
+ break;
+ }
+ case CODEC_ID_ADPCM_YAMAHA:
+ while (src < buf + buf_size) {
+ if (st) {
+ *samples++ = adpcm_yamaha_expand_nibble(&c->status[0],
+ src[0] & 0x0F);
+ *samples++ = adpcm_yamaha_expand_nibble(&c->status[1],
+ (src[0] >> 4) & 0x0F);
+ } else {
+ *samples++ = adpcm_yamaha_expand_nibble(&c->status[0],
+ src[0] & 0x0F);
+ *samples++ = adpcm_yamaha_expand_nibble(&c->status[0],
+ (src[0] >> 4) & 0x0F);
+ }
+ src++;
+ }
+ break;
+ default:
+ return -1;
+ }
+ *data_size = (uint8_t *)samples - (uint8_t *)data;
+ return src - buf;
+}
+
+
+
+#ifdef CONFIG_ENCODERS
+#define ADPCM_ENCODER(id,name) \
+AVCodec name ## _encoder = { \
+ #name, \
+ CODEC_TYPE_AUDIO, \
+ id, \
+ sizeof(ADPCMContext), \
+ adpcm_encode_init, \
+ adpcm_encode_frame, \
+ adpcm_encode_close, \
+ NULL, \
+};
+#else
+#define ADPCM_ENCODER(id,name)
+#endif
+
+#ifdef CONFIG_DECODERS
+#define ADPCM_DECODER(id,name) \
+AVCodec name ## _decoder = { \
+ #name, \
+ CODEC_TYPE_AUDIO, \
+ id, \
+ sizeof(ADPCMContext), \
+ adpcm_decode_init, \
+ NULL, \
+ NULL, \
+ adpcm_decode_frame, \
+};
+#else
+#define ADPCM_DECODER(id,name)
+#endif
+
+#define ADPCM_CODEC(id, name) \
+ADPCM_ENCODER(id,name) ADPCM_DECODER(id,name)
+
+ADPCM_CODEC(CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt);
+ADPCM_CODEC(CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav);
+ADPCM_CODEC(CODEC_ID_ADPCM_IMA_DK3, adpcm_ima_dk3);
+ADPCM_CODEC(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4);
+ADPCM_CODEC(CODEC_ID_ADPCM_IMA_WS, adpcm_ima_ws);
+ADPCM_CODEC(CODEC_ID_ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg);
+ADPCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms);
+ADPCM_CODEC(CODEC_ID_ADPCM_4XM, adpcm_4xm);
+ADPCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa);
+ADPCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea);
+ADPCM_CODEC(CODEC_ID_ADPCM_CT, adpcm_ct);
+ADPCM_CODEC(CODEC_ID_ADPCM_SWF, adpcm_swf);
+ADPCM_CODEC(CODEC_ID_ADPCM_YAMAHA, adpcm_yamaha);
+ADPCM_CODEC(CODEC_ID_ADPCM_SBPRO_4, adpcm_sbpro_4);
+ADPCM_CODEC(CODEC_ID_ADPCM_SBPRO_3, adpcm_sbpro_3);
+ADPCM_CODEC(CODEC_ID_ADPCM_SBPRO_2, adpcm_sbpro_2);
+
+#undef ADPCM_CODEC
diff --git a/contrib/ffmpeg/libavcodec/adx.c b/contrib/ffmpeg/libavcodec/adx.c
new file mode 100644
index 000000000..b449c9124
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/adx.c
@@ -0,0 +1,412 @@
+/*
+ * 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"
+
+/**
+ * @file adx.c
+ * 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/
+ */
+
+typedef struct {
+ int s1,s2;
+} PREV;
+
+typedef struct {
+ PREV prev[2];
+ int header_parsed;
+ unsigned char dec_temp[18*2];
+ unsigned short enc_temp[32*2];
+ int in_temp;
+} ADXContext;
+
+//#define BASEVOL 0x11e0
+#define BASEVOL 0x4000
+#define SCALE1 0x7298
+#define SCALE2 0x3350
+
+#define CLIP(s) if (s>32767) s=32767; else if (s<-32768) s=-32768
+
+/* 18 bytes <-> 32 samples */
+
+#ifdef CONFIG_ENCODERS
+static void adx_encode(unsigned char *adx,const short *wav,PREV *prev)
+{
+ int scale;
+ int i;
+ int s0,s1,s2,d;
+ int max=0;
+ int min=0;
+ int data[32];
+
+ s1 = prev->s1;
+ s2 = prev->s2;
+ for(i=0;i<32;i++) {
+ s0 = wav[i];
+ d = ((s0<<14) - SCALE1*s1 + SCALE2*s2)/BASEVOL;
+ data[i]=d;
+ if (max<d) max=d;
+ if (min>d) min=d;
+ s2 = s1;
+ s1 = s0;
+ }
+ prev->s1 = s1;
+ prev->s2 = s2;
+
+ /* -8..+7 */
+
+ if (max==0 && min==0) {
+ memset(adx,0,18);
+ return;
+ }
+
+ if (max/7>-min/8) scale = max/7;
+ else scale = -min/8;
+
+ if (scale==0) scale=1;
+
+ adx[0] = scale>>8;
+ adx[1] = scale;
+
+ for(i=0;i<16;i++) {
+ adx[i+2] = ((data[i*2]/scale)<<4) | ((data[i*2+1]/scale)&0xf);
+ }
+}
+#endif //CONFIG_ENCODERS
+
+static void adx_decode(short *out,const unsigned char *in,PREV *prev)
+{
+ int scale = ((in[0]<<8)|(in[1]));
+ int i;
+ int s0,s1,s2,d;
+
+// printf("%x ",scale);
+
+ in+=2;
+ s1 = prev->s1;
+ s2 = prev->s2;
+ for(i=0;i<16;i++) {
+ d = in[i];
+ // d>>=4; if (d&8) d-=16;
+ d = ((signed char)d >> 4);
+ s0 = (BASEVOL*d*scale + SCALE1*s1 - SCALE2*s2)>>14;
+ CLIP(s0);
+ *out++=s0;
+ s2 = s1;
+ s1 = s0;
+
+ d = in[i];
+ //d&=15; if (d&8) d-=16;
+ d = ((signed char)(d<<4) >> 4);
+ s0 = (BASEVOL*d*scale + SCALE1*s1 - SCALE2*s2)>>14;
+ CLIP(s0);
+ *out++=s0;
+ s2 = s1;
+ s1 = s0;
+ }
+ prev->s1 = s1;
+ prev->s2 = s2;
+
+}
+
+static void adx_decode_stereo(short *out,const unsigned char *in,PREV *prev)
+{
+ short tmp[32*2];
+ int i;
+
+ adx_decode(tmp ,in ,prev);
+ adx_decode(tmp+32,in+18,prev+1);
+ for(i=0;i<32;i++) {
+ out[i*2] = tmp[i];
+ out[i*2+1] = tmp[i+32];
+ }
+}
+
+#ifdef CONFIG_ENCODERS
+
+static void write_long(unsigned char *p,uint32_t v)
+{
+ p[0] = v>>24;
+ p[1] = v>>16;
+ p[2] = v>>8;
+ p[3] = v;
+}
+
+static int adx_encode_header(AVCodecContext *avctx,unsigned char *buf,size_t bufsize)
+{
+#if 0
+ struct {
+ uint32_t offset; /* 0x80000000 + sample start - 4 */
+ unsigned char unknown1[3]; /* 03 12 04 */
+ unsigned char channel; /* 1 or 2 */
+ uint32_t freq;
+ uint32_t size;
+ uint32_t unknown2; /* 01 f4 03 00 */
+ uint32_t unknown3; /* 00 00 00 00 */
+ uint32_t unknown4; /* 00 00 00 00 */
+
+ /* if loop
+ unknown3 00 15 00 01
+ unknown4 00 00 00 01
+ long loop_start_sample;
+ long loop_start_byte;
+ long loop_end_sample;
+ long loop_end_byte;
+ long
+ */
+ } adxhdr; /* big endian */
+ /* offset-6 "(c)CRI" */
+#endif
+ write_long(buf+0x00,0x80000000|0x20);
+ write_long(buf+0x04,0x03120400|avctx->channels);
+ write_long(buf+0x08,avctx->sample_rate);
+ write_long(buf+0x0c,0); /* FIXME: set after */
+ write_long(buf+0x10,0x01040300);
+ write_long(buf+0x14,0x00000000);
+ write_long(buf+0x18,0x00000000);
+ memcpy(buf+0x1c,"\0\0(c)CRI",8);
+ return 0x20+4;
+}
+
+static int adx_decode_init(AVCodecContext *avctx);
+static int adx_encode_init(AVCodecContext *avctx)
+{
+ if (avctx->channels > 2)
+ return -1; /* only stereo or mono =) */
+ avctx->frame_size = 32;
+
+ avctx->coded_frame= avcodec_alloc_frame();
+ avctx->coded_frame->key_frame= 1;
+
+// avctx->bit_rate = avctx->sample_rate*avctx->channels*18*8/32;
+
+ av_log(avctx, AV_LOG_DEBUG, "adx encode init\n");
+ adx_decode_init(avctx);
+
+ return 0;
+}
+
+static int adx_encode_close(AVCodecContext *avctx)
+{
+ av_freep(&avctx->coded_frame);
+
+ return 0;
+}
+
+static int adx_encode_frame(AVCodecContext *avctx,
+ uint8_t *frame, int buf_size, void *data)
+{
+ ADXContext *c = avctx->priv_data;
+ const short *samples = data;
+ unsigned char *dst = frame;
+ int rest = avctx->frame_size;
+
+/*
+ input data size =
+ ffmpeg.c: do_audio_out()
+ frame_bytes = enc->frame_size * 2 * enc->channels;
+*/
+
+// printf("sz=%d ",buf_size); fflush(stdout);
+ if (!c->header_parsed) {
+ int hdrsize = adx_encode_header(avctx,dst,buf_size);
+ dst+=hdrsize;
+ c->header_parsed = 1;
+ }
+
+ if (avctx->channels==1) {
+ while(rest>=32) {
+ adx_encode(dst,samples,c->prev);
+ dst+=18;
+ samples+=32;
+ rest-=32;
+ }
+ } else {
+ while(rest>=32*2) {
+ short tmpbuf[32*2];
+ int i;
+
+ for(i=0;i<32;i++) {
+ tmpbuf[i] = samples[i*2];
+ tmpbuf[i+32] = samples[i*2+1];
+ }
+
+ adx_encode(dst,tmpbuf,c->prev);
+ adx_encode(dst+18,tmpbuf+32,c->prev+1);
+ dst+=18*2;
+ samples+=32*2;
+ rest-=32*2;
+ }
+ }
+ return dst-frame;
+}
+
+#endif //CONFIG_ENCODERS
+
+static uint32_t read_long(const unsigned char *p)
+{
+ return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
+}
+
+static int is_adx(const unsigned char *buf,size_t bufsize)
+{
+ int offset;
+
+ if (buf[0]!=0x80) return 0;
+ offset = (read_long(buf)^0x80000000)+4;
+ if (bufsize<offset || memcmp(buf+offset-6,"(c)CRI",6)) return 0;
+ return offset;
+}
+
+/* return data offset or 6 */
+static int adx_decode_header(AVCodecContext *avctx,const unsigned char *buf,size_t bufsize)
+{
+ int offset;
+ int channels,freq,size;
+
+ offset = is_adx(buf,bufsize);
+ if (offset==0) return 0;
+
+ channels = buf[7];
+ freq = read_long(buf+8);
+ size = read_long(buf+12);
+
+// printf("freq=%d ch=%d\n",freq,channels);
+
+ avctx->sample_rate = freq;
+ avctx->channels = channels;
+ avctx->bit_rate = freq*channels*18*8/32;
+// avctx->frame_size = 18*channels;
+
+ return offset;
+}
+
+static int adx_decode_init(AVCodecContext * avctx)
+{
+ ADXContext *c = avctx->priv_data;
+
+// printf("adx_decode_init\n"); fflush(stdout);
+ c->prev[0].s1 = 0;
+ c->prev[0].s2 = 0;
+ c->prev[1].s1 = 0;
+ c->prev[1].s2 = 0;
+ c->header_parsed = 0;
+ c->in_temp = 0;
+ return 0;
+}
+
+#if 0
+static void dump(unsigned char *buf,size_t len)
+{
+ int i;
+ for(i=0;i<len;i++) {
+ if ((i&15)==0) av_log(NULL, AV_LOG_DEBUG, "%04x ",i);
+ av_log(NULL, AV_LOG_DEBUG, "%02x ",buf[i]);
+ if ((i&15)==15) av_log(NULL, AV_LOG_DEBUG, "\n");
+ }
+ av_log(NULL, AV_LOG_ERROR, "\n");
+}
+#endif
+
+static int adx_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf0, int buf_size)
+{
+ ADXContext *c = avctx->priv_data;
+ short *samples = data;
+ const uint8_t *buf = buf0;
+ int rest = buf_size;
+
+ if (!c->header_parsed) {
+ int hdrsize = adx_decode_header(avctx,buf,rest);
+ if (hdrsize==0) return -1;
+ c->header_parsed = 1;
+ buf += hdrsize;
+ rest -= hdrsize;
+ }
+
+ if (c->in_temp) {
+ int copysize = 18*avctx->channels - c->in_temp;
+ memcpy(c->dec_temp+c->in_temp,buf,copysize);
+ rest -= copysize;
+ buf += copysize;
+ if (avctx->channels==1) {
+ adx_decode(samples,c->dec_temp,c->prev);
+ samples += 32;
+ } else {
+ adx_decode_stereo(samples,c->dec_temp,c->prev);
+ samples += 32*2;
+ }
+ }
+ //
+ if (avctx->channels==1) {
+ while(rest>=18) {
+ adx_decode(samples,buf,c->prev);
+ rest-=18;
+ buf+=18;
+ samples+=32;
+ }
+ } else {
+ while(rest>=18*2) {
+ adx_decode_stereo(samples,buf,c->prev);
+ rest-=18*2;
+ buf+=18*2;
+ samples+=32*2;
+ }
+ }
+ //
+ c->in_temp = rest;
+ if (rest) {
+ memcpy(c->dec_temp,buf,rest);
+ buf+=rest;
+ }
+ *data_size = (uint8_t*)samples - (uint8_t*)data;
+// printf("%d:%d ",buf-buf0,*data_size); fflush(stdout);
+ return buf-buf0;
+}
+
+#ifdef CONFIG_ENCODERS
+AVCodec adpcm_adx_encoder = {
+ "adpcm_adx",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_ADPCM_ADX,
+ sizeof(ADXContext),
+ adx_encode_init,
+ adx_encode_frame,
+ adx_encode_close,
+ NULL,
+};
+#endif //CONFIG_ENCODERS
+
+AVCodec adpcm_adx_decoder = {
+ "adpcm_adx",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_ADPCM_ADX,
+ sizeof(ADXContext),
+ adx_decode_init,
+ NULL,
+ NULL,
+ adx_decode_frame,
+};
+
diff --git a/contrib/ffmpeg/libavcodec/alac.c b/contrib/ffmpeg/libavcodec/alac.c
new file mode 100644
index 000000000..793f71a11
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/alac.c
@@ -0,0 +1,859 @@
+/*
+ * ALAC (Apple Lossless Audio Codec) decoder
+ * Copyright (c) 2005 David Hammerton
+ * All rights reserved.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * 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.c
+ * ALAC (Apple Lossless Audio Codec) decoder
+ * @author 2005 David Hammerton
+ *
+ * For more information on the ALAC format, visit:
+ * http://crazney.net/programs/itunes/alac.html
+ *
+ * Note: This decoder expects a 36- (0x24-)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:
+ * bytes 0-3 atom size (0x24), big-endian
+ * bytes 4-7 atom type ('alac', not the 'alac' tag from start of stsd)
+ * bytes 8-35 data bytes needed by decoder
+ *
+ * Extradata:
+ * 32bit size
+ * 32bit tag (=alac)
+ * 32bit zero?
+ * 32bit max sample per frame
+ * 8bit ?? (zero?)
+ * 8bit sample size
+ * 8bit history mult
+ * 8bit initial history
+ * 8bit kmodifier
+ * 8bit channels?
+ * 16bit ??
+ * 32bit max coded frame size
+ * 32bit bitrate?
+ * 32bit samplerate
+ */
+
+
+#include "avcodec.h"
+#include "bitstream.h"
+
+#define ALAC_EXTRADATA_SIZE 36
+
+typedef struct {
+
+ AVCodecContext *avctx;
+ GetBitContext gb;
+ /* init to 0; first frame decode should initialize from extradata and
+ * set this to 1 */
+ int context_initialized;
+
+ int samplesize;
+ int numchannels;
+ int bytespersample;
+
+ /* buffers */
+ int32_t *predicterror_buffer_a;
+ int32_t *predicterror_buffer_b;
+
+ int32_t *outputsamples_buffer_a;
+ int32_t *outputsamples_buffer_b;
+
+ /* stuff from setinfo */
+ uint32_t setinfo_max_samples_per_frame; /* 0x1000 = 4096 */ /* max samples per frame? */
+ uint8_t setinfo_7a; /* 0x00 */
+ uint8_t setinfo_sample_size; /* 0x10 */
+ uint8_t setinfo_rice_historymult; /* 0x28 */
+ uint8_t setinfo_rice_initialhistory; /* 0x0a */
+ uint8_t setinfo_rice_kmodifier; /* 0x0e */
+ uint8_t setinfo_7f; /* 0x02 */
+ uint16_t setinfo_80; /* 0x00ff */
+ uint32_t setinfo_82; /* 0x000020e7 */
+ uint32_t setinfo_86; /* 0x00069fe4 */
+ uint32_t setinfo_8a_rate; /* 0x0000ac44 */
+ /* end setinfo stuff */
+
+} ALACContext;
+
+static void allocate_buffers(ALACContext *alac)
+{
+ alac->predicterror_buffer_a = av_malloc(alac->setinfo_max_samples_per_frame * 4);
+ alac->predicterror_buffer_b = av_malloc(alac->setinfo_max_samples_per_frame * 4);
+
+ alac->outputsamples_buffer_a = av_malloc(alac->setinfo_max_samples_per_frame * 4);
+ alac->outputsamples_buffer_b = av_malloc(alac->setinfo_max_samples_per_frame * 4);
+}
+
+static int alac_set_info(ALACContext *alac)
+{
+ unsigned char *ptr = alac->avctx->extradata;
+
+ ptr += 4; /* size */
+ ptr += 4; /* alac */
+ ptr += 4; /* 0 ? */
+
+ if(BE_32(ptr) >= UINT_MAX/4){
+ av_log(alac->avctx, AV_LOG_ERROR, "setinfo_max_samples_per_frame too large\n");
+ return -1;
+ }
+ alac->setinfo_max_samples_per_frame = BE_32(ptr); /* buffer size / 2 ? */
+ ptr += 4;
+ alac->setinfo_7a = *ptr++;
+ alac->setinfo_sample_size = *ptr++;
+ alac->setinfo_rice_historymult = *ptr++;
+ alac->setinfo_rice_initialhistory = *ptr++;
+ alac->setinfo_rice_kmodifier = *ptr++;
+ alac->setinfo_7f = *ptr++; // channels?
+ alac->setinfo_80 = BE_16(ptr);
+ ptr += 2;
+ alac->setinfo_82 = BE_32(ptr); // max coded frame size
+ ptr += 4;
+ alac->setinfo_86 = BE_32(ptr); // bitrate ?
+ ptr += 4;
+ alac->setinfo_8a_rate = BE_32(ptr); // samplerate
+ ptr += 4;
+
+ allocate_buffers(alac);
+
+ return 0;
+}
+
+/* hideously inefficient. could use a bitmask search,
+ * alternatively bsr on x86,
+ */
+static int count_leading_zeros(int32_t input)
+{
+ int i = 0;
+ while (!(0x80000000 & input) && i < 32) {
+ i++;
+ input = input << 1;
+ }
+ return i;
+}
+
+static void bastardized_rice_decompress(ALACContext *alac,
+ int32_t *output_buffer,
+ int output_size,
+ int readsamplesize, /* arg_10 */
+ int rice_initialhistory, /* arg424->b */
+ int rice_kmodifier, /* arg424->d */
+ int rice_historymult, /* arg424->c */
+ int rice_kmodifier_mask /* arg424->e */
+ )
+{
+ int output_count;
+ unsigned int history = rice_initialhistory;
+ int sign_modifier = 0;
+
+ for (output_count = 0; output_count < output_size; output_count++) {
+ int32_t x = 0;
+ int32_t x_modified;
+ int32_t final_val;
+
+ /* read x - number of 1s before 0 represent the rice */
+ while (x <= 8 && get_bits1(&alac->gb)) {
+ x++;
+ }
+
+
+ if (x > 8) { /* RICE THRESHOLD */
+ /* use alternative encoding */
+ int32_t value;
+
+ value = get_bits(&alac->gb, readsamplesize);
+
+ /* mask value to readsamplesize size */
+ if (readsamplesize != 32)
+ value &= (0xffffffff >> (32 - readsamplesize));
+
+ x = value;
+ } else {
+ /* standard rice encoding */
+ int extrabits;
+ int k; /* size of extra bits */
+
+ /* read k, that is bits as is */
+ k = 31 - rice_kmodifier - count_leading_zeros((history >> 9) + 3);
+
+ if (k < 0)
+ k += rice_kmodifier;
+ else
+ k = rice_kmodifier;
+
+ if (k != 1) {
+ extrabits = show_bits(&alac->gb, k);
+
+ /* multiply x by 2^k - 1, as part of their strange algorithm */
+ x = (x << k) - x;
+
+ if (extrabits > 1) {
+ x += extrabits - 1;
+ get_bits(&alac->gb, k);
+ } else {
+ get_bits(&alac->gb, k - 1);
+ }
+ }
+ }
+
+ x_modified = sign_modifier + x;
+ final_val = (x_modified + 1) / 2;
+ if (x_modified & 1) final_val *= -1;
+
+ output_buffer[output_count] = final_val;
+
+ sign_modifier = 0;
+
+ /* now update the history */
+ history += (x_modified * rice_historymult)
+ - ((history * rice_historymult) >> 9);
+
+ if (x_modified > 0xffff)
+ history = 0xffff;
+
+ /* special case: there may be compressed blocks of 0 */
+ if ((history < 128) && (output_count+1 < output_size)) {
+ int block_size;
+
+ sign_modifier = 1;
+
+ x = 0;
+ while (x <= 8 && get_bits1(&alac->gb)) {
+ x++;
+ }
+
+ if (x > 8) {
+ block_size = get_bits(&alac->gb, 16);
+ block_size &= 0xffff;
+ } else {
+ int k;
+ int extrabits;
+
+ k = count_leading_zeros(history) + ((history + 16) >> 6 /* / 64 */) - 24;
+
+ extrabits = show_bits(&alac->gb, k);
+
+ block_size = (((1 << k) - 1) & rice_kmodifier_mask) * x
+ + extrabits - 1;
+
+ if (extrabits < 2) {
+ x = 1 - extrabits;
+ block_size += x;
+ get_bits(&alac->gb, k - 1);
+ } else {
+ get_bits(&alac->gb, k);
+ }
+ }
+
+ if (block_size > 0) {
+ memset(&output_buffer[output_count+1], 0, block_size * 4);
+ output_count += block_size;
+
+ }
+
+ if (block_size > 0xffff)
+ sign_modifier = 0;
+
+ history = 0;
+ }
+ }
+}
+
+#define SIGN_EXTENDED32(val, bits) ((val << (32 - bits)) >> (32 - bits))
+
+#define SIGN_ONLY(v) \
+ ((v < 0) ? (-1) : \
+ ((v > 0) ? (1) : \
+ (0)))
+
+static void predictor_decompress_fir_adapt(int32_t *error_buffer,
+ int32_t *buffer_out,
+ int output_size,
+ int readsamplesize,
+ int16_t *predictor_coef_table,
+ int predictor_coef_num,
+ int predictor_quantitization)
+{
+ int i;
+
+ /* first sample always copies */
+ *buffer_out = *error_buffer;
+
+ if (!predictor_coef_num) {
+ if (output_size <= 1) return;
+ memcpy(buffer_out+1, error_buffer+1, (output_size-1) * 4);
+ return;
+ }
+
+ if (predictor_coef_num == 0x1f) { /* 11111 - max value of predictor_coef_num */
+ /* second-best case scenario for fir decompression,
+ * error describes a small difference from the previous sample only
+ */
+ if (output_size <= 1) return;
+ for (i = 0; i < output_size - 1; i++) {
+ int32_t prev_value;
+ int32_t error_value;
+
+ prev_value = buffer_out[i];
+ error_value = error_buffer[i+1];
+ buffer_out[i+1] = SIGN_EXTENDED32((prev_value + error_value), readsamplesize);
+ }
+ return;
+ }
+
+ /* read warm-up samples */
+ if (predictor_coef_num > 0) {
+ int i;
+ for (i = 0; i < predictor_coef_num; i++) {
+ int32_t val;
+
+ val = buffer_out[i] + error_buffer[i+1];
+
+ val = SIGN_EXTENDED32(val, readsamplesize);
+
+ buffer_out[i+1] = val;
+ }
+ }
+
+#if 0
+ /* 4 and 8 are very common cases (the only ones i've seen). these
+ * should be unrolled and optimised
+ */
+ if (predictor_coef_num == 4) {
+ /* FIXME: optimised general case */
+ return;
+ }
+
+ if (predictor_coef_table == 8) {
+ /* FIXME: optimised general case */
+ return;
+ }
+#endif
+
+
+ /* general case */
+ if (predictor_coef_num > 0) {
+ for (i = predictor_coef_num + 1;
+ i < output_size;
+ i++) {
+ int j;
+ int sum = 0;
+ int outval;
+ int error_val = error_buffer[i];
+
+ for (j = 0; j < predictor_coef_num; j++) {
+ sum += (buffer_out[predictor_coef_num-j] - buffer_out[0]) *
+ predictor_coef_table[j];
+ }
+
+ outval = (1 << (predictor_quantitization-1)) + sum;
+ outval = outval >> predictor_quantitization;
+ outval = outval + buffer_out[0] + error_val;
+ outval = SIGN_EXTENDED32(outval, readsamplesize);
+
+ buffer_out[predictor_coef_num+1] = outval;
+
+ if (error_val > 0) {
+ int predictor_num = predictor_coef_num - 1;
+
+ while (predictor_num >= 0 && error_val > 0) {
+ int val = buffer_out[0] - buffer_out[predictor_coef_num - predictor_num];
+ int sign = SIGN_ONLY(val);
+
+ predictor_coef_table[predictor_num] -= sign;
+
+ val *= sign; /* absolute value */
+
+ error_val -= ((val >> predictor_quantitization) *
+ (predictor_coef_num - predictor_num));
+
+ predictor_num--;
+ }
+ } else if (error_val < 0) {
+ int predictor_num = predictor_coef_num - 1;
+
+ while (predictor_num >= 0 && error_val < 0) {
+ int val = buffer_out[0] - buffer_out[predictor_coef_num - predictor_num];
+ int sign = - SIGN_ONLY(val);
+
+ predictor_coef_table[predictor_num] -= sign;
+
+ val *= sign; /* neg value */
+
+ error_val -= ((val >> predictor_quantitization) *
+ (predictor_coef_num - predictor_num));
+
+ predictor_num--;
+ }
+ }
+
+ buffer_out++;
+ }
+ }
+}
+
+static void deinterlace_16(int32_t *buffer_a, int32_t *buffer_b,
+ int16_t *buffer_out,
+ int numchannels, int numsamples,
+ uint8_t interlacing_shift,
+ uint8_t interlacing_leftweight)
+{
+ int i;
+ if (numsamples <= 0) return;
+
+ /* weighted interlacing */
+ if (interlacing_leftweight) {
+ for (i = 0; i < numsamples; i++) {
+ int32_t difference, midright;
+ int16_t left;
+ int16_t right;
+
+ midright = buffer_a[i];
+ difference = buffer_b[i];
+
+
+ right = midright - ((difference * interlacing_leftweight) >> interlacing_shift);
+ left = (midright - ((difference * interlacing_leftweight) >> interlacing_shift))
+ + difference;
+
+ buffer_out[i*numchannels] = left;
+ buffer_out[i*numchannels + 1] = right;
+ }
+
+ return;
+ }
+
+ /* otherwise basic interlacing took place */
+ for (i = 0; i < numsamples; i++) {
+ int16_t left, right;
+
+ left = buffer_a[i];
+ right = buffer_b[i];
+
+ buffer_out[i*numchannels] = left;
+ buffer_out[i*numchannels + 1] = right;
+ }
+}
+
+static int alac_decode_frame(AVCodecContext *avctx,
+ void *outbuffer, int *outputsize,
+ uint8_t *inbuffer, int input_buffer_size)
+{
+ ALACContext *alac = avctx->priv_data;
+
+ int channels;
+ int32_t outputsamples;
+
+ /* short-circuit null buffers */
+ if (!inbuffer || !input_buffer_size)
+ return input_buffer_size;
+
+ /* initialize from the extradata */
+ if (!alac->context_initialized) {
+ if (alac->avctx->extradata_size != ALAC_EXTRADATA_SIZE) {
+ av_log(avctx, AV_LOG_ERROR, "alac: expected %d extradata bytes\n",
+ ALAC_EXTRADATA_SIZE);
+ return input_buffer_size;
+ }
+ if (alac_set_info(alac)) {
+ av_log(avctx, AV_LOG_ERROR, "alac: set_info failed\n");
+ return input_buffer_size;
+ }
+ alac->context_initialized = 1;
+ }
+
+ outputsamples = alac->setinfo_max_samples_per_frame;
+
+ init_get_bits(&alac->gb, inbuffer, input_buffer_size * 8);
+
+ channels = get_bits(&alac->gb, 3);
+
+ *outputsize = outputsamples * alac->bytespersample;
+
+ switch(channels) {
+ case 0: { /* 1 channel */
+ int hassize;
+ int isnotcompressed;
+ int readsamplesize;
+
+ int wasted_bytes;
+ int ricemodifier;
+
+
+ /* 2^result = something to do with output waiting.
+ * perhaps matters if we read > 1 frame in a pass?
+ */
+ get_bits(&alac->gb, 4);
+
+ get_bits(&alac->gb, 12); /* unknown, skip 12 bits */
+
+ hassize = get_bits(&alac->gb, 1); /* the output sample size is stored soon */
+
+ wasted_bytes = get_bits(&alac->gb, 2); /* unknown ? */
+
+ isnotcompressed = get_bits(&alac->gb, 1); /* whether the frame is compressed */
+
+ if (hassize) {
+ /* now read the number of samples,
+ * as a 32bit integer */
+ outputsamples = get_bits(&alac->gb, 32);
+ *outputsize = outputsamples * alac->bytespersample;
+ }
+
+ readsamplesize = alac->setinfo_sample_size - (wasted_bytes * 8);
+
+ if (!isnotcompressed) {
+ /* so it is compressed */
+ int16_t predictor_coef_table[32];
+ int predictor_coef_num;
+ int prediction_type;
+ int prediction_quantitization;
+ int i;
+
+ /* FIXME: skip 16 bits, not sure what they are. seem to be used in
+ * two channel case */
+ get_bits(&alac->gb, 8);
+ get_bits(&alac->gb, 8);
+
+ prediction_type = get_bits(&alac->gb, 4);
+ prediction_quantitization = get_bits(&alac->gb, 4);
+
+ ricemodifier = get_bits(&alac->gb, 3);
+ predictor_coef_num = get_bits(&alac->gb, 5);
+
+ /* read the predictor table */
+ for (i = 0; i < predictor_coef_num; i++) {
+ predictor_coef_table[i] = (int16_t)get_bits(&alac->gb, 16);
+ }
+
+ if (wasted_bytes) {
+ /* these bytes seem to have something to do with
+ * > 2 channel files.
+ */
+ av_log(avctx, AV_LOG_ERROR, "FIXME: unimplemented, unhandling of wasted_bytes\n");
+ }
+
+ bastardized_rice_decompress(alac,
+ alac->predicterror_buffer_a,
+ outputsamples,
+ readsamplesize,
+ alac->setinfo_rice_initialhistory,
+ alac->setinfo_rice_kmodifier,
+ ricemodifier * alac->setinfo_rice_historymult / 4,
+ (1 << alac->setinfo_rice_kmodifier) - 1);
+
+ if (prediction_type == 0) {
+ /* adaptive fir */
+ predictor_decompress_fir_adapt(alac->predicterror_buffer_a,
+ alac->outputsamples_buffer_a,
+ outputsamples,
+ readsamplesize,
+ predictor_coef_table,
+ predictor_coef_num,
+ prediction_quantitization);
+ } else {
+ av_log(avctx, AV_LOG_ERROR, "FIXME: unhandled prediction type: %i\n", prediction_type);
+ /* i think the only other prediction type (or perhaps this is just a
+ * boolean?) runs adaptive fir twice.. like:
+ * predictor_decompress_fir_adapt(predictor_error, tempout, ...)
+ * predictor_decompress_fir_adapt(predictor_error, outputsamples ...)
+ * little strange..
+ */
+ }
+
+ } else {
+ /* not compressed, easy case */
+ if (readsamplesize <= 16) {
+ int i;
+ for (i = 0; i < outputsamples; i++) {
+ int32_t audiobits = get_bits(&alac->gb, readsamplesize);
+
+ audiobits = SIGN_EXTENDED32(audiobits, readsamplesize);
+
+ alac->outputsamples_buffer_a[i] = audiobits;
+ }
+ } else {
+ int i;
+ for (i = 0; i < outputsamples; i++) {
+ int32_t audiobits;
+
+ audiobits = get_bits(&alac->gb, 16);
+ /* special case of sign extension..
+ * as we'll be ORing the low 16bits into this */
+ audiobits = audiobits << 16;
+ audiobits = audiobits >> (32 - readsamplesize);
+
+ audiobits |= get_bits(&alac->gb, readsamplesize - 16);
+
+ alac->outputsamples_buffer_a[i] = audiobits;
+ }
+ }
+ /* wasted_bytes = 0; // unused */
+ }
+
+ switch(alac->setinfo_sample_size) {
+ case 16: {
+ int i;
+ for (i = 0; i < outputsamples; i++) {
+ int16_t sample = alac->outputsamples_buffer_a[i];
+ ((int16_t*)outbuffer)[i * alac->numchannels] = sample;
+ }
+ break;
+ }
+ case 20:
+ case 24:
+ case 32:
+ av_log(avctx, AV_LOG_ERROR, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case 1: { /* 2 channels */
+ int hassize;
+ int isnotcompressed;
+ int readsamplesize;
+
+ int wasted_bytes;
+
+ uint8_t interlacing_shift;
+ uint8_t interlacing_leftweight;
+
+ /* 2^result = something to do with output waiting.
+ * perhaps matters if we read > 1 frame in a pass?
+ */
+ get_bits(&alac->gb, 4);
+
+ get_bits(&alac->gb, 12); /* unknown, skip 12 bits */
+
+ hassize = get_bits(&alac->gb, 1); /* the output sample size is stored soon */
+
+ wasted_bytes = get_bits(&alac->gb, 2); /* unknown ? */
+
+ isnotcompressed = get_bits(&alac->gb, 1); /* whether the frame is compressed */
+
+ if (hassize) {
+ /* now read the number of samples,
+ * as a 32bit integer */
+ outputsamples = get_bits(&alac->gb, 32);
+ *outputsize = outputsamples * alac->bytespersample;
+ }
+
+ readsamplesize = alac->setinfo_sample_size - (wasted_bytes * 8) + 1;
+
+ if (!isnotcompressed) {
+ /* compressed */
+ int16_t predictor_coef_table_a[32];
+ int predictor_coef_num_a;
+ int prediction_type_a;
+ int prediction_quantitization_a;
+ int ricemodifier_a;
+
+ int16_t predictor_coef_table_b[32];
+ int predictor_coef_num_b;
+ int prediction_type_b;
+ int prediction_quantitization_b;
+ int ricemodifier_b;
+
+ int i;
+
+ interlacing_shift = get_bits(&alac->gb, 8);
+ interlacing_leftweight = get_bits(&alac->gb, 8);
+
+ /******** channel 1 ***********/
+ prediction_type_a = get_bits(&alac->gb, 4);
+ prediction_quantitization_a = get_bits(&alac->gb, 4);
+
+ ricemodifier_a = get_bits(&alac->gb, 3);
+ predictor_coef_num_a = get_bits(&alac->gb, 5);
+
+ /* read the predictor table */
+ for (i = 0; i < predictor_coef_num_a; i++) {
+ predictor_coef_table_a[i] = (int16_t)get_bits(&alac->gb, 16);
+ }
+
+ /******** channel 2 *********/
+ prediction_type_b = get_bits(&alac->gb, 4);
+ prediction_quantitization_b = get_bits(&alac->gb, 4);
+
+ ricemodifier_b = get_bits(&alac->gb, 3);
+ predictor_coef_num_b = get_bits(&alac->gb, 5);
+
+ /* read the predictor table */
+ for (i = 0; i < predictor_coef_num_b; i++) {
+ predictor_coef_table_b[i] = (int16_t)get_bits(&alac->gb, 16);
+ }
+
+ /*********************/
+ if (wasted_bytes) {
+ /* see mono case */
+ av_log(avctx, AV_LOG_ERROR, "FIXME: unimplemented, unhandling of wasted_bytes\n");
+ }
+
+ /* channel 1 */
+ bastardized_rice_decompress(alac,
+ alac->predicterror_buffer_a,
+ outputsamples,
+ readsamplesize,
+ alac->setinfo_rice_initialhistory,
+ alac->setinfo_rice_kmodifier,
+ ricemodifier_a * alac->setinfo_rice_historymult / 4,
+ (1 << alac->setinfo_rice_kmodifier) - 1);
+
+ if (prediction_type_a == 0) {
+ /* adaptive fir */
+ predictor_decompress_fir_adapt(alac->predicterror_buffer_a,
+ alac->outputsamples_buffer_a,
+ outputsamples,
+ readsamplesize,
+ predictor_coef_table_a,
+ predictor_coef_num_a,
+ prediction_quantitization_a);
+ } else {
+ /* see mono case */
+ av_log(avctx, AV_LOG_ERROR, "FIXME: unhandled prediction type: %i\n", prediction_type_a);
+ }
+
+ /* channel 2 */
+ bastardized_rice_decompress(alac,
+ alac->predicterror_buffer_b,
+ outputsamples,
+ readsamplesize,
+ alac->setinfo_rice_initialhistory,
+ alac->setinfo_rice_kmodifier,
+ ricemodifier_b * alac->setinfo_rice_historymult / 4,
+ (1 << alac->setinfo_rice_kmodifier) - 1);
+
+ if (prediction_type_b == 0) {
+ /* adaptive fir */
+ predictor_decompress_fir_adapt(alac->predicterror_buffer_b,
+ alac->outputsamples_buffer_b,
+ outputsamples,
+ readsamplesize,
+ predictor_coef_table_b,
+ predictor_coef_num_b,
+ prediction_quantitization_b);
+ } else {
+ av_log(avctx, AV_LOG_ERROR, "FIXME: unhandled prediction type: %i\n", prediction_type_b);
+ }
+ } else {
+ /* not compressed, easy case */
+ if (alac->setinfo_sample_size <= 16) {
+ int i;
+ for (i = 0; i < outputsamples; i++) {
+ int32_t audiobits_a, audiobits_b;
+
+ audiobits_a = get_bits(&alac->gb, alac->setinfo_sample_size);
+ audiobits_b = get_bits(&alac->gb, alac->setinfo_sample_size);
+
+ audiobits_a = SIGN_EXTENDED32(audiobits_a, alac->setinfo_sample_size);
+ audiobits_b = SIGN_EXTENDED32(audiobits_b, alac->setinfo_sample_size);
+
+ alac->outputsamples_buffer_a[i] = audiobits_a;
+ alac->outputsamples_buffer_b[i] = audiobits_b;
+ }
+ } else {
+ int i;
+ for (i = 0; i < outputsamples; i++) {
+ int32_t audiobits_a, audiobits_b;
+
+ audiobits_a = get_bits(&alac->gb, 16);
+ audiobits_a = audiobits_a << 16;
+ audiobits_a = audiobits_a >> (32 - alac->setinfo_sample_size);
+ audiobits_a |= get_bits(&alac->gb, alac->setinfo_sample_size - 16);
+
+ audiobits_b = get_bits(&alac->gb, 16);
+ audiobits_b = audiobits_b << 16;
+ audiobits_b = audiobits_b >> (32 - alac->setinfo_sample_size);
+ audiobits_b |= get_bits(&alac->gb, alac->setinfo_sample_size - 16);
+
+ alac->outputsamples_buffer_a[i] = audiobits_a;
+ alac->outputsamples_buffer_b[i] = audiobits_b;
+ }
+ }
+ /* wasted_bytes = 0; */
+ interlacing_shift = 0;
+ interlacing_leftweight = 0;
+ }
+
+ switch(alac->setinfo_sample_size) {
+ case 16: {
+ deinterlace_16(alac->outputsamples_buffer_a,
+ alac->outputsamples_buffer_b,
+ (int16_t*)outbuffer,
+ alac->numchannels,
+ outputsamples,
+ interlacing_shift,
+ interlacing_leftweight);
+ break;
+ }
+ case 20:
+ case 24:
+ case 32:
+ av_log(avctx, AV_LOG_ERROR, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size);
+ break;
+ default:
+ break;
+ }
+
+ break;
+ }
+ }
+
+ return input_buffer_size;
+}
+
+static int alac_decode_init(AVCodecContext * avctx)
+{
+ ALACContext *alac = avctx->priv_data;
+ alac->avctx = avctx;
+ alac->context_initialized = 0;
+
+ alac->samplesize = alac->avctx->bits_per_sample;
+ alac->numchannels = alac->avctx->channels;
+ alac->bytespersample = (alac->samplesize / 8) * alac->numchannels;
+
+ return 0;
+}
+
+static int alac_decode_close(AVCodecContext *avctx)
+{
+ ALACContext *alac = avctx->priv_data;
+
+ av_free(alac->predicterror_buffer_a);
+ av_free(alac->predicterror_buffer_b);
+
+ av_free(alac->outputsamples_buffer_a);
+ av_free(alac->outputsamples_buffer_b);
+
+ return 0;
+}
+
+AVCodec alac_decoder = {
+ "alac",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_ALAC,
+ sizeof(ALACContext),
+ alac_decode_init,
+ NULL,
+ alac_decode_close,
+ alac_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/allcodecs.c b/contrib/ffmpeg/libavcodec/allcodecs.c
new file mode 100644
index 000000000..9678f6bee
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/allcodecs.c
@@ -0,0 +1,289 @@
+/*
+ * Utils 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 allcodecs.c
+ * Utils for libavcodec.
+ */
+
+#include "avcodec.h"
+
+#define REGISTER_ENCODER(X,x) \
+ if(ENABLE_##X##_ENCODER) register_avcodec(&x##_encoder)
+#define REGISTER_DECODER(X,x) \
+ if(ENABLE_##X##_DECODER) register_avcodec(&x##_decoder)
+#define REGISTER_ENCDEC(X,x) REGISTER_ENCODER(X,x); REGISTER_DECODER(X,x)
+
+#define REGISTER_PARSER(X,x) \
+ if(ENABLE_##X##_PARSER) av_register_codec_parser(&x##_parser)
+
+/* If you do not call this function, then you can select exactly which
+ formats you want to support */
+
+/**
+ * simple call to register all the codecs.
+ */
+void avcodec_register_all(void)
+{
+ static int inited = 0;
+
+ if (inited != 0)
+ return;
+ inited = 1;
+
+ /* video codecs */
+ REGISTER_DECODER(AASC, aasc);
+ REGISTER_ENCDEC (ASV1, asv1);
+ REGISTER_ENCDEC (ASV2, asv2);
+ REGISTER_DECODER(AVS, avs);
+ REGISTER_DECODER(BMP, bmp);
+ REGISTER_DECODER(CAVS, cavs);
+ REGISTER_DECODER(CINEPAK, cinepak);
+ REGISTER_DECODER(CLJR, cljr);
+ REGISTER_DECODER(CSCD, cscd);
+ REGISTER_DECODER(CYUV, cyuv);
+ REGISTER_DECODER(DSICINVIDEO, dsicinvideo);
+ REGISTER_ENCDEC (DVVIDEO, dvvideo);
+ REGISTER_DECODER(EIGHTBPS, eightbps);
+ REGISTER_ENCDEC (FFV1, ffv1);
+ REGISTER_ENCDEC (FFVHUFF, ffvhuff);
+ REGISTER_DECODER(FLASHSV, flashsv);
+ REGISTER_DECODER(FLIC, flic);
+ REGISTER_ENCDEC (FLV, flv);
+ REGISTER_DECODER(FOURXM, fourxm);
+ REGISTER_DECODER(FRAPS, fraps);
+ REGISTER_ENCDEC (GIF, gif);
+ REGISTER_ENCDEC (H261, h261);
+ REGISTER_ENCDEC (H263, h263);
+ REGISTER_DECODER(H263I, h263i);
+ REGISTER_ENCODER(H263P, h263p);
+ REGISTER_DECODER(H264, h264);
+ REGISTER_ENCDEC (HUFFYUV, huffyuv);
+ REGISTER_DECODER(IDCIN, idcin);
+ REGISTER_DECODER(INDEO2, indeo2);
+ REGISTER_DECODER(INDEO3, indeo3);
+ REGISTER_DECODER(INTERPLAY_VIDEO, interplay_video);
+ REGISTER_ENCODER(JPEGLS, jpegls);
+ REGISTER_DECODER(KMVC, kmvc);
+ REGISTER_ENCODER(LJPEG, ljpeg);
+ REGISTER_DECODER(LOCO, loco);
+ REGISTER_DECODER(MDEC, mdec);
+ REGISTER_ENCDEC (MJPEG, mjpeg);
+ REGISTER_DECODER(MJPEGB, mjpegb);
+ REGISTER_DECODER(MMVIDEO, mmvideo);
+#ifdef HAVE_XVMC
+ REGISTER_DECODER(MPEG_XVMC, mpeg_xvmc);
+#endif
+ REGISTER_ENCDEC (MPEG1VIDEO, mpeg1video);
+ REGISTER_ENCDEC (MPEG2VIDEO, mpeg2video);
+ REGISTER_ENCDEC (MPEG4, mpeg4);
+ REGISTER_DECODER(MPEGVIDEO, mpegvideo);
+ REGISTER_ENCDEC (MSMPEG4V1, msmpeg4v1);
+ REGISTER_ENCDEC (MSMPEG4V2, msmpeg4v2);
+ REGISTER_ENCDEC (MSMPEG4V3, msmpeg4v3);
+ REGISTER_DECODER(MSRLE, msrle);
+ REGISTER_DECODER(MSVIDEO1, msvideo1);
+ REGISTER_DECODER(MSZH, mszh);
+ REGISTER_DECODER(NUV, nuv);
+ REGISTER_ENCODER(PAM, pam);
+ REGISTER_ENCODER(PBM, pbm);
+ REGISTER_ENCODER(PGM, pgm);
+ REGISTER_ENCODER(PGMYUV, pgmyuv);
+#ifdef CONFIG_ZLIB
+ REGISTER_ENCDEC (PNG, png);
+#endif
+ REGISTER_ENCODER(PPM, ppm);
+ REGISTER_DECODER(QDRAW, qdraw);
+ REGISTER_DECODER(QPEG, qpeg);
+ REGISTER_DECODER(QTRLE, qtrle);
+ REGISTER_ENCDEC (RAWVIDEO, rawvideo);
+ REGISTER_DECODER(ROQ, roq);
+ REGISTER_DECODER(RPZA, rpza);
+ REGISTER_ENCDEC (RV10, rv10);
+ REGISTER_ENCDEC (RV20, rv20);
+ REGISTER_DECODER(SMACKER, smacker);
+ REGISTER_DECODER(SMC, smc);
+ REGISTER_ENCDEC (SNOW, snow);
+ REGISTER_DECODER(SP5X, sp5x);
+ REGISTER_ENCDEC (SVQ1, svq1);
+ REGISTER_DECODER(SVQ3, svq3);
+ REGISTER_DECODER(TARGA, targa);
+ REGISTER_DECODER(THEORA, theora);
+ REGISTER_DECODER(TIERTEXSEQVIDEO, tiertexseqvideo);
+ REGISTER_DECODER(TIFF, tiff);
+ REGISTER_DECODER(TRUEMOTION1, truemotion1);
+ REGISTER_DECODER(TRUEMOTION2, truemotion2);
+ REGISTER_DECODER(TSCC, tscc);
+ REGISTER_DECODER(ULTI, ulti);
+ REGISTER_DECODER(VC1, vc1);
+ 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(VP6F, vp6f);
+ REGISTER_DECODER(VQA, vqa);
+ REGISTER_ENCDEC (WMV1, wmv1);
+ REGISTER_ENCDEC (WMV2, wmv2);
+ REGISTER_DECODER(WMV3, wmv3);
+ REGISTER_DECODER(WNV1, wnv1);
+#ifdef CONFIG_X264
+ REGISTER_ENCODER(X264, x264);
+#endif
+ REGISTER_DECODER(XAN_WC3, xan_wc3);
+ REGISTER_DECODER(XL, xl);
+#ifdef CONFIG_XVID
+ REGISTER_ENCODER(XVID, xvid);
+#endif
+ REGISTER_ENCDEC (ZLIB, zlib);
+ REGISTER_DECODER(ZMBV, zmbv);
+
+ /* audio codecs */
+#ifdef CONFIG_FAAD
+ REGISTER_DECODER(AAC, aac);
+ REGISTER_DECODER(MPEG4AAC, mpeg4aac);
+#endif
+#ifdef CONFIG_A52
+ REGISTER_DECODER(AC3, ac3);
+#endif
+ REGISTER_ENCODER(AC3, ac3);
+ REGISTER_DECODER(ALAC, alac);
+#if defined(CONFIG_AMR_NB) || defined(CONFIG_AMR_NB_FIXED)
+ REGISTER_ENCDEC (AMR_NB, amr_nb);
+#endif
+#ifdef CONFIG_AMR_WB
+ REGISTER_ENCDEC (AMR_WB, amr_wb);
+#endif
+ REGISTER_DECODER(COOK, cook);
+ REGISTER_DECODER(DSICINAUDIO, dsicinaudio);
+#ifdef CONFIG_DTS
+ REGISTER_DECODER(DTS, dts);
+#endif
+#ifdef CONFIG_FAAC
+ REGISTER_ENCODER(FAAC, faac);
+#endif
+ REGISTER_ENCDEC (FLAC, flac);
+ REGISTER_DECODER(IMC, imc);
+#ifdef CONFIG_LIBGSM
+ REGISTER_ENCDEC (LIBGSM, libgsm);
+#endif
+ REGISTER_DECODER(MACE3, mace3);
+ REGISTER_DECODER(MACE6, mace6);
+ REGISTER_ENCDEC (MP2, mp2);
+ REGISTER_DECODER(MP3, mp3);
+ REGISTER_DECODER(MP3ADU, mp3adu);
+#ifdef CONFIG_MP3LAME
+ REGISTER_ENCODER(MP3LAME, mp3lame);
+#endif
+ REGISTER_DECODER(MP3ON4, mp3on4);
+#ifdef CONFIG_LIBVORBIS
+ if (!ENABLE_VORBIS_ENCODER) REGISTER_ENCODER(OGGVORBIS, oggvorbis);
+ if (!ENABLE_VORBIS_DECODER) REGISTER_DECODER(OGGVORBIS, oggvorbis);
+#endif
+ REGISTER_DECODER(QDM2, qdm2);
+ REGISTER_DECODER(RA_144, ra_144);
+ REGISTER_DECODER(RA_288, ra_288);
+ REGISTER_DECODER(SHORTEN, shorten);
+ REGISTER_DECODER(SMACKAUD, smackaud);
+ REGISTER_ENCDEC (SONIC, sonic);
+ REGISTER_ENCODER(SONIC_LS, sonic_ls);
+ REGISTER_DECODER(TRUESPEECH, truespeech);
+ REGISTER_DECODER(TTA, tta);
+ REGISTER_DECODER(VMDAUDIO, vmdaudio);
+ REGISTER_ENCDEC (VORBIS, vorbis);
+ REGISTER_DECODER(WAVPACK, wavpack);
+ REGISTER_DECODER(WMAV1, wmav1);
+ REGISTER_DECODER(WMAV2, wmav2);
+ REGISTER_DECODER(WS_SND1, ws_snd1);
+
+ /* pcm codecs */
+ REGISTER_ENCDEC (PCM_ALAW, pcm_alaw);
+ REGISTER_ENCDEC (PCM_MULAW, pcm_mulaw);
+ REGISTER_ENCDEC (PCM_S8, pcm_s8);
+ REGISTER_ENCDEC (PCM_S16BE, pcm_s16be);
+ REGISTER_ENCDEC (PCM_S16LE, pcm_s16le);
+ REGISTER_ENCDEC (PCM_S24BE, pcm_s24be);
+ REGISTER_ENCDEC (PCM_S24DAUD, pcm_s24daud);
+ REGISTER_ENCDEC (PCM_S24LE, pcm_s24le);
+ REGISTER_ENCDEC (PCM_S32BE, pcm_s32be);
+ REGISTER_ENCDEC (PCM_S32LE, pcm_s32le);
+ 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);
+
+ /* dpcm codecs */
+ REGISTER_DECODER(INTERPLAY_DPCM, interplay_dpcm);
+ REGISTER_DECODER(ROQ_DPCM, roq_dpcm);
+ REGISTER_DECODER(SOL_DPCM, sol_dpcm);
+ REGISTER_DECODER(XAN_DPCM, xan_dpcm);
+
+ /* adpcm codecs */
+ REGISTER_ENCDEC (ADPCM_4XM, adpcm_4xm);
+ REGISTER_ENCDEC (ADPCM_ADX, adpcm_adx);
+ REGISTER_ENCDEC (ADPCM_CT, adpcm_ct);
+ REGISTER_ENCDEC (ADPCM_EA, adpcm_ea);
+ REGISTER_ENCDEC (ADPCM_G726, adpcm_g726);
+ REGISTER_ENCDEC (ADPCM_IMA_DK3, adpcm_ima_dk3);
+ REGISTER_ENCDEC (ADPCM_IMA_DK4, adpcm_ima_dk4);
+ REGISTER_ENCDEC (ADPCM_IMA_QT, adpcm_ima_qt);
+ REGISTER_ENCDEC (ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg);
+ REGISTER_ENCDEC (ADPCM_IMA_WAV, adpcm_ima_wav);
+ REGISTER_ENCDEC (ADPCM_IMA_WS, adpcm_ima_ws);
+ REGISTER_ENCDEC (ADPCM_MS, adpcm_ms);
+ REGISTER_ENCDEC (ADPCM_SBPRO_2, adpcm_sbpro_2);
+ REGISTER_ENCDEC (ADPCM_SBPRO_3, adpcm_sbpro_3);
+ REGISTER_ENCDEC (ADPCM_SBPRO_4, adpcm_sbpro_4);
+ REGISTER_ENCDEC (ADPCM_SWF, adpcm_swf);
+ REGISTER_ENCDEC (ADPCM_XA, adpcm_xa);
+ REGISTER_ENCDEC (ADPCM_YAMAHA, adpcm_yamaha);
+
+ /* subtitles */
+ REGISTER_ENCDEC (DVBSUB, dvbsub);
+ REGISTER_ENCDEC (DVDSUB, dvdsub);
+
+ /* parsers */
+ REGISTER_PARSER (AAC, aac);
+ REGISTER_PARSER (AC3, ac3);
+ REGISTER_PARSER (CAVSVIDEO, cavsvideo);
+ REGISTER_PARSER (DVBSUB, dvbsub);
+ REGISTER_PARSER (DVDSUB, dvdsub);
+ REGISTER_PARSER (H261, h261);
+ REGISTER_PARSER (H263, h263);
+ REGISTER_PARSER (H264, h264);
+ REGISTER_PARSER (MJPEG, mjpeg);
+ REGISTER_PARSER (MPEG4VIDEO, mpeg4video);
+ REGISTER_PARSER (MPEGAUDIO, mpegaudio);
+ REGISTER_PARSER (MPEGVIDEO, mpegvideo);
+ REGISTER_PARSER (PNM, pnm);
+
+ av_register_bitstream_filter(&dump_extradata_bsf);
+ av_register_bitstream_filter(&remove_extradata_bsf);
+ av_register_bitstream_filter(&noise_bsf);
+ av_register_bitstream_filter(&mp3_header_compress_bsf);
+ av_register_bitstream_filter(&mp3_header_decompress_bsf);
+ av_register_bitstream_filter(&mjpega_dump_header_bsf);
+}
+
diff --git a/contrib/ffmpeg/libavcodec/alpha/asm.h b/contrib/ffmpeg/libavcodec/alpha/asm.h
new file mode 100644
index 000000000..c0ddde528
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/alpha/asm.h
@@ -0,0 +1,191 @@
+/*
+ * Alpha optimized DSP utils
+ * Copyright (c) 2002 Falk Hueffner <falk@debian.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
+ */
+
+#ifndef LIBAVCODEC_ALPHA_ASM_H
+#define LIBAVCODEC_ALPHA_ASM_H
+
+#include <inttypes.h>
+
+#if defined __GNUC__
+# define GNUC_PREREQ(maj, min) \
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#else
+# define GNUC_PREREQ(maj, min) 0
+#endif
+
+#if GNUC_PREREQ(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) \
+ (((union { \
+ uint64_t __l; \
+ __typeof__(*(p)) __s[sizeof (uint64_t) / sizeof *(p)]; \
+ } *) (p))->__l)
+#define ldl(p) \
+ (((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 GNUC_PREREQ(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 GNUC_PREREQ(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 <c_asm.h>
+#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 /* LIBAVCODEC_ALPHA_ASM_H */
diff --git a/contrib/ffmpeg/libavcodec/alpha/dsputil_alpha.c b/contrib/ffmpeg/libavcodec/alpha/dsputil_alpha.c
new file mode 100644
index 000000000..c98d6f7ff
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/alpha/dsputil_alpha.c
@@ -0,0 +1,362 @@
+/*
+ * Alpha optimized DSP utils
+ * Copyright (c) 2002 Falk Hueffner <falk@debian.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
+ */
+
+#include "asm.h"
+#include "../dsputil.h"
+
+extern void simple_idct_axp(DCTELEM *block);
+extern void simple_idct_put_axp(uint8_t *dest, int line_size, DCTELEM *block);
+extern void simple_idct_add_axp(uint8_t *dest, int line_size, DCTELEM *block);
+
+void put_pixels_axp_asm(uint8_t *block, const uint8_t *pixels,
+ int line_size, int h);
+void put_pixels_clamped_mvi_asm(const DCTELEM *block, uint8_t *pixels,
+ int line_size);
+void add_pixels_clamped_mvi_asm(const DCTELEM *block, uint8_t *pixels,
+ int line_size);
+void (*put_pixels_clamped_axp_p)(const DCTELEM *block, uint8_t *pixels,
+ int line_size);
+void (*add_pixels_clamped_axp_p)(const DCTELEM *block, uint8_t *pixels,
+ int line_size);
+
+void get_pixels_mvi(DCTELEM *restrict block,
+ const uint8_t *restrict pixels, int line_size);
+void diff_pixels_mvi(DCTELEM *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(uint8_t *pix1, uint8_t *pix2, int line_size);
+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);
+
+#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 DCTELEM *block, uint8_t *pixels,
+ int 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 DCTELEM *block, uint8_t *pixels,
+ int 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(DCTELEM *blocks) {
+ uint64_t *p = (uint64_t *) blocks;
+ int n = sizeof(DCTELEM) * 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);
+}
+
+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, \
+ int 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, \
+ int 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);
+
+void put_pixels16_axp_asm(uint8_t *block, const uint8_t *pixels,
+ int line_size, int h)
+{
+ put_pixels_axp_asm(block, pixels, line_size, h);
+ put_pixels_axp_asm(block + 8, pixels + 8, line_size, h);
+}
+
+static int sad16x16_mvi(void *s, uint8_t *a, uint8_t *b, int stride)
+{
+ return pix_abs16x16_mvi_asm(a, b, stride);
+}
+
+void dsputil_init_alpha(DSPContext* c, AVCodecContext *avctx)
+{
+ 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][0] = avg_no_rnd_pixels16_axp;
+ c->avg_no_rnd_pixels_tab[0][1] = avg_no_rnd_pixels16_x2_axp;
+ c->avg_no_rnd_pixels_tab[0][2] = avg_no_rnd_pixels16_y2_axp;
+ c->avg_no_rnd_pixels_tab[0][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;
+
+ c->avg_no_rnd_pixels_tab[1][0] = avg_no_rnd_pixels_axp;
+ c->avg_no_rnd_pixels_tab[1][1] = avg_no_rnd_pixels_x2_axp;
+ c->avg_no_rnd_pixels_tab[1][2] = avg_no_rnd_pixels_y2_axp;
+ c->avg_no_rnd_pixels_tab[1][3] = avg_no_rnd_pixels_xy2_axp;
+
+ 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;
+
+ c->get_pixels = get_pixels_mvi;
+ c->diff_pixels = diff_pixels_mvi;
+ c->sad[0] = sad16x16_mvi;
+ c->sad[1] = pix_abs8x8_mvi;
+// c->pix_abs[0][0] = pix_abs16x16_mvi_asm; //FIXME function arguments for the asm must be fixed
+ c->pix_abs[0][0] = sad16x16_mvi;
+ 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;
+
+ c->idct_put = simple_idct_put_axp;
+ c->idct_add = simple_idct_add_axp;
+ c->idct = simple_idct_axp;
+}
diff --git a/contrib/ffmpeg/libavcodec/alpha/dsputil_alpha_asm.S b/contrib/ffmpeg/libavcodec/alpha/dsputil_alpha_asm.S
new file mode 100644
index 000000000..367f2d743
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/alpha/dsputil_alpha_asm.S
@@ -0,0 +1,285 @@
+/*
+ * Alpha optimized DSP utils
+ * Copyright (c) 2002 Falk Hueffner <falk@debian.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
+ */
+
+/*
+ * 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
+
+#ifdef HAVE_GPROF
+ lda AT, _mcount
+ jsr AT, (AT), _mcount
+#endif
+
+ 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
+
+/************************************************************************
+ * void put_pixels_clamped_mvi_asm(const DCTELEM *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
+
+#ifdef HAVE_GPROF
+ lda AT, _mcount
+ jsr AT, (AT), _mcount
+#endif
+
+ 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 DCTELEM *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
+
+#ifdef HAVE_GPROF
+ lda AT, _mcount
+ jsr AT, (AT), _mcount
+#endif
+
+ 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/contrib/ffmpeg/libavcodec/alpha/motion_est_alpha.c b/contrib/ffmpeg/libavcodec/alpha/motion_est_alpha.c
new file mode 100644
index 000000000..337ffb38e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/alpha/motion_est_alpha.c
@@ -0,0 +1,345 @@
+/*
+ * Alpha optimized DSP utils
+ * Copyright (c) 2002 Falk Hueffner <falk@debian.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
+ */
+
+#include "asm.h"
+#include "../dsputil.h"
+
+void get_pixels_mvi(DCTELEM *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(DCTELEM *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/contrib/ffmpeg/libavcodec/alpha/motion_est_mvi_asm.S b/contrib/ffmpeg/libavcodec/alpha/motion_est_mvi_asm.S
new file mode 100644
index 000000000..6015a7824
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/alpha/motion_est_mvi_asm.S
@@ -0,0 +1,185 @@
+/*
+ * Alpha optimized DSP utils
+ * Copyright (c) 2002 Falk Hueffner <falk@debian.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
+ */
+
+#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
+
+#ifdef HAVE_GPROF
+ lda AT, _mcount
+ jsr AT, (AT), _mcount
+#endif
+
+ and a1, 7, t0
+ clr v0
+ lda a3, 16
+ 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(a1) # left_u
+ ldq_u t1, 8(a1) # mid
+ ldq_u t2, 16(a1) # right_u
+ ldq t3, 0(a0) # ref left
+ ldq t4, 8(a0) # ref right
+ addq a0, a2, a0 # pix1
+ addq a1, a2, a1 # pix2
+ /* load line 1 */
+ ldq_u t5, 0(a1) # left_u
+ ldq_u t6, 8(a1) # mid
+ ldq_u t7, 16(a1) # right_u
+ ldq t8, 0(a0) # ref left
+ ldq t9, 8(a0) # ref right
+ addq a0, a2, a0 # pix1
+ addq a1, a2, a1 # pix2
+ /* calc line 0 */
+ extql t0, a1, t0 # left lo
+ extqh t1, a1, ta # left hi
+ extql t1, a1, tb # right lo
+ or t0, ta, t0 # left
+ extqh t2, a1, 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, a1, t5 # left lo
+ extqh t6, a1, ta # left hi
+ extql t6, a1, tb # right lo
+ or t5, ta, t5 # left
+ extqh t7, a1, 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 a3, 2, a3 # h -= 2
+ bne a3, $unaligned
+ ret
+
+ .align 4
+$aligned:
+ /* load line 0 */
+ ldq t0, 0(a1) # left
+ ldq t1, 8(a1) # right
+ addq a1, a2, a1 # pix2
+ ldq t2, 0(a0) # ref left
+ ldq t3, 8(a0) # ref right
+ addq a0, a2, a0 # pix1
+ /* load line 1 */
+ ldq t4, 0(a1) # left
+ ldq t5, 8(a1) # right
+ addq a1, a2, a1 # pix2
+ ldq t6, 0(a0) # ref left
+ ldq t7, 8(a0) # ref right
+ addq a0, a2, a0 # pix1
+ /* load line 2 */
+ ldq t8, 0(a1) # left
+ ldq t9, 8(a1) # right
+ addq a1, a2, a1 # pix2
+ ldq ta, 0(a0) # ref left
+ ldq tb, 8(a0) # ref right
+ addq a0, a2, a0 # pix1
+ /* load line 3 */
+ ldq tc, 0(a1) # left
+ ldq td, 8(a1) # right
+ addq a1, a2, a1 # pix2
+ ldq te, 0(a0) # ref left
+ ldq tf, 8(a0) # ref right
+ /* calc line 0 */
+ perr t0, t2, t0 # error left
+ addq a0, a2, a0 # 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, tf, t1 # error right
+ addq v0, t0, v0 # add error left
+ addq v0, t1, v0 # add error right
+ /* loop */
+ subq a3, 4, a3 # h -= 4
+ bne a3, $aligned
+ ret
+ .end pix_abs16x16_mvi_asm
diff --git a/contrib/ffmpeg/libavcodec/alpha/mpegvideo_alpha.c b/contrib/ffmpeg/libavcodec/alpha/mpegvideo_alpha.c
new file mode 100644
index 000000000..8ad264b06
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/alpha/mpegvideo_alpha.c
@@ -0,0 +1,147 @@
+/*
+ * Alpha optimized DSP utils
+ * Copyright (c) 2002 Falk Hueffner <falk@debian.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
+ */
+
+#include "asm.h"
+#include "../dsputil.h"
+#include "../mpegvideo.h"
+
+static void dct_unquantize_h263_intra_axp(MpegEncContext *s, DCTELEM *block,
+ int n, int qscale)
+{
+ int i, n_coeffs;
+ uint64_t qmul, qadd;
+ uint64_t correction;
+ DCTELEM *orig_block = block;
+ DCTELEM block0; /* might not be used uninitialized */
+
+ qadd = WORD_VEC((qscale - 1) | 1);
+ qmul = qscale << 1;
+ /* This mask kills spill from negative subwords to the next subword. */
+ correction = WORD_VEC((qmul - 1) + 1); /* multiplication / addition */
+
+ if (!s->h263_aic) {
+ if (n < 4)
+ block0 = block[0] * s->y_dc_scale;
+ else
+ block0 = block[0] * s->c_dc_scale;
+ } else {
+ qadd = 0;
+ }
+ n_coeffs = 63; // does not always use zigzag table
+
+ for(i = 0; i <= n_coeffs; block += 4, i += 4) {
+ uint64_t levels, negmask, zeros, add;
+
+ 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);
+
+ /* Negate qadd for negative levels. */
+ add = qadd ^ negmask;
+ add += WORD_VEC(0x0001) & negmask;
+ /* Set qadd to 0 for levels == 0. */
+ add = zap(add, zeros);
+
+ levels += add;
+
+ stq(levels, block);
+ }
+
+ if (s->mb_intra && !s->h263_aic)
+ orig_block[0] = block0;
+}
+
+static void dct_unquantize_h263_inter_axp(MpegEncContext *s, DCTELEM *block,
+ int n, int qscale)
+{
+ int i, n_coeffs;
+ uint64_t qmul, qadd;
+ uint64_t correction;
+
+ qadd = WORD_VEC((qscale - 1) | 1);
+ qmul = qscale << 1;
+ /* This mask kills spill from negative subwords to the next subword. */
+ correction = WORD_VEC((qmul - 1) + 1); /* multiplication / addition */
+
+ n_coeffs = s->intra_scantable.raster_end[s->block_last_index[n]];
+
+ for(i = 0; i <= n_coeffs; block += 4, i += 4) {
+ uint64_t levels, negmask, zeros, add;
+
+ 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);
+
+ /* Negate qadd for negative levels. */
+ add = qadd ^ negmask;
+ add += WORD_VEC(0x0001) & negmask;
+ /* Set qadd to 0 for levels == 0. */
+ add = zap(add, zeros);
+
+ levels += add;
+
+ stq(levels, block);
+ }
+}
+
+void 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/contrib/ffmpeg/libavcodec/alpha/regdef.h b/contrib/ffmpeg/libavcodec/alpha/regdef.h
new file mode 100644
index 000000000..01e263bac
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/alpha/regdef.h
@@ -0,0 +1,66 @@
+/*
+ * Alpha optimized DSP utils
+ * copyright (c) 2002 Falk Hueffner <falk@debian.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
+ */
+
+/* Some BSDs don't seem to have regdef.h... sigh */
+#ifndef alpha_regdef_h
+#define 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 /* alpha_regdef_h */
diff --git a/contrib/ffmpeg/libavcodec/alpha/simple_idct_alpha.c b/contrib/ffmpeg/libavcodec/alpha/simple_idct_alpha.c
new file mode 100644
index 000000000..adadd3ab0
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/alpha/simple_idct_alpha.c
@@ -0,0 +1,308 @@
+/*
+ * Simple IDCT (Alpha optimized)
+ *
+ * Copyright (c) 2001 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * based upon some outcommented c code from mpeg2dec (idct_mmx.c
+ * written by Aaron Holtzman <aholtzma@ess.engr.uvic.ca>)
+ *
+ * Alpha optimiziations by Måns Rullgård <mru@users.sourceforge.net>
+ * and Falk Hueffner <falk@debian.org>
+ */
+
+#include "asm.h"
+#include "../dsputil.h"
+
+extern void (*put_pixels_clamped_axp_p)(const DCTELEM *block, uint8_t *pixels,
+ int line_size);
+extern void (*add_pixels_clamped_axp_p)(const DCTELEM *block, uint8_t *pixels,
+ int line_size);
+
+// 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 ((int_fast32_t) 22725)
+#define W2 ((int_fast32_t) 21407)
+#define W3 ((int_fast32_t) 19266)
+#define W4 ((int_fast32_t) 16383)
+#define W5 ((int_fast32_t) 12873)
+#define W6 ((int_fast32_t) 8867)
+#define W7 ((int_fast32_t) 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(DCTELEM *row)
+{
+ int_fast32_t 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(DCTELEM *col)
+{
+ int_fast32_t 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(DCTELEM *col)
+{
+ int i;
+ uint64_t l, r;
+
+ for (i = 0; i < 8; ++i) {
+ int_fast32_t 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 simple_idct_axp(DCTELEM *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 simple_idct_put_axp(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ simple_idct_axp(block);
+ put_pixels_clamped_axp_p(block, dest, line_size);
+}
+
+void simple_idct_add_axp(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ simple_idct_axp(block);
+ add_pixels_clamped_axp_p(block, dest, line_size);
+}
diff --git a/contrib/ffmpeg/libavcodec/amr.c b/contrib/ffmpeg/libavcodec/amr.c
new file mode 100644
index 000000000..2d1877b22
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/amr.c
@@ -0,0 +1,715 @@
+/*
+ * 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
+ */
+ /*
+ This code implements amr-nb and amr-wb audio encoder/decoder through external reference
+ code from www.3gpp.org. The licence of the code from 3gpp is unclear so you
+ have to download the code separately. Two versions exists: One fixed-point
+ and one with floats. For some reason the float-encoder is significant faster
+ atleast on a P4 1.5GHz (0.9s instead of 9.9s on a 30s audio clip at MR102).
+ Both float and fixed point is supported for amr-nb, but only float for
+ amr-wb.
+
+ --AMR-NB--
+ The fixed-point (TS26.073) can be downloaded from:
+ http://www.3gpp.org/ftp/Specs/archive/26_series/26.073/26073-510.zip
+ Extract the soure into ffmpeg/libavcodec/amr
+ To use the fixed version run "./configure" with "--enable-amr_nb-fixed"
+
+ The float version (default) can be downloaded from:
+ http://www.3gpp.org/ftp/Specs/archive/26_series/26.104/26104-510.zip
+ Extract the soure into ffmpeg/libavcodec/amr_float
+
+ The specification for amr-nb can be found in TS 26.071
+ (http://www.3gpp.org/ftp/Specs/html-info/26071.htm) and some other
+ info at http://www.3gpp.org/ftp/Specs/html-info/26-series.htm
+
+ --AMR-WB--
+ The reference code can be downloaded from:
+ http://www.3gpp.org/ftp/Specs/archive/26_series/26.204/26204-510.zip
+ It should be extracted to "libavcodec/amrwb_float". Enable it with
+ "--enable-amr_wb".
+
+ The specification for amr-wb can be downloaded from:
+ http://www.3gpp.org/ftp/Specs/archive/26_series/26.171/26171-500.zip
+
+ If someone want to use the fixed point version it can be downloaded
+ from: http://www.3gpp.org/ftp/Specs/archive/26_series/26.173/26173-571.zip
+
+ */
+
+#include "avcodec.h"
+
+#ifdef CONFIG_AMR_NB_FIXED
+
+#define MMS_IO
+
+#include "amr/sp_dec.h"
+#include "amr/d_homing.h"
+#include "amr/typedef.h"
+#include "amr/sp_enc.h"
+#include "amr/sid_sync.h"
+#include "amr/e_homing.h"
+
+#else
+#include "amr_float/interf_dec.h"
+#include "amr_float/interf_enc.h"
+#endif
+
+/* Common code for fixed and float version*/
+typedef struct AMR_bitrates
+{
+ int startrate;
+ int stoprate;
+ enum Mode mode;
+
+} AMR_bitrates;
+
+/* Match desired bitrate with closest one*/
+static enum Mode getBitrateMode(int bitrate)
+{
+ /* Adjusted so that all bitrates can be used from commandline where
+ only a multiple of 1000 can be specified*/
+ AMR_bitrates rates[]={ {0,4999,MR475}, //4
+ {5000,5899,MR515},//5
+ {5900,6699,MR59},//6
+ {6700,7000,MR67},//7
+ {7001,7949,MR74},//8
+ {7950,9999,MR795},//9
+ {10000,11999,MR102},//10
+ {12000,64000,MR122},//12
+
+ };
+ int i;
+ for(i=0;i<8;i++)
+ {
+ if(rates[i].startrate<=bitrate && rates[i].stoprate>=bitrate)
+ {
+ return(rates[i].mode);
+ }
+ }
+ /*Return highest possible*/
+ return(MR122);
+}
+
+static void amr_decode_fix_avctx(AVCodecContext * avctx)
+{
+ const int is_amr_wb = 1 + (avctx->codec_id == CODEC_ID_AMR_WB);
+
+ if(avctx->sample_rate == 0)
+ {
+ avctx->sample_rate = 8000 * is_amr_wb;
+ }
+
+ if(avctx->channels == 0)
+ {
+ avctx->channels = 1;
+ }
+
+ avctx->frame_size = 160 * is_amr_wb;
+}
+
+#ifdef CONFIG_AMR_NB_FIXED
+/* fixed point version*/
+/* frame size in serial bitstream file (frame type + serial stream + flags) */
+#define SERIAL_FRAMESIZE (1+MAX_SERIAL_SIZE+5)
+
+typedef struct AMRContext {
+ int frameCount;
+ Speech_Decode_FrameState *speech_decoder_state;
+ enum RXFrameType rx_type;
+ enum Mode mode;
+ Word16 reset_flag;
+ Word16 reset_flag_old;
+
+ enum Mode enc_bitrate;
+ Speech_Encode_FrameState *enstate;
+ sid_syncState *sidstate;
+ enum TXFrameType tx_frametype;
+
+
+} AMRContext;
+
+static int amr_nb_decode_init(AVCodecContext * avctx)
+{
+ AMRContext *s = avctx->priv_data;
+ s->frameCount=0;
+ s->speech_decoder_state=NULL;
+ s->rx_type = (enum RXFrameType)0;
+ s->mode= (enum Mode)0;
+ s->reset_flag=0;
+ s->reset_flag_old=1;
+
+ if(Speech_Decode_Frame_init(&s->speech_decoder_state, "Decoder"))
+ {
+ av_log(avctx, AV_LOG_ERROR, "Speech_Decode_Frame_init error\n");
+ return -1;
+ }
+
+ amr_decode_fix_avctx(avctx);
+
+ if(avctx->channels > 1)
+ {
+ av_log(avctx, AV_LOG_ERROR, "amr_nb: multichannel decoding not supported\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int amr_nb_encode_init(AVCodecContext * avctx)
+{
+ AMRContext *s = avctx->priv_data;
+ s->frameCount=0;
+ s->speech_decoder_state=NULL;
+ s->rx_type = (enum RXFrameType)0;
+ s->mode= (enum Mode)0;
+ s->reset_flag=0;
+ s->reset_flag_old=1;
+
+ if(avctx->sample_rate!=8000)
+ {
+ if(avctx->debug)
+ {
+ av_log(avctx, AV_LOG_DEBUG, "Only 8000Hz sample rate supported\n");
+ }
+ return -1;
+ }
+
+ if(avctx->channels!=1)
+ {
+ if(avctx->debug)
+ {
+ av_log(avctx, AV_LOG_DEBUG, "Only mono supported\n");
+ }
+ return -1;
+ }
+
+ avctx->frame_size=160;
+ avctx->coded_frame= avcodec_alloc_frame();
+
+ if(Speech_Encode_Frame_init(&s->enstate, 0, "encoder") || sid_sync_init (&s->sidstate))
+ {
+ if(avctx->debug)
+ {
+ av_log(avctx, AV_LOG_DEBUG, "Speech_Encode_Frame_init error\n");
+ }
+ return -1;
+ }
+
+ s->enc_bitrate=getBitrateMode(avctx->bit_rate);
+
+ return 0;
+}
+
+static int amr_nb_encode_close(AVCodecContext * avctx)
+{
+ AMRContext *s = avctx->priv_data;
+ Speech_Encode_Frame_exit(&s->enstate);
+ sid_sync_exit (&s->sidstate);
+ av_freep(&avctx->coded_frame);
+ return 0;
+}
+
+static int amr_nb_decode_close(AVCodecContext * avctx)
+{
+ AMRContext *s = avctx->priv_data;
+ Speech_Decode_Frame_exit(&s->speech_decoder_state);
+ return 0;
+}
+
+static int amr_nb_decode_frame(AVCodecContext * avctx,
+ void *data, int *data_size,
+ uint8_t * buf, int buf_size)
+{
+ AMRContext *s = avctx->priv_data;
+
+ uint8_t*amrData=buf;
+ int offset=0;
+
+ UWord8 toc, q, ft;
+
+ Word16 serial[SERIAL_FRAMESIZE]; /* coded bits */
+ Word16 *synth;
+ UWord8 *packed_bits;
+
+ static Word16 packed_size[16] = {12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0};
+ int i;
+
+ //printf("amr_decode_frame data_size=%i buf=0x%X buf_size=%d frameCount=%d!!\n",*data_size,buf,buf_size,s->frameCount);
+
+ synth=data;
+
+// while(offset<buf_size)
+ {
+ toc=amrData[offset];
+ /* read rest of the frame based on ToC byte */
+ q = (toc >> 2) & 0x01;
+ ft = (toc >> 3) & 0x0F;
+
+ //printf("offset=%d, packet_size=%d amrData= 0x%X %X %X %X\n",offset,packed_size[ft],amrData[offset],amrData[offset+1],amrData[offset+2],amrData[offset+3]);
+
+ offset++;
+
+ packed_bits=amrData+offset;
+
+ offset+=packed_size[ft];
+
+ //Unsort and unpack bits
+ s->rx_type = UnpackBits(q, ft, packed_bits, &s->mode, &serial[1]);
+
+ //We have a new frame
+ s->frameCount++;
+
+ if (s->rx_type == RX_NO_DATA)
+ {
+ s->mode = s->speech_decoder_state->prev_mode;
+ }
+ else {
+ s->speech_decoder_state->prev_mode = s->mode;
+ }
+
+ /* if homed: check if this frame is another homing frame */
+ if (s->reset_flag_old == 1)
+ {
+ /* only check until end of first subframe */
+ s->reset_flag = decoder_homing_frame_test_first(&serial[1], s->mode);
+ }
+ /* produce encoder homing frame if homed & input=decoder homing frame */
+ if ((s->reset_flag != 0) && (s->reset_flag_old != 0))
+ {
+ for (i = 0; i < L_FRAME; i++)
+ {
+ synth[i] = EHF_MASK;
+ }
+ }
+ else
+ {
+ /* decode frame */
+ Speech_Decode_Frame(s->speech_decoder_state, s->mode, &serial[1], s->rx_type, synth);
+ }
+
+ //Each AMR-frame results in 160 16-bit samples
+ *data_size+=160*2;
+ synth+=160;
+
+ /* if not homed: check whether current frame is a homing frame */
+ if (s->reset_flag_old == 0)
+ {
+ /* check whole frame */
+ s->reset_flag = decoder_homing_frame_test(&serial[1], s->mode);
+ }
+ /* reset decoder if current frame is a homing frame */
+ if (s->reset_flag != 0)
+ {
+ Speech_Decode_Frame_reset(s->speech_decoder_state);
+ }
+ s->reset_flag_old = s->reset_flag;
+
+ }
+ return offset;
+}
+
+
+static int amr_nb_encode_frame(AVCodecContext *avctx,
+ unsigned char *frame/*out*/, int buf_size, void *data/*in*/)
+{
+ short serial_data[250] = {0};
+
+ AMRContext *s = avctx->priv_data;
+ int written;
+
+ s->reset_flag = encoder_homing_frame_test(data);
+
+ Speech_Encode_Frame(s->enstate, s->enc_bitrate, data, &serial_data[1], &s->mode);
+
+ /* add frame type and mode */
+ sid_sync (s->sidstate, s->mode, &s->tx_frametype);
+
+ written = PackBits(s->mode, s->enc_bitrate, s->tx_frametype, &serial_data[1], frame);
+
+ if (s->reset_flag != 0)
+ {
+ Speech_Encode_Frame_reset(s->enstate);
+ sid_sync_reset(s->sidstate);
+ }
+ return written;
+}
+
+
+#elif defined(CONFIG_AMR_NB) /* Float point version*/
+
+typedef struct AMRContext {
+ int frameCount;
+ void * decState;
+ int *enstate;
+ enum Mode enc_bitrate;
+} AMRContext;
+
+static int amr_nb_decode_init(AVCodecContext * avctx)
+{
+ AMRContext *s = avctx->priv_data;
+ s->frameCount=0;
+ s->decState=Decoder_Interface_init();
+ if(!s->decState)
+ {
+ av_log(avctx, AV_LOG_ERROR, "Decoder_Interface_init error\r\n");
+ return -1;
+ }
+
+ amr_decode_fix_avctx(avctx);
+
+ if(avctx->channels > 1)
+ {
+ av_log(avctx, AV_LOG_ERROR, "amr_nb: multichannel decoding not supported\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int amr_nb_encode_init(AVCodecContext * avctx)
+{
+ AMRContext *s = avctx->priv_data;
+ s->frameCount=0;
+
+ if(avctx->sample_rate!=8000)
+ {
+ if(avctx->debug)
+ {
+ av_log(avctx, AV_LOG_DEBUG, "Only 8000Hz sample rate supported\n");
+ }
+ return -1;
+ }
+
+ if(avctx->channels!=1)
+ {
+ if(avctx->debug)
+ {
+ av_log(avctx, AV_LOG_DEBUG, "Only mono supported\n");
+ }
+ return -1;
+ }
+
+ avctx->frame_size=160;
+ avctx->coded_frame= avcodec_alloc_frame();
+
+ s->enstate=Encoder_Interface_init(0);
+ if(!s->enstate)
+ {
+ if(avctx->debug)
+ {
+ av_log(avctx, AV_LOG_DEBUG, "Encoder_Interface_init error\n");
+ }
+ return -1;
+ }
+
+ s->enc_bitrate=getBitrateMode(avctx->bit_rate);
+
+ return 0;
+}
+
+static int amr_nb_decode_close(AVCodecContext * avctx)
+{
+ AMRContext *s = avctx->priv_data;
+ Decoder_Interface_exit(s->decState);
+ return 0;
+}
+
+static int amr_nb_encode_close(AVCodecContext * avctx)
+{
+ AMRContext *s = avctx->priv_data;
+ Encoder_Interface_exit(s->enstate);
+ av_freep(&avctx->coded_frame);
+ return 0;
+}
+
+static int amr_nb_decode_frame(AVCodecContext * avctx,
+ void *data, int *data_size,
+ uint8_t * buf, int buf_size)
+{
+ AMRContext *s = (AMRContext*)avctx->priv_data;
+
+ uint8_t*amrData=buf;
+ static short 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;
+
+ /* av_log(NULL,AV_LOG_DEBUG,"amr_decode_frame buf=%p buf_size=%d frameCount=%d!!\n",buf,buf_size,s->frameCount); */
+
+ if(buf_size==0) {
+ /* nothing to do */
+ return 0;
+ }
+
+ 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 -1;
+ }
+
+ s->frameCount++;
+ /* av_log(NULL,AV_LOG_DEBUG,"packet_size=%d amrData= 0x%X %X %X %X\n",packet_size,amrData[0],amrData[1],amrData[2],amrData[3]); */
+ /* call decoder */
+ Decoder_Interface_Decode(s->decState, amrData, data, 0);
+ *data_size=160*2;
+
+ return packet_size;
+}
+
+static int amr_nb_encode_frame(AVCodecContext *avctx,
+ unsigned char *frame/*out*/, int buf_size, void *data/*in*/)
+{
+ AMRContext *s = (AMRContext*)avctx->priv_data;
+ int written;
+
+ s->enc_bitrate=getBitrateMode(avctx->bit_rate);
+
+ written = Encoder_Interface_Encode(s->enstate,
+ s->enc_bitrate,
+ data,
+ frame,
+ 0);
+ /* av_log(NULL,AV_LOG_DEBUG,"amr_nb_encode_frame encoded %u bytes, bitrate %u, first byte was %#02x\n",written, s->enc_bitrate, frame[0] ); */
+
+ return written;
+}
+
+#endif
+
+#if defined(CONFIG_AMR_NB) || defined(CONFIG_AMR_NB_FIXED)
+
+AVCodec amr_nb_decoder =
+{
+ "amr_nb",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_AMR_NB,
+ sizeof(AMRContext),
+ amr_nb_decode_init,
+ NULL,
+ amr_nb_decode_close,
+ amr_nb_decode_frame,
+};
+
+AVCodec amr_nb_encoder =
+{
+ "amr_nb",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_AMR_NB,
+ sizeof(AMRContext),
+ amr_nb_encode_init,
+ amr_nb_encode_frame,
+ amr_nb_encode_close,
+ NULL,
+};
+
+#endif
+
+/* -----------AMR wideband ------------*/
+#ifdef CONFIG_AMR_WB
+
+#ifdef _TYPEDEF_H
+//To avoid duplicate typedefs from typdef in amr-nb
+#define typedef_h
+#endif
+
+#include "amrwb_float/enc_if.h"
+#include "amrwb_float/dec_if.h"
+
+/* Common code for fixed and float version*/
+typedef struct AMRWB_bitrates
+{
+ int startrate;
+ int stoprate;
+ int mode;
+
+} AMRWB_bitrates;
+
+static int getWBBitrateMode(int bitrate)
+{
+ /* Adjusted so that all bitrates can be used from commandline where
+ only a multiple of 1000 can be specified*/
+ AMRWB_bitrates rates[]={ {0,7999,0}, //6.6kHz
+ {8000,9999,1},//8.85
+ {10000,13000,2},//12.65
+ {13001,14999,3},//14.25
+ {15000,17000,4},//15.85
+ {17001,18000,5},//18.25
+ {18001,22000,6},//19.85
+ {22001,23000,7},//23.05
+ {23001,24000,8},//23.85
+
+ };
+ int i;
+
+ for(i=0;i<9;i++)
+ {
+ if(rates[i].startrate<=bitrate && rates[i].stoprate>=bitrate)
+ {
+ return(rates[i].mode);
+ }
+ }
+ /*Return highest possible*/
+ return(8);
+}
+
+
+typedef struct AMRWBContext {
+ int frameCount;
+ void *state;
+ int mode;
+ Word16 allow_dtx;
+} AMRWBContext;
+
+static int amr_wb_encode_init(AVCodecContext * avctx)
+{
+ AMRWBContext *s = (AMRWBContext*)avctx->priv_data;
+ s->frameCount=0;
+
+ if(avctx->sample_rate!=16000)
+ {
+ if(avctx->debug)
+ {
+ av_log(avctx, AV_LOG_DEBUG, "Only 16000Hz sample rate supported\n");
+ }
+ return -1;
+ }
+
+ if(avctx->channels!=1)
+ {
+ if(avctx->debug)
+ {
+ av_log(avctx, AV_LOG_DEBUG, "Only mono supported\n");
+ }
+ return -1;
+ }
+
+ avctx->frame_size=320;
+ avctx->coded_frame= avcodec_alloc_frame();
+
+ s->state = E_IF_init();
+ s->mode=getWBBitrateMode(avctx->bit_rate);
+ s->allow_dtx=0;
+
+ return 0;
+}
+
+static int amr_wb_encode_close(AVCodecContext * avctx)
+{
+ AMRWBContext *s = (AMRWBContext*) avctx->priv_data;
+ E_IF_exit(s->state);
+ av_freep(&avctx->coded_frame);
+ s->frameCount++;
+ return 0;
+}
+
+static int amr_wb_encode_frame(AVCodecContext *avctx,
+ unsigned char *frame/*out*/, int buf_size, void *data/*in*/)
+{
+ AMRWBContext *s;
+ int size;
+ s = (AMRWBContext*) avctx->priv_data;
+ s->mode=getWBBitrateMode(avctx->bit_rate);
+ size = E_IF_encode(s->state, s->mode, data, frame, s->allow_dtx);
+ return size;
+}
+
+static int amr_wb_decode_init(AVCodecContext * avctx)
+{
+ AMRWBContext *s = (AMRWBContext *)avctx->priv_data;
+ s->frameCount=0;
+ s->state = D_IF_init();
+
+ amr_decode_fix_avctx(avctx);
+
+ if(avctx->channels > 1)
+ {
+ av_log(avctx, AV_LOG_ERROR, "amr_wb: multichannel decoding not supported\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+extern const UWord8 block_size[];
+
+static int amr_wb_decode_frame(AVCodecContext * avctx,
+ void *data, int *data_size,
+ uint8_t * buf, int buf_size)
+{
+ AMRWBContext *s = (AMRWBContext*)avctx->priv_data;
+
+ uint8_t*amrData=buf;
+ int mode;
+ int packet_size;
+
+ if(buf_size==0) {
+ /* nothing to do */
+ return 0;
+ }
+
+ mode = (amrData[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 -1;
+ }
+
+ s->frameCount++;
+ D_IF_decode( s->state, amrData, data, _good_frame);
+ *data_size=320*2;
+ return packet_size;
+}
+
+static int amr_wb_decode_close(AVCodecContext * avctx)
+{
+ AMRWBContext *s = (AMRWBContext *)avctx->priv_data;
+ D_IF_exit(s->state);
+ return 0;
+}
+
+AVCodec amr_wb_decoder =
+{
+ "amr_wb",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_AMR_WB,
+ sizeof(AMRWBContext),
+ amr_wb_decode_init,
+ NULL,
+ amr_wb_decode_close,
+ amr_wb_decode_frame,
+};
+
+AVCodec amr_wb_encoder =
+{
+ "amr_wb",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_AMR_WB,
+ sizeof(AMRWBContext),
+ amr_wb_encode_init,
+ amr_wb_encode_frame,
+ amr_wb_encode_close,
+ NULL,
+};
+
+#endif //CONFIG_AMR_WB
diff --git a/contrib/ffmpeg/libavcodec/apiexample.c b/contrib/ffmpeg/libavcodec/apiexample.c
new file mode 100644
index 000000000..484c77876
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/apiexample.c
@@ -0,0 +1,457 @@
+/*
+ * 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 apiexample.c
+ * avcodec API use example.
+ *
+ * Note that this library only handles codecs (mpeg, mpeg4, etc...),
+ * not file formats (avi, vob, etc...). See library 'libavformat' for the
+ * format handling
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#ifdef HAVE_AV_CONFIG_H
+#undef HAVE_AV_CONFIG_H
+#endif
+
+#include "avcodec.h"
+
+#define INBUF_SIZE 4096
+
+/*
+ * Audio encoding example
+ */
+void audio_encode_example(const char *filename)
+{
+ AVCodec *codec;
+ AVCodecContext *c= NULL;
+ int frame_size, i, j, out_size, outbuf_size;
+ FILE *f;
+ short *samples;
+ float t, tincr;
+ uint8_t *outbuf;
+
+ printf("Audio encoding\n");
+
+ /* find the MP2 encoder */
+ codec = avcodec_find_encoder(CODEC_ID_MP2);
+ if (!codec) {
+ fprintf(stderr, "codec not found\n");
+ exit(1);
+ }
+
+ c= avcodec_alloc_context();
+
+ /* put sample parameters */
+ c->bit_rate = 64000;
+ c->sample_rate = 44100;
+ c->channels = 2;
+
+ /* open it */
+ if (avcodec_open(c, codec) < 0) {
+ fprintf(stderr, "could not open codec\n");
+ exit(1);
+ }
+
+ /* the codec gives us the frame size, in samples */
+ frame_size = c->frame_size;
+ samples = malloc(frame_size * 2 * c->channels);
+ outbuf_size = 10000;
+ outbuf = malloc(outbuf_size);
+
+ f = fopen(filename, "wb");
+ if (!f) {
+ fprintf(stderr, "could not open %s\n", filename);
+ exit(1);
+ }
+
+ /* encode a single tone sound */
+ t = 0;
+ tincr = 2 * M_PI * 440.0 / c->sample_rate;
+ for(i=0;i<200;i++) {
+ for(j=0;j<frame_size;j++) {
+ samples[2*j] = (int)(sin(t) * 10000);
+ samples[2*j+1] = samples[2*j];
+ t += tincr;
+ }
+ /* encode the samples */
+ out_size = avcodec_encode_audio(c, outbuf, outbuf_size, samples);
+ fwrite(outbuf, 1, out_size, f);
+ }
+ fclose(f);
+ free(outbuf);
+ free(samples);
+
+ avcodec_close(c);
+ av_free(c);
+}
+
+/*
+ * Audio decoding.
+ */
+void audio_decode_example(const char *outfilename, const char *filename)
+{
+ AVCodec *codec;
+ AVCodecContext *c= NULL;
+ int out_size, size, len;
+ FILE *f, *outfile;
+ uint8_t *outbuf;
+ uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE], *inbuf_ptr;
+
+ printf("Audio decoding\n");
+
+ /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */
+ memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+
+ /* find the mpeg audio decoder */
+ codec = avcodec_find_decoder(CODEC_ID_MP2);
+ if (!codec) {
+ fprintf(stderr, "codec not found\n");
+ exit(1);
+ }
+
+ c= avcodec_alloc_context();
+
+ /* open it */
+ if (avcodec_open(c, codec) < 0) {
+ fprintf(stderr, "could not open codec\n");
+ exit(1);
+ }
+
+ outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
+
+ f = fopen(filename, "rb");
+ if (!f) {
+ fprintf(stderr, "could not open %s\n", filename);
+ exit(1);
+ }
+ outfile = fopen(outfilename, "wb");
+ if (!outfile) {
+ av_free(c);
+ exit(1);
+ }
+
+ /* decode until eof */
+ inbuf_ptr = inbuf;
+ for(;;) {
+ size = fread(inbuf, 1, INBUF_SIZE, f);
+ if (size == 0)
+ break;
+
+ inbuf_ptr = inbuf;
+ while (size > 0) {
+ len = avcodec_decode_audio(c, (short *)outbuf, &out_size,
+ inbuf_ptr, size);
+ if (len < 0) {
+ fprintf(stderr, "Error while decoding\n");
+ exit(1);
+ }
+ if (out_size > 0) {
+ /* if a frame has been decoded, output it */
+ fwrite(outbuf, 1, out_size, outfile);
+ }
+ size -= len;
+ inbuf_ptr += len;
+ }
+ }
+
+ fclose(outfile);
+ fclose(f);
+ free(outbuf);
+
+ avcodec_close(c);
+ av_free(c);
+}
+
+/*
+ * Video encoding example
+ */
+void video_encode_example(const char *filename)
+{
+ AVCodec *codec;
+ AVCodecContext *c= NULL;
+ int i, out_size, size, x, y, outbuf_size;
+ FILE *f;
+ AVFrame *picture;
+ uint8_t *outbuf, *picture_buf;
+
+ printf("Video encoding\n");
+
+ /* find the mpeg1 video encoder */
+ codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO);
+ if (!codec) {
+ fprintf(stderr, "codec not found\n");
+ exit(1);
+ }
+
+ c= avcodec_alloc_context();
+ picture= avcodec_alloc_frame();
+
+ /* put sample parameters */
+ c->bit_rate = 400000;
+ /* resolution must be a multiple of two */
+ c->width = 352;
+ c->height = 288;
+ /* frames per second */
+ c->time_base= (AVRational){1,25};
+ c->gop_size = 10; /* emit one intra frame every ten frames */
+ c->max_b_frames=1;
+ c->pix_fmt = PIX_FMT_YUV420P;
+
+ /* open it */
+ if (avcodec_open(c, codec) < 0) {
+ fprintf(stderr, "could not open codec\n");
+ exit(1);
+ }
+
+ /* the codec gives us the frame size, in samples */
+
+ f = fopen(filename, "wb");
+ if (!f) {
+ fprintf(stderr, "could not open %s\n", filename);
+ exit(1);
+ }
+
+ /* alloc image and output buffer */
+ outbuf_size = 100000;
+ outbuf = malloc(outbuf_size);
+ size = c->width * c->height;
+ picture_buf = malloc((size * 3) / 2); /* size for YUV 420 */
+
+ picture->data[0] = picture_buf;
+ picture->data[1] = picture->data[0] + size;
+ picture->data[2] = picture->data[1] + size / 4;
+ picture->linesize[0] = c->width;
+ picture->linesize[1] = c->width / 2;
+ picture->linesize[2] = c->width / 2;
+
+ /* encode 1 second of video */
+ for(i=0;i<25;i++) {
+ fflush(stdout);
+ /* prepare a dummy image */
+ /* Y */
+ for(y=0;y<c->height;y++) {
+ for(x=0;x<c->width;x++) {
+ picture->data[0][y * picture->linesize[0] + x] = x + y + i * 3;
+ }
+ }
+
+ /* Cb and Cr */
+ for(y=0;y<c->height/2;y++) {
+ for(x=0;x<c->width/2;x++) {
+ picture->data[1][y * picture->linesize[1] + x] = 128 + y + i * 2;
+ picture->data[2][y * picture->linesize[2] + x] = 64 + x + i * 5;
+ }
+ }
+
+ /* encode the image */
+ out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
+ printf("encoding frame %3d (size=%5d)\n", i, out_size);
+ fwrite(outbuf, 1, out_size, f);
+ }
+
+ /* get the delayed frames */
+ for(; out_size; i++) {
+ fflush(stdout);
+
+ out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL);
+ printf("write frame %3d (size=%5d)\n", i, out_size);
+ fwrite(outbuf, 1, out_size, f);
+ }
+
+ /* add sequence end code to have a real mpeg file */
+ outbuf[0] = 0x00;
+ outbuf[1] = 0x00;
+ outbuf[2] = 0x01;
+ outbuf[3] = 0xb7;
+ fwrite(outbuf, 1, 4, f);
+ fclose(f);
+ free(picture_buf);
+ free(outbuf);
+
+ avcodec_close(c);
+ av_free(c);
+ av_free(picture);
+ printf("\n");
+}
+
+/*
+ * Video decoding example
+ */
+
+void pgm_save(unsigned char *buf,int wrap, int xsize,int ysize,char *filename)
+{
+ FILE *f;
+ int i;
+
+ f=fopen(filename,"w");
+ fprintf(f,"P5\n%d %d\n%d\n",xsize,ysize,255);
+ for(i=0;i<ysize;i++)
+ fwrite(buf + i * wrap,1,xsize,f);
+ fclose(f);
+}
+
+void video_decode_example(const char *outfilename, const char *filename)
+{
+ AVCodec *codec;
+ AVCodecContext *c= NULL;
+ int frame, size, got_picture, len;
+ FILE *f;
+ AVFrame *picture;
+ uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE], *inbuf_ptr;
+ char buf[1024];
+
+ /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */
+ memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+
+ printf("Video decoding\n");
+
+ /* find the mpeg1 video decoder */
+ codec = avcodec_find_decoder(CODEC_ID_MPEG1VIDEO);
+ if (!codec) {
+ fprintf(stderr, "codec not found\n");
+ exit(1);
+ }
+
+ c= avcodec_alloc_context();
+ picture= avcodec_alloc_frame();
+
+ if(codec->capabilities&CODEC_CAP_TRUNCATED)
+ c->flags|= CODEC_FLAG_TRUNCATED; /* we dont send complete frames */
+
+ /* for some codecs, such as msmpeg4 and mpeg4, width and height
+ MUST be initialized there because these info are not available
+ in the bitstream */
+
+ /* open it */
+ if (avcodec_open(c, codec) < 0) {
+ fprintf(stderr, "could not open codec\n");
+ exit(1);
+ }
+
+ /* the codec gives us the frame size, in samples */
+
+ f = fopen(filename, "rb");
+ if (!f) {
+ fprintf(stderr, "could not open %s\n", filename);
+ exit(1);
+ }
+
+ frame = 0;
+ for(;;) {
+ size = fread(inbuf, 1, INBUF_SIZE, f);
+ if (size == 0)
+ break;
+
+ /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio)
+ and this is the only method to use them because you cannot
+ know the compressed data size before analysing it.
+
+ BUT some other codecs (msmpeg4, mpeg4) are inherently frame
+ based, so you must call them with all the data for one
+ frame exactly. You must also initialize 'width' and
+ 'height' before initializing them. */
+
+ /* NOTE2: some codecs allow the raw parameters (frame size,
+ sample rate) to be changed at any frame. We handle this, so
+ you should also take care of it */
+
+ /* here, we use a stream based decoder (mpeg1video), so we
+ feed decoder and see if it could decode a frame */
+ inbuf_ptr = inbuf;
+ while (size > 0) {
+ len = avcodec_decode_video(c, picture, &got_picture,
+ inbuf_ptr, size);
+ if (len < 0) {
+ fprintf(stderr, "Error while decoding frame %d\n", frame);
+ exit(1);
+ }
+ if (got_picture) {
+ printf("saving frame %3d\n", frame);
+ fflush(stdout);
+
+ /* the picture is allocated by the decoder. no need to
+ free it */
+ snprintf(buf, sizeof(buf), outfilename, frame);
+ pgm_save(picture->data[0], picture->linesize[0],
+ c->width, c->height, buf);
+ frame++;
+ }
+ size -= len;
+ inbuf_ptr += len;
+ }
+ }
+
+ /* some codecs, such as MPEG, transmit the I and P frame with a
+ latency of one frame. You must do the following to have a
+ chance to get the last frame of the video */
+ len = avcodec_decode_video(c, picture, &got_picture,
+ NULL, 0);
+ if (got_picture) {
+ printf("saving last frame %3d\n", frame);
+ fflush(stdout);
+
+ /* the picture is allocated by the decoder. no need to
+ free it */
+ snprintf(buf, sizeof(buf), outfilename, frame);
+ pgm_save(picture->data[0], picture->linesize[0],
+ c->width, c->height, buf);
+ frame++;
+ }
+
+ fclose(f);
+
+ avcodec_close(c);
+ av_free(c);
+ av_free(picture);
+ printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+ const char *filename;
+
+ /* must be called before using avcodec lib */
+ avcodec_init();
+
+ /* register all the codecs (you can also register only the codec
+ you wish to have smaller code */
+ avcodec_register_all();
+
+ if (argc <= 1) {
+ audio_encode_example("/tmp/test.mp2");
+ audio_decode_example("/tmp/test.sw", "/tmp/test.mp2");
+
+ video_encode_example("/tmp/test.mpg");
+ filename = "/tmp/test.mpg";
+ } else {
+ filename = argv[1];
+ }
+
+ // audio_decode_example("/tmp/test.sw", filename);
+ video_decode_example("/tmp/test%d.pgm", filename);
+
+ return 0;
+}
diff --git a/contrib/ffmpeg/libavcodec/armv4l/dsputil_arm.c b/contrib/ffmpeg/libavcodec/armv4l/dsputil_arm.c
new file mode 100644
index 000000000..9f0bfa2af
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/armv4l/dsputil_arm.c
@@ -0,0 +1,262 @@
+/*
+ * ARMv4L 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 "../dsputil.h"
+#ifdef HAVE_IPP
+#include "ipp.h"
+#endif
+
+extern void dsputil_init_iwmmxt(DSPContext* c, AVCodecContext *avctx);
+
+extern void j_rev_dct_ARM(DCTELEM *data);
+extern void simple_idct_ARM(DCTELEM *data);
+
+extern void simple_idct_armv5te(DCTELEM *data);
+extern void simple_idct_put_armv5te(uint8_t *dest, int line_size,
+ DCTELEM *data);
+extern void simple_idct_add_armv5te(uint8_t *dest, int line_size,
+ DCTELEM *data);
+
+/* XXX: local hack */
+static void (*ff_put_pixels_clamped)(const DCTELEM *block, uint8_t *pixels, int line_size);
+static void (*ff_add_pixels_clamped)(const DCTELEM *block, uint8_t *pixels, int line_size);
+
+void put_pixels8_arm(uint8_t *block, const uint8_t *pixels, int line_size, int h);
+void put_pixels8_x2_arm(uint8_t *block, const uint8_t *pixels, int line_size, int h);
+void put_pixels8_y2_arm(uint8_t *block, const uint8_t *pixels, int line_size, int h);
+void put_pixels8_xy2_arm(uint8_t *block, const uint8_t *pixels, int line_size, int h);
+
+void put_no_rnd_pixels8_x2_arm(uint8_t *block, const uint8_t *pixels, int line_size, int h);
+void put_no_rnd_pixels8_y2_arm(uint8_t *block, const uint8_t *pixels, int line_size, int h);
+void put_no_rnd_pixels8_xy2_arm(uint8_t *block, const uint8_t *pixels, int line_size, int h);
+
+void put_pixels16_arm(uint8_t *block, const uint8_t *pixels, int line_size, int h);
+
+CALL_2X_PIXELS(put_pixels16_x2_arm , put_pixels8_x2_arm , 8)
+CALL_2X_PIXELS(put_pixels16_y2_arm , put_pixels8_y2_arm , 8)
+CALL_2X_PIXELS(put_pixels16_xy2_arm, put_pixels8_xy2_arm, 8)
+CALL_2X_PIXELS(put_no_rnd_pixels16_x2_arm , put_no_rnd_pixels8_x2_arm , 8)
+CALL_2X_PIXELS(put_no_rnd_pixels16_y2_arm , put_no_rnd_pixels8_y2_arm , 8)
+CALL_2X_PIXELS(put_no_rnd_pixels16_xy2_arm, put_no_rnd_pixels8_xy2_arm, 8)
+
+static void add_pixels_clamped_ARM(short *block, unsigned char *dest, int line_size)
+{
+ asm volatile (
+ "mov r10, #8 \n\t"
+
+ "1: \n\t"
+
+ /* load dest */
+ "ldr r4, [%1] \n\t"
+ /* block[0] and block[1]*/
+ "ldrsh r5, [%0] \n\t"
+ "ldrsh r7, [%0, #2] \n\t"
+ "and r6, r4, #0xFF \n\t"
+ "and r8, r4, #0xFF00 \n\t"
+ "add r6, r5, r6 \n\t"
+ "add r8, r7, r8, lsr #8 \n\t"
+ "mvn r5, r5 \n\t"
+ "mvn r7, r7 \n\t"
+ "tst r6, #0x100 \n\t"
+ "movne r6, r5, lsr #24 \n\t"
+ "tst r8, #0x100 \n\t"
+ "movne r8, r7, lsr #24 \n\t"
+ "mov r9, r6 \n\t"
+ "ldrsh r5, [%0, #4] \n\t" /* moved form [A] */
+ "orr r9, r9, r8, lsl #8 \n\t"
+ /* block[2] and block[3] */
+ /* [A] */
+ "ldrsh r7, [%0, #6] \n\t"
+ "and r6, r4, #0xFF0000 \n\t"
+ "and r8, r4, #0xFF000000 \n\t"
+ "add r6, r5, r6, lsr #16 \n\t"
+ "add r8, r7, r8, lsr #24 \n\t"
+ "mvn r5, r5 \n\t"
+ "mvn r7, r7 \n\t"
+ "tst r6, #0x100 \n\t"
+ "movne r6, r5, lsr #24 \n\t"
+ "tst r8, #0x100 \n\t"
+ "movne r8, r7, lsr #24 \n\t"
+ "orr r9, r9, r6, lsl #16 \n\t"
+ "ldr r4, [%1, #4] \n\t" /* moved form [B] */
+ "orr r9, r9, r8, lsl #24 \n\t"
+ /* store dest */
+ "ldrsh r5, [%0, #8] \n\t" /* moved form [C] */
+ "str r9, [%1] \n\t"
+
+ /* load dest */
+ /* [B] */
+ /* block[4] and block[5] */
+ /* [C] */
+ "ldrsh r7, [%0, #10] \n\t"
+ "and r6, r4, #0xFF \n\t"
+ "and r8, r4, #0xFF00 \n\t"
+ "add r6, r5, r6 \n\t"
+ "add r8, r7, r8, lsr #8 \n\t"
+ "mvn r5, r5 \n\t"
+ "mvn r7, r7 \n\t"
+ "tst r6, #0x100 \n\t"
+ "movne r6, r5, lsr #24 \n\t"
+ "tst r8, #0x100 \n\t"
+ "movne r8, r7, lsr #24 \n\t"
+ "mov r9, r6 \n\t"
+ "ldrsh r5, [%0, #12] \n\t" /* moved from [D] */
+ "orr r9, r9, r8, lsl #8 \n\t"
+ /* block[6] and block[7] */
+ /* [D] */
+ "ldrsh r7, [%0, #14] \n\t"
+ "and r6, r4, #0xFF0000 \n\t"
+ "and r8, r4, #0xFF000000 \n\t"
+ "add r6, r5, r6, lsr #16 \n\t"
+ "add r8, r7, r8, lsr #24 \n\t"
+ "mvn r5, r5 \n\t"
+ "mvn r7, r7 \n\t"
+ "tst r6, #0x100 \n\t"
+ "movne r6, r5, lsr #24 \n\t"
+ "tst r8, #0x100 \n\t"
+ "movne r8, r7, lsr #24 \n\t"
+ "orr r9, r9, r6, lsl #16 \n\t"
+ "add %0, %0, #16 \n\t" /* moved from [E] */
+ "orr r9, r9, r8, lsl #24 \n\t"
+ "subs r10, r10, #1 \n\t" /* moved from [F] */
+ /* store dest */
+ "str r9, [%1, #4] \n\t"
+
+ /* [E] */
+ /* [F] */
+ "add %1, %1, %2 \n\t"
+ "bne 1b \n\t"
+ : "+r"(block),
+ "+r"(dest)
+ : "r"(line_size)
+ : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "cc", "memory" );
+}
+
+/* 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, DCTELEM *block)
+{
+ 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, DCTELEM *block)
+{
+ 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, DCTELEM *block)
+{
+ simple_idct_ARM (block);
+ ff_put_pixels_clamped(block, dest, line_size);
+}
+static void simple_idct_ARM_add(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ simple_idct_ARM (block);
+ ff_add_pixels_clamped(block, dest, line_size);
+}
+
+#ifdef HAVE_IPP
+static void simple_idct_ipp(DCTELEM *block)
+{
+ ippiDCT8x8Inv_Video_16s_C1I(block);
+}
+static void simple_idct_ipp_put(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ippiDCT8x8Inv_Video_16s8u_C1R(block, dest, line_size);
+}
+
+void add_pixels_clamped_iwmmxt(const DCTELEM *block, uint8_t *pixels, int line_size);
+
+static void simple_idct_ipp_add(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ippiDCT8x8Inv_Video_16s_C1I(block);
+#ifdef HAVE_IWMMXT
+ add_pixels_clamped_iwmmxt(block, dest, line_size);
+#else
+ add_pixels_clamped_ARM(block, dest, line_size);
+#endif
+}
+#endif
+
+void dsputil_init_armv4l(DSPContext* c, AVCodecContext *avctx)
+{
+ int idct_algo= avctx->idct_algo;
+
+ ff_put_pixels_clamped = c->put_pixels_clamped;
+ ff_add_pixels_clamped = c->add_pixels_clamped;
+
+ if(idct_algo == FF_IDCT_AUTO){
+#if defined(HAVE_IPP)
+ idct_algo = FF_IDCT_IPP;
+#elif defined(HAVE_ARMV5TE)
+ idct_algo = FF_IDCT_SIMPLEARMV5TE;
+#else
+ idct_algo = FF_IDCT_ARM;
+#endif
+ }
+
+ if(idct_algo==FF_IDCT_ARM){
+ c->idct_put= j_rev_dct_ARM_put;
+ c->idct_add= j_rev_dct_ARM_add;
+ c->idct = j_rev_dct_ARM;
+ c->idct_permutation_type= FF_LIBMPEG2_IDCT_PERM;/* FF_NO_IDCT_PERM */
+ } else if (idct_algo==FF_IDCT_SIMPLEARM){
+ c->idct_put= simple_idct_ARM_put;
+ c->idct_add= simple_idct_ARM_add;
+ c->idct = simple_idct_ARM;
+ c->idct_permutation_type= FF_NO_IDCT_PERM;
+#ifdef HAVE_ARMV5TE
+ } else if (idct_algo==FF_IDCT_SIMPLEARMV5TE){
+ c->idct_put= simple_idct_put_armv5te;
+ c->idct_add= simple_idct_add_armv5te;
+ c->idct = simple_idct_armv5te;
+ c->idct_permutation_type = FF_NO_IDCT_PERM;
+#endif
+#ifdef HAVE_IPP
+ } else if (idct_algo==FF_IDCT_IPP){
+ c->idct_put= simple_idct_ipp_put;
+ c->idct_add= simple_idct_ipp_add;
+ c->idct = simple_idct_ipp;
+ c->idct_permutation_type= FF_NO_IDCT_PERM;
+#endif
+ }
+
+/* c->put_pixels_tab[0][0] = put_pixels16_arm; */ // NG!
+ c->put_pixels_tab[0][1] = put_pixels16_x2_arm; //OK!
+ c->put_pixels_tab[0][2] = put_pixels16_y2_arm; //OK!
+/* c->put_pixels_tab[0][3] = put_pixels16_xy2_arm; /\* NG *\/ */
+/* c->put_no_rnd_pixels_tab[0][0] = put_pixels16_arm; */
+ c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_arm; // OK
+ c->put_no_rnd_pixels_tab[0][2] = put_no_rnd_pixels16_y2_arm; //OK
+/* c->put_no_rnd_pixels_tab[0][3] = put_no_rnd_pixels16_xy2_arm; //NG */
+ c->put_pixels_tab[1][0] = put_pixels8_arm; //OK
+ c->put_pixels_tab[1][1] = put_pixels8_x2_arm; //OK
+/* c->put_pixels_tab[1][2] = put_pixels8_y2_arm; //NG */
+/* c->put_pixels_tab[1][3] = put_pixels8_xy2_arm; //NG */
+ c->put_no_rnd_pixels_tab[1][0] = put_pixels8_arm;//OK
+ c->put_no_rnd_pixels_tab[1][1] = put_no_rnd_pixels8_x2_arm; //OK
+ c->put_no_rnd_pixels_tab[1][2] = put_no_rnd_pixels8_y2_arm; //OK
+/* c->put_no_rnd_pixels_tab[1][3] = put_no_rnd_pixels8_xy2_arm;//NG */
+
+#ifdef HAVE_IWMMXT
+ dsputil_init_iwmmxt(c, avctx);
+#endif
+}
diff --git a/contrib/ffmpeg/libavcodec/armv4l/dsputil_arm_s.S b/contrib/ffmpeg/libavcodec/armv4l/dsputil_arm_s.S
new file mode 100644
index 000000000..2a3ee9c50
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/armv4l/dsputil_arm_s.S
@@ -0,0 +1,696 @@
+@
+@ ARMv4L optimized DSP utils
+@ Copyright (c) 2004 AGAWA Koji <i (AT) atty (DOT) jp>
+@
+@ This file is part of FFmpeg.
+@
+@ FFmpeg is free software; you can redistribute it and/or
+@ modify it under the terms of the GNU Lesser General Public
+@ License as published by the Free Software Foundation; either
+@ version 2.1 of the License, or (at your option) any later version.
+@
+@ FFmpeg is distributed in the hope that it will be useful,
+@ but WITHOUT ANY WARRANTY; without even the implied warranty of
+@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+@ Lesser General Public License for more details.
+@
+@ You should have received a copy of the GNU Lesser General Public
+@ License along with FFmpeg; if not, write to the Free Software
+@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+@
+
+.macro ADJ_ALIGN_QUADWORD_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 ADJ_ALIGN_DOUBLEWORD 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 ADJ_ALIGN_DOUBLEWORD_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
+
+@ ----------------------------------------------------------------
+ .align 8
+ .global put_pixels16_arm
+put_pixels16_arm:
+ @ void func(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+ @ block = word aligned, pixles = unaligned
+ pld [r1]
+ stmfd sp!, {r4-r11, lr} @ R14 is also called LR
+ adr r5, 5f
+ ands r4, r1, #3
+ bic r1, r1, #3
+ add r5, r5, r4, lsl #2
+ ldrne pc, [r5]
+1:
+ ldmia r1, {r4-r7}
+ add r1, r1, r2
+ stmia r0, {r4-r7}
+ pld [r1]
+ subs r3, r3, #1
+ add r0, r0, r2
+ bne 1b
+ ldmfd sp!, {r4-r11, pc}
+ .align 8
+2:
+ ldmia r1, {r4-r8}
+ add r1, r1, r2
+ ADJ_ALIGN_QUADWORD_D 1, r9, r10, r11, r12, r4, r5, r6, r7, r8
+ pld [r1]
+ subs r3, r3, #1
+ stmia r0, {r9-r12}
+ add r0, r0, r2
+ bne 2b
+ ldmfd sp!, {r4-r11, pc}
+ .align 8
+3:
+ ldmia r1, {r4-r8}
+ add r1, r1, r2
+ ADJ_ALIGN_QUADWORD_D 2, r9, r10, r11, r12, r4, r5, r6, r7, r8
+ pld [r1]
+ subs r3, r3, #1
+ stmia r0, {r9-r12}
+ add r0, r0, r2
+ bne 3b
+ ldmfd sp!, {r4-r11, pc}
+ .align 8
+4:
+ ldmia r1, {r4-r8}
+ add r1, r1, r2
+ ADJ_ALIGN_QUADWORD_D 3, r9, r10, r11, r12, r4, r5, r6, r7, r8
+ pld [r1]
+ subs r3, r3, #1
+ stmia r0, {r9-r12}
+ add r0, r0, r2
+ bne 4b
+ ldmfd sp!, {r4-r11,pc}
+ .align 8
+5:
+ .word 1b
+ .word 2b
+ .word 3b
+ .word 4b
+
+@ ----------------------------------------------------------------
+ .align 8
+ .global put_pixels8_arm
+put_pixels8_arm:
+ @ void func(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+ @ block = word aligned, pixles = unaligned
+ pld [r1]
+ stmfd sp!, {r4-r5,lr} @ R14 is also called LR
+ adr r5, 5f
+ ands r4, r1, #3
+ bic r1, r1, #3
+ add r5, r5, r4, lsl #2
+ ldrne pc, [r5]
+1:
+ ldmia r1, {r4-r5}
+ add r1, r1, r2
+ subs r3, r3, #1
+ pld [r1]
+ stmia r0, {r4-r5}
+ add r0, r0, r2
+ bne 1b
+ ldmfd sp!, {r4-r5,pc}
+ .align 8
+2:
+ ldmia r1, {r4-r5, r12}
+ add r1, r1, r2
+ ADJ_ALIGN_DOUBLEWORD 1, r4, r5, r12
+ pld [r1]
+ subs r3, r3, #1
+ stmia r0, {r4-r5}
+ add r0, r0, r2
+ bne 2b
+ ldmfd sp!, {r4-r5,pc}
+ .align 8
+3:
+ ldmia r1, {r4-r5, r12}
+ add r1, r1, r2
+ ADJ_ALIGN_DOUBLEWORD 2, r4, r5, r12
+ pld [r1]
+ subs r3, r3, #1
+ stmia r0, {r4-r5}
+ add r0, r0, r2
+ bne 3b
+ ldmfd sp!, {r4-r5,pc}
+ .align 8
+4:
+ ldmia r1, {r4-r5, r12}
+ add r1, r1, r2
+ ADJ_ALIGN_DOUBLEWORD 3, r4, r5, r12
+ pld [r1]
+ subs r3, r3, #1
+ stmia r0, {r4-r5}
+ add r0, r0, r2
+ bne 4b
+ ldmfd sp!, {r4-r5,pc}
+ .align 8
+5:
+ .word 1b
+ .word 2b
+ .word 3b
+ .word 4b
+
+@ ----------------------------------------------------------------
+ .align 8
+ .global put_pixels8_x2_arm
+put_pixels8_x2_arm:
+ @ void func(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+ @ block = word aligned, pixles = unaligned
+ pld [r1]
+ stmfd sp!, {r4-r10,lr} @ R14 is also called LR
+ adr r5, 5f
+ ands r4, r1, #3
+ ldr r12, [r5]
+ add r5, r5, r4, lsl #2
+ bic r1, r1, #3
+ ldrne pc, [r5]
+1:
+ ldmia r1, {r4-r5, r10}
+ add r1, r1, r2
+ ADJ_ALIGN_DOUBLEWORD_D 1, r6, r7, r4, r5, r10
+ pld [r1]
+ RND_AVG32 r8, r9, r4, r5, r6, r7, r12
+ subs r3, r3, #1
+ stmia r0, {r8-r9}
+ add r0, r0, r2
+ bne 1b
+ ldmfd sp!, {r4-r10,pc}
+ .align 8
+2:
+ ldmia r1, {r4-r5, r10}
+ add r1, r1, r2
+ ADJ_ALIGN_DOUBLEWORD_D 1, r6, r7, r4, r5, r10
+ ADJ_ALIGN_DOUBLEWORD_D 2, r8, r9, r4, r5, r10
+ pld [r1]
+ RND_AVG32 r4, r5, r6, r7, r8, r9, r12
+ subs r3, r3, #1
+ stmia r0, {r4-r5}
+ add r0, r0, r2
+ bne 2b
+ ldmfd sp!, {r4-r10,pc}
+ .align 8
+3:
+ ldmia r1, {r4-r5, r10}
+ add r1, r1, r2
+ ADJ_ALIGN_DOUBLEWORD_D 2, r6, r7, r4, r5, r10
+ ADJ_ALIGN_DOUBLEWORD_D 3, r8, r9, r4, r5, r10
+ pld [r1]
+ RND_AVG32 r4, r5, r6, r7, r8, r9, r12
+ subs r3, r3, #1
+ stmia r0, {r4-r5}
+ add r0, r0, r2
+ bne 3b
+ ldmfd sp!, {r4-r10,pc}
+ .align 8
+4:
+ ldmia r1, {r4-r5, r10}
+ add r1, r1, r2
+ ADJ_ALIGN_DOUBLEWORD_D 3, r6, r7, r4, r5, r10
+ pld [r1]
+ RND_AVG32 r8, r9, r6, r7, r5, r10, r12
+ subs r3, r3, #1
+ stmia r0, {r8-r9}
+ add r0, r0, r2
+ bne 4b
+ ldmfd sp!, {r4-r10,pc} @@ update PC with LR content.
+ .align 8
+5:
+ .word 0xFEFEFEFE
+ .word 2b
+ .word 3b
+ .word 4b
+
+ .align 8
+ .global put_no_rnd_pixels8_x2_arm
+put_no_rnd_pixels8_x2_arm:
+ @ void func(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+ @ block = word aligned, pixles = unaligned
+ pld [r1]
+ stmfd sp!, {r4-r10,lr} @ R14 is also called LR
+ adr r5, 5f
+ ands r4, r1, #3
+ ldr r12, [r5]
+ add r5, r5, r4, lsl #2
+ bic r1, r1, #3
+ ldrne pc, [r5]
+1:
+ ldmia r1, {r4-r5, r10}
+ add r1, r1, r2
+ ADJ_ALIGN_DOUBLEWORD_D 1, r6, r7, r4, r5, r10
+ pld [r1]
+ NO_RND_AVG32 r8, r9, r4, r5, r6, r7, r12
+ subs r3, r3, #1
+ stmia r0, {r8-r9}
+ add r0, r0, r2
+ bne 1b
+ ldmfd sp!, {r4-r10,pc}
+ .align 8
+2:
+ ldmia r1, {r4-r5, r10}
+ add r1, r1, r2
+ ADJ_ALIGN_DOUBLEWORD_D 1, r6, r7, r4, r5, r10
+ ADJ_ALIGN_DOUBLEWORD_D 2, r8, r9, r4, r5, r10
+ pld [r1]
+ NO_RND_AVG32 r4, r5, r6, r7, r8, r9, r12
+ subs r3, r3, #1
+ stmia r0, {r4-r5}
+ add r0, r0, r2
+ bne 2b
+ ldmfd sp!, {r4-r10,pc}
+ .align 8
+3:
+ ldmia r1, {r4-r5, r10}
+ add r1, r1, r2
+ ADJ_ALIGN_DOUBLEWORD_D 2, r6, r7, r4, r5, r10
+ ADJ_ALIGN_DOUBLEWORD_D 3, r8, r9, r4, r5, r10
+ pld [r1]
+ NO_RND_AVG32 r4, r5, r6, r7, r8, r9, r12
+ subs r3, r3, #1
+ stmia r0, {r4-r5}
+ add r0, r0, r2
+ bne 3b
+ ldmfd sp!, {r4-r10,pc}
+ .align 8
+4:
+ ldmia r1, {r4-r5, r10}
+ add r1, r1, r2
+ ADJ_ALIGN_DOUBLEWORD_D 3, r6, r7, r4, r5, r10
+ pld [r1]
+ NO_RND_AVG32 r8, r9, r6, r7, r5, r10, r12
+ subs r3, r3, #1
+ stmia r0, {r8-r9}
+ add r0, r0, r2
+ bne 4b
+ ldmfd sp!, {r4-r10,pc} @@ update PC with LR content.
+ .align 8
+5:
+ .word 0xFEFEFEFE
+ .word 2b
+ .word 3b
+ .word 4b
+
+
+@ ----------------------------------------------------------------
+ .align 8
+ .global put_pixels8_y2_arm
+put_pixels8_y2_arm:
+ @ void func(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+ @ block = word aligned, pixles = unaligned
+ pld [r1]
+ stmfd sp!, {r4-r11,lr} @ R14 is also called LR
+ adr r5, 5f
+ ands r4, r1, #3
+ mov r3, r3, lsr #1
+ ldr r12, [r5]
+ add r5, r5, r4, lsl #2
+ bic r1, r1, #3
+ ldrne pc, [r5]
+1:
+ ldmia r1, {r4-r5}
+ add r1, r1, r2
+6: ldmia r1, {r6-r7}
+ add r1, r1, r2
+ pld [r1]
+ RND_AVG32 r8, r9, r4, r5, r6, r7, r12
+ ldmia r1, {r4-r5}
+ add r1, r1, r2
+ stmia r0, {r8-r9}
+ add r0, r0, r2
+ pld [r1]
+ RND_AVG32 r8, r9, r6, r7, r4, r5, r12
+ subs r3, r3, #1
+ stmia r0, {r8-r9}
+ add r0, r0, r2
+ bne 6b
+ ldmfd sp!, {r4-r11,pc}
+ .align 8
+2:
+ ldmia r1, {r4-r6}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 1, r4, r5, r6
+6: ldmia r1, {r7-r9}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 1, r7, r8, r9
+ RND_AVG32 r10, r11, r4, r5, r7, r8, r12
+ stmia r0, {r10-r11}
+ add r0, r0, r2
+ ldmia r1, {r4-r6}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 1, r4, r5, r6
+ subs r3, r3, #1
+ RND_AVG32 r10, r11, r7, r8, r4, r5, r12
+ stmia r0, {r10-r11}
+ add r0, r0, r2
+ bne 6b
+ ldmfd sp!, {r4-r11,pc}
+ .align 8
+3:
+ ldmia r1, {r4-r6}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 2, r4, r5, r6
+6: ldmia r1, {r7-r9}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 2, r7, r8, r9
+ RND_AVG32 r10, r11, r4, r5, r7, r8, r12
+ stmia r0, {r10-r11}
+ add r0, r0, r2
+ ldmia r1, {r4-r6}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 2, r4, r5, r6
+ subs r3, r3, #1
+ RND_AVG32 r10, r11, r7, r8, r4, r5, r12
+ stmia r0, {r10-r11}
+ add r0, r0, r2
+ bne 6b
+ ldmfd sp!, {r4-r11,pc}
+ .align 8
+4:
+ ldmia r1, {r4-r6}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 3, r4, r5, r6
+6: ldmia r1, {r7-r9}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 3, r7, r8, r9
+ RND_AVG32 r10, r11, r4, r5, r7, r8, r12
+ stmia r0, {r10-r11}
+ add r0, r0, r2
+ ldmia r1, {r4-r6}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 3, r4, r5, r6
+ subs r3, r3, #1
+ RND_AVG32 r10, r11, r7, r8, r4, r5, r12
+ stmia r0, {r10-r11}
+ add r0, r0, r2
+ bne 6b
+ ldmfd sp!, {r4-r11,pc}
+
+ .align 8
+5:
+ .word 0xFEFEFEFE
+ .word 2b
+ .word 3b
+ .word 4b
+
+ .align 8
+ .global put_no_rnd_pixels8_y2_arm
+put_no_rnd_pixels8_y2_arm:
+ @ void func(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+ @ block = word aligned, pixles = unaligned
+ pld [r1]
+ stmfd sp!, {r4-r11,lr} @ R14 is also called LR
+ adr r5, 5f
+ ands r4, r1, #3
+ mov r3, r3, lsr #1
+ ldr r12, [r5]
+ add r5, r5, r4, lsl #2
+ bic r1, r1, #3
+ ldrne pc, [r5]
+1:
+ ldmia r1, {r4-r5}
+ add r1, r1, r2
+6: ldmia r1, {r6-r7}
+ add r1, r1, r2
+ pld [r1]
+ NO_RND_AVG32 r8, r9, r4, r5, r6, r7, r12
+ ldmia r1, {r4-r5}
+ add r1, r1, r2
+ stmia r0, {r8-r9}
+ add r0, r0, r2
+ pld [r1]
+ NO_RND_AVG32 r8, r9, r6, r7, r4, r5, r12
+ subs r3, r3, #1
+ stmia r0, {r8-r9}
+ add r0, r0, r2
+ bne 6b
+ ldmfd sp!, {r4-r11,pc}
+ .align 8
+2:
+ ldmia r1, {r4-r6}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 1, r4, r5, r6
+6: ldmia r1, {r7-r9}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 1, r7, r8, r9
+ NO_RND_AVG32 r10, r11, r4, r5, r7, r8, r12
+ stmia r0, {r10-r11}
+ add r0, r0, r2
+ ldmia r1, {r4-r6}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 1, r4, r5, r6
+ subs r3, r3, #1
+ NO_RND_AVG32 r10, r11, r7, r8, r4, r5, r12
+ stmia r0, {r10-r11}
+ add r0, r0, r2
+ bne 6b
+ ldmfd sp!, {r4-r11,pc}
+ .align 8
+3:
+ ldmia r1, {r4-r6}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 2, r4, r5, r6
+6: ldmia r1, {r7-r9}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 2, r7, r8, r9
+ NO_RND_AVG32 r10, r11, r4, r5, r7, r8, r12
+ stmia r0, {r10-r11}
+ add r0, r0, r2
+ ldmia r1, {r4-r6}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 2, r4, r5, r6
+ subs r3, r3, #1
+ NO_RND_AVG32 r10, r11, r7, r8, r4, r5, r12
+ stmia r0, {r10-r11}
+ add r0, r0, r2
+ bne 6b
+ ldmfd sp!, {r4-r11,pc}
+ .align 8
+4:
+ ldmia r1, {r4-r6}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 3, r4, r5, r6
+6: ldmia r1, {r7-r9}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 3, r7, r8, r9
+ NO_RND_AVG32 r10, r11, r4, r5, r7, r8, r12
+ stmia r0, {r10-r11}
+ add r0, r0, r2
+ ldmia r1, {r4-r6}
+ add r1, r1, r2
+ pld [r1]
+ ADJ_ALIGN_DOUBLEWORD 3, r4, r5, r6
+ subs r3, r3, #1
+ NO_RND_AVG32 r10, r11, r7, r8, r4, r5, r12
+ stmia r0, {r10-r11}
+ add r0, r0, r2
+ bne 6b
+ ldmfd sp!, {r4-r11,pc}
+ .align 8
+5:
+ .word 0xFEFEFEFE
+ .word 2b
+ .word 3b
+ .word 4b
+
+@ ----------------------------------------------------------------
+.macro RND_XY2_IT align, rnd
+ @ l1= (a & 0x03030303) + (b & 0x03030303) ?(+ 0x02020202)
+ @ h1= ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2)
+.if \align == 0
+ ldmia r1, {r6-r8}
+.elseif \align == 3
+ ldmia r1, {r5-r7}
+.else
+ ldmia r1, {r8-r10}
+.endif
+ add r1, r1, r2
+ pld [r1]
+.if \align == 0
+ ADJ_ALIGN_DOUBLEWORD_D 1, r4, r5, r6, r7, r8
+.elseif \align == 1
+ ADJ_ALIGN_DOUBLEWORD_D 1, r4, r5, r8, r9, r10
+ ADJ_ALIGN_DOUBLEWORD_D 2, r6, r7, r8, r9, r10
+.elseif \align == 2
+ ADJ_ALIGN_DOUBLEWORD_D 2, r4, r5, r8, r9, r10
+ ADJ_ALIGN_DOUBLEWORD_D 3, r6, r7, r8, r9, r10
+.elseif \align == 3
+ ADJ_ALIGN_DOUBLEWORD_D 3, r4, r5, r5, r6, r7
+.endif
+ ldr r14, [r12, #0] @ 0x03030303
+ tst r3, #1
+ and r8, r4, r14
+ and r9, r5, r14
+ and r10, r6, r14
+ and r11, r7, r14
+.if \rnd == 1
+ ldreq r14, [r12, #16] @ 0x02020202
+.else
+ ldreq r14, [r12, #28] @ 0x01010101
+.endif
+ add r8, r8, r10
+ add r9, r9, r11
+ addeq r8, r8, r14
+ addeq r9, r9, r14
+ ldr r14, [r12, #20] @ 0xFCFCFCFC >> 2
+ and r4, r14, r4, lsr #2
+ and r5, r14, r5, lsr #2
+ and r6, r14, r6, lsr #2
+ and r7, r14, r7, lsr #2
+ add r10, r4, r6
+ add r11, r5, r7
+.endm
+
+.macro RND_XY2_EXPAND align, rnd
+ RND_XY2_IT \align, \rnd
+6: stmfd sp!, {r8-r11}
+ RND_XY2_IT \align, \rnd
+ ldmfd sp!, {r4-r7}
+ add r4, r4, r8
+ add r5, r5, r9
+ add r6, r6, r10
+ add r7, r7, r11
+ ldr r14, [r12, #24] @ 0x0F0F0F0F
+ and r4, r14, r4, lsr #2
+ and r5, r14, r5, lsr #2
+ add r4, r4, r6
+ add r5, r5, r7
+ subs r3, r3, #1
+ stmia r0, {r4-r5}
+ add r0, r0, r2
+ bne 6b
+ ldmfd sp!, {r4-r11,pc}
+.endm
+
+ .align 8
+ .global put_pixels8_xy2_arm
+put_pixels8_xy2_arm:
+ @ void func(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+ @ block = word aligned, pixles = unaligned
+ pld [r1]
+ stmfd sp!, {r4-r11,lr} @ R14 is also called LR
+ adrl r12, 5f
+ ands r4, r1, #3
+ add r5, r12, r4, lsl #2
+ bic r1, r1, #3
+ ldrne pc, [r5]
+1:
+ RND_XY2_EXPAND 0, 1
+
+ .align 8
+2:
+ RND_XY2_EXPAND 1, 1
+
+ .align 8
+3:
+ RND_XY2_EXPAND 2, 1
+
+ .align 8
+4:
+ RND_XY2_EXPAND 3, 1
+
+5:
+ .word 0x03030303
+ .word 2b
+ .word 3b
+ .word 4b
+ .word 0x02020202
+ .word 0xFCFCFCFC >> 2
+ .word 0x0F0F0F0F
+ .word 0x01010101
+
+ .align 8
+ .global put_no_rnd_pixels8_xy2_arm
+put_no_rnd_pixels8_xy2_arm:
+ @ void func(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+ @ block = word aligned, pixles = unaligned
+ pld [r1]
+ stmfd sp!, {r4-r11,lr} @ R14 is also called LR
+ adrl r12, 5f
+ ands r4, r1, #3
+ add r5, r12, r4, lsl #2
+ bic r1, r1, #3
+ ldrne pc, [r5]
+1:
+ RND_XY2_EXPAND 0, 0
+
+ .align 8
+2:
+ RND_XY2_EXPAND 1, 0
+
+ .align 8
+3:
+ RND_XY2_EXPAND 2, 0
+
+ .align 8
+4:
+ RND_XY2_EXPAND 3, 0
+
+5:
+ .word 0x03030303
+ .word 2b
+ .word 3b
+ .word 4b
+ .word 0x02020202
+ .word 0xFCFCFCFC >> 2
+ .word 0x0F0F0F0F
+ .word 0x01010101
diff --git a/contrib/ffmpeg/libavcodec/armv4l/dsputil_iwmmxt.c b/contrib/ffmpeg/libavcodec/armv4l/dsputil_iwmmxt.c
new file mode 100644
index 000000000..d7401e760
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/armv4l/dsputil_iwmmxt.c
@@ -0,0 +1,188 @@
+/*
+ * iWMMXt 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 "../dsputil.h"
+
+#define DEF(x, y) x ## _no_rnd_ ## y ##_iwmmxt
+#define SET_RND(regd) __asm__ __volatile__ ("mov r12, #1 \n\t tbcsth " #regd ", r12":::"r12");
+#define WAVG2B "wavg2b"
+#include "dsputil_iwmmxt_rnd.h"
+#undef DEF
+#undef SET_RND
+#undef WAVG2B
+
+#define DEF(x, y) x ## _ ## y ##_iwmmxt
+#define SET_RND(regd) __asm__ __volatile__ ("mov r12, #2 \n\t tbcsth " #regd ", r12":::"r12");
+#define WAVG2B "wavg2br"
+#include "dsputil_iwmmxt_rnd.h"
+#undef DEF
+#undef SET_RND
+#undef WAVG2BR
+
+// need scheduling
+#define OP(AVG) \
+ asm volatile ( \
+ /* alignment */ \
+ "and r12, %[pixels], #7 \n\t" \
+ "bic %[pixels], %[pixels], #7 \n\t" \
+ "tmcr wcgr1, r12 \n\t" \
+ \
+ "wldrd wr0, [%[pixels]] \n\t" \
+ "wldrd wr1, [%[pixels], #8] \n\t" \
+ "add %[pixels], %[pixels], %[line_size] \n\t" \
+ "walignr1 wr4, wr0, wr1 \n\t" \
+ \
+ "1: \n\t" \
+ \
+ "wldrd wr2, [%[pixels]] \n\t" \
+ "wldrd wr3, [%[pixels], #8] \n\t" \
+ "add %[pixels], %[pixels], %[line_size] \n\t" \
+ "pld [%[pixels]] \n\t" \
+ "walignr1 wr5, wr2, wr3 \n\t" \
+ AVG " wr6, wr4, wr5 \n\t" \
+ "wstrd wr6, [%[block]] \n\t" \
+ "add %[block], %[block], %[line_size] \n\t" \
+ \
+ "wldrd wr0, [%[pixels]] \n\t" \
+ "wldrd wr1, [%[pixels], #8] \n\t" \
+ "add %[pixels], %[pixels], %[line_size] \n\t" \
+ "walignr1 wr4, wr0, wr1 \n\t" \
+ "pld [%[pixels]] \n\t" \
+ AVG " wr6, wr4, wr5 \n\t" \
+ "wstrd wr6, [%[block]] \n\t" \
+ "add %[block], %[block], %[line_size] \n\t" \
+ \
+ "subs %[h], %[h], #2 \n\t" \
+ "bne 1b \n\t" \
+ : [block]"+r"(block), [pixels]"+r"(pixels), [h]"+r"(h) \
+ : [line_size]"r"(line_size) \
+ : "memory", "r12");
+void put_pixels8_y2_iwmmxt(uint8_t *block, const uint8_t *pixels, const int line_size, int h)
+{
+ OP("wavg2br");
+}
+void put_no_rnd_pixels8_y2_iwmmxt(uint8_t *block, const uint8_t *pixels, const int line_size, int h)
+{
+ OP("wavg2b");
+}
+#undef OP
+
+void add_pixels_clamped_iwmmxt(const DCTELEM *block, uint8_t *pixels, int line_size)
+{
+ uint8_t *pixels2 = pixels + line_size;
+
+ __asm__ __volatile__ (
+ "mov r12, #4 \n\t"
+ "1: \n\t"
+ "pld [%[pixels], %[line_size2]] \n\t"
+ "pld [%[pixels2], %[line_size2]] \n\t"
+ "wldrd wr4, [%[pixels]] \n\t"
+ "wldrd wr5, [%[pixels2]] \n\t"
+ "pld [%[block], #32] \n\t"
+ "wunpckelub wr6, wr4 \n\t"
+ "wldrd wr0, [%[block]] \n\t"
+ "wunpckehub wr7, wr4 \n\t"
+ "wldrd wr1, [%[block], #8] \n\t"
+ "wunpckelub wr8, wr5 \n\t"
+ "wldrd wr2, [%[block], #16] \n\t"
+ "wunpckehub wr9, wr5 \n\t"
+ "wldrd wr3, [%[block], #24] \n\t"
+ "add %[block], %[block], #32 \n\t"
+ "waddhss wr10, wr0, wr6 \n\t"
+ "waddhss wr11, wr1, wr7 \n\t"
+ "waddhss wr12, wr2, wr8 \n\t"
+ "waddhss wr13, wr3, wr9 \n\t"
+ "wpackhus wr14, wr10, wr11 \n\t"
+ "wpackhus wr15, wr12, wr13 \n\t"
+ "wstrd wr14, [%[pixels]] \n\t"
+ "add %[pixels], %[pixels], %[line_size2] \n\t"
+ "subs r12, r12, #1 \n\t"
+ "wstrd wr15, [%[pixels2]] \n\t"
+ "add %[pixels2], %[pixels2], %[line_size2] \n\t"
+ "bne 1b \n\t"
+ : [block]"+r"(block), [pixels]"+r"(pixels), [pixels2]"+r"(pixels2)
+ : [line_size2]"r"(line_size << 1)
+ : "cc", "memory", "r12");
+}
+
+static void nop(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ return;
+}
+
+int mm_flags; /* multimedia extension flags */
+
+int mm_support(void)
+{
+ return 0; /* TODO, implement proper detection */
+}
+
+void dsputil_init_iwmmxt(DSPContext* c, AVCodecContext *avctx)
+{
+ mm_flags = mm_support();
+
+ if (avctx->dsp_mask) {
+ if (avctx->dsp_mask & FF_MM_FORCE)
+ mm_flags |= (avctx->dsp_mask & 0xffff);
+ else
+ mm_flags &= ~(avctx->dsp_mask & 0xffff);
+ }
+
+ if (!(mm_flags & MM_IWMMXT)) return;
+
+ c->add_pixels_clamped = add_pixels_clamped_iwmmxt;
+
+ c->put_pixels_tab[0][0] = put_pixels16_iwmmxt;
+ c->put_pixels_tab[0][1] = put_pixels16_x2_iwmmxt;
+ c->put_pixels_tab[0][2] = put_pixels16_y2_iwmmxt;
+ c->put_pixels_tab[0][3] = put_pixels16_xy2_iwmmxt;
+ c->put_no_rnd_pixels_tab[0][0] = put_pixels16_iwmmxt;
+ c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_iwmmxt;
+ c->put_no_rnd_pixels_tab[0][2] = put_no_rnd_pixels16_y2_iwmmxt;
+ c->put_no_rnd_pixels_tab[0][3] = put_no_rnd_pixels16_xy2_iwmmxt;
+
+ c->put_pixels_tab[1][0] = put_pixels8_iwmmxt;
+ c->put_pixels_tab[1][1] = put_pixels8_x2_iwmmxt;
+ c->put_pixels_tab[1][2] = put_pixels8_y2_iwmmxt;
+ c->put_pixels_tab[1][3] = put_pixels8_xy2_iwmmxt;
+ c->put_no_rnd_pixels_tab[1][0] = put_pixels8_iwmmxt;
+ c->put_no_rnd_pixels_tab[1][1] = put_no_rnd_pixels8_x2_iwmmxt;
+ c->put_no_rnd_pixels_tab[1][2] = put_no_rnd_pixels8_y2_iwmmxt;
+ c->put_no_rnd_pixels_tab[1][3] = put_no_rnd_pixels8_xy2_iwmmxt;
+
+ c->avg_pixels_tab[0][0] = avg_pixels16_iwmmxt;
+ c->avg_pixels_tab[0][1] = avg_pixels16_x2_iwmmxt;
+ c->avg_pixels_tab[0][2] = avg_pixels16_y2_iwmmxt;
+ c->avg_pixels_tab[0][3] = avg_pixels16_xy2_iwmmxt;
+ c->avg_no_rnd_pixels_tab[0][0] = avg_pixels16_iwmmxt;
+ c->avg_no_rnd_pixels_tab[0][1] = avg_no_rnd_pixels16_x2_iwmmxt;
+ c->avg_no_rnd_pixels_tab[0][2] = avg_no_rnd_pixels16_y2_iwmmxt;
+ c->avg_no_rnd_pixels_tab[0][3] = avg_no_rnd_pixels16_xy2_iwmmxt;
+
+ c->avg_pixels_tab[1][0] = avg_pixels8_iwmmxt;
+ c->avg_pixels_tab[1][1] = avg_pixels8_x2_iwmmxt;
+ c->avg_pixels_tab[1][2] = avg_pixels8_y2_iwmmxt;
+ c->avg_pixels_tab[1][3] = avg_pixels8_xy2_iwmmxt;
+ c->avg_no_rnd_pixels_tab[1][0] = avg_no_rnd_pixels8_iwmmxt;
+ c->avg_no_rnd_pixels_tab[1][1] = avg_no_rnd_pixels8_x2_iwmmxt;
+ c->avg_no_rnd_pixels_tab[1][2] = avg_no_rnd_pixels8_y2_iwmmxt;
+ c->avg_no_rnd_pixels_tab[1][3] = avg_no_rnd_pixels8_xy2_iwmmxt;
+}
diff --git a/contrib/ffmpeg/libavcodec/armv4l/dsputil_iwmmxt_rnd.h b/contrib/ffmpeg/libavcodec/armv4l/dsputil_iwmmxt_rnd.h
new file mode 100644
index 000000000..51ba61c47
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/armv4l/dsputil_iwmmxt_rnd.h
@@ -0,0 +1,1114 @@
+/*
+ * iWMMXt 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
+ */
+
+void DEF(put, pixels8)(uint8_t *block, const uint8_t *pixels, const int line_size, int h)
+{
+ int stride = line_size;
+ __asm__ __volatile__ (
+ "and r12, %[pixels], #7 \n\t"
+ "bic %[pixels], %[pixels], #7 \n\t"
+ "tmcr wcgr1, r12 \n\t"
+ "add r4, %[pixels], %[line_size] \n\t"
+ "add r5, %[block], %[line_size] \n\t"
+ "mov %[line_size], %[line_size], lsl #1 \n\t"
+ "1: \n\t"
+ "wldrd wr0, [%[pixels]] \n\t"
+ "subs %[h], %[h], #2 \n\t"
+ "wldrd wr1, [%[pixels], #8] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "wldrd wr3, [r4] \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "wldrd wr4, [r4, #8] \n\t"
+ "add r4, r4, %[line_size] \n\t"
+ "walignr1 wr8, wr0, wr1 \n\t"
+ "pld [r4] \n\t"
+ "pld [r4, #32] \n\t"
+ "walignr1 wr10, wr3, wr4 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+ "wstrd wr10, [r5] \n\t"
+ "add r5, r5, %[line_size] \n\t"
+ "bne 1b \n\t"
+ : [block]"+r"(block), [pixels]"+r"(pixels), [line_size]"+r"(stride), [h]"+r"(h)
+ :
+ : "memory", "r4", "r5", "r12");
+}
+
+void DEF(avg, pixels8)(uint8_t *block, const uint8_t *pixels, const int line_size, int h)
+{
+ int stride = line_size;
+ __asm__ __volatile__ (
+ "and r12, %[pixels], #7 \n\t"
+ "bic %[pixels], %[pixels], #7 \n\t"
+ "tmcr wcgr1, r12 \n\t"
+ "add r4, %[pixels], %[line_size] \n\t"
+ "add r5, %[block], %[line_size] \n\t"
+ "mov %[line_size], %[line_size], lsl #1 \n\t"
+ "1: \n\t"
+ "wldrd wr0, [%[pixels]] \n\t"
+ "subs %[h], %[h], #2 \n\t"
+ "wldrd wr1, [%[pixels], #8] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "wldrd wr3, [r4] \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "wldrd wr4, [r4, #8] \n\t"
+ "add r4, r4, %[line_size] \n\t"
+ "walignr1 wr8, wr0, wr1 \n\t"
+ "wldrd wr0, [%[block]] \n\t"
+ "wldrd wr2, [r5] \n\t"
+ "pld [r4] \n\t"
+ "pld [r4, #32] \n\t"
+ "walignr1 wr10, wr3, wr4 \n\t"
+ WAVG2B" wr8, wr8, wr0 \n\t"
+ WAVG2B" wr10, wr10, wr2 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+ "wstrd wr10, [r5] \n\t"
+ "pld [%[block]] \n\t"
+ "pld [%[block], #32] \n\t"
+ "add r5, r5, %[line_size] \n\t"
+ "pld [r5] \n\t"
+ "pld [r5, #32] \n\t"
+ "bne 1b \n\t"
+ : [block]"+r"(block), [pixels]"+r"(pixels), [line_size]"+r"(stride), [h]"+r"(h)
+ :
+ : "memory", "r4", "r5", "r12");
+}
+
+void DEF(put, pixels16)(uint8_t *block, const uint8_t *pixels, const int line_size, int h)
+{
+ int stride = line_size;
+ __asm__ __volatile__ (
+ "and r12, %[pixels], #7 \n\t"
+ "bic %[pixels], %[pixels], #7 \n\t"
+ "tmcr wcgr1, r12 \n\t"
+ "add r4, %[pixels], %[line_size] \n\t"
+ "add r5, %[block], %[line_size] \n\t"
+ "mov %[line_size], %[line_size], lsl #1 \n\t"
+ "1: \n\t"
+ "wldrd wr0, [%[pixels]] \n\t"
+ "wldrd wr1, [%[pixels], #8] \n\t"
+ "subs %[h], %[h], #2 \n\t"
+ "wldrd wr2, [%[pixels], #16] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "wldrd wr3, [r4] \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr8, wr0, wr1 \n\t"
+ "wldrd wr4, [r4, #8] \n\t"
+ "walignr1 wr9, wr1, wr2 \n\t"
+ "wldrd wr5, [r4, #16] \n\t"
+ "add r4, r4, %[line_size] \n\t"
+ "pld [r4] \n\t"
+ "pld [r4, #32] \n\t"
+ "walignr1 wr10, wr3, wr4 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "walignr1 wr11, wr4, wr5 \n\t"
+ "wstrd wr9, [%[block], #8] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+ "wstrd wr10, [r5] \n\t"
+ "wstrd wr11, [r5, #8] \n\t"
+ "add r5, r5, %[line_size] \n\t"
+ "bne 1b \n\t"
+ : [block]"+r"(block), [pixels]"+r"(pixels), [line_size]"+r"(stride), [h]"+r"(h)
+ :
+ : "memory", "r4", "r5", "r12");
+}
+
+void DEF(avg, pixels16)(uint8_t *block, const uint8_t *pixels, const int line_size, int h)
+{
+ int stride = line_size;
+ __asm__ __volatile__ (
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "pld [%[block]] \n\t"
+ "pld [%[block], #32] \n\t"
+ "and r12, %[pixels], #7 \n\t"
+ "bic %[pixels], %[pixels], #7 \n\t"
+ "tmcr wcgr1, r12 \n\t"
+ "add r4, %[pixels], %[line_size]\n\t"
+ "add r5, %[block], %[line_size] \n\t"
+ "mov %[line_size], %[line_size], lsl #1 \n\t"
+ "1: \n\t"
+ "wldrd wr0, [%[pixels]] \n\t"
+ "wldrd wr1, [%[pixels], #8] \n\t"
+ "subs %[h], %[h], #2 \n\t"
+ "wldrd wr2, [%[pixels], #16] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "wldrd wr3, [r4] \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr8, wr0, wr1 \n\t"
+ "wldrd wr4, [r4, #8] \n\t"
+ "walignr1 wr9, wr1, wr2 \n\t"
+ "wldrd wr5, [r4, #16] \n\t"
+ "add r4, r4, %[line_size] \n\t"
+ "wldrd wr0, [%[block]] \n\t"
+ "pld [r4] \n\t"
+ "wldrd wr1, [%[block], #8] \n\t"
+ "pld [r4, #32] \n\t"
+ "wldrd wr2, [r5] \n\t"
+ "walignr1 wr10, wr3, wr4 \n\t"
+ "wldrd wr3, [r5, #8] \n\t"
+ WAVG2B" wr8, wr8, wr0 \n\t"
+ WAVG2B" wr9, wr9, wr1 \n\t"
+ WAVG2B" wr10, wr10, wr2 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "walignr1 wr11, wr4, wr5 \n\t"
+ WAVG2B" wr11, wr11, wr3 \n\t"
+ "wstrd wr9, [%[block], #8] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+ "wstrd wr10, [r5] \n\t"
+ "pld [%[block]] \n\t"
+ "pld [%[block], #32] \n\t"
+ "wstrd wr11, [r5, #8] \n\t"
+ "add r5, r5, %[line_size] \n\t"
+ "pld [r5] \n\t"
+ "pld [r5, #32] \n\t"
+ "bne 1b \n\t"
+ : [block]"+r"(block), [pixels]"+r"(pixels), [line_size]"+r"(stride), [h]"+r"(h)
+ :
+ : "memory", "r4", "r5", "r12");
+}
+
+void DEF(put, pixels8_x2)(uint8_t *block, const uint8_t *pixels, const int line_size, int h)
+{
+ int stride = line_size;
+ // [wr0 wr1 wr2 wr3] for previous line
+ // [wr4 wr5 wr6 wr7] for current line
+ SET_RND(wr15); // =2 for rnd and =1 for no_rnd version
+ __asm__ __volatile__(
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "and r12, %[pixels], #7 \n\t"
+ "bic %[pixels], %[pixels], #7 \n\t"
+ "tmcr wcgr1, r12 \n\t"
+ "add r12, r12, #1 \n\t"
+ "add r4, %[pixels], %[line_size]\n\t"
+ "tmcr wcgr2, r12 \n\t"
+ "add r5, %[block], %[line_size] \n\t"
+ "mov %[line_size], %[line_size], lsl #1 \n\t"
+
+ "1: \n\t"
+ "wldrd wr10, [%[pixels]] \n\t"
+ "cmp r12, #8 \n\t"
+ "wldrd wr11, [%[pixels], #8] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "wldrd wr13, [r4] \n\t"
+ "pld [%[pixels]] \n\t"
+ "wldrd wr14, [r4, #8] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "add r4, r4, %[line_size] \n\t"
+ "walignr1 wr0, wr10, wr11 \n\t"
+ "pld [r4] \n\t"
+ "pld [r4, #32] \n\t"
+ "walignr1 wr2, wr13, wr14 \n\t"
+ "wmoveq wr4, wr11 \n\t"
+ "wmoveq wr6, wr14 \n\t"
+ "walignr2ne wr4, wr10, wr11 \n\t"
+ "walignr2ne wr6, wr13, wr14 \n\t"
+ WAVG2B" wr0, wr0, wr4 \n\t"
+ WAVG2B" wr2, wr2, wr6 \n\t"
+ "wstrd wr0, [%[block]] \n\t"
+ "subs %[h], %[h], #2 \n\t"
+ "wstrd wr2, [r5] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+ "add r5, r5, %[line_size] \n\t"
+ "bne 1b \n\t"
+ : [h]"+r"(h), [pixels]"+r"(pixels), [block]"+r"(block), [line_size]"+r"(stride)
+ :
+ : "r4", "r5", "r12", "memory");
+}
+
+void DEF(put, pixels16_x2)(uint8_t *block, const uint8_t *pixels, const int line_size, int h)
+{
+ int stride = line_size;
+ // [wr0 wr1 wr2 wr3] for previous line
+ // [wr4 wr5 wr6 wr7] for current line
+ SET_RND(wr15); // =2 for rnd and =1 for no_rnd version
+ __asm__ __volatile__(
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "and r12, %[pixels], #7 \n\t"
+ "bic %[pixels], %[pixels], #7 \n\t"
+ "tmcr wcgr1, r12 \n\t"
+ "add r12, r12, #1 \n\t"
+ "add r4, %[pixels], %[line_size]\n\t"
+ "tmcr wcgr2, r12 \n\t"
+ "add r5, %[block], %[line_size] \n\t"
+ "mov %[line_size], %[line_size], lsl #1 \n\t"
+
+ "1: \n\t"
+ "wldrd wr10, [%[pixels]] \n\t"
+ "cmp r12, #8 \n\t"
+ "wldrd wr11, [%[pixels], #8] \n\t"
+ "wldrd wr12, [%[pixels], #16] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "wldrd wr13, [r4] \n\t"
+ "pld [%[pixels]] \n\t"
+ "wldrd wr14, [r4, #8] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "wldrd wr15, [r4, #16] \n\t"
+ "add r4, r4, %[line_size] \n\t"
+ "walignr1 wr0, wr10, wr11 \n\t"
+ "pld [r4] \n\t"
+ "pld [r4, #32] \n\t"
+ "walignr1 wr1, wr11, wr12 \n\t"
+ "walignr1 wr2, wr13, wr14 \n\t"
+ "walignr1 wr3, wr14, wr15 \n\t"
+ "wmoveq wr4, wr11 \n\t"
+ "wmoveq wr5, wr12 \n\t"
+ "wmoveq wr6, wr14 \n\t"
+ "wmoveq wr7, wr15 \n\t"
+ "walignr2ne wr4, wr10, wr11 \n\t"
+ "walignr2ne wr5, wr11, wr12 \n\t"
+ "walignr2ne wr6, wr13, wr14 \n\t"
+ "walignr2ne wr7, wr14, wr15 \n\t"
+ WAVG2B" wr0, wr0, wr4 \n\t"
+ WAVG2B" wr1, wr1, wr5 \n\t"
+ "wstrd wr0, [%[block]] \n\t"
+ WAVG2B" wr2, wr2, wr6 \n\t"
+ "wstrd wr1, [%[block], #8] \n\t"
+ WAVG2B" wr3, wr3, wr7 \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+ "wstrd wr2, [r5] \n\t"
+ "subs %[h], %[h], #2 \n\t"
+ "wstrd wr3, [r5, #8] \n\t"
+ "add r5, r5, %[line_size] \n\t"
+ "bne 1b \n\t"
+ : [h]"+r"(h), [pixels]"+r"(pixels), [block]"+r"(block), [line_size]"+r"(stride)
+ :
+ : "r4", "r5", "r12", "memory");
+}
+
+void DEF(avg, pixels8_x2)(uint8_t *block, const uint8_t *pixels, const int line_size, int h)
+{
+ int stride = line_size;
+ // [wr0 wr1 wr2 wr3] for previous line
+ // [wr4 wr5 wr6 wr7] for current line
+ SET_RND(wr15); // =2 for rnd and =1 for no_rnd version
+ __asm__ __volatile__(
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "pld [%[block]] \n\t"
+ "pld [%[block], #32] \n\t"
+ "and r12, %[pixels], #7 \n\t"
+ "bic %[pixels], %[pixels], #7 \n\t"
+ "tmcr wcgr1, r12 \n\t"
+ "add r12, r12, #1 \n\t"
+ "add r4, %[pixels], %[line_size]\n\t"
+ "tmcr wcgr2, r12 \n\t"
+ "add r5, %[block], %[line_size] \n\t"
+ "mov %[line_size], %[line_size], lsl #1 \n\t"
+ "pld [r5] \n\t"
+ "pld [r5, #32] \n\t"
+
+ "1: \n\t"
+ "wldrd wr10, [%[pixels]] \n\t"
+ "cmp r12, #8 \n\t"
+ "wldrd wr11, [%[pixels], #8] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "wldrd wr13, [r4] \n\t"
+ "pld [%[pixels]] \n\t"
+ "wldrd wr14, [r4, #8] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "add r4, r4, %[line_size] \n\t"
+ "walignr1 wr0, wr10, wr11 \n\t"
+ "pld [r4] \n\t"
+ "pld [r4, #32] \n\t"
+ "walignr1 wr2, wr13, wr14 \n\t"
+ "wmoveq wr4, wr11 \n\t"
+ "wmoveq wr6, wr14 \n\t"
+ "walignr2ne wr4, wr10, wr11 \n\t"
+ "wldrd wr10, [%[block]] \n\t"
+ "walignr2ne wr6, wr13, wr14 \n\t"
+ "wldrd wr12, [r5] \n\t"
+ WAVG2B" wr0, wr0, wr4 \n\t"
+ WAVG2B" wr2, wr2, wr6 \n\t"
+ WAVG2B" wr0, wr0, wr10 \n\t"
+ WAVG2B" wr2, wr2, wr12 \n\t"
+ "wstrd wr0, [%[block]] \n\t"
+ "subs %[h], %[h], #2 \n\t"
+ "wstrd wr2, [r5] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+ "add r5, r5, %[line_size] \n\t"
+ "pld [%[block]] \n\t"
+ "pld [%[block], #32] \n\t"
+ "pld [r5] \n\t"
+ "pld [r5, #32] \n\t"
+ "bne 1b \n\t"
+ : [h]"+r"(h), [pixels]"+r"(pixels), [block]"+r"(block), [line_size]"+r"(stride)
+ :
+ : "r4", "r5", "r12", "memory");
+}
+
+void DEF(avg, pixels16_x2)(uint8_t *block, const uint8_t *pixels, const int line_size, int h)
+{
+ int stride = line_size;
+ // [wr0 wr1 wr2 wr3] for previous line
+ // [wr4 wr5 wr6 wr7] for current line
+ SET_RND(wr15); // =2 for rnd and =1 for no_rnd version
+ __asm__ __volatile__(
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "pld [%[block]] \n\t"
+ "pld [%[block], #32] \n\t"
+ "and r12, %[pixels], #7 \n\t"
+ "bic %[pixels], %[pixels], #7 \n\t"
+ "tmcr wcgr1, r12 \n\t"
+ "add r12, r12, #1 \n\t"
+ "add r4, %[pixels], %[line_size]\n\t"
+ "tmcr wcgr2, r12 \n\t"
+ "add r5, %[block], %[line_size] \n\t"
+ "mov %[line_size], %[line_size], lsl #1 \n\t"
+ "pld [r5] \n\t"
+ "pld [r5, #32] \n\t"
+
+ "1: \n\t"
+ "wldrd wr10, [%[pixels]] \n\t"
+ "cmp r12, #8 \n\t"
+ "wldrd wr11, [%[pixels], #8] \n\t"
+ "wldrd wr12, [%[pixels], #16] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "wldrd wr13, [r4] \n\t"
+ "pld [%[pixels]] \n\t"
+ "wldrd wr14, [r4, #8] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "wldrd wr15, [r4, #16] \n\t"
+ "add r4, r4, %[line_size] \n\t"
+ "walignr1 wr0, wr10, wr11 \n\t"
+ "pld [r4] \n\t"
+ "pld [r4, #32] \n\t"
+ "walignr1 wr1, wr11, wr12 \n\t"
+ "walignr1 wr2, wr13, wr14 \n\t"
+ "walignr1 wr3, wr14, wr15 \n\t"
+ "wmoveq wr4, wr11 \n\t"
+ "wmoveq wr5, wr12 \n\t"
+ "wmoveq wr6, wr14 \n\t"
+ "wmoveq wr7, wr15 \n\t"
+ "walignr2ne wr4, wr10, wr11 \n\t"
+ "walignr2ne wr5, wr11, wr12 \n\t"
+ "walignr2ne wr6, wr13, wr14 \n\t"
+ "walignr2ne wr7, wr14, wr15 \n\t"
+ "wldrd wr10, [%[block]] \n\t"
+ WAVG2B" wr0, wr0, wr4 \n\t"
+ "wldrd wr11, [%[block], #8] \n\t"
+ WAVG2B" wr1, wr1, wr5 \n\t"
+ "wldrd wr12, [r5] \n\t"
+ WAVG2B" wr2, wr2, wr6 \n\t"
+ "wldrd wr13, [r5, #8] \n\t"
+ WAVG2B" wr3, wr3, wr7 \n\t"
+ WAVG2B" wr0, wr0, wr10 \n\t"
+ WAVG2B" wr1, wr1, wr11 \n\t"
+ WAVG2B" wr2, wr2, wr12 \n\t"
+ WAVG2B" wr3, wr3, wr13 \n\t"
+ "wstrd wr0, [%[block]] \n\t"
+ "subs %[h], %[h], #2 \n\t"
+ "wstrd wr1, [%[block], #8] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+ "wstrd wr2, [r5] \n\t"
+ "pld [%[block]] \n\t"
+ "wstrd wr3, [r5, #8] \n\t"
+ "add r5, r5, %[line_size] \n\t"
+ "pld [%[block], #32] \n\t"
+ "pld [r5] \n\t"
+ "pld [r5, #32] \n\t"
+ "bne 1b \n\t"
+ : [h]"+r"(h), [pixels]"+r"(pixels), [block]"+r"(block), [line_size]"+r"(stride)
+ :
+ :"r4", "r5", "r12", "memory");
+}
+
+void DEF(avg, pixels8_y2)(uint8_t *block, const uint8_t *pixels, const int line_size, int h)
+{
+ int stride = line_size;
+ // [wr0 wr1 wr2 wr3] for previous line
+ // [wr4 wr5 wr6 wr7] for current line
+ __asm__ __volatile__(
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "and r12, %[pixels], #7 \n\t"
+ "tmcr wcgr1, r12 \n\t"
+ "bic %[pixels], %[pixels], #7 \n\t"
+
+ "wldrd wr10, [%[pixels]] \n\t"
+ "wldrd wr11, [%[pixels], #8] \n\t"
+ "pld [%[block]] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "walignr1 wr0, wr10, wr11 \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+
+ "1: \n\t"
+ "wldrd wr10, [%[pixels]] \n\t"
+ "wldrd wr11, [%[pixels], #8] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr4, wr10, wr11 \n\t"
+ "wldrd wr10, [%[block]] \n\t"
+ WAVG2B" wr8, wr0, wr4 \n\t"
+ WAVG2B" wr8, wr8, wr10 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+
+ "wldrd wr10, [%[pixels]] \n\t"
+ "wldrd wr11, [%[pixels], #8] \n\t"
+ "pld [%[block]] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr0, wr10, wr11 \n\t"
+ "wldrd wr10, [%[block]] \n\t"
+ WAVG2B" wr8, wr0, wr4 \n\t"
+ WAVG2B" wr8, wr8, wr10 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+
+ "subs %[h], %[h], #2 \n\t"
+ "pld [%[block]] \n\t"
+ "bne 1b \n\t"
+ : [h]"+r"(h), [pixels]"+r"(pixels), [block]"+r"(block), [line_size]"+r"(stride)
+ :
+ : "cc", "memory", "r12");
+}
+
+void DEF(put, pixels16_y2)(uint8_t *block, const uint8_t *pixels, const int line_size, int h)
+{
+ int stride = line_size;
+ // [wr0 wr1 wr2 wr3] for previous line
+ // [wr4 wr5 wr6 wr7] for current line
+ __asm__ __volatile__(
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "and r12, %[pixels], #7 \n\t"
+ "tmcr wcgr1, r12 \n\t"
+ "bic %[pixels], %[pixels], #7 \n\t"
+
+ "wldrd wr10, [%[pixels]] \n\t"
+ "wldrd wr11, [%[pixels], #8] \n\t"
+ "wldrd wr12, [%[pixels], #16] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr0, wr10, wr11 \n\t"
+ "walignr1 wr1, wr11, wr12 \n\t"
+
+ "1: \n\t"
+ "wldrd wr10, [%[pixels]] \n\t"
+ "wldrd wr11, [%[pixels], #8] \n\t"
+ "wldrd wr12, [%[pixels], #16] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr4, wr10, wr11 \n\t"
+ "walignr1 wr5, wr11, wr12 \n\t"
+ WAVG2B" wr8, wr0, wr4 \n\t"
+ WAVG2B" wr9, wr1, wr5 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "wstrd wr9, [%[block], #8] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+
+ "wldrd wr10, [%[pixels]] \n\t"
+ "wldrd wr11, [%[pixels], #8] \n\t"
+ "wldrd wr12, [%[pixels], #16] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr0, wr10, wr11 \n\t"
+ "walignr1 wr1, wr11, wr12 \n\t"
+ WAVG2B" wr8, wr0, wr4 \n\t"
+ WAVG2B" wr9, wr1, wr5 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "wstrd wr9, [%[block], #8] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+
+ "subs %[h], %[h], #2 \n\t"
+ "bne 1b \n\t"
+ : [h]"+r"(h), [pixels]"+r"(pixels), [block]"+r"(block), [line_size]"+r"(stride)
+ :
+ : "r4", "r5", "r12", "memory");
+}
+
+void DEF(avg, pixels16_y2)(uint8_t *block, const uint8_t *pixels, const int line_size, int h)
+{
+ int stride = line_size;
+ // [wr0 wr1 wr2 wr3] for previous line
+ // [wr4 wr5 wr6 wr7] for current line
+ __asm__ __volatile__(
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "and r12, %[pixels], #7 \n\t"
+ "tmcr wcgr1, r12 \n\t"
+ "bic %[pixels], %[pixels], #7 \n\t"
+
+ "wldrd wr10, [%[pixels]] \n\t"
+ "wldrd wr11, [%[pixels], #8] \n\t"
+ "pld [%[block]] \n\t"
+ "wldrd wr12, [%[pixels], #16] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr0, wr10, wr11 \n\t"
+ "walignr1 wr1, wr11, wr12 \n\t"
+
+ "1: \n\t"
+ "wldrd wr10, [%[pixels]] \n\t"
+ "wldrd wr11, [%[pixels], #8] \n\t"
+ "wldrd wr12, [%[pixels], #16] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr4, wr10, wr11 \n\t"
+ "walignr1 wr5, wr11, wr12 \n\t"
+ "wldrd wr10, [%[block]] \n\t"
+ "wldrd wr11, [%[block], #8] \n\t"
+ WAVG2B" wr8, wr0, wr4 \n\t"
+ WAVG2B" wr9, wr1, wr5 \n\t"
+ WAVG2B" wr8, wr8, wr10 \n\t"
+ WAVG2B" wr9, wr9, wr11 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "wstrd wr9, [%[block], #8] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+
+ "wldrd wr10, [%[pixels]] \n\t"
+ "wldrd wr11, [%[pixels], #8] \n\t"
+ "pld [%[block]] \n\t"
+ "wldrd wr12, [%[pixels], #16] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr0, wr10, wr11 \n\t"
+ "walignr1 wr1, wr11, wr12 \n\t"
+ "wldrd wr10, [%[block]] \n\t"
+ "wldrd wr11, [%[block], #8] \n\t"
+ WAVG2B" wr8, wr0, wr4 \n\t"
+ WAVG2B" wr9, wr1, wr5 \n\t"
+ WAVG2B" wr8, wr8, wr10 \n\t"
+ WAVG2B" wr9, wr9, wr11 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "wstrd wr9, [%[block], #8] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+
+ "subs %[h], %[h], #2 \n\t"
+ "pld [%[block]] \n\t"
+ "bne 1b \n\t"
+ : [h]"+r"(h), [pixels]"+r"(pixels), [block]"+r"(block), [line_size]"+r"(stride)
+ :
+ : "r4", "r5", "r12", "memory");
+}
+
+void DEF(put, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, const int line_size, int h)
+{
+ // [wr0 wr1 wr2 wr3] for previous line
+ // [wr4 wr5 wr6 wr7] for current line
+ SET_RND(wr15); // =2 for rnd and =1 for no_rnd version
+ __asm__ __volatile__(
+ "pld [%[pixels]] \n\t"
+ "mov r12, #2 \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "tmcr wcgr0, r12 \n\t" /* for shift value */
+ "and r12, %[pixels], #7 \n\t"
+ "bic %[pixels], %[pixels], #7 \n\t"
+ "tmcr wcgr1, r12 \n\t"
+
+ // [wr0 wr1 wr2 wr3] <= *
+ // [wr4 wr5 wr6 wr7]
+ "wldrd wr12, [%[pixels]] \n\t"
+ "add r12, r12, #1 \n\t"
+ "wldrd wr13, [%[pixels], #8] \n\t"
+ "tmcr wcgr2, r12 \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "cmp r12, #8 \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr2, wr12, wr13 \n\t"
+ "wmoveq wr10, wr13 \n\t"
+ "walignr2ne wr10, wr12, wr13 \n\t"
+ "wunpckelub wr0, wr2 \n\t"
+ "wunpckehub wr1, wr2 \n\t"
+ "wunpckelub wr8, wr10 \n\t"
+ "wunpckehub wr9, wr10 \n\t"
+ "waddhus wr0, wr0, wr8 \n\t"
+ "waddhus wr1, wr1, wr9 \n\t"
+
+ "1: \n\t"
+ // [wr0 wr1 wr2 wr3]
+ // [wr4 wr5 wr6 wr7] <= *
+ "wldrd wr12, [%[pixels]] \n\t"
+ "cmp r12, #8 \n\t"
+ "wldrd wr13, [%[pixels], #8] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "walignr1 wr6, wr12, wr13 \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "wmoveq wr10, wr13 \n\t"
+ "walignr2ne wr10, wr12, wr13 \n\t"
+ "wunpckelub wr4, wr6 \n\t"
+ "wunpckehub wr5, wr6 \n\t"
+ "wunpckelub wr8, wr10 \n\t"
+ "wunpckehub wr9, wr10 \n\t"
+ "waddhus wr4, wr4, wr8 \n\t"
+ "waddhus wr5, wr5, wr9 \n\t"
+ "waddhus wr8, wr0, wr4 \n\t"
+ "waddhus wr9, wr1, wr5 \n\t"
+ "waddhus wr8, wr8, wr15 \n\t"
+ "waddhus wr9, wr9, wr15 \n\t"
+ "wsrlhg wr8, wr8, wcgr0 \n\t"
+ "wsrlhg wr9, wr9, wcgr0 \n\t"
+ "wpackhus wr8, wr8, wr9 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+
+ // [wr0 wr1 wr2 wr3] <= *
+ // [wr4 wr5 wr6 wr7]
+ "wldrd wr12, [%[pixels]] \n\t"
+ "wldrd wr13, [%[pixels], #8] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "walignr1 wr2, wr12, wr13 \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "wmoveq wr10, wr13 \n\t"
+ "walignr2ne wr10, wr12, wr13 \n\t"
+ "wunpckelub wr0, wr2 \n\t"
+ "wunpckehub wr1, wr2 \n\t"
+ "wunpckelub wr8, wr10 \n\t"
+ "wunpckehub wr9, wr10 \n\t"
+ "waddhus wr0, wr0, wr8 \n\t"
+ "waddhus wr1, wr1, wr9 \n\t"
+ "waddhus wr8, wr0, wr4 \n\t"
+ "waddhus wr9, wr1, wr5 \n\t"
+ "waddhus wr8, wr8, wr15 \n\t"
+ "waddhus wr9, wr9, wr15 \n\t"
+ "wsrlhg wr8, wr8, wcgr0 \n\t"
+ "wsrlhg wr9, wr9, wcgr0 \n\t"
+ "wpackhus wr8, wr8, wr9 \n\t"
+ "subs %[h], %[h], #2 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+ "bne 1b \n\t"
+ : [h]"+r"(h), [pixels]"+r"(pixels), [block]"+r"(block)
+ : [line_size]"r"(line_size)
+ : "r12", "memory");
+}
+
+void DEF(put, pixels16_xy2)(uint8_t *block, const uint8_t *pixels, const int line_size, int h)
+{
+ // [wr0 wr1 wr2 wr3] for previous line
+ // [wr4 wr5 wr6 wr7] for current line
+ SET_RND(wr15); // =2 for rnd and =1 for no_rnd version
+ __asm__ __volatile__(
+ "pld [%[pixels]] \n\t"
+ "mov r12, #2 \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "tmcr wcgr0, r12 \n\t" /* for shift value */
+ /* alignment */
+ "and r12, %[pixels], #7 \n\t"
+ "bic %[pixels], %[pixels], #7 \n\t"
+ "tmcr wcgr1, r12 \n\t"
+ "add r12, r12, #1 \n\t"
+ "tmcr wcgr2, r12 \n\t"
+
+ // [wr0 wr1 wr2 wr3] <= *
+ // [wr4 wr5 wr6 wr7]
+ "wldrd wr12, [%[pixels]] \n\t"
+ "cmp r12, #8 \n\t"
+ "wldrd wr13, [%[pixels], #8] \n\t"
+ "wldrd wr14, [%[pixels], #16] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "pld [%[pixels]] \n\t"
+ "walignr1 wr2, wr12, wr13 \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr3, wr13, wr14 \n\t"
+ "wmoveq wr10, wr13 \n\t"
+ "wmoveq wr11, wr14 \n\t"
+ "walignr2ne wr10, wr12, wr13 \n\t"
+ "walignr2ne wr11, wr13, wr14 \n\t"
+ "wunpckelub wr0, wr2 \n\t"
+ "wunpckehub wr1, wr2 \n\t"
+ "wunpckelub wr2, wr3 \n\t"
+ "wunpckehub wr3, wr3 \n\t"
+ "wunpckelub wr8, wr10 \n\t"
+ "wunpckehub wr9, wr10 \n\t"
+ "wunpckelub wr10, wr11 \n\t"
+ "wunpckehub wr11, wr11 \n\t"
+ "waddhus wr0, wr0, wr8 \n\t"
+ "waddhus wr1, wr1, wr9 \n\t"
+ "waddhus wr2, wr2, wr10 \n\t"
+ "waddhus wr3, wr3, wr11 \n\t"
+
+ "1: \n\t"
+ // [wr0 wr1 wr2 wr3]
+ // [wr4 wr5 wr6 wr7] <= *
+ "wldrd wr12, [%[pixels]] \n\t"
+ "cmp r12, #8 \n\t"
+ "wldrd wr13, [%[pixels], #8] \n\t"
+ "wldrd wr14, [%[pixels], #16] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "walignr1 wr6, wr12, wr13 \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr7, wr13, wr14 \n\t"
+ "wmoveq wr10, wr13 \n\t"
+ "wmoveq wr11, wr14 \n\t"
+ "walignr2ne wr10, wr12, wr13 \n\t"
+ "walignr2ne wr11, wr13, wr14 \n\t"
+ "wunpckelub wr4, wr6 \n\t"
+ "wunpckehub wr5, wr6 \n\t"
+ "wunpckelub wr6, wr7 \n\t"
+ "wunpckehub wr7, wr7 \n\t"
+ "wunpckelub wr8, wr10 \n\t"
+ "wunpckehub wr9, wr10 \n\t"
+ "wunpckelub wr10, wr11 \n\t"
+ "wunpckehub wr11, wr11 \n\t"
+ "waddhus wr4, wr4, wr8 \n\t"
+ "waddhus wr5, wr5, wr9 \n\t"
+ "waddhus wr6, wr6, wr10 \n\t"
+ "waddhus wr7, wr7, wr11 \n\t"
+ "waddhus wr8, wr0, wr4 \n\t"
+ "waddhus wr9, wr1, wr5 \n\t"
+ "waddhus wr10, wr2, wr6 \n\t"
+ "waddhus wr11, wr3, wr7 \n\t"
+ "waddhus wr8, wr8, wr15 \n\t"
+ "waddhus wr9, wr9, wr15 \n\t"
+ "waddhus wr10, wr10, wr15 \n\t"
+ "waddhus wr11, wr11, wr15 \n\t"
+ "wsrlhg wr8, wr8, wcgr0 \n\t"
+ "wsrlhg wr9, wr9, wcgr0 \n\t"
+ "wsrlhg wr10, wr10, wcgr0 \n\t"
+ "wsrlhg wr11, wr11, wcgr0 \n\t"
+ "wpackhus wr8, wr8, wr9 \n\t"
+ "wpackhus wr9, wr10, wr11 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "wstrd wr9, [%[block], #8] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+
+ // [wr0 wr1 wr2 wr3] <= *
+ // [wr4 wr5 wr6 wr7]
+ "wldrd wr12, [%[pixels]] \n\t"
+ "wldrd wr13, [%[pixels], #8] \n\t"
+ "wldrd wr14, [%[pixels], #16] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "walignr1 wr2, wr12, wr13 \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr3, wr13, wr14 \n\t"
+ "wmoveq wr10, wr13 \n\t"
+ "wmoveq wr11, wr14 \n\t"
+ "walignr2ne wr10, wr12, wr13 \n\t"
+ "walignr2ne wr11, wr13, wr14 \n\t"
+ "wunpckelub wr0, wr2 \n\t"
+ "wunpckehub wr1, wr2 \n\t"
+ "wunpckelub wr2, wr3 \n\t"
+ "wunpckehub wr3, wr3 \n\t"
+ "wunpckelub wr8, wr10 \n\t"
+ "wunpckehub wr9, wr10 \n\t"
+ "wunpckelub wr10, wr11 \n\t"
+ "wunpckehub wr11, wr11 \n\t"
+ "waddhus wr0, wr0, wr8 \n\t"
+ "waddhus wr1, wr1, wr9 \n\t"
+ "waddhus wr2, wr2, wr10 \n\t"
+ "waddhus wr3, wr3, wr11 \n\t"
+ "waddhus wr8, wr0, wr4 \n\t"
+ "waddhus wr9, wr1, wr5 \n\t"
+ "waddhus wr10, wr2, wr6 \n\t"
+ "waddhus wr11, wr3, wr7 \n\t"
+ "waddhus wr8, wr8, wr15 \n\t"
+ "waddhus wr9, wr9, wr15 \n\t"
+ "waddhus wr10, wr10, wr15 \n\t"
+ "waddhus wr11, wr11, wr15 \n\t"
+ "wsrlhg wr8, wr8, wcgr0 \n\t"
+ "wsrlhg wr9, wr9, wcgr0 \n\t"
+ "wsrlhg wr10, wr10, wcgr0 \n\t"
+ "wsrlhg wr11, wr11, wcgr0 \n\t"
+ "wpackhus wr8, wr8, wr9 \n\t"
+ "wpackhus wr9, wr10, wr11 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "wstrd wr9, [%[block], #8] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+
+ "subs %[h], %[h], #2 \n\t"
+ "bne 1b \n\t"
+ : [h]"+r"(h), [pixels]"+r"(pixels), [block]"+r"(block)
+ : [line_size]"r"(line_size)
+ : "r12", "memory");
+}
+
+void DEF(avg, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, const int line_size, int h)
+{
+ // [wr0 wr1 wr2 wr3] for previous line
+ // [wr4 wr5 wr6 wr7] for current line
+ SET_RND(wr15); // =2 for rnd and =1 for no_rnd version
+ __asm__ __volatile__(
+ "pld [%[block]] \n\t"
+ "pld [%[block], #32] \n\t"
+ "pld [%[pixels]] \n\t"
+ "mov r12, #2 \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "tmcr wcgr0, r12 \n\t" /* for shift value */
+ "and r12, %[pixels], #7 \n\t"
+ "bic %[pixels], %[pixels], #7 \n\t"
+ "tmcr wcgr1, r12 \n\t"
+
+ // [wr0 wr1 wr2 wr3] <= *
+ // [wr4 wr5 wr6 wr7]
+ "wldrd wr12, [%[pixels]] \n\t"
+ "add r12, r12, #1 \n\t"
+ "wldrd wr13, [%[pixels], #8] \n\t"
+ "tmcr wcgr2, r12 \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "cmp r12, #8 \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr2, wr12, wr13 \n\t"
+ "wmoveq wr10, wr13 \n\t"
+ "walignr2ne wr10, wr12, wr13 \n\t"
+ "wunpckelub wr0, wr2 \n\t"
+ "wunpckehub wr1, wr2 \n\t"
+ "wunpckelub wr8, wr10 \n\t"
+ "wunpckehub wr9, wr10 \n\t"
+ "waddhus wr0, wr0, wr8 \n\t"
+ "waddhus wr1, wr1, wr9 \n\t"
+
+ "1: \n\t"
+ // [wr0 wr1 wr2 wr3]
+ // [wr4 wr5 wr6 wr7] <= *
+ "wldrd wr12, [%[pixels]] \n\t"
+ "cmp r12, #8 \n\t"
+ "wldrd wr13, [%[pixels], #8] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "walignr1 wr6, wr12, wr13 \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "wmoveq wr10, wr13 \n\t"
+ "walignr2ne wr10, wr12, wr13 \n\t"
+ "wunpckelub wr4, wr6 \n\t"
+ "wunpckehub wr5, wr6 \n\t"
+ "wunpckelub wr8, wr10 \n\t"
+ "wunpckehub wr9, wr10 \n\t"
+ "waddhus wr4, wr4, wr8 \n\t"
+ "waddhus wr5, wr5, wr9 \n\t"
+ "waddhus wr8, wr0, wr4 \n\t"
+ "waddhus wr9, wr1, wr5 \n\t"
+ "waddhus wr8, wr8, wr15 \n\t"
+ "waddhus wr9, wr9, wr15 \n\t"
+ "wldrd wr12, [%[block]] \n\t"
+ "wsrlhg wr8, wr8, wcgr0 \n\t"
+ "wsrlhg wr9, wr9, wcgr0 \n\t"
+ "wpackhus wr8, wr8, wr9 \n\t"
+ WAVG2B" wr8, wr8, wr12 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+ "wldrd wr12, [%[pixels]] \n\t"
+ "pld [%[block]] \n\t"
+ "pld [%[block], #32] \n\t"
+
+ // [wr0 wr1 wr2 wr3] <= *
+ // [wr4 wr5 wr6 wr7]
+ "wldrd wr13, [%[pixels], #8] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "walignr1 wr2, wr12, wr13 \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "wmoveq wr10, wr13 \n\t"
+ "walignr2ne wr10, wr12, wr13 \n\t"
+ "wunpckelub wr0, wr2 \n\t"
+ "wunpckehub wr1, wr2 \n\t"
+ "wunpckelub wr8, wr10 \n\t"
+ "wunpckehub wr9, wr10 \n\t"
+ "waddhus wr0, wr0, wr8 \n\t"
+ "waddhus wr1, wr1, wr9 \n\t"
+ "waddhus wr8, wr0, wr4 \n\t"
+ "waddhus wr9, wr1, wr5 \n\t"
+ "waddhus wr8, wr8, wr15 \n\t"
+ "waddhus wr9, wr9, wr15 \n\t"
+ "wldrd wr12, [%[block]] \n\t"
+ "wsrlhg wr8, wr8, wcgr0 \n\t"
+ "wsrlhg wr9, wr9, wcgr0 \n\t"
+ "wpackhus wr8, wr8, wr9 \n\t"
+ "subs %[h], %[h], #2 \n\t"
+ WAVG2B" wr8, wr8, wr12 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+ "pld [%[block]] \n\t"
+ "pld [%[block], #32] \n\t"
+ "bne 1b \n\t"
+ : [h]"+r"(h), [pixels]"+r"(pixels), [block]"+r"(block)
+ : [line_size]"r"(line_size)
+ : "r12", "memory");
+}
+
+void DEF(avg, pixels16_xy2)(uint8_t *block, const uint8_t *pixels, const int line_size, int h)
+{
+ // [wr0 wr1 wr2 wr3] for previous line
+ // [wr4 wr5 wr6 wr7] for current line
+ SET_RND(wr15); // =2 for rnd and =1 for no_rnd version
+ __asm__ __volatile__(
+ "pld [%[block]] \n\t"
+ "pld [%[block], #32] \n\t"
+ "pld [%[pixels]] \n\t"
+ "mov r12, #2 \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "tmcr wcgr0, r12 \n\t" /* for shift value */
+ /* alignment */
+ "and r12, %[pixels], #7 \n\t"
+ "bic %[pixels], %[pixels], #7 \n\t"
+ "tmcr wcgr1, r12 \n\t"
+ "add r12, r12, #1 \n\t"
+ "tmcr wcgr2, r12 \n\t"
+
+ // [wr0 wr1 wr2 wr3] <= *
+ // [wr4 wr5 wr6 wr7]
+ "wldrd wr12, [%[pixels]] \n\t"
+ "cmp r12, #8 \n\t"
+ "wldrd wr13, [%[pixels], #8] \n\t"
+ "wldrd wr14, [%[pixels], #16] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "pld [%[pixels]] \n\t"
+ "walignr1 wr2, wr12, wr13 \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr3, wr13, wr14 \n\t"
+ "wmoveq wr10, wr13 \n\t"
+ "wmoveq wr11, wr14 \n\t"
+ "walignr2ne wr10, wr12, wr13 \n\t"
+ "walignr2ne wr11, wr13, wr14 \n\t"
+ "wunpckelub wr0, wr2 \n\t"
+ "wunpckehub wr1, wr2 \n\t"
+ "wunpckelub wr2, wr3 \n\t"
+ "wunpckehub wr3, wr3 \n\t"
+ "wunpckelub wr8, wr10 \n\t"
+ "wunpckehub wr9, wr10 \n\t"
+ "wunpckelub wr10, wr11 \n\t"
+ "wunpckehub wr11, wr11 \n\t"
+ "waddhus wr0, wr0, wr8 \n\t"
+ "waddhus wr1, wr1, wr9 \n\t"
+ "waddhus wr2, wr2, wr10 \n\t"
+ "waddhus wr3, wr3, wr11 \n\t"
+
+ "1: \n\t"
+ // [wr0 wr1 wr2 wr3]
+ // [wr4 wr5 wr6 wr7] <= *
+ "wldrd wr12, [%[pixels]] \n\t"
+ "cmp r12, #8 \n\t"
+ "wldrd wr13, [%[pixels], #8] \n\t"
+ "wldrd wr14, [%[pixels], #16] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "walignr1 wr6, wr12, wr13 \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr7, wr13, wr14 \n\t"
+ "wmoveq wr10, wr13 \n\t"
+ "wmoveq wr11, wr14 \n\t"
+ "walignr2ne wr10, wr12, wr13 \n\t"
+ "walignr2ne wr11, wr13, wr14 \n\t"
+ "wunpckelub wr4, wr6 \n\t"
+ "wunpckehub wr5, wr6 \n\t"
+ "wunpckelub wr6, wr7 \n\t"
+ "wunpckehub wr7, wr7 \n\t"
+ "wunpckelub wr8, wr10 \n\t"
+ "wunpckehub wr9, wr10 \n\t"
+ "wunpckelub wr10, wr11 \n\t"
+ "wunpckehub wr11, wr11 \n\t"
+ "waddhus wr4, wr4, wr8 \n\t"
+ "waddhus wr5, wr5, wr9 \n\t"
+ "waddhus wr6, wr6, wr10 \n\t"
+ "waddhus wr7, wr7, wr11 \n\t"
+ "waddhus wr8, wr0, wr4 \n\t"
+ "waddhus wr9, wr1, wr5 \n\t"
+ "waddhus wr10, wr2, wr6 \n\t"
+ "waddhus wr11, wr3, wr7 \n\t"
+ "waddhus wr8, wr8, wr15 \n\t"
+ "waddhus wr9, wr9, wr15 \n\t"
+ "waddhus wr10, wr10, wr15 \n\t"
+ "waddhus wr11, wr11, wr15 \n\t"
+ "wsrlhg wr8, wr8, wcgr0 \n\t"
+ "wsrlhg wr9, wr9, wcgr0 \n\t"
+ "wldrd wr12, [%[block]] \n\t"
+ "wldrd wr13, [%[block], #8] \n\t"
+ "wsrlhg wr10, wr10, wcgr0 \n\t"
+ "wsrlhg wr11, wr11, wcgr0 \n\t"
+ "wpackhus wr8, wr8, wr9 \n\t"
+ "wpackhus wr9, wr10, wr11 \n\t"
+ WAVG2B" wr8, wr8, wr12 \n\t"
+ WAVG2B" wr9, wr9, wr13 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "wstrd wr9, [%[block], #8] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+
+ // [wr0 wr1 wr2 wr3] <= *
+ // [wr4 wr5 wr6 wr7]
+ "wldrd wr12, [%[pixels]] \n\t"
+ "pld [%[block]] \n\t"
+ "wldrd wr13, [%[pixels], #8] \n\t"
+ "pld [%[block], #32] \n\t"
+ "wldrd wr14, [%[pixels], #16] \n\t"
+ "add %[pixels], %[pixels], %[line_size] \n\t"
+ "walignr1 wr2, wr12, wr13 \n\t"
+ "pld [%[pixels]] \n\t"
+ "pld [%[pixels], #32] \n\t"
+ "walignr1 wr3, wr13, wr14 \n\t"
+ "wmoveq wr10, wr13 \n\t"
+ "wmoveq wr11, wr14 \n\t"
+ "walignr2ne wr10, wr12, wr13 \n\t"
+ "walignr2ne wr11, wr13, wr14 \n\t"
+ "wunpckelub wr0, wr2 \n\t"
+ "wunpckehub wr1, wr2 \n\t"
+ "wunpckelub wr2, wr3 \n\t"
+ "wunpckehub wr3, wr3 \n\t"
+ "wunpckelub wr8, wr10 \n\t"
+ "wunpckehub wr9, wr10 \n\t"
+ "wunpckelub wr10, wr11 \n\t"
+ "wunpckehub wr11, wr11 \n\t"
+ "waddhus wr0, wr0, wr8 \n\t"
+ "waddhus wr1, wr1, wr9 \n\t"
+ "waddhus wr2, wr2, wr10 \n\t"
+ "waddhus wr3, wr3, wr11 \n\t"
+ "waddhus wr8, wr0, wr4 \n\t"
+ "waddhus wr9, wr1, wr5 \n\t"
+ "waddhus wr10, wr2, wr6 \n\t"
+ "waddhus wr11, wr3, wr7 \n\t"
+ "waddhus wr8, wr8, wr15 \n\t"
+ "waddhus wr9, wr9, wr15 \n\t"
+ "waddhus wr10, wr10, wr15 \n\t"
+ "waddhus wr11, wr11, wr15 \n\t"
+ "wsrlhg wr8, wr8, wcgr0 \n\t"
+ "wsrlhg wr9, wr9, wcgr0 \n\t"
+ "wldrd wr12, [%[block]] \n\t"
+ "wldrd wr13, [%[block], #8] \n\t"
+ "wsrlhg wr10, wr10, wcgr0 \n\t"
+ "wsrlhg wr11, wr11, wcgr0 \n\t"
+ "wpackhus wr8, wr8, wr9 \n\t"
+ "wpackhus wr9, wr10, wr11 \n\t"
+ WAVG2B" wr8, wr8, wr12 \n\t"
+ WAVG2B" wr9, wr9, wr13 \n\t"
+ "wstrd wr8, [%[block]] \n\t"
+ "wstrd wr9, [%[block], #8] \n\t"
+ "add %[block], %[block], %[line_size] \n\t"
+ "subs %[h], %[h], #2 \n\t"
+ "pld [%[block]] \n\t"
+ "pld [%[block], #32] \n\t"
+ "bne 1b \n\t"
+ : [h]"+r"(h), [pixels]"+r"(pixels), [block]"+r"(block)
+ : [line_size]"r"(line_size)
+ : "r12", "memory");
+}
diff --git a/contrib/ffmpeg/libavcodec/armv4l/jrevdct_arm.S b/contrib/ffmpeg/libavcodec/armv4l/jrevdct_arm.S
new file mode 100644
index 000000000..294ea4750
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/armv4l/jrevdct_arm.S
@@ -0,0 +1,386 @@
+/*
+ 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.
+
+*/
+#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
+ .text
+ .align
+
+ .global j_rev_dct_ARM
+j_rev_dct_ARM:
+ stmdb sp!, { r4 - r12, lr } @ all callee saved regs
+
+ sub sp, sp, #4 @ reserve some space on the stack
+ str r0, [ sp ] @ save the DCT pointer to the stack
+
+ mov lr, r0 @ lr = pointer to the current row
+ mov r12, #8 @ r12 = row-counter
+ add r11, pc, #(const_array-.-8) @ r11 = base pointer to the constants array
+row_loop:
+ ldrsh r0, [lr, # 0] @ r0 = 'd0'
+ ldrsh r1, [lr, # 8] @ r1 = 'd1'
+
+ @ Optimization for row that have all items except the first set to 0
+ @ (this works as the DCTELEMS are always 4-byte aligned)
+ ldr r5, [lr, # 0]
+ ldr r2, [lr, # 4]
+ ldr r3, [lr, # 8]
+ ldr r4, [lr, #12]
+ orr r3, r3, r4
+ orr r3, r3, r2
+ orrs r5, r3, r5
+ beq end_of_row_loop @ nothing to be done as ALL of them are '0'
+ orrs r2, r3, r1
+ beq empty_row
+
+ ldrsh r2, [lr, # 2] @ r2 = 'd2'
+ 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
+
+ stmdb sp!, { 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
+
+ ldmia sp!, { 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
+ ldr lr, [ sp ]
+ 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
+
+ stmdb sp!, { 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
+
+ ldmia sp!, { 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....
+ add sp, sp, #4
+ ldmia sp!, { r4 - r12, pc } @ restore callee saved regs and return
+
+const_array:
+ .align
+ .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
diff --git a/contrib/ffmpeg/libavcodec/armv4l/mathops.h b/contrib/ffmpeg/libavcodec/armv4l/mathops.h
new file mode 100644
index 000000000..7ddd0ec6e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/armv4l/mathops.h
@@ -0,0 +1,49 @@
+/*
+ * simple math operations
+ * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> 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
+ */
+
+#ifdef FRAC_BITS
+# define MULL(a, b) \
+ ({ int lo, hi;\
+ asm("smull %0, %1, %2, %3 \n\t"\
+ "mov %0, %0, lsr %4\n\t"\
+ "add %1, %0, %1, lsl %5\n\t"\
+ : "=&r"(lo), "=&r"(hi)\
+ : "r"(b), "r"(a), "i"(FRAC_BITS), "i"(32-FRAC_BITS));\
+ hi; })
+#endif
+
+#define MULH(a, b) \
+ ({ int lo, hi;\
+ asm ("smull %0, %1, %2, %3" : "=&r"(lo), "=&r"(hi) : "r"(b), "r"(a));\
+ hi; })
+
+#if defined(HAVE_ARMV5TE)
+
+/* signed 16x16 -> 32 multiply add accumulate */
+# define MAC16(rt, ra, rb) \
+ asm ("smlabb %0, %2, %3, %0" : "=r" (rt) : "0" (rt), "r" (ra), "r" (rb));
+/* signed 16x16 -> 32 multiply */
+# define MUL16(ra, rb) \
+ ({ int __rt; \
+ asm ("smulbb %0, %1, %2" : "=r" (__rt) : "r" (ra), "r" (rb)); \
+ __rt; })
+
+#endif
diff --git a/contrib/ffmpeg/libavcodec/armv4l/mpegvideo_arm.c b/contrib/ffmpeg/libavcodec/armv4l/mpegvideo_arm.c
new file mode 100644
index 000000000..10a005cd3
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/armv4l/mpegvideo_arm.c
@@ -0,0 +1,33 @@
+/*
+ * 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 "../dsputil.h"
+#include "../mpegvideo.h"
+#include "../avcodec.h"
+
+extern void MPV_common_init_iwmmxt(MpegEncContext *s);
+
+void MPV_common_init_armv4l(MpegEncContext *s)
+{
+#ifdef HAVE_IWMMXT
+ MPV_common_init_iwmmxt(s);
+#endif
+}
diff --git a/contrib/ffmpeg/libavcodec/armv4l/mpegvideo_iwmmxt.c b/contrib/ffmpeg/libavcodec/armv4l/mpegvideo_iwmmxt.c
new file mode 100644
index 000000000..1336ac5f8
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/armv4l/mpegvideo_iwmmxt.c
@@ -0,0 +1,119 @@
+/*
+ * 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 "../dsputil.h"
+#include "../mpegvideo.h"
+#include "../avcodec.h"
+
+static void dct_unquantize_h263_intra_iwmmxt(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale)
+{
+ int level, qmul, qadd;
+ int nCoeffs;
+ DCTELEM *block_orig = block;
+
+ assert(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] ];
+
+ __asm__ __volatile__ (
+/* "movd %1, %%mm6 \n\t" //qmul */
+/* "packssdw %%mm6, %%mm6 \n\t" */
+/* "packssdw %%mm6, %%mm6 \n\t" */
+ "tbcsth wr6, %[qmul] \n\t"
+/* "movd %2, %%mm5 \n\t" //qadd */
+/* "packssdw %%mm5, %%mm5 \n\t" */
+/* "packssdw %%mm5, %%mm5 \n\t" */
+ "tbcsth wr5, %[qadd] \n\t"
+ "wzero wr7 \n\t" /* "pxor %%mm7, %%mm7 \n\t" */
+ "wzero wr4 \n\t" /* "pxor %%mm4, %%mm4 \n\t" */
+ "wsubh wr7, wr5, wr7 \n\t" /* "psubw %%mm5, %%mm7 \n\t" */
+ "1: \n\t"
+ "wldrd wr2, [%[block]] \n\t" /* "movq (%0, %3), %%mm0 \n\t" */
+ "wldrd wr3, [%[block], #8] \n\t" /* "movq 8(%0, %3), %%mm1 \n\t" */
+ "wmulsl wr0, wr6, wr2 \n\t" /* "pmullw %%mm6, %%mm0 \n\t" */
+ "wmulsl wr1, wr6, wr3 \n\t" /* "pmullw %%mm6, %%mm1 \n\t" */
+/* "movq (%0, %3), %%mm2 \n\t" */
+/* "movq 8(%0, %3), %%mm3 \n\t" */
+ "wcmpgtsh wr2, wr4, wr2 \n\t" /* "pcmpgtw %%mm4, %%mm2 \n\t" // block[i] < 0 ? -1 : 0 */
+ "wcmpgtsh wr3, wr4, wr2 \n\t" /* "pcmpgtw %%mm4, %%mm3 \n\t" // block[i] < 0 ? -1 : 0 */
+ "wxor wr0, wr2, wr0 \n\t" /* "pxor %%mm2, %%mm0 \n\t" */
+ "wxor wr1, wr3, wr1 \n\t" /* "pxor %%mm3, %%mm1 \n\t" */
+ "waddh wr0, wr7, wr0 \n\t" /* "paddw %%mm7, %%mm0 \n\t" */
+ "waddh wr1, wr7, wr1 \n\t" /* "paddw %%mm7, %%mm1 \n\t" */
+ "wxor wr2, wr0, wr2 \n\t" /* "pxor %%mm0, %%mm2 \n\t" */
+ "wxor wr3, wr1, wr3 \n\t" /* "pxor %%mm1, %%mm3 \n\t" */
+ "wcmpeqh wr0, wr7, wr0 \n\t" /* "pcmpeqw %%mm7, %%mm0 \n\t" // block[i] == 0 ? -1 : 0 */
+ "wcmpeqh wr1, wr7, wr1 \n\t" /* "pcmpeqw %%mm7, %%mm1 \n\t" // block[i] == 0 ? -1 : 0 */
+ "wandn wr0, wr2, wr0 \n\t" /* "pandn %%mm2, %%mm0 \n\t" */
+ "wandn wr1, wr3, wr1 \n\t" /* "pandn %%mm3, %%mm1 \n\t" */
+ "wstrd wr0, [%[block]] \n\t" /* "movq %%mm0, (%0, %3) \n\t" */
+ "wstrd wr1, [%[block], #8] \n\t" /* "movq %%mm1, 8(%0, %3) \n\t" */
+ "add %[block], %[block], #16 \n\t" /* "addl $16, %3 \n\t" */
+ "subs %[i], %[i], #1 \n\t"
+ "bne 1b \n\t" /* "jng 1b \n\t" */
+ :[block]"+r"(block)
+ :[i]"r"((nCoeffs + 8) / 8), [qmul]"r"(qmul), [qadd]"r"(qadd)
+ :"memory");
+
+ block_orig[0] = level;
+}
+
+#if 0
+static void dct_unquantize_h263_inter_iwmmxt(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale)
+{
+ int nCoeffs;
+
+ assert(s->block_last_index[n]>=0);
+
+ if(s->ac_pred)
+ nCoeffs=63;
+ else
+ nCoeffs= s->inter_scantable.raster_end[ s->block_last_index[n] ];
+
+ ippiQuantInvInter_Compact_H263_16s_I(block, nCoeffs+1, qscale);
+}
+#endif
+
+void MPV_common_init_iwmmxt(MpegEncContext *s)
+{
+ if (!(mm_flags & MM_IWMMXT)) return;
+
+ s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_iwmmxt;
+#if 0
+ s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_iwmmxt;
+#endif
+}
diff --git a/contrib/ffmpeg/libavcodec/armv4l/simple_idct_arm.S b/contrib/ffmpeg/libavcodec/armv4l/simple_idct_arm.S
new file mode 100644
index 000000000..b5a20f6da
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/armv4l/simple_idct_arm.S
@@ -0,0 +1,487 @@
+/*
+ * simple_idct_arm.S
+ * Copyright (C) 2002 Frederic 'dilb' Boulay.
+ * All Rights Reserved.
+ *
+ * Author: Frederic Boulay <dilb@handhelds.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
+ *
+ * The function defined in this file, is derived from the simple_idct function
+ * from the libavcodec library part of the ffmpeg project.
+ */
+
+/* useful constants for the algorithm, they are save in __constant_ptr__ at */
+/* the end of the source code.*/
+#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
+
+/* offsets of the constants in the vector */
+#define offW1 0
+#define offW2 4
+#define offW3 8
+#define offW4 12
+#define offW5 16
+#define offW6 20
+#define offW7 24
+#define offMASK_MSHW 28
+
+#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) */
+
+
+ .text
+ .align
+ .global simple_idct_ARM
+
+simple_idct_ARM:
+ @@ 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 r12, pc, #(__constant_ptr__-.-8) @ R12=__constant_ptr__, the vector containing the constants, probably not necessary to reserve a register for it
+ @@ 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 optimise 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, [r12, #offW1] @ 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, [r12, #offW3] @ R9=W3
+ ldr r10, [r12, #offW5] @ 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, [r12, #offW7] @ 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
+ 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)
+ 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
+ mlane r0, r10, r3, r0 @ R0+=W5*ROWr16[5]=b0
+ mov r4, r4, asr #16 @ R4=ROWr16[7]
+ 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
+ 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
+ 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, [r12, #offW4] @ R9=W4
+ mul r6, r9, r6 @ R6=W4*ROWr16[0]
+ ldr r10, [r12, #offW6] @ 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, [r12, #offW2] @ 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
+ mulne r11, r9, r11 @ R11=W4*ROWr16[4]
+ @@ R9 is free now
+ ldrsh r9, [r14, #12] @ R9=ROWr16[6]
+ 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
+ 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)
+ 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, [r12, #offMASK_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, [r12, #offW1] @ 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, [r12, #offW3] @ R9=W3
+ ldr r10, [r12, #offW5] @ 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, [r12, #offW7] @ 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
+ 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)
+ 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
+ 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]
+ mlane r1, r8, r3, r1 @ R7-=W1*ROWr16[5x8]=b1
+ @@ R3 is free now
+ teq r4, #0 @ if 0 then avoid muls
+ 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
+ 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, [r12, #offW4] @ R9=W4
+ mul r6, r9, r6 @ R6=W4*ROWr16[0]
+ ldr r10, [r12, #offW6] @ 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, [r12, #offW2] @ 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
+ 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]
+ 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
+ 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)
+ 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 optimisation 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
+
+
+__constant_ptr__: @@ see #defines at the beginning of the source code for values.
+ .align
+ .word W1
+ .word W2
+ .word W3
+ .word W4
+ .word W5
+ .word W6
+ .word W7
+ .word MASK_MSHW
diff --git a/contrib/ffmpeg/libavcodec/armv4l/simple_idct_armv5te.S b/contrib/ffmpeg/libavcodec/armv4l/simple_idct_armv5te.S
new file mode 100644
index 000000000..28bee0643
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/armv4l/simple_idct_armv5te.S
@@ -0,0 +1,718 @@
+/*
+ * Simple IDCT
+ *
+ * Copyright (c) 2001 Michael Niedermayer <michaelni@gmx.at>
+ * Copyright (c) 2006 Mans Rullgard <mru@inprovide.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
+ */
+
+#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))
+
+ .text
+ .align
+w13: .long W13
+w26: .long W26
+w57: .long W57
+
+ .align
+ .func idct_row_armv5te
+idct_row_armv5te:
+ str lr, [sp, #-4]!
+
+ ldrd v1, [a1, #8]
+ ldrd a3, [a1] /* a3 = row[1:0], a4 = row[3:2] */
+ orrs v1, v1, v2
+ 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, [pc, #(w26-.-8)] /* 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, [pc, #(w13-.-8)] /* ip = W1 | (W3 << 16) */
+ ldr lr, [pc, #(w57-.-8)] /* 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, [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, [pc, #(w26-.-8)] /* 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, [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, [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, [a1]
+ strd a3, [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, [pc, #(w26-.-8)]
+ 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, [pc, #(w13-.-8)]
+ ldr a4, [a1, #(16*1)]
+ ldr lr, [pc, #(w57-.-8)]
+ 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
+
+ .align
+ .func idct_col_armv5te
+idct_col_armv5te:
+ str lr, [sp, #-4]!
+
+ idct_col
+
+ ldmfd sp!, {a3, a4}
+ adds a2, a3, v1
+ mov a2, a2, lsr #20
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+
+ .align
+ .func idct_col_put_armv5te
+idct_col_put_armv5te:
+ str lr, [sp, #-4]!
+
+ idct_col
+
+ ldmfd sp!, {a3, a4}
+ ldr lr, [sp, #32]
+ add a2, a3, v1
+ movs a2, a2, asr #20
+ movmi a2, #0
+ cmp a2, #255
+ movgt a2, #255
+ add ip, a4, v2
+ movs ip, ip, asr #20
+ movmi ip, #0
+ cmp ip, #255
+ movgt ip, #255
+ orr a2, a2, ip, lsl #8
+ sub a3, a3, v1
+ movs a3, a3, asr #20
+ movmi a3, #0
+ cmp a3, #255
+ movgt a3, #255
+ sub a4, a4, v2
+ movs a4, a4, asr #20
+ movmi a4, #0
+ cmp a4, #255
+ ldr v1, [sp, #28]
+ movgt a4, #255
+ 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 a2, [v2, v1]!
+
+ sub a2, a3, v3
+ movs a2, a2, asr #20
+ movmi a2, #0
+ cmp a2, #255
+ movgt a2, #255
+ sub ip, a4, v4
+ movs ip, ip, asr #20
+ movmi ip, #0
+ cmp ip, #255
+ movgt ip, #255
+ orr a2, a2, ip, lsl #8
+ strh a2, [v1, lr]!
+ add a3, a3, v3
+ movs a2, a3, asr #20
+ movmi a2, #0
+ cmp a2, #255
+ movgt a2, #255
+ add a4, a4, v4
+ movs a4, a4, asr #20
+ movmi a4, #0
+ cmp a4, #255
+ movgt a4, #255
+ orr a2, a2, a4, lsl #8
+ ldmfd sp!, {a3, a4}
+ strh a2, [v2, -lr]!
+
+ add a2, a3, v5
+ movs a2, a2, asr #20
+ movmi a2, #0
+ cmp a2, #255
+ movgt a2, #255
+ add ip, a4, v6
+ movs ip, ip, asr #20
+ movmi ip, #0
+ cmp ip, #255
+ movgt ip, #255
+ orr a2, a2, ip, lsl #8
+ strh a2, [v1, lr]!
+ sub a3, a3, v5
+ movs a2, a3, asr #20
+ movmi a2, #0
+ cmp a2, #255
+ movgt a2, #255
+ sub a4, a4, v6
+ movs a4, a4, asr #20
+ movmi a4, #0
+ cmp a4, #255
+ movgt a4, #255
+ orr a2, a2, a4, lsl #8
+ ldmfd sp!, {a3, a4}
+ strh a2, [v2, -lr]!
+
+ add a2, a3, v7
+ movs a2, a2, asr #20
+ movmi a2, #0
+ cmp a2, #255
+ movgt a2, #255
+ add ip, a4, fp
+ movs ip, ip, asr #20
+ movmi ip, #0
+ cmp ip, #255
+ movgt ip, #255
+ orr a2, a2, ip, lsl #8
+ strh a2, [v1, lr]
+ sub a3, a3, v7
+ movs a2, a3, asr #20
+ movmi a2, #0
+ cmp a2, #255
+ movgt a2, #255
+ sub a4, a4, fp
+ movs a4, a4, asr #20
+ movmi a4, #0
+ cmp a4, #255
+ movgt a4, #255
+ orr a2, a2, a4, lsl #8
+ strh a2, [v2, -lr]
+
+ ldr pc, [sp], #4
+ .endfunc
+
+ .align
+ .func idct_col_add_armv5te
+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
+ mov a2, a2, asr #20
+ sub a3, a3, v1
+ and v1, ip, #255
+ adds a2, a2, v1
+ movmi a2, #0
+ cmp a2, #255
+ movgt a2, #255
+ add v1, a4, v2
+ mov v1, v1, asr #20
+ adds v1, v1, ip, lsr #8
+ movmi v1, #0
+ cmp v1, #255
+ movgt v1, #255
+ orr a2, a2, v1, lsl #8
+ ldr v1, [sp, #32]
+ sub a4, a4, v2
+ rsb v2, v1, v1, lsl #3
+ ldrh ip, [v2, lr]!
+ strh a2, [lr]
+ mov a3, a3, asr #20
+ and a2, ip, #255
+ adds a3, a3, a2
+ movmi a3, #0
+ cmp a3, #255
+ movgt a3, #255
+ mov a4, a4, asr #20
+ adds a4, a4, ip, lsr #8
+ movmi a4, #0
+ cmp a4, #255
+ movgt a4, #255
+ add a2, lr, #2
+ str a2, [sp, #28]
+ orr a2, a3, a4, lsl #8
+ strh a2, [v2]
+
+ ldmfd sp!, {a3, a4}
+ ldrh ip, [lr, v1]!
+ sub a2, a3, v3
+ mov a2, a2, asr #20
+ add a3, a3, v3
+ and v3, ip, #255
+ adds a2, a2, v3
+ movmi a2, #0
+ cmp a2, #255
+ movgt a2, #255
+ sub v3, a4, v4
+ mov v3, v3, asr #20
+ adds v3, v3, ip, lsr #8
+ movmi v3, #0
+ cmp v3, #255
+ movgt v3, #255
+ orr a2, a2, v3, lsl #8
+ add a4, a4, v4
+ ldrh ip, [v2, -v1]!
+ strh a2, [lr]
+ mov a3, a3, asr #20
+ and a2, ip, #255
+ adds a3, a3, a2
+ movmi a3, #0
+ cmp a3, #255
+ movgt a3, #255
+ mov a4, a4, asr #20
+ adds a4, a4, ip, lsr #8
+ movmi a4, #0
+ cmp a4, #255
+ movgt a4, #255
+ orr a2, a3, a4, lsl #8
+ strh a2, [v2]
+
+ ldmfd sp!, {a3, a4}
+ ldrh ip, [lr, v1]!
+ add a2, a3, v5
+ mov a2, a2, asr #20
+ sub a3, a3, v5
+ and v3, ip, #255
+ adds a2, a2, v3
+ movmi a2, #0
+ cmp a2, #255
+ movgt a2, #255
+ add v3, a4, v6
+ mov v3, v3, asr #20
+ adds v3, v3, ip, lsr #8
+ movmi v3, #0
+ cmp v3, #255
+ movgt v3, #255
+ orr a2, a2, v3, lsl #8
+ sub a4, a4, v6
+ ldrh ip, [v2, -v1]!
+ strh a2, [lr]
+ mov a3, a3, asr #20
+ and a2, ip, #255
+ adds a3, a3, a2
+ movmi a3, #0
+ cmp a3, #255
+ movgt a3, #255
+ mov a4, a4, asr #20
+ adds a4, a4, ip, lsr #8
+ movmi a4, #0
+ cmp a4, #255
+ movgt a4, #255
+ orr a2, a3, a4, lsl #8
+ strh a2, [v2]
+
+ ldmfd sp!, {a3, a4}
+ ldrh ip, [lr, v1]!
+ add a2, a3, v7
+ mov a2, a2, asr #20
+ sub a3, a3, v7
+ and v3, ip, #255
+ adds a2, a2, v3
+ movmi a2, #0
+ cmp a2, #255
+ movgt a2, #255
+ add v3, a4, fp
+ mov v3, v3, asr #20
+ adds v3, v3, ip, lsr #8
+ movmi v3, #0
+ cmp v3, #255
+ movgt v3, #255
+ orr a2, a2, v3, lsl #8
+ sub a4, a4, fp
+ ldrh ip, [v2, -v1]!
+ strh a2, [lr]
+ mov a3, a3, asr #20
+ and a2, ip, #255
+ adds a3, a3, a2
+ movmi a3, #0
+ cmp a3, #255
+ movgt a3, #255
+ mov a4, a4, asr #20
+ adds a4, a4, ip, lsr #8
+ movmi a4, #0
+ cmp a4, #255
+ movgt a4, #255
+ orr a2, a3, a4, lsl #8
+ strh a2, [v2]
+
+ ldr pc, [sp], #4
+ .endfunc
+
+ .align
+ .global simple_idct_armv5te
+ .func simple_idct_armv5te
+simple_idct_armv5te:
+ 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
+
+ .align
+ .global simple_idct_add_armv5te
+ .func simple_idct_add_armv5te
+simple_idct_add_armv5te:
+ 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
+
+ .align
+ .global simple_idct_put_armv5te
+ .func simple_idct_put_armv5te
+simple_idct_put_armv5te:
+ 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/contrib/ffmpeg/libavcodec/asv1.c b/contrib/ffmpeg/libavcodec/asv1.c
new file mode 100644
index 000000000..ec6bbb9ba
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/asv1.c
@@ -0,0 +1,655 @@
+/*
+ * ASUS V1/V2 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 asv1.c
+ * ASUS V1/V2 codec.
+ */
+
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+//#undef NDEBUG
+//#include <assert.h>
+
+#define VLC_BITS 6
+#define ASV2_LEVEL_VLC_BITS 10
+
+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_8(DCTELEM, block[6][64]);
+ DECLARE_ALIGNED_8(uint16_t, intra_matrix[64]);
+ DECLARE_ALIGNED_8(int, q_intra_matrix[64]);
+ uint8_t *bitstream_buffer;
+ unsigned int bitstream_buffer_size;
+} ASV1Context;
+
+static const uint8_t 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,
+};
+
+
+static const uint8_t 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
+};
+
+static const uint8_t level_tab[7][2]={
+ {3,4}, {3,3}, {3,2}, {0,3}, {2,2}, {2,3}, {2,4}
+};
+
+static const uint8_t dc_ccp_tab[8][2]={
+ {0x1,2}, {0xD,4}, {0xF,4}, {0xC,4},
+ {0x5,3}, {0xE,4}, {0x4,3}, {0x0,2},
+};
+
+static const uint8_t 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},
+};
+
+static const uint8_t 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},
+};
+
+
+static VLC ccp_vlc;
+static VLC level_vlc;
+static VLC dc_ccp_vlc;
+static VLC ac_ccp_vlc;
+static VLC asv2_level_vlc;
+
+static void init_vlcs(ASV1Context *a){
+ static int done = 0;
+
+ if (!done) {
+ done = 1;
+
+ init_vlc(&ccp_vlc, VLC_BITS, 17,
+ &ccp_tab[0][1], 2, 1,
+ &ccp_tab[0][0], 2, 1, 1);
+ init_vlc(&dc_ccp_vlc, VLC_BITS, 8,
+ &dc_ccp_tab[0][1], 2, 1,
+ &dc_ccp_tab[0][0], 2, 1, 1);
+ init_vlc(&ac_ccp_vlc, VLC_BITS, 16,
+ &ac_ccp_tab[0][1], 2, 1,
+ &ac_ccp_tab[0][0], 2, 1, 1);
+ init_vlc(&level_vlc, VLC_BITS, 7,
+ &level_tab[0][1], 2, 1,
+ &level_tab[0][0], 2, 1, 1);
+ init_vlc(&asv2_level_vlc, ASV2_LEVEL_VLC_BITS, 63,
+ &asv2_level_tab[0][1], 2, 1,
+ &asv2_level_tab[0][0], 2, 1, 1);
+ }
+}
+
+//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 void asv2_put_bits(PutBitContext *pb, int n, int v){
+ put_bits(pb, n, ff_reverse[ v << (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 void asv1_put_level(PutBitContext *pb, int level){
+ unsigned int index= level + 3;
+
+ if(index <= 6) put_bits(pb, level_tab[index][1], level_tab[index][0]);
+ else{
+ put_bits(pb, level_tab[3][1], level_tab[3][0]);
+ put_bits(pb, 8, level&0xFF);
+ }
+}
+
+static inline void asv2_put_level(PutBitContext *pb, int level){
+ unsigned int index= level + 31;
+
+ if(index <= 62) put_bits(pb, asv2_level_tab[index][1], asv2_level_tab[index][0]);
+ else{
+ put_bits(pb, asv2_level_tab[31][1], asv2_level_tab[31][0]);
+ asv2_put_bits(pb, 8, level&0xFF);
+ }
+}
+
+static inline int asv1_decode_block(ASV1Context *a, DCTELEM 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 -1;
+ }
+
+ 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, DCTELEM 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 void asv1_encode_block(ASV1Context *a, DCTELEM 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= 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, ccp_tab[0][1], ccp_tab[0][0]);
+
+ put_bits(&a->pb, ccp_tab[ccp][1], 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, ccp_tab[16][1], ccp_tab[16][0]);
+}
+
+static inline void asv2_encode_block(ASV1Context *a, DCTELEM block[64]){
+ int i;
+ int count=0;
+
+ for(count=63; count>3; count--){
+ const int index= 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= 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;
+
+ assert(i || ccp<8);
+ if(i) put_bits(&a->pb, ac_ccp_tab[ccp][1], ac_ccp_tab[ccp][0]);
+ else put_bits(&a->pb, dc_ccp_tab[ccp][1], 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]);
+ }
+ }
+}
+
+static inline int decode_mb(ASV1Context *a, DCTELEM block[6][64]){
+ int i;
+
+ a->dsp.clear_blocks(block[0]);
+
+ if(a->avctx->codec_id == 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 int encode_mb(ASV1Context *a, DCTELEM block[6][64]){
+ int i;
+
+ if(a->pb.buf_end - a->pb.buf - (put_bits_count(&a->pb)>>3) < 30*16*16*3/2/8){
+ av_log(a->avctx, AV_LOG_ERROR, "encoded frame too large\n");
+ return -1;
+ }
+
+ if(a->avctx->codec_id == 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 idct_put(ASV1Context *a, int mb_x, int mb_y){
+ DCTELEM (*block)[64]= a->block;
+ int linesize= a->picture.linesize[0];
+
+ uint8_t *dest_y = a->picture.data[0] + (mb_y * 16* linesize ) + mb_x * 16;
+ uint8_t *dest_cb = a->picture.data[1] + (mb_y * 8 * a->picture.linesize[1]) + mb_x * 8;
+ uint8_t *dest_cr = a->picture.data[2] + (mb_y * 8 * a->picture.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, a->picture.linesize[1], block[4]);
+ a->dsp.idct_put(dest_cr, a->picture.linesize[2], block[5]);
+ }
+}
+
+static inline void dct_get(ASV1Context *a, int mb_x, int mb_y){
+ DCTELEM (*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 decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ ASV1Context * const a = avctx->priv_data;
+ AVFrame *picture = data;
+ AVFrame * const p= (AVFrame*)&a->picture;
+ int mb_x, mb_y;
+
+ if(p->data[0])
+ avctx->release_buffer(avctx, p);
+
+ p->reference= 0;
+ if(avctx->get_buffer(avctx, p) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+ p->pict_type= I_TYPE;
+ p->key_frame= 1;
+
+ a->bitstream_buffer= av_fast_realloc(a->bitstream_buffer, &a->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+
+ if(avctx->codec_id == CODEC_ID_ASV1)
+ a->dsp.bswap_buf((uint32_t*)a->bitstream_buffer, (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( decode_mb(a, a->block) <0)
+ return -1;
+
+ idct_put(a, 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( decode_mb(a, a->block) <0)
+ return -1;
+
+ idct_put(a, 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( decode_mb(a, a->block) <0)
+ return -1;
+
+ idct_put(a, mb_x, mb_y);
+ }
+ }
+#if 0
+int i;
+printf("%d %d\n", 8*buf_size, get_bits_count(&a->gb));
+for(i=get_bits_count(&a->gb); i<8*buf_size; i++){
+ printf("%d", get_bits1(&a->gb));
+}
+
+for(i=0; i<s->avctx->extradata_size; i++){
+ printf("%c\n", ((uint8_t*)s->avctx->extradata)[i]);
+}
+#endif
+
+ *picture= *(AVFrame*)&a->picture;
+ *data_size = sizeof(AVPicture);
+
+ emms_c();
+
+ return (get_bits_count(&a->gb)+31)/32*4;
+}
+
+#ifdef CONFIG_ENCODERS
+static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
+ ASV1Context * const a = avctx->priv_data;
+ AVFrame *pict = data;
+ AVFrame * const p= (AVFrame*)&a->picture;
+ int size;
+ int mb_x, mb_y;
+
+ init_put_bits(&a->pb, buf, buf_size);
+
+ *p = *pict;
+ p->pict_type= I_TYPE;
+ p->key_frame= 1;
+
+ for(mb_y=0; mb_y<a->mb_height2; mb_y++){
+ for(mb_x=0; mb_x<a->mb_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_y<a->mb_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_x<a->mb_width; mb_x++){
+ dct_get(a, mb_x, mb_y);
+ encode_mb(a, a->block);
+ }
+ }
+ emms_c();
+
+ 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 == CODEC_ID_ASV1)
+ a->dsp.bswap_buf((uint32_t*)buf, (uint32_t*)buf, size);
+ else{
+ int i;
+ for(i=0; i<4*size; i++)
+ buf[i]= ff_reverse[ buf[i] ];
+ }
+
+ return size*4;
+}
+#endif /* CONFIG_ENCODERS */
+
+static void common_init(AVCodecContext *avctx){
+ ASV1Context * const a = avctx->priv_data;
+
+ 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= (AVFrame*)&a->picture;
+ a->avctx= avctx;
+}
+
+static int decode_init(AVCodecContext *avctx){
+ ASV1Context * const a = avctx->priv_data;
+ AVFrame *p= (AVFrame*)&a->picture;
+ int i;
+ const int scale= avctx->codec_id == CODEC_ID_ASV1 ? 1 : 2;
+
+ common_init(avctx);
+ init_vlcs(a);
+ ff_init_scantable(a->dsp.idct_permutation, &a->scantable, scantab);
+ avctx->pix_fmt= PIX_FMT_YUV420P;
+
+ a->inv_qscale= ((uint8_t*)avctx->extradata)[0];
+ if(a->inv_qscale == 0){
+ av_log(avctx, AV_LOG_ERROR, "illegal qscale 0\n");
+ if(avctx->codec_id == CODEC_ID_ASV1)
+ a->inv_qscale= 6;
+ else
+ a->inv_qscale= 10;
+ }
+
+ for(i=0; i<64; i++){
+ int index= scantab[i];
+
+ a->intra_matrix[i]= 64*scale*ff_mpeg1_default_intra_matrix[index] / a->inv_qscale;
+ }
+
+ p->qstride= a->mb_width;
+ p->qscale_table= av_malloc( p->qstride * a->mb_height);
+ p->quality= (32*scale + a->inv_qscale/2)/a->inv_qscale;
+ memset(p->qscale_table, p->quality, p->qstride*a->mb_height);
+
+ return 0;
+}
+
+#ifdef CONFIG_ENCODERS
+static int encode_init(AVCodecContext *avctx){
+ ASV1Context * const a = avctx->priv_data;
+ int i;
+ const int scale= avctx->codec_id == CODEC_ID_ASV1 ? 1 : 2;
+
+ 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]= le2me_32(a->inv_qscale);
+ ((uint32_t*)avctx->extradata)[1]= le2me_32(ff_get_fourcc("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;
+}
+#endif
+
+static int decode_end(AVCodecContext *avctx){
+ ASV1Context * const a = avctx->priv_data;
+
+ av_freep(&a->bitstream_buffer);
+ av_freep(&a->picture.qscale_table);
+ a->bitstream_buffer_size=0;
+
+ return 0;
+}
+
+AVCodec asv1_decoder = {
+ "asv1",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_ASV1,
+ sizeof(ASV1Context),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
+
+AVCodec asv2_decoder = {
+ "asv2",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_ASV2,
+ sizeof(ASV1Context),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
+
+#ifdef CONFIG_ENCODERS
+
+AVCodec asv1_encoder = {
+ "asv1",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_ASV1,
+ sizeof(ASV1Context),
+ encode_init,
+ encode_frame,
+ //encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+};
+
+AVCodec asv2_encoder = {
+ "asv2",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_ASV2,
+ sizeof(ASV1Context),
+ encode_init,
+ encode_frame,
+ //encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+};
+
+#endif //CONFIG_ENCODERS
diff --git a/contrib/ffmpeg/libavcodec/audioconvert.c b/contrib/ffmpeg/libavcodec/audioconvert.c
new file mode 100644
index 000000000..e6291ac6d
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/audioconvert.c
@@ -0,0 +1,79 @@
+/*
+ * audio conversion
+ * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/**
+ * @file audioconvert.c
+ * audio conversion
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#include "avcodec.h"
+
+int av_audio_convert(void *maybe_dspcontext_or_something_av_convert_specific,
+ void *out[6], int out_stride[6], enum SampleFormat out_fmt,
+ void * in[6], int in_stride[6], enum SampleFormat in_fmt, int len){
+ int ch;
+ const int isize= FFMIN( in_fmt+1, 4);
+ const int osize= FFMIN(out_fmt+1, 4);
+ const int fmt_pair= out_fmt + 5*in_fmt;
+
+ //FIXME optimize common cases
+
+ for(ch=0; ch<6; ch++){
+ const int is= in_stride[ch] * isize;
+ const int os= out_stride[ch] * osize;
+ uint8_t *pi= in[ch];
+ uint8_t *po= out[ch];
+ uint8_t *end= po + os;
+ if(!out[ch])
+ continue;
+
+#define CONV(ofmt, otype, ifmt, expr)\
+if(fmt_pair == ofmt + 5*ifmt){\
+ do{\
+ *(otype*)po = expr; pi += is; po += os;\
+ }while(po < end);\
+}
+
+//FIXME put things below under ifdefs so we dont waste space for cases no codec will need
+//FIXME rounding and cliping ?
+
+ CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_U8 , *(uint8_t*)pi)
+ else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_U8 , (*(uint8_t*)pi - 0x80)<<8)
+ else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_U8 , (*(uint8_t*)pi - 0x80)<<24)
+ else CONV(SAMPLE_FMT_FLT, float , SAMPLE_FMT_U8 , (*(uint8_t*)pi - 0x80)*(1.0 / (1<<7)))
+ else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_S16, (*(int16_t*)pi>>8) + 0x80)
+ else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_S16, *(int16_t*)pi)
+ else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_S16, *(int16_t*)pi<<16)
+ else CONV(SAMPLE_FMT_FLT, float , SAMPLE_FMT_S16, *(int16_t*)pi*(1.0 / (1<<15)))
+ else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_S32, (*(int32_t*)pi>>24) + 0x80)
+ else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_S32, *(int32_t*)pi>>16)
+ else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_S32, *(int32_t*)pi)
+ else CONV(SAMPLE_FMT_FLT, float , SAMPLE_FMT_S32, *(int32_t*)pi*(1.0 / (1<<31)))
+ else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_FLT, lrintf(*(float*)pi * (1<<7)) + 0x80)
+ else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_FLT, lrintf(*(float*)pi * (1<<15)))
+ else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_FLT, lrintf(*(float*)pi * (1<<31)))
+ else CONV(SAMPLE_FMT_FLT, float , SAMPLE_FMT_FLT, *(float*)pi)
+ else return -1;
+ }
+ return 0;
+}
diff --git a/contrib/ffmpeg/libavcodec/avcodec.h b/contrib/ffmpeg/libavcodec/avcodec.h
new file mode 100644
index 000000000..da063b562
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/avcodec.h
@@ -0,0 +1,2707 @@
+/*
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_H
+#define AVCODEC_H
+
+/**
+ * @file avcodec.h
+ * external api header.
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "avutil.h"
+#include <sys/types.h> /* size_t */
+
+#define AV_STRINGIFY(s) AV_TOSTRING(s)
+#define AV_TOSTRING(s) #s
+
+#define LIBAVCODEC_VERSION_INT ((51<<16)+(25<<8)+0)
+#define LIBAVCODEC_VERSION 51.25.0
+#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT
+
+#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION)
+
+#define AV_NOPTS_VALUE int64_t_C(0x8000000000000000)
+#define AV_TIME_BASE 1000000
+#define AV_TIME_BASE_Q (AVRational){1, AV_TIME_BASE}
+
+enum CodecID {
+ CODEC_ID_NONE,
+ CODEC_ID_MPEG1VIDEO,
+ CODEC_ID_MPEG2VIDEO, /* prefered ID for MPEG Video 1 or 2 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_SNOW,
+ CODEC_ID_TSCC,
+ CODEC_ID_ULTI,
+ CODEC_ID_QDRAW,
+ CODEC_ID_VIXL,
+ CODEC_ID_QPEG,
+ CODEC_ID_XVID,
+ 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,
+
+ /* various pcm "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,
+
+ /* 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,
+
+ /* 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,
+
+ CODEC_ID_MP2= 0x15000,
+ CODEC_ID_MP3, /* prefered ID for MPEG Audio layer 1, 2 or3 decoding */
+ CODEC_ID_AAC,
+#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
+ CODEC_ID_MPEG4AAC,
+#endif
+ 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_SONIC,
+ CODEC_ID_SONIC_LS,
+ CODEC_ID_FLAC,
+ CODEC_ID_MP3ADU,
+ CODEC_ID_MP3ON4,
+ CODEC_ID_SHORTEN,
+ CODEC_ID_ALAC,
+ CODEC_ID_WESTWOOD_SND1,
+ CODEC_ID_GSM,
+ 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,
+
+ /* subtitle codecs */
+ CODEC_ID_DVD_SUBTITLE= 0x17000,
+ CODEC_ID_DVB_SUBTITLE,
+
+ CODEC_ID_MPEG2TS= 0x20000, /* _FAKE_ codec to indicate a raw MPEG2 transport
+ stream (only used by libavformat) */
+};
+
+/* CODEC_ID_MP3LAME is absolete */
+#define CODEC_ID_MP3LAME CODEC_ID_MP3
+
+enum CodecType {
+ CODEC_TYPE_UNKNOWN = -1,
+ CODEC_TYPE_VIDEO,
+ CODEC_TYPE_AUDIO,
+ CODEC_TYPE_DATA,
+ CODEC_TYPE_SUBTITLE,
+};
+
+/* currently unused, may be used if 24/32 bits samples ever supported */
+/* all in native endian */
+enum SampleFormat {
+ SAMPLE_FMT_NONE = -1,
+ SAMPLE_FMT_U8, ///< unsigned 8 bits
+ SAMPLE_FMT_S16, ///< signed 16 bits
+ SAMPLE_FMT_S24, ///< signed 24 bits
+ SAMPLE_FMT_S32, ///< signed 32 bits
+ SAMPLE_FMT_FLT, ///< float
+};
+
+/* in bytes */
+#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio
+
+/**
+ * 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<br>
+ * 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 8
+
+/**
+ * minimum encoding buffer size.
+ * used to avoid some checks during header writing
+ */
+#define FF_MIN_BUFFER_SIZE 16384
+
+/* motion estimation type, EPZS by default */
+enum Motion_Est_ID {
+ ME_ZERO = 1,
+ ME_FULL,
+ ME_LOG,
+ ME_PHODS,
+ ME_EPZS,
+ ME_X1,
+ ME_HEX,
+ ME_UMH,
+ ME_ITER,
+};
+
+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
+};
+
+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 initing
+ 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 H263
+#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>
+#define CODEC_FLAG_PART 0x0080 ///< use data partitioning
+/* parent program gurantees that the input for b-frame containing streams is not written to
+ for at least s->max_b_frames+1 frames, if this is not set than 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_EXTERN_HUFF 0x1000 ///< use external huffman table (for mjpeg)
+#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_ALT_SCAN 0x00100000 ///< use alternate scan
+#define CODEC_FLAG_TRELLIS_QUANT 0x00200000 ///< use trellis quantization
+#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_H263P_AIC 0x01000000 ///< H263 Advanced intra coding / MPEG4 AC prediction (remove this)
+#define CODEC_FLAG_AC_PRED 0x01000000 ///< H263 Advanced intra coding / MPEG4 AC prediction
+#define CODEC_FLAG_H263P_UMV 0x02000000 ///< Unlimited motion vector
+#define CODEC_FLAG_CBP_RD 0x04000000 ///< use rate distortion optimization for cbp
+#define CODEC_FLAG_QP_RD 0x08000000 ///< use rate distortion optimization for qp selectioon
+#define CODEC_FLAG_H263P_AIV 0x00000008 ///< H263 Alternative inter vlc
+#define CODEC_FLAG_OBMC 0x00000001 ///< OBMC
+#define CODEC_FLAG_LOOP_FILTER 0x00000800 ///< loop filter
+#define CODEC_FLAG_H263P_SLICE_STRUCT 0x10000000
+#define CODEC_FLAG_INTERLACED_ME 0x20000000 ///< interlaced motion estimation
+#define CODEC_FLAG_SVCD_SCAN_OFFSET 0x40000000 ///< will reserve space for SVCD scan offset user data
+#define CODEC_FLAG_CLOSED_GOP ((int)0x80000000)
+#define CODEC_FLAG2_FAST 0x00000001 ///< allow non spec compliant speedup tricks
+#define CODEC_FLAG2_STRICT_GOP 0x00000002 ///< strictly enforce GOP size
+#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_BPYRAMID 0x00000010 ///< H.264 allow b-frames to be used as references
+#define CODEC_FLAG2_WPRED 0x00000020 ///< H.264 weighted biprediction for b-frames
+#define CODEC_FLAG2_MIXED_REFS 0x00000040 ///< H.264 multiple references per partition
+#define CODEC_FLAG2_8X8DCT 0x00000080 ///< H.264 high profile 8x8 transform
+#define CODEC_FLAG2_FASTPSKIP 0x00000100 ///< H.264 fast pskip
+#define CODEC_FLAG2_AUD 0x00000200 ///< H.264 access unit delimiters
+#define CODEC_FLAG2_BRDO 0x00000400 ///< b-frame rate-distortion optimization
+#define CODEC_FLAG2_INTRA_VLC 0x00000800 ///< use MPEG-2 intra VLC table
+#define CODEC_FLAG2_MEMC_ONLY 0x00001000 ///< only do ME/MC (I frames -> ref, P frame -> ME+MC)
+#define CODEC_FLAG2_DROP_FRAME_TIMECODE 0x00002000 ///< timecode is in drop frame format
+
+/* Unsupported options :
+ * Syntax Arithmetic coding (SAC)
+ * Reference Picture Selection
+ * Independant 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.
+ * direct rendering method 1
+ */
+#define CODEC_CAP_DR1 0x0002
+/* if 'parse_only' field is true, then avcodec_parse_frame() can be
+ used */
+#define CODEC_CAP_PARSE_ONLY 0x0004
+#define CODEC_CAP_TRUNCATED 0x0008
+/* codec can export data for HW decoding (XvMC) */
+#define CODEC_CAP_HWACCEL 0x0010
+/**
+ * codec has a non zero delay and needs to be feeded with NULL at the end to get the delayed data.
+ * if this is not set, the codec is guranteed to never be feeded with NULL data
+ */
+#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
+
+//the following defines may change, don't expect compatibility if you use them
+#define MB_TYPE_INTRA4x4 0x0001
+#define MB_TYPE_INTRA16x16 0x0002 //FIXME h264 specific
+#define MB_TYPE_INTRA_PCM 0x0004 //FIXME h264 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 lavc
+ */
+ int id;
+
+ /**
+ * width and height in 1/16 pel
+ * - encoding: set by user.
+ * - decoding: set by lavc
+ */
+ 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 lavc
+ */
+ int16_t position[3][2];
+}AVPanScan;
+
+#define FF_COMMON_FRAME \
+ /**\
+ * pointer to the picture planes.\
+ * this might be different from the first allocated byte\
+ * - encoding: \
+ * - decoding: \
+ */\
+ uint8_t *data[4];\
+ int linesize[4];\
+ /**\
+ * pointer to the first allocated byte of the picture. can be used in get_buffer/release_buffer\
+ * this isn't used by lavc unless the default get/release_buffer() is used\
+ * - encoding: \
+ * - decoding: \
+ */\
+ uint8_t *base[4];\
+ /**\
+ * 1 -> keyframe, 0-> not\
+ * - encoding: set by lavc\
+ * - decoding: set by lavc\
+ */\
+ int key_frame;\
+\
+ /**\
+ * picture type of the frame, see ?_TYPE below.\
+ * - encoding: set by lavc for coded_picture (and set by user for input)\
+ * - decoding: set by lavc\
+ */\
+ int pict_type;\
+\
+ /**\
+ * presentation timestamp in time_base units (time when frame should be shown to user)\
+ * if AV_NOPTS_VALUE then frame_rate = 1/time_base will be assumed\
+ * - encoding: MUST be set by user\
+ * - decoding: set by lavc\
+ */\
+ int64_t pts;\
+\
+ /**\
+ * picture number in bitstream order.\
+ * - encoding: set by\
+ * - decoding: set by lavc\
+ */\
+ int coded_picture_number;\
+ /**\
+ * picture number in display order.\
+ * - encoding: set by\
+ * - decoding: set by lavc\
+ */\
+ int display_picture_number;\
+\
+ /**\
+ * quality (between 1 (good) and FF_LAMBDA_MAX (bad)) \
+ * - encoding: set by lavc for coded_picture (and set by user for input)\
+ * - decoding: set by lavc\
+ */\
+ int quality; \
+\
+ /**\
+ * buffer age (1->was last buffer and dint change, 2->..., ...).\
+ * set to INT_MAX if the buffer has not been used yet \
+ * - encoding: unused\
+ * - decoding: MUST be set by get_buffer()\
+ */\
+ int age;\
+\
+ /**\
+ * is this picture used as reference\
+ * - encoding: unused\
+ * - decoding: set by lavc (before get_buffer() call))\
+ */\
+ int reference;\
+\
+ /**\
+ * QP table\
+ * - encoding: unused\
+ * - decoding: set by lavc\
+ */\
+ int8_t *qscale_table;\
+ /**\
+ * QP store stride\
+ * - encoding: unused\
+ * - decoding: set by lavc\
+ */\
+ int qstride;\
+\
+ /**\
+ * mbskip_table[mb]>=1 if MB didnt change\
+ * stride= mb_width = (width+15)>>4\
+ * - encoding: unused\
+ * - decoding: set by lavc\
+ */\
+ uint8_t *mbskip_table;\
+\
+ /**\
+ * Motion vector table.\
+ * @code\
+ * example:\
+ * int mv_sample_log2= 4 - motion_subsample_log2;\
+ * int mb_width= (width+15)>>4;\
+ * int mv_stride= (mb_width << mv_sample_log2) + 1;\
+ * motion_val[direction][x + y*mv_stride][0->mv_x, 1->mv_y];\
+ * @endcode\
+ * - encoding: set by user\
+ * - decoding: set by lavc\
+ */\
+ int16_t (*motion_val[2])[2];\
+\
+ /**\
+ * Macroblock type table\
+ * mb_type_base + mb_width + 2\
+ * - encoding: set by user\
+ * - decoding: set by lavc\
+ */\
+ uint32_t *mb_type;\
+\
+ /**\
+ * log2 of the size of the block which a single vector in motion_val represents: \
+ * (4->16x16, 3->8x8, 2-> 4x4, 1-> 2x2)\
+ * - encoding: unused\
+ * - decoding: set by lavc\
+ */\
+ uint8_t motion_subsample_log2;\
+\
+ /**\
+ * for some private data of the user\
+ * - encoding: unused\
+ * - decoding: set by user\
+ */\
+ void *opaque;\
+\
+ /**\
+ * error\
+ * - encoding: set by lavc if flags&CODEC_FLAG_PSNR\
+ * - decoding: unused\
+ */\
+ uint64_t error[4];\
+\
+ /**\
+ * type of the buffer (to keep track of who has to dealloc data[*])\
+ * - encoding: set by the one who allocs it\
+ * - decoding: set by the one who allocs it\
+ * Note: user allocated (direct rendering) & internal buffers can not coexist currently\
+ */\
+ int type;\
+ \
+ /**\
+ * when decoding, this signal how much the picture must be delayed.\
+ * extra_delay = repeat_pict / (2*fps)\
+ * - encoding: unused\
+ * - decoding: set by lavc\
+ */\
+ int repeat_pict;\
+ \
+ /**\
+ * \
+ */\
+ int qscale_type;\
+ \
+ /**\
+ * The content of the picture is interlaced.\
+ * - encoding: set by user\
+ * - decoding: set by lavc (default 0)\
+ */\
+ int interlaced_frame;\
+ \
+ /**\
+ * if the content is interlaced, is top field displayed first.\
+ * - encoding: set by user\
+ * - decoding: set by lavc\
+ */\
+ int top_field_first;\
+ \
+ /**\
+ * Pan scan.\
+ * - encoding: set by user\
+ * - decoding: set by lavc\
+ */\
+ AVPanScan *pan_scan;\
+ \
+ /**\
+ * tell user application that palette has changed from previous frame.\
+ * - encoding: ??? (no palette-enabled encoder yet)\
+ * - decoding: set by lavc (default 0)\
+ */\
+ int palette_has_changed;\
+ \
+ /**\
+ * Codec suggestion on buffer type if != 0\
+ * - encoding: unused\
+ * - decoding: set by lavc (before get_buffer() call))\
+ */\
+ int buffer_hints;\
+\
+ /**\
+ * DCT coeffitients\
+ * - encoding: unused\
+ * - decoding: set by lavc\
+ */\
+ short *dct_coeff;\
+\
+ /**\
+ * Motion referece frame index\
+ * - encoding: set by user\
+ * - decoding: set by lavc\
+ */\
+ int8_t *ref_index[2];
+
+#define FF_QSCALE_TYPE_MPEG1 0
+#define FF_QSCALE_TYPE_MPEG2 1
+#define FF_QSCALE_TYPE_H264 2
+
+#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 dealloc 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 dealloc anything
+
+
+#define FF_I_TYPE 1 // Intra
+#define FF_P_TYPE 2 // Predicted
+#define FF_B_TYPE 3 // Bi-dir predicted
+#define FF_S_TYPE 4 // S(GMC)-VOP MPEG4
+#define FF_SI_TYPE 5
+#define FF_SP_TYPE 6
+
+#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)
+
+/**
+ * Audio Video Frame.
+ */
+typedef struct AVFrame {
+ FF_COMMON_FRAME
+} AVFrame;
+
+#define DEFAULT_FRAME_RATE_BASE 1001000
+
+/**
+ * main external api structure.
+ */
+typedef struct AVCodecContext {
+ /**
+ * Info on struct for av_log
+ * - set by avcodec_alloc_context
+ */
+ AVClass *av_class;
+ /**
+ * the average bitrate.
+ * - encoding: set by user. unused for constant quantizer encoding
+ * - decoding: set by lavc. 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;
+
+ /**
+ * CODEC_FLAG_*.
+ * - encoding: set by user.
+ * - decoding: set by user.
+ */
+ int flags;
+
+ /**
+ * some codecs needs additionnal format info. It is stored here
+ * - encoding: set by user.
+ * - decoding: set by lavc. (FIXME is this ok?)
+ */
+ int sub_id;
+
+ /**
+ * 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) [7, 8 are x264 specific, 9 is snow specific]
+ * - encoding: MUST be set by user.
+ * - decoding: unused
+ */
+ int me_method;
+
+ /**
+ * some codecs need / can use extra-data 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
+ * then extradata_size to avoid prolems if its read with the bitstream reader
+ * the bytewise contents of extradata must not depend on the architecture or cpu endianness
+ * - encoding: set/allocated/freed by lavc.
+ * - 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 lavc.
+ */
+ AVRational time_base;
+
+ /* video only */
+ /**
+ * picture width / height.
+ * - encoding: MUST be set by user.
+ * - decoding: set by lavc.
+ * Note, for compatibility its possible to set this instead of
+ * coded_width/height before decoding
+ */
+ int width, height;
+
+#define FF_ASPECT_EXTENDED 15
+
+ /**
+ * the number of pictures in a group of pitures, or 0 for intra_only.
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int gop_size;
+
+ /**
+ * pixel format, see PIX_FMT_xxx.
+ * - encoding: set by user.
+ * - decoding: set by lavc.
+ */
+ enum PixelFormat pix_fmt;
+
+ /**
+ * Frame rate emulation. If not zero lower layer (i.e. format handler)
+ * has to read frames at native frame rate.
+ * - encoding: set by user.
+ * - decoding: unused.
+ */
+ int rate_emu;
+
+ /**
+ * if non NULL, 'draw_horiz_band' is called by the libavcodec
+ * decoder to draw an horizontal band. It improve cache usage. Not
+ * all codecs can do that. You must check the codec capabilities
+ * before
+ * - 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[4],
+ int y, int type, int height);
+
+ /* audio only */
+ int sample_rate; ///< samples per sec
+ int channels;
+
+ /**
+ * audio sample format.
+ * - encoding: set by user.
+ * - decoding: set by lavc.
+ */
+ enum SampleFormat sample_fmt; ///< sample format, currenly unused
+
+ /* the following data should not be initialized */
+ /**
+ * samples per packet. initialized when calling 'init'
+ */
+ int frame_size;
+ int frame_number; ///< audio or video frame number
+ int real_pict_num; ///< returns the real picture number of previous encoded frame
+
+ /**
+ * number of frames the decoded output will be delayed relative to
+ * the encoded input.
+ * - encoding: set by lavc.
+ * - decoding: unused
+ */
+ int delay;
+
+ /* - 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 etween frames.
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int max_qdiff;
+
+ /**
+ * 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.
+ * - 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;
+
+ /**
+ * hurry up amount.
+ * deprecated in favor of skip_idct and skip_frame
+ * - encoding: unused
+ * - decoding: set by user. 1-> skip b frames, 2-> skip idct/dequant too, 5-> skip everything except header
+ */
+ int hurry_up;
+
+ struct AVCodec *codec;
+
+ void *priv_data;
+
+ /* unused, FIXME remove*/
+ int rtp_mode;
+
+ int rtp_payload_size; /* The size of the RTP payload: the coder will */
+ /* do it's 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 transmited RTP payload */
+
+
+ /* The RTP callback: This function is called */
+ /* every time the encoder has a packet to send */
+ /* 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);
+
+ /* 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 lavc
+ * - decoding: unused
+ */
+ int frame_bits;
+
+ /**
+ * private data of the user, can be used to carry app specific stuff.
+ * - encoding: set by user
+ * - decoding: set by user
+ */
+ void *opaque;
+
+ char codec_name[32];
+ enum CodecType codec_type; /* see CODEC_TYPE_xxx */
+ enum CodecID codec_id; /* see CODEC_ID_xxx */
+
+ /**
+ * fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A').
+ * this is used to workaround some encoder bugs
+ * - encoding: set by user, if not then the default based on codec_id will be used
+ * - decoding: set by user, will be converted to upper case by lavc during init
+ */
+ unsigned int codec_tag;
+
+ /**
+ * workaround 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 ///< workaround various bugs in microsofts broken decoders
+//#define FF_BUG_FAKE_SCALABILITY 16 //autodetection should work 100%
+
+ /**
+ * luma single coeff elimination threshold.
+ * - encoding: set by user
+ * - decoding: unused
+ */
+ int luma_elim_threshold;
+
+ /**
+ * chroma single coeff elimination threshold.
+ * - encoding: set by user
+ * - decoding: unused
+ */
+ int chroma_elim_threshold;
+
+ /**
+ * strictly follow the std (MPEG4, ...).
+ * - encoding: set by user
+ * - decoding: unused
+ */
+ int strict_std_compliance;
+#define FF_COMPLIANCE_VERY_STRICT 2 ///< strictly conform to a 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_INOFFICIAL -1 ///< allow inofficial extensions
+#define FF_COMPLIANCE_EXPERIMENTAL -2 ///< allow non standarized experimental things
+
+ /**
+ * qscale offset 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_offset;
+
+ /**
+ * error resilience higher values will detect more errors but may missdetect
+ * some more or less valid parts as errors.
+ * - encoding: unused
+ * - decoding: set by user
+ */
+ int error_resilience;
+#define FF_ER_CAREFUL 1
+#define FF_ER_COMPLIANT 2
+#define FF_ER_AGGRESSIVE 3
+#define FF_ER_VERY_AGGRESSIVE 4
+
+ /**
+ * called at the beginning of each frame to get a buffer for it.
+ * if pic.reference is set then the frame will be read later by lavc
+ * avcodec_align_dimensions() should be used to find the required width and
+ * height, as they normally need to be rounded up to the next multiple of 16
+ * - encoding: unused
+ * - decoding: set by lavc, user can override
+ */
+ int (*get_buffer)(struct AVCodecContext *c, AVFrame *pic);
+
+ /**
+ * called to release buffers which where allocated with get_buffer.
+ * a released buffer can be reused in get_buffer()
+ * pic.data[*] must be set to NULL
+ * - encoding: unused
+ * - decoding: set by lavc, user can override
+ */
+ void (*release_buffer)(struct AVCodecContext *c, AVFrame *pic);
+
+ /**
+ * if 1 the stream has a 1 frame delay during decoding.
+ * - encoding: set by lavc
+ * - decoding: set by lavc
+ */
+ int has_b_frames;
+
+ /**
+ * number of bytes per packet if constant and known or 0
+ * used by some WAV based audio codecs
+ */
+ int block_align;
+
+ int parse_only; /* - decoding only: if true, only parsing is done
+ (function avcodec_parse_frame()). The frame
+ data is returned. Only MPEG codecs support this now. */
+
+ /**
+ * 0-> h263 quant 1-> mpeg quant.
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int mpeg_quant;
+
+ /**
+ * pass1 encoding statistics output buffer.
+ * - encoding: set by lavc
+ * - 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;
+
+ /**
+ * ratecontrol qmin qmax limiting method.
+ * 0-> clipping, 1-> use a nice continous function to limit qscale wthin qmin/qmax
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ float rc_qsquish;
+
+ float rc_qmod_amp;
+ int rc_qmod_freq;
+
+ /**
+ * ratecontrol override, see RcOverride.
+ * - encoding: allocated/set/freed by user.
+ * - decoding: unused
+ */
+ RcOverride *rc_override;
+ int rc_override_count;
+
+ /**
+ * rate control equation.
+ * - encoding: set by user
+ * - decoding: unused
+ */
+ 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;
+
+ /**
+ * decoder bitstream buffer size.
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int rc_buffer_size;
+ float rc_buffer_aggressivity;
+
+ /**
+ * 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;
+
+ /**
+ * initial complexity for pass1 ratecontrol.
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ float rc_initial_cplx;
+
+ /**
+ * 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_MLIB 4
+#define FF_DCT_ALTIVEC 5
+#define FF_DCT_FAAN 6
+
+ /**
+ * 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;
+
+
+ /* for binary compatibility */
+ int unused;
+
+ /**
+ * 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_LIBMPEG2MMX 4
+#define FF_IDCT_PS2 5
+#define FF_IDCT_MLIB 6
+#define FF_IDCT_ARM 7
+#define FF_IDCT_ALTIVEC 8
+#define FF_IDCT_SH4 9
+#define FF_IDCT_SIMPLEARM 10
+#define FF_IDCT_H264 11
+#define FF_IDCT_VP3 12
+#define FF_IDCT_IPP 13
+#define FF_IDCT_XVIDMMX 14
+#define FF_IDCT_CAVS 15
+#define FF_IDCT_SIMPLEARMV5TE 16
+
+ /**
+ * slice count.
+ * - encoding: set by lavc
+ * - decoding: set by user (or 0)
+ */
+ int slice_count;
+ /**
+ * slice offsets in the frame in bytes.
+ * - encoding: set/allocated by lavc
+ * - decoding: set/allocated by user (or NULL)
+ */
+ int *slice_offset;
+
+ /**
+ * error concealment flags.
+ * - encoding: unused
+ * - decoding: set by user
+ */
+ int error_concealment;
+#define FF_EC_GUESS_MVS 1
+#define FF_EC_DEBLOCK 2
+
+ /**
+ * dsp_mask could be add used to disable unwanted CPU features
+ * CPU features (i.e. MMX, SSE. ...)
+ *
+ * with FORCE flag you may instead enable given CPU features
+ * (Dangerous: usable in case of misdetection, improper usage however will
+ * result into program crash)
+ */
+ unsigned dsp_mask;
+#define FF_MM_FORCE 0x80000000 /* force usage of selected flags (OR) */
+ /* lower 16 bits - CPU features */
+#ifdef HAVE_MMX
+#define FF_MM_MMX 0x0001 /* standard MMX */
+#define FF_MM_3DNOW 0x0004 /* AMD 3DNOW */
+#define FF_MM_MMXEXT 0x0002 /* SSE integer functions or AMD MMX ext */
+#define FF_MM_SSE 0x0008 /* SSE functions */
+#define FF_MM_SSE2 0x0010 /* PIV SSE2 functions */
+#define FF_MM_3DNOWEXT 0x0020 /* AMD 3DNowExt */
+#endif /* HAVE_MMX */
+#ifdef HAVE_IWMMXT
+#define FF_MM_IWMMXT 0x0100 /* XScale IWMMXT */
+#endif /* HAVE_IWMMXT */
+
+ /**
+ * bits per sample/pixel from the demuxer (needed for huffyuv).
+ * - encoding: set by lavc
+ * - decoding: set by user
+ */
+ int bits_per_sample;
+
+ /**
+ * 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
+
+ /**
+ * sample aspect ratio (0 if unknown).
+ * numerator and denominator must be relative prime and smaller then 256 for some video standards
+ * - encoding: set by user.
+ * - decoding: set by lavc.
+ */
+ AVRational sample_aspect_ratio;
+
+ /**
+ * the picture in the bitstream.
+ * - encoding: set by lavc
+ * - decoding: set by lavc
+ */
+ AVFrame *coded_frame;
+
+ /**
+ * 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
+
+ /**
+ * 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.
+ * - encoding: set by lavc if flags&CODEC_FLAG_PSNR
+ * - decoding: unused
+ */
+ uint64_t error[4];
+
+ /**
+ * minimum MB quantizer.
+ * - encoding: unused
+ * - decoding: unused
+ */
+ int mb_qmin;
+
+ /**
+ * maximum MB quantizer.
+ * - encoding: unused
+ * - decoding: unused
+ */
+ int mb_qmax;
+
+ /**
+ * motion estimation compare function.
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int me_cmp;
+ /**
+ * subpixel motion estimation compare function.
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int me_sub_cmp;
+ /**
+ * macroblock compare function (not supported yet).
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int mb_cmp;
+ /**
+ * interlaced dct compare 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;
+
+ /**
+ * pre pass for motion estimation.
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int pre_me;
+
+ /**
+ * motion estimation pre pass compare function.
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int me_pre_cmp;
+
+ /**
+ * ME pre pass 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;
+
+ /**
+ * callback to negotiate the pixelFormat.
+ * @param fmt is the list of formats which are supported by the codec,
+ * its terminated by -1 as 0 is a valid format, the formats are ordered by quality
+ * the first is allways the native one
+ * @return the choosen format
+ * - encoding: unused
+ * - decoding: set by user, if not set then the native format will always be choosen
+ */
+ enum PixelFormat (*get_format)(struct AVCodecContext *s, const enum PixelFormat * fmt);
+
+ /**
+ * DTG active format information (additionnal aspect ratio
+ * information only used in DVB MPEG2 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;
+
+ /**
+ * color table ID.
+ * - encoding: unused.
+ * - decoding: which clrtable should be used for 8bit RGB images
+ * table have to be stored somewhere FIXME
+ */
+ int color_table_id;
+
+ /**
+ * internal_buffer count.
+ * Don't touch, used by lavc default_get_buffer()
+ */
+ int internal_buffer_count;
+
+ /**
+ * internal_buffers.
+ * Don't touch, used by lavc default_get_buffer()
+ */
+ void *internal_buffer;
+
+#define FF_LAMBDA_SHIFT 7
+#define FF_LAMBDA_SCALE (1<<FF_LAMBDA_SHIFT)
+#define FF_QP2LAMBDA 118 ///< factor to convert from H.263 QP to lambda
+#define FF_LAMBDA_MAX (256*128-1)
+
+#define FF_QUALITY_SCALE FF_LAMBDA_SCALE //FIXME maybe remove
+ /**
+ * global quality for codecs which cannot change it per frame.
+ * this should be proportional to MPEG1/2/4 qscale.
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int global_quality;
+
+#define FF_CODER_TYPE_VLC 0
+#define FF_CODER_TYPE_AC 1
+ /**
+ * coder type
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int coder_type;
+
+ /**
+ * context model
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int context_model;
+#if 0
+ /**
+ *
+ * - encoding: unused
+ * - decoding: set by user.
+ */
+ uint8_t * (*realloc)(struct AVCodecContext *s, uint8_t *buf, int buf_size);
+#endif
+
+ /**
+ * 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 distoration
+
+ /**
+ * custom intra quantization matrix
+ * - encoding: set by user, can be NULL
+ * - decoding: set by lavc
+ */
+ uint16_t *intra_matrix;
+
+ /**
+ * custom inter quantization matrix
+ * - encoding: set by user, can be NULL
+ * - decoding: set by lavc
+ */
+ uint16_t *inter_matrix;
+
+ /**
+ * fourcc from the AVI stream header (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A').
+ * this is used to workaround some encoder bugs
+ * - encoding: unused
+ * - decoding: set by user, will be converted to upper case by lavc during init
+ */
+ unsigned int stream_codec_tag;
+
+ /**
+ * scene change detection threshold.
+ * 0 is default, larger means fewer detected scene changes
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int scenechange_threshold;
+
+ /**
+ * minimum lagrange multipler
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int lmin;
+
+ /**
+ * maximum lagrange multipler
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int lmax;
+
+ /**
+ * Palette control structure
+ * - encoding: ??? (no palette-enabled encoder yet)
+ * - decoding: set by user.
+ */
+ struct AVPaletteControl *palctrl;
+
+ /**
+ * noise reduction strength
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int noise_reduction;
+
+ /**
+ * called at the beginning of a frame to get cr buffer for it.
+ * buffer type (size, hints) must be the same. lavc won't check it.
+ * lavc 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().
+ * - encoding: unused
+ * - decoding: set by lavc, user can override
+ */
+ int (*reget_buffer)(struct AVCodecContext *c, AVFrame *pic);
+
+ /**
+ * 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;
+
+ /**
+ *
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int inter_threshold;
+
+ /**
+ * CODEC_FLAG2_*.
+ * - encoding: set by user.
+ * - decoding: set by user.
+ */
+ int flags2;
+
+ /**
+ * simulates errors in the bitstream to test error concealment.
+ * - encoding: set by user.
+ * - decoding: unused.
+ */
+ int error_rate;
+
+ /**
+ * MP3 antialias algorithm, see FF_AA_* below.
+ * - encoding: unused
+ * - decoding: set by user
+ */
+ int antialias_algo;
+#define FF_AA_AUTO 0
+#define FF_AA_FASTINT 1 //not implemented yet
+#define FF_AA_INT 2
+#define FF_AA_FLOAT 3
+ /**
+ * Quantizer noise shaping.
+ * - encoding: set by user
+ * - decoding: unused
+ */
+ int quantizer_noise_shaping;
+
+ /**
+ * Thread count.
+ * is used to decide how many independant tasks should be passed to execute()
+ * - encoding: set by user
+ * - decoding: set by user
+ */
+ int thread_count;
+
+ /**
+ * the codec may call this to execute several independant 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 lavc, user can override
+ * - decoding: set by lavc, user can override
+ */
+ int (*execute)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg), 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;
+
+ /**
+ * Motion estimation threshold. under 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. under 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;
+
+ /**
+ * noise vs. sse weight for the nsse comparsion function.
+ * - encoding: set by user
+ * - decoding: unused
+ */
+ int nsse_weight;
+
+ /**
+ * 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;
+
+ /**
+ * profile
+ * - encoding: set by user
+ * - decoding: set by lavc
+ */
+ int profile;
+#define FF_PROFILE_UNKNOWN -99
+
+ /**
+ * level
+ * - encoding: set by user
+ * - decoding: set by lavc
+ */
+ int level;
+#define FF_LEVEL_UNKNOWN -99
+
+ /**
+ * low resolution decoding. 1-> 1/2 size, 2->1/4 size
+ * - encoding: unused
+ * - decoding: set by user
+ */
+ int lowres;
+
+ /**
+ * bitsream width / height. may be different from width/height if lowres
+ * or other things are used
+ * - encoding: unused
+ * - decoding: set by user before init if known, codec should override / dynamically change if needed
+ */
+ int coded_width, coded_height;
+
+ /**
+ * 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 comparission function
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int frame_skip_cmp;
+
+ /**
+ * 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: unused
+ * - decoding: set by user.
+ */
+ enum AVDiscard skip_loop_filter;
+
+ /**
+ *
+ * - encoding: unused
+ * - decoding: set by user.
+ */
+ enum AVDiscard skip_idct;
+
+ /**
+ *
+ * - encoding: unused
+ * - decoding: set by user.
+ */
+ enum AVDiscard skip_frame;
+
+ /**
+ *
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int bidir_refine;
+
+ /**
+ *
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int brd_scale;
+
+ /**
+ * constant rate factor - quality-based VBR - values ~correspond to qps
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ float crf;
+
+ /**
+ * constant quantization parameter rate control method
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int cqp;
+
+ /**
+ * minimum gop size
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int keyint_min;
+
+ /**
+ * number of reference frames
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int refs;
+
+ /**
+ * chroma qp offset from luma
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int chromaoffset;
+
+ /**
+ * influences how often b-frames are used
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int bframebias;
+
+ /**
+ * trellis RD quantization
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int trellis;
+
+ /**
+ * reduce fluctuations in qp (before curve compression)
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ float complexityblur;
+
+ /**
+ * in-loop deblocking filter alphac0 parameter
+ * alpha is in the range -6...6
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int deblockalpha;
+
+ /**
+ * in-loop deblocking filter beta parameter
+ * beta is in the range -6...6
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int deblockbeta;
+
+ /**
+ * macroblock subpartition sizes to consider - p8x8, p4x4, b8x8, i8x8, i4x4
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int partitions;
+#define X264_PART_I4X4 0x001 /* Analyse i4x4 */
+#define X264_PART_I8X8 0x002 /* Analyse i8x8 (requires 8x8 transform) */
+#define X264_PART_P8X8 0x010 /* Analyse p16x8, p8x16 and p8x8 */
+#define X264_PART_P4X4 0x020 /* Analyse p8x4, p4x8, p4x4 */
+#define X264_PART_B8X8 0x100 /* Analyse b16x8, b8x16 and b8x8 */
+
+ /**
+ * direct mv prediction mode - 0 (none), 1 (spatial), 2 (temporal)
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int directpred;
+
+ /**
+ * audio cutoff bandwidth (0 means "automatic") . Currently used only by FAAC
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int cutoff;
+
+ /**
+ * 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 functin used for fullpel ME
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int mv0_threshold;
+
+ /**
+ * adjusts sensitivity of b_frame_strategy 1
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int b_sensitivity;
+
+ /**
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int compression_level;
+#define FF_COMPRESSION_DEFAULT -1
+
+ /**
+ * sets whether to use LPC mode - used by FLAC encoder
+ * - encoding: set by user.
+ * - decoding: unused.
+ */
+ int use_lpc;
+
+ /**
+ * LPC coefficient precision - used by FLAC encoder
+ * - encoding: set by user.
+ * - decoding: unused.
+ */
+ int lpc_coeff_precision;
+
+ /**
+ * - encoding: set by user.
+ * - decoding: unused.
+ */
+ int min_prediction_order;
+
+ /**
+ * - encoding: set by user.
+ * - decoding: unused.
+ */
+ int max_prediction_order;
+
+ /**
+ * search method for selecting prediction order
+ * - encoding: set by user.
+ * - decoding: unused.
+ */
+ int prediction_order_method;
+
+ /**
+ * - encoding: set by user.
+ * - decoding: unused.
+ */
+ int min_partition_order;
+
+ /**
+ * - encoding: set by user.
+ * - decoding: unused.
+ */
+ int max_partition_order;
+
+ /**
+ * GOP timecode frame start number, in non drop frame format
+ * - encoding: set by user.
+ * - decoding: unused.
+ */
+ int64_t timecode_frame_start;
+} AVCodecContext;
+
+/**
+ * AVCodec.
+ */
+typedef struct AVCodec {
+ const char *name;
+ enum CodecType type;
+ enum CodecID id;
+ int priv_data_size;
+ int (*init)(AVCodecContext *);
+ int (*encode)(AVCodecContext *, uint8_t *buf, int buf_size, void *data);
+ int (*close)(AVCodecContext *);
+ int (*decode)(AVCodecContext *, void *outdata, int *outdata_size,
+ uint8_t *buf, int buf_size);
+ int capabilities;
+#if LIBAVCODEC_VERSION_INT < ((50<<16)+(0<<8)+0)
+ void *dummy; // FIXME remove next time we break binary compatibility
+#endif
+ struct AVCodec *next;
+ void (*flush)(AVCodecContext *);
+ const AVRational *supported_framerates; ///array of supported framerates, or NULL if any, array is terminated by {0,0}
+ const enum PixelFormat *pix_fmts; ///array of supported pixel formats, or NULL if unknown, array is terminanted by -1
+} AVCodec;
+
+/**
+ * four components are given, that's all.
+ * the last component is alpha
+ */
+typedef struct AVPicture {
+ uint8_t *data[4];
+ int linesize[4]; ///< number of bytes per line
+} AVPicture;
+
+/**
+ * AVPaletteControl
+ * This structure defines a method for communicating palette changes
+ * between and demuxer and a decoder.
+ * this is totally broken, palette changes should be sent as AVPackets
+ */
+#define AVPALETTE_SIZE 1024
+#define AVPALETTE_COUNT 256
+typedef struct AVPaletteControl {
+
+ /* demuxer sets this to 1 to indicate the palette has changed;
+ * decoder resets to 0 */
+ int palette_changed;
+
+ /* 4-byte ARGB palette entries, stored in native byte order; note that
+ * the individual palette components should be on a 8-bit scale; if
+ * the palette data comes from a IBM VGA native format, the component
+ * data is probably 6 bits in size and needs to be scaled */
+ unsigned int palette[AVPALETTE_COUNT];
+
+} AVPaletteControl attribute_deprecated;
+
+typedef struct AVSubtitleRect {
+ uint16_t x;
+ uint16_t y;
+ uint16_t w;
+ uint16_t h;
+ uint16_t nb_colors;
+ int linesize;
+ uint32_t *rgba_palette;
+ uint8_t *bitmap;
+} 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 */
+ uint32_t num_rects;
+ AVSubtitleRect *rects;
+} AVSubtitle;
+
+extern AVCodec ac3_encoder;
+extern AVCodec mp2_encoder;
+extern AVCodec mp3lame_encoder;
+extern AVCodec oggvorbis_encoder;
+extern AVCodec faac_encoder;
+extern AVCodec flac_encoder;
+extern AVCodec gif_encoder;
+extern AVCodec xvid_encoder;
+extern AVCodec mpeg1video_encoder;
+extern AVCodec mpeg2video_encoder;
+extern AVCodec h261_encoder;
+extern AVCodec h263_encoder;
+extern AVCodec h263p_encoder;
+extern AVCodec flv_encoder;
+extern AVCodec rv10_encoder;
+extern AVCodec rv20_encoder;
+extern AVCodec dvvideo_encoder;
+extern AVCodec mjpeg_encoder;
+extern AVCodec ljpeg_encoder;
+extern AVCodec jpegls_encoder;
+extern AVCodec png_encoder;
+extern AVCodec ppm_encoder;
+extern AVCodec pgm_encoder;
+extern AVCodec pgmyuv_encoder;
+extern AVCodec pbm_encoder;
+extern AVCodec pam_encoder;
+extern AVCodec mpeg4_encoder;
+extern AVCodec msmpeg4v1_encoder;
+extern AVCodec msmpeg4v2_encoder;
+extern AVCodec msmpeg4v3_encoder;
+extern AVCodec wmv1_encoder;
+extern AVCodec wmv2_encoder;
+extern AVCodec huffyuv_encoder;
+extern AVCodec ffvhuff_encoder;
+extern AVCodec h264_encoder;
+extern AVCodec asv1_encoder;
+extern AVCodec asv2_encoder;
+extern AVCodec vcr1_encoder;
+extern AVCodec ffv1_encoder;
+extern AVCodec snow_encoder;
+extern AVCodec vorbis_encoder;
+extern AVCodec mdec_encoder;
+extern AVCodec zlib_encoder;
+extern AVCodec sonic_encoder;
+extern AVCodec sonic_ls_encoder;
+extern AVCodec svq1_encoder;
+extern AVCodec x264_encoder;
+
+extern AVCodec gif_decoder;
+extern AVCodec h263_decoder;
+extern AVCodec h261_decoder;
+extern AVCodec mpeg4_decoder;
+extern AVCodec msmpeg4v1_decoder;
+extern AVCodec msmpeg4v2_decoder;
+extern AVCodec msmpeg4v3_decoder;
+extern AVCodec wmv1_decoder;
+extern AVCodec wmv2_decoder;
+extern AVCodec vc1_decoder;
+extern AVCodec wmv3_decoder;
+extern AVCodec mpeg1video_decoder;
+extern AVCodec mpeg2video_decoder;
+extern AVCodec mpegvideo_decoder;
+extern AVCodec mpeg_xvmc_decoder;
+extern AVCodec h263i_decoder;
+extern AVCodec flv_decoder;
+extern AVCodec rv10_decoder;
+extern AVCodec rv20_decoder;
+extern AVCodec rv30_decoder;
+extern AVCodec rv40_decoder;
+extern AVCodec svq1_decoder;
+extern AVCodec svq3_decoder;
+extern AVCodec dvvideo_decoder;
+extern AVCodec wmav1_decoder;
+extern AVCodec wmav2_decoder;
+extern AVCodec mjpeg_decoder;
+extern AVCodec mjpegb_decoder;
+extern AVCodec sp5x_decoder;
+extern AVCodec png_decoder;
+extern AVCodec mp2_decoder;
+extern AVCodec mp3_decoder;
+extern AVCodec mp3adu_decoder;
+extern AVCodec mp3on4_decoder;
+extern AVCodec qdm2_decoder;
+extern AVCodec cook_decoder;
+extern AVCodec truespeech_decoder;
+extern AVCodec tta_decoder;
+extern AVCodec mace3_decoder;
+extern AVCodec mace6_decoder;
+extern AVCodec huffyuv_decoder;
+extern AVCodec ffvhuff_decoder;
+extern AVCodec oggvorbis_decoder;
+extern AVCodec cyuv_decoder;
+extern AVCodec h264_decoder;
+extern AVCodec indeo3_decoder;
+extern AVCodec vp3_decoder;
+extern AVCodec theora_decoder;
+extern AVCodec vp5_decoder;
+extern AVCodec vp6_decoder;
+extern AVCodec vp6f_decoder;
+extern AVCodec amr_nb_decoder;
+extern AVCodec amr_nb_encoder;
+extern AVCodec amr_wb_encoder;
+extern AVCodec amr_wb_decoder;
+extern AVCodec aac_decoder;
+extern AVCodec mpeg4aac_decoder;
+extern AVCodec asv1_decoder;
+extern AVCodec asv2_decoder;
+extern AVCodec vcr1_decoder;
+extern AVCodec cljr_decoder;
+extern AVCodec ffv1_decoder;
+extern AVCodec snow_decoder;
+extern AVCodec fourxm_decoder;
+extern AVCodec mdec_decoder;
+extern AVCodec roq_decoder;
+extern AVCodec interplay_video_decoder;
+extern AVCodec xan_wc3_decoder;
+extern AVCodec rpza_decoder;
+extern AVCodec cinepak_decoder;
+extern AVCodec msrle_decoder;
+extern AVCodec msvideo1_decoder;
+extern AVCodec vqa_decoder;
+extern AVCodec idcin_decoder;
+extern AVCodec eightbps_decoder;
+extern AVCodec smc_decoder;
+extern AVCodec flic_decoder;
+extern AVCodec vmdvideo_decoder;
+extern AVCodec vmdaudio_decoder;
+extern AVCodec truemotion1_decoder;
+extern AVCodec truemotion2_decoder;
+extern AVCodec mszh_decoder;
+extern AVCodec zlib_decoder;
+extern AVCodec ra_144_decoder;
+extern AVCodec ra_288_decoder;
+extern AVCodec roq_dpcm_decoder;
+extern AVCodec interplay_dpcm_decoder;
+extern AVCodec xan_dpcm_decoder;
+extern AVCodec sol_dpcm_decoder;
+extern AVCodec sonic_decoder;
+extern AVCodec qtrle_decoder;
+extern AVCodec flac_decoder;
+extern AVCodec tscc_decoder;
+extern AVCodec cscd_decoder;
+extern AVCodec nuv_decoder;
+extern AVCodec ulti_decoder;
+extern AVCodec qdraw_decoder;
+extern AVCodec xl_decoder;
+extern AVCodec qpeg_decoder;
+extern AVCodec shorten_decoder;
+extern AVCodec loco_decoder;
+extern AVCodec wnv1_decoder;
+extern AVCodec aasc_decoder;
+extern AVCodec alac_decoder;
+extern AVCodec ws_snd1_decoder;
+extern AVCodec indeo2_decoder;
+extern AVCodec vorbis_decoder;
+extern AVCodec fraps_decoder;
+extern AVCodec libgsm_encoder;
+extern AVCodec libgsm_decoder;
+extern AVCodec bmp_decoder;
+extern AVCodec mmvideo_decoder;
+extern AVCodec zmbv_decoder;
+extern AVCodec avs_decoder;
+extern AVCodec smacker_decoder;
+extern AVCodec smackaud_decoder;
+extern AVCodec kmvc_decoder;
+extern AVCodec flashsv_decoder;
+extern AVCodec cavs_decoder;
+extern AVCodec vmnc_decoder;
+extern AVCodec wavpack_decoder;
+extern AVCodec targa_decoder;
+extern AVCodec dsicinvideo_decoder;
+extern AVCodec dsicinaudio_decoder;
+extern AVCodec tiertexseqvideo_decoder;
+extern AVCodec tiff_decoder;
+extern AVCodec imc_decoder;
+
+/* pcm codecs */
+#define PCM_CODEC(id, name) \
+extern AVCodec name ## _decoder; \
+extern AVCodec name ## _encoder
+
+PCM_CODEC(CODEC_ID_PCM_S32LE, pcm_s32le);
+PCM_CODEC(CODEC_ID_PCM_S32BE, pcm_s32be);
+PCM_CODEC(CODEC_ID_PCM_U32LE, pcm_u32le);
+PCM_CODEC(CODEC_ID_PCM_U32BE, pcm_u32be);
+PCM_CODEC(CODEC_ID_PCM_S24LE, pcm_s24le);
+PCM_CODEC(CODEC_ID_PCM_S24BE, pcm_s24be);
+PCM_CODEC(CODEC_ID_PCM_U24LE, pcm_u24le);
+PCM_CODEC(CODEC_ID_PCM_U24BE, pcm_u24be);
+PCM_CODEC(CODEC_ID_PCM_S24DAUD, pcm_s24daud);
+PCM_CODEC(CODEC_ID_PCM_S16LE, pcm_s16le);
+PCM_CODEC(CODEC_ID_PCM_S16BE, pcm_s16be);
+PCM_CODEC(CODEC_ID_PCM_U16LE, pcm_u16le);
+PCM_CODEC(CODEC_ID_PCM_U16BE, pcm_u16be);
+PCM_CODEC(CODEC_ID_PCM_S8, pcm_s8);
+PCM_CODEC(CODEC_ID_PCM_U8, pcm_u8);
+PCM_CODEC(CODEC_ID_PCM_ALAW, pcm_alaw);
+PCM_CODEC(CODEC_ID_PCM_MULAW, pcm_mulaw);
+
+/* adpcm codecs */
+
+PCM_CODEC(CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt);
+PCM_CODEC(CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav);
+PCM_CODEC(CODEC_ID_ADPCM_IMA_DK3, adpcm_ima_dk3);
+PCM_CODEC(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4);
+PCM_CODEC(CODEC_ID_ADPCM_IMA_WS, adpcm_ima_ws);
+PCM_CODEC(CODEC_ID_ADPCM_SMJPEG, adpcm_ima_smjpeg);
+PCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms);
+PCM_CODEC(CODEC_ID_ADPCM_4XM, adpcm_4xm);
+PCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa);
+PCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx);
+PCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea);
+PCM_CODEC(CODEC_ID_ADPCM_G726, adpcm_g726);
+PCM_CODEC(CODEC_ID_ADPCM_CT, adpcm_ct);
+PCM_CODEC(CODEC_ID_ADPCM_SWF, adpcm_swf);
+PCM_CODEC(CODEC_ID_ADPCM_YAMAHA, adpcm_yamaha);
+PCM_CODEC(CODEC_ID_ADPCM_SBPRO_4, adpcm_sbpro_4);
+PCM_CODEC(CODEC_ID_ADPCM_SBPRO_3, adpcm_sbpro_3);
+PCM_CODEC(CODEC_ID_ADPCM_SBPRO_2, adpcm_sbpro_2);
+
+#undef PCM_CODEC
+
+/* dummy raw video codec */
+extern AVCodec rawvideo_encoder;
+extern AVCodec rawvideo_decoder;
+
+/* the following codecs use external GPL libs */
+extern AVCodec ac3_decoder;
+extern AVCodec dts_decoder;
+
+/* subtitles */
+extern AVCodec dvdsub_encoder;
+extern AVCodec dvdsub_decoder;
+extern AVCodec dvbsub_encoder;
+extern AVCodec dvbsub_decoder;
+
+/* resample.c */
+
+struct ReSampleContext;
+struct AVResampleContext;
+
+typedef struct ReSampleContext ReSampleContext;
+
+ReSampleContext *audio_resample_init(int output_channels, int input_channels,
+ int output_rate, int input_rate);
+int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples);
+void audio_resample_close(ReSampleContext *s);
+
+struct AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_length, int log2_phase_count, int linear, double cutoff);
+int av_resample(struct AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx);
+void av_resample_compensate(struct AVResampleContext *c, int sample_delta, int compensation_distance);
+void av_resample_close(struct AVResampleContext *c);
+
+/* YUV420 format is assumed ! */
+
+struct ImgReSampleContext;
+
+typedef struct ImgReSampleContext ImgReSampleContext;
+
+ImgReSampleContext *img_resample_init(int output_width, int output_height,
+ int input_width, int input_height);
+
+ImgReSampleContext *img_resample_full_init(int owidth, int oheight,
+ int iwidth, int iheight,
+ int topBand, int bottomBand,
+ int leftBand, int rightBand,
+ int padtop, int padbottom,
+ int padleft, int padright);
+
+
+void img_resample(ImgReSampleContext *s,
+ AVPicture *output, const AVPicture *input);
+
+void img_resample_close(ImgReSampleContext *s);
+
+/**
+ * Allocate memory for a picture. Call avpicture_free to free it.
+ *
+ * @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 0 if successful, -1 if not.
+ */
+int avpicture_alloc(AVPicture *picture, int pix_fmt, int width, int height);
+
+/* Free a picture previously allocated by avpicture_alloc. */
+void avpicture_free(AVPicture *picture);
+
+int avpicture_fill(AVPicture *picture, uint8_t *ptr,
+ int pix_fmt, int width, int height);
+int avpicture_layout(const AVPicture* src, int pix_fmt, int width, int height,
+ unsigned char *dest, int dest_size);
+int avpicture_get_size(int pix_fmt, int width, int height);
+void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift);
+const char *avcodec_get_pix_fmt_name(int pix_fmt);
+void avcodec_set_dimensions(AVCodecContext *s, int width, int height);
+enum PixelFormat avcodec_get_pix_fmt(const char* name);
+unsigned int avcodec_pix_fmt_to_codec_tag(enum PixelFormat p);
+
+#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) */
+
+int avcodec_get_pix_fmt_loss(int dst_pix_fmt, int src_pix_fmt,
+ int has_alpha);
+int avcodec_find_best_pix_fmt(int pix_fmt_mask, int src_pix_fmt,
+ int has_alpha, int *loss_ptr);
+
+#define FF_ALPHA_TRANSP 0x0001 /* image has some totally transparent pixels */
+#define FF_ALPHA_SEMI_TRANSP 0x0002 /* image has some transparent pixels */
+int img_get_alpha_info(const AVPicture *src,
+ int pix_fmt, int width, int height);
+
+/* convert among pixel formats */
+int img_convert(AVPicture *dst, int dst_pix_fmt,
+ const AVPicture *src, int pix_fmt,
+ int width, int height);
+
+/* deinterlace a picture */
+int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
+ int pix_fmt, int width, int height);
+
+/* external high level API */
+
+extern AVCodec *first_avcodec;
+
+/* returns LIBAVCODEC_VERSION_INT constant */
+unsigned avcodec_version(void);
+/* returns LIBAVCODEC_BUILD constant */
+unsigned avcodec_build(void);
+void avcodec_init(void);
+
+void register_avcodec(AVCodec *format);
+AVCodec *avcodec_find_encoder(enum CodecID id);
+AVCodec *avcodec_find_encoder_by_name(const char *name);
+AVCodec *avcodec_find_decoder(enum CodecID id);
+AVCodec *avcodec_find_decoder_by_name(const char *name);
+void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode);
+
+void avcodec_get_context_defaults(AVCodecContext *s);
+AVCodecContext *avcodec_alloc_context(void);
+void avcodec_get_frame_defaults(AVFrame *pic);
+AVFrame *avcodec_alloc_frame(void);
+
+int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic);
+void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic);
+int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic);
+void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height);
+int avcodec_check_dimensions(void *av_log_ctx, unsigned int w, unsigned int h);
+enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum PixelFormat * fmt);
+
+int avcodec_thread_init(AVCodecContext *s, int thread_count);
+void avcodec_thread_free(AVCodecContext *s);
+int avcodec_thread_execute(AVCodecContext *s, int (*func)(AVCodecContext *c2, void *arg2),void **arg, int *ret, int count);
+int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void **arg, int *ret, int count);
+//FIXME func typedef
+
+/**
+ * opens / inits the AVCodecContext.
+ * not thread save!
+ */
+int avcodec_open(AVCodecContext *avctx, AVCodec *codec);
+
+/**
+ * Decode an audio frame.
+ *
+ * @param avctx the codec context.
+ * @param samples output buffer, 16 byte aligned
+ * @param frame_size_ptr the output buffer size in bytes, zero if no frame could be compressed
+ * @param buf input buffer, 16 byte aligned
+ * @param buf_size the input buffer size
+ * @return 0 if successful, -1 if not.
+ */
+
+int avcodec_decode_audio(AVCodecContext *avctx, int16_t *samples,
+ int *frame_size_ptr,
+ uint8_t *buf, int buf_size);
+int avcodec_decode_video(AVCodecContext *avctx, AVFrame *picture,
+ int *got_picture_ptr,
+ uint8_t *buf, int buf_size);
+int avcodec_decode_subtitle(AVCodecContext *avctx, AVSubtitle *sub,
+ int *got_sub_ptr,
+ const uint8_t *buf, int buf_size);
+int avcodec_parse_frame(AVCodecContext *avctx, uint8_t **pdata,
+ int *data_size_ptr,
+ uint8_t *buf, int buf_size);
+int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size,
+ const short *samples);
+int avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size,
+ const AVFrame *pict);
+int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size,
+ const AVSubtitle *sub);
+
+int avcodec_close(AVCodecContext *avctx);
+
+void avcodec_register_all(void);
+
+void avcodec_flush_buffers(AVCodecContext *avctx);
+
+void avcodec_default_free_buffers(AVCodecContext *s);
+
+/* misc usefull functions */
+
+/**
+ * returns a single letter to describe the picture type
+ */
+char av_get_pict_type_char(int pict_type);
+
+/**
+ * returns codec bits per sample
+ */
+int av_get_bits_per_sample(enum CodecID codec_id);
+
+/* 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 last_frame_offset; /* offset of the last frame */
+ /* video info */
+ int pict_type; /* XXX: put it back in AVCodecContext */
+ 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
+} 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,
+ 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;
+
+extern AVCodecParser *av_first_parser;
+
+void av_register_codec_parser(AVCodecParser *parser);
+AVCodecParserContext *av_parser_init(int codec_id);
+int av_parser_parse(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size,
+ int64_t pts, int64_t dts);
+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);
+
+extern AVCodecParser mpegvideo_parser;
+extern AVCodecParser mpeg4video_parser;
+extern AVCodecParser cavsvideo_parser;
+extern AVCodecParser h261_parser;
+extern AVCodecParser h263_parser;
+extern AVCodecParser h264_parser;
+extern AVCodecParser mjpeg_parser;
+extern AVCodecParser pnm_parser;
+extern AVCodecParser mpegaudio_parser;
+extern AVCodecParser ac3_parser;
+extern AVCodecParser dvdsub_parser;
+extern AVCodecParser dvbsub_parser;
+extern AVCodecParser aac_parser;
+
+
+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);
+ struct AVBitStreamFilter *next;
+} AVBitStreamFilter;
+
+extern AVBitStreamFilter *av_first_bitstream_filter;
+
+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);
+
+extern AVBitStreamFilter dump_extradata_bsf;
+extern AVBitStreamFilter remove_extradata_bsf;
+extern AVBitStreamFilter noise_bsf;
+extern AVBitStreamFilter mp3_header_compress_bsf;
+extern AVBitStreamFilter mp3_header_decompress_bsf;
+extern AVBitStreamFilter mjpega_dump_header_bsf;
+
+
+/* memory */
+void *av_fast_realloc(void *ptr, unsigned int *size, unsigned int min_size);
+/* for static data only */
+/* call av_free_static to release all staticaly allocated tables */
+void av_free_static(void);
+void *av_mallocz_static(unsigned int size);
+void *av_realloc_static(void *ptr, unsigned int size);
+
+void img_copy(AVPicture *dst, const AVPicture *src,
+ int pix_fmt, int width, int height);
+
+int img_crop(AVPicture *dst, const AVPicture *src,
+ int pix_fmt, int top_band, int left_band);
+
+int img_pad(AVPicture *dst, const AVPicture *src, int height, int width, int pix_fmt,
+ int padtop, int padbottom, int padleft, int padright, int *color);
+
+/* endian macros */
+#if !defined(BE_16) || !defined(BE_32) || !defined(LE_16) || !defined(LE_32)
+#define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
+#define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \
+ (((uint8_t*)(x))[1] << 16) | \
+ (((uint8_t*)(x))[2] << 8) | \
+ ((uint8_t*)(x))[3])
+#define LE_16(x) ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
+#define LE_32(x) ((((uint8_t*)(x))[3] << 24) | \
+ (((uint8_t*)(x))[2] << 16) | \
+ (((uint8_t*)(x))[1] << 8) | \
+ ((uint8_t*)(x))[0])
+#endif
+
+extern unsigned int av_xiphlacing(unsigned char *s, unsigned int v);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVCODEC_H */
diff --git a/contrib/ffmpeg/libavcodec/avs.c b/contrib/ffmpeg/libavcodec/avs.c
new file mode 100644
index 000000000..953aea1be
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/avs.c
@@ -0,0 +1,160 @@
+/*
+ * AVS video decoder.
+ * Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avcodec.h"
+#include "bitstream.h"
+
+
+typedef struct {
+ AVFrame picture;
+} avs_context_t;
+
+typedef enum {
+ AVS_VIDEO = 0x01,
+ AVS_AUDIO = 0x02,
+ AVS_PALETTE = 0x03,
+ AVS_GAME_DATA = 0x04,
+} avs_block_type_t;
+
+typedef enum {
+ AVS_I_FRAME = 0x00,
+ AVS_P_FRAME_3X3 = 0x01,
+ AVS_P_FRAME_2X2 = 0x02,
+ AVS_P_FRAME_2X3 = 0x03,
+} avs_video_sub_type_t;
+
+
+static int
+avs_decode_frame(AVCodecContext * avctx,
+ void *data, int *data_size, uint8_t * buf, int buf_size)
+{
+ avs_context_t *const avs = avctx->priv_data;
+ AVFrame *picture = data;
+ AVFrame *const p = (AVFrame *) & avs->picture;
+ uint8_t *table, *vect, *out;
+ int i, j, x, y, stride, vect_w = 3, vect_h = 3;
+ int sub_type;
+ avs_block_type_t type;
+ GetBitContext change_map;
+
+ if (avctx->reget_buffer(avctx, p)) {
+ av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+ return -1;
+ }
+ p->reference = 1;
+ p->pict_type = FF_P_TYPE;
+ p->key_frame = 0;
+
+ out = avs->picture.data[0];
+ stride = avs->picture.linesize[0];
+
+ 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 = LE_16(buf);
+ last = first + LE_16(buf + 2);
+ buf += 4;
+ for (i=first; i<last; i++, buf+=3)
+ pal[i] = (buf[0] << 18) | (buf[1] << 10) | (buf[2] << 2);
+
+ sub_type = buf[0];
+ type = buf[1];
+ buf += 4;
+ }
+
+ if (type != AVS_VIDEO)
+ return -1;
+
+ switch (sub_type) {
+ case AVS_I_FRAME:
+ p->pict_type = FF_I_TYPE;
+ 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 -1;
+ }
+
+ table = buf + (256 * vect_w * vect_h);
+ if (sub_type != AVS_I_FRAME) {
+ int map_size = ((318 / vect_w + 7) / 8) * (198 / vect_h);
+ init_get_bits(&change_map, table, map_size);
+ 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)) {
+ vect = &buf[*table++ * (vect_w * vect_h)];
+ for (j=0; j<vect_w; j++) {
+ out[(y + 0) * stride + x + j] = vect[(0 * vect_w) + j];
+ out[(y + 1) * stride + x + j] = vect[(1 * vect_w) + j];
+ if (vect_h == 3)
+ out[(y + 2) * stride + x + j] =
+ vect[(2 * vect_w) + j];
+ }
+ }
+ }
+ if (sub_type != AVS_I_FRAME)
+ align_get_bits(&change_map);
+ }
+
+ *picture = *(AVFrame *) & avs->picture;
+ *data_size = sizeof(AVPicture);
+
+ return buf_size;
+}
+
+static int avs_decode_init(AVCodecContext * avctx)
+{
+ avctx->pix_fmt = PIX_FMT_PAL8;
+ return 0;
+}
+
+AVCodec avs_decoder = {
+ "avs",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_AVS,
+ sizeof(avs_context_t),
+ avs_decode_init,
+ NULL,
+ NULL,
+ avs_decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/beosthread.c b/contrib/ffmpeg/libavcodec/beosthread.c
new file mode 100644
index 000000000..3d059912b
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/beosthread.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2004 François Revol <revol@free.fr>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 "avcodec.h"
+#include "common.h"
+
+#include <OS.h>
+
+typedef struct ThreadContext{
+ AVCodecContext *avctx;
+ thread_id thread;
+ sem_id work_sem;
+ sem_id done_sem;
+ int (*func)(AVCodecContext *c, void *arg);
+ void *arg;
+ int ret;
+}ThreadContext;
+
+// it's odd Be never patented that :D
+struct benaphore {
+ vint32 atom;
+ sem_id sem;
+};
+static inline int lock_ben(struct benaphore *ben)
+{
+ if (atomic_add(&ben->atom, 1) > 0)
+ return acquire_sem(ben->sem);
+ return B_OK;
+}
+static inline int unlock_ben(struct benaphore *ben)
+{
+ if (atomic_add(&ben->atom, -1) > 1)
+ return release_sem(ben->sem);
+ return B_OK;
+}
+
+static struct benaphore av_thread_lib_ben;
+
+static int32 ff_thread_func(void *v){
+ ThreadContext *c= v;
+
+ for(;;){
+//printf("thread_func %X enter wait\n", (int)v); fflush(stdout);
+ acquire_sem(c->work_sem);
+//printf("thread_func %X after wait (func=%X)\n", (int)v, (int)c->func); fflush(stdout);
+ if(c->func)
+ c->ret= c->func(c->avctx, c->arg);
+ else
+ return 0;
+//printf("thread_func %X signal complete\n", (int)v); fflush(stdout);
+ release_sem(c->done_sem);
+ }
+
+ return B_OK;
+}
+
+/**
+ * free what has been allocated by avcodec_thread_init().
+ * must be called after decoding has finished, especially dont call while avcodec_thread_execute() is running
+ */
+void avcodec_thread_free(AVCodecContext *s){
+ ThreadContext *c= s->thread_opaque;
+ int i;
+ int32 ret;
+
+ for(i=0; i<s->thread_count; i++){
+
+ c[i].func= NULL;
+ release_sem(c[i].work_sem);
+ wait_for_thread(c[i].thread, &ret);
+ if(c[i].work_sem > B_OK) delete_sem(c[i].work_sem);
+ if(c[i].done_sem > B_OK) delete_sem(c[i].done_sem);
+ }
+
+ av_freep(&s->thread_opaque);
+}
+
+int avcodec_thread_execute(AVCodecContext *s, int (*func)(AVCodecContext *c2, void *arg2),void **arg, int *ret, int count){
+ ThreadContext *c= s->thread_opaque;
+ int i;
+
+ assert(s == c->avctx);
+ assert(count <= s->thread_count);
+
+ /* note, we can be certain that this is not called with the same AVCodecContext by different threads at the same time */
+
+ for(i=0; i<count; i++){
+ c[i].arg= arg[i];
+ c[i].func= func;
+ c[i].ret= 12345;
+
+ release_sem(c[i].work_sem);
+ }
+ for(i=0; i<count; i++){
+ acquire_sem(c[i].done_sem);
+
+ c[i].func= NULL;
+ if(ret) ret[i]= c[i].ret;
+ }
+ return 0;
+}
+
+int avcodec_thread_init(AVCodecContext *s, int thread_count){
+ int i;
+ ThreadContext *c;
+
+ s->thread_count= thread_count;
+
+ assert(!s->thread_opaque);
+ c= av_mallocz(sizeof(ThreadContext)*thread_count);
+ s->thread_opaque= c;
+
+ for(i=0; i<thread_count; i++){
+//printf("init semaphors %d\n", i); fflush(stdout);
+ c[i].avctx= s;
+
+ if((c[i].work_sem = create_sem(0, "ff work sem")) < B_OK)
+ goto fail;
+ if((c[i].done_sem = create_sem(0, "ff done sem")) < B_OK)
+ goto fail;
+
+//printf("create thread %d\n", i); fflush(stdout);
+ c[i].thread = spawn_thread(ff_thread_func, "libavcodec thread", B_LOW_PRIORITY, &c[i] );
+ if( c[i].thread < B_OK ) goto fail;
+ resume_thread(c[i].thread );
+ }
+//printf("init done\n"); fflush(stdout);
+
+ s->execute= avcodec_thread_execute;
+
+ return 0;
+fail:
+ avcodec_thread_free(s);
+ return -1;
+}
+
+/* provide a mean to serialize calls to avcodec_*() for thread safety. */
+
+int avcodec_thread_lock_lib(void)
+{
+ return lock_ben(&av_thread_lib_ben);
+}
+
+int avcodec_thread_unlock_lib(void)
+{
+ return unlock_ben(&av_thread_lib_ben);
+}
+
+/* our versions of _init and _fini (which are called by those actually from crt.o) */
+
+void initialize_after(void)
+{
+ av_thread_lib_ben.atom = 0;
+ av_thread_lib_ben.sem = create_sem(0, "libavcodec benaphore");
+}
+
+void uninitialize_before(void)
+{
+ delete_sem(av_thread_lib_ben.sem);
+}
+
+
+
diff --git a/contrib/ffmpeg/libavcodec/bfin/dsputil_bfin.c b/contrib/ffmpeg/libavcodec/bfin/dsputil_bfin.c
new file mode 100644
index 000000000..196ef6fea
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/bfin/dsputil_bfin.c
@@ -0,0 +1,55 @@
+/*
+ * 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 "../avcodec.h"
+#include "../dsputil.h"
+
+static int sad8x8_bfin( void *c, uint8_t *blk1, uint8_t *blk2, int line_size, int h )
+{
+ int sum;
+ __asm__ __volatile__ (
+ "P0 = %1;" // blk1
+ "P1 = %2;" // blk2
+ "P2 = %3;\n" // h
+ "I0 = P0;"
+ "I1 = P1;\n"
+ "A0 = 0;"
+ "A1 = 0;\n"
+ "M0 = P2;\n"
+ "P3 = 32;\n"
+ "LSETUP (sad8x8LoopBegin, sad8x8LoopEnd) LC0=P3;\n"
+ "sad8x8LoopBegin:\n"
+ " DISALGNEXCPT || R0 = [I0] || R2 = [I1];\n"
+ " DISALGNEXCPT || R1 = [I0++] || R3 = [I1++];\n"
+ "sad8x8LoopEnd:\n"
+ " SAA ( R1:0 , R3:2 );\n"
+ "R3 = A1.L + A1.H, R2 = A0.L + A0.H;\n"
+ "%0 = R2 + R3 (S);\n"
+ : "=&d" (sum)
+ : "m"(blk1), "m"(blk2), "m"(h)
+ : "P0","P1","P2","I0","I1","A0","A1","R0","R1","R2","R3");
+ return sum;
+}
+
+void dsputil_init_bfin( DSPContext* c, AVCodecContext *avctx )
+{
+ c->pix_abs[1][0] = sad8x8_bfin;
+ c->sad[1] = sad8x8_bfin;
+}
diff --git a/contrib/ffmpeg/libavcodec/bitstream.c b/contrib/ffmpeg/libavcodec/bitstream.c
new file mode 100644
index 000000000..22d256df5
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/bitstream.c
@@ -0,0 +1,254 @@
+/*
+ * Common bit i/o utils
+ * Copyright (c) 2000, 2001 Fabrice Bellard.
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * alternative bitstream reader & writer by Michael Niedermayer <michaelni@gmx.at>
+ */
+
+/**
+ * @file bitstream.c
+ * bitstream api.
+ */
+
+#include "avcodec.h"
+#include "bitstream.h"
+
+void align_put_bits(PutBitContext *s)
+{
+#ifdef ALT_BITSTREAM_WRITER
+ put_bits(s,( - s->index) & 7,0);
+#else
+ put_bits(s,s->bit_left & 7,0);
+#endif
+}
+
+void ff_put_string(PutBitContext * pbc, char *s, int put_zero)
+{
+ while(*s){
+ put_bits(pbc, 8, *s);
+ s++;
+ }
+ if(put_zero)
+ put_bits(pbc, 8, 0);
+}
+
+/* VLC decoding */
+
+//#define DEBUG_VLC
+
+#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) {
+ vlc->table_allocated += (1 << vlc->bits);
+ if(use_static)
+ vlc->table = av_realloc_static(vlc->table,
+ sizeof(VLC_TYPE) * 2 * vlc->table_allocated);
+ else
+ vlc->table = av_realloc(vlc->table,
+ sizeof(VLC_TYPE) * 2 * vlc->table_allocated);
+ if (!vlc->table)
+ return -1;
+ }
+ return index;
+}
+
+static int build_table(VLC *vlc, int table_nb_bits,
+ int nb_codes,
+ const void *bits, int bits_wrap, int bits_size,
+ const void *codes, int codes_wrap, int codes_size,
+ uint32_t code_prefix, int n_prefix, int flags)
+{
+ int i, j, k, n, table_size, table_index, nb, n1, index, code_prefix2;
+ uint32_t code;
+ VLC_TYPE (*table)[2];
+
+ table_size = 1 << table_nb_bits;
+ table_index = alloc_table(vlc, table_size, flags & INIT_VLC_USE_STATIC);
+#ifdef DEBUG_VLC
+ printf("new table index=%d size=%d code_prefix=%x n=%d\n",
+ table_index, table_size, code_prefix, n_prefix);
+#endif
+ 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 auxillary table sizes */
+ for(i=0;i<nb_codes;i++) {
+ GET_DATA(n, bits, i, bits_wrap, bits_size);
+ GET_DATA(code, codes, i, codes_wrap, codes_size);
+ /* we accept tables with holes */
+ if (n <= 0)
+ continue;
+#if defined(DEBUG_VLC) && 0
+ printf("i=%d n=%d code=0x%x\n", i, n, code);
+#endif
+ /* if code matches the prefix, it is in the table */
+ n -= n_prefix;
+ if(flags & INIT_VLC_LE)
+ code_prefix2= code & (n_prefix>=32 ? 0xffffffff : (1 << n_prefix)-1);
+ else
+ code_prefix2= code >> n;
+ if (n > 0 && code_prefix2 == code_prefix) {
+ if (n <= table_nb_bits) {
+ /* no need to add another table */
+ j = (code << (table_nb_bits - n)) & (table_size - 1);
+ nb = 1 << (table_nb_bits - n);
+ for(k=0;k<nb;k++) {
+ if(flags & INIT_VLC_LE)
+ j = (code >> n_prefix) + (k<<n);
+#ifdef DEBUG_VLC
+ av_log(NULL, AV_LOG_DEBUG, "%4x: code=%d n=%d\n",
+ j, i, n);
+#endif
+ 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] = i; //code
+ j++;
+ }
+ } else {
+ n -= table_nb_bits;
+ j = (code >> ((flags & INIT_VLC_LE) ? n_prefix : n)) & ((1 << table_nb_bits) - 1);
+#ifdef DEBUG_VLC
+ printf("%4x: n=%d (subtable)\n",
+ j, n);
+#endif
+ /* compute table size */
+ n1 = -table[j][1]; //bits
+ if (n > n1)
+ n1 = n;
+ table[j][1] = -n1; //bits
+ }
+ }
+ }
+
+ /* second pass : fill auxillary tables recursively */
+ for(i=0;i<table_size;i++) {
+ n = table[i][1]; //bits
+ if (n < 0) {
+ n = -n;
+ if (n > table_nb_bits) {
+ n = table_nb_bits;
+ table[i][1] = -n; //bits
+ }
+ index = build_table(vlc, n, nb_codes,
+ bits, bits_wrap, bits_size,
+ codes, codes_wrap, codes_size,
+ (flags & INIT_VLC_LE) ? (code_prefix | (i << n_prefix)) : ((code_prefix << table_nb_bits) | i),
+ n_prefix + table_nb_bits, flags);
+ if (index < 0)
+ return -1;
+ /* note: realloc has been done, so reload tables */
+ table = &vlc->table[table_index];
+ table[i][0] = index; //code
+ }
+ }
+ 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.
+
+ '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' and 'codes' tables.
+
+ 'use_static' should be set to 1 for tables, which should be freed
+ with av_free_static(), 0 if free_vlc() will be used.
+*/
+int init_vlc(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,
+ int use_static)
+{
+ vlc->bits = nb_bits;
+ if(!use_static) {
+ vlc->table = NULL;
+ vlc->table_allocated = 0;
+ vlc->table_size = 0;
+ } else {
+ /* Static tables are initially always NULL, return
+ if vlc->table != NULL to avoid double allocation */
+ if(vlc->table)
+ return 0;
+ }
+
+#ifdef DEBUG_VLC
+ printf("build table nb_codes=%d\n", nb_codes);
+#endif
+
+ if (build_table(vlc, nb_bits, nb_codes,
+ bits, bits_wrap, bits_size,
+ codes, codes_wrap, codes_size,
+ 0, 0, use_static) < 0) {
+ av_free(vlc->table);
+ return -1;
+ }
+ return 0;
+}
+
+
+void free_vlc(VLC *vlc)
+{
+ av_free(vlc->table);
+}
+
diff --git a/contrib/ffmpeg/libavcodec/bitstream.h b/contrib/ffmpeg/libavcodec/bitstream.h
new file mode 100644
index 000000000..af25b6dcf
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/bitstream.h
@@ -0,0 +1,956 @@
+/*
+ * copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * 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.h
+ * bitstream api header.
+ */
+
+#ifndef BITSTREAM_H
+#define BITSTREAM_H
+
+#include "log.h"
+
+#if defined(ALT_BITSTREAM_READER_LE) && !defined(ALT_BITSTREAM_READER)
+#define ALT_BITSTREAM_READER
+#endif
+
+//#define ALT_BITSTREAM_WRITER
+//#define ALIGNED_BITSTREAM_WRITER
+#if !defined(LIBMPEG2_BITSTREAM_READER) && !defined(A32_BITSTREAM_READER) && !defined(ALT_BITSTREAM_READER)
+# ifdef ARCH_ARMV4L
+# define A32_BITSTREAM_READER
+# else
+#define ALT_BITSTREAM_READER
+//#define LIBMPEG2_BITSTREAM_READER
+//#define A32_BITSTREAM_READER
+# endif
+#endif
+#define LIBMPEG2_BITSTREAM_READER_HACK //add BERO
+
+extern const uint8_t ff_reverse[256];
+
+#if defined(ARCH_X86)
+// avoid +32 for shift optimization (gcc should do that ...)
+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;
+}
+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;
+}
+#else
+# define NEG_SSR32(a,s) ((( int32_t)(a))>>(32-(s)))
+# define NEG_USR32(a,s) (((uint32_t)(a))>>(32-(s)))
+#endif
+
+/* bit output */
+
+/* buf and buf_end must be present and used by every alternative writer. */
+typedef struct PutBitContext {
+#ifdef ALT_BITSTREAM_WRITER
+ uint8_t *buf, *buf_end;
+ int index;
+#else
+ uint32_t bit_buf;
+ int bit_left;
+ uint8_t *buf, *buf_ptr, *buf_end;
+#endif
+} PutBitContext;
+
+static inline void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
+{
+ if(buffer_size < 0) {
+ buffer_size = 0;
+ buffer = NULL;
+ }
+
+ s->buf = buffer;
+ s->buf_end = s->buf + buffer_size;
+#ifdef ALT_BITSTREAM_WRITER
+ s->index=0;
+ ((uint32_t*)(s->buf))[0]=0;
+// memset(buffer, 0, buffer_size);
+#else
+ s->buf_ptr = s->buf;
+ s->bit_left=32;
+ s->bit_buf=0;
+#endif
+}
+
+/* return the number of bits output */
+static inline int put_bits_count(PutBitContext *s)
+{
+#ifdef ALT_BITSTREAM_WRITER
+ return s->index;
+#else
+ return (s->buf_ptr - s->buf) * 8 + 32 - s->bit_left;
+#endif
+}
+
+/* pad the end of the output stream with zeros */
+static inline void flush_put_bits(PutBitContext *s)
+{
+#ifdef ALT_BITSTREAM_WRITER
+ align_put_bits(s);
+#else
+ s->bit_buf<<= s->bit_left;
+ while (s->bit_left < 32) {
+ /* XXX: should test end of buffer */
+ *s->buf_ptr++=s->bit_buf >> 24;
+ s->bit_buf<<=8;
+ s->bit_left+=8;
+ }
+ s->bit_left=32;
+ s->bit_buf=0;
+#endif
+}
+
+void align_put_bits(PutBitContext *s);
+void ff_put_string(PutBitContext * pbc, char *s, int put_zero);
+
+/* bit input */
+/* buffer, buffer_end and size_in_bits must be present and used by every reader */
+typedef struct GetBitContext {
+ const uint8_t *buffer, *buffer_end;
+#ifdef ALT_BITSTREAM_READER
+ int index;
+#elif defined LIBMPEG2_BITSTREAM_READER
+ uint8_t *buffer_ptr;
+ uint32_t cache;
+ int bit_count;
+#elif defined A32_BITSTREAM_READER
+ uint32_t *buffer_ptr;
+ uint32_t cache0;
+ uint32_t cache1;
+ int bit_count;
+#endif
+ int size_in_bits;
+} 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;
+
+#if defined(ARCH_SPARC) || defined(ARCH_ARMV4L) || defined(ARCH_MIPS)
+#define UNALIGNED_STORES_ARE_BAD
+#endif
+
+/* used to avoid missaligned exceptions on some archs (alpha, ...) */
+#if defined(ARCH_X86)
+# define unaligned16(a) (*(const uint16_t*)(a))
+# define unaligned32(a) (*(const uint32_t*)(a))
+# define unaligned64(a) (*(const uint64_t*)(a))
+#else
+# ifdef __GNUC__
+# define unaligned(x) \
+static inline uint##x##_t unaligned##x(const void *v) { \
+ struct Unaligned { \
+ uint##x##_t i; \
+ } __attribute__((packed)); \
+ \
+ return ((const struct Unaligned *) v)->i; \
+}
+# elif defined(__DECC)
+# define unaligned(x) \
+static inline uint##x##_t unaligned##x##(const void *v) { \
+ return *(const __unaligned uint##x##_t *) v; \
+}
+# else
+# define unaligned(x) \
+static inline uint##x##_t unaligned##x##(const void *v) { \
+ return *(const uint##x##_t *) v; \
+}
+# endif
+unaligned(16)
+unaligned(32)
+unaligned(64)
+#undef unaligned
+#endif /* defined(ARCH_X86) */
+
+#ifndef ALT_BITSTREAM_WRITER
+static inline void put_bits(PutBitContext *s, int n, unsigned int value)
+{
+ unsigned int bit_buf;
+ int bit_left;
+
+ // printf("put_bits=%d %x\n", n, value);
+ assert(n == 32 || value < (1U << n));
+
+ bit_buf = s->bit_buf;
+ bit_left = s->bit_left;
+
+ // printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf);
+ /* XXX: optimize */
+ if (n < bit_left) {
+ bit_buf = (bit_buf<<n) | value;
+ bit_left-=n;
+ } else {
+ bit_buf<<=bit_left;
+ bit_buf |= value >> (n - bit_left);
+#ifdef UNALIGNED_STORES_ARE_BAD
+ if (3 & (intptr_t) s->buf_ptr) {
+ s->buf_ptr[0] = bit_buf >> 24;
+ s->buf_ptr[1] = bit_buf >> 16;
+ s->buf_ptr[2] = bit_buf >> 8;
+ s->buf_ptr[3] = bit_buf ;
+ } else
+#endif
+ *(uint32_t *)s->buf_ptr = be2me_32(bit_buf);
+ //printf("bitbuf = %08x\n", bit_buf);
+ s->buf_ptr+=4;
+ bit_left+=32 - n;
+ bit_buf = value;
+ }
+
+ s->bit_buf = bit_buf;
+ s->bit_left = bit_left;
+}
+#endif
+
+
+#ifdef ALT_BITSTREAM_WRITER
+static inline void put_bits(PutBitContext *s, int n, unsigned int value)
+{
+# ifdef ALIGNED_BITSTREAM_WRITER
+# if defined(ARCH_X86)
+ asm volatile(
+ "movl %0, %%ecx \n\t"
+ "xorl %%eax, %%eax \n\t"
+ "shrdl %%cl, %1, %%eax \n\t"
+ "shrl %%cl, %1 \n\t"
+ "movl %0, %%ecx \n\t"
+ "shrl $3, %%ecx \n\t"
+ "andl $0xFFFFFFFC, %%ecx \n\t"
+ "bswapl %1 \n\t"
+ "orl %1, (%2, %%ecx) \n\t"
+ "bswapl %%eax \n\t"
+ "addl %3, %0 \n\t"
+ "movl %%eax, 4(%2, %%ecx) \n\t"
+ : "=&r" (s->index), "=&r" (value)
+ : "r" (s->buf), "r" (n), "0" (s->index), "1" (value<<(-n))
+ : "%eax", "%ecx"
+ );
+# else
+ int index= s->index;
+ uint32_t *ptr= ((uint32_t *)s->buf)+(index>>5);
+
+ value<<= 32-n;
+
+ ptr[0] |= be2me_32(value>>(index&31));
+ ptr[1] = be2me_32(value<<(32-(index&31)));
+//if(n>24) printf("%d %d\n", n, value);
+ index+= n;
+ s->index= index;
+# endif
+# else //ALIGNED_BITSTREAM_WRITER
+# if defined(ARCH_X86)
+ asm volatile(
+ "movl $7, %%ecx \n\t"
+ "andl %0, %%ecx \n\t"
+ "addl %3, %%ecx \n\t"
+ "negl %%ecx \n\t"
+ "shll %%cl, %1 \n\t"
+ "bswapl %1 \n\t"
+ "movl %0, %%ecx \n\t"
+ "shrl $3, %%ecx \n\t"
+ "orl %1, (%%ecx, %2) \n\t"
+ "addl %3, %0 \n\t"
+ "movl $0, 4(%%ecx, %2) \n\t"
+ : "=&r" (s->index), "=&r" (value)
+ : "r" (s->buf), "r" (n), "0" (s->index), "1" (value)
+ : "%ecx"
+ );
+# else
+ int index= s->index;
+ uint32_t *ptr= (uint32_t*)(((uint8_t *)s->buf)+(index>>3));
+
+ ptr[0] |= be2me_32(value<<(32-n-(index&7) ));
+ ptr[1] = 0;
+//if(n>24) printf("%d %d\n", n, value);
+ index+= n;
+ s->index= index;
+# endif
+# endif //!ALIGNED_BITSTREAM_WRITER
+}
+#endif
+
+
+static inline uint8_t* pbBufPtr(PutBitContext *s)
+{
+#ifdef ALT_BITSTREAM_WRITER
+ return s->buf + (s->index>>3);
+#else
+ return s->buf_ptr;
+#endif
+}
+
+/**
+ *
+ * PutBitContext must be flushed & aligned to a byte boundary before calling this.
+ */
+static inline void skip_put_bytes(PutBitContext *s, int n){
+ assert((put_bits_count(s)&7)==0);
+#ifdef ALT_BITSTREAM_WRITER
+ FIXME may need some cleaning of the buffer
+ s->index += n<<3;
+#else
+ assert(s->bit_left==32);
+ s->buf_ptr += n;
+#endif
+}
+
+/**
+ * skips the given number of bits.
+ * must only be used if the actual values in the bitstream dont matter
+ */
+static inline void skip_put_bits(PutBitContext *s, int n){
+#ifdef ALT_BITSTREAM_WRITER
+ s->index += n;
+#else
+ s->bit_left -= n;
+ s->buf_ptr-= s->bit_left>>5;
+ s->bit_left &= 31;
+#endif
+}
+
+/**
+ * Changes the end of the buffer.
+ */
+static inline void set_put_bits_buffer_size(PutBitContext *s, int size){
+ s->buf_end= s->buf + size;
+}
+
+/* Bitstream reader API docs:
+name
+ abritary name which is used as prefix for the internal variables
+
+gb
+ getbitcontext
+
+OPEN_READER(name, gb)
+ loads gb into local variables
+
+CLOSE_READER(name, gb)
+ stores local vars in gb
+
+UPDATE_CACHE(name, gb)
+ refills 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_CACHE(name, gb, num)
+ will remove the next num bits from the cache if it is needed for UPDATE_CACHE otherwise it will do nothing
+
+LAST_SKIP_BITS(name, gb, num)
+ is equivalent to SKIP_LAST_CACHE; SKIP_COUNTER
+
+for examples see get_bits, show_bits, skip_bits, get_vlc
+*/
+
+static inline int unaligned32_be(const void *v)
+{
+#ifdef CONFIG_ALIGN
+ const uint8_t *p=v;
+ return (((p[0]<<8) | p[1])<<16) | (p[2]<<8) | (p[3]);
+#else
+ return be2me_32( unaligned32(v)); //original
+#endif
+}
+
+static inline int unaligned32_le(const void *v)
+{
+#ifdef CONFIG_ALIGN
+ const uint8_t *p=v;
+ return (((p[3]<<8) | p[2])<<16) | (p[1]<<8) | (p[0]);
+#else
+ return le2me_32( unaligned32(v)); //original
+#endif
+}
+
+#ifdef ALT_BITSTREAM_READER
+# define MIN_CACHE_BITS 25
+
+# define OPEN_READER(name, gb)\
+ int name##_index= (gb)->index;\
+ int name##_cache= 0;\
+
+# define CLOSE_READER(name, gb)\
+ (gb)->index= name##_index;\
+
+# ifdef ALT_BITSTREAM_READER_LE
+# define UPDATE_CACHE(name, gb)\
+ name##_cache= unaligned32_le( ((const uint8_t *)(gb)->buffer)+(name##_index>>3) ) >> (name##_index&0x07);\
+
+# define SKIP_CACHE(name, gb, num)\
+ name##_cache >>= (num);
+# else
+# define UPDATE_CACHE(name, gb)\
+ name##_cache= unaligned32_be( ((const uint8_t *)(gb)->buffer)+(name##_index>>3) ) << (name##_index&0x07);\
+
+# define SKIP_CACHE(name, gb, num)\
+ name##_cache <<= (num);
+# endif
+
+// FIXME name?
+# define SKIP_COUNTER(name, gb, num)\
+ name##_index += (num);\
+
+# define SKIP_BITS(name, gb, num)\
+ {\
+ SKIP_CACHE(name, gb, num)\
+ SKIP_COUNTER(name, gb, num)\
+ }\
+
+# define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num)
+# define LAST_SKIP_CACHE(name, gb, num) ;
+
+# ifdef ALT_BITSTREAM_READER_LE
+# define SHOW_UBITS(name, gb, num)\
+ ((name##_cache) & (NEG_USR32(0xffffffff,num)))
+
+# define SHOW_SBITS(name, gb, num)\
+ NEG_SSR32((name##_cache)<<(32-(num)), 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(GetBitContext *s){
+ return s->index;
+}
+
+static inline void skip_bits_long(GetBitContext *s, int n){
+ s->index += n;
+}
+
+#elif defined LIBMPEG2_BITSTREAM_READER
+//libmpeg2 like reader
+
+# define MIN_CACHE_BITS 17
+
+# define OPEN_READER(name, gb)\
+ int name##_bit_count=(gb)->bit_count;\
+ int name##_cache= (gb)->cache;\
+ uint8_t * name##_buffer_ptr=(gb)->buffer_ptr;\
+
+# define CLOSE_READER(name, gb)\
+ (gb)->bit_count= name##_bit_count;\
+ (gb)->cache= name##_cache;\
+ (gb)->buffer_ptr= name##_buffer_ptr;\
+
+#ifdef LIBMPEG2_BITSTREAM_READER_HACK
+
+# define UPDATE_CACHE(name, gb)\
+ if(name##_bit_count >= 0){\
+ name##_cache+= (int)be2me_16(*(uint16_t*)name##_buffer_ptr) << name##_bit_count;\
+ name##_buffer_ptr += 2;\
+ name##_bit_count-= 16;\
+ }\
+
+#else
+
+# define UPDATE_CACHE(name, gb)\
+ if(name##_bit_count >= 0){\
+ name##_cache+= ((name##_buffer_ptr[0]<<8) + name##_buffer_ptr[1]) << name##_bit_count;\
+ name##_buffer_ptr+=2;\
+ name##_bit_count-= 16;\
+ }\
+
+#endif
+
+# define SKIP_CACHE(name, gb, num)\
+ name##_cache <<= (num);\
+
+# define SKIP_COUNTER(name, gb, num)\
+ name##_bit_count += (num);\
+
+# define SKIP_BITS(name, gb, num)\
+ {\
+ SKIP_CACHE(name, gb, num)\
+ SKIP_COUNTER(name, gb, num)\
+ }\
+
+# define LAST_SKIP_BITS(name, gb, num) SKIP_BITS(name, gb, num)
+# define LAST_SKIP_CACHE(name, gb, num) SKIP_CACHE(name, gb, num)
+
+# define SHOW_UBITS(name, gb, num)\
+ NEG_USR32(name##_cache, num)
+
+# define SHOW_SBITS(name, gb, num)\
+ NEG_SSR32(name##_cache, num)
+
+# define GET_CACHE(name, gb)\
+ ((uint32_t)name##_cache)
+
+static inline int get_bits_count(GetBitContext *s){
+ return (s->buffer_ptr - s->buffer)*8 - 16 + s->bit_count;
+}
+
+static inline void skip_bits_long(GetBitContext *s, int n){
+ OPEN_READER(re, s)
+ re_bit_count += n;
+ re_buffer_ptr += 2*(re_bit_count>>4);
+ re_bit_count &= 15;
+ re_cache = ((re_buffer_ptr[-2]<<8) + re_buffer_ptr[-1]) << (16+re_bit_count);
+ UPDATE_CACHE(re, s)
+ CLOSE_READER(re, s)
+}
+
+#elif defined A32_BITSTREAM_READER
+
+# define MIN_CACHE_BITS 32
+
+# define OPEN_READER(name, gb)\
+ int name##_bit_count=(gb)->bit_count;\
+ uint32_t name##_cache0= (gb)->cache0;\
+ uint32_t name##_cache1= (gb)->cache1;\
+ uint32_t * name##_buffer_ptr=(gb)->buffer_ptr;\
+
+# define CLOSE_READER(name, gb)\
+ (gb)->bit_count= name##_bit_count;\
+ (gb)->cache0= name##_cache0;\
+ (gb)->cache1= name##_cache1;\
+ (gb)->buffer_ptr= name##_buffer_ptr;\
+
+# define UPDATE_CACHE(name, gb)\
+ if(name##_bit_count > 0){\
+ const uint32_t next= be2me_32( *name##_buffer_ptr );\
+ name##_cache0 |= NEG_USR32(next,name##_bit_count);\
+ name##_cache1 |= next<<name##_bit_count;\
+ name##_buffer_ptr++;\
+ name##_bit_count-= 32;\
+ }\
+
+#if defined(ARCH_X86)
+# define SKIP_CACHE(name, gb, num)\
+ asm(\
+ "shldl %2, %1, %0 \n\t"\
+ "shll %2, %1 \n\t"\
+ : "+r" (name##_cache0), "+r" (name##_cache1)\
+ : "Ic" ((uint8_t)(num))\
+ );
+#else
+# define SKIP_CACHE(name, gb, num)\
+ name##_cache0 <<= (num);\
+ name##_cache0 |= NEG_USR32(name##_cache1,num);\
+ name##_cache1 <<= (num);
+#endif
+
+# define SKIP_COUNTER(name, gb, num)\
+ name##_bit_count += (num);\
+
+# define SKIP_BITS(name, gb, num)\
+ {\
+ SKIP_CACHE(name, gb, num)\
+ SKIP_COUNTER(name, gb, num)\
+ }\
+
+# define LAST_SKIP_BITS(name, gb, num) SKIP_BITS(name, gb, num)
+# define LAST_SKIP_CACHE(name, gb, num) SKIP_CACHE(name, gb, num)
+
+# define SHOW_UBITS(name, gb, num)\
+ NEG_USR32(name##_cache0, num)
+
+# define SHOW_SBITS(name, gb, num)\
+ NEG_SSR32(name##_cache0, num)
+
+# define GET_CACHE(name, gb)\
+ (name##_cache0)
+
+static inline int get_bits_count(GetBitContext *s){
+ return ((uint8_t*)s->buffer_ptr - s->buffer)*8 - 32 + s->bit_count;
+}
+
+static inline void skip_bits_long(GetBitContext *s, int n){
+ OPEN_READER(re, s)
+ re_bit_count += n;
+ re_buffer_ptr += re_bit_count>>5;
+ re_bit_count &= 31;
+ re_cache0 = be2me_32( re_buffer_ptr[-1] ) << re_bit_count;
+ re_cache1 = 0;
+ UPDATE_CACHE(re, s)
+ CLOSE_READER(re, s)
+}
+
+#endif
+
+/**
+ * read mpeg1 dc style vlc (sign bit + mantisse with no MSB).
+ * if MSB not set it is negative
+ * @param n length in bits
+ * @author BERO
+ */
+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)
+ UPDATE_CACHE(re, s)
+ tmp= SHOW_SBITS(re, s, n);
+ LAST_SKIP_BITS(re, s, n)
+ CLOSE_READER(re, s)
+ return tmp;
+}
+
+/**
+ * reads 0-17 bits.
+ * Note, the alt bitstream reader can read up to 25 bits, but the libmpeg2 reader can't
+ */
+static inline unsigned int get_bits(GetBitContext *s, int n){
+ register int tmp;
+ OPEN_READER(re, s)
+ UPDATE_CACHE(re, s)
+ tmp= SHOW_UBITS(re, s, n);
+ LAST_SKIP_BITS(re, s, n)
+ CLOSE_READER(re, s)
+ return tmp;
+}
+
+/**
+ * shows 0-17 bits.
+ * Note, the alt bitstream reader can read up to 25 bits, but the libmpeg2 reader can't
+ */
+static inline unsigned int show_bits(GetBitContext *s, int n){
+ register int tmp;
+ OPEN_READER(re, s)
+ UPDATE_CACHE(re, s)
+ tmp= SHOW_UBITS(re, s, n);
+// CLOSE_READER(re, s)
+ return tmp;
+}
+
+static inline void skip_bits(GetBitContext *s, int n){
+ //Note gcc seems to optimize this to s->index+=n for the ALT_READER :))
+ 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){
+#ifdef ALT_BITSTREAM_READER
+ int index= s->index;
+ uint8_t result= s->buffer[ index>>3 ];
+#ifdef ALT_BITSTREAM_READER_LE
+ result>>= (index&0x07);
+ result&= 1;
+#else
+ result<<= (index&0x07);
+ result>>= 8 - 1;
+#endif
+ index++;
+ s->index= index;
+
+ return result;
+#else
+ return get_bits(s, 1);
+#endif
+}
+
+static inline unsigned int show_bits1(GetBitContext *s){
+ return show_bits(s, 1);
+}
+
+static inline void skip_bits1(GetBitContext *s){
+ skip_bits(s, 1);
+}
+
+/**
+ * reads 0-32 bits.
+ */
+static inline unsigned int get_bits_long(GetBitContext *s, int n){
+ if(n<=17) return get_bits(s, n);
+ else{
+#ifdef ALT_BITSTREAM_READER_LE
+ int ret= get_bits(s, 16);
+ return ret | (get_bits(s, n-16) << 16);
+#else
+ int ret= get_bits(s, 16) << (n-16);
+ return ret | get_bits(s, n-16);
+#endif
+ }
+}
+
+/**
+ * shows 0-32 bits.
+ */
+static inline unsigned int show_bits_long(GetBitContext *s, int n){
+ if(n<=17) return show_bits(s, n);
+ else{
+ GetBitContext gb= *s;
+ int ret= get_bits_long(s, n);
+ *s= gb;
+ return ret;
+ }
+}
+
+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;
+}
+
+/**
+ * init GetBitContext.
+ * @param buffer bitstream buffer, must be FF_INPUT_BUFFER_PADDING_SIZE bytes larger then 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
+ */
+static inline void init_get_bits(GetBitContext *s,
+ const uint8_t *buffer, int bit_size)
+{
+ int buffer_size= (bit_size+7)>>3;
+ if(buffer_size < 0 || bit_size < 0) {
+ buffer_size = bit_size = 0;
+ buffer = NULL;
+ }
+
+ s->buffer= buffer;
+ s->size_in_bits= bit_size;
+ s->buffer_end= buffer + buffer_size;
+#ifdef ALT_BITSTREAM_READER
+ s->index=0;
+#elif defined LIBMPEG2_BITSTREAM_READER
+ s->buffer_ptr = (uint8_t*)((intptr_t)buffer&(~1));
+ s->bit_count = 16 + 8*((intptr_t)buffer&1);
+ skip_bits_long(s, 0);
+#elif defined A32_BITSTREAM_READER
+ s->buffer_ptr = (uint32_t*)((intptr_t)buffer&(~3));
+ s->bit_count = 32 + 8*((intptr_t)buffer&3);
+ skip_bits_long(s, 0);
+#endif
+}
+
+static inline void align_get_bits(GetBitContext *s)
+{
+ int n= (-get_bits_count(s)) & 7;
+ if(n) skip_bits(s, n);
+}
+
+int init_vlc(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,
+ int flags);
+#define INIT_VLC_USE_STATIC 1
+#define INIT_VLC_LE 2
+void free_vlc(VLC *vlc);
+
+/**
+ *
+ * if the vlc code is invalid and max_depth=1 than no bits will be removed
+ * if the vlc code is invalid and max_depth>1 than the number of bits removed
+ * is undefined
+ */
+#define GET_VLC(code, name, gb, table, bits, max_depth)\
+{\
+ int n, index, nb_bits;\
+\
+ 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)\
+}
+
+#define GET_RL_VLC(level, run, name, gb, table, bits, max_depth, need_update)\
+{\
+ int n, index, nb_bits;\
+\
+ 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)\
+}
+
+
+/**
+ * parses a vlc code, faster then get_vlc()
+ * @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 readed to completly
+ * read the longest vlc code
+ * = (max_vlc_length + bits - 1) / bits
+ */
+static 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;
+}
+
+//#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, 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, 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, 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(...) av_log(NULL, AV_LOG_DEBUG, __VA_ARGS__)
+
+#else //TRACE
+#define tprintf(...) {}
+#endif
+
+static inline int decode012(GetBitContext *gb){
+ int n;
+ n = get_bits1(gb);
+ if (n == 0)
+ return 0;
+ else
+ return get_bits1(gb) + 1;
+}
+
+#endif /* BITSTREAM_H */
diff --git a/contrib/ffmpeg/libavcodec/bitstream_filter.c b/contrib/ffmpeg/libavcodec/bitstream_filter.c
new file mode 100644
index 000000000..b52acf60a
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/bitstream_filter.c
@@ -0,0 +1,284 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * 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 "mpegaudio.h"
+
+AVBitStreamFilter *first_bitstream_filter= NULL;
+
+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= av_mallocz(bsf->priv_data_size);
+ return bsfc;
+ }
+ bsf= bsf->next;
+ }
+ return NULL;
+}
+
+void av_bitstream_filter_close(AVBitStreamFilterContext *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);
+}
+
+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;
+}
+
+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;
+}
+
+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){
+ int amount= args ? atoi(args) : 10000;
+ unsigned int *state= bsfc->priv_data;
+ int i;
+
+ *poutbuf= av_malloc(buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+
+ memcpy(*poutbuf, buf, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ for(i=0; i<buf_size; i++){
+ (*state) += (*poutbuf)[i] + 1;
+ if(*state % amount == 0)
+ (*poutbuf)[i] = *state;
+ }
+ return 1;
+}
+
+#define MP3_MASK 0xFFFE0CCF
+
+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 = BE_32(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 = BE_32(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;
+}
+
+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 = BE_32(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= BE_32(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= 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 = 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, "couldnt 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;
+ }
+ }
+
+ (*poutbuf)[0]= header>>24;
+ (*poutbuf)[1]= header>>16;
+ (*poutbuf)[2]= header>> 8;
+ (*poutbuf)[3]= header ;
+
+ return 1;
+}
+
+AVBitStreamFilter dump_extradata_bsf={
+ "dump_extra",
+ 0,
+ dump_extradata,
+};
+
+AVBitStreamFilter remove_extradata_bsf={
+ "remove_extra",
+ 0,
+ remove_extradata,
+};
+
+AVBitStreamFilter noise_bsf={
+ "noise",
+ sizeof(int),
+ noise,
+};
+
+AVBitStreamFilter mp3_header_compress_bsf={
+ "mp3comp",
+ 0,
+ mp3_header_compress,
+};
+
+AVBitStreamFilter mp3_header_decompress_bsf={
+ "mp3decomp",
+ 0,
+ mp3_header_decompress,
+};
diff --git a/contrib/ffmpeg/libavcodec/bmp.c b/contrib/ffmpeg/libavcodec/bmp.c
new file mode 100644
index 000000000..2a4d83393
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/bmp.c
@@ -0,0 +1,254 @@
+/*
+ * BMP image format
+ * 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 "bitstream.h"
+#include "bswap.h"
+
+typedef struct BMPContext {
+ AVFrame picture;
+} BMPContext;
+
+#define BMP_RGB 0
+#define BMP_RLE8 1
+#define BMP_RLE4 2
+#define BMP_BITFIELDS 3
+
+#define read16(bits) bswap_16(get_bits(bits, 16))
+#define read32(bits) bswap_32(get_bits_long(bits, 32))
+
+static int bmp_decode_init(AVCodecContext *avctx){
+ BMPContext *s = avctx->priv_data;
+
+ avcodec_get_frame_defaults((AVFrame*)&s->picture);
+ avctx->coded_frame = (AVFrame*)&s->picture;
+
+ return 0;
+}
+
+static int bmp_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ BMPContext *s = avctx->priv_data;
+ AVFrame *picture = data;
+ AVFrame *p = &s->picture;
+ GetBitContext bits;
+ unsigned int fsize, hsize;
+ int width, height;
+ unsigned int depth;
+ unsigned int comp;
+ unsigned int ihsize;
+ int i, j, n, linesize;
+ uint32_t rgb[3];
+ uint8_t *ptr;
+ int dsize;
+
+ if(buf_size < 14){
+ av_log(avctx, AV_LOG_ERROR, "buf size too small (%d)\n", buf_size);
+ return -1;
+ }
+
+ init_get_bits(&bits, buf, buf_size);
+
+ if(get_bits(&bits, 16) != 0x424d){ /* 'BM' */
+ av_log(avctx, AV_LOG_ERROR, "bad magic number\n");
+ return -1;
+ }
+
+ fsize = read32(&bits);
+ if(buf_size < fsize){
+ av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n",
+ buf_size, fsize);
+ return -1;
+ }
+
+ skip_bits(&bits, 16); /* reserved1 */
+ skip_bits(&bits, 16); /* reserved2 */
+
+ hsize = read32(&bits); /* header size */
+ if(fsize <= hsize){
+ av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n",
+ fsize, hsize);
+ return -1;
+ }
+
+ ihsize = read32(&bits); /* more header size */
+ if(ihsize + 14 > hsize){
+ av_log(avctx, AV_LOG_ERROR, "invalid header size %d\n", hsize);
+ return -1;
+ }
+
+ width = read32(&bits);
+ height = read32(&bits);
+
+ if(read16(&bits) != 1){ /* planes */
+ av_log(avctx, AV_LOG_ERROR, "invalid BMP header\n");
+ return -1;
+ }
+
+ depth = read16(&bits);
+
+ if(ihsize > 16)
+ comp = read32(&bits);
+ else
+ comp = BMP_RGB;
+
+ if(comp != BMP_RGB && comp != BMP_BITFIELDS){
+ av_log(avctx, AV_LOG_ERROR, "BMP coding %d not supported\n", comp);
+ return -1;
+ }
+
+ if(comp == BMP_BITFIELDS){
+ skip_bits(&bits, 20 * 8);
+ rgb[0] = read32(&bits);
+ rgb[1] = read32(&bits);
+ rgb[2] = read32(&bits);
+ }
+
+ avctx->codec_id = CODEC_ID_BMP;
+ avctx->width = width;
+ avctx->height = height > 0? height: -height;
+
+ avctx->pix_fmt = PIX_FMT_NONE;
+
+ switch(depth){
+ case 32:
+ if(comp == BMP_BITFIELDS){
+ rgb[0] = (rgb[0] >> 15) & 3;
+ rgb[1] = (rgb[1] >> 15) & 3;
+ rgb[2] = (rgb[2] >> 15) & 3;
+
+ if(rgb[0] + rgb[1] + rgb[2] != 3 ||
+ rgb[0] == rgb[1] || rgb[0] == rgb[2] || rgb[1] == rgb[2]){
+ break;
+ }
+ } else {
+ rgb[0] = 2;
+ rgb[1] = 1;
+ rgb[2] = 0;
+ }
+
+ avctx->pix_fmt = PIX_FMT_BGR24;
+ break;
+ case 24:
+ avctx->pix_fmt = PIX_FMT_BGR24;
+ break;
+ case 16:
+ if(comp == BMP_RGB)
+ avctx->pix_fmt = PIX_FMT_RGB555;
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "depth %d not supported\n", depth);
+ return -1;
+ }
+
+ if(avctx->pix_fmt == PIX_FMT_NONE){
+ av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n");
+ return -1;
+ }
+
+ p->reference = 0;
+ if(avctx->get_buffer(avctx, p) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+ p->pict_type = FF_I_TYPE;
+ p->key_frame = 1;
+
+ buf += hsize;
+ dsize = buf_size - hsize;
+
+ /* Line size in file multiple of 4 */
+ n = (avctx->width * (depth / 8) + 3) & ~3;
+
+ if(n * avctx->height > dsize){
+ av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n",
+ dsize, n * avctx->height);
+ return -1;
+ }
+
+ 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];
+ }
+
+ switch(depth){
+ case 24:
+ for(i = 0; i < avctx->height; i++){
+ memcpy(ptr, buf, n);
+ buf += n;
+ ptr += linesize;
+ }
+ break;
+ case 16:
+ for(i = 0; i < avctx->height; i++){
+ uint16_t *src = (uint16_t *) buf;
+ uint16_t *dst = (uint16_t *) ptr;
+
+ for(j = 0; j < avctx->width; j++)
+ *dst++ = le2me_16(*src++);
+
+ buf += n;
+ ptr += linesize;
+ }
+ break;
+ case 32:
+ for(i = 0; i < avctx->height; i++){
+ uint8_t *src = buf;
+ uint8_t *dst = ptr;
+
+ for(j = 0; j < avctx->width; j++){
+ dst[0] = src[rgb[2]];
+ dst[1] = src[rgb[1]];
+ dst[2] = src[rgb[0]];
+ dst += 3;
+ src += 4;
+ }
+
+ buf += n;
+ ptr += linesize;
+ }
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "BMP decoder is broken\n");
+ return -1;
+ }
+
+ *picture = s->picture;
+ *data_size = sizeof(AVPicture);
+
+ return buf_size;
+}
+
+AVCodec bmp_decoder = {
+ "bmp",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_BMP,
+ sizeof(BMPContext),
+ bmp_decode_init,
+ NULL,
+ NULL,
+ bmp_decode_frame
+};
diff --git a/contrib/ffmpeg/libavcodec/bytestream.h b/contrib/ffmpeg/libavcodec/bytestream.h
new file mode 100644
index 000000000..25c457fe4
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/bytestream.h
@@ -0,0 +1,89 @@
+/*
+ * Bytestream functions
+ * copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@free.fr>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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_BYTESTREAM_H
+#define FFMPEG_BYTESTREAM_H
+
+static always_inline unsigned int bytestream_get_le32(uint8_t **b)
+{
+ (*b) += 4;
+ return LE_32(*b - 4);
+}
+
+static always_inline unsigned int bytestream_get_le16(uint8_t **b)
+{
+ (*b) += 2;
+ return LE_16(*b - 2);
+}
+
+static always_inline unsigned int bytestream_get_byte(uint8_t **b)
+{
+ (*b)++;
+ return (*b)[-1];
+}
+
+static always_inline unsigned int bytestream_get_buffer(uint8_t **b, uint8_t *dst, unsigned int size)
+{
+ memcpy(dst, *b, size);
+ (*b) += size;
+ return size;
+}
+
+static always_inline void bytestream_put_be32(uint8_t **b, const unsigned int value)
+{
+ *(*b)++ = value >> 24;
+ *(*b)++ = value >> 16;
+ *(*b)++ = value >> 8;
+ *(*b)++ = value;
+};
+
+static always_inline void bytestream_put_be16(uint8_t **b, const unsigned int value)
+{
+ *(*b)++ = value >> 8;
+ *(*b)++ = value;
+}
+
+static always_inline void bytestream_put_le32(uint8_t **b, const unsigned int value)
+{
+ *(*b)++ = value;
+ *(*b)++ = value >> 8;
+ *(*b)++ = value >> 16;
+ *(*b)++ = value >> 24;
+}
+
+static always_inline void bytestream_put_le16(uint8_t **b, const unsigned int value)
+{
+ *(*b)++ = value;
+ *(*b)++ = value >> 8;
+}
+
+static always_inline void bytestream_put_byte(uint8_t **b, const unsigned int value)
+{
+ *(*b)++ = value;
+}
+
+static always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
+{
+ memcpy(*b, src, size);
+ (*b) += size;
+}
+
+#endif /* FFMPEG_BYTESTREAM_H */
diff --git a/contrib/ffmpeg/libavcodec/cabac.c b/contrib/ffmpeg/libavcodec/cabac.c
new file mode 100644
index 000000000..c6da6292a
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/cabac.c
@@ -0,0 +1,265 @@
+/*
+ * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder
+ * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/**
+ * @file cabac.c
+ * Context Adaptive Binary Arithmetic Coder.
+ */
+
+#include <string.h>
+
+#include "common.h"
+#include "bitstream.h"
+#include "cabac.h"
+
+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},
+};
+
+uint8_t ff_h264_mlps_state[4*64];
+uint8_t ff_h264_lps_range[4*2*64];
+uint8_t ff_h264_lps_state[2*64];
+uint8_t ff_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,
+};
+#if 0
+const uint8_t ff_h264_norm_shift_old[128]= {
+ 7,6,5,5,4,4,4,4,3,3,3,3,3,3,3,3,
+ 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,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+};
+#endif
+const uint8_t ff_h264_norm_shift[512]= {
+ 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,
+};
+
+/**
+ *
+ * @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;
+#ifdef STRICT_LIMITS
+ c->sym_count =0;
+#endif
+
+ 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(CABACContext *c){
+ 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]=
+ ff_h264_mps_state[2*i+0]= 2*mps_state[i]+0;
+ ff_h264_mlps_state[128+2*i+1]=
+ ff_h264_mps_state[2*i+1]= 2*mps_state[i]+1;
+
+ if( i ){
+#ifdef BRANCHLESS_CABAC_DECODER
+ ff_h264_mlps_state[128-2*i-1]= 2*lps_state[i]+0;
+ ff_h264_mlps_state[128-2*i-2]= 2*lps_state[i]+1;
+ }else{
+ ff_h264_mlps_state[128-2*i-1]= 1;
+ ff_h264_mlps_state[128-2*i-2]= 0;
+#else
+ ff_h264_lps_state[2*i+0]= 2*lps_state[i]+0;
+ ff_h264_lps_state[2*i+1]= 2*lps_state[i]+1;
+ }else{
+ ff_h264_lps_state[2*i+0]= 1;
+ ff_h264_lps_state[2*i+1]= 0;
+#endif
+ }
+ }
+}
+
+#if 0 //selftest
+#define SIZE 10240
+
+#include "avcodec.h"
+
+int main(){
+ CABACContext c;
+ uint8_t b[9*SIZE];
+ uint8_t r[9*SIZE];
+ int i;
+ uint8_t state[10]= {0};
+
+ ff_init_cabac_encoder(&c, b, SIZE);
+ ff_init_cabac_states(&c, ff_h264_lps_range, ff_h264_mps_state, ff_h264_lps_state, 64);
+
+ for(i=0; i<SIZE; i++){
+ r[i]= random()%7;
+ }
+
+ for(i=0; i<SIZE; i++){
+START_TIMER
+ put_cabac_bypass(&c, r[i]&1);
+STOP_TIMER("put_cabac_bypass")
+ }
+
+ for(i=0; i<SIZE; i++){
+START_TIMER
+ put_cabac(&c, state, r[i]&1);
+STOP_TIMER("put_cabac")
+ }
+
+ for(i=0; i<SIZE; i++){
+START_TIMER
+ put_cabac_u(&c, state, r[i], 6, 3, i&1);
+STOP_TIMER("put_cabac_u")
+ }
+
+ for(i=0; i<SIZE; i++){
+START_TIMER
+ put_cabac_ueg(&c, state, r[i], 3, 0, 1, 2);
+STOP_TIMER("put_cabac_ueg")
+ }
+
+ put_cabac_terminate(&c, 1);
+
+ ff_init_cabac_decoder(&c, b, SIZE);
+
+ memset(state, 0, sizeof(state));
+
+ for(i=0; i<SIZE; i++){
+START_TIMER
+ if( (r[i]&1) != get_cabac_bypass(&c) )
+ av_log(NULL, AV_LOG_ERROR, "CABAC bypass failure at %d\n", i);
+STOP_TIMER("get_cabac_bypass")
+ }
+
+ for(i=0; i<SIZE; i++){
+START_TIMER
+ if( (r[i]&1) != get_cabac(&c, state) )
+ av_log(NULL, AV_LOG_ERROR, "CABAC failure at %d\n", i);
+STOP_TIMER("get_cabac")
+ }
+#if 0
+ for(i=0; i<SIZE; i++){
+START_TIMER
+ if( r[i] != get_cabac_u(&c, state, (i&1) ? 6 : 7, 3, i&1) )
+ av_log(NULL, AV_LOG_ERROR, "CABAC unary (truncated) binarization failure at %d\n", i);
+STOP_TIMER("get_cabac_u")
+ }
+
+ for(i=0; i<SIZE; i++){
+START_TIMER
+ if( r[i] != get_cabac_ueg(&c, state, 3, 0, 1, 2))
+ av_log(NULL, AV_LOG_ERROR, "CABAC unary (truncated) binarization failure at %d\n", i);
+STOP_TIMER("get_cabac_ueg")
+ }
+#endif
+ if(!get_cabac_terminate(&c))
+ av_log(NULL, AV_LOG_ERROR, "where's the Terminator?\n");
+
+ return 0;
+}
+
+#endif
diff --git a/contrib/ffmpeg/libavcodec/cabac.h b/contrib/ffmpeg/libavcodec/cabac.h
new file mode 100644
index 000000000..43fe78e3b
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/cabac.h
@@ -0,0 +1,859 @@
+/*
+ * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder
+ * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/**
+ * @file cabac.h
+ * Context Adaptive Binary Arithmetic Coder.
+ */
+
+
+//#undef NDEBUG
+#include <assert.h>
+#ifdef ARCH_X86
+#include "x86_cpu.h"
+#endif
+
+#define CABAC_BITS 16
+#define CABAC_MASK ((1<<CABAC_BITS)-1)
+#define BRANCHLESS_CABAC_DECODER 1
+//#define ARCH_X86_DISABLED 1
+
+typedef struct CABACContext{
+ int low;
+ int range;
+ int outstanding_count;
+#ifdef STRICT_LIMITS
+ int symCount;
+#endif
+ const uint8_t *bytestream_start;
+ const uint8_t *bytestream;
+ const uint8_t *bytestream_end;
+ PutBitContext pb;
+}CABACContext;
+
+extern uint8_t ff_h264_mlps_state[4*64];
+extern uint8_t ff_h264_lps_range[4*2*64]; ///< rangeTabLPS
+extern uint8_t ff_h264_mps_state[2*64]; ///< transIdxMPS
+extern uint8_t ff_h264_lps_state[2*64]; ///< transIdxLPS
+extern const uint8_t ff_h264_norm_shift[512];
+
+
+void ff_init_cabac_encoder(CABACContext *c, uint8_t *buf, int buf_size);
+void ff_init_cabac_decoder(CABACContext *c, const uint8_t *buf, int buf_size);
+void ff_init_cabac_states(CABACContext *c);
+
+
+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= ff_h264_mps_state[*state];
+ }else{
+ c->low += c->range - RangeLPS;
+ c->range = RangeLPS;
+ *state= ff_h264_lps_state[*state];
+ }
+
+ renorm_cabac_encoder(c);
+
+#ifdef STRICT_LIMITS
+ c->symCount++;
+#endif
+}
+
+static void put_cabac_static(CABACContext *c, int RangeLPS, int bit){
+ assert(c->range > RangeLPS);
+
+ if(!bit){
+ c->range -= RangeLPS;
+ }else{
+ c->low += c->range - RangeLPS;
+ c->range = RangeLPS;
+ }
+
+ renorm_cabac_encoder(c);
+
+#ifdef STRICT_LIMITS
+ c->symCount++;
+#endif
+}
+
+/**
+ * @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;
+ }
+
+#ifdef STRICT_LIMITS
+ c->symCount++;
+#endif
+}
+
+/**
+ *
+ * @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);
+
+ assert(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
+ }
+
+#ifdef STRICT_LIMITS
+ c->symCount++;
+#endif
+
+ return (put_bits_count(&c->pb)+7)>>3;
+}
+
+/**
+ * put (truncated) unary binarization.
+ */
+static void put_cabac_u(CABACContext *c, uint8_t * state, int v, int max, int max_index, int truncated){
+ int i;
+
+ assert(v <= max);
+
+#if 1
+ for(i=0; i<v; i++){
+ put_cabac(c, state, 1);
+ if(i < max_index) state++;
+ }
+ if(truncated==0 || v<max)
+ put_cabac(c, state, 0);
+#else
+ if(v <= max_index){
+ for(i=0; i<v; i++){
+ put_cabac(c, state+i, 1);
+ }
+ if(truncated==0 || v<max)
+ put_cabac(c, state+i, 0);
+ }else{
+ for(i=0; i<=max_index; i++){
+ put_cabac(c, state+i, 1);
+ }
+ for(; i<v; i++){
+ put_cabac(c, state+max_index, 1);
+ }
+ if(truncated==0 || v<max)
+ put_cabac(c, state+max_index, 0);
+ }
+#endif
+}
+
+/**
+ * put unary exp golomb k-th order binarization.
+ */
+static void put_cabac_ueg(CABACContext *c, uint8_t * state, int v, int max, int is_signed, int k, int max_index){
+ int i;
+
+ if(v==0)
+ put_cabac(c, state, 0);
+ else{
+ const int sign= v < 0;
+
+ if(is_signed) v= FFABS(v);
+
+ if(v<max){
+ for(i=0; i<v; i++){
+ put_cabac(c, state, 1);
+ if(i < max_index) state++;
+ }
+
+ put_cabac(c, state, 0);
+ }else{
+ int m= 1<<k;
+
+ for(i=0; i<max; i++){
+ put_cabac(c, state, 1);
+ if(i < max_index) state++;
+ }
+
+ v -= max;
+ while(v >= m){ //FIXME optimize
+ put_cabac_bypass(c, 1);
+ v-= m;
+ m+= m;
+ }
+ put_cabac_bypass(c, 0);
+ while(m>>=1){
+ put_cabac_bypass(c, v&m);
+ }
+ }
+
+ if(is_signed)
+ put_cabac_bypass(c, sign);
+ }
+}
+
+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 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<<i;
+ c->bytestream+= CABAC_BITS/8;
+}
+
+static inline void renorm_cabac_decoder(CABACContext *c){
+ while(c->range < 0x100){
+ c->range+= c->range;
+ c->low+= c->low;
+ if(!(c->low & CABAC_MASK))
+ refill(c);
+ }
+}
+
+static inline void renorm_cabac_decoder_once(CABACContext *c){
+#ifdef ARCH_X86_DISABLED
+ int temp;
+#if 0
+ //P3:683 athlon:475
+ asm(
+ "lea -0x100(%0), %2 \n\t"
+ "shr $31, %2 \n\t" //FIXME 31->63 for x86-64
+ "shl %%cl, %0 \n\t"
+ "shl %%cl, %1 \n\t"
+ : "+r"(c->range), "+r"(c->low), "+c"(temp)
+ );
+#elif 0
+ //P3:680 athlon:474
+ asm(
+ "cmp $0x100, %0 \n\t"
+ "setb %%cl \n\t" //FIXME 31->63 for x86-64
+ "shl %%cl, %0 \n\t"
+ "shl %%cl, %1 \n\t"
+ : "+r"(c->range), "+r"(c->low), "+c"(temp)
+ );
+#elif 1
+ int temp2;
+ //P3:665 athlon:517
+ asm(
+ "lea -0x100(%0), %%eax \n\t"
+ "cdq \n\t"
+ "mov %0, %%eax \n\t"
+ "and %%edx, %0 \n\t"
+ "and %1, %%edx \n\t"
+ "add %%eax, %0 \n\t"
+ "add %%edx, %1 \n\t"
+ : "+r"(c->range), "+r"(c->low), "+a"(temp), "+d"(temp2)
+ );
+#elif 0
+ int temp2;
+ //P3:673 athlon:509
+ asm(
+ "cmp $0x100, %0 \n\t"
+ "sbb %%edx, %%edx \n\t"
+ "mov %0, %%eax \n\t"
+ "and %%edx, %0 \n\t"
+ "and %1, %%edx \n\t"
+ "add %%eax, %0 \n\t"
+ "add %%edx, %1 \n\t"
+ : "+r"(c->range), "+r"(c->low), "+a"(temp), "+d"(temp2)
+ );
+#else
+ int temp2;
+ //P3:677 athlon:511
+ asm(
+ "cmp $0x100, %0 \n\t"
+ "lea (%0, %0), %%eax \n\t"
+ "lea (%1, %1), %%edx \n\t"
+ "cmovb %%eax, %0 \n\t"
+ "cmovb %%edx, %1 \n\t"
+ : "+r"(c->range), "+r"(c->low), "+a"(temp), "+d"(temp2)
+ );
+#endif
+#else
+ //P3:675 athlon:476
+ int shift= (uint32_t)(c->range - 0x100)>>31;
+ c->range<<= shift;
+ c->low <<= shift;
+#endif
+ if(!(c->low & CABAC_MASK))
+ refill(c);
+}
+
+static int always_inline get_cabac_inline(CABACContext *c, uint8_t * const state){
+ //FIXME gcc generates duplicate load/stores for c->low and c->range
+#define LOW "0"
+#define RANGE "4"
+#ifdef ARCH_X86_64
+#define BYTESTART "16"
+#define BYTE "24"
+#define BYTEEND "32"
+#else
+#define BYTESTART "12"
+#define BYTE "16"
+#define BYTEEND "20"
+#endif
+#if defined(ARCH_X86) && !(defined(PIC) && defined(__GNUC__))
+ int bit;
+
+#ifndef BRANCHLESS_CABAC_DECODER
+ asm volatile(
+ "movzbl (%1), %0 \n\t"
+ "movl "RANGE "(%2), %%ebx \n\t"
+ "movl "RANGE "(%2), %%edx \n\t"
+ "andl $0xC0, %%ebx \n\t"
+ "movzbl "MANGLE(ff_h264_lps_range)"(%0, %%ebx, 2), %%esi\n\t"
+ "movl "LOW "(%2), %%ebx \n\t"
+//eax:state ebx:low, edx:range, esi:RangeLPS
+ "subl %%esi, %%edx \n\t"
+ "movl %%edx, %%ecx \n\t"
+ "shll $17, %%ecx \n\t"
+ "cmpl %%ecx, %%ebx \n\t"
+ " ja 1f \n\t"
+
+#if 1
+ //athlon:4067 P3:4110
+ "lea -0x100(%%edx), %%ecx \n\t"
+ "shr $31, %%ecx \n\t"
+ "shl %%cl, %%edx \n\t"
+ "shl %%cl, %%ebx \n\t"
+#else
+ //athlon:4057 P3:4130
+ "cmp $0x100, %%edx \n\t" //FIXME avoidable
+ "setb %%cl \n\t"
+ "shl %%cl, %%edx \n\t"
+ "shl %%cl, %%ebx \n\t"
+#endif
+ "movzbl "MANGLE(ff_h264_mps_state)"(%0), %%ecx \n\t"
+ "movb %%cl, (%1) \n\t"
+//eax:state ebx:low, edx:range, esi:RangeLPS
+ "test %%bx, %%bx \n\t"
+ " jnz 2f \n\t"
+ "mov "BYTE "(%2), %%"REG_S" \n\t"
+ "subl $0xFFFF, %%ebx \n\t"
+ "movzwl (%%"REG_S"), %%ecx \n\t"
+ "bswap %%ecx \n\t"
+ "shrl $15, %%ecx \n\t"
+ "add $2, %%"REG_S" \n\t"
+ "addl %%ecx, %%ebx \n\t"
+ "mov %%"REG_S", "BYTE "(%2) \n\t"
+ "jmp 2f \n\t"
+ "1: \n\t"
+//eax:state ebx:low, edx:range, esi:RangeLPS
+ "subl %%ecx, %%ebx \n\t"
+ "movl %%esi, %%edx \n\t"
+ "movzbl " MANGLE(ff_h264_norm_shift) "(%%esi), %%ecx \n\t"
+ "shll %%cl, %%ebx \n\t"
+ "shll %%cl, %%edx \n\t"
+ "movzbl "MANGLE(ff_h264_lps_state)"(%0), %%ecx \n\t"
+ "movb %%cl, (%1) \n\t"
+ "add $1, %0 \n\t"
+ "test %%bx, %%bx \n\t"
+ " jnz 2f \n\t"
+
+ "mov "BYTE "(%2), %%"REG_c" \n\t"
+ "movzwl (%%"REG_c"), %%esi \n\t"
+ "bswap %%esi \n\t"
+ "shrl $15, %%esi \n\t"
+ "subl $0xFFFF, %%esi \n\t"
+ "add $2, %%"REG_c" \n\t"
+ "mov %%"REG_c", "BYTE "(%2) \n\t"
+
+ "leal -1(%%ebx), %%ecx \n\t"
+ "xorl %%ebx, %%ecx \n\t"
+ "shrl $15, %%ecx \n\t"
+ "movzbl " MANGLE(ff_h264_norm_shift) "(%%ecx), %%ecx \n\t"
+ "neg %%ecx \n\t"
+ "add $7, %%ecx \n\t"
+
+ "shll %%cl , %%esi \n\t"
+ "addl %%esi, %%ebx \n\t"
+ "2: \n\t"
+ "movl %%edx, "RANGE "(%2) \n\t"
+ "movl %%ebx, "LOW "(%2) \n\t"
+ :"=&a"(bit) //FIXME this is fragile gcc either runs out of registers or misscompiles it (for example if "+a"(bit) or "+m"(*state) is used
+ :"r"(state), "r"(c)
+ : "%"REG_c, "%ebx", "%edx", "%"REG_S, "memory"
+ );
+ bit&=1;
+#else /* BRANCHLESS_CABAC_DECODER */
+
+
+#if defined CMOV_IS_FAST
+#define BRANCHLESS_GET_CABAC_UPDATE(ret, cabac, statep, low, lowword, range, tmp, tmpbyte)\
+ "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"\
+ "sub "tmp" , "low" \n\t"\
+ "xor %%ecx , "ret" \n\t"
+#else /* CMOV_IS_FAST */
+#define BRANCHLESS_GET_CABAC_UPDATE(ret, cabac, statep, low, lowword, range, tmp, tmpbyte)\
+ "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 /* CMOV_IS_FAST */
+
+
+#define BRANCHLESS_GET_CABAC(ret, cabac, statep, low, lowword, range, tmp, tmpbyte)\
+ "movzbl "statep" , "ret" \n\t"\
+ "mov "range" , "tmp" \n\t"\
+ "and $0xC0 , "range" \n\t"\
+ "movzbl "MANGLE(ff_h264_lps_range)"("ret", "range", 2), "range" \n\t"\
+ "sub "range" , "tmp" \n\t"\
+ BRANCHLESS_GET_CABAC_UPDATE(ret, cabac, statep, low, lowword, range, tmp, tmpbyte)\
+ "movzbl " MANGLE(ff_h264_norm_shift) "("range"), %%ecx \n\t"\
+ "shl %%cl , "range" \n\t"\
+ "movzbl "MANGLE(ff_h264_mlps_state)"+128("ret"), "tmp" \n\t"\
+ "mov "tmpbyte" , "statep" \n\t"\
+ "shl %%cl , "low" \n\t"\
+ "test "lowword" , "lowword" \n\t"\
+ " jnz 1f \n\t"\
+ "mov "BYTE"("cabac"), %%"REG_c" \n\t"\
+ "movzwl (%%"REG_c") , "tmp" \n\t"\
+ "bswap "tmp" \n\t"\
+ "shr $15 , "tmp" \n\t"\
+ "sub $0xFFFF , "tmp" \n\t"\
+ "add $2 , %%"REG_c" \n\t"\
+ "mov %%"REG_c" , "BYTE "("cabac") \n\t"\
+ "lea -1("low") , %%ecx \n\t"\
+ "xor "low" , %%ecx \n\t"\
+ "shr $15 , %%ecx \n\t"\
+ "movzbl " MANGLE(ff_h264_norm_shift) "(%%ecx), %%ecx \n\t"\
+ "neg %%ecx \n\t"\
+ "add $7 , %%ecx \n\t"\
+ "shl %%cl , "tmp" \n\t"\
+ "add "tmp" , "low" \n\t"\
+ "1: \n\t"
+
+ asm volatile(
+ "movl "RANGE "(%2), %%esi \n\t"
+ "movl "LOW "(%2), %%ebx \n\t"
+ BRANCHLESS_GET_CABAC("%0", "%2", "(%1)", "%%ebx", "%%bx", "%%esi", "%%edx", "%%dl")
+ "movl %%esi, "RANGE "(%2) \n\t"
+ "movl %%ebx, "LOW "(%2) \n\t"
+
+ :"=&a"(bit)
+ :"r"(state), "r"(c)
+ : "%"REG_c, "%ebx", "%edx", "%esi", "memory"
+ );
+ bit&=1;
+#endif /* BRANCHLESS_CABAC_DECODER */
+#else /* defined(ARCH_X86) && !(defined(PIC) && defined(__GNUC__)) */
+ int s = *state;
+ int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + s];
+ int bit, lps_mask attribute_unused;
+
+ c->range -= RangeLPS;
+#ifndef BRANCHLESS_CABAC_DECODER
+ if(c->low < (c->range<<17)){
+ bit= s&1;
+ *state= ff_h264_mps_state[s];
+ renorm_cabac_decoder_once(c);
+ }else{
+ bit= ff_h264_norm_shift[RangeLPS];
+ c->low -= (c->range<<17);
+ *state= ff_h264_lps_state[s];
+ c->range = RangeLPS<<bit;
+ c->low <<= bit;
+ bit= (s&1)^1;
+
+ if(!(c->low & 0xFFFF)){
+ refill2(c);
+ }
+ }
+#else /* BRANCHLESS_CABAC_DECODER */
+ lps_mask= ((c->range<<17) - c->low)>>31;
+
+ c->low -= (c->range<<17) & 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);
+#endif /* BRANCHLESS_CABAC_DECODER */
+#endif /* defined(ARCH_X86) && !(defined(PIC) && defined(__GNUC__)) */
+ return bit;
+}
+
+static int __attribute((noinline)) get_cabac_noinline(CABACContext *c, uint8_t * const state){
+ return get_cabac_inline(c,state);
+}
+
+static int get_cabac(CABACContext *c, uint8_t * const state){
+ return get_cabac_inline(c,state);
+}
+
+static int get_cabac_bypass(CABACContext *c){
+#if 0 //not faster
+ int bit;
+ asm volatile(
+ "movl "RANGE "(%1), %%ebx \n\t"
+ "movl "LOW "(%1), %%eax \n\t"
+ "shl $17, %%ebx \n\t"
+ "add %%eax, %%eax \n\t"
+ "sub %%ebx, %%eax \n\t"
+ "cdq \n\t"
+ "and %%edx, %%ebx \n\t"
+ "add %%ebx, %%eax \n\t"
+ "test %%ax, %%ax \n\t"
+ " jnz 1f \n\t"
+ "movl "BYTE "(%1), %%"REG_b" \n\t"
+ "subl $0xFFFF, %%eax \n\t"
+ "movzwl (%%"REG_b"), %%ecx \n\t"
+ "bswap %%ecx \n\t"
+ "shrl $15, %%ecx \n\t"
+ "addl $2, %%"REG_b" \n\t"
+ "addl %%ecx, %%eax \n\t"
+ "movl %%"REG_b", "BYTE "(%1) \n\t"
+ "1: \n\t"
+ "movl %%eax, "LOW "(%1) \n\t"
+
+ :"=&d"(bit)
+ :"r"(c)
+ : "%eax", "%"REG_b, "%ecx", "memory"
+ );
+ return bit+1;
+#else
+ int range;
+ c->low += c->low;
+
+ if(!(c->low & CABAC_MASK))
+ refill(c);
+
+ range= c->range<<17;
+ if(c->low < range){
+ return 0;
+ }else{
+ c->low -= range;
+ return 1;
+ }
+#endif
+}
+
+
+static always_inline int get_cabac_bypass_sign(CABACContext *c, int val){
+#if defined(ARCH_X86) && !(defined(PIC) && defined(__GNUC__))
+ asm volatile(
+ "movl "RANGE "(%1), %%ebx \n\t"
+ "movl "LOW "(%1), %%eax \n\t"
+ "shl $17, %%ebx \n\t"
+ "add %%eax, %%eax \n\t"
+ "sub %%ebx, %%eax \n\t"
+ "cdq \n\t"
+ "and %%edx, %%ebx \n\t"
+ "add %%ebx, %%eax \n\t"
+ "xor %%edx, %%ecx \n\t"
+ "sub %%edx, %%ecx \n\t"
+ "test %%ax, %%ax \n\t"
+ " jnz 1f \n\t"
+ "mov "BYTE "(%1), %%"REG_b" \n\t"
+ "subl $0xFFFF, %%eax \n\t"
+ "movzwl (%%"REG_b"), %%edx \n\t"
+ "bswap %%edx \n\t"
+ "shrl $15, %%edx \n\t"
+ "add $2, %%"REG_b" \n\t"
+ "addl %%edx, %%eax \n\t"
+ "mov %%"REG_b", "BYTE "(%1) \n\t"
+ "1: \n\t"
+ "movl %%eax, "LOW "(%1) \n\t"
+
+ :"+c"(val)
+ :"r"(c)
+ : "%eax", "%"REG_b, "%edx", "memory"
+ );
+ return val;
+#else
+ int range, mask;
+ c->low += c->low;
+
+ if(!(c->low & CABAC_MASK))
+ refill(c);
+
+ range= c->range<<17;
+ c->low -= range;
+ mask= c->low >> 31;
+ range &= mask;
+ c->low += range;
+ return (val^mask)-mask;
+#endif
+}
+
+//FIXME the x86 code from this file should be moved into i386/h264 or cabac something.c/h (note ill kill you if you move my code away from under my fingers before iam finished with it!)
+//FIXME use some macros to avoid duplicatin get_cabac (cant be done yet as that would make optimization work hard)
+#if defined(ARCH_X86) && !(defined(PIC) && defined(__GNUC__))
+static int decode_significance_x86(CABACContext *c, int max_coeff, uint8_t *significant_coeff_ctx_base, int *index){
+ void *end= significant_coeff_ctx_base + max_coeff - 1;
+ int minusstart= -(int)significant_coeff_ctx_base;
+ int minusindex= 4-(int)index;
+ int coeff_count;
+ asm volatile(
+ "movl "RANGE "(%3), %%esi \n\t"
+ "movl "LOW "(%3), %%ebx \n\t"
+
+ "2: \n\t"
+
+ BRANCHLESS_GET_CABAC("%%edx", "%3", "(%1)", "%%ebx", "%%bx", "%%esi", "%%eax", "%%al")
+
+ "test $1, %%edx \n\t"
+ " jz 3f \n\t"
+
+ BRANCHLESS_GET_CABAC("%%edx", "%3", "61(%1)", "%%ebx", "%%bx", "%%esi", "%%eax", "%%al")
+
+ "mov %2, %%"REG_a" \n\t"
+ "movl %4, %%ecx \n\t"
+ "add %1, %%"REG_c" \n\t"
+ "movl %%ecx, (%%"REG_a") \n\t"
+
+ "test $1, %%edx \n\t"
+ " jnz 4f \n\t"
+
+ "add $4, %%"REG_a" \n\t"
+ "mov %%"REG_a", %2 \n\t"
+
+ "3: \n\t"
+ "add $1, %1 \n\t"
+ "cmp %5, %1 \n\t"
+ " jb 2b \n\t"
+ "mov %2, %%"REG_a" \n\t"
+ "movl %4, %%ecx \n\t"
+ "add %1, %%"REG_c" \n\t"
+ "movl %%ecx, (%%"REG_a") \n\t"
+ "4: \n\t"
+ "add %6, %%eax \n\t"
+ "shr $2, %%eax \n\t"
+
+ "movl %%esi, "RANGE "(%3) \n\t"
+ "movl %%ebx, "LOW "(%3) \n\t"
+ :"=&a"(coeff_count), "+r"(significant_coeff_ctx_base), "+m"(index)\
+ :"r"(c), "m"(minusstart), "m"(end), "m"(minusindex)\
+ : "%"REG_c, "%ebx", "%edx", "%esi", "memory"\
+ );
+ return coeff_count;
+}
+
+static int decode_significance_8x8_x86(CABACContext *c, uint8_t *significant_coeff_ctx_base, int *index, uint8_t *sig_off){
+ int minusindex= 4-(int)index;
+ int coeff_count;
+ long last=0;
+ asm volatile(
+ "movl "RANGE "(%3), %%esi \n\t"
+ "movl "LOW "(%3), %%ebx \n\t"
+
+ "mov %1, %%"REG_D" \n\t"
+ "2: \n\t"
+
+ "mov %6, %%"REG_a" \n\t"
+ "movzbl (%%"REG_a", %%"REG_D"), %%edi \n\t"
+ "add %5, %%"REG_D" \n\t"
+
+ BRANCHLESS_GET_CABAC("%%edx", "%3", "(%%"REG_D")", "%%ebx", "%%bx", "%%esi", "%%eax", "%%al")
+
+ "mov %1, %%edi \n\t"
+ "test $1, %%edx \n\t"
+ " jz 3f \n\t"
+
+ "movzbl "MANGLE(last_coeff_flag_offset_8x8)"(%%edi), %%edi\n\t"
+ "add %5, %%"REG_D" \n\t"
+
+ BRANCHLESS_GET_CABAC("%%edx", "%3", "15(%%"REG_D")", "%%ebx", "%%bx", "%%esi", "%%eax", "%%al")
+
+ "mov %2, %%"REG_a" \n\t"
+ "mov %1, %%edi \n\t"
+ "movl %%edi, (%%"REG_a") \n\t"
+
+ "test $1, %%edx \n\t"
+ " jnz 4f \n\t"
+
+ "add $4, %%"REG_a" \n\t"
+ "mov %%"REG_a", %2 \n\t"
+
+ "3: \n\t"
+ "addl $1, %%edi \n\t"
+ "mov %%edi, %1 \n\t"
+ "cmpl $63, %%edi \n\t"
+ " jb 2b \n\t"
+ "mov %2, %%"REG_a" \n\t"
+ "movl %%edi, (%%"REG_a") \n\t"
+ "4: \n\t"
+ "addl %4, %%eax \n\t"
+ "shr $2, %%eax \n\t"
+
+ "movl %%esi, "RANGE "(%3) \n\t"
+ "movl %%ebx, "LOW "(%3) \n\t"
+ :"=&a"(coeff_count),"+m"(last), "+m"(index)\
+ :"r"(c), "m"(minusindex), "m"(significant_coeff_ctx_base), "m"(sig_off)\
+ : "%"REG_c, "%ebx", "%edx", "%esi", "%"REG_D, "memory"\
+ );
+ return coeff_count;
+}
+#endif /* defined(ARCH_X86) && !(defined(PIC) && defined(__GNUC__)) */
+
+/**
+ *
+ * @return the number of bytes read or 0 if no end
+ */
+static int get_cabac_terminate(CABACContext *c){
+ c->range -= 2;
+ if(c->low < c->range<<17){
+ renorm_cabac_decoder_once(c);
+ return 0;
+ }else{
+ return c->bytestream - c->bytestream_start;
+ }
+}
+
+/**
+ * get (truncated) unnary binarization.
+ */
+static int get_cabac_u(CABACContext *c, uint8_t * state, int max, int max_index, int truncated){
+ int i;
+
+ for(i=0; i<max; i++){
+ if(get_cabac(c, state)==0)
+ return i;
+
+ if(i< max_index) state++;
+ }
+
+ return truncated ? max : -1;
+}
+
+/**
+ * get unary exp golomb k-th order binarization.
+ */
+static int get_cabac_ueg(CABACContext *c, uint8_t * state, int max, int is_signed, int k, int max_index){
+ int i, v;
+ int m= 1<<k;
+
+ if(get_cabac(c, state)==0)
+ return 0;
+
+ if(0 < max_index) state++;
+
+ for(i=1; i<max; i++){
+ if(get_cabac(c, state)==0){
+ if(is_signed && get_cabac_bypass(c)){
+ return -i;
+ }else
+ return i;
+ }
+
+ if(i < max_index) state++;
+ }
+
+ while(get_cabac_bypass(c)){
+ i+= m;
+ m+= m;
+ }
+
+ v=0;
+ while(m>>=1){
+ v+= v + get_cabac_bypass(c);
+ }
+ i += v;
+
+ if(is_signed && get_cabac_bypass(c)){
+ return -i;
+ }else
+ return i;
+}
diff --git a/contrib/ffmpeg/libavcodec/cavs.c b/contrib/ffmpeg/libavcodec/cavs.c
new file mode 100644
index 000000000..ee862bbc7
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/cavs.c
@@ -0,0 +1,1540 @@
+/*
+ * Chinese AVS video (AVS1-P2, JiZhun profile) decoder.
+ * Copyright (c) 2006 Stefan Gehrer <stefan.gehrer@gmx.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file cavs.c
+ * Chinese AVS video (AVS1-P2, JiZhun profile) decoder
+ * @author Stefan Gehrer <stefan.gehrer@gmx.de>
+ */
+
+#include "avcodec.h"
+#include "bitstream.h"
+#include "golomb.h"
+#include "mpegvideo.h"
+#include "cavsdata.h"
+
+#ifdef CONFIG_CAVS_DECODER
+typedef struct {
+ MpegEncContext s;
+ Picture picture; ///< currently decoded frame
+ Picture DPB[2]; ///< reference frames
+ int dist[2]; ///< temporal distances from current frame to ref frames
+ int profile, level;
+ int aspect_ratio;
+ int mb_width, mb_height;
+ int pic_type;
+ 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; ///< 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 */
+ vector_t mv[2*4*3];
+ vector_t *top_mv[2];
+ vector_t *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;
+ uint8_t *col_type;
+
+ /* 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
+
+ int got_keyframe;
+ DCTELEM *block;
+} AVSContext;
+
+/*****************************************************************************
+ *
+ * in-loop deblocking filter
+ *
+ ****************************************************************************/
+
+static inline int get_bs(vector_t *mvP, vector_t *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[clip(qp_avg + h->alpha_offset,0,63)]; \
+ beta = beta_tab[clip(qp_avg + h->beta_offset, 0,63)]; \
+ tc = tc_tab[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 |
+ * ---------
+ *
+ */
+static void filter_mb(AVSContext *h, enum mb_t mb_type) {
+ DECLARE_ALIGNED_8(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)
+ *((uint64_t *)bs) = 0x0202020202020202ULL;
+ else{
+ *((uint64_t *)bs) = 0;
+ if(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(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( *((uint64_t *)bs) ) {
+ if(h->flags & A_AVAIL) {
+ qp_avg = (h->qp + h->left_qp + 1) >> 1;
+ SET_PARAMS;
+ h->s.dsp.cavs_filter_lv(h->cy,h->l_stride,alpha,beta,tc,bs[0],bs[1]);
+ h->s.dsp.cavs_filter_cv(h->cu,h->c_stride,alpha,beta,tc,bs[0],bs[1]);
+ h->s.dsp.cavs_filter_cv(h->cv,h->c_stride,alpha,beta,tc,bs[0],bs[1]);
+ }
+ qp_avg = h->qp;
+ SET_PARAMS;
+ h->s.dsp.cavs_filter_lv(h->cy + 8,h->l_stride,alpha,beta,tc,bs[2],bs[3]);
+ h->s.dsp.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->s.dsp.cavs_filter_lh(h->cy,h->l_stride,alpha,beta,tc,bs[4],bs[5]);
+ h->s.dsp.cavs_filter_ch(h->cu,h->c_stride,alpha,beta,tc,bs[4],bs[5]);
+ h->s.dsp.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
+ *
+ ****************************************************************************/
+
+static inline void 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;
+ }
+}
+
+static void intra_pred_vert(uint8_t *d,uint8_t *top,uint8_t *left,int stride) {
+ int y;
+ uint64_t a = unaligned64(&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 int_fast8_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;
+ }
+}
+
+/*****************************************************************************
+ *
+ * motion compensation
+ *
+ ****************************************************************************/
+
+static inline void mc_dir_part(AVSContext *h,Picture *pic,int square,
+ 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,vector_t *mv){
+ MpegEncContext * const s = &h->s;
+ 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; //(s->flags&CODEC_FLAG_EMU_EDGE) ? 0 : 16;
+ 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){
+ ff_emulated_edge_mc(s->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= s->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(!square){
+ qpix_op[luma_xy](dest_y + delta, src_y + delta, h->l_stride);
+ }
+
+ if(emu){
+ ff_emulated_edge_mc(s->edge_emu_buffer, src_cb, h->c_stride,
+ 9, 9/*FIXME*/, (mx>>3), (my>>3), pic_width>>1, pic_height>>1);
+ src_cb= s->edge_emu_buffer;
+ }
+ chroma_op(dest_cb, src_cb, h->c_stride, chroma_height, mx&7, my&7);
+
+ if(emu){
+ ff_emulated_edge_mc(s->edge_emu_buffer, src_cr, h->c_stride,
+ 9, 9/*FIXME*/, (mx>>3), (my>>3), pic_width>>1, pic_height>>1);
+ src_cr= s->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 square,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, vector_t *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){
+ Picture *ref= &h->DPB[mv->ref];
+ mc_dir_part(h, ref, square, 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){
+ Picture *ref= &h->DPB[0];
+ mc_dir_part(h, ref, square, chroma_height, delta, 1,
+ dest_y, dest_cb, dest_cr, x_offset, y_offset,
+ qpix_op, chroma_op, mv+MV_BWD_OFFS);
+ }
+}
+
+static void inter_pred(AVSContext *h, enum mb_t mb_type) {
+ if(partition_flags[mb_type] == 0){ // 16x16
+ mc_part_std(h, 1, 8, 0, h->cy, h->cu, h->cv, 0, 0,
+ h->s.dsp.put_cavs_qpel_pixels_tab[0],
+ h->s.dsp.put_h264_chroma_pixels_tab[0],
+ h->s.dsp.avg_cavs_qpel_pixels_tab[0],
+ h->s.dsp.avg_h264_chroma_pixels_tab[0],&h->mv[MV_FWD_X0]);
+ }else{
+ mc_part_std(h, 1, 4, 0, h->cy, h->cu, h->cv, 0, 0,
+ h->s.dsp.put_cavs_qpel_pixels_tab[1],
+ h->s.dsp.put_h264_chroma_pixels_tab[1],
+ h->s.dsp.avg_cavs_qpel_pixels_tab[1],
+ h->s.dsp.avg_h264_chroma_pixels_tab[1],&h->mv[MV_FWD_X0]);
+ mc_part_std(h, 1, 4, 0, h->cy, h->cu, h->cv, 4, 0,
+ h->s.dsp.put_cavs_qpel_pixels_tab[1],
+ h->s.dsp.put_h264_chroma_pixels_tab[1],
+ h->s.dsp.avg_cavs_qpel_pixels_tab[1],
+ h->s.dsp.avg_h264_chroma_pixels_tab[1],&h->mv[MV_FWD_X1]);
+ mc_part_std(h, 1, 4, 0, h->cy, h->cu, h->cv, 0, 4,
+ h->s.dsp.put_cavs_qpel_pixels_tab[1],
+ h->s.dsp.put_h264_chroma_pixels_tab[1],
+ h->s.dsp.avg_cavs_qpel_pixels_tab[1],
+ h->s.dsp.avg_h264_chroma_pixels_tab[1],&h->mv[MV_FWD_X2]);
+ mc_part_std(h, 1, 4, 0, h->cy, h->cu, h->cv, 4, 4,
+ h->s.dsp.put_cavs_qpel_pixels_tab[1],
+ h->s.dsp.put_h264_chroma_pixels_tab[1],
+ h->s.dsp.avg_cavs_qpel_pixels_tab[1],
+ h->s.dsp.avg_h264_chroma_pixels_tab[1],&h->mv[MV_FWD_X3]);
+ }
+ /* set intra prediction modes to default values */
+ 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;
+}
+
+/*****************************************************************************
+ *
+ * motion vector prediction
+ *
+ ****************************************************************************/
+
+static inline void set_mvs(vector_t *mv, enum block_t 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;
+ }
+}
+
+static inline void store_mvs(AVSContext *h) {
+ h->col_mv[(h->mby*h->mb_width + h->mbx)*4 + 0] = h->mv[MV_FWD_X0];
+ h->col_mv[(h->mby*h->mb_width + h->mbx)*4 + 1] = h->mv[MV_FWD_X1];
+ h->col_mv[(h->mby*h->mb_width + h->mbx)*4 + 2] = h->mv[MV_FWD_X2];
+ h->col_mv[(h->mby*h->mb_width + h->mbx)*4 + 3] = h->mv[MV_FWD_X3];
+}
+
+static inline void scale_mv(AVSContext *h, int *d_x, int *d_y, vector_t *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, vector_t *mvP, vector_t *mvA, vector_t *mvB, vector_t *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;
+ }
+}
+
+static inline void mv_pred_direct(AVSContext *h, vector_t *pmv_fw,
+ vector_t *col_mv) {
+ vector_t *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, vector_t *src, enum block_t size) {
+ vector_t *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);
+}
+
+static void mv_pred(AVSContext *h, enum mv_loc_t nP, enum mv_loc_t nC,
+ enum mv_pred_t mode, enum block_t size, int ref) {
+ vector_t *mvP = &h->mv[nP];
+ vector_t *mvA = &h->mv[nP-1];
+ vector_t *mvB = &h->mv[nP-4];
+ vector_t *mvC = &h->mv[nC];
+ const vector_t *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->s.gb);
+ mvP->y += get_se_golomb(&h->s.gb);
+ }
+ set_mvs(mvP,size);
+}
+
+/*****************************************************************************
+ *
+ * residual data decoding
+ *
+ ****************************************************************************/
+
+/** kth-order exponential golomb code */
+static inline int get_ue_code(GetBitContext *gb, int order) {
+ if(order) {
+ int ret = get_ue_golomb(gb) << order;
+ return ret + get_bits(gb,order);
+ }
+ return get_ue_golomb(gb);
+}
+
+/**
+ * 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 residual_vlc_t *r, int esc_golomb_order,
+ int qp, uint8_t *dst, int stride) {
+ int i,pos = -1;
+ int level_code, esc_code, level, run, mask;
+ int level_buf[64];
+ int run_buf[64];
+ int dqm = dequant_mul[qp];
+ int dqs = dequant_shift[qp];
+ int dqa = 1 << (dqs - 1);
+ const uint8_t *scantab = h->scantable.permutated;
+ DCTELEM *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;
+ 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;
+ }
+ /* inverse scan and dequantization */
+ while(--i >= 0){
+ pos += run_buf[i];
+ if(pos > 63) {
+ av_log(h->s.avctx, AV_LOG_ERROR,
+ "position out of block bounds at pic %d MB(%d,%d)\n",
+ h->picture.poc, h->mbx, h->mby);
+ return -1;
+ }
+ block[scantab[pos]] = (level_buf[i]*dqm + dqa) >> dqs;
+ }
+ h->s.dsp.cavs_idct8_add(dst,block,stride);
+ return 0;
+}
+
+
+static inline void decode_residual_chroma(AVSContext *h) {
+ if(h->cbp & (1<<4))
+ decode_residual_block(h,&h->s.gb,chroma_2dvlc,0, chroma_qp[h->qp],
+ h->cu,h->c_stride);
+ if(h->cbp & (1<<5))
+ decode_residual_block(h,&h->s.gb,chroma_2dvlc,0, 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->s.gb);
+ if(cbp > 63){
+ av_log(h->s.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->s.gb)) & 63;
+ for(block=0;block<4;block++)
+ if(h->cbp & (1<<block))
+ decode_residual_block(h,&h->s.gb,inter_2dvlc,0,h->qp,
+ h->cy + h->luma_scan[block], h->l_stride);
+ decode_residual_chroma(h);
+
+ return 0;
+}
+
+/*****************************************************************************
+ *
+ * macroblock level
+ *
+ ****************************************************************************/
+
+/**
+ * initialise predictors for motion vectors and intra prediction
+ */
+static inline void 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;
+ }
+ /* set pointer for co-located macroblock type */
+ h->col_type = &h->col_type_base[h->mby*h->mb_width + h->mbx];
+}
+
+static inline void check_for_slice(AVSContext *h);
+
+/**
+ * save predictors for later macroblocks and increase
+ * macroblock address
+ * @returns 0 if end of frame is reached, 1 otherwise
+ */
+static inline int 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->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->picture.data[0] + h->mby*16*h->l_stride;
+ h->cu = h->picture.data[1] + h->mby*8*h->c_stride;
+ h->cv = h->picture.data[2] + h->mby*8*h->c_stride;
+ if(h->mby == h->mb_height) { //frame end
+ return 0;
+ } else {
+ //check_for_slice(h);
+ }
+ }
+ return 1;
+}
+
+static int decode_mb_i(AVSContext *h, int cbp_code) {
+ GetBitContext *gb = &h->s.gb;
+ int block, pred_mode_uv;
+ uint8_t top[18];
+ uint8_t *left = NULL;
+ uint8_t *d;
+
+ 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->s.avctx, AV_LOG_ERROR, "illegal intra chroma pred mode\n");
+ return -1;
+ }
+
+ /* 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 );
+ }
+
+ /* get coded block pattern */
+ if(h->pic_type == FF_I_TYPE)
+ cbp_code = get_ue_golomb(gb);
+ if(cbp_code > 63){
+ av_log(h->s.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];
+ 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<<block))
+ decode_residual_block(h,gb,intra_2dvlc,1,h->qp,d,h->l_stride);
+ }
+
+ /* chroma intra prediction */
+ /* 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];
+ }
+ 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);
+ filter_mb(h,I_8X8);
+
+ /* mark motion vectors as intra */
+ h->mv[MV_FWD_X0] = intra_mv;
+ set_mvs(&h->mv[MV_FWD_X0], BLK_16X16);
+ h->mv[MV_BWD_X0] = intra_mv;
+ set_mvs(&h->mv[MV_BWD_X0], BLK_16X16);
+ if(h->pic_type != FF_B_TYPE)
+ *h->col_type = I_8X8;
+
+ return 0;
+}
+
+static void decode_mb_p(AVSContext *h, enum mb_t mb_type) {
+ GetBitContext *gb = &h->s.gb;
+ int ref[4];
+
+ init_mb(h);
+ switch(mb_type) {
+ case P_SKIP:
+ mv_pred(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);
+ mv_pred(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);
+ mv_pred(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_TOP, BLK_16X8, ref[0]);
+ mv_pred(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);
+ mv_pred(h, MV_FWD_X0, MV_FWD_B3, MV_PRED_LEFT, BLK_8X16, ref[0]);
+ mv_pred(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);
+ mv_pred(h, MV_FWD_X0, MV_FWD_B3, MV_PRED_MEDIAN, BLK_8X8, ref[0]);
+ mv_pred(h, MV_FWD_X1, MV_FWD_C2, MV_PRED_MEDIAN, BLK_8X8, ref[1]);
+ mv_pred(h, MV_FWD_X2, MV_FWD_X1, MV_PRED_MEDIAN, BLK_8X8, ref[2]);
+ mv_pred(h, MV_FWD_X3, MV_FWD_X0, MV_PRED_MEDIAN, BLK_8X8, ref[3]);
+ }
+ inter_pred(h, mb_type);
+ store_mvs(h);
+ if(mb_type != P_SKIP)
+ decode_residual_inter(h);
+ filter_mb(h,mb_type);
+ *h->col_type = mb_type;
+}
+
+static void decode_mb_b(AVSContext *h, enum mb_t mb_type) {
+ int block;
+ enum sub_mb_t sub_type[4];
+ int flags;
+
+ init_mb(h);
+
+ /* reset all MVs */
+ h->mv[MV_FWD_X0] = dir_mv;
+ set_mvs(&h->mv[MV_FWD_X0], BLK_16X16);
+ h->mv[MV_BWD_X0] = dir_mv;
+ set_mvs(&h->mv[MV_BWD_X0], BLK_16X16);
+ switch(mb_type) {
+ case B_SKIP:
+ case B_DIRECT:
+ if(!(*h->col_type)) {
+ /* intra MB at co-location, do in-plane prediction */
+ mv_pred(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_BSKIP, BLK_16X16, 1);
+ mv_pred(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->mby*h->mb_width+h->mbx)*4 + block]);
+ break;
+ case B_FWD_16X16:
+ mv_pred(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_MEDIAN, BLK_16X16, 1);
+ break;
+ case B_SYM_16X16:
+ mv_pred(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:
+ mv_pred(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->s.gb,2);
+ for(block=0;block<4;block++) {
+ switch(sub_type[block]) {
+ case B_SUB_DIRECT:
+ if(!(*h->col_type)) {
+ /* intra MB at co-location, do in-plane prediction */
+ mv_pred(h, mv_scan[block], mv_scan[block]-3,
+ MV_PRED_BSKIP, BLK_8X8, 1);
+ mv_pred(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->mby*h->mb_width + h->mbx)*4 + block]);
+ break;
+ case B_SUB_FWD:
+ mv_pred(h, mv_scan[block], mv_scan[block]-3,
+ MV_PRED_MEDIAN, BLK_8X8, 1);
+ break;
+ case B_SUB_SYM:
+ mv_pred(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)
+ mv_pred(h, mv_scan[block]+MV_BWD_OFFS,
+ mv_scan[block]+MV_BWD_OFFS-3,
+ MV_PRED_MEDIAN, BLK_8X8, 0);
+ }
+ break;
+ default:
+ assert((mb_type > B_SYM_16X16) && (mb_type < B_8X8));
+ flags = partition_flags[mb_type];
+ if(mb_type & 1) { /* 16x8 macroblock types */
+ if(flags & FWD0)
+ mv_pred(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)
+ mv_pred(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)
+ mv_pred(h, MV_BWD_X0, MV_BWD_C2, MV_PRED_TOP, BLK_16X8, 0);
+ if(flags & BWD1)
+ mv_pred(h, MV_BWD_X2, MV_BWD_A1, MV_PRED_LEFT, BLK_16X8, 0);
+ } else { /* 8x16 macroblock types */
+ if(flags & FWD0)
+ mv_pred(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)
+ mv_pred(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)
+ mv_pred(h, MV_BWD_X0, MV_BWD_B3, MV_PRED_LEFT, BLK_8X16, 0);
+ if(flags & BWD1)
+ mv_pred(h, MV_BWD_X1, MV_BWD_C2, MV_PRED_TOPRIGHT,BLK_8X16, 0);
+ }
+ }
+ inter_pred(h, mb_type);
+ if(mb_type != B_SKIP)
+ decode_residual_inter(h);
+ filter_mb(h,mb_type);
+}
+
+/*****************************************************************************
+ *
+ * slice level
+ *
+ ****************************************************************************/
+
+static inline int decode_slice_header(AVSContext *h, GetBitContext *gb) {
+ if(h->stc > 0xAF)
+ av_log(h->s.avctx, AV_LOG_ERROR, "unexpected start code 0x%02x\n", h->stc);
+ h->mby = h->stc;
+ 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->pic_type != FF_I_TYPE) || (!h->pic_structure && h->mby >= h->mb_width/2))
+ if(get_bits1(gb)) { //slice_weighting_flag
+ av_log(h->s.avctx, AV_LOG_ERROR,
+ "weighted prediction not yet supported\n");
+ }
+ return 0;
+}
+
+static inline void check_for_slice(AVSContext *h) {
+ GetBitContext *gb = &h->s.gb;
+ int align;
+ align = (-get_bits_count(gb)) & 7;
+ if((show_bits_long(gb,24+align) & 0xFFFFFF) == 0x000001) {
+ get_bits_long(gb,24+align);
+ h->stc = get_bits(gb,8);
+ decode_slice_header(h,gb);
+ }
+}
+
+/*****************************************************************************
+ *
+ * frame level
+ *
+ ****************************************************************************/
+
+static void 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] = dir_mv;
+ set_mvs(&h->mv[MV_BWD_X0], BLK_16X16);
+ h->mv[MV_FWD_X0] = 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->picture.data[0];
+ h->cu = h->picture.data[1];
+ h->cv = h->picture.data[2];
+ h->l_stride = h->picture.linesize[0];
+ h->c_stride = h->picture.linesize[1];
+ h->luma_scan[2] = 8*h->l_stride;
+ h->luma_scan[3] = 8*h->l_stride+8;
+ h->mbx = h->mby = 0;
+ h->flags = 0;
+}
+
+static int decode_pic(AVSContext *h) {
+ MpegEncContext *s = &h->s;
+ int skip_count;
+ enum mb_t mb_type;
+
+ if (!s->context_initialized) {
+ s->avctx->idct_algo = FF_IDCT_CAVS;
+ if (MPV_common_init(s) < 0)
+ return -1;
+ ff_init_scantable(s->dsp.idct_permutation,&h->scantable,ff_zigzag_direct);
+ }
+ get_bits(&s->gb,16);//bbv_dwlay
+ if(h->stc == PIC_PB_START_CODE) {
+ h->pic_type = get_bits(&s->gb,2) + FF_I_TYPE;
+ if(h->pic_type > FF_B_TYPE) {
+ av_log(s->avctx, AV_LOG_ERROR, "illegal picture type\n");
+ return -1;
+ }
+ /* make sure we have the reference frames we need */
+ if(!h->DPB[0].data[0] ||
+ (!h->DPB[1].data[0] && h->pic_type == FF_B_TYPE))
+ return -1;
+ } else {
+ h->pic_type = FF_I_TYPE;
+ if(get_bits1(&s->gb))
+ get_bits(&s->gb,16);//time_code
+ }
+ /* release last B frame */
+ if(h->picture.data[0])
+ s->avctx->release_buffer(s->avctx, (AVFrame *)&h->picture);
+
+ s->avctx->get_buffer(s->avctx, (AVFrame *)&h->picture);
+ init_pic(h);
+ h->picture.poc = get_bits(&s->gb,8)*2;
+
+ /* get temporal distances and MV scaling factors */
+ if(h->pic_type != FF_B_TYPE) {
+ h->dist[0] = (h->picture.poc - h->DPB[0].poc + 512) % 512;
+ } else {
+ h->dist[0] = (h->DPB[0].poc - h->picture.poc + 512) % 512;
+ }
+ h->dist[1] = (h->picture.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->pic_type == FF_B_TYPE) {
+ 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(s->low_delay)
+ get_ue_golomb(&s->gb); //bbv_check_times
+ h->progressive = get_bits1(&s->gb);
+ if(h->progressive)
+ h->pic_structure = 1;
+ else if(!(h->pic_structure = get_bits1(&s->gb) && (h->stc == PIC_PB_START_CODE)) )
+ get_bits1(&s->gb); //advanced_pred_mode_disable
+ skip_bits1(&s->gb); //top_field_first
+ skip_bits1(&s->gb); //repeat_first_field
+ h->qp_fixed = get_bits1(&s->gb);
+ h->qp = get_bits(&s->gb,6);
+ if(h->pic_type == FF_I_TYPE) {
+ if(!h->progressive && !h->pic_structure)
+ skip_bits1(&s->gb);//what is this?
+ skip_bits(&s->gb,4); //reserved bits
+ } else {
+ if(!(h->pic_type == FF_B_TYPE && h->pic_structure == 1))
+ h->ref_flag = get_bits1(&s->gb);
+ skip_bits(&s->gb,4); //reserved bits
+ h->skip_mode_flag = get_bits1(&s->gb);
+ }
+ h->loop_filter_disable = get_bits1(&s->gb);
+ if(!h->loop_filter_disable && get_bits1(&s->gb)) {
+ h->alpha_offset = get_se_golomb(&s->gb);
+ h->beta_offset = get_se_golomb(&s->gb);
+ } else {
+ h->alpha_offset = h->beta_offset = 0;
+ }
+ check_for_slice(h);
+ if(h->pic_type == FF_I_TYPE) {
+ do {
+ decode_mb_i(h, 0);
+ } while(next_mb(h));
+ } else if(h->pic_type == FF_P_TYPE) {
+ do {
+ if(h->skip_mode_flag) {
+ skip_count = get_ue_golomb(&s->gb);
+ while(skip_count--) {
+ decode_mb_p(h,P_SKIP);
+ if(!next_mb(h))
+ goto done;
+ }
+ mb_type = get_ue_golomb(&s->gb) + P_16X16;
+ } else
+ mb_type = get_ue_golomb(&s->gb) + P_SKIP;
+ if(mb_type > P_8X8) {
+ decode_mb_i(h, mb_type - P_8X8 - 1);
+ } else
+ decode_mb_p(h,mb_type);
+ } while(next_mb(h));
+ } else { /* FF_B_TYPE */
+ do {
+ if(h->skip_mode_flag) {
+ skip_count = get_ue_golomb(&s->gb);
+ while(skip_count--) {
+ decode_mb_b(h,B_SKIP);
+ if(!next_mb(h))
+ goto done;
+ }
+ mb_type = get_ue_golomb(&s->gb) + B_DIRECT;
+ } else
+ mb_type = get_ue_golomb(&s->gb) + B_SKIP;
+ if(mb_type > B_8X8) {
+ decode_mb_i(h, mb_type - B_8X8 - 1);
+ } else
+ decode_mb_b(h,mb_type);
+ } while(next_mb(h));
+ }
+ done:
+ if(h->pic_type != FF_B_TYPE) {
+ if(h->DPB[1].data[0])
+ s->avctx->release_buffer(s->avctx, (AVFrame *)&h->DPB[1]);
+ memcpy(&h->DPB[1], &h->DPB[0], sizeof(Picture));
+ memcpy(&h->DPB[0], &h->picture, sizeof(Picture));
+ memset(&h->picture,0,sizeof(Picture));
+ }
+ 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
+ */
+static void init_top_lines(AVSContext *h) {
+ /* alloc top line of predictors */
+ h->top_qp = av_malloc( h->mb_width);
+ h->top_mv[0] = av_malloc((h->mb_width*2+1)*sizeof(vector_t));
+ h->top_mv[1] = av_malloc((h->mb_width*2+1)*sizeof(vector_t));
+ h->top_pred_Y = av_malloc( h->mb_width*2*sizeof(*h->top_pred_Y));
+ h->top_border_y = av_malloc((h->mb_width+1)*16);
+ h->top_border_u = av_malloc((h->mb_width)*10);
+ h->top_border_v = av_malloc((h->mb_width)*10);
+
+ /* alloc space for co-located MVs and types */
+ h->col_mv = av_malloc( h->mb_width*h->mb_height*4*sizeof(vector_t));
+ h->col_type_base = av_malloc(h->mb_width*h->mb_height);
+ h->block = av_mallocz(64*sizeof(DCTELEM));
+}
+
+static int decode_seq_header(AVSContext *h) {
+ MpegEncContext *s = &h->s;
+ extern const AVRational ff_frame_rate_tab[];
+ int frame_rate_code;
+
+ h->profile = get_bits(&s->gb,8);
+ h->level = get_bits(&s->gb,8);
+ skip_bits1(&s->gb); //progressive sequence
+ s->width = get_bits(&s->gb,14);
+ s->height = get_bits(&s->gb,14);
+ skip_bits(&s->gb,2); //chroma format
+ skip_bits(&s->gb,3); //sample_precision
+ h->aspect_ratio = get_bits(&s->gb,4);
+ frame_rate_code = get_bits(&s->gb,4);
+ skip_bits(&s->gb,18);//bit_rate_lower
+ skip_bits1(&s->gb); //marker_bit
+ skip_bits(&s->gb,12);//bit_rate_upper
+ s->low_delay = get_bits1(&s->gb);
+ h->mb_width = (s->width + 15) >> 4;
+ h->mb_height = (s->height + 15) >> 4;
+ h->s.avctx->time_base.den = ff_frame_rate_tab[frame_rate_code].num;
+ h->s.avctx->time_base.num = ff_frame_rate_tab[frame_rate_code].den;
+ h->s.avctx->width = s->width;
+ h->s.avctx->height = s->height;
+ if(!h->top_qp)
+ 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 *data_size,
+ uint8_t * buf, int buf_size) {
+ AVSContext *h = avctx->priv_data;
+ MpegEncContext *s = &h->s;
+ int input_size;
+ const uint8_t *buf_end;
+ const uint8_t *buf_ptr;
+ AVFrame *picture = data;
+ uint32_t stc;
+
+ s->avctx = avctx;
+
+ if (buf_size == 0) {
+ if(!s->low_delay && h->DPB[0].data[0]) {
+ *data_size = sizeof(AVPicture);
+ *picture = *(AVFrame *) &h->DPB[0];
+ }
+ return 0;
+ }
+
+ buf_ptr = buf;
+ buf_end = buf + buf_size;
+ for(;;) {
+ buf_ptr = ff_find_start_code(buf_ptr,buf_end, &stc);
+ if(stc & 0xFFFFFE00)
+ return FFMAX(0, buf_ptr - buf - s->parse_context.last_index);
+ input_size = (buf_end - buf_ptr)*8;
+ switch(stc) {
+ case SEQ_START_CODE:
+ init_get_bits(&s->gb, buf_ptr, input_size);
+ decode_seq_header(h);
+ break;
+ case PIC_I_START_CODE:
+ if(!h->got_keyframe) {
+ if(h->DPB[0].data[0])
+ avctx->release_buffer(avctx, (AVFrame *)&h->DPB[0]);
+ if(h->DPB[1].data[0])
+ avctx->release_buffer(avctx, (AVFrame *)&h->DPB[1]);
+ h->got_keyframe = 1;
+ }
+ case PIC_PB_START_CODE:
+ *data_size = 0;
+ if(!h->got_keyframe)
+ break;
+ init_get_bits(&s->gb, buf_ptr, input_size);
+ h->stc = stc;
+ if(decode_pic(h))
+ break;
+ *data_size = sizeof(AVPicture);
+ if(h->pic_type != FF_B_TYPE) {
+ if(h->DPB[1].data[0]) {
+ *picture = *(AVFrame *) &h->DPB[1];
+ } else {
+ *data_size = 0;
+ }
+ } else
+ *picture = *(AVFrame *) &h->picture;
+ 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_MIN_START_CODE &&
+ stc <= SLICE_MAX_START_CODE) {
+ init_get_bits(&s->gb, buf_ptr, input_size);
+ decode_slice_header(h, &s->gb);
+ }
+ break;
+ }
+ }
+}
+
+static int cavs_decode_init(AVCodecContext * avctx) {
+ AVSContext *h = avctx->priv_data;
+ MpegEncContext * const s = &h->s;
+
+ MPV_decode_defaults(s);
+ s->avctx = avctx;
+
+ avctx->pix_fmt= PIX_FMT_YUV420P;
+
+ 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;
+}
+
+static int cavs_decode_end(AVCodecContext * avctx) {
+ AVSContext *h = avctx->priv_data;
+
+ 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);
+ return 0;
+}
+
+AVCodec cavs_decoder = {
+ "cavs",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_CAVS,
+ sizeof(AVSContext),
+ cavs_decode_init,
+ NULL,
+ cavs_decode_end,
+ cavs_decode_frame,
+ CODEC_CAP_DR1 | CODEC_CAP_DELAY,
+ .flush= cavs_flush,
+};
+#endif /* CONFIG_CAVS_DECODER */
+
+#ifdef CONFIG_CAVSVIDEO_PARSER
+/**
+ * finds 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<buf_size; i++){
+ state= (state<<8) | buf[i];
+ if(state == PIC_I_START_CODE || state == PIC_PB_START_CODE){
+ i++;
+ pic_found=1;
+ break;
+ }
+ }
+ }
+
+ if(pic_found){
+ /* EOF considered as end of frame */
+ if (buf_size == 0)
+ return 0;
+ for(; i<buf_size; i++){
+ state= (state<<8) | buf[i];
+ if((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;
+ }
+ }
+ }
+ }
+ pc->frame_start_found= pic_found;
+ pc->state= state;
+ return END_NOT_FOUND;
+}
+
+static int cavsvideo_parse(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ 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, (uint8_t **)&buf, &buf_size) < 0) {
+ *poutbuf = NULL;
+ *poutbuf_size = 0;
+ return buf_size;
+ }
+ }
+ *poutbuf = (uint8_t *)buf;
+ *poutbuf_size = buf_size;
+ return next;
+}
+
+AVCodecParser cavsvideo_parser = {
+ { CODEC_ID_CAVS },
+ sizeof(ParseContext1),
+ NULL,
+ cavsvideo_parse,
+ ff_parse1_close,
+ ff_mpeg4video_split,
+};
+#endif /* CONFIG_CAVSVIDEO_PARSER */
diff --git a/contrib/ffmpeg/libavcodec/cavsdata.h b/contrib/ffmpeg/libavcodec/cavsdata.h
new file mode 100644
index 000000000..d76985136
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/cavsdata.h
@@ -0,0 +1,643 @@
+/*
+ * Chinese AVS video (AVS1-P2, JiZhun profile) decoder.
+ * Copyright (c) 2006 Stefan Gehrer <stefan.gehrer@gmx.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define SLICE_MIN_START_CODE 0x00000101
+#define SLICE_MAX_START_CODE 0x000001af
+#define EXT_START_CODE 0x000001b5
+#define USER_START_CODE 0x000001b2
+#define SEQ_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 mb_t {
+ 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 sub_mb_t {
+ B_SUB_DIRECT,
+ B_SUB_FWD,
+ B_SUB_BWD,
+ B_SUB_SYM
+};
+
+enum intra_luma_t {
+ 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 intra_chroma_t {
+ 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 mv_pred_t {
+ MV_PRED_MEDIAN,
+ MV_PRED_LEFT,
+ MV_PRED_TOP,
+ MV_PRED_TOPRIGHT,
+ MV_PRED_PSKIP,
+ MV_PRED_BSKIP
+};
+
+enum block_t {
+ BLK_16X16,
+ BLK_16X8,
+ BLK_8X16,
+ BLK_8X8
+};
+
+enum mv_loc_t {
+ 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
+};
+
+#ifdef CONFIG_CAVS_DECODER
+static const uint8_t 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
+};
+
+static const uint8_t scan3x3[4] = {4,5,7,8};
+
+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 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
+};
+
+DECLARE_ALIGNED_8(typedef, struct) {
+ int16_t x;
+ int16_t y;
+ int16_t dist;
+ int16_t ref;
+} vector_t;
+
+/** marks block as unavailable, i.e. out of picture
+ or not yet decoded */
+static const vector_t un_mv = {0,0,1,NOT_AVAIL};
+
+/** marks block as "no prediction from this direction"
+ e.g. forward motion vector in BWD partition */
+static const vector_t dir_mv = {0,0,1,REF_DIR};
+
+/** marks block as using intra prediction */
+static const vector_t intra_mv = {0,0,1,REF_INTRA};
+
+typedef struct residual_vlc_t {
+ int8_t rltab[59][3];
+ int8_t level_add[27];
+ int8_t golomb_order;
+ int inc_limit;
+ int8_t max_run;
+} residual_vlc_t;
+
+#define EOB 0,0,0
+
+static const residual_vlc_t intra_2dvlc[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 residual_vlc_t inter_2dvlc[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 residual_vlc_t chroma_2dvlc[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
+
+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
+};
+
+static const int_fast8_t left_modifier_l[8] = { 0,-1, 6,-1,-1, 7, 6, 7};
+static const int_fast8_t top_modifier_l[8] = {-1, 1, 5,-1,-1, 5, 7, 7};
+static const int_fast8_t left_modifier_c[7] = { 5,-1, 2,-1, 6, 5, 6};
+static const int_fast8_t top_modifier_c[7] = { 4, 1,-1,-1, 4, 6, 6};
+#endif /* CONFIG_CAVS_DECODER */
diff --git a/contrib/ffmpeg/libavcodec/cavsdsp.c b/contrib/ffmpeg/libavcodec/cavsdsp.c
new file mode 100644
index 000000000..220dec1b8
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/cavsdsp.c
@@ -0,0 +1,546 @@
+/*
+ * Chinese AVS video (AVS1-P2, JiZhun profile) decoder.
+ *
+ * DSP functions
+ *
+ * Copyright (c) 2006 Stefan Gehrer <stefan.gehrer@gmx.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include "dsputil.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)<alpha && abs(P1-p0)<beta && abs(Q1-q0)<beta) {
+ int s = p0 + q0 + 2;
+ alpha = (alpha>>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)<alpha && abs(P1-p0)<beta && abs(Q1-q0)<beta) {
+ int delta = clip(((q0-p0)*3+P1-Q1+4)>>3,-tc, tc);
+ P0 = clip_uint8(p0+delta);
+ Q0 = clip_uint8(q0-delta);
+ if(abs(P2-p0)<beta) {
+ delta = clip(((P0-P1)*3+P2-Q0+4)>>3, -tc, tc);
+ P1 = clip_uint8(P1+delta);
+ }
+ if(abs(Q2-q0)<beta) {
+ delta = clip(((Q1-Q0)*3+P0-Q2+4)>>3, -tc, tc);
+ Q1 = 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)<alpha && abs(P1-p0)<beta && abs(Q1-q0)<beta) {
+ int s = p0 + q0 + 2;
+ alpha = (alpha>>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)<alpha && abs(P1-P0)<beta && abs(Q1-Q0)<beta) {
+ int delta = clip(((Q0-P0)*3+P1-Q1+4)>>3, -tc, tc);
+ P0 = clip_uint8(P0+delta);
+ Q0 = 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, DCTELEM *block, int stride) {
+ int i;
+ DCTELEM (*src)[8] = (DCTELEM(*)[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)];
+ }
+ memset(block,0,64*sizeof(DCTELEM));
+}
+
+/*****************************************************************************
+ *
+ * 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<h; i++)\
+ {\
+ OP(dst[0], A*src[-2] + B*src[-1] + C*src[0] + D*src[1] + E*src[2] + F*src[3]);\
+ OP(dst[1], A*src[-1] + B*src[ 0] + C*src[1] + D*src[2] + E*src[3] + F*src[4]);\
+ OP(dst[2], A*src[ 0] + B*src[ 1] + C*src[2] + D*src[3] + E*src[4] + F*src[5]);\
+ OP(dst[3], A*src[ 1] + B*src[ 2] + C*src[3] + D*src[4] + E*src[5] + F*src[6]);\
+ OP(dst[4], A*src[ 2] + B*src[ 3] + C*src[4] + D*src[5] + E*src[6] + F*src[7]);\
+ OP(dst[5], A*src[ 3] + B*src[ 4] + C*src[5] + D*src[6] + E*src[7] + F*src[8]);\
+ OP(dst[6], A*src[ 4] + B*src[ 5] + C*src[6] + D*src[7] + E*src[8] + F*src[9]);\
+ OP(dst[7], A*src[ 5] + B*src[ 6] + C*src[7] + D*src[8] + E*src[9] + F*src[10]);\
+ dst+=dstStride;\
+ src+=srcStride;\
+ }\
+}\
+\
+static void OPNAME ## cavs_filt8_v_ ## NAME(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ const int w=8;\
+ 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], A*srcB + B*srcA + C*src0 + D*src1 + E*src2 + F*src3);\
+ OP(dst[1*dstStride], A*srcA + B*src0 + C*src1 + D*src2 + E*src3 + F*src4);\
+ OP(dst[2*dstStride], A*src0 + B*src1 + C*src2 + D*src3 + E*src4 + F*src5);\
+ OP(dst[3*dstStride], A*src1 + B*src2 + C*src3 + D*src4 + E*src5 + F*src6);\
+ OP(dst[4*dstStride], A*src2 + B*src3 + C*src4 + D*src5 + E*src6 + F*src7);\
+ OP(dst[5*dstStride], A*src3 + B*src4 + C*src5 + D*src6 + E*src7 + F*src8);\
+ OP(dst[6*dstStride], A*src4 + B*src5 + C*src6 + D*src7 + E*src8 + F*src9);\
+ OP(dst[7*dstStride], A*src5 + B*src6 + C*src7 + D*src8 + E*src9 + F*src10);\
+ dst++;\
+ src++;\
+ }\
+}\
+\
+static void OPNAME ## cavs_filt16_v_ ## NAME(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ OPNAME ## cavs_filt8_v_ ## NAME(dst , src , dstStride, srcStride);\
+ OPNAME ## cavs_filt8_v_ ## NAME(dst+8, src+8, dstStride, srcStride);\
+ src += 8*srcStride;\
+ dst += 8*dstStride;\
+ OPNAME ## cavs_filt8_v_ ## NAME(dst , src , dstStride, srcStride);\
+ OPNAME ## cavs_filt8_v_ ## NAME(dst+8, src+8, dstStride, srcStride);\
+}\
+\
+static void OPNAME ## cavs_filt16_h_ ## NAME(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ OPNAME ## cavs_filt8_h_ ## NAME(dst , src , dstStride, srcStride);\
+ OPNAME ## cavs_filt8_h_ ## NAME(dst+8, src+8, dstStride, srcStride);\
+ src += 8*srcStride;\
+ dst += 8*dstStride;\
+ OPNAME ## cavs_filt8_h_ ## NAME(dst , src , dstStride, srcStride);\
+ OPNAME ## cavs_filt8_h_ ## NAME(dst+8, src+8, dstStride, srcStride);\
+}\
+
+#define CAVS_SUBPIX_HV(OPNAME, OP, NAME, AH, BH, CH, DH, EH, FH, AV, BV, CV, DV, EV, FV, FULL) \
+static void OPNAME ## cavs_filt8_hv_ ## NAME(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int srcStride){\
+ int16_t temp[8*(8+5)];\
+ int16_t *tmp = temp;\
+ const int h=8;\
+ const int w=8;\
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\
+ int i;\
+ src1 -= 2*srcStride;\
+ for(i=0; i<h+5; i++)\
+ {\
+ tmp[0]= AH*src1[-2] + BH*src1[-1] + CH*src1[0] + DH*src1[1] + EH*src1[2] + FH*src1[3];\
+ tmp[1]= AH*src1[-1] + BH*src1[ 0] + CH*src1[1] + DH*src1[2] + EH*src1[3] + FH*src1[4];\
+ tmp[2]= AH*src1[ 0] + BH*src1[ 1] + CH*src1[2] + DH*src1[3] + EH*src1[4] + FH*src1[5];\
+ tmp[3]= AH*src1[ 1] + BH*src1[ 2] + CH*src1[3] + DH*src1[4] + EH*src1[5] + FH*src1[6];\
+ tmp[4]= AH*src1[ 2] + BH*src1[ 3] + CH*src1[4] + DH*src1[5] + EH*src1[6] + FH*src1[7];\
+ tmp[5]= AH*src1[ 3] + BH*src1[ 4] + CH*src1[5] + DH*src1[6] + EH*src1[7] + FH*src1[8];\
+ tmp[6]= AH*src1[ 4] + BH*src1[ 5] + CH*src1[6] + DH*src1[7] + EH*src1[8] + FH*src1[9];\
+ tmp[7]= AH*src1[ 5] + BH*src1[ 6] + CH*src1[7] + DH*src1[8] + EH*src1[9] + FH*src1[10];\
+ tmp+=8;\
+ src1+=srcStride;\
+ }\
+ if(FULL) {\
+ tmp = temp+8*2; \
+ for(i=0; i<w; i++) \
+ { \
+ const int tmpB= tmp[-2*8]; \
+ const int tmpA= tmp[-1*8]; \
+ const int tmp0= tmp[0 *8]; \
+ const int tmp1= tmp[1 *8]; \
+ const int tmp2= tmp[2 *8]; \
+ const int tmp3= tmp[3 *8]; \
+ const int tmp4= tmp[4 *8]; \
+ const int tmp5= tmp[5 *8]; \
+ const int tmp6= tmp[6 *8]; \
+ const int tmp7= tmp[7 *8]; \
+ const int tmp8= tmp[8 *8]; \
+ const int tmp9= tmp[9 *8]; \
+ const int tmp10=tmp[10*8]; \
+ OP(dst[0*dstStride], AV*tmpB + BV*tmpA + CV*tmp0 + DV*tmp1 + EV*tmp2 + FV*tmp3 + 64*src2[0*srcStride]); \
+ OP(dst[1*dstStride], AV*tmpA + BV*tmp0 + CV*tmp1 + DV*tmp2 + EV*tmp3 + FV*tmp4 + 64*src2[1*srcStride]); \
+ OP(dst[2*dstStride], AV*tmp0 + BV*tmp1 + CV*tmp2 + DV*tmp3 + EV*tmp4 + FV*tmp5 + 64*src2[2*srcStride]); \
+ OP(dst[3*dstStride], AV*tmp1 + BV*tmp2 + CV*tmp3 + DV*tmp4 + EV*tmp5 + FV*tmp6 + 64*src2[3*srcStride]); \
+ OP(dst[4*dstStride], AV*tmp2 + BV*tmp3 + CV*tmp4 + DV*tmp5 + EV*tmp6 + FV*tmp7 + 64*src2[4*srcStride]); \
+ OP(dst[5*dstStride], AV*tmp3 + BV*tmp4 + CV*tmp5 + DV*tmp6 + EV*tmp7 + FV*tmp8 + 64*src2[5*srcStride]); \
+ OP(dst[6*dstStride], AV*tmp4 + BV*tmp5 + CV*tmp6 + DV*tmp7 + EV*tmp8 + FV*tmp9 + 64*src2[6*srcStride]); \
+ OP(dst[7*dstStride], AV*tmp5 + BV*tmp6 + CV*tmp7 + DV*tmp8 + EV*tmp9 + FV*tmp10 + 64*src2[7*srcStride]); \
+ dst++; \
+ tmp++; \
+ src2++; \
+ } \
+ } else {\
+ tmp = temp+8*2; \
+ for(i=0; i<w; i++) \
+ { \
+ const int tmpB= tmp[-2*8]; \
+ const int tmpA= tmp[-1*8]; \
+ const int tmp0= tmp[0 *8]; \
+ const int tmp1= tmp[1 *8]; \
+ const int tmp2= tmp[2 *8]; \
+ const int tmp3= tmp[3 *8]; \
+ const int tmp4= tmp[4 *8]; \
+ const int tmp5= tmp[5 *8]; \
+ const int tmp6= tmp[6 *8]; \
+ const int tmp7= tmp[7 *8]; \
+ const int tmp8= tmp[8 *8]; \
+ const int tmp9= tmp[9 *8]; \
+ const int tmp10=tmp[10*8]; \
+ OP(dst[0*dstStride], AV*tmpB + BV*tmpA + CV*tmp0 + DV*tmp1 + EV*tmp2 + FV*tmp3); \
+ OP(dst[1*dstStride], AV*tmpA + BV*tmp0 + CV*tmp1 + DV*tmp2 + EV*tmp3 + FV*tmp4); \
+ OP(dst[2*dstStride], AV*tmp0 + BV*tmp1 + CV*tmp2 + DV*tmp3 + EV*tmp4 + FV*tmp5); \
+ OP(dst[3*dstStride], AV*tmp1 + BV*tmp2 + CV*tmp3 + DV*tmp4 + EV*tmp5 + FV*tmp6); \
+ OP(dst[4*dstStride], AV*tmp2 + BV*tmp3 + CV*tmp4 + DV*tmp5 + EV*tmp6 + FV*tmp7); \
+ OP(dst[5*dstStride], AV*tmp3 + BV*tmp4 + CV*tmp5 + DV*tmp6 + EV*tmp7 + FV*tmp8); \
+ OP(dst[6*dstStride], AV*tmp4 + BV*tmp5 + CV*tmp6 + DV*tmp7 + EV*tmp8 + FV*tmp9); \
+ OP(dst[7*dstStride], AV*tmp5 + BV*tmp6 + CV*tmp7 + DV*tmp8 + EV*tmp9 + FV*tmp10); \
+ dst++; \
+ tmp++; \
+ } \
+ }\
+}\
+\
+static void OPNAME ## cavs_filt16_hv_ ## NAME(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int srcStride){ \
+ OPNAME ## cavs_filt8_hv_ ## NAME(dst , src1, src2 , dstStride, srcStride); \
+ OPNAME ## cavs_filt8_hv_ ## NAME(dst+8, src1+8, src2+8, dstStride, srcStride); \
+ src1 += 8*srcStride;\
+ src2 += 8*srcStride;\
+ dst += 8*dstStride;\
+ OPNAME ## cavs_filt8_hv_ ## NAME(dst , src1, src2 , dstStride, srcStride); \
+ OPNAME ## cavs_filt8_hv_ ## NAME(dst+8, src1+8, src2+8, dstStride, srcStride); \
+}\
+
+#define CAVS_MC(OPNAME, SIZE) \
+static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc10_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## cavs_filt ## SIZE ## _h_qpel_l(dst, src, stride, stride);\
+}\
+\
+static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc20_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## cavs_filt ## SIZE ## _h_hpel(dst, src, stride, stride);\
+}\
+\
+static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc30_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## cavs_filt ## SIZE ## _h_qpel_r(dst, src, stride, stride);\
+}\
+\
+static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc01_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## cavs_filt ## SIZE ## _v_qpel_l(dst, src, stride, stride);\
+}\
+\
+static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc02_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## cavs_filt ## SIZE ## _v_hpel(dst, src, stride, stride);\
+}\
+\
+static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc03_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## cavs_filt ## SIZE ## _v_qpel_r(dst, src, stride, stride);\
+}\
+\
+static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc22_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## cavs_filt ## SIZE ## _hv_jj(dst, src, NULL, stride, stride); \
+}\
+\
+static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc11_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## cavs_filt ## SIZE ## _hv_egpr(dst, src, src, stride, stride); \
+}\
+\
+static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc13_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## cavs_filt ## SIZE ## _hv_egpr(dst, src, src+stride, stride, stride); \
+}\
+\
+static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc31_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## cavs_filt ## SIZE ## _hv_egpr(dst, src, src+1, stride, stride); \
+}\
+\
+static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc33_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## cavs_filt ## SIZE ## _hv_egpr(dst, src, src+stride+1,stride, stride); \
+}\
+\
+static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc21_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## cavs_filt ## SIZE ## _hv_ff(dst, src, src+stride+1,stride, stride); \
+}\
+\
+static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc12_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## cavs_filt ## SIZE ## _hv_ii(dst, src, src+stride+1,stride, stride); \
+}\
+\
+static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc32_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## cavs_filt ## SIZE ## _hv_kk(dst, src, src+stride+1,stride, stride); \
+}\
+\
+static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc23_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## cavs_filt ## SIZE ## _hv_qq(dst, src, src+stride+1,stride, stride); \
+}\
+
+#define op_put1(a, b) a = cm[((b)+4)>>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)
+
+void ff_put_cavs_qpel8_mc00_c(uint8_t *dst, uint8_t *src, int stride);
+void ff_avg_cavs_qpel8_mc00_c(uint8_t *dst, uint8_t *src, int stride);
+void ff_put_cavs_qpel16_mc00_c(uint8_t *dst, uint8_t *src, int stride);
+void ff_avg_cavs_qpel16_mc00_c(uint8_t *dst, uint8_t *src, int stride);
+
+void ff_cavsdsp_init(DSPContext* 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;
+}
diff --git a/contrib/ffmpeg/libavcodec/cinepak.c b/contrib/ffmpeg/libavcodec/cinepak.c
new file mode 100644
index 000000000..e137377e5
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/cinepak.c
@@ -0,0 +1,453 @@
+/*
+ * 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.c
+ * Cinepak video decoder
+ * by Ewald Snel <ewald@rambo.its.tudelft.nl>
+ * For more information on the Cinepak algorithm, visit:
+ * http://www.csse.monash.edu.au/~timf/
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.h"
+
+
+typedef struct {
+ uint8_t y0, y1, y2, y3;
+ uint8_t u, v;
+} cvid_codebook_t;
+
+#define MAX_STRIPS 32
+
+typedef struct {
+ uint16_t id;
+ uint16_t x1, y1;
+ uint16_t x2, y2;
+ cvid_codebook_t v4_codebook[256];
+ cvid_codebook_t v1_codebook[256];
+} cvid_strip_t;
+
+typedef struct CinepakContext {
+
+ AVCodecContext *avctx;
+ DSPContext dsp;
+ AVFrame frame;
+
+ unsigned char *data;
+ int size;
+
+ int width, height;
+
+ int palette_video;
+ cvid_strip_t strips[MAX_STRIPS];
+
+} CinepakContext;
+
+static void cinepak_decode_codebook (cvid_codebook_t *codebook,
+ int chunk_id, int size, uint8_t *data)
+{
+ uint8_t *eod = (data + size);
+ uint32_t flag, mask;
+ int i, n;
+
+ /* check if this chunk contains 4- or 6-element vectors */
+ n = (chunk_id & 0x0400) ? 4 : 6;
+ flag = 0;
+ mask = 0;
+
+ for (i=0; i < 256; i++) {
+ if ((chunk_id & 0x0100) && !(mask >>= 1)) {
+ if ((data + 4) > eod)
+ break;
+
+ flag = BE_32 (data);
+ data += 4;
+ mask = 0x80000000;
+ }
+
+ if (!(chunk_id & 0x0100) || (flag & mask)) {
+ if ((data + n) > eod)
+ break;
+
+ if (n == 6) {
+ codebook[i].y0 = *data++;
+ codebook[i].y1 = *data++;
+ codebook[i].y2 = *data++;
+ codebook[i].y3 = *data++;
+ codebook[i].u = 128 + *data++;
+ codebook[i].v = 128 + *data++;
+ } else {
+ /* this codebook type indicates either greyscale or
+ * palettized video; if palettized, U & V components will
+ * not be used so it is safe to set them to 128 for the
+ * benefit of greyscale rendering in YUV420P */
+ codebook[i].y0 = *data++;
+ codebook[i].y1 = *data++;
+ codebook[i].y2 = *data++;
+ codebook[i].y3 = *data++;
+ codebook[i].u = 128;
+ codebook[i].v = 128;
+ }
+ }
+ }
+}
+
+static int cinepak_decode_vectors (CinepakContext *s, cvid_strip_t *strip,
+ int chunk_id, int size, uint8_t *data)
+{
+ uint8_t *eod = (data + size);
+ uint32_t flag, mask;
+ cvid_codebook_t *codebook;
+ unsigned int x, y;
+ uint32_t iy[4];
+ uint32_t iu[2];
+ uint32_t iv[2];
+
+ flag = 0;
+ mask = 0;
+
+ for (y=strip->y1; y < strip->y2; y+=4) {
+
+ iy[0] = strip->x1 + (y * s->frame.linesize[0]);
+ iy[1] = iy[0] + s->frame.linesize[0];
+ iy[2] = iy[1] + s->frame.linesize[0];
+ iy[3] = iy[2] + s->frame.linesize[0];
+ iu[0] = (strip->x1/2) + ((y/2) * s->frame.linesize[1]);
+ iu[1] = iu[0] + s->frame.linesize[1];
+ iv[0] = (strip->x1/2) + ((y/2) * s->frame.linesize[2]);
+ iv[1] = iv[0] + s->frame.linesize[2];
+
+ for (x=strip->x1; x < strip->x2; x+=4) {
+ if ((chunk_id & 0x0100) && !(mask >>= 1)) {
+ if ((data + 4) > eod)
+ return -1;
+
+ flag = BE_32 (data);
+ data += 4;
+ mask = 0x80000000;
+ }
+
+ if (!(chunk_id & 0x0100) || (flag & mask)) {
+ if (!(chunk_id & 0x0200) && !(mask >>= 1)) {
+ if ((data + 4) > eod)
+ return -1;
+
+ flag = BE_32 (data);
+ data += 4;
+ mask = 0x80000000;
+ }
+
+ if ((chunk_id & 0x0200) || (~flag & mask)) {
+ if (data >= eod)
+ return -1;
+
+ codebook = &strip->v1_codebook[*data++];
+ s->frame.data[0][iy[0] + 0] = codebook->y0;
+ s->frame.data[0][iy[0] + 1] = codebook->y0;
+ s->frame.data[0][iy[1] + 0] = codebook->y0;
+ s->frame.data[0][iy[1] + 1] = codebook->y0;
+ if (!s->palette_video) {
+ s->frame.data[1][iu[0]] = codebook->u;
+ s->frame.data[2][iv[0]] = codebook->v;
+ }
+
+ s->frame.data[0][iy[0] + 2] = codebook->y1;
+ s->frame.data[0][iy[0] + 3] = codebook->y1;
+ s->frame.data[0][iy[1] + 2] = codebook->y1;
+ s->frame.data[0][iy[1] + 3] = codebook->y1;
+ if (!s->palette_video) {
+ s->frame.data[1][iu[0] + 1] = codebook->u;
+ s->frame.data[2][iv[0] + 1] = codebook->v;
+ }
+
+ s->frame.data[0][iy[2] + 0] = codebook->y2;
+ s->frame.data[0][iy[2] + 1] = codebook->y2;
+ s->frame.data[0][iy[3] + 0] = codebook->y2;
+ s->frame.data[0][iy[3] + 1] = codebook->y2;
+ if (!s->palette_video) {
+ s->frame.data[1][iu[1]] = codebook->u;
+ s->frame.data[2][iv[1]] = codebook->v;
+ }
+
+ s->frame.data[0][iy[2] + 2] = codebook->y3;
+ s->frame.data[0][iy[2] + 3] = codebook->y3;
+ s->frame.data[0][iy[3] + 2] = codebook->y3;
+ s->frame.data[0][iy[3] + 3] = codebook->y3;
+ if (!s->palette_video) {
+ s->frame.data[1][iu[1] + 1] = codebook->u;
+ s->frame.data[2][iv[1] + 1] = codebook->v;
+ }
+
+ } else if (flag & mask) {
+ if ((data + 4) > eod)
+ return -1;
+
+ codebook = &strip->v4_codebook[*data++];
+ s->frame.data[0][iy[0] + 0] = codebook->y0;
+ s->frame.data[0][iy[0] + 1] = codebook->y1;
+ s->frame.data[0][iy[1] + 0] = codebook->y2;
+ s->frame.data[0][iy[1] + 1] = codebook->y3;
+ if (!s->palette_video) {
+ s->frame.data[1][iu[0]] = codebook->u;
+ s->frame.data[2][iv[0]] = codebook->v;
+ }
+
+ codebook = &strip->v4_codebook[*data++];
+ s->frame.data[0][iy[0] + 2] = codebook->y0;
+ s->frame.data[0][iy[0] + 3] = codebook->y1;
+ s->frame.data[0][iy[1] + 2] = codebook->y2;
+ s->frame.data[0][iy[1] + 3] = codebook->y3;
+ if (!s->palette_video) {
+ s->frame.data[1][iu[0] + 1] = codebook->u;
+ s->frame.data[2][iv[0] + 1] = codebook->v;
+ }
+
+ codebook = &strip->v4_codebook[*data++];
+ s->frame.data[0][iy[2] + 0] = codebook->y0;
+ s->frame.data[0][iy[2] + 1] = codebook->y1;
+ s->frame.data[0][iy[3] + 0] = codebook->y2;
+ s->frame.data[0][iy[3] + 1] = codebook->y3;
+ if (!s->palette_video) {
+ s->frame.data[1][iu[1]] = codebook->u;
+ s->frame.data[2][iv[1]] = codebook->v;
+ }
+
+ codebook = &strip->v4_codebook[*data++];
+ s->frame.data[0][iy[2] + 2] = codebook->y0;
+ s->frame.data[0][iy[2] + 3] = codebook->y1;
+ s->frame.data[0][iy[3] + 2] = codebook->y2;
+ s->frame.data[0][iy[3] + 3] = codebook->y3;
+ if (!s->palette_video) {
+ s->frame.data[1][iu[1] + 1] = codebook->u;
+ s->frame.data[2][iv[1] + 1] = codebook->v;
+ }
+
+ }
+ }
+
+ iy[0] += 4; iy[1] += 4;
+ iy[2] += 4; iy[3] += 4;
+ iu[0] += 2; iu[1] += 2;
+ iv[0] += 2; iv[1] += 2;
+ }
+ }
+
+ return 0;
+}
+
+static int cinepak_decode_strip (CinepakContext *s,
+ cvid_strip_t *strip, uint8_t *data, int size)
+{
+ uint8_t *eod = (data + size);
+ int chunk_id, chunk_size;
+
+ /* coordinate sanity checks */
+ if (strip->x1 >= s->width || strip->x2 > s->width ||
+ strip->y1 >= s->height || strip->y2 > s->height ||
+ strip->x1 >= strip->x2 || strip->y1 >= strip->y2)
+ return -1;
+
+ while ((data + 4) <= eod) {
+ chunk_id = BE_16 (&data[0]);
+ chunk_size = BE_16 (&data[2]) - 4;
+ if(chunk_size < 0)
+ return -1;
+
+ data += 4;
+ chunk_size = ((data + chunk_size) > eod) ? (eod - data) : chunk_size;
+
+ switch (chunk_id) {
+
+ case 0x2000:
+ case 0x2100:
+ case 0x2400:
+ case 0x2500:
+ cinepak_decode_codebook (strip->v4_codebook, chunk_id,
+ chunk_size, data);
+ break;
+
+ case 0x2200:
+ case 0x2300:
+ case 0x2600:
+ case 0x2700:
+ cinepak_decode_codebook (strip->v1_codebook, chunk_id,
+ chunk_size, data);
+ break;
+
+ case 0x3000:
+ case 0x3100:
+ case 0x3200:
+ return cinepak_decode_vectors (s, strip, chunk_id,
+ chunk_size, data);
+ }
+
+ data += chunk_size;
+ }
+
+ return -1;
+}
+
+static int cinepak_decode (CinepakContext *s)
+{
+ uint8_t *eod = (s->data + s->size);
+ int i, result, strip_size, frame_flags, num_strips;
+ int y0 = 0;
+ int encoded_buf_size;
+ /* if true, Cinepak data is from a Sega FILM/CPK file */
+ int sega_film_data = 0;
+
+ if (s->size < 10)
+ return -1;
+
+ frame_flags = s->data[0];
+ num_strips = BE_16 (&s->data[8]);
+ encoded_buf_size = ((s->data[1] << 16) | BE_16 (&s->data[2]));
+ if (encoded_buf_size != s->size)
+ sega_film_data = 1;
+ if (sega_film_data)
+ s->data += 12;
+ else
+ s->data += 10;
+
+ if (num_strips > MAX_STRIPS)
+ num_strips = MAX_STRIPS;
+
+ for (i=0; i < num_strips; i++) {
+ if ((s->data + 12) > eod)
+ return -1;
+
+ s->strips[i].id = BE_16 (s->data);
+ s->strips[i].y1 = y0;
+ s->strips[i].x1 = 0;
+ s->strips[i].y2 = y0 + BE_16 (&s->data[8]);
+ s->strips[i].x2 = s->avctx->width;
+
+ strip_size = BE_16 (&s->data[2]) - 12;
+ 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 int cinepak_decode_init(AVCodecContext *avctx)
+{
+ CinepakContext *s = (CinepakContext *)avctx->priv_data;
+
+ s->avctx = avctx;
+ s->width = (avctx->width + 3) & ~3;
+ s->height = (avctx->height + 3) & ~3;
+
+ // check for paletted data
+ if ((avctx->palctrl == NULL) || (avctx->bits_per_sample == 40)) {
+ s->palette_video = 0;
+ avctx->pix_fmt = PIX_FMT_YUV420P;
+ } else {
+ s->palette_video = 1;
+ avctx->pix_fmt = PIX_FMT_PAL8;
+ }
+
+ avctx->has_b_frames = 0;
+ dsputil_init(&s->dsp, avctx);
+
+ s->frame.data[0] = NULL;
+
+ return 0;
+}
+
+static int cinepak_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ CinepakContext *s = (CinepakContext *)avctx->priv_data;
+
+ s->data = buf;
+ s->size = buf_size;
+
+ s->frame.reference = 1;
+ s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
+ FF_BUFFER_HINTS_REUSABLE;
+ if (avctx->reget_buffer(avctx, &s->frame)) {
+ av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+ return -1;
+ }
+
+ cinepak_decode(s);
+
+ if (s->palette_video) {
+ memcpy (s->frame.data[1], avctx->palctrl->palette, AVPALETTE_SIZE);
+ if (avctx->palctrl->palette_changed) {
+ s->frame.palette_has_changed = 1;
+ avctx->palctrl->palette_changed = 0;
+ } else
+ s->frame.palette_has_changed = 0;
+ }
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = s->frame;
+
+ /* report that the buffer was completely consumed */
+ return buf_size;
+}
+
+static int cinepak_decode_end(AVCodecContext *avctx)
+{
+ CinepakContext *s = (CinepakContext *)avctx->priv_data;
+
+ if (s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ return 0;
+}
+
+AVCodec cinepak_decoder = {
+ "cinepak",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_CINEPAK,
+ sizeof(CinepakContext),
+ cinepak_decode_init,
+ NULL,
+ cinepak_decode_end,
+ cinepak_decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/cljr.c b/contrib/ffmpeg/libavcodec/cljr.c
new file mode 100644
index 000000000..44810f5cf
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/cljr.c
@@ -0,0 +1,158 @@
+/*
+ * 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 cljr.c
+ * Cirrus Logic AccuPak codec.
+ */
+
+#include "avcodec.h"
+#include "mpegvideo.h"
+
+typedef struct CLJRContext{
+ AVCodecContext *avctx;
+ AVFrame picture;
+ int delta[16];
+ int offset[4];
+ GetBitContext gb;
+} CLJRContext;
+
+static int decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ CLJRContext * const a = avctx->priv_data;
+ AVFrame *picture = data;
+ AVFrame * const p= (AVFrame*)&a->picture;
+ int x, y;
+
+ if(p->data[0])
+ avctx->release_buffer(avctx, p);
+
+ p->reference= 0;
+ if(avctx->get_buffer(avctx, p) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+ p->pict_type= I_TYPE;
+ p->key_frame= 1;
+
+ init_get_bits(&a->gb, buf, buf_size);
+
+ for(y=0; y<avctx->height; y++){
+ uint8_t *luma= &a->picture.data[0][ y*a->picture.linesize[0] ];
+ uint8_t *cb= &a->picture.data[1][ y*a->picture.linesize[1] ];
+ uint8_t *cr= &a->picture.data[2][ y*a->picture.linesize[2] ];
+ for(x=0; x<avctx->width; x+=4){
+ luma[3] = get_bits(&a->gb, 5) << 3;
+ luma[2] = get_bits(&a->gb, 5) << 3;
+ luma[1] = get_bits(&a->gb, 5) << 3;
+ luma[0] = get_bits(&a->gb, 5) << 3;
+ luma+= 4;
+ *(cb++) = get_bits(&a->gb, 6) << 2;
+ *(cr++) = get_bits(&a->gb, 6) << 2;
+ }
+ }
+
+ *picture= *(AVFrame*)&a->picture;
+ *data_size = sizeof(AVPicture);
+
+ emms_c();
+
+ return buf_size;
+}
+
+#if 0
+static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
+ CLJRContext * const a = avctx->priv_data;
+ AVFrame *pict = data;
+ AVFrame * const p= (AVFrame*)&a->picture;
+ int size;
+ int mb_x, mb_y;
+
+ *p = *pict;
+ p->pict_type= I_TYPE;
+ p->key_frame= 1;
+
+ emms_c();
+
+ align_put_bits(&a->pb);
+ while(get_bit_count(&a->pb)&31)
+ put_bits(&a->pb, 8, 0);
+
+ size= get_bit_count(&a->pb)/32;
+
+ return size*4;
+}
+#endif
+
+static void common_init(AVCodecContext *avctx){
+ CLJRContext * const a = avctx->priv_data;
+
+ avctx->coded_frame= (AVFrame*)&a->picture;
+ a->avctx= avctx;
+}
+
+static int decode_init(AVCodecContext *avctx){
+
+ common_init(avctx);
+
+ avctx->pix_fmt= PIX_FMT_YUV411P;
+
+ return 0;
+}
+
+#if 0
+static int encode_init(AVCodecContext *avctx){
+
+ common_init(avctx);
+
+ return 0;
+}
+#endif
+
+AVCodec cljr_decoder = {
+ "cljr",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_CLJR,
+ sizeof(CLJRContext),
+ decode_init,
+ NULL,
+ NULL,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
+#if 0
+#ifdef CONFIG_ENCODERS
+
+AVCodec cljr_encoder = {
+ "cljr",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_cljr,
+ sizeof(CLJRContext),
+ encode_init,
+ encode_frame,
+ //encode_end,
+};
+
+#endif //CONFIG_ENCODERS
+#endif
diff --git a/contrib/ffmpeg/libavcodec/cook.c b/contrib/ffmpeg/libavcodec/cook.c
new file mode 100644
index 000000000..47d9ce2c3
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/cook.c
@@ -0,0 +1,1312 @@
+/*
+ * 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.c
+ * Cook compatible decoder.
+ * 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 <math.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include "avcodec.h"
+#include "bitstream.h"
+#include "dsputil.h"
+
+#include "cookdata.h"
+
+/* the different Cook versions */
+#define MONO_COOK1 0x1000001
+#define MONO_COOK2 0x1000002
+#define JOINT_STEREO 0x1000003
+#define MC_COOK 0x2000000 //multichannel Cook, not supported
+
+#define SUBBAND_SIZE 20
+//#define COOKDEBUG
+
+typedef struct {
+ int size;
+ int qidx_table1[8];
+ int qidx_table2[8];
+} COOKgain;
+
+typedef struct __attribute__((__packed__)){
+ /* codec data start */
+ uint32_t cookversion; //in network order, bigendian
+ uint16_t samples_per_frame; //amount of samples per frame per channel, bigendian
+ uint16_t subbands; //amount of bands used in the frequency domain, bigendian
+ /* Mono extradata ends here. */
+ uint32_t unused;
+ uint16_t js_subband_start; //bigendian
+ uint16_t js_vlc_bits; //bigendian
+ /* Stereo extradata ends here. */
+} COOKextradata;
+
+
+typedef struct {
+ GetBitContext gb;
+ /* stream data */
+ int nb_channels;
+ int joint_stereo;
+ int bit_rate;
+ int sample_rate;
+ int samples_per_channel;
+ int samples_per_frame;
+ int subbands;
+ int log2_numvector_size;
+ int numvector_size; //1 << log2_numvector_size;
+ int js_subband_start;
+ int total_subbands;
+ int num_vectors;
+ int bits_per_subpacket;
+ /* states */
+ int random_state;
+
+ /* transform data */
+ FFTContext fft_ctx;
+ FFTSample mlt_tmp[1024] __attribute__((aligned(16))); /* temporary storage for imlt */
+ float* mlt_window;
+ float* mlt_precos;
+ float* mlt_presin;
+ float* mlt_postcos;
+ int fft_size;
+ int fft_order;
+ int mlt_size; //modulated lapped transform size
+
+ /* gain buffers */
+ COOKgain* gain_now_ptr;
+ COOKgain* gain_previous_ptr;
+ COOKgain gain_current;
+ COOKgain gain_now;
+ COOKgain gain_previous;
+ COOKgain gain_channel1[2];
+ COOKgain gain_channel2[2];
+
+ /* VLC data */
+ int js_vlc_bits;
+ VLC envelope_quant_index[13];
+ VLC sqvh[7]; //scalar quantization
+ VLC ccpl; //channel coupling
+
+ /* generatable tables and related variables */
+ int gain_size_factor;
+ float gain_table[23];
+ float pow2tab[127];
+ float rootpow2tab[127];
+
+ /* data buffers */
+
+ uint8_t* decoded_bytes_buffer;
+ float mono_mdct_output[2048] __attribute__((aligned(16)));
+ float* previous_buffer_ptr[2];
+ float mono_previous_buffer1[1024];
+ float mono_previous_buffer2[1024];
+ float* decode_buf_ptr[4];
+ float* decode_buf_ptr2[2];
+ float decode_buffer_1[1024];
+ float decode_buffer_2[1024];
+ float decode_buffer_3[1024];
+ float decode_buffer_4[1024];
+} COOKContext;
+
+/* debug functions */
+
+#ifdef COOKDEBUG
+static void dump_float_table(float* table, int size, int delimiter) {
+ int i=0;
+ av_log(NULL,AV_LOG_ERROR,"\n[%d]: ",i);
+ for (i=0 ; i<size ; i++) {
+ av_log(NULL, AV_LOG_ERROR, "%5.1f, ", table[i]);
+ if ((i+1)%delimiter == 0) av_log(NULL,AV_LOG_ERROR,"\n[%d]: ",i+1);
+ }
+}
+
+static void dump_int_table(int* table, int size, int delimiter) {
+ int i=0;
+ av_log(NULL,AV_LOG_ERROR,"\n[%d]: ",i);
+ for (i=0 ; i<size ; i++) {
+ av_log(NULL, AV_LOG_ERROR, "%d, ", table[i]);
+ if ((i+1)%delimiter == 0) av_log(NULL,AV_LOG_ERROR,"\n[%d]: ",i+1);
+ }
+}
+
+static void dump_short_table(short* table, int size, int delimiter) {
+ int i=0;
+ av_log(NULL,AV_LOG_ERROR,"\n[%d]: ",i);
+ for (i=0 ; i<size ; i++) {
+ av_log(NULL, AV_LOG_ERROR, "%d, ", table[i]);
+ if ((i+1)%delimiter == 0) av_log(NULL,AV_LOG_ERROR,"\n[%d]: ",i+1);
+ }
+}
+
+#endif
+
+/*************** init functions ***************/
+
+/* table generator */
+static void init_pow2table(COOKContext *q){
+ int i;
+ q->pow2tab[63] = 1.0;
+ for (i=1 ; i<64 ; i++){
+ q->pow2tab[63+i]=(float)((uint64_t)1<<i);
+ q->pow2tab[63-i]=1.0/(float)((uint64_t)1<<i);
+ }
+}
+
+/* table generator */
+static void init_rootpow2table(COOKContext *q){
+ int i;
+ q->rootpow2tab[63] = 1.0;
+ for (i=1 ; i<64 ; i++){
+ q->rootpow2tab[63+i]=sqrt((float)((uint64_t)1<<i));
+ q->rootpow2tab[63-i]=sqrt(1.0/(float)((uint64_t)1<<i));
+ }
+}
+
+/* table generator */
+static 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((double)q->pow2tab[i+52] ,
+ (1.0/(double)q->gain_size_factor));
+ }
+}
+
+
+static 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(NULL,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);
+ }
+
+ if (q->nb_channels==2 && q->joint_stereo==1){
+ result &= init_vlc (&q->ccpl, 6, (1<<q->js_vlc_bits)-1,
+ ccpl_huffbits[q->js_vlc_bits-2], 1, 1,
+ ccpl_huffcodes[q->js_vlc_bits-2], 2, 2, 0);
+ av_log(NULL,AV_LOG_DEBUG,"Joint-stereo VLC used.\n");
+ }
+
+ av_log(NULL,AV_LOG_DEBUG,"VLC tables initialized.\n");
+ return result;
+}
+
+static int init_cook_mlt(COOKContext *q) {
+ int j;
+ float alpha;
+
+ /* Allocate the buffers, could be replaced with a static [512]
+ array if needed. */
+ q->mlt_size = q->samples_per_channel;
+ q->mlt_window = av_malloc(sizeof(float)*q->mlt_size);
+ q->mlt_precos = av_malloc(sizeof(float)*q->mlt_size/2);
+ q->mlt_presin = av_malloc(sizeof(float)*q->mlt_size/2);
+ q->mlt_postcos = av_malloc(sizeof(float)*q->mlt_size/2);
+
+ /* Initialize the MLT window: simple sine window. */
+ alpha = M_PI / (2.0 * (float)q->mlt_size);
+ for(j=0 ; j<q->mlt_size ; j++) {
+ q->mlt_window[j] = sin((j + 512.0/(float)q->mlt_size) * alpha);
+ }
+
+ /* pre/post twiddle factors */
+ for (j=0 ; j<q->mlt_size/2 ; j++){
+ q->mlt_precos[j] = cos( ((j+0.25)*M_PI)/q->mlt_size);
+ q->mlt_presin[j] = sin( ((j+0.25)*M_PI)/q->mlt_size);
+ q->mlt_postcos[j] = (float)sqrt(2.0/(float)q->mlt_size)*cos( ((float)j*M_PI) /q->mlt_size); //sqrt(2/MLT_size) = scalefactor
+ }
+
+ /* Initialize the FFT. */
+ ff_fft_init(&q->fft_ctx, av_log2(q->mlt_size)-1, 0);
+ av_log(NULL,AV_LOG_DEBUG,"FFT initialized, order = %d.\n",
+ av_log2(q->samples_per_channel)-1);
+
+ return (int)(q->mlt_window && q->mlt_precos && q->mlt_presin && q->mlt_postcos);
+}
+
+/*************** init functions end ***********/
+
+/**
+ * Cook indata decoding, every 32 bits are XORed with 0x37c511f2.
+ * Why? No idea, some checksum/error detection method maybe.
+ * Nice way to waste CPU cycles.
+ *
+ * @param in pointer to 32bit array of indata
+ * @param bits amount of bits
+ * @param out pointer to 32bit array of outdata
+ */
+
+static inline void decode_bytes(uint8_t* inbuffer, uint8_t* out, int bytes){
+ int i;
+ uint32_t* buf = (uint32_t*) inbuffer;
+ 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^be2me_64(int64_t)in[i]);
+ * Buffer alignment needs to be checked. */
+
+
+ for(i=0 ; i<bytes/4 ; i++){
+#ifdef WORDS_BIGENDIAN
+ obuf[i] = 0x37c511f2^buf[i];
+#else
+ obuf[i] = 0xf211c537^buf[i];
+#endif
+ }
+}
+
+/**
+ * Cook uninit
+ */
+
+static int cook_decode_close(AVCodecContext *avctx)
+{
+ int i;
+ COOKContext *q = avctx->priv_data;
+ av_log(NULL,AV_LOG_DEBUG, "Deallocating memory.\n");
+
+ /* Free allocated memory buffers. */
+ av_free(q->mlt_window);
+ av_free(q->mlt_precos);
+ av_free(q->mlt_presin);
+ av_free(q->mlt_postcos);
+ av_free(q->decoded_bytes_buffer);
+
+ /* Free the transform. */
+ ff_fft_end(&q->fft_ctx);
+
+ /* Free the VLC tables. */
+ for (i=0 ; i<13 ; i++) {
+ free_vlc(&q->envelope_quant_index[i]);
+ }
+ for (i=0 ; i<7 ; i++) {
+ free_vlc(&q->sqvh[i]);
+ }
+ if(q->nb_channels==2 && q->joint_stereo==1 ){
+ free_vlc(&q->ccpl);
+ }
+
+ av_log(NULL,AV_LOG_DEBUG,"Memory deallocated.\n");
+
+ return 0;
+}
+
+/**
+ * Fill the COOKgain structure for the timedomain quantization.
+ *
+ * @param q pointer to the COOKContext
+ * @param gaininfo pointer to the COOKgain
+ */
+
+static void decode_gain_info(GetBitContext *gb, COOKgain* gaininfo) {
+ int i;
+
+ while (get_bits1(gb)) {}
+
+ gaininfo->size = get_bits_count(gb) - 1; //amount of elements*2 to update
+
+ if (get_bits_count(gb) - 1 <= 0) return;
+
+ for (i=0 ; i<gaininfo->size ; i++){
+ gaininfo->qidx_table1[i] = get_bits(gb,3);
+ if (get_bits1(gb)) {
+ gaininfo->qidx_table2[i] = get_bits(gb,4) - 7; //convert to signed
+ } else {
+ gaininfo->qidx_table2[i] = -1;
+ }
+ }
+}
+
+/**
+ * Create the quant index table needed for the envelope.
+ *
+ * @param q pointer to the COOKContext
+ * @param quant_index_table pointer to the array
+ */
+
+static void decode_envelope(COOKContext *q, int* quant_index_table) {
+ int i,j, vlc_index;
+ int bitbias;
+
+ bitbias = get_bits_count(&q->gb);
+ quant_index_table[0]= get_bits(&q->gb,6) - 6; //This is used later in categorize
+
+ for (i=1 ; i < q->total_subbands ; i++){
+ vlc_index=i;
+ if (i >= q->js_subband_start * 2) {
+ vlc_index-=q->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
+ }
+}
+
+/**
+ * Create the quant value table.
+ *
+ * @param q pointer to the COOKContext
+ * @param quant_value_table pointer to the array
+ */
+
+static void inline dequant_envelope(COOKContext *q, int* quant_index_table,
+ float* quant_value_table){
+
+ int i;
+ for(i=0 ; i < q->total_subbands ; i++){
+ quant_value_table[i] = q->rootpow2tab[quant_index_table[i]+63];
+ }
+}
+
+/**
+ * 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, int* quant_index_table,
+ int* category, int* category_index){
+ int exp_idx, bias, tmpbias, bits_left, num_bits, index, v, i, j;
+ int exp_index2[102];
+ int exp_index1[102];
+
+ int tmp_categorize_array1[128];
+ int tmp_categorize_array1_idx=0;
+ int tmp_categorize_array2[128];
+ int tmp_categorize_array2_idx=0;
+ int category_index_size=0;
+
+ bits_left = q->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;
+ //av_log(NULL, AV_LOG_ERROR, "bits_left = %d\n",bits_left);
+ }
+
+ memset(&exp_index1,0,102*sizeof(int));
+ memset(&exp_index2,0,102*sizeof(int));
+ memset(&tmp_categorize_array1,0,128*sizeof(int));
+ memset(&tmp_categorize_array2,0,128*sizeof(int));
+
+ bias=-32;
+
+ /* Estimate bias. */
+ for (i=32 ; i>0 ; i=i/2){
+ num_bits = 0;
+ index = 0;
+ for (j=q->total_subbands ; j>0 ; j--){
+ exp_idx = (i - quant_index_table[index] + bias) / 2;
+ if (exp_idx<0){
+ exp_idx=0;
+ } else if(exp_idx >7) {
+ exp_idx=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<q->total_subbands ; i++) {
+ exp_idx = (bias - quant_index_table[i]) / 2;
+ if (exp_idx<0) {
+ exp_idx=0;
+ } else if(exp_idx >7) {
+ exp_idx=7;
+ }
+ num_bits += expbits_tab[exp_idx];
+ exp_index1[i] = exp_idx;
+ exp_index2[i] = exp_idx;
+ }
+ tmpbias = bias = num_bits;
+
+ for (j = 1 ; j < q->numvector_size ; j++) {
+ if (tmpbias + bias > 2*bits_left) { /* ---> */
+ int max = -999999;
+ index=-1;
+ for (i=0 ; i<q->total_subbands ; i++){
+ if (exp_index1[i] < 7) {
+ v = (-2*exp_index1[i]) - quant_index_table[i] - 32;
+ if ( v >= max) {
+ max = v;
+ index = i;
+ }
+ }
+ }
+ if(index==-1)break;
+ tmp_categorize_array1[tmp_categorize_array1_idx++] = index;
+ tmpbias -= expbits_tab[exp_index1[index]] -
+ expbits_tab[exp_index1[index]+1];
+ ++exp_index1[index];
+ } else { /* <--- */
+ int min = 999999;
+ index=-1;
+ for (i=0 ; i<q->total_subbands ; i++){
+ if(exp_index2[i] > 0){
+ v = (-2*exp_index2[i])-quant_index_table[i];
+ if ( v < min) {
+ min = v;
+ index = i;
+ }
+ }
+ }
+ if(index == -1)break;
+ tmp_categorize_array2[tmp_categorize_array2_idx++] = index;
+ tmpbias -= expbits_tab[exp_index2[index]] -
+ expbits_tab[exp_index2[index]-1];
+ --exp_index2[index];
+ }
+ }
+
+ for(i=0 ; i<q->total_subbands ; i++)
+ category[i] = exp_index2[i];
+
+ /* Concatenate the two arrays. */
+ for(i=tmp_categorize_array2_idx-1 ; i >= 0; i--)
+ category_index[category_index_size++] = tmp_categorize_array2[i];
+
+ for(i=0;i<tmp_categorize_array1_idx;i++)
+ category_index[category_index_size++ ] = tmp_categorize_array1[i];
+
+ /* FIXME: mc_sich_ra8_20.rm triggers this, not sure with what we
+ should fill the remaining bytes. */
+ for(i=category_index_size;i<q->numvector_size;i++)
+ category_index[i]=0;
+
+}
+
+
+/**
+ * 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 void inline expand_category(COOKContext *q, int* category,
+ int* category_index){
+ int i;
+ for(i=0 ; i<q->num_vectors ; i++){
+ ++category[category_index[i]];
+ }
+}
+
+/**
+ * The real requantization of the mltcoefs
+ *
+ * @param q pointer to the COOKContext
+ * @param index index
+ * @param band current subband
+ * @param quant_value_table pointer to the array
+ * @param subband_coef_index array of indexes to quant_centroid_tab
+ * @param subband_coef_noise use random noise instead of predetermined value
+ * @param mlt_buffer pointer to the mlt buffer
+ */
+
+
+static void scalar_dequant(COOKContext *q, int index, int band,
+ float* quant_value_table, int* subband_coef_index,
+ int* subband_coef_noise, float* mlt_buffer){
+ int i;
+ float f1;
+
+ for(i=0 ; i<SUBBAND_SIZE ; i++) {
+ if (subband_coef_index[i]) {
+ if (subband_coef_noise[i]) {
+ f1 = -quant_centroid_tab[index][subband_coef_index[i]];
+ } else {
+ f1 = quant_centroid_tab[index][subband_coef_index[i]];
+ }
+ } else {
+ /* noise coding if subband_coef_noise[i] == 0 */
+ q->random_state = q->random_state * 214013 + 2531011; //typical RNG numbers
+ f1 = randsign[(q->random_state/0x1000000)&1] * dither_tab[index]; //>>31
+ }
+ mlt_buffer[band*20+ i] = f1 * quant_value_table[band];
+ }
+}
+/**
+ * Unpack the subband_coef_index and subband_coef_noise 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_noise use random noise instead of predetermined value
+ */
+
+static int unpack_SQVH(COOKContext *q, int category, int* subband_coef_index,
+ int* subband_coef_noise) {
+ int i,j;
+ int vlc, vd ,tmp, result;
+ int ub;
+ int cb;
+
+ vd = vd_tab[category];
+ result = 0;
+ for(i=0 ; i<vpr_tab[category] ; i++){
+ ub = get_bits_count(&q->gb);
+ vlc = get_vlc2(&q->gb, q->sqvh[category].table, q->sqvh[category].bits, 3);
+ cb = get_bits_count(&q->gb);
+ if (q->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) < q->bits_per_subpacket){
+ subband_coef_noise[i*vd+j] = get_bits1(&q->gb);
+ } else {
+ result=1;
+ subband_coef_noise[i*vd+j]=0;
+ }
+ } else {
+ subband_coef_noise[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_value_table pointer to the array
+ * @param mlt_buffer pointer to mlt coefficients
+ */
+
+
+static void decode_vectors(COOKContext* q, int* category,
+ float* quant_value_table, float* mlt_buffer){
+ /* A zero in this table means that the subband coefficient is
+ random noise coded. */
+ int subband_coef_noise[SUBBAND_SIZE];
+ /* A zero in this table means that the subband coefficient is a
+ positive multiplicator. */
+ int subband_coef_index[SUBBAND_SIZE];
+ int band, j;
+ int index=0;
+
+ for(band=0 ; band<q->total_subbands ; band++){
+ index = category[band];
+ if(category[band] < 7){
+ if(unpack_SQVH(q, category[band], subband_coef_index, subband_coef_noise)){
+ index=7;
+ for(j=0 ; j<q->total_subbands ; j++) category[band+j]=7;
+ }
+ }
+ if(index==7) {
+ memset(subband_coef_index, 0, sizeof(subband_coef_index));
+ memset(subband_coef_noise, 0, sizeof(subband_coef_noise));
+ }
+ scalar_dequant(q, index, band, quant_value_table, subband_coef_index,
+ subband_coef_noise, mlt_buffer);
+ }
+
+ if(q->total_subbands*SUBBAND_SIZE >= q->samples_per_channel){
+ return;
+ }
+}
+
+
+/**
+ * function for decoding mono 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 void mono_decode(COOKContext *q, float* mlt_buffer) {
+
+ int category_index[128];
+ float quant_value_table[102];
+ int quant_index_table[102];
+ int category[128];
+
+ memset(&category, 0, 128*sizeof(int));
+ memset(&quant_value_table, 0, 102*sizeof(int));
+ memset(&category_index, 0, 128*sizeof(int));
+
+ decode_envelope(q, quant_index_table);
+ q->num_vectors = get_bits(&q->gb,q->log2_numvector_size);
+ dequant_envelope(q, quant_index_table, quant_value_table);
+ categorize(q, quant_index_table, category, category_index);
+ expand_category(q, category, category_index);
+ decode_vectors(q, category, quant_value_table, mlt_buffer);
+}
+
+
+/**
+ * The modulated lapped transform, this takes transform coefficients
+ * and transforms them into timedomain samples. This is done through
+ * an FFT-based algorithm with pre- and postrotation steps.
+ * A window and reorder step is also included.
+ *
+ * @param q pointer to the COOKContext
+ * @param inbuffer pointer to the mltcoefficients
+ * @param outbuffer pointer to the timedomain buffer
+ * @param mlt_tmp pointer to temporary storage space
+ */
+
+static void cook_imlt(COOKContext *q, float* inbuffer, float* outbuffer,
+ float* mlt_tmp){
+ int i;
+
+ /* prerotation */
+ for(i=0 ; i<q->mlt_size ; i+=2){
+ outbuffer[i] = (q->mlt_presin[i/2] * inbuffer[q->mlt_size-1-i]) +
+ (q->mlt_precos[i/2] * inbuffer[i]);
+ outbuffer[i+1] = (q->mlt_precos[i/2] * inbuffer[q->mlt_size-1-i]) -
+ (q->mlt_presin[i/2] * inbuffer[i]);
+ }
+
+ /* FFT */
+ ff_fft_permute(&q->fft_ctx, (FFTComplex *) outbuffer);
+ ff_fft_calc (&q->fft_ctx, (FFTComplex *) outbuffer);
+
+ /* postrotation */
+ for(i=0 ; i<q->mlt_size ; i+=2){
+ mlt_tmp[i] = (q->mlt_postcos[(q->mlt_size-1-i)/2] * outbuffer[i+1]) +
+ (q->mlt_postcos[i/2] * outbuffer[i]);
+ mlt_tmp[q->mlt_size-1-i] = (q->mlt_postcos[(q->mlt_size-1-i)/2] * outbuffer[i]) -
+ (q->mlt_postcos[i/2] * outbuffer[i+1]);
+ }
+
+ /* window and reorder */
+ for(i=0 ; i<q->mlt_size/2 ; i++){
+ outbuffer[i] = mlt_tmp[q->mlt_size/2-1-i] * q->mlt_window[i];
+ outbuffer[q->mlt_size-1-i]= mlt_tmp[q->mlt_size/2-1-i] *
+ q->mlt_window[q->mlt_size-1-i];
+ outbuffer[q->mlt_size+i]= mlt_tmp[q->mlt_size/2+i] *
+ q->mlt_window[q->mlt_size-1-i];
+ outbuffer[2*q->mlt_size-1-i]= -(mlt_tmp[q->mlt_size/2+i] *
+ q->mlt_window[i]);
+ }
+}
+
+
+/**
+ * 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(COOKContext *q, float* buffer,
+ int gain_index, int gain_index_next){
+ int i;
+ float fc1, fc2;
+ fc1 = q->pow2tab[gain_index+63];
+
+ if(gain_index == gain_index_next){ //static gain
+ for(i=0 ; i<q->gain_size_factor ; i++){
+ buffer[i]*=fc1;
+ }
+ return;
+ } 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;
+ }
+ return;
+ }
+}
+
+/**
+ * timedomain requantization of the timedomain samples
+ *
+ * @param q pointer to the COOKContext
+ * @param buffer pointer to the timedomain buffer
+ * @param gain_now current gain structure
+ * @param gain_previous previous gain structure
+ */
+
+static void gain_window(COOKContext *q, float* buffer, COOKgain* gain_now,
+ COOKgain* gain_previous){
+ int i, index;
+ int gain_index[9];
+ int tmp_gain_index;
+
+ gain_index[8]=0;
+ index = gain_previous->size;
+ for (i=7 ; i>=0 ; i--) {
+ if(index && gain_previous->qidx_table1[index-1]==i) {
+ gain_index[i] = gain_previous->qidx_table2[index-1];
+ index--;
+ } else {
+ gain_index[i]=gain_index[i+1];
+ }
+ }
+ /* This is applied to the to be previous data buffer. */
+ for(i=0;i<8;i++){
+ interpolate(q, &buffer[q->samples_per_channel+q->gain_size_factor*i],
+ gain_index[i], gain_index[i+1]);
+ }
+
+ tmp_gain_index = gain_index[0];
+ index = gain_now->size;
+ for (i=7 ; i>=0 ; i--) {
+ if(index && gain_now->qidx_table1[index-1]==i) {
+ gain_index[i]= gain_now->qidx_table2[index-1];
+ index--;
+ } else {
+ gain_index[i]=gain_index[i+1];
+ }
+ }
+
+ /* This is applied to the to be current block. */
+ for(i=0;i<8;i++){
+ interpolate(q, &buffer[i*q->gain_size_factor],
+ tmp_gain_index+gain_index[i],
+ tmp_gain_index+gain_index[i+1]);
+ }
+}
+
+
+/**
+ * mlt overlapping and buffer management
+ *
+ * @param q pointer to the COOKContext
+ * @param buffer pointer to the timedomain buffer
+ * @param gain_now current gain structure
+ * @param gain_previous previous gain structure
+ * @param previous_buffer pointer to the previous buffer to be used for overlapping
+ *
+ */
+
+static void gain_compensate(COOKContext *q, float* buffer, COOKgain* gain_now,
+ COOKgain* gain_previous, float* previous_buffer) {
+ int i;
+ if((gain_now->size || gain_previous->size)) {
+ gain_window(q, buffer, gain_now, gain_previous);
+ }
+
+ /* Overlap with the previous block. */
+ for(i=0 ; i<q->samples_per_channel ; i++) buffer[i]+=previous_buffer[i];
+
+ /* Save away the current to be previous block. */
+ memcpy(previous_buffer, buffer+q->samples_per_channel,
+ sizeof(float)*q->samples_per_channel);
+}
+
+
+/**
+ * function for getting the jointstereo coupling information
+ *
+ * @param q pointer to the COOKContext
+ * @param decouple_tab decoupling array
+ *
+ */
+
+static void decouple_info(COOKContext *q, int* decouple_tab){
+ int length, i;
+
+ if(get_bits1(&q->gb)) {
+ if(cplband[q->js_subband_start] > cplband[q->subbands-1]) return;
+
+ length = cplband[q->subbands-1] - cplband[q->js_subband_start] + 1;
+ for (i=0 ; i<length ; i++) {
+ decouple_tab[cplband[q->js_subband_start] + i] = get_vlc2(&q->gb, q->ccpl.table, q->ccpl.bits, 2);
+ }
+ return;
+ }
+
+ if(cplband[q->js_subband_start] > cplband[q->subbands-1]) return;
+
+ length = cplband[q->subbands-1] - cplband[q->js_subband_start] + 1;
+ for (i=0 ; i<length ; i++) {
+ decouple_tab[cplband[q->js_subband_start] + i] = get_bits(&q->gb, q->js_vlc_bits);
+ }
+ return;
+}
+
+
+/**
+ * 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 void joint_decode(COOKContext *q, float* mlt_buffer1,
+ float* mlt_buffer2) {
+ int i,j;
+ int decouple_tab[SUBBAND_SIZE];
+ float decode_buffer[1060];
+ int idx, cpl_tmp,tmp_idx;
+ float f1,f2;
+ float* cplscale;
+
+ memset(decouple_tab, 0, sizeof(decouple_tab));
+ memset(decode_buffer, 0, sizeof(decode_buffer));
+
+ /* Make sure the buffers are zeroed out. */
+ memset(mlt_buffer1,0, 1024*sizeof(float));
+ memset(mlt_buffer2,0, 1024*sizeof(float));
+ decouple_info(q, decouple_tab);
+ mono_decode(q, decode_buffer);
+
+ /* The two channels are stored interleaved in decode_buffer. */
+ for (i=0 ; i<q->js_subband_start ; i++) {
+ for (j=0 ; j<SUBBAND_SIZE ; j++) {
+ mlt_buffer1[i*20+j] = decode_buffer[i*40+j];
+ mlt_buffer2[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 << q->js_vlc_bits) - 1;
+ for (i=q->js_subband_start ; i<q->subbands ; i++) {
+ cpl_tmp = cplband[i];
+ idx -=decouple_tab[cpl_tmp];
+ cplscale = (float*)cplscales[q->js_vlc_bits-2]; //choose decoupler table
+ f1 = cplscale[decouple_tab[cpl_tmp]];
+ f2 = cplscale[idx-1];
+ for (j=0 ; j<SUBBAND_SIZE ; j++) {
+ tmp_idx = ((q->js_subband_start + i)*20)+j;
+ mlt_buffer1[20*i + j] = f1 * decode_buffer[tmp_idx];
+ mlt_buffer2[20*i + j] = f2 * decode_buffer[tmp_idx];
+ }
+ idx = (1 << q->js_vlc_bits) - 1;
+ }
+}
+
+/**
+ * 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 sub_packet_size subpacket size
+ * @param outbuffer pointer to the outbuffer
+ */
+
+
+static int decode_subpacket(COOKContext *q, uint8_t *inbuffer,
+ int sub_packet_size, int16_t *outbuffer) {
+ int i,j;
+ int value;
+ float* tmp_ptr;
+
+ /* packet dump */
+// for (i=0 ; i<sub_packet_size ; i++) {
+// av_log(NULL, AV_LOG_ERROR, "%02x", inbuffer[i]);
+// }
+// av_log(NULL, AV_LOG_ERROR, "\n");
+
+ decode_bytes(inbuffer, q->decoded_bytes_buffer, sub_packet_size);
+ init_get_bits(&q->gb, q->decoded_bytes_buffer, sub_packet_size*8);
+ decode_gain_info(&q->gb, &q->gain_current);
+
+ if(q->nb_channels==2 && q->joint_stereo==1){
+ joint_decode(q, q->decode_buf_ptr[0], q->decode_buf_ptr[2]);
+
+ /* Swap buffer pointers. */
+ tmp_ptr = q->decode_buf_ptr[1];
+ q->decode_buf_ptr[1] = q->decode_buf_ptr[0];
+ q->decode_buf_ptr[0] = tmp_ptr;
+ tmp_ptr = q->decode_buf_ptr[3];
+ q->decode_buf_ptr[3] = q->decode_buf_ptr[2];
+ q->decode_buf_ptr[2] = tmp_ptr;
+
+ /* FIXME: Rethink the gainbuffer handling, maybe a rename?
+ now/previous swap */
+ q->gain_now_ptr = &q->gain_now;
+ q->gain_previous_ptr = &q->gain_previous;
+ for (i=0 ; i<q->nb_channels ; i++){
+
+ cook_imlt(q, q->decode_buf_ptr[i*2], q->mono_mdct_output, q->mlt_tmp);
+ gain_compensate(q, q->mono_mdct_output, q->gain_now_ptr,
+ q->gain_previous_ptr, q->previous_buffer_ptr[0]);
+
+ /* Swap out the previous buffer. */
+ tmp_ptr = q->previous_buffer_ptr[0];
+ q->previous_buffer_ptr[0] = q->previous_buffer_ptr[1];
+ q->previous_buffer_ptr[1] = tmp_ptr;
+
+ /* Clip and convert the floats to 16 bits. */
+ for (j=0 ; j<q->samples_per_frame ; j++){
+ value = lrintf(q->mono_mdct_output[j]);
+ if(value < -32768) value = -32768;
+ else if(value > 32767) value = 32767;
+ outbuffer[2*j+i] = value;
+ }
+ }
+
+ memcpy(&q->gain_now, &q->gain_previous, sizeof(COOKgain));
+ memcpy(&q->gain_previous, &q->gain_current, sizeof(COOKgain));
+
+ } else if (q->nb_channels==2 && q->joint_stereo==0) {
+ /* channel 0 */
+ mono_decode(q, q->decode_buf_ptr2[0]);
+
+ tmp_ptr = q->decode_buf_ptr2[0];
+ q->decode_buf_ptr2[0] = q->decode_buf_ptr2[1];
+ q->decode_buf_ptr2[1] = tmp_ptr;
+
+ memcpy(&q->gain_channel1[0], &q->gain_current ,sizeof(COOKgain));
+ q->gain_now_ptr = &q->gain_channel1[0];
+ q->gain_previous_ptr = &q->gain_channel1[1];
+
+ cook_imlt(q, q->decode_buf_ptr2[0], q->mono_mdct_output,q->mlt_tmp);
+ gain_compensate(q, q->mono_mdct_output, q->gain_now_ptr,
+ q->gain_previous_ptr, q->mono_previous_buffer1);
+
+ memcpy(&q->gain_channel1[1], &q->gain_channel1[0],sizeof(COOKgain));
+
+
+ for (j=0 ; j<q->samples_per_frame ; j++){
+ value = lrintf(q->mono_mdct_output[j]);
+ if(value < -32768) value = -32768;
+ else if(value > 32767) value = 32767;
+ outbuffer[2*j+1] = value;
+ }
+
+ /* channel 1 */
+ //av_log(NULL,AV_LOG_ERROR,"bits = %d\n",get_bits_count(&q->gb));
+ init_get_bits(&q->gb, q->decoded_bytes_buffer, sub_packet_size*8+q->bits_per_subpacket);
+
+ q->gain_now_ptr = &q->gain_channel2[0];
+ q->gain_previous_ptr = &q->gain_channel2[1];
+
+ decode_gain_info(&q->gb, &q->gain_channel2[0]);
+ mono_decode(q, q->decode_buf_ptr[0]);
+
+ tmp_ptr = q->decode_buf_ptr[0];
+ q->decode_buf_ptr[0] = q->decode_buf_ptr[1];
+ q->decode_buf_ptr[1] = tmp_ptr;
+
+ cook_imlt(q, q->decode_buf_ptr[0], q->mono_mdct_output,q->mlt_tmp);
+ gain_compensate(q, q->mono_mdct_output, q->gain_now_ptr,
+ q->gain_previous_ptr, q->mono_previous_buffer2);
+
+ /* Swap out the previous buffer. */
+ tmp_ptr = q->previous_buffer_ptr[0];
+ q->previous_buffer_ptr[0] = q->previous_buffer_ptr[1];
+ q->previous_buffer_ptr[1] = tmp_ptr;
+
+ memcpy(&q->gain_channel2[1], &q->gain_channel2[0] ,sizeof(COOKgain));
+
+ for (j=0 ; j<q->samples_per_frame ; j++){
+ value = lrintf(q->mono_mdct_output[j]);
+ if(value < -32768) value = -32768;
+ else if(value > 32767) value = 32767;
+ outbuffer[2*j] = value;
+ }
+
+ } else {
+ mono_decode(q, q->decode_buf_ptr[0]);
+
+ /* Swap buffer pointers. */
+ tmp_ptr = q->decode_buf_ptr[1];
+ q->decode_buf_ptr[1] = q->decode_buf_ptr[0];
+ q->decode_buf_ptr[0] = tmp_ptr;
+
+ /* FIXME: Rethink the gainbuffer handling, maybe a rename?
+ now/previous swap */
+ q->gain_now_ptr = &q->gain_now;
+ q->gain_previous_ptr = &q->gain_previous;
+
+ cook_imlt(q, q->decode_buf_ptr[0], q->mono_mdct_output,q->mlt_tmp);
+ gain_compensate(q, q->mono_mdct_output, q->gain_now_ptr,
+ q->gain_previous_ptr, q->mono_previous_buffer1);
+
+ /* Clip and convert the floats to 16 bits */
+ for (j=0 ; j<q->samples_per_frame ; j++){
+ value = lrintf(q->mono_mdct_output[j]);
+ if(value < -32768) value = -32768;
+ else if(value > 32767) value = 32767;
+ outbuffer[j] = value;
+ }
+ memcpy(&q->gain_now, &q->gain_previous, sizeof(COOKgain));
+ memcpy(&q->gain_previous, &q->gain_current, sizeof(COOKgain));
+ }
+ return q->samples_per_frame * sizeof(int16_t);
+}
+
+
+/**
+ * Cook frame decoding
+ *
+ * @param avctx pointer to the AVCodecContext
+ */
+
+static int cook_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size) {
+ COOKContext *q = avctx->priv_data;
+
+ if (buf_size < avctx->block_align)
+ return buf_size;
+
+ *data_size = decode_subpacket(q, buf, avctx->block_align, data);
+
+ return avctx->block_align;
+}
+
+#ifdef COOKDEBUG
+static void dump_cook_context(COOKContext *q, COOKextradata *e)
+{
+ //int i=0;
+#define PRINT(a,b) av_log(NULL,AV_LOG_ERROR," %s = %d\n", a, b);
+ av_log(NULL,AV_LOG_ERROR,"COOKextradata\n");
+ av_log(NULL,AV_LOG_ERROR,"cookversion=%x\n",e->cookversion);
+ if (e->cookversion > MONO_COOK2) {
+ PRINT("js_subband_start",e->js_subband_start);
+ PRINT("js_vlc_bits",e->js_vlc_bits);
+ }
+ av_log(NULL,AV_LOG_ERROR,"COOKContext\n");
+ PRINT("nb_channels",q->nb_channels);
+ PRINT("bit_rate",q->bit_rate);
+ PRINT("sample_rate",q->sample_rate);
+ PRINT("samples_per_channel",q->samples_per_channel);
+ PRINT("samples_per_frame",q->samples_per_frame);
+ PRINT("subbands",q->subbands);
+ PRINT("random_state",q->random_state);
+ PRINT("mlt_size",q->mlt_size);
+ PRINT("js_subband_start",q->js_subband_start);
+ PRINT("log2_numvector_size",q->log2_numvector_size);
+ PRINT("numvector_size",q->numvector_size);
+ PRINT("total_subbands",q->total_subbands);
+}
+#endif
+
+/**
+ * Cook initialization
+ *
+ * @param avctx pointer to the AVCodecContext
+ */
+
+static int cook_decode_init(AVCodecContext *avctx)
+{
+ COOKextradata *e = avctx->extradata;
+ COOKContext *q = avctx->priv_data;
+
+ /* Take care of the codec specific extradata. */
+ if (avctx->extradata_size <= 0) {
+ av_log(NULL,AV_LOG_ERROR,"Necessary extradata missing!\n");
+ return -1;
+ } else {
+ /* 8 for mono, 16 for stereo, ? for multichannel
+ Swap to right endianness so we don't need to care later on. */
+ av_log(NULL,AV_LOG_DEBUG,"codecdata_length=%d\n",avctx->extradata_size);
+ if (avctx->extradata_size >= 8){
+ e->cookversion = be2me_32(e->cookversion);
+ e->samples_per_frame = be2me_16(e->samples_per_frame);
+ e->subbands = be2me_16(e->subbands);
+ }
+ if (avctx->extradata_size >= 16){
+ e->js_subband_start = be2me_16(e->js_subband_start);
+ e->js_vlc_bits = be2me_16(e->js_vlc_bits);
+ }
+ }
+
+ /* Take data from the AVCodecContext (RM container). */
+ q->sample_rate = avctx->sample_rate;
+ q->nb_channels = avctx->channels;
+ q->bit_rate = avctx->bit_rate;
+
+ /* Initialize state. */
+ q->random_state = 1;
+
+ /* Initialize extradata related variables. */
+ q->samples_per_channel = e->samples_per_frame / q->nb_channels;
+ q->samples_per_frame = e->samples_per_frame;
+ q->subbands = e->subbands;
+ q->bits_per_subpacket = avctx->block_align * 8;
+
+ /* Initialize default data states. */
+ q->js_subband_start = 0;
+ q->log2_numvector_size = 5;
+ q->total_subbands = q->subbands;
+
+ /* Initialize version-dependent variables */
+ av_log(NULL,AV_LOG_DEBUG,"e->cookversion=%x\n",e->cookversion);
+ switch (e->cookversion) {
+ case MONO_COOK1:
+ if (q->nb_channels != 1) {
+ av_log(NULL,AV_LOG_ERROR,"Container channels != 1, report sample!\n");
+ return -1;
+ }
+ av_log(NULL,AV_LOG_DEBUG,"MONO_COOK1\n");
+ break;
+ case MONO_COOK2:
+ if (q->nb_channels != 1) {
+ q->joint_stereo = 0;
+ q->bits_per_subpacket = q->bits_per_subpacket/2;
+ }
+ av_log(NULL,AV_LOG_DEBUG,"MONO_COOK2\n");
+ break;
+ case JOINT_STEREO:
+ if (q->nb_channels != 2) {
+ av_log(NULL,AV_LOG_ERROR,"Container channels != 2, report sample!\n");
+ return -1;
+ }
+ av_log(NULL,AV_LOG_DEBUG,"JOINT_STEREO\n");
+ if (avctx->extradata_size >= 16){
+ q->total_subbands = q->subbands + e->js_subband_start;
+ q->js_subband_start = e->js_subband_start;
+ q->joint_stereo = 1;
+ q->js_vlc_bits = e->js_vlc_bits;
+ }
+ if (q->samples_per_channel > 256) {
+ q->log2_numvector_size = 6;
+ }
+ if (q->samples_per_channel > 512) {
+ q->log2_numvector_size = 7;
+ }
+ break;
+ case MC_COOK:
+ av_log(NULL,AV_LOG_ERROR,"MC_COOK not supported!\n");
+ return -1;
+ break;
+ default:
+ av_log(NULL,AV_LOG_ERROR,"Unknown Cook version, report sample!\n");
+ return -1;
+ break;
+ }
+
+ /* Initialize variable relations */
+ q->mlt_size = q->samples_per_channel;
+ q->numvector_size = (1 << q->log2_numvector_size);
+
+ /* Generate tables */
+ init_rootpow2table(q);
+ init_pow2table(q);
+ init_gain_table(q);
+
+ if (init_cook_vlc_tables(q) != 0)
+ return -1;
+
+
+ if(avctx->block_align >= UINT_MAX/2)
+ return -1;
+
+ /* Pad the databuffer with FF_INPUT_BUFFER_PADDING_SIZE,
+ this is for the bitstreamreader. */
+ if ((q->decoded_bytes_buffer = av_mallocz((avctx->block_align+(4-avctx->block_align%4) + FF_INPUT_BUFFER_PADDING_SIZE)*sizeof(uint8_t))) == NULL)
+ return -1;
+
+ q->decode_buf_ptr[0] = q->decode_buffer_1;
+ q->decode_buf_ptr[1] = q->decode_buffer_2;
+ q->decode_buf_ptr[2] = q->decode_buffer_3;
+ q->decode_buf_ptr[3] = q->decode_buffer_4;
+
+ q->decode_buf_ptr2[0] = q->decode_buffer_3;
+ q->decode_buf_ptr2[1] = q->decode_buffer_4;
+
+ q->previous_buffer_ptr[0] = q->mono_previous_buffer1;
+ q->previous_buffer_ptr[1] = q->mono_previous_buffer2;
+
+ /* Initialize transform. */
+ if ( init_cook_mlt(q) == 0 )
+ return -1;
+
+ /* Try to catch some obviously faulty streams, othervise it might be exploitable */
+ if (q->total_subbands > 53) {
+ av_log(NULL,AV_LOG_ERROR,"total_subbands > 53, report sample!\n");
+ return -1;
+ }
+ if (q->subbands > 50) {
+ av_log(NULL,AV_LOG_ERROR,"subbands > 50, report sample!\n");
+ return -1;
+ }
+ if ((q->samples_per_channel == 256) || (q->samples_per_channel == 512) || (q->samples_per_channel == 1024)) {
+ } else {
+ av_log(NULL,AV_LOG_ERROR,"unknown amount of samples_per_channel = %d, report sample!\n",q->samples_per_channel);
+ return -1;
+ }
+
+#ifdef COOKDEBUG
+ dump_cook_context(q,e);
+#endif
+ return 0;
+}
+
+
+AVCodec cook_decoder =
+{
+ .name = "cook",
+ .type = CODEC_TYPE_AUDIO,
+ .id = CODEC_ID_COOK,
+ .priv_data_size = sizeof(COOKContext),
+ .init = cook_decode_init,
+ .close = cook_decode_close,
+ .decode = cook_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/cookdata.h b/contrib/ffmpeg/libavcodec/cookdata.h
new file mode 100644
index 000000000..395c9a7dd
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/cookdata.h
@@ -0,0 +1,559 @@
+/*
+ * 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 cookdata.h
+ * Cook AKA RealAudio G2 compatible decoderdata
+ */
+
+/* various data tables */
+
+static const int expbits_tab[8] = {
+ 52,47,43,37,29,22,16,0,
+};
+
+static const float dither_tab[8] = {
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.176777, 0.25, 0.707107,
+};
+
+static const float randsign[2] = {1.0, -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* cvh_huffcodes[7] = {
+ cvh_huffcodes0, cvh_huffcodes1, cvh_huffcodes2, cvh_huffcodes3,
+ cvh_huffcodes4, cvh_huffcodes5, cvh_huffcodes6,
+};
+
+static const uint8_t* 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* ccpl_huffcodes[5] = {
+ ccpl_huffcodes2,ccpl_huffcodes3,
+ ccpl_huffcodes4,ccpl_huffcodes5,ccpl_huffcodes6
+};
+
+static const uint8_t* 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,
+};
+
+static const float cplscale2[3] = {
+0.953020632266998,0.70710676908493,0.302905440330505,
+};
+
+static const float cplscale3[7] = {
+0.981279790401459,0.936997592449188,0.875934481620789,0.70710676908493,
+0.482430040836334,0.349335819482803,0.192587479948997,
+};
+
+static const float cplscale4[15] = {
+0.991486728191376,0.973249018192291,0.953020632266998,0.930133521556854,
+0.903453230857849,0.870746195316315,0.826180458068848,0.70710676908493,
+0.563405573368073,0.491732746362686,0.428686618804932,0.367221474647522,
+0.302905440330505,0.229752898216248,0.130207896232605,
+};
+
+static const float cplscale5[31] = {
+0.995926380157471,0.987517595291138,0.978726446628571,0.969505727291107,
+0.95979779958725,0.949531257152557,0.938616216182709,0.926936149597168,
+0.914336204528809,0.900602877140045,0.885426938533783,0.868331849575043,
+0.84851086139679,0.824381768703461,0.791833400726318,0.70710676908493,
+0.610737144947052,0.566034197807312,0.529177963733673,0.495983630418777,
+0.464778542518616,0.434642940759659,0.404955863952637,0.375219136476517,
+0.344963222742081,0.313672333955765,0.280692428350449,0.245068684220314,
+0.205169528722763,0.157508864998817,0.0901700109243393,
+};
+
+static const float cplscale6[63] = {
+0.998005926609039,0.993956744670868,0.989822506904602,0.985598564147949,
+0.981279790401459,0.976860702037811,0.972335040569305,0.967696130275726,
+0.962936460971832,0.958047747612000,0.953020632266998,0.947844684123993,
+0.942508161067963,0.936997592449188,0.931297719478607,0.925390899181366,
+0.919256627559662,0.912870943546295,0.906205296516418,0.899225592613220,
+0.891890347003937,0.884148240089417,0.875934481620789,0.867165684700012,
+0.857730865478516,0.847477376461029,0.836184680461884,0.823513329029083,
+0.808890223503113,0.791194140911102,0.767520070075989,0.707106769084930,
+0.641024887561798,0.611565053462982,0.587959706783295,0.567296981811523,
+0.548448026180267,0.530831515789032,0.514098942279816,0.498019754886627,
+0.482430040836334,0.467206478118896,0.452251672744751,0.437485188245773,
+0.422837972640991,0.408248275518417,0.393658757209778,0.379014074802399,
+0.364258885383606,0.349335819482803,0.334183186292648,0.318732559680939,
+0.302905440330505,0.286608695983887,0.269728302955627,0.252119421958923,
+0.233590632677078,0.213876649737358,0.192587479948997,0.169101938605309,
+0.142307326197624,0.109772264957428,0.0631198287010193,
+};
+
+static const float* cplscales[5] = {
+ cplscale2, cplscale3, cplscale4, cplscale5, cplscale6,
+};
diff --git a/contrib/ffmpeg/libavcodec/cscd.c b/contrib/ffmpeg/libavcodec/cscd.c
new file mode 100644
index 000000000..e4257f4c0
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/cscd.c
@@ -0,0 +1,264 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+
+#include "common.h"
+#include "avcodec.h"
+
+#ifdef CONFIG_ZLIB
+#include <zlib.h>
+#endif
+#include "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, uint8_t *src,
+ int linelen, int height) {
+ int i;
+ uint8_t *dst = f->data[0];
+ dst += (height - 1) * f->linesize[0];
+ for (i = height; i; i--) {
+ memcpy(dst, src, linelen);
+ src += linelen;
+ dst -= f->linesize[0];
+ }
+}
+
+static void add_frame_default(AVFrame *f, uint8_t *src,
+ int linelen, int height) {
+ int i, j;
+ uint8_t *dst = f->data[0];
+ dst += (height - 1) * f->linesize[0];
+ for (i = height; i; i--) {
+ for (j = linelen; j; j--)
+ *dst++ += *src++;
+ dst -= f->linesize[0] + linelen;
+ }
+}
+
+#ifndef WORDS_BIGENDIAN
+#define copy_frame_16 copy_frame_default
+#define copy_frame_32 copy_frame_default
+#define add_frame_16 add_frame_default
+#define add_frame_32 add_frame_default
+#else
+static void copy_frame_16(AVFrame *f, uint8_t *src,
+ int linelen, int height) {
+ int i, j;
+ uint8_t *dst = f->data[0];
+ dst += (height - 1) * f->linesize[0];
+ for (i = height; i; i--) {
+ for (j = linelen / 2; j; j--) {
+ dst[0] = src[1];
+ dst[1] = src[0];
+ src += 2;
+ dst += 2;
+ }
+ dst -= f->linesize[0] + linelen;
+ }
+}
+
+static void copy_frame_32(AVFrame *f, uint8_t *src,
+ int linelen, int height) {
+ int i, j;
+ uint8_t *dst = f->data[0];
+ dst += (height - 1) * f->linesize[0];
+ for (i = height; i; i--) {
+ for (j = linelen / 4; j; j--) {
+ dst[0] = src[3];
+ dst[1] = src[2];
+ dst[2] = src[1];
+ dst[3] = src[0];
+ src += 4;
+ dst += 4;
+ }
+ dst -= f->linesize[0] + linelen;
+ }
+}
+
+static void add_frame_16(AVFrame *f, uint8_t *src,
+ int linelen, int height) {
+ int i, j;
+ uint8_t *dst = f->data[0];
+ dst += (height - 1) * f->linesize[0];
+ for (i = height; i; i--) {
+ for (j = linelen / 2; j; j--) {
+ dst[0] += src[1];
+ dst[1] += src[0];
+ src += 2;
+ dst += 2;
+ }
+ dst -= f->linesize[0] + linelen;
+ }
+}
+
+static void add_frame_32(AVFrame *f, uint8_t *src,
+ int linelen, int height) {
+ int i, j;
+ uint8_t *dst = f->data[0];
+ dst += (height - 1) * f->linesize[0];
+ for (i = height; i; i--) {
+ for (j = linelen / 4; j; j--) {
+ dst[0] += src[3];
+ dst[1] += src[2];
+ dst[2] += src[1];
+ dst[3] += src[0];
+ src += 4;
+ dst += 4;
+ }
+ dst -= f->linesize[0] + linelen;
+ }
+}
+#endif
+
+static int decode_frame(AVCodecContext *avctx, void *data, int *data_size,
+ uint8_t *buf, int buf_size) {
+ CamStudioContext *c = (CamStudioContext *)avctx->priv_data;
+ AVFrame *picture = data;
+
+ if (buf_size < 2) {
+ av_log(avctx, AV_LOG_ERROR, "coded frame too small\n");
+ return -1;
+ }
+
+ if (c->pic.data[0])
+ avctx->release_buffer(avctx, &c->pic);
+ c->pic.reference = 1;
+ c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_READABLE |
+ FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
+ if (avctx->get_buffer(avctx, &c->pic) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ // decompress data
+ switch ((buf[0] >> 1) & 7) {
+ case 0: { // lzo compression
+ int outlen = c->decomp_size, inlen = buf_size - 2;
+ if (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
+#ifdef 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 -1;
+#endif
+ }
+ default:
+ av_log(avctx, AV_LOG_ERROR, "unknown compression\n");
+ return -1;
+ }
+
+ // flip upside down, add difference frame
+ if (buf[0] & 1) { // keyframe
+ c->pic.pict_type = FF_I_TYPE;
+ c->pic.key_frame = 1;
+ switch (c->bpp) {
+ case 16:
+ copy_frame_16(&c->pic, c->decomp_buf, c->linelen, c->height);
+ break;
+ case 32:
+ copy_frame_32(&c->pic, c->decomp_buf, c->linelen, c->height);
+ break;
+ default:
+ copy_frame_default(&c->pic, c->decomp_buf, c->linelen, c->height);
+ }
+ } else {
+ c->pic.pict_type = FF_P_TYPE;
+ c->pic.key_frame = 0;
+ switch (c->bpp) {
+ case 16:
+ add_frame_16(&c->pic, c->decomp_buf, c->linelen, c->height);
+ break;
+ case 32:
+ add_frame_32(&c->pic, c->decomp_buf, c->linelen, c->height);
+ break;
+ default:
+ add_frame_default(&c->pic, c->decomp_buf, c->linelen, c->height);
+ }
+ }
+
+ *picture = c->pic;
+ *data_size = sizeof(AVFrame);
+ return buf_size;
+}
+
+static int decode_init(AVCodecContext *avctx) {
+ CamStudioContext *c = (CamStudioContext *)avctx->priv_data;
+ if (avcodec_check_dimensions(avctx, avctx->height, avctx->width) < 0) {
+ return 1;
+ }
+ avctx->has_b_frames = 0;
+ switch (avctx->bits_per_sample) {
+ case 16: avctx->pix_fmt = PIX_FMT_RGB565; break;
+ case 24: avctx->pix_fmt = PIX_FMT_BGR24; break;
+ case 32: avctx->pix_fmt = PIX_FMT_RGBA32; break;
+ default:
+ av_log(avctx, AV_LOG_ERROR,
+ "CamStudio codec error: unvalid depth %i bpp\n",
+ avctx->bits_per_sample);
+ return 1;
+ }
+ c->bpp = avctx->bits_per_sample;
+ c->pic.data[0] = NULL;
+ c->linelen = avctx->width * avctx->bits_per_sample / 8;
+ c->height = avctx->height;
+ c->decomp_size = c->height * c->linelen;
+ c->decomp_buf = av_malloc(c->decomp_size + LZO_OUTPUT_PADDING);
+ if (!c->decomp_buf) {
+ av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
+ return 1;
+ }
+ return 0;
+}
+
+static int decode_end(AVCodecContext *avctx) {
+ CamStudioContext *c = (CamStudioContext *)avctx->priv_data;
+ av_freep(&c->decomp_buf);
+ if (c->pic.data[0])
+ avctx->release_buffer(avctx, &c->pic);
+ return 0;
+}
+
+AVCodec cscd_decoder = {
+ "camstudio",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_CSCD,
+ sizeof(CamStudioContext),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
+
diff --git a/contrib/ffmpeg/libavcodec/cyuv.c b/contrib/ffmpeg/libavcodec/cyuv.c
new file mode 100644
index 000000000..101f2bd85
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/cyuv.c
@@ -0,0 +1,190 @@
+/*
+ *
+ * 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
+ *
+ * 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
+ *
+ */
+
+/**
+ * @file cyuv.c
+ * Creative YUV (CYUV) Video Decoder.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+
+typedef struct CyuvDecodeContext {
+ AVCodecContext *avctx;
+ int width, height;
+ AVFrame frame;
+} CyuvDecodeContext;
+
+static 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 -1;
+ s->height = avctx->height;
+ avctx->pix_fmt = PIX_FMT_YUV411P;
+ avctx->has_b_frames = 0;
+
+ return 0;
+}
+
+static int cyuv_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ CyuvDecodeContext *s=avctx->priv_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) */
+ signed char *y_table = (signed char*)buf + 0;
+ signed char *u_table = (signed char*)buf + 16;
+ signed char *v_table = (signed char*)buf + 32;
+
+ unsigned char y_pred, u_pred, v_pred;
+ int stream_ptr;
+ unsigned char cur_byte;
+ int pixel_groups;
+
+ /* 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)) {
+ av_log(avctx, AV_LOG_ERROR, "ffmpeg: cyuv: got a buffer with %d bytes when %d were expected\n",
+ buf_size,
+ 48 + s->height * (s->width * 3 / 4));
+ return -1;
+ }
+
+ /* pixel data starts 48 bytes in, after 3x16-byte tables */
+ stream_ptr = 48;
+
+ if(s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ s->frame.buffer_hints = FF_BUFFER_HINTS_VALID;
+ s->frame.reference = 0;
+ if(avctx->get_buffer(avctx, &s->frame) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ y_plane = s->frame.data[0];
+ u_plane = s->frame.data[1];
+ v_plane = s->frame.data[2];
+
+ /* iterate through each line in the height */
+ for (y_ptr = 0, u_ptr = 0, v_ptr = 0;
+ y_ptr < (s->height * s->frame.linesize[0]);
+ y_ptr += s->frame.linesize[0] - s->width,
+ u_ptr += s->frame.linesize[1] - s->width / 4,
+ v_ptr += s->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;
+
+ }
+ }
+
+ *data_size=sizeof(AVFrame);
+ *(AVFrame*)data= s->frame;
+
+ return buf_size;
+}
+
+static int cyuv_decode_end(AVCodecContext *avctx)
+{
+/* CyuvDecodeContext *s = avctx->priv_data;*/
+
+ return 0;
+}
+
+AVCodec cyuv_decoder = {
+ "cyuv",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_CYUV,
+ sizeof(CyuvDecodeContext),
+ cyuv_decode_init,
+ NULL,
+ cyuv_decode_end,
+ cyuv_decode_frame,
+ CODEC_CAP_DR1,
+ NULL
+};
+
diff --git a/contrib/ffmpeg/libavcodec/dct-test.c b/contrib/ffmpeg/libavcodec/dct-test.c
new file mode 100644
index 000000000..2c16f47e4
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/dct-test.c
@@ -0,0 +1,535 @@
+/*
+ * (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 dct-test.c
+ * DCT test. (c) 2001 Fabrice Bellard.
+ * Started from sample code by Juan J. Sierralta P.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "dsputil.h"
+
+#include "simple_idct.h"
+#include "faandct.h"
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#undef printf
+
+void *fast_memcpy(void *a, const void *b, size_t c){return memcpy(a,b,c);};
+
+/* reference fdct/idct */
+extern void fdct(DCTELEM *block);
+extern void idct(DCTELEM *block);
+extern void ff_idct_xvid_mmx(DCTELEM *block);
+extern void ff_idct_xvid_mmx2(DCTELEM *block);
+extern void init_fdct();
+
+extern void j_rev_dct(DCTELEM *data);
+extern void ff_mmx_idct(DCTELEM *data);
+extern void ff_mmxext_idct(DCTELEM *data);
+
+extern void odivx_idct_c (short *block);
+
+#define AANSCALE_BITS 12
+static const unsigned short 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
+};
+
+uint8_t cropTbl[256 + 2 * MAX_NEG_CROP];
+
+int64_t gettime(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
+}
+
+#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,
+};
+
+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);
+// idct_simple_mmx_perm[i] = simple_block_permute_op(i);
+ }
+}
+
+static DCTELEM block[64] __attribute__ ((aligned (8)));
+static DCTELEM block1[64] __attribute__ ((aligned (8)));
+static DCTELEM block_org[64] __attribute__ ((aligned (8)));
+
+void dct_error(const char *name, int is_idct,
+ void (*fdct_func)(DCTELEM *block),
+ void (*fdct_ref)(DCTELEM *block), int test)
+{
+ int it, i, scale;
+ int err_inf, v;
+ int64_t err2, ti, ti1, it1;
+ int64_t sysErr[64], sysErrMax=0;
+ int maxout=0;
+ int blockSumErrMax=0, blockSumErr;
+
+ srandom(0);
+
+ err_inf = 0;
+ err2 = 0;
+ for(i=0; i<64; i++) sysErr[i]=0;
+ for(it=0;it<NB_ITS;it++) {
+ for(i=0;i<64;i++)
+ block1[i] = 0;
+ switch(test){
+ case 0:
+ for(i=0;i<64;i++)
+ block1[i] = (random() % 512) -256;
+ if (is_idct){
+ fdct(block1);
+
+ for(i=0;i<64;i++)
+ block1[i]>>=3;
+ }
+ break;
+ case 1:{
+ int num= (random()%10)+1;
+ for(i=0;i<num;i++)
+ block1[random()%64] = (random() % 512) -256;
+ }break;
+ case 2:
+ block1[0]= (random()%4096)-2048;
+ block1[63]= (block1[0]&1)^1;
+ break;
+ }
+
+#if 0 // simulate mismatch control
+{ int sum=0;
+ for(i=0;i<64;i++)
+ sum+=block1[i];
+
+ if((sum&1)==0) block1[63]^=1;
+}
+#endif
+
+ for(i=0; i<64; i++)
+ block_org[i]= block1[i];
+
+ if (fdct_func == ff_mmx_idct ||
+ fdct_func == j_rev_dct || fdct_func == ff_mmxext_idct) {
+ for(i=0;i<64;i++)
+ block[idct_mmx_perm[i]] = block1[i];
+ } else if(fdct_func == ff_simple_idct_mmx ) {
+ for(i=0;i<64;i++)
+ block[idct_simple_mmx_perm[i]] = block1[i];
+
+ } else {
+ for(i=0; i<64; i++)
+ block[i]= block1[i];
+ }
+#if 0 // simulate mismatch control for tested IDCT but not the ref
+{ int sum=0;
+ for(i=0;i<64;i++)
+ sum+=block[i];
+
+ if((sum&1)==0) block[63]^=1;
+}
+#endif
+
+ fdct_func(block);
+ emms(); /* for ff_mmx_idct */
+
+ if (fdct_func == fdct_ifast
+#ifndef FAAN_POSTSCALE
+ || fdct_func == ff_faandct
+#endif
+ ) {
+ for(i=0; i<64; i++) {
+ scale = 8*(1 << (AANSCALE_BITS + 11)) / aanscales[i];
+ block[i] = (block[i] * scale /*+ (1<<(AANSCALE_BITS-1))*/) >> AANSCALE_BITS;
+ }
+ }
+
+ fdct_ref(block1);
+
+ blockSumErr=0;
+ for(i=0;i<64;i++) {
+ v = abs(block[i] - block1[i]);
+ 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;
+#if 0 // print different matrix pairs
+ if(blockSumErr){
+ printf("\n");
+ for(i=0; i<64; i++){
+ if((i&7)==0) printf("\n");
+ printf("%4d ", block_org[i]);
+ }
+ for(i=0; i<64; i++){
+ if((i&7)==0) printf("\n");
+ printf("%4d ", block[i] - block1[i]);
+ }
+ }
+#endif
+ }
+ for(i=0; i<64; i++) sysErrMax= MAX(sysErrMax, FFABS(sysErr[i]));
+
+#if 1 // dump systematic errors
+ for(i=0; i<64; i++){
+ if(i%8==0) printf("\n");
+ printf("%5d ", (int)sysErr[i]);
+ }
+ printf("\n");
+#endif
+
+ printf("%s %s: err_inf=%d err2=%0.8f syserr=%0.8f maxout=%d blockSumErr=%d\n",
+ is_idct ? "IDCT" : "DCT",
+ name, err_inf, (double)err2 / NB_ITS / 64.0, (double)sysErrMax / NB_ITS, maxout, blockSumErrMax);
+#if 1 //Speed test
+ /* speed test */
+ for(i=0;i<64;i++)
+ block1[i] = 0;
+ switch(test){
+ case 0:
+ for(i=0;i<64;i++)
+ block1[i] = (random() % 512) -256;
+ if (is_idct){
+ fdct(block1);
+
+ for(i=0;i<64;i++)
+ block1[i]>>=3;
+ }
+ break;
+ case 1:{
+ case 2:
+ block1[0] = (random() % 512) -256;
+ block1[1] = (random() % 512) -256;
+ block1[2] = (random() % 512) -256;
+ block1[3] = (random() % 512) -256;
+ }break;
+ }
+
+ if (fdct_func == ff_mmx_idct ||
+ fdct_func == j_rev_dct || fdct_func == ff_mmxext_idct) {
+ for(i=0;i<64;i++)
+ block[idct_mmx_perm[i]] = block1[i];
+ } else if(fdct_func == ff_simple_idct_mmx ) {
+ for(i=0;i<64;i++)
+ block[idct_simple_mmx_perm[i]] = block1[i];
+ } else {
+ for(i=0; i<64; i++)
+ block[i]= block1[i];
+ }
+
+ ti = gettime();
+ it1 = 0;
+ do {
+ for(it=0;it<NB_ITS_SPEED;it++) {
+ for(i=0; i<64; i++)
+ block[i]= block1[i];
+// memcpy(block, block1, sizeof(DCTELEM) * 64);
+// dont memcpy especially not fastmemcpy because it does movntq !!!
+ fdct_func(block);
+ }
+ it1 += NB_ITS_SPEED;
+ ti1 = gettime() - ti;
+ } while (ti1 < 1000000);
+ emms();
+
+ printf("%s %s: %0.1f kdct/s\n",
+ is_idct ? "IDCT" : "DCT",
+ name, (double)it1 * 1000.0 / (double)ti1);
+#endif
+}
+
+static uint8_t img_dest[64] __attribute__ ((aligned (8)));
+static uint8_t img_dest1[64] __attribute__ ((aligned (8)));
+
+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);
+ }
+ }
+}
+
+void idct248_error(const char *name,
+ void (*idct248_put)(uint8_t *dest, int line_size, int16_t *block))
+{
+ int it, i, it1, ti, ti1, err_max, v;
+
+ srandom(0);
+
+ /* 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] = (random() % 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);
+
+ ti = gettime();
+ it1 = 0;
+ do {
+ for(it=0;it<NB_ITS_SPEED;it++) {
+ for(i=0; i<64; i++)
+ block[i]= block1[i];
+// memcpy(block, block1, sizeof(DCTELEM) * 64);
+// dont memcpy especially not fastmemcpy because it does movntq !!!
+ idct248_put(img_dest, 8, block);
+ }
+ it1 += NB_ITS_SPEED;
+ ti1 = gettime() - ti;
+ } while (ti1 < 1000000);
+ emms();
+
+ printf("%s %s: %0.1f kdct/s\n",
+ 1 ? "IDCT248" : "DCT248",
+ name, (double)it1 * 1000.0 / (double)ti1);
+}
+
+void help(void)
+{
+ printf("dct-test [-i] [<test-number>]\n"
+ "test-number 0 -> test with random matrixes\n"
+ " 1 -> test with random sparse matrixes\n"
+ " 2 -> do 3. test from mpeg4 std\n"
+ "-i test IDCT implementations\n"
+ "-4 test IDCT248 implementations\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ int test_idct = 0, test_248_dct = 0;
+ int c,i;
+ int test=1;
+
+ init_fdct();
+ idct_mmx_init();
+
+ for(i=0;i<256;i++) cropTbl[i + MAX_NEG_CROP] = i;
+ for(i=0;i<MAX_NEG_CROP;i++) {
+ cropTbl[i] = 0;
+ cropTbl[i + MAX_NEG_CROP + 256] = 255;
+ }
+
+ for(;;) {
+ c = getopt(argc, argv, "ih4");
+ if (c == -1)
+ break;
+ switch(c) {
+ case 'i':
+ test_idct = 1;
+ break;
+ case '4':
+ test_248_dct = 1;
+ break;
+ default :
+ case 'h':
+ help();
+ break;
+ }
+ }
+
+ if(optind <argc) test= atoi(argv[optind]);
+
+ printf("ffmpeg DCT/IDCT test\n");
+
+ if (test_248_dct) {
+ idct248_error("SIMPLE-C", simple_idct248_put);
+ } else {
+ if (!test_idct) {
+ dct_error("REF-DBL", 0, fdct, fdct, test); /* only to verify code ! */
+ dct_error("IJG-AAN-INT", 0, fdct_ifast, fdct, test);
+ dct_error("IJG-LLM-INT", 0, ff_jpeg_fdct_islow, fdct, test);
+ dct_error("MMX", 0, ff_fdct_mmx, fdct, test);
+ dct_error("MMX2", 0, ff_fdct_mmx2, fdct, test);
+ dct_error("FAAN", 0, ff_faandct, fdct, test);
+ } else {
+ dct_error("REF-DBL", 1, idct, idct, test);
+ dct_error("INT", 1, j_rev_dct, idct, test);
+ dct_error("LIBMPEG2-MMX", 1, ff_mmx_idct, idct, test);
+ dct_error("LIBMPEG2-MMXEXT", 1, ff_mmxext_idct, idct, test);
+ dct_error("SIMPLE-C", 1, simple_idct, idct, test);
+ dct_error("SIMPLE-MMX", 1, ff_simple_idct_mmx, idct, test);
+ dct_error("XVID-MMX", 1, ff_idct_xvid_mmx, idct, test);
+ dct_error("XVID-MMX2", 1, ff_idct_xvid_mmx2, idct, test);
+ // dct_error("ODIVX-C", 1, odivx_idct_c, idct);
+ //printf(" test against odivx idct\n");
+ // dct_error("REF", 1, idct, odivx_idct_c);
+ // dct_error("INT", 1, j_rev_dct, odivx_idct_c);
+ // dct_error("MMX", 1, ff_mmx_idct, odivx_idct_c);
+ // dct_error("MMXEXT", 1, ff_mmxext_idct, odivx_idct_c);
+ // dct_error("SIMPLE-C", 1, simple_idct, odivx_idct_c);
+ // dct_error("SIMPLE-MMX", 1, ff_simple_idct_mmx, odivx_idct_c);
+ // dct_error("ODIVX-C", 1, odivx_idct_c, odivx_idct_c);
+ }
+ }
+ return 0;
+}
diff --git a/contrib/ffmpeg/libavcodec/dpcm.c b/contrib/ffmpeg/libavcodec/dpcm.c
new file mode 100644
index 000000000..99c0cac64
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/dpcm.c
@@ -0,0 +1,335 @@
+/*
+ * 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: dpcm.c
+ * 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 "avcodec.h"
+
+typedef struct DPCMContext {
+ int channels;
+ short roq_square_array[256];
+ long sample[2];//for SOL_DPCM
+ const int *sol_table;//for SOL_DPCM
+} DPCMContext;
+
+#define SATURATE_S16(x) if (x < -32768) x = -32768; \
+ else if (x > 32767) x = 32767;
+#define SE_16BIT(x) if (x & 0x8000) x -= 0x10000;
+
+static int 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 int sol_table_old[16] =
+ { 0x0, 0x1, 0x2 , 0x3, 0x6, 0xA, 0xF, 0x15,
+ -0x15, -0xF, -0xA, -0x6, -0x3, -0x2, -0x1, 0x0};
+
+static const int sol_table_new[16] =
+ { 0x0, 0x1, 0x2, 0x3, 0x6, 0xA, 0xF, 0x15,
+ 0x0, -0x1, -0x2, -0x3, -0x6, -0xA, -0xF, -0x15};
+
+static const int 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 int dpcm_decode_init(AVCodecContext *avctx)
+{
+ DPCMContext *s = avctx->priv_data;
+ int i;
+ short square;
+
+ s->channels = avctx->channels;
+ s->sample[0] = s->sample[1] = 0;
+
+ switch(avctx->codec->id) {
+
+ case CODEC_ID_ROQ_DPCM:
+ /* initialize square table */
+ for (i = 0; i < 128; i++) {
+ square = i * i;
+ s->roq_square_array[i] = square;
+ s->roq_square_array[i + 128] = -square;
+ }
+ break;
+
+
+ case 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:
+ s->sol_table=sol_table_16;
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "Unknown SOL subcodec\n");
+ return -1;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int dpcm_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ DPCMContext *s = avctx->priv_data;
+ int in, out = 0;
+ int predictor[2];
+ int channel_number = 0;
+ short *output_samples = data;
+ int shift[2];
+ unsigned char byte;
+ short diff;
+
+ if (!buf_size)
+ return 0;
+
+ switch(avctx->codec->id) {
+
+ case CODEC_ID_ROQ_DPCM:
+ if (s->channels == 1)
+ predictor[0] = LE_16(&buf[6]);
+ else {
+ predictor[0] = buf[7] << 8;
+ predictor[1] = buf[6] << 8;
+ }
+ SE_16BIT(predictor[0]);
+ SE_16BIT(predictor[1]);
+
+ /* decode the samples */
+ for (in = 8, out = 0; in < buf_size; in++, out++) {
+ predictor[channel_number] += s->roq_square_array[buf[in]];
+ SATURATE_S16(predictor[channel_number]);
+ output_samples[out] = predictor[channel_number];
+
+ /* toggle channel */
+ channel_number ^= s->channels - 1;
+ }
+ break;
+
+ case CODEC_ID_INTERPLAY_DPCM:
+ in = 6; /* skip over the stream mask and stream length */
+ predictor[0] = LE_16(&buf[in]);
+ in += 2;
+ SE_16BIT(predictor[0])
+ output_samples[out++] = predictor[0];
+ if (s->channels == 2) {
+ predictor[1] = LE_16(&buf[in]);
+ in += 2;
+ SE_16BIT(predictor[1])
+ output_samples[out++] = predictor[1];
+ }
+
+ while (in < buf_size) {
+ predictor[channel_number] += interplay_delta_table[buf[in++]];
+ SATURATE_S16(predictor[channel_number]);
+ output_samples[out++] = predictor[channel_number];
+
+ /* toggle channel */
+ channel_number ^= s->channels - 1;
+ }
+
+ break;
+
+ case CODEC_ID_XAN_DPCM:
+ in = 0;
+ shift[0] = shift[1] = 4;
+ predictor[0] = LE_16(&buf[in]);
+ in += 2;
+ SE_16BIT(predictor[0]);
+ if (s->channels == 2) {
+ predictor[1] = LE_16(&buf[in]);
+ in += 2;
+ SE_16BIT(predictor[1]);
+ }
+
+ while (in < buf_size) {
+ byte = buf[in++];
+ diff = (byte & 0xFC) << 8;
+ if ((byte & 0x03) == 3)
+ shift[channel_number]++;
+ else
+ shift[channel_number] -= (2 * (byte & 3));
+ /* saturate the shifter to a lower limit of 0 */
+ if (shift[channel_number] < 0)
+ shift[channel_number] = 0;
+
+ diff >>= shift[channel_number];
+ predictor[channel_number] += diff;
+
+ SATURATE_S16(predictor[channel_number]);
+ output_samples[out++] = predictor[channel_number];
+
+ /* toggle channel */
+ channel_number ^= s->channels - 1;
+ }
+ break;
+ case CODEC_ID_SOL_DPCM:
+ in = 0;
+ if (avctx->codec_tag != 3) {
+ while (in < buf_size) {
+ int n1, n2;
+ n1 = (buf[in] >> 4) & 0xF;
+ n2 = buf[in++] & 0xF;
+ s->sample[0] += s->sol_table[n1];
+ if (s->sample[0] < 0) s->sample[0] = 0;
+ if (s->sample[0] > 255) s->sample[0] = 255;
+ output_samples[out++] = (s->sample[0] - 128) << 8;
+ s->sample[s->channels - 1] += s->sol_table[n2];
+ if (s->sample[s->channels - 1] < 0) s->sample[s->channels - 1] = 0;
+ if (s->sample[s->channels - 1] > 255) s->sample[s->channels - 1] = 255;
+ output_samples[out++] = (s->sample[s->channels - 1] - 128) << 8;
+ }
+ } else {
+ while (in < buf_size) {
+ int n;
+ n = buf[in++];
+ if (n & 0x80) s->sample[channel_number] -= s->sol_table[n & 0x7F];
+ else s->sample[channel_number] += s->sol_table[n & 0x7F];
+ SATURATE_S16(s->sample[channel_number]);
+ output_samples[out++] = s->sample[channel_number];
+ /* toggle channel */
+ channel_number ^= s->channels - 1;
+ }
+ }
+ break;
+ }
+
+ *data_size = out * sizeof(short);
+ return buf_size;
+}
+
+AVCodec roq_dpcm_decoder = {
+ "roq_dpcm",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_ROQ_DPCM,
+ sizeof(DPCMContext),
+ dpcm_decode_init,
+ NULL,
+ NULL,
+ dpcm_decode_frame,
+};
+
+AVCodec interplay_dpcm_decoder = {
+ "interplay_dpcm",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_INTERPLAY_DPCM,
+ sizeof(DPCMContext),
+ dpcm_decode_init,
+ NULL,
+ NULL,
+ dpcm_decode_frame,
+};
+
+AVCodec xan_dpcm_decoder = {
+ "xan_dpcm",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_XAN_DPCM,
+ sizeof(DPCMContext),
+ dpcm_decode_init,
+ NULL,
+ NULL,
+ dpcm_decode_frame,
+};
+
+AVCodec sol_dpcm_decoder = {
+ "sol_dpcm",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_SOL_DPCM,
+ sizeof(DPCMContext),
+ dpcm_decode_init,
+ NULL,
+ NULL,
+ dpcm_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/dsicinav.c b/contrib/ffmpeg/libavcodec/dsicinav.c
new file mode 100644
index 000000000..ded53c45a
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/dsicinav.c
@@ -0,0 +1,362 @@
+/*
+ * 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 dsicinav.c
+ * Delphine Software International CIN audio/video decoders
+ */
+
+#include "avcodec.h"
+#include "common.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 {
+ AVCodecContext *avctx;
+ 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 int cinvideo_decode_init(AVCodecContext *avctx)
+{
+ CinVideoContext *cin = (CinVideoContext *)avctx->priv_data;
+ unsigned int i;
+
+ cin->avctx = avctx;
+ avctx->pix_fmt = PIX_FMT_PAL8;
+ avctx->has_b_frames = 0;
+
+ cin->frame.data[0] = NULL;
+
+ cin->bitmap_size = avctx->width * avctx->height;
+ for (i = 0; i < 3; ++i) {
+ cin->bitmap_table[i] = av_mallocz(cin->bitmap_size);
+ if (!cin->bitmap_table[i])
+ av_log(avctx, AV_LOG_ERROR, "Can't allocate bitmap buffers.\n");
+ }
+
+ 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; src_size -= 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 void 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;
+ 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 = LE_16(src); src += 2;
+ offset = cmd >> 4;
+ 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;
+ }
+ }
+ }
+ }
+}
+
+static void 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 < 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;
+ memcpy(dst, src, FFMIN(len, dst_end - dst));
+ src += len;
+ }
+ dst += len;
+ }
+}
+
+static int cinvideo_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ CinVideoContext *cin = (CinVideoContext *)avctx->priv_data;
+ int i, y, palette_type, palette_colors_count, bitmap_frame_type, bitmap_frame_size;
+
+ cin->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
+ if (avctx->reget_buffer(avctx, &cin->frame)) {
+ av_log(cin->avctx, AV_LOG_ERROR, "delphinecinvideo: reget_buffer() failed to allocate a frame\n");
+ return -1;
+ }
+
+ palette_type = buf[0];
+ palette_colors_count = buf[1] | (buf[2] << 8);
+ bitmap_frame_type = buf[3];
+ buf += 4;
+
+ bitmap_frame_size = buf_size - 4;
+
+ /* handle palette */
+ if (palette_type == 0) {
+ for (i = 0; i < palette_colors_count; ++i) {
+ cin->palette[i] = (buf[2] << 16) | (buf[1] << 8) | buf[0];
+ buf += 3;
+ bitmap_frame_size -= 3;
+ }
+ } else {
+ for (i = 0; i < palette_colors_count; ++i) {
+ cin->palette[buf[0]] = (buf[3] << 16) | (buf[2] << 8) | buf[1];
+ buf += 4;
+ bitmap_frame_size -= 4;
+ }
+ }
+ memcpy(cin->frame.data[1], cin->palette, sizeof(cin->palette));
+ cin->frame.palette_has_changed = 1;
+
+ /* 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:
+ 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:
+ cin_decode_lzss(buf, bitmap_frame_size,
+ cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size);
+ break;
+ case 39:
+ cin_decode_lzss(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;
+ }
+
+ 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]);
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame *)data = cin->frame;
+
+ return buf_size;
+}
+
+static int cinvideo_decode_end(AVCodecContext *avctx)
+{
+ CinVideoContext *cin = (CinVideoContext *)avctx->priv_data;
+ int i;
+
+ if (cin->frame.data[0])
+ avctx->release_buffer(avctx, &cin->frame);
+
+ for (i = 0; i < 3; ++i)
+ av_free(cin->bitmap_table[i]);
+
+ return 0;
+}
+
+static int cinaudio_decode_init(AVCodecContext *avctx)
+{
+ CinAudioContext *cin = (CinAudioContext *)avctx->priv_data;
+
+ cin->avctx = avctx;
+ cin->initial_decode_frame = 1;
+ cin->delta = 0;
+
+ return 0;
+}
+
+static int cinaudio_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ CinAudioContext *cin = (CinAudioContext *)avctx->priv_data;
+ uint8_t *src = buf;
+ int16_t *samples = (int16_t *)data;
+
+ if (cin->initial_decode_frame) {
+ cin->initial_decode_frame = 0;
+ cin->delta = (int16_t)LE_16(src); src += 2;
+ *samples++ = cin->delta;
+ buf_size -= 2;
+ }
+ while (buf_size > 0) {
+ cin->delta += cinaudio_delta16_table[*src++];
+ cin->delta = clip(cin->delta, -32768, 32767);
+ *samples++ = cin->delta;
+ --buf_size;
+ }
+
+ *data_size = (uint8_t *)samples - (uint8_t *)data;
+
+ return src - buf;
+}
+
+
+AVCodec dsicinvideo_decoder = {
+ "dsicinvideo",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_DSICINVIDEO,
+ sizeof(CinVideoContext),
+ cinvideo_decode_init,
+ NULL,
+ cinvideo_decode_end,
+ cinvideo_decode_frame,
+ CODEC_CAP_DR1,
+};
+
+AVCodec dsicinaudio_decoder = {
+ "dsicinaudio",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_DSICINAUDIO,
+ sizeof(CinAudioContext),
+ cinaudio_decode_init,
+ NULL,
+ NULL,
+ cinaudio_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/dsputil.c b/contrib/ffmpeg/libavcodec/dsputil.c
new file mode 100644
index 000000000..51eddbc60
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/dsputil.c
@@ -0,0 +1,4156 @@
+/*
+ * DSP utils
+ * Copyright (c) 2000, 2001 Fabrice Bellard.
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * gmc & q-pel & 32/64 bit based MC by Michael Niedermayer <michaelni@gmx.at>
+ */
+
+/**
+ * @file dsputil.c
+ * DSP utils
+ */
+
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+#include "simple_idct.h"
+#include "faandct.h"
+#include "snow.h"
+
+/* snow.c */
+void ff_spatial_dwt(int *buffer, int width, int height, int stride, int type, int decomposition_count);
+
+/* vorbis.c */
+void vorbis_inverse_coupling(float *mag, float *ang, int blocksize);
+
+uint8_t ff_cropTbl[256 + 2 * MAX_NEG_CROP] = {0, };
+uint32_t ff_squareTbl[512] = {0, };
+
+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
+};
+
+/* 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_8(uint16_t, inv_zigzag_direct16[64]) = {0, };
+
+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,
+};
+
+/* a*inverse[b]>>32 == a/b for all 0<=a<=65536 && 2<=b<=255 */
+const uint32_t ff_inverse[256]={
+ 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,
+};
+
+/* 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 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 LONG_MAX > 2147483647
+ 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, uint32_t *src, int w){
+ int i;
+
+ for(i=0; i+8<=w; i+=8){
+ dst[i+0]= bswap_32(src[i+0]);
+ dst[i+1]= bswap_32(src[i+1]);
+ dst[i+2]= bswap_32(src[i+2]);
+ dst[i+3]= bswap_32(src[i+3]);
+ dst[i+4]= bswap_32(src[i+4]);
+ dst[i+5]= bswap_32(src[i+5]);
+ dst[i+6]= bswap_32(src[i+6]);
+ dst[i+7]= bswap_32(src[i+7]);
+ }
+ for(;i<w; i++){
+ dst[i+0]= bswap_32(src[i+0]);
+ }
+}
+
+static int sse4_c(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h)
+{
+ int s, i;
+ uint32_t *sq = ff_squareTbl + 256;
+
+ s = 0;
+ for (i = 0; i < h; i++) {
+ s += sq[pix1[0] - pix2[0]];
+ s += sq[pix1[1] - pix2[1]];
+ s += sq[pix1[2] - pix2[2]];
+ s += sq[pix1[3] - pix2[3]];
+ pix1 += line_size;
+ pix2 += line_size;
+ }
+ return s;
+}
+
+static int sse8_c(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h)
+{
+ int s, i;
+ uint32_t *sq = ff_squareTbl + 256;
+
+ s = 0;
+ for (i = 0; i < h; i++) {
+ s += sq[pix1[0] - pix2[0]];
+ s += sq[pix1[1] - pix2[1]];
+ s += sq[pix1[2] - pix2[2]];
+ s += sq[pix1[3] - pix2[3]];
+ s += sq[pix1[4] - pix2[4]];
+ s += sq[pix1[5] - pix2[5]];
+ s += sq[pix1[6] - pix2[6]];
+ s += sq[pix1[7] - pix2[7]];
+ pix1 += line_size;
+ pix2 += line_size;
+ }
+ return s;
+}
+
+static int sse16_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+{
+ int s, i;
+ uint32_t *sq = ff_squareTbl + 256;
+
+ s = 0;
+ for (i = 0; i < h; i++) {
+ s += sq[pix1[ 0] - pix2[ 0]];
+ s += sq[pix1[ 1] - pix2[ 1]];
+ s += sq[pix1[ 2] - pix2[ 2]];
+ s += sq[pix1[ 3] - pix2[ 3]];
+ s += sq[pix1[ 4] - pix2[ 4]];
+ s += sq[pix1[ 5] - pix2[ 5]];
+ s += sq[pix1[ 6] - pix2[ 6]];
+ s += sq[pix1[ 7] - pix2[ 7]];
+ s += sq[pix1[ 8] - pix2[ 8]];
+ s += sq[pix1[ 9] - pix2[ 9]];
+ s += sq[pix1[10] - pix2[10]];
+ s += sq[pix1[11] - pix2[11]];
+ s += sq[pix1[12] - pix2[12]];
+ s += sq[pix1[13] - pix2[13]];
+ s += sq[pix1[14] - pix2[14]];
+ s += sq[pix1[15] - pix2[15]];
+
+ pix1 += line_size;
+ pix2 += line_size;
+ }
+ return s;
+}
+
+
+#ifdef CONFIG_SNOW_ENCODER //dwt is in snow.c
+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];
+ 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, w, h, 32, type, dec_count);
+
+ s=0;
+ assert(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);
+ }
+ }
+ }
+ }
+ assert(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 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 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);
+}
+#endif
+
+static void get_pixels_c(DCTELEM *restrict block, const uint8_t *pixels, int line_size)
+{
+ int i;
+
+ /* read the pixels */
+ for(i=0;i<8;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;
+ }
+}
+
+static void diff_pixels_c(DCTELEM *restrict block, const uint8_t *s1,
+ const uint8_t *s2, int stride){
+ int i;
+
+ /* read the pixels */
+ for(i=0;i<8;i++) {
+ block[0] = s1[0] - s2[0];
+ block[1] = s1[1] - s2[1];
+ block[2] = s1[2] - s2[2];
+ block[3] = s1[3] - s2[3];
+ block[4] = s1[4] - s2[4];
+ block[5] = s1[5] - s2[5];
+ block[6] = s1[6] - s2[6];
+ block[7] = s1[7] - s2[7];
+ s1 += stride;
+ s2 += stride;
+ block += 8;
+ }
+}
+
+
+static void put_pixels_clamped_c(const DCTELEM *block, uint8_t *restrict pixels,
+ int line_size)
+{
+ int i;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ /* read the pixels */
+ for(i=0;i<8;i++) {
+ pixels[0] = cm[block[0]];
+ pixels[1] = cm[block[1]];
+ pixels[2] = cm[block[2]];
+ pixels[3] = cm[block[3]];
+ pixels[4] = cm[block[4]];
+ pixels[5] = cm[block[5]];
+ pixels[6] = cm[block[6]];
+ pixels[7] = cm[block[7]];
+
+ pixels += line_size;
+ block += 8;
+ }
+}
+
+static void put_pixels_clamped4_c(const DCTELEM *block, uint8_t *restrict pixels,
+ int line_size)
+{
+ int i;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ /* read the pixels */
+ for(i=0;i<4;i++) {
+ pixels[0] = cm[block[0]];
+ pixels[1] = cm[block[1]];
+ pixels[2] = cm[block[2]];
+ pixels[3] = cm[block[3]];
+
+ pixels += line_size;
+ block += 8;
+ }
+}
+
+static void put_pixels_clamped2_c(const DCTELEM *block, uint8_t *restrict pixels,
+ int line_size)
+{
+ int i;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ /* read the pixels */
+ for(i=0;i<2;i++) {
+ pixels[0] = cm[block[0]];
+ pixels[1] = cm[block[1]];
+
+ pixels += line_size;
+ block += 8;
+ }
+}
+
+static void put_signed_pixels_clamped_c(const DCTELEM *block,
+ uint8_t *restrict pixels,
+ int line_size)
+{
+ int i, j;
+
+ for (i = 0; i < 8; i++) {
+ for (j = 0; j < 8; j++) {
+ if (*block < -128)
+ *pixels = 0;
+ else if (*block > 127)
+ *pixels = 255;
+ else
+ *pixels = (uint8_t)(*block + 128);
+ block++;
+ pixels++;
+ }
+ pixels += (line_size - 8);
+ }
+}
+
+static void add_pixels_clamped_c(const DCTELEM *block, uint8_t *restrict pixels,
+ int line_size)
+{
+ int i;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ /* read the pixels */
+ for(i=0;i<8;i++) {
+ pixels[0] = cm[pixels[0] + block[0]];
+ pixels[1] = cm[pixels[1] + block[1]];
+ pixels[2] = cm[pixels[2] + block[2]];
+ pixels[3] = cm[pixels[3] + block[3]];
+ pixels[4] = cm[pixels[4] + block[4]];
+ pixels[5] = cm[pixels[5] + block[5]];
+ pixels[6] = cm[pixels[6] + block[6]];
+ pixels[7] = cm[pixels[7] + block[7]];
+ pixels += line_size;
+ block += 8;
+ }
+}
+
+static void add_pixels_clamped4_c(const DCTELEM *block, uint8_t *restrict pixels,
+ int line_size)
+{
+ int i;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ /* read the pixels */
+ for(i=0;i<4;i++) {
+ pixels[0] = cm[pixels[0] + block[0]];
+ pixels[1] = cm[pixels[1] + block[1]];
+ pixels[2] = cm[pixels[2] + block[2]];
+ pixels[3] = cm[pixels[3] + block[3]];
+ pixels += line_size;
+ block += 8;
+ }
+}
+
+static void add_pixels_clamped2_c(const DCTELEM *block, uint8_t *restrict pixels,
+ int line_size)
+{
+ int i;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ /* read the pixels */
+ for(i=0;i<2;i++) {
+ pixels[0] = cm[pixels[0] + block[0]];
+ pixels[1] = cm[pixels[1] + block[1]];
+ pixels += line_size;
+ block += 8;
+ }
+}
+
+static void add_pixels8_c(uint8_t *restrict pixels, DCTELEM *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_pixels4_c(uint8_t *restrict pixels, DCTELEM *block, int line_size)
+{
+ int i;
+ for(i=0;i<4;i++) {
+ pixels[0] += block[0];
+ pixels[1] += block[1];
+ pixels[2] += block[2];
+ pixels[3] += block[3];
+ pixels += line_size;
+ block += 4;
+ }
+}
+
+#if 0
+
+#define PIXOP2(OPNAME, OP) \
+static void OPNAME ## _pixels(uint8_t *block, const uint8_t *pixels, int line_size, int h)\
+{\
+ int i;\
+ for(i=0; i<h; i++){\
+ OP(*((uint64_t*)block), LD64(pixels));\
+ pixels+=line_size;\
+ block +=line_size;\
+ }\
+}\
+\
+static void OPNAME ## _no_rnd_pixels_x2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h)\
+{\
+ int i;\
+ for(i=0; i<h; i++){\
+ const uint64_t a= LD64(pixels );\
+ const uint64_t b= LD64(pixels+1);\
+ OP(*((uint64_t*)block), (a&b) + (((a^b)&0xFEFEFEFEFEFEFEFEULL)>>1));\
+ pixels+=line_size;\
+ block +=line_size;\
+ }\
+}\
+\
+static void OPNAME ## _pixels_x2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h)\
+{\
+ int i;\
+ for(i=0; i<h; i++){\
+ const uint64_t a= LD64(pixels );\
+ const uint64_t b= LD64(pixels+1);\
+ OP(*((uint64_t*)block), (a|b) - (((a^b)&0xFEFEFEFEFEFEFEFEULL)>>1));\
+ pixels+=line_size;\
+ block +=line_size;\
+ }\
+}\
+\
+static void OPNAME ## _no_rnd_pixels_y2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h)\
+{\
+ int i;\
+ for(i=0; i<h; i++){\
+ const uint64_t a= LD64(pixels );\
+ const uint64_t b= LD64(pixels+line_size);\
+ OP(*((uint64_t*)block), (a&b) + (((a^b)&0xFEFEFEFEFEFEFEFEULL)>>1));\
+ pixels+=line_size;\
+ block +=line_size;\
+ }\
+}\
+\
+static void OPNAME ## _pixels_y2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h)\
+{\
+ int i;\
+ for(i=0; i<h; i++){\
+ const uint64_t a= LD64(pixels );\
+ const uint64_t b= LD64(pixels+line_size);\
+ OP(*((uint64_t*)block), (a|b) - (((a^b)&0xFEFEFEFEFEFEFEFEULL)>>1));\
+ pixels+=line_size;\
+ block +=line_size;\
+ }\
+}\
+\
+static void OPNAME ## _pixels_xy2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h)\
+{\
+ int i;\
+ const uint64_t a= LD64(pixels );\
+ const uint64_t b= LD64(pixels+1);\
+ uint64_t l0= (a&0x0303030303030303ULL)\
+ + (b&0x0303030303030303ULL)\
+ + 0x0202020202020202ULL;\
+ uint64_t h0= ((a&0xFCFCFCFCFCFCFCFCULL)>>2)\
+ + ((b&0xFCFCFCFCFCFCFCFCULL)>>2);\
+ uint64_t l1,h1;\
+\
+ pixels+=line_size;\
+ for(i=0; i<h; i+=2){\
+ uint64_t a= LD64(pixels );\
+ uint64_t b= LD64(pixels+1);\
+ l1= (a&0x0303030303030303ULL)\
+ + (b&0x0303030303030303ULL);\
+ h1= ((a&0xFCFCFCFCFCFCFCFCULL)>>2)\
+ + ((b&0xFCFCFCFCFCFCFCFCULL)>>2);\
+ OP(*((uint64_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0F0F0F0F0FULL));\
+ pixels+=line_size;\
+ block +=line_size;\
+ a= LD64(pixels );\
+ b= LD64(pixels+1);\
+ l0= (a&0x0303030303030303ULL)\
+ + (b&0x0303030303030303ULL)\
+ + 0x0202020202020202ULL;\
+ h0= ((a&0xFCFCFCFCFCFCFCFCULL)>>2)\
+ + ((b&0xFCFCFCFCFCFCFCFCULL)>>2);\
+ OP(*((uint64_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0F0F0F0F0FULL));\
+ pixels+=line_size;\
+ block +=line_size;\
+ }\
+}\
+\
+static void OPNAME ## _no_rnd_pixels_xy2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h)\
+{\
+ int i;\
+ const uint64_t a= LD64(pixels );\
+ const uint64_t b= LD64(pixels+1);\
+ uint64_t l0= (a&0x0303030303030303ULL)\
+ + (b&0x0303030303030303ULL)\
+ + 0x0101010101010101ULL;\
+ uint64_t h0= ((a&0xFCFCFCFCFCFCFCFCULL)>>2)\
+ + ((b&0xFCFCFCFCFCFCFCFCULL)>>2);\
+ uint64_t l1,h1;\
+\
+ pixels+=line_size;\
+ for(i=0; i<h; i+=2){\
+ uint64_t a= LD64(pixels );\
+ uint64_t b= LD64(pixels+1);\
+ l1= (a&0x0303030303030303ULL)\
+ + (b&0x0303030303030303ULL);\
+ h1= ((a&0xFCFCFCFCFCFCFCFCULL)>>2)\
+ + ((b&0xFCFCFCFCFCFCFCFCULL)>>2);\
+ OP(*((uint64_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0F0F0F0F0FULL));\
+ pixels+=line_size;\
+ block +=line_size;\
+ a= LD64(pixels );\
+ b= LD64(pixels+1);\
+ l0= (a&0x0303030303030303ULL)\
+ + (b&0x0303030303030303ULL)\
+ + 0x0101010101010101ULL;\
+ h0= ((a&0xFCFCFCFCFCFCFCFCULL)>>2)\
+ + ((b&0xFCFCFCFCFCFCFCFCULL)>>2);\
+ OP(*((uint64_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0F0F0F0F0FULL));\
+ pixels+=line_size;\
+ block +=line_size;\
+ }\
+}\
+\
+CALL_2X_PIXELS(OPNAME ## _pixels16_c , OPNAME ## _pixels_c , 8)\
+CALL_2X_PIXELS(OPNAME ## _pixels16_x2_c , OPNAME ## _pixels_x2_c , 8)\
+CALL_2X_PIXELS(OPNAME ## _pixels16_y2_c , OPNAME ## _pixels_y2_c , 8)\
+CALL_2X_PIXELS(OPNAME ## _pixels16_xy2_c, OPNAME ## _pixels_xy2_c, 8)\
+CALL_2X_PIXELS(OPNAME ## _no_rnd_pixels16_x2_c , OPNAME ## _no_rnd_pixels_x2_c , 8)\
+CALL_2X_PIXELS(OPNAME ## _no_rnd_pixels16_y2_c , OPNAME ## _no_rnd_pixels_y2_c , 8)\
+CALL_2X_PIXELS(OPNAME ## _no_rnd_pixels16_xy2_c, OPNAME ## _no_rnd_pixels_xy2_c, 8)
+
+#define op_avg(a, b) a = ( ((a)|(b)) - ((((a)^(b))&0xFEFEFEFEFEFEFEFEULL)>>1) )
+#else // 64 bit variant
+
+#define PIXOP2(OPNAME, OP) \
+static void OPNAME ## _pixels2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h){\
+ int i;\
+ for(i=0; i<h; i++){\
+ OP(*((uint16_t*)(block )), LD16(pixels ));\
+ pixels+=line_size;\
+ block +=line_size;\
+ }\
+}\
+static void OPNAME ## _pixels4_c(uint8_t *block, const uint8_t *pixels, int line_size, int h){\
+ int i;\
+ for(i=0; i<h; i++){\
+ OP(*((uint32_t*)(block )), LD32(pixels ));\
+ pixels+=line_size;\
+ block +=line_size;\
+ }\
+}\
+static void OPNAME ## _pixels8_c(uint8_t *block, const uint8_t *pixels, int line_size, int h){\
+ int i;\
+ for(i=0; i<h; i++){\
+ OP(*((uint32_t*)(block )), LD32(pixels ));\
+ OP(*((uint32_t*)(block+4)), LD32(pixels+4));\
+ pixels+=line_size;\
+ block +=line_size;\
+ }\
+}\
+static inline void OPNAME ## _no_rnd_pixels8_c(uint8_t *block, const uint8_t *pixels, int line_size, int h){\
+ OPNAME ## _pixels8_c(block, pixels, line_size, h);\
+}\
+\
+static inline void 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<h; i++){\
+ uint32_t a,b;\
+ a= LD32(&src1[i*src_stride1 ]);\
+ b= LD32(&src2[i*src_stride2 ]);\
+ OP(*((uint32_t*)&dst[i*dst_stride ]), no_rnd_avg32(a, b));\
+ a= LD32(&src1[i*src_stride1+4]);\
+ b= LD32(&src2[i*src_stride2+4]);\
+ OP(*((uint32_t*)&dst[i*dst_stride+4]), no_rnd_avg32(a, b));\
+ }\
+}\
+\
+static inline void OPNAME ## _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<h; i++){\
+ uint32_t a,b;\
+ a= LD32(&src1[i*src_stride1 ]);\
+ b= LD32(&src2[i*src_stride2 ]);\
+ OP(*((uint32_t*)&dst[i*dst_stride ]), rnd_avg32(a, b));\
+ a= LD32(&src1[i*src_stride1+4]);\
+ b= LD32(&src2[i*src_stride2+4]);\
+ OP(*((uint32_t*)&dst[i*dst_stride+4]), rnd_avg32(a, b));\
+ }\
+}\
+\
+static inline void OPNAME ## _pixels4_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<h; i++){\
+ uint32_t a,b;\
+ a= LD32(&src1[i*src_stride1 ]);\
+ b= LD32(&src2[i*src_stride2 ]);\
+ OP(*((uint32_t*)&dst[i*dst_stride ]), rnd_avg32(a, b));\
+ }\
+}\
+\
+static inline void OPNAME ## _pixels2_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<h; i++){\
+ uint32_t a,b;\
+ a= LD16(&src1[i*src_stride1 ]);\
+ b= LD16(&src2[i*src_stride2 ]);\
+ OP(*((uint16_t*)&dst[i*dst_stride ]), rnd_avg32(a, b));\
+ }\
+}\
+\
+static inline void OPNAME ## _pixels16_l2(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(dst , src1 , src2 , dst_stride, src_stride1, src_stride2, h);\
+ OPNAME ## _pixels8_l2(dst+8, src1+8, src2+8, dst_stride, src_stride1, src_stride2, h);\
+}\
+\
+static inline void OPNAME ## _no_rnd_pixels16_l2(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(dst , src1 , src2 , dst_stride, src_stride1, src_stride2, h);\
+ OPNAME ## _no_rnd_pixels8_l2(dst+8, src1+8, src2+8, dst_stride, src_stride1, src_stride2, h);\
+}\
+\
+static inline void OPNAME ## _no_rnd_pixels8_x2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h){\
+ OPNAME ## _no_rnd_pixels8_l2(block, pixels, pixels+1, line_size, line_size, line_size, h);\
+}\
+\
+static inline void OPNAME ## _pixels8_x2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h){\
+ OPNAME ## _pixels8_l2(block, pixels, pixels+1, line_size, line_size, line_size, h);\
+}\
+\
+static inline void OPNAME ## _no_rnd_pixels8_y2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h){\
+ OPNAME ## _no_rnd_pixels8_l2(block, pixels, pixels+line_size, line_size, line_size, line_size, h);\
+}\
+\
+static inline void OPNAME ## _pixels8_y2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h){\
+ OPNAME ## _pixels8_l2(block, pixels, pixels+line_size, line_size, line_size, line_size, h);\
+}\
+\
+static inline void OPNAME ## _pixels8_l4(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){\
+ int i;\
+ for(i=0; i<h; i++){\
+ uint32_t a, b, c, d, l0, l1, h0, h1;\
+ a= LD32(&src1[i*src_stride1]);\
+ b= LD32(&src2[i*src_stride2]);\
+ c= LD32(&src3[i*src_stride3]);\
+ d= LD32(&src4[i*src_stride4]);\
+ 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]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\
+ a= LD32(&src1[i*src_stride1+4]);\
+ b= LD32(&src2[i*src_stride2+4]);\
+ c= LD32(&src3[i*src_stride3+4]);\
+ d= LD32(&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 OPNAME ## _pixels4_x2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h){\
+ OPNAME ## _pixels4_l2(block, pixels, pixels+1, line_size, line_size, line_size, h);\
+}\
+\
+static inline void OPNAME ## _pixels4_y2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h){\
+ OPNAME ## _pixels4_l2(block, pixels, pixels+line_size, line_size, line_size, line_size, h);\
+}\
+\
+static inline void OPNAME ## _pixels2_x2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h){\
+ OPNAME ## _pixels2_l2(block, pixels, pixels+1, line_size, line_size, line_size, h);\
+}\
+\
+static inline void OPNAME ## _pixels2_y2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h){\
+ OPNAME ## _pixels2_l2(block, pixels, pixels+line_size, line_size, line_size, line_size, h);\
+}\
+\
+static inline void OPNAME ## _no_rnd_pixels8_l4(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){\
+ int i;\
+ for(i=0; i<h; i++){\
+ uint32_t a, b, c, d, l0, l1, h0, h1;\
+ a= LD32(&src1[i*src_stride1]);\
+ b= LD32(&src2[i*src_stride2]);\
+ c= LD32(&src3[i*src_stride3]);\
+ d= LD32(&src4[i*src_stride4]);\
+ 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]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\
+ a= LD32(&src1[i*src_stride1+4]);\
+ b= LD32(&src2[i*src_stride2+4]);\
+ c= LD32(&src3[i*src_stride3+4]);\
+ d= LD32(&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 OPNAME ## _pixels16_l4(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){\
+ OPNAME ## _pixels8_l4(dst , src1 , src2 , src3 , src4 , dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\
+ OPNAME ## _pixels8_l4(dst+8, src1+8, src2+8, src3+8, src4+8, dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\
+}\
+static inline void OPNAME ## _no_rnd_pixels16_l4(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){\
+ OPNAME ## _no_rnd_pixels8_l4(dst , src1 , src2 , src3 , src4 , dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\
+ OPNAME ## _no_rnd_pixels8_l4(dst+8, src1+8, src2+8, src3+8, src4+8, dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\
+}\
+\
+static inline void OPNAME ## _pixels2_xy2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h)\
+{\
+ int i, a0, b0, a1, b1;\
+ a0= pixels[0];\
+ b0= pixels[1] + 2;\
+ a0 += b0;\
+ b0 += pixels[2];\
+\
+ pixels+=line_size;\
+ for(i=0; i<h; i+=2){\
+ a1= pixels[0];\
+ b1= pixels[1];\
+ a1 += b1;\
+ b1 += pixels[2];\
+\
+ block[0]= (a1+a0)>>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 OPNAME ## _pixels4_xy2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h)\
+{\
+ int i;\
+ const uint32_t a= LD32(pixels );\
+ const uint32_t b= LD32(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<h; i+=2){\
+ uint32_t a= LD32(pixels );\
+ uint32_t b= LD32(pixels+1);\
+ l1= (a&0x03030303UL)\
+ + (b&0x03030303UL);\
+ h1= ((a&0xFCFCFCFCUL)>>2)\
+ + ((b&0xFCFCFCFCUL)>>2);\
+ OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\
+ pixels+=line_size;\
+ block +=line_size;\
+ a= LD32(pixels );\
+ b= LD32(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 OPNAME ## _pixels8_xy2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h)\
+{\
+ int j;\
+ for(j=0; j<2; j++){\
+ int i;\
+ const uint32_t a= LD32(pixels );\
+ const uint32_t b= LD32(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<h; i+=2){\
+ uint32_t a= LD32(pixels );\
+ uint32_t b= LD32(pixels+1);\
+ l1= (a&0x03030303UL)\
+ + (b&0x03030303UL);\
+ h1= ((a&0xFCFCFCFCUL)>>2)\
+ + ((b&0xFCFCFCFCUL)>>2);\
+ OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\
+ pixels+=line_size;\
+ block +=line_size;\
+ a= LD32(pixels );\
+ b= LD32(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 OPNAME ## _no_rnd_pixels8_xy2_c(uint8_t *block, const uint8_t *pixels, int line_size, int h)\
+{\
+ int j;\
+ for(j=0; j<2; j++){\
+ int i;\
+ const uint32_t a= LD32(pixels );\
+ const uint32_t b= LD32(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<h; i+=2){\
+ uint32_t a= LD32(pixels );\
+ uint32_t b= LD32(pixels+1);\
+ l1= (a&0x03030303UL)\
+ + (b&0x03030303UL);\
+ h1= ((a&0xFCFCFCFCUL)>>2)\
+ + ((b&0xFCFCFCFCUL)>>2);\
+ OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\
+ pixels+=line_size;\
+ block +=line_size;\
+ a= LD32(pixels );\
+ b= LD32(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(OPNAME ## _pixels16_c , OPNAME ## _pixels8_c , 8)\
+CALL_2X_PIXELS(OPNAME ## _pixels16_x2_c , OPNAME ## _pixels8_x2_c , 8)\
+CALL_2X_PIXELS(OPNAME ## _pixels16_y2_c , OPNAME ## _pixels8_y2_c , 8)\
+CALL_2X_PIXELS(OPNAME ## _pixels16_xy2_c, OPNAME ## _pixels8_xy2_c, 8)\
+CALL_2X_PIXELS(OPNAME ## _no_rnd_pixels16_c , OPNAME ## _pixels8_c , 8)\
+CALL_2X_PIXELS(OPNAME ## _no_rnd_pixels16_x2_c , OPNAME ## _no_rnd_pixels8_x2_c , 8)\
+CALL_2X_PIXELS(OPNAME ## _no_rnd_pixels16_y2_c , OPNAME ## _no_rnd_pixels8_y2_c , 8)\
+CALL_2X_PIXELS(OPNAME ## _no_rnd_pixels16_xy2_c, OPNAME ## _no_rnd_pixels8_xy2_c, 8)\
+
+#define op_avg(a, b) a = rnd_avg32(a, b)
+#endif
+#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 put_no_rnd_pixels16_l2_c(uint8_t *dst, const uint8_t *a, const uint8_t *b, int stride, int h){
+ put_no_rnd_pixels16_l2(dst, a, b, stride, stride, stride, h);
+}
+
+static void put_no_rnd_pixels8_l2_c(uint8_t *dst, const uint8_t *a, const uint8_t *b, int stride, int h){
+ put_no_rnd_pixels8_l2(dst, a, b, stride, stride, stride, h);
+}
+
+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<h; i++)
+ {
+ dst[0]= (A*src[0] + B*src[1] + C*src[stride+0] + D*src[stride+1] + rounder)>>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<<shift;
+
+ width--;
+ height--;
+
+ for(y=0; y<h; y++){
+ int x;
+
+ vx= ox;
+ vy= oy;
+ for(x=0; x<8; x++){ //XXX FIXME optimize
+ int src_x, src_y, frac_x, frac_y, index;
+
+ src_x= vx>>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 + 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= 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= clip(src_x, 0, width) + 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_c (dst, src, stride, height); break;
+ case 4: put_pixels4_c (dst, src, stride, height); break;
+ case 8: put_pixels8_c (dst, src, stride, height); break;
+ case 16:put_pixels16_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_c (dst, src, stride, height); break;
+ case 4: avg_pixels4_c (dst, src, stride, height); break;
+ case 8: avg_pixels8_c (dst, src, stride, height); break;
+ case 16:avg_pixels16_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;
+ }
+}
+#if 0
+#define TPEL_WIDTH(width)\
+static void put_tpel_pixels ## width ## _mc00_c(uint8_t *dst, const uint8_t *src, int stride, int height){\
+ void put_tpel_pixels_mc00_c(dst, src, stride, width, height);}\
+static void put_tpel_pixels ## width ## _mc10_c(uint8_t *dst, const uint8_t *src, int stride, int height){\
+ void put_tpel_pixels_mc10_c(dst, src, stride, width, height);}\
+static void put_tpel_pixels ## width ## _mc20_c(uint8_t *dst, const uint8_t *src, int stride, int height){\
+ void put_tpel_pixels_mc20_c(dst, src, stride, width, height);}\
+static void put_tpel_pixels ## width ## _mc01_c(uint8_t *dst, const uint8_t *src, int stride, int height){\
+ void put_tpel_pixels_mc01_c(dst, src, stride, width, height);}\
+static void put_tpel_pixels ## width ## _mc11_c(uint8_t *dst, const uint8_t *src, int stride, int height){\
+ void put_tpel_pixels_mc11_c(dst, src, stride, width, height);}\
+static void put_tpel_pixels ## width ## _mc21_c(uint8_t *dst, const uint8_t *src, int stride, int height){\
+ void put_tpel_pixels_mc21_c(dst, src, stride, width, height);}\
+static void put_tpel_pixels ## width ## _mc02_c(uint8_t *dst, const uint8_t *src, int stride, int height){\
+ void put_tpel_pixels_mc02_c(dst, src, stride, width, height);}\
+static void put_tpel_pixels ## width ## _mc12_c(uint8_t *dst, const uint8_t *src, int stride, int height){\
+ void put_tpel_pixels_mc12_c(dst, src, stride, width, height);}\
+static void put_tpel_pixels ## width ## _mc22_c(uint8_t *dst, const uint8_t *src, int stride, int height){\
+ void put_tpel_pixels_mc22_c(dst, src, stride, width, height);}
+#endif
+
+#define H264_CHROMA_MC(OPNAME, OP)\
+static void OPNAME ## h264_chroma_mc2_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;\
+ \
+ assert(x<8 && y<8 && x>=0 && y>=0);\
+\
+ for(i=0; i<h; i++)\
+ {\
+ OP(dst[0], (A*src[0] + B*src[1] + C*src[stride+0] + D*src[stride+1]));\
+ OP(dst[1], (A*src[1] + B*src[2] + C*src[stride+1] + D*src[stride+2]));\
+ dst+= stride;\
+ src+= stride;\
+ }\
+}\
+\
+static void OPNAME ## h264_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;\
+ \
+ assert(x<8 && y<8 && x>=0 && y>=0);\
+\
+ for(i=0; i<h; i++)\
+ {\
+ OP(dst[0], (A*src[0] + B*src[1] + C*src[stride+0] + D*src[stride+1]));\
+ OP(dst[1], (A*src[1] + B*src[2] + C*src[stride+1] + D*src[stride+2]));\
+ OP(dst[2], (A*src[2] + B*src[3] + C*src[stride+2] + D*src[stride+3]));\
+ OP(dst[3], (A*src[3] + B*src[4] + C*src[stride+3] + D*src[stride+4]));\
+ dst+= stride;\
+ src+= stride;\
+ }\
+}\
+\
+static void OPNAME ## h264_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;\
+ \
+ assert(x<8 && y<8 && x>=0 && y>=0);\
+\
+ for(i=0; i<h; i++)\
+ {\
+ OP(dst[0], (A*src[0] + B*src[1] + C*src[stride+0] + D*src[stride+1]));\
+ OP(dst[1], (A*src[1] + B*src[2] + C*src[stride+1] + D*src[stride+2]));\
+ OP(dst[2], (A*src[2] + B*src[3] + C*src[stride+2] + D*src[stride+3]));\
+ OP(dst[3], (A*src[3] + B*src[4] + C*src[stride+3] + D*src[stride+4]));\
+ OP(dst[4], (A*src[4] + B*src[5] + C*src[stride+4] + D*src[stride+5]));\
+ OP(dst[5], (A*src[5] + B*src[6] + C*src[stride+5] + D*src[stride+6]));\
+ OP(dst[6], (A*src[6] + B*src[7] + C*src[stride+6] + D*src[stride+7]));\
+ OP(dst[7], (A*src[7] + B*src[8] + C*src[stride+7] + D*src[stride+8]));\
+ dst+= stride;\
+ src+= stride;\
+ }\
+}
+
+#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
+
+static void put_no_rnd_h264_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;
+
+ assert(x<8 && y<8 && x>=0 && y>=0);
+
+ for(i=0; i<h; i++)
+ {
+ dst[0] = (A*src[0] + B*src[1] + C*src[stride+0] + D*src[stride+1] + 32 - 4) >> 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;
+ }
+}
+
+#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<h; i++)\
+ {\
+ OP(dst[0], (src[0]+src[1])*20 - (src[0]+src[2])*6 + (src[1]+src[3])*3 - (src[2]+src[4]));\
+ OP(dst[1], (src[1]+src[2])*20 - (src[0]+src[3])*6 + (src[0]+src[4])*3 - (src[1]+src[5]));\
+ OP(dst[2], (src[2]+src[3])*20 - (src[1]+src[4])*6 + (src[0]+src[5])*3 - (src[0]+src[6]));\
+ OP(dst[3], (src[3]+src[4])*20 - (src[2]+src[5])*6 + (src[1]+src[6])*3 - (src[0]+src[7]));\
+ OP(dst[4], (src[4]+src[5])*20 - (src[3]+src[6])*6 + (src[2]+src[7])*3 - (src[1]+src[8]));\
+ OP(dst[5], (src[5]+src[6])*20 - (src[4]+src[7])*6 + (src[3]+src[8])*3 - (src[2]+src[8]));\
+ OP(dst[6], (src[6]+src[7])*20 - (src[5]+src[8])*6 + (src[4]+src[8])*3 - (src[3]+src[7]));\
+ OP(dst[7], (src[7]+src[8])*20 - (src[6]+src[8])*6 + (src[5]+src[7])*3 - (src[4]+src[6]));\
+ dst+=dstStride;\
+ src+=srcStride;\
+ }\
+}\
+\
+static void OPNAME ## mpeg4_qpel8_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ const int w=8;\
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\
+ int i;\
+ for(i=0; i<w; i++)\
+ {\
+ 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];\
+ OP(dst[0*dstStride], (src0+src1)*20 - (src0+src2)*6 + (src1+src3)*3 - (src2+src4));\
+ OP(dst[1*dstStride], (src1+src2)*20 - (src0+src3)*6 + (src0+src4)*3 - (src1+src5));\
+ OP(dst[2*dstStride], (src2+src3)*20 - (src1+src4)*6 + (src0+src5)*3 - (src0+src6));\
+ OP(dst[3*dstStride], (src3+src4)*20 - (src2+src5)*6 + (src1+src6)*3 - (src0+src7));\
+ OP(dst[4*dstStride], (src4+src5)*20 - (src3+src6)*6 + (src2+src7)*3 - (src1+src8));\
+ OP(dst[5*dstStride], (src5+src6)*20 - (src4+src7)*6 + (src3+src8)*3 - (src2+src8));\
+ OP(dst[6*dstStride], (src6+src7)*20 - (src5+src8)*6 + (src4+src8)*3 - (src3+src7));\
+ OP(dst[7*dstStride], (src7+src8)*20 - (src6+src8)*6 + (src5+src7)*3 - (src4+src6));\
+ dst++;\
+ src++;\
+ }\
+}\
+\
+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;\
+ int i;\
+ \
+ for(i=0; i<h; i++)\
+ {\
+ OP(dst[ 0], (src[ 0]+src[ 1])*20 - (src[ 0]+src[ 2])*6 + (src[ 1]+src[ 3])*3 - (src[ 2]+src[ 4]));\
+ OP(dst[ 1], (src[ 1]+src[ 2])*20 - (src[ 0]+src[ 3])*6 + (src[ 0]+src[ 4])*3 - (src[ 1]+src[ 5]));\
+ OP(dst[ 2], (src[ 2]+src[ 3])*20 - (src[ 1]+src[ 4])*6 + (src[ 0]+src[ 5])*3 - (src[ 0]+src[ 6]));\
+ OP(dst[ 3], (src[ 3]+src[ 4])*20 - (src[ 2]+src[ 5])*6 + (src[ 1]+src[ 6])*3 - (src[ 0]+src[ 7]));\
+ OP(dst[ 4], (src[ 4]+src[ 5])*20 - (src[ 3]+src[ 6])*6 + (src[ 2]+src[ 7])*3 - (src[ 1]+src[ 8]));\
+ OP(dst[ 5], (src[ 5]+src[ 6])*20 - (src[ 4]+src[ 7])*6 + (src[ 3]+src[ 8])*3 - (src[ 2]+src[ 9]));\
+ OP(dst[ 6], (src[ 6]+src[ 7])*20 - (src[ 5]+src[ 8])*6 + (src[ 4]+src[ 9])*3 - (src[ 3]+src[10]));\
+ OP(dst[ 7], (src[ 7]+src[ 8])*20 - (src[ 6]+src[ 9])*6 + (src[ 5]+src[10])*3 - (src[ 4]+src[11]));\
+ OP(dst[ 8], (src[ 8]+src[ 9])*20 - (src[ 7]+src[10])*6 + (src[ 6]+src[11])*3 - (src[ 5]+src[12]));\
+ OP(dst[ 9], (src[ 9]+src[10])*20 - (src[ 8]+src[11])*6 + (src[ 7]+src[12])*3 - (src[ 6]+src[13]));\
+ OP(dst[10], (src[10]+src[11])*20 - (src[ 9]+src[12])*6 + (src[ 8]+src[13])*3 - (src[ 7]+src[14]));\
+ OP(dst[11], (src[11]+src[12])*20 - (src[10]+src[13])*6 + (src[ 9]+src[14])*3 - (src[ 8]+src[15]));\
+ OP(dst[12], (src[12]+src[13])*20 - (src[11]+src[14])*6 + (src[10]+src[15])*3 - (src[ 9]+src[16]));\
+ OP(dst[13], (src[13]+src[14])*20 - (src[12]+src[15])*6 + (src[11]+src[16])*3 - (src[10]+src[16]));\
+ OP(dst[14], (src[14]+src[15])*20 - (src[13]+src[16])*6 + (src[12]+src[16])*3 - (src[11]+src[15]));\
+ OP(dst[15], (src[15]+src[16])*20 - (src[14]+src[16])*6 + (src[13]+src[15])*3 - (src[12]+src[14]));\
+ dst+=dstStride;\
+ src+=srcStride;\
+ }\
+}\
+\
+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 i;\
+ const int w=16;\
+ for(i=0; i<w; i++)\
+ {\
+ 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];\
+ const int src11= src[11*srcStride];\
+ const int src12= src[12*srcStride];\
+ const int src13= src[13*srcStride];\
+ const int src14= src[14*srcStride];\
+ const int src15= src[15*srcStride];\
+ const int src16= src[16*srcStride];\
+ OP(dst[ 0*dstStride], (src0 +src1 )*20 - (src0 +src2 )*6 + (src1 +src3 )*3 - (src2 +src4 ));\
+ OP(dst[ 1*dstStride], (src1 +src2 )*20 - (src0 +src3 )*6 + (src0 +src4 )*3 - (src1 +src5 ));\
+ OP(dst[ 2*dstStride], (src2 +src3 )*20 - (src1 +src4 )*6 + (src0 +src5 )*3 - (src0 +src6 ));\
+ OP(dst[ 3*dstStride], (src3 +src4 )*20 - (src2 +src5 )*6 + (src1 +src6 )*3 - (src0 +src7 ));\
+ OP(dst[ 4*dstStride], (src4 +src5 )*20 - (src3 +src6 )*6 + (src2 +src7 )*3 - (src1 +src8 ));\
+ OP(dst[ 5*dstStride], (src5 +src6 )*20 - (src4 +src7 )*6 + (src3 +src8 )*3 - (src2 +src9 ));\
+ OP(dst[ 6*dstStride], (src6 +src7 )*20 - (src5 +src8 )*6 + (src4 +src9 )*3 - (src3 +src10));\
+ OP(dst[ 7*dstStride], (src7 +src8 )*20 - (src6 +src9 )*6 + (src5 +src10)*3 - (src4 +src11));\
+ OP(dst[ 8*dstStride], (src8 +src9 )*20 - (src7 +src10)*6 + (src6 +src11)*3 - (src5 +src12));\
+ OP(dst[ 9*dstStride], (src9 +src10)*20 - (src8 +src11)*6 + (src7 +src12)*3 - (src6 +src13));\
+ OP(dst[10*dstStride], (src10+src11)*20 - (src9 +src12)*6 + (src8 +src13)*3 - (src7 +src14));\
+ OP(dst[11*dstStride], (src11+src12)*20 - (src10+src13)*6 + (src9 +src14)*3 - (src8 +src15));\
+ OP(dst[12*dstStride], (src12+src13)*20 - (src11+src14)*6 + (src10+src15)*3 - (src9 +src16));\
+ OP(dst[13*dstStride], (src13+src14)*20 - (src12+src15)*6 + (src11+src16)*3 - (src10+src16));\
+ OP(dst[14*dstStride], (src14+src15)*20 - (src13+src16)*6 + (src12+src16)*3 - (src11+src15));\
+ OP(dst[15*dstStride], (src15+src16)*20 - (src14+src16)*6 + (src13+src15)*3 - (src12+src14));\
+ dst++;\
+ src++;\
+ }\
+}\
+\
+static void OPNAME ## qpel8_mc00_c (uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## pixels8_c(dst, src, stride, 8);\
+}\
+\
+static void OPNAME ## qpel8_mc10_c(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(dst, src, half, stride, stride, 8, 8);\
+}\
+\
+static void OPNAME ## qpel8_mc20_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## mpeg4_qpel8_h_lowpass(dst, src, stride, stride, 8);\
+}\
+\
+static void OPNAME ## qpel8_mc30_c(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(dst, src+1, half, stride, stride, 8, 8);\
+}\
+\
+static void OPNAME ## qpel8_mc01_c(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(dst, full, half, stride, 16, 8, 8);\
+}\
+\
+static void OPNAME ## qpel8_mc02_c(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_c(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(dst, full+16, half, stride, 16, 8, 8);\
+}\
+void ff_ ## OPNAME ## qpel8_mc11_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[16*9];\
+ uint8_t halfH[72];\
+ uint8_t halfV[64];\
+ uint8_t halfHV[64];\
+ copy_block9(full, src, 16, stride, 9);\
+ put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full, 8, 16);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l4(dst, full, halfH, halfV, halfHV, stride, 16, 8, 8, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc11_c(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(halfH, halfH, full, 8, 8, 16, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l2(dst, halfH, halfHV, stride, 8, 8, 8);\
+}\
+void ff_ ## OPNAME ## qpel8_mc31_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[16*9];\
+ uint8_t halfH[72];\
+ uint8_t halfV[64];\
+ uint8_t halfHV[64];\
+ copy_block9(full, src, 16, stride, 9);\
+ put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full+1, 8, 16);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l4(dst, full+1, halfH, halfV, halfHV, stride, 16, 8, 8, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc31_c(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(halfH, halfH, full+1, 8, 8, 16, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l2(dst, halfH, halfHV, stride, 8, 8, 8);\
+}\
+void ff_ ## OPNAME ## qpel8_mc13_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[16*9];\
+ uint8_t halfH[72];\
+ uint8_t halfV[64];\
+ uint8_t halfHV[64];\
+ copy_block9(full, src, 16, stride, 9);\
+ put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full, 8, 16);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l4(dst, full+16, halfH+8, halfV, halfHV, stride, 16, 8, 8, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc13_c(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(halfH, halfH, full, 8, 8, 16, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l2(dst, halfH+8, halfHV, stride, 8, 8, 8);\
+}\
+void ff_ ## OPNAME ## qpel8_mc33_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[16*9];\
+ uint8_t halfH[72];\
+ uint8_t halfV[64];\
+ uint8_t halfHV[64];\
+ copy_block9(full, src, 16, stride, 9);\
+ put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full , 8, 16, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full+1, 8, 16);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l4(dst, full+17, halfH+8, halfV, halfHV, stride, 16, 8, 8, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc33_c(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(halfH, halfH, full+1, 8, 8, 16, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l2(dst, halfH+8, halfHV, stride, 8, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc21_c(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(dst, halfH, halfHV, stride, 8, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc23_c(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(dst, halfH+8, halfHV, stride, 8, 8, 8);\
+}\
+void ff_ ## OPNAME ## qpel8_mc12_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[16*9];\
+ uint8_t halfH[72];\
+ uint8_t halfV[64];\
+ uint8_t halfHV[64];\
+ copy_block9(full, src, 16, stride, 9);\
+ put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full, 8, 16);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l2(dst, halfV, halfHV, stride, 8, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc12_c(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(halfH, halfH, full, 8, 8, 16, 9);\
+ OPNAME ## mpeg4_qpel8_v_lowpass(dst, halfH, stride, 8);\
+}\
+void ff_ ## OPNAME ## qpel8_mc32_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[16*9];\
+ uint8_t halfH[72];\
+ uint8_t halfV[64];\
+ uint8_t halfHV[64];\
+ copy_block9(full, src, 16, stride, 9);\
+ put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full+1, 8, 16);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l2(dst, halfV, halfHV, stride, 8, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc32_c(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(halfH, halfH, full+1, 8, 8, 16, 9);\
+ OPNAME ## mpeg4_qpel8_v_lowpass(dst, halfH, stride, 8);\
+}\
+static void OPNAME ## qpel8_mc22_c(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_c (uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## pixels16_c(dst, src, stride, 16);\
+}\
+\
+static void OPNAME ## qpel16_mc10_c(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(dst, src, half, stride, stride, 16, 16);\
+}\
+\
+static void OPNAME ## qpel16_mc20_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## mpeg4_qpel16_h_lowpass(dst, src, stride, stride, 16);\
+}\
+\
+static void OPNAME ## qpel16_mc30_c(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(dst, src+1, half, stride, stride, 16, 16);\
+}\
+\
+static void OPNAME ## qpel16_mc01_c(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(dst, full, half, stride, 24, 16, 16);\
+}\
+\
+static void OPNAME ## qpel16_mc02_c(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_c(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(dst, full+24, half, stride, 24, 16, 16);\
+}\
+void ff_ ## OPNAME ## qpel16_mc11_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[24*17];\
+ uint8_t halfH[272];\
+ uint8_t halfV[256];\
+ uint8_t halfHV[256];\
+ copy_block17(full, src, 24, stride, 17);\
+ put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full, 16, 24);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l4(dst, full, halfH, halfV, halfHV, stride, 24, 16, 16, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc11_c(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(halfH, halfH, full, 16, 16, 24, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l2(dst, halfH, halfHV, stride, 16, 16, 16);\
+}\
+void ff_ ## OPNAME ## qpel16_mc31_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[24*17];\
+ uint8_t halfH[272];\
+ uint8_t halfV[256];\
+ uint8_t halfHV[256];\
+ copy_block17(full, src, 24, stride, 17);\
+ put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full+1, 16, 24);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l4(dst, full+1, halfH, halfV, halfHV, stride, 24, 16, 16, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc31_c(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(halfH, halfH, full+1, 16, 16, 24, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l2(dst, halfH, halfHV, stride, 16, 16, 16);\
+}\
+void ff_ ## OPNAME ## qpel16_mc13_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[24*17];\
+ uint8_t halfH[272];\
+ uint8_t halfV[256];\
+ uint8_t halfHV[256];\
+ copy_block17(full, src, 24, stride, 17);\
+ put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full, 16, 24);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l4(dst, full+24, halfH+16, halfV, halfHV, stride, 24, 16, 16, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc13_c(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(halfH, halfH, full, 16, 16, 24, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l2(dst, halfH+16, halfHV, stride, 16, 16, 16);\
+}\
+void ff_ ## OPNAME ## qpel16_mc33_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[24*17];\
+ uint8_t halfH[272];\
+ uint8_t halfV[256];\
+ uint8_t halfHV[256];\
+ copy_block17(full, src, 24, stride, 17);\
+ put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full , 16, 24, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full+1, 16, 24);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l4(dst, full+25, halfH+16, halfV, halfHV, stride, 24, 16, 16, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc33_c(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(halfH, halfH, full+1, 16, 16, 24, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l2(dst, halfH+16, halfHV, stride, 16, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc21_c(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(dst, halfH, halfHV, stride, 16, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc23_c(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(dst, halfH+16, halfHV, stride, 16, 16, 16);\
+}\
+void ff_ ## OPNAME ## qpel16_mc12_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[24*17];\
+ uint8_t halfH[272];\
+ uint8_t halfV[256];\
+ uint8_t halfHV[256];\
+ copy_block17(full, src, 24, stride, 17);\
+ put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full, 16, 24);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l2(dst, halfV, halfHV, stride, 16, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc12_c(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(halfH, halfH, full, 16, 16, 24, 17);\
+ OPNAME ## mpeg4_qpel16_v_lowpass(dst, halfH, stride, 16);\
+}\
+void ff_ ## OPNAME ## qpel16_mc32_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[24*17];\
+ uint8_t halfH[272];\
+ uint8_t halfV[256];\
+ uint8_t halfHV[256];\
+ copy_block17(full, src, 24, stride, 17);\
+ put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full+1, 16, 24);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l2(dst, halfV, halfHV, stride, 16, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc32_c(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(halfH, halfH, full+1, 16, 16, 24, 17);\
+ OPNAME ## mpeg4_qpel16_v_lowpass(dst, halfH, stride, 16);\
+}\
+static void OPNAME ## qpel16_mc22_c(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
+
+#if 1
+#define H264_LOWPASS(OPNAME, OP, OP2) \
+static void OPNAME ## h264_qpel2_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ const int h=2;\
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\
+ int i;\
+ for(i=0; i<h; i++)\
+ {\
+ OP(dst[0], (src[0]+src[1])*20 - (src[-1]+src[2])*5 + (src[-2]+src[3]));\
+ OP(dst[1], (src[1]+src[2])*20 - (src[0 ]+src[3])*5 + (src[-1]+src[4]));\
+ dst+=dstStride;\
+ src+=srcStride;\
+ }\
+}\
+\
+static void OPNAME ## h264_qpel2_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ const int w=2;\
+ 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];\
+ OP(dst[0*dstStride], (src0+src1)*20 - (srcA+src2)*5 + (srcB+src3));\
+ OP(dst[1*dstStride], (src1+src2)*20 - (src0+src3)*5 + (srcA+src4));\
+ dst++;\
+ src++;\
+ }\
+}\
+\
+static void OPNAME ## h264_qpel2_hv_lowpass(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride){\
+ const int h=2;\
+ const int w=2;\
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\
+ int i;\
+ src -= 2*srcStride;\
+ for(i=0; i<h+5; i++)\
+ {\
+ tmp[0]= (src[0]+src[1])*20 - (src[-1]+src[2])*5 + (src[-2]+src[3]);\
+ tmp[1]= (src[1]+src[2])*20 - (src[0 ]+src[3])*5 + (src[-1]+src[4]);\
+ tmp+=tmpStride;\
+ src+=srcStride;\
+ }\
+ tmp -= tmpStride*(h+5-2);\
+ for(i=0; i<w; i++)\
+ {\
+ const int tmpB= tmp[-2*tmpStride];\
+ const int tmpA= tmp[-1*tmpStride];\
+ const int tmp0= tmp[0 *tmpStride];\
+ const int tmp1= tmp[1 *tmpStride];\
+ const int tmp2= tmp[2 *tmpStride];\
+ const int tmp3= tmp[3 *tmpStride];\
+ const int tmp4= tmp[4 *tmpStride];\
+ OP2(dst[0*dstStride], (tmp0+tmp1)*20 - (tmpA+tmp2)*5 + (tmpB+tmp3));\
+ OP2(dst[1*dstStride], (tmp1+tmp2)*20 - (tmp0+tmp3)*5 + (tmpA+tmp4));\
+ dst++;\
+ tmp++;\
+ }\
+}\
+static void OPNAME ## h264_qpel4_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ const int h=4;\
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\
+ int i;\
+ for(i=0; i<h; i++)\
+ {\
+ OP(dst[0], (src[0]+src[1])*20 - (src[-1]+src[2])*5 + (src[-2]+src[3]));\
+ OP(dst[1], (src[1]+src[2])*20 - (src[0 ]+src[3])*5 + (src[-1]+src[4]));\
+ OP(dst[2], (src[2]+src[3])*20 - (src[1 ]+src[4])*5 + (src[0 ]+src[5]));\
+ OP(dst[3], (src[3]+src[4])*20 - (src[2 ]+src[5])*5 + (src[1 ]+src[6]));\
+ dst+=dstStride;\
+ src+=srcStride;\
+ }\
+}\
+\
+static void OPNAME ## h264_qpel4_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ const int w=4;\
+ 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];\
+ OP(dst[0*dstStride], (src0+src1)*20 - (srcA+src2)*5 + (srcB+src3));\
+ OP(dst[1*dstStride], (src1+src2)*20 - (src0+src3)*5 + (srcA+src4));\
+ OP(dst[2*dstStride], (src2+src3)*20 - (src1+src4)*5 + (src0+src5));\
+ OP(dst[3*dstStride], (src3+src4)*20 - (src2+src5)*5 + (src1+src6));\
+ dst++;\
+ src++;\
+ }\
+}\
+\
+static void OPNAME ## h264_qpel4_hv_lowpass(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride){\
+ const int h=4;\
+ const int w=4;\
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\
+ int i;\
+ src -= 2*srcStride;\
+ for(i=0; i<h+5; i++)\
+ {\
+ tmp[0]= (src[0]+src[1])*20 - (src[-1]+src[2])*5 + (src[-2]+src[3]);\
+ tmp[1]= (src[1]+src[2])*20 - (src[0 ]+src[3])*5 + (src[-1]+src[4]);\
+ tmp[2]= (src[2]+src[3])*20 - (src[1 ]+src[4])*5 + (src[0 ]+src[5]);\
+ tmp[3]= (src[3]+src[4])*20 - (src[2 ]+src[5])*5 + (src[1 ]+src[6]);\
+ tmp+=tmpStride;\
+ src+=srcStride;\
+ }\
+ tmp -= tmpStride*(h+5-2);\
+ for(i=0; i<w; i++)\
+ {\
+ const int tmpB= tmp[-2*tmpStride];\
+ const int tmpA= tmp[-1*tmpStride];\
+ const int tmp0= tmp[0 *tmpStride];\
+ const int tmp1= tmp[1 *tmpStride];\
+ const int tmp2= tmp[2 *tmpStride];\
+ const int tmp3= tmp[3 *tmpStride];\
+ const int tmp4= tmp[4 *tmpStride];\
+ const int tmp5= tmp[5 *tmpStride];\
+ const int tmp6= tmp[6 *tmpStride];\
+ OP2(dst[0*dstStride], (tmp0+tmp1)*20 - (tmpA+tmp2)*5 + (tmpB+tmp3));\
+ OP2(dst[1*dstStride], (tmp1+tmp2)*20 - (tmp0+tmp3)*5 + (tmpA+tmp4));\
+ OP2(dst[2*dstStride], (tmp2+tmp3)*20 - (tmp1+tmp4)*5 + (tmp0+tmp5));\
+ OP2(dst[3*dstStride], (tmp3+tmp4)*20 - (tmp2+tmp5)*5 + (tmp1+tmp6));\
+ dst++;\
+ tmp++;\
+ }\
+}\
+\
+static void OPNAME ## h264_qpel8_h_lowpass(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<h; i++)\
+ {\
+ OP(dst[0], (src[0]+src[1])*20 - (src[-1]+src[2])*5 + (src[-2]+src[3 ]));\
+ OP(dst[1], (src[1]+src[2])*20 - (src[0 ]+src[3])*5 + (src[-1]+src[4 ]));\
+ OP(dst[2], (src[2]+src[3])*20 - (src[1 ]+src[4])*5 + (src[0 ]+src[5 ]));\
+ OP(dst[3], (src[3]+src[4])*20 - (src[2 ]+src[5])*5 + (src[1 ]+src[6 ]));\
+ OP(dst[4], (src[4]+src[5])*20 - (src[3 ]+src[6])*5 + (src[2 ]+src[7 ]));\
+ OP(dst[5], (src[5]+src[6])*20 - (src[4 ]+src[7])*5 + (src[3 ]+src[8 ]));\
+ OP(dst[6], (src[6]+src[7])*20 - (src[5 ]+src[8])*5 + (src[4 ]+src[9 ]));\
+ OP(dst[7], (src[7]+src[8])*20 - (src[6 ]+src[9])*5 + (src[5 ]+src[10]));\
+ dst+=dstStride;\
+ src+=srcStride;\
+ }\
+}\
+\
+static void OPNAME ## h264_qpel8_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ const int w=8;\
+ 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], (src0+src1)*20 - (srcA+src2)*5 + (srcB+src3));\
+ OP(dst[1*dstStride], (src1+src2)*20 - (src0+src3)*5 + (srcA+src4));\
+ OP(dst[2*dstStride], (src2+src3)*20 - (src1+src4)*5 + (src0+src5));\
+ OP(dst[3*dstStride], (src3+src4)*20 - (src2+src5)*5 + (src1+src6));\
+ OP(dst[4*dstStride], (src4+src5)*20 - (src3+src6)*5 + (src2+src7));\
+ OP(dst[5*dstStride], (src5+src6)*20 - (src4+src7)*5 + (src3+src8));\
+ OP(dst[6*dstStride], (src6+src7)*20 - (src5+src8)*5 + (src4+src9));\
+ OP(dst[7*dstStride], (src7+src8)*20 - (src6+src9)*5 + (src5+src10));\
+ dst++;\
+ src++;\
+ }\
+}\
+\
+static void OPNAME ## h264_qpel8_hv_lowpass(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride){\
+ const int h=8;\
+ const int w=8;\
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\
+ int i;\
+ src -= 2*srcStride;\
+ for(i=0; i<h+5; i++)\
+ {\
+ tmp[0]= (src[0]+src[1])*20 - (src[-1]+src[2])*5 + (src[-2]+src[3 ]);\
+ tmp[1]= (src[1]+src[2])*20 - (src[0 ]+src[3])*5 + (src[-1]+src[4 ]);\
+ tmp[2]= (src[2]+src[3])*20 - (src[1 ]+src[4])*5 + (src[0 ]+src[5 ]);\
+ tmp[3]= (src[3]+src[4])*20 - (src[2 ]+src[5])*5 + (src[1 ]+src[6 ]);\
+ tmp[4]= (src[4]+src[5])*20 - (src[3 ]+src[6])*5 + (src[2 ]+src[7 ]);\
+ tmp[5]= (src[5]+src[6])*20 - (src[4 ]+src[7])*5 + (src[3 ]+src[8 ]);\
+ tmp[6]= (src[6]+src[7])*20 - (src[5 ]+src[8])*5 + (src[4 ]+src[9 ]);\
+ tmp[7]= (src[7]+src[8])*20 - (src[6 ]+src[9])*5 + (src[5 ]+src[10]);\
+ tmp+=tmpStride;\
+ src+=srcStride;\
+ }\
+ tmp -= tmpStride*(h+5-2);\
+ for(i=0; i<w; i++)\
+ {\
+ const int tmpB= tmp[-2*tmpStride];\
+ const int tmpA= tmp[-1*tmpStride];\
+ const int tmp0= tmp[0 *tmpStride];\
+ const int tmp1= tmp[1 *tmpStride];\
+ const int tmp2= tmp[2 *tmpStride];\
+ const int tmp3= tmp[3 *tmpStride];\
+ const int tmp4= tmp[4 *tmpStride];\
+ const int tmp5= tmp[5 *tmpStride];\
+ const int tmp6= tmp[6 *tmpStride];\
+ const int tmp7= tmp[7 *tmpStride];\
+ const int tmp8= tmp[8 *tmpStride];\
+ const int tmp9= tmp[9 *tmpStride];\
+ const int tmp10=tmp[10*tmpStride];\
+ OP2(dst[0*dstStride], (tmp0+tmp1)*20 - (tmpA+tmp2)*5 + (tmpB+tmp3));\
+ OP2(dst[1*dstStride], (tmp1+tmp2)*20 - (tmp0+tmp3)*5 + (tmpA+tmp4));\
+ OP2(dst[2*dstStride], (tmp2+tmp3)*20 - (tmp1+tmp4)*5 + (tmp0+tmp5));\
+ OP2(dst[3*dstStride], (tmp3+tmp4)*20 - (tmp2+tmp5)*5 + (tmp1+tmp6));\
+ OP2(dst[4*dstStride], (tmp4+tmp5)*20 - (tmp3+tmp6)*5 + (tmp2+tmp7));\
+ OP2(dst[5*dstStride], (tmp5+tmp6)*20 - (tmp4+tmp7)*5 + (tmp3+tmp8));\
+ OP2(dst[6*dstStride], (tmp6+tmp7)*20 - (tmp5+tmp8)*5 + (tmp4+tmp9));\
+ OP2(dst[7*dstStride], (tmp7+tmp8)*20 - (tmp6+tmp9)*5 + (tmp5+tmp10));\
+ dst++;\
+ tmp++;\
+ }\
+}\
+\
+static void OPNAME ## h264_qpel16_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ OPNAME ## h264_qpel8_v_lowpass(dst , src , dstStride, srcStride);\
+ OPNAME ## h264_qpel8_v_lowpass(dst+8, src+8, dstStride, srcStride);\
+ src += 8*srcStride;\
+ dst += 8*dstStride;\
+ OPNAME ## h264_qpel8_v_lowpass(dst , src , dstStride, srcStride);\
+ OPNAME ## h264_qpel8_v_lowpass(dst+8, src+8, dstStride, srcStride);\
+}\
+\
+static void OPNAME ## h264_qpel16_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ OPNAME ## h264_qpel8_h_lowpass(dst , src , dstStride, srcStride);\
+ OPNAME ## h264_qpel8_h_lowpass(dst+8, src+8, dstStride, srcStride);\
+ src += 8*srcStride;\
+ dst += 8*dstStride;\
+ OPNAME ## h264_qpel8_h_lowpass(dst , src , dstStride, srcStride);\
+ OPNAME ## h264_qpel8_h_lowpass(dst+8, src+8, dstStride, srcStride);\
+}\
+\
+static void OPNAME ## h264_qpel16_hv_lowpass(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride){\
+ OPNAME ## h264_qpel8_hv_lowpass(dst , tmp , src , dstStride, tmpStride, srcStride);\
+ OPNAME ## h264_qpel8_hv_lowpass(dst+8, tmp+8, src+8, dstStride, tmpStride, srcStride);\
+ src += 8*srcStride;\
+ dst += 8*dstStride;\
+ OPNAME ## h264_qpel8_hv_lowpass(dst , tmp , src , dstStride, tmpStride, srcStride);\
+ OPNAME ## h264_qpel8_hv_lowpass(dst+8, tmp+8, src+8, dstStride, tmpStride, srcStride);\
+}\
+
+#define H264_MC(OPNAME, SIZE) \
+static void OPNAME ## h264_qpel ## SIZE ## _mc00_c (uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## pixels ## SIZE ## _c(dst, src, stride, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc10_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t half[SIZE*SIZE];\
+ put_h264_qpel ## SIZE ## _h_lowpass(half, src, SIZE, stride);\
+ OPNAME ## pixels ## SIZE ## _l2(dst, src, half, stride, stride, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc20_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## h264_qpel ## SIZE ## _h_lowpass(dst, src, stride, stride);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc30_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t half[SIZE*SIZE];\
+ put_h264_qpel ## SIZE ## _h_lowpass(half, src, SIZE, stride);\
+ OPNAME ## pixels ## SIZE ## _l2(dst, src+1, half, stride, stride, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc01_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ uint8_t half[SIZE*SIZE];\
+ copy_block ## SIZE (full, src - stride*2, SIZE, stride, SIZE + 5);\
+ put_h264_qpel ## SIZE ## _v_lowpass(half, full_mid, SIZE, SIZE);\
+ OPNAME ## pixels ## SIZE ## _l2(dst, full_mid, half, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc02_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ copy_block ## SIZE (full, src - stride*2, SIZE, stride, SIZE + 5);\
+ OPNAME ## h264_qpel ## SIZE ## _v_lowpass(dst, full_mid, stride, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc03_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ uint8_t half[SIZE*SIZE];\
+ copy_block ## SIZE (full, src - stride*2, SIZE, stride, SIZE + 5);\
+ put_h264_qpel ## SIZE ## _v_lowpass(half, full_mid, SIZE, SIZE);\
+ OPNAME ## pixels ## SIZE ## _l2(dst, full_mid+SIZE, half, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc11_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ uint8_t halfH[SIZE*SIZE];\
+ uint8_t halfV[SIZE*SIZE];\
+ put_h264_qpel ## SIZE ## _h_lowpass(halfH, src, SIZE, stride);\
+ copy_block ## SIZE (full, src - stride*2, SIZE, stride, SIZE + 5);\
+ put_h264_qpel ## SIZE ## _v_lowpass(halfV, full_mid, SIZE, SIZE);\
+ OPNAME ## pixels ## SIZE ## _l2(dst, halfH, halfV, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc31_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ uint8_t halfH[SIZE*SIZE];\
+ uint8_t halfV[SIZE*SIZE];\
+ put_h264_qpel ## SIZE ## _h_lowpass(halfH, src, SIZE, stride);\
+ copy_block ## SIZE (full, src - stride*2 + 1, SIZE, stride, SIZE + 5);\
+ put_h264_qpel ## SIZE ## _v_lowpass(halfV, full_mid, SIZE, SIZE);\
+ OPNAME ## pixels ## SIZE ## _l2(dst, halfH, halfV, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc13_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ uint8_t halfH[SIZE*SIZE];\
+ uint8_t halfV[SIZE*SIZE];\
+ put_h264_qpel ## SIZE ## _h_lowpass(halfH, src + stride, SIZE, stride);\
+ copy_block ## SIZE (full, src - stride*2, SIZE, stride, SIZE + 5);\
+ put_h264_qpel ## SIZE ## _v_lowpass(halfV, full_mid, SIZE, SIZE);\
+ OPNAME ## pixels ## SIZE ## _l2(dst, halfH, halfV, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc33_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ uint8_t halfH[SIZE*SIZE];\
+ uint8_t halfV[SIZE*SIZE];\
+ put_h264_qpel ## SIZE ## _h_lowpass(halfH, src + stride, SIZE, stride);\
+ copy_block ## SIZE (full, src - stride*2 + 1, SIZE, stride, SIZE + 5);\
+ put_h264_qpel ## SIZE ## _v_lowpass(halfV, full_mid, SIZE, SIZE);\
+ OPNAME ## pixels ## SIZE ## _l2(dst, halfH, halfV, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc22_c(uint8_t *dst, uint8_t *src, int stride){\
+ int16_t tmp[SIZE*(SIZE+5)];\
+ OPNAME ## h264_qpel ## SIZE ## _hv_lowpass(dst, tmp, src, stride, SIZE, stride);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc21_c(uint8_t *dst, uint8_t *src, int stride){\
+ int16_t tmp[SIZE*(SIZE+5)];\
+ uint8_t halfH[SIZE*SIZE];\
+ uint8_t halfHV[SIZE*SIZE];\
+ put_h264_qpel ## SIZE ## _h_lowpass(halfH, src, SIZE, stride);\
+ put_h264_qpel ## SIZE ## _hv_lowpass(halfHV, tmp, src, SIZE, SIZE, stride);\
+ OPNAME ## pixels ## SIZE ## _l2(dst, halfH, halfHV, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc23_c(uint8_t *dst, uint8_t *src, int stride){\
+ int16_t tmp[SIZE*(SIZE+5)];\
+ uint8_t halfH[SIZE*SIZE];\
+ uint8_t halfHV[SIZE*SIZE];\
+ put_h264_qpel ## SIZE ## _h_lowpass(halfH, src + stride, SIZE, stride);\
+ put_h264_qpel ## SIZE ## _hv_lowpass(halfHV, tmp, src, SIZE, SIZE, stride);\
+ OPNAME ## pixels ## SIZE ## _l2(dst, halfH, halfHV, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc12_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ int16_t tmp[SIZE*(SIZE+5)];\
+ uint8_t halfV[SIZE*SIZE];\
+ uint8_t halfHV[SIZE*SIZE];\
+ copy_block ## SIZE (full, src - stride*2, SIZE, stride, SIZE + 5);\
+ put_h264_qpel ## SIZE ## _v_lowpass(halfV, full_mid, SIZE, SIZE);\
+ put_h264_qpel ## SIZE ## _hv_lowpass(halfHV, tmp, src, SIZE, SIZE, stride);\
+ OPNAME ## pixels ## SIZE ## _l2(dst, halfV, halfHV, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc32_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ int16_t tmp[SIZE*(SIZE+5)];\
+ uint8_t halfV[SIZE*SIZE];\
+ uint8_t halfHV[SIZE*SIZE];\
+ copy_block ## SIZE (full, src - stride*2 + 1, SIZE, stride, SIZE + 5);\
+ put_h264_qpel ## SIZE ## _v_lowpass(halfV, full_mid, SIZE, SIZE);\
+ put_h264_qpel ## SIZE ## _hv_lowpass(halfHV, tmp, src, SIZE, SIZE, stride);\
+ OPNAME ## pixels ## SIZE ## _l2(dst, halfV, halfHV, stride, SIZE, SIZE, SIZE);\
+}\
+
+#define op_avg(a, b) a = (((a)+cm[((b) + 16)>>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 = cm[((b) + 16)>>5]
+#define op2_avg(a, b) a = (((a)+cm[((b) + 512)>>10]+1)>>1)
+#define op2_put(a, b) a = cm[((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
+#endif
+
+#define op_scale1(x) block[x] = clip_uint8( (block[x]*weight + offset) >> log2_denom )
+#define op_scale2(x) dst[x] = clip_uint8( (src[x]*weights + dst[x]*weightd + offset) >> (log2_denom+1))
+#define H264_WEIGHT(W,H) \
+static void weight_h264_pixels ## W ## x ## H ## _c(uint8_t *block, int stride, int log2_denom, int weight, int offset){ \
+ int y; \
+ offset <<= log2_denom; \
+ if(log2_denom) offset += 1<<(log2_denom-1); \
+ for(y=0; y<H; 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 biweight_h264_pixels ## W ## x ## H ## _c(uint8_t *dst, uint8_t *src, int stride, int log2_denom, int weightd, int weights, int offset){ \
+ int y; \
+ offset = ((offset + 1) | 1) << log2_denom; \
+ for(y=0; y<H; 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,16)
+H264_WEIGHT(16,8)
+H264_WEIGHT(8,16)
+H264_WEIGHT(8,8)
+H264_WEIGHT(8,4)
+H264_WEIGHT(4,8)
+H264_WEIGHT(4,4)
+H264_WEIGHT(4,2)
+H264_WEIGHT(2,4)
+H264_WEIGHT(2,2)
+
+#undef op_scale1
+#undef op_scale2
+#undef H264_WEIGHT
+
+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<h; i++){
+ dst[0]= cm[(9*(src[0] + src[1]) - (src[-1] + src[2]) + 8)>>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;
+ }
+}
+
+#ifdef CONFIG_CAVS_DECODER
+/* AVS specific */
+void ff_cavsdsp_init(DSPContext* c, AVCodecContext *avctx);
+
+void ff_put_cavs_qpel8_mc00_c(uint8_t *dst, uint8_t *src, int stride) {
+ put_pixels8_c(dst, src, stride, 8);
+}
+void ff_avg_cavs_qpel8_mc00_c(uint8_t *dst, uint8_t *src, int stride) {
+ avg_pixels8_c(dst, src, stride, 8);
+}
+void ff_put_cavs_qpel16_mc00_c(uint8_t *dst, uint8_t *src, int stride) {
+ put_pixels16_c(dst, src, stride, 16);
+}
+void ff_avg_cavs_qpel16_mc00_c(uint8_t *dst, uint8_t *src, int stride) {
+ avg_pixels16_c(dst, src, stride, 16);
+}
+#endif /* CONFIG_CAVS_DECODER */
+
+#if defined(CONFIG_VC1_DECODER) || defined(CONFIG_WMV3_DECODER)
+/* VC-1 specific */
+void ff_vc1dsp_init(DSPContext* c, AVCodecContext *avctx);
+
+void ff_put_vc1_mspel_mc00_c(uint8_t *dst, uint8_t *src, int stride, int rnd) {
+ put_pixels8_c(dst, src, stride, 8);
+}
+#endif /* CONFIG_VC1_DECODER||CONFIG_WMV3_DECODER */
+
+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<w; i++){
+ const int src_1= src[ -srcStride];
+ const int src0 = src[0 ];
+ const int src1 = src[ 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];
+ dst[0*dstStride]= cm[(9*(src0 + src1) - (src_1 + src2) + 8)>>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_mc00_c (uint8_t *dst, uint8_t *src, int stride){
+ put_pixels8_c(dst, src, stride, 8);
+}
+
+static void put_mspel8_mc10_c(uint8_t *dst, uint8_t *src, int stride){
+ uint8_t half[64];
+ wmv2_mspel8_h_lowpass(half, src, 8, stride, 8);
+ put_pixels8_l2(dst, src, half, stride, stride, 8, 8);
+}
+
+static void put_mspel8_mc20_c(uint8_t *dst, uint8_t *src, int stride){
+ wmv2_mspel8_h_lowpass(dst, src, stride, stride, 8);
+}
+
+static void put_mspel8_mc30_c(uint8_t *dst, uint8_t *src, int stride){
+ uint8_t half[64];
+ wmv2_mspel8_h_lowpass(half, src, 8, stride, 8);
+ put_pixels8_l2(dst, src+1, half, stride, stride, 8, 8);
+}
+
+static void put_mspel8_mc02_c(uint8_t *dst, uint8_t *src, int stride){
+ wmv2_mspel8_v_lowpass(dst, src, stride, stride, 8);
+}
+
+static void put_mspel8_mc12_c(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(dst, halfV, halfHV, stride, 8, 8, 8);
+}
+static void put_mspel8_mc32_c(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(dst, halfV, halfHV, stride, 8, 8, 8);
+}
+static void put_mspel8_mc22_c(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);
+}
+
+static void h263_v_loop_filter_c(uint8_t *src, int stride, int qscale){
+ 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= 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){
+ 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= 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 void h264_loop_filter_luma_c(uint8_t *pix, int xstride, int ystride, int alpha, int beta, int8_t *tc0)
+{
+ int i, d;
+ for( i = 0; i < 4; i++ ) {
+ if( tc0[i] < 0 ) {
+ pix += 4*ystride;
+ continue;
+ }
+ for( d = 0; d < 4; 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 = tc0[i];
+ int i_delta;
+
+ if( FFABS( p2 - p0 ) < beta ) {
+ pix[-2*xstride] = p1 + clip( (( p2 + ( ( p0 + q0 + 1 ) >> 1 ) ) >> 1) - p1, -tc0[i], tc0[i] );
+ tc++;
+ }
+ if( FFABS( q2 - q0 ) < beta ) {
+ pix[ xstride] = q1 + clip( (( q2 + ( ( p0 + q0 + 1 ) >> 1 ) ) >> 1) - q1, -tc0[i], tc0[i] );
+ tc++;
+ }
+
+ i_delta = clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
+ pix[-xstride] = clip_uint8( p0 + i_delta ); /* p0' */
+ pix[0] = clip_uint8( q0 - i_delta ); /* q0' */
+ }
+ pix += ystride;
+ }
+ }
+}
+static void h264_v_loop_filter_luma_c(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0)
+{
+ h264_loop_filter_luma_c(pix, stride, 1, alpha, beta, tc0);
+}
+static void h264_h_loop_filter_luma_c(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0)
+{
+ h264_loop_filter_luma_c(pix, 1, stride, alpha, beta, tc0);
+}
+
+static inline void h264_loop_filter_chroma_c(uint8_t *pix, int xstride, int ystride, int alpha, int beta, int8_t *tc0)
+{
+ int i, d;
+ for( i = 0; i < 4; i++ ) {
+ const int tc = tc0[i];
+ if( tc <= 0 ) {
+ pix += 2*ystride;
+ continue;
+ }
+ for( d = 0; d < 2; 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 = clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
+
+ pix[-xstride] = clip_uint8( p0 + delta ); /* p0' */
+ pix[0] = clip_uint8( q0 - delta ); /* q0' */
+ }
+ pix += ystride;
+ }
+ }
+}
+static void h264_v_loop_filter_chroma_c(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0)
+{
+ h264_loop_filter_chroma_c(pix, stride, 1, alpha, beta, tc0);
+}
+static void h264_h_loop_filter_chroma_c(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0)
+{
+ h264_loop_filter_chroma_c(pix, 1, stride, alpha, beta, tc0);
+}
+
+static inline void h264_loop_filter_chroma_intra_c(uint8_t *pix, int xstride, int ystride, int alpha, int beta)
+{
+ int d;
+ for( d = 0; d < 8; 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 h264_v_loop_filter_chroma_intra_c(uint8_t *pix, int stride, int alpha, int beta)
+{
+ h264_loop_filter_chroma_intra_c(pix, stride, 1, alpha, beta);
+}
+static void h264_h_loop_filter_chroma_intra_c(uint8_t *pix, int stride, int alpha, int beta)
+{
+ h264_loop_filter_chroma_intra_c(pix, 1, stride, alpha, beta);
+}
+
+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;i<h;i++) {
+ s += abs(pix1[0] - pix2[0]);
+ s += abs(pix1[1] - pix2[1]);
+ s += abs(pix1[2] - pix2[2]);
+ s += abs(pix1[3] - pix2[3]);
+ s += abs(pix1[4] - pix2[4]);
+ s += abs(pix1[5] - pix2[5]);
+ s += abs(pix1[6] - pix2[6]);
+ s += abs(pix1[7] - pix2[7]);
+ s += abs(pix1[8] - pix2[8]);
+ s += abs(pix1[9] - pix2[9]);
+ s += abs(pix1[10] - pix2[10]);
+ s += abs(pix1[11] - pix2[11]);
+ s += abs(pix1[12] - pix2[12]);
+ s += abs(pix1[13] - pix2[13]);
+ s += abs(pix1[14] - pix2[14]);
+ s += abs(pix1[15] - pix2[15]);
+ pix1 += line_size;
+ pix2 += line_size;
+ }
+ return s;
+}
+
+static int pix_abs16_x2_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+{
+ int s, i;
+
+ s = 0;
+ for(i=0;i<h;i++) {
+ s += abs(pix1[0] - avg2(pix2[0], pix2[1]));
+ s += abs(pix1[1] - avg2(pix2[1], pix2[2]));
+ s += abs(pix1[2] - avg2(pix2[2], pix2[3]));
+ s += abs(pix1[3] - avg2(pix2[3], pix2[4]));
+ s += abs(pix1[4] - avg2(pix2[4], pix2[5]));
+ s += abs(pix1[5] - avg2(pix2[5], pix2[6]));
+ s += abs(pix1[6] - avg2(pix2[6], pix2[7]));
+ s += abs(pix1[7] - avg2(pix2[7], pix2[8]));
+ s += abs(pix1[8] - avg2(pix2[8], pix2[9]));
+ s += abs(pix1[9] - avg2(pix2[9], pix2[10]));
+ s += abs(pix1[10] - avg2(pix2[10], pix2[11]));
+ s += abs(pix1[11] - avg2(pix2[11], pix2[12]));
+ s += abs(pix1[12] - avg2(pix2[12], pix2[13]));
+ s += abs(pix1[13] - avg2(pix2[13], pix2[14]));
+ s += abs(pix1[14] - avg2(pix2[14], pix2[15]));
+ s += abs(pix1[15] - avg2(pix2[15], pix2[16]));
+ pix1 += line_size;
+ pix2 += line_size;
+ }
+ return s;
+}
+
+static int pix_abs16_y2_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+{
+ int s, i;
+ uint8_t *pix3 = pix2 + line_size;
+
+ s = 0;
+ for(i=0;i<h;i++) {
+ s += abs(pix1[0] - avg2(pix2[0], pix3[0]));
+ s += abs(pix1[1] - avg2(pix2[1], pix3[1]));
+ s += abs(pix1[2] - avg2(pix2[2], pix3[2]));
+ s += abs(pix1[3] - avg2(pix2[3], pix3[3]));
+ s += abs(pix1[4] - avg2(pix2[4], pix3[4]));
+ s += abs(pix1[5] - avg2(pix2[5], pix3[5]));
+ s += abs(pix1[6] - avg2(pix2[6], pix3[6]));
+ s += abs(pix1[7] - avg2(pix2[7], pix3[7]));
+ s += abs(pix1[8] - avg2(pix2[8], pix3[8]));
+ s += abs(pix1[9] - avg2(pix2[9], pix3[9]));
+ s += abs(pix1[10] - avg2(pix2[10], pix3[10]));
+ s += abs(pix1[11] - avg2(pix2[11], pix3[11]));
+ s += abs(pix1[12] - avg2(pix2[12], pix3[12]));
+ s += abs(pix1[13] - avg2(pix2[13], pix3[13]));
+ s += abs(pix1[14] - avg2(pix2[14], pix3[14]));
+ s += abs(pix1[15] - avg2(pix2[15], pix3[15]));
+ pix1 += line_size;
+ pix2 += line_size;
+ pix3 += line_size;
+ }
+ return s;
+}
+
+static int pix_abs16_xy2_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+{
+ int s, i;
+ uint8_t *pix3 = pix2 + line_size;
+
+ s = 0;
+ for(i=0;i<h;i++) {
+ s += abs(pix1[0] - avg4(pix2[0], pix2[1], pix3[0], pix3[1]));
+ s += abs(pix1[1] - avg4(pix2[1], pix2[2], pix3[1], pix3[2]));
+ s += abs(pix1[2] - avg4(pix2[2], pix2[3], pix3[2], pix3[3]));
+ s += abs(pix1[3] - avg4(pix2[3], pix2[4], pix3[3], pix3[4]));
+ s += abs(pix1[4] - avg4(pix2[4], pix2[5], pix3[4], pix3[5]));
+ s += abs(pix1[5] - avg4(pix2[5], pix2[6], pix3[5], pix3[6]));
+ s += abs(pix1[6] - avg4(pix2[6], pix2[7], pix3[6], pix3[7]));
+ s += abs(pix1[7] - avg4(pix2[7], pix2[8], pix3[7], pix3[8]));
+ s += abs(pix1[8] - avg4(pix2[8], pix2[9], pix3[8], pix3[9]));
+ s += abs(pix1[9] - avg4(pix2[9], pix2[10], pix3[9], pix3[10]));
+ s += abs(pix1[10] - avg4(pix2[10], pix2[11], pix3[10], pix3[11]));
+ s += abs(pix1[11] - avg4(pix2[11], pix2[12], pix3[11], pix3[12]));
+ s += abs(pix1[12] - avg4(pix2[12], pix2[13], pix3[12], pix3[13]));
+ s += abs(pix1[13] - avg4(pix2[13], pix2[14], pix3[13], pix3[14]));
+ s += abs(pix1[14] - avg4(pix2[14], pix2[15], pix3[14], pix3[15]));
+ s += abs(pix1[15] - avg4(pix2[15], pix2[16], pix3[15], pix3[16]));
+ pix1 += line_size;
+ pix2 += line_size;
+ pix3 += line_size;
+ }
+ return s;
+}
+
+static inline int pix_abs8_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+{
+ int s, i;
+
+ s = 0;
+ for(i=0;i<h;i++) {
+ s += abs(pix1[0] - pix2[0]);
+ s += abs(pix1[1] - pix2[1]);
+ s += abs(pix1[2] - pix2[2]);
+ s += abs(pix1[3] - pix2[3]);
+ s += abs(pix1[4] - pix2[4]);
+ s += abs(pix1[5] - pix2[5]);
+ s += abs(pix1[6] - pix2[6]);
+ s += abs(pix1[7] - pix2[7]);
+ pix1 += line_size;
+ pix2 += line_size;
+ }
+ return s;
+}
+
+static int pix_abs8_x2_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+{
+ int s, i;
+
+ s = 0;
+ for(i=0;i<h;i++) {
+ s += abs(pix1[0] - avg2(pix2[0], pix2[1]));
+ s += abs(pix1[1] - avg2(pix2[1], pix2[2]));
+ s += abs(pix1[2] - avg2(pix2[2], pix2[3]));
+ s += abs(pix1[3] - avg2(pix2[3], pix2[4]));
+ s += abs(pix1[4] - avg2(pix2[4], pix2[5]));
+ s += abs(pix1[5] - avg2(pix2[5], pix2[6]));
+ s += abs(pix1[6] - avg2(pix2[6], pix2[7]));
+ s += abs(pix1[7] - avg2(pix2[7], pix2[8]));
+ pix1 += line_size;
+ pix2 += line_size;
+ }
+ return s;
+}
+
+static int pix_abs8_y2_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+{
+ int s, i;
+ uint8_t *pix3 = pix2 + line_size;
+
+ s = 0;
+ for(i=0;i<h;i++) {
+ s += abs(pix1[0] - avg2(pix2[0], pix3[0]));
+ s += abs(pix1[1] - avg2(pix2[1], pix3[1]));
+ s += abs(pix1[2] - avg2(pix2[2], pix3[2]));
+ s += abs(pix1[3] - avg2(pix2[3], pix3[3]));
+ s += abs(pix1[4] - avg2(pix2[4], pix3[4]));
+ s += abs(pix1[5] - avg2(pix2[5], pix3[5]));
+ s += abs(pix1[6] - avg2(pix2[6], pix3[6]));
+ s += abs(pix1[7] - avg2(pix2[7], pix3[7]));
+ pix1 += line_size;
+ pix2 += line_size;
+ pix3 += line_size;
+ }
+ return s;
+}
+
+static int pix_abs8_xy2_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+{
+ int s, i;
+ uint8_t *pix3 = pix2 + line_size;
+
+ s = 0;
+ for(i=0;i<h;i++) {
+ s += abs(pix1[0] - avg4(pix2[0], pix2[1], pix3[0], pix3[1]));
+ s += abs(pix1[1] - avg4(pix2[1], pix2[2], pix3[1], pix3[2]));
+ s += abs(pix1[2] - avg4(pix2[2], pix2[3], pix3[2], pix3[3]));
+ s += abs(pix1[3] - avg4(pix2[3], pix2[4], pix3[3], pix3[4]));
+ s += abs(pix1[4] - avg4(pix2[4], pix2[5], pix3[4], pix3[5]));
+ s += abs(pix1[5] - avg4(pix2[5], pix2[6], pix3[5], pix3[6]));
+ s += abs(pix1[6] - avg4(pix2[6], pix2[7], pix3[6], pix3[7]));
+ s += abs(pix1[7] - avg4(pix2[7], pix2[8], pix3[7], pix3[8]));
+ pix1 += line_size;
+ pix2 += line_size;
+ pix3 += line_size;
+ }
+ return s;
+}
+
+static int nsse16_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; y<h; y++){
+ for(x=0; x<16; x++){
+ score1+= (s1[x ] - s2[x ])*(s1[x ] - s2[x ]);
+ }
+ if(y+1<h){
+ for(x=0; x<15; x++){
+ score2+= FFABS( s1[x ] - s1[x +stride]
+ - s1[x+1] + s1[x+1+stride])
+ -FFABS( s2[x ] - s2[x +stride]
+ - s2[x+1] + s2[x+1+stride]);
+ }
+ }
+ s1+= stride;
+ s2+= stride;
+ }
+
+ if(c) return score1 + FFABS(score2)*c->avctx->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; y<h; y++){
+ for(x=0; x<8; x++){
+ score1+= (s1[x ] - s2[x ])*(s1[x ] - s2[x ]);
+ }
+ if(y+1<h){
+ for(x=0; x<7; x++){
+ score2+= FFABS( s1[x ] - s1[x +stride]
+ - s1[x+1] + s1[x+1+stride])
+ -FFABS( s2[x ] - s2[x +stride]
+ - s2[x+1] + s2[x+1+stride]);
+ }
+ }
+ s1+= stride;
+ s2+= stride;
+ }
+
+ if(c) return score1 + FFABS(score2)*c->avctx->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;
+ assert(-512<b && b<512);
+
+ sum += (w*b)*(w*b)>>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);
+ }
+}
+
+/**
+ * permutes 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(DCTELEM *block, uint8_t *permutation, const uint8_t *scantable, int last)
+{
+ int i;
+ DCTELEM temp[64];
+
+ if(last<=0) return;
+ //if(permutation[1]==1) return; //FIXME its ok but not clean and might fail for some perms
+
+ 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];
+ }
+}
+
+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*)*5);
+
+ for(i=0; i<5; 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;
+#ifdef CONFIG_SNOW_ENCODER
+ 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");
+ }
+ }
+}
+
+/**
+ * memset(blocks, 0, sizeof(DCTELEM)*6*64)
+ */
+static void clear_blocks_c(DCTELEM *blocks)
+{
+ memset(blocks, 0, sizeof(DCTELEM)*6*64);
+}
+
+static void add_bytes_c(uint8_t *dst, uint8_t *src, int w){
+ int i;
+ for(i=0; i+7<w; i+=8){
+ dst[i+0] += src[i+0];
+ dst[i+1] += src[i+1];
+ dst[i+2] += src[i+2];
+ dst[i+3] += src[i+3];
+ dst[i+4] += src[i+4];
+ dst[i+5] += src[i+5];
+ dst[i+6] += src[i+6];
+ dst[i+7] += src[i+7];
+ }
+ for(; i<w; i++)
+ dst[i+0] += src[i+0];
+}
+
+static void diff_bytes_c(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w){
+ int i;
+ for(i=0; i+7<w; i+=8){
+ dst[i+0] = src1[i+0]-src2[i+0];
+ dst[i+1] = src1[i+1]-src2[i+1];
+ dst[i+2] = src1[i+2]-src2[i+2];
+ dst[i+3] = src1[i+3]-src2[i+3];
+ dst[i+4] = src1[i+4]-src2[i+4];
+ dst[i+5] = src1[i+5]-src2[i+5];
+ dst[i+6] = src1[i+6]-src2[i+6];
+ dst[i+7] = src1[i+7]-src2[i+7];
+ }
+ for(; i<w; i++)
+ dst[i+0] = src1[i+0]-src2[i+0];
+}
+
+static void sub_hfyu_median_prediction_c(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w, int *left, int *left_top){
+ int i;
+ uint8_t l, lt;
+
+ l= *left;
+ lt= *left_top;
+
+ for(i=0; i<w; i++){
+ const int pred= mid_pred(l, src1[i], (l + src1[i] - lt)&0xFF);
+ lt= src1[i];
+ l= src2[i];
+ dst[i]= l - pred;
+ }
+
+ *left= l;
+ *left_top= lt;
+}
+
+#define BUTTERFLY2(o1,o2,i1,i2) \
+o1= (i1)+(i2);\
+o2= (i1)-(i2);
+
+#define BUTTERFLY1(x,y) \
+{\
+ int a,b;\
+ a= x;\
+ b= y;\
+ x= a+b;\
+ y= a-b;\
+}
+
+#define BUTTERFLYA(x,y) (FFABS((x)+(y)) + FFABS((x)-(y)))
+
+static int hadamard8_diff8x8_c(/*MpegEncContext*/ void *s, uint8_t *dst, uint8_t *src, int stride, int h){
+ int i;
+ int temp[64];
+ int sum=0;
+
+ assert(h==8);
+
+ for(i=0; i<8; i++){
+ //FIXME try pointer walks
+ BUTTERFLY2(temp[8*i+0], temp[8*i+1], src[stride*i+0]-dst[stride*i+0],src[stride*i+1]-dst[stride*i+1]);
+ BUTTERFLY2(temp[8*i+2], temp[8*i+3], src[stride*i+2]-dst[stride*i+2],src[stride*i+3]-dst[stride*i+3]);
+ BUTTERFLY2(temp[8*i+4], temp[8*i+5], src[stride*i+4]-dst[stride*i+4],src[stride*i+5]-dst[stride*i+5]);
+ BUTTERFLY2(temp[8*i+6], temp[8*i+7], src[stride*i+6]-dst[stride*i+6],src[stride*i+7]-dst[stride*i+7]);
+
+ BUTTERFLY1(temp[8*i+0], temp[8*i+2]);
+ BUTTERFLY1(temp[8*i+1], temp[8*i+3]);
+ BUTTERFLY1(temp[8*i+4], temp[8*i+6]);
+ BUTTERFLY1(temp[8*i+5], temp[8*i+7]);
+
+ BUTTERFLY1(temp[8*i+0], temp[8*i+4]);
+ BUTTERFLY1(temp[8*i+1], temp[8*i+5]);
+ BUTTERFLY1(temp[8*i+2], temp[8*i+6]);
+ BUTTERFLY1(temp[8*i+3], temp[8*i+7]);
+ }
+
+ for(i=0; i<8; i++){
+ BUTTERFLY1(temp[8*0+i], temp[8*1+i]);
+ BUTTERFLY1(temp[8*2+i], temp[8*3+i]);
+ BUTTERFLY1(temp[8*4+i], temp[8*5+i]);
+ BUTTERFLY1(temp[8*6+i], temp[8*7+i]);
+
+ BUTTERFLY1(temp[8*0+i], temp[8*2+i]);
+ BUTTERFLY1(temp[8*1+i], temp[8*3+i]);
+ BUTTERFLY1(temp[8*4+i], temp[8*6+i]);
+ BUTTERFLY1(temp[8*5+i], temp[8*7+i]);
+
+ sum +=
+ BUTTERFLYA(temp[8*0+i], temp[8*4+i])
+ +BUTTERFLYA(temp[8*1+i], temp[8*5+i])
+ +BUTTERFLYA(temp[8*2+i], temp[8*6+i])
+ +BUTTERFLYA(temp[8*3+i], temp[8*7+i]);
+ }
+#if 0
+static int maxi=0;
+if(sum>maxi){
+ maxi=sum;
+ printf("MAX:%d\n", maxi);
+}
+#endif
+ return sum;
+}
+
+static int hadamard8_intra8x8_c(/*MpegEncContext*/ void *s, uint8_t *src, uint8_t *dummy, int stride, int h){
+ int i;
+ int temp[64];
+ int sum=0;
+
+ assert(h==8);
+
+ for(i=0; i<8; i++){
+ //FIXME try pointer walks
+ BUTTERFLY2(temp[8*i+0], temp[8*i+1], src[stride*i+0],src[stride*i+1]);
+ BUTTERFLY2(temp[8*i+2], temp[8*i+3], src[stride*i+2],src[stride*i+3]);
+ BUTTERFLY2(temp[8*i+4], temp[8*i+5], src[stride*i+4],src[stride*i+5]);
+ BUTTERFLY2(temp[8*i+6], temp[8*i+7], src[stride*i+6],src[stride*i+7]);
+
+ BUTTERFLY1(temp[8*i+0], temp[8*i+2]);
+ BUTTERFLY1(temp[8*i+1], temp[8*i+3]);
+ BUTTERFLY1(temp[8*i+4], temp[8*i+6]);
+ BUTTERFLY1(temp[8*i+5], temp[8*i+7]);
+
+ BUTTERFLY1(temp[8*i+0], temp[8*i+4]);
+ BUTTERFLY1(temp[8*i+1], temp[8*i+5]);
+ BUTTERFLY1(temp[8*i+2], temp[8*i+6]);
+ BUTTERFLY1(temp[8*i+3], temp[8*i+7]);
+ }
+
+ for(i=0; i<8; i++){
+ BUTTERFLY1(temp[8*0+i], temp[8*1+i]);
+ BUTTERFLY1(temp[8*2+i], temp[8*3+i]);
+ BUTTERFLY1(temp[8*4+i], temp[8*5+i]);
+ BUTTERFLY1(temp[8*6+i], temp[8*7+i]);
+
+ BUTTERFLY1(temp[8*0+i], temp[8*2+i]);
+ BUTTERFLY1(temp[8*1+i], temp[8*3+i]);
+ BUTTERFLY1(temp[8*4+i], temp[8*6+i]);
+ BUTTERFLY1(temp[8*5+i], temp[8*7+i]);
+
+ sum +=
+ BUTTERFLYA(temp[8*0+i], temp[8*4+i])
+ +BUTTERFLYA(temp[8*1+i], temp[8*5+i])
+ +BUTTERFLYA(temp[8*2+i], temp[8*6+i])
+ +BUTTERFLYA(temp[8*3+i], temp[8*7+i]);
+ }
+
+ sum -= FFABS(temp[8*0] + temp[8*4]); // -mean
+
+ return sum;
+}
+
+static int dct_sad8x8_c(/*MpegEncContext*/ void *c, uint8_t *src1, uint8_t *src2, int stride, int h){
+ MpegEncContext * const s= (MpegEncContext *)c;
+ DECLARE_ALIGNED_8(uint64_t, aligned_temp[sizeof(DCTELEM)*64/8]);
+ DCTELEM * const temp= (DCTELEM*)aligned_temp;
+ int sum=0, i;
+
+ assert(h==8);
+
+ s->dsp.diff_pixels(temp, src1, src2, stride);
+ s->dsp.fdct(temp);
+
+ for(i=0; i<64; i++)
+ sum+= FFABS(temp[i]);
+
+ return sum;
+}
+
+#ifdef 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, 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;
+ DECLARE_ALIGNED_8(uint64_t, aligned_temp[sizeof(DCTELEM)*64/8]);
+ DCTELEM * const temp= (DCTELEM*)aligned_temp;
+ int sum=0, i;
+
+ assert(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;
+ DECLARE_ALIGNED_8 (uint64_t, aligned_temp[sizeof(DCTELEM)*64*2/8]);
+ DCTELEM * const temp= (DCTELEM*)aligned_temp;
+ DCTELEM * const bak = ((DCTELEM*)aligned_temp)+64;
+ int sum=0, i;
+
+ assert(h==8);
+ s->mb_intra=0;
+
+ s->dsp.diff_pixels(temp, src1, src2, stride);
+
+ memcpy(bak, temp, 64*sizeof(DCTELEM));
+
+ 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);
+ simple_idct(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;
+ DECLARE_ALIGNED_8 (uint64_t, aligned_temp[sizeof(DCTELEM)*64/8]);
+ DECLARE_ALIGNED_8 (uint64_t, aligned_bak[stride]);
+ DCTELEM * const temp= (DCTELEM*)aligned_temp;
+ uint8_t * const bak= (uint8_t*)aligned_bak;
+ int i, last, run, bits, level, distoration, start_i;
+ const int esc_length= s->ac_esc_length;
+ uint8_t * length;
+ uint8_t * last_length;
+
+ assert(h==8);
+
+ for(i=0; i<8; i++){
+ ((uint32_t*)(bak + i*stride))[0]= ((uint32_t*)(src2 + i*stride))[0];
+ ((uint32_t*)(bak + i*stride))[1]= ((uint32_t*)(src2 + i*stride))[1];
+ }
+
+ 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<last; i++){
+ int j= scantable[i];
+ level= temp[j];
+
+ if(level){
+ level+=64;
+ if((level&(~127)) == 0){
+ bits+= length[UNI_AC_ENC_INDEX(run, level)];
+ }else
+ bits+= esc_length;
+ run=0;
+ }else
+ run++;
+ }
+ i= scantable[last];
+
+ level= temp[i] + 64;
+
+ assert(level - 64);
+
+ if((level&(~127)) == 0){
+ bits+= last_length[UNI_AC_ENC_INDEX(run, level)];
+ }else
+ bits+= esc_length;
+
+ }
+
+ if(last>=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(bak, stride, temp);
+
+ distoration= s->dsp.sse[1](NULL, bak, src1, stride, 8);
+
+ return distoration + ((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;
+ DECLARE_ALIGNED_8 (uint64_t, aligned_temp[sizeof(DCTELEM)*64/8]);
+ DCTELEM * const temp= (DCTELEM*)aligned_temp;
+ int i, last, run, bits, level, start_i;
+ const int esc_length= s->ac_esc_length;
+ uint8_t * length;
+ uint8_t * last_length;
+
+ assert(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<last; i++){
+ int j= scantable[i];
+ level= temp[j];
+
+ if(level){
+ level+=64;
+ if((level&(~127)) == 0){
+ bits+= length[UNI_AC_ENC_INDEX(run, level)];
+ }else
+ bits+= esc_length;
+ run=0;
+ }else
+ run++;
+ }
+ i= scantable[last];
+
+ level= temp[i] + 64;
+
+ assert(level - 64);
+
+ if((level&(~127)) == 0){
+ bits+= last_length[UNI_AC_ENC_INDEX(run, level)];
+ }else
+ bits+= esc_length;
+ }
+
+ return bits;
+}
+
+static int vsad_intra16_c(/*MpegEncContext*/ void *c, uint8_t *s, uint8_t *dummy, int stride, int h){
+ int score=0;
+ int x,y;
+
+ for(y=1; y<h; y++){
+ for(x=0; x<16; x+=4){
+ score+= FFABS(s[x ] - s[x +stride]) + FFABS(s[x+1] - s[x+1+stride])
+ +FFABS(s[x+2] - s[x+2+stride]) + FFABS(s[x+3] - s[x+3+stride]);
+ }
+ s+= stride;
+ }
+
+ return score;
+}
+
+static int vsad16_c(/*MpegEncContext*/ void *c, uint8_t *s1, uint8_t *s2, int stride, int h){
+ int score=0;
+ int x,y;
+
+ for(y=1; y<h; y++){
+ for(x=0; x<16; x++){
+ score+= FFABS(s1[x ] - s2[x ] - s1[x +stride] + s2[x +stride]);
+ }
+ s1+= stride;
+ s2+= stride;
+ }
+
+ return score;
+}
+
+#define SQ(a) ((a)*(a))
+static int vsse_intra16_c(/*MpegEncContext*/ void *c, uint8_t *s, uint8_t *dummy, int stride, int h){
+ int score=0;
+ int x,y;
+
+ for(y=1; y<h; y++){
+ for(x=0; x<16; x+=4){
+ score+= SQ(s[x ] - s[x +stride]) + SQ(s[x+1] - s[x+1+stride])
+ +SQ(s[x+2] - s[x+2+stride]) + SQ(s[x+3] - s[x+3+stride]);
+ }
+ s+= stride;
+ }
+
+ return score;
+}
+
+static int vsse16_c(/*MpegEncContext*/ void *c, uint8_t *s1, uint8_t *s2, int stride, int h){
+ int score=0;
+ int x,y;
+
+ for(y=1; y<h; y++){
+ for(x=0; x<16; x++){
+ score+= SQ(s1[x ] - s2[x ] - s1[x +stride] + s2[x +stride]);
+ }
+ s1+= stride;
+ s2+= stride;
+ }
+
+ return score;
+}
+
+WARPER8_16_SQ(hadamard8_diff8x8_c, hadamard8_diff16_c)
+WARPER8_16_SQ(hadamard8_intra8x8_c, hadamard8_intra16_c)
+WARPER8_16_SQ(dct_sad8x8_c, dct_sad16_c)
+#ifdef CONFIG_GPL
+WARPER8_16_SQ(dct264_sad8x8_c, dct264_sad16_c)
+#endif
+WARPER8_16_SQ(dct_max8x8_c, dct_max16_c)
+WARPER8_16_SQ(quant_psnr8x8_c, quant_psnr16_c)
+WARPER8_16_SQ(rd8x8_c, rd16_c)
+WARPER8_16_SQ(bit8x8_c, bit16_c)
+
+static void vector_fmul_c(float *dst, const float *src, int len){
+ int i;
+ for(i=0; i<len; i++)
+ dst[i] *= src[i];
+}
+
+static void vector_fmul_reverse_c(float *dst, const float *src0, const float *src1, int len){
+ int i;
+ src1 += len-1;
+ for(i=0; i<len; i++)
+ dst[i] = src0[i] * src1[-i];
+}
+
+void ff_vector_fmul_add_add_c(float *dst, const float *src0, const float *src1, const float *src2, int src3, int len, int step){
+ int i;
+ for(i=0; i<len; i++)
+ dst[i*step] = src0[i] * src1[i] + src2[i] + src3;
+}
+
+void ff_float_to_int16_c(int16_t *dst, const float *src, int len){
+ int i;
+ for(i=0; i<len; i++) {
+ int_fast32_t tmp = ((int32_t*)src)[i];
+ if(tmp & 0xf0000){
+ tmp = (0x43c0ffff - tmp)>>31;
+ // is this faster on some gcc/cpu combinations?
+// if(tmp > 0x43c0ffff) tmp = 0xFFFF;
+// else tmp = 0;
+ }
+ dst[i] = tmp - 0x8000;
+ }
+}
+
+/* XXX: those functions should be suppressed ASAP when all IDCTs are
+ converted */
+static void ff_jref_idct_put(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ j_rev_dct (block);
+ put_pixels_clamped_c(block, dest, line_size);
+}
+static void ff_jref_idct_add(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ j_rev_dct (block);
+ add_pixels_clamped_c(block, dest, line_size);
+}
+
+static void ff_jref_idct4_put(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ j_rev_dct4 (block);
+ put_pixels_clamped4_c(block, dest, line_size);
+}
+static void ff_jref_idct4_add(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ j_rev_dct4 (block);
+ add_pixels_clamped4_c(block, dest, line_size);
+}
+
+static void ff_jref_idct2_put(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ j_rev_dct2 (block);
+ put_pixels_clamped2_c(block, dest, line_size);
+}
+static void ff_jref_idct2_add(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ j_rev_dct2 (block);
+ add_pixels_clamped2_c(block, dest, line_size);
+}
+
+static void ff_jref_idct1_put(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ dest[0] = cm[(block[0] + 4)>>3];
+}
+static void ff_jref_idct1_add(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ dest[0] = cm[dest[0] + ((block[0] + 4)>>3)];
+}
+
+static void just_return() { return; }
+
+/* init static data */
+void dsputil_static_init(void)
+{
+ int i;
+
+ for(i=0;i<256;i++) ff_cropTbl[i + MAX_NEG_CROP] = i;
+ for(i=0;i<MAX_NEG_CROP;i++) {
+ ff_cropTbl[i] = 0;
+ ff_cropTbl[i + MAX_NEG_CROP + 256] = 255;
+ }
+
+ for(i=0;i<512;i++) {
+ ff_squareTbl[i] = (i - 256) * (i - 256);
+ }
+
+ for(i=0; i<64; i++) inv_zigzag_direct16[ff_zigzag_direct[i]]= i+1;
+}
+
+
+void dsputil_init(DSPContext* c, AVCodecContext *avctx)
+{
+ int i;
+
+#ifdef CONFIG_ENCODERS
+ if(avctx->dct_algo==FF_DCT_FASTINT) {
+ c->fdct = fdct_ifast;
+ c->fdct248 = 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; //slow/accurate/default
+ c->fdct248 = ff_fdct248_islow;
+ }
+#endif //CONFIG_ENCODERS
+
+ if(avctx->lowres==1){
+ if(avctx->idct_algo==FF_IDCT_INT || avctx->idct_algo==FF_IDCT_AUTO){
+ c->idct_put= ff_jref_idct4_put;
+ c->idct_add= ff_jref_idct4_add;
+ }else{
+ c->idct_put= ff_h264_lowres_idct_put_c;
+ c->idct_add= ff_h264_lowres_idct_add_c;
+ }
+ c->idct = 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 = 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 = j_rev_dct1;
+ 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 = j_rev_dct;
+ c->idct_permutation_type= FF_LIBMPEG2_IDCT_PERM;
+ }else if(avctx->idct_algo==FF_IDCT_VP3){
+ c->idct_put= ff_vp3_idct_put_c;
+ c->idct_add= ff_vp3_idct_add_c;
+ c->idct = ff_vp3_idct_c;
+ c->idct_permutation_type= FF_NO_IDCT_PERM;
+ }else{ //accurate/default
+ c->idct_put= simple_idct_put;
+ c->idct_add= simple_idct_add;
+ c->idct = simple_idct;
+ c->idct_permutation_type= FF_NO_IDCT_PERM;
+ }
+ }
+
+ c->h264_idct_add= ff_h264_idct_add_c;
+ c->h264_idct8_add= ff_h264_idct8_add_c;
+ c->h264_idct_dc_add= ff_h264_idct_dc_add_c;
+ c->h264_idct8_dc_add= ff_h264_idct8_dc_add_c;
+
+ c->get_pixels = get_pixels_c;
+ 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->add_pixels8 = add_pixels8_c;
+ c->add_pixels4 = add_pixels4_c;
+ c->gmc1 = gmc1_c;
+ c->gmc = ff_gmc_c;
+ c->clear_blocks = clear_blocks_c;
+ c->pix_sum = pix_sum_c;
+ c->pix_norm1 = pix_norm1_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;
+
+#define dspfunc(PFX, IDX, NUM) \
+ c->PFX ## _pixels_tab[IDX][0] = PFX ## _pixels ## NUM ## _c; \
+ c->PFX ## _pixels_tab[IDX][1] = PFX ## _pixels ## NUM ## _x2_c; \
+ c->PFX ## _pixels_tab[IDX][2] = PFX ## _pixels ## NUM ## _y2_c; \
+ c->PFX ## _pixels_tab[IDX][3] = PFX ## _pixels ## NUM ## _xy2_c
+
+ dspfunc(put, 0, 16);
+ dspfunc(put_no_rnd, 0, 16);
+ dspfunc(put, 1, 8);
+ dspfunc(put_no_rnd, 1, 8);
+ dspfunc(put, 2, 4);
+ dspfunc(put, 3, 2);
+
+ dspfunc(avg, 0, 16);
+ dspfunc(avg_no_rnd, 0, 16);
+ dspfunc(avg, 1, 8);
+ dspfunc(avg_no_rnd, 1, 8);
+ dspfunc(avg, 2, 4);
+ dspfunc(avg, 3, 2);
+#undef dspfunc
+
+ c->put_no_rnd_pixels_l2[0]= put_no_rnd_pixels16_l2_c;
+ c->put_no_rnd_pixels_l2[1]= put_no_rnd_pixels8_l2_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); */
+
+ dspfunc(put_h264_qpel, 0, 16);
+ dspfunc(put_h264_qpel, 1, 8);
+ dspfunc(put_h264_qpel, 2, 4);
+ dspfunc(put_h264_qpel, 3, 2);
+ dspfunc(avg_h264_qpel, 0, 16);
+ dspfunc(avg_h264_qpel, 1, 8);
+ dspfunc(avg_h264_qpel, 2, 4);
+
+#undef dspfunc
+ c->put_h264_chroma_pixels_tab[0]= put_h264_chroma_mc8_c;
+ c->put_h264_chroma_pixels_tab[1]= put_h264_chroma_mc4_c;
+ c->put_h264_chroma_pixels_tab[2]= put_h264_chroma_mc2_c;
+ c->avg_h264_chroma_pixels_tab[0]= avg_h264_chroma_mc8_c;
+ c->avg_h264_chroma_pixels_tab[1]= avg_h264_chroma_mc4_c;
+ c->avg_h264_chroma_pixels_tab[2]= avg_h264_chroma_mc2_c;
+ c->put_no_rnd_h264_chroma_pixels_tab[0]= put_no_rnd_h264_chroma_mc8_c;
+
+ c->weight_h264_pixels_tab[0]= weight_h264_pixels16x16_c;
+ c->weight_h264_pixels_tab[1]= weight_h264_pixels16x8_c;
+ c->weight_h264_pixels_tab[2]= weight_h264_pixels8x16_c;
+ c->weight_h264_pixels_tab[3]= weight_h264_pixels8x8_c;
+ c->weight_h264_pixels_tab[4]= weight_h264_pixels8x4_c;
+ c->weight_h264_pixels_tab[5]= weight_h264_pixels4x8_c;
+ c->weight_h264_pixels_tab[6]= weight_h264_pixels4x4_c;
+ c->weight_h264_pixels_tab[7]= weight_h264_pixels4x2_c;
+ c->weight_h264_pixels_tab[8]= weight_h264_pixels2x4_c;
+ c->weight_h264_pixels_tab[9]= weight_h264_pixels2x2_c;
+ c->biweight_h264_pixels_tab[0]= biweight_h264_pixels16x16_c;
+ c->biweight_h264_pixels_tab[1]= biweight_h264_pixels16x8_c;
+ c->biweight_h264_pixels_tab[2]= biweight_h264_pixels8x16_c;
+ c->biweight_h264_pixels_tab[3]= biweight_h264_pixels8x8_c;
+ c->biweight_h264_pixels_tab[4]= biweight_h264_pixels8x4_c;
+ c->biweight_h264_pixels_tab[5]= biweight_h264_pixels4x8_c;
+ c->biweight_h264_pixels_tab[6]= biweight_h264_pixels4x4_c;
+ c->biweight_h264_pixels_tab[7]= biweight_h264_pixels4x2_c;
+ c->biweight_h264_pixels_tab[8]= biweight_h264_pixels2x4_c;
+ c->biweight_h264_pixels_tab[9]= biweight_h264_pixels2x2_c;
+
+#ifdef CONFIG_CAVS_DECODER
+ ff_cavsdsp_init(c,avctx);
+#endif
+#if defined(CONFIG_VC1_DECODER) || defined(CONFIG_WMV3_DECODER)
+ ff_vc1dsp_init(c,avctx);
+#endif
+
+ c->put_mspel_pixels_tab[0]= put_mspel8_mc00_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;
+ SET_CMP_FUNC(dct_sad)
+ SET_CMP_FUNC(dct_max)
+#ifdef 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->vsse[0]= vsse16_c;
+ c->vsse[4]= vsse_intra16_c;
+ c->nsse[0]= nsse16_c;
+ c->nsse[1]= nsse8_c;
+#ifdef CONFIG_SNOW_ENCODER
+ c->w53[0]= w53_16_c;
+ c->w53[1]= w53_8_c;
+ c->w97[0]= w97_16_c;
+ c->w97[1]= w97_8_c;
+#endif
+
+ c->add_bytes= add_bytes_c;
+ c->diff_bytes= diff_bytes_c;
+ c->sub_hfyu_median_prediction= sub_hfyu_median_prediction_c;
+ c->bswap_buf= bswap_buf;
+
+ c->h264_v_loop_filter_luma= h264_v_loop_filter_luma_c;
+ c->h264_h_loop_filter_luma= h264_h_loop_filter_luma_c;
+ c->h264_v_loop_filter_chroma= h264_v_loop_filter_chroma_c;
+ c->h264_h_loop_filter_chroma= h264_h_loop_filter_chroma_c;
+ c->h264_v_loop_filter_chroma_intra= h264_v_loop_filter_chroma_intra_c;
+ c->h264_h_loop_filter_chroma_intra= h264_h_loop_filter_chroma_intra_c;
+ c->h264_loop_filter_strength= NULL;
+
+ 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;
+
+#ifdef CONFIG_SNOW_ENCODER
+ c->vertical_compose97i = ff_snow_vertical_compose97i;
+ c->horizontal_compose97i = ff_snow_horizontal_compose97i;
+ c->inner_add_yblock = ff_snow_inner_add_yblock;
+#endif
+
+#ifdef CONFIG_VORBIS_DECODER
+ c->vorbis_inverse_coupling = vorbis_inverse_coupling;
+#endif
+ c->vector_fmul = vector_fmul_c;
+ c->vector_fmul_reverse = vector_fmul_reverse_c;
+ c->vector_fmul_add_add = ff_vector_fmul_add_add_c;
+ c->float_to_int16 = ff_float_to_int16_c;
+
+ c->shrink[0]= ff_img_copy_plane;
+ c->shrink[1]= ff_shrink22;
+ c->shrink[2]= ff_shrink44;
+ c->shrink[3]= ff_shrink88;
+
+ c->prefetch= just_return;
+
+ memset(c->put_2tap_qpel_pixels_tab, 0, sizeof(c->put_2tap_qpel_pixels_tab));
+ memset(c->avg_2tap_qpel_pixels_tab, 0, sizeof(c->avg_2tap_qpel_pixels_tab));
+
+#ifdef HAVE_MMX
+ dsputil_init_mmx(c, avctx);
+#endif
+#ifdef ARCH_ARMV4L
+ dsputil_init_armv4l(c, avctx);
+#endif
+#ifdef HAVE_MLIB
+ dsputil_init_mlib(c, avctx);
+#endif
+#ifdef ARCH_SPARC
+ dsputil_init_vis(c,avctx);
+#endif
+#ifdef ARCH_ALPHA
+ dsputil_init_alpha(c, avctx);
+#endif
+#ifdef ARCH_POWERPC
+ dsputil_init_ppc(c, avctx);
+#endif
+#ifdef HAVE_MMI
+ dsputil_init_mmi(c, avctx);
+#endif
+#ifdef ARCH_SH4
+ dsputil_init_sh4(c,avctx);
+#endif
+#ifdef ARCH_BFIN
+ dsputil_init_bfin(c,avctx);
+#endif
+
+ for(i=0; i<64; i++){
+ if(!c->put_2tap_qpel_pixels_tab[0][i])
+ c->put_2tap_qpel_pixels_tab[0][i]= c->put_h264_qpel_pixels_tab[0][i];
+ if(!c->avg_2tap_qpel_pixels_tab[0][i])
+ c->avg_2tap_qpel_pixels_tab[0][i]= c->avg_h264_qpel_pixels_tab[0][i];
+ }
+
+ switch(c->idct_permutation_type){
+ case FF_NO_IDCT_PERM:
+ for(i=0; i<64; i++)
+ c->idct_permutation[i]= i;
+ break;
+ case FF_LIBMPEG2_IDCT_PERM:
+ for(i=0; i<64; i++)
+ c->idct_permutation[i]= (i & 0x38) | ((i & 6) >> 1) | ((i & 1) << 2);
+ break;
+ case FF_SIMPLE_IDCT_PERM:
+ for(i=0; i<64; i++)
+ c->idct_permutation[i]= simple_mmx_permutation[i];
+ break;
+ case FF_TRANSPOSE_IDCT_PERM:
+ for(i=0; i<64; i++)
+ c->idct_permutation[i]= ((i&7)<<3) | (i>>3);
+ break;
+ case FF_PARTTRANS_IDCT_PERM:
+ for(i=0; i<64; i++)
+ c->idct_permutation[i]= (i&0x24) | ((i&3)<<3) | ((i>>3)&3);
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "Internal error, IDCT permutation not set\n");
+ }
+}
+
diff --git a/contrib/ffmpeg/libavcodec/dsputil.h b/contrib/ffmpeg/libavcodec/dsputil.h
new file mode 100644
index 000000000..35deb6aab
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/dsputil.h
@@ -0,0 +1,778 @@
+/*
+ * DSP utils
+ * Copyright (c) 2000, 2001, 2002 Fabrice Bellard.
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file dsputil.h
+ * 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 DSPUTIL_H
+#define DSPUTIL_H
+
+#include "common.h"
+#include "avcodec.h"
+
+
+//#define DEBUG
+/* dct code */
+typedef short DCTELEM;
+typedef int DWTELEM;
+
+void fdct_ifast (DCTELEM *data);
+void fdct_ifast248 (DCTELEM *data);
+void ff_jpeg_fdct_islow (DCTELEM *data);
+void ff_fdct248_islow (DCTELEM *data);
+
+void j_rev_dct (DCTELEM *data);
+void j_rev_dct4 (DCTELEM *data);
+void j_rev_dct2 (DCTELEM *data);
+void j_rev_dct1 (DCTELEM *data);
+
+void ff_fdct_mmx(DCTELEM *block);
+void ff_fdct_mmx2(DCTELEM *block);
+void ff_fdct_sse2(DCTELEM *block);
+
+void ff_h264_idct8_add_c(uint8_t *dst, DCTELEM *block, int stride);
+void ff_h264_idct_add_c(uint8_t *dst, DCTELEM *block, int stride);
+void ff_h264_idct8_dc_add_c(uint8_t *dst, DCTELEM *block, int stride);
+void ff_h264_idct_dc_add_c(uint8_t *dst, DCTELEM *block, int stride);
+void ff_h264_lowres_idct_add_c(uint8_t *dst, int stride, DCTELEM *block);
+void ff_h264_lowres_idct_put_c(uint8_t *dst, int stride, DCTELEM *block);
+
+void ff_vector_fmul_add_add_c(float *dst, const float *src0, const float *src1,
+ const float *src2, int src3, int blocksize, int step);
+void ff_float_to_int16_c(int16_t *dst, const float *src, int len);
+
+/* 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 uint8_t ff_cropTbl[256 + 2 * MAX_NEG_CROP];
+
+/* VP3 DSP functions */
+void ff_vp3_idct_c(DCTELEM *block/* align 16*/);
+void ff_vp3_idct_put_c(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/);
+void ff_vp3_idct_add_c(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/);
+
+/* 1/2^n downscaling functions from imgconvert.c */
+void ff_img_copy_plane(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height);
+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);
+
+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 u 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-dev list, ...
+
+!warning these alignments might not match reallity, (missing attribute((align)) stuff somewhere possible)
+i (michael) didnt check them, these are just the alignents which i think could be reached easily ...
+
+!future video codecs might need functions with less strict alignment
+*/
+
+/*
+void get_pixels_c(DCTELEM *block, const uint8_t *pixels, int line_size);
+void diff_pixels_c(DCTELEM *block, const uint8_t *s1, const uint8_t *s2, int stride);
+void put_pixels_clamped_c(const DCTELEM *block, uint8_t *pixels, int line_size);
+void add_pixels_clamped_c(const DCTELEM *block, uint8_t *pixels, int line_size);
+void clear_blocks_c(DCTELEM *blocks);
+*/
+
+/* 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 then 4
+typedef void (*op_pixels_func)(uint8_t *block/*align width (8 or 16)*/, const uint8_t *pixels/*align 1*/, int line_size, int h);
+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*/, int stride);
+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 void (*h264_weight_func)(uint8_t *block, int stride, int log2_denom, int weight, int offset);
+typedef void (*h264_biweight_func)(uint8_t *dst, uint8_t *src, int stride, int log2_denom, int weightd, int weights, int offset);
+
+#define DEF_OLD_QPEL(name)\
+void ff_put_ ## name (uint8_t *dst/*align width (8 or 16)*/, uint8_t *src/*align 1*/, int stride);\
+void ff_put_no_rnd_ ## name (uint8_t *dst/*align width (8 or 16)*/, uint8_t *src/*align 1*/, int stride);\
+void ff_avg_ ## name (uint8_t *dst/*align width (8 or 16)*/, uint8_t *src/*align 1*/, int 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)
+
+#define CALL_2X_PIXELS(a, b, n)\
+static void a(uint8_t *block, const uint8_t *pixels, int line_size, int h){\
+ b(block , pixels , line_size, h);\
+ b(block+n, pixels+n, line_size, h);\
+}
+
+/* motion estimation */
+// h is limited to {width/2, width, 2*width} but never larger than 16 and never smaller then 2
+// allthough currently h<4 is not used as functions with width <8 are not used and neither 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))*/;
+
+
+// for snow slices
+typedef struct slice_buffer_s slice_buffer;
+
+/**
+ * DSPContext.
+ */
+typedef struct DSPContext {
+ /* pixel ops : interface with DCT */
+ void (*get_pixels)(DCTELEM *block/*align 16*/, const uint8_t *pixels/*align 8*/, int line_size);
+ void (*diff_pixels)(DCTELEM *block/*align 16*/, const uint8_t *s1/*align 8*/, const uint8_t *s2/*align 8*/, int stride);
+ void (*put_pixels_clamped)(const DCTELEM *block/*align 16*/, uint8_t *pixels/*align 8*/, int line_size);
+ void (*put_signed_pixels_clamped)(const DCTELEM *block/*align 16*/, uint8_t *pixels/*align 8*/, int line_size);
+ void (*add_pixels_clamped)(const DCTELEM *block/*align 16*/, uint8_t *pixels/*align 8*/, int line_size);
+ void (*add_pixels8)(uint8_t *pixels, DCTELEM *block, int line_size);
+ void (*add_pixels4)(uint8_t *pixels, DCTELEM *block, int line_size);
+ /**
+ * 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_blocks)(DCTELEM *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[5]; /* identical to pix_absAxA except additional void * */
+ me_cmp_func sse[5];
+ me_cmp_func hadamard8_diff[5];
+ me_cmp_func dct_sad[5];
+ me_cmp_func quant_psnr[5];
+ me_cmp_func bit[5];
+ me_cmp_func rd[5];
+ me_cmp_func vsad[5];
+ me_cmp_func vsse[5];
+ me_cmp_func nsse[5];
+ me_cmp_func w53[5];
+ me_cmp_func w97[5];
+ me_cmp_func dct_max[5];
+ me_cmp_func dct264_sad[5];
+
+ me_cmp_func me_pre_cmp[5];
+ me_cmp_func me_cmp[5];
+ me_cmp_func me_sub_cmp[5];
+ me_cmp_func mb_cmp[5];
+ me_cmp_func ildct_cmp[5]; //only width 16 used
+ me_cmp_func frame_skip_cmp[5]; //only width 8 used
+
+ /**
+ * 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<br>
+ * *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<br>
+ * *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[2][4] of motion compensation funcions for 2
+ * horizontal blocksizes (8,16) and the 4 halfpel positions<br>
+ * *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[2][4] of motion compensation funcions for 2
+ * horizontal blocksizes (8,16) and the 4 halfpel positions<br>
+ * *pixels_tab[ 0->16xH 1->8xH ][ 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][4];
+
+ void (*put_no_rnd_pixels_l2[2])(uint8_t *block/*align width (8 or 16)*/, const uint8_t *a/*align 1*/, const uint8_t *b/*align 1*/, int line_size, int h);
+
+ /**
+ * Thirdpel motion compensation with rounding (a+b+1)>>1.
+ * this is an array[12] of motion compensation funcions for the 9 thirdpel positions<br>
+ * *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 avg_no_rnd_qpel_pixels_tab[2][16];
+ qpel_mc_func put_mspel_pixels_tab[8];
+
+ /**
+ * h264 Chram MC
+ */
+ h264_chroma_mc_func put_h264_chroma_pixels_tab[3];
+ /* This is really one func used in VC-1 decoding */
+ h264_chroma_mc_func put_no_rnd_h264_chroma_pixels_tab[3];
+ h264_chroma_mc_func avg_h264_chroma_pixels_tab[3];
+
+ qpel_mc_func put_h264_qpel_pixels_tab[4][16];
+ qpel_mc_func avg_h264_qpel_pixels_tab[4][16];
+
+ qpel_mc_func put_2tap_qpel_pixels_tab[4][16];
+ qpel_mc_func avg_2tap_qpel_pixels_tab[4][16];
+
+ h264_weight_func weight_h264_pixels_tab[10];
+ h264_biweight_func biweight_h264_pixels_tab[10];
+
+ /* AVS specific */
+ 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, DCTELEM *block, int stride);
+
+ 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*/, uint8_t *src1/*align 16*/, 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, uint8_t *src1, uint8_t *src2, int w, int *left, int *left_top);
+ void (*bswap_buf)(uint32_t *dst, uint32_t *src, int w);
+
+ void (*h264_v_loop_filter_luma)(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0);
+ void (*h264_h_loop_filter_luma)(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0);
+ void (*h264_v_loop_filter_chroma)(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0);
+ void (*h264_h_loop_filter_chroma)(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0);
+ void (*h264_v_loop_filter_chroma_intra)(uint8_t *pix, int stride, int alpha, int beta);
+ void (*h264_h_loop_filter_chroma_intra)(uint8_t *pix, 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);
+
+ 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 4, and arrays are 16-byte aligned */
+ void (*vorbis_inverse_coupling)(float *mag, float *ang, int blocksize);
+ /* assume len is a multiple of 8, and arrays are 16-byte aligned */
+ void (*vector_fmul)(float *dst, const float *src, int len);
+ void (*vector_fmul_reverse)(float *dst, const float *src0, const float *src1, int len);
+ /* assume len is a multiple of 8, and src arrays are 16-byte aligned */
+ void (*vector_fmul_add_add)(float *dst, const float *src0, const float *src1, const float *src2, int src3, int len, int step);
+
+ /* C version: convert floats from the range [384.0,386.0] to ints in [-32768,32767]
+ * simd versions: convert floats from [-32768.0,32767.0] without rescaling and arrays are 16byte aligned */
+ void (*float_to_int16)(int16_t *dst, const float *src, int len);
+
+ /* (I)DCT */
+ void (*fdct)(DCTELEM *block/* align 16*/);
+ void (*fdct248)(DCTELEM *block/* align 16*/);
+
+ /* IDCT really*/
+ void (*idct)(DCTELEM *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 horizotal line of dest
+ */
+ void (*idct_put)(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/);
+
+ /**
+ * block -> idct -> add dest -> clip to unsigned 8 bit -> dest.
+ * @param line_size size in bytes of a horizotal line of dest
+ */
+ void (*idct_add)(uint8_t *dest/*align 8*/, int line_size, DCTELEM *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<br>
+ * an example to avoid confusion:
+ * - (->decode coeffs -> zigzag reorder -> dequant -> reference idct ->...)
+ * - (x -> referece dct -> reference idct -> x)
+ * - (x -> referece 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
+
+ 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 (*h264_idct_add)(uint8_t *dst, DCTELEM *block, int stride);
+ void (*h264_idct8_add)(uint8_t *dst, DCTELEM *block, int stride);
+ void (*h264_idct_dc_add)(uint8_t *dst, DCTELEM *block, int stride);
+ void (*h264_idct8_dc_add)(uint8_t *dst, DCTELEM *block, int stride);
+
+ /* snow wavelet */
+ void (*vertical_compose97i)(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, DWTELEM *b3, DWTELEM *b4, DWTELEM *b5, int width);
+ void (*horizontal_compose97i)(DWTELEM *b, int width);
+ void (*inner_add_yblock)(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);
+
+ void (*prefetch)(void *mem, int stride, int h);
+
+ void (*shrink[4])(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height);
+
+ /* vc1 functions */
+ void (*vc1_inv_trans_8x8)(DCTELEM *b);
+ void (*vc1_inv_trans_8x4)(DCTELEM *b, int n);
+ void (*vc1_inv_trans_4x8)(DCTELEM *b, int n);
+ void (*vc1_inv_trans_4x4)(DCTELEM *b, int n);
+ void (*vc1_v_overlap)(uint8_t* src, int stride);
+ void (*vc1_h_overlap)(uint8_t* src, int stride);
+ /* put 8x8 block with bicubic interpolation and quarterpel precision
+ * last argument is actually round value instead of height
+ */
+ op_pixels_func put_vc1_mspel_pixels_tab[16];
+} DSPContext;
+
+void dsputil_static_init(void);
+void dsputil_init(DSPContext* p, AVCodecContext *avctx);
+
+/**
+ * permute block according to permuatation.
+ * @param last last non zero element in scantable order
+ */
+void ff_block_permute(DCTELEM *block, uint8_t *permutation, const uint8_t *scantable, int last);
+
+void ff_set_cmp(DSPContext* c, me_cmp_func *cmp, int type);
+
+#define BYTE_VEC32(c) ((c)*0x01010101UL)
+
+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 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;
+ }
+}
+
+/**
+ * Empty mmx state.
+ * this must be called between any dsp function and float/double code.
+ * for example sin(); dsp->idct_put(); emms_c(); cos()
+ */
+#define emms_c()
+
+/* should be defined by architectures supporting
+ one or more MultiMedia extension */
+int mm_support(void);
+
+#ifdef __GNUC__
+ #define DECLARE_ALIGNED_16(t,v) t v __attribute__ ((aligned (16)))
+#else
+ #define DECLARE_ALIGNED_16(t,v) __declspec(align(16)) t v
+#endif
+
+#if defined(HAVE_MMX)
+
+#undef emms_c
+
+#define MM_MMX 0x0001 /* standard MMX */
+#define MM_3DNOW 0x0004 /* AMD 3DNOW */
+#define MM_MMXEXT 0x0002 /* SSE integer functions or AMD MMX ext */
+#define MM_SSE 0x0008 /* SSE functions */
+#define MM_SSE2 0x0010 /* PIV SSE2 functions */
+#define MM_3DNOWEXT 0x0020 /* AMD 3DNowExt */
+#define MM_SSE3 0x0040 /* Prescott SSE3 functions */
+
+extern int mm_flags;
+
+void add_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size);
+void put_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size);
+void put_signed_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size);
+
+static inline void emms(void)
+{
+ __asm __volatile ("emms;":::"memory");
+}
+
+
+#define emms_c() \
+{\
+ if (mm_flags & MM_MMX)\
+ emms();\
+}
+
+#ifdef __GNUC__
+ #define DECLARE_ALIGNED_8(t,v) t v __attribute__ ((aligned (8)))
+#else
+ #define DECLARE_ALIGNED_8(t,v) __declspec(align(8)) t v
+#endif
+
+#define STRIDE_ALIGN 8
+
+void dsputil_init_mmx(DSPContext* c, AVCodecContext *avctx);
+void dsputil_init_pix_mmx(DSPContext* c, AVCodecContext *avctx);
+
+#elif defined(ARCH_ARMV4L)
+
+/* This is to use 4 bytes read to the IDCT pointers for some 'zero'
+ line optimizations */
+#define DECLARE_ALIGNED_8(t,v) t v __attribute__ ((aligned (4)))
+#define STRIDE_ALIGN 4
+
+#define MM_IWMMXT 0x0100 /* XScale IWMMXT */
+
+extern int mm_flags;
+
+void dsputil_init_armv4l(DSPContext* c, AVCodecContext *avctx);
+
+#elif defined(HAVE_MLIB)
+
+/* SPARC/VIS IDCT needs 8-byte aligned DCT blocks */
+#define DECLARE_ALIGNED_8(t,v) t v __attribute__ ((aligned (8)))
+#define STRIDE_ALIGN 8
+
+void dsputil_init_mlib(DSPContext* c, AVCodecContext *avctx);
+
+#elif defined(ARCH_SPARC)
+
+/* SPARC/VIS IDCT needs 8-byte aligned DCT blocks */
+#define DECLARE_ALIGNED_8(t,v) t v __attribute__ ((aligned (8)))
+#define STRIDE_ALIGN 8
+void dsputil_init_vis(DSPContext* c, AVCodecContext *avctx);
+
+#elif defined(ARCH_ALPHA)
+
+#define DECLARE_ALIGNED_8(t,v) t v __attribute__ ((aligned (8)))
+#define STRIDE_ALIGN 8
+
+void dsputil_init_alpha(DSPContext* c, AVCodecContext *avctx);
+
+#elif defined(ARCH_POWERPC)
+
+#define MM_ALTIVEC 0x0001 /* standard AltiVec */
+
+extern int mm_flags;
+
+#if defined(HAVE_ALTIVEC) && !defined(CONFIG_DARWIN)
+#define pixel altivec_pixel
+#include <altivec.h>
+#undef pixel
+#endif
+
+#define DECLARE_ALIGNED_8(t,v) t v __attribute__ ((aligned (16)))
+#define STRIDE_ALIGN 16
+
+void dsputil_init_ppc(DSPContext* c, AVCodecContext *avctx);
+
+#elif defined(HAVE_MMI)
+
+#define DECLARE_ALIGNED_8(t,v) t v __attribute__ ((aligned (16)))
+#define STRIDE_ALIGN 16
+
+void dsputil_init_mmi(DSPContext* c, AVCodecContext *avctx);
+
+#elif defined(ARCH_SH4)
+
+#define DECLARE_ALIGNED_8(t,v) t v __attribute__ ((aligned (8)))
+#define STRIDE_ALIGN 8
+
+void dsputil_init_sh4(DSPContext* c, AVCodecContext *avctx);
+
+#elif defined(ARCH_BFIN)
+
+#define DECLARE_ALIGNED_8(t,v) t v __attribute__ ((aligned (8)))
+#define STRIDE_ALIGN 8
+
+void dsputil_init_bfin(DSPContext* c, AVCodecContext *avctx);
+
+#else
+
+#define DECLARE_ALIGNED_8(t,v) t v __attribute__ ((aligned (8)))
+#define STRIDE_ALIGN 8
+
+#endif
+
+#ifdef __GNUC__
+
+struct unaligned_64 { uint64_t l; } __attribute__((packed));
+struct unaligned_32 { uint32_t l; } __attribute__((packed));
+struct unaligned_16 { uint16_t l; } __attribute__((packed));
+
+#define LD16(a) (((const struct unaligned_16 *) (a))->l)
+#define LD32(a) (((const struct unaligned_32 *) (a))->l)
+#define LD64(a) (((const struct unaligned_64 *) (a))->l)
+
+#define ST16(a, b) (((struct unaligned_16 *) (a))->l) = (b)
+#define ST32(a, b) (((struct unaligned_32 *) (a))->l) = (b)
+
+#else /* __GNUC__ */
+
+#define LD16(a) (*((uint16_t*)(a)))
+#define LD32(a) (*((uint32_t*)(a)))
+#define LD64(a) (*((uint64_t*)(a)))
+
+#define ST16(a, b) *((uint16_t*)(a)) = (b)
+#define ST32(a, b) *((uint32_t*)(a)) = (b)
+
+#endif /* !__GNUC__ */
+
+/* PSNR */
+void get_psnr(uint8_t *orig_image[3], uint8_t *coded_image[3],
+ int orig_linesize[3], int coded_linesize,
+ AVCodecContext *avctx);
+
+/* FFT computation */
+
+/* NOTE: soon integer code will be added, so you must use the
+ FFTSample type */
+typedef float FFTSample;
+
+struct MDCTContext;
+
+typedef struct FFTComplex {
+ FFTSample re, im;
+} FFTComplex;
+
+typedef struct FFTContext {
+ int nbits;
+ int inverse;
+ uint16_t *revtab;
+ FFTComplex *exptab;
+ FFTComplex *exptab1; /* only used by SSE code */
+ void (*fft_calc)(struct FFTContext *s, FFTComplex *z);
+ void (*imdct_calc)(struct MDCTContext *s, FFTSample *output,
+ const FFTSample *input, FFTSample *tmp);
+} FFTContext;
+
+int ff_fft_init(FFTContext *s, int nbits, int inverse);
+void ff_fft_permute(FFTContext *s, FFTComplex *z);
+void ff_fft_calc_c(FFTContext *s, FFTComplex *z);
+void ff_fft_calc_sse(FFTContext *s, FFTComplex *z);
+void ff_fft_calc_3dn(FFTContext *s, FFTComplex *z);
+void ff_fft_calc_3dn2(FFTContext *s, FFTComplex *z);
+void ff_fft_calc_altivec(FFTContext *s, FFTComplex *z);
+
+static inline void ff_fft_calc(FFTContext *s, FFTComplex *z)
+{
+ s->fft_calc(s, z);
+}
+void ff_fft_end(FFTContext *s);
+
+/* MDCT computation */
+
+typedef struct MDCTContext {
+ int n; /* size of MDCT (i.e. number of input data * 2) */
+ int nbits; /* n = 2^nbits */
+ /* pre/post rotation tables */
+ FFTSample *tcos;
+ FFTSample *tsin;
+ FFTContext fft;
+} MDCTContext;
+
+int ff_mdct_init(MDCTContext *s, int nbits, int inverse);
+void ff_imdct_calc(MDCTContext *s, FFTSample *output,
+ const FFTSample *input, FFTSample *tmp);
+void ff_imdct_calc_3dn2(MDCTContext *s, FFTSample *output,
+ const FFTSample *input, FFTSample *tmp);
+void ff_imdct_calc_sse(MDCTContext *s, FFTSample *output,
+ const FFTSample *input, FFTSample *tmp);
+void ff_mdct_calc(MDCTContext *s, FFTSample *out,
+ const FFTSample *input, FFTSample *tmp);
+void ff_mdct_end(MDCTContext *s);
+
+#define WARPER8_16(name8, name16)\
+static int name16(void /*MpegEncContext*/ *s, uint8_t *dst, uint8_t *src, int stride, int h){\
+ return name8(s, dst , src , stride, h)\
+ +name8(s, dst+8 , src+8 , stride, h);\
+}
+
+#define WARPER8_16_SQ(name8, name16)\
+static int name16(void /*MpegEncContext*/ *s, uint8_t *dst, uint8_t *src, int stride, int h){\
+ int score=0;\
+ score +=name8(s, dst , src , stride, 8);\
+ score +=name8(s, dst+8 , src+8 , stride, 8);\
+ if(h==16){\
+ dst += 8*stride;\
+ src += 8*stride;\
+ score +=name8(s, dst , src , stride, 8);\
+ score +=name8(s, dst+8 , src+8 , stride, 8);\
+ }\
+ return score;\
+}
+
+
+static inline void copy_block2(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h)
+{
+ int i;
+ for(i=0; i<h; i++)
+ {
+ ST16(dst , LD16(src ));
+ dst+=dstStride;
+ src+=srcStride;
+ }
+}
+
+static inline void copy_block4(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h)
+{
+ int i;
+ for(i=0; i<h; i++)
+ {
+ ST32(dst , LD32(src ));
+ dst+=dstStride;
+ src+=srcStride;
+ }
+}
+
+static inline void copy_block8(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h)
+{
+ int i;
+ for(i=0; i<h; i++)
+ {
+ ST32(dst , LD32(src ));
+ ST32(dst+4 , LD32(src+4 ));
+ dst+=dstStride;
+ src+=srcStride;
+ }
+}
+
+static inline void copy_block9(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h)
+{
+ int i;
+ for(i=0; i<h; i++)
+ {
+ ST32(dst , LD32(src ));
+ ST32(dst+4 , LD32(src+4 ));
+ dst[8]= src[8];
+ dst+=dstStride;
+ src+=srcStride;
+ }
+}
+
+static inline void copy_block16(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h)
+{
+ int i;
+ for(i=0; i<h; i++)
+ {
+ ST32(dst , LD32(src ));
+ ST32(dst+4 , LD32(src+4 ));
+ ST32(dst+8 , LD32(src+8 ));
+ ST32(dst+12, LD32(src+12));
+ dst+=dstStride;
+ src+=srcStride;
+ }
+}
+
+static inline void copy_block17(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h)
+{
+ int i;
+ for(i=0; i<h; i++)
+ {
+ ST32(dst , LD32(src ));
+ ST32(dst+4 , LD32(src+4 ));
+ ST32(dst+8 , LD32(src+8 ));
+ ST32(dst+12, LD32(src+12));
+ dst[16]= src[16];
+ dst+=dstStride;
+ src+=srcStride;
+ }
+}
+
+#endif
diff --git a/contrib/ffmpeg/libavcodec/dtsdec.c b/contrib/ffmpeg/libavcodec/dtsdec.c
new file mode 100644
index 000000000..456f3fdef
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/dtsdec.c
@@ -0,0 +1,320 @@
+/*
+ * dtsdec.c : free DTS Coherent Acoustics stream decoder.
+ * Copyright (C) 2004 Benjamin Zores <ben@geexbox.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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef HAVE_AV_CONFIG_H
+#undef HAVE_AV_CONFIG_H
+#endif
+
+#include "avcodec.h"
+#include <dts.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#define BUFFER_SIZE 18726
+#define HEADER_SIZE 14
+
+#ifdef LIBDTS_FIXED
+#define CONVERT_LEVEL (1 << 26)
+#define CONVERT_BIAS 0
+#else
+#define CONVERT_LEVEL 1
+#define CONVERT_BIAS 384
+#endif
+
+static inline
+int16_t convert (int32_t i)
+{
+#ifdef LIBDTS_FIXED
+ i >>= 15;
+#else
+ i -= 0x43c00000;
+#endif
+ return (i > 32767) ? 32767 : ((i < -32768) ? -32768 : i);
+}
+
+static void
+convert2s16_2 (sample_t * _f, int16_t * s16)
+{
+ int i;
+ int32_t * f = (int32_t *) _f;
+
+ for (i = 0; i < 256; i++)
+ {
+ s16[2*i] = convert (f[i]);
+ s16[2*i+1] = convert (f[i+256]);
+ }
+}
+
+static void
+convert2s16_4 (sample_t * _f, int16_t * s16)
+{
+ int i;
+ int32_t * f = (int32_t *) _f;
+
+ for (i = 0; i < 256; i++)
+ {
+ s16[4*i] = convert (f[i]);
+ s16[4*i+1] = convert (f[i+256]);
+ s16[4*i+2] = convert (f[i+512]);
+ s16[4*i+3] = convert (f[i+768]);
+ }
+}
+
+static void
+convert2s16_5 (sample_t * _f, int16_t * s16)
+{
+ int i;
+ int32_t * f = (int32_t *) _f;
+
+ for (i = 0; i < 256; i++)
+ {
+ s16[5*i] = convert (f[i]);
+ s16[5*i+1] = convert (f[i+256]);
+ s16[5*i+2] = convert (f[i+512]);
+ s16[5*i+3] = convert (f[i+768]);
+ s16[5*i+4] = convert (f[i+1024]);
+ }
+}
+
+static void
+convert2s16_multi (sample_t * _f, int16_t * s16, int flags)
+{
+ int i;
+ int32_t * f = (int32_t *) _f;
+
+ switch (flags)
+ {
+ case DTS_MONO:
+ for (i = 0; i < 256; i++)
+ {
+ s16[5*i] = s16[5*i+1] = s16[5*i+2] = s16[5*i+3] = 0;
+ s16[5*i+4] = convert (f[i]);
+ }
+ break;
+ case DTS_CHANNEL:
+ case DTS_STEREO:
+ case DTS_DOLBY:
+ convert2s16_2 (_f, s16);
+ break;
+ case DTS_3F:
+ for (i = 0; i < 256; i++)
+ {
+ s16[5*i] = convert (f[i]);
+ s16[5*i+1] = convert (f[i+512]);
+ s16[5*i+2] = s16[5*i+3] = 0;
+ s16[5*i+4] = convert (f[i+256]);
+ }
+ break;
+ case DTS_2F2R:
+ convert2s16_4 (_f, s16);
+ break;
+ case DTS_3F2R:
+ convert2s16_5 (_f, s16);
+ break;
+ case DTS_MONO | DTS_LFE:
+ for (i = 0; i < 256; i++)
+ {
+ s16[6*i] = s16[6*i+1] = s16[6*i+2] = s16[6*i+3] = 0;
+ s16[6*i+4] = convert (f[i+256]);
+ s16[6*i+5] = convert (f[i]);
+ }
+ break;
+ case DTS_CHANNEL | DTS_LFE:
+ case DTS_STEREO | DTS_LFE:
+ case DTS_DOLBY | DTS_LFE:
+ for (i = 0; i < 256; i++)
+ {
+ s16[6*i] = convert (f[i+256]);
+ s16[6*i+1] = convert (f[i+512]);
+ s16[6*i+2] = s16[6*i+3] = s16[6*i+4] = 0;
+ s16[6*i+5] = convert (f[i]);
+ }
+ break;
+ case DTS_3F | DTS_LFE:
+ for (i = 0; i < 256; i++)
+ {
+ s16[6*i] = convert (f[i+256]);
+ s16[6*i+1] = convert (f[i+768]);
+ s16[6*i+2] = s16[6*i+3] = 0;
+ s16[6*i+4] = convert (f[i+512]);
+ s16[6*i+5] = convert (f[i]);
+ }
+ break;
+ case DTS_2F2R | DTS_LFE:
+ for (i = 0; i < 256; i++)
+ {
+ s16[6*i] = convert (f[i+256]);
+ s16[6*i+1] = convert (f[i+512]);
+ s16[6*i+2] = convert (f[i+768]);
+ s16[6*i+3] = convert (f[i+1024]);
+ s16[6*i+4] = 0;
+ s16[6*i+5] = convert (f[i]);
+ }
+ break;
+ case DTS_3F2R | DTS_LFE:
+ for (i = 0; i < 256; i++)
+ {
+ s16[6*i] = convert (f[i+256]);
+ s16[6*i+1] = convert (f[i+768]);
+ s16[6*i+2] = convert (f[i+1024]);
+ s16[6*i+3] = convert (f[i+1280]);
+ s16[6*i+4] = convert (f[i+512]);
+ s16[6*i+5] = convert (f[i]);
+ }
+ break;
+ }
+}
+
+static int
+channels_multi (int flags)
+{
+ if (flags & DTS_LFE)
+ return 6;
+ else if (flags & 1) /* center channel */
+ return 5;
+ else if ((flags & DTS_CHANNEL_MASK) == DTS_2F2R)
+ return 4;
+ else
+ return 2;
+}
+
+static int
+dts_decode_frame (AVCodecContext *avctx, void *data, int *data_size,
+ uint8_t *buff, int buff_size)
+{
+ uint8_t * start = buff;
+ uint8_t * end = buff + buff_size;
+ static uint8_t buf[BUFFER_SIZE];
+ static uint8_t * bufptr = buf;
+ static uint8_t * bufpos = buf + HEADER_SIZE;
+
+ static int sample_rate;
+ static int frame_length;
+ static int flags;
+ int bit_rate;
+ int len;
+ dts_state_t *state = avctx->priv_data;
+
+ *data_size = 0;
+
+ while (1)
+ {
+ len = end - start;
+ if (!len)
+ break;
+ if (len > bufpos - bufptr)
+ len = bufpos - bufptr;
+ memcpy (bufptr, start, len);
+ bufptr += len;
+ start += len;
+ if (bufptr != bufpos)
+ return start - buff;
+ if (bufpos != buf + HEADER_SIZE)
+ break;
+
+ {
+ int length;
+
+ length = dts_syncinfo (state, buf, &flags, &sample_rate,
+ &bit_rate, &frame_length);
+ if (!length)
+ {
+ av_log (NULL, AV_LOG_INFO, "skip\n");
+ for (bufptr = buf; bufptr < buf + HEADER_SIZE-1; bufptr++)
+ bufptr[0] = bufptr[1];
+ continue;
+ }
+ bufpos = buf + length;
+ }
+ }
+
+ {
+ level_t level;
+ sample_t bias;
+ int i;
+
+ flags = 2; /* ???????????? */
+ level = CONVERT_LEVEL;
+ bias = CONVERT_BIAS;
+
+ flags |= DTS_ADJUST_LEVEL;
+ if (dts_frame (state, buf, &flags, &level, bias))
+ goto error;
+ avctx->sample_rate = sample_rate;
+ avctx->channels = channels_multi (flags);
+ avctx->bit_rate = bit_rate;
+ for (i = 0; i < dts_blocks_num (state); i++)
+ {
+ if (dts_block (state))
+ goto error;
+ {
+ int chans;
+ chans = channels_multi (flags);
+ convert2s16_multi (dts_samples (state), data,
+ flags & (DTS_CHANNEL_MASK | DTS_LFE));
+
+ data += 256 * sizeof (int16_t) * chans;
+ *data_size += 256 * sizeof (int16_t) * chans;
+ }
+ }
+ bufptr = buf;
+ bufpos = buf + HEADER_SIZE;
+ return start-buff;
+ error:
+ av_log (NULL, AV_LOG_ERROR, "error\n");
+ bufptr = buf;
+ bufpos = buf + HEADER_SIZE;
+ }
+
+ return start-buff;
+}
+
+static int
+dts_decode_init (AVCodecContext *avctx)
+{
+ avctx->priv_data = dts_init (0);
+ if (avctx->priv_data == NULL)
+ return -1;
+
+ return 0;
+}
+
+static int
+dts_decode_end (AVCodecContext *s)
+{
+ return 0;
+}
+
+AVCodec dts_decoder = {
+ "dts",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_DTS,
+ sizeof (dts_state_t *),
+ dts_decode_init,
+ NULL,
+ dts_decode_end,
+ dts_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/dv.c b/contrib/ffmpeg/libavcodec/dv.c
new file mode 100644
index 000000000..76095a481
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/dv.c
@@ -0,0 +1,1265 @@
+/*
+ * 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 <dmaas@maasdigital.com>
+ *
+ * Many thanks to Dan Dennedy <dan@dennedy.org> 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.c
+ * DV codec.
+ */
+#define ALT_BITSTREAM_READER
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+#include "simple_idct.h"
+#include "dvdata.h"
+
+//#undef NDEBUG
+//#include <assert.h>
+
+typedef struct DVVideoContext {
+ const DVprofile* sys;
+ AVFrame picture;
+ AVCodecContext *avctx;
+ uint8_t *buf;
+
+ uint8_t dv_zigzag[2][64];
+ uint8_t dv_idct_shift[2][2][22][64];
+
+ void (*get_pixels)(DCTELEM *block, const uint8_t *pixels, int line_size);
+ void (*fdct[2])(DCTELEM *block);
+ void (*idct_put[2])(uint8_t *dest, int line_size, DCTELEM *block);
+} DVVideoContext;
+
+/* MultiThreading - dv_anchor applies to entire DV codec, not just the avcontext */
+/* one element is needed for each video segment in a DV frame */
+/* at most there are 2 DIF channels * 12 DIF sequences * 27 video segments (PAL 50Mbps) */
+#define DV_ANCHOR_SIZE (2*12*27)
+
+static void* dv_anchor[DV_ANCHOR_SIZE];
+
+#define TEX_VLC_BITS 9
+
+#ifdef DV_CODEC_TINY_TARGET
+#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
+
+/* XXX: also include quantization */
+static RL_VLC_ELEM *dv_rl_vlc;
+/* VLC encoding lookup table */
+static struct dv_vlc_pair {
+ uint32_t vlc;
+ uint8_t size;
+} (*dv_vlc_map)[DV_VLC_MAP_LEV_SIZE] = NULL;
+
+static void dv_build_unquantize_tables(DVVideoContext *s, uint8_t* perm)
+{
+ int i, q, j;
+
+ /* NOTE: max left shift is 6 */
+ for(q = 0; q < 22; q++) {
+ /* 88DCT */
+ for(i = 1; i < 64; i++) {
+ /* 88 table */
+ j = perm[i];
+ s->dv_idct_shift[0][0][q][j] =
+ dv_quant_shifts[q][dv_88_areas[i]] + 1;
+ s->dv_idct_shift[1][0][q][j] = s->dv_idct_shift[0][0][q][j] + 1;
+ }
+
+ /* 248DCT */
+ for(i = 1; i < 64; i++) {
+ /* 248 table */
+ s->dv_idct_shift[0][1][q][i] =
+ dv_quant_shifts[q][dv_248_areas[i]] + 1;
+ s->dv_idct_shift[1][1][q][i] = s->dv_idct_shift[0][1][q][i] + 1;
+ }
+ }
+}
+
+static int 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;
+
+ dv_vlc_map = av_mallocz_static(DV_VLC_MAP_LEV_SIZE*DV_VLC_MAP_RUN_SIZE*sizeof(struct dv_vlc_pair));
+ if (!dv_vlc_map)
+ return -ENOMEM;
+
+ /* dv_anchor lets each thread know its Id */
+ for (i=0; i<DV_ANCHOR_SIZE; i++)
+ dv_anchor[i] = (void*)(size_t)i;
+
+ /* 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);
+
+ dv_rl_vlc = av_mallocz_static(dv_vlc.table_size * sizeof(RL_VLC_ELEM));
+ if (!dv_rl_vlc)
+ return -ENOMEM;
+
+ 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];
+ }
+ dv_rl_vlc[i].len = len;
+ dv_rl_vlc[i].level = level;
+ dv_rl_vlc[i].run = run;
+ }
+ free_vlc(&dv_vlc);
+
+ for (i = 0; i < NB_DV_VLC - 1; i++) {
+ if (dv_vlc_run[i] >= DV_VLC_MAP_RUN_SIZE)
+ continue;
+#ifdef DV_CODEC_TINY_TARGET
+ 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++) {
+#ifdef DV_CODEC_TINY_TARGET
+ 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
+ }
+ }
+
+ /* Generic DSP setup */
+ dsputil_init(&dsp, avctx);
+ s->get_pixels = dsp.get_pixels;
+
+ /* 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] = 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);
+
+ /* XXX: do it only for constant case */
+ dv_build_unquantize_tables(s, dsp.idct_permutation);
+
+ avctx->coded_frame = &s->picture;
+ s->avctx= avctx;
+
+ return 0;
+}
+
+// #define VLC_DEBUG
+// #define printf(...) av_log(NULL, AV_LOG_ERROR, __VA_ARGS__)
+
+typedef struct BlockInfo {
+ const uint8_t *shift_table;
+ const uint8_t *scan_table;
+ const int *iweight_table;
+ uint8_t pos; /* position in block */
+ uint8_t dct_mode;
+ uint8_t partial_bit_count;
+ uint16_t partial_bit_buffer;
+ int shift_offset;
+} BlockInfo;
+
+/* block size in bits */
+static const uint16_t block_sizes[6] = {
+ 112, 112, 112, 112, 80, 80
+};
+/* bit budget for AC only in 5 MBs */
+static const int vs_total_ac_bits = (100 * 4 + 68*2) * 5;
+/* see dv_88_areas and dv_248_areas for details */
+static const int mb_area_start[5] = { 1, 6, 21, 43, 64 };
+
+static inline int get_bits_left(GetBitContext *s)
+{
+ return s->size_in_bits - get_bits_count(s);
+}
+
+static inline int get_bits_size(GetBitContext *s)
+{
+ return s->size_in_bits;
+}
+
+static inline int put_bits_left(PutBitContext* s)
+{
+ return (s->buf_end - s->buf) * 8 - put_bits_count(s);
+}
+
+/* decode ac coefs */
+static void dv_decode_ac(GetBitContext *gb, BlockInfo *mb, DCTELEM *block)
+{
+ int last_index = get_bits_size(gb);
+ const uint8_t *scan_table = mb->scan_table;
+ const uint8_t *shift_table = mb->shift_table;
+ const int *iweight_table = mb->iweight_table;
+ int pos = mb->pos;
+ int partial_bit_count = mb->partial_bit_count;
+ int level, pos1, 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 = ((unsigned)re_cache >> partial_bit_count) |
+ (mb->partial_bit_buffer << (sizeof(re_cache)*8 - partial_bit_count));
+ re_index -= partial_bit_count;
+ mb->partial_bit_count = 0;
+ }
+
+ /* get the AC coefficients until last_index is reached */
+ for(;;) {
+#ifdef VLC_DEBUG
+ printf("%2d: bits=%04x index=%d\n", pos, SHOW_UBITS(re, gb, 16), re_index);
+#endif
+ /* our own optimized GET_RL_VLC */
+ index = NEG_USR32(re_cache, TEX_VLC_BITS);
+ vlc_len = dv_rl_vlc[index].len;
+ if (vlc_len < 0) {
+ index = NEG_USR32((unsigned)re_cache << TEX_VLC_BITS, -vlc_len) + dv_rl_vlc[index].level;
+ vlc_len = TEX_VLC_BITS - vlc_len;
+ }
+ level = dv_rl_vlc[index].level;
+ run = 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 = NEG_USR32(re_cache, mb->partial_bit_count);
+ re_index = last_index;
+ break;
+ }
+ re_index += vlc_len;
+
+#ifdef VLC_DEBUG
+ printf("run=%d level=%d\n", run, level);
+#endif
+ pos += run;
+ if (pos >= 64)
+ break;
+
+ pos1 = scan_table[pos];
+ level <<= shift_table[pos1];
+
+ /* unweigh, round, and shift down */
+ level = (level*iweight_table[pos] + (1 << (dv_iweight_bits-1))) >> dv_iweight_bits;
+
+ block[pos1] = 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 inline void dv_decode_video_segment(DVVideoContext *s,
+ uint8_t *buf_ptr1,
+ const uint16_t *mb_pos_ptr)
+{
+ int quant, dc, dct_mode, class1, j;
+ int mb_index, mb_x, mb_y, v, last_index;
+ DCTELEM *block, *block1;
+ int c_offset;
+ uint8_t *y_ptr;
+ void (*idct_put)(uint8_t *dest, int line_size, DCTELEM *block);
+ uint8_t *buf_ptr;
+ PutBitContext pb, vs_pb;
+ GetBitContext gb;
+ BlockInfo mb_data[5 * 6], *mb, *mb1;
+ DECLARE_ALIGNED_8(DCTELEM, sblock[5*6][64]);
+ DECLARE_ALIGNED_8(uint8_t, mb_bit_buffer[80 + 4]); /* allow some slack */
+ DECLARE_ALIGNED_8(uint8_t, vs_bit_buffer[5 * 80 + 4]); /* allow some slack */
+ const int log2_blocksize= 3-s->avctx->lowres;
+
+ assert((((int)mb_bit_buffer)&7)==0);
+ assert((((int)vs_bit_buffer)&7)==0);
+
+ memset(sblock, 0, sizeof(sblock));
+
+ /* pass 1 : read DC and AC coefficients in blocks */
+ buf_ptr = buf_ptr1;
+ 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 += 6, block1 += 6 * 64) {
+ /* skip header */
+ quant = buf_ptr[3] & 0x0f;
+ buf_ptr += 4;
+ init_put_bits(&pb, mb_bit_buffer, 80);
+ mb = mb1;
+ block = block1;
+ for(j = 0;j < 6; j++) {
+ last_index = block_sizes[j];
+ init_get_bits(&gb, buf_ptr, last_index);
+
+ /* get the dc */
+ dc = get_sbits(&gb, 9);
+ dct_mode = get_bits1(&gb);
+ mb->dct_mode = dct_mode;
+ mb->scan_table = s->dv_zigzag[dct_mode];
+ mb->iweight_table = dct_mode ? dv_iweight_248 : dv_iweight_88;
+ class1 = get_bits(&gb, 2);
+ mb->shift_table = s->dv_idct_shift[class1 == 3][dct_mode]
+ [quant + dv_quant_offset[class1]];
+ 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;
+
+#ifdef VLC_DEBUG
+ printf("MB block: %d, %d ", mb_index, j);
+#endif
+ 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 */
+#ifdef VLC_DEBUG
+ printf("***pass 2 size=%d MB#=%d\n", put_bits_count(&pb), mb_index);
+#endif
+ block = block1;
+ mb = mb1;
+ init_get_bits(&gb, mb_bit_buffer, put_bits_count(&pb));
+ flush_put_bits(&pb);
+ for(j = 0;j < 6; 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 >= 6)
+ bit_copy(&vs_pb, &gb);
+ }
+
+ /* we need a pass other the whole video segment */
+#ifdef VLC_DEBUG
+ printf("***pass 3 size=%d\n", put_bits_count(&vs_pb));
+#endif
+ block = &sblock[0][0];
+ mb = mb_data;
+ init_get_bits(&gb, vs_bit_buffer, put_bits_count(&vs_pb));
+ flush_put_bits(&vs_pb);
+ for(mb_index = 0; mb_index < 5; mb_index++) {
+ for(j = 0;j < 6; j++) {
+ if (mb->pos < 64) {
+#ifdef VLC_DEBUG
+ printf("start %d:%d\n", mb_index, j);
+#endif
+ dv_decode_ac(&gb, mb, block);
+ }
+ if (mb->pos >= 64 && mb->pos < 127)
+ av_log(NULL, 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++) {
+ v = *mb_pos_ptr++;
+ mb_x = v & 0xff;
+ mb_y = v >> 8;
+ if (s->sys->pix_fmt == PIX_FMT_YUV422P) {
+ y_ptr = s->picture.data[0] + ((mb_y * s->picture.linesize[0] + (mb_x>>1))<<log2_blocksize);
+ c_offset = ((mb_y * s->picture.linesize[1] + (mb_x >> 2))<<log2_blocksize);
+ } else { /* 4:1:1 or 4:2:0 */
+ y_ptr = s->picture.data[0] + ((mb_y * s->picture.linesize[0] + mb_x)<<log2_blocksize);
+ if (s->sys->pix_fmt == PIX_FMT_YUV411P)
+ c_offset = ((mb_y * s->picture.linesize[1] + (mb_x >> 2))<<log2_blocksize);
+ else /* 4:2:0 */
+ c_offset = (((mb_y >> 1) * s->picture.linesize[1] + (mb_x >> 1))<<log2_blocksize);
+ }
+ for(j = 0;j < 6; j++) {
+ idct_put = s->idct_put[mb->dct_mode && log2_blocksize==3];
+ if (s->sys->pix_fmt == PIX_FMT_YUV422P) { /* 4:2:2 */
+ if (j == 0 || j == 2) {
+ /* Y0 Y1 */
+ idct_put(y_ptr + ((j >> 1)<<log2_blocksize),
+ s->picture.linesize[0], block);
+ } else if(j > 3) {
+ /* Cr Cb */
+ idct_put(s->picture.data[6 - j] + c_offset,
+ s->picture.linesize[6 - j], block);
+ }
+ /* note: j=1 and j=3 are "dummy" blocks in 4:2:2 */
+ } else { /* 4:1:1 or 4:2:0 */
+ if (j < 4) {
+ if (s->sys->pix_fmt == PIX_FMT_YUV411P && mb_x < (704 / 8)) {
+ /* NOTE: at end of line, the macroblock is handled as 420 */
+ idct_put(y_ptr + (j<<log2_blocksize), s->picture.linesize[0], block);
+ } else {
+ idct_put(y_ptr + (((j & 1) + (j >> 1) * s->picture.linesize[0])<<log2_blocksize),
+ s->picture.linesize[0], block);
+ }
+ } else {
+ if (s->sys->pix_fmt == PIX_FMT_YUV411P && mb_x >= (704 / 8)) {
+ uint64_t aligned_pixels[64/8];
+ uint8_t *pixels= (uint8_t*)aligned_pixels;
+ uint8_t *c_ptr, *c_ptr1, *ptr, *ptr1;
+ int x, y, linesize;
+ /* NOTE: at end of line, the macroblock is handled as 420 */
+ idct_put(pixels, 8, block);
+ linesize = s->picture.linesize[6 - j];
+ c_ptr = s->picture.data[6 - j] + c_offset;
+ ptr = pixels;
+ for(y = 0;y < (1<<log2_blocksize); y++) {
+ ptr1= ptr + (1<<(log2_blocksize-1));
+ c_ptr1 = c_ptr + (linesize<<log2_blocksize);
+ for(x=0; x < (1<<(log2_blocksize-1)); x++){
+ c_ptr[x]= ptr[x]; c_ptr1[x]= ptr1[x];
+ }
+ c_ptr += linesize;
+ ptr += 8;
+ }
+ } else {
+ /* don't ask me why they inverted Cb and Cr ! */
+ idct_put(s->picture.data[6 - j] + c_offset,
+ s->picture.linesize[6 - j], block);
+ }
+ }
+ }
+ block += 64;
+ mb++;
+ }
+ }
+}
+
+#ifdef DV_CODEC_TINY_TARGET
+/* Converts run and level (where level != 0) pair into vlc, returning bit size */
+static 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 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 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 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;
+ DCTELEM 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 always_inline PutBitContext* dv_encode_ac(EncBlockInfo* bi, PutBitContext* pb_pool,
+ PutBitContext* pb_end)
+{
+ int prev;
+ int 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 always_inline void dv_set_class_number(DCTELEM* blk, EncBlockInfo* bi,
+ const uint8_t* zigzag_scan, const int *weight, int bias)
+{
+ 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;
+
+ bi->mb[0] = blk[0];
+
+ 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;
+ /* weigh 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;
+ }
+}
+
+//FIXME replace this by dsputil
+#define SC(x, y) ((s[x] - s[y]) ^ ((s[x] - s[y]) >> 7))
+static always_inline int dv_guess_dct_mode(DCTELEM *blk) {
+ DCTELEM *s;
+ int score88 = 0;
+ int score248 = 0;
+ int i;
+
+ /* Compute 8-8 score (small values give a better chance for 8-8 DCT) */
+ s = blk;
+ for(i=0; i<7; i++) {
+ score88 += SC(0, 8) + SC(1, 9) + SC(2, 10) + SC(3, 11) +
+ SC(4, 12) + SC(5,13) + SC(6, 14) + SC(7, 15);
+ s += 8;
+ }
+ /* Compute 2-4-8 score (small values give a better chance for 2-4-8 DCT) */
+ s = blk;
+ for(i=0; i<6; i++) {
+ score248 += SC(0, 16) + SC(1,17) + SC(2, 18) + SC(3, 19) +
+ SC(4, 20) + SC(5,21) + SC(6, 22) + SC(7, 23);
+ s += 8;
+ }
+
+ return (score88 - score248 > -10);
+}
+
+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] != dv_quant_shifts[qnos[i] + 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];
+ assert(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;
+ assert(a2<4);
+ assert(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]]);
+ assert(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 inline void dv_encode_video_segment(DVVideoContext *s,
+ uint8_t *dif,
+ const uint16_t *mb_pos_ptr)
+{
+ int mb_index, i, j, v;
+ int mb_x, mb_y, c_offset, linesize;
+ uint8_t* y_ptr;
+ uint8_t* data;
+ uint8_t* ptr;
+ int do_edge_wrap;
+ DECLARE_ALIGNED_8(DCTELEM, block[64]);
+ EncBlockInfo enc_blks[5*6];
+ PutBitContext pbs[5*6];
+ PutBitContext* pb;
+ EncBlockInfo* enc_blk;
+ int vs_bit_size = 0;
+ int qnos[5];
+
+ assert((((int)block) & 7) == 0);
+
+ enc_blk = &enc_blks[0];
+ pb = &pbs[0];
+ for(mb_index = 0; mb_index < 5; mb_index++) {
+ v = *mb_pos_ptr++;
+ mb_x = v & 0xff;
+ mb_y = v >> 8;
+ if (s->sys->pix_fmt == PIX_FMT_YUV422P) {
+ y_ptr = s->picture.data[0] + (mb_y * s->picture.linesize[0] * 8) + (mb_x * 4);
+ } else { /* 4:1:1 */
+ y_ptr = s->picture.data[0] + (mb_y * s->picture.linesize[0] * 8) + (mb_x * 8);
+ }
+ if (s->sys->pix_fmt == PIX_FMT_YUV420P) {
+ c_offset = (((mb_y >> 1) * s->picture.linesize[1] * 8) + ((mb_x >> 1) * 8));
+ } else { /* 4:2:2 or 4:1:1 */
+ c_offset = ((mb_y * s->picture.linesize[1] * 8) + ((mb_x >> 2) * 8));
+ }
+ do_edge_wrap = 0;
+ qnos[mb_index] = 15; /* No quantization */
+ ptr = dif + mb_index*80 + 4;
+ for(j = 0;j < 6; j++) {
+ int dummy = 0;
+ if (s->sys->pix_fmt == PIX_FMT_YUV422P) { /* 4:2:2 */
+ if (j == 0 || j == 2) {
+ /* Y0 Y1 */
+ data = y_ptr + ((j>>1) * 8);
+ linesize = s->picture.linesize[0];
+ } else if (j > 3) {
+ /* Cr Cb */
+ data = s->picture.data[6 - j] + c_offset;
+ linesize = s->picture.linesize[6 - j];
+ } else {
+ /* j=1 and j=3 are "dummy" blocks, used for AC data only */
+ data = 0;
+ linesize = 0;
+ dummy = 1;
+ }
+ } else { /* 4:1:1 or 4:2:0 */
+ if (j < 4) { /* Four Y blocks */
+ /* NOTE: at end of line, the macroblock is handled as 420 */
+ if (s->sys->pix_fmt == PIX_FMT_YUV411P && mb_x < (704 / 8)) {
+ data = y_ptr + (j * 8);
+ } else {
+ data = y_ptr + ((j & 1) * 8) + ((j >> 1) * 8 * s->picture.linesize[0]);
+ }
+ linesize = s->picture.linesize[0];
+ } else { /* Cr and Cb blocks */
+ /* don't ask Fabrice why they inverted Cb and Cr ! */
+ data = s->picture.data[6 - j] + c_offset;
+ linesize = s->picture.linesize[6 - j];
+ if (s->sys->pix_fmt == PIX_FMT_YUV411P && mb_x >= (704 / 8))
+ do_edge_wrap = 1;
+ }
+ }
+
+ /* Everything is set up -- now just copy data -> DCT block */
+ if (do_edge_wrap) { /* Edge wrap copy: 4x16 -> 8x8 */
+ uint8_t* d;
+ DCTELEM *b = block;
+ for (i=0;i<8;i++) {
+ d = data + 8 * linesize;
+ b[0] = data[0]; b[1] = data[1]; b[2] = data[2]; b[3] = data[3];
+ b[4] = d[0]; b[5] = d[1]; b[6] = d[2]; b[7] = d[3];
+ data += linesize;
+ b += 8;
+ }
+ } else { /* Simple copy: 8x8 -> 8x8 */
+ if (!dummy)
+ s->get_pixels(block, data, linesize);
+ }
+
+ if(s->avctx->flags & CODEC_FLAG_INTERLACED_DCT)
+ enc_blk->dct_mode = dv_guess_dct_mode(block);
+ else
+ enc_blk->dct_mode = 0;
+ enc_blk->area_q[0] = enc_blk->area_q[1] = enc_blk->area_q[2] = enc_blk->area_q[3] = 0;
+ enc_blk->partial_bit_count = 0;
+ enc_blk->partial_bit_buffer = 0;
+ enc_blk->cur_ac = 0;
+
+ if (dummy) {
+ /* 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(block, 0, sizeof(block));
+ } else {
+ s->fdct[enc_blk->dct_mode](block);
+ }
+
+ dv_set_class_number(block, enc_blk,
+ enc_blk->dct_mode ? ff_zigzag248_direct : ff_zigzag_direct,
+ enc_blk->dct_mode ? dv_weight_248 : dv_weight_88,
+ j/4);
+
+ init_put_bits(pb, ptr, block_sizes[j]/8);
+ put_bits(pb, 9, (uint16_t)(((enc_blk->mb[0] >> 3) - 1024 + 2) >> 2));
+ put_bits(pb, 1, enc_blk->dct_mode);
+ put_bits(pb, 2, enc_blk->cno);
+
+ vs_bit_size += enc_blk->bit_size[0] + enc_blk->bit_size[1] +
+ enc_blk->bit_size[2] + enc_blk->bit_size[3];
+ ++enc_blk;
+ ++pb;
+ ptr += block_sizes[j]/8;
+ }
+ }
+
+ if (vs_total_ac_bits < vs_bit_size)
+ dv_guess_qnos(&enc_blks[0], &qnos[0]);
+
+ for (i=0; i<5; i++) {
+ dif[i*80 + 3] = qnos[i];
+ }
+
+ /* First pass over individual cells only */
+ for (j=0; j<5*6; j++)
+ dv_encode_ac(&enc_blks[j], &pbs[j], &pbs[j+1]);
+
+ /* Second pass over each MB space */
+ for (j=0; j<5*6; j+=6) {
+ pb= &pbs[j];
+ for (i=0; i<6; i++) {
+ if (enc_blks[i+j].partial_bit_count)
+ pb=dv_encode_ac(&enc_blks[i+j], pb, &pbs[j+6]);
+ }
+ }
+
+ /* Third and final pass over the whole vides segment space */
+ pb= &pbs[0];
+ for (j=0; j<5*6; j++) {
+ if (enc_blks[j].partial_bit_count)
+ pb=dv_encode_ac(&enc_blks[j], pb, &pbs[6*5]);
+ if (enc_blks[j].partial_bit_count)
+ av_log(NULL, AV_LOG_ERROR, "ac bitstream overflow\n");
+ }
+
+ for (j=0; j<5*6; j++)
+ flush_put_bits(&pbs[j]);
+}
+
+static int dv_decode_mt(AVCodecContext *avctx, void* sl)
+{
+ DVVideoContext *s = avctx->priv_data;
+ int slice = (size_t)sl;
+
+ /* which DIF channel is this? */
+ int chan = slice / (s->sys->difseg_size * 27);
+
+ /* slice within the DIF channel */
+ int chan_slice = slice % (s->sys->difseg_size * 27);
+
+ /* byte offset of this channel's data */
+ int chan_offset = chan * s->sys->difseg_size * 150 * 80;
+
+ dv_decode_video_segment(s, &s->buf[((chan_slice/27)*6+(chan_slice/3)+chan_slice*5+7)*80 + chan_offset],
+ &s->sys->video_place[slice*5]);
+ return 0;
+}
+
+#ifdef CONFIG_ENCODERS
+static int dv_encode_mt(AVCodecContext *avctx, void* sl)
+{
+ DVVideoContext *s = avctx->priv_data;
+ int slice = (size_t)sl;
+
+ /* which DIF channel is this? */
+ int chan = slice / (s->sys->difseg_size * 27);
+
+ /* slice within the DIF channel */
+ int chan_slice = slice % (s->sys->difseg_size * 27);
+
+ /* byte offset of this channel's data */
+ int chan_offset = chan * s->sys->difseg_size * 150 * 80;
+
+ dv_encode_video_segment(s, &s->buf[((chan_slice/27)*6+(chan_slice/3)+chan_slice*5+7)*80 + chan_offset],
+ &s->sys->video_place[slice*5]);
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_DECODERS
+/* 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 *data_size,
+ uint8_t *buf, int buf_size)
+{
+ DVVideoContext *s = avctx->priv_data;
+
+ s->sys = dv_frame_profile(buf);
+ if (!s->sys || buf_size < s->sys->frame_size)
+ return -1; /* NOTE: we only accept several full frames */
+
+ if(s->picture.data[0])
+ avctx->release_buffer(avctx, &s->picture);
+
+ s->picture.reference = 0;
+ s->picture.key_frame = 1;
+ s->picture.pict_type = FF_I_TYPE;
+ avctx->pix_fmt = s->sys->pix_fmt;
+ avcodec_set_dimensions(avctx, s->sys->width, s->sys->height);
+ if(avctx->get_buffer(avctx, &s->picture) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+ s->picture.interlaced_frame = 1;
+ s->picture.top_field_first = 0;
+
+ s->buf = buf;
+ avctx->execute(avctx, dv_decode_mt, (void**)&dv_anchor[0], NULL,
+ s->sys->n_difchan * s->sys->difseg_size * 27);
+
+ emms_c();
+
+ /* return image */
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data= s->picture;
+
+ return s->sys->frame_size;
+}
+#endif
+
+
+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 == PIX_FMT_YUV420P ? 0 : 1);
+ int stype = (c->sys->pix_fmt == PIX_FMT_YUV422P ? 4 : 0);
+
+ 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 */
+ 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 */
+ (1 << 6) | /* 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;
+}
+
+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 macro block: 1 bytes control
+ 4 * 14 bytes Y 8x8 data
+ 10 bytes Cr 8x8 data
+ 10 bytes Cb 8x8 data */
+ }
+ }
+ }
+}
+
+
+#ifdef CONFIG_ENCODERS
+static int dvvideo_encode_frame(AVCodecContext *c, uint8_t *buf, int buf_size,
+ void *data)
+{
+ DVVideoContext *s = c->priv_data;
+
+ s->sys = dv_codec_profile(c);
+ if (!s->sys)
+ return -1;
+ if(buf_size < s->sys->frame_size)
+ return -1;
+
+ c->pix_fmt = s->sys->pix_fmt;
+ s->picture = *((AVFrame *)data);
+ s->picture.key_frame = 1;
+ s->picture.pict_type = FF_I_TYPE;
+
+ s->buf = buf;
+ c->execute(c, dv_encode_mt, (void**)&dv_anchor[0], NULL,
+ s->sys->n_difchan * s->sys->difseg_size * 27);
+
+ emms_c();
+
+ dv_format_frame(s, buf);
+
+ return s->sys->frame_size;
+}
+#endif
+
+static int dvvideo_close(AVCodecContext *c)
+{
+
+ return 0;
+}
+
+
+#ifdef CONFIG_DVVIDEO_ENCODER
+AVCodec dvvideo_encoder = {
+ "dvvideo",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_DVVIDEO,
+ sizeof(DVVideoContext),
+ dvvideo_init,
+ dvvideo_encode_frame,
+ dvvideo_close,
+ NULL,
+ CODEC_CAP_DR1,
+ NULL
+};
+#endif // CONFIG_DVVIDEO_ENCODER
+
+#ifdef CONFIG_DVVIDEO_DECODER
+AVCodec dvvideo_decoder = {
+ "dvvideo",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_DVVIDEO,
+ sizeof(DVVideoContext),
+ dvvideo_init,
+ NULL,
+ dvvideo_close,
+ dvvideo_decode_frame,
+ CODEC_CAP_DR1,
+ NULL
+};
+#endif
diff --git a/contrib/ffmpeg/libavcodec/dvbsub.c b/contrib/ffmpeg/libavcodec/dvbsub.c
new file mode 100644
index 000000000..44ba19d86
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/dvbsub.c
@@ -0,0 +1,445 @@
+/*
+ * DVB subtitle encoding for ffmpeg
+ * 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"
+
+typedef struct DVBSubtitleContext {
+ int hide_state;
+ 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;
+}
+
+#define SCALEBITS 10
+#define ONE_HALF (1 << (SCALEBITS - 1))
+#define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
+
+#define RGB_TO_Y_CCIR(r, g, b) \
+((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
+ FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
+
+#define RGB_TO_U_CCIR(r1, g1, b1, shift)\
+(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \
+ FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
+
+#define RGB_TO_V_CCIR(r1, g1, b1, shift)\
+(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \
+ FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
+
+static inline void putbe16(uint8_t **pq, uint16_t v)
+{
+ uint8_t *q;
+ q = *pq;
+ *q++ = v >> 8;
+ *q++ = v;
+ *pq = q;
+}
+
+static int encode_dvb_subtitles(DVBSubtitleContext *s,
+ uint8_t *outbuf, 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 == 0 || h->rects == NULL)
+ return -1;
+
+ *q++ = 0x00; /* subtitle_stream_id */
+
+ /* page composition segment */
+
+ *q++ = 0x0f; /* sync_byte */
+ *q++ = 0x10; /* segment_type */
+ putbe16(&q, page_id);
+ pseg_len = q;
+ q += 2; /* segment length */
+ *q++ = 30; /* page_timeout (seconds) */
+ if (s->hide_state)
+ page_state = 0; /* normal case */
+ else
+ page_state = 2; /* mode change */
+ /* page_version = 0 + page_state */
+ *q++ = s->object_version | (page_state << 2) | 3;
+
+ for (region_id = 0; region_id < h->num_rects; region_id++) {
+ *q++ = region_id;
+ *q++ = 0xff; /* reserved */
+ putbe16(&q, h->rects[region_id].x); /* left pos */
+ putbe16(&q, h->rects[region_id].y); /* top pos */
+ }
+
+ putbe16(&pseg_len, q - pseg_len - 2);
+
+ if (!s->hide_state) {
+ 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 {
+ return -1;
+ }
+
+ *q++ = 0x0f; /* sync byte */
+ *q++ = 0x12; /* CLUT definition segment */
+ putbe16(&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;
+ a = (h->rects[clut_id].rgba_palette[i] >> 24) & 0xff;
+ r = (h->rects[clut_id].rgba_palette[i] >> 16) & 0xff;
+ g = (h->rects[clut_id].rgba_palette[i] >> 8) & 0xff;
+ b = (h->rects[clut_id].rgba_palette[i] >> 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;
+ }
+ }
+
+ putbe16(&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 */
+ putbe16(&q, page_id);
+ pseg_len = q;
+ q += 2; /* segment length */
+ *q++ = region_id;
+ *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */
+ putbe16(&q, h->rects[region_id].w); /* region width */
+ putbe16(&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 */
+
+ if (!s->hide_state) {
+ putbe16(&q, region_id); /* object_id == region_id */
+ *q++ = (0 << 6) | (0 << 4);
+ *q++ = 0;
+ *q++ = 0xf0;
+ *q++ = 0;
+ }
+
+ putbe16(&pseg_len, q - pseg_len - 2);
+ }
+
+ if (!s->hide_state) {
+
+ for (object_id = 0; object_id < h->num_rects; object_id++) {
+ /* Object Data segment */
+
+ if (h->rects[object_id].nb_colors <= 4) {
+ /* 2 bpp, some decoders do not support it correctly */
+ bpp_index = 0;
+ } else if (h->rects[object_id].nb_colors <= 16) {
+ /* 4 bpp, standard encoding */
+ bpp_index = 1;
+ } else {
+ return -1;
+ }
+
+ *q++ = 0x0f; /* sync byte */
+ *q++ = 0x13;
+ putbe16(&q, page_id);
+ pseg_len = q;
+ q += 2; /* segment length */
+
+ putbe16(&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;
+ void (*dvb_encode_rle)(uint8_t **pq,
+ const uint8_t *bitmap, int linesize,
+ int w, int h);
+ ptop_field_len = q;
+ q += 2;
+ pbottom_field_len = q;
+ q += 2;
+
+ if (bpp_index == 0)
+ dvb_encode_rle = dvb_encode_rle2;
+ else
+ dvb_encode_rle = dvb_encode_rle4;
+
+ top_ptr = q;
+ dvb_encode_rle(&q, h->rects[object_id].bitmap, 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].bitmap + h->rects[object_id].w,
+ h->rects[object_id].w * 2, h->rects[object_id].w,
+ h->rects[object_id].h >> 1);
+
+ putbe16(&ptop_field_len, bottom_ptr - top_ptr);
+ putbe16(&pbottom_field_len, q - bottom_ptr);
+ }
+
+ putbe16(&pseg_len, q - pseg_len - 2);
+ }
+ }
+
+ /* end of display set segment */
+
+ *q++ = 0x0f; /* sync_byte */
+ *q++ = 0x80; /* segment_type */
+ putbe16(&q, page_id);
+ pseg_len = q;
+ q += 2; /* segment length */
+
+ putbe16(&pseg_len, q - pseg_len - 2);
+
+ *q++ = 0xff; /* end of PES data */
+
+ s->object_version = (s->object_version + 1) & 0xf;
+ s->hide_state = !s->hide_state;
+ return q - outbuf;
+}
+
+static int dvbsub_init_decoder(AVCodecContext *avctx)
+{
+ return 0;
+}
+
+static int dvbsub_close_decoder(AVCodecContext *avctx)
+{
+ return 0;
+}
+
+static int dvbsub_encode(AVCodecContext *avctx,
+ unsigned char *buf, int buf_size, void *data)
+{
+ DVBSubtitleContext *s = avctx->priv_data;
+ AVSubtitle *sub = data;
+ int ret;
+
+ ret = encode_dvb_subtitles(s, buf, sub);
+ return ret;
+}
+
+AVCodec dvbsub_encoder = {
+ "dvbsub",
+ CODEC_TYPE_SUBTITLE,
+ CODEC_ID_DVB_SUBTITLE,
+ sizeof(DVBSubtitleContext),
+ dvbsub_init_decoder,
+ dvbsub_encode,
+ dvbsub_close_decoder,
+};
diff --git a/contrib/ffmpeg/libavcodec/dvbsubdec.c b/contrib/ffmpeg/libavcodec/dvbsubdec.c
new file mode 100644
index 000000000..ff43ca6b9
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/dvbsubdec.c
@@ -0,0 +1,1633 @@
+/*
+ * DVB subtitle decoding 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 "dsputil.h"
+#include "bitstream.h"
+
+//#define DEBUG
+//#define DEBUG_PACKET_CONTENTS
+//#define DEBUG_SAVE_IMAGES
+
+#define DVBSUB_PAGE_SEGMENT 0x10
+#define DVBSUB_REGION_SEGMENT 0x11
+#define DVBSUB_CLUT_SEGMENT 0x12
+#define DVBSUB_OBJECT_SEGMENT 0x13
+#define DVBSUB_DISPLAY_SEGMENT 0x80
+
+static unsigned char *cm;
+
+#ifdef DEBUG_SAVE_IMAGES
+#undef fprintf
+#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);
+ 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);
+
+
+ snprintf(fname2, 40, "%s-a.pgm", filename);
+
+ f = fopen(fname2, "w");
+ if (!f) {
+ perror(fname2);
+ exit(1);
+ }
+ 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, 40, "%s.ppm", filename);
+
+ f = fopen(fname, "w");
+ if (!f) {
+ perror(fname);
+ 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 = 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);
+ exit(1);
+ }
+ 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, 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
+
+#define RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
+
+typedef struct DVBSubCLUT {
+ int id;
+
+ 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 fgcolour;
+ int bgcolour;
+
+ struct DVBSubObjectDisplay *region_list_next;
+ struct DVBSubObjectDisplay *object_list_next;
+} DVBSubObjectDisplay;
+
+typedef struct DVBSubObject {
+ int id;
+
+ 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 width;
+ int height;
+ int depth;
+
+ int clut;
+ int bgcolour;
+
+ uint8_t *pbuf;
+ int buf_size;
+
+ DVBSubObjectDisplay *display_list;
+
+ struct DVBSubRegion *next;
+} DVBSubRegion;
+
+typedef struct DVBSubContext {
+ int composition_id;
+ int ancillary_id;
+
+ int time_out;
+ DVBSubRegion *region_list;
+ DVBSubCLUT *clut_list;
+ DVBSubObject *object_list;
+
+ int display_list_size;
+ DVBSubRegionDisplay *display_list;
+} DVBSubContext;
+
+
+static DVBSubObject* get_object(DVBSubContext *ctx, int object_id)
+{
+ DVBSubObject *ptr = ctx->object_list;
+
+ while (ptr != NULL && 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 != NULL && 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 != NULL && 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 != NULL) {
+ display = region->display_list;
+
+ object = get_object(ctx, display->object_id);
+
+ if (object != NULL) {
+ obj_disp = object->display_list;
+ obj_disp_ptr = &object->display_list;
+
+ while (obj_disp != NULL && obj_disp != display) {
+ obj_disp_ptr = &obj_disp->object_list_next;
+ obj_disp = obj_disp->object_list_next;
+ }
+
+ if (obj_disp) {
+ *obj_disp_ptr = obj_disp->object_list_next;
+
+ if (object->display_list == NULL) {
+ obj2 = ctx->object_list;
+ obj2_ptr = &ctx->object_list;
+
+ while (obj2 != NULL && obj2 != object) {
+ obj2_ptr = &obj2->next;
+ obj2 = obj2->next;
+ }
+
+ *obj2_ptr = obj2->next;
+
+ av_free(obj2);
+ }
+ }
+ }
+
+ region->display_list = display->region_list_next;
+
+ av_free(display);
+ }
+
+}
+
+static void delete_state(DVBSubContext *ctx)
+{
+ DVBSubRegion *region;
+ DVBSubCLUT *clut;
+
+ while (ctx->region_list != NULL)
+ {
+ region = ctx->region_list;
+
+ ctx->region_list = region->next;
+
+ delete_region_display_list(ctx, region);
+ if (region->pbuf != NULL)
+ av_free(region->pbuf);
+
+ av_free(region);
+ }
+
+ while (ctx->clut_list != NULL)
+ {
+ clut = ctx->clut_list;
+
+ ctx->clut_list = clut->next;
+
+ av_free(clut);
+ }
+
+ /* Should already be null */
+ if (ctx->object_list != NULL)
+ av_log(0, AV_LOG_ERROR, "Memory deallocation error!\n");
+}
+
+static int dvbsub_init_decoder(AVCodecContext *avctx)
+{
+ int i, r, g, b, a = 0;
+ DVBSubContext *ctx = (DVBSubContext*) avctx->priv_data;
+
+ cm = ff_cropTbl + MAX_NEG_CROP;
+
+ memset(avctx->priv_data, 0, sizeof(DVBSubContext));
+
+ ctx->composition_id = avctx->sub_id & 0xffff;
+ ctx->ancillary_id = avctx->sub_id >> 16;
+
+ 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 int dvbsub_close_decoder(AVCodecContext *avctx)
+{
+ DVBSubContext *ctx = (DVBSubContext*) avctx->priv_data;
+ DVBSubRegionDisplay *display;
+
+ delete_state(ctx);
+
+ while (ctx->display_list != NULL)
+ {
+ 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,
+ uint8_t **srcbuf, int buf_size,
+ int non_mod, uint8_t *map_table)
+{
+ GetBitContext gb;
+
+ int bits;
+ int run_length;
+ int pixels_read = 0;
+
+ init_get_bits(&gb, *srcbuf, buf_size << 8);
+
+ while (get_bits_count(&gb) < (buf_size << 8) && pixels_read < dbuf_len) {
+ bits = get_bits(&gb, 2);
+
+ if (bits != 0) {
+ if (non_mod != 1 || bits != 1) {
+ if (map_table != NULL)
+ *destbuf++ = map_table[bits];
+ else
+ *destbuf++ = bits;
+ }
+ pixels_read++;
+ } else {
+ bits = get_bits(&gb, 1);
+ 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 != NULL)
+ bits = map_table[bits];
+ while (run_length-- > 0 && pixels_read < dbuf_len) {
+ *destbuf++ = bits;
+ pixels_read++;
+ }
+ }
+ } else {
+ bits = get_bits(&gb, 1);
+ 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 != NULL)
+ 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 != NULL)
+ bits = map_table[bits];
+ while (run_length-- > 0 && pixels_read < dbuf_len) {
+ *destbuf++ = bits;
+ pixels_read++;
+ }
+ }
+ } else if (bits == 1) {
+ pixels_read += 2;
+ if (map_table != NULL)
+ bits = map_table[0];
+ else
+ bits = 0;
+ if (pixels_read <= dbuf_len) {
+ *destbuf++ = bits;
+ *destbuf++ = bits;
+ }
+ } else {
+ (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;
+ return pixels_read;
+ }
+ } else {
+ if (map_table != NULL)
+ bits = map_table[0];
+ else
+ bits = 0;
+ *destbuf++ = bits;
+ pixels_read++;
+ }
+ }
+ }
+ }
+
+ if (get_bits(&gb, 6) != 0)
+ 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,
+ uint8_t **srcbuf, int buf_size,
+ int non_mod, uint8_t *map_table)
+{
+ GetBitContext gb;
+
+ int bits;
+ int run_length;
+ int pixels_read = 0;
+
+ init_get_bits(&gb, *srcbuf, buf_size << 8);
+
+ while (get_bits_count(&gb) < (buf_size << 8) && pixels_read < dbuf_len) {
+ bits = get_bits(&gb, 4);
+
+ if (bits != 0) {
+ if (non_mod != 1 || bits != 1) {
+ if (map_table != NULL)
+ *destbuf++ = map_table[bits];
+ else
+ *destbuf++ = bits;
+ }
+ pixels_read++;
+ } else {
+ bits = get_bits(&gb, 1);
+ 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 != NULL)
+ bits = map_table[0];
+ else
+ bits = 0;
+
+ while (run_length-- > 0 && pixels_read < dbuf_len) {
+ *destbuf++ = bits;
+ pixels_read++;
+ }
+ } else {
+ bits = get_bits(&gb, 1);
+ 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 != NULL)
+ 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 != NULL)
+ 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 != NULL)
+ bits = map_table[bits];
+ while (run_length-- > 0 && pixels_read < dbuf_len) {
+ *destbuf++ = bits;
+ pixels_read++;
+ }
+ }
+ } else if (bits == 1) {
+ pixels_read += 2;
+ if (map_table != NULL)
+ bits = map_table[0];
+ else
+ bits = 0;
+ if (pixels_read <= dbuf_len) {
+ *destbuf++ = bits;
+ *destbuf++ = bits;
+ }
+ } else {
+ if (map_table != NULL)
+ bits = map_table[0];
+ else
+ bits = 0;
+ *destbuf++ = bits;
+ pixels_read ++;
+ }
+ }
+ }
+ }
+ }
+
+ if (get_bits(&gb, 8) != 0)
+ 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,
+ uint8_t **srcbuf, int buf_size,
+ int non_mod, uint8_t *map_table)
+{
+ uint8_t *sbuf_end = (*srcbuf) + buf_size;
+ int bits;
+ int run_length;
+ int pixels_read = 0;
+
+ while (*srcbuf < sbuf_end && pixels_read < dbuf_len) {
+ bits = *(*srcbuf)++;
+
+ if (bits != 0) {
+ if (non_mod != 1 || bits != 1) {
+ if (map_table != NULL)
+ *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 != NULL)
+ 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 != NULL)
+ bits = map_table[bits];
+ else while (run_length-- > 0 && pixels_read < dbuf_len) {
+ *destbuf++ = bits;
+ pixels_read++;
+ }
+ }
+ }
+ }
+
+ if (*(*srcbuf)++ != 0)
+ 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,
+ uint8_t *buf, int buf_size, int top_bottom, int non_mod)
+{
+ DVBSubContext *ctx = (DVBSubContext*) avctx->priv_data;
+
+ DVBSubRegion *region = get_region(ctx, display->region_id);
+ 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;
+
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_INFO, "DVB pixel block size %d, %s field:\n", buf_size,
+ top_bottom ? "bottom" : "top");
+#endif
+
+#ifdef DEBUG_PACKET_CONTENTS
+ for (i = 0; i < buf_size; i++)
+ {
+ if (i % 16 == 0)
+ av_log(avctx, AV_LOG_INFO, "0x%08p: ", buf+i);
+
+ av_log(avctx, AV_LOG_INFO, "%02x ", buf[i]);
+ if (i % 16 == 15)
+ av_log(avctx, AV_LOG_INFO, "\n");
+ }
+
+ if (i % 16 != 0)
+ av_log(avctx, AV_LOG_INFO, "\n");
+
+#endif
+
+ if (region == 0)
+ return;
+
+ pbuf = region->pbuf;
+
+ x_pos = display->x_pos;
+ y_pos = display->y_pos;
+
+ if ((y_pos & 1) != top_bottom)
+ y_pos++;
+
+ while (buf < buf_end) {
+ if (x_pos > region->width || y_pos > region->height) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid object location!\n");
+ 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) + x_pos,
+ region->width - x_pos, &buf, buf_size,
+ non_mod, map_table);
+ 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) + x_pos,
+ region->width - x_pos, &buf, buf_size,
+ non_mod, map_table);
+ 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) + x_pos,
+ region->width - x_pos, &buf, buf_size,
+ non_mod, NULL);
+ 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,
+ uint8_t *buf, int buf_size)
+{
+ DVBSubContext *ctx = (DVBSubContext*) avctx->priv_data;
+
+ uint8_t *buf_end = buf + buf_size;
+ uint8_t *block;
+ int object_id;
+ DVBSubObject *object;
+ DVBSubObjectDisplay *display;
+ int top_field_len, bottom_field_len;
+
+ int coding_method, non_modifying_colour;
+
+ object_id = BE_16(buf);
+ buf += 2;
+
+ object = get_object(ctx, object_id);
+
+ if (!object)
+ return;
+
+ coding_method = ((*buf) >> 2) & 3;
+ non_modifying_colour = ((*buf++) >> 1) & 1;
+
+ if (coding_method == 0) {
+ top_field_len = BE_16(buf);
+ buf += 2;
+ bottom_field_len = BE_16(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 != 0; display = display->object_list_next) {
+ block = buf;
+
+ dvbsub_parse_pixel_data_block(avctx, display, block, top_field_len, 0,
+ non_modifying_colour);
+
+ if (bottom_field_len > 0)
+ block = buf + top_field_len;
+ else
+ bottom_field_len = top_field_len;
+
+ dvbsub_parse_pixel_data_block(avctx, display, block, bottom_field_len, 1,
+ non_modifying_colour);
+ }
+
+/* } else if (coding_method == 1) {*/
+
+ } else {
+ av_log(avctx, AV_LOG_ERROR, "Unknown object coding %d\n", coding_method);
+ }
+
+}
+
+#define SCALEBITS 10
+#define ONE_HALF (1 << (SCALEBITS - 1))
+#define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
+
+#define YUV_TO_RGB1_CCIR(cb1, cr1)\
+{\
+ cb = (cb1) - 128;\
+ cr = (cr1) - 128;\
+ r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;\
+ g_add = - FIX(0.34414*255.0/224.0) * cb - FIX(0.71414*255.0/224.0) * cr + \
+ ONE_HALF;\
+ b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;\
+}
+
+#define YUV_TO_RGB2_CCIR(r, g, b, y1)\
+{\
+ y = ((y1) - 16) * FIX(255.0/219.0);\
+ r = cm[(y + r_add) >> SCALEBITS];\
+ g = cm[(y + g_add) >> SCALEBITS];\
+ b = cm[(y + b_add) >> SCALEBITS];\
+}
+
+
+static void dvbsub_parse_clut_segment(AVCodecContext *avctx,
+ uint8_t *buf, int buf_size)
+{
+ DVBSubContext *ctx = (DVBSubContext*) avctx->priv_data;
+
+ uint8_t *buf_end = buf + buf_size;
+ int clut_id;
+ DVBSubCLUT *clut;
+ int entry_id, depth , full_range;
+ int y, cr, cb, alpha;
+ int r, g, b, r_add, g_add, b_add;
+
+#ifdef DEBUG_PACKET_CONTENTS
+ int i;
+
+ av_log(avctx, AV_LOG_INFO, "DVB clut packet:\n");
+
+ for (i=0; i < buf_size; i++)
+ {
+ av_log(avctx, AV_LOG_INFO, "%02x ", buf[i]);
+ if (i % 16 == 15)
+ av_log(avctx, AV_LOG_INFO, "\n");
+ }
+
+ if (i % 16 != 0)
+ av_log(avctx, AV_LOG_INFO, "\n");
+
+#endif
+
+ clut_id = *buf++;
+ buf += 1;
+
+ clut = get_clut(ctx, clut_id);
+
+ if (clut == NULL) {
+ clut = av_malloc(sizeof(DVBSubCLUT));
+
+ memcpy(clut, &default_clut, sizeof(DVBSubCLUT));
+
+ clut->id = clut_id;
+
+ clut->next = ctx->clut_list;
+ ctx->clut_list = clut;
+ }
+
+ 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);
+
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_INFO, "clut %d := (%d,%d,%d,%d)\n", entry_id, r, g, b, alpha);
+#endif
+
+ 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,
+ uint8_t *buf, int buf_size)
+{
+ DVBSubContext *ctx = (DVBSubContext*) avctx->priv_data;
+
+ uint8_t *buf_end = buf + buf_size;
+ int region_id, object_id;
+ DVBSubRegion *region;
+ DVBSubObject *object;
+ DVBSubObjectDisplay *display;
+ int fill;
+
+ if (buf_size < 10)
+ return;
+
+ region_id = *buf++;
+
+ region = get_region(ctx, region_id);
+
+ if (region == NULL)
+ {
+ region = av_mallocz(sizeof(DVBSubRegion));
+
+ region->id = region_id;
+
+ region->next = ctx->region_list;
+ ctx->region_list = region;
+ }
+
+ fill = ((*buf++) >> 3) & 1;
+
+ region->width = BE_16(buf);
+ buf += 2;
+ region->height = BE_16(buf);
+ buf += 2;
+
+ if (region->width * region->height != region->buf_size) {
+ if (region->pbuf != 0)
+ av_free(region->pbuf);
+
+ region->buf_size = region->width * region->height;
+
+ region->pbuf = av_malloc(region->buf_size);
+
+ fill = 1;
+ }
+
+ region->depth = 1 << (((*buf++) >> 2) & 7);
+ region->clut = *buf++;
+
+ if (region->depth == 8)
+ region->bgcolour = *buf++;
+ else {
+ buf += 1;
+
+ if (region->depth == 4)
+ region->bgcolour = (((*buf++) >> 4) & 15);
+ else
+ region->bgcolour = (((*buf++) >> 2) & 3);
+ }
+
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_INFO, "Region %d, (%dx%d)\n", region_id, region->width, region->height);
+#endif
+
+ if (fill) {
+ memset(region->pbuf, region->bgcolour, region->buf_size);
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_INFO, "Fill region (%d)\n", region->bgcolour);
+#endif
+ }
+
+ delete_region_display_list(ctx, region);
+
+ while (buf + 5 < buf_end) {
+ object_id = BE_16(buf);
+ buf += 2;
+
+ object = get_object(ctx, object_id);
+
+ if (object == NULL) {
+ 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 = BE_16(buf) & 0xfff;
+ buf += 2;
+ display->y_pos = BE_16(buf) & 0xfff;
+ buf += 2;
+
+ if ((object->type == 1 || object->type == 2) && buf+1 < buf_end) {
+ display->fgcolour = *buf++;
+ display->bgcolour = *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,
+ uint8_t *buf, int buf_size)
+{
+ DVBSubContext *ctx = (DVBSubContext*) avctx->priv_data;
+ DVBSubRegionDisplay *display;
+ DVBSubRegionDisplay *tmp_display_list, **tmp_ptr;
+
+ uint8_t *buf_end = buf + buf_size;
+ int region_id;
+ int page_state;
+
+ if (buf_size < 1)
+ return;
+
+ ctx->time_out = *buf++;
+ page_state = ((*buf++) >> 2) & 3;
+
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_INFO, "Page time out %ds, state %d\n", ctx->time_out, page_state);
+#endif
+
+ if (page_state == 2)
+ {
+ delete_state(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 != NULL && display->region_id != region_id) {
+ tmp_ptr = &display->next;
+ display = display->next;
+ }
+
+ if (display == NULL)
+ display = av_mallocz(sizeof(DVBSubRegionDisplay));
+
+ display->region_id = region_id;
+
+ display->x_pos = BE_16(buf);
+ buf += 2;
+ display->y_pos = BE_16(buf);
+ buf += 2;
+
+ *tmp_ptr = display->next;
+
+ display->next = ctx->display_list;
+ ctx->display_list = display;
+ ctx->display_list_size++;
+
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_INFO, "Region %d, (%d,%d)\n", region_id, display->x_pos, display->y_pos);
+#endif
+ }
+
+ while (tmp_display_list != 0) {
+ display = tmp_display_list;
+
+ tmp_display_list = display->next;
+
+ av_free(display);
+ }
+
+}
+
+
+#ifdef DEBUG_SAVE_IMAGES
+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 != NULL; 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 != NULL; 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, 32, "dvbs.%d", fileno_index);
+
+ png_save2(filename, pbuf, width, height);
+
+ av_free(pbuf);
+ }
+
+ fileno_index++;
+}
+#endif
+
+static int dvbsub_display_end_segment(AVCodecContext *avctx, uint8_t *buf,
+ int buf_size, AVSubtitle *sub)
+{
+ DVBSubContext *ctx = (DVBSubContext*) avctx->priv_data;
+
+ DVBSubRegion *region;
+ DVBSubRegionDisplay *display;
+ AVSubtitleRect *rect;
+ DVBSubCLUT *clut;
+ uint32_t *clut_table;
+ int i;
+
+ sub->rects = NULL;
+ sub->start_display_time = 0;
+ sub->end_display_time = ctx->time_out * 1000;
+ sub->format = 0;
+
+ sub->num_rects = ctx->display_list_size;
+
+ if (sub->num_rects > 0)
+ sub->rects = av_mallocz(sizeof(AVSubtitleRect) * sub->num_rects);
+
+ i = 0;
+
+ for (display = ctx->display_list; display != NULL; display = display->next) {
+ region = get_region(ctx, display->region_id);
+ rect = &sub->rects[i];
+
+ if (region == NULL)
+ continue;
+
+ rect->x = display->x_pos;
+ rect->y = display->y_pos;
+ rect->w = region->width;
+ rect->h = region->height;
+ rect->nb_colors = 16;
+ rect->linesize = region->width;
+
+ clut = get_clut(ctx, region->clut);
+
+ if (clut == NULL)
+ 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->rgba_palette = av_malloc((1 << region->depth) * sizeof(uint32_t));
+ memcpy(rect->rgba_palette, clut_table, (1 << region->depth) * sizeof(uint32_t));
+
+ rect->bitmap = av_malloc(region->buf_size);
+ memcpy(rect->bitmap, region->pbuf, region->buf_size);
+
+ i++;
+ }
+
+ sub->num_rects = i;
+
+#ifdef DEBUG_SAVE_IMAGES
+ save_display_set(ctx);
+#endif
+
+ return 1;
+}
+
+static int dvbsub_decode(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ DVBSubContext *ctx = (DVBSubContext*) avctx->priv_data;
+ AVSubtitle *sub = (AVSubtitle*) data;
+ uint8_t *p, *p_end;
+ int segment_type;
+ int page_id;
+ int segment_length;
+
+#ifdef DEBUG_PACKET_CONTENTS
+ int i;
+
+ av_log(avctx, AV_LOG_INFO, "DVB sub packet:\n");
+
+ for (i=0; i < buf_size; i++)
+ {
+ av_log(avctx, AV_LOG_INFO, "%02x ", buf[i]);
+ if (i % 16 == 15)
+ av_log(avctx, AV_LOG_INFO, "\n");
+ }
+
+ if (i % 16 != 0)
+ av_log(avctx, AV_LOG_INFO, "\n");
+
+#endif
+
+ if (buf_size <= 2)
+ return -1;
+
+ p = buf;
+ p_end = buf + buf_size;
+
+ while (p < p_end && *p == 0x0f)
+ {
+ p += 1;
+ segment_type = *p++;
+ page_id = BE_16(p);
+ p += 2;
+ segment_length = BE_16(p);
+ p += 2;
+
+ if (page_id == ctx->composition_id || page_id == ctx->ancillary_id) {
+ switch (segment_type) {
+ case DVBSUB_PAGE_SEGMENT:
+ dvbsub_parse_page_segment(avctx, p, segment_length);
+ break;
+ case DVBSUB_REGION_SEGMENT:
+ dvbsub_parse_region_segment(avctx, p, segment_length);
+ break;
+ case DVBSUB_CLUT_SEGMENT:
+ dvbsub_parse_clut_segment(avctx, p, segment_length);
+ break;
+ case DVBSUB_OBJECT_SEGMENT:
+ dvbsub_parse_object_segment(avctx, p, segment_length);
+ break;
+ case DVBSUB_DISPLAY_SEGMENT:
+ *data_size = dvbsub_display_end_segment(avctx, p, segment_length, sub);
+ break;
+ default:
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_INFO, "Subtitling segment type 0x%x, page id %d, length %d\n",
+ segment_type, page_id, segment_length);
+#endif
+ break;
+ }
+ }
+
+ p += segment_length;
+ }
+
+ if (p != p_end)
+ {
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_INFO, "Junk at end of packet\n");
+#endif
+ return -1;
+ }
+
+ return buf_size;
+}
+
+
+AVCodec dvbsub_decoder = {
+ "dvbsub",
+ CODEC_TYPE_SUBTITLE,
+ CODEC_ID_DVB_SUBTITLE,
+ sizeof(DVBSubContext),
+ dvbsub_init_decoder,
+ NULL,
+ dvbsub_close_decoder,
+ dvbsub_decode,
+};
+
+/* 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 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,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size)
+{
+ DVBSubParseContext *pc = s->priv_data;
+ uint8_t *p, *p_end;
+ int len, buf_pos = 0;
+
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_INFO, "DVB parse packet pts=%"PRIx64", lpts=%"PRIx64", cpts=%"PRIx64":\n",
+ s->pts, s->last_pts, s->cur_frame_pts[s->cur_frame_start_index]);
+#endif
+
+#ifdef DEBUG_PACKET_CONTENTS
+ int i;
+
+ for (i=0; i < buf_size; i++)
+ {
+ av_log(avctx, AV_LOG_INFO, "%02x ", buf[i]);
+ if (i % 16 == 15)
+ av_log(avctx, AV_LOG_INFO, "\n");
+ }
+
+ if (i % 16 != 0)
+ av_log(avctx, AV_LOG_INFO, "\n");
+
+#endif
+
+ *poutbuf = NULL;
+ *poutbuf_size = 0;
+
+ s->fetch_timestamp = 1;
+
+ if (s->last_pts != s->pts && s->last_pts != AV_NOPTS_VALUE) /* Start of a new packet */
+ {
+ if (pc->packet_index != pc->packet_start)
+ {
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_INFO, "Discarding %d bytes\n",
+ pc->packet_index - pc->packet_start);
+#endif
+ }
+
+ pc->packet_start = 0;
+ pc->packet_index = 0;
+
+ if (buf_size < 2 || buf[0] != 0x20 || buf[1] != 0x00) {
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_INFO, "Bad packet header\n");
+#endif
+ 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 = BE_16(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)
+ {
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_INFO, "Junk at end of packet\n");
+#endif
+ }
+ 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->last_pts == AV_NOPTS_VALUE)
+ s->last_pts = s->pts;
+
+ return buf_size;
+}
+
+static void dvbsub_parse_close(AVCodecParserContext *s)
+{
+ DVBSubParseContext *pc = s->priv_data;
+ av_freep(&pc->packet_buf);
+}
+
+AVCodecParser dvbsub_parser = {
+ { CODEC_ID_DVB_SUBTITLE },
+ sizeof(DVBSubParseContext),
+ dvbsub_parse_init,
+ dvbsub_parse,
+ dvbsub_parse_close,
+};
diff --git a/contrib/ffmpeg/libavcodec/dvdata.h b/contrib/ffmpeg/libavcodec/dvdata.h
new file mode 100644
index 000000000..dce4aba98
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/dvdata.h
@@ -0,0 +1,2724 @@
+/*
+ * 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 dvdata.h
+ * Constants for DV codec.
+ */
+
+/*
+ * 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 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 */
+ int frame_rate;
+ int frame_rate_base;
+ 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 */
+ const uint16_t *video_place; /* positions of all DV macro blocks */
+ enum PixelFormat pix_fmt; /* picture pixel format */
+
+ int audio_stride; /* size of audio_shuffle table */
+ int audio_min_samples[3];/* min ammount 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 uint16_t (*audio_shuffle)[9]; /* PCM shuffling table */
+} DVprofile;
+
+#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[409] = {
+ 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[409] = {
+ 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[409] = {
+ 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[409] = {
+ 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,
+};
+
+/* unquant tables (not used directly) */
+static const uint8_t dv_88_areas[64] = {
+ 0,0,0,1,1,1,2,2,
+ 0,0,1,1,1,2,2,2,
+ 0,1,1,1,2,2,2,3,
+ 1,1,1,2,2,2,3,3,
+ 1,1,2,2,2,3,3,3,
+ 1,2,2,2,3,3,3,3,
+ 2,2,2,3,3,3,3,3,
+ 2,2,3,3,3,3,3,3,
+};
+
+static const uint8_t dv_248_areas[64] = {
+ 0,0,1,1,1,2,2,3,
+ 0,0,1,1,2,2,2,3,
+ 0,1,1,2,2,2,3,3,
+ 0,1,1,2,2,2,3,3,
+ 1,1,2,2,2,3,3,3,
+ 1,1,2,2,2,3,3,3,
+ 1,2,2,2,3,3,3,3,
+ 1,2,2,3,3,3,3,3,
+};
+
+static const uint8_t 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 },
+};
+
+static const uint8_t dv_quant_offset[4] = { 6, 3, 0, 1 };
+
+/* NOTE: I prefer hardcoding the positionning of dv blocks, it is
+ simpler :-) */
+
+static const uint16_t dv_place_420[1620] = {
+ 0x0c24, 0x2412, 0x3036, 0x0000, 0x1848,
+ 0x0e24, 0x2612, 0x3236, 0x0200, 0x1a48,
+ 0x1024, 0x2812, 0x3436, 0x0400, 0x1c48,
+ 0x1026, 0x2814, 0x3438, 0x0402, 0x1c4a,
+ 0x0e26, 0x2614, 0x3238, 0x0202, 0x1a4a,
+ 0x0c26, 0x2414, 0x3038, 0x0002, 0x184a,
+ 0x0c28, 0x2416, 0x303a, 0x0004, 0x184c,
+ 0x0e28, 0x2616, 0x323a, 0x0204, 0x1a4c,
+ 0x1028, 0x2816, 0x343a, 0x0404, 0x1c4c,
+ 0x102a, 0x2818, 0x343c, 0x0406, 0x1c4e,
+ 0x0e2a, 0x2618, 0x323c, 0x0206, 0x1a4e,
+ 0x0c2a, 0x2418, 0x303c, 0x0006, 0x184e,
+ 0x0c2c, 0x241a, 0x303e, 0x0008, 0x1850,
+ 0x0e2c, 0x261a, 0x323e, 0x0208, 0x1a50,
+ 0x102c, 0x281a, 0x343e, 0x0408, 0x1c50,
+ 0x102e, 0x281c, 0x3440, 0x040a, 0x1c52,
+ 0x0e2e, 0x261c, 0x3240, 0x020a, 0x1a52,
+ 0x0c2e, 0x241c, 0x3040, 0x000a, 0x1852,
+ 0x0c30, 0x241e, 0x3042, 0x000c, 0x1854,
+ 0x0e30, 0x261e, 0x3242, 0x020c, 0x1a54,
+ 0x1030, 0x281e, 0x3442, 0x040c, 0x1c54,
+ 0x1032, 0x2820, 0x3444, 0x040e, 0x1c56,
+ 0x0e32, 0x2620, 0x3244, 0x020e, 0x1a56,
+ 0x0c32, 0x2420, 0x3044, 0x000e, 0x1856,
+ 0x0c34, 0x2422, 0x3046, 0x0010, 0x1858,
+ 0x0e34, 0x2622, 0x3246, 0x0210, 0x1a58,
+ 0x1034, 0x2822, 0x3446, 0x0410, 0x1c58,
+ 0x1224, 0x2a12, 0x3636, 0x0600, 0x1e48,
+ 0x1424, 0x2c12, 0x3836, 0x0800, 0x2048,
+ 0x1624, 0x2e12, 0x3a36, 0x0a00, 0x2248,
+ 0x1626, 0x2e14, 0x3a38, 0x0a02, 0x224a,
+ 0x1426, 0x2c14, 0x3838, 0x0802, 0x204a,
+ 0x1226, 0x2a14, 0x3638, 0x0602, 0x1e4a,
+ 0x1228, 0x2a16, 0x363a, 0x0604, 0x1e4c,
+ 0x1428, 0x2c16, 0x383a, 0x0804, 0x204c,
+ 0x1628, 0x2e16, 0x3a3a, 0x0a04, 0x224c,
+ 0x162a, 0x2e18, 0x3a3c, 0x0a06, 0x224e,
+ 0x142a, 0x2c18, 0x383c, 0x0806, 0x204e,
+ 0x122a, 0x2a18, 0x363c, 0x0606, 0x1e4e,
+ 0x122c, 0x2a1a, 0x363e, 0x0608, 0x1e50,
+ 0x142c, 0x2c1a, 0x383e, 0x0808, 0x2050,
+ 0x162c, 0x2e1a, 0x3a3e, 0x0a08, 0x2250,
+ 0x162e, 0x2e1c, 0x3a40, 0x0a0a, 0x2252,
+ 0x142e, 0x2c1c, 0x3840, 0x080a, 0x2052,
+ 0x122e, 0x2a1c, 0x3640, 0x060a, 0x1e52,
+ 0x1230, 0x2a1e, 0x3642, 0x060c, 0x1e54,
+ 0x1430, 0x2c1e, 0x3842, 0x080c, 0x2054,
+ 0x1630, 0x2e1e, 0x3a42, 0x0a0c, 0x2254,
+ 0x1632, 0x2e20, 0x3a44, 0x0a0e, 0x2256,
+ 0x1432, 0x2c20, 0x3844, 0x080e, 0x2056,
+ 0x1232, 0x2a20, 0x3644, 0x060e, 0x1e56,
+ 0x1234, 0x2a22, 0x3646, 0x0610, 0x1e58,
+ 0x1434, 0x2c22, 0x3846, 0x0810, 0x2058,
+ 0x1634, 0x2e22, 0x3a46, 0x0a10, 0x2258,
+ 0x1824, 0x3012, 0x3c36, 0x0c00, 0x2448,
+ 0x1a24, 0x3212, 0x3e36, 0x0e00, 0x2648,
+ 0x1c24, 0x3412, 0x4036, 0x1000, 0x2848,
+ 0x1c26, 0x3414, 0x4038, 0x1002, 0x284a,
+ 0x1a26, 0x3214, 0x3e38, 0x0e02, 0x264a,
+ 0x1826, 0x3014, 0x3c38, 0x0c02, 0x244a,
+ 0x1828, 0x3016, 0x3c3a, 0x0c04, 0x244c,
+ 0x1a28, 0x3216, 0x3e3a, 0x0e04, 0x264c,
+ 0x1c28, 0x3416, 0x403a, 0x1004, 0x284c,
+ 0x1c2a, 0x3418, 0x403c, 0x1006, 0x284e,
+ 0x1a2a, 0x3218, 0x3e3c, 0x0e06, 0x264e,
+ 0x182a, 0x3018, 0x3c3c, 0x0c06, 0x244e,
+ 0x182c, 0x301a, 0x3c3e, 0x0c08, 0x2450,
+ 0x1a2c, 0x321a, 0x3e3e, 0x0e08, 0x2650,
+ 0x1c2c, 0x341a, 0x403e, 0x1008, 0x2850,
+ 0x1c2e, 0x341c, 0x4040, 0x100a, 0x2852,
+ 0x1a2e, 0x321c, 0x3e40, 0x0e0a, 0x2652,
+ 0x182e, 0x301c, 0x3c40, 0x0c0a, 0x2452,
+ 0x1830, 0x301e, 0x3c42, 0x0c0c, 0x2454,
+ 0x1a30, 0x321e, 0x3e42, 0x0e0c, 0x2654,
+ 0x1c30, 0x341e, 0x4042, 0x100c, 0x2854,
+ 0x1c32, 0x3420, 0x4044, 0x100e, 0x2856,
+ 0x1a32, 0x3220, 0x3e44, 0x0e0e, 0x2656,
+ 0x1832, 0x3020, 0x3c44, 0x0c0e, 0x2456,
+ 0x1834, 0x3022, 0x3c46, 0x0c10, 0x2458,
+ 0x1a34, 0x3222, 0x3e46, 0x0e10, 0x2658,
+ 0x1c34, 0x3422, 0x4046, 0x1010, 0x2858,
+ 0x1e24, 0x3612, 0x4236, 0x1200, 0x2a48,
+ 0x2024, 0x3812, 0x4436, 0x1400, 0x2c48,
+ 0x2224, 0x3a12, 0x4636, 0x1600, 0x2e48,
+ 0x2226, 0x3a14, 0x4638, 0x1602, 0x2e4a,
+ 0x2026, 0x3814, 0x4438, 0x1402, 0x2c4a,
+ 0x1e26, 0x3614, 0x4238, 0x1202, 0x2a4a,
+ 0x1e28, 0x3616, 0x423a, 0x1204, 0x2a4c,
+ 0x2028, 0x3816, 0x443a, 0x1404, 0x2c4c,
+ 0x2228, 0x3a16, 0x463a, 0x1604, 0x2e4c,
+ 0x222a, 0x3a18, 0x463c, 0x1606, 0x2e4e,
+ 0x202a, 0x3818, 0x443c, 0x1406, 0x2c4e,
+ 0x1e2a, 0x3618, 0x423c, 0x1206, 0x2a4e,
+ 0x1e2c, 0x361a, 0x423e, 0x1208, 0x2a50,
+ 0x202c, 0x381a, 0x443e, 0x1408, 0x2c50,
+ 0x222c, 0x3a1a, 0x463e, 0x1608, 0x2e50,
+ 0x222e, 0x3a1c, 0x4640, 0x160a, 0x2e52,
+ 0x202e, 0x381c, 0x4440, 0x140a, 0x2c52,
+ 0x1e2e, 0x361c, 0x4240, 0x120a, 0x2a52,
+ 0x1e30, 0x361e, 0x4242, 0x120c, 0x2a54,
+ 0x2030, 0x381e, 0x4442, 0x140c, 0x2c54,
+ 0x2230, 0x3a1e, 0x4642, 0x160c, 0x2e54,
+ 0x2232, 0x3a20, 0x4644, 0x160e, 0x2e56,
+ 0x2032, 0x3820, 0x4444, 0x140e, 0x2c56,
+ 0x1e32, 0x3620, 0x4244, 0x120e, 0x2a56,
+ 0x1e34, 0x3622, 0x4246, 0x1210, 0x2a58,
+ 0x2034, 0x3822, 0x4446, 0x1410, 0x2c58,
+ 0x2234, 0x3a22, 0x4646, 0x1610, 0x2e58,
+ 0x2424, 0x3c12, 0x0036, 0x1800, 0x3048,
+ 0x2624, 0x3e12, 0x0236, 0x1a00, 0x3248,
+ 0x2824, 0x4012, 0x0436, 0x1c00, 0x3448,
+ 0x2826, 0x4014, 0x0438, 0x1c02, 0x344a,
+ 0x2626, 0x3e14, 0x0238, 0x1a02, 0x324a,
+ 0x2426, 0x3c14, 0x0038, 0x1802, 0x304a,
+ 0x2428, 0x3c16, 0x003a, 0x1804, 0x304c,
+ 0x2628, 0x3e16, 0x023a, 0x1a04, 0x324c,
+ 0x2828, 0x4016, 0x043a, 0x1c04, 0x344c,
+ 0x282a, 0x4018, 0x043c, 0x1c06, 0x344e,
+ 0x262a, 0x3e18, 0x023c, 0x1a06, 0x324e,
+ 0x242a, 0x3c18, 0x003c, 0x1806, 0x304e,
+ 0x242c, 0x3c1a, 0x003e, 0x1808, 0x3050,
+ 0x262c, 0x3e1a, 0x023e, 0x1a08, 0x3250,
+ 0x282c, 0x401a, 0x043e, 0x1c08, 0x3450,
+ 0x282e, 0x401c, 0x0440, 0x1c0a, 0x3452,
+ 0x262e, 0x3e1c, 0x0240, 0x1a0a, 0x3252,
+ 0x242e, 0x3c1c, 0x0040, 0x180a, 0x3052,
+ 0x2430, 0x3c1e, 0x0042, 0x180c, 0x3054,
+ 0x2630, 0x3e1e, 0x0242, 0x1a0c, 0x3254,
+ 0x2830, 0x401e, 0x0442, 0x1c0c, 0x3454,
+ 0x2832, 0x4020, 0x0444, 0x1c0e, 0x3456,
+ 0x2632, 0x3e20, 0x0244, 0x1a0e, 0x3256,
+ 0x2432, 0x3c20, 0x0044, 0x180e, 0x3056,
+ 0x2434, 0x3c22, 0x0046, 0x1810, 0x3058,
+ 0x2634, 0x3e22, 0x0246, 0x1a10, 0x3258,
+ 0x2834, 0x4022, 0x0446, 0x1c10, 0x3458,
+ 0x2a24, 0x4212, 0x0636, 0x1e00, 0x3648,
+ 0x2c24, 0x4412, 0x0836, 0x2000, 0x3848,
+ 0x2e24, 0x4612, 0x0a36, 0x2200, 0x3a48,
+ 0x2e26, 0x4614, 0x0a38, 0x2202, 0x3a4a,
+ 0x2c26, 0x4414, 0x0838, 0x2002, 0x384a,
+ 0x2a26, 0x4214, 0x0638, 0x1e02, 0x364a,
+ 0x2a28, 0x4216, 0x063a, 0x1e04, 0x364c,
+ 0x2c28, 0x4416, 0x083a, 0x2004, 0x384c,
+ 0x2e28, 0x4616, 0x0a3a, 0x2204, 0x3a4c,
+ 0x2e2a, 0x4618, 0x0a3c, 0x2206, 0x3a4e,
+ 0x2c2a, 0x4418, 0x083c, 0x2006, 0x384e,
+ 0x2a2a, 0x4218, 0x063c, 0x1e06, 0x364e,
+ 0x2a2c, 0x421a, 0x063e, 0x1e08, 0x3650,
+ 0x2c2c, 0x441a, 0x083e, 0x2008, 0x3850,
+ 0x2e2c, 0x461a, 0x0a3e, 0x2208, 0x3a50,
+ 0x2e2e, 0x461c, 0x0a40, 0x220a, 0x3a52,
+ 0x2c2e, 0x441c, 0x0840, 0x200a, 0x3852,
+ 0x2a2e, 0x421c, 0x0640, 0x1e0a, 0x3652,
+ 0x2a30, 0x421e, 0x0642, 0x1e0c, 0x3654,
+ 0x2c30, 0x441e, 0x0842, 0x200c, 0x3854,
+ 0x2e30, 0x461e, 0x0a42, 0x220c, 0x3a54,
+ 0x2e32, 0x4620, 0x0a44, 0x220e, 0x3a56,
+ 0x2c32, 0x4420, 0x0844, 0x200e, 0x3856,
+ 0x2a32, 0x4220, 0x0644, 0x1e0e, 0x3656,
+ 0x2a34, 0x4222, 0x0646, 0x1e10, 0x3658,
+ 0x2c34, 0x4422, 0x0846, 0x2010, 0x3858,
+ 0x2e34, 0x4622, 0x0a46, 0x2210, 0x3a58,
+ 0x3024, 0x0012, 0x0c36, 0x2400, 0x3c48,
+ 0x3224, 0x0212, 0x0e36, 0x2600, 0x3e48,
+ 0x3424, 0x0412, 0x1036, 0x2800, 0x4048,
+ 0x3426, 0x0414, 0x1038, 0x2802, 0x404a,
+ 0x3226, 0x0214, 0x0e38, 0x2602, 0x3e4a,
+ 0x3026, 0x0014, 0x0c38, 0x2402, 0x3c4a,
+ 0x3028, 0x0016, 0x0c3a, 0x2404, 0x3c4c,
+ 0x3228, 0x0216, 0x0e3a, 0x2604, 0x3e4c,
+ 0x3428, 0x0416, 0x103a, 0x2804, 0x404c,
+ 0x342a, 0x0418, 0x103c, 0x2806, 0x404e,
+ 0x322a, 0x0218, 0x0e3c, 0x2606, 0x3e4e,
+ 0x302a, 0x0018, 0x0c3c, 0x2406, 0x3c4e,
+ 0x302c, 0x001a, 0x0c3e, 0x2408, 0x3c50,
+ 0x322c, 0x021a, 0x0e3e, 0x2608, 0x3e50,
+ 0x342c, 0x041a, 0x103e, 0x2808, 0x4050,
+ 0x342e, 0x041c, 0x1040, 0x280a, 0x4052,
+ 0x322e, 0x021c, 0x0e40, 0x260a, 0x3e52,
+ 0x302e, 0x001c, 0x0c40, 0x240a, 0x3c52,
+ 0x3030, 0x001e, 0x0c42, 0x240c, 0x3c54,
+ 0x3230, 0x021e, 0x0e42, 0x260c, 0x3e54,
+ 0x3430, 0x041e, 0x1042, 0x280c, 0x4054,
+ 0x3432, 0x0420, 0x1044, 0x280e, 0x4056,
+ 0x3232, 0x0220, 0x0e44, 0x260e, 0x3e56,
+ 0x3032, 0x0020, 0x0c44, 0x240e, 0x3c56,
+ 0x3034, 0x0022, 0x0c46, 0x2410, 0x3c58,
+ 0x3234, 0x0222, 0x0e46, 0x2610, 0x3e58,
+ 0x3434, 0x0422, 0x1046, 0x2810, 0x4058,
+ 0x3624, 0x0612, 0x1236, 0x2a00, 0x4248,
+ 0x3824, 0x0812, 0x1436, 0x2c00, 0x4448,
+ 0x3a24, 0x0a12, 0x1636, 0x2e00, 0x4648,
+ 0x3a26, 0x0a14, 0x1638, 0x2e02, 0x464a,
+ 0x3826, 0x0814, 0x1438, 0x2c02, 0x444a,
+ 0x3626, 0x0614, 0x1238, 0x2a02, 0x424a,
+ 0x3628, 0x0616, 0x123a, 0x2a04, 0x424c,
+ 0x3828, 0x0816, 0x143a, 0x2c04, 0x444c,
+ 0x3a28, 0x0a16, 0x163a, 0x2e04, 0x464c,
+ 0x3a2a, 0x0a18, 0x163c, 0x2e06, 0x464e,
+ 0x382a, 0x0818, 0x143c, 0x2c06, 0x444e,
+ 0x362a, 0x0618, 0x123c, 0x2a06, 0x424e,
+ 0x362c, 0x061a, 0x123e, 0x2a08, 0x4250,
+ 0x382c, 0x081a, 0x143e, 0x2c08, 0x4450,
+ 0x3a2c, 0x0a1a, 0x163e, 0x2e08, 0x4650,
+ 0x3a2e, 0x0a1c, 0x1640, 0x2e0a, 0x4652,
+ 0x382e, 0x081c, 0x1440, 0x2c0a, 0x4452,
+ 0x362e, 0x061c, 0x1240, 0x2a0a, 0x4252,
+ 0x3630, 0x061e, 0x1242, 0x2a0c, 0x4254,
+ 0x3830, 0x081e, 0x1442, 0x2c0c, 0x4454,
+ 0x3a30, 0x0a1e, 0x1642, 0x2e0c, 0x4654,
+ 0x3a32, 0x0a20, 0x1644, 0x2e0e, 0x4656,
+ 0x3832, 0x0820, 0x1444, 0x2c0e, 0x4456,
+ 0x3632, 0x0620, 0x1244, 0x2a0e, 0x4256,
+ 0x3634, 0x0622, 0x1246, 0x2a10, 0x4258,
+ 0x3834, 0x0822, 0x1446, 0x2c10, 0x4458,
+ 0x3a34, 0x0a22, 0x1646, 0x2e10, 0x4658,
+ 0x3c24, 0x0c12, 0x1836, 0x3000, 0x0048,
+ 0x3e24, 0x0e12, 0x1a36, 0x3200, 0x0248,
+ 0x4024, 0x1012, 0x1c36, 0x3400, 0x0448,
+ 0x4026, 0x1014, 0x1c38, 0x3402, 0x044a,
+ 0x3e26, 0x0e14, 0x1a38, 0x3202, 0x024a,
+ 0x3c26, 0x0c14, 0x1838, 0x3002, 0x004a,
+ 0x3c28, 0x0c16, 0x183a, 0x3004, 0x004c,
+ 0x3e28, 0x0e16, 0x1a3a, 0x3204, 0x024c,
+ 0x4028, 0x1016, 0x1c3a, 0x3404, 0x044c,
+ 0x402a, 0x1018, 0x1c3c, 0x3406, 0x044e,
+ 0x3e2a, 0x0e18, 0x1a3c, 0x3206, 0x024e,
+ 0x3c2a, 0x0c18, 0x183c, 0x3006, 0x004e,
+ 0x3c2c, 0x0c1a, 0x183e, 0x3008, 0x0050,
+ 0x3e2c, 0x0e1a, 0x1a3e, 0x3208, 0x0250,
+ 0x402c, 0x101a, 0x1c3e, 0x3408, 0x0450,
+ 0x402e, 0x101c, 0x1c40, 0x340a, 0x0452,
+ 0x3e2e, 0x0e1c, 0x1a40, 0x320a, 0x0252,
+ 0x3c2e, 0x0c1c, 0x1840, 0x300a, 0x0052,
+ 0x3c30, 0x0c1e, 0x1842, 0x300c, 0x0054,
+ 0x3e30, 0x0e1e, 0x1a42, 0x320c, 0x0254,
+ 0x4030, 0x101e, 0x1c42, 0x340c, 0x0454,
+ 0x4032, 0x1020, 0x1c44, 0x340e, 0x0456,
+ 0x3e32, 0x0e20, 0x1a44, 0x320e, 0x0256,
+ 0x3c32, 0x0c20, 0x1844, 0x300e, 0x0056,
+ 0x3c34, 0x0c22, 0x1846, 0x3010, 0x0058,
+ 0x3e34, 0x0e22, 0x1a46, 0x3210, 0x0258,
+ 0x4034, 0x1022, 0x1c46, 0x3410, 0x0458,
+ 0x4224, 0x1212, 0x1e36, 0x3600, 0x0648,
+ 0x4424, 0x1412, 0x2036, 0x3800, 0x0848,
+ 0x4624, 0x1612, 0x2236, 0x3a00, 0x0a48,
+ 0x4626, 0x1614, 0x2238, 0x3a02, 0x0a4a,
+ 0x4426, 0x1414, 0x2038, 0x3802, 0x084a,
+ 0x4226, 0x1214, 0x1e38, 0x3602, 0x064a,
+ 0x4228, 0x1216, 0x1e3a, 0x3604, 0x064c,
+ 0x4428, 0x1416, 0x203a, 0x3804, 0x084c,
+ 0x4628, 0x1616, 0x223a, 0x3a04, 0x0a4c,
+ 0x462a, 0x1618, 0x223c, 0x3a06, 0x0a4e,
+ 0x442a, 0x1418, 0x203c, 0x3806, 0x084e,
+ 0x422a, 0x1218, 0x1e3c, 0x3606, 0x064e,
+ 0x422c, 0x121a, 0x1e3e, 0x3608, 0x0650,
+ 0x442c, 0x141a, 0x203e, 0x3808, 0x0850,
+ 0x462c, 0x161a, 0x223e, 0x3a08, 0x0a50,
+ 0x462e, 0x161c, 0x2240, 0x3a0a, 0x0a52,
+ 0x442e, 0x141c, 0x2040, 0x380a, 0x0852,
+ 0x422e, 0x121c, 0x1e40, 0x360a, 0x0652,
+ 0x4230, 0x121e, 0x1e42, 0x360c, 0x0654,
+ 0x4430, 0x141e, 0x2042, 0x380c, 0x0854,
+ 0x4630, 0x161e, 0x2242, 0x3a0c, 0x0a54,
+ 0x4632, 0x1620, 0x2244, 0x3a0e, 0x0a56,
+ 0x4432, 0x1420, 0x2044, 0x380e, 0x0856,
+ 0x4232, 0x1220, 0x1e44, 0x360e, 0x0656,
+ 0x4234, 0x1222, 0x1e46, 0x3610, 0x0658,
+ 0x4434, 0x1422, 0x2046, 0x3810, 0x0858,
+ 0x4634, 0x1622, 0x2246, 0x3a10, 0x0a58,
+ 0x0024, 0x1812, 0x2436, 0x3c00, 0x0c48,
+ 0x0224, 0x1a12, 0x2636, 0x3e00, 0x0e48,
+ 0x0424, 0x1c12, 0x2836, 0x4000, 0x1048,
+ 0x0426, 0x1c14, 0x2838, 0x4002, 0x104a,
+ 0x0226, 0x1a14, 0x2638, 0x3e02, 0x0e4a,
+ 0x0026, 0x1814, 0x2438, 0x3c02, 0x0c4a,
+ 0x0028, 0x1816, 0x243a, 0x3c04, 0x0c4c,
+ 0x0228, 0x1a16, 0x263a, 0x3e04, 0x0e4c,
+ 0x0428, 0x1c16, 0x283a, 0x4004, 0x104c,
+ 0x042a, 0x1c18, 0x283c, 0x4006, 0x104e,
+ 0x022a, 0x1a18, 0x263c, 0x3e06, 0x0e4e,
+ 0x002a, 0x1818, 0x243c, 0x3c06, 0x0c4e,
+ 0x002c, 0x181a, 0x243e, 0x3c08, 0x0c50,
+ 0x022c, 0x1a1a, 0x263e, 0x3e08, 0x0e50,
+ 0x042c, 0x1c1a, 0x283e, 0x4008, 0x1050,
+ 0x042e, 0x1c1c, 0x2840, 0x400a, 0x1052,
+ 0x022e, 0x1a1c, 0x2640, 0x3e0a, 0x0e52,
+ 0x002e, 0x181c, 0x2440, 0x3c0a, 0x0c52,
+ 0x0030, 0x181e, 0x2442, 0x3c0c, 0x0c54,
+ 0x0230, 0x1a1e, 0x2642, 0x3e0c, 0x0e54,
+ 0x0430, 0x1c1e, 0x2842, 0x400c, 0x1054,
+ 0x0432, 0x1c20, 0x2844, 0x400e, 0x1056,
+ 0x0232, 0x1a20, 0x2644, 0x3e0e, 0x0e56,
+ 0x0032, 0x1820, 0x2444, 0x3c0e, 0x0c56,
+ 0x0034, 0x1822, 0x2446, 0x3c10, 0x0c58,
+ 0x0234, 0x1a22, 0x2646, 0x3e10, 0x0e58,
+ 0x0434, 0x1c22, 0x2846, 0x4010, 0x1058,
+ 0x0624, 0x1e12, 0x2a36, 0x4200, 0x1248,
+ 0x0824, 0x2012, 0x2c36, 0x4400, 0x1448,
+ 0x0a24, 0x2212, 0x2e36, 0x4600, 0x1648,
+ 0x0a26, 0x2214, 0x2e38, 0x4602, 0x164a,
+ 0x0826, 0x2014, 0x2c38, 0x4402, 0x144a,
+ 0x0626, 0x1e14, 0x2a38, 0x4202, 0x124a,
+ 0x0628, 0x1e16, 0x2a3a, 0x4204, 0x124c,
+ 0x0828, 0x2016, 0x2c3a, 0x4404, 0x144c,
+ 0x0a28, 0x2216, 0x2e3a, 0x4604, 0x164c,
+ 0x0a2a, 0x2218, 0x2e3c, 0x4606, 0x164e,
+ 0x082a, 0x2018, 0x2c3c, 0x4406, 0x144e,
+ 0x062a, 0x1e18, 0x2a3c, 0x4206, 0x124e,
+ 0x062c, 0x1e1a, 0x2a3e, 0x4208, 0x1250,
+ 0x082c, 0x201a, 0x2c3e, 0x4408, 0x1450,
+ 0x0a2c, 0x221a, 0x2e3e, 0x4608, 0x1650,
+ 0x0a2e, 0x221c, 0x2e40, 0x460a, 0x1652,
+ 0x082e, 0x201c, 0x2c40, 0x440a, 0x1452,
+ 0x062e, 0x1e1c, 0x2a40, 0x420a, 0x1252,
+ 0x0630, 0x1e1e, 0x2a42, 0x420c, 0x1254,
+ 0x0830, 0x201e, 0x2c42, 0x440c, 0x1454,
+ 0x0a30, 0x221e, 0x2e42, 0x460c, 0x1654,
+ 0x0a32, 0x2220, 0x2e44, 0x460e, 0x1656,
+ 0x0832, 0x2020, 0x2c44, 0x440e, 0x1456,
+ 0x0632, 0x1e20, 0x2a44, 0x420e, 0x1256,
+ 0x0634, 0x1e22, 0x2a46, 0x4210, 0x1258,
+ 0x0834, 0x2022, 0x2c46, 0x4410, 0x1458,
+ 0x0a34, 0x2222, 0x2e46, 0x4610, 0x1658,
+};
+
+static const uint16_t dv_place_411P[1620] = {
+ 0x0c24, 0x2710, 0x3334, 0x0000, 0x1848,
+ 0x0d24, 0x2810, 0x3434, 0x0100, 0x1948,
+ 0x0e24, 0x2910, 0x3534, 0x0200, 0x1a48,
+ 0x0f24, 0x2914, 0x3538, 0x0300, 0x1b48,
+ 0x1024, 0x2814, 0x3438, 0x0400, 0x1c48,
+ 0x1124, 0x2714, 0x3338, 0x0500, 0x1d48,
+ 0x1128, 0x2614, 0x3238, 0x0504, 0x1d4c,
+ 0x1028, 0x2514, 0x3138, 0x0404, 0x1c4c,
+ 0x0f28, 0x2414, 0x3038, 0x0304, 0x1b4c,
+ 0x0e28, 0x2418, 0x303c, 0x0204, 0x1a4c,
+ 0x0d28, 0x2518, 0x313c, 0x0104, 0x194c,
+ 0x0c28, 0x2618, 0x323c, 0x0004, 0x184c,
+ 0x0c2c, 0x2718, 0x333c, 0x0008, 0x1850,
+ 0x0d2c, 0x2818, 0x343c, 0x0108, 0x1950,
+ 0x0e2c, 0x2918, 0x353c, 0x0208, 0x1a50,
+ 0x0f2c, 0x291c, 0x3540, 0x0308, 0x1b50,
+ 0x102c, 0x281c, 0x3440, 0x0408, 0x1c50,
+ 0x112c, 0x271c, 0x3340, 0x0508, 0x1d50,
+ 0x1130, 0x261c, 0x3240, 0x050c, 0x1d54,
+ 0x1030, 0x251c, 0x3140, 0x040c, 0x1c54,
+ 0x0f30, 0x241c, 0x3040, 0x030c, 0x1b54,
+ 0x0e30, 0x2420, 0x3044, 0x020c, 0x1a54,
+ 0x0d30, 0x2520, 0x3144, 0x010c, 0x1954,
+ 0x0c30, 0x2620, 0x3244, 0x000c, 0x1854,
+ 0x0c34, 0x2720, 0x3344, 0x0010, 0x1858,
+ 0x0d34, 0x2820, 0x3444, 0x0110, 0x1a58,
+ 0x0e34, 0x2920, 0x3544, 0x0210, 0x1c58,
+ 0x1224, 0x2d10, 0x3934, 0x0600, 0x1e48,
+ 0x1324, 0x2e10, 0x3a34, 0x0700, 0x1f48,
+ 0x1424, 0x2f10, 0x3b34, 0x0800, 0x2048,
+ 0x1524, 0x2f14, 0x3b38, 0x0900, 0x2148,
+ 0x1624, 0x2e14, 0x3a38, 0x0a00, 0x2248,
+ 0x1724, 0x2d14, 0x3938, 0x0b00, 0x2348,
+ 0x1728, 0x2c14, 0x3838, 0x0b04, 0x234c,
+ 0x1628, 0x2b14, 0x3738, 0x0a04, 0x224c,
+ 0x1528, 0x2a14, 0x3638, 0x0904, 0x214c,
+ 0x1428, 0x2a18, 0x363c, 0x0804, 0x204c,
+ 0x1328, 0x2b18, 0x373c, 0x0704, 0x1f4c,
+ 0x1228, 0x2c18, 0x383c, 0x0604, 0x1e4c,
+ 0x122c, 0x2d18, 0x393c, 0x0608, 0x1e50,
+ 0x132c, 0x2e18, 0x3a3c, 0x0708, 0x1f50,
+ 0x142c, 0x2f18, 0x3b3c, 0x0808, 0x2050,
+ 0x152c, 0x2f1c, 0x3b40, 0x0908, 0x2150,
+ 0x162c, 0x2e1c, 0x3a40, 0x0a08, 0x2250,
+ 0x172c, 0x2d1c, 0x3940, 0x0b08, 0x2350,
+ 0x1730, 0x2c1c, 0x3840, 0x0b0c, 0x2354,
+ 0x1630, 0x2b1c, 0x3740, 0x0a0c, 0x2254,
+ 0x1530, 0x2a1c, 0x3640, 0x090c, 0x2154,
+ 0x1430, 0x2a20, 0x3644, 0x080c, 0x2054,
+ 0x1330, 0x2b20, 0x3744, 0x070c, 0x1f54,
+ 0x1230, 0x2c20, 0x3844, 0x060c, 0x1e54,
+ 0x1234, 0x2d20, 0x3944, 0x0610, 0x1e58,
+ 0x1334, 0x2e20, 0x3a44, 0x0710, 0x2058,
+ 0x1434, 0x2f20, 0x3b44, 0x0810, 0x2258,
+ 0x1824, 0x3310, 0x3f34, 0x0c00, 0x2448,
+ 0x1924, 0x3410, 0x4034, 0x0d00, 0x2548,
+ 0x1a24, 0x3510, 0x4134, 0x0e00, 0x2648,
+ 0x1b24, 0x3514, 0x4138, 0x0f00, 0x2748,
+ 0x1c24, 0x3414, 0x4038, 0x1000, 0x2848,
+ 0x1d24, 0x3314, 0x3f38, 0x1100, 0x2948,
+ 0x1d28, 0x3214, 0x3e38, 0x1104, 0x294c,
+ 0x1c28, 0x3114, 0x3d38, 0x1004, 0x284c,
+ 0x1b28, 0x3014, 0x3c38, 0x0f04, 0x274c,
+ 0x1a28, 0x3018, 0x3c3c, 0x0e04, 0x264c,
+ 0x1928, 0x3118, 0x3d3c, 0x0d04, 0x254c,
+ 0x1828, 0x3218, 0x3e3c, 0x0c04, 0x244c,
+ 0x182c, 0x3318, 0x3f3c, 0x0c08, 0x2450,
+ 0x192c, 0x3418, 0x403c, 0x0d08, 0x2550,
+ 0x1a2c, 0x3518, 0x413c, 0x0e08, 0x2650,
+ 0x1b2c, 0x351c, 0x4140, 0x0f08, 0x2750,
+ 0x1c2c, 0x341c, 0x4040, 0x1008, 0x2850,
+ 0x1d2c, 0x331c, 0x3f40, 0x1108, 0x2950,
+ 0x1d30, 0x321c, 0x3e40, 0x110c, 0x2954,
+ 0x1c30, 0x311c, 0x3d40, 0x100c, 0x2854,
+ 0x1b30, 0x301c, 0x3c40, 0x0f0c, 0x2754,
+ 0x1a30, 0x3020, 0x3c44, 0x0e0c, 0x2654,
+ 0x1930, 0x3120, 0x3d44, 0x0d0c, 0x2554,
+ 0x1830, 0x3220, 0x3e44, 0x0c0c, 0x2454,
+ 0x1834, 0x3320, 0x3f44, 0x0c10, 0x2458,
+ 0x1934, 0x3420, 0x4044, 0x0d10, 0x2658,
+ 0x1a34, 0x3520, 0x4144, 0x0e10, 0x2858,
+ 0x1e24, 0x3910, 0x4534, 0x1200, 0x2a48,
+ 0x1f24, 0x3a10, 0x4634, 0x1300, 0x2b48,
+ 0x2024, 0x3b10, 0x4734, 0x1400, 0x2c48,
+ 0x2124, 0x3b14, 0x4738, 0x1500, 0x2d48,
+ 0x2224, 0x3a14, 0x4638, 0x1600, 0x2e48,
+ 0x2324, 0x3914, 0x4538, 0x1700, 0x2f48,
+ 0x2328, 0x3814, 0x4438, 0x1704, 0x2f4c,
+ 0x2228, 0x3714, 0x4338, 0x1604, 0x2e4c,
+ 0x2128, 0x3614, 0x4238, 0x1504, 0x2d4c,
+ 0x2028, 0x3618, 0x423c, 0x1404, 0x2c4c,
+ 0x1f28, 0x3718, 0x433c, 0x1304, 0x2b4c,
+ 0x1e28, 0x3818, 0x443c, 0x1204, 0x2a4c,
+ 0x1e2c, 0x3918, 0x453c, 0x1208, 0x2a50,
+ 0x1f2c, 0x3a18, 0x463c, 0x1308, 0x2b50,
+ 0x202c, 0x3b18, 0x473c, 0x1408, 0x2c50,
+ 0x212c, 0x3b1c, 0x4740, 0x1508, 0x2d50,
+ 0x222c, 0x3a1c, 0x4640, 0x1608, 0x2e50,
+ 0x232c, 0x391c, 0x4540, 0x1708, 0x2f50,
+ 0x2330, 0x381c, 0x4440, 0x170c, 0x2f54,
+ 0x2230, 0x371c, 0x4340, 0x160c, 0x2e54,
+ 0x2130, 0x361c, 0x4240, 0x150c, 0x2d54,
+ 0x2030, 0x3620, 0x4244, 0x140c, 0x2c54,
+ 0x1f30, 0x3720, 0x4344, 0x130c, 0x2b54,
+ 0x1e30, 0x3820, 0x4444, 0x120c, 0x2a54,
+ 0x1e34, 0x3920, 0x4544, 0x1210, 0x2a58,
+ 0x1f34, 0x3a20, 0x4644, 0x1310, 0x2c58,
+ 0x2034, 0x3b20, 0x4744, 0x1410, 0x2e58,
+ 0x2424, 0x3f10, 0x0334, 0x1800, 0x3048,
+ 0x2524, 0x4010, 0x0434, 0x1900, 0x3148,
+ 0x2624, 0x4110, 0x0534, 0x1a00, 0x3248,
+ 0x2724, 0x4114, 0x0538, 0x1b00, 0x3348,
+ 0x2824, 0x4014, 0x0438, 0x1c00, 0x3448,
+ 0x2924, 0x3f14, 0x0338, 0x1d00, 0x3548,
+ 0x2928, 0x3e14, 0x0238, 0x1d04, 0x354c,
+ 0x2828, 0x3d14, 0x0138, 0x1c04, 0x344c,
+ 0x2728, 0x3c14, 0x0038, 0x1b04, 0x334c,
+ 0x2628, 0x3c18, 0x003c, 0x1a04, 0x324c,
+ 0x2528, 0x3d18, 0x013c, 0x1904, 0x314c,
+ 0x2428, 0x3e18, 0x023c, 0x1804, 0x304c,
+ 0x242c, 0x3f18, 0x033c, 0x1808, 0x3050,
+ 0x252c, 0x4018, 0x043c, 0x1908, 0x3150,
+ 0x262c, 0x4118, 0x053c, 0x1a08, 0x3250,
+ 0x272c, 0x411c, 0x0540, 0x1b08, 0x3350,
+ 0x282c, 0x401c, 0x0440, 0x1c08, 0x3450,
+ 0x292c, 0x3f1c, 0x0340, 0x1d08, 0x3550,
+ 0x2930, 0x3e1c, 0x0240, 0x1d0c, 0x3554,
+ 0x2830, 0x3d1c, 0x0140, 0x1c0c, 0x3454,
+ 0x2730, 0x3c1c, 0x0040, 0x1b0c, 0x3354,
+ 0x2630, 0x3c20, 0x0044, 0x1a0c, 0x3254,
+ 0x2530, 0x3d20, 0x0144, 0x190c, 0x3154,
+ 0x2430, 0x3e20, 0x0244, 0x180c, 0x3054,
+ 0x2434, 0x3f20, 0x0344, 0x1810, 0x3058,
+ 0x2534, 0x4020, 0x0444, 0x1910, 0x3258,
+ 0x2634, 0x4120, 0x0544, 0x1a10, 0x3458,
+ 0x2a24, 0x4510, 0x0934, 0x1e00, 0x3648,
+ 0x2b24, 0x4610, 0x0a34, 0x1f00, 0x3748,
+ 0x2c24, 0x4710, 0x0b34, 0x2000, 0x3848,
+ 0x2d24, 0x4714, 0x0b38, 0x2100, 0x3948,
+ 0x2e24, 0x4614, 0x0a38, 0x2200, 0x3a48,
+ 0x2f24, 0x4514, 0x0938, 0x2300, 0x3b48,
+ 0x2f28, 0x4414, 0x0838, 0x2304, 0x3b4c,
+ 0x2e28, 0x4314, 0x0738, 0x2204, 0x3a4c,
+ 0x2d28, 0x4214, 0x0638, 0x2104, 0x394c,
+ 0x2c28, 0x4218, 0x063c, 0x2004, 0x384c,
+ 0x2b28, 0x4318, 0x073c, 0x1f04, 0x374c,
+ 0x2a28, 0x4418, 0x083c, 0x1e04, 0x364c,
+ 0x2a2c, 0x4518, 0x093c, 0x1e08, 0x3650,
+ 0x2b2c, 0x4618, 0x0a3c, 0x1f08, 0x3750,
+ 0x2c2c, 0x4718, 0x0b3c, 0x2008, 0x3850,
+ 0x2d2c, 0x471c, 0x0b40, 0x2108, 0x3950,
+ 0x2e2c, 0x461c, 0x0a40, 0x2208, 0x3a50,
+ 0x2f2c, 0x451c, 0x0940, 0x2308, 0x3b50,
+ 0x2f30, 0x441c, 0x0840, 0x230c, 0x3b54,
+ 0x2e30, 0x431c, 0x0740, 0x220c, 0x3a54,
+ 0x2d30, 0x421c, 0x0640, 0x210c, 0x3954,
+ 0x2c30, 0x4220, 0x0644, 0x200c, 0x3854,
+ 0x2b30, 0x4320, 0x0744, 0x1f0c, 0x3754,
+ 0x2a30, 0x4420, 0x0844, 0x1e0c, 0x3654,
+ 0x2a34, 0x4520, 0x0944, 0x1e10, 0x3658,
+ 0x2b34, 0x4620, 0x0a44, 0x1f10, 0x3858,
+ 0x2c34, 0x4720, 0x0b44, 0x2010, 0x3a58,
+ 0x3024, 0x0310, 0x0f34, 0x2400, 0x3c48,
+ 0x3124, 0x0410, 0x1034, 0x2500, 0x3d48,
+ 0x3224, 0x0510, 0x1134, 0x2600, 0x3e48,
+ 0x3324, 0x0514, 0x1138, 0x2700, 0x3f48,
+ 0x3424, 0x0414, 0x1038, 0x2800, 0x4048,
+ 0x3524, 0x0314, 0x0f38, 0x2900, 0x4148,
+ 0x3528, 0x0214, 0x0e38, 0x2904, 0x414c,
+ 0x3428, 0x0114, 0x0d38, 0x2804, 0x404c,
+ 0x3328, 0x0014, 0x0c38, 0x2704, 0x3f4c,
+ 0x3228, 0x0018, 0x0c3c, 0x2604, 0x3e4c,
+ 0x3128, 0x0118, 0x0d3c, 0x2504, 0x3d4c,
+ 0x3028, 0x0218, 0x0e3c, 0x2404, 0x3c4c,
+ 0x302c, 0x0318, 0x0f3c, 0x2408, 0x3c50,
+ 0x312c, 0x0418, 0x103c, 0x2508, 0x3d50,
+ 0x322c, 0x0518, 0x113c, 0x2608, 0x3e50,
+ 0x332c, 0x051c, 0x1140, 0x2708, 0x3f50,
+ 0x342c, 0x041c, 0x1040, 0x2808, 0x4050,
+ 0x352c, 0x031c, 0x0f40, 0x2908, 0x4150,
+ 0x3530, 0x021c, 0x0e40, 0x290c, 0x4154,
+ 0x3430, 0x011c, 0x0d40, 0x280c, 0x4054,
+ 0x3330, 0x001c, 0x0c40, 0x270c, 0x3f54,
+ 0x3230, 0x0020, 0x0c44, 0x260c, 0x3e54,
+ 0x3130, 0x0120, 0x0d44, 0x250c, 0x3d54,
+ 0x3030, 0x0220, 0x0e44, 0x240c, 0x3c54,
+ 0x3034, 0x0320, 0x0f44, 0x2410, 0x3c58,
+ 0x3134, 0x0420, 0x1044, 0x2510, 0x3e58,
+ 0x3234, 0x0520, 0x1144, 0x2610, 0x4058,
+ 0x3624, 0x0910, 0x1534, 0x2a00, 0x4248,
+ 0x3724, 0x0a10, 0x1634, 0x2b00, 0x4348,
+ 0x3824, 0x0b10, 0x1734, 0x2c00, 0x4448,
+ 0x3924, 0x0b14, 0x1738, 0x2d00, 0x4548,
+ 0x3a24, 0x0a14, 0x1638, 0x2e00, 0x4648,
+ 0x3b24, 0x0914, 0x1538, 0x2f00, 0x4748,
+ 0x3b28, 0x0814, 0x1438, 0x2f04, 0x474c,
+ 0x3a28, 0x0714, 0x1338, 0x2e04, 0x464c,
+ 0x3928, 0x0614, 0x1238, 0x2d04, 0x454c,
+ 0x3828, 0x0618, 0x123c, 0x2c04, 0x444c,
+ 0x3728, 0x0718, 0x133c, 0x2b04, 0x434c,
+ 0x3628, 0x0818, 0x143c, 0x2a04, 0x424c,
+ 0x362c, 0x0918, 0x153c, 0x2a08, 0x4250,
+ 0x372c, 0x0a18, 0x163c, 0x2b08, 0x4350,
+ 0x382c, 0x0b18, 0x173c, 0x2c08, 0x4450,
+ 0x392c, 0x0b1c, 0x1740, 0x2d08, 0x4550,
+ 0x3a2c, 0x0a1c, 0x1640, 0x2e08, 0x4650,
+ 0x3b2c, 0x091c, 0x1540, 0x2f08, 0x4750,
+ 0x3b30, 0x081c, 0x1440, 0x2f0c, 0x4754,
+ 0x3a30, 0x071c, 0x1340, 0x2e0c, 0x4654,
+ 0x3930, 0x061c, 0x1240, 0x2d0c, 0x4554,
+ 0x3830, 0x0620, 0x1244, 0x2c0c, 0x4454,
+ 0x3730, 0x0720, 0x1344, 0x2b0c, 0x4354,
+ 0x3630, 0x0820, 0x1444, 0x2a0c, 0x4254,
+ 0x3634, 0x0920, 0x1544, 0x2a10, 0x4258,
+ 0x3734, 0x0a20, 0x1644, 0x2b10, 0x4458,
+ 0x3834, 0x0b20, 0x1744, 0x2c10, 0x4658,
+ 0x3c24, 0x0f10, 0x1b34, 0x3000, 0x0048,
+ 0x3d24, 0x1010, 0x1c34, 0x3100, 0x0148,
+ 0x3e24, 0x1110, 0x1d34, 0x3200, 0x0248,
+ 0x3f24, 0x1114, 0x1d38, 0x3300, 0x0348,
+ 0x4024, 0x1014, 0x1c38, 0x3400, 0x0448,
+ 0x4124, 0x0f14, 0x1b38, 0x3500, 0x0548,
+ 0x4128, 0x0e14, 0x1a38, 0x3504, 0x054c,
+ 0x4028, 0x0d14, 0x1938, 0x3404, 0x044c,
+ 0x3f28, 0x0c14, 0x1838, 0x3304, 0x034c,
+ 0x3e28, 0x0c18, 0x183c, 0x3204, 0x024c,
+ 0x3d28, 0x0d18, 0x193c, 0x3104, 0x014c,
+ 0x3c28, 0x0e18, 0x1a3c, 0x3004, 0x004c,
+ 0x3c2c, 0x0f18, 0x1b3c, 0x3008, 0x0050,
+ 0x3d2c, 0x1018, 0x1c3c, 0x3108, 0x0150,
+ 0x3e2c, 0x1118, 0x1d3c, 0x3208, 0x0250,
+ 0x3f2c, 0x111c, 0x1d40, 0x3308, 0x0350,
+ 0x402c, 0x101c, 0x1c40, 0x3408, 0x0450,
+ 0x412c, 0x0f1c, 0x1b40, 0x3508, 0x0550,
+ 0x4130, 0x0e1c, 0x1a40, 0x350c, 0x0554,
+ 0x4030, 0x0d1c, 0x1940, 0x340c, 0x0454,
+ 0x3f30, 0x0c1c, 0x1840, 0x330c, 0x0354,
+ 0x3e30, 0x0c20, 0x1844, 0x320c, 0x0254,
+ 0x3d30, 0x0d20, 0x1944, 0x310c, 0x0154,
+ 0x3c30, 0x0e20, 0x1a44, 0x300c, 0x0054,
+ 0x3c34, 0x0f20, 0x1b44, 0x3010, 0x0058,
+ 0x3d34, 0x1020, 0x1c44, 0x3110, 0x0258,
+ 0x3e34, 0x1120, 0x1d44, 0x3210, 0x0458,
+ 0x4224, 0x1510, 0x2134, 0x3600, 0x0648,
+ 0x4324, 0x1610, 0x2234, 0x3700, 0x0748,
+ 0x4424, 0x1710, 0x2334, 0x3800, 0x0848,
+ 0x4524, 0x1714, 0x2338, 0x3900, 0x0948,
+ 0x4624, 0x1614, 0x2238, 0x3a00, 0x0a48,
+ 0x4724, 0x1514, 0x2138, 0x3b00, 0x0b48,
+ 0x4728, 0x1414, 0x2038, 0x3b04, 0x0b4c,
+ 0x4628, 0x1314, 0x1f38, 0x3a04, 0x0a4c,
+ 0x4528, 0x1214, 0x1e38, 0x3904, 0x094c,
+ 0x4428, 0x1218, 0x1e3c, 0x3804, 0x084c,
+ 0x4328, 0x1318, 0x1f3c, 0x3704, 0x074c,
+ 0x4228, 0x1418, 0x203c, 0x3604, 0x064c,
+ 0x422c, 0x1518, 0x213c, 0x3608, 0x0650,
+ 0x432c, 0x1618, 0x223c, 0x3708, 0x0750,
+ 0x442c, 0x1718, 0x233c, 0x3808, 0x0850,
+ 0x452c, 0x171c, 0x2340, 0x3908, 0x0950,
+ 0x462c, 0x161c, 0x2240, 0x3a08, 0x0a50,
+ 0x472c, 0x151c, 0x2140, 0x3b08, 0x0b50,
+ 0x4730, 0x141c, 0x2040, 0x3b0c, 0x0b54,
+ 0x4630, 0x131c, 0x1f40, 0x3a0c, 0x0a54,
+ 0x4530, 0x121c, 0x1e40, 0x390c, 0x0954,
+ 0x4430, 0x1220, 0x1e44, 0x380c, 0x0854,
+ 0x4330, 0x1320, 0x1f44, 0x370c, 0x0754,
+ 0x4230, 0x1420, 0x2044, 0x360c, 0x0654,
+ 0x4234, 0x1520, 0x2144, 0x3610, 0x0658,
+ 0x4334, 0x1620, 0x2244, 0x3710, 0x0858,
+ 0x4434, 0x1720, 0x2344, 0x3810, 0x0a58,
+ 0x0024, 0x1b10, 0x2734, 0x3c00, 0x0c48,
+ 0x0124, 0x1c10, 0x2834, 0x3d00, 0x0d48,
+ 0x0224, 0x1d10, 0x2934, 0x3e00, 0x0e48,
+ 0x0324, 0x1d14, 0x2938, 0x3f00, 0x0f48,
+ 0x0424, 0x1c14, 0x2838, 0x4000, 0x1048,
+ 0x0524, 0x1b14, 0x2738, 0x4100, 0x1148,
+ 0x0528, 0x1a14, 0x2638, 0x4104, 0x114c,
+ 0x0428, 0x1914, 0x2538, 0x4004, 0x104c,
+ 0x0328, 0x1814, 0x2438, 0x3f04, 0x0f4c,
+ 0x0228, 0x1818, 0x243c, 0x3e04, 0x0e4c,
+ 0x0128, 0x1918, 0x253c, 0x3d04, 0x0d4c,
+ 0x0028, 0x1a18, 0x263c, 0x3c04, 0x0c4c,
+ 0x002c, 0x1b18, 0x273c, 0x3c08, 0x0c50,
+ 0x012c, 0x1c18, 0x283c, 0x3d08, 0x0d50,
+ 0x022c, 0x1d18, 0x293c, 0x3e08, 0x0e50,
+ 0x032c, 0x1d1c, 0x2940, 0x3f08, 0x0f50,
+ 0x042c, 0x1c1c, 0x2840, 0x4008, 0x1050,
+ 0x052c, 0x1b1c, 0x2740, 0x4108, 0x1150,
+ 0x0530, 0x1a1c, 0x2640, 0x410c, 0x1154,
+ 0x0430, 0x191c, 0x2540, 0x400c, 0x1054,
+ 0x0330, 0x181c, 0x2440, 0x3f0c, 0x0f54,
+ 0x0230, 0x1820, 0x2444, 0x3e0c, 0x0e54,
+ 0x0130, 0x1920, 0x2544, 0x3d0c, 0x0d54,
+ 0x0030, 0x1a20, 0x2644, 0x3c0c, 0x0c54,
+ 0x0034, 0x1b20, 0x2744, 0x3c10, 0x0c58,
+ 0x0134, 0x1c20, 0x2844, 0x3d10, 0x0e58,
+ 0x0234, 0x1d20, 0x2944, 0x3e10, 0x1058,
+ 0x0624, 0x2110, 0x2d34, 0x4200, 0x1248,
+ 0x0724, 0x2210, 0x2e34, 0x4300, 0x1348,
+ 0x0824, 0x2310, 0x2f34, 0x4400, 0x1448,
+ 0x0924, 0x2314, 0x2f38, 0x4500, 0x1548,
+ 0x0a24, 0x2214, 0x2e38, 0x4600, 0x1648,
+ 0x0b24, 0x2114, 0x2d38, 0x4700, 0x1748,
+ 0x0b28, 0x2014, 0x2c38, 0x4704, 0x174c,
+ 0x0a28, 0x1f14, 0x2b38, 0x4604, 0x164c,
+ 0x0928, 0x1e14, 0x2a38, 0x4504, 0x154c,
+ 0x0828, 0x1e18, 0x2a3c, 0x4404, 0x144c,
+ 0x0728, 0x1f18, 0x2b3c, 0x4304, 0x134c,
+ 0x0628, 0x2018, 0x2c3c, 0x4204, 0x124c,
+ 0x062c, 0x2118, 0x2d3c, 0x4208, 0x1250,
+ 0x072c, 0x2218, 0x2e3c, 0x4308, 0x1350,
+ 0x082c, 0x2318, 0x2f3c, 0x4408, 0x1450,
+ 0x092c, 0x231c, 0x2f40, 0x4508, 0x1550,
+ 0x0a2c, 0x221c, 0x2e40, 0x4608, 0x1650,
+ 0x0b2c, 0x211c, 0x2d40, 0x4708, 0x1750,
+ 0x0b30, 0x201c, 0x2c40, 0x470c, 0x1754,
+ 0x0a30, 0x1f1c, 0x2b40, 0x460c, 0x1654,
+ 0x0930, 0x1e1c, 0x2a40, 0x450c, 0x1554,
+ 0x0830, 0x1e20, 0x2a44, 0x440c, 0x1454,
+ 0x0730, 0x1f20, 0x2b44, 0x430c, 0x1354,
+ 0x0630, 0x2020, 0x2c44, 0x420c, 0x1254,
+ 0x0634, 0x2120, 0x2d44, 0x4210, 0x1258,
+ 0x0734, 0x2220, 0x2e44, 0x4310, 0x1458,
+ 0x0834, 0x2320, 0x2f44, 0x4410, 0x1658,
+};
+
+static const uint16_t dv_place_411[1350] = {
+ 0x0c24, 0x2710, 0x3334, 0x0000, 0x1848,
+ 0x0d24, 0x2810, 0x3434, 0x0100, 0x1948,
+ 0x0e24, 0x2910, 0x3534, 0x0200, 0x1a48,
+ 0x0f24, 0x2914, 0x3538, 0x0300, 0x1b48,
+ 0x1024, 0x2814, 0x3438, 0x0400, 0x1c48,
+ 0x1124, 0x2714, 0x3338, 0x0500, 0x1d48,
+ 0x1128, 0x2614, 0x3238, 0x0504, 0x1d4c,
+ 0x1028, 0x2514, 0x3138, 0x0404, 0x1c4c,
+ 0x0f28, 0x2414, 0x3038, 0x0304, 0x1b4c,
+ 0x0e28, 0x2418, 0x303c, 0x0204, 0x1a4c,
+ 0x0d28, 0x2518, 0x313c, 0x0104, 0x194c,
+ 0x0c28, 0x2618, 0x323c, 0x0004, 0x184c,
+ 0x0c2c, 0x2718, 0x333c, 0x0008, 0x1850,
+ 0x0d2c, 0x2818, 0x343c, 0x0108, 0x1950,
+ 0x0e2c, 0x2918, 0x353c, 0x0208, 0x1a50,
+ 0x0f2c, 0x291c, 0x3540, 0x0308, 0x1b50,
+ 0x102c, 0x281c, 0x3440, 0x0408, 0x1c50,
+ 0x112c, 0x271c, 0x3340, 0x0508, 0x1d50,
+ 0x1130, 0x261c, 0x3240, 0x050c, 0x1d54,
+ 0x1030, 0x251c, 0x3140, 0x040c, 0x1c54,
+ 0x0f30, 0x241c, 0x3040, 0x030c, 0x1b54,
+ 0x0e30, 0x2420, 0x3044, 0x020c, 0x1a54,
+ 0x0d30, 0x2520, 0x3144, 0x010c, 0x1954,
+ 0x0c30, 0x2620, 0x3244, 0x000c, 0x1854,
+ 0x0c34, 0x2720, 0x3344, 0x0010, 0x1858,
+ 0x0d34, 0x2820, 0x3444, 0x0110, 0x1a58,
+ 0x0e34, 0x2920, 0x3544, 0x0210, 0x1c58,
+ 0x1224, 0x2d10, 0x3934, 0x0600, 0x1e48,
+ 0x1324, 0x2e10, 0x3a34, 0x0700, 0x1f48,
+ 0x1424, 0x2f10, 0x3b34, 0x0800, 0x2048,
+ 0x1524, 0x2f14, 0x3b38, 0x0900, 0x2148,
+ 0x1624, 0x2e14, 0x3a38, 0x0a00, 0x2248,
+ 0x1724, 0x2d14, 0x3938, 0x0b00, 0x2348,
+ 0x1728, 0x2c14, 0x3838, 0x0b04, 0x234c,
+ 0x1628, 0x2b14, 0x3738, 0x0a04, 0x224c,
+ 0x1528, 0x2a14, 0x3638, 0x0904, 0x214c,
+ 0x1428, 0x2a18, 0x363c, 0x0804, 0x204c,
+ 0x1328, 0x2b18, 0x373c, 0x0704, 0x1f4c,
+ 0x1228, 0x2c18, 0x383c, 0x0604, 0x1e4c,
+ 0x122c, 0x2d18, 0x393c, 0x0608, 0x1e50,
+ 0x132c, 0x2e18, 0x3a3c, 0x0708, 0x1f50,
+ 0x142c, 0x2f18, 0x3b3c, 0x0808, 0x2050,
+ 0x152c, 0x2f1c, 0x3b40, 0x0908, 0x2150,
+ 0x162c, 0x2e1c, 0x3a40, 0x0a08, 0x2250,
+ 0x172c, 0x2d1c, 0x3940, 0x0b08, 0x2350,
+ 0x1730, 0x2c1c, 0x3840, 0x0b0c, 0x2354,
+ 0x1630, 0x2b1c, 0x3740, 0x0a0c, 0x2254,
+ 0x1530, 0x2a1c, 0x3640, 0x090c, 0x2154,
+ 0x1430, 0x2a20, 0x3644, 0x080c, 0x2054,
+ 0x1330, 0x2b20, 0x3744, 0x070c, 0x1f54,
+ 0x1230, 0x2c20, 0x3844, 0x060c, 0x1e54,
+ 0x1234, 0x2d20, 0x3944, 0x0610, 0x1e58,
+ 0x1334, 0x2e20, 0x3a44, 0x0710, 0x2058,
+ 0x1434, 0x2f20, 0x3b44, 0x0810, 0x2258,
+ 0x1824, 0x3310, 0x0334, 0x0c00, 0x2448,
+ 0x1924, 0x3410, 0x0434, 0x0d00, 0x2548,
+ 0x1a24, 0x3510, 0x0534, 0x0e00, 0x2648,
+ 0x1b24, 0x3514, 0x0538, 0x0f00, 0x2748,
+ 0x1c24, 0x3414, 0x0438, 0x1000, 0x2848,
+ 0x1d24, 0x3314, 0x0338, 0x1100, 0x2948,
+ 0x1d28, 0x3214, 0x0238, 0x1104, 0x294c,
+ 0x1c28, 0x3114, 0x0138, 0x1004, 0x284c,
+ 0x1b28, 0x3014, 0x0038, 0x0f04, 0x274c,
+ 0x1a28, 0x3018, 0x003c, 0x0e04, 0x264c,
+ 0x1928, 0x3118, 0x013c, 0x0d04, 0x254c,
+ 0x1828, 0x3218, 0x023c, 0x0c04, 0x244c,
+ 0x182c, 0x3318, 0x033c, 0x0c08, 0x2450,
+ 0x192c, 0x3418, 0x043c, 0x0d08, 0x2550,
+ 0x1a2c, 0x3518, 0x053c, 0x0e08, 0x2650,
+ 0x1b2c, 0x351c, 0x0540, 0x0f08, 0x2750,
+ 0x1c2c, 0x341c, 0x0440, 0x1008, 0x2850,
+ 0x1d2c, 0x331c, 0x0340, 0x1108, 0x2950,
+ 0x1d30, 0x321c, 0x0240, 0x110c, 0x2954,
+ 0x1c30, 0x311c, 0x0140, 0x100c, 0x2854,
+ 0x1b30, 0x301c, 0x0040, 0x0f0c, 0x2754,
+ 0x1a30, 0x3020, 0x0044, 0x0e0c, 0x2654,
+ 0x1930, 0x3120, 0x0144, 0x0d0c, 0x2554,
+ 0x1830, 0x3220, 0x0244, 0x0c0c, 0x2454,
+ 0x1834, 0x3320, 0x0344, 0x0c10, 0x2458,
+ 0x1934, 0x3420, 0x0444, 0x0d10, 0x2658,
+ 0x1a34, 0x3520, 0x0544, 0x0e10, 0x2858,
+ 0x1e24, 0x3910, 0x0934, 0x1200, 0x2a48,
+ 0x1f24, 0x3a10, 0x0a34, 0x1300, 0x2b48,
+ 0x2024, 0x3b10, 0x0b34, 0x1400, 0x2c48,
+ 0x2124, 0x3b14, 0x0b38, 0x1500, 0x2d48,
+ 0x2224, 0x3a14, 0x0a38, 0x1600, 0x2e48,
+ 0x2324, 0x3914, 0x0938, 0x1700, 0x2f48,
+ 0x2328, 0x3814, 0x0838, 0x1704, 0x2f4c,
+ 0x2228, 0x3714, 0x0738, 0x1604, 0x2e4c,
+ 0x2128, 0x3614, 0x0638, 0x1504, 0x2d4c,
+ 0x2028, 0x3618, 0x063c, 0x1404, 0x2c4c,
+ 0x1f28, 0x3718, 0x073c, 0x1304, 0x2b4c,
+ 0x1e28, 0x3818, 0x083c, 0x1204, 0x2a4c,
+ 0x1e2c, 0x3918, 0x093c, 0x1208, 0x2a50,
+ 0x1f2c, 0x3a18, 0x0a3c, 0x1308, 0x2b50,
+ 0x202c, 0x3b18, 0x0b3c, 0x1408, 0x2c50,
+ 0x212c, 0x3b1c, 0x0b40, 0x1508, 0x2d50,
+ 0x222c, 0x3a1c, 0x0a40, 0x1608, 0x2e50,
+ 0x232c, 0x391c, 0x0940, 0x1708, 0x2f50,
+ 0x2330, 0x381c, 0x0840, 0x170c, 0x2f54,
+ 0x2230, 0x371c, 0x0740, 0x160c, 0x2e54,
+ 0x2130, 0x361c, 0x0640, 0x150c, 0x2d54,
+ 0x2030, 0x3620, 0x0644, 0x140c, 0x2c54,
+ 0x1f30, 0x3720, 0x0744, 0x130c, 0x2b54,
+ 0x1e30, 0x3820, 0x0844, 0x120c, 0x2a54,
+ 0x1e34, 0x3920, 0x0944, 0x1210, 0x2a58,
+ 0x1f34, 0x3a20, 0x0a44, 0x1310, 0x2c58,
+ 0x2034, 0x3b20, 0x0b44, 0x1410, 0x2e58,
+ 0x2424, 0x0310, 0x0f34, 0x1800, 0x3048,
+ 0x2524, 0x0410, 0x1034, 0x1900, 0x3148,
+ 0x2624, 0x0510, 0x1134, 0x1a00, 0x3248,
+ 0x2724, 0x0514, 0x1138, 0x1b00, 0x3348,
+ 0x2824, 0x0414, 0x1038, 0x1c00, 0x3448,
+ 0x2924, 0x0314, 0x0f38, 0x1d00, 0x3548,
+ 0x2928, 0x0214, 0x0e38, 0x1d04, 0x354c,
+ 0x2828, 0x0114, 0x0d38, 0x1c04, 0x344c,
+ 0x2728, 0x0014, 0x0c38, 0x1b04, 0x334c,
+ 0x2628, 0x0018, 0x0c3c, 0x1a04, 0x324c,
+ 0x2528, 0x0118, 0x0d3c, 0x1904, 0x314c,
+ 0x2428, 0x0218, 0x0e3c, 0x1804, 0x304c,
+ 0x242c, 0x0318, 0x0f3c, 0x1808, 0x3050,
+ 0x252c, 0x0418, 0x103c, 0x1908, 0x3150,
+ 0x262c, 0x0518, 0x113c, 0x1a08, 0x3250,
+ 0x272c, 0x051c, 0x1140, 0x1b08, 0x3350,
+ 0x282c, 0x041c, 0x1040, 0x1c08, 0x3450,
+ 0x292c, 0x031c, 0x0f40, 0x1d08, 0x3550,
+ 0x2930, 0x021c, 0x0e40, 0x1d0c, 0x3554,
+ 0x2830, 0x011c, 0x0d40, 0x1c0c, 0x3454,
+ 0x2730, 0x001c, 0x0c40, 0x1b0c, 0x3354,
+ 0x2630, 0x0020, 0x0c44, 0x1a0c, 0x3254,
+ 0x2530, 0x0120, 0x0d44, 0x190c, 0x3154,
+ 0x2430, 0x0220, 0x0e44, 0x180c, 0x3054,
+ 0x2434, 0x0320, 0x0f44, 0x1810, 0x3058,
+ 0x2534, 0x0420, 0x1044, 0x1910, 0x3258,
+ 0x2634, 0x0520, 0x1144, 0x1a10, 0x3458,
+ 0x2a24, 0x0910, 0x1534, 0x1e00, 0x3648,
+ 0x2b24, 0x0a10, 0x1634, 0x1f00, 0x3748,
+ 0x2c24, 0x0b10, 0x1734, 0x2000, 0x3848,
+ 0x2d24, 0x0b14, 0x1738, 0x2100, 0x3948,
+ 0x2e24, 0x0a14, 0x1638, 0x2200, 0x3a48,
+ 0x2f24, 0x0914, 0x1538, 0x2300, 0x3b48,
+ 0x2f28, 0x0814, 0x1438, 0x2304, 0x3b4c,
+ 0x2e28, 0x0714, 0x1338, 0x2204, 0x3a4c,
+ 0x2d28, 0x0614, 0x1238, 0x2104, 0x394c,
+ 0x2c28, 0x0618, 0x123c, 0x2004, 0x384c,
+ 0x2b28, 0x0718, 0x133c, 0x1f04, 0x374c,
+ 0x2a28, 0x0818, 0x143c, 0x1e04, 0x364c,
+ 0x2a2c, 0x0918, 0x153c, 0x1e08, 0x3650,
+ 0x2b2c, 0x0a18, 0x163c, 0x1f08, 0x3750,
+ 0x2c2c, 0x0b18, 0x173c, 0x2008, 0x3850,
+ 0x2d2c, 0x0b1c, 0x1740, 0x2108, 0x3950,
+ 0x2e2c, 0x0a1c, 0x1640, 0x2208, 0x3a50,
+ 0x2f2c, 0x091c, 0x1540, 0x2308, 0x3b50,
+ 0x2f30, 0x081c, 0x1440, 0x230c, 0x3b54,
+ 0x2e30, 0x071c, 0x1340, 0x220c, 0x3a54,
+ 0x2d30, 0x061c, 0x1240, 0x210c, 0x3954,
+ 0x2c30, 0x0620, 0x1244, 0x200c, 0x3854,
+ 0x2b30, 0x0720, 0x1344, 0x1f0c, 0x3754,
+ 0x2a30, 0x0820, 0x1444, 0x1e0c, 0x3654,
+ 0x2a34, 0x0920, 0x1544, 0x1e10, 0x3658,
+ 0x2b34, 0x0a20, 0x1644, 0x1f10, 0x3858,
+ 0x2c34, 0x0b20, 0x1744, 0x2010, 0x3a58,
+ 0x3024, 0x0f10, 0x1b34, 0x2400, 0x0048,
+ 0x3124, 0x1010, 0x1c34, 0x2500, 0x0148,
+ 0x3224, 0x1110, 0x1d34, 0x2600, 0x0248,
+ 0x3324, 0x1114, 0x1d38, 0x2700, 0x0348,
+ 0x3424, 0x1014, 0x1c38, 0x2800, 0x0448,
+ 0x3524, 0x0f14, 0x1b38, 0x2900, 0x0548,
+ 0x3528, 0x0e14, 0x1a38, 0x2904, 0x054c,
+ 0x3428, 0x0d14, 0x1938, 0x2804, 0x044c,
+ 0x3328, 0x0c14, 0x1838, 0x2704, 0x034c,
+ 0x3228, 0x0c18, 0x183c, 0x2604, 0x024c,
+ 0x3128, 0x0d18, 0x193c, 0x2504, 0x014c,
+ 0x3028, 0x0e18, 0x1a3c, 0x2404, 0x004c,
+ 0x302c, 0x0f18, 0x1b3c, 0x2408, 0x0050,
+ 0x312c, 0x1018, 0x1c3c, 0x2508, 0x0150,
+ 0x322c, 0x1118, 0x1d3c, 0x2608, 0x0250,
+ 0x332c, 0x111c, 0x1d40, 0x2708, 0x0350,
+ 0x342c, 0x101c, 0x1c40, 0x2808, 0x0450,
+ 0x352c, 0x0f1c, 0x1b40, 0x2908, 0x0550,
+ 0x3530, 0x0e1c, 0x1a40, 0x290c, 0x0554,
+ 0x3430, 0x0d1c, 0x1940, 0x280c, 0x0454,
+ 0x3330, 0x0c1c, 0x1840, 0x270c, 0x0354,
+ 0x3230, 0x0c20, 0x1844, 0x260c, 0x0254,
+ 0x3130, 0x0d20, 0x1944, 0x250c, 0x0154,
+ 0x3030, 0x0e20, 0x1a44, 0x240c, 0x0054,
+ 0x3034, 0x0f20, 0x1b44, 0x2410, 0x0058,
+ 0x3134, 0x1020, 0x1c44, 0x2510, 0x0258,
+ 0x3234, 0x1120, 0x1d44, 0x2610, 0x0458,
+ 0x3624, 0x1510, 0x2134, 0x2a00, 0x0648,
+ 0x3724, 0x1610, 0x2234, 0x2b00, 0x0748,
+ 0x3824, 0x1710, 0x2334, 0x2c00, 0x0848,
+ 0x3924, 0x1714, 0x2338, 0x2d00, 0x0948,
+ 0x3a24, 0x1614, 0x2238, 0x2e00, 0x0a48,
+ 0x3b24, 0x1514, 0x2138, 0x2f00, 0x0b48,
+ 0x3b28, 0x1414, 0x2038, 0x2f04, 0x0b4c,
+ 0x3a28, 0x1314, 0x1f38, 0x2e04, 0x0a4c,
+ 0x3928, 0x1214, 0x1e38, 0x2d04, 0x094c,
+ 0x3828, 0x1218, 0x1e3c, 0x2c04, 0x084c,
+ 0x3728, 0x1318, 0x1f3c, 0x2b04, 0x074c,
+ 0x3628, 0x1418, 0x203c, 0x2a04, 0x064c,
+ 0x362c, 0x1518, 0x213c, 0x2a08, 0x0650,
+ 0x372c, 0x1618, 0x223c, 0x2b08, 0x0750,
+ 0x382c, 0x1718, 0x233c, 0x2c08, 0x0850,
+ 0x392c, 0x171c, 0x2340, 0x2d08, 0x0950,
+ 0x3a2c, 0x161c, 0x2240, 0x2e08, 0x0a50,
+ 0x3b2c, 0x151c, 0x2140, 0x2f08, 0x0b50,
+ 0x3b30, 0x141c, 0x2040, 0x2f0c, 0x0b54,
+ 0x3a30, 0x131c, 0x1f40, 0x2e0c, 0x0a54,
+ 0x3930, 0x121c, 0x1e40, 0x2d0c, 0x0954,
+ 0x3830, 0x1220, 0x1e44, 0x2c0c, 0x0854,
+ 0x3730, 0x1320, 0x1f44, 0x2b0c, 0x0754,
+ 0x3630, 0x1420, 0x2044, 0x2a0c, 0x0654,
+ 0x3634, 0x1520, 0x2144, 0x2a10, 0x0658,
+ 0x3734, 0x1620, 0x2244, 0x2b10, 0x0858,
+ 0x3834, 0x1720, 0x2344, 0x2c10, 0x0a58,
+ 0x0024, 0x1b10, 0x2734, 0x3000, 0x0c48,
+ 0x0124, 0x1c10, 0x2834, 0x3100, 0x0d48,
+ 0x0224, 0x1d10, 0x2934, 0x3200, 0x0e48,
+ 0x0324, 0x1d14, 0x2938, 0x3300, 0x0f48,
+ 0x0424, 0x1c14, 0x2838, 0x3400, 0x1048,
+ 0x0524, 0x1b14, 0x2738, 0x3500, 0x1148,
+ 0x0528, 0x1a14, 0x2638, 0x3504, 0x114c,
+ 0x0428, 0x1914, 0x2538, 0x3404, 0x104c,
+ 0x0328, 0x1814, 0x2438, 0x3304, 0x0f4c,
+ 0x0228, 0x1818, 0x243c, 0x3204, 0x0e4c,
+ 0x0128, 0x1918, 0x253c, 0x3104, 0x0d4c,
+ 0x0028, 0x1a18, 0x263c, 0x3004, 0x0c4c,
+ 0x002c, 0x1b18, 0x273c, 0x3008, 0x0c50,
+ 0x012c, 0x1c18, 0x283c, 0x3108, 0x0d50,
+ 0x022c, 0x1d18, 0x293c, 0x3208, 0x0e50,
+ 0x032c, 0x1d1c, 0x2940, 0x3308, 0x0f50,
+ 0x042c, 0x1c1c, 0x2840, 0x3408, 0x1050,
+ 0x052c, 0x1b1c, 0x2740, 0x3508, 0x1150,
+ 0x0530, 0x1a1c, 0x2640, 0x350c, 0x1154,
+ 0x0430, 0x191c, 0x2540, 0x340c, 0x1054,
+ 0x0330, 0x181c, 0x2440, 0x330c, 0x0f54,
+ 0x0230, 0x1820, 0x2444, 0x320c, 0x0e54,
+ 0x0130, 0x1920, 0x2544, 0x310c, 0x0d54,
+ 0x0030, 0x1a20, 0x2644, 0x300c, 0x0c54,
+ 0x0034, 0x1b20, 0x2744, 0x3010, 0x0c58,
+ 0x0134, 0x1c20, 0x2844, 0x3110, 0x0e58,
+ 0x0234, 0x1d20, 0x2944, 0x3210, 0x1058,
+ 0x0624, 0x2110, 0x2d34, 0x3600, 0x1248,
+ 0x0724, 0x2210, 0x2e34, 0x3700, 0x1348,
+ 0x0824, 0x2310, 0x2f34, 0x3800, 0x1448,
+ 0x0924, 0x2314, 0x2f38, 0x3900, 0x1548,
+ 0x0a24, 0x2214, 0x2e38, 0x3a00, 0x1648,
+ 0x0b24, 0x2114, 0x2d38, 0x3b00, 0x1748,
+ 0x0b28, 0x2014, 0x2c38, 0x3b04, 0x174c,
+ 0x0a28, 0x1f14, 0x2b38, 0x3a04, 0x164c,
+ 0x0928, 0x1e14, 0x2a38, 0x3904, 0x154c,
+ 0x0828, 0x1e18, 0x2a3c, 0x3804, 0x144c,
+ 0x0728, 0x1f18, 0x2b3c, 0x3704, 0x134c,
+ 0x0628, 0x2018, 0x2c3c, 0x3604, 0x124c,
+ 0x062c, 0x2118, 0x2d3c, 0x3608, 0x1250,
+ 0x072c, 0x2218, 0x2e3c, 0x3708, 0x1350,
+ 0x082c, 0x2318, 0x2f3c, 0x3808, 0x1450,
+ 0x092c, 0x231c, 0x2f40, 0x3908, 0x1550,
+ 0x0a2c, 0x221c, 0x2e40, 0x3a08, 0x1650,
+ 0x0b2c, 0x211c, 0x2d40, 0x3b08, 0x1750,
+ 0x0b30, 0x201c, 0x2c40, 0x3b0c, 0x1754,
+ 0x0a30, 0x1f1c, 0x2b40, 0x3a0c, 0x1654,
+ 0x0930, 0x1e1c, 0x2a40, 0x390c, 0x1554,
+ 0x0830, 0x1e20, 0x2a44, 0x380c, 0x1454,
+ 0x0730, 0x1f20, 0x2b44, 0x370c, 0x1354,
+ 0x0630, 0x2020, 0x2c44, 0x360c, 0x1254,
+ 0x0634, 0x2120, 0x2d44, 0x3610, 0x1258,
+ 0x0734, 0x2220, 0x2e44, 0x3710, 0x1458,
+ 0x0834, 0x2320, 0x2f44, 0x3810, 0x1658,
+};
+
+/* 4:2:2 macroblock placement tables created by dvtables.py */
+
+/* 2 channels per frame, 10 DIF sequences per channel,
+ 27 video segments per DIF sequence, 5 macroblocks per video segment */
+static const uint16_t dv_place_422_525[2*10*27*5] = {
+ 0x0c48, 0x2424, 0x306c, 0x0000, 0x1890,
+ 0x0d48, 0x2524, 0x316c, 0x0100, 0x1990,
+ 0x0e48, 0x2624, 0x326c, 0x0200, 0x1a90,
+ 0x0e4c, 0x2628, 0x3270, 0x0204, 0x1a94,
+ 0x0d4c, 0x2528, 0x3170, 0x0104, 0x1994,
+ 0x0c4c, 0x2428, 0x3070, 0x0004, 0x1894,
+ 0x0c50, 0x242c, 0x3074, 0x0008, 0x1898,
+ 0x0d50, 0x252c, 0x3174, 0x0108, 0x1998,
+ 0x0e50, 0x262c, 0x3274, 0x0208, 0x1a98,
+ 0x0e54, 0x2630, 0x3278, 0x020c, 0x1a9c,
+ 0x0d54, 0x2530, 0x3178, 0x010c, 0x199c,
+ 0x0c54, 0x2430, 0x3078, 0x000c, 0x189c,
+ 0x0c58, 0x2434, 0x307c, 0x0010, 0x18a0,
+ 0x0d58, 0x2534, 0x317c, 0x0110, 0x19a0,
+ 0x0e58, 0x2634, 0x327c, 0x0210, 0x1aa0,
+ 0x0e5c, 0x2638, 0x3280, 0x0214, 0x1aa4,
+ 0x0d5c, 0x2538, 0x3180, 0x0114, 0x19a4,
+ 0x0c5c, 0x2438, 0x3080, 0x0014, 0x18a4,
+ 0x0c60, 0x243c, 0x3084, 0x0018, 0x18a8,
+ 0x0d60, 0x253c, 0x3184, 0x0118, 0x19a8,
+ 0x0e60, 0x263c, 0x3284, 0x0218, 0x1aa8,
+ 0x0e64, 0x2640, 0x3288, 0x021c, 0x1aac,
+ 0x0d64, 0x2540, 0x3188, 0x011c, 0x19ac,
+ 0x0c64, 0x2440, 0x3088, 0x001c, 0x18ac,
+ 0x0c68, 0x2444, 0x308c, 0x0020, 0x18b0,
+ 0x0d68, 0x2544, 0x318c, 0x0120, 0x19b0,
+ 0x0e68, 0x2644, 0x328c, 0x0220, 0x1ab0,
+ 0x1248, 0x2a24, 0x366c, 0x0600, 0x1e90,
+ 0x1348, 0x2b24, 0x376c, 0x0700, 0x1f90,
+ 0x1448, 0x2c24, 0x386c, 0x0800, 0x2090,
+ 0x144c, 0x2c28, 0x3870, 0x0804, 0x2094,
+ 0x134c, 0x2b28, 0x3770, 0x0704, 0x1f94,
+ 0x124c, 0x2a28, 0x3670, 0x0604, 0x1e94,
+ 0x1250, 0x2a2c, 0x3674, 0x0608, 0x1e98,
+ 0x1350, 0x2b2c, 0x3774, 0x0708, 0x1f98,
+ 0x1450, 0x2c2c, 0x3874, 0x0808, 0x2098,
+ 0x1454, 0x2c30, 0x3878, 0x080c, 0x209c,
+ 0x1354, 0x2b30, 0x3778, 0x070c, 0x1f9c,
+ 0x1254, 0x2a30, 0x3678, 0x060c, 0x1e9c,
+ 0x1258, 0x2a34, 0x367c, 0x0610, 0x1ea0,
+ 0x1358, 0x2b34, 0x377c, 0x0710, 0x1fa0,
+ 0x1458, 0x2c34, 0x387c, 0x0810, 0x20a0,
+ 0x145c, 0x2c38, 0x3880, 0x0814, 0x20a4,
+ 0x135c, 0x2b38, 0x3780, 0x0714, 0x1fa4,
+ 0x125c, 0x2a38, 0x3680, 0x0614, 0x1ea4,
+ 0x1260, 0x2a3c, 0x3684, 0x0618, 0x1ea8,
+ 0x1360, 0x2b3c, 0x3784, 0x0718, 0x1fa8,
+ 0x1460, 0x2c3c, 0x3884, 0x0818, 0x20a8,
+ 0x1464, 0x2c40, 0x3888, 0x081c, 0x20ac,
+ 0x1364, 0x2b40, 0x3788, 0x071c, 0x1fac,
+ 0x1264, 0x2a40, 0x3688, 0x061c, 0x1eac,
+ 0x1268, 0x2a44, 0x368c, 0x0620, 0x1eb0,
+ 0x1368, 0x2b44, 0x378c, 0x0720, 0x1fb0,
+ 0x1468, 0x2c44, 0x388c, 0x0820, 0x20b0,
+ 0x1848, 0x3024, 0x006c, 0x0c00, 0x2490,
+ 0x1948, 0x3124, 0x016c, 0x0d00, 0x2590,
+ 0x1a48, 0x3224, 0x026c, 0x0e00, 0x2690,
+ 0x1a4c, 0x3228, 0x0270, 0x0e04, 0x2694,
+ 0x194c, 0x3128, 0x0170, 0x0d04, 0x2594,
+ 0x184c, 0x3028, 0x0070, 0x0c04, 0x2494,
+ 0x1850, 0x302c, 0x0074, 0x0c08, 0x2498,
+ 0x1950, 0x312c, 0x0174, 0x0d08, 0x2598,
+ 0x1a50, 0x322c, 0x0274, 0x0e08, 0x2698,
+ 0x1a54, 0x3230, 0x0278, 0x0e0c, 0x269c,
+ 0x1954, 0x3130, 0x0178, 0x0d0c, 0x259c,
+ 0x1854, 0x3030, 0x0078, 0x0c0c, 0x249c,
+ 0x1858, 0x3034, 0x007c, 0x0c10, 0x24a0,
+ 0x1958, 0x3134, 0x017c, 0x0d10, 0x25a0,
+ 0x1a58, 0x3234, 0x027c, 0x0e10, 0x26a0,
+ 0x1a5c, 0x3238, 0x0280, 0x0e14, 0x26a4,
+ 0x195c, 0x3138, 0x0180, 0x0d14, 0x25a4,
+ 0x185c, 0x3038, 0x0080, 0x0c14, 0x24a4,
+ 0x1860, 0x303c, 0x0084, 0x0c18, 0x24a8,
+ 0x1960, 0x313c, 0x0184, 0x0d18, 0x25a8,
+ 0x1a60, 0x323c, 0x0284, 0x0e18, 0x26a8,
+ 0x1a64, 0x3240, 0x0288, 0x0e1c, 0x26ac,
+ 0x1964, 0x3140, 0x0188, 0x0d1c, 0x25ac,
+ 0x1864, 0x3040, 0x0088, 0x0c1c, 0x24ac,
+ 0x1868, 0x3044, 0x008c, 0x0c20, 0x24b0,
+ 0x1968, 0x3144, 0x018c, 0x0d20, 0x25b0,
+ 0x1a68, 0x3244, 0x028c, 0x0e20, 0x26b0,
+ 0x1e48, 0x3624, 0x066c, 0x1200, 0x2a90,
+ 0x1f48, 0x3724, 0x076c, 0x1300, 0x2b90,
+ 0x2048, 0x3824, 0x086c, 0x1400, 0x2c90,
+ 0x204c, 0x3828, 0x0870, 0x1404, 0x2c94,
+ 0x1f4c, 0x3728, 0x0770, 0x1304, 0x2b94,
+ 0x1e4c, 0x3628, 0x0670, 0x1204, 0x2a94,
+ 0x1e50, 0x362c, 0x0674, 0x1208, 0x2a98,
+ 0x1f50, 0x372c, 0x0774, 0x1308, 0x2b98,
+ 0x2050, 0x382c, 0x0874, 0x1408, 0x2c98,
+ 0x2054, 0x3830, 0x0878, 0x140c, 0x2c9c,
+ 0x1f54, 0x3730, 0x0778, 0x130c, 0x2b9c,
+ 0x1e54, 0x3630, 0x0678, 0x120c, 0x2a9c,
+ 0x1e58, 0x3634, 0x067c, 0x1210, 0x2aa0,
+ 0x1f58, 0x3734, 0x077c, 0x1310, 0x2ba0,
+ 0x2058, 0x3834, 0x087c, 0x1410, 0x2ca0,
+ 0x205c, 0x3838, 0x0880, 0x1414, 0x2ca4,
+ 0x1f5c, 0x3738, 0x0780, 0x1314, 0x2ba4,
+ 0x1e5c, 0x3638, 0x0680, 0x1214, 0x2aa4,
+ 0x1e60, 0x363c, 0x0684, 0x1218, 0x2aa8,
+ 0x1f60, 0x373c, 0x0784, 0x1318, 0x2ba8,
+ 0x2060, 0x383c, 0x0884, 0x1418, 0x2ca8,
+ 0x2064, 0x3840, 0x0888, 0x141c, 0x2cac,
+ 0x1f64, 0x3740, 0x0788, 0x131c, 0x2bac,
+ 0x1e64, 0x3640, 0x0688, 0x121c, 0x2aac,
+ 0x1e68, 0x3644, 0x068c, 0x1220, 0x2ab0,
+ 0x1f68, 0x3744, 0x078c, 0x1320, 0x2bb0,
+ 0x2068, 0x3844, 0x088c, 0x1420, 0x2cb0,
+ 0x2448, 0x0024, 0x0c6c, 0x1800, 0x3090,
+ 0x2548, 0x0124, 0x0d6c, 0x1900, 0x3190,
+ 0x2648, 0x0224, 0x0e6c, 0x1a00, 0x3290,
+ 0x264c, 0x0228, 0x0e70, 0x1a04, 0x3294,
+ 0x254c, 0x0128, 0x0d70, 0x1904, 0x3194,
+ 0x244c, 0x0028, 0x0c70, 0x1804, 0x3094,
+ 0x2450, 0x002c, 0x0c74, 0x1808, 0x3098,
+ 0x2550, 0x012c, 0x0d74, 0x1908, 0x3198,
+ 0x2650, 0x022c, 0x0e74, 0x1a08, 0x3298,
+ 0x2654, 0x0230, 0x0e78, 0x1a0c, 0x329c,
+ 0x2554, 0x0130, 0x0d78, 0x190c, 0x319c,
+ 0x2454, 0x0030, 0x0c78, 0x180c, 0x309c,
+ 0x2458, 0x0034, 0x0c7c, 0x1810, 0x30a0,
+ 0x2558, 0x0134, 0x0d7c, 0x1910, 0x31a0,
+ 0x2658, 0x0234, 0x0e7c, 0x1a10, 0x32a0,
+ 0x265c, 0x0238, 0x0e80, 0x1a14, 0x32a4,
+ 0x255c, 0x0138, 0x0d80, 0x1914, 0x31a4,
+ 0x245c, 0x0038, 0x0c80, 0x1814, 0x30a4,
+ 0x2460, 0x003c, 0x0c84, 0x1818, 0x30a8,
+ 0x2560, 0x013c, 0x0d84, 0x1918, 0x31a8,
+ 0x2660, 0x023c, 0x0e84, 0x1a18, 0x32a8,
+ 0x2664, 0x0240, 0x0e88, 0x1a1c, 0x32ac,
+ 0x2564, 0x0140, 0x0d88, 0x191c, 0x31ac,
+ 0x2464, 0x0040, 0x0c88, 0x181c, 0x30ac,
+ 0x2468, 0x0044, 0x0c8c, 0x1820, 0x30b0,
+ 0x2568, 0x0144, 0x0d8c, 0x1920, 0x31b0,
+ 0x2668, 0x0244, 0x0e8c, 0x1a20, 0x32b0,
+ 0x2a48, 0x0624, 0x126c, 0x1e00, 0x3690,
+ 0x2b48, 0x0724, 0x136c, 0x1f00, 0x3790,
+ 0x2c48, 0x0824, 0x146c, 0x2000, 0x3890,
+ 0x2c4c, 0x0828, 0x1470, 0x2004, 0x3894,
+ 0x2b4c, 0x0728, 0x1370, 0x1f04, 0x3794,
+ 0x2a4c, 0x0628, 0x1270, 0x1e04, 0x3694,
+ 0x2a50, 0x062c, 0x1274, 0x1e08, 0x3698,
+ 0x2b50, 0x072c, 0x1374, 0x1f08, 0x3798,
+ 0x2c50, 0x082c, 0x1474, 0x2008, 0x3898,
+ 0x2c54, 0x0830, 0x1478, 0x200c, 0x389c,
+ 0x2b54, 0x0730, 0x1378, 0x1f0c, 0x379c,
+ 0x2a54, 0x0630, 0x1278, 0x1e0c, 0x369c,
+ 0x2a58, 0x0634, 0x127c, 0x1e10, 0x36a0,
+ 0x2b58, 0x0734, 0x137c, 0x1f10, 0x37a0,
+ 0x2c58, 0x0834, 0x147c, 0x2010, 0x38a0,
+ 0x2c5c, 0x0838, 0x1480, 0x2014, 0x38a4,
+ 0x2b5c, 0x0738, 0x1380, 0x1f14, 0x37a4,
+ 0x2a5c, 0x0638, 0x1280, 0x1e14, 0x36a4,
+ 0x2a60, 0x063c, 0x1284, 0x1e18, 0x36a8,
+ 0x2b60, 0x073c, 0x1384, 0x1f18, 0x37a8,
+ 0x2c60, 0x083c, 0x1484, 0x2018, 0x38a8,
+ 0x2c64, 0x0840, 0x1488, 0x201c, 0x38ac,
+ 0x2b64, 0x0740, 0x1388, 0x1f1c, 0x37ac,
+ 0x2a64, 0x0640, 0x1288, 0x1e1c, 0x36ac,
+ 0x2a68, 0x0644, 0x128c, 0x1e20, 0x36b0,
+ 0x2b68, 0x0744, 0x138c, 0x1f20, 0x37b0,
+ 0x2c68, 0x0844, 0x148c, 0x2020, 0x38b0,
+ 0x3048, 0x0c24, 0x186c, 0x2400, 0x0090,
+ 0x3148, 0x0d24, 0x196c, 0x2500, 0x0190,
+ 0x3248, 0x0e24, 0x1a6c, 0x2600, 0x0290,
+ 0x324c, 0x0e28, 0x1a70, 0x2604, 0x0294,
+ 0x314c, 0x0d28, 0x1970, 0x2504, 0x0194,
+ 0x304c, 0x0c28, 0x1870, 0x2404, 0x0094,
+ 0x3050, 0x0c2c, 0x1874, 0x2408, 0x0098,
+ 0x3150, 0x0d2c, 0x1974, 0x2508, 0x0198,
+ 0x3250, 0x0e2c, 0x1a74, 0x2608, 0x0298,
+ 0x3254, 0x0e30, 0x1a78, 0x260c, 0x029c,
+ 0x3154, 0x0d30, 0x1978, 0x250c, 0x019c,
+ 0x3054, 0x0c30, 0x1878, 0x240c, 0x009c,
+ 0x3058, 0x0c34, 0x187c, 0x2410, 0x00a0,
+ 0x3158, 0x0d34, 0x197c, 0x2510, 0x01a0,
+ 0x3258, 0x0e34, 0x1a7c, 0x2610, 0x02a0,
+ 0x325c, 0x0e38, 0x1a80, 0x2614, 0x02a4,
+ 0x315c, 0x0d38, 0x1980, 0x2514, 0x01a4,
+ 0x305c, 0x0c38, 0x1880, 0x2414, 0x00a4,
+ 0x3060, 0x0c3c, 0x1884, 0x2418, 0x00a8,
+ 0x3160, 0x0d3c, 0x1984, 0x2518, 0x01a8,
+ 0x3260, 0x0e3c, 0x1a84, 0x2618, 0x02a8,
+ 0x3264, 0x0e40, 0x1a88, 0x261c, 0x02ac,
+ 0x3164, 0x0d40, 0x1988, 0x251c, 0x01ac,
+ 0x3064, 0x0c40, 0x1888, 0x241c, 0x00ac,
+ 0x3068, 0x0c44, 0x188c, 0x2420, 0x00b0,
+ 0x3168, 0x0d44, 0x198c, 0x2520, 0x01b0,
+ 0x3268, 0x0e44, 0x1a8c, 0x2620, 0x02b0,
+ 0x3648, 0x1224, 0x1e6c, 0x2a00, 0x0690,
+ 0x3748, 0x1324, 0x1f6c, 0x2b00, 0x0790,
+ 0x3848, 0x1424, 0x206c, 0x2c00, 0x0890,
+ 0x384c, 0x1428, 0x2070, 0x2c04, 0x0894,
+ 0x374c, 0x1328, 0x1f70, 0x2b04, 0x0794,
+ 0x364c, 0x1228, 0x1e70, 0x2a04, 0x0694,
+ 0x3650, 0x122c, 0x1e74, 0x2a08, 0x0698,
+ 0x3750, 0x132c, 0x1f74, 0x2b08, 0x0798,
+ 0x3850, 0x142c, 0x2074, 0x2c08, 0x0898,
+ 0x3854, 0x1430, 0x2078, 0x2c0c, 0x089c,
+ 0x3754, 0x1330, 0x1f78, 0x2b0c, 0x079c,
+ 0x3654, 0x1230, 0x1e78, 0x2a0c, 0x069c,
+ 0x3658, 0x1234, 0x1e7c, 0x2a10, 0x06a0,
+ 0x3758, 0x1334, 0x1f7c, 0x2b10, 0x07a0,
+ 0x3858, 0x1434, 0x207c, 0x2c10, 0x08a0,
+ 0x385c, 0x1438, 0x2080, 0x2c14, 0x08a4,
+ 0x375c, 0x1338, 0x1f80, 0x2b14, 0x07a4,
+ 0x365c, 0x1238, 0x1e80, 0x2a14, 0x06a4,
+ 0x3660, 0x123c, 0x1e84, 0x2a18, 0x06a8,
+ 0x3760, 0x133c, 0x1f84, 0x2b18, 0x07a8,
+ 0x3860, 0x143c, 0x2084, 0x2c18, 0x08a8,
+ 0x3864, 0x1440, 0x2088, 0x2c1c, 0x08ac,
+ 0x3764, 0x1340, 0x1f88, 0x2b1c, 0x07ac,
+ 0x3664, 0x1240, 0x1e88, 0x2a1c, 0x06ac,
+ 0x3668, 0x1244, 0x1e8c, 0x2a20, 0x06b0,
+ 0x3768, 0x1344, 0x1f8c, 0x2b20, 0x07b0,
+ 0x3868, 0x1444, 0x208c, 0x2c20, 0x08b0,
+ 0x0048, 0x1824, 0x246c, 0x3000, 0x0c90,
+ 0x0148, 0x1924, 0x256c, 0x3100, 0x0d90,
+ 0x0248, 0x1a24, 0x266c, 0x3200, 0x0e90,
+ 0x024c, 0x1a28, 0x2670, 0x3204, 0x0e94,
+ 0x014c, 0x1928, 0x2570, 0x3104, 0x0d94,
+ 0x004c, 0x1828, 0x2470, 0x3004, 0x0c94,
+ 0x0050, 0x182c, 0x2474, 0x3008, 0x0c98,
+ 0x0150, 0x192c, 0x2574, 0x3108, 0x0d98,
+ 0x0250, 0x1a2c, 0x2674, 0x3208, 0x0e98,
+ 0x0254, 0x1a30, 0x2678, 0x320c, 0x0e9c,
+ 0x0154, 0x1930, 0x2578, 0x310c, 0x0d9c,
+ 0x0054, 0x1830, 0x2478, 0x300c, 0x0c9c,
+ 0x0058, 0x1834, 0x247c, 0x3010, 0x0ca0,
+ 0x0158, 0x1934, 0x257c, 0x3110, 0x0da0,
+ 0x0258, 0x1a34, 0x267c, 0x3210, 0x0ea0,
+ 0x025c, 0x1a38, 0x2680, 0x3214, 0x0ea4,
+ 0x015c, 0x1938, 0x2580, 0x3114, 0x0da4,
+ 0x005c, 0x1838, 0x2480, 0x3014, 0x0ca4,
+ 0x0060, 0x183c, 0x2484, 0x3018, 0x0ca8,
+ 0x0160, 0x193c, 0x2584, 0x3118, 0x0da8,
+ 0x0260, 0x1a3c, 0x2684, 0x3218, 0x0ea8,
+ 0x0264, 0x1a40, 0x2688, 0x321c, 0x0eac,
+ 0x0164, 0x1940, 0x2588, 0x311c, 0x0dac,
+ 0x0064, 0x1840, 0x2488, 0x301c, 0x0cac,
+ 0x0068, 0x1844, 0x248c, 0x3020, 0x0cb0,
+ 0x0168, 0x1944, 0x258c, 0x3120, 0x0db0,
+ 0x0268, 0x1a44, 0x268c, 0x3220, 0x0eb0,
+ 0x0648, 0x1e24, 0x2a6c, 0x3600, 0x1290,
+ 0x0748, 0x1f24, 0x2b6c, 0x3700, 0x1390,
+ 0x0848, 0x2024, 0x2c6c, 0x3800, 0x1490,
+ 0x084c, 0x2028, 0x2c70, 0x3804, 0x1494,
+ 0x074c, 0x1f28, 0x2b70, 0x3704, 0x1394,
+ 0x064c, 0x1e28, 0x2a70, 0x3604, 0x1294,
+ 0x0650, 0x1e2c, 0x2a74, 0x3608, 0x1298,
+ 0x0750, 0x1f2c, 0x2b74, 0x3708, 0x1398,
+ 0x0850, 0x202c, 0x2c74, 0x3808, 0x1498,
+ 0x0854, 0x2030, 0x2c78, 0x380c, 0x149c,
+ 0x0754, 0x1f30, 0x2b78, 0x370c, 0x139c,
+ 0x0654, 0x1e30, 0x2a78, 0x360c, 0x129c,
+ 0x0658, 0x1e34, 0x2a7c, 0x3610, 0x12a0,
+ 0x0758, 0x1f34, 0x2b7c, 0x3710, 0x13a0,
+ 0x0858, 0x2034, 0x2c7c, 0x3810, 0x14a0,
+ 0x085c, 0x2038, 0x2c80, 0x3814, 0x14a4,
+ 0x075c, 0x1f38, 0x2b80, 0x3714, 0x13a4,
+ 0x065c, 0x1e38, 0x2a80, 0x3614, 0x12a4,
+ 0x0660, 0x1e3c, 0x2a84, 0x3618, 0x12a8,
+ 0x0760, 0x1f3c, 0x2b84, 0x3718, 0x13a8,
+ 0x0860, 0x203c, 0x2c84, 0x3818, 0x14a8,
+ 0x0864, 0x2040, 0x2c88, 0x381c, 0x14ac,
+ 0x0764, 0x1f40, 0x2b88, 0x371c, 0x13ac,
+ 0x0664, 0x1e40, 0x2a88, 0x361c, 0x12ac,
+ 0x0668, 0x1e44, 0x2a8c, 0x3620, 0x12b0,
+ 0x0768, 0x1f44, 0x2b8c, 0x3720, 0x13b0,
+ 0x0868, 0x2044, 0x2c8c, 0x3820, 0x14b0,
+ 0x0f48, 0x2724, 0x336c, 0x0300, 0x1b90,
+ 0x1048, 0x2824, 0x346c, 0x0400, 0x1c90,
+ 0x1148, 0x2924, 0x356c, 0x0500, 0x1d90,
+ 0x114c, 0x2928, 0x3570, 0x0504, 0x1d94,
+ 0x104c, 0x2828, 0x3470, 0x0404, 0x1c94,
+ 0x0f4c, 0x2728, 0x3370, 0x0304, 0x1b94,
+ 0x0f50, 0x272c, 0x3374, 0x0308, 0x1b98,
+ 0x1050, 0x282c, 0x3474, 0x0408, 0x1c98,
+ 0x1150, 0x292c, 0x3574, 0x0508, 0x1d98,
+ 0x1154, 0x2930, 0x3578, 0x050c, 0x1d9c,
+ 0x1054, 0x2830, 0x3478, 0x040c, 0x1c9c,
+ 0x0f54, 0x2730, 0x3378, 0x030c, 0x1b9c,
+ 0x0f58, 0x2734, 0x337c, 0x0310, 0x1ba0,
+ 0x1058, 0x2834, 0x347c, 0x0410, 0x1ca0,
+ 0x1158, 0x2934, 0x357c, 0x0510, 0x1da0,
+ 0x115c, 0x2938, 0x3580, 0x0514, 0x1da4,
+ 0x105c, 0x2838, 0x3480, 0x0414, 0x1ca4,
+ 0x0f5c, 0x2738, 0x3380, 0x0314, 0x1ba4,
+ 0x0f60, 0x273c, 0x3384, 0x0318, 0x1ba8,
+ 0x1060, 0x283c, 0x3484, 0x0418, 0x1ca8,
+ 0x1160, 0x293c, 0x3584, 0x0518, 0x1da8,
+ 0x1164, 0x2940, 0x3588, 0x051c, 0x1dac,
+ 0x1064, 0x2840, 0x3488, 0x041c, 0x1cac,
+ 0x0f64, 0x2740, 0x3388, 0x031c, 0x1bac,
+ 0x0f68, 0x2744, 0x338c, 0x0320, 0x1bb0,
+ 0x1068, 0x2844, 0x348c, 0x0420, 0x1cb0,
+ 0x1168, 0x2944, 0x358c, 0x0520, 0x1db0,
+ 0x1548, 0x2d24, 0x396c, 0x0900, 0x2190,
+ 0x1648, 0x2e24, 0x3a6c, 0x0a00, 0x2290,
+ 0x1748, 0x2f24, 0x3b6c, 0x0b00, 0x2390,
+ 0x174c, 0x2f28, 0x3b70, 0x0b04, 0x2394,
+ 0x164c, 0x2e28, 0x3a70, 0x0a04, 0x2294,
+ 0x154c, 0x2d28, 0x3970, 0x0904, 0x2194,
+ 0x1550, 0x2d2c, 0x3974, 0x0908, 0x2198,
+ 0x1650, 0x2e2c, 0x3a74, 0x0a08, 0x2298,
+ 0x1750, 0x2f2c, 0x3b74, 0x0b08, 0x2398,
+ 0x1754, 0x2f30, 0x3b78, 0x0b0c, 0x239c,
+ 0x1654, 0x2e30, 0x3a78, 0x0a0c, 0x229c,
+ 0x1554, 0x2d30, 0x3978, 0x090c, 0x219c,
+ 0x1558, 0x2d34, 0x397c, 0x0910, 0x21a0,
+ 0x1658, 0x2e34, 0x3a7c, 0x0a10, 0x22a0,
+ 0x1758, 0x2f34, 0x3b7c, 0x0b10, 0x23a0,
+ 0x175c, 0x2f38, 0x3b80, 0x0b14, 0x23a4,
+ 0x165c, 0x2e38, 0x3a80, 0x0a14, 0x22a4,
+ 0x155c, 0x2d38, 0x3980, 0x0914, 0x21a4,
+ 0x1560, 0x2d3c, 0x3984, 0x0918, 0x21a8,
+ 0x1660, 0x2e3c, 0x3a84, 0x0a18, 0x22a8,
+ 0x1760, 0x2f3c, 0x3b84, 0x0b18, 0x23a8,
+ 0x1764, 0x2f40, 0x3b88, 0x0b1c, 0x23ac,
+ 0x1664, 0x2e40, 0x3a88, 0x0a1c, 0x22ac,
+ 0x1564, 0x2d40, 0x3988, 0x091c, 0x21ac,
+ 0x1568, 0x2d44, 0x398c, 0x0920, 0x21b0,
+ 0x1668, 0x2e44, 0x3a8c, 0x0a20, 0x22b0,
+ 0x1768, 0x2f44, 0x3b8c, 0x0b20, 0x23b0,
+ 0x1b48, 0x3324, 0x036c, 0x0f00, 0x2790,
+ 0x1c48, 0x3424, 0x046c, 0x1000, 0x2890,
+ 0x1d48, 0x3524, 0x056c, 0x1100, 0x2990,
+ 0x1d4c, 0x3528, 0x0570, 0x1104, 0x2994,
+ 0x1c4c, 0x3428, 0x0470, 0x1004, 0x2894,
+ 0x1b4c, 0x3328, 0x0370, 0x0f04, 0x2794,
+ 0x1b50, 0x332c, 0x0374, 0x0f08, 0x2798,
+ 0x1c50, 0x342c, 0x0474, 0x1008, 0x2898,
+ 0x1d50, 0x352c, 0x0574, 0x1108, 0x2998,
+ 0x1d54, 0x3530, 0x0578, 0x110c, 0x299c,
+ 0x1c54, 0x3430, 0x0478, 0x100c, 0x289c,
+ 0x1b54, 0x3330, 0x0378, 0x0f0c, 0x279c,
+ 0x1b58, 0x3334, 0x037c, 0x0f10, 0x27a0,
+ 0x1c58, 0x3434, 0x047c, 0x1010, 0x28a0,
+ 0x1d58, 0x3534, 0x057c, 0x1110, 0x29a0,
+ 0x1d5c, 0x3538, 0x0580, 0x1114, 0x29a4,
+ 0x1c5c, 0x3438, 0x0480, 0x1014, 0x28a4,
+ 0x1b5c, 0x3338, 0x0380, 0x0f14, 0x27a4,
+ 0x1b60, 0x333c, 0x0384, 0x0f18, 0x27a8,
+ 0x1c60, 0x343c, 0x0484, 0x1018, 0x28a8,
+ 0x1d60, 0x353c, 0x0584, 0x1118, 0x29a8,
+ 0x1d64, 0x3540, 0x0588, 0x111c, 0x29ac,
+ 0x1c64, 0x3440, 0x0488, 0x101c, 0x28ac,
+ 0x1b64, 0x3340, 0x0388, 0x0f1c, 0x27ac,
+ 0x1b68, 0x3344, 0x038c, 0x0f20, 0x27b0,
+ 0x1c68, 0x3444, 0x048c, 0x1020, 0x28b0,
+ 0x1d68, 0x3544, 0x058c, 0x1120, 0x29b0,
+ 0x2148, 0x3924, 0x096c, 0x1500, 0x2d90,
+ 0x2248, 0x3a24, 0x0a6c, 0x1600, 0x2e90,
+ 0x2348, 0x3b24, 0x0b6c, 0x1700, 0x2f90,
+ 0x234c, 0x3b28, 0x0b70, 0x1704, 0x2f94,
+ 0x224c, 0x3a28, 0x0a70, 0x1604, 0x2e94,
+ 0x214c, 0x3928, 0x0970, 0x1504, 0x2d94,
+ 0x2150, 0x392c, 0x0974, 0x1508, 0x2d98,
+ 0x2250, 0x3a2c, 0x0a74, 0x1608, 0x2e98,
+ 0x2350, 0x3b2c, 0x0b74, 0x1708, 0x2f98,
+ 0x2354, 0x3b30, 0x0b78, 0x170c, 0x2f9c,
+ 0x2254, 0x3a30, 0x0a78, 0x160c, 0x2e9c,
+ 0x2154, 0x3930, 0x0978, 0x150c, 0x2d9c,
+ 0x2158, 0x3934, 0x097c, 0x1510, 0x2da0,
+ 0x2258, 0x3a34, 0x0a7c, 0x1610, 0x2ea0,
+ 0x2358, 0x3b34, 0x0b7c, 0x1710, 0x2fa0,
+ 0x235c, 0x3b38, 0x0b80, 0x1714, 0x2fa4,
+ 0x225c, 0x3a38, 0x0a80, 0x1614, 0x2ea4,
+ 0x215c, 0x3938, 0x0980, 0x1514, 0x2da4,
+ 0x2160, 0x393c, 0x0984, 0x1518, 0x2da8,
+ 0x2260, 0x3a3c, 0x0a84, 0x1618, 0x2ea8,
+ 0x2360, 0x3b3c, 0x0b84, 0x1718, 0x2fa8,
+ 0x2364, 0x3b40, 0x0b88, 0x171c, 0x2fac,
+ 0x2264, 0x3a40, 0x0a88, 0x161c, 0x2eac,
+ 0x2164, 0x3940, 0x0988, 0x151c, 0x2dac,
+ 0x2168, 0x3944, 0x098c, 0x1520, 0x2db0,
+ 0x2268, 0x3a44, 0x0a8c, 0x1620, 0x2eb0,
+ 0x2368, 0x3b44, 0x0b8c, 0x1720, 0x2fb0,
+ 0x2748, 0x0324, 0x0f6c, 0x1b00, 0x3390,
+ 0x2848, 0x0424, 0x106c, 0x1c00, 0x3490,
+ 0x2948, 0x0524, 0x116c, 0x1d00, 0x3590,
+ 0x294c, 0x0528, 0x1170, 0x1d04, 0x3594,
+ 0x284c, 0x0428, 0x1070, 0x1c04, 0x3494,
+ 0x274c, 0x0328, 0x0f70, 0x1b04, 0x3394,
+ 0x2750, 0x032c, 0x0f74, 0x1b08, 0x3398,
+ 0x2850, 0x042c, 0x1074, 0x1c08, 0x3498,
+ 0x2950, 0x052c, 0x1174, 0x1d08, 0x3598,
+ 0x2954, 0x0530, 0x1178, 0x1d0c, 0x359c,
+ 0x2854, 0x0430, 0x1078, 0x1c0c, 0x349c,
+ 0x2754, 0x0330, 0x0f78, 0x1b0c, 0x339c,
+ 0x2758, 0x0334, 0x0f7c, 0x1b10, 0x33a0,
+ 0x2858, 0x0434, 0x107c, 0x1c10, 0x34a0,
+ 0x2958, 0x0534, 0x117c, 0x1d10, 0x35a0,
+ 0x295c, 0x0538, 0x1180, 0x1d14, 0x35a4,
+ 0x285c, 0x0438, 0x1080, 0x1c14, 0x34a4,
+ 0x275c, 0x0338, 0x0f80, 0x1b14, 0x33a4,
+ 0x2760, 0x033c, 0x0f84, 0x1b18, 0x33a8,
+ 0x2860, 0x043c, 0x1084, 0x1c18, 0x34a8,
+ 0x2960, 0x053c, 0x1184, 0x1d18, 0x35a8,
+ 0x2964, 0x0540, 0x1188, 0x1d1c, 0x35ac,
+ 0x2864, 0x0440, 0x1088, 0x1c1c, 0x34ac,
+ 0x2764, 0x0340, 0x0f88, 0x1b1c, 0x33ac,
+ 0x2768, 0x0344, 0x0f8c, 0x1b20, 0x33b0,
+ 0x2868, 0x0444, 0x108c, 0x1c20, 0x34b0,
+ 0x2968, 0x0544, 0x118c, 0x1d20, 0x35b0,
+ 0x2d48, 0x0924, 0x156c, 0x2100, 0x3990,
+ 0x2e48, 0x0a24, 0x166c, 0x2200, 0x3a90,
+ 0x2f48, 0x0b24, 0x176c, 0x2300, 0x3b90,
+ 0x2f4c, 0x0b28, 0x1770, 0x2304, 0x3b94,
+ 0x2e4c, 0x0a28, 0x1670, 0x2204, 0x3a94,
+ 0x2d4c, 0x0928, 0x1570, 0x2104, 0x3994,
+ 0x2d50, 0x092c, 0x1574, 0x2108, 0x3998,
+ 0x2e50, 0x0a2c, 0x1674, 0x2208, 0x3a98,
+ 0x2f50, 0x0b2c, 0x1774, 0x2308, 0x3b98,
+ 0x2f54, 0x0b30, 0x1778, 0x230c, 0x3b9c,
+ 0x2e54, 0x0a30, 0x1678, 0x220c, 0x3a9c,
+ 0x2d54, 0x0930, 0x1578, 0x210c, 0x399c,
+ 0x2d58, 0x0934, 0x157c, 0x2110, 0x39a0,
+ 0x2e58, 0x0a34, 0x167c, 0x2210, 0x3aa0,
+ 0x2f58, 0x0b34, 0x177c, 0x2310, 0x3ba0,
+ 0x2f5c, 0x0b38, 0x1780, 0x2314, 0x3ba4,
+ 0x2e5c, 0x0a38, 0x1680, 0x2214, 0x3aa4,
+ 0x2d5c, 0x0938, 0x1580, 0x2114, 0x39a4,
+ 0x2d60, 0x093c, 0x1584, 0x2118, 0x39a8,
+ 0x2e60, 0x0a3c, 0x1684, 0x2218, 0x3aa8,
+ 0x2f60, 0x0b3c, 0x1784, 0x2318, 0x3ba8,
+ 0x2f64, 0x0b40, 0x1788, 0x231c, 0x3bac,
+ 0x2e64, 0x0a40, 0x1688, 0x221c, 0x3aac,
+ 0x2d64, 0x0940, 0x1588, 0x211c, 0x39ac,
+ 0x2d68, 0x0944, 0x158c, 0x2120, 0x39b0,
+ 0x2e68, 0x0a44, 0x168c, 0x2220, 0x3ab0,
+ 0x2f68, 0x0b44, 0x178c, 0x2320, 0x3bb0,
+ 0x3348, 0x0f24, 0x1b6c, 0x2700, 0x0390,
+ 0x3448, 0x1024, 0x1c6c, 0x2800, 0x0490,
+ 0x3548, 0x1124, 0x1d6c, 0x2900, 0x0590,
+ 0x354c, 0x1128, 0x1d70, 0x2904, 0x0594,
+ 0x344c, 0x1028, 0x1c70, 0x2804, 0x0494,
+ 0x334c, 0x0f28, 0x1b70, 0x2704, 0x0394,
+ 0x3350, 0x0f2c, 0x1b74, 0x2708, 0x0398,
+ 0x3450, 0x102c, 0x1c74, 0x2808, 0x0498,
+ 0x3550, 0x112c, 0x1d74, 0x2908, 0x0598,
+ 0x3554, 0x1130, 0x1d78, 0x290c, 0x059c,
+ 0x3454, 0x1030, 0x1c78, 0x280c, 0x049c,
+ 0x3354, 0x0f30, 0x1b78, 0x270c, 0x039c,
+ 0x3358, 0x0f34, 0x1b7c, 0x2710, 0x03a0,
+ 0x3458, 0x1034, 0x1c7c, 0x2810, 0x04a0,
+ 0x3558, 0x1134, 0x1d7c, 0x2910, 0x05a0,
+ 0x355c, 0x1138, 0x1d80, 0x2914, 0x05a4,
+ 0x345c, 0x1038, 0x1c80, 0x2814, 0x04a4,
+ 0x335c, 0x0f38, 0x1b80, 0x2714, 0x03a4,
+ 0x3360, 0x0f3c, 0x1b84, 0x2718, 0x03a8,
+ 0x3460, 0x103c, 0x1c84, 0x2818, 0x04a8,
+ 0x3560, 0x113c, 0x1d84, 0x2918, 0x05a8,
+ 0x3564, 0x1140, 0x1d88, 0x291c, 0x05ac,
+ 0x3464, 0x1040, 0x1c88, 0x281c, 0x04ac,
+ 0x3364, 0x0f40, 0x1b88, 0x271c, 0x03ac,
+ 0x3368, 0x0f44, 0x1b8c, 0x2720, 0x03b0,
+ 0x3468, 0x1044, 0x1c8c, 0x2820, 0x04b0,
+ 0x3568, 0x1144, 0x1d8c, 0x2920, 0x05b0,
+ 0x3948, 0x1524, 0x216c, 0x2d00, 0x0990,
+ 0x3a48, 0x1624, 0x226c, 0x2e00, 0x0a90,
+ 0x3b48, 0x1724, 0x236c, 0x2f00, 0x0b90,
+ 0x3b4c, 0x1728, 0x2370, 0x2f04, 0x0b94,
+ 0x3a4c, 0x1628, 0x2270, 0x2e04, 0x0a94,
+ 0x394c, 0x1528, 0x2170, 0x2d04, 0x0994,
+ 0x3950, 0x152c, 0x2174, 0x2d08, 0x0998,
+ 0x3a50, 0x162c, 0x2274, 0x2e08, 0x0a98,
+ 0x3b50, 0x172c, 0x2374, 0x2f08, 0x0b98,
+ 0x3b54, 0x1730, 0x2378, 0x2f0c, 0x0b9c,
+ 0x3a54, 0x1630, 0x2278, 0x2e0c, 0x0a9c,
+ 0x3954, 0x1530, 0x2178, 0x2d0c, 0x099c,
+ 0x3958, 0x1534, 0x217c, 0x2d10, 0x09a0,
+ 0x3a58, 0x1634, 0x227c, 0x2e10, 0x0aa0,
+ 0x3b58, 0x1734, 0x237c, 0x2f10, 0x0ba0,
+ 0x3b5c, 0x1738, 0x2380, 0x2f14, 0x0ba4,
+ 0x3a5c, 0x1638, 0x2280, 0x2e14, 0x0aa4,
+ 0x395c, 0x1538, 0x2180, 0x2d14, 0x09a4,
+ 0x3960, 0x153c, 0x2184, 0x2d18, 0x09a8,
+ 0x3a60, 0x163c, 0x2284, 0x2e18, 0x0aa8,
+ 0x3b60, 0x173c, 0x2384, 0x2f18, 0x0ba8,
+ 0x3b64, 0x1740, 0x2388, 0x2f1c, 0x0bac,
+ 0x3a64, 0x1640, 0x2288, 0x2e1c, 0x0aac,
+ 0x3964, 0x1540, 0x2188, 0x2d1c, 0x09ac,
+ 0x3968, 0x1544, 0x218c, 0x2d20, 0x09b0,
+ 0x3a68, 0x1644, 0x228c, 0x2e20, 0x0ab0,
+ 0x3b68, 0x1744, 0x238c, 0x2f20, 0x0bb0,
+ 0x0348, 0x1b24, 0x276c, 0x3300, 0x0f90,
+ 0x0448, 0x1c24, 0x286c, 0x3400, 0x1090,
+ 0x0548, 0x1d24, 0x296c, 0x3500, 0x1190,
+ 0x054c, 0x1d28, 0x2970, 0x3504, 0x1194,
+ 0x044c, 0x1c28, 0x2870, 0x3404, 0x1094,
+ 0x034c, 0x1b28, 0x2770, 0x3304, 0x0f94,
+ 0x0350, 0x1b2c, 0x2774, 0x3308, 0x0f98,
+ 0x0450, 0x1c2c, 0x2874, 0x3408, 0x1098,
+ 0x0550, 0x1d2c, 0x2974, 0x3508, 0x1198,
+ 0x0554, 0x1d30, 0x2978, 0x350c, 0x119c,
+ 0x0454, 0x1c30, 0x2878, 0x340c, 0x109c,
+ 0x0354, 0x1b30, 0x2778, 0x330c, 0x0f9c,
+ 0x0358, 0x1b34, 0x277c, 0x3310, 0x0fa0,
+ 0x0458, 0x1c34, 0x287c, 0x3410, 0x10a0,
+ 0x0558, 0x1d34, 0x297c, 0x3510, 0x11a0,
+ 0x055c, 0x1d38, 0x2980, 0x3514, 0x11a4,
+ 0x045c, 0x1c38, 0x2880, 0x3414, 0x10a4,
+ 0x035c, 0x1b38, 0x2780, 0x3314, 0x0fa4,
+ 0x0360, 0x1b3c, 0x2784, 0x3318, 0x0fa8,
+ 0x0460, 0x1c3c, 0x2884, 0x3418, 0x10a8,
+ 0x0560, 0x1d3c, 0x2984, 0x3518, 0x11a8,
+ 0x0564, 0x1d40, 0x2988, 0x351c, 0x11ac,
+ 0x0464, 0x1c40, 0x2888, 0x341c, 0x10ac,
+ 0x0364, 0x1b40, 0x2788, 0x331c, 0x0fac,
+ 0x0368, 0x1b44, 0x278c, 0x3320, 0x0fb0,
+ 0x0468, 0x1c44, 0x288c, 0x3420, 0x10b0,
+ 0x0568, 0x1d44, 0x298c, 0x3520, 0x11b0,
+ 0x0948, 0x2124, 0x2d6c, 0x3900, 0x1590,
+ 0x0a48, 0x2224, 0x2e6c, 0x3a00, 0x1690,
+ 0x0b48, 0x2324, 0x2f6c, 0x3b00, 0x1790,
+ 0x0b4c, 0x2328, 0x2f70, 0x3b04, 0x1794,
+ 0x0a4c, 0x2228, 0x2e70, 0x3a04, 0x1694,
+ 0x094c, 0x2128, 0x2d70, 0x3904, 0x1594,
+ 0x0950, 0x212c, 0x2d74, 0x3908, 0x1598,
+ 0x0a50, 0x222c, 0x2e74, 0x3a08, 0x1698,
+ 0x0b50, 0x232c, 0x2f74, 0x3b08, 0x1798,
+ 0x0b54, 0x2330, 0x2f78, 0x3b0c, 0x179c,
+ 0x0a54, 0x2230, 0x2e78, 0x3a0c, 0x169c,
+ 0x0954, 0x2130, 0x2d78, 0x390c, 0x159c,
+ 0x0958, 0x2134, 0x2d7c, 0x3910, 0x15a0,
+ 0x0a58, 0x2234, 0x2e7c, 0x3a10, 0x16a0,
+ 0x0b58, 0x2334, 0x2f7c, 0x3b10, 0x17a0,
+ 0x0b5c, 0x2338, 0x2f80, 0x3b14, 0x17a4,
+ 0x0a5c, 0x2238, 0x2e80, 0x3a14, 0x16a4,
+ 0x095c, 0x2138, 0x2d80, 0x3914, 0x15a4,
+ 0x0960, 0x213c, 0x2d84, 0x3918, 0x15a8,
+ 0x0a60, 0x223c, 0x2e84, 0x3a18, 0x16a8,
+ 0x0b60, 0x233c, 0x2f84, 0x3b18, 0x17a8,
+ 0x0b64, 0x2340, 0x2f88, 0x3b1c, 0x17ac,
+ 0x0a64, 0x2240, 0x2e88, 0x3a1c, 0x16ac,
+ 0x0964, 0x2140, 0x2d88, 0x391c, 0x15ac,
+ 0x0968, 0x2144, 0x2d8c, 0x3920, 0x15b0,
+ 0x0a68, 0x2244, 0x2e8c, 0x3a20, 0x16b0,
+ 0x0b68, 0x2344, 0x2f8c, 0x3b20, 0x17b0,
+};
+
+/* 2 channels per frame, 12 DIF sequences per channel,
+ 27 video segments per DIF sequence, 5 macroblocks per video segment */
+static const uint16_t dv_place_422_625[2*12*27*5] = {
+ 0x0c48, 0x2424, 0x306c, 0x0000, 0x1890,
+ 0x0d48, 0x2524, 0x316c, 0x0100, 0x1990,
+ 0x0e48, 0x2624, 0x326c, 0x0200, 0x1a90,
+ 0x0e4c, 0x2628, 0x3270, 0x0204, 0x1a94,
+ 0x0d4c, 0x2528, 0x3170, 0x0104, 0x1994,
+ 0x0c4c, 0x2428, 0x3070, 0x0004, 0x1894,
+ 0x0c50, 0x242c, 0x3074, 0x0008, 0x1898,
+ 0x0d50, 0x252c, 0x3174, 0x0108, 0x1998,
+ 0x0e50, 0x262c, 0x3274, 0x0208, 0x1a98,
+ 0x0e54, 0x2630, 0x3278, 0x020c, 0x1a9c,
+ 0x0d54, 0x2530, 0x3178, 0x010c, 0x199c,
+ 0x0c54, 0x2430, 0x3078, 0x000c, 0x189c,
+ 0x0c58, 0x2434, 0x307c, 0x0010, 0x18a0,
+ 0x0d58, 0x2534, 0x317c, 0x0110, 0x19a0,
+ 0x0e58, 0x2634, 0x327c, 0x0210, 0x1aa0,
+ 0x0e5c, 0x2638, 0x3280, 0x0214, 0x1aa4,
+ 0x0d5c, 0x2538, 0x3180, 0x0114, 0x19a4,
+ 0x0c5c, 0x2438, 0x3080, 0x0014, 0x18a4,
+ 0x0c60, 0x243c, 0x3084, 0x0018, 0x18a8,
+ 0x0d60, 0x253c, 0x3184, 0x0118, 0x19a8,
+ 0x0e60, 0x263c, 0x3284, 0x0218, 0x1aa8,
+ 0x0e64, 0x2640, 0x3288, 0x021c, 0x1aac,
+ 0x0d64, 0x2540, 0x3188, 0x011c, 0x19ac,
+ 0x0c64, 0x2440, 0x3088, 0x001c, 0x18ac,
+ 0x0c68, 0x2444, 0x308c, 0x0020, 0x18b0,
+ 0x0d68, 0x2544, 0x318c, 0x0120, 0x19b0,
+ 0x0e68, 0x2644, 0x328c, 0x0220, 0x1ab0,
+ 0x1248, 0x2a24, 0x366c, 0x0600, 0x1e90,
+ 0x1348, 0x2b24, 0x376c, 0x0700, 0x1f90,
+ 0x1448, 0x2c24, 0x386c, 0x0800, 0x2090,
+ 0x144c, 0x2c28, 0x3870, 0x0804, 0x2094,
+ 0x134c, 0x2b28, 0x3770, 0x0704, 0x1f94,
+ 0x124c, 0x2a28, 0x3670, 0x0604, 0x1e94,
+ 0x1250, 0x2a2c, 0x3674, 0x0608, 0x1e98,
+ 0x1350, 0x2b2c, 0x3774, 0x0708, 0x1f98,
+ 0x1450, 0x2c2c, 0x3874, 0x0808, 0x2098,
+ 0x1454, 0x2c30, 0x3878, 0x080c, 0x209c,
+ 0x1354, 0x2b30, 0x3778, 0x070c, 0x1f9c,
+ 0x1254, 0x2a30, 0x3678, 0x060c, 0x1e9c,
+ 0x1258, 0x2a34, 0x367c, 0x0610, 0x1ea0,
+ 0x1358, 0x2b34, 0x377c, 0x0710, 0x1fa0,
+ 0x1458, 0x2c34, 0x387c, 0x0810, 0x20a0,
+ 0x145c, 0x2c38, 0x3880, 0x0814, 0x20a4,
+ 0x135c, 0x2b38, 0x3780, 0x0714, 0x1fa4,
+ 0x125c, 0x2a38, 0x3680, 0x0614, 0x1ea4,
+ 0x1260, 0x2a3c, 0x3684, 0x0618, 0x1ea8,
+ 0x1360, 0x2b3c, 0x3784, 0x0718, 0x1fa8,
+ 0x1460, 0x2c3c, 0x3884, 0x0818, 0x20a8,
+ 0x1464, 0x2c40, 0x3888, 0x081c, 0x20ac,
+ 0x1364, 0x2b40, 0x3788, 0x071c, 0x1fac,
+ 0x1264, 0x2a40, 0x3688, 0x061c, 0x1eac,
+ 0x1268, 0x2a44, 0x368c, 0x0620, 0x1eb0,
+ 0x1368, 0x2b44, 0x378c, 0x0720, 0x1fb0,
+ 0x1468, 0x2c44, 0x388c, 0x0820, 0x20b0,
+ 0x1848, 0x3024, 0x3c6c, 0x0c00, 0x2490,
+ 0x1948, 0x3124, 0x3d6c, 0x0d00, 0x2590,
+ 0x1a48, 0x3224, 0x3e6c, 0x0e00, 0x2690,
+ 0x1a4c, 0x3228, 0x3e70, 0x0e04, 0x2694,
+ 0x194c, 0x3128, 0x3d70, 0x0d04, 0x2594,
+ 0x184c, 0x3028, 0x3c70, 0x0c04, 0x2494,
+ 0x1850, 0x302c, 0x3c74, 0x0c08, 0x2498,
+ 0x1950, 0x312c, 0x3d74, 0x0d08, 0x2598,
+ 0x1a50, 0x322c, 0x3e74, 0x0e08, 0x2698,
+ 0x1a54, 0x3230, 0x3e78, 0x0e0c, 0x269c,
+ 0x1954, 0x3130, 0x3d78, 0x0d0c, 0x259c,
+ 0x1854, 0x3030, 0x3c78, 0x0c0c, 0x249c,
+ 0x1858, 0x3034, 0x3c7c, 0x0c10, 0x24a0,
+ 0x1958, 0x3134, 0x3d7c, 0x0d10, 0x25a0,
+ 0x1a58, 0x3234, 0x3e7c, 0x0e10, 0x26a0,
+ 0x1a5c, 0x3238, 0x3e80, 0x0e14, 0x26a4,
+ 0x195c, 0x3138, 0x3d80, 0x0d14, 0x25a4,
+ 0x185c, 0x3038, 0x3c80, 0x0c14, 0x24a4,
+ 0x1860, 0x303c, 0x3c84, 0x0c18, 0x24a8,
+ 0x1960, 0x313c, 0x3d84, 0x0d18, 0x25a8,
+ 0x1a60, 0x323c, 0x3e84, 0x0e18, 0x26a8,
+ 0x1a64, 0x3240, 0x3e88, 0x0e1c, 0x26ac,
+ 0x1964, 0x3140, 0x3d88, 0x0d1c, 0x25ac,
+ 0x1864, 0x3040, 0x3c88, 0x0c1c, 0x24ac,
+ 0x1868, 0x3044, 0x3c8c, 0x0c20, 0x24b0,
+ 0x1968, 0x3144, 0x3d8c, 0x0d20, 0x25b0,
+ 0x1a68, 0x3244, 0x3e8c, 0x0e20, 0x26b0,
+ 0x1e48, 0x3624, 0x426c, 0x1200, 0x2a90,
+ 0x1f48, 0x3724, 0x436c, 0x1300, 0x2b90,
+ 0x2048, 0x3824, 0x446c, 0x1400, 0x2c90,
+ 0x204c, 0x3828, 0x4470, 0x1404, 0x2c94,
+ 0x1f4c, 0x3728, 0x4370, 0x1304, 0x2b94,
+ 0x1e4c, 0x3628, 0x4270, 0x1204, 0x2a94,
+ 0x1e50, 0x362c, 0x4274, 0x1208, 0x2a98,
+ 0x1f50, 0x372c, 0x4374, 0x1308, 0x2b98,
+ 0x2050, 0x382c, 0x4474, 0x1408, 0x2c98,
+ 0x2054, 0x3830, 0x4478, 0x140c, 0x2c9c,
+ 0x1f54, 0x3730, 0x4378, 0x130c, 0x2b9c,
+ 0x1e54, 0x3630, 0x4278, 0x120c, 0x2a9c,
+ 0x1e58, 0x3634, 0x427c, 0x1210, 0x2aa0,
+ 0x1f58, 0x3734, 0x437c, 0x1310, 0x2ba0,
+ 0x2058, 0x3834, 0x447c, 0x1410, 0x2ca0,
+ 0x205c, 0x3838, 0x4480, 0x1414, 0x2ca4,
+ 0x1f5c, 0x3738, 0x4380, 0x1314, 0x2ba4,
+ 0x1e5c, 0x3638, 0x4280, 0x1214, 0x2aa4,
+ 0x1e60, 0x363c, 0x4284, 0x1218, 0x2aa8,
+ 0x1f60, 0x373c, 0x4384, 0x1318, 0x2ba8,
+ 0x2060, 0x383c, 0x4484, 0x1418, 0x2ca8,
+ 0x2064, 0x3840, 0x4488, 0x141c, 0x2cac,
+ 0x1f64, 0x3740, 0x4388, 0x131c, 0x2bac,
+ 0x1e64, 0x3640, 0x4288, 0x121c, 0x2aac,
+ 0x1e68, 0x3644, 0x428c, 0x1220, 0x2ab0,
+ 0x1f68, 0x3744, 0x438c, 0x1320, 0x2bb0,
+ 0x2068, 0x3844, 0x448c, 0x1420, 0x2cb0,
+ 0x2448, 0x3c24, 0x006c, 0x1800, 0x3090,
+ 0x2548, 0x3d24, 0x016c, 0x1900, 0x3190,
+ 0x2648, 0x3e24, 0x026c, 0x1a00, 0x3290,
+ 0x264c, 0x3e28, 0x0270, 0x1a04, 0x3294,
+ 0x254c, 0x3d28, 0x0170, 0x1904, 0x3194,
+ 0x244c, 0x3c28, 0x0070, 0x1804, 0x3094,
+ 0x2450, 0x3c2c, 0x0074, 0x1808, 0x3098,
+ 0x2550, 0x3d2c, 0x0174, 0x1908, 0x3198,
+ 0x2650, 0x3e2c, 0x0274, 0x1a08, 0x3298,
+ 0x2654, 0x3e30, 0x0278, 0x1a0c, 0x329c,
+ 0x2554, 0x3d30, 0x0178, 0x190c, 0x319c,
+ 0x2454, 0x3c30, 0x0078, 0x180c, 0x309c,
+ 0x2458, 0x3c34, 0x007c, 0x1810, 0x30a0,
+ 0x2558, 0x3d34, 0x017c, 0x1910, 0x31a0,
+ 0x2658, 0x3e34, 0x027c, 0x1a10, 0x32a0,
+ 0x265c, 0x3e38, 0x0280, 0x1a14, 0x32a4,
+ 0x255c, 0x3d38, 0x0180, 0x1914, 0x31a4,
+ 0x245c, 0x3c38, 0x0080, 0x1814, 0x30a4,
+ 0x2460, 0x3c3c, 0x0084, 0x1818, 0x30a8,
+ 0x2560, 0x3d3c, 0x0184, 0x1918, 0x31a8,
+ 0x2660, 0x3e3c, 0x0284, 0x1a18, 0x32a8,
+ 0x2664, 0x3e40, 0x0288, 0x1a1c, 0x32ac,
+ 0x2564, 0x3d40, 0x0188, 0x191c, 0x31ac,
+ 0x2464, 0x3c40, 0x0088, 0x181c, 0x30ac,
+ 0x2468, 0x3c44, 0x008c, 0x1820, 0x30b0,
+ 0x2568, 0x3d44, 0x018c, 0x1920, 0x31b0,
+ 0x2668, 0x3e44, 0x028c, 0x1a20, 0x32b0,
+ 0x2a48, 0x4224, 0x066c, 0x1e00, 0x3690,
+ 0x2b48, 0x4324, 0x076c, 0x1f00, 0x3790,
+ 0x2c48, 0x4424, 0x086c, 0x2000, 0x3890,
+ 0x2c4c, 0x4428, 0x0870, 0x2004, 0x3894,
+ 0x2b4c, 0x4328, 0x0770, 0x1f04, 0x3794,
+ 0x2a4c, 0x4228, 0x0670, 0x1e04, 0x3694,
+ 0x2a50, 0x422c, 0x0674, 0x1e08, 0x3698,
+ 0x2b50, 0x432c, 0x0774, 0x1f08, 0x3798,
+ 0x2c50, 0x442c, 0x0874, 0x2008, 0x3898,
+ 0x2c54, 0x4430, 0x0878, 0x200c, 0x389c,
+ 0x2b54, 0x4330, 0x0778, 0x1f0c, 0x379c,
+ 0x2a54, 0x4230, 0x0678, 0x1e0c, 0x369c,
+ 0x2a58, 0x4234, 0x067c, 0x1e10, 0x36a0,
+ 0x2b58, 0x4334, 0x077c, 0x1f10, 0x37a0,
+ 0x2c58, 0x4434, 0x087c, 0x2010, 0x38a0,
+ 0x2c5c, 0x4438, 0x0880, 0x2014, 0x38a4,
+ 0x2b5c, 0x4338, 0x0780, 0x1f14, 0x37a4,
+ 0x2a5c, 0x4238, 0x0680, 0x1e14, 0x36a4,
+ 0x2a60, 0x423c, 0x0684, 0x1e18, 0x36a8,
+ 0x2b60, 0x433c, 0x0784, 0x1f18, 0x37a8,
+ 0x2c60, 0x443c, 0x0884, 0x2018, 0x38a8,
+ 0x2c64, 0x4440, 0x0888, 0x201c, 0x38ac,
+ 0x2b64, 0x4340, 0x0788, 0x1f1c, 0x37ac,
+ 0x2a64, 0x4240, 0x0688, 0x1e1c, 0x36ac,
+ 0x2a68, 0x4244, 0x068c, 0x1e20, 0x36b0,
+ 0x2b68, 0x4344, 0x078c, 0x1f20, 0x37b0,
+ 0x2c68, 0x4444, 0x088c, 0x2020, 0x38b0,
+ 0x3048, 0x0024, 0x0c6c, 0x2400, 0x3c90,
+ 0x3148, 0x0124, 0x0d6c, 0x2500, 0x3d90,
+ 0x3248, 0x0224, 0x0e6c, 0x2600, 0x3e90,
+ 0x324c, 0x0228, 0x0e70, 0x2604, 0x3e94,
+ 0x314c, 0x0128, 0x0d70, 0x2504, 0x3d94,
+ 0x304c, 0x0028, 0x0c70, 0x2404, 0x3c94,
+ 0x3050, 0x002c, 0x0c74, 0x2408, 0x3c98,
+ 0x3150, 0x012c, 0x0d74, 0x2508, 0x3d98,
+ 0x3250, 0x022c, 0x0e74, 0x2608, 0x3e98,
+ 0x3254, 0x0230, 0x0e78, 0x260c, 0x3e9c,
+ 0x3154, 0x0130, 0x0d78, 0x250c, 0x3d9c,
+ 0x3054, 0x0030, 0x0c78, 0x240c, 0x3c9c,
+ 0x3058, 0x0034, 0x0c7c, 0x2410, 0x3ca0,
+ 0x3158, 0x0134, 0x0d7c, 0x2510, 0x3da0,
+ 0x3258, 0x0234, 0x0e7c, 0x2610, 0x3ea0,
+ 0x325c, 0x0238, 0x0e80, 0x2614, 0x3ea4,
+ 0x315c, 0x0138, 0x0d80, 0x2514, 0x3da4,
+ 0x305c, 0x0038, 0x0c80, 0x2414, 0x3ca4,
+ 0x3060, 0x003c, 0x0c84, 0x2418, 0x3ca8,
+ 0x3160, 0x013c, 0x0d84, 0x2518, 0x3da8,
+ 0x3260, 0x023c, 0x0e84, 0x2618, 0x3ea8,
+ 0x3264, 0x0240, 0x0e88, 0x261c, 0x3eac,
+ 0x3164, 0x0140, 0x0d88, 0x251c, 0x3dac,
+ 0x3064, 0x0040, 0x0c88, 0x241c, 0x3cac,
+ 0x3068, 0x0044, 0x0c8c, 0x2420, 0x3cb0,
+ 0x3168, 0x0144, 0x0d8c, 0x2520, 0x3db0,
+ 0x3268, 0x0244, 0x0e8c, 0x2620, 0x3eb0,
+ 0x3648, 0x0624, 0x126c, 0x2a00, 0x4290,
+ 0x3748, 0x0724, 0x136c, 0x2b00, 0x4390,
+ 0x3848, 0x0824, 0x146c, 0x2c00, 0x4490,
+ 0x384c, 0x0828, 0x1470, 0x2c04, 0x4494,
+ 0x374c, 0x0728, 0x1370, 0x2b04, 0x4394,
+ 0x364c, 0x0628, 0x1270, 0x2a04, 0x4294,
+ 0x3650, 0x062c, 0x1274, 0x2a08, 0x4298,
+ 0x3750, 0x072c, 0x1374, 0x2b08, 0x4398,
+ 0x3850, 0x082c, 0x1474, 0x2c08, 0x4498,
+ 0x3854, 0x0830, 0x1478, 0x2c0c, 0x449c,
+ 0x3754, 0x0730, 0x1378, 0x2b0c, 0x439c,
+ 0x3654, 0x0630, 0x1278, 0x2a0c, 0x429c,
+ 0x3658, 0x0634, 0x127c, 0x2a10, 0x42a0,
+ 0x3758, 0x0734, 0x137c, 0x2b10, 0x43a0,
+ 0x3858, 0x0834, 0x147c, 0x2c10, 0x44a0,
+ 0x385c, 0x0838, 0x1480, 0x2c14, 0x44a4,
+ 0x375c, 0x0738, 0x1380, 0x2b14, 0x43a4,
+ 0x365c, 0x0638, 0x1280, 0x2a14, 0x42a4,
+ 0x3660, 0x063c, 0x1284, 0x2a18, 0x42a8,
+ 0x3760, 0x073c, 0x1384, 0x2b18, 0x43a8,
+ 0x3860, 0x083c, 0x1484, 0x2c18, 0x44a8,
+ 0x3864, 0x0840, 0x1488, 0x2c1c, 0x44ac,
+ 0x3764, 0x0740, 0x1388, 0x2b1c, 0x43ac,
+ 0x3664, 0x0640, 0x1288, 0x2a1c, 0x42ac,
+ 0x3668, 0x0644, 0x128c, 0x2a20, 0x42b0,
+ 0x3768, 0x0744, 0x138c, 0x2b20, 0x43b0,
+ 0x3868, 0x0844, 0x148c, 0x2c20, 0x44b0,
+ 0x3c48, 0x0c24, 0x186c, 0x3000, 0x0090,
+ 0x3d48, 0x0d24, 0x196c, 0x3100, 0x0190,
+ 0x3e48, 0x0e24, 0x1a6c, 0x3200, 0x0290,
+ 0x3e4c, 0x0e28, 0x1a70, 0x3204, 0x0294,
+ 0x3d4c, 0x0d28, 0x1970, 0x3104, 0x0194,
+ 0x3c4c, 0x0c28, 0x1870, 0x3004, 0x0094,
+ 0x3c50, 0x0c2c, 0x1874, 0x3008, 0x0098,
+ 0x3d50, 0x0d2c, 0x1974, 0x3108, 0x0198,
+ 0x3e50, 0x0e2c, 0x1a74, 0x3208, 0x0298,
+ 0x3e54, 0x0e30, 0x1a78, 0x320c, 0x029c,
+ 0x3d54, 0x0d30, 0x1978, 0x310c, 0x019c,
+ 0x3c54, 0x0c30, 0x1878, 0x300c, 0x009c,
+ 0x3c58, 0x0c34, 0x187c, 0x3010, 0x00a0,
+ 0x3d58, 0x0d34, 0x197c, 0x3110, 0x01a0,
+ 0x3e58, 0x0e34, 0x1a7c, 0x3210, 0x02a0,
+ 0x3e5c, 0x0e38, 0x1a80, 0x3214, 0x02a4,
+ 0x3d5c, 0x0d38, 0x1980, 0x3114, 0x01a4,
+ 0x3c5c, 0x0c38, 0x1880, 0x3014, 0x00a4,
+ 0x3c60, 0x0c3c, 0x1884, 0x3018, 0x00a8,
+ 0x3d60, 0x0d3c, 0x1984, 0x3118, 0x01a8,
+ 0x3e60, 0x0e3c, 0x1a84, 0x3218, 0x02a8,
+ 0x3e64, 0x0e40, 0x1a88, 0x321c, 0x02ac,
+ 0x3d64, 0x0d40, 0x1988, 0x311c, 0x01ac,
+ 0x3c64, 0x0c40, 0x1888, 0x301c, 0x00ac,
+ 0x3c68, 0x0c44, 0x188c, 0x3020, 0x00b0,
+ 0x3d68, 0x0d44, 0x198c, 0x3120, 0x01b0,
+ 0x3e68, 0x0e44, 0x1a8c, 0x3220, 0x02b0,
+ 0x4248, 0x1224, 0x1e6c, 0x3600, 0x0690,
+ 0x4348, 0x1324, 0x1f6c, 0x3700, 0x0790,
+ 0x4448, 0x1424, 0x206c, 0x3800, 0x0890,
+ 0x444c, 0x1428, 0x2070, 0x3804, 0x0894,
+ 0x434c, 0x1328, 0x1f70, 0x3704, 0x0794,
+ 0x424c, 0x1228, 0x1e70, 0x3604, 0x0694,
+ 0x4250, 0x122c, 0x1e74, 0x3608, 0x0698,
+ 0x4350, 0x132c, 0x1f74, 0x3708, 0x0798,
+ 0x4450, 0x142c, 0x2074, 0x3808, 0x0898,
+ 0x4454, 0x1430, 0x2078, 0x380c, 0x089c,
+ 0x4354, 0x1330, 0x1f78, 0x370c, 0x079c,
+ 0x4254, 0x1230, 0x1e78, 0x360c, 0x069c,
+ 0x4258, 0x1234, 0x1e7c, 0x3610, 0x06a0,
+ 0x4358, 0x1334, 0x1f7c, 0x3710, 0x07a0,
+ 0x4458, 0x1434, 0x207c, 0x3810, 0x08a0,
+ 0x445c, 0x1438, 0x2080, 0x3814, 0x08a4,
+ 0x435c, 0x1338, 0x1f80, 0x3714, 0x07a4,
+ 0x425c, 0x1238, 0x1e80, 0x3614, 0x06a4,
+ 0x4260, 0x123c, 0x1e84, 0x3618, 0x06a8,
+ 0x4360, 0x133c, 0x1f84, 0x3718, 0x07a8,
+ 0x4460, 0x143c, 0x2084, 0x3818, 0x08a8,
+ 0x4464, 0x1440, 0x2088, 0x381c, 0x08ac,
+ 0x4364, 0x1340, 0x1f88, 0x371c, 0x07ac,
+ 0x4264, 0x1240, 0x1e88, 0x361c, 0x06ac,
+ 0x4268, 0x1244, 0x1e8c, 0x3620, 0x06b0,
+ 0x4368, 0x1344, 0x1f8c, 0x3720, 0x07b0,
+ 0x4468, 0x1444, 0x208c, 0x3820, 0x08b0,
+ 0x0048, 0x1824, 0x246c, 0x3c00, 0x0c90,
+ 0x0148, 0x1924, 0x256c, 0x3d00, 0x0d90,
+ 0x0248, 0x1a24, 0x266c, 0x3e00, 0x0e90,
+ 0x024c, 0x1a28, 0x2670, 0x3e04, 0x0e94,
+ 0x014c, 0x1928, 0x2570, 0x3d04, 0x0d94,
+ 0x004c, 0x1828, 0x2470, 0x3c04, 0x0c94,
+ 0x0050, 0x182c, 0x2474, 0x3c08, 0x0c98,
+ 0x0150, 0x192c, 0x2574, 0x3d08, 0x0d98,
+ 0x0250, 0x1a2c, 0x2674, 0x3e08, 0x0e98,
+ 0x0254, 0x1a30, 0x2678, 0x3e0c, 0x0e9c,
+ 0x0154, 0x1930, 0x2578, 0x3d0c, 0x0d9c,
+ 0x0054, 0x1830, 0x2478, 0x3c0c, 0x0c9c,
+ 0x0058, 0x1834, 0x247c, 0x3c10, 0x0ca0,
+ 0x0158, 0x1934, 0x257c, 0x3d10, 0x0da0,
+ 0x0258, 0x1a34, 0x267c, 0x3e10, 0x0ea0,
+ 0x025c, 0x1a38, 0x2680, 0x3e14, 0x0ea4,
+ 0x015c, 0x1938, 0x2580, 0x3d14, 0x0da4,
+ 0x005c, 0x1838, 0x2480, 0x3c14, 0x0ca4,
+ 0x0060, 0x183c, 0x2484, 0x3c18, 0x0ca8,
+ 0x0160, 0x193c, 0x2584, 0x3d18, 0x0da8,
+ 0x0260, 0x1a3c, 0x2684, 0x3e18, 0x0ea8,
+ 0x0264, 0x1a40, 0x2688, 0x3e1c, 0x0eac,
+ 0x0164, 0x1940, 0x2588, 0x3d1c, 0x0dac,
+ 0x0064, 0x1840, 0x2488, 0x3c1c, 0x0cac,
+ 0x0068, 0x1844, 0x248c, 0x3c20, 0x0cb0,
+ 0x0168, 0x1944, 0x258c, 0x3d20, 0x0db0,
+ 0x0268, 0x1a44, 0x268c, 0x3e20, 0x0eb0,
+ 0x0648, 0x1e24, 0x2a6c, 0x4200, 0x1290,
+ 0x0748, 0x1f24, 0x2b6c, 0x4300, 0x1390,
+ 0x0848, 0x2024, 0x2c6c, 0x4400, 0x1490,
+ 0x084c, 0x2028, 0x2c70, 0x4404, 0x1494,
+ 0x074c, 0x1f28, 0x2b70, 0x4304, 0x1394,
+ 0x064c, 0x1e28, 0x2a70, 0x4204, 0x1294,
+ 0x0650, 0x1e2c, 0x2a74, 0x4208, 0x1298,
+ 0x0750, 0x1f2c, 0x2b74, 0x4308, 0x1398,
+ 0x0850, 0x202c, 0x2c74, 0x4408, 0x1498,
+ 0x0854, 0x2030, 0x2c78, 0x440c, 0x149c,
+ 0x0754, 0x1f30, 0x2b78, 0x430c, 0x139c,
+ 0x0654, 0x1e30, 0x2a78, 0x420c, 0x129c,
+ 0x0658, 0x1e34, 0x2a7c, 0x4210, 0x12a0,
+ 0x0758, 0x1f34, 0x2b7c, 0x4310, 0x13a0,
+ 0x0858, 0x2034, 0x2c7c, 0x4410, 0x14a0,
+ 0x085c, 0x2038, 0x2c80, 0x4414, 0x14a4,
+ 0x075c, 0x1f38, 0x2b80, 0x4314, 0x13a4,
+ 0x065c, 0x1e38, 0x2a80, 0x4214, 0x12a4,
+ 0x0660, 0x1e3c, 0x2a84, 0x4218, 0x12a8,
+ 0x0760, 0x1f3c, 0x2b84, 0x4318, 0x13a8,
+ 0x0860, 0x203c, 0x2c84, 0x4418, 0x14a8,
+ 0x0864, 0x2040, 0x2c88, 0x441c, 0x14ac,
+ 0x0764, 0x1f40, 0x2b88, 0x431c, 0x13ac,
+ 0x0664, 0x1e40, 0x2a88, 0x421c, 0x12ac,
+ 0x0668, 0x1e44, 0x2a8c, 0x4220, 0x12b0,
+ 0x0768, 0x1f44, 0x2b8c, 0x4320, 0x13b0,
+ 0x0868, 0x2044, 0x2c8c, 0x4420, 0x14b0,
+ 0x0f48, 0x2724, 0x336c, 0x0300, 0x1b90,
+ 0x1048, 0x2824, 0x346c, 0x0400, 0x1c90,
+ 0x1148, 0x2924, 0x356c, 0x0500, 0x1d90,
+ 0x114c, 0x2928, 0x3570, 0x0504, 0x1d94,
+ 0x104c, 0x2828, 0x3470, 0x0404, 0x1c94,
+ 0x0f4c, 0x2728, 0x3370, 0x0304, 0x1b94,
+ 0x0f50, 0x272c, 0x3374, 0x0308, 0x1b98,
+ 0x1050, 0x282c, 0x3474, 0x0408, 0x1c98,
+ 0x1150, 0x292c, 0x3574, 0x0508, 0x1d98,
+ 0x1154, 0x2930, 0x3578, 0x050c, 0x1d9c,
+ 0x1054, 0x2830, 0x3478, 0x040c, 0x1c9c,
+ 0x0f54, 0x2730, 0x3378, 0x030c, 0x1b9c,
+ 0x0f58, 0x2734, 0x337c, 0x0310, 0x1ba0,
+ 0x1058, 0x2834, 0x347c, 0x0410, 0x1ca0,
+ 0x1158, 0x2934, 0x357c, 0x0510, 0x1da0,
+ 0x115c, 0x2938, 0x3580, 0x0514, 0x1da4,
+ 0x105c, 0x2838, 0x3480, 0x0414, 0x1ca4,
+ 0x0f5c, 0x2738, 0x3380, 0x0314, 0x1ba4,
+ 0x0f60, 0x273c, 0x3384, 0x0318, 0x1ba8,
+ 0x1060, 0x283c, 0x3484, 0x0418, 0x1ca8,
+ 0x1160, 0x293c, 0x3584, 0x0518, 0x1da8,
+ 0x1164, 0x2940, 0x3588, 0x051c, 0x1dac,
+ 0x1064, 0x2840, 0x3488, 0x041c, 0x1cac,
+ 0x0f64, 0x2740, 0x3388, 0x031c, 0x1bac,
+ 0x0f68, 0x2744, 0x338c, 0x0320, 0x1bb0,
+ 0x1068, 0x2844, 0x348c, 0x0420, 0x1cb0,
+ 0x1168, 0x2944, 0x358c, 0x0520, 0x1db0,
+ 0x1548, 0x2d24, 0x396c, 0x0900, 0x2190,
+ 0x1648, 0x2e24, 0x3a6c, 0x0a00, 0x2290,
+ 0x1748, 0x2f24, 0x3b6c, 0x0b00, 0x2390,
+ 0x174c, 0x2f28, 0x3b70, 0x0b04, 0x2394,
+ 0x164c, 0x2e28, 0x3a70, 0x0a04, 0x2294,
+ 0x154c, 0x2d28, 0x3970, 0x0904, 0x2194,
+ 0x1550, 0x2d2c, 0x3974, 0x0908, 0x2198,
+ 0x1650, 0x2e2c, 0x3a74, 0x0a08, 0x2298,
+ 0x1750, 0x2f2c, 0x3b74, 0x0b08, 0x2398,
+ 0x1754, 0x2f30, 0x3b78, 0x0b0c, 0x239c,
+ 0x1654, 0x2e30, 0x3a78, 0x0a0c, 0x229c,
+ 0x1554, 0x2d30, 0x3978, 0x090c, 0x219c,
+ 0x1558, 0x2d34, 0x397c, 0x0910, 0x21a0,
+ 0x1658, 0x2e34, 0x3a7c, 0x0a10, 0x22a0,
+ 0x1758, 0x2f34, 0x3b7c, 0x0b10, 0x23a0,
+ 0x175c, 0x2f38, 0x3b80, 0x0b14, 0x23a4,
+ 0x165c, 0x2e38, 0x3a80, 0x0a14, 0x22a4,
+ 0x155c, 0x2d38, 0x3980, 0x0914, 0x21a4,
+ 0x1560, 0x2d3c, 0x3984, 0x0918, 0x21a8,
+ 0x1660, 0x2e3c, 0x3a84, 0x0a18, 0x22a8,
+ 0x1760, 0x2f3c, 0x3b84, 0x0b18, 0x23a8,
+ 0x1764, 0x2f40, 0x3b88, 0x0b1c, 0x23ac,
+ 0x1664, 0x2e40, 0x3a88, 0x0a1c, 0x22ac,
+ 0x1564, 0x2d40, 0x3988, 0x091c, 0x21ac,
+ 0x1568, 0x2d44, 0x398c, 0x0920, 0x21b0,
+ 0x1668, 0x2e44, 0x3a8c, 0x0a20, 0x22b0,
+ 0x1768, 0x2f44, 0x3b8c, 0x0b20, 0x23b0,
+ 0x1b48, 0x3324, 0x3f6c, 0x0f00, 0x2790,
+ 0x1c48, 0x3424, 0x406c, 0x1000, 0x2890,
+ 0x1d48, 0x3524, 0x416c, 0x1100, 0x2990,
+ 0x1d4c, 0x3528, 0x4170, 0x1104, 0x2994,
+ 0x1c4c, 0x3428, 0x4070, 0x1004, 0x2894,
+ 0x1b4c, 0x3328, 0x3f70, 0x0f04, 0x2794,
+ 0x1b50, 0x332c, 0x3f74, 0x0f08, 0x2798,
+ 0x1c50, 0x342c, 0x4074, 0x1008, 0x2898,
+ 0x1d50, 0x352c, 0x4174, 0x1108, 0x2998,
+ 0x1d54, 0x3530, 0x4178, 0x110c, 0x299c,
+ 0x1c54, 0x3430, 0x4078, 0x100c, 0x289c,
+ 0x1b54, 0x3330, 0x3f78, 0x0f0c, 0x279c,
+ 0x1b58, 0x3334, 0x3f7c, 0x0f10, 0x27a0,
+ 0x1c58, 0x3434, 0x407c, 0x1010, 0x28a0,
+ 0x1d58, 0x3534, 0x417c, 0x1110, 0x29a0,
+ 0x1d5c, 0x3538, 0x4180, 0x1114, 0x29a4,
+ 0x1c5c, 0x3438, 0x4080, 0x1014, 0x28a4,
+ 0x1b5c, 0x3338, 0x3f80, 0x0f14, 0x27a4,
+ 0x1b60, 0x333c, 0x3f84, 0x0f18, 0x27a8,
+ 0x1c60, 0x343c, 0x4084, 0x1018, 0x28a8,
+ 0x1d60, 0x353c, 0x4184, 0x1118, 0x29a8,
+ 0x1d64, 0x3540, 0x4188, 0x111c, 0x29ac,
+ 0x1c64, 0x3440, 0x4088, 0x101c, 0x28ac,
+ 0x1b64, 0x3340, 0x3f88, 0x0f1c, 0x27ac,
+ 0x1b68, 0x3344, 0x3f8c, 0x0f20, 0x27b0,
+ 0x1c68, 0x3444, 0x408c, 0x1020, 0x28b0,
+ 0x1d68, 0x3544, 0x418c, 0x1120, 0x29b0,
+ 0x2148, 0x3924, 0x456c, 0x1500, 0x2d90,
+ 0x2248, 0x3a24, 0x466c, 0x1600, 0x2e90,
+ 0x2348, 0x3b24, 0x476c, 0x1700, 0x2f90,
+ 0x234c, 0x3b28, 0x4770, 0x1704, 0x2f94,
+ 0x224c, 0x3a28, 0x4670, 0x1604, 0x2e94,
+ 0x214c, 0x3928, 0x4570, 0x1504, 0x2d94,
+ 0x2150, 0x392c, 0x4574, 0x1508, 0x2d98,
+ 0x2250, 0x3a2c, 0x4674, 0x1608, 0x2e98,
+ 0x2350, 0x3b2c, 0x4774, 0x1708, 0x2f98,
+ 0x2354, 0x3b30, 0x4778, 0x170c, 0x2f9c,
+ 0x2254, 0x3a30, 0x4678, 0x160c, 0x2e9c,
+ 0x2154, 0x3930, 0x4578, 0x150c, 0x2d9c,
+ 0x2158, 0x3934, 0x457c, 0x1510, 0x2da0,
+ 0x2258, 0x3a34, 0x467c, 0x1610, 0x2ea0,
+ 0x2358, 0x3b34, 0x477c, 0x1710, 0x2fa0,
+ 0x235c, 0x3b38, 0x4780, 0x1714, 0x2fa4,
+ 0x225c, 0x3a38, 0x4680, 0x1614, 0x2ea4,
+ 0x215c, 0x3938, 0x4580, 0x1514, 0x2da4,
+ 0x2160, 0x393c, 0x4584, 0x1518, 0x2da8,
+ 0x2260, 0x3a3c, 0x4684, 0x1618, 0x2ea8,
+ 0x2360, 0x3b3c, 0x4784, 0x1718, 0x2fa8,
+ 0x2364, 0x3b40, 0x4788, 0x171c, 0x2fac,
+ 0x2264, 0x3a40, 0x4688, 0x161c, 0x2eac,
+ 0x2164, 0x3940, 0x4588, 0x151c, 0x2dac,
+ 0x2168, 0x3944, 0x458c, 0x1520, 0x2db0,
+ 0x2268, 0x3a44, 0x468c, 0x1620, 0x2eb0,
+ 0x2368, 0x3b44, 0x478c, 0x1720, 0x2fb0,
+ 0x2748, 0x3f24, 0x036c, 0x1b00, 0x3390,
+ 0x2848, 0x4024, 0x046c, 0x1c00, 0x3490,
+ 0x2948, 0x4124, 0x056c, 0x1d00, 0x3590,
+ 0x294c, 0x4128, 0x0570, 0x1d04, 0x3594,
+ 0x284c, 0x4028, 0x0470, 0x1c04, 0x3494,
+ 0x274c, 0x3f28, 0x0370, 0x1b04, 0x3394,
+ 0x2750, 0x3f2c, 0x0374, 0x1b08, 0x3398,
+ 0x2850, 0x402c, 0x0474, 0x1c08, 0x3498,
+ 0x2950, 0x412c, 0x0574, 0x1d08, 0x3598,
+ 0x2954, 0x4130, 0x0578, 0x1d0c, 0x359c,
+ 0x2854, 0x4030, 0x0478, 0x1c0c, 0x349c,
+ 0x2754, 0x3f30, 0x0378, 0x1b0c, 0x339c,
+ 0x2758, 0x3f34, 0x037c, 0x1b10, 0x33a0,
+ 0x2858, 0x4034, 0x047c, 0x1c10, 0x34a0,
+ 0x2958, 0x4134, 0x057c, 0x1d10, 0x35a0,
+ 0x295c, 0x4138, 0x0580, 0x1d14, 0x35a4,
+ 0x285c, 0x4038, 0x0480, 0x1c14, 0x34a4,
+ 0x275c, 0x3f38, 0x0380, 0x1b14, 0x33a4,
+ 0x2760, 0x3f3c, 0x0384, 0x1b18, 0x33a8,
+ 0x2860, 0x403c, 0x0484, 0x1c18, 0x34a8,
+ 0x2960, 0x413c, 0x0584, 0x1d18, 0x35a8,
+ 0x2964, 0x4140, 0x0588, 0x1d1c, 0x35ac,
+ 0x2864, 0x4040, 0x0488, 0x1c1c, 0x34ac,
+ 0x2764, 0x3f40, 0x0388, 0x1b1c, 0x33ac,
+ 0x2768, 0x3f44, 0x038c, 0x1b20, 0x33b0,
+ 0x2868, 0x4044, 0x048c, 0x1c20, 0x34b0,
+ 0x2968, 0x4144, 0x058c, 0x1d20, 0x35b0,
+ 0x2d48, 0x4524, 0x096c, 0x2100, 0x3990,
+ 0x2e48, 0x4624, 0x0a6c, 0x2200, 0x3a90,
+ 0x2f48, 0x4724, 0x0b6c, 0x2300, 0x3b90,
+ 0x2f4c, 0x4728, 0x0b70, 0x2304, 0x3b94,
+ 0x2e4c, 0x4628, 0x0a70, 0x2204, 0x3a94,
+ 0x2d4c, 0x4528, 0x0970, 0x2104, 0x3994,
+ 0x2d50, 0x452c, 0x0974, 0x2108, 0x3998,
+ 0x2e50, 0x462c, 0x0a74, 0x2208, 0x3a98,
+ 0x2f50, 0x472c, 0x0b74, 0x2308, 0x3b98,
+ 0x2f54, 0x4730, 0x0b78, 0x230c, 0x3b9c,
+ 0x2e54, 0x4630, 0x0a78, 0x220c, 0x3a9c,
+ 0x2d54, 0x4530, 0x0978, 0x210c, 0x399c,
+ 0x2d58, 0x4534, 0x097c, 0x2110, 0x39a0,
+ 0x2e58, 0x4634, 0x0a7c, 0x2210, 0x3aa0,
+ 0x2f58, 0x4734, 0x0b7c, 0x2310, 0x3ba0,
+ 0x2f5c, 0x4738, 0x0b80, 0x2314, 0x3ba4,
+ 0x2e5c, 0x4638, 0x0a80, 0x2214, 0x3aa4,
+ 0x2d5c, 0x4538, 0x0980, 0x2114, 0x39a4,
+ 0x2d60, 0x453c, 0x0984, 0x2118, 0x39a8,
+ 0x2e60, 0x463c, 0x0a84, 0x2218, 0x3aa8,
+ 0x2f60, 0x473c, 0x0b84, 0x2318, 0x3ba8,
+ 0x2f64, 0x4740, 0x0b88, 0x231c, 0x3bac,
+ 0x2e64, 0x4640, 0x0a88, 0x221c, 0x3aac,
+ 0x2d64, 0x4540, 0x0988, 0x211c, 0x39ac,
+ 0x2d68, 0x4544, 0x098c, 0x2120, 0x39b0,
+ 0x2e68, 0x4644, 0x0a8c, 0x2220, 0x3ab0,
+ 0x2f68, 0x4744, 0x0b8c, 0x2320, 0x3bb0,
+ 0x3348, 0x0324, 0x0f6c, 0x2700, 0x3f90,
+ 0x3448, 0x0424, 0x106c, 0x2800, 0x4090,
+ 0x3548, 0x0524, 0x116c, 0x2900, 0x4190,
+ 0x354c, 0x0528, 0x1170, 0x2904, 0x4194,
+ 0x344c, 0x0428, 0x1070, 0x2804, 0x4094,
+ 0x334c, 0x0328, 0x0f70, 0x2704, 0x3f94,
+ 0x3350, 0x032c, 0x0f74, 0x2708, 0x3f98,
+ 0x3450, 0x042c, 0x1074, 0x2808, 0x4098,
+ 0x3550, 0x052c, 0x1174, 0x2908, 0x4198,
+ 0x3554, 0x0530, 0x1178, 0x290c, 0x419c,
+ 0x3454, 0x0430, 0x1078, 0x280c, 0x409c,
+ 0x3354, 0x0330, 0x0f78, 0x270c, 0x3f9c,
+ 0x3358, 0x0334, 0x0f7c, 0x2710, 0x3fa0,
+ 0x3458, 0x0434, 0x107c, 0x2810, 0x40a0,
+ 0x3558, 0x0534, 0x117c, 0x2910, 0x41a0,
+ 0x355c, 0x0538, 0x1180, 0x2914, 0x41a4,
+ 0x345c, 0x0438, 0x1080, 0x2814, 0x40a4,
+ 0x335c, 0x0338, 0x0f80, 0x2714, 0x3fa4,
+ 0x3360, 0x033c, 0x0f84, 0x2718, 0x3fa8,
+ 0x3460, 0x043c, 0x1084, 0x2818, 0x40a8,
+ 0x3560, 0x053c, 0x1184, 0x2918, 0x41a8,
+ 0x3564, 0x0540, 0x1188, 0x291c, 0x41ac,
+ 0x3464, 0x0440, 0x1088, 0x281c, 0x40ac,
+ 0x3364, 0x0340, 0x0f88, 0x271c, 0x3fac,
+ 0x3368, 0x0344, 0x0f8c, 0x2720, 0x3fb0,
+ 0x3468, 0x0444, 0x108c, 0x2820, 0x40b0,
+ 0x3568, 0x0544, 0x118c, 0x2920, 0x41b0,
+ 0x3948, 0x0924, 0x156c, 0x2d00, 0x4590,
+ 0x3a48, 0x0a24, 0x166c, 0x2e00, 0x4690,
+ 0x3b48, 0x0b24, 0x176c, 0x2f00, 0x4790,
+ 0x3b4c, 0x0b28, 0x1770, 0x2f04, 0x4794,
+ 0x3a4c, 0x0a28, 0x1670, 0x2e04, 0x4694,
+ 0x394c, 0x0928, 0x1570, 0x2d04, 0x4594,
+ 0x3950, 0x092c, 0x1574, 0x2d08, 0x4598,
+ 0x3a50, 0x0a2c, 0x1674, 0x2e08, 0x4698,
+ 0x3b50, 0x0b2c, 0x1774, 0x2f08, 0x4798,
+ 0x3b54, 0x0b30, 0x1778, 0x2f0c, 0x479c,
+ 0x3a54, 0x0a30, 0x1678, 0x2e0c, 0x469c,
+ 0x3954, 0x0930, 0x1578, 0x2d0c, 0x459c,
+ 0x3958, 0x0934, 0x157c, 0x2d10, 0x45a0,
+ 0x3a58, 0x0a34, 0x167c, 0x2e10, 0x46a0,
+ 0x3b58, 0x0b34, 0x177c, 0x2f10, 0x47a0,
+ 0x3b5c, 0x0b38, 0x1780, 0x2f14, 0x47a4,
+ 0x3a5c, 0x0a38, 0x1680, 0x2e14, 0x46a4,
+ 0x395c, 0x0938, 0x1580, 0x2d14, 0x45a4,
+ 0x3960, 0x093c, 0x1584, 0x2d18, 0x45a8,
+ 0x3a60, 0x0a3c, 0x1684, 0x2e18, 0x46a8,
+ 0x3b60, 0x0b3c, 0x1784, 0x2f18, 0x47a8,
+ 0x3b64, 0x0b40, 0x1788, 0x2f1c, 0x47ac,
+ 0x3a64, 0x0a40, 0x1688, 0x2e1c, 0x46ac,
+ 0x3964, 0x0940, 0x1588, 0x2d1c, 0x45ac,
+ 0x3968, 0x0944, 0x158c, 0x2d20, 0x45b0,
+ 0x3a68, 0x0a44, 0x168c, 0x2e20, 0x46b0,
+ 0x3b68, 0x0b44, 0x178c, 0x2f20, 0x47b0,
+ 0x3f48, 0x0f24, 0x1b6c, 0x3300, 0x0390,
+ 0x4048, 0x1024, 0x1c6c, 0x3400, 0x0490,
+ 0x4148, 0x1124, 0x1d6c, 0x3500, 0x0590,
+ 0x414c, 0x1128, 0x1d70, 0x3504, 0x0594,
+ 0x404c, 0x1028, 0x1c70, 0x3404, 0x0494,
+ 0x3f4c, 0x0f28, 0x1b70, 0x3304, 0x0394,
+ 0x3f50, 0x0f2c, 0x1b74, 0x3308, 0x0398,
+ 0x4050, 0x102c, 0x1c74, 0x3408, 0x0498,
+ 0x4150, 0x112c, 0x1d74, 0x3508, 0x0598,
+ 0x4154, 0x1130, 0x1d78, 0x350c, 0x059c,
+ 0x4054, 0x1030, 0x1c78, 0x340c, 0x049c,
+ 0x3f54, 0x0f30, 0x1b78, 0x330c, 0x039c,
+ 0x3f58, 0x0f34, 0x1b7c, 0x3310, 0x03a0,
+ 0x4058, 0x1034, 0x1c7c, 0x3410, 0x04a0,
+ 0x4158, 0x1134, 0x1d7c, 0x3510, 0x05a0,
+ 0x415c, 0x1138, 0x1d80, 0x3514, 0x05a4,
+ 0x405c, 0x1038, 0x1c80, 0x3414, 0x04a4,
+ 0x3f5c, 0x0f38, 0x1b80, 0x3314, 0x03a4,
+ 0x3f60, 0x0f3c, 0x1b84, 0x3318, 0x03a8,
+ 0x4060, 0x103c, 0x1c84, 0x3418, 0x04a8,
+ 0x4160, 0x113c, 0x1d84, 0x3518, 0x05a8,
+ 0x4164, 0x1140, 0x1d88, 0x351c, 0x05ac,
+ 0x4064, 0x1040, 0x1c88, 0x341c, 0x04ac,
+ 0x3f64, 0x0f40, 0x1b88, 0x331c, 0x03ac,
+ 0x3f68, 0x0f44, 0x1b8c, 0x3320, 0x03b0,
+ 0x4068, 0x1044, 0x1c8c, 0x3420, 0x04b0,
+ 0x4168, 0x1144, 0x1d8c, 0x3520, 0x05b0,
+ 0x4548, 0x1524, 0x216c, 0x3900, 0x0990,
+ 0x4648, 0x1624, 0x226c, 0x3a00, 0x0a90,
+ 0x4748, 0x1724, 0x236c, 0x3b00, 0x0b90,
+ 0x474c, 0x1728, 0x2370, 0x3b04, 0x0b94,
+ 0x464c, 0x1628, 0x2270, 0x3a04, 0x0a94,
+ 0x454c, 0x1528, 0x2170, 0x3904, 0x0994,
+ 0x4550, 0x152c, 0x2174, 0x3908, 0x0998,
+ 0x4650, 0x162c, 0x2274, 0x3a08, 0x0a98,
+ 0x4750, 0x172c, 0x2374, 0x3b08, 0x0b98,
+ 0x4754, 0x1730, 0x2378, 0x3b0c, 0x0b9c,
+ 0x4654, 0x1630, 0x2278, 0x3a0c, 0x0a9c,
+ 0x4554, 0x1530, 0x2178, 0x390c, 0x099c,
+ 0x4558, 0x1534, 0x217c, 0x3910, 0x09a0,
+ 0x4658, 0x1634, 0x227c, 0x3a10, 0x0aa0,
+ 0x4758, 0x1734, 0x237c, 0x3b10, 0x0ba0,
+ 0x475c, 0x1738, 0x2380, 0x3b14, 0x0ba4,
+ 0x465c, 0x1638, 0x2280, 0x3a14, 0x0aa4,
+ 0x455c, 0x1538, 0x2180, 0x3914, 0x09a4,
+ 0x4560, 0x153c, 0x2184, 0x3918, 0x09a8,
+ 0x4660, 0x163c, 0x2284, 0x3a18, 0x0aa8,
+ 0x4760, 0x173c, 0x2384, 0x3b18, 0x0ba8,
+ 0x4764, 0x1740, 0x2388, 0x3b1c, 0x0bac,
+ 0x4664, 0x1640, 0x2288, 0x3a1c, 0x0aac,
+ 0x4564, 0x1540, 0x2188, 0x391c, 0x09ac,
+ 0x4568, 0x1544, 0x218c, 0x3920, 0x09b0,
+ 0x4668, 0x1644, 0x228c, 0x3a20, 0x0ab0,
+ 0x4768, 0x1744, 0x238c, 0x3b20, 0x0bb0,
+ 0x0348, 0x1b24, 0x276c, 0x3f00, 0x0f90,
+ 0x0448, 0x1c24, 0x286c, 0x4000, 0x1090,
+ 0x0548, 0x1d24, 0x296c, 0x4100, 0x1190,
+ 0x054c, 0x1d28, 0x2970, 0x4104, 0x1194,
+ 0x044c, 0x1c28, 0x2870, 0x4004, 0x1094,
+ 0x034c, 0x1b28, 0x2770, 0x3f04, 0x0f94,
+ 0x0350, 0x1b2c, 0x2774, 0x3f08, 0x0f98,
+ 0x0450, 0x1c2c, 0x2874, 0x4008, 0x1098,
+ 0x0550, 0x1d2c, 0x2974, 0x4108, 0x1198,
+ 0x0554, 0x1d30, 0x2978, 0x410c, 0x119c,
+ 0x0454, 0x1c30, 0x2878, 0x400c, 0x109c,
+ 0x0354, 0x1b30, 0x2778, 0x3f0c, 0x0f9c,
+ 0x0358, 0x1b34, 0x277c, 0x3f10, 0x0fa0,
+ 0x0458, 0x1c34, 0x287c, 0x4010, 0x10a0,
+ 0x0558, 0x1d34, 0x297c, 0x4110, 0x11a0,
+ 0x055c, 0x1d38, 0x2980, 0x4114, 0x11a4,
+ 0x045c, 0x1c38, 0x2880, 0x4014, 0x10a4,
+ 0x035c, 0x1b38, 0x2780, 0x3f14, 0x0fa4,
+ 0x0360, 0x1b3c, 0x2784, 0x3f18, 0x0fa8,
+ 0x0460, 0x1c3c, 0x2884, 0x4018, 0x10a8,
+ 0x0560, 0x1d3c, 0x2984, 0x4118, 0x11a8,
+ 0x0564, 0x1d40, 0x2988, 0x411c, 0x11ac,
+ 0x0464, 0x1c40, 0x2888, 0x401c, 0x10ac,
+ 0x0364, 0x1b40, 0x2788, 0x3f1c, 0x0fac,
+ 0x0368, 0x1b44, 0x278c, 0x3f20, 0x0fb0,
+ 0x0468, 0x1c44, 0x288c, 0x4020, 0x10b0,
+ 0x0568, 0x1d44, 0x298c, 0x4120, 0x11b0,
+ 0x0948, 0x2124, 0x2d6c, 0x4500, 0x1590,
+ 0x0a48, 0x2224, 0x2e6c, 0x4600, 0x1690,
+ 0x0b48, 0x2324, 0x2f6c, 0x4700, 0x1790,
+ 0x0b4c, 0x2328, 0x2f70, 0x4704, 0x1794,
+ 0x0a4c, 0x2228, 0x2e70, 0x4604, 0x1694,
+ 0x094c, 0x2128, 0x2d70, 0x4504, 0x1594,
+ 0x0950, 0x212c, 0x2d74, 0x4508, 0x1598,
+ 0x0a50, 0x222c, 0x2e74, 0x4608, 0x1698,
+ 0x0b50, 0x232c, 0x2f74, 0x4708, 0x1798,
+ 0x0b54, 0x2330, 0x2f78, 0x470c, 0x179c,
+ 0x0a54, 0x2230, 0x2e78, 0x460c, 0x169c,
+ 0x0954, 0x2130, 0x2d78, 0x450c, 0x159c,
+ 0x0958, 0x2134, 0x2d7c, 0x4510, 0x15a0,
+ 0x0a58, 0x2234, 0x2e7c, 0x4610, 0x16a0,
+ 0x0b58, 0x2334, 0x2f7c, 0x4710, 0x17a0,
+ 0x0b5c, 0x2338, 0x2f80, 0x4714, 0x17a4,
+ 0x0a5c, 0x2238, 0x2e80, 0x4614, 0x16a4,
+ 0x095c, 0x2138, 0x2d80, 0x4514, 0x15a4,
+ 0x0960, 0x213c, 0x2d84, 0x4518, 0x15a8,
+ 0x0a60, 0x223c, 0x2e84, 0x4618, 0x16a8,
+ 0x0b60, 0x233c, 0x2f84, 0x4718, 0x17a8,
+ 0x0b64, 0x2340, 0x2f88, 0x471c, 0x17ac,
+ 0x0a64, 0x2240, 0x2e88, 0x461c, 0x16ac,
+ 0x0964, 0x2140, 0x2d88, 0x451c, 0x15ac,
+ 0x0968, 0x2144, 0x2d8c, 0x4520, 0x15b0,
+ 0x0a68, 0x2244, 0x2e8c, 0x4620, 0x16b0,
+ 0x0b68, 0x2344, 0x2f8c, 0x4720, 0x17b0,
+};
+
+/* DV25/50 DCT coefficient weights and inverse weights */
+/* created by dvtables.py */
+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 const int dv_iweight_bits = 14;
+static const int 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,
+};
+static const int 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,
+};
+
+static const uint16_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 uint16_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},
+};
+
+static const __attribute__((unused)) int dv_audio_frequency[3] = {
+ 48000, 44100, 32000,
+};
+
+static const DVprofile dv_profiles[] = {
+ { .dsf = 0,
+ .frame_size = 120000, /* IEC 61834, SMPTE-314M - 525/60 (NTSC) */
+ .difseg_size = 10,
+ .n_difchan = 1,
+ .frame_rate = 30000,
+ .ltc_divisor = 30,
+ .frame_rate_base = 1001,
+ .height = 480,
+ .width = 720,
+ .sar = {{10, 11}, {40, 33}},
+ .video_place = dv_place_411,
+ .pix_fmt = PIX_FMT_YUV411P,
+ .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,
+ .frame_size = 144000, /* IEC 61834 - 625/50 (PAL) */
+ .difseg_size = 12,
+ .n_difchan = 1,
+ .frame_rate = 25,
+ .frame_rate_base = 1,
+ .ltc_divisor = 25,
+ .height = 576,
+ .width = 720,
+ .sar = {{59, 54}, {118, 81}},
+ .video_place = dv_place_420,
+ .pix_fmt = PIX_FMT_YUV420P,
+ .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,
+ .frame_size = 144000, /* SMPTE-314M - 625/50 (PAL) */
+ .difseg_size = 12,
+ .n_difchan = 1,
+ .frame_rate = 25,
+ .frame_rate_base = 1,
+ .ltc_divisor = 25,
+ .height = 576,
+ .width = 720,
+ .sar = {{59, 54}, {118, 81}},
+ .video_place = dv_place_411P,
+ .pix_fmt = PIX_FMT_YUV411P,
+ .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,
+ .frame_size = 240000, /* SMPTE-314M - 525/60 (NTSC) 50 Mbps */
+ .difseg_size = 10, /* also known as "DVCPRO50" */
+ .n_difchan = 2,
+ .frame_rate = 30000,
+ .ltc_divisor = 30,
+ .frame_rate_base = 1001,
+ .height = 480,
+ .width = 720,
+ .sar = {{10, 11}, {40, 33}},
+ .video_place = dv_place_422_525,
+ .pix_fmt = PIX_FMT_YUV422P,
+ .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,
+ .frame_size = 288000, /* SMPTE-314M - 625/50 (PAL) 50 Mbps */
+ .difseg_size = 12, /* also known as "DVCPRO50" */
+ .n_difchan = 2,
+ .frame_rate = 25,
+ .frame_rate_base = 1,
+ .ltc_divisor = 25,
+ .height = 576,
+ .width = 720,
+ .sar = {{59, 54}, {118, 81}},
+ .video_place = dv_place_422_625,
+ .pix_fmt = PIX_FMT_YUV422P,
+ .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,
+ }
+};
+
+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,
+};
+
+/* 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 */
+
+/* largest possible DV frame, in bytes (PAL 50Mbps) */
+#define DV_MAX_FRAME_SIZE 288000
+
+static inline const DVprofile* dv_frame_profile(uint8_t* frame)
+{
+ if ((frame[3] & 0x80) == 0) { /* DSF flag */
+ /* it's an NTSC format */
+ if ((frame[80*5 + 48 + 3] & 0x4)) { /* 4:2:2 sampling */
+ return &dv_profiles[3]; /* NTSC 50Mbps */
+ } else { /* 4:1:1 sampling */
+ return &dv_profiles[0]; /* NTSC 25Mbps */
+ }
+ } else {
+ /* it's a PAL format */
+ if ((frame[80*5 + 48 + 3] & 0x4)) { /* 4:2:2 sampling */
+ return &dv_profiles[4]; /* PAL 50Mbps */
+ } else if ((frame[5] & 0x07) == 0) { /* APT flag */
+ return &dv_profiles[1]; /* PAL 25Mbps 4:2:0 */
+ } else
+ return &dv_profiles[2]; /* PAL 25Mbps 4:1:1 */
+ }
+}
+
+static inline const DVprofile* dv_codec_profile(AVCodecContext* codec)
+{
+ int i;
+
+ if (codec->width != 720)
+ return NULL;
+
+ for (i=0; i<sizeof(dv_profiles)/sizeof(DVprofile); i++)
+ if (codec->height == dv_profiles[i].height && codec->pix_fmt == dv_profiles[i].pix_fmt)
+ return &dv_profiles[i];
+
+ return NULL;
+}
+
+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;
+}
diff --git a/contrib/ffmpeg/libavcodec/dvdsubdec.c b/contrib/ffmpeg/libavcodec/dvdsubdec.c
new file mode 100644
index 000000000..9a0dd7756
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/dvdsubdec.c
@@ -0,0 +1,477 @@
+/*
+ * DVD subtitle decoding for ffmpeg
+ * 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"
+
+//#define DEBUG
+
+static int dvdsub_init_decoder(AVCodecContext *avctx)
+{
+ return 0;
+}
+
+static uint16_t getbe16(const uint8_t *p)
+{
+ return (p[0] << 8) | p[1];
+}
+
+static int get_nibble(const uint8_t *buf, int nibble_offset)
+{
+ return (buf[nibble_offset >> 1] >> ((1 - (nibble_offset & 1)) << 2)) & 0xf;
+}
+
+static int decode_rle(uint8_t *bitmap, int linesize, int w, int h,
+ const uint8_t *buf, int nibble_offset, int buf_size)
+{
+ unsigned int v;
+ int x, y, len, color, nibble_end;
+ uint8_t *d;
+
+ nibble_end = buf_size * 2;
+ x = 0;
+ y = 0;
+ d = bitmap;
+ for(;;) {
+ if (nibble_offset >= nibble_end)
+ return -1;
+ v = get_nibble(buf, nibble_offset++);
+ if (v < 0x4) {
+ v = (v << 4) | get_nibble(buf, nibble_offset++);
+ if (v < 0x10) {
+ v = (v << 4) | get_nibble(buf, nibble_offset++);
+ if (v < 0x040) {
+ v = (v << 4) | get_nibble(buf, nibble_offset++);
+ if (v < 4) {
+ v |= (w - x) << 2;
+ }
+ }
+ }
+ }
+ len = v >> 2;
+ if (len > (w - x))
+ len = (w - x);
+ color = v & 0x03;
+ memset(d + x, color, len);
+ x += len;
+ if (x >= w) {
+ y++;
+ if (y >= h)
+ break;
+ d += linesize;
+ x = 0;
+ /* byte align */
+ nibble_offset += (nibble_offset & 1);
+ }
+ }
+ return 0;
+}
+
+static void guess_palette(uint32_t *rgba_palette,
+ uint8_t *palette,
+ uint8_t *alpha,
+ uint32_t subtitle_color)
+{
+ uint8_t color_used[16];
+ int nb_opaque_colors, i, level, j, r, g, b;
+
+ for(i = 0; i < 4; i++)
+ rgba_palette[i] = 0;
+
+ memset(color_used, 0, 16);
+ nb_opaque_colors = 0;
+ for(i = 0; i < 4; i++) {
+ if (alpha[i] != 0 && !color_used[palette[i]]) {
+ color_used[palette[i]] = 1;
+ nb_opaque_colors++;
+ }
+ }
+
+ if (nb_opaque_colors == 0)
+ return;
+
+ j = nb_opaque_colors;
+ memset(color_used, 0, 16);
+ for(i = 0; i < 4; i++) {
+ if (alpha[i] != 0) {
+ if (!color_used[palette[i]]) {
+ level = (0xff * j) / nb_opaque_colors;
+ 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[palette[i]] = (i + 1);
+ j--;
+ } else {
+ rgba_palette[i] = (rgba_palette[color_used[palette[i]] - 1] & 0x00ffffff) |
+ ((alpha[i] * 17) << 24);
+ }
+ }
+ }
+}
+
+static int decode_dvd_subtitles(AVSubtitle *sub_header,
+ const uint8_t *buf, int buf_size)
+{
+ int cmd_pos, pos, cmd, x1, y1, x2, y2, offset1, offset2, next_cmd_pos;
+ uint8_t palette[4], alpha[4];
+ int date;
+ int i;
+ int is_menu = 0;
+
+ if (buf_size < 4)
+ return -1;
+ sub_header->rects = NULL;
+ sub_header->num_rects = 0;
+ sub_header->start_display_time = 0;
+ sub_header->end_display_time = 0;
+
+ cmd_pos = getbe16(buf + 2);
+ while ((cmd_pos + 4) < buf_size) {
+ date = getbe16(buf + cmd_pos);
+ next_cmd_pos = getbe16(buf + cmd_pos + 2);
+#ifdef DEBUG
+ av_log(NULL, AV_LOG_INFO, "cmd_pos=0x%04x next=0x%04x date=%d\n",
+ cmd_pos, next_cmd_pos, date);
+#endif
+ pos = cmd_pos + 4;
+ offset1 = -1;
+ offset2 = -1;
+ x1 = y1 = x2 = y2 = 0;
+ while (pos < buf_size) {
+ cmd = buf[pos++];
+#ifdef DEBUG
+ av_log(NULL, AV_LOG_INFO, "cmd=%02x\n", cmd);
+#endif
+ 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 palette */
+ if ((buf_size - pos) < 2)
+ goto fail;
+ palette[3] = buf[pos] >> 4;
+ palette[2] = buf[pos] & 0x0f;
+ palette[1] = buf[pos + 1] >> 4;
+ palette[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;
+#ifdef DEBUG
+ av_log(NULL, AV_LOG_INFO, "alpha=%x%x%x%x\n", alpha[0],alpha[1],alpha[2],alpha[3]);
+#endif
+ break;
+ case 0x05:
+ 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];
+#ifdef DEBUG
+ av_log(NULL, AV_LOG_INFO, "x1=%d x2=%d y1=%d y2=%d\n",
+ x1, x2, y1, y2);
+#endif
+ pos += 6;
+ break;
+ case 0x06:
+ if ((buf_size - pos) < 4)
+ goto fail;
+ offset1 = getbe16(buf + pos);
+ offset2 = getbe16(buf + pos + 2);
+#ifdef DEBUG
+ av_log(NULL, AV_LOG_INFO, "offset1=0x%04x offset2=0x%04x\n", offset1, offset2);
+#endif
+ pos += 4;
+ break;
+ case 0xff:
+ default:
+ 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_free(sub_header->rects[i].bitmap);
+ av_free(sub_header->rects[i].rgba_palette);
+ }
+ av_freep(&sub_header->rects);
+ sub_header->num_rects = 0;
+ }
+
+ bitmap = av_malloc(w * h);
+ sub_header->rects = av_mallocz(sizeof(AVSubtitleRect));
+ sub_header->num_rects = 1;
+ sub_header->rects[0].rgba_palette = av_malloc(4 * 4);
+ decode_rle(bitmap, w * 2, w, h / 2,
+ buf, offset1 * 2, buf_size);
+ decode_rle(bitmap + w, w * 2, w, h / 2,
+ buf, offset2 * 2, buf_size);
+ guess_palette(sub_header->rects[0].rgba_palette,
+ palette, alpha, 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].nb_colors = 4;
+ sub_header->rects[0].linesize = w;
+ sub_header->rects[0].bitmap = bitmap;
+ }
+ }
+ if (next_cmd_pos == cmd_pos)
+ break;
+ cmd_pos = next_cmd_pos;
+ }
+ if (sub_header->num_rects > 0)
+ return is_menu;
+ fail:
+ 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];
+ 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;
+
+ memset(transp_color, 0, 256);
+ for(i = 0; i < s->rects[0].nb_colors; i++) {
+ if ((s->rects[0].rgba_palette[i] >> 24) == 0)
+ transp_color[i] = 1;
+ }
+ y1 = 0;
+ while (y1 < s->rects[0].h && is_transp(s->rects[0].bitmap + y1 * s->rects[0].linesize,
+ 1, s->rects[0].w, transp_color))
+ y1++;
+ if (y1 == s->rects[0].h) {
+ av_freep(&s->rects[0].bitmap);
+ 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].bitmap + y2 * s->rects[0].linesize, 1,
+ s->rects[0].w, transp_color))
+ y2--;
+ x1 = 0;
+ while (x1 < (s->rects[0].w - 1) && is_transp(s->rects[0].bitmap + x1, s->rects[0].linesize,
+ s->rects[0].h, transp_color))
+ x1++;
+ x2 = s->rects[0].w - 1;
+ while (x2 > 0 && is_transp(s->rects[0].bitmap + x2, s->rects[0].linesize, 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].bitmap + x1 + (y1 + y) * s->rects[0].linesize, w);
+ }
+ av_freep(&s->rects[0].bitmap);
+ s->rects[0].bitmap = bitmap;
+ s->rects[0].linesize = w;
+ s->rects[0].w = w;
+ s->rects[0].h = h;
+ s->rects[0].x += x1;
+ s->rects[0].y += y1;
+ return 1;
+}
+
+static int dvdsub_close_decoder(AVCodecContext *avctx)
+{
+ return 0;
+}
+
+#ifdef DEBUG
+#undef fprintf
+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,
+ uint8_t *buf, int buf_size)
+{
+ AVSubtitle *sub = (void *)data;
+ int is_menu;
+
+ is_menu = decode_dvd_subtitles(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_log(NULL, AV_LOG_INFO, "start=%d ms end =%d ms\n",
+ sub->start_display_time,
+ sub->end_display_time);
+ ppm_save("/tmp/a.ppm", sub->rects[0].bitmap,
+ sub->rects[0].w, sub->rects[0].h, sub->rects[0].rgba_palette);
+#endif
+
+ *data_size = 1;
+ return buf_size;
+}
+
+AVCodec dvdsub_decoder = {
+ "dvdsub",
+ CODEC_TYPE_SUBTITLE,
+ CODEC_ID_DVD_SUBTITLE,
+ 0,
+ dvdsub_init_decoder,
+ NULL,
+ dvdsub_close_decoder,
+ dvdsub_decode,
+};
+
+/* parser definition */
+typedef struct DVDSubParseContext {
+ uint8_t *packet;
+ int packet_len;
+ int packet_index;
+} DVDSubParseContext;
+
+static int dvdsub_parse_init(AVCodecParserContext *s)
+{
+ return 0;
+}
+
+static int dvdsub_parse(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ 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 = (buf[0] << 8) | buf[1];
+ 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 void dvdsub_parse_close(AVCodecParserContext *s)
+{
+ DVDSubParseContext *pc = s->priv_data;
+ av_freep(&pc->packet);
+}
+
+AVCodecParser dvdsub_parser = {
+ { CODEC_ID_DVD_SUBTITLE },
+ sizeof(DVDSubParseContext),
+ dvdsub_parse_init,
+ dvdsub_parse,
+ dvdsub_parse_close,
+};
diff --git a/contrib/ffmpeg/libavcodec/dvdsubenc.c b/contrib/ffmpeg/libavcodec/dvdsubenc.c
new file mode 100644
index 000000000..fac29acc2
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/dvdsubenc.c
@@ -0,0 +1,247 @@
+/*
+ * DVD subtitle encoding for ffmpeg
+ * 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"
+
+#undef NDEBUG
+#include <assert.h>
+
+// 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];
+ assert(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 inline void putbe16(uint8_t **pq, uint16_t v)
+{
+ uint8_t *q = *pq;
+ *q++ = v >> 8;
+ *q++ = v;
+ *pq = q;
+}
+
+static int encode_dvd_subtitles(uint8_t *outbuf, int outbuf_size,
+ const AVSubtitle *h)
+{
+ uint8_t *q, *qq;
+ int object_id;
+ int offset1[20], offset2[20];
+ int i, imax, color, alpha, rects = h->num_rects;
+ unsigned long hmax;
+ unsigned long hist[256];
+ int cmap[256];
+
+ if (rects == 0 || h->rects == NULL)
+ return -1;
+ if (rects > 20)
+ rects = 20;
+
+ // analyze bitmaps, compress to 4 colors
+ for (i=0; i<256; ++i) {
+ hist[i] = 0;
+ cmap[i] = 0;
+ }
+ for (object_id = 0; object_id < rects; object_id++)
+ for (i=0; i<h->rects[object_id].w*h->rects[object_id].h; ++i) {
+ color = h->rects[object_id].bitmap[i];
+ // only count non-transparent pixels
+ alpha = h->rects[object_id].rgba_palette[color] >> 24;
+ hist[color] += alpha;
+ }
+ for (color=3;; --color) {
+ hmax = 0;
+ imax = 0;
+ for (i=0; i<256; ++i)
+ if (hist[i] > hmax) {
+ imax = i;
+ hmax = hist[i];
+ }
+ if (hmax == 0)
+ break;
+ if (color == 0)
+ color = 3;
+ av_log(NULL, AV_LOG_DEBUG, "dvd_subtitle hist[%d]=%ld -> col %d\n",
+ imax, hist[imax], color);
+ cmap[imax] = color;
+ hist[imax] = 0;
+ }
+
+
+ // encode data block
+ q = outbuf + 4;
+ for (object_id = 0; object_id < rects; object_id++) {
+ offset1[object_id] = q - outbuf;
+ // worst case memory requirement: 1 nibble per pixel..
+ if ((q - outbuf) + h->rects[object_id].w*h->rects[object_id].h/2
+ + 17*rects + 21 > outbuf_size) {
+ av_log(NULL, AV_LOG_ERROR, "dvd_subtitle too big\n");
+ return -1;
+ }
+ dvd_encode_rle(&q, h->rects[object_id].bitmap,
+ h->rects[object_id].w*2,
+ h->rects[object_id].w, h->rects[object_id].h >> 1,
+ cmap);
+ offset2[object_id] = q - outbuf;
+ dvd_encode_rle(&q, h->rects[object_id].bitmap + h->rects[object_id].w,
+ h->rects[object_id].w*2,
+ h->rects[object_id].w, h->rects[object_id].h >> 1,
+ cmap);
+ }
+
+ // set data packet size
+ qq = outbuf + 2;
+ putbe16(&qq, q - outbuf);
+
+ // send start display command
+ putbe16(&q, (h->start_display_time*90) >> 10);
+ putbe16(&q, (q - outbuf) /*- 2 */ + 8 + 12*rects + 2);
+ *q++ = 0x03; // palette - 4 nibbles
+ *q++ = 0x03; *q++ = 0x7f;
+ *q++ = 0x04; // alpha - 4 nibbles
+ *q++ = 0xf0; *q++ = 0x00;
+ //*q++ = 0x0f; *q++ = 0xff;
+
+ // XXX not sure if more than one rect can really be encoded..
+ // 12 bytes per rect
+ for (object_id = 0; object_id < rects; object_id++) {
+ int x2 = h->rects[object_id].x + h->rects[object_id].w - 1;
+ int y2 = h->rects[object_id].y + h->rects[object_id].h - 1;
+
+ *q++ = 0x05;
+ // x1 x2 -> 6 nibbles
+ *q++ = h->rects[object_id].x >> 4;
+ *q++ = (h->rects[object_id].x << 4) | ((x2 >> 8) & 0xf);
+ *q++ = x2;
+ // y1 y2 -> 6 nibbles
+ *q++ = h->rects[object_id].y >> 4;
+ *q++ = (h->rects[object_id].y << 4) | ((y2 >> 8) & 0xf);
+ *q++ = y2;
+
+ *q++ = 0x06;
+ // offset1, offset2
+ putbe16(&q, offset1[object_id]);
+ putbe16(&q, offset2[object_id]);
+ }
+ *q++ = 0x01; // start command
+ *q++ = 0xff; // terminating command
+
+ // send stop display command last
+ putbe16(&q, (h->end_display_time*90) >> 10);
+ putbe16(&q, (q - outbuf) - 2 /*+ 4*/);
+ *q++ = 0x02; // set end
+ *q++ = 0xff; // terminating command
+
+ qq = outbuf;
+ putbe16(&qq, q - outbuf);
+
+ av_log(NULL, AV_LOG_DEBUG, "subtitle_packet size=%td\n", q - outbuf);
+ return q - outbuf;
+}
+
+static int dvdsub_init_encoder(AVCodecContext *avctx)
+{
+ return 0;
+}
+
+static int dvdsub_close_encoder(AVCodecContext *avctx)
+{
+ return 0;
+}
+
+static int dvdsub_encode(AVCodecContext *avctx,
+ unsigned char *buf, int buf_size, void *data)
+{
+ //DVDSubtitleContext *s = avctx->priv_data;
+ AVSubtitle *sub = data;
+ int ret;
+
+ ret = encode_dvd_subtitles(buf, buf_size, sub);
+ return ret;
+}
+
+AVCodec dvdsub_encoder = {
+ "dvdsub",
+ CODEC_TYPE_SUBTITLE,
+ CODEC_ID_DVD_SUBTITLE,
+ 0,
+ dvdsub_init_encoder,
+ dvdsub_encode,
+ dvdsub_close_encoder,
+};
+
+/* Local Variables: */
+/* c-basic-offset:4 */
+/* End: */
diff --git a/contrib/ffmpeg/libavcodec/error_resilience.c b/contrib/ffmpeg/libavcodec/error_resilience.c
new file mode 100644
index 000000000..0923721ee
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/error_resilience.c
@@ -0,0 +1,1030 @@
+/*
+ * Error resilience / concealment
+ *
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * 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.c
+ * Error resilience / concealment.
+ */
+
+#include <limits.h>
+
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+#include "common.h"
+
+static void decode_mb(MpegEncContext *s){
+ s->dest[0] = s->current_picture.data[0] + (s->mb_y * 16* s->linesize ) + s->mb_x * 16;
+ s->dest[1] = s->current_picture.data[1] + (s->mb_y * 8 * s->uvlinesize) + s->mb_x * 8;
+ s->dest[2] = s->current_picture.data[2] + (s->mb_y * 8 * s->uvlinesize) + s->mb_x * 8;
+
+ MPV_decode_mb(s, s->block);
+}
+
+/**
+ * replaces the current MB with a flat dc only version.
+ */
+static void put_dc(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int mb_x, int mb_y)
+{
+ 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)*s->linesize]= 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*(s->uvlinesize)]= dcu/8;
+ dest_cr[x + y*(s->uvlinesize)]= 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 dont have a undamaged dc
+ * @param w width in 8 pixel blocks
+ * @param h height in 8 pixel blocks
+ */
+static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, int is_luma){
+ int b_x, b_y;
+
+ for(b_y=0; b_y<h; b_y++){
+ for(b_x=0; b_x<w; b_x++){
+ int color[4]={1024,1024,1024,1024};
+ int distance[4]={9999,9999,9999,9999};
+ 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->current_picture.mb_type[mb_index])) continue; //inter
+ if(!(error&DC_ERROR)) continue; //dc-ok
+
+ /* right block */
+ for(j=b_x+1; j<w; j++){
+ int mb_index_j= (j>>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->current_picture.mb_type[mb_index_j]);
+ if(intra_j==0 || !(error_j&DC_ERROR)){
+ color[0]= dc[j + b_y*stride];
+ distance[0]= j-b_x;
+ break;
+ }
+ }
+
+ /* left block */
+ for(j=b_x-1; j>=0; j--){
+ int mb_index_j= (j>>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->current_picture.mb_type[mb_index_j]);
+ if(intra_j==0 || !(error_j&DC_ERROR)){
+ color[1]= dc[j + b_y*stride];
+ distance[1]= b_x-j;
+ break;
+ }
+ }
+
+ /* bottom block */
+ for(j=b_y+1; j<h; j++){
+ int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride;
+ int error_j= s->error_status_table[mb_index_j];
+ int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
+ if(intra_j==0 || !(error_j&DC_ERROR)){
+ color[2]= dc[b_x + j*stride];
+ distance[2]= j-b_y;
+ break;
+ }
+ }
+
+ /* top block */
+ for(j=b_y-1; j>=0; j--){
+ int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride;
+ int error_j= s->error_status_table[mb_index_j];
+ int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
+ if(intra_j==0 || !(error_j&DC_ERROR)){
+ color[3]= dc[b_x + j*stride];
+ distance[3]= b_y-j;
+ break;
+ }
+ }
+
+ weight_sum=0;
+ guess=0;
+ for(j=0; j<4; j++){
+ int64_t weight= 256*256*256*16/distance[j];
+ guess+= weight*(int64_t)color[j];
+ weight_sum+= weight;
+ }
+ guess= (guess + weight_sum/2) / weight_sum;
+
+ dc[b_x + b_y*stride]= guess;
+ }
+ }
+}
+
+/**
+ * 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(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){
+ int b_x, b_y;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ 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->current_picture.mb_type [( b_x >>is_luma) + (b_y>>is_luma)*s->mb_stride]);
+ int right_intra= IS_INTRA(s->current_picture.mb_type [((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_stride]);
+ int left_damage = left_status&(DC_ERROR|AC_ERROR|MV_ERROR);
+ int right_damage= right_status&(DC_ERROR|AC_ERROR|MV_ERROR);
+ int offset= b_x*8 + b_y*stride*8;
+ int16_t *left_mv= s->current_picture.motion_val[0][s->b8_stride*(b_y<<(1-is_luma)) + ( b_x <<(1-is_luma))];
+ int16_t *right_mv= s->current_picture.motion_val[0][s->b8_stride*(b_y<<(1-is_luma)) + ((b_x+1)<<(1-is_luma))];
+
+ 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(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){
+ int b_x, b_y;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ 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->current_picture.mb_type [(b_x>>is_luma) + ( b_y >>is_luma)*s->mb_stride]);
+ int bottom_intra= IS_INTRA(s->current_picture.mb_type [(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_stride]);
+ int top_damage = top_status&(DC_ERROR|AC_ERROR|MV_ERROR);
+ int bottom_damage= bottom_status&(DC_ERROR|AC_ERROR|MV_ERROR);
+ int offset= b_x*8 + b_y*stride*8;
+ int16_t *top_mv= s->current_picture.motion_val[0][s->b8_stride*( b_y <<(1-is_luma)) + (b_x<<(1-is_luma))];
+ int16_t *bottom_mv= s->current_picture.motion_val[0][s->b8_stride*((b_y+1)<<(1-is_luma)) + (b_x<<(1-is_luma))];
+
+ 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(MpegEncContext *s){
+ uint8_t fixed[s->mb_stride * s->mb_height];
+#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;
+
+ 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->current_picture.mb_type[mb_xy])) f=MV_FROZEN; //intra //FIXME check
+ if(!(error&MV_ERROR)) f=MV_FROZEN; //inter with undamaged MV
+
+ fixed[mb_xy]= f;
+ if(f==MV_FROZEN)
+ num_avail++;
+ }
+
+ 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;
+
+ if(IS_INTRA(s->current_picture.mb_type[mb_xy])) continue;
+ if(!(s->error_status_table[mb_xy]&MV_ERROR)) continue;
+
+ s->mv_dir = MV_DIR_FORWARD;
+ s->mb_intra=0;
+ s->mv_type = MV_TYPE_16X16;
+ s->mb_skipped=0;
+
+ s->dsp.clear_blocks(s->block[0]);
+
+ s->mb_x= mb_x;
+ s->mb_y= mb_y;
+ s->mv[0][0][0]= 0;
+ s->mv[0][0][1]= 0;
+ decode_mb(s);
+ }
+ }
+ 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 pred_count=0;
+ int j;
+ int best_score=256*256*256*64;
+ int best_pred=0;
+ const int mot_stride= s->b8_stride;
+ const int mot_index= mb_x*2 + mb_y*2*mot_stride;
+ int prev_x= s->current_picture.motion_val[0][mot_index][0];
+ int prev_y= s->current_picture.motion_val[0][mot_index][1];
+
+ if((mb_x^mb_y^pass)&1) continue;
+
+ if(fixed[mb_xy]==MV_FROZEN) continue;
+ assert(!IS_INTRA(s->current_picture.mb_type[mb_xy]));
+ assert(s->last_picture_ptr && s->last_picture_ptr->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->current_picture.motion_val[0][mot_index - 2][0];
+ mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - 2][1];
+ pred_count++;
+ }
+ if(mb_x+1<mb_width && fixed[mb_xy+1]){
+ mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index + 2][0];
+ mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + 2][1];
+ pred_count++;
+ }
+ if(mb_y>0 && fixed[mb_xy-mb_stride]){
+ mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index - mot_stride*2][0];
+ mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - mot_stride*2][1];
+ pred_count++;
+ }
+ if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){
+ mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index + mot_stride*2][0];
+ mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + mot_stride*2][1];
+ pred_count++;
+ }
+ if(pred_count==0) continue;
+
+ if(pred_count>1){
+ int sum_x=0, sum_y=0;
+ int max_x, max_y, min_x, min_y;
+
+ for(j=0; j<pred_count; j++){
+ sum_x+= mv_predictor[j][0];
+ sum_y+= mv_predictor[j][1];
+ }
+
+ /* mean */
+ mv_predictor[pred_count][0] = sum_x/j;
+ mv_predictor[pred_count][1] = sum_y/j;
+
+ /* median */
+ if(pred_count>=3){
+ min_y= min_x= 99999;
+ max_y= max_x=-99999;
+ }else{
+ min_x=min_y=max_x=max_y=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]);
+ min_x= FFMIN(min_x, mv_predictor[j][0]);
+ min_y= FFMIN(min_y, mv_predictor[j][1]);
+ }
+ mv_predictor[pred_count+1][0] = sum_x - max_x - min_x;
+ mv_predictor[pred_count+1][1] = sum_y - max_y - min_y;
+
+ if(pred_count==4){
+ mv_predictor[pred_count+1][0] /= 2;
+ mv_predictor[pred_count+1][1] /= 2;
+ }
+ pred_count+=2;
+ }
+
+ /* zero MV */
+ pred_count++;
+
+ /* last MV */
+ mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index][0];
+ mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index][1];
+ pred_count++;
+
+ s->mv_dir = MV_DIR_FORWARD;
+ s->mb_intra=0;
+ s->mv_type = MV_TYPE_16X16;
+ s->mb_skipped=0;
+
+ s->dsp.clear_blocks(s->block[0]);
+
+ s->mb_x= mb_x;
+ s->mb_y= mb_y;
+
+ for(j=0; j<pred_count; j++){
+ int score=0;
+ uint8_t *src= s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
+
+ s->current_picture.motion_val[0][mot_index][0]= s->mv[0][0][0]= mv_predictor[j][0];
+ s->current_picture.motion_val[0][mot_index][1]= s->mv[0][0][1]= mv_predictor[j][1];
+
+ decode_mb(s);
+
+ if(mb_x>0 && fixed[mb_xy-1]){
+ int k;
+ for(k=0; k<16; k++)
+ score += FFABS(src[k*s->linesize-1 ]-src[k*s->linesize ]);
+ }
+ if(mb_x+1<mb_width && fixed[mb_xy+1]){
+ int k;
+ for(k=0; k<16; k++)
+ score += FFABS(src[k*s->linesize+15]-src[k*s->linesize+16]);
+ }
+ if(mb_y>0 && fixed[mb_xy-mb_stride]){
+ int k;
+ for(k=0; k<16; k++)
+ score += FFABS(src[k-s->linesize ]-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+s->linesize*15]-src[k+s->linesize*16]);
+ }
+
+ if(score <= best_score){ // <= will favor the last MV
+ best_score= score;
+ best_pred= j;
+ }
+ }
+score_sum+= best_score;
+//FIXME no need to set s->current_picture.motion_val[0][mot_index][0] explicit
+ s->current_picture.motion_val[0][mot_index][0]= s->mv[0][0][0]= mv_predictor[best_pred][0];
+ s->current_picture.motion_val[0][mot_index][1]= s->mv[0][0][1]= mv_predictor[best_pred][1];
+
+ decode_mb(s);
+
+
+ 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;
+ }
+ }
+
+// printf(".%d/%d", changed, score_sum); fflush(stdout);
+ }
+
+ 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;
+ }
+// printf(":"); fflush(stdout);
+ }
+}
+
+static int is_intra_more_likely(MpegEncContext *s){
+ int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y;
+
+ if(s->last_picture_ptr==NULL) 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&DC_ERROR) && (error&MV_ERROR)))
+ undamaged_count++;
+ }
+
+ if(undamaged_count < 5) return 0; //allmost all MBs damaged -> use temporal prediction
+
+ skip_amount= FFMAX(undamaged_count/50, 1); //check only upto 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&DC_ERROR) && (error&MV_ERROR))
+ continue; //skip damaged
+
+ j++;
+ if((j%skip_amount) != 0) continue; //skip a few to speed things up
+
+ if(s->pict_type==I_TYPE){
+ uint8_t *mb_ptr = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
+ uint8_t *last_mb_ptr= s->last_picture.data [0] + mb_x*16 + mb_y*16*s->linesize;
+
+ is_intra_likely += s->dsp.sad[0](NULL, last_mb_ptr, mb_ptr , s->linesize, 16);
+ is_intra_likely -= s->dsp.sad[0](NULL, last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize, 16);
+ }else{
+ if(IS_INTRA(s->current_picture.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(MpegEncContext *s){
+ if(!s->error_resilience) return;
+
+ memset(s->error_status_table, MV_ERROR|AC_ERROR|DC_ERROR|VP_START|AC_END|DC_END|MV_END, s->mb_stride*s->mb_height*sizeof(uint8_t));
+ s->error_count= 3*s->mb_num;
+}
+
+/**
+ * adds 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 (MV_END, AC_ERROR, ...), it is assumed that no earlier end or
+ * error of the same type occured
+ */
+void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status){
+ const int start_i= clip(startx + starty * s->mb_width , 0, s->mb_num-1);
+ const int end_i = 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->error_resilience) return;
+
+ mask &= ~VP_START;
+ if(status & (AC_ERROR|AC_END)){
+ mask &= ~(AC_ERROR|AC_END);
+ s->error_count -= end_i - start_i + 1;
+ }
+ if(status & (DC_ERROR|DC_END)){
+ mask &= ~(DC_ERROR|DC_END);
+ s->error_count -= end_i - start_i + 1;
+ }
+ if(status & (MV_ERROR|MV_END)){
+ mask &= ~(MV_ERROR|MV_END);
+ s->error_count -= end_i - start_i + 1;
+ }
+
+ if(status & (AC_ERROR|DC_ERROR|MV_ERROR)) 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->thread_count <= 1 && 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 != (MV_END|DC_END|AC_END)) s->error_count= INT_MAX;
+ }
+}
+
+void ff_er_frame_end(MpegEncContext *s){
+ 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;
+ Picture *pic= s->current_picture_ptr;
+
+ if(!s->error_resilience || s->error_count==0 ||
+ s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) return;
+
+ if(s->current_picture.motion_val[0] == NULL){
+ av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n");
+
+ for(i=0; i<2; i++){
+ pic->ref_index[i]= av_mallocz(size * sizeof(uint8_t));
+ pic->motion_val_base[i]= av_mallocz((size+4) * 2 * sizeof(uint16_t));
+ pic->motion_val[i]= pic->motion_val_base[i]+4;
+ }
+ pic->motion_subsample_log2= 3;
+ s->current_picture= *s->current_picture_ptr;
+ }
+
+ for(i=0; i<2; i++){
+ if(pic->ref_index[i])
+ memset(pic->ref_index[i], 0, size * sizeof(uint8_t));
+ }
+
+ 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&AC_END)
+ end_ok=0;
+ if((error&MV_END) || (error&DC_END) || (error&AC_ERROR))
+ end_ok=1;
+
+ if(!end_ok)
+ s->error_status_table[mb_xy]|= AC_ERROR;
+
+ if(error&VP_START)
+ end_ok=0;
+ }
+ }
+#endif
+ /* handle missing slices */
+ if(s->error_resilience>=4){
+ int end_ok=1;
+
+ for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack
+ 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|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
+ && error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
+ && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninited
+ end_ok=0;
+ }
+
+ if(!end_ok)
+ s->error_status_table[mb_xy]|= DC_ERROR|AC_ERROR|MV_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& (DC_ERROR|AC_ERROR|MV_ERROR);
+ else{
+ error|= old_error& (DC_ERROR|AC_ERROR|MV_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&(AC_ERROR|DC_ERROR|MV_ERROR))
+ error|= AC_ERROR|DC_ERROR|MV_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&DC_ERROR) dc_error ++;
+ if(error&AC_ERROR) ac_error ++;
+ if(error&MV_ERROR) mv_error ++;
+ }
+ av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n", dc_error, ac_error, mv_error);
+
+ 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&DC_ERROR) && (error&MV_ERROR)))
+ continue;
+
+ if(is_intra_likely)
+ s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
+ else
+ s->current_picture.mb_type[mb_xy]= MB_TYPE_16x16 | MB_TYPE_L0;
+ }
+
+ /* 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->current_picture.mb_type[mb_xy];
+ error= s->error_status_table[mb_xy];
+
+ if(IS_INTRA(mb_type)) continue; //intra
+ if(error&MV_ERROR) continue; //inter with damaged MV
+ if(!(error&AC_ERROR)) continue; //undamaged inter
+
+ s->mv_dir = MV_DIR_FORWARD;
+ s->mb_intra=0;
+ s->mb_skipped=0;
+ if(IS_8X8(mb_type)){
+ int mb_index= mb_x*2 + mb_y*2*s->b8_stride;
+ int j;
+ s->mv_type = MV_TYPE_8X8;
+ for(j=0; j<4; j++){
+ s->mv[0][j][0] = s->current_picture.motion_val[0][ mb_index + (j&1) + (j>>1)*s->b8_stride ][0];
+ s->mv[0][j][1] = s->current_picture.motion_val[0][ mb_index + (j&1) + (j>>1)*s->b8_stride ][1];
+ }
+ }else{
+ s->mv_type = MV_TYPE_16X16;
+ s->mv[0][0][0] = s->current_picture.motion_val[0][ mb_x*2 + mb_y*2*s->b8_stride ][0];
+ s->mv[0][0][1] = s->current_picture.motion_val[0][ mb_x*2 + mb_y*2*s->b8_stride ][1];
+ }
+
+ s->dsp.clear_blocks(s->block[0]);
+
+ s->mb_x= mb_x;
+ s->mb_y= mb_y;
+ decode_mb(s);
+ }
+ }
+
+ /* guess MVs */
+ if(s->pict_type==B_TYPE){
+ 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->current_picture.mb_type[mb_xy];
+ error= s->error_status_table[mb_xy];
+
+ if(IS_INTRA(mb_type)) continue;
+ if(!(error&MV_ERROR)) continue; //inter with undamaged MV
+ if(!(error&AC_ERROR)) continue; //undamaged inter
+
+ s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD;
+ s->mb_intra=0;
+ s->mv_type = MV_TYPE_16X16;
+ s->mb_skipped=0;
+
+ if(s->pp_time){
+ int time_pp= s->pp_time;
+ int time_pb= s->pb_time;
+
+ s->mv[0][0][0] = s->next_picture.motion_val[0][xy][0]*time_pb/time_pp;
+ s->mv[0][0][1] = s->next_picture.motion_val[0][xy][1]*time_pb/time_pp;
+ s->mv[1][0][0] = s->next_picture.motion_val[0][xy][0]*(time_pb - time_pp)/time_pp;
+ s->mv[1][0][1] = s->next_picture.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->dsp.clear_blocks(s->block[0]);
+ s->mb_x= mb_x;
+ s->mb_y= mb_y;
+ decode_mb(s);
+ }
+ }
+ }else
+ guess_mv(s);
+
+#ifdef HAVE_XVMC
+ /* the filters below are not XvMC compatible, skip them */
+ if(s->avctx->xvmc_acceleration) goto ec_clean;
+#endif
+ /* 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->current_picture.mb_type[mb_xy];
+
+ error= s->error_status_table[mb_xy];
+
+ if(IS_INTRA(mb_type) && s->partitioned_frame) continue;
+// if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
+
+ dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
+ dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
+ dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
+
+ 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)*s->linesize];
+ }
+ }
+ 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*(s->uvlinesize)];
+ dcv+=dest_cr[x + y*(s->uvlinesize)];
+ }
+ }
+ 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->current_picture.mb_type[mb_xy];
+
+ error= s->error_status_table[mb_xy];
+
+ if(IS_INTER(mb_type)) continue;
+ if(!(error&AC_ERROR)) continue; //undamaged
+
+ dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
+ dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
+ dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
+
+ 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->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1);
+ h_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0);
+ h_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0);
+
+ /* filter vertical block boundaries */
+ v_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1);
+ v_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0);
+ v_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0);
+ }
+
+#ifdef HAVE_XVMC
+ec_clean:
+#endif
+ /* 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->pict_type!=B_TYPE && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){
+ s->mbskip_table[mb_xy]=0;
+ }
+ s->mbintra_table[mb_xy]=1;
+ }
+}
diff --git a/contrib/ffmpeg/libavcodec/eval.c b/contrib/ffmpeg/libavcodec/eval.c
new file mode 100644
index 000000000..961c8b5ac
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/eval.c
@@ -0,0 +1,466 @@
+/*
+ * simple arithmetic expression evaluator
+ *
+ * Copyright (c) 2002-2006 Michael Niedermayer <michaelni@gmx.at>
+ * Copyright (c) 2006 Oded Shimon <ods15@ods15.dyndns.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 eval.c
+ * simple arithmetic expression evaluator.
+ *
+ * see http://joe.hotchkiss.com/programming/eval/eval.html
+ */
+
+#include "avcodec.h"
+#include "mpegvideo.h"
+#include "eval.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifndef NAN
+ #define NAN 0.0/0.0
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+typedef struct Parser{
+ int stack_index;
+ char *s;
+ double *const_value;
+ const char **const_name; // NULL terminated
+ double (**func1)(void *, double a); // NULL terminated
+ const char **func1_name; // NULL terminated
+ double (**func2)(void *, double a, double b); // NULL terminated
+ char **func2_name; // NULL terminated
+ void *opaque;
+ char **error;
+#define VARS 10
+ double var[VARS];
+} Parser;
+
+static int8_t si_prefixes['z' - 'E' + 1]={
+ ['y'-'E']= -24,
+ ['z'-'E']= -21,
+ ['a'-'E']= -18,
+ ['f'-'E']= -15,
+ ['p'-'E']= -12,
+ ['n'-'E']= - 9,
+ ['u'-'E']= - 6,
+ ['m'-'E']= - 3,
+ ['c'-'E']= - 2,
+ ['d'-'E']= - 1,
+ ['h'-'E']= 2,
+ ['k'-'E']= 3,
+ ['K'-'E']= 3,
+ ['M'-'E']= 6,
+ ['G'-'E']= 9,
+ ['T'-'E']= 12,
+ ['P'-'E']= 15,
+ ['E'-'E']= 18,
+ ['Z'-'E']= 21,
+ ['Y'-'E']= 24,
+};
+
+/** strtod() function extended with 'k', 'M', 'G', 'ki', 'Mi', 'Gi' and 'B'
+ * postfixes. This allows using f.e. kB, MiB, G and B as a postfix. This
+ * function assumes that the unit of numbers is bits not bytes.
+ */
+static double av_strtod(const char *name, char **tail) {
+ double d;
+ char *next;
+ d = strtod(name, &next);
+ /* if parsing succeeded, check for and interpret postfixes */
+ if (next!=name) {
+
+ if(*next >= 'E' && *next <= 'z'){
+ int e= si_prefixes[*next - 'E'];
+ if(e){
+ if(next[1] == 'i'){
+ d*= pow( 2, e/0.3);
+ next+=2;
+ }else{
+ d*= pow(10, e);
+ next++;
+ }
+ }
+ }
+
+ if(*next=='B') {
+ d*=8;
+ *next++;
+ }
+ }
+ /* if requested, fill in tail with the position after the last parsed
+ character */
+ if (tail)
+ *tail = next;
+ return d;
+}
+
+static int strmatch(const char *s, const char *prefix){
+ int i;
+ for(i=0; prefix[i]; i++){
+ if(prefix[i] != s[i]) return 0;
+ }
+ return 1;
+}
+
+struct ff_expr_s {
+ enum {
+ e_value, e_const, e_func0, e_func1, e_func2,
+ e_squish, e_gauss, e_ld,
+ e_mod, e_max, e_min, e_eq, e_gt, e_gte,
+ e_pow, e_mul, e_div, e_add,
+ e_last, e_st, e_while,
+ } type;
+ double value; // is sign in other types
+ union {
+ int const_index;
+ double (*func0)(double);
+ double (*func1)(void *, double);
+ double (*func2)(void *, double, double);
+ } a;
+ AVEvalExpr * param[2];
+};
+
+static double eval_expr(Parser * p, AVEvalExpr * e) {
+ switch (e->type) {
+ case e_value: return e->value;
+ case e_const: return e->value * p->const_value[e->a.const_index];
+ case e_func0: return e->value * e->a.func0(eval_expr(p, e->param[0]));
+ case e_func1: return e->value * e->a.func1(p->opaque, eval_expr(p, e->param[0]));
+ case e_func2: return e->value * e->a.func2(p->opaque, eval_expr(p, e->param[0]), eval_expr(p, e->param[1]));
+ case e_squish: return 1/(1+exp(4*eval_expr(p, e->param[0])));
+ case e_gauss: { double d = eval_expr(p, e->param[0]); return exp(-d*d/2)/sqrt(2*M_PI); }
+ case e_ld: return e->value * p->var[clip(eval_expr(p, e->param[0]), 0, VARS-1)];
+ case e_while: {
+ double d = NAN;
+ while(eval_expr(p, e->param[0]))
+ d=eval_expr(p, e->param[1]);
+ return d;
+ }
+ default: {
+ double d = eval_expr(p, e->param[0]);
+ double d2 = eval_expr(p, e->param[1]);
+ switch (e->type) {
+ case e_mod: return e->value * (d - floor(d/d2)*d2);
+ case e_max: return e->value * (d > d2 ? d : d2);
+ case e_min: return e->value * (d < d2 ? d : d2);
+ case e_eq: return e->value * (d == d2 ? 1.0 : 0.0);
+ case e_gt: return e->value * (d > d2 ? 1.0 : 0.0);
+ case e_gte: return e->value * (d >= d2 ? 1.0 : 0.0);
+ case e_pow: return e->value * pow(d, d2);
+ case e_mul: return e->value * (d * d2);
+ case e_div: return e->value * (d / d2);
+ case e_add: return e->value * (d + d2);
+ case e_last:return e->value * d2;
+ case e_st : return e->value * (p->var[clip(d, 0, VARS-1)]= d2);
+ }
+ }
+ }
+ return NAN;
+}
+
+static AVEvalExpr * parse_expr(Parser *p);
+
+void ff_eval_free(AVEvalExpr * e) {
+ if (!e) return;
+ ff_eval_free(e->param[0]);
+ ff_eval_free(e->param[1]);
+ av_freep(&e);
+}
+
+static AVEvalExpr * parse_primary(Parser *p) {
+ AVEvalExpr * d = av_mallocz(sizeof(AVEvalExpr));
+ char *next= p->s;
+ int i;
+
+ /* number */
+ d->value = av_strtod(p->s, &next);
+ if(next != p->s){
+ d->type = e_value;
+ p->s= next;
+ return d;
+ }
+ d->value = 1;
+
+ /* named constants */
+ for(i=0; p->const_name && p->const_name[i]; i++){
+ if(strmatch(p->s, p->const_name[i])){
+ p->s+= strlen(p->const_name[i]);
+ d->type = e_const;
+ d->a.const_index = i;
+ return d;
+ }
+ }
+
+ p->s= strchr(p->s, '(');
+ if(p->s==NULL){
+ *p->error = "missing (";
+ p->s= next;
+ ff_eval_free(d);
+ return NULL;
+ }
+ p->s++; // "("
+ if (*next == '(') { // special case do-nothing
+ av_freep(&d);
+ d = parse_expr(p);
+ if(p->s[0] != ')'){
+ *p->error = "missing )";
+ ff_eval_free(d);
+ return NULL;
+ }
+ p->s++; // ")"
+ return d;
+ }
+ d->param[0] = parse_expr(p);
+ if(p->s[0]== ','){
+ p->s++; // ","
+ d->param[1] = parse_expr(p);
+ }
+ if(p->s[0] != ')'){
+ *p->error = "missing )";
+ ff_eval_free(d);
+ return NULL;
+ }
+ p->s++; // ")"
+
+ d->type = e_func0;
+ if( strmatch(next, "sinh" ) ) d->a.func0 = sinh;
+ else if( strmatch(next, "cosh" ) ) d->a.func0 = cosh;
+ else if( strmatch(next, "tanh" ) ) d->a.func0 = tanh;
+ else if( strmatch(next, "sin" ) ) d->a.func0 = sin;
+ else if( strmatch(next, "cos" ) ) d->a.func0 = cos;
+ else if( strmatch(next, "tan" ) ) d->a.func0 = tan;
+ else if( strmatch(next, "atan" ) ) d->a.func0 = atan;
+ else if( strmatch(next, "asin" ) ) d->a.func0 = asin;
+ else if( strmatch(next, "acos" ) ) d->a.func0 = acos;
+ else if( strmatch(next, "exp" ) ) d->a.func0 = exp;
+ else if( strmatch(next, "log" ) ) d->a.func0 = log;
+ else if( strmatch(next, "abs" ) ) d->a.func0 = fabs;
+ else if( strmatch(next, "squish") ) d->type = e_squish;
+ else if( strmatch(next, "gauss" ) ) d->type = e_gauss;
+ else if( strmatch(next, "mod" ) ) d->type = e_mod;
+ else if( strmatch(next, "max" ) ) d->type = e_max;
+ else if( strmatch(next, "min" ) ) d->type = e_min;
+ else if( strmatch(next, "eq" ) ) d->type = e_eq;
+ else if( strmatch(next, "gte" ) ) d->type = e_gte;
+ else if( strmatch(next, "gt" ) ) d->type = e_gt;
+ else if( strmatch(next, "lte" ) ) { AVEvalExpr * tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; d->type = e_gt; }
+ else if( strmatch(next, "lt" ) ) { AVEvalExpr * tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; d->type = e_gte; }
+ else if( strmatch(next, "ld" ) ) d->type = e_ld;
+ else if( strmatch(next, "st" ) ) d->type = e_st;
+ else if( strmatch(next, "while" ) ) d->type = e_while;
+ else {
+ for(i=0; p->func1_name && p->func1_name[i]; i++){
+ if(strmatch(next, p->func1_name[i])){
+ d->a.func1 = p->func1[i];
+ d->type = e_func1;
+ return d;
+ }
+ }
+
+ for(i=0; p->func2_name && p->func2_name[i]; i++){
+ if(strmatch(next, p->func2_name[i])){
+ d->a.func2 = p->func2[i];
+ d->type = e_func2;
+ return d;
+ }
+ }
+
+ *p->error = "unknown function";
+ ff_eval_free(d);
+ return NULL;
+ }
+
+ return d;
+}
+
+static AVEvalExpr * new_eval_expr(int type, int value, AVEvalExpr *p0, AVEvalExpr *p1){
+ AVEvalExpr * e = av_mallocz(sizeof(AVEvalExpr));
+ e->type =type ;
+ e->value =value ;
+ e->param[0] =p0 ;
+ e->param[1] =p1 ;
+ return e;
+}
+
+static AVEvalExpr * parse_pow(Parser *p, int *sign){
+ *sign= (*p->s == '+') - (*p->s == '-');
+ p->s += *sign&1;
+ return parse_primary(p);
+}
+
+static AVEvalExpr * parse_factor(Parser *p){
+ int sign, sign2;
+ AVEvalExpr * e = parse_pow(p, &sign);
+ while(p->s[0]=='^'){
+ p->s++;
+ e= new_eval_expr(e_pow, 1, e, parse_pow(p, &sign2));
+ if (e->param[1]) e->param[1]->value *= (sign2|1);
+ }
+ if (e) e->value *= (sign|1);
+ return e;
+}
+
+static AVEvalExpr * parse_term(Parser *p){
+ AVEvalExpr * e = parse_factor(p);
+ while(p->s[0]=='*' || p->s[0]=='/'){
+ int c= *p->s++;
+ e= new_eval_expr(c == '*' ? e_mul : e_div, 1, e, parse_factor(p));
+ }
+ return e;
+}
+
+static AVEvalExpr * parse_subexpr(Parser *p) {
+ AVEvalExpr * e = parse_term(p);
+ while(*p->s == '+' || *p->s == '-') {
+ e= new_eval_expr(e_add, 1, e, parse_term(p));
+ };
+
+ return e;
+}
+
+static AVEvalExpr * parse_expr(Parser *p) {
+ AVEvalExpr * e;
+
+ if(p->stack_index <= 0) //protect against stack overflows
+ return NULL;
+ p->stack_index--;
+
+ e = parse_subexpr(p);
+
+ while(*p->s == ';') {
+ p->s++;
+ e= new_eval_expr(e_last, 1, e, parse_subexpr(p));
+ };
+
+ p->stack_index++;
+
+ return e;
+}
+
+static int verify_expr(AVEvalExpr * e) {
+ if (!e) return 0;
+ switch (e->type) {
+ case e_value:
+ case e_const: return 1;
+ case e_func0:
+ case e_func1:
+ case e_squish:
+ case e_ld:
+ case e_gauss: return verify_expr(e->param[0]);
+ default: return verify_expr(e->param[0]) && verify_expr(e->param[1]);
+ }
+}
+
+AVEvalExpr * ff_parse(char *s, const char **const_name,
+ double (**func1)(void *, double), const char **func1_name,
+ double (**func2)(void *, double, double), char **func2_name,
+ char **error){
+ Parser p;
+ AVEvalExpr * e;
+ char w[strlen(s) + 1], * wp = w;
+
+ while (*s)
+ if (!isspace(*s++)) *wp++ = s[-1];
+ *wp++ = 0;
+
+ p.stack_index=100;
+ p.s= w;
+ p.const_name = const_name;
+ p.func1 = func1;
+ p.func1_name = func1_name;
+ p.func2 = func2;
+ p.func2_name = func2_name;
+ p.error= error;
+
+ e = parse_expr(&p);
+ if (!verify_expr(e)) {
+ ff_eval_free(e);
+ return NULL;
+ }
+ return e;
+}
+
+double ff_parse_eval(AVEvalExpr * e, double *const_value, void *opaque) {
+ Parser p;
+
+ p.const_value= const_value;
+ p.opaque = opaque;
+ return eval_expr(&p, e);
+}
+
+double ff_eval2(char *s, double *const_value, const char **const_name,
+ double (**func1)(void *, double), const char **func1_name,
+ double (**func2)(void *, double, double), char **func2_name,
+ void *opaque, char **error){
+ AVEvalExpr * e = ff_parse(s, const_name, func1, func1_name, func2, func2_name, error);
+ double d;
+ if (!e) return NAN;
+ d = ff_parse_eval(e, const_value, opaque);
+ ff_eval_free(e);
+ return d;
+}
+
+#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
+attribute_deprecated double ff_eval(char *s, double *const_value, const char **const_name,
+ double (**func1)(void *, double), const char **func1_name,
+ double (**func2)(void *, double, double), char **func2_name,
+ void *opaque){
+ char *error=NULL;
+ double ret;
+ ret = ff_eval2(s, const_value, const_name, func1, func1_name, func2, func2_name, opaque, &error);
+ if (error)
+ av_log(NULL, AV_LOG_ERROR, "Error evaluating \"%s\": %s\n", s, error);
+ return ret;
+}
+#endif
+
+#ifdef TEST
+#undef printf
+static double const_values[]={
+ M_PI,
+ M_E,
+ 0
+};
+static const char *const_names[]={
+ "PI",
+ "E",
+ 0
+};
+main(){
+ int i;
+ printf("%f == 12.7\n", ff_eval("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_values, const_names, NULL, NULL, NULL, NULL, NULL));
+ printf("%f == 0.931322575\n", ff_eval("80G/80Gi", const_values, const_names, NULL, NULL, NULL, NULL, NULL));
+
+ for(i=0; i<1050; i++){
+ START_TIMER
+ ff_eval("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_values, const_names, NULL, NULL, NULL, NULL, NULL);
+ STOP_TIMER("ff_eval")
+ }
+}
+#endif
diff --git a/contrib/ffmpeg/libavcodec/eval.h b/contrib/ffmpeg/libavcodec/eval.h
new file mode 100644
index 000000000..b52199cf4
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/eval.h
@@ -0,0 +1,84 @@
+/*
+ * simple arithmetic expression evaluator
+ *
+ * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file eval.h
+ * eval header.
+ */
+
+#ifndef AVCODEC_EVAL_H
+#define AVCODEC_EVAL_H
+
+#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
+double ff_eval(char *s, double *const_value, const char **const_name,
+ double (**func1)(void *, double), const char **func1_name,
+ double (**func2)(void *, double, double), char **func2_name,
+ void *opaque);
+#endif
+
+/**
+ * Parses and evaluates an expression.
+ * Note, this is significantly slower than ff_parse_eval()
+ * @param s expression as a zero terminated string for example "1+2^3+5*5+sin(2/3)"
+ * @param func1 NULL terminated array of function pointers for functions which take 1 argument
+ * @param func2 NULL terminated array of function pointers for functions which take 2 arguments
+ * @param const_name NULL terminated array of zero terminated strings of constant identifers for example {"PI", "E", 0}
+ * @param func1_name NULL terminated array of zero terminated strings of func1 identifers
+ * @param func2_name NULL terminated array of zero terminated strings of func2 identifers
+ * @param error pointer to a char* which is set to an error message if something goes wrong
+ * @param const_value a zero terminated array of values for the identifers from const_name
+ * @param opaque a pointer which will be passed to all functions from func1 and func2
+ * @return the value of the expression
+ */
+double ff_eval2(char *s, double *const_value, const char **const_name,
+ double (**func1)(void *, double), const char **func1_name,
+ double (**func2)(void *, double, double), char **func2_name,
+ void *opaque, char **error);
+
+typedef struct ff_expr_s AVEvalExpr;
+
+/**
+ * Parses a expression.
+ * @param s expression as a zero terminated string for example "1+2^3+5*5+sin(2/3)"
+ * @param func1 NULL terminated array of function pointers for functions which take 1 argument
+ * @param func2 NULL terminated array of function pointers for functions which take 2 arguments
+ * @param const_name NULL terminated array of zero terminated strings of constant identifers for example {"PI", "E", 0}
+ * @param func1_name NULL terminated array of zero terminated strings of func1 identifers
+ * @param func2_name NULL terminated array of zero terminated strings of func2 identifers
+ * @param error pointer to a char* which is set to an error message if something goes wrong
+ * @return AVEvalExpr which must be freed with ff_eval_free by the user when its not needed anymore
+ * NULL if anything went wrong
+ */
+AVEvalExpr * ff_parse(char *s, const char **const_name,
+ double (**func1)(void *, double), const char **func1_name,
+ double (**func2)(void *, double, double), char **func2_name,
+ char **error);
+/**
+ * Evaluates a previously parsed expression.
+ * @param const_value a zero terminated array of values for the identifers from ff_parse const_name
+ * @param opaque a pointer which will be passed to all functions from func1 and func2
+ * @return the value of the expression
+ */
+double ff_parse_eval(AVEvalExpr * e, double *const_value, void *opaque);
+void ff_eval_free(AVEvalExpr * e);
+
+#endif /* AVCODEC_EVAL_H */
diff --git a/contrib/ffmpeg/libavcodec/faac.c b/contrib/ffmpeg/libavcodec/faac.c
new file mode 100644
index 000000000..06e0b4920
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/faac.c
@@ -0,0 +1,133 @@
+/*
+ * Interface to libfaac for aac encoding
+ * Copyright (c) 2002 Gildas Bazin <gbazin@netcourrier.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 faacaudio.c
+ * Interface to libfaac for aac encoding.
+ */
+
+#include "avcodec.h"
+#include <faac.h>
+
+typedef struct FaacAudioContext {
+ faacEncHandle faac_handle;
+} FaacAudioContext;
+
+static int Faac_encode_init(AVCodecContext *avctx)
+{
+ FaacAudioContext *s = avctx->priv_data;
+ faacEncConfigurationPtr faac_cfg;
+ unsigned long samples_input, max_bytes_output;
+
+ /* number of channels */
+ if (avctx->channels < 1 || avctx->channels > 6)
+ return -1;
+
+ s->faac_handle = faacEncOpen(avctx->sample_rate,
+ avctx->channels,
+ &samples_input, &max_bytes_output);
+
+ /* 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);
+ faacEncClose(s->faac_handle);
+ return -1;
+ }
+
+ /* put the options in the configuration struct */
+ faac_cfg->aacObjectType = LOW;
+ 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;
+
+ avctx->frame_size = samples_input / avctx->channels;
+
+ avctx->coded_frame= avcodec_alloc_frame();
+ avctx->coded_frame->key_frame= 1;
+
+ /* Set decoder specific info */
+ avctx->extradata_size = 0;
+ if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) {
+
+ unsigned char *buffer;
+ unsigned long decoder_specific_info_size;
+
+ if (!faacEncGetDecoderSpecificInfo(s->faac_handle, &buffer,
+ &decoder_specific_info_size)) {
+ avctx->extradata = buffer;
+ avctx->extradata_size = decoder_specific_info_size;
+ faac_cfg->outputFormat = 0;
+ }
+ }
+
+ if (!faacEncSetConfiguration(s->faac_handle, faac_cfg)) {
+ av_log(avctx, AV_LOG_ERROR, "libfaac doesn't support this output format!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int Faac_encode_frame(AVCodecContext *avctx,
+ unsigned char *frame, int buf_size, void *data)
+{
+ FaacAudioContext *s = avctx->priv_data;
+ int bytes_written;
+
+ bytes_written = faacEncEncode(s->faac_handle,
+ data,
+ avctx->frame_size * avctx->channels,
+ frame,
+ buf_size);
+
+ return bytes_written;
+}
+
+static int Faac_encode_close(AVCodecContext *avctx)
+{
+ FaacAudioContext *s = avctx->priv_data;
+
+ av_freep(&avctx->coded_frame);
+
+ //if (avctx->extradata_size) free(avctx->extradata);
+
+ faacEncClose(s->faac_handle);
+ return 0;
+}
+
+AVCodec faac_encoder = {
+ "aac",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_AAC,
+ sizeof(FaacAudioContext),
+ Faac_encode_init,
+ Faac_encode_frame,
+ Faac_encode_close
+};
diff --git a/contrib/ffmpeg/libavcodec/faad.c b/contrib/ffmpeg/libavcodec/faad.c
new file mode 100644
index 000000000..df33ea0b2
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/faad.c
@@ -0,0 +1,334 @@
+/*
+ * Faad decoder
+ * Copyright (c) 2003 Zdenek Kabelac.
+ * Copyright (c) 2004 Thomas Raivio.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file faad.c
+ * AAC decoder.
+ *
+ * still a bit unfinished - but it plays something
+ */
+
+#include "avcodec.h"
+#include "faad.h"
+
+#ifndef FAADAPI
+#define FAADAPI
+#endif
+
+/*
+ * when CONFIG_FAADBIN is defined the libfaad will be opened at runtime
+ */
+//#undef CONFIG_FAADBIN
+//#define CONFIG_FAADBIN
+
+#ifdef CONFIG_FAADBIN
+#include <dlfcn.h>
+static const char* libfaadname = "libfaad.so.0";
+#else
+#define dlopen(a)
+#define dlclose(a)
+#endif
+
+typedef struct {
+ void* handle; /* dlopen handle */
+ void* faac_handle; /* FAAD library handle */
+ int sample_size;
+ int init;
+
+ /* faad calls */
+ faacDecHandle FAADAPI (*faacDecOpen)(void);
+ faacDecConfigurationPtr FAADAPI (*faacDecGetCurrentConfiguration)(faacDecHandle hDecoder);
+#ifndef FAAD2_VERSION
+ int FAADAPI (*faacDecSetConfiguration)(faacDecHandle hDecoder,
+ faacDecConfigurationPtr config);
+ int FAADAPI (*faacDecInit)(faacDecHandle hDecoder,
+ unsigned char *buffer,
+ unsigned long *samplerate,
+ unsigned long *channels);
+ int FAADAPI (*faacDecInit2)(faacDecHandle hDecoder, unsigned char *pBuffer,
+ unsigned long SizeOfDecoderSpecificInfo,
+ unsigned long *samplerate, unsigned long *channels);
+ int FAADAPI (*faacDecDecode)(faacDecHandle hDecoder,
+ unsigned char *buffer,
+ unsigned long *bytesconsumed,
+ short *sample_buffer,
+ unsigned long *samples);
+#else
+ unsigned char FAADAPI (*faacDecSetConfiguration)(faacDecHandle hDecoder,
+ faacDecConfigurationPtr config);
+ long FAADAPI (*faacDecInit)(faacDecHandle hDecoder,
+ unsigned char *buffer,
+ unsigned long buffer_size,
+ unsigned long *samplerate,
+ unsigned char *channels);
+ char FAADAPI (*faacDecInit2)(faacDecHandle hDecoder, unsigned char *pBuffer,
+ unsigned long SizeOfDecoderSpecificInfo,
+ unsigned long *samplerate, unsigned char *channels);
+ void *FAADAPI (*faacDecDecode)(faacDecHandle hDecoder,
+ faacDecFrameInfo *hInfo,
+ unsigned char *buffer,
+ unsigned long buffer_size);
+ char* FAADAPI (*faacDecGetErrorMessage)(unsigned char errcode);
+#endif
+
+ void FAADAPI (*faacDecClose)(faacDecHandle hDecoder);
+
+
+} FAACContext;
+
+static const unsigned long faac_srates[] =
+{
+ 96000, 88200, 64000, 48000, 44100, 32000,
+ 24000, 22050, 16000, 12000, 11025, 8000
+};
+
+static int faac_init_mp4(AVCodecContext *avctx)
+{
+ FAACContext *s = (FAACContext *) avctx->priv_data;
+ unsigned long samplerate;
+#ifndef FAAD2_VERSION
+ unsigned long channels;
+#else
+ unsigned char channels;
+#endif
+ int r = 0;
+
+ if (avctx->extradata){
+ r = s->faacDecInit2(s->faac_handle, (uint8_t*) avctx->extradata,
+ avctx->extradata_size,
+ &samplerate, &channels);
+ if (r < 0){
+ av_log(avctx, AV_LOG_ERROR,
+ "faacDecInit2 failed r:%d sr:%ld ch:%ld s:%d\n",
+ r, samplerate, (long)channels, avctx->extradata_size);
+ } else {
+ avctx->sample_rate = samplerate;
+ avctx->channels = channels;
+ s->init = 1;
+ }
+ }
+
+ return r;
+}
+
+static int faac_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ FAACContext *s = (FAACContext *) avctx->priv_data;
+#ifndef FAAD2_VERSION
+ unsigned long bytesconsumed;
+ short *sample_buffer = NULL;
+ unsigned long samples;
+ int out;
+#else
+ faacDecFrameInfo frame_info;
+ void *out;
+#endif
+ if(buf_size == 0)
+ return 0;
+#ifndef FAAD2_VERSION
+ out = s->faacDecDecode(s->faac_handle,
+ (unsigned char*)buf,
+ &bytesconsumed,
+ data,
+ &samples);
+ samples *= s->sample_size;
+ if (data_size)
+ *data_size = samples;
+ return (buf_size < (int)bytesconsumed)
+ ? buf_size : (int)bytesconsumed;
+#else
+
+ if(!s->init){
+ unsigned long srate;
+ unsigned char channels;
+ int r = s->faacDecInit(s->faac_handle, buf, buf_size, &srate, &channels);
+ if(r < 0){
+ av_log(avctx, AV_LOG_ERROR, "faac: codec init failed: %s\n",
+ s->faacDecGetErrorMessage(frame_info.error));
+ return -1;
+ }
+ avctx->sample_rate = srate;
+ avctx->channels = channels;
+ s->init = 1;
+ }
+
+ out = s->faacDecDecode(s->faac_handle, &frame_info, (unsigned char*)buf, (unsigned long)buf_size);
+
+ if (frame_info.error > 0) {
+ av_log(avctx, AV_LOG_ERROR, "faac: frame decoding failed: %s\n",
+ s->faacDecGetErrorMessage(frame_info.error));
+ return -1;
+ }
+
+ frame_info.samples *= s->sample_size;
+ memcpy(data, out, frame_info.samples); // CHECKME - can we cheat this one
+
+ if (data_size)
+ *data_size = frame_info.samples;
+
+ return (buf_size < (int)frame_info.bytesconsumed)
+ ? buf_size : (int)frame_info.bytesconsumed;
+#endif
+}
+
+static int faac_decode_end(AVCodecContext *avctx)
+{
+ FAACContext *s = (FAACContext *) avctx->priv_data;
+
+ if (s->faacDecClose)
+ s->faacDecClose(s->faac_handle);
+
+ dlclose(s->handle);
+ return 0;
+}
+
+static int faac_decode_init(AVCodecContext *avctx)
+{
+ FAACContext *s = (FAACContext *) avctx->priv_data;
+ faacDecConfigurationPtr faac_cfg;
+
+#ifdef CONFIG_FAADBIN
+ const char* err = 0;
+
+ s->handle = dlopen(libfaadname, RTLD_LAZY);
+ if (!s->handle)
+ {
+ av_log(avctx, AV_LOG_ERROR, "FAAD library: %s could not be opened! \n%s\n",
+ libfaadname, dlerror());
+ return -1;
+ }
+#define dfaac(a, b) \
+ do { static const char* n = "faacDec" #a; \
+ if ((s->faacDec ## a = b dlsym( s->handle, n )) == NULL) { err = n; break; } } while(0)
+ for(;;) {
+#else /* !CONFIG_FAADBIN */
+#define dfaac(a, b) s->faacDec ## a = faacDec ## a
+#endif /* CONFIG_FAADBIN */
+
+ // resolve all needed function calls
+ dfaac(Open, (faacDecHandle FAADAPI (*)(void)));
+ dfaac(GetCurrentConfiguration, (faacDecConfigurationPtr
+ FAADAPI (*)(faacDecHandle)));
+#ifndef FAAD2_VERSION
+ dfaac(SetConfiguration, (int FAADAPI (*)(faacDecHandle,
+ faacDecConfigurationPtr)));
+
+ dfaac(Init, (int FAADAPI (*)(faacDecHandle, unsigned char*,
+ unsigned long*, unsigned long*)));
+ dfaac(Init2, (int FAADAPI (*)(faacDecHandle, unsigned char*,
+ unsigned long, unsigned long*,
+ unsigned long*)));
+ dfaac(Close, (void FAADAPI (*)(faacDecHandle hDecoder)));
+ dfaac(Decode, (int FAADAPI (*)(faacDecHandle, unsigned char*,
+ unsigned long*, short*, unsigned long*)));
+#else
+ dfaac(SetConfiguration, (unsigned char FAADAPI (*)(faacDecHandle,
+ faacDecConfigurationPtr)));
+ dfaac(Init, (long FAADAPI (*)(faacDecHandle, unsigned char*,
+ unsigned long, unsigned long*, unsigned char*)));
+ dfaac(Init2, (char FAADAPI (*)(faacDecHandle, unsigned char*,
+ unsigned long, unsigned long*,
+ unsigned char*)));
+ dfaac(Decode, (void *FAADAPI (*)(faacDecHandle, faacDecFrameInfo*,
+ unsigned char*, unsigned long)));
+ dfaac(GetErrorMessage, (char* FAADAPI (*)(unsigned char)));
+#endif
+#undef dfacc
+
+#ifdef CONFIG_FAADBIN
+ break;
+ }
+ if (err) {
+ dlclose(s->handle);
+ av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot resolve %s in %s!\n",
+ err, libfaadname);
+ return -1;
+ }
+#endif
+
+ s->faac_handle = s->faacDecOpen();
+ if (!s->faac_handle) {
+ av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot create handler!\n");
+ faac_decode_end(avctx);
+ return -1;
+ }
+
+
+ faac_cfg = s->faacDecGetCurrentConfiguration(s->faac_handle);
+
+ if (faac_cfg) {
+ switch (avctx->bits_per_sample) {
+ case 8: av_log(avctx, AV_LOG_ERROR, "FAADlib unsupported bps %d\n", avctx->bits_per_sample); break;
+ default:
+ case 16:
+#ifdef FAAD2_VERSION
+ faac_cfg->outputFormat = FAAD_FMT_16BIT;
+#endif
+ s->sample_size = 2;
+ break;
+ case 24:
+#ifdef FAAD2_VERSION
+ faac_cfg->outputFormat = FAAD_FMT_24BIT;
+#endif
+ s->sample_size = 3;
+ break;
+ case 32:
+#ifdef FAAD2_VERSION
+ faac_cfg->outputFormat = FAAD_FMT_32BIT;
+#endif
+ s->sample_size = 4;
+ break;
+ }
+
+ faac_cfg->defSampleRate = (!avctx->sample_rate) ? 44100 : avctx->sample_rate;
+ faac_cfg->defObjectType = LC;
+ }
+
+ s->faacDecSetConfiguration(s->faac_handle, faac_cfg);
+
+ faac_init_mp4(avctx);
+
+ return 0;
+}
+
+#define AAC_CODEC(id, name) \
+AVCodec name ## _decoder = { \
+ #name, \
+ CODEC_TYPE_AUDIO, \
+ id, \
+ sizeof(FAACContext), \
+ faac_decode_init, \
+ NULL, \
+ faac_decode_end, \
+ faac_decode_frame, \
+}
+
+// FIXME - raw AAC files - maybe just one entry will be enough
+AAC_CODEC(CODEC_ID_AAC, aac);
+#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
+// If it's mp4 file - usually embeded into Qt Mov
+AAC_CODEC(CODEC_ID_MPEG4AAC, mpeg4aac);
+#endif
+
+#undef AAC_CODEC
diff --git a/contrib/ffmpeg/libavcodec/faandct.c b/contrib/ffmpeg/libavcodec/faandct.c
new file mode 100644
index 000000000..e3c0d84a2
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/faandct.c
@@ -0,0 +1,220 @@
+/*
+ * Floating point AAN DCT
+ * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 implementation is based upon the IJG integer AAN DCT (see jfdctfst.c)
+ */
+
+/**
+ * @file faandct.c
+ * @brief
+ * Floating point AAN DCT
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#include "dsputil.h"
+#include "faandct.h"
+
+#define FLOAT float
+#ifdef FAAN_POSTSCALE
+# define SCALE(x) postscale[x]
+#else
+# define SCALE(x) 1
+#endif
+
+//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 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 always_inline void row_fdct(FLOAT temp[64], DCTELEM * data)
+{
+ FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ FLOAT tmp10, tmp11, tmp12, tmp13;
+ FLOAT z1, z2, z3, z4, z5, z11, z13;
+ 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;
+
+ z1= (tmp12 + tmp13)*A1;
+ temp[2 + i]= tmp13 + z1;
+ temp[6 + i]= tmp13 - z1;
+
+ tmp10= tmp4 + tmp5;
+ tmp11= tmp5 + tmp6;
+ tmp12= tmp6 + tmp7;
+
+ z5= (tmp10 - tmp12) * A5;
+ z2= tmp10*A2 + z5;
+ z4= tmp12*A4 + z5;
+ z3= tmp11*A1;
+
+ z11= tmp7 + z3;
+ z13= tmp7 - z3;
+
+ temp[5 + i]= z13 + z2;
+ temp[3 + i]= z13 - z2;
+ temp[1 + i]= z11 + z4;
+ temp[7 + i]= z11 - z4;
+ }
+}
+
+void ff_faandct(DCTELEM * data)
+{
+ FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ FLOAT tmp10, tmp11, tmp12, tmp13;
+ FLOAT z1, z2, z3, z4, z5, z11, z13;
+ 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(SCALE(8*0 + i) * (tmp10 + tmp11));
+ data[8*4 + i]= lrintf(SCALE(8*4 + i) * (tmp10 - tmp11));
+
+ z1= (tmp12 + tmp13)* A1;
+ data[8*2 + i]= lrintf(SCALE(8*2 + i) * (tmp13 + z1));
+ data[8*6 + i]= lrintf(SCALE(8*6 + i) * (tmp13 - z1));
+
+ tmp10= tmp4 + tmp5;
+ tmp11= tmp5 + tmp6;
+ tmp12= tmp6 + tmp7;
+
+ z5= (tmp10 - tmp12) * A5;
+ z2= tmp10*A2 + z5;
+ z4= tmp12*A4 + z5;
+ z3= tmp11*A1;
+
+ z11= tmp7 + z3;
+ z13= tmp7 - z3;
+
+ data[8*5 + i]= lrintf(SCALE(8*5 + i) * (z13 + z2));
+ data[8*3 + i]= lrintf(SCALE(8*3 + i) * (z13 - z2));
+ data[8*1 + i]= lrintf(SCALE(8*1 + i) * (z11 + z4));
+ data[8*7 + i]= lrintf(SCALE(8*7 + i) * (z11 - z4));
+ }
+}
+
+void ff_faandct248(DCTELEM * data)
+{
+ FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ FLOAT tmp10, tmp11, tmp12, tmp13;
+ FLOAT z1;
+ 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(SCALE(8*0 + i) * (tmp10 + tmp11));
+ data[8*4 + i] = lrintf(SCALE(8*4 + i) * (tmp10 - tmp11));
+
+ z1 = (tmp12 + tmp13)* A1;
+ data[8*2 + i] = lrintf(SCALE(8*2 + i) * (tmp13 + z1));
+ data[8*6 + i] = lrintf(SCALE(8*6 + i) * (tmp13 - z1));
+
+ tmp10 = tmp4 + tmp7;
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp5 - tmp6;
+ tmp13 = tmp4 - tmp7;
+
+ data[8*1 + i] = lrintf(SCALE(8*0 + i) * (tmp10 + tmp11));
+ data[8*5 + i] = lrintf(SCALE(8*4 + i) * (tmp10 - tmp11));
+
+ z1 = (tmp12 + tmp13)* A1;
+ data[8*3 + i] = lrintf(SCALE(8*2 + i) * (tmp13 + z1));
+ data[8*7 + i] = lrintf(SCALE(8*6 + i) * (tmp13 - z1));
+ }
+}
diff --git a/contrib/ffmpeg/libavcodec/faandct.h b/contrib/ffmpeg/libavcodec/faandct.h
new file mode 100644
index 000000000..77dd41dae
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/faandct.h
@@ -0,0 +1,33 @@
+/*
+ * Floating point AAN DCT
+ * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/**
+ * @file faandct.h
+ * @brief
+ * Floating point AAN DCT
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#define FAAN_POSTSCALE
+
+void ff_faandct(DCTELEM * data);
+void ff_faandct248(DCTELEM * data);
diff --git a/contrib/ffmpeg/libavcodec/fdctref.c b/contrib/ffmpeg/libavcodec/fdctref.c
new file mode 100644
index 000000000..5eff36849
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/fdctref.c
@@ -0,0 +1,158 @@
+/**
+ * @file fdctref.c
+ * forward discrete cosine transform, double precision.
+ */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <math.h>
+
+#ifndef PI
+# ifdef M_PI
+# define PI M_PI
+# else
+# define PI 3.14159265358979323846
+# endif
+#endif
+
+/* global declarations */
+void init_fdct (void);
+void fdct (short *block);
+
+/* private data */
+static double c[8][8]; /* transform coefficients */
+
+void init_fdct()
+{
+ int i, j;
+ double s;
+
+ for (i=0; i<8; i++)
+ {
+ s = (i==0) ? sqrt(0.125) : 0.5;
+
+ for (j=0; j<8; j++)
+ c[i][j] = s * cos((PI/8.0)*i*(j+0.5));
+ }
+}
+
+void fdct(block)
+short *block;
+{
+ register int i, j;
+ double s;
+ double tmp[64];
+
+ for(i = 0; i < 8; i++)
+ for(j = 0; j < 8; j++)
+ {
+ s = 0.0;
+
+/*
+ * for(k = 0; k < 8; k++)
+ * s += c[j][k] * block[8 * i + k];
+ */
+ s += c[j][0] * block[8 * i + 0];
+ s += c[j][1] * block[8 * i + 1];
+ s += c[j][2] * block[8 * i + 2];
+ s += c[j][3] * block[8 * i + 3];
+ s += c[j][4] * block[8 * i + 4];
+ s += c[j][5] * block[8 * i + 5];
+ s += c[j][6] * block[8 * i + 6];
+ s += c[j][7] * block[8 * i + 7];
+
+ tmp[8 * i + j] = s;
+ }
+
+ for(j = 0; j < 8; j++)
+ for(i = 0; i < 8; i++)
+ {
+ s = 0.0;
+
+/*
+ * for(k = 0; k < 8; k++)
+ * s += c[i][k] * tmp[8 * k + j];
+ */
+ s += c[i][0] * tmp[8 * 0 + j];
+ s += c[i][1] * tmp[8 * 1 + j];
+ s += c[i][2] * tmp[8 * 2 + j];
+ s += c[i][3] * tmp[8 * 3 + j];
+ s += c[i][4] * tmp[8 * 4 + j];
+ s += c[i][5] * tmp[8 * 5 + j];
+ s += c[i][6] * tmp[8 * 6 + j];
+ s += c[i][7] * tmp[8 * 7 + j];
+ s*=8.0;
+
+ block[8 * i + j] = (short)floor(s + 0.499999);
+/*
+ * reason for adding 0.499999 instead of 0.5:
+ * s is quite often x.5 (at least for i and/or j = 0 or 4)
+ * and setting the rounding threshold exactly to 0.5 leads to an
+ * extremely high arithmetic implementation dependency of the result;
+ * s being between x.5 and x.500001 (which is now incorrectly rounded
+ * downwards instead of upwards) is assumed to occur less often
+ * (if at all)
+ */
+ }
+}
+
+/* perform IDCT matrix multiply for 8x8 coefficient block */
+
+void idct(block)
+short *block;
+{
+ int i, j, k, v;
+ double partial_product;
+ double tmp[64];
+
+ for (i=0; i<8; i++)
+ for (j=0; j<8; j++)
+ {
+ partial_product = 0.0;
+
+ for (k=0; k<8; k++)
+ partial_product+= c[k][j]*block[8*i+k];
+
+ tmp[8*i+j] = partial_product;
+ }
+
+ /* Transpose operation is integrated into address mapping by switching
+ loop order of i and j */
+
+ for (j=0; j<8; j++)
+ for (i=0; i<8; i++)
+ {
+ partial_product = 0.0;
+
+ for (k=0; k<8; k++)
+ partial_product+= c[k][i]*tmp[8*k+j];
+
+ v = (int) floor(partial_product+0.5);
+ block[8*i+j] = v;
+ }
+}
diff --git a/contrib/ffmpeg/libavcodec/fft-test.c b/contrib/ffmpeg/libavcodec/fft-test.c
new file mode 100644
index 000000000..e108a6f7b
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/fft-test.c
@@ -0,0 +1,297 @@
+/*
+ * (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-test.c
+ * FFT and MDCT tests.
+ */
+
+#include "dsputil.h"
+#include <math.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+int mm_flags;
+
+/* 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));\
+}
+
+FFTComplex *exptab;
+
+void fft_ref_init(int nbits, int inverse)
+{
+ int n, i;
+ float c1, s1, alpha;
+
+ n = 1 << nbits;
+ exptab = av_malloc((n / 2) * sizeof(FFTComplex));
+
+ 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;
+ }
+}
+
+void fft_ref(FFTComplex *tabr, FFTComplex *tab, int nbits)
+{
+ int n, i, j, k, n2;
+ float 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 = tmp_re;
+ tabr[i].im = tmp_im;
+ }
+}
+
+void imdct_ref(float *out, float *in, int n)
+{
+ int k, i, a;
+ float sum, f;
+
+ for(i=0;i<n;i++) {
+ sum = 0;
+ for(k=0;k<n/2;k++) {
+ a = (2 * i + 1 + (n / 2)) * (2 * k + 1);
+ f = cos(M_PI * a / (double)(2 * n));
+ sum += f * in[k];
+ }
+ out[i] = -sum;
+ }
+}
+
+/* NOTE: no normalisation by 1 / N is done */
+void mdct_ref(float *output, float *input, int n)
+{
+ int k, i;
+ float a, s;
+
+ /* do it by hand */
+ for(k=0;k<n/2;k++) {
+ s = 0;
+ for(i=0;i<n;i++) {
+ a = (2*M_PI*(2*i+1+n/2)*(2*k+1) / (4 * n));
+ s += input[i] * cos(a);
+ }
+ output[k] = s;
+ }
+}
+
+
+float frandom(void)
+{
+ return (float)((random() & 0xffff) - 32768) / 32768.0;
+}
+
+int64_t gettime(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
+}
+
+void check_diff(float *tab1, float *tab2, int n)
+{
+ int i;
+
+ for(i=0;i<n;i++) {
+ if (fabsf(tab1[i] - tab2[i]) >= 1e-3) {
+ av_log(NULL, AV_LOG_ERROR, "ERROR %d: %f %f\n",
+ i, tab1[i], tab2[i]);
+ }
+ }
+}
+
+
+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"
+ "-i inverse transform test\n"
+ "-n b set the transform size to 2^b\n"
+ );
+ exit(1);
+}
+
+
+
+int main(int argc, char **argv)
+{
+ FFTComplex *tab, *tab1, *tab_ref;
+ FFTSample *tabtmp, *tab2;
+ int it, i, c;
+ int do_speed = 0;
+ int do_mdct = 0;
+ int do_inverse = 0;
+ FFTContext s1, *s = &s1;
+ MDCTContext m1, *m = &m1;
+ int fft_nbits, fft_size;
+
+ mm_flags = 0;
+ fft_nbits = 9;
+ for(;;) {
+ c = getopt(argc, argv, "hsimn:");
+ if (c == -1)
+ break;
+ switch(c) {
+ case 'h':
+ help();
+ break;
+ case 's':
+ do_speed = 1;
+ break;
+ case 'i':
+ do_inverse = 1;
+ break;
+ case 'm':
+ do_mdct = 1;
+ break;
+ case 'n':
+ fft_nbits = atoi(optarg);
+ 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));
+ tabtmp = av_malloc(fft_size / 2 * sizeof(FFTSample));
+ tab2 = av_malloc(fft_size * sizeof(FFTSample));
+
+ if (do_mdct) {
+ 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);
+ } else {
+ 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);
+ }
+ 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();
+ tab1[i].im = frandom();
+ }
+
+ /* checking result */
+ av_log(NULL, AV_LOG_INFO,"Checking...\n");
+
+ if (do_mdct) {
+ if (do_inverse) {
+ imdct_ref((float *)tab_ref, (float *)tab1, fft_size);
+ ff_imdct_calc(m, tab2, (float *)tab1, tabtmp);
+ check_diff((float *)tab_ref, tab2, fft_size);
+ } else {
+ mdct_ref((float *)tab_ref, (float *)tab1, fft_size);
+
+ ff_mdct_calc(m, tab2, (float *)tab1, tabtmp);
+
+ check_diff((float *)tab_ref, tab2, fft_size / 2);
+ }
+ } else {
+ memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
+ ff_fft_permute(s, tab);
+ ff_fft_calc(s, tab);
+
+ fft_ref(tab_ref, tab1, fft_nbits);
+ check_diff((float *)tab_ref, (float *)tab, fft_size * 2);
+ }
+
+ /* 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 = gettime();
+ for(it=0;it<nb_its;it++) {
+ if (do_mdct) {
+ if (do_inverse) {
+ ff_imdct_calc(m, (float *)tab, (float *)tab1, tabtmp);
+ } else {
+ ff_mdct_calc(m, (float *)tab, (float *)tab1, tabtmp);
+ }
+ } else {
+ memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
+ ff_fft_calc(s, tab);
+ }
+ }
+ duration = 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);
+ }
+
+ if (do_mdct) {
+ ff_mdct_end(m);
+ } else {
+ ff_fft_end(s);
+ }
+ return 0;
+}
diff --git a/contrib/ffmpeg/libavcodec/fft.c b/contrib/ffmpeg/libavcodec/fft.c
new file mode 100644
index 000000000..62a6a5576
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/fft.c
@@ -0,0 +1,262 @@
+/*
+ * FFT/IFFT 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
+ */
+
+/**
+ * @file fft.c
+ * FFT/IFFT transforms.
+ */
+
+#include "dsputil.h"
+
+/**
+ * The size of the FFT is 2^nbits. If inverse is TRUE, inverse FFT is
+ * done
+ */
+int ff_fft_init(FFTContext *s, int nbits, int inverse)
+{
+ int i, j, m, n;
+ float alpha, c1, s1, s2;
+
+ s->nbits = nbits;
+ n = 1 << nbits;
+
+ s->exptab = av_malloc((n / 2) * sizeof(FFTComplex));
+ if (!s->exptab)
+ goto fail;
+ s->revtab = av_malloc(n * sizeof(uint16_t));
+ if (!s->revtab)
+ goto fail;
+ s->inverse = inverse;
+
+ s2 = inverse ? 1.0 : -1.0;
+
+ for(i=0;i<(n/2);i++) {
+ alpha = 2 * M_PI * (float)i / (float)n;
+ c1 = cos(alpha);
+ s1 = sin(alpha) * s2;
+ s->exptab[i].re = c1;
+ s->exptab[i].im = s1;
+ }
+ s->fft_calc = ff_fft_calc_c;
+ s->imdct_calc = ff_imdct_calc;
+ s->exptab1 = NULL;
+
+ /* compute constant table for HAVE_SSE version */
+#if defined(HAVE_MMX) \
+ || (defined(HAVE_ALTIVEC) && !defined(ALTIVEC_USE_REFERENCE_C_CODE))
+ {
+ int has_vectors = mm_support();
+
+ if (has_vectors) {
+#if defined(HAVE_MMX)
+ if (has_vectors & MM_3DNOWEXT) {
+ /* 3DNowEx for K7/K8 */
+ s->imdct_calc = ff_imdct_calc_3dn2;
+ s->fft_calc = ff_fft_calc_3dn2;
+ } else if (has_vectors & MM_3DNOW) {
+ /* 3DNow! for K6-2/3 */
+ s->fft_calc = ff_fft_calc_3dn;
+ } else if (has_vectors & MM_SSE) {
+ /* SSE for P3/P4 */
+ s->imdct_calc = ff_imdct_calc_sse;
+ s->fft_calc = ff_fft_calc_sse;
+ }
+#else /* HAVE_MMX */
+ if (has_vectors & MM_ALTIVEC)
+ s->fft_calc = ff_fft_calc_altivec;
+#endif
+ }
+ if (s->fft_calc != ff_fft_calc_c) {
+ int np, nblocks, np2, l;
+ FFTComplex *q;
+
+ np = 1 << nbits;
+ nblocks = np >> 3;
+ np2 = np >> 1;
+ s->exptab1 = av_malloc(np * 2 * sizeof(FFTComplex));
+ if (!s->exptab1)
+ goto fail;
+ q = s->exptab1;
+ do {
+ for(l = 0; l < np2; l += 2 * nblocks) {
+ *q++ = s->exptab[l];
+ *q++ = s->exptab[l + nblocks];
+
+ q->re = -s->exptab[l].im;
+ q->im = s->exptab[l].re;
+ q++;
+ q->re = -s->exptab[l + nblocks].im;
+ q->im = s->exptab[l + nblocks].re;
+ q++;
+ }
+ nblocks = nblocks >> 1;
+ } while (nblocks != 0);
+ av_freep(&s->exptab);
+ }
+ }
+#endif
+
+ /* compute bit reverse table */
+
+ for(i=0;i<n;i++) {
+ m=0;
+ for(j=0;j<nbits;j++) {
+ m |= ((i >> j) & 1) << (nbits-j-1);
+ }
+ s->revtab[i]=m;
+ }
+ return 0;
+ fail:
+ av_freep(&s->revtab);
+ av_freep(&s->exptab);
+ av_freep(&s->exptab1);
+ return -1;
+}
+
+/* butter fly op */
+#define BF(pre, pim, qre, qim, pre1, pim1, qre1, qim1) \
+{\
+ FFTSample ax, ay, bx, by;\
+ bx=pre1;\
+ by=pim1;\
+ ax=qre1;\
+ ay=qim1;\
+ pre = (bx + ax);\
+ pim = (by + ay);\
+ qre = (bx - ax);\
+ qim = (by - ay);\
+}
+
+#define MUL16(a,b) ((a) * (b))
+
+#define CMUL(pre, pim, are, aim, bre, bim) \
+{\
+ pre = (MUL16(are, bre) - MUL16(aim, bim));\
+ pim = (MUL16(are, bim) + MUL16(bre, aim));\
+}
+
+/**
+ * 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.
+ */
+void ff_fft_calc_c(FFTContext *s, FFTComplex *z)
+{
+ int ln = s->nbits;
+ int j, np, np2;
+ int nblocks, nloops;
+ register FFTComplex *p, *q;
+ FFTComplex *exptab = s->exptab;
+ int l;
+ FFTSample tmp_re, tmp_im;
+
+ np = 1 << ln;
+
+ /* pass 0 */
+
+ p=&z[0];
+ j=(np >> 1);
+ do {
+ BF(p[0].re, p[0].im, p[1].re, p[1].im,
+ p[0].re, p[0].im, p[1].re, p[1].im);
+ p+=2;
+ } while (--j != 0);
+
+ /* pass 1 */
+
+
+ p=&z[0];
+ j=np >> 2;
+ if (s->inverse) {
+ do {
+ BF(p[0].re, p[0].im, p[2].re, p[2].im,
+ p[0].re, p[0].im, p[2].re, p[2].im);
+ BF(p[1].re, p[1].im, p[3].re, p[3].im,
+ p[1].re, p[1].im, -p[3].im, p[3].re);
+ p+=4;
+ } while (--j != 0);
+ } else {
+ do {
+ BF(p[0].re, p[0].im, p[2].re, p[2].im,
+ p[0].re, p[0].im, p[2].re, p[2].im);
+ BF(p[1].re, p[1].im, p[3].re, p[3].im,
+ p[1].re, p[1].im, p[3].im, -p[3].re);
+ p+=4;
+ } while (--j != 0);
+ }
+ /* pass 2 .. ln-1 */
+
+ nblocks = np >> 3;
+ nloops = 1 << 2;
+ np2 = np >> 1;
+ do {
+ p = z;
+ q = z + nloops;
+ for (j = 0; j < nblocks; ++j) {
+ BF(p->re, p->im, q->re, q->im,
+ p->re, p->im, q->re, q->im);
+
+ p++;
+ q++;
+ for(l = nblocks; l < np2; l += nblocks) {
+ CMUL(tmp_re, tmp_im, exptab[l].re, exptab[l].im, q->re, q->im);
+ BF(p->re, p->im, q->re, q->im,
+ p->re, p->im, tmp_re, tmp_im);
+ p++;
+ q++;
+ }
+
+ p += nloops;
+ q += nloops;
+ }
+ nblocks = nblocks >> 1;
+ nloops = nloops << 1;
+ } while (nblocks != 0);
+}
+
+/**
+ * Do the permutation needed BEFORE calling ff_fft_calc()
+ */
+void ff_fft_permute(FFTContext *s, FFTComplex *z)
+{
+ int j, k, np;
+ FFTComplex tmp;
+ const uint16_t *revtab = s->revtab;
+
+ /* reverse */
+ np = 1 << s->nbits;
+ for(j=0;j<np;j++) {
+ k = revtab[j];
+ if (k < j) {
+ tmp = z[k];
+ z[k] = z[j];
+ z[j] = tmp;
+ }
+ }
+}
+
+void ff_fft_end(FFTContext *s)
+{
+ av_freep(&s->revtab);
+ av_freep(&s->exptab);
+ av_freep(&s->exptab1);
+}
+
diff --git a/contrib/ffmpeg/libavcodec/ffv1.c b/contrib/ffmpeg/libavcodec/ffv1.c
new file mode 100644
index 000000000..62623e591
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ffv1.c
@@ -0,0 +1,1040 @@
+/*
+ * FFV1 codec for libavcodec
+ *
+ * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/**
+ * @file ffv1.c
+ * FF Video Codec 1 (an experimental lossless codec)
+ */
+
+#include "common.h"
+#include "bitstream.h"
+#include "avcodec.h"
+#include "dsputil.h"
+#include "rangecoder.h"
+#include "golomb.h"
+
+#define MAX_PLANES 4
+#define CONTEXT_SIZE 32
+
+static const int8_t quant3[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, 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 quant7[256]={
+ 0, 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, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,
+-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,
+-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,
+-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,
+-3,-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,-1,-1,
+};
+static const int8_t quant9[256]={
+ 0, 1, 1, 2, 2, 2, 2, 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,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,
+-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,
+-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,
+-4,-4,-4,-4,-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,-2,-2,-2,-2,-1,-1,
+};
+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 int8_t quant13[256]={
+ 0, 1, 2, 2, 3, 3, 3, 3, 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, 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, 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,-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,-5,
+-5,-5,-5,-5,-5,-5,-5,-5,-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,-3,-3,-3,-3,-2,-2,-1,
+};
+
+static const uint8_t log2_run[32]={
+ 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,
+};
+
+typedef struct VlcState{
+ int16_t drift;
+ uint16_t error_sum;
+ int8_t bias;
+ uint8_t count;
+} VlcState;
+
+typedef struct PlaneContext{
+ int context_count;
+ uint8_t (*state)[CONTEXT_SIZE];
+ VlcState *vlc_state;
+ uint8_t interlace_bit_state[2];
+} PlaneContext;
+
+typedef struct FFV1Context{
+ AVCodecContext *avctx;
+ RangeCoder c;
+ GetBitContext gb;
+ PutBitContext pb;
+ int version;
+ int width, height;
+ int chroma_h_shift, chroma_v_shift;
+ int flags;
+ int picture_number;
+ AVFrame picture;
+ int plane_count;
+ int ac; ///< 1-> CABAC 0-> golomb rice
+ PlaneContext plane[MAX_PLANES];
+ int16_t quant_table[5][256];
+ int run_index;
+ int colorspace;
+
+ DSPContext dsp;
+}FFV1Context;
+
+static 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(int_fast16_t *src, int_fast16_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(FFV1Context *f, int_fast16_t *src, int_fast16_t *last, int_fast16_t *last2){
+ const int LT= last[-1];
+ const int T= last[ 0];
+ const int RT= last[ 1];
+ const int L = src[-1];
+
+ if(f->quant_table[3][127]){
+ const int TT= last2[0];
+ const int LL= src[-2];
+ return f->quant_table[0][(L-LT) & 0xFF] + f->quant_table[1][(LT-T) & 0xFF] + f->quant_table[2][(T-RT) & 0xFF]
+ +f->quant_table[3][(LL-L) & 0xFF] + f->quant_table[4][(TT-T) & 0xFF];
+ }else
+ return f->quant_table[0][(L-LT) & 0xFF] + f->quant_table[1][(LT-T) & 0xFF] + f->quant_table[2][(T-RT) & 0xFF];
+}
+
+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);
+ put_rac(c, state+0, 0);
+
+ assert(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{
+ 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 + e)){ //1..10
+ e++;
+ }
+ assert(e<=9);
+
+ a= 1;
+ for(i=e-1; i>=0; i--){
+ a += a + get_rac(c, state+22 + i); //22..31
+ }
+
+ if(is_signed && get_rac(c, state+11 + e)) //11..21
+ return -a;
+ else
+ return a;
+ }
+}
+
+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;
+}
+
+static inline void put_vlc_symbol(PutBitContext *pb, VlcState * const state, int v, int bits){
+ int i, k, code;
+//printf("final: %d ", v);
+ v = fold(v - state->bias, bits);
+
+ i= state->count;
+ k=0;
+ while(i < state->error_sum){ //FIXME optimize
+ k++;
+ i += i;
+ }
+
+ assert(k<=8);
+
+#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
+
+//printf("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 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;
+ }
+
+ assert(k<=8);
+
+ v= get_sr_golomb(gb, k, 12, bits);
+//printf("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);
+//printf("final: %d\n", ret);
+ return ret;
+}
+
+#ifdef CONFIG_ENCODERS
+static inline int encode_line(FFV1Context *s, int w, int_fast16_t *sample[2], 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 -1;
+ }
+ }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 -1;
+ }
+ }
+
+ for(x=0; x<w; x++){
+ int diff, context;
+
+ context= get_context(s, 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){
+ put_symbol(c, p->state[context], diff, 1);
+ }else{
+ if(context == 0) run_mode=1;
+
+ if(run_mode){
+
+ if(diff){
+ while(run_count >= 1<<log2_run[run_index]){
+ run_count -= 1<<log2_run[run_index];
+ run_index++;
+ put_bits(&s->pb, 1, 1);
+ }
+
+ put_bits(&s->pb, 1 + log2_run[run_index], run_count);
+ if(run_index) run_index--;
+ run_count=0;
+ run_mode=0;
+ if(diff>0) diff--;
+ }else{
+ run_count++;
+ }
+ }
+
+// printf("count:%d index:%d, mode:%d, x:%d y:%d pos:%d\n", run_count, run_index, run_mode, x, y, (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<<log2_run[run_index]){
+ run_count -= 1<<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;
+ int_fast16_t sample_buffer[ring_size][w+6], *sample[ring_size];
+ s->run_index=0;
+
+ memset(sample_buffer, 0, sizeof(sample_buffer));
+
+ for(y=0; y<h; y++){
+ for(i=0; i<ring_size; i++)
+ sample[i]= sample_buffer[(h+i-y)%ring_size]+3;
+
+ sample[0][-1]= sample[1][0 ];
+ sample[1][ w]= sample[1][w-1];
+//{START_TIMER
+ for(x=0; x<w; x++){
+ sample[0][x]= src[x + stride*y];
+ }
+ encode_line(s, w, sample, plane_index, 8);
+//STOP_TIMER("encode line")}
+ }
+}
+
+static void encode_rgb_frame(FFV1Context *s, uint32_t *src, int w, int h, int stride){
+ int x, y, p, i;
+ const int ring_size= s->avctx->context_model ? 3 : 2;
+ int_fast16_t sample_buffer[3][ring_size][w+6], *sample[3][ring_size];
+ s->run_index=0;
+
+ memset(sample_buffer, 0, sizeof(sample_buffer));
+
+ for(y=0; y<h; y++){
+ for(i=0; i<ring_size; i++)
+ for(p=0; p<3; p++)
+ sample[p][i]= sample_buffer[p][(h+i-y)%ring_size]+3;
+
+ for(x=0; x<w; x++){
+ int v= src[x + stride*y];
+ int b= v&0xFF;
+ int g= (v>>8)&0xFF;
+ int r= (v>>16)&0xFF;
+
+ b -= g;
+ r -= g;
+ g += (b + r)>>2;
+ b += 0x100;
+ r += 0x100;
+
+// assert(g>=0 && b>=0 && r>=0);
+// assert(g<256 && b<512 && r<512);
+ sample[0][0][x]= g;
+ sample[1][0][x]= b;
+ sample[2][0][x]= r;
+ }
+ for(p=0; p<3; p++){
+ sample[p][0][-1]= sample[p][1][0 ];
+ sample[p][1][ w]= sample[p][1][w-1];
+ encode_line(s, w, sample[p], FFMIN(p, 1), 9);
+ }
+ }
+}
+
+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_header(FFV1Context *f){
+ uint8_t state[CONTEXT_SIZE];
+ int i;
+ RangeCoder * const c= &f->c;
+
+ memset(state, 128, sizeof(state));
+
+ put_symbol(c, state, f->version, 0);
+ put_symbol(c, state, f->avctx->coder_type, 0);
+ put_symbol(c, state, f->colorspace, 0); //YUV cs type
+ put_rac(c, state, 1); //chroma planes
+ put_symbol(c, state, f->chroma_h_shift, 0);
+ put_symbol(c, state, f->chroma_v_shift, 0);
+ put_rac(c, state, 0); //no transparency plane
+
+ for(i=0; i<5; i++)
+ write_quant_table(c, f->quant_table[i]);
+}
+#endif /* CONFIG_ENCODERS */
+
+static int common_init(AVCodecContext *avctx){
+ FFV1Context *s = avctx->priv_data;
+ int width, height;
+
+ s->avctx= avctx;
+ s->flags= avctx->flags;
+
+ dsputil_init(&s->dsp, avctx);
+
+ width= s->width= avctx->width;
+ height= s->height= avctx->height;
+
+ assert(width && height);
+
+ return 0;
+}
+
+#ifdef CONFIG_ENCODERS
+static int encode_init(AVCodecContext *avctx)
+{
+ FFV1Context *s = avctx->priv_data;
+ int i;
+
+ common_init(avctx);
+
+ s->version=0;
+ s->ac= avctx->coder_type;
+
+ s->plane_count=2;
+ for(i=0; i<256; i++){
+ s->quant_table[0][i]= quant11[i];
+ s->quant_table[1][i]= 11*quant11[i];
+ if(avctx->context_model==0){
+ s->quant_table[2][i]= 11*11*quant11[i];
+ s->quant_table[3][i]=
+ s->quant_table[4][i]=0;
+ }else{
+ s->quant_table[2][i]= 11*11*quant5 [i];
+ s->quant_table[3][i]= 5*11*11*quant5 [i];
+ s->quant_table[4][i]= 5*5*11*11*quant5 [i];
+ }
+ }
+
+ for(i=0; i<s->plane_count; i++){
+ PlaneContext * const p= &s->plane[i];
+
+ if(avctx->context_model==0){
+ p->context_count= (11*11*11+1)/2;
+ }else{
+ p->context_count= (11*11*5*5*5+1)/2;
+ }
+
+ if(s->ac){
+ if(!p->state) p->state= av_malloc(CONTEXT_SIZE*p->context_count*sizeof(uint8_t));
+ }else{
+ if(!p->vlc_state) p->vlc_state= av_malloc(p->context_count*sizeof(VlcState));
+ }
+ }
+
+ avctx->coded_frame= &s->picture;
+ switch(avctx->pix_fmt){
+ case PIX_FMT_YUV444P:
+ case PIX_FMT_YUV422P:
+ case PIX_FMT_YUV420P:
+ case PIX_FMT_YUV411P:
+ case PIX_FMT_YUV410P:
+ s->colorspace= 0;
+ break;
+ case PIX_FMT_RGBA32:
+ s->colorspace= 1;
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "format not supported\n");
+ return -1;
+ }
+ avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_h_shift, &s->chroma_v_shift);
+
+ s->picture_number=0;
+
+ return 0;
+}
+#endif /* CONFIG_ENCODERS */
+
+
+static void clear_state(FFV1Context *f){
+ int i, j;
+
+ for(i=0; i<f->plane_count; i++){
+ PlaneContext *p= &f->plane[i];
+
+ p->interlace_bit_state[0]= 128;
+ p->interlace_bit_state[1]= 128;
+
+ for(j=0; j<p->context_count; j++){
+ if(f->ac){
+ memset(p->state[j], 128, sizeof(uint8_t)*CONTEXT_SIZE);
+ }else{
+ 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;
+ }
+ }
+ }
+}
+
+#ifdef CONFIG_ENCODERS
+static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
+ FFV1Context *f = avctx->priv_data;
+ RangeCoder * const c= &f->c;
+ AVFrame *pict = data;
+ const int width= f->width;
+ const int height= f->height;
+ AVFrame * const p= &f->picture;
+ int used_count= 0;
+ uint8_t keystate=128;
+
+ ff_init_range_encoder(c, buf, buf_size);
+// ff_init_cabac_states(c, ff_h264_lps_range, ff_h264_mps_state, ff_h264_lps_state, 64);
+ ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
+
+ *p = *pict;
+ p->pict_type= FF_I_TYPE;
+
+ if(avctx->gop_size==0 || f->picture_number % avctx->gop_size == 0){
+ put_rac(c, &keystate, 1);
+ p->key_frame= 1;
+ write_header(f);
+ clear_state(f);
+ }else{
+ put_rac(c, &keystate, 0);
+ p->key_frame= 0;
+ }
+
+ if(!f->ac){
+ used_count += ff_rac_terminate(c);
+//printf("pos=%d\n", used_count);
+ init_put_bits(&f->pb, buf + used_count, buf_size - used_count);
+ }
+
+ if(f->colorspace==0){
+ const int chroma_width = -((-width )>>f->chroma_h_shift);
+ const int chroma_height= -((-height)>>f->chroma_v_shift);
+
+ encode_plane(f, p->data[0], width, height, p->linesize[0], 0);
+
+ encode_plane(f, p->data[1], chroma_width, chroma_height, p->linesize[1], 1);
+ encode_plane(f, p->data[2], chroma_width, chroma_height, p->linesize[2], 1);
+ }else{
+ encode_rgb_frame(f, (uint32_t*)(p->data[0]), width, height, p->linesize[0]/4);
+ }
+ emms_c();
+
+ f->picture_number++;
+
+ if(f->ac){
+ return ff_rac_terminate(c);
+ }else{
+ flush_put_bits(&f->pb); //nicer padding FIXME
+ return used_count + (put_bits_count(&f->pb)+7)/8;
+ }
+}
+#endif /* CONFIG_ENCODERS */
+
+static int common_end(AVCodecContext *avctx){
+ FFV1Context *s = avctx->priv_data;
+ int i;
+
+ for(i=0; i<s->plane_count; i++){
+ PlaneContext *p= &s->plane[i];
+
+ av_freep(&p->state);
+ }
+
+ return 0;
+}
+
+static inline void decode_line(FFV1Context *s, int w, int_fast16_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(s, sample[1] + x, sample[0] + x, sample[1] + x);
+ if(context < 0){
+ context= -context;
+ sign=1;
+ }else
+ sign=0;
+
+
+ if(s->ac){
+ diff= get_symbol(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<<log2_run[run_index];
+ if(x + run_count <= w) run_index++;
+ }else{
+ if(log2_run[run_index]) run_count = get_bits(&s->gb, 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);
+
+// printf("count:%d index:%d, mode:%d, x:%d y:%d pos:%d\n", run_count, run_index, run_mode, x, y, 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;
+ int_fast16_t sample_buffer[2][w+6];
+ int_fast16_t *sample[2]= {sample_buffer[0]+3, sample_buffer[1]+3};
+
+ s->run_index=0;
+
+ memset(sample_buffer, 0, sizeof(sample_buffer));
+
+ for(y=0; y<h; y++){
+ int_fast16_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
+ decode_line(s, w, sample, plane_index, 8);
+ for(x=0; x<w; x++){
+ src[x + stride*y]= sample[1][x];
+ }
+//STOP_TIMER("decode-line")}
+ }
+}
+
+static void decode_rgb_frame(FFV1Context *s, uint32_t *src, int w, int h, int stride){
+ int x, y, p;
+ int_fast16_t sample_buffer[3][2][w+6];
+ int_fast16_t *sample[3][2]= {
+ {sample_buffer[0][0]+3, sample_buffer[0][1]+3},
+ {sample_buffer[1][0]+3, sample_buffer[1][1]+3},
+ {sample_buffer[2][0]+3, sample_buffer[2][1]+3}};
+
+ s->run_index=0;
+
+ memset(sample_buffer, 0, sizeof(sample_buffer));
+
+ for(y=0; y<h; y++){
+ for(p=0; p<3; p++){
+ int_fast16_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];
+ decode_line(s, w, sample[p], FFMIN(p, 1), 9);
+ }
+ for(x=0; x<w; x++){
+ int g= sample[0][1][x];
+ int b= sample[1][1][x];
+ int r= sample[2][1][x];
+
+// assert(g>=0 && b>=0 && r>=0);
+// assert(g<256 && b<512 && r<512);
+
+ b -= 0x100;
+ r -= 0x100;
+ g -= (b + r)>>2;
+ b += g;
+ r += g;
+
+ src[x + stride*y]= b + (g<<8) + (r<<16);
+ }
+ }
+}
+
+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++){
+ int len= get_symbol(c, state, 0) + 1;
+
+ if(len + i > 128) return -1;
+
+ while(len--){
+ quant_table[i] = scale*v;
+ i++;
+//printf("%2d ",v);
+//if(i%16==0) printf("\n");
+ }
+ }
+
+ 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_header(FFV1Context *f){
+ uint8_t state[CONTEXT_SIZE];
+ int i, context_count;
+ RangeCoder * const c= &f->c;
+
+ memset(state, 128, sizeof(state));
+
+ f->version= get_symbol(c, state, 0);
+ f->ac= f->avctx->coder_type= get_symbol(c, state, 0);
+ f->colorspace= get_symbol(c, state, 0); //YUV cs type
+ get_rac(c, state); //no chroma = false
+ f->chroma_h_shift= get_symbol(c, state, 0);
+ f->chroma_v_shift= get_symbol(c, state, 0);
+ get_rac(c, state); //transparency plane
+ f->plane_count= 2;
+
+ if(f->colorspace==0){
+ switch(16*f->chroma_h_shift + f->chroma_v_shift){
+ case 0x00: f->avctx->pix_fmt= PIX_FMT_YUV444P; break;
+ case 0x10: f->avctx->pix_fmt= PIX_FMT_YUV422P; break;
+ case 0x11: f->avctx->pix_fmt= PIX_FMT_YUV420P; break;
+ case 0x20: f->avctx->pix_fmt= PIX_FMT_YUV411P; break;
+ case 0x22: f->avctx->pix_fmt= PIX_FMT_YUV410P; break;
+ default:
+ av_log(f->avctx, AV_LOG_ERROR, "format not supported\n");
+ return -1;
+ }
+ }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 -1;
+ }
+ f->avctx->pix_fmt= PIX_FMT_RGBA32;
+ }else{
+ av_log(f->avctx, AV_LOG_ERROR, "colorspace not supported\n");
+ return -1;
+ }
+
+//printf("%d %d %d\n", f->chroma_h_shift, f->chroma_v_shift,f->avctx->pix_fmt);
+
+ context_count=1;
+ for(i=0; i<5; i++){
+ context_count*= read_quant_table(c, f->quant_table[i], context_count);
+ if(context_count < 0 || context_count > 32768){
+ av_log(f->avctx, AV_LOG_ERROR, "read_quant_table error\n");
+ return -1;
+ }
+ }
+ context_count= (context_count+1)/2;
+
+ for(i=0; i<f->plane_count; i++){
+ PlaneContext * const p= &f->plane[i];
+
+ p->context_count= context_count;
+
+ if(f->ac){
+ if(!p->state) p->state= av_malloc(CONTEXT_SIZE*p->context_count*sizeof(uint8_t));
+ }else{
+ if(!p->vlc_state) p->vlc_state= av_malloc(p->context_count*sizeof(VlcState));
+ }
+ }
+
+ return 0;
+}
+
+static int decode_init(AVCodecContext *avctx)
+{
+// FFV1Context *s = avctx->priv_data;
+
+ common_init(avctx);
+
+ return 0;
+}
+
+static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size){
+ FFV1Context *f = avctx->priv_data;
+ RangeCoder * const c= &f->c;
+ const int width= f->width;
+ const int height= f->height;
+ AVFrame * const p= &f->picture;
+ int bytes_read;
+ uint8_t keystate= 128;
+
+ AVFrame *picture = data;
+
+ ff_init_range_decoder(c, buf, buf_size);
+ ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
+
+
+ p->pict_type= FF_I_TYPE; //FIXME I vs. P
+ if(get_rac(c, &keystate)){
+ p->key_frame= 1;
+ if(read_header(f) < 0)
+ return -1;
+ clear_state(f);
+ }else{
+ p->key_frame= 0;
+ }
+ if(!f->plane[0].state && !f->plane[0].vlc_state)
+ return -1;
+
+ p->reference= 0;
+ if(avctx->get_buffer(avctx, p) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ if(avctx->debug&FF_DEBUG_PICT_INFO)
+ av_log(avctx, AV_LOG_ERROR, "keyframe:%d coder:%d\n", p->key_frame, f->ac);
+
+ if(!f->ac){
+ bytes_read = c->bytestream - c->bytestream_start - 1;
+ if(bytes_read ==0) av_log(avctx, AV_LOG_ERROR, "error at end of AC stream\n"); //FIXME
+//printf("pos=%d\n", bytes_read);
+ init_get_bits(&f->gb, buf + bytes_read, buf_size - bytes_read);
+ } else {
+ bytes_read = 0; /* avoid warning */
+ }
+
+ if(f->colorspace==0){
+ const int chroma_width = -((-width )>>f->chroma_h_shift);
+ const int chroma_height= -((-height)>>f->chroma_v_shift);
+ decode_plane(f, p->data[0], width, height, p->linesize[0], 0);
+
+ decode_plane(f, p->data[1], chroma_width, chroma_height, p->linesize[1], 1);
+ decode_plane(f, p->data[2], chroma_width, chroma_height, p->linesize[2], 1);
+ }else{
+ decode_rgb_frame(f, (uint32_t*)p->data[0], width, height, p->linesize[0]/4);
+ }
+
+ emms_c();
+
+ f->picture_number++;
+
+ *picture= *p;
+
+ avctx->release_buffer(avctx, p); //FIXME
+
+ *data_size = sizeof(AVFrame);
+
+ if(f->ac){
+ bytes_read= c->bytestream - c->bytestream_start - 1;
+ if(bytes_read ==0) av_log(f->avctx, AV_LOG_ERROR, "error at end of frame\n");
+ }else{
+ bytes_read+= (get_bits_count(&f->gb)+7)/8;
+ }
+
+ return bytes_read;
+}
+
+AVCodec ffv1_decoder = {
+ "ffv1",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_FFV1,
+ sizeof(FFV1Context),
+ decode_init,
+ NULL,
+ common_end,
+ decode_frame,
+ CODEC_CAP_DR1 /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
+ NULL
+};
+
+#ifdef CONFIG_ENCODERS
+AVCodec ffv1_encoder = {
+ "ffv1",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_FFV1,
+ sizeof(FFV1Context),
+ encode_init,
+ encode_frame,
+ common_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV444P, PIX_FMT_YUV422P, PIX_FMT_YUV411P, PIX_FMT_YUV410P, PIX_FMT_RGBA32, -1},
+};
+#endif
diff --git a/contrib/ffmpeg/libavcodec/flac.c b/contrib/ffmpeg/libavcodec/flac.c
new file mode 100644
index 000000000..6c64ad0a1
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/flac.c
@@ -0,0 +1,752 @@
+/*
+ * 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.c
+ * FLAC (Free Lossless Audio Codec) decoder
+ * @author Alex Beregszaszi
+ *
+ * For more information on the FLAC format, visit:
+ * 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 <limits.h>
+
+#define ALT_BITSTREAM_READER
+#include "avcodec.h"
+#include "bitstream.h"
+#include "golomb.h"
+#include "crc.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+#define MAX_CHANNELS 8
+#define MAX_BLOCKSIZE 65535
+#define FLAC_STREAMINFO_SIZE 34
+
+enum decorrelation_type {
+ INDEPENDENT,
+ LEFT_SIDE,
+ RIGHT_SIDE,
+ MID_SIDE,
+};
+
+typedef struct FLACContext {
+ AVCodecContext *avctx;
+ GetBitContext gb;
+
+ int min_blocksize, max_blocksize;
+ int min_framesize, max_framesize;
+ int samplerate, channels;
+ int blocksize/*, last_blocksize*/;
+ int bps, curr_bps;
+ enum decorrelation_type decorrelation;
+
+ int32_t *decoded[MAX_CHANNELS];
+ uint8_t *bitstream;
+ int bitstream_size;
+ int bitstream_index;
+ unsigned int allocated_bitstream_size;
+} FLACContext;
+
+#define METADATA_TYPE_STREAMINFO 0
+
+static int sample_rate_table[] =
+{ 0, 0, 0, 0,
+ 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
+ 0, 0, 0, 0 };
+
+static int sample_size_table[] =
+{ 0, 8, 12, 0, 16, 20, 24, 0 };
+
+static int blocksize_table[] = {
+ 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
+};
+
+static int64_t get_utf8(GetBitContext *gb){
+ int64_t val;
+ GET_UTF8(val, get_bits(gb, 8), return -1;)
+ return val;
+}
+
+static void metadata_streaminfo(FLACContext *s);
+static void allocate_buffers(FLACContext *s);
+static int metadata_parse(FLACContext *s);
+
+static int flac_decode_init(AVCodecContext * avctx)
+{
+ FLACContext *s = avctx->priv_data;
+ s->avctx = avctx;
+
+ if (avctx->extradata_size > 4) {
+ /* initialize based on the demuxer-supplied streamdata header */
+ init_get_bits(&s->gb, avctx->extradata, avctx->extradata_size*8);
+ if (avctx->extradata_size == FLAC_STREAMINFO_SIZE) {
+ metadata_streaminfo(s);
+ allocate_buffers(s);
+ } else {
+ metadata_parse(s);
+ }
+ }
+
+ return 0;
+}
+
+static void dump_headers(FLACContext *s)
+{
+ av_log(s->avctx, AV_LOG_DEBUG, " Blocksize: %d .. %d (%d)\n", s->min_blocksize, s->max_blocksize, s->blocksize);
+ av_log(s->avctx, AV_LOG_DEBUG, " Framesize: %d .. %d\n", s->min_framesize, s->max_framesize);
+ av_log(s->avctx, AV_LOG_DEBUG, " Samplerate: %d\n", s->samplerate);
+ av_log(s->avctx, AV_LOG_DEBUG, " Channels: %d\n", s->channels);
+ av_log(s->avctx, AV_LOG_DEBUG, " Bits: %d\n", s->bps);
+}
+
+static void allocate_buffers(FLACContext *s){
+ int i;
+
+ assert(s->max_blocksize);
+
+ if(s->max_framesize == 0 && s->max_blocksize){
+ s->max_framesize= (s->channels * s->bps * s->max_blocksize + 7)/ 8; //FIXME header overhead
+ }
+
+ for (i = 0; i < s->channels; i++)
+ {
+ s->decoded[i] = av_realloc(s->decoded[i], sizeof(int32_t)*s->max_blocksize);
+ }
+
+ s->bitstream= av_fast_realloc(s->bitstream, &s->allocated_bitstream_size, s->max_framesize);
+}
+
+static void metadata_streaminfo(FLACContext *s)
+{
+ /* mandatory streaminfo */
+ s->min_blocksize = get_bits(&s->gb, 16);
+ s->max_blocksize = get_bits(&s->gb, 16);
+
+ s->min_framesize = get_bits_long(&s->gb, 24);
+ s->max_framesize = get_bits_long(&s->gb, 24);
+
+ s->samplerate = get_bits_long(&s->gb, 20);
+ s->channels = get_bits(&s->gb, 3) + 1;
+ s->bps = get_bits(&s->gb, 5) + 1;
+
+ s->avctx->channels = s->channels;
+ s->avctx->sample_rate = s->samplerate;
+
+ skip_bits(&s->gb, 36); /* total num of samples */
+
+ skip_bits(&s->gb, 64); /* md5 sum */
+ skip_bits(&s->gb, 64); /* md5 sum */
+
+ dump_headers(s);
+}
+
+/**
+ * Parse a list of metadata blocks. This list of blocks must begin with
+ * the fLaC marker.
+ * @param s the flac decoding context containing the gb bit reader used to
+ * parse metadata
+ * @return 1 if some metadata was read, 0 if no fLaC marker was found
+ */
+static int metadata_parse(FLACContext *s)
+{
+ int i, metadata_last, metadata_type, metadata_size, streaminfo_updated=0;
+
+ if (show_bits_long(&s->gb, 32) == MKBETAG('f','L','a','C')) {
+ skip_bits(&s->gb, 32);
+
+ av_log(s->avctx, AV_LOG_DEBUG, "STREAM HEADER\n");
+ do {
+ metadata_last = get_bits(&s->gb, 1);
+ metadata_type = get_bits(&s->gb, 7);
+ metadata_size = get_bits_long(&s->gb, 24);
+
+ av_log(s->avctx, AV_LOG_DEBUG,
+ " metadata block: flag = %d, type = %d, size = %d\n",
+ metadata_last, metadata_type, metadata_size);
+ if (metadata_size) {
+ switch (metadata_type) {
+ case METADATA_TYPE_STREAMINFO:
+ metadata_streaminfo(s);
+ streaminfo_updated = 1;
+ break;
+
+ default:
+ for (i=0; i<metadata_size; i++)
+ skip_bits(&s->gb, 8);
+ }
+ }
+ } while (!metadata_last);
+
+ if (streaminfo_updated)
+ allocate_buffers(s);
+ return 1;
+ }
+ return 0;
+}
+
+static int decode_residuals(FLACContext *s, int channel, int pred_order)
+{
+ int i, tmp, partition, method_type, rice_order;
+ int sample = 0, samples;
+
+ method_type = get_bits(&s->gb, 2);
+ if (method_type != 0){
+ av_log(s->avctx, AV_LOG_DEBUG, "illegal residual coding method %d\n", method_type);
+ return -1;
+ }
+
+ rice_order = get_bits(&s->gb, 4);
+
+ samples= s->blocksize >> rice_order;
+
+ sample=
+ i= pred_order;
+ for (partition = 0; partition < (1 << rice_order); partition++)
+ {
+ tmp = get_bits(&s->gb, 4);
+ if (tmp == 15)
+ {
+ av_log(s->avctx, AV_LOG_DEBUG, "fixed len partition\n");
+ tmp = get_bits(&s->gb, 5);
+ for (; i < samples; i++, sample++)
+ s->decoded[channel][sample] = get_sbits(&s->gb, tmp);
+ }
+ else
+ {
+// av_log(s->avctx, AV_LOG_DEBUG, "rice coded partition k=%d\n", tmp);
+ for (; i < samples; i++, sample++){
+ s->decoded[channel][sample] = get_sr_golomb_flac(&s->gb, tmp, INT_MAX, 0);
+ }
+ }
+ i= 0;
+ }
+
+// av_log(s->avctx, AV_LOG_DEBUG, "partitions: %d, samples: %d\n", 1 << rice_order, sample);
+
+ return 0;
+}
+
+static int decode_subframe_fixed(FLACContext *s, int channel, int pred_order)
+{
+ int i;
+
+// av_log(s->avctx, AV_LOG_DEBUG, " SUBFRAME FIXED\n");
+
+ /* warm up samples */
+// av_log(s->avctx, AV_LOG_DEBUG, " warm up samples: %d\n", pred_order);
+
+ for (i = 0; i < pred_order; i++)
+ {
+ s->decoded[channel][i] = get_sbits(&s->gb, s->curr_bps);
+// av_log(s->avctx, AV_LOG_DEBUG, " %d: %d\n", i, s->decoded[channel][i]);
+ }
+
+ if (decode_residuals(s, channel, pred_order) < 0)
+ return -1;
+
+ switch(pred_order)
+ {
+ case 0:
+ break;
+ case 1:
+ for (i = pred_order; i < s->blocksize; i++)
+ s->decoded[channel][i] += s->decoded[channel][i-1];
+ break;
+ case 2:
+ for (i = pred_order; i < s->blocksize; i++)
+ s->decoded[channel][i] += 2*s->decoded[channel][i-1]
+ - s->decoded[channel][i-2];
+ break;
+ case 3:
+ for (i = pred_order; i < s->blocksize; i++)
+ s->decoded[channel][i] += 3*s->decoded[channel][i-1]
+ - 3*s->decoded[channel][i-2]
+ + s->decoded[channel][i-3];
+ break;
+ case 4:
+ for (i = pred_order; i < s->blocksize; i++)
+ s->decoded[channel][i] += 4*s->decoded[channel][i-1]
+ - 6*s->decoded[channel][i-2]
+ + 4*s->decoded[channel][i-3]
+ - s->decoded[channel][i-4];
+ 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, int channel, int pred_order)
+{
+ int i, j;
+ int coeff_prec, qlevel;
+ int coeffs[pred_order];
+
+// av_log(s->avctx, AV_LOG_DEBUG, " SUBFRAME LPC\n");
+
+ /* warm up samples */
+// av_log(s->avctx, AV_LOG_DEBUG, " warm up samples: %d\n", pred_order);
+
+ for (i = 0; i < pred_order; i++)
+ {
+ s->decoded[channel][i] = get_sbits(&s->gb, s->curr_bps);
+// av_log(s->avctx, AV_LOG_DEBUG, " %d: %d\n", i, s->decoded[channel][i]);
+ }
+
+ coeff_prec = get_bits(&s->gb, 4) + 1;
+ if (coeff_prec == 16)
+ {
+ av_log(s->avctx, AV_LOG_DEBUG, "invalid coeff precision\n");
+ return -1;
+ }
+// av_log(s->avctx, AV_LOG_DEBUG, " qlp coeff prec: %d\n", coeff_prec);
+ qlevel = get_sbits(&s->gb, 5);
+// av_log(s->avctx, AV_LOG_DEBUG, " quant level: %d\n", qlevel);
+ if(qlevel < 0){
+ av_log(s->avctx, AV_LOG_DEBUG, "qlevel %d not supported, maybe buggy stream\n", qlevel);
+ return -1;
+ }
+
+ for (i = 0; i < pred_order; i++)
+ {
+ coeffs[i] = get_sbits(&s->gb, coeff_prec);
+// av_log(s->avctx, AV_LOG_DEBUG, " %d: %d\n", i, coeffs[i]);
+ }
+
+ if (decode_residuals(s, channel, pred_order) < 0)
+ return -1;
+
+ if (s->bps > 16) {
+ int64_t sum;
+ for (i = pred_order; i < s->blocksize; i++)
+ {
+ sum = 0;
+ for (j = 0; j < pred_order; j++)
+ sum += (int64_t)coeffs[j] * s->decoded[channel][i-j-1];
+ s->decoded[channel][i] += sum >> qlevel;
+ }
+ } else {
+ int sum;
+ for (i = pred_order; i < s->blocksize; i++)
+ {
+ sum = 0;
+ for (j = 0; j < pred_order; j++)
+ sum += coeffs[j] * s->decoded[channel][i-j-1];
+ s->decoded[channel][i] += sum >> qlevel;
+ }
+ }
+
+ return 0;
+}
+
+static inline int decode_subframe(FLACContext *s, int channel)
+{
+ int type, wasted = 0;
+ int i, tmp;
+
+ s->curr_bps = s->bps;
+ if(channel == 0){
+ if(s->decorrelation == RIGHT_SIDE)
+ s->curr_bps++;
+ }else{
+ if(s->decorrelation == LEFT_SIDE || s->decorrelation == MID_SIDE)
+ s->curr_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);
+// wasted = get_bits1(&s->gb);
+
+// if (wasted)
+// {
+// while (!get_bits1(&s->gb))
+// wasted++;
+// if (wasted)
+// wasted++;
+// s->curr_bps -= wasted;
+// }
+#if 0
+ wasted= 16 - av_log2(show_bits(&s->gb, 17));
+ skip_bits(&s->gb, wasted+1);
+ s->curr_bps -= wasted;
+#else
+ if (get_bits1(&s->gb))
+ {
+ wasted = 1;
+ while (!get_bits1(&s->gb))
+ wasted++;
+ s->curr_bps -= wasted;
+ av_log(s->avctx, AV_LOG_DEBUG, "%d wasted bits\n", wasted);
+ }
+#endif
+//FIXME use av_log2 for types
+ if (type == 0)
+ {
+ av_log(s->avctx, AV_LOG_DEBUG, "coding type: constant\n");
+ tmp = get_sbits(&s->gb, s->curr_bps);
+ for (i = 0; i < s->blocksize; i++)
+ s->decoded[channel][i] = tmp;
+ }
+ else if (type == 1)
+ {
+ av_log(s->avctx, AV_LOG_DEBUG, "coding type: verbatim\n");
+ for (i = 0; i < s->blocksize; i++)
+ s->decoded[channel][i] = get_sbits(&s->gb, s->curr_bps);
+ }
+ else if ((type >= 8) && (type <= 12))
+ {
+// av_log(s->avctx, AV_LOG_DEBUG, "coding type: fixed\n");
+ if (decode_subframe_fixed(s, channel, type & ~0x8) < 0)
+ return -1;
+ }
+ else if (type >= 32)
+ {
+// av_log(s->avctx, AV_LOG_DEBUG, "coding type: lpc\n");
+ if (decode_subframe_lpc(s, channel, (type & ~0x20)+1) < 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++)
+ s->decoded[channel][i] <<= wasted;
+ }
+
+ return 0;
+}
+
+static int decode_frame(FLACContext *s)
+{
+ int blocksize_code, sample_rate_code, sample_size_code, assignment, i, crc8;
+ int decorrelation, bps, blocksize, samplerate;
+
+ blocksize_code = get_bits(&s->gb, 4);
+
+ sample_rate_code = get_bits(&s->gb, 4);
+
+ assignment = get_bits(&s->gb, 4); /* channel assignment */
+ if (assignment < 8 && s->channels == assignment+1)
+ decorrelation = INDEPENDENT;
+ else if (assignment >=8 && assignment < 11 && s->channels == 2)
+ decorrelation = LEFT_SIDE + assignment - 8;
+ else
+ {
+ av_log(s->avctx, AV_LOG_ERROR, "unsupported channel assignment %d (channels=%d)\n", assignment, s->channels);
+ return -1;
+ }
+
+ sample_size_code = get_bits(&s->gb, 3);
+ if(sample_size_code == 0)
+ bps= s->bps;
+ else if((sample_size_code != 3) && (sample_size_code != 7))
+ bps = sample_size_table[sample_size_code];
+ else
+ {
+ av_log(s->avctx, AV_LOG_ERROR, "invalid sample size code (%d)\n", sample_size_code);
+ return -1;
+ }
+
+ if (get_bits1(&s->gb))
+ {
+ av_log(s->avctx, AV_LOG_ERROR, "broken stream, invalid padding\n");
+ return -1;
+ }
+
+ if(get_utf8(&s->gb) < 0){
+ av_log(s->avctx, AV_LOG_ERROR, "utf8 fscked\n");
+ return -1;
+ }
+#if 0
+ if (/*((blocksize_code == 6) || (blocksize_code == 7)) &&*/
+ (s->min_blocksize != s->max_blocksize)){
+ }else{
+ }
+#endif
+
+ if (blocksize_code == 0)
+ blocksize = s->min_blocksize;
+ else if (blocksize_code == 6)
+ blocksize = get_bits(&s->gb, 8)+1;
+ else if (blocksize_code == 7)
+ blocksize = get_bits(&s->gb, 16)+1;
+ else
+ blocksize = blocksize_table[blocksize_code];
+
+ if(blocksize > s->max_blocksize){
+ av_log(s->avctx, AV_LOG_ERROR, "blocksize %d > %d\n", blocksize, s->max_blocksize);
+ return -1;
+ }
+
+ if (sample_rate_code == 0){
+ samplerate= s->samplerate;
+ }else if ((sample_rate_code > 3) && (sample_rate_code < 12))
+ samplerate = sample_rate_table[sample_rate_code];
+ else if (sample_rate_code == 12)
+ samplerate = get_bits(&s->gb, 8) * 1000;
+ else if (sample_rate_code == 13)
+ samplerate = get_bits(&s->gb, 16);
+ else if (sample_rate_code == 14)
+ samplerate = get_bits(&s->gb, 16) * 10;
+ else{
+ av_log(s->avctx, AV_LOG_ERROR, "illegal sample rate code %d\n", sample_rate_code);
+ return -1;
+ }
+
+ skip_bits(&s->gb, 8);
+ crc8= av_crc(av_crc07, 0, s->gb.buffer, get_bits_count(&s->gb)/8);
+ if(crc8){
+ av_log(s->avctx, AV_LOG_ERROR, "header crc mismatch crc=%2X\n", crc8);
+ return -1;
+ }
+
+ s->blocksize = blocksize;
+ s->samplerate = samplerate;
+ s->bps = bps;
+ s->decorrelation= decorrelation;
+
+// dump_headers(s);
+
+ /* subframes */
+ for (i = 0; i < s->channels; i++)
+ {
+// av_log(s->avctx, AV_LOG_DEBUG, "decoded: %x residual: %x\n", s->decoded[i], s->residual[i]);
+ if (decode_subframe(s, i) < 0)
+ return -1;
+ }
+
+ align_get_bits(&s->gb);
+
+ /* frame footer */
+ skip_bits(&s->gb, 16); /* data crc */
+
+ return 0;
+}
+
+static inline int16_t shift_to_16_bits(int32_t data, int bps)
+{
+ if (bps == 24) {
+ return (data >> 8);
+ } else if (bps == 20) {
+ return (data >> 4);
+ } else {
+ return data;
+ }
+}
+
+static int flac_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ FLACContext *s = avctx->priv_data;
+ int tmp = 0, i, j = 0, input_buf_size = 0;
+ int16_t *samples = data;
+
+ if(s->max_framesize == 0){
+ s->max_framesize= 65536; // should hopefully be enough for the first header
+ s->bitstream= av_fast_realloc(s->bitstream, &s->allocated_bitstream_size, s->max_framesize);
+ }
+
+ if(1 && s->max_framesize){//FIXME truncated
+ buf_size= FFMAX(FFMIN(buf_size, s->max_framesize - s->bitstream_size), 0);
+ input_buf_size= buf_size;
+
+ if(s->bitstream_index + s->bitstream_size + buf_size > s->allocated_bitstream_size){
+// printf("memmove\n");
+ memmove(s->bitstream, &s->bitstream[s->bitstream_index], s->bitstream_size);
+ s->bitstream_index=0;
+ }
+ 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;
+
+ if(buf_size < s->max_framesize){
+// printf("wanna more data ...\n");
+ return input_buf_size;
+ }
+ }
+
+ init_get_bits(&s->gb, buf, buf_size*8);
+
+ if (!metadata_parse(s))
+ {
+ tmp = show_bits(&s->gb, 16);
+ if(tmp != 0xFFF8){
+ av_log(s->avctx, AV_LOG_ERROR, "FRAME HEADER not here\n");
+ while(get_bits_count(&s->gb)/8+2 < buf_size && show_bits(&s->gb, 16) != 0xFFF8)
+ skip_bits(&s->gb, 8);
+ goto end; // we may not have enough bits left to decode a frame, so try next time
+ }
+ skip_bits(&s->gb, 16);
+ if (decode_frame(s) < 0){
+ av_log(s->avctx, AV_LOG_ERROR, "decode_frame() failed\n");
+ s->bitstream_size=0;
+ s->bitstream_index=0;
+ return -1;
+ }
+ }
+
+
+#if 0
+ /* fix the channel order here */
+ if (s->order == MID_SIDE)
+ {
+ short *left = samples;
+ short *right = samples + s->blocksize;
+ for (i = 0; i < s->blocksize; i += 2)
+ {
+ uint32_t x = s->decoded[0][i];
+ uint32_t y = s->decoded[0][i+1];
+
+ right[i] = x - (y / 2);
+ left[i] = right[i] + y;
+ }
+ *data_size = 2 * s->blocksize;
+ }
+ else
+ {
+ for (i = 0; i < s->channels; i++)
+ {
+ switch(s->order)
+ {
+ case INDEPENDENT:
+ for (j = 0; j < s->blocksize; j++)
+ samples[(s->blocksize*i)+j] = s->decoded[i][j];
+ break;
+ case LEFT_SIDE:
+ case RIGHT_SIDE:
+ if (i == 0)
+ for (j = 0; j < s->blocksize; j++)
+ samples[(s->blocksize*i)+j] = s->decoded[0][j];
+ else
+ for (j = 0; j < s->blocksize; j++)
+ samples[(s->blocksize*i)+j] = s->decoded[0][j] - s->decoded[i][j];
+ break;
+// case MID_SIDE:
+// av_log(s->avctx, AV_LOG_DEBUG, "mid-side unsupported\n");
+ }
+ *data_size += s->blocksize;
+ }
+ }
+#else
+#define DECORRELATE(left, right)\
+ assert(s->channels == 2);\
+ for (i = 0; i < s->blocksize; i++)\
+ {\
+ int a= s->decoded[0][i];\
+ int b= s->decoded[1][i];\
+ *(samples++) = (left ) >> (16 - s->bps);\
+ *(samples++) = (right) >> (16 - s->bps);\
+ }\
+ break;
+
+ switch(s->decorrelation)
+ {
+ case INDEPENDENT:
+ for (j = 0; j < s->blocksize; j++)
+ {
+ for (i = 0; i < s->channels; i++)
+ *(samples++) = shift_to_16_bits(s->decoded[i][j], s->bps);
+ }
+ break;
+ case LEFT_SIDE:
+ DECORRELATE(a,a-b)
+ case RIGHT_SIDE:
+ DECORRELATE(a+b,b)
+ case MID_SIDE:
+ DECORRELATE( (a-=b>>1) + b, a)
+ }
+#endif
+
+ *data_size = (int8_t *)samples - (int8_t *)data;
+// av_log(s->avctx, AV_LOG_DEBUG, "data size: %d\n", *data_size);
+
+// s->last_blocksize = s->blocksize;
+end:
+ i= (get_bits_count(&s->gb)+7)/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 -1;
+ }
+
+ if(s->bitstream_size){
+ s->bitstream_index += i;
+ s->bitstream_size -= i;
+ return input_buf_size;
+ }else
+ return i;
+}
+
+static int flac_decode_close(AVCodecContext *avctx)
+{
+ FLACContext *s = avctx->priv_data;
+ int i;
+
+ for (i = 0; i < s->channels; i++)
+ {
+ av_freep(&s->decoded[i]);
+ }
+ av_freep(&s->bitstream);
+
+ return 0;
+}
+
+static void flac_flush(AVCodecContext *avctx){
+ FLACContext *s = avctx->priv_data;
+
+ s->bitstream_size=
+ s->bitstream_index= 0;
+}
+
+AVCodec flac_decoder = {
+ "flac",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_FLAC,
+ sizeof(FLACContext),
+ flac_decode_init,
+ NULL,
+ flac_decode_close,
+ flac_decode_frame,
+ .flush= flac_flush,
+};
diff --git a/contrib/ffmpeg/libavcodec/flacenc.c b/contrib/ffmpeg/libavcodec/flacenc.c
new file mode 100644
index 000000000..b7b7d0d8e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/flacenc.c
@@ -0,0 +1,1371 @@
+/**
+ * FLAC audio encoder
+ * Copyright (c) 2006 Justin Ruggles <jruggle@earthlink.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 "bitstream.h"
+#include "crc.h"
+#include "golomb.h"
+#include "lls.h"
+
+#define FLAC_MAX_CH 8
+#define FLAC_MIN_BLOCKSIZE 16
+#define FLAC_MAX_BLOCKSIZE 65535
+
+#define FLAC_SUBFRAME_CONSTANT 0
+#define FLAC_SUBFRAME_VERBATIM 1
+#define FLAC_SUBFRAME_FIXED 8
+#define FLAC_SUBFRAME_LPC 32
+
+#define FLAC_CHMODE_NOT_STEREO 0
+#define FLAC_CHMODE_LEFT_RIGHT 1
+#define FLAC_CHMODE_LEFT_SIDE 8
+#define FLAC_CHMODE_RIGHT_SIDE 9
+#define FLAC_CHMODE_MID_SIDE 10
+
+#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 FLAC_STREAMINFO_SIZE 34
+
+#define MIN_LPC_ORDER 1
+#define MAX_LPC_ORDER 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
+#define MAX_RICE_PARAM 14
+
+typedef struct CompressionOptions {
+ int compression_level;
+ int block_time_ms;
+ int use_lpc;
+ int lpc_coeff_precision;
+ int min_prediction_order;
+ int max_prediction_order;
+ int prediction_order_method;
+ int min_partition_order;
+ int max_partition_order;
+} CompressionOptions;
+
+typedef struct RiceContext {
+ int porder;
+ int params[MAX_PARTITIONS];
+} RiceContext;
+
+typedef struct FlacSubframe {
+ int type;
+ int type_code;
+ int obits;
+ int order;
+ int32_t coefs[MAX_LPC_ORDER];
+ int shift;
+ RiceContext rc;
+ int32_t samples[FLAC_MAX_BLOCKSIZE];
+ int32_t residual[FLAC_MAX_BLOCKSIZE];
+} FlacSubframe;
+
+typedef struct FlacFrame {
+ FlacSubframe subframes[FLAC_MAX_CH];
+ int blocksize;
+ int bs_code[2];
+ uint8_t crc8;
+ int ch_mode;
+} FlacFrame;
+
+typedef struct FlacEncodeContext {
+ PutBitContext pb;
+ int channels;
+ int ch_code;
+ int samplerate;
+ int sr_code[2];
+ int blocksize;
+ int max_framesize;
+ uint32_t frame_count;
+ FlacFrame frame;
+ CompressionOptions options;
+ AVCodecContext *avctx;
+} FlacEncodeContext;
+
+static const int flac_samplerates[16] = {
+ 0, 0, 0, 0,
+ 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
+ 0, 0, 0, 0
+};
+
+static const int flac_blocksizes[16] = {
+ 0,
+ 192,
+ 576, 1152, 2304, 4608,
+ 0, 0,
+ 256, 512, 1024, 2048, 4096, 8192, 16384, 32768
+};
+
+/**
+ * Writes 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->blocksize);
+ put_bits(&pb, 16, s->blocksize);
+ put_bits(&pb, 24, 0);
+ put_bits(&pb, 24, s->max_framesize);
+ put_bits(&pb, 20, s->samplerate);
+ put_bits(&pb, 3, s->channels-1);
+ put_bits(&pb, 5, 15); /* bits per sample - 1 */
+ flush_put_bits(&pb);
+ /* total samples = 0 */
+ /* MD5 signature = 0 */
+}
+
+/**
+ * Sets blocksize based on samplerate
+ * Chooses the closest predefined blocksize >= BLOCK_TIME_MS milliseconds
+ */
+static int select_blocksize(int samplerate, int block_time_ms)
+{
+ int i;
+ int target;
+ int blocksize;
+
+ assert(samplerate > 0);
+ blocksize = flac_blocksizes[1];
+ target = (samplerate * block_time_ms) / 1000;
+ for(i=0; i<16; i++) {
+ if(target >= flac_blocksizes[i] && flac_blocksizes[i] > blocksize) {
+ blocksize = flac_blocksizes[i];
+ }
+ }
+ return blocksize;
+}
+
+static int flac_encode_init(AVCodecContext *avctx)
+{
+ int freq = avctx->sample_rate;
+ int channels = avctx->channels;
+ FlacEncodeContext *s = avctx->priv_data;
+ int i, level;
+ uint8_t *streaminfo;
+
+ s->avctx = avctx;
+
+ if(avctx->sample_fmt != SAMPLE_FMT_S16) {
+ return -1;
+ }
+
+ if(channels < 1 || channels > FLAC_MAX_CH) {
+ return -1;
+ }
+ s->channels = channels;
+ s->ch_code = s->channels-1;
+
+ /* find samplerate in table */
+ if(freq < 1)
+ return -1;
+ for(i=4; i<12; i++) {
+ if(freq == flac_samplerates[i]) {
+ s->samplerate = flac_samplerates[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 {
+ return -1;
+ }
+ 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;
+ }
+ av_log(avctx, AV_LOG_DEBUG, " compression: %d\n", s->options.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 -1;
+ }
+
+ s->options.block_time_ms = ((int[]){ 27, 27, 27,105,105,105,105,105,105,105,105,105,105})[level];
+ s->options.use_lpc = ((int[]){ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1})[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];
+ 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];
+ s->options.min_partition_order = ((int[]){ 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})[level];
+ s->options.max_partition_order = ((int[]){ 2, 2, 3, 3, 3, 8, 8, 8, 8, 8, 8, 8, 8})[level];
+
+ /* set compression option overrides from AVCodecContext */
+ if(avctx->use_lpc >= 0) {
+ s->options.use_lpc = clip(avctx->use_lpc, 0, 11);
+ }
+ if(s->options.use_lpc == 1)
+ av_log(avctx, AV_LOG_DEBUG, " use lpc: Levinson-Durbin recursion with Welch window\n");
+ else if(s->options.use_lpc > 1)
+ av_log(avctx, AV_LOG_DEBUG, " use lpc: Cholesky factorization\n");
+
+ if(avctx->min_prediction_order >= 0) {
+ if(s->options.use_lpc) {
+ 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 -1;
+ }
+ } else {
+ 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 -1;
+ }
+ }
+ s->options.min_prediction_order = avctx->min_prediction_order;
+ }
+ if(avctx->max_prediction_order >= 0) {
+ if(s->options.use_lpc) {
+ 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 -1;
+ }
+ } else {
+ 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 -1;
+ }
+ }
+ 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 -1;
+ }
+ av_log(avctx, AV_LOG_DEBUG, " prediction order: %d, %d\n",
+ s->options.min_prediction_order, s->options.max_prediction_order);
+
+ if(avctx->prediction_order_method >= 0) {
+ if(avctx->prediction_order_method > ORDER_METHOD_LOG) {
+ av_log(avctx, AV_LOG_ERROR, "invalid prediction order method: %d\n",
+ avctx->prediction_order_method);
+ return -1;
+ }
+ s->options.prediction_order_method = avctx->prediction_order_method;
+ }
+ switch(s->options.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;
+ }
+
+ if(avctx->min_partition_order >= 0) {
+ if(avctx->min_partition_order > MAX_PARTITION_ORDER) {
+ av_log(avctx, AV_LOG_ERROR, "invalid min partition order: %d\n",
+ avctx->min_partition_order);
+ return -1;
+ }
+ s->options.min_partition_order = avctx->min_partition_order;
+ }
+ if(avctx->max_partition_order >= 0) {
+ if(avctx->max_partition_order > MAX_PARTITION_ORDER) {
+ av_log(avctx, AV_LOG_ERROR, "invalid max partition order: %d\n",
+ avctx->max_partition_order);
+ return -1;
+ }
+ s->options.max_partition_order = avctx->max_partition_order;
+ }
+ if(s->options.max_partition_order < s->options.min_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 -1;
+ }
+ av_log(avctx, AV_LOG_DEBUG, " partition order: %d, %d\n",
+ s->options.min_partition_order, s->options.max_partition_order);
+
+ 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 -1;
+ }
+ s->blocksize = avctx->frame_size;
+ } else {
+ s->blocksize = select_blocksize(s->samplerate, s->options.block_time_ms);
+ avctx->frame_size = s->blocksize;
+ }
+ av_log(avctx, AV_LOG_DEBUG, " block size: %d\n", s->blocksize);
+
+ /* set LPC precision */
+ if(avctx->lpc_coeff_precision > 0) {
+ if(avctx->lpc_coeff_precision > MAX_LPC_PRECISION) {
+ av_log(avctx, AV_LOG_ERROR, "invalid lpc coeff precision: %d\n",
+ avctx->lpc_coeff_precision);
+ return -1;
+ }
+ s->options.lpc_coeff_precision = avctx->lpc_coeff_precision;
+ } else {
+ /* select LPC precision based on block size */
+ if( s->blocksize <= 192) s->options.lpc_coeff_precision = 7;
+ else if(s->blocksize <= 384) s->options.lpc_coeff_precision = 8;
+ else if(s->blocksize <= 576) s->options.lpc_coeff_precision = 9;
+ else if(s->blocksize <= 1152) s->options.lpc_coeff_precision = 10;
+ else if(s->blocksize <= 2304) s->options.lpc_coeff_precision = 11;
+ else if(s->blocksize <= 4608) s->options.lpc_coeff_precision = 12;
+ else if(s->blocksize <= 8192) s->options.lpc_coeff_precision = 13;
+ else if(s->blocksize <= 16384) s->options.lpc_coeff_precision = 14;
+ else s->options.lpc_coeff_precision = 15;
+ }
+ av_log(avctx, AV_LOG_DEBUG, " lpc precision: %d\n",
+ s->options.lpc_coeff_precision);
+
+ /* set maximum encoded frame size in verbatim mode */
+ if(s->channels == 2) {
+ s->max_framesize = 14 + ((s->blocksize * 33 + 7) >> 3);
+ } else {
+ s->max_framesize = 14 + (s->blocksize * s->channels * 2);
+ }
+
+ streaminfo = av_malloc(FLAC_STREAMINFO_SIZE);
+ write_streaminfo(s, streaminfo);
+ avctx->extradata = streaminfo;
+ avctx->extradata_size = FLAC_STREAMINFO_SIZE;
+
+ s->frame_count = 0;
+
+ avctx->coded_frame = avcodec_alloc_frame();
+ avctx->coded_frame->key_frame = 1;
+
+ return 0;
+}
+
+static void init_frame(FlacEncodeContext *s)
+{
+ int i, ch;
+ FlacFrame *frame;
+
+ frame = &s->frame;
+
+ for(i=0; i<16; i++) {
+ if(s->blocksize == flac_blocksizes[i]) {
+ frame->blocksize = flac_blocksizes[i];
+ frame->bs_code[0] = i;
+ frame->bs_code[1] = 0;
+ break;
+ }
+ }
+ if(i == 16) {
+ frame->blocksize = s->blocksize;
+ 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++) {
+ frame->subframes[ch].obits = 16;
+ }
+}
+
+/**
+ * Copy channel-interleaved input samples into separate subframes
+ */
+static void copy_samples(FlacEncodeContext *s, int16_t *samples)
+{
+ int i, j, ch;
+ FlacFrame *frame;
+
+ 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] = samples[j];
+ }
+ }
+}
+
+
+#define rice_encode_count(sum, n, k) (((n)*((k)+1))+((sum-(n>>1))>>(k)))
+
+static int find_optimal_param(uint32_t sum, int n)
+{
+ int k, k_opt;
+ uint32_t nbits[MAX_RICE_PARAM+1];
+
+ k_opt = 0;
+ nbits[0] = UINT32_MAX;
+ for(k=0; k<=MAX_RICE_PARAM; k++) {
+ nbits[k] = rice_encode_count(sum, n, k);
+ if(nbits[k] < nbits[k_opt]) {
+ k_opt = k;
+ }
+ }
+ return k_opt;
+}
+
+static uint32_t calc_optimal_rice_params(RiceContext *rc, int porder,
+ uint32_t *sums, int n, int pred_order)
+{
+ int i;
+ int k, cnt, part;
+ uint32_t all_bits;
+
+ part = (1 << porder);
+ all_bits = 0;
+
+ cnt = (n >> porder) - pred_order;
+ for(i=0; i<part; i++) {
+ if(i == 1) cnt = (n >> porder);
+ k = find_optimal_param(sums[i], cnt);
+ rc->params[i] = k;
+ all_bits += rice_encode_count(sums[i], cnt, k);
+ }
+ all_bits += (4 * part);
+
+ rc->porder = porder;
+
+ return all_bits;
+}
+
+static void calc_sums(int pmin, int pmax, uint32_t *data, int n, int pred_order,
+ uint32_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++) {
+ sums[pmax][i] = 0;
+ while(res < res_end){
+ sums[pmax][i] += *(res++);
+ }
+ 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 uint32_t calc_rice_params(RiceContext *rc, int pmin, int pmax,
+ int32_t *data, int n, int pred_order)
+{
+ int i;
+ uint32_t bits[MAX_PARTITION_ORDER+1];
+ int opt_porder;
+ RiceContext tmp_rc;
+ uint32_t *udata;
+ uint32_t sums[MAX_PARTITION_ORDER+1][MAX_PARTITIONS];
+
+ assert(pmin >= 0 && pmin <= MAX_PARTITION_ORDER);
+ assert(pmax >= 0 && pmax <= MAX_PARTITION_ORDER);
+ assert(pmin <= pmax);
+
+ 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 uint32_t calc_rice_params_fixed(RiceContext *rc, int pmin, int pmax,
+ int32_t *data, int n, int pred_order,
+ int bps)
+{
+ uint32_t bits;
+ pmin = get_max_p_order(pmin, n, pred_order);
+ pmax = get_max_p_order(pmax, n, pred_order);
+ bits = pred_order*bps + 6;
+ bits += calc_rice_params(rc, pmin, pmax, data, n, pred_order);
+ return bits;
+}
+
+static uint32_t calc_rice_params_lpc(RiceContext *rc, int pmin, int pmax,
+ int32_t *data, int n, int pred_order,
+ int bps, int precision)
+{
+ uint32_t bits;
+ pmin = get_max_p_order(pmin, n, pred_order);
+ pmax = get_max_p_order(pmax, n, pred_order);
+ bits = pred_order*bps + 4 + 5 + pred_order*precision + 6;
+ bits += calc_rice_params(rc, pmin, pmax, data, n, pred_order);
+ return bits;
+}
+
+/**
+ * Apply Welch window function to audio block
+ */
+static void apply_welch_window(const int32_t *data, int len, double *w_data)
+{
+ int i, n2;
+ double w;
+ double c;
+
+ n2 = (len >> 1);
+ c = 2.0 / (len - 1.0);
+ for(i=0; i<n2; i++) {
+ w = c - i - 1.0;
+ w = 1.0 - (w * w);
+ w_data[i] = data[i] * w;
+ w_data[len-1-i] = data[len-1-i] * w;
+ }
+}
+
+/**
+ * Calculates autocorrelation data from audio samples
+ * A Welch window function is applied before calculation.
+ */
+static void compute_autocorr(const int32_t *data, int len, int lag,
+ double *autoc)
+{
+ int i, lag_ptr;
+ double tmp[len + lag];
+ double *data1= tmp + lag;
+
+ apply_welch_window(data, len, data1);
+
+ for(i=0; i<lag; i++){
+ autoc[i] = 1.0;
+ data1[i-lag]= 0.0;
+ }
+
+ for(i=0; i<len; i++){
+ for(lag_ptr= i-lag; lag_ptr<=i; lag_ptr++){
+ autoc[i-lag_ptr] += data1[i] * data1[lag_ptr];
+ }
+ }
+}
+
+/**
+ * Levinson-Durbin recursion.
+ * Produces LPC coefficients from autocorrelation data.
+ */
+static void compute_lpc_coefs(const double *autoc, int max_order,
+ double lpc[][MAX_LPC_ORDER], double *ref)
+{
+ int i, j, i2;
+ double r, err, tmp;
+ double lpc_tmp[MAX_LPC_ORDER];
+
+ for(i=0; i<max_order; i++) lpc_tmp[i] = 0;
+ err = autoc[0];
+
+ for(i=0; i<max_order; i++) {
+ r = -autoc[i+1];
+ for(j=0; j<i; j++) {
+ r -= lpc_tmp[j] * autoc[i-j];
+ }
+ r /= err;
+ ref[i] = fabs(r);
+
+ err *= 1.0 - (r * r);
+
+ i2 = (i >> 1);
+ lpc_tmp[i] = r;
+ for(j=0; j<i2; j++) {
+ tmp = lpc_tmp[j];
+ lpc_tmp[j] += r * lpc_tmp[i-1-j];
+ lpc_tmp[i-1-j] += r * tmp;
+ }
+ if(i & 1) {
+ lpc_tmp[j] += lpc_tmp[j] * r;
+ }
+
+ for(j=0; j<=i; j++) {
+ lpc[i][j] = -lpc_tmp[j];
+ }
+ }
+}
+
+/**
+ * Quantize LPC coefficients
+ */
+static void quantize_lpc_coefs(double *lpc_in, int order, int precision,
+ int32_t *lpc_out, int *shift)
+{
+ int i;
+ double cmax, error;
+ int32_t qmax;
+ int sh;
+
+ /* define maximum levels */
+ qmax = (1 << (precision - 1)) - 1;
+
+ /* find maximum coefficient value */
+ cmax = 0.0;
+ for(i=0; i<order; i++) {
+ cmax= FFMAX(cmax, fabs(lpc_in[i]));
+ }
+
+ /* if maximum value quantizes to zero, return all zeros */
+ if(cmax * (1 << MAX_LPC_SHIFT) < 1.0) {
+ *shift = 0;
+ memset(lpc_out, 0, sizeof(int32_t) * order);
+ return;
+ }
+
+ /* calculate level shift which scales max coeff to available bits */
+ sh = MAX_LPC_SHIFT;
+ while((cmax * (1 << sh) > 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<order; i++) {
+ lpc_in[i] *= scale;
+ }
+ }
+
+ /* output quantized coefficients and level shift */
+ error=0;
+ for(i=0; i<order; i++) {
+ error += lpc_in[i] * (1 << sh);
+ lpc_out[i] = clip(lrintf(error), -qmax, qmax);
+ error -= lpc_out[i];
+ }
+ *shift = sh;
+}
+
+static int estimate_best_order(double *ref, int max_order)
+{
+ int i, est;
+
+ est = 1;
+ for(i=max_order-1; i>=0; i--) {
+ if(ref[i] > 0.10) {
+ est = i+1;
+ break;
+ }
+ }
+ return est;
+}
+
+/**
+ * Calculate LPC coefficients for multiple orders
+ */
+static int lpc_calc_coefs(const int32_t *samples, int blocksize, int max_order,
+ int precision, int32_t coefs[][MAX_LPC_ORDER],
+ int *shift, int use_lpc, int omethod)
+{
+ 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;
+
+ assert(max_order >= MIN_LPC_ORDER && max_order <= MAX_LPC_ORDER);
+
+ if(use_lpc == 1){
+ compute_autocorr(samples, blocksize, max_order+1, autoc);
+
+ compute_lpc_coefs(autoc, max_order, lpc, ref);
+ }else{
+ LLSModel m[2];
+ double var[MAX_LPC_ORDER+1], eval, weight;
+
+ for(pass=0; pass<use_lpc-1; pass++){
+ av_init_lls(&m[pass&1], max_order);
+
+ weight=0;
+ for(i=max_order; i<blocksize; i++){
+ for(j=0; j<=max_order; j++)
+ var[j]= samples[i-j];
+
+ if(pass){
+ eval= av_evaluate_lls(&m[(pass-1)&1], var+1, max_order-1);
+ eval= (512>>pass) + fabs(eval - var[0]);
+ for(j=0; j<=max_order; j++)
+ var[j]/= sqrt(eval);
+ weight += 1/eval;
+ }else
+ weight++;
+
+ av_update_lls(&m[pass&1], var, 1.0);
+ }
+ av_solve_lls(&m[pass&1], 0.001, 0);
+ }
+
+ for(i=0; i<max_order; i++){
+ for(j=0; j<max_order; j++)
+ lpc[i][j]= m[(pass-1)&1].coeff[i][j];
+ ref[i]= sqrt(m[(pass-1)&1].variance[i] / weight) * (blocksize - max_order) / 4000;
+ }
+ for(i=max_order-1; i>0; i--)
+ ref[i] = ref[i-1] - ref[i];
+ }
+ opt_order = max_order;
+
+ if(omethod == ORDER_METHOD_EST) {
+ opt_order = estimate_best_order(ref, max_order);
+ i = opt_order-1;
+ quantize_lpc_coefs(lpc[i], i+1, precision, coefs[i], &shift[i]);
+ } else {
+ for(i=0; i<max_order; i++) {
+ quantize_lpc_coefs(lpc[i], i+1, precision, coefs[i], &shift[i]);
+ }
+ }
+
+ return opt_order;
+}
+
+
+static void encode_residual_verbatim(int32_t *res, int32_t *smp, int n)
+{
+ assert(n > 0);
+ memcpy(res, smp, n * sizeof(int32_t));
+}
+
+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){
+ for(i=order; i<n; i++)
+ res[i]= smp[i] - 2*smp[i-1] + smp[i-2];
+ }else if(order==3){
+ for(i=order; i<n; i++)
+ res[i]= smp[i] - 3*smp[i-1] + 3*smp[i-2] - smp[i-3];
+ }else{
+ for(i=order; i<n; i++)
+ res[i]= smp[i] - 4*smp[i-1] + 6*smp[i-2] - 4*smp[i-3] + smp[i-4];
+ }
+}
+
+static void encode_residual_lpc(int32_t *res, const int32_t *smp, int n,
+ int order, const int32_t *coefs, int shift)
+{
+ int i, j;
+ int32_t pred;
+
+ for(i=0; i<order; i++) {
+ res[i] = smp[i];
+ }
+ for(i=order; i<n; i++) {
+ pred = 0;
+ for(j=0; j<order; j++) {
+ pred += coefs[j] * smp[i-j-1];
+ }
+ res[i] = smp[i] - (pred >> shift);
+ }
+}
+
+static int encode_residual(FlacEncodeContext *ctx, int ch)
+{
+ int i, n;
+ int min_order, max_order, opt_order, precision, omethod;
+ int min_porder, max_porder;
+ FlacFrame *frame;
+ FlacSubframe *sub;
+ int32_t coefs[MAX_LPC_ORDER][MAX_LPC_ORDER];
+ int shift[MAX_LPC_ORDER];
+ int32_t *res, *smp;
+
+ frame = &ctx->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 sub->obits;
+ }
+
+ /* VERBATIM */
+ if(n < 5) {
+ sub->type = sub->type_code = FLAC_SUBFRAME_VERBATIM;
+ encode_residual_verbatim(res, smp, n);
+ return sub->obits * n;
+ }
+
+ min_order = ctx->options.min_prediction_order;
+ max_order = ctx->options.max_prediction_order;
+ min_porder = ctx->options.min_partition_order;
+ max_porder = ctx->options.max_partition_order;
+ precision = ctx->options.lpc_coeff_precision;
+ omethod = ctx->options.prediction_order_method;
+
+ /* FIXED */
+ if(!ctx->options.use_lpc || max_order == 0 || (n <= max_order)) {
+ uint32_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] = calc_rice_params_fixed(&sub->rc, min_porder, max_porder, res,
+ n, i, sub->obits);
+ if(bits[i] < bits[opt_order]) {
+ opt_order = i;
+ }
+ }
+ sub->order = opt_order;
+ sub->type = FLAC_SUBFRAME_FIXED;
+ sub->type_code = sub->type | sub->order;
+ if(sub->order != max_order) {
+ encode_residual_fixed(res, smp, n, sub->order);
+ return calc_rice_params_fixed(&sub->rc, min_porder, max_porder, res, n,
+ sub->order, sub->obits);
+ }
+ return bits[sub->order];
+ }
+
+ /* LPC */
+ opt_order = lpc_calc_coefs(smp, n, max_order, precision, coefs, shift, ctx->options.use_lpc, omethod);
+
+ if(omethod == ORDER_METHOD_2LEVEL ||
+ omethod == ORDER_METHOD_4LEVEL ||
+ omethod == ORDER_METHOD_8LEVEL) {
+ int levels = 1 << omethod;
+ uint32_t bits[levels];
+ int order;
+ int opt_index = levels-1;
+ opt_order = max_order-1;
+ bits[opt_index] = UINT32_MAX;
+ for(i=levels-1; i>=0; i--) {
+ order = min_order + (((max_order-min_order+1) * (i+1)) / levels)-1;
+ if(order < 0) order = 0;
+ encode_residual_lpc(res, smp, n, order+1, coefs[order], shift[order]);
+ bits[i] = calc_rice_params_lpc(&sub->rc, min_porder, max_porder,
+ res, n, order+1, sub->obits, precision);
+ 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
+ uint32_t bits[MAX_LPC_ORDER];
+ opt_order = 0;
+ bits[0] = UINT32_MAX;
+ for(i=min_order-1; i<max_order; i++) {
+ encode_residual_lpc(res, smp, n, i+1, coefs[i], shift[i]);
+ bits[i] = calc_rice_params_lpc(&sub->rc, min_porder, max_porder,
+ res, n, i+1, sub->obits, precision);
+ if(bits[i] < bits[opt_order]) {
+ opt_order = i;
+ }
+ }
+ opt_order++;
+ } else if(omethod == ORDER_METHOD_LOG) {
+ uint32_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;
+ encode_residual_lpc(res, smp, n, i+1, coefs[i], shift[i]);
+ bits[i] = calc_rice_params_lpc(&sub->rc, min_porder, max_porder,
+ res, n, i+1, sub->obits, precision);
+ if(bits[i] < bits[opt_order])
+ opt_order= i;
+ }
+ }
+ opt_order++;
+ }
+
+ sub->order = opt_order;
+ sub->type = FLAC_SUBFRAME_LPC;
+ 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];
+ }
+ encode_residual_lpc(res, smp, n, sub->order, sub->coefs, sub->shift);
+ return calc_rice_params_lpc(&sub->rc, min_porder, max_porder, res, n, sub->order,
+ sub->obits, precision);
+}
+
+static int encode_residual_v(FlacEncodeContext *ctx, int ch)
+{
+ int i, n;
+ FlacFrame *frame;
+ FlacSubframe *sub;
+ int32_t *res, *smp;
+
+ frame = &ctx->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 sub->obits;
+ }
+
+ /* VERBATIM */
+ sub->type = sub->type_code = FLAC_SUBFRAME_VERBATIM;
+ encode_residual_verbatim(res, smp, n);
+ return sub->obits * n;
+}
+
+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];
+ 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);
+ 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;
+ }
+ }
+ if(best == 0) {
+ return FLAC_CHMODE_LEFT_RIGHT;
+ } else if(best == 1) {
+ return FLAC_CHMODE_LEFT_SIDE;
+ } else if(best == 2) {
+ return FLAC_CHMODE_RIGHT_SIDE;
+ } else {
+ return FLAC_CHMODE_MID_SIDE;
+ }
+}
+
+/**
+ * Perform stereo channel decorrelation
+ */
+static void channel_decorrelation(FlacEncodeContext *ctx)
+{
+ FlacFrame *frame;
+ int32_t *left, *right;
+ int i, n;
+
+ frame = &ctx->frame;
+ n = frame->blocksize;
+ left = frame->subframes[0].samples;
+ right = frame->subframes[1].samples;
+
+ if(ctx->channels != 2) {
+ frame->ch_mode = FLAC_CHMODE_NOT_STEREO;
+ return;
+ }
+
+ frame->ch_mode = estimate_stereo_mode(left, right, n);
+
+ /* perform decorrelation and adjust bits-per-sample */
+ if(frame->ch_mode == FLAC_CHMODE_LEFT_RIGHT) {
+ 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 put_sbits(PutBitContext *pb, int bits, int32_t val)
+{
+ assert(bits >= 0 && bits <= 31);
+
+ put_bits(pb, bits, val & ((1<<bits)-1));
+}
+
+static void write_utf8(PutBitContext *pb, uint32_t val)
+{
+ uint8_t tmp;
+ PUT_UTF8(val, tmp, put_bits(pb, 8, tmp);)
+}
+
+static void output_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_NOT_STEREO) {
+ put_bits(&s->pb, 4, s->ch_code);
+ } else {
+ put_bits(&s->pb, 4, frame->ch_mode);
+ }
+ put_bits(&s->pb, 3, 4); /* bits-per-sample 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_crc07, 0, s->pb.buf, put_bits_count(&s->pb)>>3);
+ put_bits(&s->pb, 8, crc);
+}
+
+static void output_subframe_constant(FlacEncodeContext *s, int ch)
+{
+ FlacSubframe *sub;
+ int32_t res;
+
+ sub = &s->frame.subframes[ch];
+ res = sub->residual[0];
+ put_sbits(&s->pb, sub->obits, res);
+}
+
+static void output_subframe_verbatim(FlacEncodeContext *s, int ch)
+{
+ int i;
+ FlacFrame *frame;
+ FlacSubframe *sub;
+ int32_t res;
+
+ frame = &s->frame;
+ sub = &frame->subframes[ch];
+
+ for(i=0; i<frame->blocksize; i++) {
+ res = sub->residual[i];
+ put_sbits(&s->pb, sub->obits, res);
+ }
+}
+
+static void output_residual(FlacEncodeContext *ctx, int ch)
+{
+ int i, j, p, n, parts;
+ int k, porder, psize, res_cnt;
+ FlacFrame *frame;
+ FlacSubframe *sub;
+ int32_t *res;
+
+ frame = &ctx->frame;
+ sub = &frame->subframes[ch];
+ res = sub->residual;
+ n = frame->blocksize;
+
+ /* rice-encoded block */
+ put_bits(&ctx->pb, 2, 0);
+
+ /* partition order */
+ porder = sub->rc.porder;
+ psize = n >> porder;
+ parts = (1 << porder);
+ put_bits(&ctx->pb, 4, porder);
+ res_cnt = psize - sub->order;
+
+ /* residual */
+ j = sub->order;
+ for(p=0; p<parts; p++) {
+ k = sub->rc.params[p];
+ put_bits(&ctx->pb, 4, k);
+ if(p == 1) res_cnt = psize;
+ for(i=0; i<res_cnt && j<n; i++, j++) {
+ set_sr_golomb_flac(&ctx->pb, res[j], k, INT32_MAX, 0);
+ }
+ }
+}
+
+static void output_subframe_fixed(FlacEncodeContext *ctx, int ch)
+{
+ int i;
+ FlacFrame *frame;
+ FlacSubframe *sub;
+
+ frame = &ctx->frame;
+ sub = &frame->subframes[ch];
+
+ /* warm-up samples */
+ for(i=0; i<sub->order; i++) {
+ put_sbits(&ctx->pb, sub->obits, sub->residual[i]);
+ }
+
+ /* residual */
+ output_residual(ctx, ch);
+}
+
+static void output_subframe_lpc(FlacEncodeContext *ctx, int ch)
+{
+ int i, cbits;
+ FlacFrame *frame;
+ FlacSubframe *sub;
+
+ frame = &ctx->frame;
+ sub = &frame->subframes[ch];
+
+ /* warm-up samples */
+ for(i=0; i<sub->order; i++) {
+ put_sbits(&ctx->pb, sub->obits, sub->residual[i]);
+ }
+
+ /* LPC coefficients */
+ cbits = ctx->options.lpc_coeff_precision;
+ put_bits(&ctx->pb, 4, cbits-1);
+ put_sbits(&ctx->pb, 5, sub->shift);
+ for(i=0; i<sub->order; i++) {
+ put_sbits(&ctx->pb, cbits, sub->coefs[i]);
+ }
+
+ /* residual */
+ output_residual(ctx, ch);
+}
+
+static void output_subframes(FlacEncodeContext *s)
+{
+ FlacFrame *frame;
+ FlacSubframe *sub;
+ int ch;
+
+ frame = &s->frame;
+
+ for(ch=0; ch<s->channels; ch++) {
+ sub = &frame->subframes[ch];
+
+ /* subframe header */
+ put_bits(&s->pb, 1, 0);
+ put_bits(&s->pb, 6, sub->type_code);
+ put_bits(&s->pb, 1, 0); /* no wasted bits */
+
+ /* subframe */
+ if(sub->type == FLAC_SUBFRAME_CONSTANT) {
+ output_subframe_constant(s, ch);
+ } else if(sub->type == FLAC_SUBFRAME_VERBATIM) {
+ output_subframe_verbatim(s, ch);
+ } else if(sub->type == FLAC_SUBFRAME_FIXED) {
+ output_subframe_fixed(s, ch);
+ } else if(sub->type == FLAC_SUBFRAME_LPC) {
+ output_subframe_lpc(s, ch);
+ }
+ }
+}
+
+static void output_frame_footer(FlacEncodeContext *s)
+{
+ int crc;
+ flush_put_bits(&s->pb);
+ crc = bswap_16(av_crc(av_crc8005, 0, s->pb.buf, put_bits_count(&s->pb)>>3));
+ put_bits(&s->pb, 16, crc);
+ flush_put_bits(&s->pb);
+}
+
+static int flac_encode_frame(AVCodecContext *avctx, uint8_t *frame,
+ int buf_size, void *data)
+{
+ int ch;
+ FlacEncodeContext *s;
+ int16_t *samples = data;
+ int out_bytes;
+
+ s = avctx->priv_data;
+
+ s->blocksize = avctx->frame_size;
+ init_frame(s);
+
+ copy_samples(s, samples);
+
+ channel_decorrelation(s);
+
+ for(ch=0; ch<s->channels; ch++) {
+ encode_residual(s, ch);
+ }
+ init_put_bits(&s->pb, frame, buf_size);
+ output_frame_header(s);
+ output_subframes(s);
+ output_frame_footer(s);
+ out_bytes = put_bits_count(&s->pb) >> 3;
+
+ if(out_bytes > s->max_framesize || out_bytes >= buf_size) {
+ /* frame too large. use verbatim mode */
+ for(ch=0; ch<s->channels; ch++) {
+ encode_residual_v(s, ch);
+ }
+ init_put_bits(&s->pb, frame, buf_size);
+ output_frame_header(s);
+ output_subframes(s);
+ output_frame_footer(s);
+ out_bytes = put_bits_count(&s->pb) >> 3;
+
+ if(out_bytes > s->max_framesize || out_bytes >= buf_size) {
+ /* still too large. must be an error. */
+ av_log(avctx, AV_LOG_ERROR, "error encoding frame\n");
+ return -1;
+ }
+ }
+
+ s->frame_count++;
+ return out_bytes;
+}
+
+static int flac_encode_close(AVCodecContext *avctx)
+{
+ av_freep(&avctx->extradata);
+ avctx->extradata_size = 0;
+ av_freep(&avctx->coded_frame);
+ return 0;
+}
+
+AVCodec flac_encoder = {
+ "flac",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_FLAC,
+ sizeof(FlacEncodeContext),
+ flac_encode_init,
+ flac_encode_frame,
+ flac_encode_close,
+ NULL,
+ .capabilities = CODEC_CAP_SMALL_LAST_FRAME,
+};
diff --git a/contrib/ffmpeg/libavcodec/flashsv.c b/contrib/ffmpeg/libavcodec/flashsv.c
new file mode 100644
index 000000000..fea8e2224
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/flashsv.c
@@ -0,0 +1,276 @@
+/*
+ * 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 flashsv.c
+ * Flash Screen Video decoder
+ * @author Alex Beregszaszi
+ * @author Benjamin Larsson
+ */
+
+/* Bitstream description
+ * The picture is divided into blocks that are zlib compressed.
+ *
+ * The decoder is fed complete frames, the frameheader contains:
+ * 4bits of block width
+ * 12bits of frame width
+ * 4bits of block height
+ * 12bits of frame height
+ *
+ * Directly after the header are the compressed blocks. The blocks
+ * have their compressed size represented with 16bits in the beginnig.
+ * If the size = 0 then the block is unchanged from the previous frame.
+ * All blocks are decompressed until the buffer is consumed.
+ *
+ * Encoding ideas, a basic encoder would just use a fixed block size.
+ * Block sizes can be multipels of 16, from 16 to 256. The blocks don't
+ * have to be quadratic. A brute force search with a set of diffrent
+ * block sizes should give a better result then to just use a fixed size.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "bitstream.h"
+
+#ifdef CONFIG_ZLIB
+#include <zlib.h>
+#endif
+
+typedef struct FlashSVContext {
+ AVCodecContext *avctx;
+ AVFrame frame;
+ int image_width, image_height;
+ int block_width, block_height;
+ uint8_t* tmpblock;
+ int block_size;
+#ifdef CONFIG_ZLIB
+ z_stream zstream;
+#endif
+} FlashSVContext;
+
+
+static void copy_region(uint8_t *sptr, uint8_t *dptr,
+ int dx, int dy, int h, int w, int stride)
+{
+ int i;
+
+ for (i = dx+h; i > dx; i--)
+ {
+ memcpy(dptr+(i*stride)+dy*3, sptr, w*3);
+ sptr += w*3;
+ }
+}
+
+
+static int flashsv_decode_init(AVCodecContext *avctx)
+{
+ FlashSVContext *s = (FlashSVContext *)avctx->priv_data;
+ int zret; // Zlib return code
+
+ s->avctx = avctx;
+#ifdef CONFIG_ZLIB
+ 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;
+ }
+#else
+ av_log(avctx, AV_LOG_ERROR, "Zlib support not compiled. Needed for the decoder.\n");
+ return 1;
+#endif
+ avctx->pix_fmt = PIX_FMT_BGR24;
+ avctx->has_b_frames = 0;
+ s->frame.data[0] = NULL;
+
+ return 0;
+}
+
+
+static int flashsv_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ FlashSVContext *s = (FlashSVContext *)avctx->priv_data;
+ int h_blocks, v_blocks, h_part, v_part, i, j;
+ GetBitContext gb;
+
+ /* no supplementary picture */
+ if (buf_size == 0)
+ return 0;
+
+ if(s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ init_get_bits(&gb, buf, 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);
+
+ /* calculate amount of blocks and the size of the border 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) {
+ if (s->tmpblock != NULL)
+ av_free(s->tmpblock);
+ s->block_size = s->block_width*s->block_height;
+ if ((s->tmpblock = av_malloc(3*s->block_size)) == NULL) {
+ av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
+ return -1;
+ }
+ }
+
+ /* init the image size once */
+ if((avctx->width==0) && (avctx->height==0)){
+ avctx->width = s->image_width;
+ avctx->height = 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 frames!\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 -1;
+ }
+
+ av_log(avctx, AV_LOG_DEBUG, "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);
+
+ s->frame.reference = 1;
+ s->frame.buffer_hints = FF_BUFFER_HINTS_VALID;
+ if (avctx->get_buffer(avctx, &s->frame) < 0) {
+ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ /* loop over all block columns */
+ for (j = 0; j < v_blocks + (v_part?1:0); j++)
+ {
+
+ int hp = j*s->block_height; // horiz position in frame
+ int hs = (j<v_blocks)?s->block_height:v_part; // size of block
+
+
+ /* loop over all block rows */
+ for (i = 0; i < h_blocks + (h_part?1:0); i++)
+ {
+ int wp = i*s->block_width; // vert position in frame
+ int ws = (i<h_blocks)?s->block_width:h_part; // size of block
+
+ /* get the size of the compressed zlib chunk */
+ int size = get_bits(&gb, 16);
+
+ if (size == 0) {
+ /* no change, don't do anything */
+ } else {
+ /* decompress block */
+#ifdef CONFIG_ZLIB
+ int ret = inflateReset(&(s->zstream));
+ if (ret != Z_OK)
+ {
+ av_log(avctx, AV_LOG_ERROR, "error in decompression (reset) of block %dx%d\n", i, j);
+ /* return -1; */
+ }
+ s->zstream.next_in = buf+(get_bits_count(&gb)/8);
+ s->zstream.avail_in = 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 occured\n");
+ inflateSync(&(s->zstream));
+ ret = inflate(&(s->zstream), Z_FINISH);
+ }
+
+ if ((ret != Z_OK) && (ret != Z_STREAM_END))
+ {
+ av_log(avctx, AV_LOG_ERROR, "error in decompression of block %dx%d: %d\n", i, j, ret);
+ /* return -1; */
+ }
+#else
+ av_log(avctx, AV_LOG_ERROR, "Zlib support not compiled in.\n");
+ return -1;
+#endif
+ copy_region(s->tmpblock, s->frame.data[0], s->image_height-(hp+hs+1), wp, hs, ws, s->frame.linesize[0]);
+ skip_bits(&gb, 8*size); /* skip the consumed bits */
+ }
+ }
+ }
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = s->frame;
+
+ 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 int flashsv_decode_end(AVCodecContext *avctx)
+{
+ FlashSVContext *s = (FlashSVContext *)avctx->priv_data;
+#ifdef CONFIG_ZLIB
+ inflateEnd(&(s->zstream));
+#endif
+ /* release the frame if needed */
+ if (s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ /* free the tmpblock */
+ if (s->tmpblock != NULL)
+ av_free(s->tmpblock);
+
+ return 0;
+}
+
+
+AVCodec flashsv_decoder = {
+ "flashsv",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_FLASHSV,
+ sizeof(FlashSVContext),
+ flashsv_decode_init,
+ NULL,
+ flashsv_decode_end,
+ flashsv_decode_frame,
+ CODEC_CAP_DR1,
+ .pix_fmts = (enum PixelFormat[]){PIX_FMT_BGR24, -1},
+};
diff --git a/contrib/ffmpeg/libavcodec/flicvideo.c b/contrib/ffmpeg/libavcodec/flicvideo.c
new file mode 100644
index 000000000..95cb26ce4
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/flicvideo.c
@@ -0,0 +1,754 @@
+/*
+ * 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 flic.c
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "bswap.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_INFO, "Problem: pixel_ptr >= pixel_limit (%d >= %d)\n", \
+ pixel_ptr + n, pixel_limit); \
+ return -1; \
+ } \
+
+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 int flic_decode_init(AVCodecContext *avctx)
+{
+ FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data;
+ unsigned char *fli_header = (unsigned char *)avctx->extradata;
+ int depth;
+
+ s->avctx = avctx;
+ avctx->has_b_frames = 0;
+
+ s->fli_type = LE_16(&fli_header[4]); /* Might be overridden if a Magic Carpet FLC */
+ depth = LE_16(&fli_header[12]);
+
+ if (depth == 0) {
+ depth = 8; /* Some FLC generators set depth to zero, when they mean 8Bpp. Fix up here */
+ }
+
+ if (s->avctx->extradata_size == 12) {
+ /* special case for magic carpet FLIs */
+ s->fli_type = FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE;
+ } else if (s->avctx->extradata_size != 128) {
+ av_log(avctx, AV_LOG_ERROR, "Expected extradata of 12 or 128 bytes\n");
+ return -1;
+ }
+
+ 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 = PIX_FMT_PAL8; break;
+ case 15 : avctx->pix_fmt = PIX_FMT_RGB555; break;
+ case 16 : avctx->pix_fmt = PIX_FMT_RGB565; break;
+ case 24 : avctx->pix_fmt = 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 -1;
+ break;
+ default :
+ av_log(avctx, AV_LOG_ERROR, "Unkown FLC/FLX depth of %d Bpp is unsupported.\n",depth);
+ return -1;
+ }
+
+ s->frame.data[0] = NULL;
+ s->new_palette = 0;
+
+ return 0;
+}
+
+static int flic_decode_frame_8BPP(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data;
+
+ int stream_ptr = 0;
+ int stream_ptr_after_color_chunk;
+ 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;
+
+ 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;
+ int pixel_limit;
+
+ s->frame.reference = 1;
+ s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
+ if (avctx->reget_buffer(avctx, &s->frame) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+ return -1;
+ }
+
+ pixels = s->frame.data[0];
+ pixel_limit = s->avctx->height * s->frame.linesize[0];
+
+ frame_size = LE_32(&buf[stream_ptr]);
+ stream_ptr += 6; /* skip the magic number */
+ num_chunks = LE_16(&buf[stream_ptr]);
+ stream_ptr += 10; /* skip padding */
+
+ frame_size -= 16;
+
+ /* iterate through the chunks */
+ while ((frame_size > 0) && (num_chunks > 0)) {
+ chunk_size = LE_32(&buf[stream_ptr]);
+ stream_ptr += 4;
+ chunk_type = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+
+ switch (chunk_type) {
+ case FLI_256_COLOR:
+ case FLI_COLOR:
+ stream_ptr_after_color_chunk = stream_ptr + chunk_size - 6;
+
+ /* 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 = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+ palette_ptr = 0;
+ for (i = 0; i < color_packets; i++) {
+ /* first byte is how many colors to skip */
+ palette_ptr += buf[stream_ptr++];
+
+ /* next byte indicates how many entries to change */
+ color_changes = buf[stream_ptr++];
+
+ /* if there are 0 color changes, there are actually 256 */
+ if (color_changes == 0)
+ color_changes = 256;
+
+ for (j = 0; j < color_changes; j++) {
+ unsigned int entry;
+
+ /* wrap around, for good measure */
+ if ((unsigned)palette_ptr >= 256)
+ palette_ptr = 0;
+
+ r = buf[stream_ptr++] << color_shift;
+ g = buf[stream_ptr++] << color_shift;
+ b = buf[stream_ptr++] << color_shift;
+ entry = (r << 16) | (g << 8) | b;
+ if (s->palette[palette_ptr] != entry)
+ s->new_palette = 1;
+ s->palette[palette_ptr++] = entry;
+ }
+ }
+
+ /* color chunks sometimes have weird 16-bit alignment issues;
+ * therefore, take the hardline approach and set the stream_ptr
+ * to the value calculated w.r.t. the size specified by the color
+ * chunk header */
+ stream_ptr = stream_ptr_after_color_chunk;
+
+ break;
+
+ case FLI_DELTA:
+ y_ptr = 0;
+ compressed_lines = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+ while (compressed_lines > 0) {
+ line_packets = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+ 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
+ pixels[y_ptr + s->frame.linesize[0] - 1] = line_packets & 0xff;
+ } else {
+ compressed_lines--;
+ pixel_ptr = y_ptr;
+ pixel_countdown = s->avctx->width;
+ for (i = 0; i < line_packets; i++) {
+ /* account for the skip bytes */
+ pixel_skip = buf[stream_ptr++];
+ pixel_ptr += pixel_skip;
+ pixel_countdown -= pixel_skip;
+ byte_run = (signed char)(buf[stream_ptr++]);
+ if (byte_run < 0) {
+ byte_run = -byte_run;
+ palette_idx1 = buf[stream_ptr++];
+ palette_idx2 = buf[stream_ptr++];
+ CHECK_PIXEL_PTR(byte_run);
+ 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);
+ for (j = 0; j < byte_run * 2; j++, pixel_countdown--) {
+ palette_idx1 = buf[stream_ptr++];
+ pixels[pixel_ptr++] = palette_idx1;
+ }
+ }
+ }
+
+ y_ptr += s->frame.linesize[0];
+ }
+ }
+ break;
+
+ case FLI_LC:
+ /* line compressed */
+ starting_line = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+ y_ptr = 0;
+ y_ptr += starting_line * s->frame.linesize[0];
+
+ compressed_lines = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+ while (compressed_lines > 0) {
+ pixel_ptr = y_ptr;
+ pixel_countdown = s->avctx->width;
+ line_packets = buf[stream_ptr++];
+ if (line_packets > 0) {
+ for (i = 0; i < line_packets; i++) {
+ /* account for the skip bytes */
+ pixel_skip = buf[stream_ptr++];
+ pixel_ptr += pixel_skip;
+ pixel_countdown -= pixel_skip;
+ byte_run = (signed char)(buf[stream_ptr++]);
+ if (byte_run > 0) {
+ CHECK_PIXEL_PTR(byte_run);
+ for (j = 0; j < byte_run; j++, pixel_countdown--) {
+ palette_idx1 = buf[stream_ptr++];
+ pixels[pixel_ptr++] = palette_idx1;
+ }
+ } else if (byte_run < 0) {
+ byte_run = -byte_run;
+ palette_idx1 = buf[stream_ptr++];
+ 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 */
+ stream_ptr++;
+ pixel_countdown = s->avctx->width;
+ while (pixel_countdown > 0) {
+ byte_run = (signed char)(buf[stream_ptr++]);
+ if (byte_run > 0) {
+ palette_idx1 = buf[stream_ptr++];
+ 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)\n",
+ pixel_countdown);
+ }
+ } else { /* copy bytes if byte_run < 0 */
+ byte_run = -byte_run;
+ CHECK_PIXEL_PTR(byte_run);
+ for (j = 0; j < byte_run; j++) {
+ palette_idx1 = buf[stream_ptr++];
+ pixels[pixel_ptr++] = palette_idx1;
+ 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:
+ /* 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) " \
+ "bigger than image, skipping chunk\n", chunk_size - 6);
+ stream_ptr += chunk_size - 6;
+ } else {
+ for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;
+ y_ptr += s->frame.linesize[0]) {
+ memcpy(&pixels[y_ptr], &buf[stream_ptr],
+ s->avctx->width);
+ stream_ptr += s->avctx->width;
+ }
+ }
+ break;
+
+ case FLI_MINI:
+ /* some sort of a thumbnail? disregard this chunk... */
+ stream_ptr += 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 ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1))
+ av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
+ "and final chunk ptr = %d\n", buf_size, stream_ptr);
+
+ /* 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;
+ }
+
+ *data_size=sizeof(AVFrame);
+ *(AVFrame*)data = s->frame;
+
+ return buf_size;
+}
+
+static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
+ void *data, int *data_size,
+ 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 = (FlicDecodeContext *)avctx->priv_data;
+
+ int stream_ptr = 0;
+ int pixel_ptr;
+ unsigned char palette_idx1;
+
+ unsigned int frame_size;
+ int num_chunks;
+
+ unsigned int chunk_size;
+ int chunk_type;
+
+ int i, j;
+
+ 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;
+ int pixel_limit;
+
+ s->frame.reference = 1;
+ s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
+ if (avctx->reget_buffer(avctx, &s->frame) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+ return -1;
+ }
+
+ pixels = s->frame.data[0];
+ pixel_limit = s->avctx->height * s->frame.linesize[0];
+
+ frame_size = LE_32(&buf[stream_ptr]);
+ stream_ptr += 6; /* skip the magic number */
+ num_chunks = LE_16(&buf[stream_ptr]);
+ stream_ptr += 10; /* skip padding */
+
+ frame_size -= 16;
+
+ /* iterate through the chunks */
+ while ((frame_size > 0) && (num_chunks > 0)) {
+ chunk_size = LE_32(&buf[stream_ptr]);
+ stream_ptr += 4;
+ chunk_type = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+
+ switch (chunk_type) {
+ case FLI_256_COLOR:
+ case FLI_COLOR:
+ /* For some reason, it seems that non-paletised flics do include one of these */
+ /* chunks in their first frame. Why i do not know, it seems rather extraneous */
+/* av_log(avctx, AV_LOG_ERROR, "Unexpected Palette chunk %d in non-paletised FLC\n",chunk_type);*/
+ stream_ptr = stream_ptr + chunk_size - 6;
+ break;
+
+ case FLI_DELTA:
+ case FLI_DTA_LC:
+ y_ptr = 0;
+ compressed_lines = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+ while (compressed_lines > 0) {
+ line_packets = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+ if (line_packets < 0) {
+ line_packets = -line_packets;
+ y_ptr += line_packets * s->frame.linesize[0];
+ } else {
+ compressed_lines--;
+ pixel_ptr = y_ptr;
+ pixel_countdown = s->avctx->width;
+ for (i = 0; i < line_packets; i++) {
+ /* account for the skip bytes */
+ pixel_skip = buf[stream_ptr++];
+ pixel_ptr += (pixel_skip*2); /* Pixel is 2 bytes wide */
+ pixel_countdown -= pixel_skip;
+ byte_run = (signed char)(buf[stream_ptr++]);
+ if (byte_run < 0) {
+ byte_run = -byte_run;
+ pixel = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+ CHECK_PIXEL_PTR(byte_run);
+ for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
+ *((signed short*)(&pixels[pixel_ptr])) = pixel;
+ pixel_ptr += 2;
+ }
+ } else {
+ CHECK_PIXEL_PTR(byte_run);
+ for (j = 0; j < byte_run; j++, pixel_countdown--) {
+ *((signed short*)(&pixels[pixel_ptr])) = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+ 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");
+ stream_ptr = stream_ptr + 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 */
+ stream_ptr++;
+ pixel_countdown = (s->avctx->width * 2);
+
+ while (pixel_countdown > 0) {
+ byte_run = (signed char)(buf[stream_ptr++]);
+ if (byte_run > 0) {
+ palette_idx1 = buf[stream_ptr++];
+ 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)\n",
+ pixel_countdown);
+ }
+ } else { /* copy bytes if byte_run < 0 */
+ byte_run = -byte_run;
+ CHECK_PIXEL_PTR(byte_run);
+ for (j = 0; j < byte_run; j++) {
+ palette_idx1 = buf[stream_ptr++];
+ pixels[pixel_ptr++] = palette_idx1;
+ pixel_countdown--;
+ if (pixel_countdown < 0)
+ av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
+ pixel_countdown);
+ }
+ }
+ }
+
+ /* Now FLX is strange, in that it is "byte" as opposed to "pixel" run length compressed.
+ * This doesnt give us any good oportunity to perform word endian conversion
+ * during decompression. So if its requried (ie, this isnt a LE target, we do
+ * a second pass over the line here, swapping the bytes.
+ */
+ pixel = 0xFF00;
+ if (0xFF00 != LE_16(&pixel)) /* Check if its not an LE Target */
+ {
+ pixel_ptr = y_ptr;
+ pixel_countdown = s->avctx->width;
+ while (pixel_countdown > 0) {
+ *((signed short*)(&pixels[pixel_ptr])) = LE_16(&buf[pixel_ptr]);
+ pixel_ptr += 2;
+ }
+ }
+ 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 */
+ stream_ptr++;
+ pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */
+
+ while (pixel_countdown > 0) {
+ byte_run = (signed char)(buf[stream_ptr++]);
+ if (byte_run > 0) {
+ pixel = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+ CHECK_PIXEL_PTR(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;
+ CHECK_PIXEL_PTR(byte_run);
+ for (j = 0; j < byte_run; j++) {
+ *((signed short*)(&pixels[pixel_ptr])) = LE_16(&buf[stream_ptr]);
+ stream_ptr += 2;
+ 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);
+ stream_ptr += 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])) = LE_16(&buf[stream_ptr+pixel_ptr]);
+ pixel_ptr += 2;
+ pixel_countdown--;
+ }
+ stream_ptr += s->avctx->width*2;
+ }
+ }
+ break;
+
+ case FLI_MINI:
+ /* some sort of a thumbnail? disregard this chunk... */
+ stream_ptr += 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 ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1))
+ av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
+ "and final chunk ptr = %d\n", buf_size, stream_ptr);
+
+
+ *data_size=sizeof(AVFrame);
+ *(AVFrame*)data = s->frame;
+
+ return buf_size;
+}
+
+static int flic_decode_frame_24BPP(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ av_log(avctx, AV_LOG_ERROR, "24Bpp FLC Unsupported due to lack of test files.\n");
+ return -1;
+}
+
+static int flic_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ if (avctx->pix_fmt == PIX_FMT_PAL8) {
+ return flic_decode_frame_8BPP(avctx, data, data_size,
+ buf, buf_size);
+ }
+ else if ((avctx->pix_fmt == PIX_FMT_RGB555) ||
+ (avctx->pix_fmt == PIX_FMT_RGB565)) {
+ return flic_decode_frame_15_16BPP(avctx, data, data_size,
+ buf, buf_size);
+ }
+ else if (avctx->pix_fmt == PIX_FMT_BGR24) {
+ return flic_decode_frame_24BPP(avctx, data, data_size,
+ buf, buf_size);
+ }
+
+ /* Shouldnt 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 Format of FLC. My Science cant explain how this happened\n");
+ return -1;
+}
+
+
+static int flic_decode_end(AVCodecContext *avctx)
+{
+ FlicDecodeContext *s = avctx->priv_data;
+
+ if (s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ return 0;
+}
+
+AVCodec flic_decoder = {
+ "flic",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_FLIC,
+ sizeof(FlicDecodeContext),
+ flic_decode_init,
+ NULL,
+ flic_decode_end,
+ flic_decode_frame,
+ CODEC_CAP_DR1,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
diff --git a/contrib/ffmpeg/libavcodec/fraps.c b/contrib/ffmpeg/libavcodec/fraps.c
new file mode 100644
index 000000000..18d270049
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/fraps.c
@@ -0,0 +1,398 @@
+/*
+ * 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 fraps.c
+ * Lossless Fraps 'FPS1' decoder
+ * @author Roine Gustafsson <roine at users sf net>
+ * @author Konstantin Shishkov
+ *
+ * Codec algorithm for version 0 is taken from Transcode <www.transcoding.org>
+ *
+ * Version 2 files support by Konstantin Shishkov
+ */
+
+#include "avcodec.h"
+#include "bitstream.h"
+#include "dsputil.h"
+
+#define FPS_TAG MKTAG('F', 'P', 'S', 'x')
+
+/* symbol for Huffman tree node */
+#define HNODE -1
+
+/**
+ * Huffman node
+ * FIXME one day this should belong to one general framework
+ */
+typedef struct Node{
+ int16_t sym;
+ int16_t n0;
+ int count;
+}Node;
+
+/**
+ * local variable storage
+ */
+typedef struct FrapsContext{
+ AVCodecContext *avctx;
+ AVFrame frame;
+ Node nodes[512];
+ uint8_t *tmpbuf;
+ DSPContext dsp;
+} FrapsContext;
+
+
+/**
+ * initializes decoder
+ * @param avctx codec context
+ * @return 0 on success or negative if fails
+ */
+static int decode_init(AVCodecContext *avctx)
+{
+ FrapsContext * const s = avctx->priv_data;
+
+ avctx->coded_frame = (AVFrame*)&s->frame;
+ avctx->has_b_frames = 0;
+ avctx->pix_fmt= PIX_FMT_NONE; /* set in decode_frame */
+
+ s->avctx = avctx;
+ s->frame.data[0] = NULL;
+ s->tmpbuf = NULL;
+
+ dsputil_init(&s->dsp, avctx);
+
+ return 0;
+}
+
+/**
+ * Comparator - our nodes should ascend by count
+ * but with preserved symbol order
+ */
+static int huff_cmp(const Node *a, const Node *b){
+ return (a->count - b->count)*256 + a->sym - b->sym;
+}
+
+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 s;
+
+ s = nodes[node].sym;
+ if(s != HNODE || !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);
+ pfx |= 1;
+ get_tree_codes(bits, lens, xlat, nodes, nodes[node].n0+1, pfx, pl, pos);
+ }
+}
+
+static int build_huff_tree(VLC *vlc, Node *nodes, uint8_t *xlat)
+{
+ uint32_t bits[256];
+ int16_t lens[256];
+ int pos = 0;
+
+ get_tree_codes(bits, lens, xlat, nodes, 510, 0, 0, &pos);
+ return init_vlc(vlc, 9, pos, lens, 2, 2, bits, 4, 4, 0);
+}
+
+
+/**
+ * decode Fraps v2 packed plane
+ */
+static int fraps2_decode_plane(FrapsContext *s, uint8_t *dst, int stride, int w,
+ int h, uint8_t *src, int size, int Uoff)
+{
+ int i, j;
+ int cur_node;
+ GetBitContext gb;
+ VLC vlc;
+ int64_t sum = 0;
+ uint8_t recode[256];
+
+ for(i = 0; i < 256; i++){
+ s->nodes[i].sym = i;
+ s->nodes[i].count = LE_32(src);
+ s->nodes[i].n0 = -2;
+ if(s->nodes[i].count < 0) {
+ av_log(s->avctx, AV_LOG_ERROR, "Symbol count < 0\n");
+ return -1;
+ }
+ src += 4;
+ sum += s->nodes[i].count;
+ }
+ size -= 1024;
+
+ if(sum >> 31) {
+ av_log(s->avctx, AV_LOG_ERROR, "Too high symbol frequencies. Tree construction is not possible\n");
+ return -1;
+ }
+ qsort(s->nodes, 256, sizeof(Node), huff_cmp);
+ cur_node = 256;
+ for(i = 0; i < 511; i += 2){
+ s->nodes[cur_node].sym = HNODE;
+ s->nodes[cur_node].count = s->nodes[i].count + s->nodes[i+1].count;
+ s->nodes[cur_node].n0 = i;
+ for(j = cur_node; j > 0; j--){
+ if(s->nodes[j].count >= s->nodes[j - 1].count) break;
+ FFSWAP(Node, s->nodes[j], s->nodes[j - 1]);
+ }
+ cur_node++;
+ }
+ if(build_huff_tree(&vlc, s->nodes, recode) < 0){
+ av_log(s->avctx, AV_LOG_ERROR, "Error building tree\n");
+ return -1;
+ }
+ /* 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(s->tmpbuf, src, size >> 2);
+
+ init_get_bits(&gb, s->tmpbuf, size * 8);
+ for(j = 0; j < h; j++){
+ for(i = 0; i < w; i++){
+ dst[i] = recode[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;
+ }
+ dst += stride;
+ }
+ free_vlc(&vlc);
+ 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 buf input data frame
+ * @param buf_size size of input data frame
+ * @return number of consumed bytes on success or negative if decode fails
+ */
+static int decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ FrapsContext * const s = avctx->priv_data;
+ AVFrame *frame = data;
+ AVFrame * const f = (AVFrame*)&s->frame;
+ uint32_t header;
+ unsigned int version,header_size;
+ unsigned int x, y;
+ uint32_t *buf32;
+ uint32_t *luma1,*luma2,*cb,*cr;
+ uint32_t offs[4];
+ int i, is_chroma, planes;
+
+
+ header = LE_32(buf);
+ version = header & 0xff;
+ header_size = (header & (1<<30))? 8 : 4; /* bit 30 means pad to 8 bytes */
+
+ if (version > 2 && version != 4) {
+ av_log(avctx, AV_LOG_ERROR,
+ "This file is encoded with Fraps version %d. " \
+ "This codec can only decode version 0, 1, 2 and 4.\n", version);
+ return -1;
+ }
+
+ buf+=4;
+ if (header_size == 8)
+ buf+=4;
+
+ switch(version) {
+ case 0:
+ default:
+ /* Fraps v0 is a reordered YUV420 */
+ avctx->pix_fmt = PIX_FMT_YUV420P;
+
+ if ( (buf_size != avctx->width*avctx->height*3/2+header_size) &&
+ (buf_size != header_size) ) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Invalid frame length %d (should be %d)\n",
+ buf_size, avctx->width*avctx->height*3/2+header_size);
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ f->reference = 1;
+ f->buffer_hints = FF_BUFFER_HINTS_VALID |
+ FF_BUFFER_HINTS_PRESERVE |
+ FF_BUFFER_HINTS_REUSABLE;
+ if (avctx->reget_buffer(avctx, f)) {
+ av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+ return -1;
+ }
+ /* bit 31 means same as previous pic */
+ f->pict_type = (header & (1<<31))? FF_P_TYPE : FF_I_TYPE;
+ f->key_frame = f->pict_type == FF_I_TYPE;
+
+ if (f->pict_type == FF_I_TYPE) {
+ buf32=(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 */
+ avctx->pix_fmt = PIX_FMT_BGR24;
+
+ if ( (buf_size != avctx->width*avctx->height*3+header_size) &&
+ (buf_size != header_size) ) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Invalid frame length %d (should be %d)\n",
+ buf_size, avctx->width*avctx->height*3+header_size);
+ return -1;
+ }
+
+ f->reference = 1;
+ f->buffer_hints = FF_BUFFER_HINTS_VALID |
+ FF_BUFFER_HINTS_PRESERVE |
+ FF_BUFFER_HINTS_REUSABLE;
+ if (avctx->reget_buffer(avctx, f)) {
+ av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+ return -1;
+ }
+ /* bit 31 means same as previous pic */
+ f->pict_type = (header & (1<<31))? FF_P_TYPE : FF_I_TYPE;
+ f->key_frame = f->pict_type == FF_I_TYPE;
+
+ if (f->pict_type == FF_I_TYPE) {
+ for(y=0; y<avctx->height; y++)
+ memcpy(&f->data[0][ (avctx->height-y)*f->linesize[0] ],
+ &buf[y*avctx->width*3],
+ f->linesize[0]);
+ }
+ break;
+
+ case 2:
+ case 4:
+ /**
+ * Fraps v2 is Huffman-coded YUV420 planes
+ * Fraps v4 is virtually the same
+ */
+ avctx->pix_fmt = PIX_FMT_YUV420P;
+ planes = 3;
+ f->reference = 1;
+ f->buffer_hints = FF_BUFFER_HINTS_VALID |
+ FF_BUFFER_HINTS_PRESERVE |
+ FF_BUFFER_HINTS_REUSABLE;
+ if (avctx->reget_buffer(avctx, f)) {
+ av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+ return -1;
+ }
+ /* skip frame */
+ if(buf_size == 8) {
+ f->pict_type = FF_P_TYPE;
+ f->key_frame = 0;
+ break;
+ }
+ f->pict_type = FF_I_TYPE;
+ f->key_frame = 1;
+ if ((LE_32(buf) != FPS_TAG)||(buf_size < (planes*1024 + 24))) {
+ av_log(avctx, AV_LOG_ERROR, "Fraps: error in data stream\n");
+ return -1;
+ }
+ for(i = 0; i < planes; i++) {
+ offs[i] = LE_32(buf + 4 + i * 4);
+ if(offs[i] >= buf_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 -1;
+ }
+ }
+ offs[planes] = buf_size;
+ for(i = 0; i < planes; i++){
+ is_chroma = !!i;
+ s->tmpbuf = av_realloc(s->tmpbuf, offs[i + 1] - offs[i] - 1024 + FF_INPUT_BUFFER_PADDING_SIZE);
+ if(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) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Error decoding plane %i\n", i);
+ return -1;
+ }
+ }
+ break;
+ }
+
+ *frame = *f;
+ *data_size = sizeof(AVFrame);
+
+ return buf_size;
+}
+
+
+/**
+ * closes decoder
+ * @param avctx codec context
+ * @return 0 on success or negative if fails
+ */
+static int decode_end(AVCodecContext *avctx)
+{
+ FrapsContext *s = (FrapsContext*)avctx->priv_data;
+
+ if (s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ av_freep(&s->tmpbuf);
+ return 0;
+}
+
+
+AVCodec fraps_decoder = {
+ "fraps",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_FRAPS,
+ sizeof(FrapsContext),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/g726.c b/contrib/ffmpeg/libavcodec/g726.c
new file mode 100644
index 000000000..c509292b6
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/g726.c
@@ -0,0 +1,429 @@
+/*
+ * 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 <limits.h>
+#include "avcodec.h"
+#include "common.h"
+#include "bitstream.h"
+
+/**
+ * G.726 11bit float.
+ * G.726 Standard uses rather odd 11bit floating point arithmentic for
+ * numerous occasions. It's a mistery to me why they did it this way
+ * instead of simply using 32bit integer arithmetic.
+ */
+typedef struct Float11 {
+ int sign; /**< 1bit sign */
+ int exp; /**< 4bit exponent */
+ int mant; /**< 6bit mantissa */
+} Float11;
+
+static inline Float11* i2f(int16_t 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) << 7;
+ res = exp > 26 ? res << (exp - 26) : res >> (26 - exp);
+ return (f1->sign ^ f2->sign) ? -res : res;
+}
+
+static inline int sgn(int value)
+{
+ return (value < 0) ? -1 : 1;
+}
+
+typedef struct G726Tables {
+ int bits; /**< bits per sample */
+ int* quant; /**< quantization table */
+ int* iquant; /**< inverse quantization table */
+ int* W; /**< special table #1 ;-) */
+ int* F; /**< special table #2 */
+} G726Tables;
+
+typedef struct G726Context {
+ 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 */
+} G726Context;
+
+static int quant_tbl16[] = /**< 16kbit/s 2bits per sample */
+ { 260, INT_MAX };
+static int iquant_tbl16[] =
+ { 116, 365, 365, 116 };
+static int W_tbl16[] =
+ { -22, 439, 439, -22 };
+static int F_tbl16[] =
+ { 0, 7, 7, 0 };
+
+static int quant_tbl24[] = /**< 24kbit/s 3bits per sample */
+ { 7, 217, 330, INT_MAX };
+static int iquant_tbl24[] =
+ { INT_MIN, 135, 273, 373, 373, 273, 135, INT_MIN };
+static int W_tbl24[] =
+ { -4, 30, 137, 582, 582, 137, 30, -4 };
+static int F_tbl24[] =
+ { 0, 1, 2, 7, 7, 2, 1, 0 };
+
+static int quant_tbl32[] = /**< 32kbit/s 4bits per sample */
+ { -125, 79, 177, 245, 299, 348, 399, INT_MAX };
+static int iquant_tbl32[] =
+ { INT_MIN, 4, 135, 213, 273, 323, 373, 425,
+ 425, 373, 323, 273, 213, 135, 4, INT_MIN };
+static int W_tbl32[] =
+ { -12, 18, 41, 64, 112, 198, 355, 1122,
+ 1122, 355, 198, 112, 64, 41, 18, -12};
+static int F_tbl32[] =
+ { 0, 0, 0, 1, 1, 1, 3, 7, 7, 3, 1, 1, 1, 0, 0, 0 };
+
+static 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 int iquant_tbl40[] =
+ { INT_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, INT_MIN };
+static int 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 int 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 G726Tables G726Tables_pool[] =
+ {{ 2, quant_tbl16, iquant_tbl16, W_tbl16, F_tbl16 },
+ { 3, quant_tbl24, iquant_tbl24, W_tbl24, F_tbl24 },
+ { 4, quant_tbl32, iquant_tbl32, W_tbl32, F_tbl32 },
+ { 5, 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->tbls->bits != 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) >> (14-dex));
+}
+
+static inline int16_t g726_iterate(G726Context* c, int16_t I)
+{
+ int dq, re_signal, pk0, fa1, i, tr, ylint, ylfrac, thr2, al, dq0;
+ Float11 f;
+
+ dq = inverse_quant(c, I);
+ if (I >> (c->tbls->bits - 1)) /* get the sign */
+ dq = -dq;
+ re_signal = c->se + dq;
+
+ /* Transition detect */
+ ylint = (c->yl >> 15);
+ ylfrac = (c->yl >> 10) & 0x1f;
+ thr2 = (ylint > 9) ? 0x1f << 10 : (0x20 + ylfrac) << ylint;
+ if (c->td == 1 && abs(dq) > ((thr2+(thr2>>1))>>1))
+ tr = 1;
+ else
+ tr = 0;
+
+ /* 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 = 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] = clip(c->a[1], -12288, 12288);
+ c->a[0] += 64*3*pk0*c->pk[0] - (c->a[0] >> 8);
+ c->a[0] = 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 >> (c->tbls->bits - 1); /* Isn't it crazy ?!?! */
+
+ /* Update tone detect [I'm not sure 'tr == 0' is really needed] */
+ c->td = (tr == 0 && c->a[1] < -11776);
+
+ /* Update Ap */
+ c->dms += ((c->tbls->F[I]<<9) - c->dms) >> 5;
+ c->dml += ((c->tbls->F[I]<<11) - c->dml) >> 7;
+ if (tr)
+ c->ap = 256;
+ else if (c->y > 1535 && !c->td && (abs((c->dms << 2) - c->dml) < (c->dml >> 3)))
+ c->ap += (-c->ap) >> 4;
+ else
+ c->ap += (0x200 - c->ap) >> 4;
+
+ /* Update Yu and Yl */
+ c->yu = clip(c->y + (((c->tbls->W[I] << 5) - 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 clip(re_signal << 2, -0xffff, 0xffff);
+}
+
+static int g726_reset(G726Context* c, int bit_rate)
+{
+ int i;
+
+ c->tbls = &G726Tables_pool[bit_rate/8000 - 2];
+ for (i=0; i<2; i++) {
+ i2f(0, &c->sr[i]);
+ c->a[i] = 0;
+ c->pk[i] = 1;
+ }
+ for (i=0; i<6; i++) {
+ i2f(0, &c->dq[i]);
+ c->b[i] = 0;
+ }
+ c->ap = 0;
+ c->dms = 0;
+ c->dml = 0;
+ c->yu = 544;
+ c->yl = 34816;
+ c->td = 0;
+
+ c->se = 0;
+ c->sez = 0;
+ c->y = 544;
+
+ return 0;
+}
+
+static int16_t g726_decode(G726Context* c, int16_t i)
+{
+ return g726_iterate(c, i);
+}
+
+#ifdef CONFIG_ENCODERS
+static int16_t g726_encode(G726Context* c, int16_t sig)
+{
+ uint8_t i;
+
+ i = quant(c, sig/4 - c->se) & ((1<<c->tbls->bits) - 1);
+ g726_iterate(c, i);
+ return i;
+}
+#endif
+
+/* Interfacing to the libavcodec */
+
+typedef struct AVG726Context {
+ G726Context c;
+ int bits_left;
+ int bit_buffer;
+ int code_size;
+} AVG726Context;
+
+static int g726_init(AVCodecContext * avctx)
+{
+ AVG726Context* c = (AVG726Context*)avctx->priv_data;
+
+ if (avctx->channels != 1 ||
+ (avctx->bit_rate != 16000 && avctx->bit_rate != 24000 &&
+ avctx->bit_rate != 32000 && avctx->bit_rate != 40000)) {
+ av_log(avctx, AV_LOG_ERROR, "G726: unsupported audio format\n");
+ return -1;
+ }
+ if (avctx->sample_rate != 8000 && avctx->strict_std_compliance>FF_COMPLIANCE_INOFFICIAL) {
+ av_log(avctx, AV_LOG_ERROR, "G726: unsupported audio format\n");
+ return -1;
+ }
+ g726_reset(&c->c, avctx->bit_rate);
+ c->code_size = c->c.tbls->bits;
+ c->bit_buffer = 0;
+ c->bits_left = 0;
+
+ avctx->coded_frame = avcodec_alloc_frame();
+ if (!avctx->coded_frame)
+ return -ENOMEM;
+ avctx->coded_frame->key_frame = 1;
+
+ return 0;
+}
+
+static int g726_close(AVCodecContext *avctx)
+{
+ av_freep(&avctx->coded_frame);
+ return 0;
+}
+
+#ifdef CONFIG_ENCODERS
+static int g726_encode_frame(AVCodecContext *avctx,
+ uint8_t *dst, int buf_size, void *data)
+{
+ AVG726Context *c = avctx->priv_data;
+ short *samples = data;
+ PutBitContext pb;
+
+ init_put_bits(&pb, dst, 1024*1024);
+
+ for (; buf_size; buf_size--)
+ put_bits(&pb, c->code_size, g726_encode(&c->c, *samples++));
+
+ flush_put_bits(&pb);
+
+ return put_bits_count(&pb)>>3;
+}
+#endif
+
+static int g726_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ AVG726Context *c = avctx->priv_data;
+ short *samples = data;
+ uint8_t code;
+ uint8_t mask;
+ GetBitContext gb;
+
+ if (!buf_size)
+ goto out;
+
+ mask = (1<<c->code_size) - 1;
+ init_get_bits(&gb, buf, buf_size * 8);
+ if (c->bits_left) {
+ int s = c->code_size - c->bits_left;;
+ code = (c->bit_buffer << s) | get_bits(&gb, s);
+ *samples++ = g726_decode(&c->c, code & mask);
+ }
+
+ while (get_bits_count(&gb) + c->code_size <= buf_size*8)
+ *samples++ = g726_decode(&c->c, get_bits(&gb, c->code_size) & mask);
+
+ c->bits_left = buf_size*8 - get_bits_count(&gb);
+ c->bit_buffer = get_bits(&gb, c->bits_left);
+
+out:
+ *data_size = (uint8_t*)samples - (uint8_t*)data;
+ return buf_size;
+}
+
+#ifdef CONFIG_ENCODERS
+AVCodec adpcm_g726_encoder = {
+ "g726",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_ADPCM_G726,
+ sizeof(AVG726Context),
+ g726_init,
+ g726_encode_frame,
+ g726_close,
+ NULL,
+};
+#endif //CONFIG_ENCODERS
+
+AVCodec adpcm_g726_decoder = {
+ "g726",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_ADPCM_G726,
+ sizeof(AVG726Context),
+ g726_init,
+ NULL,
+ g726_close,
+ g726_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/gif.c b/contrib/ffmpeg/libavcodec/gif.c
new file mode 100644
index 000000000..f67ab52c2
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/gif.c
@@ -0,0 +1,350 @@
+/*
+ * 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:
+ * - currently no compression is performed,
+ * in fact the size of the data is 9/8 the size of the image in 8bpp
+ * - 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
+ *
+ * this url claims to have an LZW algorithm not covered by Unisys patent:
+ * http://www.msg.net/utility/whirlgif/gifencod.html
+ * could help reduce the size of the files _a lot_...
+ * some sites mentions an RLE type compression also.
+ */
+
+#include "avcodec.h"
+#include "bytestream.h"
+#include "bitstream.h"
+
+/* bitstream minipacket size */
+#define GIF_CHUNKS 100
+
+/* slows down the decoding (and some browsers don't like it) */
+/* update on the 'some browsers don't like it issue from above: this was probably due to missing 'Data Sub-block Terminator' (byte 19) in the app_header */
+#define GIF_ADD_APP_HEADER // required to enable looping of animated gif
+
+typedef struct {
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+} rgb_triplet;
+
+/* we use the standard 216 color palette */
+
+/* this script was used to create the palette:
+ * for r in 00 33 66 99 cc ff; do for g in 00 33 66 99 cc ff; do echo -n " "; for b in 00 33 66 99 cc ff; do
+ * echo -n "{ 0x$r, 0x$g, 0x$b }, "; done; echo ""; done; done
+ */
+
+static const rgb_triplet gif_clut[216] = {
+ { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x33 }, { 0x00, 0x00, 0x66 }, { 0x00, 0x00, 0x99 }, { 0x00, 0x00, 0xcc }, { 0x00, 0x00, 0xff },
+ { 0x00, 0x33, 0x00 }, { 0x00, 0x33, 0x33 }, { 0x00, 0x33, 0x66 }, { 0x00, 0x33, 0x99 }, { 0x00, 0x33, 0xcc }, { 0x00, 0x33, 0xff },
+ { 0x00, 0x66, 0x00 }, { 0x00, 0x66, 0x33 }, { 0x00, 0x66, 0x66 }, { 0x00, 0x66, 0x99 }, { 0x00, 0x66, 0xcc }, { 0x00, 0x66, 0xff },
+ { 0x00, 0x99, 0x00 }, { 0x00, 0x99, 0x33 }, { 0x00, 0x99, 0x66 }, { 0x00, 0x99, 0x99 }, { 0x00, 0x99, 0xcc }, { 0x00, 0x99, 0xff },
+ { 0x00, 0xcc, 0x00 }, { 0x00, 0xcc, 0x33 }, { 0x00, 0xcc, 0x66 }, { 0x00, 0xcc, 0x99 }, { 0x00, 0xcc, 0xcc }, { 0x00, 0xcc, 0xff },
+ { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0x33 }, { 0x00, 0xff, 0x66 }, { 0x00, 0xff, 0x99 }, { 0x00, 0xff, 0xcc }, { 0x00, 0xff, 0xff },
+ { 0x33, 0x00, 0x00 }, { 0x33, 0x00, 0x33 }, { 0x33, 0x00, 0x66 }, { 0x33, 0x00, 0x99 }, { 0x33, 0x00, 0xcc }, { 0x33, 0x00, 0xff },
+ { 0x33, 0x33, 0x00 }, { 0x33, 0x33, 0x33 }, { 0x33, 0x33, 0x66 }, { 0x33, 0x33, 0x99 }, { 0x33, 0x33, 0xcc }, { 0x33, 0x33, 0xff },
+ { 0x33, 0x66, 0x00 }, { 0x33, 0x66, 0x33 }, { 0x33, 0x66, 0x66 }, { 0x33, 0x66, 0x99 }, { 0x33, 0x66, 0xcc }, { 0x33, 0x66, 0xff },
+ { 0x33, 0x99, 0x00 }, { 0x33, 0x99, 0x33 }, { 0x33, 0x99, 0x66 }, { 0x33, 0x99, 0x99 }, { 0x33, 0x99, 0xcc }, { 0x33, 0x99, 0xff },
+ { 0x33, 0xcc, 0x00 }, { 0x33, 0xcc, 0x33 }, { 0x33, 0xcc, 0x66 }, { 0x33, 0xcc, 0x99 }, { 0x33, 0xcc, 0xcc }, { 0x33, 0xcc, 0xff },
+ { 0x33, 0xff, 0x00 }, { 0x33, 0xff, 0x33 }, { 0x33, 0xff, 0x66 }, { 0x33, 0xff, 0x99 }, { 0x33, 0xff, 0xcc }, { 0x33, 0xff, 0xff },
+ { 0x66, 0x00, 0x00 }, { 0x66, 0x00, 0x33 }, { 0x66, 0x00, 0x66 }, { 0x66, 0x00, 0x99 }, { 0x66, 0x00, 0xcc }, { 0x66, 0x00, 0xff },
+ { 0x66, 0x33, 0x00 }, { 0x66, 0x33, 0x33 }, { 0x66, 0x33, 0x66 }, { 0x66, 0x33, 0x99 }, { 0x66, 0x33, 0xcc }, { 0x66, 0x33, 0xff },
+ { 0x66, 0x66, 0x00 }, { 0x66, 0x66, 0x33 }, { 0x66, 0x66, 0x66 }, { 0x66, 0x66, 0x99 }, { 0x66, 0x66, 0xcc }, { 0x66, 0x66, 0xff },
+ { 0x66, 0x99, 0x00 }, { 0x66, 0x99, 0x33 }, { 0x66, 0x99, 0x66 }, { 0x66, 0x99, 0x99 }, { 0x66, 0x99, 0xcc }, { 0x66, 0x99, 0xff },
+ { 0x66, 0xcc, 0x00 }, { 0x66, 0xcc, 0x33 }, { 0x66, 0xcc, 0x66 }, { 0x66, 0xcc, 0x99 }, { 0x66, 0xcc, 0xcc }, { 0x66, 0xcc, 0xff },
+ { 0x66, 0xff, 0x00 }, { 0x66, 0xff, 0x33 }, { 0x66, 0xff, 0x66 }, { 0x66, 0xff, 0x99 }, { 0x66, 0xff, 0xcc }, { 0x66, 0xff, 0xff },
+ { 0x99, 0x00, 0x00 }, { 0x99, 0x00, 0x33 }, { 0x99, 0x00, 0x66 }, { 0x99, 0x00, 0x99 }, { 0x99, 0x00, 0xcc }, { 0x99, 0x00, 0xff },
+ { 0x99, 0x33, 0x00 }, { 0x99, 0x33, 0x33 }, { 0x99, 0x33, 0x66 }, { 0x99, 0x33, 0x99 }, { 0x99, 0x33, 0xcc }, { 0x99, 0x33, 0xff },
+ { 0x99, 0x66, 0x00 }, { 0x99, 0x66, 0x33 }, { 0x99, 0x66, 0x66 }, { 0x99, 0x66, 0x99 }, { 0x99, 0x66, 0xcc }, { 0x99, 0x66, 0xff },
+ { 0x99, 0x99, 0x00 }, { 0x99, 0x99, 0x33 }, { 0x99, 0x99, 0x66 }, { 0x99, 0x99, 0x99 }, { 0x99, 0x99, 0xcc }, { 0x99, 0x99, 0xff },
+ { 0x99, 0xcc, 0x00 }, { 0x99, 0xcc, 0x33 }, { 0x99, 0xcc, 0x66 }, { 0x99, 0xcc, 0x99 }, { 0x99, 0xcc, 0xcc }, { 0x99, 0xcc, 0xff },
+ { 0x99, 0xff, 0x00 }, { 0x99, 0xff, 0x33 }, { 0x99, 0xff, 0x66 }, { 0x99, 0xff, 0x99 }, { 0x99, 0xff, 0xcc }, { 0x99, 0xff, 0xff },
+ { 0xcc, 0x00, 0x00 }, { 0xcc, 0x00, 0x33 }, { 0xcc, 0x00, 0x66 }, { 0xcc, 0x00, 0x99 }, { 0xcc, 0x00, 0xcc }, { 0xcc, 0x00, 0xff },
+ { 0xcc, 0x33, 0x00 }, { 0xcc, 0x33, 0x33 }, { 0xcc, 0x33, 0x66 }, { 0xcc, 0x33, 0x99 }, { 0xcc, 0x33, 0xcc }, { 0xcc, 0x33, 0xff },
+ { 0xcc, 0x66, 0x00 }, { 0xcc, 0x66, 0x33 }, { 0xcc, 0x66, 0x66 }, { 0xcc, 0x66, 0x99 }, { 0xcc, 0x66, 0xcc }, { 0xcc, 0x66, 0xff },
+ { 0xcc, 0x99, 0x00 }, { 0xcc, 0x99, 0x33 }, { 0xcc, 0x99, 0x66 }, { 0xcc, 0x99, 0x99 }, { 0xcc, 0x99, 0xcc }, { 0xcc, 0x99, 0xff },
+ { 0xcc, 0xcc, 0x00 }, { 0xcc, 0xcc, 0x33 }, { 0xcc, 0xcc, 0x66 }, { 0xcc, 0xcc, 0x99 }, { 0xcc, 0xcc, 0xcc }, { 0xcc, 0xcc, 0xff },
+ { 0xcc, 0xff, 0x00 }, { 0xcc, 0xff, 0x33 }, { 0xcc, 0xff, 0x66 }, { 0xcc, 0xff, 0x99 }, { 0xcc, 0xff, 0xcc }, { 0xcc, 0xff, 0xff },
+ { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0x33 }, { 0xff, 0x00, 0x66 }, { 0xff, 0x00, 0x99 }, { 0xff, 0x00, 0xcc }, { 0xff, 0x00, 0xff },
+ { 0xff, 0x33, 0x00 }, { 0xff, 0x33, 0x33 }, { 0xff, 0x33, 0x66 }, { 0xff, 0x33, 0x99 }, { 0xff, 0x33, 0xcc }, { 0xff, 0x33, 0xff },
+ { 0xff, 0x66, 0x00 }, { 0xff, 0x66, 0x33 }, { 0xff, 0x66, 0x66 }, { 0xff, 0x66, 0x99 }, { 0xff, 0x66, 0xcc }, { 0xff, 0x66, 0xff },
+ { 0xff, 0x99, 0x00 }, { 0xff, 0x99, 0x33 }, { 0xff, 0x99, 0x66 }, { 0xff, 0x99, 0x99 }, { 0xff, 0x99, 0xcc }, { 0xff, 0x99, 0xff },
+ { 0xff, 0xcc, 0x00 }, { 0xff, 0xcc, 0x33 }, { 0xff, 0xcc, 0x66 }, { 0xff, 0xcc, 0x99 }, { 0xff, 0xcc, 0xcc }, { 0xff, 0xcc, 0xff },
+ { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0x33 }, { 0xff, 0xff, 0x66 }, { 0xff, 0xff, 0x99 }, { 0xff, 0xff, 0xcc }, { 0xff, 0xff, 0xff },
+};
+
+/* The GIF format uses reversed order for bitstreams... */
+/* at least they don't use PDP_ENDIAN :) */
+/* so we 'extend' PutBitContext. hmmm, OOP :) */
+/* seems this thing changed slightly since I wrote it... */
+
+#ifdef ALT_BITSTREAM_WRITER
+# error no ALT_BITSTREAM_WRITER support for now
+#endif
+
+static void gif_put_bits_rev(PutBitContext *s, int n, unsigned int value)
+{
+ unsigned int bit_buf;
+ int bit_cnt;
+
+ // printf("put_bits=%d %x\n", n, value);
+ assert(n == 32 || value < (1U << n));
+
+ bit_buf = s->bit_buf;
+ bit_cnt = 32 - s->bit_left; /* XXX:lazyness... was = s->bit_cnt; */
+
+ // printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf);
+ /* XXX: optimize */
+ if (n < (32-bit_cnt)) {
+ bit_buf |= value << (bit_cnt);
+ bit_cnt+=n;
+ } else {
+ bit_buf |= value << (bit_cnt);
+
+ *s->buf_ptr = bit_buf & 0xff;
+ s->buf_ptr[1] = (bit_buf >> 8) & 0xff;
+ s->buf_ptr[2] = (bit_buf >> 16) & 0xff;
+ s->buf_ptr[3] = (bit_buf >> 24) & 0xff;
+
+ //printf("bitbuf = %08x\n", bit_buf);
+ s->buf_ptr+=4;
+ if (s->buf_ptr >= s->buf_end)
+ puts("bit buffer overflow !!"); // should never happen ! who got rid of the callback ???
+// flush_buffer_rev(s);
+ bit_cnt=bit_cnt + n - 32;
+ if (bit_cnt == 0) {
+ bit_buf = 0;
+ } else {
+ bit_buf = value >> (n - bit_cnt);
+ }
+ }
+
+ s->bit_buf = bit_buf;
+ s->bit_left = 32 - bit_cnt;
+}
+
+/* pad the end of the output stream with zeros */
+static void gif_flush_put_bits_rev(PutBitContext *s)
+{
+ while (s->bit_left < 32) {
+ /* XXX: should test end of buffer */
+ *s->buf_ptr++=s->bit_buf & 0xff;
+ s->bit_buf>>=8;
+ s->bit_left+=8;
+ }
+// flush_buffer_rev(s);
+ s->bit_left=32;
+ s->bit_buf=0;
+}
+
+/* !RevPutBitContext */
+
+/* GIF header */
+static int gif_image_write_header(uint8_t **bytestream,
+ int width, int height, int loop_count,
+ uint32_t *palette)
+{
+ int i;
+ unsigned int v;
+
+ bytestream_put_buffer(bytestream, "GIF", 3);
+ bytestream_put_buffer(bytestream, "89a", 3);
+ bytestream_put_le16(bytestream, width);
+ bytestream_put_le16(bytestream, 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 */
+ if (!palette) {
+ bytestream_put_buffer(bytestream, (const unsigned char *)gif_clut, 216*3);
+ for(i=0;i<((256-216)*3);i++)
+ bytestream_put_byte(bytestream, 0);
+ } else {
+ for(i=0;i<256;i++) {
+ v = palette[i];
+ bytestream_put_byte(bytestream, (v >> 16) & 0xff);
+ bytestream_put_byte(bytestream, (v >> 8) & 0xff);
+ bytestream_put_byte(bytestream, (v) & 0xff);
+ }
+ }
+
+ /* update: this is the 'NETSCAPE EXTENSION' that allows for looped animated gif
+ see http://members.aol.com/royalef/gifabout.htm#net-extension
+
+ byte 1 : 33 (hex 0x21) GIF Extension code
+ byte 2 : 255 (hex 0xFF) Application Extension Label
+ byte 3 : 11 (hex (0x0B) Length of Application Block
+ (eleven bytes of data to follow)
+ bytes 4 to 11 : "NETSCAPE"
+ bytes 12 to 14 : "2.0"
+ byte 15 : 3 (hex 0x03) Length of Data Sub-Block
+ (three bytes of data to follow)
+ byte 16 : 1 (hex 0x01)
+ bytes 17 to 18 : 0 to 65535, an unsigned integer in
+ lo-hi byte format. This indicate the
+ number of iterations the loop should
+ be executed.
+ bytes 19 : 0 (hex 0x00) a Data Sub-block Terminator
+ */
+
+ /* application extension header */
+#ifdef GIF_ADD_APP_HEADER
+ if (loop_count >= 0 && loop_count <= 65535) {
+ bytestream_put_byte(bytestream, 0x21);
+ bytestream_put_byte(bytestream, 0xff);
+ bytestream_put_byte(bytestream, 0x0b);
+ bytestream_put_buffer(bytestream, "NETSCAPE2.0", 11); // bytes 4 to 14
+ bytestream_put_byte(bytestream, 0x03); // byte 15
+ bytestream_put_byte(bytestream, 0x01); // byte 16
+ bytestream_put_le16(bytestream, (uint16_t)loop_count);
+ bytestream_put_byte(bytestream, 0x00); // byte 19
+ }
+#endif
+ return 0;
+}
+
+/* this is maybe slow, but allows for extensions */
+static inline unsigned char gif_clut_index(uint8_t r, uint8_t g, uint8_t b)
+{
+ return ((((r)/47)%6)*6*6+(((g)/47)%6)*6+(((b)/47)%6));
+}
+
+
+static int gif_image_write_image(uint8_t **bytestream,
+ int x1, int y1, int width, int height,
+ const uint8_t *buf, int linesize, int pix_fmt)
+{
+ PutBitContext p;
+ uint8_t buffer[200]; /* 100 * 9 / 8 = 113 */
+ int i, left, w, v;
+ const uint8_t *ptr;
+ /* image block */
+
+ bytestream_put_byte(bytestream, 0x2c);
+ bytestream_put_le16(bytestream, x1);
+ bytestream_put_le16(bytestream, y1);
+ bytestream_put_le16(bytestream, width);
+ bytestream_put_le16(bytestream, height);
+ bytestream_put_byte(bytestream, 0x00); /* flags */
+ /* no local clut */
+
+ bytestream_put_byte(bytestream, 0x08);
+
+ left= width * height;
+
+ init_put_bits(&p, buffer, 130);
+
+/*
+ * the thing here is the bitstream is written as little packets, with a size byte before
+ * but it's still the same bitstream between packets (no flush !)
+ */
+ ptr = buf;
+ w = width;
+ while(left>0) {
+
+ gif_put_bits_rev(&p, 9, 0x0100); /* clear code */
+
+ for(i=(left<GIF_CHUNKS)?left:GIF_CHUNKS;i;i--) {
+ if (pix_fmt == PIX_FMT_RGB24) {
+ v = gif_clut_index(ptr[0], ptr[1], ptr[2]);
+ ptr+=3;
+ } else {
+ v = *ptr++;
+ }
+ gif_put_bits_rev(&p, 9, v);
+ if (--w == 0) {
+ w = width;
+ buf += linesize;
+ ptr = buf;
+ }
+ }
+
+ if(left<=GIF_CHUNKS) {
+ gif_put_bits_rev(&p, 9, 0x101); /* end of stream */
+ gif_flush_put_bits_rev(&p);
+ }
+ if(pbBufPtr(&p) - p.buf > 0) {
+ bytestream_put_byte(bytestream, pbBufPtr(&p) - p.buf); /* byte count of the packet */
+ bytestream_put_buffer(bytestream, p.buf, pbBufPtr(&p) - p.buf); /* the actual buffer */
+ p.buf_ptr = p.buf; /* dequeue the bytes off the bitstream */
+ }
+ left-=GIF_CHUNKS;
+ }
+ bytestream_put_byte(bytestream, 0x00); /* end of image block */
+ bytestream_put_byte(bytestream, 0x3b);
+ return 0;
+}
+
+typedef struct {
+ int64_t time, file_time;
+ uint8_t buffer[100]; /* data chunks */
+ AVFrame picture;
+} GIFContext;
+
+static int gif_encode_init(AVCodecContext *avctx)
+{
+ GIFContext *s = avctx->priv_data;
+
+ avctx->coded_frame = &s->picture;
+ return 0;
+}
+
+/* better than nothing gif encoder */
+static int gif_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data)
+{
+ GIFContext *s = avctx->priv_data;
+ AVFrame *pict = data;
+ AVFrame *const p = (AVFrame *)&s->picture;
+ uint8_t *outbuf_ptr = outbuf;
+
+ *p = *pict;
+ p->pict_type = FF_I_TYPE;
+ p->key_frame = 1;
+ gif_image_write_header(&outbuf_ptr, avctx->width, avctx->height, -1, (uint32_t *)pict->data[1]);
+ gif_image_write_image(&outbuf_ptr, 0, 0, avctx->width, avctx->height, pict->data[0], pict->linesize[0], PIX_FMT_PAL8);
+ return outbuf_ptr - outbuf;
+}
+
+AVCodec gif_encoder = {
+ "gif",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_GIF,
+ sizeof(GIFContext),
+ gif_encode_init,
+ gif_encode_frame,
+ NULL, //encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_PAL8, -1},
+};
diff --git a/contrib/ffmpeg/libavcodec/gifdec.c b/contrib/ffmpeg/libavcodec/gifdec.c
new file mode 100644
index 000000000..5a5712299
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/gifdec.c
@@ -0,0 +1,339 @@
+/*
+ * GIF decoder
+ * Copyright (c) 2003 Fabrice Bellard.
+ * 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
+ */
+
+//#define DEBUG
+
+#include "avcodec.h"
+#include "bytestream.h"
+#include "lzw.h"
+
+#define GCE_DISPOSAL_NONE 0
+#define GCE_DISPOSAL_INPLACE 1
+#define GCE_DISPOSAL_BACKGROUND 2
+#define GCE_DISPOSAL_RESTORE 3
+
+typedef struct GifState {
+ AVFrame picture;
+ int screen_width;
+ int screen_height;
+ int bits_per_pixel;
+ int background_color_index;
+ int transparent_color_index;
+ int color_resolution;
+ uint32_t *image_palette;
+
+ /* after the frame is displayed, the disposal method is used */
+ int gce_disposal;
+ /* delay during which the frame is shown */
+ int gce_delay;
+
+ /* LZW compatible decoder */
+ uint8_t *bytestream;
+ LZWState *lzw;
+
+ /* aux buffers */
+ uint8_t global_palette[256 * 3];
+ uint8_t local_palette[256 * 3];
+} GifState;
+
+static const uint8_t gif87a_sig[6] = "GIF87a";
+static const uint8_t gif89a_sig[6] = "GIF89a";
+
+static int gif_read_image(GifState *s)
+{
+ int left, top, width, height, bits_per_pixel, code_size, flags;
+ int is_interleaved, has_local_palette, y, pass, y1, linesize, n, i;
+ uint8_t *ptr, *spal, *palette, *ptr1;
+
+ left = bytestream_get_le16(&s->bytestream);
+ top = bytestream_get_le16(&s->bytestream);
+ width = bytestream_get_le16(&s->bytestream);
+ height = bytestream_get_le16(&s->bytestream);
+ flags = bytestream_get_byte(&s->bytestream);
+ is_interleaved = flags & 0x40;
+ has_local_palette = flags & 0x80;
+ bits_per_pixel = (flags & 0x07) + 1;
+#ifdef DEBUG
+ dprintf("gif: image x=%d y=%d w=%d h=%d\n", left, top, width, height);
+#endif
+
+ if (has_local_palette) {
+ bytestream_get_buffer(&s->bytestream, s->local_palette, 3 * (1 << bits_per_pixel));
+ palette = s->local_palette;
+ } else {
+ palette = s->global_palette;
+ bits_per_pixel = s->bits_per_pixel;
+ }
+
+ /* verify that all the image is inside the screen dimensions */
+ if (left + width > s->screen_width ||
+ top + height > s->screen_height)
+ return -EINVAL;
+
+ /* build the palette */
+ n = (1 << bits_per_pixel);
+ spal = palette;
+ for(i = 0; i < n; i++) {
+ s->image_palette[i] = (0xff << 24) |
+ (spal[0] << 16) | (spal[1] << 8) | (spal[2]);
+ spal += 3;
+ }
+ for(; i < 256; i++)
+ s->image_palette[i] = (0xff << 24);
+ /* handle transparency */
+ if (s->transparent_color_index >= 0)
+ s->image_palette[s->transparent_color_index] = 0;
+
+ /* now get the image data */
+ code_size = bytestream_get_byte(&s->bytestream);
+ //TODO: add proper data size
+ ff_lzw_decode_init(s->lzw, code_size, s->bytestream, 0, FF_LZW_GIF);
+
+ /* read all the image */
+ linesize = s->picture.linesize[0];
+ ptr1 = s->picture.data[0] + top * linesize + left;
+ ptr = ptr1;
+ pass = 0;
+ y1 = 0;
+ for (y = 0; y < height; y++) {
+ ff_lzw_decode(s->lzw, ptr, width);
+ if (is_interleaved) {
+ switch(pass) {
+ default:
+ case 0:
+ case 1:
+ y1 += 8;
+ ptr += linesize * 8;
+ if (y1 >= height) {
+ y1 = 4;
+ if (pass == 0)
+ ptr = ptr1 + linesize * 4;
+ else
+ ptr = ptr1 + linesize * 2;
+ 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;
+ }
+ }
+ /* read the garbage data until end marker is found */
+ ff_lzw_decode_tail(s->lzw);
+ s->bytestream = ff_lzw_cur_ptr(s->lzw);
+ return 0;
+}
+
+static int gif_read_extension(GifState *s)
+{
+ int ext_code, ext_len, i, gce_flags, gce_transparent_index;
+
+ /* extension */
+ ext_code = bytestream_get_byte(&s->bytestream);
+ ext_len = bytestream_get_byte(&s->bytestream);
+#ifdef DEBUG
+ dprintf("gif: ext_code=0x%x len=%d\n", ext_code, ext_len);
+#endif
+ switch(ext_code) {
+ case 0xf9:
+ if (ext_len != 4)
+ goto discard_ext;
+ s->transparent_color_index = -1;
+ gce_flags = bytestream_get_byte(&s->bytestream);
+ s->gce_delay = bytestream_get_le16(&s->bytestream);
+ gce_transparent_index = bytestream_get_byte(&s->bytestream);
+ if (gce_flags & 0x01)
+ s->transparent_color_index = gce_transparent_index;
+ else
+ s->transparent_color_index = -1;
+ s->gce_disposal = (gce_flags >> 2) & 0x7;
+#ifdef DEBUG
+ dprintf("gif: gce_flags=%x delay=%d tcolor=%d disposal=%d\n",
+ gce_flags, s->gce_delay,
+ s->transparent_color_index, s->gce_disposal);
+#endif
+ ext_len = bytestream_get_byte(&s->bytestream);
+ break;
+ }
+
+ /* NOTE: many extension blocks can come after */
+ discard_ext:
+ while (ext_len != 0) {
+ for (i = 0; i < ext_len; i++)
+ bytestream_get_byte(&s->bytestream);
+ ext_len = bytestream_get_byte(&s->bytestream);
+#ifdef DEBUG
+ dprintf("gif: ext_len1=%d\n", ext_len);
+#endif
+ }
+ return 0;
+}
+
+static int gif_read_header1(GifState *s)
+{
+ uint8_t sig[6];
+ int v, n;
+ int has_global_palette;
+
+ /* read gif signature */
+ bytestream_get_buffer(&s->bytestream, sig, 6);
+ if (memcmp(sig, gif87a_sig, 6) != 0 &&
+ memcmp(sig, gif89a_sig, 6) != 0)
+ return -1;
+
+ /* read screen header */
+ s->transparent_color_index = -1;
+ s->screen_width = bytestream_get_le16(&s->bytestream);
+ s->screen_height = bytestream_get_le16(&s->bytestream);
+ if( (unsigned)s->screen_width > 32767
+ || (unsigned)s->screen_height > 32767){
+ av_log(NULL, AV_LOG_ERROR, "picture size too large\n");
+ return -1;
+ }
+
+ v = bytestream_get_byte(&s->bytestream);
+ s->color_resolution = ((v & 0x70) >> 4) + 1;
+ has_global_palette = (v & 0x80);
+ s->bits_per_pixel = (v & 0x07) + 1;
+ s->background_color_index = bytestream_get_byte(&s->bytestream);
+ bytestream_get_byte(&s->bytestream); /* ignored */
+#ifdef DEBUG
+ dprintf("gif: screen_w=%d screen_h=%d bpp=%d global_palette=%d\n",
+ s->screen_width, s->screen_height, s->bits_per_pixel,
+ has_global_palette);
+#endif
+ if (has_global_palette) {
+ n = 1 << s->bits_per_pixel;
+ bytestream_get_buffer(&s->bytestream, s->global_palette, n * 3);
+ }
+ return 0;
+}
+
+static int gif_parse_next_image(GifState *s)
+{
+ int ret, code;
+
+ for (;;) {
+ code = bytestream_get_byte(&s->bytestream);
+#ifdef DEBUG
+ dprintf("gif: code=%02x '%c'\n", code, code);
+#endif
+ switch (code) {
+ case ',':
+ if (gif_read_image(s) < 0)
+ return -1;
+ ret = 0;
+ goto the_end;
+ case ';':
+ /* end of image */
+ ret = -1;
+ goto the_end;
+ case '!':
+ if (gif_read_extension(s) < 0)
+ return -1;
+ break;
+ case EOF:
+ default:
+ /* error or errneous EOF */
+ ret = -1;
+ goto the_end;
+ }
+ }
+ the_end:
+ return ret;
+}
+
+static int gif_decode_init(AVCodecContext *avctx)
+{
+ GifState *s = avctx->priv_data;
+
+ avcodec_get_frame_defaults(&s->picture);
+ avctx->coded_frame= &s->picture;
+ s->picture.data[0] = NULL;
+ ff_lzw_decode_open(&s->lzw);
+ return 0;
+}
+
+static int gif_decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size)
+{
+ GifState *s = avctx->priv_data;
+ AVFrame *picture = data;
+ int ret;
+
+ s->bytestream = buf;
+ if (gif_read_header1(s) < 0)
+ return -1;
+
+ avctx->pix_fmt = PIX_FMT_PAL8;
+ if (avcodec_check_dimensions(avctx, s->screen_width, s->screen_height))
+ return -1;
+ avcodec_set_dimensions(avctx, s->screen_width, s->screen_height);
+
+ if (s->picture.data[0])
+ avctx->release_buffer(avctx, &s->picture);
+ if (avctx->get_buffer(avctx, &s->picture) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+ s->image_palette = (uint32_t *)s->picture.data[1];
+ ret = gif_parse_next_image(s);
+ if (ret < 0)
+ return ret;
+
+ *picture = s->picture;
+ *data_size = sizeof(AVPicture);
+ return 0;
+}
+
+static int gif_decode_close(AVCodecContext *avctx)
+{
+ GifState *s = avctx->priv_data;
+
+ ff_lzw_decode_close(&s->lzw);
+ if(s->picture.data[0])
+ avctx->release_buffer(avctx, &s->picture);
+ return 0;
+}
+
+AVCodec gif_decoder = {
+ "gif",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_GIF,
+ sizeof(GifState),
+ gif_decode_init,
+ NULL,
+ gif_decode_close,
+ gif_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/golomb.c b/contrib/ffmpeg/libavcodec/golomb.c
new file mode 100644
index 000000000..50df4fc40
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/golomb.c
@@ -0,0 +1,156 @@
+/*
+ * exp golomb vlc stuff
+ * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/**
+ * @file golomb.c
+ * @brief
+ * exp golomb vlc stuff
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#include "common.h"
+
+const uint8_t ff_golomb_vlc_len[512]={
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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]={
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,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]={
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,
+};
diff --git a/contrib/ffmpeg/libavcodec/golomb.h b/contrib/ffmpeg/libavcodec/golomb.h
new file mode 100644
index 000000000..9bf7aec46
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/golomb.h
@@ -0,0 +1,479 @@
+/*
+ * exp golomb vlc stuff
+ * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
+ * 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 golomb.h
+ * @brief
+ * exp golomb vlc stuff
+ * @author Michael Niedermayer <michaelni@gmx.at> and Alex Beregszaszi
+ */
+
+#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];
+
+
+ /**
+ * 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;
+ buf>>= log;
+ buf--;
+ LAST_SKIP_BITS(re, gb, 32 - log);
+ CLOSE_READER(re, gb);
+
+ return buf;
+ }
+}
+
+static inline int svq3_get_ue_golomb(GetBitContext *gb){
+ uint32_t 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_ue_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 ((buf << log) >> log) - 1;
+ }
+}
+
+/**
+ * read unsigned truncated exp golomb code.
+ */
+static inline int get_te0_golomb(GetBitContext *gb, int range){
+ assert(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){
+ assert(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= 2*av_log2(buf) - 31;
+ 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;
+ }
+}
+
+/**
+ * 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)<<k;
+ LAST_SKIP_BITS(re, gb, 32 + k - log);
+ CLOSE_READER(re, gb);
+
+ return buf;
+ }else{
+ buf >>= 32 - limit - esc_len;
+ LAST_SKIP_BITS(re, gb, esc_len + limit);
+ CLOSE_READER(re, gb);
+
+ return buf + limit - 1;
+ }
+}
+
+/**
+ * read unsigned golomb rice code (jpegls).
+ */
+static inline int get_ur_golomb_jpegls(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-11){
+ buf >>= log - k;
+ buf += (30-log)<<k;
+ LAST_SKIP_BITS(re, gb, 32 + k - log);
+ CLOSE_READER(re, gb);
+
+ return buf;
+ }else{
+ int i;
+ for(i=0; SHOW_UBITS(re, gb, 1) == 0; i++){
+ 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<<k);
+ }else if(i == limit - 1){
+ buf = SHOW_UBITS(re, gb, esc_len);
+ LAST_SKIP_BITS(re, gb, esc_len);
+ CLOSE_READER(re, gb);
+
+ return buf + 1;
+ }else
+ return -1;
+ }
+}
+
+/**
+ * read signed golomb rice code (ffv1).
+ */
+static inline int get_sr_golomb(GetBitContext *gb, int k, int limit, int esc_len){
+ int v= get_ur_golomb(gb, k, limit, esc_len);
+
+ v++;
+ if (v&1) return v>>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, 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, 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;
+
+ assert(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){
+ assert(range >= 1);
+ assert(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 (i>32767 || i<-32767)
+// av_log(NULL,AV_LOG_ERROR,"value out of range %d\n", 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;
+
+ assert(i>=0);
+
+ e= i>>k;
+ if(e<limit){
+ put_bits(pb, e + k + 1, (1<<k) + (i&((1<<k)-1)));
+ }else{
+ put_bits(pb, limit + esc_len, i - limit + 1);
+ }
+}
+
+/**
+ * write unsigned golomb rice code (jpegls).
+ */
+static inline void set_ur_golomb_jpegls(PutBitContext *pb, int i, int k, int limit, int esc_len){
+ int e;
+
+ assert(i>=0);
+
+ e= (i>>k) + 1;
+ if(e<limit){
+ while(e > 31) {
+ put_bits(pb, 31, 0);
+ e -= 31;
+ }
+ put_bits(pb, e, 1);
+ if(k)
+ put_bits(pb, k, i&((1<<k)-1));
+ }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);
+}
diff --git a/contrib/ffmpeg/libavcodec/h261.c b/contrib/ffmpeg/libavcodec/h261.c
new file mode 100644
index 000000000..8d4ca08cd
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/h261.c
@@ -0,0 +1,1055 @@
+/*
+ * H261 decoder
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ * 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 h261.c
+ * h261codec.
+ */
+
+#include "common.h"
+#include "dsputil.h"
+#include "avcodec.h"
+#include "mpegvideo.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
+#define IS_FIL(a) ((a)&MB_TYPE_H261_FIL)
+
+/**
+ * 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;
+
+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);
+}
+
+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;
+}
+
+static void h261_encode_block(H261Context * h, DCTELEM * block,
+ int n);
+static int h261_decode_block(H261Context *h, DCTELEM *block,
+ int n, int coded);
+
+void ff_h261_encode_picture_header(MpegEncContext * s, int picture_number){
+ H261Context * h = (H261Context *) s;
+ int format, temp_ref;
+
+ align_put_bits(&s->pb);
+
+ /* Update the pointer to last GOB */
+ s->ptr_lastgob = pbBufPtr(&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_bits(&s->pb, 5, temp_ref & 0x1f); /* 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;
+}
+
+/**
+ * Encodes 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,h261_mv_tab[code][1],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,h261_mv_tab[code][1],h261_mv_tab[code][0]);
+ put_bits(&s->pb,1,sign);
+ }
+}
+
+static inline int get_cbp(MpegEncContext * s,
+ DCTELEM 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,
+ DCTELEM 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, h261_mba_bits[(h->current_mba-h->previous_mba)-1], 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++;
+ assert(h->mtype > 1);
+ }
+
+ if(s->dquant)
+ h->mtype++;
+
+ put_bits(&s->pb, h261_mtype_bits[h->mtype], h261_mtype_code[h->mtype]);
+
+ h->mtype = 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)){
+ assert(cbp>0);
+ put_bits(&s->pb,h261_cbp_tab[cbp-1][1],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;
+ init_rl(&h261_rl_tcoeff, 1);
+ }
+
+ s->min_qcoeff= -127;
+ s->max_qcoeff= 127;
+ s->y_dc_scale_table=
+ s->c_dc_scale_table= ff_mpeg1_dc_scale_table;
+}
+
+
+/**
+ * encodes a 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, DCTELEM * block, int n){
+ MpegEncContext * const s = &h->s;
+ int level, run, last, i, j, last_index, last_non_zero, sign, slevel, code;
+ RLTable *rl;
+
+ rl = &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;
+ last = (i == last_index);
+ 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);
+ assert(slevel != 0);
+ assert(level <= 127);
+ put_bits(&s->pb, 8, slevel & 0xff);
+ } 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
+ }
+}
+
+/***********************************************/
+/* decoding */
+
+static VLC h261_mba_vlc;
+static VLC h261_mtype_vlc;
+static VLC h261_mv_vlc;
+static VLC h261_cbp_vlc;
+
+static void h261_decode_init_vlc(H261Context *h){
+ static int done = 0;
+
+ if(!done){
+ done = 1;
+ init_vlc(&h261_mba_vlc, H261_MBA_VLC_BITS, 35,
+ h261_mba_bits, 1, 1,
+ h261_mba_code, 1, 1, 1);
+ init_vlc(&h261_mtype_vlc, H261_MTYPE_VLC_BITS, 10,
+ h261_mtype_bits, 1, 1,
+ h261_mtype_code, 1, 1, 1);
+ init_vlc(&h261_mv_vlc, H261_MV_VLC_BITS, 17,
+ &h261_mv_tab[0][1], 2, 1,
+ &h261_mv_tab[0][0], 2, 1, 1);
+ init_vlc(&h261_cbp_vlc, H261_CBP_VLC_BITS, 63,
+ &h261_cbp_tab[0][1], 2, 1,
+ &h261_cbp_tab[0][0], 2, 1, 1);
+ init_rl(&h261_rl_tcoeff, 1);
+ init_vlc_rl(&h261_rl_tcoeff, 1);
+ }
+}
+
+static int h261_decode_init(AVCodecContext *avctx){
+ H261Context *h= avctx->priv_data;
+ MpegEncContext * const s = &h->s;
+
+ // set defaults
+ 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= PIX_FMT_YUV420P;
+
+ s->codec_id= avctx->codec->id;
+
+ h261_decode_init_vlc(h);
+
+ h->gob_start_code_skipped = 0;
+
+ return 0;
+}
+
+/**
+ * decodes the group of blocks header or slice header.
+ * @return <0 if an error occured
+ */
+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)
+ 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;
+}
+
+/**
+ * decodes 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, its not where its supposed to be ...
+ s->gb= s->last_resync_gb;
+ align_get_bits(&s->gb);
+ left= s->gb.size_in_bits - get_bits_count(&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;
+}
+
+/**
+ * decodes 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; i<mba2; i++){
+ int j, xy;
+
+ s->mb_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;
+
+ MPV_decode_mb(s, s->block);
+ }
+
+ return 0;
+}
+
+static int decode_mv_component(GetBitContext *gb, int v){
+ 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_count(&s->gb) + 7 >= s->gb.size_in_bits )
+ 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);
+ h->mtype = 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;
+ }
+
+ MPV_decode_mb(s, s->block);
+
+ return SLICE_OK;
+}
+
+/**
+ * decodes a macroblock
+ * @return <0 if an error occured
+ */
+static int h261_decode_block(H261Context * h, DCTELEM * block,
+ int n, int coded)
+{
+ MpegEncContext * const s = &h->s;
+ int code, level, i, j, run;
+ RLTable *rl = &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;
+}
+
+/**
+ * decodes the H261 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= s->gb.size_in_bits - get_bits_count(&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.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 I_TYPE 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 = P_TYPE;
+
+ 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;
+}
+
+#ifdef CONFIG_H261_PARSER
+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<buf_size && !vop_found; i++){
+ state= (state<<8) | buf[i];
+ for(j=0; j<8; j++){
+ if(((state>>j)&0xFFFFF) == 0x00010){
+ vop_found=1;
+ break;
+ }
+ }
+ }
+ if(vop_found){
+ for(; i<buf_size; i++){
+ state= (state<<8) | buf[i];
+ for(j=0; j<8; j++){
+ if(((state>>j)&0xFFFFF) == 0x00010){
+ pc->frame_start_found=0;
+ pc->state= state>>(2*8);
+ return i-1;
+ }
+ }
+ }
+ }
+
+ pc->frame_start_found= vop_found;
+ pc->state= state;
+ return END_NOT_FOUND;
+}
+
+static int h261_parse(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size)
+{
+ ParseContext *pc = s->priv_data;
+ int next;
+
+ next= h261_find_frame_end(pc,avctx, buf, buf_size);
+ if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) {
+ *poutbuf = NULL;
+ *poutbuf_size = 0;
+ return buf_size;
+ }
+ *poutbuf = (uint8_t *)buf;
+ *poutbuf_size = buf_size;
+ return next;
+}
+#endif
+
+/**
+ * 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 thats needed but ...)
+ if(pos+10>buf_size) pos=buf_size; // oops ;)
+
+ return pos;
+}
+
+static int h261_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ H261Context *h= avctx->priv_data;
+ MpegEncContext *s = &h->s;
+ int ret;
+ AVFrame *pict = data;
+
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_DEBUG, "*****frame %d size=%d\n", avctx->frame_number, buf_size);
+ av_log(avctx, AV_LOG_DEBUG, "bytes=%x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]);
+#endif
+ 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 (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 cant store anyting im there
+ if(s->current_picture_ptr==NULL || s->current_picture_ptr->data[0]){
+ int i= ff_find_unused_picture(s, 0);
+ 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 these demuxng hack to avformat
+ s->parse_context.buffer=0;
+ MPV_common_end(s);
+ s->parse_context= pc;
+ }
+ if (!s->context_initialized) {
+ avcodec_set_dimensions(avctx, s->width, s->height);
+
+ goto retry;
+ }
+
+ // for hurry_up==5
+ s->current_picture.pict_type= s->pict_type;
+ s->current_picture.key_frame= s->pict_type == I_TYPE;
+
+ /* skip everything if we are in a hurry>=5 */
+ if(avctx->hurry_up>=5) return get_consumed_bytes(s, buf_size);
+ if( (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type==B_TYPE)
+ ||(avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type!=I_TYPE)
+ || avctx->skip_frame >= AVDISCARD_ALL)
+ return get_consumed_bytes(s, buf_size);
+
+ if(MPV_frame_start(s, avctx) < 0)
+ return -1;
+
+ ff_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);
+ }
+ MPV_frame_end(s);
+
+assert(s->current_picture.pict_type == s->current_picture_ptr->pict_type);
+assert(s->current_picture.pict_type == s->pict_type);
+ *pict= *(AVFrame*)s->current_picture_ptr;
+ ff_print_debug_info(s, pict);
+
+ *data_size = sizeof(AVFrame);
+
+ return get_consumed_bytes(s, buf_size);
+}
+
+static int h261_decode_end(AVCodecContext *avctx)
+{
+ H261Context *h= avctx->priv_data;
+ MpegEncContext *s = &h->s;
+
+ MPV_common_end(s);
+ return 0;
+}
+
+#ifdef CONFIG_ENCODERS
+AVCodec h261_encoder = {
+ "h261",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_H261,
+ sizeof(H261Context),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+};
+#endif
+
+AVCodec h261_decoder = {
+ "h261",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_H261,
+ sizeof(H261Context),
+ h261_decode_init,
+ NULL,
+ h261_decode_end,
+ h261_decode_frame,
+ CODEC_CAP_DR1,
+};
+
+#ifdef CONFIG_H261_PARSER
+AVCodecParser h261_parser = {
+ { CODEC_ID_H261 },
+ sizeof(ParseContext),
+ NULL,
+ h261_parse,
+ ff_parse_close,
+};
+#endif
diff --git a/contrib/ffmpeg/libavcodec/h261data.h b/contrib/ffmpeg/libavcodec/h261data.h
new file mode 100644
index 000000000..2a93b73e3
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/h261data.h
@@ -0,0 +1,157 @@
+/*
+ * copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ * 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 h261data.h
+ * H.261 tables.
+ */
+#define MB_TYPE_H261_FIL 0x800000
+
+// H.261 VLC table for macroblock addressing
+static const uint8_t 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)
+};
+
+static const uint8_t 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
+static const uint8_t h261_mtype_code[10] = {
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ 1, 1
+};
+
+static const uint8_t h261_mtype_bits[10] = {
+ 4, 7, 1, 5,
+ 9, 8, 10, 3,
+ 2, 6
+};
+
+static const int 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
+static const uint8_t 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}
+};
+
+static const int mvmap[17] =
+{
+ 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16
+};
+
+//H.261 VLC table for coded block pattern
+static const uint8_t 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
+};
+
+static RLTable h261_rl_tcoeff = {
+ 64,
+ 64,
+ h261_tcoeff_vlc,
+ h261_tcoeff_run,
+ h261_tcoeff_level,
+};
diff --git a/contrib/ffmpeg/libavcodec/h263.c b/contrib/ffmpeg/libavcodec/h263.c
new file mode 100644
index 000000000..ba51c245a
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/h263.c
@@ -0,0 +1,6294 @@
+/*
+ * H263/MPEG4 backend for ffmpeg encoder and decoder
+ * Copyright (c) 2000,2001 Fabrice Bellard.
+ * H263+ support.
+ * Copyright (c) 2001 Juan J. Sierralta P.
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * ac prediction encoding, b-frame support, error resilience, optimizations,
+ * qpel decoding, gmc decoding, interlaced decoding,
+ * by Michael Niedermayer <michaelni@gmx.at>
+ */
+
+/**
+ * @file h263.c
+ * h263/mpeg4 codec.
+ */
+
+//#define DEBUG
+#include <limits.h>
+
+#include "common.h"
+#include "dsputil.h"
+#include "avcodec.h"
+#include "mpegvideo.h"
+#include "h263data.h"
+#include "mpeg4data.h"
+
+//#undef NDEBUG
+//#include <assert.h>
+
+#define INTRA_MCBPC_VLC_BITS 6
+#define INTER_MCBPC_VLC_BITS 7
+#define CBPY_VLC_BITS 6
+#define MV_VLC_BITS 9
+#define DC_VLC_BITS 9
+#define SPRITE_TRAJ_VLC_BITS 6
+#define MB_TYPE_B_VLC_BITS 4
+#define TEX_VLC_BITS 9
+#define H263_MBTYPE_B_VLC_BITS 6
+#define CBPC_B_VLC_BITS 3
+
+#ifdef CONFIG_ENCODERS
+static void h263_encode_block(MpegEncContext * s, DCTELEM * block,
+ int n);
+static void h263p_encode_umotion(MpegEncContext * s, int val);
+static inline void mpeg4_encode_block(MpegEncContext * s, DCTELEM * block,
+ int n, int dc, uint8_t *scan_table,
+ PutBitContext *dc_pb, PutBitContext *ac_pb);
+static int mpeg4_get_block_length(MpegEncContext * s, DCTELEM * block, int n, int intra_dc,
+ uint8_t *scan_table);
+#endif
+
+static int h263_decode_motion(MpegEncContext * s, int pred, int fcode);
+static int h263p_decode_umotion(MpegEncContext * s, int pred);
+static int h263_decode_block(MpegEncContext * s, DCTELEM * block,
+ int n, int coded);
+static inline int mpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr);
+static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
+ int n, int coded, int intra, int rvlc);
+#ifdef CONFIG_ENCODERS
+static int h263_pred_dc(MpegEncContext * s, int n, int16_t **dc_val_ptr);
+static void mpeg4_encode_visual_object_header(MpegEncContext * s);
+static void mpeg4_encode_vol_header(MpegEncContext * s, int vo_number, int vol_number);
+#endif //CONFIG_ENCODERS
+static void mpeg4_decode_sprite_trajectory(MpegEncContext * s, GetBitContext *gb);
+static inline int ff_mpeg4_pred_dc(MpegEncContext * s, int n, int level, int *dir_ptr, int encoding);
+
+#ifdef CONFIG_ENCODERS
+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];
+
+static uint8_t (*mv_penalty)[MAX_MV*2+1]= NULL;
+static uint8_t fcode_tab[MAX_MV*2+1];
+static uint8_t umv_fcode_tab[MAX_MV*2+1];
+
+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];
+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))
+
+/* mpeg4
+inter
+max level: 24/6
+max run: 53/63
+
+intra
+max level: 53/16
+max run: 29/41
+*/
+#endif
+
+#if 0 //3IV1 is quite rare and it slows things down a tiny bit
+#define IS_3IV1 s->codec_tag == ff_get_fourcc("3IV1")
+#else
+#define IS_3IV1 0
+#endif
+
+int h263_get_picture_format(int width, int height)
+{
+ int format;
+
+ if (width == 128 && height == 96)
+ format = 1;
+ else if (width == 176 && height == 144)
+ format = 2;
+ else if (width == 352 && height == 288)
+ format = 3;
+ else if (width == 704 && height == 576)
+ format = 4;
+ else if (width == 1408 && height == 1152)
+ format = 5;
+ else
+ format = 7;
+ return format;
+}
+
+#ifdef CONFIG_ENCODERS
+
+static void aspect_to_info(MpegEncContext * s, AVRational aspect){
+ int i;
+
+ if(aspect.num==0) aspect= (AVRational){1,1};
+
+ for(i=1; i<6; i++){
+ if(av_cmp_q(pixel_aspect[i], aspect) == 0){
+ s->aspect_ratio_info=i;
+ return;
+ }
+ }
+
+ s->aspect_ratio_info= FF_ASPECT_EXTENDED;
+}
+
+void ff_flv_encode_picture_header(MpegEncContext * s, int picture_number)
+{
+ int format;
+
+ 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 == P_TYPE); /* 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 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= clip(1, div, 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;
+
+ align_put_bits(&s->pb);
+
+ /* Update the pointer to last GOB */
+ s->ptr_lastgob = pbBufPtr(&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_bits(&s->pb, 8, temp_ref & 0xff); /* 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 = h263_get_picture_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 == P_TYPE));
+ /* 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 == 7)
+ 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 == P_TYPE);
+
+ 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 == 7) {
+ /* Custom Picture Format (CPFMT) */
+ aspect_to_info(s, 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_bits(&s->pb, 2, (temp_ref>>8)&3);
+ }
+
+ /* 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);
+
+ assert(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;
+ }
+}
+
+/**
+ * Encodes a group of blocks header.
+ */
+void 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 == I_TYPE); /* 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 == I_TYPE); /* GFID */
+ put_bits(&s->pb, 5, s->qscale); /* GQUANT */
+ }
+}
+
+static inline int get_block_rate(MpegEncContext * s, DCTELEM 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(j<block_last_index) rate+= s->intra_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;
+ level-= 64;
+
+ last= j;
+ }
+ }
+
+ return rate;
+}
+
+static inline int decide_ac_pred(MpegEncContext * s, DCTELEM block[6][64], 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]);
+ }
+
+ return score < 0;
+}
+
+static inline void restore_ac_coeffs(MpegEncContext * s, DCTELEM block[6][64], int dir[6], uint8_t *st[6], 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 ];
+ }
+ }
+ }
+}
+
+/**
+ * modify qscale so that encoding is acually 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;
+
+ for(i=1; i<s->mb_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 != CODEC_ID_H263P){
+ for(i=1; i<s->mb_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_INTER4V;
+ s->mb_type[mb_xy]|= CANDIDATE_MB_TYPE_INTER;
+ }
+ }
+ }
+}
+
+/**
+ * modify mb_type & qscale so that encoding is acually 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== B_TYPE){
+ 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; i<s->mb_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; i<s->mb_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; i<s->mb_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_DIRECT;
+ s->mb_type[mb_xy]|= CANDIDATE_MB_TYPE_BIDIR;
+ }
+ }
+ }
+}
+
+#endif //CONFIG_ENCODERS
+
+#define tab_size ((signed)(sizeof(s->direct_scale_mv[0])/sizeof(int16_t)))
+#define tab_bias (tab_size/2)
+
+void ff_mpeg4_init_direct_mv(MpegEncContext *s){
+ int i;
+ for(i=0; i<tab_size; i++){
+ s->direct_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= s->pp_time;
+ uint16_t time_pb= s->pb_time;
+ 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][s->block_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
+ }
+}
+
+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][xy ]=
+ s->current_picture.ref_index[0][xy + 1]= s->field_select[0][0];
+ s->current_picture.ref_index[0][xy + wrap ]=
+ s->current_picture.ref_index[0][xy + wrap + 1]= 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;
+ }
+}
+
+#ifdef CONFIG_ENCODERS
+
+static inline int h263_get_motion_length(MpegEncContext * s, int val, int f_code){
+ int l, bit_size, code;
+
+ if (val == 0) {
+ return mvtab[0][1];
+ } else {
+ bit_size = f_code - 1;
+ /* modulo encoding */
+ l= INT_BIT - 6 - bit_size;
+ val = (val<<l)>>l;
+ val--;
+ code = (val >> bit_size) + 1;
+
+ return 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,
+ DCTELEM block[6][64],
+ int motion_x, int motion_y){
+ int cbp, i;
+
+ if(s->flags & CODEC_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= 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= 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;
+ memset(s->block[i], 0, sizeof(DCTELEM)*64);
+ }
+ }
+ }else{
+ cbp= 0;
+ for (i = 0; i < 6; i++) {
+ if (s->block_last_index[i] >= 0)
+ cbp |= 1 << (5 - i);
+ }
+ }
+ return cbp;
+}
+
+static inline int get_b_cbp(MpegEncContext * s, DCTELEM block[6][64],
+ int motion_x, int motion_y, int mb_type){
+ int cbp=0, i;
+
+ if(s->flags & CODEC_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;
+ memset(s->block[i], 0, sizeof(DCTELEM)*64);
+ }
+ }
+ }else{
+ for (i = 0; i < 6; i++) {
+ if (s->block_last_index[i] >= 0)
+ cbp |= 1 << (5 - i);
+ }
+ }
+ return cbp;
+}
+
+static inline void mpeg4_encode_blocks(MpegEncContext * s, DCTELEM 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);
+ }
+ }
+ }
+}
+
+void mpeg4_encode_mb(MpegEncContext * s,
+ DCTELEM 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!=B_TYPE ? &s->tex_pb : &s->pb;
+ PutBitContext * const dc_pb = s->data_partitioning && s->pict_type!=I_TYPE ? &s->pb2 : &s->pb;
+ const int interleaved_stats= (s->flags&CODEC_FLAG_PASS1) && !s->data_partitioning ? 1 : 0;
+ const int dquant_code[5]= {1,0,9,2,3};
+
+ // printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
+ if (!s->mb_intra) {
+ int i, cbp;
+
+ if(s->pict_type==B_TYPE){
+ static const int mb_type_table[8]= {-1, 2, 3, 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;
+ }
+ }
+
+ assert(s->dquant>=-2 && s->dquant<=2);
+ assert((s->dquant&1)==0);
+ assert(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} */
+ assert(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){
+ assert(s->mv_dir & MV_DIRECT);
+ ff_h263_encode_motion_vector(s, motion_x, motion_y, 1);
+ s->b_count++;
+ s->f_count++;
+ }else{
+ assert(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==B_TYPE */
+ 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;
+ if(x+16 > s->width) x= s->width-16;
+ if(y+16 > s->height) y= s->height-16;
+
+ offset= x + y*s->linesize;
+ p_pic= s->new_picture.data[0] + offset;
+
+ s->mb_skipped=1;
+ for(i=0; i<s->max_b_frames; i++){
+ uint8_t *b_pic;
+ int diff;
+ Picture *pic= s->reordered_input_picture[i+1];
+
+ if(pic==NULL || pic->pict_type!=B_TYPE) break;
+
+ b_pic= pic->data[0] + offset;
+ if(pic->type != FF_BUFFER_TYPE_SHARED)
+ b_pic+= INPLACE_OFFSET;
+ 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,
+ inter_MCBPC_bits[cbpc],
+ inter_MCBPC_code[cbpc]);
+
+ put_bits(pb2, cbpy_tab[cbpy][1], 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 */
+ 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,
+ inter_MCBPC_bits[cbpc],
+ inter_MCBPC_code[cbpc]);
+
+ put_bits(pb2, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]);
+ if(s->dquant)
+ put_bits(pb2, 2, dquant_code[s->dquant+2]);
+
+ assert(!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 */
+ 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{
+ assert(s->mv_type==MV_TYPE_8X8);
+ put_bits(&s->pb,
+ inter_MCBPC_bits[cbpc+16],
+ inter_MCBPC_code[cbpc+16]);
+ put_bits(pb2, cbpy_tab[cbpy][1], 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*/
+ 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);
+ if(!s->ac_pred)
+ restore_ac_coeffs(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 == I_TYPE) {
+ if(s->dquant) cbpc+=4;
+ put_bits(&s->pb,
+ intra_MCBPC_bits[cbpc],
+ intra_MCBPC_code[cbpc]);
+ } else {
+ if(s->dquant) cbpc+=8;
+ put_bits(&s->pb, 1, 0); /* mb coded */
+ put_bits(&s->pb,
+ inter_MCBPC_bits[cbpc + 4],
+ inter_MCBPC_code[cbpc + 4]);
+ }
+ put_bits(pb2, 1, s->ac_pred);
+ cbpy = cbp >> 2;
+ put_bits(pb2, cbpy_tab[cbpy][1], 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);
+ }
+}
+
+void h263_encode_mb(MpegEncContext * s,
+ DCTELEM 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);
+ const int dquant_code[5]= {1,0,9,2,3};
+
+ //printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
+ 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,
+ inter_MCBPC_bits[cbpc],
+ inter_MCBPC_code[cbpc]);
+
+ put_bits(&s->pb, cbpy_tab[cbpy][1], 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 */
+ 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,
+ inter_MCBPC_bits[cbpc+16],
+ inter_MCBPC_code[cbpc+16]);
+ put_bits(&s->pb, cbpy_tab[cbpy][1], 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*/
+ 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 {
+ assert(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 = 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 == I_TYPE) {
+ if(s->dquant) cbpc+=4;
+ put_bits(&s->pb,
+ intra_MCBPC_bits[cbpc],
+ intra_MCBPC_code[cbpc]);
+ } else {
+ if(s->dquant) cbpc+=8;
+ put_bits(&s->pb, 1, 0); /* mb coded */
+ put_bits(&s->pb,
+ inter_MCBPC_bits[cbpc + 4],
+ 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, cbpy_tab[cbpy][1], 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++;
+ }
+ }
+}
+#endif
+
+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==B_TYPE && !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_t, qp_tc;
+
+ if(IS_SKIP(s->current_picture.mb_type[xy-s->mb_stride]))
+ qp_t=0;
+ else
+ qp_t= s->current_picture.qscale_table[xy-s->mb_stride];
+
+ if(qp_c)
+ qp_tc= qp_c;
+ else
+ qp_tc= qp_t;
+
+ 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_t)
+ s->dsp.h263_h_loop_filter(dest_y-8*linesize+8 , linesize, qp_t);
+
+ if(s->mb_x){
+ if(qp_t || IS_SKIP(s->current_picture.mb_type[xy-1-s->mb_stride]))
+ qp_dt= qp_t;
+ 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);
+ }
+ }
+ }
+}
+
+#ifdef CONFIG_ENCODERS
+static int h263_pred_dc(MpegEncContext * s, int n, int16_t **dc_val_ptr)
+{
+ int x, y, wrap, a, c, pred_dc, scale;
+ 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];
+ 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];
+ scale = s->c_dc_scale;
+ }
+ /* 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;
+ }
+ pred_dc = 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 */
+ //pred_dc = (pred_dc + (scale >> 1)) / scale;
+ *dc_val_ptr = &dc_val[x + y * wrap];
+ return pred_dc;
+}
+#endif /* CONFIG_ENCODERS */
+
+static void h263_pred_acdc(MpegEncContext * s, DCTELEM *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 *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;
+}
+
+#ifdef CONFIG_ENCODERS
+void ff_h263_encode_motion(MpegEncContext * s, int val, int f_code)
+{
+ int range, l, bit_size, sign, code, bits;
+
+ if (val == 0) {
+ /* zero vector */
+ code = 0;
+ put_bits(&s->pb, mvtab[code][1], mvtab[code][0]);
+ } else {
+ bit_size = f_code - 1;
+ range = 1 << bit_size;
+ /* modulo encoding */
+ l= INT_BIT - 6 - bit_size;
+ val = (val<<l)>>l;
+ sign = val>>31;
+ val= (val^sign)-sign;
+ sign&=1;
+
+ val--;
+ code = (val >> bit_size) + 1;
+ bits = val & (range - 1);
+
+ put_bits(&s->pb, mvtab[code][1] + 1, (mvtab[code][0] << 1) | sign);
+ if (bit_size > 0) {
+ put_bits(&s->pb, bit_size, bits);
+ }
+ }
+}
+
+/* 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);
+ //printf("\nVal = %d\tCode = %d", sval, code);
+ }
+}
+
+static void init_mv_penalty_and_fcode(MpegEncContext *s)
+{
+ int f_code;
+ int mv;
+
+ if(mv_penalty==NULL)
+ mv_penalty= av_mallocz( sizeof(uint8_t)*(MAX_FCODE+1)*(2*MAX_MV+1) );
+
+ for(f_code=1; f_code<=MAX_FCODE; f_code++){
+ for(mv=-MAX_MV; mv<=MAX_MV; mv++){
+ int len;
+
+ if(mv==0) len= mvtab[0][1];
+ else{
+ int val, bit_size, range, code;
+
+ bit_size = f_code - 1;
+ range = 1 << bit_size;
+
+ val=mv;
+ if (val < 0)
+ val = -val;
+ val--;
+ code = (val >> bit_size) + 1;
+ if(code<33){
+ len= mvtab[code][1] + 1 + bit_size;
+ }else{
+ len= 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<<f_code); mv<(16<<f_code); mv++){
+ fcode_tab[mv+MAX_MV]= f_code;
+ }
+ }
+
+ for(mv=0; mv<MAX_MV*2+1; mv++){
+ umv_fcode_tab[mv]= 1;
+ }
+}
+#endif
+
+#ifdef CONFIG_ENCODERS
+
+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= DCtab_lum[size][0];
+ uni_len = 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= DCtab_chrom[size][0];
+ uni_len = 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;
+
+ }
+}
+
+#endif //CONFIG_ENCODERS
+
+#ifdef CONFIG_ENCODERS
+static void init_uni_mpeg4_rl_tab(RLTable *rl, uint32_t *bits_tab, uint8_t *len_tab){
+ int slevel, run, last;
+
+ assert(MAX_LEVEL >= 64);
+ assert(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;
+ }
+#if 1
+ /* 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;
+ }
+ }
+#endif
+#if 1
+ /* 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;
+ }
+ }
+#endif
+ /* 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 void init_uni_h263_rl_tab(RLTable *rl, uint32_t *bits_tab, uint8_t *len_tab){
+ int slevel, run, last;
+
+ assert(MAX_LEVEL >= 64);
+ assert(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 h263_encode_init(MpegEncContext *s)
+{
+ static int done = 0;
+
+ if (!done) {
+ done = 1;
+
+ init_uni_dc_tab();
+
+ init_rl(&rl_inter, 1);
+ init_rl(&rl_intra, 1);
+ init_rl(&rl_intra_aic, 1);
+
+ init_uni_mpeg4_rl_tab(&rl_intra, uni_mpeg4_intra_rl_bits, uni_mpeg4_intra_rl_len);
+ init_uni_mpeg4_rl_tab(&rl_inter, uni_mpeg4_inter_rl_bits, uni_mpeg4_inter_rl_len);
+
+ init_uni_h263_rl_tab(&rl_intra_aic, NULL, uni_h263_intra_aic_rl_len);
+ init_uni_h263_rl_tab(&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 CODEC_ID_MPEG4:
+ s->fcode_tab= fcode_tab;
+ 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->chroma_dc_vlc_length= uni_DCtab_chrom_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;
+ }
+
+ break;
+ case 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 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;
+ }
+}
+
+/**
+ * encodes a 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, DCTELEM * block, int n)
+{
+ int level, run, last, i, j, last_index, last_non_zero, sign, slevel, code;
+ RLTable *rl;
+
+ rl = &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 = &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(&rl_intra_aic, last, run, level);
+ inter_vlc_bits += rl->table_vlc[code][1]+1;
+ aic_vlc_bits += rl_intra_aic.table_vlc[aic_code][1]+1;
+
+ if (code == rl->n) {
+ inter_vlc_bits += 1+6+8-1;
+ }
+ if (aic_code == 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 = &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(s->h263_flv <= 1){
+ put_bits(&s->pb, 1, last);
+ put_bits(&s->pb, 6, run);
+
+ assert(slevel != 0);
+
+ if(level < 128)
+ put_bits(&s->pb, 8, slevel & 0xff);
+ else{
+ put_bits(&s->pb, 8, 128);
+ put_bits(&s->pb, 5, slevel & 0x1f);
+ put_bits(&s->pb, 6, (slevel>>5)&0x3f);
+ }
+ }else{
+ if(level < 64) { // 7-bit level
+ put_bits(&s->pb, 1, 0);
+ put_bits(&s->pb, 1, last);
+ put_bits(&s->pb, 6, run);
+
+ put_bits(&s->pb, 7, slevel & 0x7f);
+ } else {
+ /* 11-bit level */
+ put_bits(&s->pb, 1, 1);
+ put_bits(&s->pb, 1, last);
+ put_bits(&s->pb, 6, run);
+
+ put_bits(&s->pb, 11, slevel & 0x7ff);
+ }
+ }
+ } else {
+ put_bits(&s->pb, 1, sign);
+ }
+ last_non_zero = i;
+ }
+ }
+}
+#endif
+
+#ifdef CONFIG_ENCODERS
+
+/***************************************************/
+/**
+ * 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<<length)-1);
+}
+
+/* must be called before writing the header */
+void ff_set_mpeg4_time(MpegEncContext * s, int picture_number){
+ int time_div, time_mod;
+
+ assert(s->current_picture_ptr->pts != AV_NOPTS_VALUE);
+ s->time= s->current_picture_ptr->pts*s->avctx->time_base.num;
+
+ time_div= s->time/s->avctx->time_base.den;
+ time_mod= s->time%s->avctx->time_base.den;
+
+ if(s->pict_type==B_TYPE){
+ s->pb_time= s->pp_time - (s->last_non_b_time - s->time);
+ assert(s->pb_time > 0 && s->pb_time < s->pp_time);
+ ff_mpeg4_init_direct_mv(s);
+ }else{
+ s->last_time_base= s->time_base;
+ s->time_base= time_div;
+ s->pp_time= s->time - s->last_non_b_time;
+ s->last_non_b_time= s->time;
+ assert(picture_number==0 || s->pp_time > 0);
+ }
+}
+
+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->pts;
+ if(s->reordered_input_picture[1])
+ time= FFMIN(time, s->reordered_input_picture[1]->pts);
+ time= time*s->avctx->time_base.num;
+
+ seconds= time/s->avctx->time_base.den;
+ minutes= seconds/60; seconds %= 60;
+ hours= minutes/60; minutes %= 60;
+ 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
+
+ s->last_time_base= time / s->avctx->time_base.den;
+
+ 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(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 */
+ }
+
+ aspect_to_info(s, 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){
+ 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 */
+ ff_put_string(&s->pb, LIBAVCODEC_IDENT, 0);
+ }
+}
+
+/* write mpeg4 VOP header */
+void mpeg4_encode_picture_header(MpegEncContext * s, int picture_number)
+{
+ int time_incr;
+ int time_div, time_mod;
+
+ if(s->pict_type==I_TYPE){
+ 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!=B_TYPE;
+
+//printf("num:%d rate:%d base:%d\n", s->picture_number, s->time_base.den, FRAME_RATE_BASE);
+
+ 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 */
+
+ assert(s->time>=0);
+ time_div= s->time/s->avctx->time_base.den;
+ time_mod= s->time%s->avctx->time_base.den;
+ time_incr= time_div - s->last_time_base;
+ assert(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 == P_TYPE
+ || (s->pict_type == S_TYPE && 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->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 != I_TYPE)
+ put_bits(&s->pb, 3, s->f_code); /* fcode_for */
+ if (s->pict_type == B_TYPE)
+ put_bits(&s->pb, 3, s->b_code); /* fcode_back */
+ // printf("****frame %d\n", picture_number);
+}
+
+#endif //CONFIG_ENCODERS
+
+/**
+ * set qscale and update qscale dependant 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 ];
+}
+
+/**
+ * predicts 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->error_resilience>=3){
+ 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;
+}
+
+/**
+ * predicts the ac.
+ * @param n block index (0-3 are luma, 4-5 are chroma)
+ * @param dir the ac prediction direction
+ */
+void mpeg4_pred_ac(MpegEncContext * s, DCTELEM *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 ]];
+
+}
+
+#ifdef CONFIG_ENCODERS
+
+/**
+ * encodes 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
+// if(level<-255 || level>255) printf("dc overflow\n");
+ 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, DCtab_lum[size][1], DCtab_lum[size][0]);
+ } else {
+ /* chrominance */
+ put_bits(&s->pb, DCtab_chrom[size][1], 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];
+ }
+}
+
+/**
+ * encodes a 8x8 block
+ * @param n block index (0-3 are luma, 4-5 are chroma)
+ */
+static inline void mpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n, int intra_dc,
+ uint8_t *scan_table, PutBitContext *dc_pb, PutBitContext *ac_pb)
+{
+ int i, last_non_zero;
+#if 0 //variables for the outcommented version
+ int code, sign, last;
+#endif
+ const RLTable *rl;
+ 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;
+ rl = &rl_intra;
+ bits_tab= uni_mpeg4_intra_rl_bits;
+ len_tab = uni_mpeg4_intra_rl_len;
+ } else {
+ if(last_index<0) return;
+ i = 0;
+ rl = &rl_inter;
+ bits_tab= uni_mpeg4_inter_rl_bits;
+ len_tab = uni_mpeg4_inter_rl_len;
+ }
+
+ /* AC coefs */
+ last_non_zero = i - 1;
+#if 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);
+ }
+ }
+#else
+ for (; i <= last_index; i++) {
+ const int slevel = block[ scan_table[i] ];
+ if (slevel) {
+ int level;
+ int run = i - last_non_zero - 1;
+ last = (i == last_index);
+ sign = 0;
+ level = slevel;
+ if (level < 0) {
+ sign = 1;
+ level = -level;
+ }
+ code = get_rl_index(rl, last, run, level);
+ put_bits(ac_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(ac_pb, 1, 1);
+ if (level > MAX_LEVEL)
+ goto esc3;
+ run1 = run - rl->max_run[last][level] - 1;
+ if (run1 < 0)
+ goto esc3;
+ code = get_rl_index(rl, last, run1, level);
+ if (code == rl->n) {
+ esc3:
+ /* third escape */
+ put_bits(ac_pb, 1, 1);
+ put_bits(ac_pb, 1, last);
+ put_bits(ac_pb, 6, run);
+ put_bits(ac_pb, 1, 1);
+ put_bits(ac_pb, 12, slevel & 0xfff);
+ put_bits(ac_pb, 1, 1);
+ } else {
+ /* second escape */
+ put_bits(ac_pb, 1, 0);
+ put_bits(ac_pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);
+ put_bits(ac_pb, 1, sign);
+ }
+ } else {
+ /* first escape */
+ put_bits(ac_pb, 1, 0);
+ put_bits(ac_pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);
+ put_bits(ac_pb, 1, sign);
+ }
+ } else {
+ put_bits(ac_pb, 1, sign);
+ }
+ last_non_zero = i;
+ }
+ }
+#endif
+}
+
+static int mpeg4_get_block_length(MpegEncContext * s, DCTELEM * block, int n, int intra_dc,
+ uint8_t *scan_table)
+{
+ int i, last_non_zero;
+ const RLTable *rl;
+ 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;
+ rl = &rl_intra;
+ len_tab = uni_mpeg4_intra_rl_len;
+ } else {
+ if(last_index<0) return 0;
+ i = 0;
+ rl = &rl_inter;
+ 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;
+}
+
+#endif
+
+
+/***********************************************/
+/* decoding */
+
+static VLC intra_MCBPC_vlc;
+static VLC inter_MCBPC_vlc;
+static VLC cbpy_vlc;
+static VLC mv_vlc;
+static VLC dc_lum, dc_chrom;
+static VLC sprite_trajectory;
+static VLC mb_type_b_vlc;
+static VLC h263_mbtype_b_vlc;
+static VLC cbpc_b_vlc;
+
+void init_vlc_rl(RLTable *rl, int use_static)
+{
+ int i, q;
+
+ /* Return if static table is already initialized */
+ if(use_static && rl->rl_vlc[0])
+ return;
+
+ init_vlc(&rl->vlc, 9, rl->n + 1,
+ &rl->table_vlc[0][1], 4, 2,
+ &rl->table_vlc[0][0], 4, 2, use_static);
+
+
+ for(q=0; q<32; q++){
+ int qmul= q*2;
+ int qadd= (q-1)|1;
+
+ if(q==0){
+ qmul=1;
+ qadd=0;
+ }
+ if(use_static)
+ rl->rl_vlc[q]= av_mallocz_static(rl->vlc.table_size*sizeof(RL_VLC_ELEM));
+ else
+ rl->rl_vlc[q]= av_malloc(rl->vlc.table_size*sizeof(RL_VLC_ELEM));
+ 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;
+ }
+ }
+}
+
+/* init vlcs */
+
+/* XXX: find a better solution to handle static init */
+void h263_decode_init_vlc(MpegEncContext *s)
+{
+ static int done = 0;
+
+ if (!done) {
+ done = 1;
+
+ init_vlc(&intra_MCBPC_vlc, INTRA_MCBPC_VLC_BITS, 9,
+ intra_MCBPC_bits, 1, 1,
+ intra_MCBPC_code, 1, 1, 1);
+ init_vlc(&inter_MCBPC_vlc, INTER_MCBPC_VLC_BITS, 28,
+ inter_MCBPC_bits, 1, 1,
+ inter_MCBPC_code, 1, 1, 1);
+ init_vlc(&cbpy_vlc, CBPY_VLC_BITS, 16,
+ &cbpy_tab[0][1], 2, 1,
+ &cbpy_tab[0][0], 2, 1, 1);
+ init_vlc(&mv_vlc, MV_VLC_BITS, 33,
+ &mvtab[0][1], 2, 1,
+ &mvtab[0][0], 2, 1, 1);
+ init_rl(&rl_inter, 1);
+ init_rl(&rl_intra, 1);
+ init_rl(&rvlc_rl_inter, 1);
+ init_rl(&rvlc_rl_intra, 1);
+ init_rl(&rl_intra_aic, 1);
+ init_vlc_rl(&rl_inter, 1);
+ init_vlc_rl(&rl_intra, 1);
+ init_vlc_rl(&rvlc_rl_inter, 1);
+ init_vlc_rl(&rvlc_rl_intra, 1);
+ init_vlc_rl(&rl_intra_aic, 1);
+ init_vlc(&dc_lum, DC_VLC_BITS, 10 /* 13 */,
+ &DCtab_lum[0][1], 2, 1,
+ &DCtab_lum[0][0], 2, 1, 1);
+ init_vlc(&dc_chrom, DC_VLC_BITS, 10 /* 13 */,
+ &DCtab_chrom[0][1], 2, 1,
+ &DCtab_chrom[0][0], 2, 1, 1);
+ init_vlc(&sprite_trajectory, SPRITE_TRAJ_VLC_BITS, 15,
+ &sprite_trajectory_tab[0][1], 4, 2,
+ &sprite_trajectory_tab[0][0], 4, 2, 1);
+ init_vlc(&mb_type_b_vlc, MB_TYPE_B_VLC_BITS, 4,
+ &mb_type_b_tab[0][1], 2, 1,
+ &mb_type_b_tab[0][0], 2, 1, 1);
+ init_vlc(&h263_mbtype_b_vlc, H263_MBTYPE_B_VLC_BITS, 15,
+ &h263_mbtype_b_tab[0][1], 2, 1,
+ &h263_mbtype_b_tab[0][0], 2, 1, 1);
+ init_vlc(&cbpc_b_vlc, CBPC_B_VLC_BITS, 4,
+ &cbpc_b_tab[0][1], 2, 1,
+ &cbpc_b_tab[0][0], 2, 1, 1);
+ }
+}
+
+/**
+ * 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;
+}
+
+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;
+}
+
+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);
+}
+
+/**
+ * decodes the group of blocks header or slice header.
+ * @return <0 if an error occured
+ */
+static int h263_decode_gob_header(MpegEncContext *s)
+{
+ unsigned int val, gfid, 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= s->gb.size_in_bits - get_bits_count(&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;
+ gfid = get_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;
+ gfid = get_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;
+}
+
+static inline void memsetw(short *tab, int val, int n)
+{
+ int i;
+ for(i=0;i<n;i++)
+ tab[i] = val;
+}
+
+#ifdef CONFIG_ENCODERS
+
+void ff_mpeg4_init_partitions(MpegEncContext *s)
+{
+ uint8_t *start= pbBufPtr(&s->pb);
+ uint8_t *end= s->pb.buf_end;
+ int size= end - start;
+ int pb_size = (((long)start + size/3)&(~3)) - (long)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==I_TYPE){
+ 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);
+ ff_copy_bits(&s->pb, s->pb2.buf , pb2_len);
+ ff_copy_bits(&s->pb, s->tex_pb.buf, tex_pb_len);
+ s->last_bits= put_bits_count(&s->pb);
+}
+
+#endif //CONFIG_ENCODERS
+
+int ff_mpeg4_get_video_packet_prefix_length(MpegEncContext *s){
+ switch(s->pict_type){
+ case I_TYPE:
+ return 16;
+ case P_TYPE:
+ case S_TYPE:
+ return s->f_code+15;
+ case B_TYPE:
+ return FFMAX(FFMAX(s->f_code, s->b_code)+15, 17);
+ default:
+ return -1;
+ }
+}
+
+#ifdef CONFIG_ENCODERS
+
+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 */
+}
+
+#endif //CONFIG_ENCODERS
+
+/**
+ * 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){
+ return 0;
+ }
+
+ while(v<=0xFF){
+ if(s->pict_type==B_TYPE || (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 1;
+ }else{
+ if(v == ff_mpeg4_resync_prefix[bits_count&7]){
+ int len;
+ 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;
+ }
+
+ s->gb= gb;
+
+ if(len>=ff_mpeg4_get_video_packet_prefix_length(s))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**
+ * decodes the next video packet.
+ * @return <0 if something went wrong
+ */
+static int 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;
+ }
+ if(s->pict_type == B_TYPE){
+ while(s->next_picture.mbskip_table[ s->mb_index2xy[ mb_num ] ]) mb_num++;
+ if(mb_num >= s->mb_num) return -1; // slice contains just skipped MBs which where allready decoded
+ }
+
+ 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_increment;
+ int time_incr=0;
+
+ while (get_bits1(&s->gb) != 0)
+ time_incr++;
+
+ check_marker(&s->gb, "before time_increment in video packed header");
+ time_increment= get_bits(&s->gb, s->time_increment_bits);
+ 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 == S_TYPE && s->vol_sprite_usage==GMC_SPRITE){
+ mpeg4_decode_sprite_trajectory(s, &s->gb);
+ av_log(s->avctx, AV_LOG_ERROR, "untested\n");
+ }
+
+ //FIXME reduced res stuff here
+
+ if (s->pict_type != I_TYPE) {
+ 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 == B_TYPE) {
+ 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
+
+//printf("parse ok %d %d %d %d\n", mb_num, s->mb_x + s->mb_y*s->mb_width, get_bits_count(gb), get_bits_count(&s->gb));
+
+ return 0;
+}
+
+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;
+}
+
+/**
+ * decodes the group of blocks / video packet header.
+ * @return <0 if no resync found
+ */
+int ff_h263_resync(MpegEncContext *s){
+ int left, ret;
+
+ if(s->codec_id==CODEC_ID_MPEG4){
+ skip_bits1(&s->gb);
+ align_get_bits(&s->gb);
+ }
+
+ if(show_bits(&s->gb, 16)==0){
+ if(s->codec_id==CODEC_ID_MPEG4)
+ ret= mpeg4_decode_video_packet_header(s);
+ else
+ ret= h263_decode_gob_header(s);
+ if(ret>=0)
+ return 0;
+ }
+ //ok, it's not where its supposed to be ...
+ s->gb= s->last_resync_gb;
+ align_get_bits(&s->gb);
+ left= s->gb.size_in_bits - get_bits_count(&s->gb);
+
+ for(;left>16+1+5+5; left-=8){
+ if(show_bits(&s->gb, 16)==0){
+ GetBitContext bak= s->gb;
+
+ if(s->codec_id==CODEC_ID_MPEG4)
+ ret= mpeg4_decode_video_packet_header(s);
+ else
+ ret= h263_decode_gob_header(s);
+ if(ret>=0)
+ return 0;
+
+ s->gb= bak;
+ }
+ skip_bits(&s->gb, 8);
+ }
+
+ return -1;
+}
+
+/**
+ * gets the average motion vector for a GMC MB.
+ * @param n either 0 for the x component or 1 for y
+ * @returns 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]<<s->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;
+}
+
+/**
+ * decodes first partition.
+ * @return number of MBs decoded or <0 if an error occured
+ */
+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_y<s->mb_height; s->mb_y++){
+ ff_init_block_index(s);
+ for(; s->mb_x<s->mb_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==I_TYPE){
+ int i;
+
+ do{
+ if(show_bits_long(&s->gb, 19)==DC_MARKER){
+ return mb_num-1;
+ }
+
+ cbpc = get_vlc2(&s->gb, 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==S_TYPE && 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, 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==S_TYPE && 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 */
+
+ h263_pred_motion(s, 0, 0, &pred_x, &pred_y);
+ if(!s->mcsel){
+ mx = h263_decode_motion(s, pred_x, s->f_code);
+ if (mx >= 0xffff)
+ return -1;
+
+ my = 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= h263_pred_motion(s, i, 0, &pred_x, &pred_y);
+ mx = h263_decode_motion(s, pred_x, s->f_code);
+ if (mx >= 0xffff)
+ return -1;
+
+ my = 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 occured
+ */
+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_x<s->mb_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==I_TYPE){
+ int ac_pred= get_bits1(&s->gb);
+ int cbpy = get_vlc2(&s->gb, 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, 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, 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;
+}
+
+/**
+ * decodes the first & 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==I_TYPE ? (DC_ERROR|MV_ERROR) : MV_ERROR;
+ const int part_a_end = s->pict_type==I_TYPE ? (DC_END |MV_END) : MV_END;
+
+ mb_num= mpeg4_decode_partition_a(s);
+ if(mb_num<0){
+ ff_er_add_slice(s, 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, 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==I_TYPE){
+ 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, 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==P_TYPE)
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, DC_ERROR);
+ return -1;
+ }else{
+ if(s->pict_type==P_TYPE)
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, DC_END);
+ }
+
+ return 0;
+}
+
+/**
+ * decode partition C of one MB.
+ * @return <0 if an error occured
+ */
+static int mpeg4_decode_partitioned_mb(MpegEncContext *s, DCTELEM 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 == P_TYPE || s->pict_type==S_TYPE) {
+ 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==S_TYPE && 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){
+//printf("%06X %d\n", show_bits(&s->gb, 24), s->gb.size_in_bits - get_bits_count(&s->gb));
+ 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;
+ }
+}
+
+/**
+ * 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++;
+
+ assert(s->pict_type == P_TYPE);
+
+ 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, 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, 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= h263_pred_motion(s, 0, 0, &pred_x, &pred_y);
+ if (s->umvplus)
+ mx = h263p_decode_umotion(s, pred_x);
+ else
+ mx = h263_decode_motion(s, pred_x, 1);
+
+ if (s->umvplus)
+ my = h263p_decode_umotion(s, pred_y);
+ else
+ my = 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 = h263_pred_motion(s, i, 0, &pred_x, &pred_y);
+ if (s->umvplus)
+ mx = h263p_decode_umotion(s, pred_x);
+ else
+ mx = h263_decode_motion(s, pred_x, 1);
+
+ if (s->umvplus)
+ my = h263p_decode_umotion(s, pred_y);
+ else
+ my = 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= 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);
+}
+
+int ff_h263_decode_mb(MpegEncContext *s,
+ DCTELEM 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;
+
+ assert(!s->h263_pred);
+
+ if (s->pict_type == P_TYPE) {
+ 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, inter_MCBPC_vlc.table, INTER_MCBPC_VLC_BITS, 2);
+ //fprintf(stderr, "\tCBPC: %d", cbpc);
+ 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;
+
+ cbpy = get_vlc2(&s->gb, 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;
+ h263_pred_motion(s, 0, 0, &pred_x, &pred_y);
+ if (s->umvplus)
+ mx = h263p_decode_umotion(s, pred_x);
+ else
+ mx = h263_decode_motion(s, pred_x, 1);
+
+ if (mx >= 0xffff)
+ return -1;
+
+ if (s->umvplus)
+ my = h263p_decode_umotion(s, pred_y);
+ else
+ my = 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 = h263_pred_motion(s, i, 0, &pred_x, &pred_y);
+ if (s->umvplus)
+ mx = h263p_decode_umotion(s, pred_x);
+ else
+ mx = h263_decode_motion(s, pred_x, 1);
+ if (mx >= 0xffff)
+ return -1;
+
+ if (s->umvplus)
+ my = h263p_decode_umotion(s, pred_y);
+ else
+ my = 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;
+ }
+ }
+
+ /* 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->obmc){
+ if(s->pict_type == P_TYPE && s->mb_x+1<s->mb_width && s->mb_num_left != 1)
+ preview_obmc(s);
+ }
+ } else if(s->pict_type==B_TYPE) {
+ 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, 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;
+
+ assert(!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= h263_pred_motion(s, 0, 0, &mx, &my);
+ s->mv_dir = MV_DIR_FORWARD;
+
+ mx = h263_decode_motion(s, mx, 1);
+ my = 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= h263_pred_motion(s, 0, 1, &mx, &my);
+ s->mv_dir |= MV_DIR_BACKWARD;
+
+ mx = h263_decode_motion(s, mx, 1);
+ my = 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;
+
+ /* decode each block */
+ for (i = 0; i < 6; i++) {
+ if (h263_decode_block(s, block[i], i, cbp&32) < 0)
+ return -1;
+ cbp+=cbp;
+ }
+ } else { /* I-Frame */
+ do{
+ cbpc = get_vlc2(&s->gb, 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;
+
+ cbpy = get_vlc2(&s->gb, 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);
+ }
+
+ /* decode each block */
+ for (i = 0; i < 6; i++) {
+ if (h263_decode_block(s, block[i], i, cbp&32) < 0)
+ return -1;
+ cbp+=cbp;
+ }
+ }
+end:
+
+ /* per-MB end of slice check */
+ {
+ int v= show_bits(&s->gb, 16);
+
+ if(get_bits_count(&s->gb) + 16 > s->gb.size_in_bits){
+ v>>= get_bits_count(&s->gb) + 16 - s->gb.size_in_bits;
+ }
+
+ if(v==0)
+ return SLICE_END;
+ }
+
+ return SLICE_OK;
+}
+
+int ff_mpeg4_decode_mb(MpegEncContext *s,
+ DCTELEM 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;
+
+ assert(s->h263_pred);
+
+ if (s->pict_type == P_TYPE || s->pict_type==S_TYPE) {
+ 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==S_TYPE && 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, inter_MCBPC_vlc.table, INTER_MCBPC_VLC_BITS, 2);
+ //fprintf(stderr, "\tCBPC: %d", cbpc);
+ 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==S_TYPE && s->vol_sprite_usage==GMC_SPRITE && (cbpc & 16) == 0)
+ s->mcsel= get_bits1(&s->gb);
+ else s->mcsel= 0;
+ cbpy = get_vlc2(&s->gb, 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);
+
+ h263_pred_motion(s, 0, 0, &pred_x, &pred_y);
+
+ for(i=0; i<2; i++){
+ mx = h263_decode_motion(s, pred_x, s->f_code);
+ if (mx >= 0xffff)
+ return -1;
+
+ my = 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;
+ h263_pred_motion(s, 0, 0, &pred_x, &pred_y);
+ mx = h263_decode_motion(s, pred_x, s->f_code);
+
+ if (mx >= 0xffff)
+ return -1;
+
+ my = 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 = h263_pred_motion(s, i, 0, &pred_x, &pred_y);
+ mx = h263_decode_motion(s, pred_x, s->f_code);
+ if (mx >= 0xffff)
+ return -1;
+
+ my = 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==B_TYPE) {
+ 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;
+ }
+ }
+
+ /* 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 = h263_decode_motion(s, s->last_mv[0][0][0], s->f_code);
+ my = 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 = h263_decode_motion(s, s->last_mv[1][0][0], s->b_code);
+ my = 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 = h263_decode_motion(s, s->last_mv[0][i][0] , s->f_code);
+ my = 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 = h263_decode_motion(s, s->last_mv[1][i][0] , s->b_code);
+ my = 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 = h263_decode_motion(s, 0, 1);
+ my = 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, 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, 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==CODEC_ID_MPEG4){
+ if(mpeg4_is_resync(s)){
+ const int delta= s->mb_x + 1 == s->mb_width ? 2 : 1;
+ if(s->pict_type==B_TYPE && s->next_picture.mbskip_table[xy + delta])
+ return SLICE_OK;
+ return SLICE_END;
+ }
+ }
+
+ return SLICE_OK;
+}
+
+static int h263_decode_motion(MpegEncContext * s, int pred, int f_code)
+{
+ int code, val, sign, shift, l;
+ 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) {
+ l = INT_BIT - 5 - f_code;
+ val = (val<<l)>>l;
+ } else {
+ /* horrible h263 long vector mode */
+ if (pred < -31 && val < -63)
+ val += 64;
+ if (pred > 32 && val > 63)
+ val -= 64;
+
+ }
+ return val;
+}
+
+/* Decodes 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);
+#ifdef DEBUG
+ av_log( s->avctx, AV_LOG_DEBUG,"H.263+ UMV Motion = %d\n", code);
+#endif
+ return code;
+
+}
+
+static int h263_decode_block(MpegEncContext * s, DCTELEM * block,
+ int n, int coded)
+{
+ int code, level, i, j, last, run;
+ RLTable *rl = &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 = &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 == CODEC_ID_RV10){
+#ifdef CONFIG_RV10_DECODER
+ if (s->rv10_version == 3 && s->pict_type == I_TYPE) {
+ int component, diff;
+ component = (n <= 3 ? 0 : n - 4 + 1);
+ level = s->last_dc[component];
+ if (s->rv10_first_dc_coded[component]) {
+ diff = 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->error_resilience >= FF_ER_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 (s->h263_flv > 1) {
+ int is11 = get_bits1(&s->gb);
+ last = get_bits1(&s->gb);
+ run = get_bits(&s->gb, 6);
+ if(is11){
+ level = get_sbits(&s->gb, 11);
+ } else {
+ level = get_sbits(&s->gb, 7);
+ }
+ } 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 == 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 == &rl_inter && !s->mb_intra){
+ //looks like a hack but no, it's the way its supposed to work ...
+ rl = &rl_intra_aic;
+ i = 0;
+ s->gb= gb;
+ memset(block, 0, sizeof(DCTELEM)*64);
+ 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) {
+ h263_pred_acdc(s, block, n);
+ i = 63;
+ }
+ s->block_last_index[n] = i;
+ return 0;
+}
+
+/**
+ * decodes 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->error_resilience>=2){
+ 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);
+}
+
+/**
+ * decodes a block.
+ * @return <0 if an error occured
+ */
+static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
+ int n, int coded, int intra, int rvlc)
+{
+ int level, i, last, run;
+ int 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]<<n)&32;
+ }else{
+ level = mpeg4_decode_dc(s, n, &dc_pred_dir);
+ if (level < 0)
+ return -1;
+ }
+ block[0] = level;
+ i = 0;
+ }else{
+ i = -1;
+ ff_mpeg4_pred_dc(s, n, 0, &dc_pred_dir, 0);
+ }
+ if (!coded)
+ goto not_coded;
+
+ if(rvlc){
+ rl = &rvlc_rl_intra;
+ rl_vlc = rvlc_rl_intra.rl_vlc[0];
+ }else{
+ rl = &rl_intra;
+ rl_vlc = rl_intra.rl_vlc[0];
+ }
+ 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;
+ }
+ qmul=1;
+ qadd=0;
+ } else {
+ i = -1;
+ if (!coded) {
+ s->block_last_index[n] = i;
+ return 0;
+ }
+ if(rvlc) rl = &rvlc_rl_inter;
+ else rl = &rl_inter;
+
+ scan_table = s->intra_scantable.permutated;
+
+ if(s->mpeg_quant){
+ qmul=1;
+ qadd=0;
+ if(rvlc){
+ rl_vlc = rvlc_rl_inter.rl_vlc[0];
+ }else{
+ rl_vlc = rl_inter.rl_vlc[0];
+ }
+ }else{
+ qmul = s->qscale << 1;
+ qadd = (s->qscale - 1) | 1;
+ if(rvlc){
+ rl_vlc = rvlc_rl_inter.rl_vlc[s->qscale];
+ }else{
+ rl_vlc = 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); LAST_SKIP_CACHE(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); LAST_SKIP_CACHE(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); LAST_SKIP_CACHE(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;
+ }; LAST_SKIP_CACHE(re, &s->gb, 1);
+
+ SKIP_COUNTER(re, &s->gb, 1+12+1);
+ }
+
+#if 0
+ if(s->error_resilience >= 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_resilience > 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->error_resilience > FF_ER_COMPLIANT){
+ 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 */
+#if MIN_CACHE_BITS < 20
+ LAST_SKIP_BITS(re, &s->gb, 2);
+ UPDATE_CACHE(re, &s->gb);
+#else
+ SKIP_BITS(re, &s->gb, 2);
+#endif
+ 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 */
+#if MIN_CACHE_BITS < 19
+ LAST_SKIP_BITS(re, &s->gb, 1);
+ UPDATE_CACHE(re, &s->gb);
+#else
+ SKIP_BITS(re, &s->gb, 1);
+#endif
+ 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;
+ }
+
+ 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;
+}
+
+/* most is hardcoded. should extend to handle all h263 streams */
+int 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= s->gb.size_in_bits - get_bits_count(&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->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 = h263_format[format][0];
+ height = h263_format[format][1];
+ if (!width)
+ return -1;
+
+ s->pict_type = I_TYPE + 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;
+
+ if (get_bits1(&s->gb) != 0) {
+ av_log(s->avctx, AV_LOG_ERROR, "H263 PB frame not supported\n");
+ return -1; /* not PB frame */
+ }
+ 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);
+ dprintf("ufep=1, format: %d\n", format);
+ s->custom_pcf= get_bits1(&s->gb);
+ s->umvplus = get_bits(&s->gb, 1); /* 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;
+
+ 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= I_TYPE;break;
+ case 1: s->pict_type= P_TYPE;break;
+ case 3: s->pict_type= B_TYPE;break;
+ case 7: s->pict_type= I_TYPE;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);
+ dprintf("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;
+ dprintf("\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= pixel_aspect[s->aspect_ratio_info];
+ }
+ } else {
+ width = h263_format[format][0];
+ height = 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= ff_gcd(s->avctx->time_base.den, s->avctx->time_base.num);
+ s->avctx->time_base.den /= gcd;
+ s->avctx->time_base.num /= gcd;
+// av_log(s->avctx, AV_LOG_DEBUG, "%d/%d\n", s->avctx->time_base.den, s->avctx->time_base.num);
+ }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);
+ }
+
+ s->mb_width = (s->width + 15) / 16;
+ s->mb_height = (s->height + 15) / 16;
+ s->mb_num = s->mb_width * s->mb_height;
+
+ /* 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;
+ }
+
+ 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_pict_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
+ );
+ }
+#if 1
+ if (s->pict_type == I_TYPE && s->codec_tag == ff_get_fourcc("ZYGO")){
+ 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));
+ }
+#endif
+
+ return 0;
+}
+
+static void mpeg4_decode_sprite_trajectory(MpegEncContext * s, GetBitContext *gb)
+{
+ int i;
+ int a= 2<<s->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;
+
+ for(i=0; i<s->num_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 */
+//printf("%d %d %d %d\n", x, y, i, s->sprite_warping_accuracy);
+ d[i][0]= x;
+ d[i][1]= y;
+ }
+
+ while((1<<alpha)<w) alpha++;
+ while((1<<beta )<h) beta++; // there seems to be a typo in the mpeg4 std for the definition of w' and h'
+ w2= 1<<alpha;
+ h2= 1<<beta;
+
+// Note, the 4th point isn't used for GMC
+ if(s->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<<s->sprite_shift[0]
+ && s->sprite_delta[0][1] == 0
+ && s->sprite_delta[1][0] == 0
+ && s->sprite_delta[1][1] == a<<s->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];
+//printf("shifts %d %d\n", shift_y, shift_c);
+ 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;
+ }
+#if 0
+printf("vop:%d:%d %d:%d %d:%d, sprite:%d:%d %d:%d %d:%d, virtual: %d:%d %d:%d\n",
+ vop_ref[0][0], vop_ref[0][1],
+ vop_ref[1][0], vop_ref[1][1],
+ vop_ref[2][0], vop_ref[2][1],
+ sprite_ref[0][0], sprite_ref[0][1],
+ sprite_ref[1][0], sprite_ref[1][1],
+ sprite_ref[2][0], sprite_ref[2][1],
+ virtual_ref[0][0], virtual_ref[0][1],
+ virtual_ref[1][0], virtual_ref[1][1]
+ );
+
+printf("offset: %d:%d , delta: %d %d %d %d, shift %d\n",
+ s->sprite_offset[0][0], s->sprite_offset[0][1],
+ s->sprite_delta[0][0], s->sprite_delta[0][1],
+ s->sprite_delta[1][0], s->sprite_delta[1][1],
+ s->sprite_shift[0]
+ );
+#endif
+}
+
+static int mpeg4_decode_gop_header(MpegEncContext * s, GetBitContext *gb){
+ int hours, minutes, seconds;
+
+ 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 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;
+ }
+//printf("vo type:%d\n",s->vo_type);
+ 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= 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!=1){
+ 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 overriden
+ 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");
+ 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 == ff_get_fourcc("MP4S"))){ /* they should be non zero but who knows ... */
+ s->width = width;
+ s->height = height;
+// printf("width/height: %d %d\n", width, 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);
+ 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);
+ } 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)) av_log(s->avctx, AV_LOG_ERROR, "Complexity estimation not supported\n");
+
+ 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 ref_layer_id;
+ int ref_layer_sampling_dir;
+ 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);
+ ref_layer_id= get_bits(gb, 4);
+ ref_layer_sampling_dir= get_bits1(gb);
+ 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){
+
+// fprintf(stderr, "illegal scalability header (VERY broken encoder), trying to workaround\n");
+ s->scalability=0;
+
+ *gb= bak;
+ }else
+ av_log(s->avctx, AV_LOG_ERROR, "scalability not supported\n");
+
+ // bin shape stuff FIXME
+ }
+ }
+ return 0;
+}
+
+/**
+ * decodes the user data stuff in the header.
+ * allso inits 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';
+ }
+
+ /* ffmpeg 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;
+ }
+
+//printf("User Data: %s\n", buf);
+ return 0;
+}
+
+static int decode_vop_header(MpegEncContext *s, GetBitContext *gb){
+ int time_incr, time_increment;
+
+ s->pict_type = get_bits(gb, 2) + I_TYPE; /* pict type: I = 0 , P = 1 */
+ if(s->pict_type==B_TYPE && 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!=B_TYPE;
+ if(s->partitioned_frame)
+ s->decode_mb= mpeg4_decode_partitioned_mb;
+ else
+ s->decode_mb= ff_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(show_bits(gb, s->time_increment_bits+1)&1) break;
+ }
+
+ av_log(s->avctx, AV_LOG_ERROR, "my guess is %d bits ;)\n",s->time_increment_bits);
+ }
+
+ if(IS_3IV1) time_increment= get_bits1(gb); //FIXME investigate further
+ else time_increment= get_bits(gb, s->time_increment_bits);
+
+// printf("%d %X\n", s->time_increment_bits, time_increment);
+//av_log(s->avctx, AV_LOG_DEBUG, " type:%d modulo_time_base:%d increment:%d t_frame %d\n", s->pict_type, time_incr, time_increment, s->t_frame);
+ if(s->pict_type!=B_TYPE){
+ 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){
+// fprintf(stderr, "header is not mpeg4 compatible, broken encoder, trying to workaround\n");
+ 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){
+// printf("messed up order, maybe after seeking? skipping current b frame\n");
+ 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;
+ }
+//av_log(s->avctx, AV_LOG_DEBUG, "last nonb %"PRId64" last_base %d time %"PRId64" pp %d pb %d t %d ppf %d pbf %d\n", s->last_non_b_time, s->last_time_base, s->time, s->pp_time, s->pb_time, s->t_frame, s->pp_field_time, s->pb_field_time);
+
+ if(s->avctx->time_base.num)
+ s->current_picture_ptr->pts= (s->time + s->avctx->time_base.num/2) / s->avctx->time_base.num;
+ else
+ s->current_picture_ptr->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->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;
+ }
+//printf("time %d %d %d || %"PRId64" %"PRId64" %"PRId64"\n", s->time_increment_bits, s->avctx->time_base.den, s->time_base,
+//s->time, s->last_non_b_time, s->last_non_b_time - s->pp_time);
+ if (s->shape != BIN_ONLY_SHAPE && ( s->pict_type == P_TYPE
+ || (s->pict_type == S_TYPE && 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 != I_TYPE) {
+ int width, height, hor_spat_ref, ver_spat_ref;
+
+ width = get_bits(gb, 13);
+ skip_bits1(gb); /* marker */
+ height = get_bits(gb, 13);
+ skip_bits1(gb); /* marker */
+ hor_spat_ref = get_bits(gb, 13); /* hor_spat_ref */
+ skip_bits1(gb); /* marker */
+ ver_spat_ref = get_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) {
+ s->intra_dc_threshold= 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 == S_TYPE && (s->vol_sprite_usage==STATIC_SPRITE || s->vol_sprite_usage==GMC_SPRITE)){
+ mpeg4_decode_sprite_trajectory(s, gb);
+ 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 != I_TYPE) {
+ 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");
+ return -1; // makes no sense to continue, as the MV decoding will break very quickly
+ }
+ }else
+ s->f_code=1;
+
+ if (s->pict_type == B_TYPE) {
+ s->b_code = get_bits(gb, 3);
+ }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\n",
+ s->qscale, s->f_code, s->b_code,
+ s->pict_type == I_TYPE ? "I" : (s->pict_type == P_TYPE ? "P" : (s->pict_type == B_TYPE ? "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);
+ }
+
+ if(!s->scalability){
+ if (s->shape!=RECT_SHAPE && s->pict_type!=I_TYPE) {
+ 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==0 && s->picture_number==0){
+ av_log(s->avctx, AV_LOG_ERROR, "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)
+{
+ int startcode, v;
+
+ /* search next start code */
+ align_get_bits(gb);
+
+ if(s->codec_tag == ff_get_fourcc("WV1F") && show_bits(gb, 24) == 0x575630){
+ skip_bits(gb, 24);
+ if(get_bits(gb, 8) == 0xF0)
+ return decode_vop_header(s, gb);
+ }
+
+ startcode = 0xff;
+ for(;;) {
+ if(get_bits_count(gb) >= gb->size_in_bits){
+ if(gb->size_in_bits==8 && (s->divx_version || s->xvid_build)){
+ av_log(s->avctx, AV_LOG_ERROR, "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 == VOP_STARTCODE){
+ return decode_vop_header(s, gb);
+ }
+
+ align_get_bits(gb);
+ startcode = 0xff;
+ }
+}
+
+/* don't understand why they choose a different header ! */
+int 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 != 7) {
+ av_log(s->avctx, AV_LOG_ERROR, "Intel H263 free format not supported\n");
+ return -1;
+ }
+ s->h263_plus = 0;
+
+ s->pict_type = I_TYPE + get_bits1(&s->gb);
+
+ s->unrestricted_mv = get_bits1(&s->gb);
+ s->h263_long_vectors = s->unrestricted_mv;
+
+ if (get_bits1(&s->gb) != 0) {
+ av_log(s->avctx, AV_LOG_ERROR, "SAC not supported\n");
+ return -1; /* SAC: off */
+ }
+ if (get_bits1(&s->gb) != 0) {
+ s->obmc= 1;
+ av_log(s->avctx, AV_LOG_ERROR, "Advanced Prediction Mode not supported\n");
+// return -1; /* advanced prediction mode: off */
+ }
+ if (get_bits1(&s->gb) != 0) {
+ av_log(s->avctx, AV_LOG_ERROR, "PB frame mode no supported\n");
+ return -1; /* PB frame mode */
+ }
+
+ /* skip unknown header garbage */
+ skip_bits(&s->gb, 41);
+
+ s->chroma_qscale= s->qscale = get_bits(&s->gb, 5);
+ skip_bits1(&s->gb); /* Continuous Presence Multipoint mode: off */
+
+ /* 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;
+
+ return 0;
+}
+
+int flv_h263_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 -1;
+ }
+ format = get_bits(&s->gb, 5);
+ if (format != 0 && format != 1) {
+ av_log(s->avctx, AV_LOG_ERROR, "Bad picture format\n");
+ return -1;
+ }
+ 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(avcodec_check_dimensions(s->avctx, width, height))
+ return -1;
+ s->width = width;
+ s->height = height;
+
+ s->pict_type = I_TYPE + get_bits(&s->gb, 2);
+ s->dropable= s->pict_type > P_TYPE;
+ if (s->dropable)
+ s->pict_type = P_TYPE;
+
+ 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->dropable ? 'D' : av_get_pict_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;
+}
diff --git a/contrib/ffmpeg/libavcodec/h263data.h b/contrib/ffmpeg/libavcodec/h263data.h
new file mode 100644
index 000000000..5eddc3b54
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/h263data.h
@@ -0,0 +1,308 @@
+/*
+ * copyright (c) 2000,2001 Fabrice Bellard
+ * H263+ support
+ * copyright (c) 2001 Juan J. Sierralta P.
+ * copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file h263data.h
+ * H.263 tables.
+ */
+
+
+/* intra MCBPC, mb_type = (intra), then (intraq) */
+const uint8_t intra_MCBPC_code[9] = { 1, 1, 2, 3, 1, 1, 2, 3, 1 };
+const uint8_t 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 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 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*/
+};
+
+static const uint8_t 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},
+};
+
+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,
+};
+
+static const uint8_t cbpc_b_tab[4][2] = {
+{0, 1},
+{2, 2},
+{7, 3},
+{6, 3},
+};
+
+const uint8_t 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 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 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 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 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,
+};
+
+static RLTable rl_inter = {
+ 102,
+ 58,
+ inter_vlc,
+ inter_run,
+ 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,
+};
+
+static RLTable rl_intra_aic = {
+ 102,
+ 58,
+ intra_vlc_aic,
+ intra_run_aic,
+ intra_level_aic,
+};
+
+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
+};
+
+static const uint16_t 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
+};
+
+static const uint8_t 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
+};
+
diff --git a/contrib/ffmpeg/libavcodec/h263dec.c b/contrib/ffmpeg/libavcodec/h263dec.c
new file mode 100644
index 000000000..66370c179
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/h263dec.c
@@ -0,0 +1,913 @@
+/*
+ * H.263 decoder
+ * Copyright (c) 2001 Fabrice Bellard.
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file h263dec.c
+ * H.263 decoder.
+ */
+
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+//#define DEBUG
+//#define PRINT_FRAME_TIME
+
+int ff_h263_decode_init(AVCodecContext *avctx)
+{
+ MpegEncContext *s = avctx->priv_data;
+
+ 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
+ MPV_decode_defaults(s);
+ s->quant_precision=5;
+ s->decode_mb= ff_h263_decode_mb;
+ s->low_delay= 1;
+ avctx->pix_fmt= PIX_FMT_YUV420P;
+ s->unrestricted_mv= 1;
+
+ /* select sub codec */
+ switch(avctx->codec->id) {
+ case CODEC_ID_H263:
+ s->unrestricted_mv= 0;
+ break;
+ case CODEC_ID_MPEG4:
+ s->decode_mb= ff_mpeg4_decode_mb;
+ s->time_increment_bits = 4; /* default value for broken headers */
+ s->h263_pred = 1;
+ s->low_delay = 0; //default, might be overriden in the vol header during header parsing
+ break;
+ case CODEC_ID_MSMPEG4V1:
+ s->h263_msmpeg4 = 1;
+ s->h263_pred = 1;
+ s->msmpeg4_version=1;
+ break;
+ case CODEC_ID_MSMPEG4V2:
+ s->h263_msmpeg4 = 1;
+ s->h263_pred = 1;
+ s->msmpeg4_version=2;
+ break;
+ case CODEC_ID_MSMPEG4V3:
+ s->h263_msmpeg4 = 1;
+ s->h263_pred = 1;
+ s->msmpeg4_version=3;
+ break;
+ case CODEC_ID_WMV1:
+ s->h263_msmpeg4 = 1;
+ s->h263_pred = 1;
+ s->msmpeg4_version=4;
+ break;
+ case CODEC_ID_WMV2:
+ s->h263_msmpeg4 = 1;
+ s->h263_pred = 1;
+ s->msmpeg4_version=5;
+ break;
+ case CODEC_ID_VC1:
+ case CODEC_ID_WMV3:
+ s->h263_msmpeg4 = 1;
+ s->h263_pred = 1;
+ s->msmpeg4_version=6;
+ break;
+ case CODEC_ID_H263I:
+ break;
+ case CODEC_ID_FLV1:
+ s->h263_flv = 1;
+ break;
+ default:
+ return -1;
+ }
+ s->codec_id= avctx->codec->id;
+
+ /* for h263, we allocate the images after having read the header */
+ if (avctx->codec->id != CODEC_ID_H263 && avctx->codec->id != CODEC_ID_MPEG4)
+ if (MPV_common_init(s) < 0)
+ return -1;
+
+ if (s->h263_msmpeg4)
+ ff_msmpeg4_decode_init(s);
+ else
+ h263_decode_init_vlc(s);
+
+ return 0;
+}
+
+int ff_h263_decode_end(AVCodecContext *avctx)
+{
+ MpegEncContext *s = avctx->priv_data;
+
+ MPV_common_end(s);
+ return 0;
+}
+
+/**
+ * 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)+7)>>3;
+
+ if(s->divx_packed){
+ //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 thats 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 ? (AC_END|AC_ERROR) : 0x7F;
+ const int mb_size= 16>>s->avctx->lowres;
+ 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->partitioned_frame){
+ const int qscale= s->qscale;
+
+ if(s->codec_id==CODEC_ID_MPEG4){
+ if(ff_mpeg4_decode_partitions(s) < 0)
+ return -1;
+ }
+
+ /* 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, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, AC_END|DC_END|MV_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;
+//printf("%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!=B_TYPE)
+ 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){
+ MPV_decode_mb(s, s->block);
+ if(s->loop_filter)
+ ff_h263_loop_filter(s);
+
+//printf("%d %d %d %06X\n", s->mb_x, s->mb_y, s->gb.size*8 - get_bits_count(&s->gb), show_bits(&s->gb, 24));
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END)&part_mask);
+
+ s->padding_bug_score--;
+
+ if(++s->mb_x >= s->mb_width){
+ s->mb_x=0;
+ ff_draw_horiz_band(s, s->mb_y*mb_size, mb_size);
+ 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, s->resync_mb_x, s->resync_mb_y, s->mb_x+1, s->mb_y, (AC_END|DC_END|MV_END)&part_mask);
+ return -1;
+ }
+ av_log(s->avctx, AV_LOG_ERROR, "Error at MB: %d\n", xy);
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_ERROR|DC_ERROR|MV_ERROR)&part_mask);
+
+ return -1;
+ }
+
+ MPV_decode_mb(s, s->block);
+ if(s->loop_filter)
+ ff_h263_loop_filter(s);
+ }
+
+ ff_draw_horiz_band(s, s->mb_y*mb_size, mb_size);
+
+ s->mb_x= 0;
+ }
+
+ assert(s->mb_x==0 && s->mb_y==s->mb_height);
+
+ /* try to detect the padding bug */
+ if( s->codec_id==CODEC_ID_MPEG4
+ && (s->workaround_bugs&FF_BUG_AUTODETECT)
+ && s->gb.size_in_bits - get_bits_count(&s->gb) >=0
+ && s->gb.size_in_bits - get_bits_count(&s->gb) < 48
+// && !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 || !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= s->gb.size_in_bits - get_bits_count(&s->gb);
+ int max_extra=7;
+
+ /* no markers in M$ crap */
+ if(s->msmpeg4_version && s->pict_type==I_TYPE)
+ 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->error_resilience>=3)
+ 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, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, AC_END|DC_END|MV_END);
+
+ return 0;
+ }
+
+ av_log(s->avctx, AV_LOG_ERROR, "slice end not reached but screenspace end (%d left %06X, score= %d)\n",
+ s->gb.size_in_bits - get_bits_count(&s->gb),
+ show_bits(&s->gb, 24), s->padding_bug_score);
+
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END)&part_mask);
+
+ return -1;
+}
+
+/**
+ * finds 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){
+ 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<buf_size; i++){
+ state= (state<<8) | buf[i];
+ if(state == 0x1B6){
+ i++;
+ vop_found=1;
+ break;
+ }
+ }
+ }
+
+ if(vop_found){
+ /* EOF considered as end of frame */
+ if (buf_size == 0)
+ return 0;
+ for(; i<buf_size; i++){
+ state= (state<<8) | buf[i];
+ if((state&0xFFFFFF00) == 0x100){
+ 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_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<buf_size; i++){
+ state= (state<<8) | buf[i];
+ if(state>>(32-22) == 0x20){
+ i++;
+ vop_found=1;
+ break;
+ }
+ }
+ }
+
+ if(vop_found){
+ for(; i<buf_size; i++){
+ state= (state<<8) | buf[i];
+ if(state>>(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;
+}
+
+#ifdef CONFIG_H263_PARSER
+static int h263_parse(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size)
+{
+ ParseContext *pc = s->priv_data;
+ int next;
+
+ next= h263_find_frame_end(pc, buf, buf_size);
+
+ if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) {
+ *poutbuf = NULL;
+ *poutbuf_size = 0;
+ return buf_size;
+ }
+
+ *poutbuf = (uint8_t *)buf;
+ *poutbuf_size = buf_size;
+ return next;
+}
+#endif
+
+int ff_h263_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ MpegEncContext *s = avctx->priv_data;
+ int ret;
+ AVFrame *pict = data;
+
+#ifdef PRINT_FRAME_TIME
+uint64_t time= rdtsc();
+#endif
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_DEBUG, "*****frame %d size=%d\n", avctx->frame_number, buf_size);
+ av_log(avctx, AV_LOG_DEBUG, "bytes=%x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]);
+#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) {
+ *pict= *(AVFrame*)s->next_picture_ptr;
+ s->next_picture_ptr= NULL;
+
+ *data_size = sizeof(AVFrame);
+ }
+
+ return 0;
+ }
+
+ if(s->flags&CODEC_FLAG_TRUNCATED){
+ int next;
+
+ if(s->codec_id==CODEC_ID_MPEG4){
+ next= ff_mpeg4_find_frame_end(&s->parse_context, buf, buf_size);
+ }else if(s->codec_id==CODEC_ID_H263){
+ next= 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 -1;
+ }
+
+ if( ff_combine_frame(&s->parse_context, next, &buf, &buf_size) < 0 )
+ return buf_size;
+ }
+
+
+retry:
+
+ 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 (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 cant store anyting im there
+ if(s->current_picture_ptr==NULL || s->current_picture_ptr->data[0]){
+ int i= ff_find_unused_picture(s, 0);
+ s->current_picture_ptr= &s->picture[i];
+ }
+
+ /* let's go :-) */
+ if (s->msmpeg4_version==5) {
+ ret= ff_wmv2_decode_picture_header(s);
+ } else if (s->msmpeg4_version) {
+ ret = msmpeg4_decode_picture_header(s);
+ } else if (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);
+
+ if(s->flags& CODEC_FLAG_LOW_DELAY)
+ s->low_delay=1;
+ } else if (s->codec_id == CODEC_ID_H263I) {
+ ret = intel_h263_decode_picture_header(s);
+ } else if (s->h263_flv) {
+ ret = flv_h263_decode_picture_header(s);
+ } else {
+ ret = h263_decode_picture_header(s);
+ }
+
+ 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 -1;
+ }
+
+ avctx->has_b_frames= !s->low_delay;
+
+ if(s->xvid_build==0 && s->divx_version==0 && s->lavc_build==0){
+ if(s->stream_codec_tag == ff_get_fourcc("XVID") ||
+ s->codec_tag == ff_get_fourcc("XVID") || s->codec_tag == ff_get_fourcc("XVIX") ||
+ s->codec_tag == ff_get_fourcc("RMP4"))
+ s->xvid_build= -1;
+#if 0
+ if(s->codec_tag == ff_get_fourcc("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= -1;
+#endif
+ }
+
+ if(s->xvid_build==0 && s->divx_version==0 && s->lavc_build==0){
+ if(s->codec_tag == ff_get_fourcc("DIVX") && s->vo_type==0 && s->vol_control_parameters==0)
+ s->divx_version= 400; //divx 4
+ }
+
+ if(s->xvid_build && s->divx_version){
+ s->divx_version=
+ s->divx_build= 0;
+ }
+
+ if(s->workaround_bugs&FF_BUG_AUTODETECT){
+ if(s->codec_tag == ff_get_fourcc("XVIX"))
+ s->workaround_bugs|= FF_BUG_XVID_ILACE;
+
+ if(s->codec_tag == ff_get_fourcc("UMP4")){
+ s->workaround_bugs|= FF_BUG_UMP4;
+ }
+
+ if(s->divx_version>=500){
+ s->workaround_bugs|= FF_BUG_QPEL_CHROMA;
+ }
+
+ if(s->divx_version>502){
+ s->workaround_bugs|= FF_BUG_QPEL_CHROMA2;
+ }
+
+ if(s->xvid_build && s->xvid_build<=3)
+ s->padding_bug_score= 256*256*256*64;
+
+ if(s->xvid_build && s->xvid_build<=1)
+ s->workaround_bugs|= FF_BUG_QPEL_CHROMA;
+
+ if(s->xvid_build && s->xvid_build<=12)
+ s->workaround_bugs|= FF_BUG_EDGE;
+
+ if(s->xvid_build && s->xvid_build<=32)
+ 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 && s->lavc_build<4653)
+ s->workaround_bugs|= FF_BUG_STD_QPEL;
+
+ if(s->lavc_build && s->lavc_build<4655)
+ s->workaround_bugs|= FF_BUG_DIRECT_BLOCKSIZE;
+
+ if(s->lavc_build && s->lavc_build<4670){
+ s->workaround_bugs|= FF_BUG_EDGE;
+ }
+
+ if(s->lavc_build && s->lavc_build<=4712)
+ s->workaround_bugs|= FF_BUG_DC_CLIP;
+
+ if(s->divx_version)
+ s->workaround_bugs|= FF_BUG_DIRECT_BLOCKSIZE;
+//printf("padding_bug_score: %d\n", s->padding_bug_score);
+ if(s->divx_version==501 && s->divx_build==20020416)
+ s->padding_bug_score= 256*256*256*64;
+
+ if(s->divx_version && s->divx_version<500){
+ s->workaround_bugs|= FF_BUG_EDGE;
+ }
+
+ if(s->divx_version)
+ 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
+ * lets hope this at least works
+ */
+ if( s->resync_marker==0 && s->data_partitioning==0 && s->divx_version==0
+ && s->codec_id==CODEC_ID_MPEG4 && s->vo_type==0)
+ s->workaround_bugs|= FF_BUG_NO_PADDING;
+
+ if(s->lavc_build && s->lavc_build<4609) //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 0 // dump bits per frame / qp / complexity
+{
+ static FILE *f=NULL;
+ if(!f) f=fopen("rate_qp_cplx.txt", "w");
+ fprintf(f, "%d %d %f\n", buf_size, s->qscale, buf_size*(double)s->qscale);
+}
+#endif
+
+#if defined(HAVE_MMX) && defined(CONFIG_GPL)
+ if(s->codec_id == CODEC_ID_MPEG4 && s->xvid_build && avctx->idct_algo == FF_IDCT_AUTO && (mm_flags & MM_MMX)){
+ avctx->idct_algo= FF_IDCT_XVIDMMX;
+ avctx->coded_width= 0; // force reinit
+// dsputil_init(&s->dsp, avctx);
+ s->picture_number=0;
+ }
+#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 ( s->width != avctx->coded_width
+ || s->height != avctx->coded_height) {
+ /* H.263 could change picture size any time */
+ ParseContext pc= s->parse_context; //FIXME move these demuxng hack to avformat
+ s->parse_context.buffer=0;
+ MPV_common_end(s);
+ s->parse_context= pc;
+ }
+ if (!s->context_initialized) {
+ avcodec_set_dimensions(avctx, s->width, s->height);
+
+ goto retry;
+ }
+
+ if((s->codec_id==CODEC_ID_H263 || s->codec_id==CODEC_ID_H263P))
+ s->gob_index = ff_h263_get_gob_height(s);
+
+ // for hurry_up==5
+ s->current_picture.pict_type= s->pict_type;
+ s->current_picture.key_frame= s->pict_type == I_TYPE;
+
+ /* skip B-frames if we don't have reference frames */
+ if(s->last_picture_ptr==NULL && (s->pict_type==B_TYPE || s->dropable)) return get_consumed_bytes(s, buf_size);
+ /* skip b frames if we are in a hurry */
+ if(avctx->hurry_up && s->pict_type==B_TYPE) return get_consumed_bytes(s, buf_size);
+ if( (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type==B_TYPE)
+ || (avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type!=I_TYPE)
+ || avctx->skip_frame >= AVDISCARD_ALL)
+ return get_consumed_bytes(s, buf_size);
+ /* skip everything if we are in a hurry>=5 */
+ if(avctx->hurry_up>=5) return get_consumed_bytes(s, buf_size);
+
+ if(s->next_p_frame_damaged){
+ if(s->pict_type==B_TYPE)
+ return get_consumed_bytes(s, buf_size);
+ else
+ s->next_p_frame_damaged=0;
+ }
+
+ if((s->avctx->flags2 & CODEC_FLAG2_FAST) && s->pict_type==B_TYPE){
+ s->me.qpel_put= s->dsp.put_2tap_qpel_pixels_tab;
+ s->me.qpel_avg= s->dsp.avg_2tap_qpel_pixels_tab;
+ }else if((!s->no_rounding) || s->pict_type==B_TYPE){
+ 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(MPV_frame_start(s, avctx) < 0)
+ return -1;
+
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_DEBUG, "qscale=%d\n", s->qscale);
+#endif
+
+ ff_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 isnt available before MPV_frame_start()
+ if (s->msmpeg4_version==5){
+ if(ff_wmv2_decode_secondary_picture_header(s) < 0)
+ return -1;
+ }
+
+ /* decode each macroblock */
+ s->mb_x=0;
+ s->mb_y=0;
+
+ decode_slice(s);
+ while(s->mb_y<s->mb_height){
+ if(s->msmpeg4_version){
+ if(s->mb_x!=0 || (s->mb_y%s->slice_height)!=0 || get_bits_count(&s->gb) > s->gb.size_in_bits)
+ break;
+ }else{
+ if(ff_h263_resync(s)<0)
+ break;
+ }
+
+ if(s->msmpeg4_version<4 && s->h263_pred)
+ ff_mpeg4_clean_buffers(s);
+
+ decode_slice(s);
+ }
+
+ if (s->h263_msmpeg4 && s->msmpeg4_version<4 && s->pict_type==I_TYPE)
+ if(msmpeg4_decode_ext_header(s, buf_size) < 0){
+ s->error_status_table[s->mb_num-1]= AC_ERROR|DC_ERROR|MV_ERROR;
+ }
+
+ /* divx 5.01+ bistream reorder stuff */
+ if(s->codec_id==CODEC_ID_MPEG4 && s->bitstream_buffer_size==0 && s->divx_packed){
+ int current_pos= get_bits_count(&s->gb)>>3;
+ int startcode_found=0;
+
+ if(buf_size - current_pos > 5){
+ int i;
+ for(i=current_pos; i<buf_size-3; i++){
+ if(buf[i]==0 && buf[i+1]==0 && buf[i+2]==1 && buf[i+3]==0xB6){
+ startcode_found=1;
+ break;
+ }
+ }
+ }
+ if(s->gb.buffer == s->bitstream_buffer && buf_size>20){ //xvid style
+ startcode_found=1;
+ current_pos=0;
+ }
+
+ if(startcode_found){
+ s->bitstream_buffer= av_fast_realloc(
+ s->bitstream_buffer,
+ &s->allocated_bitstream_buffer_size,
+ buf_size - current_pos + FF_INPUT_BUFFER_PADDING_SIZE);
+ memcpy(s->bitstream_buffer, buf + current_pos, buf_size - current_pos);
+ s->bitstream_buffer_size= buf_size - current_pos;
+ }
+ }
+
+ ff_er_frame_end(s);
+
+ MPV_frame_end(s);
+
+assert(s->current_picture.pict_type == s->current_picture_ptr->pict_type);
+assert(s->current_picture.pict_type == s->pict_type);
+ if (s->pict_type == B_TYPE || s->low_delay) {
+ *pict= *(AVFrame*)s->current_picture_ptr;
+ } else if (s->last_picture_ptr != NULL) {
+ *pict= *(AVFrame*)s->last_picture_ptr;
+ }
+
+ if(s->last_picture_ptr || s->low_delay){
+ *data_size = sizeof(AVFrame);
+ ff_print_debug_info(s, pict);
+ }
+
+ /* Return the Picture timestamp as the frame number */
+ /* we substract 1 because it is added on utils.c */
+ avctx->frame_number = s->picture_number - 1;
+
+#ifdef PRINT_FRAME_TIME
+av_log(avctx, AV_LOG_DEBUG, "%"PRId64"\n", rdtsc()-time);
+#endif
+
+ return get_consumed_bytes(s, buf_size);
+}
+
+AVCodec mpeg4_decoder = {
+ "mpeg4",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MPEG4,
+ sizeof(MpegEncContext),
+ ff_h263_decode_init,
+ NULL,
+ ff_h263_decode_end,
+ ff_h263_decode_frame,
+ CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY,
+ .flush= ff_mpeg_flush,
+};
+
+AVCodec h263_decoder = {
+ "h263",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_H263,
+ sizeof(MpegEncContext),
+ ff_h263_decode_init,
+ NULL,
+ ff_h263_decode_end,
+ ff_h263_decode_frame,
+ CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY,
+ .flush= ff_mpeg_flush,
+};
+
+AVCodec msmpeg4v1_decoder = {
+ "msmpeg4v1",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MSMPEG4V1,
+ sizeof(MpegEncContext),
+ ff_h263_decode_init,
+ NULL,
+ ff_h263_decode_end,
+ ff_h263_decode_frame,
+ CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1,
+};
+
+AVCodec msmpeg4v2_decoder = {
+ "msmpeg4v2",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MSMPEG4V2,
+ sizeof(MpegEncContext),
+ ff_h263_decode_init,
+ NULL,
+ ff_h263_decode_end,
+ ff_h263_decode_frame,
+ CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1,
+};
+
+AVCodec msmpeg4v3_decoder = {
+ "msmpeg4",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MSMPEG4V3,
+ sizeof(MpegEncContext),
+ ff_h263_decode_init,
+ NULL,
+ ff_h263_decode_end,
+ ff_h263_decode_frame,
+ CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1,
+};
+
+AVCodec wmv1_decoder = {
+ "wmv1",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_WMV1,
+ sizeof(MpegEncContext),
+ ff_h263_decode_init,
+ NULL,
+ ff_h263_decode_end,
+ ff_h263_decode_frame,
+ CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1,
+};
+
+AVCodec h263i_decoder = {
+ "h263i",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_H263I,
+ sizeof(MpegEncContext),
+ ff_h263_decode_init,
+ NULL,
+ ff_h263_decode_end,
+ ff_h263_decode_frame,
+ CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1,
+};
+
+AVCodec flv_decoder = {
+ "flv",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_FLV1,
+ sizeof(MpegEncContext),
+ ff_h263_decode_init,
+ NULL,
+ ff_h263_decode_end,
+ ff_h263_decode_frame,
+ CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1
+};
+
+#ifdef CONFIG_H263_PARSER
+AVCodecParser h263_parser = {
+ { CODEC_ID_H263 },
+ sizeof(ParseContext),
+ NULL,
+ h263_parse,
+ ff_parse_close,
+};
+#endif
diff --git a/contrib/ffmpeg/libavcodec/h264.c b/contrib/ffmpeg/libavcodec/h264.c
new file mode 100644
index 000000000..ad23ae120
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/h264.c
@@ -0,0 +1,8655 @@
+/*
+ * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder
+ * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/**
+ * @file h264.c
+ * H.264 / AVC / MPEG4 part10 codec.
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#include "common.h"
+#include "dsputil.h"
+#include "avcodec.h"
+#include "mpegvideo.h"
+#include "h264data.h"
+#include "golomb.h"
+
+#include "cabac.h"
+
+//#undef NDEBUG
+#include <assert.h>
+
+#define interlaced_dct interlaced_dct_is_a_bad_name
+#define mb_intra mb_intra_isnt_initalized_see_mb_type
+
+#define LUMA_DC_BLOCK_INDEX 25
+#define CHROMA_DC_BLOCK_INDEX 26
+
+#define CHROMA_DC_COEFF_TOKEN_VLC_BITS 8
+#define COEFF_TOKEN_VLC_BITS 8
+#define TOTAL_ZEROS_VLC_BITS 9
+#define CHROMA_DC_TOTAL_ZEROS_VLC_BITS 3
+#define RUN_VLC_BITS 3
+#define RUN7_VLC_BITS 6
+
+#define MAX_SPS_COUNT 32
+#define MAX_PPS_COUNT 256
+
+#define MAX_MMCO_COUNT 66
+
+/* Compiling in interlaced support reduces the speed
+ * of progressive decoding by about 2%. */
+#define ALLOW_INTERLACE
+
+#ifdef ALLOW_INTERLACE
+#define MB_MBAFF h->mb_mbaff
+#define MB_FIELD h->mb_field_decoding_flag
+#define FRAME_MBAFF h->mb_aff_frame
+#else
+#define MB_MBAFF 0
+#define MB_FIELD 0
+#define FRAME_MBAFF 0
+#undef IS_INTERLACED
+#define IS_INTERLACED(mb_type) 0
+#endif
+
+/**
+ * Sequence parameter set
+ */
+typedef struct SPS{
+
+ int profile_idc;
+ int level_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; ///< frame_width_in_mbs_minus1 + 1
+ int mb_height; ///< frame_height_in_mbs_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
+ int crop_left; ///< frame_cropping_rect_left_offset
+ int crop_right; ///< frame_cropping_rect_right_offset
+ int crop_top; ///< frame_cropping_rect_top_offset
+ int crop_bottom; ///< frame_cropping_rect_bottom_offset
+ int vui_parameters_present_flag;
+ AVRational sar;
+ 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[2][64];
+}SPS;
+
+/**
+ * Picture parameter set
+ */
+typedef struct PPS{
+ 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;
+ 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;
+ 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[2][64];
+}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_frame_num;
+ int long_index;
+} MMCO;
+
+/**
+ * H264Context
+ */
+typedef struct H264Context{
+ MpegEncContext s;
+ int nal_ref_idc;
+ int nal_unit_type;
+#define NAL_SLICE 1
+#define NAL_DPA 2
+#define NAL_DPB 3
+#define NAL_DPC 4
+#define NAL_IDR_SLICE 5
+#define NAL_SEI 6
+#define NAL_SPS 7
+#define NAL_PPS 8
+#define NAL_AUD 9
+#define NAL_END_SEQUENCE 10
+#define NAL_END_STREAM 11
+#define NAL_FILLER_DATA 12
+#define NAL_SPS_EXT 13
+#define NAL_AUXILIARY_SLICE 19
+ uint8_t *rbsp_buffer;
+ unsigned int rbsp_buffer_size;
+
+ /**
+ * Used to parse AVC variant of h264
+ */
+ int is_avc; ///< this flag is != 0 if codec is avc1
+ int got_avcC; ///< flag used to parse avcC data only once
+ int nal_length_size; ///< Number of bytes used for nal length (1, 2 or 4)
+
+ int chroma_qp; //QPc
+
+ int prev_mb_skipped;
+ int next_mb_skipped;
+
+ //prediction stuff
+ int chroma_pred_mode;
+ int intra16x16_pred_mode;
+
+ int top_mb_xy;
+ int left_mb_xy[2];
+
+ int8_t intra4x4_pred_mode_cache[5*8];
+ int8_t (*intra4x4_pred_mode)[8];
+ void (*pred4x4 [9+3])(uint8_t *src, uint8_t *topright, int stride);//FIXME move to dsp?
+ void (*pred8x8l [9+3])(uint8_t *src, int topleft, int topright, int stride);
+ void (*pred8x8 [4+3])(uint8_t *src, int stride);
+ void (*pred16x16[4+3])(uint8_t *src, int stride);
+ 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+2*8];
+ uint8_t left_border[2*(17+2*9)];
+
+ /**
+ * non zero coeff count cache.
+ * is 64 if not available.
+ */
+ DECLARE_ALIGNED_8(uint8_t, non_zero_count_cache[6*8]);
+ uint8_t (*non_zero_count)[16];
+
+ /**
+ * Motion vector cache.
+ */
+ DECLARE_ALIGNED_8(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
+
+ /**
+ * is 1 if the specific list MV&references are set to 0,0,-2.
+ */
+ int mv_cache_clean[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+8)];
+
+ uint32_t *mb2b_xy; //FIXME are these 4 a good idea?
+ uint32_t *mb2b8_xy;
+ int b_stride; //FIXME use s->b4_stride
+ int b8_stride;
+
+ int mb_linesize; ///< may be equal to s->linesize or s->linesize*2, for mbaff
+ int mb_uvlinesize;
+
+ int emu_edge_width;
+ int emu_edge_height;
+
+ int halfpel_flag;
+ int thirdpel_flag;
+
+ int unknown_svq3_flag;
+ int next_slice_index;
+
+ SPS sps_buffer[MAX_SPS_COUNT];
+ SPS sps; ///< current sps
+
+ PPS pps_buffer[MAX_PPS_COUNT];
+ /**
+ * current pps
+ */
+ PPS pps; //FIXME move to Picture perhaps? (->no) do we need that?
+
+ uint32_t dequant4_buffer[6][52][16];
+ uint32_t dequant8_buffer[2][52][64];
+ uint32_t (*dequant4_coeff[6])[16];
+ uint32_t (*dequant8_coeff[2])[64];
+ int dequant_coeff_pps; ///< reinit tables when pps changes
+
+ int slice_num;
+ uint8_t *slice_table_base;
+ uint8_t *slice_table; ///< slice_table_base + 2*mb_stride + 1
+ int slice_type;
+ 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 sub_mb_type[4];
+
+ //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 for field pics.
+ */
+ int curr_pic_num;
+
+ /**
+ * max_frame_num or 2*max_frame_num for field pics.
+ */
+ int max_pic_num;
+
+ //Weighted pred stuff
+ int use_weight;
+ int use_weight_chroma;
+ int luma_log2_weight_denom;
+ int chroma_log2_weight_denom;
+ int luma_weight[2][48];
+ int luma_offset[2][48];
+ int chroma_weight[2][48][2];
+ int chroma_offset[2][48][2];
+ int implicit_weight[48][48];
+
+ //deblock
+ int deblocking_filter; ///< disable_deblocking_filter_idc with 1<->0
+ int slice_alpha_c0_offset;
+ int slice_beta_offset;
+
+ int redundant_pic_count;
+
+ int direct_spatial_mv_pred;
+ int dist_scale_factor[16];
+ int dist_scale_factor_field[32];
+ int map_col_to_list0[2][16];
+ int map_col_to_list0_field[2][32];
+
+ /**
+ * num_ref_idx_l0/1_active_minus1 + 1
+ */
+ int ref_count[2]; ///< counts frames or fields, depending on current mb mode
+ Picture *short_ref[32];
+ Picture *long_ref[32];
+ Picture default_ref_list[2][32];
+ Picture ref_list[2][48]; ///< 0..15: frame refs, 16..47: mbaff field refs
+ Picture *delayed_pic[16]; //FIXME size?
+ Picture *delayed_output_pic;
+
+ /**
+ * memory management control operations buffer.
+ */
+ MMCO mmco[MAX_MMCO_COUNT];
+ int mmco_index;
+
+ int long_ref_count; ///< number of actual long term references
+ int short_ref_count; ///< number of actual short term references
+
+ //data partitioning
+ GetBitContext intra_gb;
+ GetBitContext inter_gb;
+ GetBitContext *intra_gb_ptr;
+ GetBitContext *inter_gb_ptr;
+
+ DECLARE_ALIGNED_8(DCTELEM, mb[16*24]);
+
+ /**
+ * Cabac
+ */
+ CABACContext cabac;
+ uint8_t cabac_state[460];
+ int cabac_init_idc;
+
+ /* 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;
+ int16_t (*mvd_table[2])[2];
+ DECLARE_ALIGNED_8(int16_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];
+ const uint8_t *zigzag_scan_q0;
+ const uint8_t *zigzag_scan8x8_q0;
+ const uint8_t *zigzag_scan8x8_cavlc_q0;
+ const uint8_t *field_scan_q0;
+ const uint8_t *field_scan8x8_q0;
+ const uint8_t *field_scan8x8_cavlc_q0;
+
+ int x264_build;
+}H264Context;
+
+static VLC coeff_token_vlc[4];
+static VLC chroma_dc_coeff_token_vlc;
+
+static VLC total_zeros_vlc[15];
+static VLC chroma_dc_total_zeros_vlc[3];
+
+static VLC run_vlc[6];
+static VLC run7_vlc;
+
+static void svq3_luma_dc_dequant_idct_c(DCTELEM *block, int qp);
+static void svq3_add_idct_c(uint8_t *dst, DCTELEM *block, int stride, int qp, int dc);
+static void 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);
+static void 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);
+
+static always_inline uint32_t pack16to32(int a, int b){
+#ifdef WORDS_BIGENDIAN
+ return (b&0xFFFF) + (a<<16);
+#else
+ return (a&0xFFFF) + (b<<16);
+#endif
+}
+
+/**
+ * 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 or 4), should be a constant
+ */
+static always_inline void fill_rectangle(void *vp, int w, int h, int stride, uint32_t val, int size){
+ uint8_t *p= (uint8_t*)vp;
+ assert(size==1 || size==4);
+ assert(w<=4);
+
+ w *= size;
+ stride *= size;
+
+ assert((((long)vp)&(FFMIN(w, STRIDE_ALIGN)-1)) == 0);
+ assert((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)=
+ *(uint16_t*)(p + 3*stride)= v;
+ }else if(w==4){
+ const uint32_t v= size==4 ? val : 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)=
+ *(uint32_t*)(p + 3*stride)= v;
+ }else if(w==8){
+ //gcc can't optimize 64bit math on x86_32
+#if defined(ARCH_X86_64) || (defined(MP_WORDSIZE) && MP_WORDSIZE >= 64)
+ const uint64_t v= 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)=
+ *(uint64_t*)(p + 3*stride)= v;
+ }else if(w==16){
+ const uint64_t v= val*0x0100000001ULL;
+ *(uint64_t*)(p + 0+0*stride)=
+ *(uint64_t*)(p + 8+0*stride)=
+ *(uint64_t*)(p + 0+1*stride)=
+ *(uint64_t*)(p + 8+1*stride)= v;
+ if(h==2) return;
+ *(uint64_t*)(p + 0+2*stride)=
+ *(uint64_t*)(p + 8+2*stride)=
+ *(uint64_t*)(p + 0+3*stride)=
+ *(uint64_t*)(p + 8+3*stride)= v;
+#else
+ *(uint32_t*)(p + 0+0*stride)=
+ *(uint32_t*)(p + 4+0*stride)= val;
+ if(h==1) return;
+ *(uint32_t*)(p + 0+1*stride)=
+ *(uint32_t*)(p + 4+1*stride)= val;
+ if(h==2) return;
+ *(uint32_t*)(p + 0+2*stride)=
+ *(uint32_t*)(p + 4+2*stride)=
+ *(uint32_t*)(p + 0+3*stride)=
+ *(uint32_t*)(p + 4+3*stride)= val;
+ }else if(w==16){
+ *(uint32_t*)(p + 0+0*stride)=
+ *(uint32_t*)(p + 4+0*stride)=
+ *(uint32_t*)(p + 8+0*stride)=
+ *(uint32_t*)(p +12+0*stride)=
+ *(uint32_t*)(p + 0+1*stride)=
+ *(uint32_t*)(p + 4+1*stride)=
+ *(uint32_t*)(p + 8+1*stride)=
+ *(uint32_t*)(p +12+1*stride)= val;
+ if(h==2) return;
+ *(uint32_t*)(p + 0+2*stride)=
+ *(uint32_t*)(p + 4+2*stride)=
+ *(uint32_t*)(p + 8+2*stride)=
+ *(uint32_t*)(p +12+2*stride)=
+ *(uint32_t*)(p + 0+3*stride)=
+ *(uint32_t*)(p + 4+3*stride)=
+ *(uint32_t*)(p + 8+3*stride)=
+ *(uint32_t*)(p +12+3*stride)= val;
+#endif
+ }else
+ assert(0);
+ assert(h==4);
+}
+
+static void fill_caches(H264Context *h, int mb_type, int for_deblock){
+ MpegEncContext * const s = &h->s;
+ const int mb_xy= s->mb_x + s->mb_y*s->mb_stride;
+ int topleft_xy, top_xy, topright_xy, left_xy[2];
+ int topleft_type, top_type, topright_type, left_type[2];
+ int left_block[8];
+ int i;
+
+ //FIXME deblocking could skip the intra and nnz parts.
+ if(for_deblock && (h->slice_num == 1 || h->slice_table[mb_xy] == h->slice_table[mb_xy-s->mb_stride]) && !FRAME_MBAFF)
+ return;
+
+ //wow what a mess, why didn't they simplify the interlacing&intra stuff, i can't imagine that these complex rules are worth it
+
+ top_xy = mb_xy - s->mb_stride;
+ topleft_xy = top_xy - 1;
+ topright_xy= top_xy + 1;
+ left_xy[1] = left_xy[0] = mb_xy-1;
+ left_block[0]= 0;
+ left_block[1]= 1;
+ left_block[2]= 2;
+ left_block[3]= 3;
+ left_block[4]= 7;
+ left_block[5]= 10;
+ left_block[6]= 8;
+ left_block[7]= 11;
+ if(FRAME_MBAFF){
+ const int pair_xy = s->mb_x + (s->mb_y & ~1)*s->mb_stride;
+ const int top_pair_xy = pair_xy - s->mb_stride;
+ const int topleft_pair_xy = top_pair_xy - 1;
+ const int topright_pair_xy = top_pair_xy + 1;
+ const int topleft_mb_frame_flag = !IS_INTERLACED(s->current_picture.mb_type[topleft_pair_xy]);
+ const int top_mb_frame_flag = !IS_INTERLACED(s->current_picture.mb_type[top_pair_xy]);
+ const int topright_mb_frame_flag = !IS_INTERLACED(s->current_picture.mb_type[topright_pair_xy]);
+ const int left_mb_frame_flag = !IS_INTERLACED(s->current_picture.mb_type[pair_xy-1]);
+ const int curr_mb_frame_flag = !IS_INTERLACED(mb_type);
+ const int bottom = (s->mb_y & 1);
+ tprintf("fill_caches: curr_mb_frame_flag:%d, left_mb_frame_flag:%d, topleft_mb_frame_flag:%d, top_mb_frame_flag:%d, topright_mb_frame_flag:%d\n", curr_mb_frame_flag, left_mb_frame_flag, topleft_mb_frame_flag, top_mb_frame_flag, topright_mb_frame_flag);
+ if (bottom
+ ? !curr_mb_frame_flag // bottom macroblock
+ : (!curr_mb_frame_flag && !top_mb_frame_flag) // top macroblock
+ ) {
+ top_xy -= s->mb_stride;
+ }
+ if (bottom
+ ? !curr_mb_frame_flag // bottom macroblock
+ : (!curr_mb_frame_flag && !topleft_mb_frame_flag) // top macroblock
+ ) {
+ topleft_xy -= s->mb_stride;
+ }
+ if (bottom
+ ? !curr_mb_frame_flag // bottom macroblock
+ : (!curr_mb_frame_flag && !topright_mb_frame_flag) // top macroblock
+ ) {
+ topright_xy -= s->mb_stride;
+ }
+ if (left_mb_frame_flag != curr_mb_frame_flag) {
+ left_xy[1] = left_xy[0] = pair_xy - 1;
+ if (curr_mb_frame_flag) {
+ if (bottom) {
+ left_block[0]= 2;
+ left_block[1]= 2;
+ left_block[2]= 3;
+ left_block[3]= 3;
+ left_block[4]= 8;
+ left_block[5]= 11;
+ left_block[6]= 8;
+ left_block[7]= 11;
+ } else {
+ left_block[0]= 0;
+ left_block[1]= 0;
+ left_block[2]= 1;
+ left_block[3]= 1;
+ left_block[4]= 7;
+ left_block[5]= 10;
+ left_block[6]= 7;
+ left_block[7]= 10;
+ }
+ } else {
+ left_xy[1] += s->mb_stride;
+ //left_block[0]= 0;
+ left_block[1]= 2;
+ left_block[2]= 0;
+ left_block[3]= 2;
+ //left_block[4]= 7;
+ left_block[5]= 10;
+ left_block[6]= 7;
+ left_block[7]= 10;
+ }
+ }
+ }
+
+ h->top_mb_xy = top_xy;
+ h->left_mb_xy[0] = left_xy[0];
+ h->left_mb_xy[1] = left_xy[1];
+ if(for_deblock){
+ topleft_type = 0;
+ topright_type = 0;
+ top_type = h->slice_table[top_xy ] < 255 ? s->current_picture.mb_type[top_xy] : 0;
+ left_type[0] = h->slice_table[left_xy[0] ] < 255 ? s->current_picture.mb_type[left_xy[0]] : 0;
+ left_type[1] = h->slice_table[left_xy[1] ] < 255 ? s->current_picture.mb_type[left_xy[1]] : 0;
+
+ if(FRAME_MBAFF && !IS_INTRA(mb_type)){
+ int list;
+ int v = *(uint16_t*)&h->non_zero_count[mb_xy][14];
+ for(i=0; i<16; i++)
+ h->non_zero_count_cache[scan8[i]] = (v>>i)&1;
+ for(list=0; list<1+(h->slice_type==B_TYPE); list++){
+ if(USES_LIST(mb_type,list)){
+ uint32_t *src = (uint32_t*)s->current_picture.motion_val[list][h->mb2b_xy[mb_xy]];
+ uint32_t *dst = (uint32_t*)h->mv_cache[list][scan8[0]];
+ int8_t *ref = &s->current_picture.ref_index[list][h->mb2b8_xy[mb_xy]];
+ for(i=0; i<4; i++, dst+=8, src+=h->b_stride){
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ }
+ *(uint32_t*)&h->ref_cache[list][scan8[ 0]] =
+ *(uint32_t*)&h->ref_cache[list][scan8[ 2]] = pack16to32(ref[0],ref[1])*0x0101;
+ ref += h->b8_stride;
+ *(uint32_t*)&h->ref_cache[list][scan8[ 8]] =
+ *(uint32_t*)&h->ref_cache[list][scan8[10]] = pack16to32(ref[0],ref[1])*0x0101;
+ }else{
+ fill_rectangle(&h-> mv_cache[list][scan8[ 0]], 4, 4, 8, 0, 4);
+ fill_rectangle(&h->ref_cache[list][scan8[ 0]], 4, 4, 8, (uint8_t)LIST_NOT_USED, 1);
+ }
+ }
+ }
+ }else{
+ topleft_type = h->slice_table[topleft_xy ] == h->slice_num ? s->current_picture.mb_type[topleft_xy] : 0;
+ top_type = h->slice_table[top_xy ] == h->slice_num ? s->current_picture.mb_type[top_xy] : 0;
+ topright_type= h->slice_table[topright_xy] == h->slice_num ? s->current_picture.mb_type[topright_xy]: 0;
+ left_type[0] = h->slice_table[left_xy[0] ] == h->slice_num ? s->current_picture.mb_type[left_xy[0]] : 0;
+ left_type[1] = h->slice_table[left_xy[1] ] == h->slice_num ? s->current_picture.mb_type[left_xy[1]] : 0;
+ }
+
+ if(IS_INTRA(mb_type)){
+ h->topleft_samples_available=
+ h->top_samples_available=
+ h->left_samples_available= 0xFFFF;
+ h->topright_samples_available= 0xEEEA;
+
+ if(!IS_INTRA(top_type) && (top_type==0 || h->pps.constrained_intra_pred)){
+ h->topleft_samples_available= 0xB3FF;
+ h->top_samples_available= 0x33FF;
+ h->topright_samples_available= 0x26EA;
+ }
+ for(i=0; i<2; i++){
+ if(!IS_INTRA(left_type[i]) && (left_type[i]==0 || h->pps.constrained_intra_pred)){
+ h->topleft_samples_available&= 0xDF5F;
+ h->left_samples_available&= 0x5F5F;
+ }
+ }
+
+ if(!IS_INTRA(topleft_type) && (topleft_type==0 || h->pps.constrained_intra_pred))
+ h->topleft_samples_available&= 0x7FFF;
+
+ if(!IS_INTRA(topright_type) && (topright_type==0 || h->pps.constrained_intra_pred))
+ h->topright_samples_available&= 0xFBFF;
+
+ if(IS_INTRA4x4(mb_type)){
+ if(IS_INTRA4x4(top_type)){
+ h->intra4x4_pred_mode_cache[4+8*0]= h->intra4x4_pred_mode[top_xy][4];
+ h->intra4x4_pred_mode_cache[5+8*0]= h->intra4x4_pred_mode[top_xy][5];
+ h->intra4x4_pred_mode_cache[6+8*0]= h->intra4x4_pred_mode[top_xy][6];
+ h->intra4x4_pred_mode_cache[7+8*0]= h->intra4x4_pred_mode[top_xy][3];
+ }else{
+ int pred;
+ if(!top_type || (IS_INTER(top_type) && h->pps.constrained_intra_pred))
+ pred= -1;
+ else{
+ pred= 2;
+ }
+ 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]= pred;
+ }
+ for(i=0; i<2; i++){
+ if(IS_INTRA4x4(left_type[i])){
+ h->intra4x4_pred_mode_cache[3+8*1 + 2*8*i]= h->intra4x4_pred_mode[left_xy[i]][left_block[0+2*i]];
+ h->intra4x4_pred_mode_cache[3+8*2 + 2*8*i]= h->intra4x4_pred_mode[left_xy[i]][left_block[1+2*i]];
+ }else{
+ int pred;
+ if(!left_type[i] || (IS_INTER(left_type[i]) && h->pps.constrained_intra_pred))
+ pred= -1;
+ else{
+ pred= 2;
+ }
+ h->intra4x4_pred_mode_cache[3+8*1 + 2*8*i]=
+ h->intra4x4_pred_mode_cache[3+8*2 + 2*8*i]= pred;
+ }
+ }
+ }
+ }
+
+
+/*
+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 (lets hope this is just a typo in the spec)
+ if(top_type){
+ h->non_zero_count_cache[4+8*0]= h->non_zero_count[top_xy][4];
+ h->non_zero_count_cache[5+8*0]= h->non_zero_count[top_xy][5];
+ h->non_zero_count_cache[6+8*0]= h->non_zero_count[top_xy][6];
+ h->non_zero_count_cache[7+8*0]= h->non_zero_count[top_xy][3];
+
+ h->non_zero_count_cache[1+8*0]= h->non_zero_count[top_xy][9];
+ h->non_zero_count_cache[2+8*0]= h->non_zero_count[top_xy][8];
+
+ h->non_zero_count_cache[1+8*3]= h->non_zero_count[top_xy][12];
+ h->non_zero_count_cache[2+8*3]= h->non_zero_count[top_xy][11];
+
+ }else{
+ h->non_zero_count_cache[4+8*0]=
+ h->non_zero_count_cache[5+8*0]=
+ h->non_zero_count_cache[6+8*0]=
+ h->non_zero_count_cache[7+8*0]=
+
+ h->non_zero_count_cache[1+8*0]=
+ h->non_zero_count_cache[2+8*0]=
+
+ h->non_zero_count_cache[1+8*3]=
+ h->non_zero_count_cache[2+8*3]= h->pps.cabac && !IS_INTRA(mb_type) ? 0 : 64;
+
+ }
+
+ for (i=0; i<2; i++) {
+ if(left_type[i]){
+ h->non_zero_count_cache[3+8*1 + 2*8*i]= h->non_zero_count[left_xy[i]][left_block[0+2*i]];
+ h->non_zero_count_cache[3+8*2 + 2*8*i]= h->non_zero_count[left_xy[i]][left_block[1+2*i]];
+ h->non_zero_count_cache[0+8*1 + 8*i]= h->non_zero_count[left_xy[i]][left_block[4+2*i]];
+ h->non_zero_count_cache[0+8*4 + 8*i]= h->non_zero_count[left_xy[i]][left_block[5+2*i]];
+ }else{
+ h->non_zero_count_cache[3+8*1 + 2*8*i]=
+ h->non_zero_count_cache[3+8*2 + 2*8*i]=
+ h->non_zero_count_cache[0+8*1 + 8*i]=
+ h->non_zero_count_cache[0+8*4 + 8*i]= h->pps.cabac && !IS_INTRA(mb_type) ? 0 : 64;
+ }
+ }
+
+ if( h->pps.cabac ) {
+ // top_cbp
+ if(top_type) {
+ h->top_cbp = h->cbp_table[top_xy];
+ } else if(IS_INTRA(mb_type)) {
+ h->top_cbp = 0x1C0;
+ } else {
+ h->top_cbp = 0;
+ }
+ // left_cbp
+ if (left_type[0]) {
+ h->left_cbp = h->cbp_table[left_xy[0]] & 0x1f0;
+ } else if(IS_INTRA(mb_type)) {
+ h->left_cbp = 0x1C0;
+ } else {
+ h->left_cbp = 0;
+ }
+ if (left_type[0]) {
+ h->left_cbp |= ((h->cbp_table[left_xy[0]]>>((left_block[0]&(~1))+1))&0x1) << 1;
+ }
+ if (left_type[1]) {
+ h->left_cbp |= ((h->cbp_table[left_xy[1]]>>((left_block[2]&(~1))+1))&0x1) << 3;
+ }
+ }
+
+#if 1
+ if(IS_INTER(mb_type) || IS_DIRECT(mb_type)){
+ int list;
+ for(list=0; list<1+(h->slice_type==B_TYPE); list++){
+ if(!USES_LIST(mb_type, list) && !IS_DIRECT(mb_type) && !h->deblocking_filter){
+ /*if(!h->mv_cache_clean[list]){
+ memset(h->mv_cache [list], 0, 8*5*2*sizeof(int16_t)); //FIXME clean only input? clean at all?
+ memset(h->ref_cache[list], PART_NOT_AVAILABLE, 8*5*sizeof(int8_t));
+ h->mv_cache_clean[list]= 1;
+ }*/
+ continue;
+ }
+ h->mv_cache_clean[list]= 0;
+
+ if(USES_LIST(top_type, list)){
+ const int b_xy= h->mb2b_xy[top_xy] + 3*h->b_stride;
+ const int b8_xy= h->mb2b8_xy[top_xy] + h->b8_stride;
+ *(uint32_t*)h->mv_cache[list][scan8[0] + 0 - 1*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + 0];
+ *(uint32_t*)h->mv_cache[list][scan8[0] + 1 - 1*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + 1];
+ *(uint32_t*)h->mv_cache[list][scan8[0] + 2 - 1*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + 2];
+ *(uint32_t*)h->mv_cache[list][scan8[0] + 3 - 1*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + 3];
+ h->ref_cache[list][scan8[0] + 0 - 1*8]=
+ h->ref_cache[list][scan8[0] + 1 - 1*8]= s->current_picture.ref_index[list][b8_xy + 0];
+ h->ref_cache[list][scan8[0] + 2 - 1*8]=
+ h->ref_cache[list][scan8[0] + 3 - 1*8]= s->current_picture.ref_index[list][b8_xy + 1];
+ }else{
+ *(uint32_t*)h->mv_cache [list][scan8[0] + 0 - 1*8]=
+ *(uint32_t*)h->mv_cache [list][scan8[0] + 1 - 1*8]=
+ *(uint32_t*)h->mv_cache [list][scan8[0] + 2 - 1*8]=
+ *(uint32_t*)h->mv_cache [list][scan8[0] + 3 - 1*8]= 0;
+ *(uint32_t*)&h->ref_cache[list][scan8[0] + 0 - 1*8]= ((top_type ? LIST_NOT_USED : PART_NOT_AVAILABLE)&0xFF)*0x01010101;
+ }
+
+ //FIXME unify cleanup or sth
+ if(USES_LIST(left_type[0], list)){
+ const int b_xy= h->mb2b_xy[left_xy[0]] + 3;
+ const int b8_xy= h->mb2b8_xy[left_xy[0]] + 1;
+ *(uint32_t*)h->mv_cache[list][scan8[0] - 1 + 0*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + h->b_stride*left_block[0]];
+ *(uint32_t*)h->mv_cache[list][scan8[0] - 1 + 1*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + h->b_stride*left_block[1]];
+ h->ref_cache[list][scan8[0] - 1 + 0*8]= s->current_picture.ref_index[list][b8_xy + h->b8_stride*(left_block[0]>>1)];
+ h->ref_cache[list][scan8[0] - 1 + 1*8]= s->current_picture.ref_index[list][b8_xy + h->b8_stride*(left_block[1]>>1)];
+ }else{
+ *(uint32_t*)h->mv_cache [list][scan8[0] - 1 + 0*8]=
+ *(uint32_t*)h->mv_cache [list][scan8[0] - 1 + 1*8]= 0;
+ h->ref_cache[list][scan8[0] - 1 + 0*8]=
+ h->ref_cache[list][scan8[0] - 1 + 1*8]= left_type[0] ? LIST_NOT_USED : PART_NOT_AVAILABLE;
+ }
+
+ if(USES_LIST(left_type[1], list)){
+ const int b_xy= h->mb2b_xy[left_xy[1]] + 3;
+ const int b8_xy= h->mb2b8_xy[left_xy[1]] + 1;
+ *(uint32_t*)h->mv_cache[list][scan8[0] - 1 + 2*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + h->b_stride*left_block[2]];
+ *(uint32_t*)h->mv_cache[list][scan8[0] - 1 + 3*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + h->b_stride*left_block[3]];
+ h->ref_cache[list][scan8[0] - 1 + 2*8]= s->current_picture.ref_index[list][b8_xy + h->b8_stride*(left_block[2]>>1)];
+ h->ref_cache[list][scan8[0] - 1 + 3*8]= s->current_picture.ref_index[list][b8_xy + h->b8_stride*(left_block[3]>>1)];
+ }else{
+ *(uint32_t*)h->mv_cache [list][scan8[0] - 1 + 2*8]=
+ *(uint32_t*)h->mv_cache [list][scan8[0] - 1 + 3*8]= 0;
+ h->ref_cache[list][scan8[0] - 1 + 2*8]=
+ h->ref_cache[list][scan8[0] - 1 + 3*8]= left_type[0] ? LIST_NOT_USED : PART_NOT_AVAILABLE;
+ assert((!left_type[0]) == (!left_type[1]));
+ }
+
+ if((for_deblock || (IS_DIRECT(mb_type) && !h->direct_spatial_mv_pred)) && !FRAME_MBAFF)
+ continue;
+
+ if(USES_LIST(topleft_type, list)){
+ const int b_xy = h->mb2b_xy[topleft_xy] + 3 + 3*h->b_stride;
+ const int b8_xy= h->mb2b8_xy[topleft_xy] + 1 + h->b8_stride;
+ *(uint32_t*)h->mv_cache[list][scan8[0] - 1 - 1*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy];
+ h->ref_cache[list][scan8[0] - 1 - 1*8]= s->current_picture.ref_index[list][b8_xy];
+ }else{
+ *(uint32_t*)h->mv_cache[list][scan8[0] - 1 - 1*8]= 0;
+ h->ref_cache[list][scan8[0] - 1 - 1*8]= topleft_type ? LIST_NOT_USED : PART_NOT_AVAILABLE;
+ }
+
+ if(USES_LIST(topright_type, list)){
+ const int b_xy= h->mb2b_xy[topright_xy] + 3*h->b_stride;
+ const int b8_xy= h->mb2b8_xy[topright_xy] + h->b8_stride;
+ *(uint32_t*)h->mv_cache[list][scan8[0] + 4 - 1*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy];
+ h->ref_cache[list][scan8[0] + 4 - 1*8]= s->current_picture.ref_index[list][b8_xy];
+ }else{
+ *(uint32_t*)h->mv_cache [list][scan8[0] + 4 - 1*8]= 0;
+ h->ref_cache[list][scan8[0] + 4 - 1*8]= topright_type ? LIST_NOT_USED : PART_NOT_AVAILABLE;
+ }
+
+ if((IS_SKIP(mb_type) || IS_DIRECT(mb_type)) && !FRAME_MBAFF)
+ continue;
+
+ h->ref_cache[list][scan8[5 ]+1] =
+ h->ref_cache[list][scan8[7 ]+1] =
+ h->ref_cache[list][scan8[13]+1] = //FIXME remove past 3 (init somewhere else)
+ h->ref_cache[list][scan8[4 ]] =
+ h->ref_cache[list][scan8[12]] = PART_NOT_AVAILABLE;
+ *(uint32_t*)h->mv_cache [list][scan8[5 ]+1]=
+ *(uint32_t*)h->mv_cache [list][scan8[7 ]+1]=
+ *(uint32_t*)h->mv_cache [list][scan8[13]+1]= //FIXME remove past 3 (init somewhere else)
+ *(uint32_t*)h->mv_cache [list][scan8[4 ]]=
+ *(uint32_t*)h->mv_cache [list][scan8[12]]= 0;
+
+ if( h->pps.cabac ) {
+ /* XXX beurk, Load mvd */
+ if(USES_LIST(top_type, list)){
+ const int b_xy= h->mb2b_xy[top_xy] + 3*h->b_stride;
+ *(uint32_t*)h->mvd_cache[list][scan8[0] + 0 - 1*8]= *(uint32_t*)h->mvd_table[list][b_xy + 0];
+ *(uint32_t*)h->mvd_cache[list][scan8[0] + 1 - 1*8]= *(uint32_t*)h->mvd_table[list][b_xy + 1];
+ *(uint32_t*)h->mvd_cache[list][scan8[0] + 2 - 1*8]= *(uint32_t*)h->mvd_table[list][b_xy + 2];
+ *(uint32_t*)h->mvd_cache[list][scan8[0] + 3 - 1*8]= *(uint32_t*)h->mvd_table[list][b_xy + 3];
+ }else{
+ *(uint32_t*)h->mvd_cache [list][scan8[0] + 0 - 1*8]=
+ *(uint32_t*)h->mvd_cache [list][scan8[0] + 1 - 1*8]=
+ *(uint32_t*)h->mvd_cache [list][scan8[0] + 2 - 1*8]=
+ *(uint32_t*)h->mvd_cache [list][scan8[0] + 3 - 1*8]= 0;
+ }
+ if(USES_LIST(left_type[0], list)){
+ const int b_xy= h->mb2b_xy[left_xy[0]] + 3;
+ *(uint32_t*)h->mvd_cache[list][scan8[0] - 1 + 0*8]= *(uint32_t*)h->mvd_table[list][b_xy + h->b_stride*left_block[0]];
+ *(uint32_t*)h->mvd_cache[list][scan8[0] - 1 + 1*8]= *(uint32_t*)h->mvd_table[list][b_xy + h->b_stride*left_block[1]];
+ }else{
+ *(uint32_t*)h->mvd_cache [list][scan8[0] - 1 + 0*8]=
+ *(uint32_t*)h->mvd_cache [list][scan8[0] - 1 + 1*8]= 0;
+ }
+ if(USES_LIST(left_type[1], list)){
+ const int b_xy= h->mb2b_xy[left_xy[1]] + 3;
+ *(uint32_t*)h->mvd_cache[list][scan8[0] - 1 + 2*8]= *(uint32_t*)h->mvd_table[list][b_xy + h->b_stride*left_block[2]];
+ *(uint32_t*)h->mvd_cache[list][scan8[0] - 1 + 3*8]= *(uint32_t*)h->mvd_table[list][b_xy + h->b_stride*left_block[3]];
+ }else{
+ *(uint32_t*)h->mvd_cache [list][scan8[0] - 1 + 2*8]=
+ *(uint32_t*)h->mvd_cache [list][scan8[0] - 1 + 3*8]= 0;
+ }
+ *(uint32_t*)h->mvd_cache [list][scan8[5 ]+1]=
+ *(uint32_t*)h->mvd_cache [list][scan8[7 ]+1]=
+ *(uint32_t*)h->mvd_cache [list][scan8[13]+1]= //FIXME remove past 3 (init somewhere else)
+ *(uint32_t*)h->mvd_cache [list][scan8[4 ]]=
+ *(uint32_t*)h->mvd_cache [list][scan8[12]]= 0;
+
+ if(h->slice_type == B_TYPE){
+ fill_rectangle(&h->direct_cache[scan8[0]], 4, 4, 8, 0, 1);
+
+ if(IS_DIRECT(top_type)){
+ *(uint32_t*)&h->direct_cache[scan8[0] - 1*8]= 0x01010101;
+ }else if(IS_8X8(top_type)){
+ int b8_xy = h->mb2b8_xy[top_xy] + h->b8_stride;
+ h->direct_cache[scan8[0] + 0 - 1*8]= h->direct_table[b8_xy];
+ h->direct_cache[scan8[0] + 2 - 1*8]= h->direct_table[b8_xy + 1];
+ }else{
+ *(uint32_t*)&h->direct_cache[scan8[0] - 1*8]= 0;
+ }
+
+ if(IS_DIRECT(left_type[0]))
+ h->direct_cache[scan8[0] - 1 + 0*8]= 1;
+ else if(IS_8X8(left_type[0]))
+ h->direct_cache[scan8[0] - 1 + 0*8]= h->direct_table[h->mb2b8_xy[left_xy[0]] + 1 + h->b8_stride*(left_block[0]>>1)];
+ else
+ h->direct_cache[scan8[0] - 1 + 0*8]= 0;
+
+ if(IS_DIRECT(left_type[1]))
+ h->direct_cache[scan8[0] - 1 + 2*8]= 1;
+ else if(IS_8X8(left_type[1]))
+ h->direct_cache[scan8[0] - 1 + 2*8]= h->direct_table[h->mb2b8_xy[left_xy[1]] + 1 + h->b8_stride*(left_block[2]>>1)];
+ else
+ h->direct_cache[scan8[0] - 1 + 2*8]= 0;
+ }
+ }
+
+ if(FRAME_MBAFF){
+#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[0])\
+ MAP_F2F(scan8[0] - 1 + 1*8, left_type[0])\
+ MAP_F2F(scan8[0] - 1 + 2*8, left_type[1])\
+ MAP_F2F(scan8[0] - 1 + 3*8, left_type[1])
+ if(MB_FIELD){
+#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] /= 2;\
+ }
+ MAP_MVS
+#undef MAP_F2F
+ }else{
+#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
+ }
+ }
+ }
+ }
+#endif
+
+ h->neighbor_transform_size= !!IS_8x8DCT(top_type) + !!IS_8x8DCT(left_type[0]);
+}
+
+static inline void write_back_intra_pred_mode(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ const int mb_xy= s->mb_x + s->mb_y*s->mb_stride;
+
+ h->intra4x4_pred_mode[mb_xy][0]= h->intra4x4_pred_mode_cache[7+8*1];
+ h->intra4x4_pred_mode[mb_xy][1]= h->intra4x4_pred_mode_cache[7+8*2];
+ h->intra4x4_pred_mode[mb_xy][2]= h->intra4x4_pred_mode_cache[7+8*3];
+ h->intra4x4_pred_mode[mb_xy][3]= h->intra4x4_pred_mode_cache[7+8*4];
+ h->intra4x4_pred_mode[mb_xy][4]= h->intra4x4_pred_mode_cache[4+8*4];
+ h->intra4x4_pred_mode[mb_xy][5]= h->intra4x4_pred_mode_cache[5+8*4];
+ h->intra4x4_pred_mode[mb_xy][6]= h->intra4x4_pred_mode_cache[6+8*4];
+}
+
+/**
+ * checks if the top & left blocks are available if needed & changes the dc mode so it only uses the available blocks.
+ */
+static inline int check_intra4x4_pred_mode(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ 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->s.avctx, AV_LOG_ERROR, "top block unavailable for requested intra4x4 mode %d at %d %d\n", status, s->mb_x, s->mb_y);
+ return -1;
+ } else if(status){
+ h->intra4x4_pred_mode_cache[scan8[0] + i]= status;
+ }
+ }
+ }
+
+ if(!(h->left_samples_available&0x8000)){
+ for(i=0; i<4; i++){
+ int status= left[ h->intra4x4_pred_mode_cache[scan8[0] + 8*i] ];
+ if(status<0){
+ av_log(h->s.avctx, AV_LOG_ERROR, "left block unavailable for requested intra4x4 mode %d at %d %d\n", status, s->mb_x, s->mb_y);
+ return -1;
+ } else if(status){
+ h->intra4x4_pred_mode_cache[scan8[0] + 8*i]= status;
+ }
+ }
+ }
+
+ return 0;
+} //FIXME cleanup like next
+
+/**
+ * checks if the top & left blocks are available if needed & changes the dc mode so it only uses the available blocks.
+ */
+static inline int check_intra_pred_mode(H264Context *h, int mode){
+ MpegEncContext * const s = &h->s;
+ 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 < 0 || mode > 6) {
+ av_log(h->s.avctx, AV_LOG_ERROR, "out of range intra chroma pred mode at %d %d\n", s->mb_x, s->mb_y);
+ return -1;
+ }
+
+ if(!(h->top_samples_available&0x8000)){
+ mode= top[ mode ];
+ if(mode<0){
+ av_log(h->s.avctx, AV_LOG_ERROR, "top block unavailable for requested intra mode at %d %d\n", s->mb_x, s->mb_y);
+ return -1;
+ }
+ }
+
+ if(!(h->left_samples_available&0x8000)){
+ mode= left[ mode ];
+ if(mode<0){
+ av_log(h->s.avctx, AV_LOG_ERROR, "left block unavailable for requested intra mode at %d %d\n", s->mb_x, s->mb_y);
+ return -1;
+ }
+ }
+
+ return mode;
+}
+
+/**
+ * gets the predicted intra4x4 prediction mode.
+ */
+static 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("mode:%d %d min:%d\n", left ,top, min);
+
+ if(min<0) return DC_PRED;
+ else return min;
+}
+
+static inline void write_back_non_zero_count(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ const int mb_xy= s->mb_x + s->mb_y*s->mb_stride;
+
+ h->non_zero_count[mb_xy][0]= h->non_zero_count_cache[7+8*1];
+ h->non_zero_count[mb_xy][1]= h->non_zero_count_cache[7+8*2];
+ h->non_zero_count[mb_xy][2]= h->non_zero_count_cache[7+8*3];
+ h->non_zero_count[mb_xy][3]= h->non_zero_count_cache[7+8*4];
+ h->non_zero_count[mb_xy][4]= h->non_zero_count_cache[4+8*4];
+ h->non_zero_count[mb_xy][5]= h->non_zero_count_cache[5+8*4];
+ h->non_zero_count[mb_xy][6]= h->non_zero_count_cache[6+8*4];
+
+ h->non_zero_count[mb_xy][9]= h->non_zero_count_cache[1+8*2];
+ h->non_zero_count[mb_xy][8]= h->non_zero_count_cache[2+8*2];
+ h->non_zero_count[mb_xy][7]= h->non_zero_count_cache[2+8*1];
+
+ h->non_zero_count[mb_xy][12]=h->non_zero_count_cache[1+8*5];
+ h->non_zero_count[mb_xy][11]=h->non_zero_count_cache[2+8*5];
+ h->non_zero_count[mb_xy][10]=h->non_zero_count_cache[2+8*4];
+
+ if(FRAME_MBAFF){
+ // store all luma nnzs, for deblocking
+ int v = 0, i;
+ for(i=0; i<16; i++)
+ v += (!!h->non_zero_count_cache[scan8[i]]) << i;
+ *(uint16_t*)&h->non_zero_count[mb_xy][14] = v;
+ }
+}
+
+/**
+ * gets the predicted number of non zero coefficients.
+ * @param n block index
+ */
+static inline int pred_non_zero_count(H264Context *h, int n){
+ const int index8= scan8[n];
+ const int left= h->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("pred_nnz L%X T%X n%d s%d P%X\n", left, top, n, scan8[n], i&31);
+
+ return i&31;
+}
+
+static 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){
+ MpegEncContext *s = &h->s;
+ const uint32_t *mb_types = s->current_picture_ptr->mb_type;
+ const int16_t *mv;
+ *(uint32_t*)h->mv_cache[list][scan8[0]-2] = 0;
+ *C = h->mv_cache[list][scan8[0]-2];
+
+ if(!MB_FIELD
+ && (s->mb_y&1) && i < scan8[0]+8 && topright_ref != PART_NOT_AVAILABLE){
+ int topright_xy = s->mb_x + (s->mb_y-1)*s->mb_stride + (i == scan8[0]+3);
+ if(IS_INTERLACED(mb_types[topright_xy])){
+#define SET_DIAG_MV(MV_OP, REF_OP, X4, Y4)\
+ const int x4 = X4, y4 = Y4;\
+ const int mb_type = mb_types[(x4>>2)+(y4>>2)*s->mb_stride];\
+ if(!USES_LIST(mb_type,list) && !IS_8X8(mb_type))\
+ return LIST_NOT_USED;\
+ mv = s->current_picture_ptr->motion_val[list][x4 + 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 s->current_picture_ptr->ref_index[list][(x4>>1) + (y4>>1)*h->b8_stride] REF_OP;
+
+ SET_DIAG_MV(*2, >>1, s->mb_x*4+(i&7)-4+part_width, s->mb_y*4-1);
+ }
+ }
+ if(topright_ref == PART_NOT_AVAILABLE
+ && ((s->mb_y&1) || i >= scan8[0]+8) && (i&7)==4
+ && h->ref_cache[list][scan8[0]-1] != PART_NOT_AVAILABLE){
+ if(!MB_FIELD
+ && IS_INTERLACED(mb_types[h->left_mb_xy[0]])){
+ SET_DIAG_MV(*2, >>1, s->mb_x*4-1, (s->mb_y|1)*4+(s->mb_y&1)*2+(i>>4)-1);
+ }
+ if(MB_FIELD
+ && !IS_INTERLACED(mb_types[h->left_mb_xy[0]])
+ && i >= scan8[0]+8){
+ // leftshift will turn LIST_NOT_USED into PART_NOT_AVAILABLE, but that's ok.
+ SET_DIAG_MV(>>1, <<1, s->mb_x*4-1, (s->mb_y&~1)*4 - 1 + ((i-scan8[0])>>3)*2);
+ }
+ }
+#undef SET_DIAG_MV
+ }
+
+ if(topright_ref != PART_NOT_AVAILABLE){
+ *C= h->mv_cache[list][ i - 8 + part_width ];
+ return topright_ref;
+ }else{
+ tprintf("topright MV not available\n");
+
+ *C= h->mv_cache[list][ i - 8 - 1 ];
+ return h->ref_cache[list][ i - 8 - 1 ];
+ }
+}
+
+/**
+ * gets 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 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;
+
+ assert(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("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("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->s.mb_x, h->s.mb_y, n, list);
+}
+
+/**
+ * gets 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 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("pred_16x8: (%2d %2d %2d) at %2d %2d %d list %d\n", top_ref, B[0], B[1], h->s.mb_x, h->s.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("pred_16x8: (%2d %2d %2d) at %2d %2d %d list %d\n", left_ref, A[0], A[1], h->s.mb_x, h->s.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);
+}
+
+/**
+ * gets 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 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("pred_8x16: (%2d %2d %2d) at %2d %2d %d list %d\n", left_ref, A[0], A[1], h->s.mb_x, h->s.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("pred_8x16: (%2d %2d %2d) at %2d %2d %d list %d\n", diagonal_ref, C[0], C[1], h->s.mb_x, h->s.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);
+}
+
+static inline void pred_pskip_motion(H264Context * const h, int * const mx, int * const my){
+ const int top_ref = h->ref_cache[0][ scan8[0] - 8 ];
+ const int left_ref= h->ref_cache[0][ scan8[0] - 1 ];
+
+ tprintf("pred_pskip: (%d) (%d) at %2d %2d\n", top_ref, left_ref, h->s.mb_x, h->s.mb_y);
+
+ if(top_ref == PART_NOT_AVAILABLE || left_ref == PART_NOT_AVAILABLE
+ || (top_ref == 0 && *(uint32_t*)h->mv_cache[0][ scan8[0] - 8 ] == 0)
+ || (left_ref == 0 && *(uint32_t*)h->mv_cache[0][ scan8[0] - 1 ] == 0)){
+
+ *mx = *my = 0;
+ return;
+ }
+
+ pred_motion(h, 0, 4, 0, 0, mx, my);
+
+ return;
+}
+
+static inline void direct_dist_scale_factor(H264Context * const h){
+ const int poc = h->s.current_picture_ptr->poc;
+ const int poc1 = h->ref_list[1][0].poc;
+ int i;
+ for(i=0; i<h->ref_count[0]; i++){
+ int poc0 = h->ref_list[0][i].poc;
+ int td = clip(poc1 - poc0, -128, 127);
+ if(td == 0 /* FIXME || pic0 is a long-term ref */){
+ h->dist_scale_factor[i] = 256;
+ }else{
+ int tb = clip(poc - poc0, -128, 127);
+ int tx = (16384 + (FFABS(td) >> 1)) / td;
+ h->dist_scale_factor[i] = clip((tb*tx + 32) >> 6, -1024, 1023);
+ }
+ }
+ if(FRAME_MBAFF){
+ for(i=0; i<h->ref_count[0]; i++){
+ h->dist_scale_factor_field[2*i] =
+ h->dist_scale_factor_field[2*i+1] = h->dist_scale_factor[i];
+ }
+ }
+}
+static inline void direct_ref_list_init(H264Context * const h){
+ MpegEncContext * const s = &h->s;
+ Picture * const ref1 = &h->ref_list[1][0];
+ Picture * const cur = s->current_picture_ptr;
+ int list, i, j;
+ if(cur->pict_type == I_TYPE)
+ cur->ref_count[0] = 0;
+ if(cur->pict_type != B_TYPE)
+ cur->ref_count[1] = 0;
+ for(list=0; list<2; list++){
+ cur->ref_count[list] = h->ref_count[list];
+ for(j=0; j<h->ref_count[list]; j++)
+ cur->ref_poc[list][j] = h->ref_list[list][j].poc;
+ }
+ if(cur->pict_type != B_TYPE || h->direct_spatial_mv_pred)
+ return;
+ for(list=0; list<2; list++){
+ for(i=0; i<ref1->ref_count[list]; i++){
+ const int poc = ref1->ref_poc[list][i];
+ h->map_col_to_list0[list][i] = 0; /* bogus; fills in for missing frames */
+ for(j=0; j<h->ref_count[list]; j++)
+ if(h->ref_list[list][j].poc == poc){
+ h->map_col_to_list0[list][i] = j;
+ break;
+ }
+ }
+ }
+ if(FRAME_MBAFF){
+ for(list=0; list<2; list++){
+ for(i=0; i<ref1->ref_count[list]; i++){
+ j = h->map_col_to_list0[list][i];
+ h->map_col_to_list0_field[list][2*i] = 2*j;
+ h->map_col_to_list0_field[list][2*i+1] = 2*j+1;
+ }
+ }
+ }
+}
+
+static inline void pred_direct_motion(H264Context * const h, int *mb_type){
+ MpegEncContext * const s = &h->s;
+ const int mb_xy = s->mb_x + s->mb_y*s->mb_stride;
+ const int b8_xy = 2*s->mb_x + 2*s->mb_y*h->b8_stride;
+ const int b4_xy = 4*s->mb_x + 4*s->mb_y*h->b_stride;
+ const int mb_type_col = h->ref_list[1][0].mb_type[mb_xy];
+ const int16_t (*l1mv0)[2] = (const int16_t (*)[2]) &h->ref_list[1][0].motion_val[0][b4_xy];
+ const int16_t (*l1mv1)[2] = (const int16_t (*)[2]) &h->ref_list[1][0].motion_val[1][b4_xy];
+ const int8_t *l1ref0 = &h->ref_list[1][0].ref_index[0][b8_xy];
+ const int8_t *l1ref1 = &h->ref_list[1][0].ref_index[1][b8_xy];
+ const int is_b8x8 = IS_8X8(*mb_type);
+ int sub_mb_type;
+ int i8, i4;
+
+#define MB_TYPE_16x16_OR_INTRA (MB_TYPE_16x16|MB_TYPE_INTRA4x4|MB_TYPE_INTRA16x16|MB_TYPE_INTRA_PCM)
+ if(IS_8X8(mb_type_col) && !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;
+ }else if(!is_b8x8 && (mb_type_col & MB_TYPE_16x16_OR_INTRA)){
+ sub_mb_type = MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_8x8 */
+ *mb_type = MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_16x16 */
+ }else{
+ sub_mb_type = MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_8x8 */
+ *mb_type = MB_TYPE_8x8|MB_TYPE_L0L1;
+ }
+ if(!is_b8x8)
+ *mb_type |= MB_TYPE_DIRECT2;
+ if(MB_FIELD)
+ *mb_type |= MB_TYPE_INTERLACED;
+
+ tprintf("mb_type = %08x, sub_mb_type = %08x, is_b8x8 = %d, mb_type_col = %08x\n", *mb_type, sub_mb_type, is_b8x8, mb_type_col);
+
+ if(h->direct_spatial_mv_pred){
+ int ref[2];
+ int mv[2][2];
+ int list;
+
+ /* FIXME interlacing + spatial direct uses wrong colocated block positions */
+
+ /* ref = min(neighbors) */
+ for(list=0; list<2; list++){
+ int refa = h->ref_cache[list][scan8[0] - 1];
+ int refb = h->ref_cache[list][scan8[0] - 8];
+ int refc = h->ref_cache[list][scan8[0] - 8 + 4];
+ if(refc == -2)
+ refc = h->ref_cache[list][scan8[0] - 8 - 1];
+ ref[list] = refa;
+ if(ref[list] < 0 || (refb < ref[list] && refb >= 0))
+ ref[list] = refb;
+ if(ref[list] < 0 || (refc < ref[list] && refc >= 0))
+ ref[list] = refc;
+ if(ref[list] < 0)
+ ref[list] = -1;
+ }
+
+ if(ref[0] < 0 && ref[1] < 0){
+ ref[0] = ref[1] = 0;
+ mv[0][0] = mv[0][1] =
+ mv[1][0] = mv[1][1] = 0;
+ }else{
+ for(list=0; list<2; list++){
+ if(ref[list] >= 0)
+ pred_motion(h, 0, 4, list, ref[list], &mv[list][0], &mv[list][1]);
+ else
+ mv[list][0] = mv[list][1] = 0;
+ }
+ }
+
+ if(ref[1] < 0){
+ *mb_type &= ~MB_TYPE_P0L1;
+ sub_mb_type &= ~MB_TYPE_P0L1;
+ }else if(ref[0] < 0){
+ *mb_type &= ~MB_TYPE_P0L0;
+ sub_mb_type &= ~MB_TYPE_P0L0;
+ }
+
+ if(IS_16X16(*mb_type)){
+ 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)
+ && ( (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>33 || !h->x264_build)))){
+ if(ref[0] > 0)
+ fill_rectangle(&h->mv_cache[0][scan8[0]], 4, 4, 8, pack16to32(mv[0][0],mv[0][1]), 4);
+ else
+ fill_rectangle(&h->mv_cache[0][scan8[0]], 4, 4, 8, 0, 4);
+ if(ref[1] > 0)
+ fill_rectangle(&h->mv_cache[1][scan8[0]], 4, 4, 8, pack16to32(mv[1][0],mv[1][1]), 4);
+ else
+ fill_rectangle(&h->mv_cache[1][scan8[0]], 4, 4, 8, 0, 4);
+ }else{
+ fill_rectangle(&h->mv_cache[0][scan8[0]], 4, 4, 8, pack16to32(mv[0][0],mv[0][1]), 4);
+ fill_rectangle(&h->mv_cache[1][scan8[0]], 4, 4, 8, pack16to32(mv[1][0],mv[1][1]), 4);
+ }
+ }else{
+ 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, pack16to32(mv[0][0],mv[0][1]), 4);
+ fill_rectangle(&h->mv_cache[1][scan8[i8*4]], 2, 2, 8, pack16to32(mv[1][0],mv[1][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);
+
+ /* col_zero_flag */
+ if(!IS_INTRA(mb_type_col) && ( l1ref0[x8 + y8*h->b8_stride] == 0
+ || (l1ref0[x8 + y8*h->b8_stride] < 0 && l1ref1[x8 + y8*h->b8_stride] == 0
+ && (h->x264_build>33 || !h->x264_build)))){
+ const int16_t (*l1mv)[2]= l1ref0[x8 + y8*h->b8_stride] == 0 ? l1mv0 : l1mv1;
+ if(IS_SUB_8X8(sub_mb_type)){
+ const int16_t *mv_col = l1mv[x8*3 + y8*3*h->b_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);
+ }
+ }else
+ for(i4=0; i4<4; i4++){
+ const int16_t *mv_col = l1mv[x8*2 + (i4&1) + (y8*2 + (i4>>1))*h->b_stride];
+ if(FFABS(mv_col[0]) <= 1 && FFABS(mv_col[1]) <= 1){
+ if(ref[0] == 0)
+ *(uint32_t*)h->mv_cache[0][scan8[i8*4+i4]] = 0;
+ if(ref[1] == 0)
+ *(uint32_t*)h->mv_cache[1][scan8[i8*4+i4]] = 0;
+ }
+ }
+ }
+ }
+ }
+ }else{ /* direct temporal mv pred */
+ 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;
+
+ if(FRAME_MBAFF){
+ if(IS_INTERLACED(*mb_type)){
+ map_col_to_list0[0] = h->map_col_to_list0_field[0];
+ map_col_to_list0[1] = h->map_col_to_list0_field[1];
+ dist_scale_factor = h->dist_scale_factor_field;
+ }
+ if(IS_INTERLACED(*mb_type) != IS_INTERLACED(mb_type_col)){
+ /* FIXME assumes direct_8x8_inference == 1 */
+ const int pair_xy = s->mb_x + (s->mb_y&~1)*s->mb_stride;
+ int mb_types_col[2];
+ int y_shift;
+
+ *mb_type = MB_TYPE_8x8|MB_TYPE_L0L1
+ | (is_b8x8 ? 0 : MB_TYPE_DIRECT2)
+ | (*mb_type & MB_TYPE_INTERLACED);
+ sub_mb_type = MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2|MB_TYPE_16x16;
+
+ if(IS_INTERLACED(*mb_type)){
+ /* frame to field scaling */
+ mb_types_col[0] = h->ref_list[1][0].mb_type[pair_xy];
+ mb_types_col[1] = h->ref_list[1][0].mb_type[pair_xy+s->mb_stride];
+ if(s->mb_y&1){
+ l1ref0 -= 2*h->b8_stride;
+ l1ref1 -= 2*h->b8_stride;
+ l1mv0 -= 4*h->b_stride;
+ l1mv1 -= 4*h->b_stride;
+ }
+ y_shift = 0;
+
+ if( (mb_types_col[0] & MB_TYPE_16x16_OR_INTRA)
+ && (mb_types_col[1] & MB_TYPE_16x16_OR_INTRA)
+ && !is_b8x8)
+ *mb_type |= MB_TYPE_16x8;
+ else
+ *mb_type |= MB_TYPE_8x8;
+ }else{
+ /* field to frame scaling */
+ /* col_mb_y = (mb_y&~1) + (topAbsDiffPOC < bottomAbsDiffPOC ? 0 : 1)
+ * but in MBAFF, top and bottom POC are equal */
+ int dy = (s->mb_y&1) ? 1 : 2;
+ mb_types_col[0] =
+ mb_types_col[1] = h->ref_list[1][0].mb_type[pair_xy+s->mb_stride];
+ l1ref0 += dy*h->b8_stride;
+ l1ref1 += dy*h->b8_stride;
+ l1mv0 += 2*dy*h->b_stride;
+ l1mv1 += 2*dy*h->b_stride;
+ y_shift = 2;
+
+ if((mb_types_col[0] & (MB_TYPE_16x16_OR_INTRA|MB_TYPE_16x8))
+ && !is_b8x8)
+ *mb_type |= MB_TYPE_16x16;
+ else
+ *mb_type |= MB_TYPE_8x8;
+ }
+
+ 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_types_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*2>>y_shift)*h->b8_stride];
+ if(ref0 >= 0)
+ ref0 = map_col_to_list0[0][ref0*2>>y_shift];
+ else{
+ ref0 = map_col_to_list0[1][l1ref1[x8 + (y8*2>>y_shift)*h->b8_stride]*2>>y_shift];
+ 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*6>>y_shift)*h->b_stride];
+ int my_col = (mv_col[1]<<y_shift)/2;
+ int mx = (scale * mv_col[0] + 128) >> 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)){
+ fill_rectangle(&h->ref_cache[1][scan8[0]], 4, 4, 8, 0, 1);
+ if(IS_INTRA(mb_type_col)){
+ fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, 0, 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);
+ }else{
+ const int ref0 = l1ref0[0] >= 0 ? map_col_to_list0[0][l1ref0[0]]
+ : map_col_to_list0[1][l1ref1[0]];
+ 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;
+ fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref0, 1);
+ fill_rectangle(&h-> mv_cache[0][scan8[0]], 4, 4, 8, pack16to32(mv_l0[0],mv_l0[1]), 4);
+ fill_rectangle(&h-> mv_cache[1][scan8[0]], 4, 4, 8, pack16to32(mv_l0[0]-mv_col[0],mv_l0[1]-mv_col[1]), 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)){
+ 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*h->b8_stride];
+ if(ref0 >= 0)
+ ref0 = map_col_to_list0[0][ref0];
+ else{
+ ref0 = map_col_to_list0[1][l1ref1[x8 + y8*h->b8_stride]];
+ 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*h->b_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))*h->b_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;
+ *(uint32_t*)h->mv_cache[1][scan8[i8*4+i4]] =
+ pack16to32(mv_l0[0]-mv_col[0],mv_l0[1]-mv_col[1]);
+ }
+ }
+ }
+ }
+}
+
+static inline void write_back_motion(H264Context *h, int mb_type){
+ MpegEncContext * const s = &h->s;
+ const int b_xy = 4*s->mb_x + 4*s->mb_y*h->b_stride;
+ const int b8_xy= 2*s->mb_x + 2*s->mb_y*h->b8_stride;
+ int list;
+
+ if(!USES_LIST(mb_type, 0))
+ fill_rectangle(&s->current_picture.ref_index[0][b8_xy], 2, 2, h->b8_stride, (uint8_t)LIST_NOT_USED, 1);
+
+ for(list=0; list<2; list++){
+ int y;
+ if(!USES_LIST(mb_type, list))
+ continue;
+
+ for(y=0; y<4; y++){
+ *(uint64_t*)s->current_picture.motion_val[list][b_xy + 0 + y*h->b_stride]= *(uint64_t*)h->mv_cache[list][scan8[0]+0 + 8*y];
+ *(uint64_t*)s->current_picture.motion_val[list][b_xy + 2 + y*h->b_stride]= *(uint64_t*)h->mv_cache[list][scan8[0]+2 + 8*y];
+ }
+ if( h->pps.cabac ) {
+ if(IS_SKIP(mb_type))
+ fill_rectangle(h->mvd_table[list][b_xy], 4, 4, h->b_stride, 0, 4);
+ else
+ for(y=0; y<4; y++){
+ *(uint64_t*)h->mvd_table[list][b_xy + 0 + y*h->b_stride]= *(uint64_t*)h->mvd_cache[list][scan8[0]+0 + 8*y];
+ *(uint64_t*)h->mvd_table[list][b_xy + 2 + y*h->b_stride]= *(uint64_t*)h->mvd_cache[list][scan8[0]+2 + 8*y];
+ }
+ }
+
+ {
+ int8_t *ref_index = &s->current_picture.ref_index[list][b8_xy];
+ ref_index[0+0*h->b8_stride]= h->ref_cache[list][scan8[0]];
+ ref_index[1+0*h->b8_stride]= h->ref_cache[list][scan8[4]];
+ ref_index[0+1*h->b8_stride]= h->ref_cache[list][scan8[8]];
+ ref_index[1+1*h->b8_stride]= h->ref_cache[list][scan8[12]];
+ }
+ }
+
+ if(h->slice_type == B_TYPE && h->pps.cabac){
+ if(IS_8X8(mb_type)){
+ uint8_t *direct_table = &h->direct_table[b8_xy];
+ direct_table[1+0*h->b8_stride] = IS_DIRECT(h->sub_mb_type[1]) ? 1 : 0;
+ direct_table[0+1*h->b8_stride] = IS_DIRECT(h->sub_mb_type[2]) ? 1 : 0;
+ direct_table[1+1*h->b8_stride] = IS_DIRECT(h->sub_mb_type[3]) ? 1 : 0;
+ }
+ }
+}
+
+/**
+ * Decodes 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?
+ * @returns decoded bytes, might be src+1 if no escapes
+ */
+static uint8_t *decode_nal(H264Context *h, uint8_t *src, int *dst_length, int *consumed, int length){
+ int i, si, di;
+ uint8_t *dst;
+
+// src[0]&0x80; //forbidden bit
+ h->nal_ref_idc= src[0]>>5;
+ h->nal_unit_type= src[0]&0x1F;
+
+ src++; length--;
+#if 0
+ for(i=0; i<length; i++)
+ printf("%2X ", src[i]);
+#endif
+ for(i=0; i+1<length; i+=2){
+ if(src[i]) continue;
+ if(i>0 && src[i-1]==0) i--;
+ 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(i>=length-1){ //no escaped 0
+ *dst_length= length;
+ *consumed= length+1; //+1 for the header
+ return src;
+ }
+
+ h->rbsp_buffer= av_fast_realloc(h->rbsp_buffer, &h->rbsp_buffer_size, length);
+ dst= h->rbsp_buffer;
+
+//printf("decoding esc\n");
+ si=di=0;
+ while(si<length){
+ //remove escapes (very rare 1:2^22)
+ if(si+2<length && src[si]==0 && src[si+1]==0 && src[si+2]<=3){
+ if(src[si+2]==3){ //escape
+ dst[di++]= 0;
+ dst[di++]= 0;
+ si+=3;
+ continue;
+ }else //next start code
+ break;
+ }
+
+ dst[di++]= src[si++];
+ }
+
+ *dst_length= di;
+ *consumed= si + 1;//+1 for the header
+//FIXME store exact number of bits in the getbitcontext (its needed for decoding)
+ return dst;
+}
+
+#if 0
+/**
+ * @param src the data which should be escaped
+ * @param dst the target buffer, dst+1 == src is allowed as a special case
+ * @param length the length of the src data
+ * @param dst_length the length of the dst array
+ * @returns length of escaped data in bytes or -1 if an error occured
+ */
+static int encode_nal(H264Context *h, uint8_t *dst, uint8_t *src, int length, int dst_length){
+ int i, escape_count, si, di;
+ uint8_t *temp;
+
+ assert(length>=0);
+ assert(dst_length>0);
+
+ dst[0]= (h->nal_ref_idc<<5) + h->nal_unit_type;
+
+ if(length==0) return 1;
+
+ escape_count= 0;
+ for(i=0; i<length; i+=2){
+ if(src[i]) continue;
+ if(i>0 && src[i-1]==0)
+ i--;
+ if(i+2<length && src[i+1]==0 && src[i+2]<=3){
+ escape_count++;
+ i+=2;
+ }
+ }
+
+ if(escape_count==0){
+ if(dst+1 != src)
+ memcpy(dst+1, src, length);
+ return length + 1;
+ }
+
+ if(length + escape_count + 1> dst_length)
+ return -1;
+
+ //this should be damn rare (hopefully)
+
+ h->rbsp_buffer= av_fast_realloc(h->rbsp_buffer, &h->rbsp_buffer_size, length + escape_count);
+ temp= h->rbsp_buffer;
+//printf("encoding esc\n");
+
+ si= 0;
+ di= 0;
+ while(si < length){
+ if(si+2<length && src[si]==0 && src[si+1]==0 && src[si+2]<=3){
+ temp[di++]= 0; si++;
+ temp[di++]= 0; si++;
+ temp[di++]= 3;
+ temp[di++]= src[si++];
+ }
+ else
+ temp[di++]= src[si++];
+ }
+ memcpy(dst+1, temp, length+escape_count);
+
+ assert(di == length+escape_count);
+
+ return di + 1;
+}
+
+/**
+ * write 1,10,100,1000,... for alignment, yes its exactly inverse to mpeg4
+ */
+static void encode_rbsp_trailing(PutBitContext *pb){
+ int length;
+ put_bits(pb, 1, 1);
+ length= (-put_bits_count(pb))&7;
+ if(length) put_bits(pb, length, 0);
+}
+#endif
+
+/**
+ * identifies the exact end of the bitstream
+ * @return the length of the trailing, or 0 if damaged
+ */
+static int decode_rbsp_trailing(uint8_t *src){
+ int v= *src;
+ int r;
+
+ tprintf("rbsp trailing %X\n", v);
+
+ for(r=1; r<9; r++){
+ if(v&1) return r;
+ v>>=1;
+ }
+ return 0;
+}
+
+/**
+ * idct tranforms the 16 dc values and dequantize them.
+ * @param qp quantization parameter
+ */
+static void h264_luma_dc_dequant_idct_c(DCTELEM *block, int qp, int qmul){
+#define stride 16
+ int i;
+ int temp[16]; //FIXME check if this is a good idea
+ static const int x_offset[4]={0, 1*stride, 4* stride, 5*stride};
+ static const int y_offset[4]={0, 2*stride, 8* stride, 10*stride};
+
+//memset(block, 64, 2*256);
+//return;
+ for(i=0; i<4; i++){
+ const int offset= y_offset[i];
+ const int z0= block[offset+stride*0] + block[offset+stride*4];
+ const int z1= block[offset+stride*0] - block[offset+stride*4];
+ const int z2= block[offset+stride*1] - block[offset+stride*5];
+ const int z3= block[offset+stride*1] + block[offset+stride*5];
+
+ 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= temp[4*0+i] + temp[4*2+i];
+ const int z1= temp[4*0+i] - temp[4*2+i];
+ const int z2= temp[4*1+i] - temp[4*3+i];
+ const int z3= temp[4*1+i] + temp[4*3+i];
+
+ block[stride*0 +offset]= ((((z0 + z3)*qmul + 128 ) >> 8)); //FIXME think about merging this into decode_resdual
+ block[stride*2 +offset]= ((((z1 + z2)*qmul + 128 ) >> 8));
+ block[stride*8 +offset]= ((((z1 - z2)*qmul + 128 ) >> 8));
+ block[stride*10+offset]= ((((z0 - z3)*qmul + 128 ) >> 8));
+ }
+}
+
+#if 0
+/**
+ * dct tranforms the 16 dc values.
+ * @param qp quantization parameter ??? FIXME
+ */
+static void h264_luma_dc_dct_c(DCTELEM *block/*, int qp*/){
+// const int qmul= dequant_coeff[qp][0];
+ int i;
+ int temp[16]; //FIXME check if this is a good idea
+ static const int x_offset[4]={0, 1*stride, 4* stride, 5*stride};
+ static const int y_offset[4]={0, 2*stride, 8* stride, 10*stride};
+
+ for(i=0; i<4; i++){
+ const int offset= y_offset[i];
+ const int z0= block[offset+stride*0] + block[offset+stride*4];
+ const int z1= block[offset+stride*0] - block[offset+stride*4];
+ const int z2= block[offset+stride*1] - block[offset+stride*5];
+ const int z3= block[offset+stride*1] + block[offset+stride*5];
+
+ 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= temp[4*0+i] + temp[4*2+i];
+ const int z1= temp[4*0+i] - temp[4*2+i];
+ const int z2= temp[4*1+i] - temp[4*3+i];
+ const int z3= temp[4*1+i] + temp[4*3+i];
+
+ block[stride*0 +offset]= (z0 + z3)>>1;
+ block[stride*2 +offset]= (z1 + z2)>>1;
+ block[stride*8 +offset]= (z1 - z2)>>1;
+ block[stride*10+offset]= (z0 - z3)>>1;
+ }
+}
+#endif
+
+#undef xStride
+#undef stride
+
+static void chroma_dc_dequant_idct_c(DCTELEM *block, int qp, int qmul){
+ const int stride= 16*2;
+ const int xStride= 16;
+ int a,b,c,d,e;
+
+ 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;
+}
+
+#if 0
+static void chroma_dc_dct_c(DCTELEM *block){
+ const int stride= 16*2;
+ const int xStride= 16;
+ int a,b,c,d,e;
+
+ 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);
+ block[stride*0 + xStride*1]= (e+b);
+ block[stride*1 + xStride*0]= (a-c);
+ block[stride*1 + xStride*1]= (e-b);
+}
+#endif
+
+/**
+ * gets the chroma qp.
+ */
+static inline int get_chroma_qp(int chroma_qp_index_offset, int qscale){
+
+ return chroma_qp[clip(qscale + chroma_qp_index_offset, 0, 51)];
+}
+
+
+#if 0
+static void h264_diff_dct_c(DCTELEM *block, uint8_t *src1, uint8_t *src2, int stride){
+ int i;
+ //FIXME try int temp instead of block
+
+ for(i=0; i<4; i++){
+ const int d0= src1[0 + i*stride] - src2[0 + i*stride];
+ const int d1= src1[1 + i*stride] - src2[1 + i*stride];
+ const int d2= src1[2 + i*stride] - src2[2 + i*stride];
+ const int d3= src1[3 + i*stride] - src2[3 + i*stride];
+ const int z0= d0 + d3;
+ const int z3= d0 - d3;
+ const int z1= d1 + d2;
+ const int z2= d1 - d2;
+
+ block[0 + 4*i]= z0 + z1;
+ block[1 + 4*i]= 2*z3 + z2;
+ block[2 + 4*i]= z0 - z1;
+ block[3 + 4*i]= z3 - 2*z2;
+ }
+
+ for(i=0; i<4; i++){
+ const int z0= block[0*4 + i] + block[3*4 + i];
+ const int z3= block[0*4 + i] - block[3*4 + i];
+ const int z1= block[1*4 + i] + block[2*4 + i];
+ const int z2= block[1*4 + i] - block[2*4 + i];
+
+ block[0*4 + i]= z0 + z1;
+ block[1*4 + i]= 2*z3 + z2;
+ block[2*4 + i]= z0 - z1;
+ block[3*4 + i]= z3 - 2*z2;
+ }
+}
+#endif
+
+//FIXME need to check that this doesnt overflow signed 32 bit for low qp, i am not sure, it's very close
+//FIXME check that gcc inlines this (and optimizes intra & seperate_dc stuff away)
+static inline int quantize_c(DCTELEM *block, uint8_t *scantable, int qscale, int intra, int seperate_dc){
+ int i;
+ const int * const quant_table= quant_coeff[qscale];
+ const int bias= intra ? (1<<QUANT_SHIFT)/3 : (1<<QUANT_SHIFT)/6;
+ const unsigned int threshold1= (1<<QUANT_SHIFT) - bias - 1;
+ const unsigned int threshold2= (threshold1<<1);
+ int last_non_zero;
+
+ if(seperate_dc){
+ if(qscale<=18){
+ //avoid overflows
+ const int dc_bias= intra ? (1<<(QUANT_SHIFT-2))/3 : (1<<(QUANT_SHIFT-2))/6;
+ const unsigned int dc_threshold1= (1<<(QUANT_SHIFT-2)) - dc_bias - 1;
+ const unsigned int dc_threshold2= (dc_threshold1<<1);
+
+ int level= block[0]*quant_coeff[qscale+18][0];
+ if(((unsigned)(level+dc_threshold1))>dc_threshold2){
+ if(level>0){
+ level= (dc_bias + level)>>(QUANT_SHIFT-2);
+ block[0]= level;
+ }else{
+ level= (dc_bias - level)>>(QUANT_SHIFT-2);
+ block[0]= -level;
+ }
+// last_non_zero = i;
+ }else{
+ block[0]=0;
+ }
+ }else{
+ const int dc_bias= intra ? (1<<(QUANT_SHIFT+1))/3 : (1<<(QUANT_SHIFT+1))/6;
+ const unsigned int dc_threshold1= (1<<(QUANT_SHIFT+1)) - dc_bias - 1;
+ const unsigned int dc_threshold2= (dc_threshold1<<1);
+
+ int level= block[0]*quant_table[0];
+ if(((unsigned)(level+dc_threshold1))>dc_threshold2){
+ if(level>0){
+ level= (dc_bias + level)>>(QUANT_SHIFT+1);
+ block[0]= level;
+ }else{
+ level= (dc_bias - level)>>(QUANT_SHIFT+1);
+ block[0]= -level;
+ }
+// last_non_zero = i;
+ }else{
+ block[0]=0;
+ }
+ }
+ last_non_zero= 0;
+ i=1;
+ }else{
+ last_non_zero= -1;
+ i=0;
+ }
+
+ for(; i<16; i++){
+ const int j= scantable[i];
+ int level= block[j]*quant_table[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)>>QUANT_SHIFT;
+ block[j]= level;
+ }else{
+ level= (bias - level)>>QUANT_SHIFT;
+ block[j]= -level;
+ }
+ last_non_zero = i;
+ }else{
+ block[j]=0;
+ }
+ }
+
+ return last_non_zero;
+}
+
+static void pred4x4_vertical_c(uint8_t *src, uint8_t *topright, int stride){
+ const uint32_t a= ((uint32_t*)(src-stride))[0];
+ ((uint32_t*)(src+0*stride))[0]= a;
+ ((uint32_t*)(src+1*stride))[0]= a;
+ ((uint32_t*)(src+2*stride))[0]= a;
+ ((uint32_t*)(src+3*stride))[0]= a;
+}
+
+static void pred4x4_horizontal_c(uint8_t *src, uint8_t *topright, int stride){
+ ((uint32_t*)(src+0*stride))[0]= src[-1+0*stride]*0x01010101;
+ ((uint32_t*)(src+1*stride))[0]= src[-1+1*stride]*0x01010101;
+ ((uint32_t*)(src+2*stride))[0]= src[-1+2*stride]*0x01010101;
+ ((uint32_t*)(src+3*stride))[0]= src[-1+3*stride]*0x01010101;
+}
+
+static void pred4x4_dc_c(uint8_t *src, uint8_t *topright, int stride){
+ 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;
+
+ ((uint32_t*)(src+0*stride))[0]=
+ ((uint32_t*)(src+1*stride))[0]=
+ ((uint32_t*)(src+2*stride))[0]=
+ ((uint32_t*)(src+3*stride))[0]= dc* 0x01010101;
+}
+
+static void pred4x4_left_dc_c(uint8_t *src, uint8_t *topright, int stride){
+ const int dc= ( src[-1+0*stride] + src[-1+1*stride] + src[-1+2*stride] + src[-1+3*stride] + 2) >>2;
+
+ ((uint32_t*)(src+0*stride))[0]=
+ ((uint32_t*)(src+1*stride))[0]=
+ ((uint32_t*)(src+2*stride))[0]=
+ ((uint32_t*)(src+3*stride))[0]= dc* 0x01010101;
+}
+
+static void pred4x4_top_dc_c(uint8_t *src, uint8_t *topright, int stride){
+ const int dc= ( src[-stride] + src[1-stride] + src[2-stride] + src[3-stride] + 2) >>2;
+
+ ((uint32_t*)(src+0*stride))[0]=
+ ((uint32_t*)(src+1*stride))[0]=
+ ((uint32_t*)(src+2*stride))[0]=
+ ((uint32_t*)(src+3*stride))[0]= dc* 0x01010101;
+}
+
+static void pred4x4_128_dc_c(uint8_t *src, uint8_t *topright, int stride){
+ ((uint32_t*)(src+0*stride))[0]=
+ ((uint32_t*)(src+1*stride))[0]=
+ ((uint32_t*)(src+2*stride))[0]=
+ ((uint32_t*)(src+3*stride))[0]= 128U*0x01010101U;
+}
+
+
+#define LOAD_TOP_RIGHT_EDGE\
+ const int t4= topright[0];\
+ const int t5= topright[1];\
+ const int t6= topright[2];\
+ const int t7= topright[3];\
+
+#define LOAD_LEFT_EDGE\
+ const int l0= src[-1+0*stride];\
+ const int l1= src[-1+1*stride];\
+ const int l2= src[-1+2*stride];\
+ const int l3= src[-1+3*stride];\
+
+#define LOAD_TOP_EDGE\
+ const int t0= src[ 0-1*stride];\
+ const int t1= src[ 1-1*stride];\
+ const int t2= src[ 2-1*stride];\
+ const int t3= src[ 3-1*stride];\
+
+static void pred4x4_down_right_c(uint8_t *src, uint8_t *topright, int stride){
+ 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 pred4x4_down_left_c(uint8_t *src, uint8_t *topright, int stride){
+ 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 pred4x4_vertical_right_c(uint8_t *src, uint8_t *topright, int stride){
+ const int lt= src[-1-1*stride];
+ LOAD_TOP_EDGE
+ LOAD_LEFT_EDGE
+ const __attribute__((unused)) int unu= l3;
+
+ 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 pred4x4_vertical_left_c(uint8_t *src, uint8_t *topright, int stride){
+ LOAD_TOP_EDGE
+ LOAD_TOP_RIGHT_EDGE
+ const __attribute__((unused)) int unu= t7;
+
+ 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 pred4x4_horizontal_up_c(uint8_t *src, uint8_t *topright, int stride){
+ 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 pred4x4_horizontal_down_c(uint8_t *src, uint8_t *topright, int stride){
+ const int lt= src[-1-1*stride];
+ LOAD_TOP_EDGE
+ LOAD_LEFT_EDGE
+ const __attribute__((unused)) int unu= t3;
+
+ 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 pred16x16_vertical_c(uint8_t *src, int stride){
+ int i;
+ const uint32_t a= ((uint32_t*)(src-stride))[0];
+ const uint32_t b= ((uint32_t*)(src-stride))[1];
+ const uint32_t c= ((uint32_t*)(src-stride))[2];
+ const uint32_t d= ((uint32_t*)(src-stride))[3];
+
+ for(i=0; i<16; i++){
+ ((uint32_t*)(src+i*stride))[0]= a;
+ ((uint32_t*)(src+i*stride))[1]= b;
+ ((uint32_t*)(src+i*stride))[2]= c;
+ ((uint32_t*)(src+i*stride))[3]= d;
+ }
+}
+
+static void pred16x16_horizontal_c(uint8_t *src, int stride){
+ int i;
+
+ for(i=0; i<16; i++){
+ ((uint32_t*)(src+i*stride))[0]=
+ ((uint32_t*)(src+i*stride))[1]=
+ ((uint32_t*)(src+i*stride))[2]=
+ ((uint32_t*)(src+i*stride))[3]= src[-1+i*stride]*0x01010101;
+ }
+}
+
+static void pred16x16_dc_c(uint8_t *src, int stride){
+ int i, dc=0;
+
+ for(i=0;i<16; i++){
+ dc+= src[-1+i*stride];
+ }
+
+ for(i=0;i<16; i++){
+ dc+= src[i-stride];
+ }
+
+ dc= 0x01010101*((dc + 16)>>5);
+
+ for(i=0; i<16; i++){
+ ((uint32_t*)(src+i*stride))[0]=
+ ((uint32_t*)(src+i*stride))[1]=
+ ((uint32_t*)(src+i*stride))[2]=
+ ((uint32_t*)(src+i*stride))[3]= dc;
+ }
+}
+
+static void pred16x16_left_dc_c(uint8_t *src, int stride){
+ int i, dc=0;
+
+ for(i=0;i<16; i++){
+ dc+= src[-1+i*stride];
+ }
+
+ dc= 0x01010101*((dc + 8)>>4);
+
+ for(i=0; i<16; i++){
+ ((uint32_t*)(src+i*stride))[0]=
+ ((uint32_t*)(src+i*stride))[1]=
+ ((uint32_t*)(src+i*stride))[2]=
+ ((uint32_t*)(src+i*stride))[3]= dc;
+ }
+}
+
+static void pred16x16_top_dc_c(uint8_t *src, int stride){
+ int i, dc=0;
+
+ for(i=0;i<16; i++){
+ dc+= src[i-stride];
+ }
+ dc= 0x01010101*((dc + 8)>>4);
+
+ for(i=0; i<16; i++){
+ ((uint32_t*)(src+i*stride))[0]=
+ ((uint32_t*)(src+i*stride))[1]=
+ ((uint32_t*)(src+i*stride))[2]=
+ ((uint32_t*)(src+i*stride))[3]= dc;
+ }
+}
+
+static void pred16x16_128_dc_c(uint8_t *src, int stride){
+ int i;
+
+ for(i=0; i<16; i++){
+ ((uint32_t*)(src+i*stride))[0]=
+ ((uint32_t*)(src+i*stride))[1]=
+ ((uint32_t*)(src+i*stride))[2]=
+ ((uint32_t*)(src+i*stride))[3]= 0x01010101U*128U;
+ }
+}
+
+static inline void pred16x16_plane_compat_c(uint8_t *src, int stride, const int svq3){
+ int i, j, k;
+ int a;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+ const uint8_t * const src0 = src+7-stride;
+ const uint8_t *src1 = src+8*stride-1;
+ const uint8_t *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{
+ 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] = cm[ (b ) >> 5 ];
+ src[17+i] = cm[ (b+ H) >> 5 ];
+ src[18+i] = cm[ (b+2*H) >> 5 ];
+ src[19+i] = cm[ (b+3*H) >> 5 ];
+ b += 4*H;
+ }
+ src += stride;
+ }
+}
+
+static void pred16x16_plane_c(uint8_t *src, int stride){
+ pred16x16_plane_compat_c(src, stride, 0);
+}
+
+static void pred8x8_vertical_c(uint8_t *src, int stride){
+ int i;
+ const uint32_t a= ((uint32_t*)(src-stride))[0];
+ const uint32_t b= ((uint32_t*)(src-stride))[1];
+
+ for(i=0; i<8; i++){
+ ((uint32_t*)(src+i*stride))[0]= a;
+ ((uint32_t*)(src+i*stride))[1]= b;
+ }
+}
+
+static void pred8x8_horizontal_c(uint8_t *src, int stride){
+ int i;
+
+ for(i=0; i<8; i++){
+ ((uint32_t*)(src+i*stride))[0]=
+ ((uint32_t*)(src+i*stride))[1]= src[-1+i*stride]*0x01010101;
+ }
+}
+
+static void pred8x8_128_dc_c(uint8_t *src, int stride){
+ int i;
+
+ for(i=0; i<8; i++){
+ ((uint32_t*)(src+i*stride))[0]=
+ ((uint32_t*)(src+i*stride))[1]= 0x01010101U*128U;
+ }
+}
+
+static void pred8x8_left_dc_c(uint8_t *src, int stride){
+ int i;
+ int dc0, dc2;
+
+ dc0=dc2=0;
+ for(i=0;i<4; i++){
+ dc0+= src[-1+i*stride];
+ dc2+= src[-1+(i+4)*stride];
+ }
+ dc0= 0x01010101*((dc0 + 2)>>2);
+ dc2= 0x01010101*((dc2 + 2)>>2);
+
+ for(i=0; i<4; i++){
+ ((uint32_t*)(src+i*stride))[0]=
+ ((uint32_t*)(src+i*stride))[1]= dc0;
+ }
+ for(i=4; i<8; i++){
+ ((uint32_t*)(src+i*stride))[0]=
+ ((uint32_t*)(src+i*stride))[1]= dc2;
+ }
+}
+
+static void pred8x8_top_dc_c(uint8_t *src, int stride){
+ int i;
+ int dc0, dc1;
+
+ dc0=dc1=0;
+ for(i=0;i<4; i++){
+ dc0+= src[i-stride];
+ dc1+= src[4+i-stride];
+ }
+ dc0= 0x01010101*((dc0 + 2)>>2);
+ dc1= 0x01010101*((dc1 + 2)>>2);
+
+ for(i=0; i<4; i++){
+ ((uint32_t*)(src+i*stride))[0]= dc0;
+ ((uint32_t*)(src+i*stride))[1]= dc1;
+ }
+ for(i=4; i<8; i++){
+ ((uint32_t*)(src+i*stride))[0]= dc0;
+ ((uint32_t*)(src+i*stride))[1]= dc1;
+ }
+}
+
+
+static void pred8x8_dc_c(uint8_t *src, int stride){
+ int i;
+ int dc0, dc1, dc2, dc3;
+
+ 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];
+ }
+ dc3= 0x01010101*((dc1 + dc2 + 4)>>3);
+ dc0= 0x01010101*((dc0 + 4)>>3);
+ dc1= 0x01010101*((dc1 + 2)>>2);
+ dc2= 0x01010101*((dc2 + 2)>>2);
+
+ for(i=0; i<4; i++){
+ ((uint32_t*)(src+i*stride))[0]= dc0;
+ ((uint32_t*)(src+i*stride))[1]= dc1;
+ }
+ for(i=4; i<8; i++){
+ ((uint32_t*)(src+i*stride))[0]= dc2;
+ ((uint32_t*)(src+i*stride))[1]= dc3;
+ }
+}
+
+static void pred8x8_plane_c(uint8_t *src, int stride){
+ int j, k;
+ int a;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+ const uint8_t * const src0 = src+3-stride;
+ const uint8_t *src1 = src+4*stride-1;
+ const uint8_t *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] = cm[ (b ) >> 5 ];
+ src[1] = cm[ (b+ H) >> 5 ];
+ src[2] = cm[ (b+2*H) >> 5 ];
+ src[3] = cm[ (b+3*H) >> 5 ];
+ src[4] = cm[ (b+4*H) >> 5 ];
+ src[5] = cm[ (b+5*H) >> 5 ];
+ src[6] = cm[ (b+6*H) >> 5 ];
+ src[7] = cm[ (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 attribute_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 attribute_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++ ) { \
+ ((uint32_t*)src)[0] = \
+ ((uint32_t*)src)[1] = v; \
+ src += stride; \
+ }
+
+static void pred8x8l_128_dc_c(uint8_t *src, int has_topleft, int has_topright, int stride)
+{
+ PREDICT_8x8_DC(0x80808080);
+}
+static void pred8x8l_left_dc_c(uint8_t *src, int has_topleft, int has_topright, int stride)
+{
+ PREDICT_8x8_LOAD_LEFT;
+ const uint32_t dc = ((l0+l1+l2+l3+l4+l5+l6+l7+4) >> 3) * 0x01010101;
+ PREDICT_8x8_DC(dc);
+}
+static void pred8x8l_top_dc_c(uint8_t *src, int has_topleft, int has_topright, int stride)
+{
+ PREDICT_8x8_LOAD_TOP;
+ const uint32_t dc = ((t0+t1+t2+t3+t4+t5+t6+t7+4) >> 3) * 0x01010101;
+ PREDICT_8x8_DC(dc);
+}
+static void pred8x8l_dc_c(uint8_t *src, int has_topleft, int has_topright, int stride)
+{
+ PREDICT_8x8_LOAD_LEFT;
+ PREDICT_8x8_LOAD_TOP;
+ const uint32_t dc = ((l0+l1+l2+l3+l4+l5+l6+l7
+ +t0+t1+t2+t3+t4+t5+t6+t7+8) >> 4) * 0x01010101;
+ PREDICT_8x8_DC(dc);
+}
+static void pred8x8l_horizontal_c(uint8_t *src, int has_topleft, int has_topright, int stride)
+{
+ PREDICT_8x8_LOAD_LEFT;
+#define ROW(y) ((uint32_t*)(src+y*stride))[0] =\
+ ((uint32_t*)(src+y*stride))[1] = 0x01010101 * l##y
+ ROW(0); ROW(1); ROW(2); ROW(3); ROW(4); ROW(5); ROW(6); ROW(7);
+#undef ROW
+}
+static void pred8x8l_vertical_c(uint8_t *src, int has_topleft, int has_topright, int stride)
+{
+ int y;
+ 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;
+ for( y = 1; y < 8; y++ )
+ *(uint64_t*)(src+y*stride) = *(uint64_t*)src;
+}
+static void pred8x8l_down_left_c(uint8_t *src, int has_topleft, int has_topright, int stride)
+{
+ 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 pred8x8l_down_right_c(uint8_t *src, int has_topleft, int has_topright, int stride)
+{
+ 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 pred8x8l_vertical_right_c(uint8_t *src, int has_topleft, int has_topright, int stride)
+{
+ 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 pred8x8l_horizontal_down_c(uint8_t *src, int has_topleft, int has_topright, int stride)
+{
+ 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 pred8x8l_vertical_left_c(uint8_t *src, int has_topleft, int has_topright, int stride)
+{
+ 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 pred8x8l_horizontal_up_c(uint8_t *src, int has_topleft, int has_topright, int stride)
+{
+ 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 inline void mc_dir_part(H264Context *h, Picture *pic, int n, int square, 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){
+ MpegEncContext * const s = &h->s;
+ 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);
+ uint8_t * src_y = pic->data[0] + (mx>>2) + (my>>2)*h->mb_linesize;
+ uint8_t * src_cb, * src_cr;
+ int extra_width= h->emu_edge_width;
+ int extra_height= h->emu_edge_height;
+ int emu=0;
+ const int full_mx= mx>>2;
+ const int full_my= my>>2;
+ const int pic_width = 16*s->mb_width;
+ const int pic_height = 16*s->mb_height >> MB_MBAFF;
+
+ 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){
+ ff_emulated_edge_mc(s->edge_emu_buffer, src_y - 2 - 2*h->mb_linesize, h->mb_linesize, 16+5, 16+5/*FIXME*/, full_mx-2, full_my-2, pic_width, pic_height);
+ src_y= s->edge_emu_buffer + 2 + 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(s->flags&CODEC_FLAG_GRAY) return;
+
+ if(MB_MBAFF){
+ // chroma offset when predicting from a field of opposite parity
+ my += 2 * ((s->mb_y & 1) - (h->ref_cache[list][scan8[n]] & 1));
+ emu |= (my>>3) < 0 || (my>>3) + 8 >= (pic_height>>1);
+ }
+ src_cb= pic->data[1] + (mx>>3) + (my>>3)*h->mb_uvlinesize;
+ src_cr= pic->data[2] + (mx>>3) + (my>>3)*h->mb_uvlinesize;
+
+ if(emu){
+ ff_emulated_edge_mc(s->edge_emu_buffer, src_cb, h->mb_uvlinesize, 9, 9/*FIXME*/, (mx>>3), (my>>3), pic_width>>1, pic_height>>1);
+ src_cb= s->edge_emu_buffer;
+ }
+ chroma_op(dest_cb, src_cb, h->mb_uvlinesize, chroma_height, mx&7, my&7);
+
+ if(emu){
+ ff_emulated_edge_mc(s->edge_emu_buffer, src_cr, h->mb_uvlinesize, 9, 9/*FIXME*/, (mx>>3), (my>>3), pic_width>>1, pic_height>>1);
+ src_cr= s->edge_emu_buffer;
+ }
+ chroma_op(dest_cr, src_cr, h->mb_uvlinesize, chroma_height, mx&7, my&7);
+}
+
+static inline void mc_part_std(H264Context *h, int n, int square, 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,
+ int list0, int list1){
+ MpegEncContext * const s = &h->s;
+ qpel_mc_func *qpix_op= qpix_put;
+ h264_chroma_mc_func chroma_op= chroma_put;
+
+ dest_y += 2*x_offset + 2*y_offset*h-> mb_linesize;
+ dest_cb += x_offset + y_offset*h->mb_uvlinesize;
+ dest_cr += x_offset + y_offset*h->mb_uvlinesize;
+ x_offset += 8*s->mb_x;
+ y_offset += 8*(s->mb_y >> MB_MBAFF);
+
+ if(list0){
+ Picture *ref= &h->ref_list[0][ h->ref_cache[0][ scan8[n] ] ];
+ mc_dir_part(h, ref, n, square, chroma_height, delta, 0,
+ dest_y, dest_cb, dest_cr, x_offset, y_offset,
+ qpix_op, chroma_op);
+
+ 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, chroma_height, delta, 1,
+ dest_y, dest_cb, dest_cr, x_offset, y_offset,
+ qpix_op, chroma_op);
+ }
+}
+
+static inline void mc_part_weighted(H264Context *h, int n, int square, 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,
+ 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){
+ MpegEncContext * const s = &h->s;
+
+ dest_y += 2*x_offset + 2*y_offset*h-> mb_linesize;
+ dest_cb += x_offset + y_offset*h->mb_uvlinesize;
+ dest_cr += x_offset + y_offset*h->mb_uvlinesize;
+ x_offset += 8*s->mb_x;
+ y_offset += 8*(s->mb_y >> MB_MBAFF);
+
+ if(list0 && list1){
+ /* don't optimize for luma-only case, since B-frames usually
+ * use implicit weights => chroma too. */
+ uint8_t *tmp_cb = s->obmc_scratchpad;
+ uint8_t *tmp_cr = s->obmc_scratchpad + 8;
+ uint8_t *tmp_y = s->obmc_scratchpad + 8*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, chroma_height, delta, 0,
+ dest_y, dest_cb, dest_cr,
+ x_offset, y_offset, qpix_put, chroma_put);
+ mc_dir_part(h, &h->ref_list[1][refn1], n, square, chroma_height, delta, 1,
+ tmp_y, tmp_cb, tmp_cr,
+ x_offset, y_offset, qpix_put, chroma_put);
+
+ if(h->use_weight == 2){
+ int weight0 = h->implicit_weight[refn0][refn1];
+ int weight1 = 64 - weight0;
+ luma_weight_avg( dest_y, tmp_y, h-> mb_linesize, 5, weight0, weight1, 0);
+ chroma_weight_avg(dest_cb, tmp_cb, h->mb_uvlinesize, 5, weight0, weight1, 0);
+ chroma_weight_avg(dest_cr, tmp_cr, h->mb_uvlinesize, 5, weight0, weight1, 0);
+ }else{
+ luma_weight_avg(dest_y, tmp_y, h->mb_linesize, h->luma_log2_weight_denom,
+ h->luma_weight[0][refn0], h->luma_weight[1][refn1],
+ h->luma_offset[0][refn0] + h->luma_offset[1][refn1]);
+ chroma_weight_avg(dest_cb, tmp_cb, h->mb_uvlinesize, h->chroma_log2_weight_denom,
+ h->chroma_weight[0][refn0][0], h->chroma_weight[1][refn1][0],
+ h->chroma_offset[0][refn0][0] + h->chroma_offset[1][refn1][0]);
+ chroma_weight_avg(dest_cr, tmp_cr, h->mb_uvlinesize, h->chroma_log2_weight_denom,
+ h->chroma_weight[0][refn0][1], h->chroma_weight[1][refn1][1],
+ h->chroma_offset[0][refn0][1] + h->chroma_offset[1][refn1][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, chroma_height, delta, list,
+ dest_y, dest_cb, dest_cr, x_offset, y_offset,
+ qpix_put, chroma_put);
+
+ luma_weight_op(dest_y, h->mb_linesize, h->luma_log2_weight_denom,
+ h->luma_weight[list][refn], h->luma_offset[list][refn]);
+ if(h->use_weight_chroma){
+ chroma_weight_op(dest_cb, h->mb_uvlinesize, h->chroma_log2_weight_denom,
+ h->chroma_weight[list][refn][0], h->chroma_offset[list][refn][0]);
+ chroma_weight_op(dest_cr, h->mb_uvlinesize, h->chroma_log2_weight_denom,
+ h->chroma_weight[list][refn][1], h->chroma_offset[list][refn][1]);
+ }
+ }
+}
+
+static inline void mc_part(H264Context *h, int n, int square, 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,
+ 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]] ] != 32))
+ || h->use_weight==1)
+ mc_part_weighted(h, n, square, chroma_height, delta, dest_y, dest_cb, dest_cr,
+ x_offset, y_offset, qpix_put, chroma_put,
+ weight_op[0], weight_op[3], weight_avg[0], weight_avg[3], list0, list1);
+ else
+ mc_part_std(h, n, square, chroma_height, delta, dest_y, dest_cb, dest_cr,
+ x_offset, y_offset, qpix_put, chroma_put, qpix_avg, chroma_avg, list0, list1);
+}
+
+static inline void prefetch_motion(H264Context *h, int list){
+ /* fetch pixels for estimated mv 4 macroblocks ahead
+ * optimized for 64byte cache lines */
+ MpegEncContext * const s = &h->s;
+ const int refn = h->ref_cache[list][scan8[0]];
+ if(refn >= 0){
+ const int mx= (h->mv_cache[list][scan8[0]][0]>>2) + 16*s->mb_x + 8;
+ const int my= (h->mv_cache[list][scan8[0]][1]>>2) + 16*s->mb_y;
+ uint8_t **src= h->ref_list[list][refn].data;
+ int off= mx + (my + (s->mb_x&3)*4)*h->mb_linesize + 64;
+ s->dsp.prefetch(src[0]+off, s->linesize, 4);
+ off= (mx>>1) + ((my>>1) + (s->mb_x&7))*s->uvlinesize + 64;
+ s->dsp.prefetch(src[1]+off, src[2]-src[1], 2);
+ }
+}
+
+static void 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){
+ MpegEncContext * const s = &h->s;
+ const int mb_xy= s->mb_x + s->mb_y*s->mb_stride;
+ const int mb_type= s->current_picture.mb_type[mb_xy];
+
+ assert(IS_INTER(mb_type));
+
+ prefetch_motion(h, 0);
+
+ if(IS_16X16(mb_type)){
+ mc_part(h, 0, 1, 8, 0, dest_y, dest_cb, dest_cr, 0, 0,
+ qpix_put[0], chroma_put[0], qpix_avg[0], chroma_avg[0],
+ &weight_op[0], &weight_avg[0],
+ IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1));
+ }else if(IS_16X8(mb_type)){
+ mc_part(h, 0, 0, 4, 8, dest_y, dest_cb, dest_cr, 0, 0,
+ qpix_put[1], chroma_put[0], qpix_avg[1], chroma_avg[0],
+ &weight_op[1], &weight_avg[1],
+ IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1));
+ mc_part(h, 8, 0, 4, 8, dest_y, dest_cb, dest_cr, 0, 4,
+ qpix_put[1], chroma_put[0], qpix_avg[1], chroma_avg[0],
+ &weight_op[1], &weight_avg[1],
+ IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1));
+ }else if(IS_8X16(mb_type)){
+ mc_part(h, 0, 0, 8, 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[2], &weight_avg[2],
+ IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1));
+ mc_part(h, 4, 0, 8, 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[2], &weight_avg[2],
+ IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1));
+ }else{
+ int i;
+
+ assert(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, 4, 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[3], &weight_avg[3],
+ 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, 2, 4, dest_y, dest_cb, dest_cr, x_offset, y_offset,
+ qpix_put[2], chroma_put[1], qpix_avg[2], chroma_avg[1],
+ &weight_op[4], &weight_avg[4],
+ IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1));
+ mc_part(h, n+2, 0, 2, 4, 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[4], &weight_avg[4],
+ 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, 4, 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[5], &weight_avg[5],
+ IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1));
+ mc_part(h, n+1, 0, 4, 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[5], &weight_avg[5],
+ IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1));
+ }else{
+ int j;
+ assert(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, 2, 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[6], &weight_avg[6],
+ IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1));
+ }
+ }
+ }
+ }
+
+ prefetch_motion(h, 1);
+}
+
+static void decode_init_vlc(){
+ static int done = 0;
+
+ if (!done) {
+ int i;
+ done = 1;
+
+ 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, 1);
+
+ for(i=0; i<4; 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, 1);
+ }
+
+ for(i=0; i<3; i++){
+ 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, 1);
+ }
+ for(i=0; i<15; i++){
+ 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, 1);
+ }
+
+ for(i=0; i<6; i++){
+ init_vlc(&run_vlc[i], RUN_VLC_BITS, 7,
+ &run_len [i][0], 1, 1,
+ &run_bits[i][0], 1, 1, 1);
+ }
+ init_vlc(&run7_vlc, RUN7_VLC_BITS, 16,
+ &run_len [6][0], 1, 1,
+ &run_bits[6][0], 1, 1, 1);
+ }
+}
+
+/**
+ * Sets the intra prediction function pointers.
+ */
+static void init_pred_ptrs(H264Context *h){
+// MpegEncContext * const s = &h->s;
+
+ h->pred4x4[VERT_PRED ]= pred4x4_vertical_c;
+ h->pred4x4[HOR_PRED ]= pred4x4_horizontal_c;
+ h->pred4x4[DC_PRED ]= pred4x4_dc_c;
+ h->pred4x4[DIAG_DOWN_LEFT_PRED ]= pred4x4_down_left_c;
+ h->pred4x4[DIAG_DOWN_RIGHT_PRED]= pred4x4_down_right_c;
+ h->pred4x4[VERT_RIGHT_PRED ]= pred4x4_vertical_right_c;
+ h->pred4x4[HOR_DOWN_PRED ]= pred4x4_horizontal_down_c;
+ h->pred4x4[VERT_LEFT_PRED ]= pred4x4_vertical_left_c;
+ h->pred4x4[HOR_UP_PRED ]= pred4x4_horizontal_up_c;
+ h->pred4x4[LEFT_DC_PRED ]= pred4x4_left_dc_c;
+ h->pred4x4[TOP_DC_PRED ]= pred4x4_top_dc_c;
+ h->pred4x4[DC_128_PRED ]= pred4x4_128_dc_c;
+
+ h->pred8x8l[VERT_PRED ]= pred8x8l_vertical_c;
+ h->pred8x8l[HOR_PRED ]= pred8x8l_horizontal_c;
+ h->pred8x8l[DC_PRED ]= pred8x8l_dc_c;
+ h->pred8x8l[DIAG_DOWN_LEFT_PRED ]= pred8x8l_down_left_c;
+ h->pred8x8l[DIAG_DOWN_RIGHT_PRED]= pred8x8l_down_right_c;
+ h->pred8x8l[VERT_RIGHT_PRED ]= pred8x8l_vertical_right_c;
+ h->pred8x8l[HOR_DOWN_PRED ]= pred8x8l_horizontal_down_c;
+ h->pred8x8l[VERT_LEFT_PRED ]= pred8x8l_vertical_left_c;
+ h->pred8x8l[HOR_UP_PRED ]= pred8x8l_horizontal_up_c;
+ h->pred8x8l[LEFT_DC_PRED ]= pred8x8l_left_dc_c;
+ h->pred8x8l[TOP_DC_PRED ]= pred8x8l_top_dc_c;
+ h->pred8x8l[DC_128_PRED ]= pred8x8l_128_dc_c;
+
+ h->pred8x8[DC_PRED8x8 ]= pred8x8_dc_c;
+ h->pred8x8[VERT_PRED8x8 ]= pred8x8_vertical_c;
+ h->pred8x8[HOR_PRED8x8 ]= pred8x8_horizontal_c;
+ h->pred8x8[PLANE_PRED8x8 ]= pred8x8_plane_c;
+ h->pred8x8[LEFT_DC_PRED8x8]= pred8x8_left_dc_c;
+ h->pred8x8[TOP_DC_PRED8x8 ]= pred8x8_top_dc_c;
+ h->pred8x8[DC_128_PRED8x8 ]= pred8x8_128_dc_c;
+
+ h->pred16x16[DC_PRED8x8 ]= pred16x16_dc_c;
+ h->pred16x16[VERT_PRED8x8 ]= pred16x16_vertical_c;
+ h->pred16x16[HOR_PRED8x8 ]= pred16x16_horizontal_c;
+ h->pred16x16[PLANE_PRED8x8 ]= pred16x16_plane_c;
+ h->pred16x16[LEFT_DC_PRED8x8]= pred16x16_left_dc_c;
+ h->pred16x16[TOP_DC_PRED8x8 ]= pred16x16_top_dc_c;
+ h->pred16x16[DC_128_PRED8x8 ]= pred16x16_128_dc_c;
+}
+
+static void free_tables(H264Context *h){
+ 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);
+ av_freep(&h->top_borders[1]);
+ av_freep(&h->top_borders[0]);
+ h->slice_table= NULL;
+
+ av_freep(&h->mb2b_xy);
+ av_freep(&h->mb2b8_xy);
+
+ av_freep(&h->s.obmc_scratchpad);
+}
+
+static void init_dequant8_coeff_table(H264Context *h){
+ int i,q,x;
+ const int transpose = (h->s.dsp.h264_idct8_add != ff_h264_idct8_add_c); //FIXME ugly
+ h->dequant8_coeff[0] = h->dequant8_buffer[0];
+ h->dequant8_coeff[1] = h->dequant8_buffer[1];
+
+ for(i=0; i<2; i++ ){
+ if(i && !memcmp(h->pps.scaling_matrix8[0], h->pps.scaling_matrix8[1], 64*sizeof(uint8_t))){
+ h->dequant8_coeff[1] = h->dequant8_buffer[0];
+ break;
+ }
+
+ for(q=0; q<52; q++){
+ int shift = div6[q];
+ int idx = rem6[q];
+ for(x=0; x<64; x++)
+ h->dequant8_coeff[i][q][transpose ? (x>>3)|((x&7)<<3) : x] =
+ ((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 transpose = (h->s.dsp.h264_idct_add != ff_h264_idct_add_c); //FIXME ugly
+ 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<52; q++){
+ int shift = div6[q] + 2;
+ int idx = rem6[q];
+ for(x=0; x<16; x++)
+ h->dequant4_coeff[i][q][transpose ? (x>>2)|((x<<2)&0xF) : x] =
+ ((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<2; i++)
+ for(x=0; x<64; x++)
+ h->dequant8_coeff[i][0][x] = 1<<6;
+ }
+}
+
+
+/**
+ * allocates tables.
+ * needs width/height
+ */
+static int alloc_tables(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ const int big_mb_num= s->mb_stride * (s->mb_height+1);
+ int x,y;
+
+ CHECKED_ALLOCZ(h->intra4x4_pred_mode, big_mb_num * 8 * sizeof(uint8_t))
+
+ CHECKED_ALLOCZ(h->non_zero_count , big_mb_num * 16 * sizeof(uint8_t))
+ CHECKED_ALLOCZ(h->slice_table_base , (big_mb_num+s->mb_stride) * sizeof(uint8_t))
+ CHECKED_ALLOCZ(h->top_borders[0] , s->mb_width * (16+8+8) * sizeof(uint8_t))
+ CHECKED_ALLOCZ(h->top_borders[1] , s->mb_width * (16+8+8) * sizeof(uint8_t))
+ CHECKED_ALLOCZ(h->cbp_table, big_mb_num * sizeof(uint16_t))
+
+ if( h->pps.cabac ) {
+ CHECKED_ALLOCZ(h->chroma_pred_mode_table, big_mb_num * sizeof(uint8_t))
+ CHECKED_ALLOCZ(h->mvd_table[0], 32*big_mb_num * sizeof(uint16_t));
+ CHECKED_ALLOCZ(h->mvd_table[1], 32*big_mb_num * sizeof(uint16_t));
+ CHECKED_ALLOCZ(h->direct_table, 32*big_mb_num * sizeof(uint8_t));
+ }
+
+ memset(h->slice_table_base, -1, (big_mb_num+s->mb_stride) * sizeof(uint8_t));
+ h->slice_table= h->slice_table_base + s->mb_stride*2 + 1;
+
+ CHECKED_ALLOCZ(h->mb2b_xy , big_mb_num * sizeof(uint32_t));
+ CHECKED_ALLOCZ(h->mb2b8_xy , big_mb_num * sizeof(uint32_t));
+ for(y=0; y<s->mb_height; y++){
+ for(x=0; x<s->mb_width; x++){
+ const int mb_xy= x + y*s->mb_stride;
+ const int b_xy = 4*x + 4*y*h->b_stride;
+ const int b8_xy= 2*x + 2*y*h->b8_stride;
+
+ h->mb2b_xy [mb_xy]= b_xy;
+ h->mb2b8_xy[mb_xy]= b8_xy;
+ }
+ }
+
+ s->obmc_scratchpad = NULL;
+
+ if(!h->dequant4_coeff[0])
+ init_dequant_tables(h);
+
+ return 0;
+fail:
+ free_tables(h);
+ return -1;
+}
+
+static void common_init(H264Context *h){
+ MpegEncContext * const s = &h->s;
+
+ s->width = s->avctx->width;
+ s->height = s->avctx->height;
+ s->codec_id= s->avctx->codec->id;
+
+ init_pred_ptrs(h);
+
+ h->dequant_coeff_pps= -1;
+ s->unrestricted_mv=1;
+ s->decode=1; //FIXME
+
+ memset(h->pps.scaling_matrix4, 16, 6*16*sizeof(uint8_t));
+ memset(h->pps.scaling_matrix8, 16, 2*64*sizeof(uint8_t));
+}
+
+static int decode_init(AVCodecContext *avctx){
+ H264Context *h= avctx->priv_data;
+ MpegEncContext * const s = &h->s;
+
+ MPV_decode_defaults(s);
+
+ s->avctx = avctx;
+ common_init(h);
+
+ s->out_format = FMT_H264;
+ s->workaround_bugs= avctx->workaround_bugs;
+
+ // set defaults
+// s->decode_mb= ff_h263_decode_mb;
+ s->low_delay= 1;
+ avctx->pix_fmt= PIX_FMT_YUV420P;
+
+ decode_init_vlc();
+
+ if(avctx->extradata_size > 0 && avctx->extradata &&
+ *(char *)avctx->extradata == 1){
+ h->is_avc = 1;
+ h->got_avcC = 0;
+ } else {
+ h->is_avc = 0;
+ }
+
+ return 0;
+}
+
+static int frame_start(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ int i;
+
+ if(MPV_frame_start(s, s->avctx) < 0)
+ return -1;
+ ff_er_frame_start(s);
+
+ assert(s->linesize && s->uvlinesize);
+
+ for(i=0; i<16; i++){
+ h->block_offset[i]= 4*((scan8[i] - scan8[0])&7) + 4*s->linesize*((scan8[i] - scan8[0])>>3);
+ h->block_offset[24+i]= 4*((scan8[i] - scan8[0])&7) + 8*s->linesize*((scan8[i] - scan8[0])>>3);
+ }
+ for(i=0; i<4; i++){
+ h->block_offset[16+i]=
+ h->block_offset[20+i]= 4*((scan8[i] - scan8[0])&7) + 4*s->uvlinesize*((scan8[i] - scan8[0])>>3);
+ h->block_offset[24+16+i]=
+ h->block_offset[24+20+i]= 4*((scan8[i] - scan8[0])&7) + 8*s->uvlinesize*((scan8[i] - scan8[0])>>3);
+ }
+
+ /* can't be in alloc_tables because linesize isn't known there.
+ * FIXME: redo bipred weight to not require extra buffer? */
+ if(!s->obmc_scratchpad)
+ s->obmc_scratchpad = av_malloc(16*2*s->linesize + 8*2*s->uvlinesize);
+
+ /* some macroblocks will be accessed before they're available */
+ if(FRAME_MBAFF)
+ memset(h->slice_table, -1, (s->mb_height*s->mb_stride-1) * sizeof(uint8_t));
+
+// s->decode= (s->flags&CODEC_FLAG_PSNR) || !s->encoding || s->current_picture.reference /*|| h->contains_intra*/ || 1;
+ return 0;
+}
+
+static inline void backup_mb_border(H264Context *h, uint8_t *src_y, uint8_t *src_cb, uint8_t *src_cr, int linesize, int uvlinesize){
+ MpegEncContext * const s = &h->s;
+ int i;
+
+ src_y -= linesize;
+ src_cb -= uvlinesize;
+ src_cr -= uvlinesize;
+
+ // There are two lines saved, the line above the the top macroblock of a pair,
+ // and the line above the bottom macroblock
+ h->left_border[0]= h->top_borders[0][s->mb_x][15];
+ for(i=1; i<17; i++){
+ h->left_border[i]= src_y[15+i* linesize];
+ }
+
+ *(uint64_t*)(h->top_borders[0][s->mb_x]+0)= *(uint64_t*)(src_y + 16*linesize);
+ *(uint64_t*)(h->top_borders[0][s->mb_x]+8)= *(uint64_t*)(src_y +8+16*linesize);
+
+ if(!(s->flags&CODEC_FLAG_GRAY)){
+ h->left_border[17 ]= h->top_borders[0][s->mb_x][16+7];
+ h->left_border[17+9]= h->top_borders[0][s->mb_x][24+7];
+ for(i=1; i<9; i++){
+ h->left_border[i+17 ]= src_cb[7+i*uvlinesize];
+ h->left_border[i+17+9]= src_cr[7+i*uvlinesize];
+ }
+ *(uint64_t*)(h->top_borders[0][s->mb_x]+16)= *(uint64_t*)(src_cb+8*uvlinesize);
+ *(uint64_t*)(h->top_borders[0][s->mb_x]+24)= *(uint64_t*)(src_cr+8*uvlinesize);
+ }
+}
+
+static 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){
+ MpegEncContext * const s = &h->s;
+ int temp8, i;
+ uint64_t temp64;
+ int deblock_left = (s->mb_x > 0);
+ int deblock_top = (s->mb_y > 0);
+
+ src_y -= linesize + 1;
+ src_cb -= uvlinesize + 1;
+ src_cr -= uvlinesize + 1;
+
+#define XCHG(a,b,t,xchg)\
+t= a;\
+if(xchg)\
+ a= b;\
+b= t;
+
+ if(deblock_left){
+ for(i = !deblock_top; i<17; i++){
+ XCHG(h->left_border[i ], src_y [i* linesize], temp8, xchg);
+ }
+ }
+
+ if(deblock_top){
+ XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x]+0), *(uint64_t*)(src_y +1), temp64, xchg);
+ XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x]+8), *(uint64_t*)(src_y +9), temp64, 1);
+ if(s->mb_x+1 < s->mb_width){
+ XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x+1]), *(uint64_t*)(src_y +17), temp64, 1);
+ }
+ }
+
+ if(!(s->flags&CODEC_FLAG_GRAY)){
+ if(deblock_left){
+ for(i = !deblock_top; i<9; i++){
+ XCHG(h->left_border[i+17 ], src_cb[i*uvlinesize], temp8, xchg);
+ XCHG(h->left_border[i+17+9], src_cr[i*uvlinesize], temp8, xchg);
+ }
+ }
+ if(deblock_top){
+ XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x]+16), *(uint64_t*)(src_cb+1), temp64, 1);
+ XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x]+24), *(uint64_t*)(src_cr+1), temp64, 1);
+ }
+ }
+}
+
+static inline void backup_pair_border(H264Context *h, uint8_t *src_y, uint8_t *src_cb, uint8_t *src_cr, int linesize, int uvlinesize){
+ MpegEncContext * const s = &h->s;
+ int i;
+
+ src_y -= 2 * linesize;
+ src_cb -= 2 * uvlinesize;
+ src_cr -= 2 * uvlinesize;
+
+ // There are two lines saved, the line above the the top macroblock of a pair,
+ // and the line above the bottom macroblock
+ h->left_border[0]= h->top_borders[0][s->mb_x][15];
+ h->left_border[1]= h->top_borders[1][s->mb_x][15];
+ for(i=2; i<34; i++){
+ h->left_border[i]= src_y[15+i* linesize];
+ }
+
+ *(uint64_t*)(h->top_borders[0][s->mb_x]+0)= *(uint64_t*)(src_y + 32*linesize);
+ *(uint64_t*)(h->top_borders[0][s->mb_x]+8)= *(uint64_t*)(src_y +8+32*linesize);
+ *(uint64_t*)(h->top_borders[1][s->mb_x]+0)= *(uint64_t*)(src_y + 33*linesize);
+ *(uint64_t*)(h->top_borders[1][s->mb_x]+8)= *(uint64_t*)(src_y +8+33*linesize);
+
+ if(!(s->flags&CODEC_FLAG_GRAY)){
+ h->left_border[34 ]= h->top_borders[0][s->mb_x][16+7];
+ h->left_border[34+ 1]= h->top_borders[1][s->mb_x][16+7];
+ h->left_border[34+18 ]= h->top_borders[0][s->mb_x][24+7];
+ h->left_border[34+18+1]= h->top_borders[1][s->mb_x][24+7];
+ for(i=2; i<18; i++){
+ h->left_border[i+34 ]= src_cb[7+i*uvlinesize];
+ h->left_border[i+34+18]= src_cr[7+i*uvlinesize];
+ }
+ *(uint64_t*)(h->top_borders[0][s->mb_x]+16)= *(uint64_t*)(src_cb+16*uvlinesize);
+ *(uint64_t*)(h->top_borders[0][s->mb_x]+24)= *(uint64_t*)(src_cr+16*uvlinesize);
+ *(uint64_t*)(h->top_borders[1][s->mb_x]+16)= *(uint64_t*)(src_cb+17*uvlinesize);
+ *(uint64_t*)(h->top_borders[1][s->mb_x]+24)= *(uint64_t*)(src_cr+17*uvlinesize);
+ }
+}
+
+static inline void xchg_pair_border(H264Context *h, uint8_t *src_y, uint8_t *src_cb, uint8_t *src_cr, int linesize, int uvlinesize, int xchg){
+ MpegEncContext * const s = &h->s;
+ int temp8, i;
+ uint64_t temp64;
+ int deblock_left = (s->mb_x > 0);
+ int deblock_top = (s->mb_y > 1);
+
+ tprintf("xchg_pair_border: src_y:%p src_cb:%p src_cr:%p ls:%d uvls:%d\n", src_y, src_cb, src_cr, linesize, uvlinesize);
+
+ src_y -= 2 * linesize + 1;
+ src_cb -= 2 * uvlinesize + 1;
+ src_cr -= 2 * uvlinesize + 1;
+
+#define XCHG(a,b,t,xchg)\
+t= a;\
+if(xchg)\
+ a= b;\
+b= t;
+
+ if(deblock_left){
+ for(i = (!deblock_top)<<1; i<34; i++){
+ XCHG(h->left_border[i ], src_y [i* linesize], temp8, xchg);
+ }
+ }
+
+ if(deblock_top){
+ XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x]+0), *(uint64_t*)(src_y +1), temp64, xchg);
+ XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x]+8), *(uint64_t*)(src_y +9), temp64, 1);
+ XCHG(*(uint64_t*)(h->top_borders[1][s->mb_x]+0), *(uint64_t*)(src_y +1 +linesize), temp64, xchg);
+ XCHG(*(uint64_t*)(h->top_borders[1][s->mb_x]+8), *(uint64_t*)(src_y +9 +linesize), temp64, 1);
+ if(s->mb_x+1 < s->mb_width){
+ XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x+1]), *(uint64_t*)(src_y +17), temp64, 1);
+ XCHG(*(uint64_t*)(h->top_borders[1][s->mb_x+1]), *(uint64_t*)(src_y +17 +linesize), temp64, 1);
+ }
+ }
+
+ if(!(s->flags&CODEC_FLAG_GRAY)){
+ if(deblock_left){
+ for(i = (!deblock_top) << 1; i<18; i++){
+ XCHG(h->left_border[i+34 ], src_cb[i*uvlinesize], temp8, xchg);
+ XCHG(h->left_border[i+34+18], src_cr[i*uvlinesize], temp8, xchg);
+ }
+ }
+ if(deblock_top){
+ XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x]+16), *(uint64_t*)(src_cb+1), temp64, 1);
+ XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x]+24), *(uint64_t*)(src_cr+1), temp64, 1);
+ XCHG(*(uint64_t*)(h->top_borders[1][s->mb_x]+16), *(uint64_t*)(src_cb+1 +uvlinesize), temp64, 1);
+ XCHG(*(uint64_t*)(h->top_borders[1][s->mb_x]+24), *(uint64_t*)(src_cr+1 +uvlinesize), temp64, 1);
+ }
+ }
+}
+
+static void hl_decode_mb(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ const int mb_x= s->mb_x;
+ const int mb_y= s->mb_y;
+ const int mb_xy= mb_x + mb_y*s->mb_stride;
+ const int mb_type= s->current_picture.mb_type[mb_xy];
+ uint8_t *dest_y, *dest_cb, *dest_cr;
+ int linesize, uvlinesize /*dct_offset*/;
+ int i;
+ int *block_offset = &h->block_offset[0];
+ const unsigned int bottom = mb_y & 1;
+ const int transform_bypass = (s->qscale == 0 && h->sps.transform_bypass);
+ void (*idct_add)(uint8_t *dst, DCTELEM *block, int stride);
+ void (*idct_dc_add)(uint8_t *dst, DCTELEM *block, int stride);
+
+ if(!s->decode)
+ return;
+
+ dest_y = s->current_picture.data[0] + (mb_y * 16* s->linesize ) + mb_x * 16;
+ dest_cb = s->current_picture.data[1] + (mb_y * 8 * s->uvlinesize) + mb_x * 8;
+ dest_cr = s->current_picture.data[2] + (mb_y * 8 * s->uvlinesize) + mb_x * 8;
+
+ s->dsp.prefetch(dest_y + (s->mb_x&3)*4*s->linesize + 64, s->linesize, 4);
+ s->dsp.prefetch(dest_cb + (s->mb_x&7)*s->uvlinesize + 64, dest_cr - dest_cb, 2);
+
+ if (MB_FIELD) {
+ linesize = h->mb_linesize = s->linesize * 2;
+ uvlinesize = h->mb_uvlinesize = s->uvlinesize * 2;
+ block_offset = &h->block_offset[24];
+ if(mb_y&1){ //FIXME move out of this func?
+ dest_y -= s->linesize*15;
+ dest_cb-= s->uvlinesize*7;
+ dest_cr-= s->uvlinesize*7;
+ }
+ if(FRAME_MBAFF) {
+ int list;
+ for(list=0; list<2; 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^(s->mb_y&1), 1);
+ }else{
+ for(i=0; i<16; i+=4){
+ //FIXME can refs be smaller than 8x8 when !direct_8x8_inference ?
+ int ref = h->ref_cache[list][scan8[i]];
+ if(ref >= 0)
+ fill_rectangle(&h->ref_cache[list][scan8[i]], 2, 2, 8, 16+ref^(s->mb_y&1), 1);
+ }
+ }
+ }
+ }
+ } else {
+ linesize = h->mb_linesize = s->linesize;
+ uvlinesize = h->mb_uvlinesize = s->uvlinesize;
+// dct_offset = s->linesize * 16;
+ }
+
+ if(transform_bypass){
+ idct_dc_add =
+ idct_add = IS_8x8DCT(mb_type) ? s->dsp.add_pixels8 : s->dsp.add_pixels4;
+ }else if(IS_8x8DCT(mb_type)){
+ idct_dc_add = s->dsp.h264_idct8_dc_add;
+ idct_add = s->dsp.h264_idct8_add;
+ }else{
+ idct_dc_add = s->dsp.h264_idct_dc_add;
+ idct_add = s->dsp.h264_idct_add;
+ }
+
+ if(FRAME_MBAFF && h->deblocking_filter && IS_INTRA(mb_type)
+ && (!bottom || !IS_INTRA(s->current_picture.mb_type[mb_xy-s->mb_stride]))){
+ int mbt_y = mb_y&~1;
+ uint8_t *top_y = s->current_picture.data[0] + (mbt_y * 16* s->linesize ) + mb_x * 16;
+ uint8_t *top_cb = s->current_picture.data[1] + (mbt_y * 8 * s->uvlinesize) + mb_x * 8;
+ uint8_t *top_cr = s->current_picture.data[2] + (mbt_y * 8 * s->uvlinesize) + mb_x * 8;
+ xchg_pair_border(h, top_y, top_cb, top_cr, s->linesize, s->uvlinesize, 1);
+ }
+
+ if (IS_INTRA_PCM(mb_type)) {
+ unsigned int x, y;
+
+ // The pixels are stored in h->mb array in the same order as levels,
+ // copy them in output in the correct order.
+ for(i=0; i<16; i++) {
+ for (y=0; y<4; y++) {
+ for (x=0; x<4; x++) {
+ *(dest_y + block_offset[i] + y*linesize + x) = h->mb[i*16+y*4+x];
+ }
+ }
+ }
+ for(i=16; i<16+4; i++) {
+ for (y=0; y<4; y++) {
+ for (x=0; x<4; x++) {
+ *(dest_cb + block_offset[i] + y*uvlinesize + x) = h->mb[i*16+y*4+x];
+ }
+ }
+ }
+ for(i=20; i<20+4; i++) {
+ for (y=0; y<4; y++) {
+ for (x=0; x<4; x++) {
+ *(dest_cr + block_offset[i] + y*uvlinesize + x) = h->mb[i*16+y*4+x];
+ }
+ }
+ }
+ } else {
+ if(IS_INTRA(mb_type)){
+ if(h->deblocking_filter && !FRAME_MBAFF)
+ xchg_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize, 1);
+
+ if(!(s->flags&CODEC_FLAG_GRAY)){
+ h->pred8x8[ h->chroma_pred_mode ](dest_cb, uvlinesize);
+ h->pred8x8[ h->chroma_pred_mode ](dest_cr, uvlinesize);
+ }
+
+ if(IS_INTRA4x4(mb_type)){
+ if(!s->encoding){
+ if(IS_8x8DCT(mb_type)){
+ 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] ];
+ const int nnz = h->non_zero_count_cache[ scan8[i] ];
+ h->pred8x8l[ dir ](ptr, (h->topleft_samples_available<<i)&0x8000,
+ (h->topright_samples_available<<(i+1))&0x8000, linesize);
+ if(nnz){
+ if(nnz == 1 && h->mb[i*16])
+ idct_dc_add(ptr, h->mb + i*16, linesize);
+ else
+ idct_add(ptr, h->mb + i*16, linesize);
+ }
+ }
+ }else
+ for(i=0; i<16; i++){
+ uint8_t * const ptr= dest_y + block_offset[i];
+ uint8_t *topright;
+ const int dir= h->intra4x4_pred_mode_cache[ scan8[i] ];
+ int nnz, tr;
+
+ if(dir == DIAG_DOWN_LEFT_PRED || dir == VERT_LEFT_PRED){
+ const int topright_avail= (h->topright_samples_available<<i)&0x8000;
+ assert(mb_y || linesize <= block_offset[i]);
+ if(!topright_avail){
+ tr= ptr[3 - linesize]*0x01010101;
+ topright= (uint8_t*) &tr;
+ }else
+ topright= ptr + 4 - linesize;
+ }else
+ topright= NULL;
+
+ h->pred4x4[ dir ](ptr, topright, linesize);
+ nnz = h->non_zero_count_cache[ scan8[i] ];
+ if(nnz){
+ if(s->codec_id == CODEC_ID_H264){
+ if(nnz == 1 && h->mb[i*16])
+ idct_dc_add(ptr, h->mb + i*16, linesize);
+ else
+ idct_add(ptr, h->mb + i*16, linesize);
+ }else
+ svq3_add_idct_c(ptr, h->mb + i*16, linesize, s->qscale, 0);
+ }
+ }
+ }
+ }else{
+ h->pred16x16[ h->intra16x16_pred_mode ](dest_y , linesize);
+ if(s->codec_id == CODEC_ID_H264){
+ if(!transform_bypass)
+ h264_luma_dc_dequant_idct_c(h->mb, s->qscale, h->dequant4_coeff[IS_INTRA(mb_type) ? 0:3][s->qscale][0]);
+ }else
+ svq3_luma_dc_dequant_idct_c(h->mb, s->qscale);
+ }
+ if(h->deblocking_filter && !FRAME_MBAFF)
+ xchg_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize, 0);
+ }else if(s->codec_id == CODEC_ID_H264){
+ hl_motion(h, dest_y, dest_cb, dest_cr,
+ s->me.qpel_put, s->dsp.put_h264_chroma_pixels_tab,
+ s->me.qpel_avg, s->dsp.avg_h264_chroma_pixels_tab,
+ s->dsp.weight_h264_pixels_tab, s->dsp.biweight_h264_pixels_tab);
+ }
+
+
+ if(!IS_INTRA4x4(mb_type)){
+ if(s->codec_id == CODEC_ID_H264){
+ if(IS_INTRA16x16(mb_type)){
+ for(i=0; i<16; i++){
+ if(h->non_zero_count_cache[ scan8[i] ])
+ idct_add(dest_y + block_offset[i], h->mb + i*16, linesize);
+ else if(h->mb[i*16])
+ idct_dc_add(dest_y + block_offset[i], h->mb + i*16, linesize);
+ }
+ }else{
+ const int di = IS_8x8DCT(mb_type) ? 4 : 1;
+ for(i=0; i<16; i+=di){
+ int nnz = h->non_zero_count_cache[ scan8[i] ];
+ if(nnz){
+ if(nnz==1 && h->mb[i*16])
+ idct_dc_add(dest_y + block_offset[i], h->mb + i*16, linesize);
+ else
+ idct_add(dest_y + block_offset[i], h->mb + i*16, linesize);
+ }
+ }
+ }
+ }else{
+ for(i=0; i<16; i++){
+ if(h->non_zero_count_cache[ scan8[i] ] || h->mb[i*16]){ //FIXME benchmark weird rule, & below
+ uint8_t * const ptr= dest_y + block_offset[i];
+ svq3_add_idct_c(ptr, h->mb + i*16, linesize, s->qscale, IS_INTRA(mb_type) ? 1 : 0);
+ }
+ }
+ }
+ }
+
+ if(!(s->flags&CODEC_FLAG_GRAY)){
+ uint8_t *dest[2] = {dest_cb, dest_cr};
+ if(transform_bypass){
+ idct_add = idct_dc_add = s->dsp.add_pixels4;
+ }else{
+ idct_add = s->dsp.h264_idct_add;
+ idct_dc_add = s->dsp.h264_idct_dc_add;
+ chroma_dc_dequant_idct_c(h->mb + 16*16, h->chroma_qp, h->dequant4_coeff[IS_INTRA(mb_type) ? 1:4][h->chroma_qp][0]);
+ chroma_dc_dequant_idct_c(h->mb + 16*16+4*16, h->chroma_qp, h->dequant4_coeff[IS_INTRA(mb_type) ? 2:5][h->chroma_qp][0]);
+ }
+ if(s->codec_id == CODEC_ID_H264){
+ for(i=16; i<16+8; i++){
+ if(h->non_zero_count_cache[ scan8[i] ])
+ idct_add(dest[(i&4)>>2] + block_offset[i], h->mb + i*16, uvlinesize);
+ else if(h->mb[i*16])
+ idct_dc_add(dest[(i&4)>>2] + block_offset[i], h->mb + i*16, uvlinesize);
+ }
+ }else{
+ for(i=16; i<16+8; i++){
+ if(h->non_zero_count_cache[ scan8[i] ] || h->mb[i*16]){
+ uint8_t * const ptr= dest[(i&4)>>2] + block_offset[i];
+ svq3_add_idct_c(ptr, h->mb + i*16, uvlinesize, chroma_qp[s->qscale + 12] - 12, 2);
+ }
+ }
+ }
+ }
+ }
+ if(h->deblocking_filter) {
+ if (FRAME_MBAFF) {
+ //FIXME try deblocking one mb at a time?
+ // the reduction in load/storing mvs and such might outweigh the extra backup/xchg_border
+ const int mb_y = s->mb_y - 1;
+ uint8_t *pair_dest_y, *pair_dest_cb, *pair_dest_cr;
+ const int mb_xy= mb_x + mb_y*s->mb_stride;
+ const int mb_type_top = s->current_picture.mb_type[mb_xy];
+ const int mb_type_bottom= s->current_picture.mb_type[mb_xy+s->mb_stride];
+ if (!bottom) return;
+ pair_dest_y = s->current_picture.data[0] + (mb_y * 16* s->linesize ) + mb_x * 16;
+ pair_dest_cb = s->current_picture.data[1] + (mb_y * 8 * s->uvlinesize) + mb_x * 8;
+ pair_dest_cr = s->current_picture.data[2] + (mb_y * 8 * s->uvlinesize) + mb_x * 8;
+
+ if(IS_INTRA(mb_type_top | mb_type_bottom))
+ xchg_pair_border(h, pair_dest_y, pair_dest_cb, pair_dest_cr, s->linesize, s->uvlinesize, 0);
+
+ backup_pair_border(h, pair_dest_y, pair_dest_cb, pair_dest_cr, s->linesize, s->uvlinesize);
+ // deblock a pair
+ // top
+ s->mb_y--;
+ tprintf("call mbaff filter_mb mb_x:%d mb_y:%d pair_dest_y = %p, dest_y = %p\n", mb_x, mb_y, pair_dest_y, dest_y);
+ fill_caches(h, mb_type_top, 1); //FIXME don't fill stuff which isn't used by filter_mb
+ h->chroma_qp = get_chroma_qp(h->pps.chroma_qp_index_offset, s->current_picture.qscale_table[mb_xy]);
+ filter_mb(h, mb_x, mb_y, pair_dest_y, pair_dest_cb, pair_dest_cr, linesize, uvlinesize);
+ // bottom
+ s->mb_y++;
+ tprintf("call mbaff filter_mb\n");
+ fill_caches(h, mb_type_bottom, 1); //FIXME don't fill stuff which isn't used by filter_mb
+ h->chroma_qp = get_chroma_qp(h->pps.chroma_qp_index_offset, s->current_picture.qscale_table[mb_xy+s->mb_stride]);
+ filter_mb(h, mb_x, mb_y+1, dest_y, dest_cb, dest_cr, linesize, uvlinesize);
+ } else {
+ tprintf("call filter_mb\n");
+ backup_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize);
+ fill_caches(h, mb_type, 1); //FIXME don't fill stuff which isn't used by filter_mb
+ filter_mb_fast(h, mb_x, mb_y, dest_y, dest_cb, dest_cr, linesize, uvlinesize);
+ }
+ }
+}
+
+/**
+ * fills the default_ref_list.
+ */
+static int fill_default_ref_list(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ int i;
+ int smallest_poc_greater_than_current = -1;
+ Picture sorted_short_ref[32];
+
+ if(h->slice_type==B_TYPE){
+ int out_i;
+ int limit= INT_MIN;
+
+ /* sort frame according to poc in B slice */
+ for(out_i=0; out_i<h->short_ref_count; out_i++){
+ int best_i=INT_MIN;
+ int best_poc=INT_MAX;
+
+ for(i=0; i<h->short_ref_count; i++){
+ const int poc= h->short_ref[i]->poc;
+ if(poc > limit && poc < best_poc){
+ best_poc= poc;
+ best_i= i;
+ }
+ }
+
+ assert(best_i != INT_MIN);
+
+ limit= best_poc;
+ sorted_short_ref[out_i]= *h->short_ref[best_i];
+ tprintf("sorted poc: %d->%d poc:%d fn:%d\n", best_i, out_i, sorted_short_ref[out_i].poc, sorted_short_ref[out_i].frame_num);
+ if (-1 == smallest_poc_greater_than_current) {
+ if (h->short_ref[best_i]->poc >= s->current_picture_ptr->poc) {
+ smallest_poc_greater_than_current = out_i;
+ }
+ }
+ }
+ }
+
+ if(s->picture_structure == PICT_FRAME){
+ if(h->slice_type==B_TYPE){
+ int list;
+ tprintf("current poc: %d, smallest_poc_greater_than_current: %d\n", s->current_picture_ptr->poc, smallest_poc_greater_than_current);
+
+ // find the largest poc
+ for(list=0; list<2; list++){
+ int index = 0;
+ int j= -99;
+ int step= list ? -1 : 1;
+
+ for(i=0; i<h->short_ref_count && index < h->ref_count[list]; i++, j+=step) {
+ while(j<0 || j>= h->short_ref_count){
+ if(j != -99 && step == (list ? -1 : 1))
+ return -1;
+ step = -step;
+ j= smallest_poc_greater_than_current + (step>>1);
+ }
+ if(sorted_short_ref[j].reference != 3) continue;
+ h->default_ref_list[list][index ]= sorted_short_ref[j];
+ h->default_ref_list[list][index++].pic_id= sorted_short_ref[j].frame_num;
+ }
+
+ for(i = 0; i < 16 && index < h->ref_count[ list ]; i++){
+ if(h->long_ref[i] == NULL) continue;
+ if(h->long_ref[i]->reference != 3) continue;
+
+ h->default_ref_list[ list ][index ]= *h->long_ref[i];
+ h->default_ref_list[ list ][index++].pic_id= i;;
+ }
+
+ if(list && (smallest_poc_greater_than_current<=0 || smallest_poc_greater_than_current>=h->short_ref_count) && (1 < index)){
+ // swap the two first elements of L1 when
+ // L0 and L1 are identical
+ Picture temp= h->default_ref_list[1][0];
+ h->default_ref_list[1][0] = h->default_ref_list[1][1];
+ h->default_ref_list[1][1] = temp;
+ }
+
+ if(index < h->ref_count[ list ])
+ memset(&h->default_ref_list[list][index], 0, sizeof(Picture)*(h->ref_count[ list ] - index));
+ }
+ }else{
+ int index=0;
+ for(i=0; i<h->short_ref_count; i++){
+ if(h->short_ref[i]->reference != 3) continue; //FIXME refernce field shit
+ h->default_ref_list[0][index ]= *h->short_ref[i];
+ h->default_ref_list[0][index++].pic_id= h->short_ref[i]->frame_num;
+ }
+ for(i = 0; i < 16; i++){
+ if(h->long_ref[i] == NULL) continue;
+ if(h->long_ref[i]->reference != 3) continue;
+ h->default_ref_list[0][index ]= *h->long_ref[i];
+ h->default_ref_list[0][index++].pic_id= i;;
+ }
+ if(index < h->ref_count[0])
+ memset(&h->default_ref_list[0][index], 0, sizeof(Picture)*(h->ref_count[0] - index));
+ }
+ }else{ //FIELD
+ if(h->slice_type==B_TYPE){
+ }else{
+ //FIXME second field balh
+ }
+ }
+#ifdef TRACE
+ for (i=0; i<h->ref_count[0]; i++) {
+ tprintf("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].data[0]);
+ }
+ if(h->slice_type==B_TYPE){
+ for (i=0; i<h->ref_count[1]; i++) {
+ tprintf("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[0][i].data[0]);
+ }
+ }
+#endif
+ return 0;
+}
+
+static void print_short_term(H264Context *h);
+static void print_long_term(H264Context *h);
+
+static int decode_ref_pic_list_reordering(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ int list, index;
+
+ print_short_term(h);
+ print_long_term(h);
+ if(h->slice_type==I_TYPE || h->slice_type==SI_TYPE) return 0; //FIXME move before func
+
+ for(list=0; list<2; list++){
+ memcpy(h->ref_list[list], h->default_ref_list[list], sizeof(Picture)*h->ref_count[list]);
+
+ if(get_bits1(&s->gb)){
+ int pred= h->curr_pic_num;
+
+ for(index=0; ; index++){
+ int reordering_of_pic_nums_idc= get_ue_golomb(&s->gb);
+ 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->s.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 int abs_diff_pic_num= get_ue_golomb(&s->gb) + 1;
+
+ if(abs_diff_pic_num >= h->max_pic_num){
+ av_log(h->s.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;
+
+ for(i= h->short_ref_count-1; i>=0; i--){
+ ref = h->short_ref[i];
+ assert(ref->reference == 3);
+ assert(!ref->long_ref);
+ if(ref->data[0] != NULL && ref->frame_num == pred && ref->long_ref == 0) // ignore non existing pictures by testing data[0] pointer
+ break;
+ }
+ if(i>=0)
+ ref->pic_id= ref->frame_num;
+ }else{
+ pic_id= get_ue_golomb(&s->gb); //long_term_pic_idx
+ ref = h->long_ref[pic_id];
+ ref->pic_id= pic_id;
+ assert(ref->reference == 3);
+ assert(ref->long_ref);
+ i=0;
+ }
+
+ if (i < 0) {
+ av_log(h->s.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--){
+ h->ref_list[list][i]= h->ref_list[list][i-1];
+ }
+ h->ref_list[list][index]= *ref;
+ }
+ }else{
+ av_log(h->s.avctx, AV_LOG_ERROR, "illegal reordering_of_pic_nums_idc\n");
+ return -1;
+ }
+ }
+ }
+
+ if(h->slice_type!=B_TYPE) break;
+ }
+ for(list=0; list<2; list++){
+ for(index= 0; index < h->ref_count[list]; index++){
+ if(!h->ref_list[list][index].data[0])
+ h->ref_list[list][index]= s->current_picture;
+ }
+ if(h->slice_type!=B_TYPE) break;
+ }
+
+ if(h->slice_type==B_TYPE && !h->direct_spatial_mv_pred)
+ direct_dist_scale_factor(h);
+ direct_ref_list_init(h);
+ return 0;
+}
+
+static void fill_mbaff_ref_list(H264Context *h){
+ int list, i, j;
+ for(list=0; list<2; 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];
+ field[0] = *frame;
+ for(j=0; j<3; j++)
+ field[0].linesize[j] <<= 1;
+ field[1] = field[0];
+ for(j=0; j<3; j++)
+ field[1].data[j] += frame->linesize[j];
+
+ h->luma_weight[list][16+2*i] = h->luma_weight[list][16+2*i+1] = h->luma_weight[list][i];
+ h->luma_offset[list][16+2*i] = h->luma_offset[list][16+2*i+1] = h->luma_offset[list][i];
+ for(j=0; j<2; j++){
+ h->chroma_weight[list][16+2*i][j] = h->chroma_weight[list][16+2*i+1][j] = h->chroma_weight[list][i][j];
+ h->chroma_offset[list][16+2*i][j] = h->chroma_offset[list][16+2*i+1][j] = h->chroma_offset[list][i][j];
+ }
+ }
+ }
+ for(j=0; j<h->ref_count[1]; j++){
+ for(i=0; i<h->ref_count[0]; i++)
+ h->implicit_weight[j][16+2*i] = h->implicit_weight[j][16+2*i+1] = h->implicit_weight[j][i];
+ memcpy(h->implicit_weight[16+2*j], h->implicit_weight[j], sizeof(*h->implicit_weight));
+ memcpy(h->implicit_weight[16+2*j+1], h->implicit_weight[j], sizeof(*h->implicit_weight));
+ }
+}
+
+static int pred_weight_table(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ 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(&s->gb);
+ h->chroma_log2_weight_denom= get_ue_golomb(&s->gb);
+ luma_def = 1<<h->luma_log2_weight_denom;
+ chroma_def = 1<<h->chroma_log2_weight_denom;
+
+ for(list=0; list<2; list++){
+ for(i=0; i<h->ref_count[list]; i++){
+ int luma_weight_flag, chroma_weight_flag;
+
+ luma_weight_flag= get_bits1(&s->gb);
+ if(luma_weight_flag){
+ h->luma_weight[list][i]= get_se_golomb(&s->gb);
+ h->luma_offset[list][i]= get_se_golomb(&s->gb);
+ if( h->luma_weight[list][i] != luma_def
+ || h->luma_offset[list][i] != 0)
+ h->use_weight= 1;
+ }else{
+ h->luma_weight[list][i]= luma_def;
+ h->luma_offset[list][i]= 0;
+ }
+
+ chroma_weight_flag= get_bits1(&s->gb);
+ if(chroma_weight_flag){
+ int j;
+ for(j=0; j<2; j++){
+ h->chroma_weight[list][i][j]= get_se_golomb(&s->gb);
+ h->chroma_offset[list][i][j]= get_se_golomb(&s->gb);
+ if( h->chroma_weight[list][i][j] != chroma_def
+ || h->chroma_offset[list][i][j] != 0)
+ h->use_weight_chroma= 1;
+ }
+ }else{
+ int j;
+ for(j=0; j<2; j++){
+ h->chroma_weight[list][i][j]= chroma_def;
+ h->chroma_offset[list][i][j]= 0;
+ }
+ }
+ }
+ if(h->slice_type != B_TYPE) break;
+ }
+ h->use_weight= h->use_weight || h->use_weight_chroma;
+ return 0;
+}
+
+static void implicit_weight_table(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ int ref0, ref1;
+ int cur_poc = s->current_picture_ptr->poc;
+
+ if( h->ref_count[0] == 1 && h->ref_count[1] == 1
+ && 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;
+ }
+
+ h->use_weight= 2;
+ h->use_weight_chroma= 2;
+ h->luma_log2_weight_denom= 5;
+ h->chroma_log2_weight_denom= 5;
+
+ for(ref0=0; ref0 < h->ref_count[0]; ref0++){
+ int poc0 = h->ref_list[0][ref0].poc;
+ for(ref1=0; ref1 < h->ref_count[1]; ref1++){
+ int poc1 = h->ref_list[1][ref1].poc;
+ int td = clip(poc1 - poc0, -128, 127);
+ if(td){
+ int tb = clip(cur_poc - poc0, -128, 127);
+ int tx = (16384 + (FFABS(td) >> 1)) / td;
+ int dist_scale_factor = clip((tb*tx + 32) >> 6, -1024, 1023) >> 2;
+ if(dist_scale_factor < -64 || dist_scale_factor > 128)
+ h->implicit_weight[ref0][ref1] = 32;
+ else
+ h->implicit_weight[ref0][ref1] = 64 - dist_scale_factor;
+ }else
+ h->implicit_weight[ref0][ref1] = 32;
+ }
+ }
+}
+
+static inline void unreference_pic(H264Context *h, Picture *pic){
+ int i;
+ pic->reference=0;
+ if(pic == h->delayed_output_pic)
+ pic->reference=1;
+ else{
+ for(i = 0; h->delayed_pic[i]; i++)
+ if(pic == h->delayed_pic[i]){
+ pic->reference=1;
+ break;
+ }
+ }
+}
+
+/**
+ * instantaneous decoder refresh.
+ */
+static void idr(H264Context *h){
+ int i;
+
+ for(i=0; i<16; i++){
+ if (h->long_ref[i] != NULL) {
+ unreference_pic(h, h->long_ref[i]);
+ h->long_ref[i]= NULL;
+ }
+ }
+ h->long_ref_count=0;
+
+ for(i=0; i<h->short_ref_count; i++){
+ unreference_pic(h, h->short_ref[i]);
+ h->short_ref[i]= NULL;
+ }
+ h->short_ref_count=0;
+}
+
+/* forget old pics after a seek */
+static void flush_dpb(AVCodecContext *avctx){
+ H264Context *h= avctx->priv_data;
+ int i;
+ for(i=0; i<16; i++) {
+ if(h->delayed_pic[i])
+ h->delayed_pic[i]->reference= 0;
+ h->delayed_pic[i]= NULL;
+ }
+ if(h->delayed_output_pic)
+ h->delayed_output_pic->reference= 0;
+ h->delayed_output_pic= NULL;
+ idr(h);
+ if(h->s.current_picture_ptr)
+ h->s.current_picture_ptr->reference= 0;
+}
+
+/**
+ *
+ * @return the removed picture or NULL if an error occurs
+ */
+static Picture * remove_short(H264Context *h, int frame_num){
+ MpegEncContext * const s = &h->s;
+ int i;
+
+ if(s->avctx->debug&FF_DEBUG_MMCO)
+ av_log(h->s.avctx, AV_LOG_DEBUG, "remove short %d count %d\n", frame_num, h->short_ref_count);
+
+ for(i=0; i<h->short_ref_count; i++){
+ Picture *pic= h->short_ref[i];
+ if(s->avctx->debug&FF_DEBUG_MMCO)
+ av_log(h->s.avctx, AV_LOG_DEBUG, "%d %d %p\n", i, pic->frame_num, pic);
+ if(pic->frame_num == frame_num){
+ h->short_ref[i]= NULL;
+ memmove(&h->short_ref[i], &h->short_ref[i+1], (h->short_ref_count - i - 1)*sizeof(Picture*));
+ h->short_ref_count--;
+ return pic;
+ }
+ }
+ return NULL;
+}
+
+/**
+ *
+ * @return the removed picture or NULL if an error occurs
+ */
+static Picture * remove_long(H264Context *h, int i){
+ Picture *pic;
+
+ pic= h->long_ref[i];
+ h->long_ref[i]= NULL;
+ if(pic) h->long_ref_count--;
+
+ return pic;
+}
+
+/**
+ * print short term list
+ */
+static void print_short_term(H264Context *h) {
+ uint32_t i;
+ if(h->s.avctx->debug&FF_DEBUG_MMCO) {
+ av_log(h->s.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->s.avctx, AV_LOG_DEBUG, "%d fn:%d poc:%d %p\n", i, pic->frame_num, pic->poc, pic->data[0]);
+ }
+ }
+}
+
+/**
+ * print long term list
+ */
+static void print_long_term(H264Context *h) {
+ uint32_t i;
+ if(h->s.avctx->debug&FF_DEBUG_MMCO) {
+ av_log(h->s.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->s.avctx, AV_LOG_DEBUG, "%d fn:%d poc:%d %p\n", i, pic->frame_num, pic->poc, pic->data[0]);
+ }
+ }
+ }
+}
+
+/**
+ * Executes the reference picture marking (memory management control operations).
+ */
+static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){
+ MpegEncContext * const s = &h->s;
+ int i, j;
+ int current_is_long=0;
+ Picture *pic;
+
+ if((s->avctx->debug&FF_DEBUG_MMCO) && mmco_count==0)
+ av_log(h->s.avctx, AV_LOG_DEBUG, "no mmco here\n");
+
+ for(i=0; i<mmco_count; i++){
+ if(s->avctx->debug&FF_DEBUG_MMCO)
+ av_log(h->s.avctx, AV_LOG_DEBUG, "mmco:%d %d %d\n", h->mmco[i].opcode, h->mmco[i].short_frame_num, h->mmco[i].long_index);
+
+ switch(mmco[i].opcode){
+ case MMCO_SHORT2UNUSED:
+ pic= remove_short(h, mmco[i].short_frame_num);
+ if(pic)
+ unreference_pic(h, pic);
+ else if(s->avctx->debug&FF_DEBUG_MMCO)
+ av_log(h->s.avctx, AV_LOG_DEBUG, "mmco: remove_short() failure\n");
+ break;
+ case MMCO_SHORT2LONG:
+ pic= remove_long(h, mmco[i].long_index);
+ if(pic) unreference_pic(h, pic);
+
+ h->long_ref[ mmco[i].long_index ]= remove_short(h, mmco[i].short_frame_num);
+ h->long_ref[ mmco[i].long_index ]->long_ref=1;
+ h->long_ref_count++;
+ break;
+ case MMCO_LONG2UNUSED:
+ pic= remove_long(h, mmco[i].long_index);
+ if(pic)
+ unreference_pic(h, pic);
+ else if(s->avctx->debug&FF_DEBUG_MMCO)
+ av_log(h->s.avctx, AV_LOG_DEBUG, "mmco: remove_long() failure\n");
+ break;
+ case MMCO_LONG:
+ pic= remove_long(h, mmco[i].long_index);
+ if(pic) unreference_pic(h, pic);
+
+ h->long_ref[ mmco[i].long_index ]= s->current_picture_ptr;
+ h->long_ref[ mmco[i].long_index ]->long_ref=1;
+ h->long_ref_count++;
+
+ current_is_long=1;
+ break;
+ case MMCO_SET_MAX_LONG:
+ assert(mmco[i].long_index <= 16);
+ // just remove the long term which index is greater than new max
+ for(j = mmco[i].long_index; j<16; j++){
+ pic = remove_long(h, j);
+ if (pic) unreference_pic(h, pic);
+ }
+ break;
+ case MMCO_RESET:
+ while(h->short_ref_count){
+ pic= remove_short(h, h->short_ref[0]->frame_num);
+ unreference_pic(h, pic);
+ }
+ for(j = 0; j < 16; j++) {
+ pic= remove_long(h, j);
+ if(pic) unreference_pic(h, pic);
+ }
+ break;
+ default: assert(0);
+ }
+ }
+
+ if(!current_is_long){
+ pic= remove_short(h, s->current_picture_ptr->frame_num);
+ if(pic){
+ unreference_pic(h, pic);
+ av_log(h->s.avctx, AV_LOG_ERROR, "illegal short term buffer state detected\n");
+ }
+
+ if(h->short_ref_count)
+ memmove(&h->short_ref[1], &h->short_ref[0], h->short_ref_count*sizeof(Picture*));
+
+ h->short_ref[0]= s->current_picture_ptr;
+ h->short_ref[0]->long_ref=0;
+ h->short_ref_count++;
+ }
+
+ print_short_term(h);
+ print_long_term(h);
+ return 0;
+}
+
+static int decode_ref_pic_marking(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ int i;
+
+ if(h->nal_unit_type == NAL_IDR_SLICE){ //FIXME fields
+ s->broken_link= get_bits1(&s->gb) -1;
+ h->mmco[0].long_index= get_bits1(&s->gb) - 1; // current_long_term_idx
+ if(h->mmco[0].long_index == -1)
+ h->mmco_index= 0;
+ else{
+ h->mmco[0].opcode= MMCO_LONG;
+ h->mmco_index= 1;
+ }
+ }else{
+ if(get_bits1(&s->gb)){ // adaptive_ref_pic_marking_mode_flag
+ for(i= 0; i<MAX_MMCO_COUNT; i++) {
+ MMCOOpcode opcode= get_ue_golomb(&s->gb);;
+
+ h->mmco[i].opcode= opcode;
+ if(opcode==MMCO_SHORT2UNUSED || opcode==MMCO_SHORT2LONG){
+ h->mmco[i].short_frame_num= (h->frame_num - get_ue_golomb(&s->gb) - 1) & ((1<<h->sps.log2_max_frame_num)-1); //FIXME fields
+/* if(h->mmco[i].short_frame_num >= h->short_ref_count || h->short_ref[ h->mmco[i].short_frame_num ] == NULL){
+ av_log(s->avctx, AV_LOG_ERROR, "illegal short ref in memory management control operation %d\n", mmco);
+ return -1;
+ }*/
+ }
+ if(opcode==MMCO_SHORT2LONG || opcode==MMCO_LONG2UNUSED || opcode==MMCO_LONG || opcode==MMCO_SET_MAX_LONG){
+ h->mmco[i].long_index= get_ue_golomb(&s->gb);
+ if(/*h->mmco[i].long_index >= h->long_ref_count || h->long_ref[ h->mmco[i].long_index ] == NULL*/ h->mmco[i].long_index >= 16){
+ av_log(h->s.avctx, AV_LOG_ERROR, "illegal long ref in memory management control operation %d\n", opcode);
+ return -1;
+ }
+ }
+
+ if(opcode > MMCO_LONG){
+ av_log(h->s.avctx, AV_LOG_ERROR, "illegal memory management control operation %d\n", opcode);
+ return -1;
+ }
+ if(opcode == MMCO_END)
+ break;
+ }
+ h->mmco_index= i;
+ }else{
+ assert(h->long_ref_count + h->short_ref_count <= h->sps.ref_frame_count);
+
+ if(h->long_ref_count + h->short_ref_count == h->sps.ref_frame_count){ //FIXME fields
+ h->mmco[0].opcode= MMCO_SHORT2UNUSED;
+ h->mmco[0].short_frame_num= h->short_ref[ h->short_ref_count - 1 ]->frame_num;
+ h->mmco_index= 1;
+ }else
+ h->mmco_index= 0;
+ }
+ }
+
+ return 0;
+}
+
+static int init_poc(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ const int max_frame_num= 1<<h->sps.log2_max_frame_num;
+ int field_poc[2];
+
+ if(h->nal_unit_type == NAL_IDR_SLICE){
+ h->frame_num_offset= 0;
+ }else{
+ if(h->frame_num < h->prev_frame_num)
+ h->frame_num_offset= h->prev_frame_num_offset + max_frame_num;
+ else
+ h->frame_num_offset= h->prev_frame_num_offset;
+ }
+
+ if(h->sps.poc_type==0){
+ const int max_poc_lsb= 1<<h->sps.log2_max_poc_lsb;
+
+ if(h->nal_unit_type == NAL_IDR_SLICE){
+ h->prev_poc_msb=
+ h->prev_poc_lsb= 0;
+ }
+
+ 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;
+//printf("poc: %d %d\n", h->poc_msb, h->poc_lsb);
+ field_poc[0] =
+ field_poc[1] = h->poc_msb + h->poc_lsb;
+ if(s->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++)
+ expected_delta_per_poc_cycle += h->sps.offset_for_ref_frame[ i ]; //FIXME integrate during sps parse
+
+ 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(s->picture_structure == PICT_FRAME)
+ field_poc[1] += h->delta_poc[1];
+ }else{
+ int poc;
+ if(h->nal_unit_type == NAL_IDR_SLICE){
+ poc= 0;
+ }else{
+ if(h->nal_ref_idc) poc= 2*(h->frame_num_offset + h->frame_num);
+ else poc= 2*(h->frame_num_offset + h->frame_num) - 1;
+ }
+ field_poc[0]= poc;
+ field_poc[1]= poc;
+ }
+
+ if(s->picture_structure != PICT_BOTTOM_FIELD)
+ s->current_picture_ptr->field_poc[0]= field_poc[0];
+ if(s->picture_structure != PICT_TOP_FIELD)
+ s->current_picture_ptr->field_poc[1]= field_poc[1];
+ if(s->picture_structure == PICT_FRAME) // FIXME field pix?
+ s->current_picture_ptr->poc= FFMIN(field_poc[0], field_poc[1]);
+
+ return 0;
+}
+
+/**
+ * decodes a slice header.
+ * this will allso call MPV_common_init() and frame_start() as needed
+ */
+static int decode_slice_header(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ int first_mb_in_slice, pps_id;
+ int num_ref_idx_active_override_flag;
+ static const uint8_t slice_type_map[5]= {P_TYPE, B_TYPE, I_TYPE, SP_TYPE, SI_TYPE};
+ int slice_type;
+ int default_ref_list_done = 0;
+
+ s->current_picture.reference= h->nal_ref_idc != 0;
+ s->dropable= h->nal_ref_idc == 0;
+
+ first_mb_in_slice= get_ue_golomb(&s->gb);
+
+ slice_type= get_ue_golomb(&s->gb);
+ if(slice_type > 9){
+ av_log(h->s.avctx, AV_LOG_ERROR, "slice type too large (%d) at %d %d\n", h->slice_type, s->mb_x, s->mb_y);
+ return -1;
+ }
+ if(slice_type > 4){
+ slice_type -= 5;
+ h->slice_type_fixed=1;
+ }else
+ h->slice_type_fixed=0;
+
+ slice_type= slice_type_map[ slice_type ];
+ if (slice_type == I_TYPE
+ || (h->slice_num != 0 && slice_type == h->slice_type) ) {
+ default_ref_list_done = 1;
+ }
+ h->slice_type= slice_type;
+
+ s->pict_type= h->slice_type; // to make a few old func happy, it's wrong though
+
+ pps_id= get_ue_golomb(&s->gb);
+ if(pps_id>255){
+ av_log(h->s.avctx, AV_LOG_ERROR, "pps_id out of range\n");
+ return -1;
+ }
+ h->pps= h->pps_buffer[pps_id];
+ if(h->pps.slice_group_count == 0){
+ av_log(h->s.avctx, AV_LOG_ERROR, "non existing PPS referenced\n");
+ return -1;
+ }
+
+ h->sps= h->sps_buffer[ h->pps.sps_id ];
+ if(h->sps.log2_max_frame_num == 0){
+ av_log(h->s.avctx, AV_LOG_ERROR, "non existing SPS referenced\n");
+ return -1;
+ }
+
+ if(h->dequant_coeff_pps != pps_id){
+ h->dequant_coeff_pps = pps_id;
+ init_dequant_tables(h);
+ }
+
+ s->mb_width= h->sps.mb_width;
+ s->mb_height= h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag);
+
+ h->b_stride= s->mb_width*4;
+ h->b8_stride= s->mb_width*2;
+
+ s->width = 16*s->mb_width - 2*(h->sps.crop_left + h->sps.crop_right );
+ if(h->sps.frame_mbs_only_flag)
+ s->height= 16*s->mb_height - 2*(h->sps.crop_top + h->sps.crop_bottom);
+ else
+ s->height= 16*s->mb_height - 4*(h->sps.crop_top + h->sps.crop_bottom); //FIXME recheck
+
+ if (s->context_initialized
+ && ( s->width != s->avctx->width || s->height != s->avctx->height)) {
+ free_tables(h);
+ MPV_common_end(s);
+ }
+ if (!s->context_initialized) {
+ if (MPV_common_init(s) < 0)
+ return -1;
+
+ if(s->dsp.h264_idct_add == ff_h264_idct_add_c){ //FIXME little ugly
+ memcpy(h->zigzag_scan, zigzag_scan, 16*sizeof(uint8_t));
+ memcpy(h-> field_scan, field_scan, 16*sizeof(uint8_t));
+ }else{
+ 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
+ }
+ }
+ if(s->dsp.h264_idct8_add == ff_h264_idct8_add_c){
+ memcpy(h->zigzag_scan8x8, zigzag_scan8x8, 64*sizeof(uint8_t));
+ memcpy(h->zigzag_scan8x8_cavlc, zigzag_scan8x8_cavlc, 64*sizeof(uint8_t));
+ memcpy(h->field_scan8x8, field_scan8x8, 64*sizeof(uint8_t));
+ memcpy(h->field_scan8x8_cavlc, field_scan8x8_cavlc, 64*sizeof(uint8_t));
+ }else{
+ int i;
+ for(i=0; i<64; i++){
+#define T(x) (x>>3) | ((x&7)<<3)
+ h->zigzag_scan8x8[i] = T(zigzag_scan8x8[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
+ h->zigzag_scan_q0 = zigzag_scan;
+ h->zigzag_scan8x8_q0 = zigzag_scan8x8;
+ h->zigzag_scan8x8_cavlc_q0 = zigzag_scan8x8_cavlc;
+ h->field_scan_q0 = field_scan;
+ h->field_scan8x8_q0 = field_scan8x8;
+ h->field_scan8x8_cavlc_q0 = field_scan8x8_cavlc;
+ }else{
+ h->zigzag_scan_q0 = h->zigzag_scan;
+ h->zigzag_scan8x8_q0 = h->zigzag_scan8x8;
+ h->zigzag_scan8x8_cavlc_q0 = h->zigzag_scan8x8_cavlc;
+ h->field_scan_q0 = h->field_scan;
+ h->field_scan8x8_q0 = h->field_scan8x8;
+ h->field_scan8x8_cavlc_q0 = h->field_scan8x8_cavlc;
+ }
+
+ alloc_tables(h);
+
+ s->avctx->width = s->width;
+ s->avctx->height = s->height;
+ s->avctx->sample_aspect_ratio= h->sps.sar;
+ if(!s->avctx->sample_aspect_ratio.den)
+ s->avctx->sample_aspect_ratio.den = 1;
+
+ if(h->sps.timing_info_present_flag){
+ s->avctx->time_base= (AVRational){h->sps.num_units_in_tick * 2, h->sps.time_scale};
+ if(h->x264_build > 0 && h->x264_build < 44)
+ s->avctx->time_base.den *= 2;
+ av_reduce(&s->avctx->time_base.num, &s->avctx->time_base.den,
+ s->avctx->time_base.num, s->avctx->time_base.den, 1<<30);
+ }
+ }
+
+ if(h->slice_num == 0){
+ if(frame_start(h) < 0)
+ return -1;
+ }
+
+ s->current_picture_ptr->frame_num= //FIXME frame_num cleanup
+ h->frame_num= get_bits(&s->gb, h->sps.log2_max_frame_num);
+
+ h->mb_mbaff = 0;
+ h->mb_aff_frame = 0;
+ if(h->sps.frame_mbs_only_flag){
+ s->picture_structure= PICT_FRAME;
+ }else{
+ if(get_bits1(&s->gb)) { //field_pic_flag
+ s->picture_structure= PICT_TOP_FIELD + get_bits1(&s->gb); //bottom_field_flag
+ av_log(h->s.avctx, AV_LOG_ERROR, "PAFF interlacing is not implemented\n");
+ } else {
+ s->picture_structure= PICT_FRAME;
+ h->mb_aff_frame = h->sps.mb_aff;
+ }
+ }
+
+ s->resync_mb_x = s->mb_x = first_mb_in_slice % s->mb_width;
+ s->resync_mb_y = s->mb_y = (first_mb_in_slice / s->mb_width) << h->mb_aff_frame;
+ if(s->mb_y >= s->mb_height){
+ return -1;
+ }
+
+ if(s->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;
+ h->max_pic_num= 1<<(h->sps.log2_max_frame_num + 1);
+ }
+
+ if(h->nal_unit_type == NAL_IDR_SLICE){
+ get_ue_golomb(&s->gb); /* idr_pic_id */
+ }
+
+ if(h->sps.poc_type==0){
+ h->poc_lsb= get_bits(&s->gb, h->sps.log2_max_poc_lsb);
+
+ if(h->pps.pic_order_present==1 && s->picture_structure==PICT_FRAME){
+ h->delta_poc_bottom= get_se_golomb(&s->gb);
+ }
+ }
+
+ if(h->sps.poc_type==1 && !h->sps.delta_pic_order_always_zero_flag){
+ h->delta_poc[0]= get_se_golomb(&s->gb);
+
+ if(h->pps.pic_order_present==1 && s->picture_structure==PICT_FRAME)
+ h->delta_poc[1]= get_se_golomb(&s->gb);
+ }
+
+ init_poc(h);
+
+ if(h->pps.redundant_pic_cnt_present){
+ h->redundant_pic_count= get_ue_golomb(&s->gb);
+ }
+
+ //set defaults, might be overriden a few line later
+ h->ref_count[0]= h->pps.ref_count[0];
+ h->ref_count[1]= h->pps.ref_count[1];
+
+ if(h->slice_type == P_TYPE || h->slice_type == SP_TYPE || h->slice_type == B_TYPE){
+ if(h->slice_type == B_TYPE){
+ h->direct_spatial_mv_pred= get_bits1(&s->gb);
+ if(h->sps.mb_aff && h->direct_spatial_mv_pred)
+ av_log(h->s.avctx, AV_LOG_ERROR, "MBAFF + spatial direct mode is not implemented\n");
+ }
+ num_ref_idx_active_override_flag= get_bits1(&s->gb);
+
+ if(num_ref_idx_active_override_flag){
+ h->ref_count[0]= get_ue_golomb(&s->gb) + 1;
+ if(h->slice_type==B_TYPE)
+ h->ref_count[1]= get_ue_golomb(&s->gb) + 1;
+
+ if(h->ref_count[0] > 32 || h->ref_count[1] > 32){
+ av_log(h->s.avctx, AV_LOG_ERROR, "reference overflow\n");
+ return -1;
+ }
+ }
+ }
+
+ if(!default_ref_list_done){
+ fill_default_ref_list(h);
+ }
+
+ if(decode_ref_pic_list_reordering(h) < 0)
+ return -1;
+
+ if( (h->pps.weighted_pred && (h->slice_type == P_TYPE || h->slice_type == SP_TYPE ))
+ || (h->pps.weighted_bipred_idc==1 && h->slice_type==B_TYPE ) )
+ pred_weight_table(h);
+ else if(h->pps.weighted_bipred_idc==2 && h->slice_type==B_TYPE)
+ implicit_weight_table(h);
+ else
+ h->use_weight = 0;
+
+ if(s->current_picture.reference)
+ decode_ref_pic_marking(h);
+
+ if(FRAME_MBAFF)
+ fill_mbaff_ref_list(h);
+
+ if( h->slice_type != I_TYPE && h->slice_type != SI_TYPE && h->pps.cabac )
+ h->cabac_init_idc = get_ue_golomb(&s->gb);
+
+ h->last_qscale_diff = 0;
+ s->qscale = h->pps.init_qp + get_se_golomb(&s->gb);
+ if(s->qscale<0 || s->qscale>51){
+ av_log(s->avctx, AV_LOG_ERROR, "QP %d out of range\n", s->qscale);
+ return -1;
+ }
+ h->chroma_qp = get_chroma_qp(h->pps.chroma_qp_index_offset, s->qscale);
+ //FIXME qscale / qp ... stuff
+ if(h->slice_type == SP_TYPE){
+ get_bits1(&s->gb); /* sp_for_switch_flag */
+ }
+ if(h->slice_type==SP_TYPE || h->slice_type == SI_TYPE){
+ get_se_golomb(&s->gb); /* slice_qs_delta */
+ }
+
+ h->deblocking_filter = 1;
+ h->slice_alpha_c0_offset = 0;
+ h->slice_beta_offset = 0;
+ if( h->pps.deblocking_filter_parameters_present ) {
+ h->deblocking_filter= get_ue_golomb(&s->gb);
+ if(h->deblocking_filter < 2)
+ h->deblocking_filter^= 1; // 1<->0
+
+ if( h->deblocking_filter ) {
+ h->slice_alpha_c0_offset = get_se_golomb(&s->gb) << 1;
+ h->slice_beta_offset = get_se_golomb(&s->gb) << 1;
+ }
+ }
+ if( s->avctx->skip_loop_filter >= AVDISCARD_ALL
+ ||(s->avctx->skip_loop_filter >= AVDISCARD_NONKEY && h->slice_type != I_TYPE)
+ ||(s->avctx->skip_loop_filter >= AVDISCARD_BIDIR && h->slice_type == B_TYPE)
+ ||(s->avctx->skip_loop_filter >= AVDISCARD_NONREF && h->nal_ref_idc == 0))
+ h->deblocking_filter= 0;
+
+#if 0 //FMO
+ if( h->pps.num_slice_groups > 1 && h->pps.mb_slice_group_map_type >= 3 && h->pps.mb_slice_group_map_type <= 5)
+ slice_group_change_cycle= get_bits(&s->gb, ?);
+#endif
+
+ h->slice_num++;
+
+ h->emu_edge_width= (s->flags&CODEC_FLAG_EMU_EDGE) ? 0 : 16;
+ h->emu_edge_height= FRAME_MBAFF ? 0 : h->emu_edge_width;
+
+ if(s->avctx->debug&FF_DEBUG_PICT_INFO){
+ av_log(h->s.avctx, AV_LOG_DEBUG, "slice:%d %s mb:%d %c pps:%d frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s\n",
+ h->slice_num,
+ (s->picture_structure==PICT_FRAME ? "F" : s->picture_structure==PICT_TOP_FIELD ? "T" : "B"),
+ first_mb_in_slice,
+ av_get_pict_type_char(h->slice_type),
+ pps_id, h->frame_num,
+ s->current_picture_ptr->field_poc[0], s->current_picture_ptr->field_poc[1],
+ h->ref_count[0], h->ref_count[1],
+ s->qscale,
+ h->deblocking_filter, h->slice_alpha_c0_offset/2, h->slice_beta_offset/2,
+ h->use_weight,
+ h->use_weight==1 && h->use_weight_chroma ? "c" : ""
+ );
+ }
+
+ if((s->avctx->flags2 & CODEC_FLAG2_FAST) && !s->current_picture.reference){
+ s->me.qpel_put= s->dsp.put_2tap_qpel_pixels_tab;
+ s->me.qpel_avg= s->dsp.avg_2tap_qpel_pixels_tab;
+ }else{
+ s->me.qpel_put= s->dsp.put_h264_qpel_pixels_tab;
+ s->me.qpel_avg= s->dsp.avg_h264_qpel_pixels_tab;
+ }
+
+ return 0;
+}
+
+/**
+ *
+ */
+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;
+}
+
+static inline int get_dct8x8_allowed(H264Context *h){
+ int i;
+ for(i=0; i<4; i++){
+ if(!IS_SUB_8X8(h->sub_mb_type[i])
+ || (!h->sps.direct_8x8_inference_flag && IS_DIRECT(h->sub_mb_type[i])))
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * decodes a residual block.
+ * @param n block index
+ * @param scantable scantable
+ * @param max_coeff number of coefficients in the block
+ * @return <0 if an error occured
+ */
+static int decode_residual(H264Context *h, GetBitContext *gb, DCTELEM *block, int n, const uint8_t *scantable, const uint32_t *qmul, int max_coeff){
+ MpegEncContext * const s = &h->s;
+ 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_num, coeff_token, total_coeff, i, j, trailing_ones, run_before;
+
+ //FIXME put trailing_onex into the context
+
+ if(n == CHROMA_DC_BLOCK_INDEX){
+ coeff_token= get_vlc2(gb, chroma_dc_coeff_token_vlc.table, CHROMA_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, 0);
+ 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;
+
+ trailing_ones= coeff_token&3;
+ tprintf("trailing:%d, total:%d\n", trailing_ones, total_coeff);
+ assert(total_coeff<=16);
+
+ for(i=0; i<trailing_ones; i++){
+ level[i]= 1 - 2*get_bits1(gb);
+ }
+
+ if(i<total_coeff) {
+ int level_code, mask;
+ int suffix_length = total_coeff > 10 && trailing_ones < 3;
+ int 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<<suffix_length) + get_bits(gb, suffix_length); //part
+ else
+ level_code= (prefix<<suffix_length); //part
+ }else if(prefix==14){
+ if(suffix_length)
+ level_code= (prefix<<suffix_length) + get_bits(gb, suffix_length); //part
+ else
+ level_code= prefix + get_bits(gb, 4); //part
+ }else if(prefix==15){
+ level_code= (prefix<<suffix_length) + get_bits(gb, 12); //part
+ if(suffix_length==0) level_code+=15; //FIXME doesn't make (much)sense
+ }else{
+ av_log(h->s.avctx, AV_LOG_ERROR, "prefix too large at %d %d\n", s->mb_x, s->mb_y);
+ return -1;
+ }
+
+ if(trailing_ones < 3) level_code += 2;
+
+ suffix_length = 1;
+ if(level_code > 5)
+ suffix_length++;
+ mask= -(level_code&1);
+ level[i]= (((2+level_code)>>1) ^ mask) - mask;
+ i++;
+
+ //remaining coefficients have suffix_length > 0
+ for(;i<total_coeff;i++) {
+ static const int suffix_limit[7] = {0,5,11,23,47,95,INT_MAX };
+ prefix = get_level_prefix(gb);
+ if(prefix<15){
+ level_code = (prefix<<suffix_length) + get_bits(gb, suffix_length);
+ }else if(prefix==15){
+ level_code = (prefix<<suffix_length) + get_bits(gb, 12);
+ }else{
+ av_log(h->s.avctx, AV_LOG_ERROR, "prefix too large at %d %d\n", s->mb_x, s->mb_y);
+ return -1;
+ }
+ mask= -(level_code&1);
+ level[i]= (((2+level_code)>>1) ^ mask) - mask;
+ if(level_code > suffix_limit[suffix_length])
+ suffix_length++;
+ }
+ }
+
+ if(total_coeff == max_coeff)
+ zeros_left=0;
+ else{
+ if(n == CHROMA_DC_BLOCK_INDEX)
+ zeros_left= get_vlc2(gb, chroma_dc_total_zeros_vlc[ total_coeff-1 ].table, CHROMA_DC_TOTAL_ZEROS_VLC_BITS, 1);
+ else
+ zeros_left= get_vlc2(gb, total_zeros_vlc[ total_coeff-1 ].table, TOTAL_ZEROS_VLC_BITS, 1);
+ }
+
+ coeff_num = zeros_left + total_coeff - 1;
+ j = scantable[coeff_num];
+ if(n > 24){
+ block[j] = level[0];
+ for(i=1;i<total_coeff;i++) {
+ if(zeros_left <= 0)
+ run_before = 0;
+ else if(zeros_left < 7){
+ run_before= get_vlc2(gb, run_vlc[zeros_left-1].table, RUN_VLC_BITS, 1);
+ }else{
+ run_before= get_vlc2(gb, run7_vlc.table, RUN7_VLC_BITS, 2);
+ }
+ zeros_left -= run_before;
+ coeff_num -= 1 + run_before;
+ j= scantable[ coeff_num ];
+
+ block[j]= level[i];
+ }
+ }else{
+ block[j] = (level[0] * qmul[j] + 32)>>6;
+ for(i=1;i<total_coeff;i++) {
+ if(zeros_left <= 0)
+ run_before = 0;
+ else if(zeros_left < 7){
+ run_before= get_vlc2(gb, run_vlc[zeros_left-1].table, RUN_VLC_BITS, 1);
+ }else{
+ run_before= get_vlc2(gb, run7_vlc.table, RUN7_VLC_BITS, 2);
+ }
+ zeros_left -= run_before;
+ coeff_num -= 1 + run_before;
+ j= scantable[ coeff_num ];
+
+ block[j]= (level[i] * qmul[j] + 32)>>6;
+ }
+ }
+
+ if(zeros_left<0){
+ av_log(h->s.avctx, AV_LOG_ERROR, "negative number of zero coeffs at %d %d\n", s->mb_x, s->mb_y);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void predict_field_decoding_flag(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ const int mb_xy= s->mb_x + s->mb_y*s->mb_stride;
+ int mb_type = (h->slice_table[mb_xy-1] == h->slice_num)
+ ? s->current_picture.mb_type[mb_xy-1]
+ : (h->slice_table[mb_xy-s->mb_stride] == h->slice_num)
+ ? s->current_picture.mb_type[mb_xy-s->mb_stride]
+ : 0;
+ h->mb_mbaff = h->mb_field_decoding_flag = IS_INTERLACED(mb_type) ? 1 : 0;
+}
+
+/**
+ * decodes a P_SKIP or B_SKIP macroblock
+ */
+static void decode_mb_skip(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ const int mb_xy= s->mb_x + s->mb_y*s->mb_stride;
+ int mb_type=0;
+
+ memset(h->non_zero_count[mb_xy], 0, 16);
+ memset(h->non_zero_count_cache + 8, 0, 8*5); //FIXME ugly, remove pfui
+
+ if(MB_FIELD)
+ mb_type|= MB_TYPE_INTERLACED;
+
+ if( h->slice_type == B_TYPE )
+ {
+ // just for fill_caches. pred_direct_motion will set the real mb_type
+ mb_type|= MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2|MB_TYPE_SKIP;
+
+ fill_caches(h, mb_type, 0); //FIXME check what is needed and what not ...
+ pred_direct_motion(h, &mb_type);
+ mb_type|= MB_TYPE_SKIP;
+ }
+ else
+ {
+ int mx, my;
+ mb_type|= MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P1L0|MB_TYPE_SKIP;
+
+ fill_caches(h, mb_type, 0); //FIXME check what is needed and what not ...
+ pred_pskip_motion(h, &mx, &my);
+ fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, 0, 1);
+ fill_rectangle( h->mv_cache[0][scan8[0]], 4, 4, 8, pack16to32(mx,my), 4);
+ }
+
+ write_back_motion(h, mb_type);
+ s->current_picture.mb_type[mb_xy]= mb_type;
+ s->current_picture.qscale_table[mb_xy]= s->qscale;
+ h->slice_table[ mb_xy ]= h->slice_num;
+ h->prev_mb_skipped= 1;
+}
+
+/**
+ * decodes a macroblock
+ * @returns 0 if ok, AC_ERROR / DC_ERROR / MV_ERROR if an error is noticed
+ */
+static int decode_mb_cavlc(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ const int mb_xy= s->mb_x + s->mb_y*s->mb_stride;
+ int mb_type, partition_count, cbp;
+ int dct8x8_allowed= h->pps.transform_8x8_mode;
+
+ s->dsp.clear_blocks(h->mb); //FIXME avoid if already clear (move after skip handlong?
+
+ tprintf("pic:%d mb:%d/%d\n", h->frame_num, s->mb_x, s->mb_y);
+ cbp = 0; /* avoid warning. FIXME: find a solution without slowing
+ down the code */
+ if(h->slice_type != I_TYPE && h->slice_type != SI_TYPE){
+ if(s->mb_skip_run==-1)
+ s->mb_skip_run= get_ue_golomb(&s->gb);
+
+ if (s->mb_skip_run--) {
+ if(FRAME_MBAFF && (s->mb_y&1) == 0){
+ if(s->mb_skip_run==0)
+ h->mb_mbaff = h->mb_field_decoding_flag = get_bits1(&s->gb);
+ else
+ predict_field_decoding_flag(h);
+ }
+ decode_mb_skip(h);
+ return 0;
+ }
+ }
+ if(FRAME_MBAFF){
+ if( (s->mb_y&1) == 0 )
+ h->mb_mbaff = h->mb_field_decoding_flag = get_bits1(&s->gb);
+ }else
+ h->mb_field_decoding_flag= (s->picture_structure!=PICT_FRAME);
+
+ h->prev_mb_skipped= 0;
+
+ mb_type= get_ue_golomb(&s->gb);
+ if(h->slice_type == B_TYPE){
+ 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 == P_TYPE /*|| h->slice_type == SP_TYPE */){
+ 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{
+ assert(h->slice_type == I_TYPE);
+decode_intra_mb:
+ if(mb_type > 25){
+ av_log(h->s.avctx, AV_LOG_ERROR, "mb_type %d in %c slice too large at %d %d\n", mb_type, av_get_pict_type_char(h->slice_type), s->mb_x, s->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)
+ mb_type |= MB_TYPE_INTERLACED;
+
+ h->slice_table[ mb_xy ]= h->slice_num;
+
+ if(IS_INTRA_PCM(mb_type)){
+ unsigned int x, y;
+
+ // we assume these blocks are very rare so we dont optimize it
+ align_get_bits(&s->gb);
+
+ // The pixels are stored in the same order as levels in h->mb array.
+ for(y=0; y<16; y++){
+ const int index= 4*(y&3) + 32*((y>>2)&1) + 128*(y>>3);
+ for(x=0; x<16; x++){
+ tprintf("LUMA ICPM LEVEL (%3d)\n", show_bits(&s->gb, 8));
+ h->mb[index + (x&3) + 16*((x>>2)&1) + 64*(x>>3)]= get_bits(&s->gb, 8);
+ }
+ }
+ for(y=0; y<8; y++){
+ const int index= 256 + 4*(y&3) + 32*(y>>2);
+ for(x=0; x<8; x++){
+ tprintf("CHROMA U ICPM LEVEL (%3d)\n", show_bits(&s->gb, 8));
+ h->mb[index + (x&3) + 16*(x>>2)]= get_bits(&s->gb, 8);
+ }
+ }
+ for(y=0; y<8; y++){
+ const int index= 256 + 64 + 4*(y&3) + 32*(y>>2);
+ for(x=0; x<8; x++){
+ tprintf("CHROMA V ICPM LEVEL (%3d)\n", show_bits(&s->gb, 8));
+ h->mb[index + (x&3) + 16*(x>>2)]= get_bits(&s->gb, 8);
+ }
+ }
+
+ // In deblocking, the quantizer is 0
+ s->current_picture.qscale_table[mb_xy]= 0;
+ h->chroma_qp = get_chroma_qp(h->pps.chroma_qp_index_offset, 0);
+ // All coeffs are present
+ memset(h->non_zero_count[mb_xy], 16, 16);
+
+ s->current_picture.mb_type[mb_xy]= mb_type;
+ return 0;
+ }
+
+ if(MB_MBAFF){
+ h->ref_count[0] <<= 1;
+ h->ref_count[1] <<= 1;
+ }
+
+ fill_caches(h, mb_type, 0);
+
+ //mb_pred
+ if(IS_INTRA(mb_type)){
+// init_top_left_availability(h);
+ if(IS_INTRA4x4(mb_type)){
+ int i;
+ int di = 1;
+ if(dct8x8_allowed && get_bits1(&s->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(&s->gb)){
+ const int rem_mode= get_bits(&s->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( check_intra4x4_pred_mode(h) < 0)
+ return -1;
+ }else{
+ h->intra16x16_pred_mode= check_intra_pred_mode(h, h->intra16x16_pred_mode);
+ if(h->intra16x16_pred_mode < 0)
+ return -1;
+ }
+ h->chroma_pred_mode= get_ue_golomb(&s->gb);
+
+ h->chroma_pred_mode= check_intra_pred_mode(h, h->chroma_pred_mode);
+ if(h->chroma_pred_mode < 0)
+ return -1;
+ }else if(partition_count==4){
+ int i, j, sub_partition_count[4], list, ref[2][4];
+
+ if(h->slice_type == B_TYPE){
+ for(i=0; i<4; i++){
+ h->sub_mb_type[i]= get_ue_golomb(&s->gb);
+ if(h->sub_mb_type[i] >=13){
+ av_log(h->s.avctx, AV_LOG_ERROR, "B sub_mb_type %d out of range at %d %d\n", h->sub_mb_type[i], s->mb_x, s->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]) || IS_DIRECT(h->sub_mb_type[1])
+ || IS_DIRECT(h->sub_mb_type[2]) || IS_DIRECT(h->sub_mb_type[3])) {
+ 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{
+ assert(h->slice_type == P_TYPE || h->slice_type == SP_TYPE); //FIXME SP correct ?
+ for(i=0; i<4; i++){
+ h->sub_mb_type[i]= get_ue_golomb(&s->gb);
+ if(h->sub_mb_type[i] >=4){
+ av_log(h->s.avctx, AV_LOG_ERROR, "P sub_mb_type %d out of range at %d %d\n", h->sub_mb_type[i], s->mb_x, s->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; list<2; list++){
+ int ref_count= IS_REF0(mb_type) ? 1 : h->ref_count[list];
+ if(ref_count == 0) continue;
+ 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)){
+ ref[list][i] = get_te0_golomb(&s->gb, ref_count); //FIXME init to 0 before and skip?
+ }else{
+ //FIXME
+ ref[list][i] = -1;
+ }
+ }
+ }
+
+ if(dct8x8_allowed)
+ dct8x8_allowed = get_dct8x8_allowed(h);
+
+ for(list=0; list<2; list++){
+ const int ref_count= IS_REF0(mb_type) ? 1 : h->ref_count[list];
+ if(ref_count == 0) continue;
+
+ 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; j<sub_partition_count[i]; j++){
+ int mx, my;
+ const int index= 4*i + block_width*j;
+ int16_t (* mv_cache)[2]= &h->mv_cache[list][ scan8[index] ];
+ pred_motion(h, index, block_width, list, h->ref_cache[list][ scan8[index] ], &mx, &my);
+ mx += get_se_golomb(&s->gb);
+ my += get_se_golomb(&s->gb);
+ tprintf("final mv:%d %d\n", mx, my);
+
+ if(IS_SUB_8X8(sub_mb_type)){
+ mv_cache[ 0 ][0]= mv_cache[ 1 ][0]=
+ mv_cache[ 8 ][0]= mv_cache[ 9 ][0]= mx;
+ mv_cache[ 0 ][1]= mv_cache[ 1 ][1]=
+ mv_cache[ 8 ][1]= mv_cache[ 9 ][1]= my;
+ }else if(IS_SUB_8X4(sub_mb_type)){
+ mv_cache[ 0 ][0]= mv_cache[ 1 ][0]= mx;
+ mv_cache[ 0 ][1]= mv_cache[ 1 ][1]= my;
+ }else if(IS_SUB_4X8(sub_mb_type)){
+ mv_cache[ 0 ][0]= mv_cache[ 8 ][0]= mx;
+ mv_cache[ 0 ][1]= mv_cache[ 8 ][1]= my;
+ }else{
+ assert(IS_SUB_4X4(sub_mb_type));
+ 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)){
+ 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; list<2; list++){
+ if(h->ref_count[list]>0){
+ if(IS_DIR(mb_type, 0, list)){
+ const int val= get_te0_golomb(&s->gb, h->ref_count[list]);
+ fill_rectangle(&h->ref_cache[list][ scan8[0] ], 4, 4, 8, val, 1);
+ }else
+ fill_rectangle(&h->ref_cache[list][ scan8[0] ], 4, 4, 8, (LIST_NOT_USED&0xFF), 1);
+ }
+ }
+ for(list=0; list<2; 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(&s->gb);
+ my += get_se_golomb(&s->gb);
+ tprintf("final mv:%d %d\n", mx, my);
+
+ fill_rectangle(h->mv_cache[list][ scan8[0] ], 4, 4, 8, pack16to32(mx,my), 4);
+ }else
+ fill_rectangle(h->mv_cache[list][ scan8[0] ], 4, 4, 8, 0, 4);
+ }
+ }
+ else if(IS_16X8(mb_type)){
+ for(list=0; list<2; list++){
+ if(h->ref_count[list]>0){
+ for(i=0; i<2; i++){
+ if(IS_DIR(mb_type, i, list)){
+ const int val= get_te0_golomb(&s->gb, h->ref_count[list]);
+ fill_rectangle(&h->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, val, 1);
+ }else
+ fill_rectangle(&h->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, (LIST_NOT_USED&0xFF), 1);
+ }
+ }
+ }
+ for(list=0; list<2; list++){
+ for(i=0; i<2; i++){
+ 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(&s->gb);
+ my += get_se_golomb(&s->gb);
+ tprintf("final mv:%d %d\n", mx, my);
+
+ fill_rectangle(h->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, pack16to32(mx,my), 4);
+ }else
+ fill_rectangle(h->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, 0, 4);
+ }
+ }
+ }else{
+ assert(IS_8X16(mb_type));
+ for(list=0; list<2; list++){
+ if(h->ref_count[list]>0){
+ for(i=0; i<2; i++){
+ if(IS_DIR(mb_type, i, list)){ //FIXME optimize
+ const int val= get_te0_golomb(&s->gb, h->ref_count[list]);
+ fill_rectangle(&h->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, val, 1);
+ }else
+ fill_rectangle(&h->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, (LIST_NOT_USED&0xFF), 1);
+ }
+ }
+ }
+ for(list=0; list<2; list++){
+ for(i=0; i<2; i++){
+ 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(&s->gb);
+ my += get_se_golomb(&s->gb);
+ tprintf("final mv:%d %d\n", mx, my);
+
+ fill_rectangle(h->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, pack16to32(mx,my), 4);
+ }else
+ fill_rectangle(h->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, 0, 4);
+ }
+ }
+ }
+ }
+
+ if(IS_INTER(mb_type))
+ write_back_motion(h, mb_type);
+
+ if(!IS_INTRA16x16(mb_type)){
+ cbp= get_ue_golomb(&s->gb);
+ if(cbp > 47){
+ av_log(h->s.avctx, AV_LOG_ERROR, "cbp too large (%d) at %d %d\n", cbp, s->mb_x, s->mb_y);
+ return -1;
+ }
+
+ if(IS_INTRA4x4(mb_type))
+ cbp= golomb_to_intra4x4_cbp[cbp];
+ else
+ cbp= golomb_to_inter_cbp[cbp];
+ }
+ h->cbp = cbp;
+
+ if(dct8x8_allowed && (cbp&15) && !IS_INTRA(mb_type)){
+ if(get_bits1(&s->gb))
+ mb_type |= MB_TYPE_8x8DCT;
+ }
+ s->current_picture.mb_type[mb_xy]= mb_type;
+
+ if(cbp || IS_INTRA16x16(mb_type)){
+ int i8x8, i4x4, chroma_idx;
+ int chroma_qp, dquant;
+ GetBitContext *gb= IS_INTRA(mb_type) ? h->intra_gb_ptr : h->inter_gb_ptr;
+ const uint8_t *scan, *scan8x8, *dc_scan;
+
+// fill_non_zero_count_cache(h);
+
+ if(IS_INTERLACED(mb_type)){
+ scan8x8= s->qscale ? h->field_scan8x8_cavlc : h->field_scan8x8_cavlc_q0;
+ scan= s->qscale ? h->field_scan : h->field_scan_q0;
+ dc_scan= luma_dc_field_scan;
+ }else{
+ scan8x8= s->qscale ? h->zigzag_scan8x8_cavlc : h->zigzag_scan8x8_cavlc_q0;
+ scan= s->qscale ? h->zigzag_scan : h->zigzag_scan_q0;
+ dc_scan= luma_dc_zigzag_scan;
+ }
+
+ dquant= get_se_golomb(&s->gb);
+
+ if( dquant > 25 || dquant < -26 ){
+ av_log(h->s.avctx, AV_LOG_ERROR, "dquant out of range (%d) at %d %d\n", dquant, s->mb_x, s->mb_y);
+ return -1;
+ }
+
+ s->qscale += dquant;
+ if(((unsigned)s->qscale) > 51){
+ if(s->qscale<0) s->qscale+= 52;
+ else s->qscale-= 52;
+ }
+
+ h->chroma_qp= chroma_qp= get_chroma_qp(h->pps.chroma_qp_index_offset, s->qscale);
+ if(IS_INTRA16x16(mb_type)){
+ if( decode_residual(h, h->intra_gb_ptr, h->mb, LUMA_DC_BLOCK_INDEX, dc_scan, h->dequant4_coeff[0][s->qscale], 16) < 0){
+ return -1; //FIXME continue if partitioned and other return -1 too
+ }
+
+ assert((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;
+ if( decode_residual(h, h->intra_gb_ptr, h->mb + 16*index, index, scan + 1, h->dequant4_coeff[0][s->qscale], 15) < 0 ){
+ return -1;
+ }
+ }
+ }
+ }else{
+ fill_rectangle(&h->non_zero_count_cache[scan8[0]], 4, 4, 8, 0, 1);
+ }
+ }else{
+ for(i8x8=0; i8x8<4; i8x8++){
+ if(cbp & (1<<i8x8)){
+ if(IS_8x8DCT(mb_type)){
+ DCTELEM *buf = &h->mb[64*i8x8];
+ uint8_t *nnz;
+ for(i4x4=0; i4x4<4; i4x4++){
+ if( decode_residual(h, gb, buf, i4x4+4*i8x8, scan8x8+16*i4x4,
+ h->dequant8_coeff[IS_INTRA( mb_type ) ? 0:1][s->qscale], 16) <0 )
+ return -1;
+ }
+ nnz= &h->non_zero_count_cache[ scan8[4*i8x8] ];
+ nnz[0] += nnz[1] + nnz[8] + nnz[9];
+ }else{
+ for(i4x4=0; i4x4<4; i4x4++){
+ const int index= i4x4 + 4*i8x8;
+
+ if( decode_residual(h, gb, h->mb + 16*index, index, scan, h->dequant4_coeff[IS_INTRA( mb_type ) ? 0:3][s->qscale], 16) <0 ){
+ return -1;
+ }
+ }
+ }
+ }else{
+ uint8_t * const nnz= &h->non_zero_count_cache[ scan8[4*i8x8] ];
+ nnz[0] = nnz[1] = nnz[8] = nnz[9] = 0;
+ }
+ }
+ }
+
+ if(cbp&0x30){
+ for(chroma_idx=0; chroma_idx<2; chroma_idx++)
+ if( decode_residual(h, gb, h->mb + 256 + 16*4*chroma_idx, CHROMA_DC_BLOCK_INDEX, chroma_dc_scan, NULL, 4) < 0){
+ return -1;
+ }
+ }
+
+ if(cbp&0x20){
+ for(chroma_idx=0; chroma_idx<2; chroma_idx++){
+ for(i4x4=0; i4x4<4; i4x4++){
+ const int index= 16 + 4*chroma_idx + i4x4;
+ if( decode_residual(h, gb, h->mb + 16*index, index, scan + 1, h->dequant4_coeff[chroma_idx+1+(IS_INTRA( mb_type ) ? 0:3)][chroma_qp], 15) < 0){
+ return -1;
+ }
+ }
+ }
+ }else{
+ uint8_t * const nnz= &h->non_zero_count_cache[0];
+ nnz[ scan8[16]+0 ] = nnz[ scan8[16]+1 ] =nnz[ scan8[16]+8 ] =nnz[ scan8[16]+9 ] =
+ nnz[ scan8[20]+0 ] = nnz[ scan8[20]+1 ] =nnz[ scan8[20]+8 ] =nnz[ scan8[20]+9 ] = 0;
+ }
+ }else{
+ uint8_t * const nnz= &h->non_zero_count_cache[0];
+ fill_rectangle(&nnz[scan8[0]], 4, 4, 8, 0, 1);
+ nnz[ scan8[16]+0 ] = nnz[ scan8[16]+1 ] =nnz[ scan8[16]+8 ] =nnz[ scan8[16]+9 ] =
+ nnz[ scan8[20]+0 ] = nnz[ scan8[20]+1 ] =nnz[ scan8[20]+8 ] =nnz[ scan8[20]+9 ] = 0;
+ }
+ s->current_picture.qscale_table[mb_xy]= s->qscale;
+ write_back_non_zero_count(h);
+
+ if(MB_MBAFF){
+ h->ref_count[0] >>= 1;
+ h->ref_count[1] >>= 1;
+ }
+
+ return 0;
+}
+
+static int decode_cabac_field_decoding_flag(H264Context *h) {
+ MpegEncContext * const s = &h->s;
+ const int mb_x = s->mb_x;
+ const int mb_y = s->mb_y & ~1;
+ const int mba_xy = mb_x - 1 + mb_y *s->mb_stride;
+ const int mbb_xy = mb_x + (mb_y-2)*s->mb_stride;
+
+ unsigned int ctx = 0;
+
+ if( h->slice_table[mba_xy] == h->slice_num && IS_INTERLACED( s->current_picture.mb_type[mba_xy] ) ) {
+ ctx += 1;
+ }
+ if( h->slice_table[mbb_xy] == h->slice_num && IS_INTERLACED( s->current_picture.mb_type[mbb_xy] ) ) {
+ ctx += 1;
+ }
+
+ 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){
+ MpegEncContext * const s = &h->s;
+ const int mba_xy = h->left_mb_xy[0];
+ const int mbb_xy = h->top_mb_xy;
+ int ctx=0;
+ if( h->slice_table[mba_xy] == h->slice_num && !IS_INTRA4x4( s->current_picture.mb_type[mba_xy] ) )
+ ctx++;
+ if( h->slice_table[mbb_xy] == h->slice_num && !IS_INTRA4x4( s->current_picture.mb_type[mbb_xy] ) )
+ ctx++;
+ if( get_cabac_noinline( &h->cabac, &state[ctx] ) == 0 )
+ return 0; /* I4x4 */
+ state += 2;
+ }else{
+ if( get_cabac_noinline( &h->cabac, &state[0] ) == 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_type( H264Context *h ) {
+ MpegEncContext * const s = &h->s;
+
+ if( h->slice_type == I_TYPE ) {
+ return decode_cabac_intra_mb_type(h, 3, 1);
+ } else if( h->slice_type == P_TYPE ) {
+ 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 */
+ return 3 * get_cabac_noinline( &h->cabac, &h->cabac_state[16] );
+ } else {
+ /* P_L0_D8x16, P_L0_D16x8 */
+ return 2 - get_cabac_noinline( &h->cabac, &h->cabac_state[17] );
+ }
+ } else {
+ return decode_cabac_intra_mb_type(h, 17, 0) + 5;
+ }
+ } else if( h->slice_type == B_TYPE ) {
+ const int mba_xy = h->left_mb_xy[0];
+ const int mbb_xy = h->top_mb_xy;
+ int ctx = 0;
+ int bits;
+
+ if( h->slice_table[mba_xy] == h->slice_num && !IS_DIRECT( s->current_picture.mb_type[mba_xy] ) )
+ ctx++;
+ if( h->slice_table[mbb_xy] == h->slice_num && !IS_DIRECT( s->current_picture.mb_type[mbb_xy] ) )
+ ctx++;
+
+ if( !get_cabac_noinline( &h->cabac, &h->cabac_state[27+ctx] ) )
+ return 0; /* B_Direct_16x16 */
+
+ if( !get_cabac_noinline( &h->cabac, &h->cabac_state[27+3] ) ) {
+ return 1 + get_cabac_noinline( &h->cabac, &h->cabac_state[27+5] ); /* B_L[01]_16x16 */
+ }
+
+ 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 )
+ return bits + 3; /* B_Bi_16x16 through B_L1_L0_16x8 */
+ else if( bits == 13 ) {
+ return decode_cabac_intra_mb_type(h, 32, 0) + 23;
+ } else if( bits == 14 )
+ return 11; /* B_L1_L0_8x16 */
+ else if( bits == 15 )
+ return 22; /* B_8x8 */
+
+ bits= ( bits<<1 ) | get_cabac_noinline( &h->cabac, &h->cabac_state[27+5] );
+ return bits - 4; /* B_L0_Bi_* through B_Bi_Bi_* */
+ } else {
+ /* TODO SI/SP frames? */
+ return -1;
+ }
+}
+
+static int decode_cabac_mb_skip( H264Context *h, int mb_x, int mb_y ) {
+ MpegEncContext * const s = &h->s;
+ int mba_xy, mbb_xy;
+ int ctx = 0;
+
+ if(FRAME_MBAFF){ //FIXME merge with the stuff in fill_caches?
+ int mb_xy = mb_x + (mb_y&~1)*s->mb_stride;
+ mba_xy = mb_xy - 1;
+ if( (mb_y&1)
+ && h->slice_table[mba_xy] == h->slice_num
+ && MB_FIELD == !!IS_INTERLACED( s->current_picture.mb_type[mba_xy] ) )
+ mba_xy += s->mb_stride;
+ if( MB_FIELD ){
+ mbb_xy = mb_xy - s->mb_stride;
+ if( !(mb_y&1)
+ && h->slice_table[mbb_xy] == h->slice_num
+ && IS_INTERLACED( s->current_picture.mb_type[mbb_xy] ) )
+ mbb_xy -= s->mb_stride;
+ }else
+ mbb_xy = mb_x + (mb_y-1)*s->mb_stride;
+ }else{
+ int mb_xy = mb_x + mb_y*s->mb_stride;
+ mba_xy = mb_xy - 1;
+ mbb_xy = mb_xy - s->mb_stride;
+ }
+
+ if( h->slice_table[mba_xy] == h->slice_num && !IS_SKIP( s->current_picture.mb_type[mba_xy] ))
+ ctx++;
+ if( h->slice_table[mbb_xy] == h->slice_num && !IS_SKIP( s->current_picture.mb_type[mbb_xy] ))
+ ctx++;
+
+ if( h->slice_type == B_TYPE )
+ 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] );
+
+ if( mode >= pred_mode )
+ return mode + 1;
+ else
+ return 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->slice_table[mba_xy] == h->slice_num && h->chroma_pred_mode_table[mba_xy] != 0 )
+ ctx++;
+
+ if( h->slice_table[mbb_xy] == h->slice_num && 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 const uint8_t block_idx_x[16] = {
+ 0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3
+};
+static const uint8_t block_idx_y[16] = {
+ 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3
+};
+static const uint8_t block_idx_xy[4][4] = {
+ { 0, 2, 8, 10},
+ { 1, 3, 9, 11},
+ { 4, 6, 12, 14},
+ { 5, 7, 13, 15}
+};
+
+static int decode_cabac_mb_cbp_luma( H264Context *h) {
+ int cbp = 0;
+ int cbp_b = -1;
+ int i8x8;
+
+ if( h->slice_table[h->top_mb_xy] == h->slice_num ) {
+ cbp_b = h->top_cbp;
+ tprintf("cbp_b = top_cbp = %x\n", cbp_b);
+ }
+
+ for( i8x8 = 0; i8x8 < 4; i8x8++ ) {
+ int cbp_a = -1;
+ int x, y;
+ int ctx = 0;
+
+ x = block_idx_x[4*i8x8];
+ y = block_idx_y[4*i8x8];
+
+ if( x > 0 )
+ cbp_a = cbp;
+ else if( h->slice_table[h->left_mb_xy[0]] == h->slice_num ) {
+ cbp_a = h->left_cbp;
+ tprintf("cbp_a = left_cbp = %x\n", cbp_a);
+ }
+
+ if( y > 0 )
+ cbp_b = cbp;
+
+ /* No need to test for skip as we put 0 for skip block */
+ /* No need to test for IPCM as we put 1 for IPCM block */
+ if( cbp_a >= 0 ) {
+ int i8x8a = block_idx_xy[(x-1)&0x03][y]/4;
+ if( ((cbp_a >> i8x8a)&0x01) == 0 )
+ ctx++;
+ }
+
+ if( cbp_b >= 0 ) {
+ int i8x8b = block_idx_xy[x][(y-1)&0x03]/4;
+ if( ((cbp_b >> i8x8b)&0x01) == 0 )
+ ctx += 2;
+ }
+
+ if( get_cabac( &h->cabac, &h->cabac_state[73 + ctx] ) ) {
+ cbp |= 1 << i8x8;
+ }
+ }
+ 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_mb_dqp( H264Context *h) {
+ MpegEncContext * const s = &h->s;
+ int mbn_xy;
+ int ctx = 0;
+ int val = 0;
+
+ if( s->mb_x > 0 )
+ mbn_xy = s->mb_x + s->mb_y*s->mb_stride - 1;
+ else
+ mbn_xy = s->mb_width - 1 + (s->mb_y-1)*s->mb_stride;
+
+ if( h->last_qscale_diff != 0 )
+ ctx++;
+
+ while( get_cabac_noinline( &h->cabac, &h->cabac_state[60 + ctx] ) ) {
+ if( ctx < 2 )
+ ctx = 2;
+ else
+ ctx = 3;
+ val++;
+ if(val > 102) //prevent infinite loop
+ return INT_MIN;
+ }
+
+ if( val&0x01 )
+ return (val + 1)/2;
+ else
+ return -(val + 1)/2;
+}
+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 inline int decode_cabac_mb_transform_size( H264Context *h ) {
+ return get_cabac_noinline( &h->cabac, &h->cabac_state[399 + h->neighbor_transform_size] );
+}
+
+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 == B_TYPE) {
+ if( refa > 0 && !h->direct_cache[scan8[n] - 1] )
+ ctx++;
+ if( refb > 0 && !h->direct_cache[scan8[n] - 8] )
+ ctx += 2;
+ } else {
+ if( refa > 0 )
+ ctx++;
+ if( refb > 0 )
+ ctx += 2;
+ }
+
+ while( get_cabac( &h->cabac, &h->cabac_state[54+ctx] ) ) {
+ ref++;
+ if( ctx < 4 )
+ ctx = 4;
+ else
+ ctx = 5;
+ }
+ return ref;
+}
+
+static int decode_cabac_mb_mvd( H264Context *h, int list, int n, int l ) {
+ int amvd = abs( h->mvd_cache[list][scan8[n] - 1][l] ) +
+ abs( h->mvd_cache[list][scan8[n] - 8][l] );
+ int ctxbase = (l == 0) ? 40 : 47;
+ int ctx, mvd;
+
+ if( amvd < 3 )
+ ctx = 0;
+ else if( amvd > 32 )
+ ctx = 2;
+ else
+ ctx = 1;
+
+ if(!get_cabac(&h->cabac, &h->cabac_state[ctxbase+ctx]))
+ return 0;
+
+ mvd= 1;
+ ctx= 3;
+ while( mvd < 9 && get_cabac( &h->cabac, &h->cabac_state[ctxbase+ctx] ) ) {
+ mvd++;
+ if( ctx < 6 )
+ ctx++;
+ }
+
+ if( mvd >= 9 ) {
+ int k = 3;
+ while( get_cabac_bypass( &h->cabac ) ) {
+ mvd += 1 << k;
+ k++;
+ }
+ while( k-- ) {
+ if( get_cabac_bypass( &h->cabac ) )
+ mvd += 1 << k;
+ }
+ }
+ return get_cabac_bypass_sign( &h->cabac, -mvd );
+}
+
+static int inline get_cabac_cbf_ctx( H264Context *h, int cat, int idx ) {
+ int nza, nzb;
+ int ctx = 0;
+
+ if( cat == 0 ) {
+ nza = h->left_cbp&0x100;
+ nzb = h-> top_cbp&0x100;
+ } else if( cat == 1 || cat == 2 ) {
+ nza = h->non_zero_count_cache[scan8[idx] - 1];
+ nzb = h->non_zero_count_cache[scan8[idx] - 8];
+ } else if( cat == 3 ) {
+ nza = (h->left_cbp>>(6+idx))&0x01;
+ nzb = (h-> top_cbp>>(6+idx))&0x01;
+ } else {
+ assert(cat == 4);
+ nza = h->non_zero_count_cache[scan8[16+idx] - 1];
+ nzb = h->non_zero_count_cache[scan8[16+idx] - 8];
+ }
+
+ if( nza > 0 )
+ ctx++;
+
+ if( nzb > 0 )
+ ctx += 2;
+
+ return ctx + 4 * cat;
+}
+
+static const __attribute((used)) 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
+};
+
+static int decode_cabac_residual( H264Context *h, DCTELEM *block, int cat, int n, const uint8_t *scantable, const uint32_t *qmul, int max_coeff) {
+ const int mb_xy = h->s.mb_x + h->s.mb_y*h->s.mb_stride;
+ static const int significant_coeff_flag_offset[2][6] = {
+ { 105+0, 105+15, 105+29, 105+44, 105+47, 402 },
+ { 277+0, 277+15, 277+29, 277+44, 277+47, 436 }
+ };
+ static const int last_coeff_flag_offset[2][6] = {
+ { 166+0, 166+15, 166+29, 166+44, 166+47, 417 },
+ { 338+0, 338+15, 338+29, 338+44, 338+47, 451 }
+ };
+ static const int coeff_abs_level_m1_offset[6] = {
+ 227+0, 227+10, 227+20, 227+30, 227+39, 426
+ };
+ 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 }
+ };
+
+ int index[64];
+
+ int last;
+ int coeff_count = 0;
+
+ int abslevel1 = 1;
+ int abslevelgt1 = 0;
+
+ uint8_t *significant_coeff_ctx_base;
+ uint8_t *last_coeff_ctx_base;
+ uint8_t *abs_level_m1_ctx_base;
+
+#ifndef 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
+
+
+ /* cat: 0-> DC 16x16 n = 0
+ * 1-> AC 16x16 n = luma4x4idx
+ * 2-> Luma4x4 n = luma4x4idx
+ * 3-> DC Chroma n = iCbCr
+ * 4-> AC Chroma n = 4 * iCbCr + chroma4x4idx
+ * 5-> Luma8x8 n = 4 * luma8x8idx
+ */
+
+ /* read coded block flag */
+ if( cat != 5 ) {
+ if( get_cabac( CC, &h->cabac_state[85 + get_cabac_cbf_ctx( h, cat, n ) ] ) == 0 ) {
+ if( cat == 1 || cat == 2 )
+ h->non_zero_count_cache[scan8[n]] = 0;
+ else if( cat == 4 )
+ h->non_zero_count_cache[scan8[16+n]] = 0;
+#ifdef CABAC_ON_STACK
+ h->cabac.range = cc.range ;
+ h->cabac.low = cc.low ;
+ h->cabac.bytestream= cc.bytestream;
+#endif
+ return 0;
+ }
+ }
+
+ significant_coeff_ctx_base = h->cabac_state
+ + significant_coeff_flag_offset[MB_FIELD][cat];
+ last_coeff_ctx_base = h->cabac_state
+ + last_coeff_flag_offset[MB_FIELD][cat];
+ abs_level_m1_ctx_base = h->cabac_state
+ + coeff_abs_level_m1_offset[cat];
+
+ if( cat == 5 ) {
+#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];
+#if defined(ARCH_X86) && !(defined(PIC) && defined(__GNUC__))
+ coeff_count= decode_significance_8x8_x86(CC, significant_coeff_ctx_base, index, sig_off);
+ } else {
+ coeff_count= decode_significance_x86(CC, max_coeff, significant_coeff_ctx_base, index);
+#else
+ DECODE_SIGNIFICANCE( 63, sig_off[last], last_coeff_flag_offset_8x8[last] );
+ } else {
+ DECODE_SIGNIFICANCE( max_coeff - 1, last, last );
+#endif
+ }
+ assert(coeff_count > 0);
+
+ if( cat == 0 )
+ h->cbp_table[mb_xy] |= 0x100;
+ else if( cat == 1 || cat == 2 )
+ h->non_zero_count_cache[scan8[n]] = coeff_count;
+ else if( cat == 3 )
+ h->cbp_table[mb_xy] |= 0x40 << n;
+ else if( cat == 4 )
+ h->non_zero_count_cache[scan8[16+n]] = coeff_count;
+ else {
+ assert( cat == 5 );
+ fill_rectangle(&h->non_zero_count_cache[scan8[n]], 2, 2, 8, coeff_count, 1);
+ }
+
+ for( coeff_count--; coeff_count >= 0; coeff_count-- ) {
+ uint8_t *ctx = (abslevelgt1 != 0 ? 0 : FFMIN( 4, abslevel1 )) + abs_level_m1_ctx_base;
+ int j= scantable[index[coeff_count]];
+
+ if( get_cabac( CC, ctx ) == 0 ) {
+ if( !qmul ) {
+ block[j] = get_cabac_bypass_sign( CC, -1);
+ }else{
+ block[j] = (get_cabac_bypass_sign( CC, -qmul[j]) + 32) >> 6;;
+ }
+
+ abslevel1++;
+ } else {
+ int coeff_abs = 2;
+ ctx = 5 + FFMIN( 4, abslevelgt1 ) + abs_level_m1_ctx_base;
+ while( coeff_abs < 15 && get_cabac( CC, ctx ) ) {
+ coeff_abs++;
+ }
+
+ if( coeff_abs >= 15 ) {
+ int j = 0;
+ while( get_cabac_bypass( CC ) ) {
+ j++;
+ }
+
+ coeff_abs=1;
+ while( j-- ) {
+ coeff_abs += coeff_abs + get_cabac_bypass( CC );
+ }
+ coeff_abs+= 14;
+ }
+
+ if( !qmul ) {
+ if( get_cabac_bypass( CC ) ) block[j] = -coeff_abs;
+ else block[j] = coeff_abs;
+ }else{
+ if( get_cabac_bypass( CC ) ) block[j] = (-coeff_abs * qmul[j] + 32) >> 6;
+ else block[j] = ( coeff_abs * qmul[j] + 32) >> 6;
+ }
+
+ abslevelgt1++;
+ }
+ }
+#ifdef CABAC_ON_STACK
+ h->cabac.range = cc.range ;
+ h->cabac.low = cc.low ;
+ h->cabac.bytestream= cc.bytestream;
+#endif
+ return 0;
+}
+
+static void inline compute_mb_neighbors(H264Context *h)
+{
+ MpegEncContext * const s = &h->s;
+ const int mb_xy = s->mb_x + s->mb_y*s->mb_stride;
+ h->top_mb_xy = mb_xy - s->mb_stride;
+ h->left_mb_xy[0] = mb_xy - 1;
+ if(FRAME_MBAFF){
+ const int pair_xy = s->mb_x + (s->mb_y & ~1)*s->mb_stride;
+ const int top_pair_xy = pair_xy - s->mb_stride;
+ const int top_mb_frame_flag = !IS_INTERLACED(s->current_picture.mb_type[top_pair_xy]);
+ const int left_mb_frame_flag = !IS_INTERLACED(s->current_picture.mb_type[pair_xy-1]);
+ const int curr_mb_frame_flag = !MB_FIELD;
+ const int bottom = (s->mb_y & 1);
+ if (bottom
+ ? !curr_mb_frame_flag // bottom macroblock
+ : (!curr_mb_frame_flag && !top_mb_frame_flag) // top macroblock
+ ) {
+ h->top_mb_xy -= s->mb_stride;
+ }
+ if (left_mb_frame_flag != curr_mb_frame_flag) {
+ h->left_mb_xy[0] = pair_xy - 1;
+ }
+ }
+ return;
+}
+
+/**
+ * decodes a macroblock
+ * @returns 0 if ok, AC_ERROR / DC_ERROR / MV_ERROR if an error is noticed
+ */
+static int decode_mb_cabac(H264Context *h) {
+ MpegEncContext * const s = &h->s;
+ const int mb_xy= s->mb_x + s->mb_y*s->mb_stride;
+ int mb_type, partition_count, cbp = 0;
+ int dct8x8_allowed= h->pps.transform_8x8_mode;
+
+ s->dsp.clear_blocks(h->mb); //FIXME avoid if already clear (move after skip handlong?)
+
+ tprintf("pic:%d mb:%d/%d\n", h->frame_num, s->mb_x, s->mb_y);
+ if( h->slice_type != I_TYPE && h->slice_type != SI_TYPE ) {
+ int skip;
+ /* a skipped mb needs the aff flag from the following mb */
+ if( FRAME_MBAFF && s->mb_x==0 && (s->mb_y&1)==0 )
+ predict_field_decoding_flag(h);
+ if( FRAME_MBAFF && (s->mb_y&1)==1 && h->prev_mb_skipped )
+ skip = h->next_mb_skipped;
+ else
+ skip = decode_cabac_mb_skip( h, s->mb_x, s->mb_y );
+ /* read skip flags */
+ if( skip ) {
+ if( FRAME_MBAFF && (s->mb_y&1)==0 ){
+ s->current_picture.mb_type[mb_xy] = MB_TYPE_SKIP;
+ h->next_mb_skipped = decode_cabac_mb_skip( h, s->mb_x, s->mb_y+1 );
+ if(h->next_mb_skipped)
+ predict_field_decoding_flag(h);
+ else
+ 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){
+ if( (s->mb_y&1) == 0 )
+ h->mb_mbaff =
+ h->mb_field_decoding_flag = decode_cabac_field_decoding_flag(h);
+ }else
+ h->mb_field_decoding_flag= (s->picture_structure!=PICT_FRAME);
+
+ h->prev_mb_skipped = 0;
+
+ compute_mb_neighbors(h);
+ if( ( mb_type = decode_cabac_mb_type( h ) ) < 0 ) {
+ av_log( h->s.avctx, AV_LOG_ERROR, "decode_cabac_mb_type failed\n" );
+ return -1;
+ }
+
+ if( h->slice_type == B_TYPE ) {
+ 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 == P_TYPE ) {
+ 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 {
+ assert(h->slice_type == I_TYPE);
+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)
+ mb_type |= MB_TYPE_INTERLACED;
+
+ h->slice_table[ mb_xy ]= h->slice_num;
+
+ if(IS_INTRA_PCM(mb_type)) {
+ const uint8_t *ptr;
+ unsigned int x, y;
+
+ // We assume these blocks are very rare so we dont 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-=CABAC_BITS/8;
+
+ // The pixels are stored in the same order as levels in h->mb array.
+ for(y=0; y<16; y++){
+ const int index= 4*(y&3) + 32*((y>>2)&1) + 128*(y>>3);
+ for(x=0; x<16; x++){
+ tprintf("LUMA ICPM LEVEL (%3d)\n", *ptr);
+ h->mb[index + (x&3) + 16*((x>>2)&1) + 64*(x>>3)]= *ptr++;
+ }
+ }
+ for(y=0; y<8; y++){
+ const int index= 256 + 4*(y&3) + 32*(y>>2);
+ for(x=0; x<8; x++){
+ tprintf("CHROMA U ICPM LEVEL (%3d)\n", *ptr);
+ h->mb[index + (x&3) + 16*(x>>2)]= *ptr++;
+ }
+ }
+ for(y=0; y<8; y++){
+ const int index= 256 + 64 + 4*(y&3) + 32*(y>>2);
+ for(x=0; x<8; x++){
+ tprintf("CHROMA V ICPM LEVEL (%3d)\n", *ptr);
+ h->mb[index + (x&3) + 16*(x>>2)]= *ptr++;
+ }
+ }
+
+ ff_init_cabac_decoder(&h->cabac, ptr, h->cabac.bytestream_end - ptr);
+
+ // All blocks are present
+ h->cbp_table[mb_xy] = 0x1ef;
+ h->chroma_pred_mode_table[mb_xy] = 0;
+ // In deblocking, the quantizer is 0
+ s->current_picture.qscale_table[mb_xy]= 0;
+ h->chroma_qp = get_chroma_qp(h->pps.chroma_qp_index_offset, 0);
+ // All coeffs are present
+ memset(h->non_zero_count[mb_xy], 16, 16);
+ s->current_picture.mb_type[mb_xy]= mb_type;
+ return 0;
+ }
+
+ if(MB_MBAFF){
+ h->ref_count[0] <<= 1;
+ h->ref_count[1] <<= 1;
+ }
+
+ fill_caches(h, mb_type, 0);
+
+ if( IS_INTRA( mb_type ) ) {
+ int i;
+ if( IS_INTRA4x4( mb_type ) ) {
+ if( dct8x8_allowed && decode_cabac_mb_transform_size( h ) ) {
+ 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_log( s->avctx, AV_LOG_ERROR, "i4x4 pred=%d mode=%d\n", pred, h->intra4x4_pred_mode_cache[ scan8[i] ] );
+ }
+ }
+ write_back_intra_pred_mode(h);
+ if( check_intra4x4_pred_mode(h) < 0 ) return -1;
+ } else {
+ h->intra16x16_pred_mode= check_intra_pred_mode( h, h->intra16x16_pred_mode );
+ if( h->intra16x16_pred_mode < 0 ) return -1;
+ }
+ h->chroma_pred_mode_table[mb_xy] =
+ h->chroma_pred_mode = decode_cabac_mb_chroma_pre_mode( h );
+
+ h->chroma_pred_mode= check_intra_pred_mode( h, h->chroma_pred_mode );
+ if( h->chroma_pred_mode < 0 ) return -1;
+ } else if( partition_count == 4 ) {
+ int i, j, sub_partition_count[4], list, ref[2][4];
+
+ if( h->slice_type == B_TYPE ) {
+ 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]) ) {
+ pred_direct_motion(h, &mb_type);
+ if( h->ref_count[0] > 1 || h->ref_count[1] > 1 ) {
+ for( i = 0; i < 4; i++ )
+ if( IS_DIRECT(h->sub_mb_type[i]) )
+ fill_rectangle( &h->direct_cache[scan8[4*i]], 2, 2, 8, 1, 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 < 2; list++ ) {
+ if( h->ref_count[list] > 0 ) {
+ 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( h->ref_count[list] > 1 )
+ ref[list][i] = decode_cabac_mb_ref( h, list, 4*i );
+ 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; list<2; list++){
+ for(i=0; i<4; i++){
+ if(IS_DIRECT(h->sub_mb_type[i])){
+ fill_rectangle(h->mvd_cache[list][scan8[4*i]], 2, 2, 8, 0, 4);
+ continue;
+ }
+ h->ref_cache[list][ scan8[4*i] ]=h->ref_cache[list][ scan8[4*i]+1 ];
+
+ 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; j<sub_partition_count[i]; j++){
+ int mpx, mpy;
+ int mx, my;
+ const int index= 4*i + block_width*j;
+ int16_t (* mv_cache)[2]= &h->mv_cache[list][ scan8[index] ];
+ int16_t (* mvd_cache)[2]= &h->mvd_cache[list][ scan8[index] ];
+ pred_motion(h, index, block_width, list, h->ref_cache[list][ scan8[index] ], &mpx, &mpy);
+
+ mx = mpx + decode_cabac_mb_mvd( h, list, index, 0 );
+ my = mpy + decode_cabac_mb_mvd( h, list, index, 1 );
+ tprintf("final mv:%d %d\n", mx, my);
+
+ if(IS_SUB_8X8(sub_mb_type)){
+ mv_cache[ 0 ][0]= mv_cache[ 1 ][0]=
+ mv_cache[ 8 ][0]= mv_cache[ 9 ][0]= mx;
+ mv_cache[ 0 ][1]= mv_cache[ 1 ][1]=
+ mv_cache[ 8 ][1]= mv_cache[ 9 ][1]= my;
+
+ mvd_cache[ 0 ][0]= mvd_cache[ 1 ][0]=
+ mvd_cache[ 8 ][0]= mvd_cache[ 9 ][0]= mx - mpx;
+ mvd_cache[ 0 ][1]= mvd_cache[ 1 ][1]=
+ mvd_cache[ 8 ][1]= mvd_cache[ 9 ][1]= my - mpy;
+ }else if(IS_SUB_8X4(sub_mb_type)){
+ mv_cache[ 0 ][0]= mv_cache[ 1 ][0]= mx;
+ mv_cache[ 0 ][1]= mv_cache[ 1 ][1]= my;
+
+ mvd_cache[ 0 ][0]= mvd_cache[ 1 ][0]= mx- mpx;
+ mvd_cache[ 0 ][1]= mvd_cache[ 1 ][1]= my - mpy;
+ }else if(IS_SUB_4X8(sub_mb_type)){
+ mv_cache[ 0 ][0]= mv_cache[ 8 ][0]= mx;
+ mv_cache[ 0 ][1]= mv_cache[ 8 ][1]= my;
+
+ mvd_cache[ 0 ][0]= mvd_cache[ 8 ][0]= mx - mpx;
+ mvd_cache[ 0 ][1]= mvd_cache[ 8 ][1]= my - mpy;
+ }else{
+ assert(IS_SUB_4X4(sub_mb_type));
+ mv_cache[ 0 ][0]= mx;
+ mv_cache[ 0 ][1]= my;
+
+ mvd_cache[ 0 ][0]= mx - mpx;
+ mvd_cache[ 0 ][1]= my - mpy;
+ }
+ }
+ }else{
+ uint32_t *p= (uint32_t *)&h->mv_cache[list][ scan8[4*i] ][0];
+ uint32_t *pd= (uint32_t *)&h->mvd_cache[list][ scan8[4*i] ][0];
+ p[0] = p[1] = p[8] = p[9] = 0;
+ pd[0]= pd[1]= pd[8]= pd[9]= 0;
+ }
+ }
+ }
+ } else if( IS_DIRECT(mb_type) ) {
+ pred_direct_motion(h, &mb_type);
+ fill_rectangle(h->mvd_cache[0][scan8[0]], 4, 4, 8, 0, 4);
+ fill_rectangle(h->mvd_cache[1][scan8[0]], 4, 4, 8, 0, 4);
+ dct8x8_allowed &= h->sps.direct_8x8_inference_flag;
+ } else {
+ int list, mx, my, i, mpx, mpy;
+ if(IS_16X16(mb_type)){
+ for(list=0; list<2; list++){
+ if(IS_DIR(mb_type, 0, list)){
+ if(h->ref_count[list] > 0 ){
+ const int ref = h->ref_count[list] > 1 ? decode_cabac_mb_ref( h, list, 0 ) : 0;
+ fill_rectangle(&h->ref_cache[list][ scan8[0] ], 4, 4, 8, ref, 1);
+ }
+ }else
+ fill_rectangle(&h->ref_cache[list][ scan8[0] ], 4, 4, 8, (uint8_t)LIST_NOT_USED, 1);
+ }
+ for(list=0; list<2; list++){
+ if(IS_DIR(mb_type, 0, list)){
+ pred_motion(h, 0, 4, list, h->ref_cache[list][ scan8[0] ], &mpx, &mpy);
+
+ mx = mpx + decode_cabac_mb_mvd( h, list, 0, 0 );
+ my = mpy + decode_cabac_mb_mvd( h, list, 0, 1 );
+ tprintf("final mv:%d %d\n", mx, my);
+
+ fill_rectangle(h->mvd_cache[list][ scan8[0] ], 4, 4, 8, pack16to32(mx-mpx,my-mpy), 4);
+ fill_rectangle(h->mv_cache[list][ scan8[0] ], 4, 4, 8, pack16to32(mx,my), 4);
+ }else
+ fill_rectangle(h->mv_cache[list][ scan8[0] ], 4, 4, 8, 0, 4);
+ }
+ }
+ else if(IS_16X8(mb_type)){
+ for(list=0; list<2; list++){
+ if(h->ref_count[list]>0){
+ for(i=0; i<2; i++){
+ if(IS_DIR(mb_type, i, list)){
+ const int ref= h->ref_count[list] > 1 ? decode_cabac_mb_ref( h, list, 8*i ) : 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; list<2; list++){
+ for(i=0; i<2; i++){
+ if(IS_DIR(mb_type, i, list)){
+ pred_16x8_motion(h, 8*i, list, h->ref_cache[list][scan8[0] + 16*i], &mpx, &mpy);
+ mx = mpx + decode_cabac_mb_mvd( h, list, 8*i, 0 );
+ my = mpy + decode_cabac_mb_mvd( h, list, 8*i, 1 );
+ tprintf("final mv:%d %d\n", mx, my);
+
+ fill_rectangle(h->mvd_cache[list][ scan8[0] + 16*i ], 4, 2, 8, pack16to32(mx-mpx,my-mpy), 4);
+ 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, 4);
+ fill_rectangle(h-> mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, 0, 4);
+ }
+ }
+ }
+ }else{
+ assert(IS_8X16(mb_type));
+ for(list=0; list<2; list++){
+ if(h->ref_count[list]>0){
+ for(i=0; i<2; i++){
+ if(IS_DIR(mb_type, i, list)){ //FIXME optimize
+ const int ref= h->ref_count[list] > 1 ? decode_cabac_mb_ref( h, list, 4*i ) : 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; list<2; list++){
+ for(i=0; i<2; i++){
+ if(IS_DIR(mb_type, i, list)){
+ pred_8x16_motion(h, i*4, list, h->ref_cache[list][ scan8[0] + 2*i ], &mpx, &mpy);
+ mx = mpx + decode_cabac_mb_mvd( h, list, 4*i, 0 );
+ my = mpy + decode_cabac_mb_mvd( h, list, 4*i, 1 );
+
+ tprintf("final mv:%d %d\n", mx, my);
+ fill_rectangle(h->mvd_cache[list][ scan8[0] + 2*i ], 2, 4, 8, pack16to32(mx-mpx,my-mpy), 4);
+ 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, 4);
+ 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 );
+ cbp |= decode_cabac_mb_cbp_chroma( h ) << 4;
+ }
+
+ h->cbp_table[mb_xy] = h->cbp = cbp;
+
+ if( dct8x8_allowed && (cbp&15) && !IS_INTRA( mb_type ) ) {
+ if( decode_cabac_mb_transform_size( h ) )
+ mb_type |= MB_TYPE_8x8DCT;
+ }
+ s->current_picture.mb_type[mb_xy]= mb_type;
+
+ if( cbp || IS_INTRA16x16( mb_type ) ) {
+ const uint8_t *scan, *scan8x8, *dc_scan;
+ int dqp;
+
+ if(IS_INTERLACED(mb_type)){
+ scan8x8= s->qscale ? h->field_scan8x8 : h->field_scan8x8_q0;
+ scan= s->qscale ? h->field_scan : h->field_scan_q0;
+ dc_scan= luma_dc_field_scan;
+ }else{
+ scan8x8= s->qscale ? h->zigzag_scan8x8 : h->zigzag_scan8x8_q0;
+ scan= s->qscale ? h->zigzag_scan : h->zigzag_scan_q0;
+ dc_scan= luma_dc_zigzag_scan;
+ }
+
+ h->last_qscale_diff = dqp = decode_cabac_mb_dqp( h );
+ if( dqp == INT_MIN ){
+ av_log(h->s.avctx, AV_LOG_ERROR, "cabac decode of qscale diff failed at %d %d\n", s->mb_x, s->mb_y);
+ return -1;
+ }
+ s->qscale += dqp;
+ if(((unsigned)s->qscale) > 51){
+ if(s->qscale<0) s->qscale+= 52;
+ else s->qscale-= 52;
+ }
+ h->chroma_qp = get_chroma_qp(h->pps.chroma_qp_index_offset, s->qscale);
+
+ if( IS_INTRA16x16( mb_type ) ) {
+ int i;
+ //av_log( s->avctx, AV_LOG_ERROR, "INTRA16x16 DC\n" );
+ if( decode_cabac_residual( h, h->mb, 0, 0, dc_scan, NULL, 16) < 0)
+ return -1;
+ if( cbp&15 ) {
+ for( i = 0; i < 16; i++ ) {
+ //av_log( s->avctx, AV_LOG_ERROR, "INTRA16x16 AC:%d\n", i );
+ if( decode_cabac_residual(h, h->mb + 16*i, 1, i, scan + 1, h->dequant4_coeff[0][s->qscale], 15) < 0 )
+ return -1;
+ }
+ } else {
+ fill_rectangle(&h->non_zero_count_cache[scan8[0]], 4, 4, 8, 0, 1);
+ }
+ } else {
+ int i8x8, i4x4;
+ for( i8x8 = 0; i8x8 < 4; i8x8++ ) {
+ if( cbp & (1<<i8x8) ) {
+ if( IS_8x8DCT(mb_type) ) {
+ if( decode_cabac_residual(h, h->mb + 64*i8x8, 5, 4*i8x8,
+ scan8x8, h->dequant8_coeff[IS_INTRA( mb_type ) ? 0:1][s->qscale], 64) < 0 )
+ return -1;
+ } else
+ for( i4x4 = 0; i4x4 < 4; i4x4++ ) {
+ const int index = 4*i8x8 + i4x4;
+ //av_log( s->avctx, AV_LOG_ERROR, "Luma4x4: %d\n", index );
+//START_TIMER
+ if( decode_cabac_residual(h, h->mb + 16*index, 2, index, scan, h->dequant4_coeff[IS_INTRA( mb_type ) ? 0:3][s->qscale], 16) < 0 )
+ return -1;
+//STOP_TIMER("decode_residual")
+ }
+ } else {
+ uint8_t * const nnz= &h->non_zero_count_cache[ scan8[4*i8x8] ];
+ nnz[0] = nnz[1] = nnz[8] = nnz[9] = 0;
+ }
+ }
+ }
+
+ if( cbp&0x30 ){
+ int c;
+ for( c = 0; c < 2; c++ ) {
+ //av_log( s->avctx, AV_LOG_ERROR, "INTRA C%d-DC\n",c );
+ if( decode_cabac_residual(h, h->mb + 256 + 16*4*c, 3, c, chroma_dc_scan, NULL, 4) < 0)
+ return -1;
+ }
+ }
+
+ if( cbp&0x20 ) {
+ int c, i;
+ for( c = 0; c < 2; c++ ) {
+ for( i = 0; i < 4; i++ ) {
+ const int index = 16 + 4 * c + i;
+ //av_log( s->avctx, AV_LOG_ERROR, "INTRA C%d-AC %d\n",c, index - 16 );
+ if( decode_cabac_residual(h, h->mb + 16*index, 4, index - 16, scan + 1, h->dequant4_coeff[c+1+(IS_INTRA( mb_type ) ? 0:3)][h->chroma_qp], 15) < 0)
+ return -1;
+ }
+ }
+ } else {
+ uint8_t * const nnz= &h->non_zero_count_cache[0];
+ nnz[ scan8[16]+0 ] = nnz[ scan8[16]+1 ] =nnz[ scan8[16]+8 ] =nnz[ scan8[16]+9 ] =
+ nnz[ scan8[20]+0 ] = nnz[ scan8[20]+1 ] =nnz[ scan8[20]+8 ] =nnz[ scan8[20]+9 ] = 0;
+ }
+ } else {
+ uint8_t * const nnz= &h->non_zero_count_cache[0];
+ fill_rectangle(&nnz[scan8[0]], 4, 4, 8, 0, 1);
+ nnz[ scan8[16]+0 ] = nnz[ scan8[16]+1 ] =nnz[ scan8[16]+8 ] =nnz[ scan8[16]+9 ] =
+ nnz[ scan8[20]+0 ] = nnz[ scan8[20]+1 ] =nnz[ scan8[20]+8 ] =nnz[ scan8[20]+9 ] = 0;
+ h->last_qscale_diff = 0;
+ }
+
+ s->current_picture.qscale_table[mb_xy]= s->qscale;
+ write_back_non_zero_count(h);
+
+ if(MB_MBAFF){
+ h->ref_count[0] >>= 1;
+ h->ref_count[1] >>= 1;
+ }
+
+ return 0;
+}
+
+
+static void filter_mb_edgev( H264Context *h, uint8_t *pix, int stride, int16_t bS[4], int qp ) {
+ int i, d;
+ const int index_a = qp + h->slice_alpha_c0_offset;
+ const int alpha = (alpha_table+52)[index_a];
+ const int beta = (beta_table+52)[qp + h->slice_beta_offset];
+
+ if( bS[0] < 4 ) {
+ int8_t tc[4];
+ for(i=0; i<4; i++)
+ tc[i] = bS[i] ? (tc0_table+52)[index_a][bS[i] - 1] : -1;
+ h->s.dsp.h264_h_loop_filter_luma(pix, stride, alpha, beta, tc);
+ } else {
+ /* 16px edge length, because bS=4 is triggered by being at
+ * the edge of an intra MB, so all 4 bS are the same */
+ for( d = 0; d < 16; d++ ) {
+ const int p0 = pix[-1];
+ const int p1 = pix[-2];
+ const int p2 = pix[-3];
+
+ const int q0 = pix[0];
+ const int q1 = pix[1];
+ const int q2 = pix[2];
+
+ 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];
+ /* p0', p1', p2' */
+ pix[-1] = ( p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 ) >> 3;
+ pix[-2] = ( p2 + p1 + p0 + q0 + 2 ) >> 2;
+ pix[-3] = ( 2*p3 + 3*p2 + p1 + p0 + q0 + 4 ) >> 3;
+ } else {
+ /* p0' */
+ pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
+ }
+ if( FFABS( q2 - q0 ) < beta)
+ {
+ const int q3 = pix[3];
+ /* q0', q1', q2' */
+ pix[0] = ( p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 ) >> 3;
+ pix[1] = ( p0 + q0 + q1 + q2 + 2 ) >> 2;
+ pix[2] = ( 2*q3 + 3*q2 + q1 + q0 + p0 + 4 ) >> 3;
+ } else {
+ /* q0' */
+ pix[0] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
+ }
+ }else{
+ /* p0', q0' */
+ pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
+ pix[ 0] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
+ }
+ tprintf("filter_mb_edgev i:%d d:%d\n# bS:4 -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, d, p2, p1, p0, q0, q1, q2, pix[-2], pix[-1], pix[0], pix[1]);
+ }
+ pix += stride;
+ }
+ }
+}
+static void filter_mb_edgecv( H264Context *h, uint8_t *pix, int stride, int16_t bS[4], int qp ) {
+ int i;
+ const int index_a = qp + h->slice_alpha_c0_offset;
+ const int alpha = (alpha_table+52)[index_a];
+ const int beta = (beta_table+52)[qp + h->slice_beta_offset];
+
+ if( bS[0] < 4 ) {
+ int8_t tc[4];
+ for(i=0; i<4; i++)
+ tc[i] = bS[i] ? (tc0_table+52)[index_a][bS[i] - 1] + 1 : 0;
+ h->s.dsp.h264_h_loop_filter_chroma(pix, stride, alpha, beta, tc);
+ } else {
+ h->s.dsp.h264_h_loop_filter_chroma_intra(pix, stride, alpha, beta);
+ }
+}
+
+static void filter_mb_mbaff_edgev( H264Context *h, uint8_t *pix, int stride, int16_t bS[8], int qp[2] ) {
+ int i;
+ for( i = 0; i < 16; i++, pix += stride) {
+ int index_a;
+ int alpha;
+ int beta;
+
+ int qp_index;
+ int bS_index = (i >> 1);
+ if (!MB_FIELD) {
+ bS_index &= ~1;
+ bS_index |= (i & 1);
+ }
+
+ if( bS[bS_index] == 0 ) {
+ continue;
+ }
+
+ qp_index = MB_FIELD ? (i >> 3) : (i & 1);
+ index_a = qp[qp_index] + h->slice_alpha_c0_offset;
+ alpha = (alpha_table+52)[index_a];
+ beta = (beta_table+52)[qp[qp_index] + h->slice_beta_offset];
+
+ if( bS[bS_index] < 4 ) {
+ const int tc0 = (tc0_table+52)[index_a][bS[bS_index] - 1];
+ const int p0 = pix[-1];
+ const int p1 = pix[-2];
+ const int p2 = pix[-3];
+ const int q0 = pix[0];
+ const int q1 = pix[1];
+ const int q2 = pix[2];
+
+ if( FFABS( p0 - q0 ) < alpha &&
+ FFABS( p1 - p0 ) < beta &&
+ FFABS( q1 - q0 ) < beta ) {
+ int tc = tc0;
+ int i_delta;
+
+ if( FFABS( p2 - p0 ) < beta ) {
+ pix[-2] = p1 + clip( ( p2 + ( ( p0 + q0 + 1 ) >> 1 ) - ( p1 << 1 ) ) >> 1, -tc0, tc0 );
+ tc++;
+ }
+ if( FFABS( q2 - q0 ) < beta ) {
+ pix[1] = q1 + clip( ( q2 + ( ( p0 + q0 + 1 ) >> 1 ) - ( q1 << 1 ) ) >> 1, -tc0, tc0 );
+ tc++;
+ }
+
+ i_delta = clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
+ pix[-1] = clip_uint8( p0 + i_delta ); /* p0' */
+ pix[0] = clip_uint8( q0 - i_delta ); /* q0' */
+ tprintf("filter_mb_mbaff_edgev i:%d, qp:%d, indexA:%d, alpha:%d, beta:%d, tc:%d\n# bS:%d -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, qp[qp_index], index_a, alpha, beta, tc, bS[bS_index], pix[-3], p1, p0, q0, q1, pix[2], p1, pix[-1], pix[0], q1);
+ }
+ }else{
+ const int p0 = pix[-1];
+ const int p1 = pix[-2];
+ const int p2 = pix[-3];
+
+ const int q0 = pix[0];
+ const int q1 = pix[1];
+ const int q2 = pix[2];
+
+ 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];
+ /* p0', p1', p2' */
+ pix[-1] = ( p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 ) >> 3;
+ pix[-2] = ( p2 + p1 + p0 + q0 + 2 ) >> 2;
+ pix[-3] = ( 2*p3 + 3*p2 + p1 + p0 + q0 + 4 ) >> 3;
+ } else {
+ /* p0' */
+ pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
+ }
+ if( FFABS( q2 - q0 ) < beta)
+ {
+ const int q3 = pix[3];
+ /* q0', q1', q2' */
+ pix[0] = ( p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 ) >> 3;
+ pix[1] = ( p0 + q0 + q1 + q2 + 2 ) >> 2;
+ pix[2] = ( 2*q3 + 3*q2 + q1 + q0 + p0 + 4 ) >> 3;
+ } else {
+ /* q0' */
+ pix[0] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
+ }
+ }else{
+ /* p0', q0' */
+ pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
+ pix[ 0] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
+ }
+ tprintf("filter_mb_mbaff_edgev i:%d, qp:%d, indexA:%d, alpha:%d, beta:%d\n# bS:4 -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x, %02x, %02x]\n", i, qp[qp_index], index_a, alpha, beta, p2, p1, p0, q0, q1, q2, pix[-3], pix[-2], pix[-1], pix[0], pix[1], pix[2]);
+ }
+ }
+ }
+}
+static void filter_mb_mbaff_edgecv( H264Context *h, uint8_t *pix, int stride, int16_t bS[8], int qp[2] ) {
+ int i;
+ for( i = 0; i < 8; i++, pix += stride) {
+ int index_a;
+ int alpha;
+ int beta;
+
+ int qp_index;
+ int bS_index = i;
+
+ if( bS[bS_index] == 0 ) {
+ continue;
+ }
+
+ qp_index = MB_FIELD ? (i >> 2) : (i & 1);
+ index_a = qp[qp_index] + h->slice_alpha_c0_offset;
+ alpha = (alpha_table+52)[index_a];
+ beta = (beta_table+52)[qp[qp_index] + h->slice_beta_offset];
+
+ if( bS[bS_index] < 4 ) {
+ const int tc = (tc0_table+52)[index_a][bS[bS_index] - 1] + 1;
+ const int p0 = pix[-1];
+ const int p1 = pix[-2];
+ const int q0 = pix[0];
+ const int q1 = pix[1];
+
+ if( FFABS( p0 - q0 ) < alpha &&
+ FFABS( p1 - p0 ) < beta &&
+ FFABS( q1 - q0 ) < beta ) {
+ const int i_delta = clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
+
+ pix[-1] = clip_uint8( p0 + i_delta ); /* p0' */
+ pix[0] = clip_uint8( q0 - i_delta ); /* q0' */
+ tprintf("filter_mb_mbaff_edgecv i:%d, qp:%d, indexA:%d, alpha:%d, beta:%d, tc:%d\n# bS:%d -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, qp[qp_index], index_a, alpha, beta, tc, bS[bS_index], pix[-3], p1, p0, q0, q1, pix[2], p1, pix[-1], pix[0], q1);
+ }
+ }else{
+ const int p0 = pix[-1];
+ const int p1 = pix[-2];
+ const int q0 = pix[0];
+ const int q1 = pix[1];
+
+ if( FFABS( p0 - q0 ) < alpha &&
+ FFABS( p1 - p0 ) < beta &&
+ FFABS( q1 - q0 ) < beta ) {
+
+ pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2; /* p0' */
+ pix[0] = ( 2*q1 + q0 + p1 + 2 ) >> 2; /* q0' */
+ tprintf("filter_mb_mbaff_edgecv i:%d\n# bS:4 -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x, %02x, %02x]\n", i, pix[-3], p1, p0, q0, q1, pix[2], pix[-3], pix[-2], pix[-1], pix[0], pix[1], pix[2]);
+ }
+ }
+ }
+}
+
+static void filter_mb_edgeh( H264Context *h, uint8_t *pix, int stride, int16_t bS[4], int qp ) {
+ int i, d;
+ const int index_a = qp + h->slice_alpha_c0_offset;
+ const int alpha = (alpha_table+52)[index_a];
+ const int beta = (beta_table+52)[qp + h->slice_beta_offset];
+ const int pix_next = stride;
+
+ if( bS[0] < 4 ) {
+ int8_t tc[4];
+ for(i=0; i<4; i++)
+ tc[i] = bS[i] ? (tc0_table+52)[index_a][bS[i] - 1] : -1;
+ h->s.dsp.h264_v_loop_filter_luma(pix, stride, alpha, beta, tc);
+ } else {
+ /* 16px edge length, see filter_mb_edgev */
+ for( d = 0; d < 16; d++ ) {
+ const int p0 = pix[-1*pix_next];
+ const int p1 = pix[-2*pix_next];
+ const int p2 = pix[-3*pix_next];
+ const int q0 = pix[0];
+ const int q1 = pix[1*pix_next];
+ const int q2 = pix[2*pix_next];
+
+ if( FFABS( p0 - q0 ) < alpha &&
+ FFABS( p1 - p0 ) < beta &&
+ FFABS( q1 - q0 ) < beta ) {
+
+ const int p3 = pix[-4*pix_next];
+ const int q3 = pix[ 3*pix_next];
+
+ if(FFABS( p0 - q0 ) < (( alpha >> 2 ) + 2 )){
+ if( FFABS( p2 - p0 ) < beta) {
+ /* p0', p1', p2' */
+ pix[-1*pix_next] = ( p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 ) >> 3;
+ pix[-2*pix_next] = ( p2 + p1 + p0 + q0 + 2 ) >> 2;
+ pix[-3*pix_next] = ( 2*p3 + 3*p2 + p1 + p0 + q0 + 4 ) >> 3;
+ } else {
+ /* p0' */
+ pix[-1*pix_next] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
+ }
+ if( FFABS( q2 - q0 ) < beta) {
+ /* q0', q1', q2' */
+ pix[0*pix_next] = ( p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 ) >> 3;
+ pix[1*pix_next] = ( p0 + q0 + q1 + q2 + 2 ) >> 2;
+ pix[2*pix_next] = ( 2*q3 + 3*q2 + q1 + q0 + p0 + 4 ) >> 3;
+ } else {
+ /* q0' */
+ pix[0*pix_next] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
+ }
+ }else{
+ /* p0', q0' */
+ pix[-1*pix_next] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
+ pix[ 0*pix_next] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
+ }
+ tprintf("filter_mb_edgeh i:%d d:%d, qp:%d, indexA:%d, alpha:%d, beta:%d\n# bS:%d -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, d, qp, index_a, alpha, beta, bS[i], p2, p1, p0, q0, q1, q2, pix[-2*pix_next], pix[-pix_next], pix[0], pix[pix_next]);
+ }
+ pix++;
+ }
+ }
+}
+
+static void filter_mb_edgech( H264Context *h, uint8_t *pix, int stride, int16_t bS[4], int qp ) {
+ int i;
+ const int index_a = qp + h->slice_alpha_c0_offset;
+ const int alpha = (alpha_table+52)[index_a];
+ const int beta = (beta_table+52)[qp + h->slice_beta_offset];
+
+ if( bS[0] < 4 ) {
+ int8_t tc[4];
+ for(i=0; i<4; i++)
+ tc[i] = bS[i] ? (tc0_table+52)[index_a][bS[i] - 1] + 1 : 0;
+ h->s.dsp.h264_v_loop_filter_chroma(pix, stride, alpha, beta, tc);
+ } else {
+ h->s.dsp.h264_v_loop_filter_chroma_intra(pix, stride, alpha, beta);
+ }
+}
+
+static void 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) {
+ MpegEncContext * const s = &h->s;
+ int mb_xy, mb_type;
+ int qp, qp0, qp1, qpc, qpc0, qpc1, qp_thresh;
+
+ if(mb_x==0 || mb_y==0 || !s->dsp.h264_loop_filter_strength) {
+ filter_mb(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize);
+ return;
+ }
+ assert(!FRAME_MBAFF);
+
+ mb_xy = mb_x + mb_y*s->mb_stride;
+ mb_type = s->current_picture.mb_type[mb_xy];
+ qp = s->current_picture.qscale_table[mb_xy];
+ qp0 = s->current_picture.qscale_table[mb_xy-1];
+ qp1 = s->current_picture.qscale_table[h->top_mb_xy];
+ qpc = get_chroma_qp( h->pps.chroma_qp_index_offset, qp );
+ qpc0 = get_chroma_qp( h->pps.chroma_qp_index_offset, qp0 );
+ qpc1 = get_chroma_qp( h->pps.chroma_qp_index_offset, qp1 );
+ qp0 = (qp + qp0 + 1) >> 1;
+ qp1 = (qp + qp1 + 1) >> 1;
+ qpc0 = (qpc + qpc0 + 1) >> 1;
+ qpc1 = (qpc + qpc1 + 1) >> 1;
+ qp_thresh = 15 - h->slice_alpha_c0_offset;
+ if(qp <= qp_thresh && qp0 <= qp_thresh && qp1 <= qp_thresh &&
+ qpc <= qp_thresh && qpc0 <= qp_thresh && qpc1 <= qp_thresh)
+ return;
+
+ if( IS_INTRA(mb_type) ) {
+ int16_t bS4[4] = {4,4,4,4};
+ int16_t bS3[4] = {3,3,3,3};
+ if( IS_8x8DCT(mb_type) ) {
+ filter_mb_edgev( h, &img_y[4*0], linesize, bS4, qp0 );
+ filter_mb_edgev( h, &img_y[4*2], linesize, bS3, qp );
+ filter_mb_edgeh( h, &img_y[4*0*linesize], linesize, bS4, qp1 );
+ filter_mb_edgeh( h, &img_y[4*2*linesize], linesize, bS3, qp );
+ } else {
+ filter_mb_edgev( h, &img_y[4*0], linesize, bS4, qp0 );
+ filter_mb_edgev( h, &img_y[4*1], linesize, bS3, qp );
+ filter_mb_edgev( h, &img_y[4*2], linesize, bS3, qp );
+ filter_mb_edgev( h, &img_y[4*3], linesize, bS3, qp );
+ filter_mb_edgeh( h, &img_y[4*0*linesize], linesize, bS4, qp1 );
+ filter_mb_edgeh( h, &img_y[4*1*linesize], linesize, bS3, qp );
+ filter_mb_edgeh( h, &img_y[4*2*linesize], linesize, bS3, qp );
+ filter_mb_edgeh( h, &img_y[4*3*linesize], linesize, bS3, qp );
+ }
+ filter_mb_edgecv( h, &img_cb[2*0], uvlinesize, bS4, qpc0 );
+ filter_mb_edgecv( h, &img_cb[2*2], uvlinesize, bS3, qpc );
+ filter_mb_edgecv( h, &img_cr[2*0], uvlinesize, bS4, qpc0 );
+ filter_mb_edgecv( h, &img_cr[2*2], uvlinesize, bS3, qpc );
+ filter_mb_edgech( h, &img_cb[2*0*uvlinesize], uvlinesize, bS4, qpc1 );
+ filter_mb_edgech( h, &img_cb[2*2*uvlinesize], uvlinesize, bS3, qpc );
+ filter_mb_edgech( h, &img_cr[2*0*uvlinesize], uvlinesize, bS4, qpc1 );
+ filter_mb_edgech( h, &img_cr[2*2*uvlinesize], uvlinesize, bS3, qpc );
+ return;
+ } else {
+ DECLARE_ALIGNED_8(int16_t, bS[2][4][4]);
+ uint64_t (*bSv)[4] = (uint64_t(*)[4])bS;
+ int edges;
+ if( IS_8x8DCT(mb_type) && (h->cbp&7) == 7 ) {
+ edges = 4;
+ bSv[0][0] = bSv[0][2] = bSv[1][0] = bSv[1][2] = 0x0002000200020002ULL;
+ } else {
+ int mask_edge1 = (mb_type & (MB_TYPE_16x16 | MB_TYPE_8x16)) ? 3 :
+ (mb_type & MB_TYPE_16x8) ? 1 : 0;
+ int mask_edge0 = (mb_type & (MB_TYPE_16x16 | MB_TYPE_8x16))
+ && (s->current_picture.mb_type[mb_xy-1] & (MB_TYPE_16x16 | MB_TYPE_8x16))
+ ? 3 : 0;
+ int step = IS_8x8DCT(mb_type) ? 2 : 1;
+ edges = (mb_type & MB_TYPE_16x16) && !(h->cbp & 15) ? 1 : 4;
+ s->dsp.h264_loop_filter_strength( bS, h->non_zero_count_cache, h->ref_cache, h->mv_cache,
+ (h->slice_type == B_TYPE), edges, step, mask_edge0, mask_edge1 );
+ }
+ if( IS_INTRA(s->current_picture.mb_type[mb_xy-1]) )
+ bSv[0][0] = 0x0004000400040004ULL;
+ if( IS_INTRA(s->current_picture.mb_type[h->top_mb_xy]) )
+ bSv[1][0] = 0x0004000400040004ULL;
+
+#define FILTER(hv,dir,edge)\
+ if(bSv[dir][edge]) {\
+ filter_mb_edge##hv( h, &img_y[4*edge*(dir?linesize:1)], linesize, bS[dir][edge], edge ? qp : qp##dir );\
+ if(!(edge&1)) {\
+ filter_mb_edgec##hv( h, &img_cb[2*edge*(dir?uvlinesize:1)], uvlinesize, bS[dir][edge], edge ? qpc : qpc##dir );\
+ filter_mb_edgec##hv( h, &img_cr[2*edge*(dir?uvlinesize:1)], uvlinesize, bS[dir][edge], edge ? qpc : qpc##dir );\
+ }\
+ }
+ if( edges == 1 ) {
+ FILTER(v,0,0);
+ FILTER(h,1,0);
+ } else if( IS_8x8DCT(mb_type) ) {
+ FILTER(v,0,0);
+ FILTER(v,0,2);
+ FILTER(h,1,0);
+ FILTER(h,1,2);
+ } else {
+ FILTER(v,0,0);
+ FILTER(v,0,1);
+ FILTER(v,0,2);
+ FILTER(v,0,3);
+ FILTER(h,1,0);
+ FILTER(h,1,1);
+ FILTER(h,1,2);
+ FILTER(h,1,3);
+ }
+#undef FILTER
+ }
+}
+
+static void 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) {
+ MpegEncContext * const s = &h->s;
+ const int mb_xy= mb_x + mb_y*s->mb_stride;
+ const int mb_type = s->current_picture.mb_type[mb_xy];
+ const int mvy_limit = IS_INTERLACED(mb_type) ? 2 : 4;
+ int first_vertical_edge_done = 0;
+ int dir;
+ /* FIXME: A given frame may occupy more than one position in
+ * the reference list. So ref2frm should be populated with
+ * frame numbers, not indices. */
+ static const int ref2frm[34] = {-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};
+
+ //for sufficiently low qp, filtering wouldn't do anything
+ //this is a conservative estimate: could also check beta_offset and more accurate chroma_qp
+ if(!FRAME_MBAFF){
+ int qp_thresh = 15 - h->slice_alpha_c0_offset - FFMAX(0, h->pps.chroma_qp_index_offset);
+ int qp = s->current_picture.qscale_table[mb_xy];
+ if(qp <= qp_thresh
+ && (mb_x == 0 || ((qp + s->current_picture.qscale_table[mb_xy-1] + 1)>>1) <= qp_thresh)
+ && (mb_y == 0 || ((qp + s->current_picture.qscale_table[h->top_mb_xy] + 1)>>1) <= qp_thresh)){
+ return;
+ }
+ }
+
+ if (FRAME_MBAFF
+ // left mb is in picture
+ && h->slice_table[mb_xy-1] != 255
+ // and current and left pair do not have the same interlaced type
+ && (IS_INTERLACED(mb_type) != IS_INTERLACED(s->current_picture.mb_type[mb_xy-1]))
+ // and left mb is in the same slice if deblocking_filter == 2
+ && (h->deblocking_filter!=2 || h->slice_table[mb_xy-1] == h->slice_table[mb_xy])) {
+ /* First vertical edge is different in MBAFF frames
+ * There are 8 different bS to compute and 2 different Qp
+ */
+ const int pair_xy = mb_x + (mb_y&~1)*s->mb_stride;
+ const int left_mb_xy[2] = { pair_xy-1, pair_xy-1+s->mb_stride };
+ int16_t bS[8];
+ int qp[2];
+ int chroma_qp[2];
+ int mb_qp, mbn0_qp, mbn1_qp;
+ int i;
+ first_vertical_edge_done = 1;
+
+ if( IS_INTRA(mb_type) )
+ bS[0] = bS[1] = bS[2] = bS[3] = bS[4] = bS[5] = bS[6] = bS[7] = 4;
+ else {
+ for( i = 0; i < 8; i++ ) {
+ int mbn_xy = MB_FIELD ? left_mb_xy[i>>2] : left_mb_xy[i&1];
+
+ if( IS_INTRA( s->current_picture.mb_type[mbn_xy] ) )
+ bS[i] = 4;
+ else if( h->non_zero_count_cache[12+8*(i>>1)] != 0 ||
+ /* FIXME: with 8x8dct + cavlc, should check cbp instead of nnz */
+ h->non_zero_count[mbn_xy][MB_FIELD ? i&3 : (i>>2)+(mb_y&1)*2] )
+ bS[i] = 2;
+ else
+ bS[i] = 1;
+ }
+ }
+
+ mb_qp = s->current_picture.qscale_table[mb_xy];
+ mbn0_qp = s->current_picture.qscale_table[left_mb_xy[0]];
+ mbn1_qp = s->current_picture.qscale_table[left_mb_xy[1]];
+ qp[0] = ( mb_qp + mbn0_qp + 1 ) >> 1;
+ chroma_qp[0] = ( get_chroma_qp( h->pps.chroma_qp_index_offset, mb_qp ) +
+ get_chroma_qp( h->pps.chroma_qp_index_offset, mbn0_qp ) + 1 ) >> 1;
+ qp[1] = ( mb_qp + mbn1_qp + 1 ) >> 1;
+ chroma_qp[1] = ( get_chroma_qp( h->pps.chroma_qp_index_offset, mb_qp ) +
+ get_chroma_qp( h->pps.chroma_qp_index_offset, mbn1_qp ) + 1 ) >> 1;
+
+ /* Filter edge */
+ tprintf("filter mb:%d/%d MBAFF, QPy:%d/%d, QPc:%d/%d ls:%d uvls:%d", mb_x, mb_y, qp[0], qp[1], chroma_qp[0], chroma_qp[1], linesize, uvlinesize);
+ { int i; for (i = 0; i < 8; i++) tprintf(" bS[%d]:%d", i, bS[i]); tprintf("\n"); }
+ filter_mb_mbaff_edgev ( h, &img_y [0], linesize, bS, qp );
+ filter_mb_mbaff_edgecv( h, &img_cb[0], uvlinesize, bS, chroma_qp );
+ filter_mb_mbaff_edgecv( h, &img_cr[0], uvlinesize, bS, chroma_qp );
+ }
+ /* dir : 0 -> vertical edge, 1 -> horizontal edge */
+ for( dir = 0; dir < 2; dir++ )
+ {
+ int edge;
+ const int mbm_xy = dir == 0 ? mb_xy -1 : h->top_mb_xy;
+ const int mbm_type = s->current_picture.mb_type[mbm_xy];
+ int start = h->slice_table[mbm_xy] == 255 ? 1 : 0;
+
+ const int edges = (mb_type & (MB_TYPE_16x16|MB_TYPE_SKIP))
+ == (MB_TYPE_16x16|MB_TYPE_SKIP) ? 1 : 4;
+ // how often to recheck mv-based bS when iterating between edges
+ const int mask_edge = (mb_type & (MB_TYPE_16x16 | (MB_TYPE_16x8 << dir))) ? 3 :
+ (mb_type & (MB_TYPE_8x16 >> dir)) ? 1 : 0;
+ // 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 (first_vertical_edge_done) {
+ start = 1;
+ first_vertical_edge_done = 0;
+ }
+
+ if (h->deblocking_filter==2 && h->slice_table[mbm_xy] != h->slice_table[mb_xy])
+ start = 1;
+
+ if (FRAME_MBAFF && (dir == 1) && ((mb_y&1) == 0) && start == 0
+ && !IS_INTERLACED(mb_type)
+ && IS_INTERLACED(mbm_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.
+ //
+ static const int nnz_idx[4] = {4,5,6,3};
+ unsigned int tmp_linesize = 2 * linesize;
+ unsigned int tmp_uvlinesize = 2 * uvlinesize;
+ int mbn_xy = mb_xy - 2 * s->mb_stride;
+ int qp, chroma_qp;
+ int i, j;
+ int16_t bS[4];
+
+ for(j=0; j<2; j++, mbn_xy += s->mb_stride){
+ if( IS_INTRA(mb_type) ||
+ IS_INTRA(s->current_picture.mb_type[mbn_xy]) ) {
+ bS[0] = bS[1] = bS[2] = bS[3] = 3;
+ } else {
+ const uint8_t *mbn_nnz = h->non_zero_count[mbn_xy];
+ for( i = 0; i < 4; i++ ) {
+ if( h->non_zero_count_cache[scan8[0]+i] != 0 ||
+ mbn_nnz[nnz_idx[i]] != 0 )
+ bS[i] = 2;
+ else
+ bS[i] = 1;
+ }
+ }
+ // Do not use s->qscale as luma quantizer because it has not the same
+ // value in IPCM macroblocks.
+ qp = ( s->current_picture.qscale_table[mb_xy] + s->current_picture.qscale_table[mbn_xy] + 1 ) >> 1;
+ tprintf("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(" bS[%d]:%d", i, bS[i]); tprintf("\n"); }
+ filter_mb_edgeh( h, &img_y[j*linesize], tmp_linesize, bS, qp );
+ chroma_qp = ( h->chroma_qp +
+ get_chroma_qp( h->pps.chroma_qp_index_offset, s->current_picture.qscale_table[mbn_xy] ) + 1 ) >> 1;
+ filter_mb_edgech( h, &img_cb[j*uvlinesize], tmp_uvlinesize, bS, chroma_qp );
+ filter_mb_edgech( h, &img_cr[j*uvlinesize], tmp_uvlinesize, bS, chroma_qp );
+ }
+
+ start = 1;
+ }
+
+ /* Calculate bS */
+ for( edge = start; edge < edges; edge++ ) {
+ /* mbn_xy: neighbor macroblock */
+ const int mbn_xy = edge > 0 ? mb_xy : mbm_xy;
+ const int mbn_type = s->current_picture.mb_type[mbn_xy];
+ int16_t bS[4];
+ int qp;
+
+ if( (edge&1) && IS_8x8DCT(mb_type) )
+ continue;
+
+ if( IS_INTRA(mb_type) ||
+ IS_INTRA(mbn_type) ) {
+ int value;
+ if (edge == 0) {
+ if ( (!IS_INTERLACED(mb_type) && !IS_INTERLACED(mbm_type))
+ || ((FRAME_MBAFF || (s->picture_structure != PICT_FRAME)) && (dir == 0))
+ ) {
+ value = 4;
+ } else {
+ value = 3;
+ }
+ } else {
+ value = 3;
+ }
+ bS[0] = bS[1] = bS[2] = bS[3] = value;
+ } else {
+ int i, l;
+ int mv_done;
+
+ if( edge & mask_edge ) {
+ bS[0] = bS[1] = bS[2] = bS[3] = 0;
+ mv_done = 1;
+ }
+ else if( FRAME_MBAFF && IS_INTERLACED(mb_type ^ mbn_type)) {
+ bS[0] = bS[1] = bS[2] = bS[3] = 1;
+ mv_done = 1;
+ }
+ else if( mask_par0 && (edge || (mbn_type & (MB_TYPE_16x16 | (MB_TYPE_8x16 >> dir)))) ) {
+ int b_idx= 8 + 4 + edge * (dir ? 8:1);
+ int bn_idx= b_idx - (dir ? 8:1);
+ int v = 0;
+ for( l = 0; !v && l < 1 + (h->slice_type == B_TYPE); l++ ) {
+ v |= ref2frm[h->ref_cache[l][b_idx]+2] != ref2frm[h->ref_cache[l][bn_idx]+2] ||
+ FFABS( h->mv_cache[l][b_idx][0] - h->mv_cache[l][bn_idx][0] ) >= 4 ||
+ FFABS( h->mv_cache[l][b_idx][1] - h->mv_cache[l][bn_idx][1] ) >= mvy_limit;
+ }
+ bS[0] = bS[1] = bS[2] = bS[3] = v;
+ 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] != 0 ||
+ h->non_zero_count_cache[bn_idx] != 0 ) {
+ bS[i] = 2;
+ }
+ else if(!mv_done)
+ {
+ bS[i] = 0;
+ for( l = 0; l < 1 + (h->slice_type == B_TYPE); l++ ) {
+ if( ref2frm[h->ref_cache[l][b_idx]+2] != ref2frm[h->ref_cache[l][bn_idx]+2] ||
+ FFABS( h->mv_cache[l][b_idx][0] - h->mv_cache[l][bn_idx][0] ) >= 4 ||
+ FFABS( h->mv_cache[l][b_idx][1] - h->mv_cache[l][bn_idx][1] ) >= mvy_limit ) {
+ bS[i] = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ 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 = ( s->current_picture.qscale_table[mb_xy] + s->current_picture.qscale_table[mbn_xy] + 1 ) >> 1;
+ //tprintf("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, s->current_picture.qscale_table[mbn_xy]);
+ tprintf("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(" bS[%d]:%d", i, bS[i]); tprintf("\n"); }
+ if( dir == 0 ) {
+ filter_mb_edgev( h, &img_y[4*edge], linesize, bS, qp );
+ if( (edge&1) == 0 ) {
+ int chroma_qp = ( h->chroma_qp +
+ get_chroma_qp( h->pps.chroma_qp_index_offset, s->current_picture.qscale_table[mbn_xy] ) + 1 ) >> 1;
+ filter_mb_edgecv( h, &img_cb[2*edge], uvlinesize, bS, chroma_qp );
+ filter_mb_edgecv( h, &img_cr[2*edge], uvlinesize, bS, chroma_qp );
+ }
+ } else {
+ filter_mb_edgeh( h, &img_y[4*edge*linesize], linesize, bS, qp );
+ if( (edge&1) == 0 ) {
+ int chroma_qp = ( h->chroma_qp +
+ get_chroma_qp( h->pps.chroma_qp_index_offset, s->current_picture.qscale_table[mbn_xy] ) + 1 ) >> 1;
+ filter_mb_edgech( h, &img_cb[2*edge*uvlinesize], uvlinesize, bS, chroma_qp );
+ filter_mb_edgech( h, &img_cr[2*edge*uvlinesize], uvlinesize, bS, chroma_qp );
+ }
+ }
+ }
+ }
+}
+
+static int decode_slice(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ const int part_mask= s->partitioned_frame ? (AC_END|AC_ERROR) : 0x7F;
+
+ s->mb_skip_run= -1;
+
+ if( h->pps.cabac ) {
+ int i;
+
+ /* realign */
+ align_get_bits( &s->gb );
+
+ /* init cabac */
+ ff_init_cabac_states( &h->cabac);
+ ff_init_cabac_decoder( &h->cabac,
+ s->gb.buffer + get_bits_count(&s->gb)/8,
+ ( s->gb.size_in_bits - get_bits_count(&s->gb) + 7)/8);
+ /* calculate pre-state */
+ for( i= 0; i < 460; i++ ) {
+ int pre;
+ if( h->slice_type == I_TYPE )
+ pre = clip( ((cabac_context_init_I[i][0] * s->qscale) >>4 ) + cabac_context_init_I[i][1], 1, 126 );
+ else
+ pre = clip( ((cabac_context_init_PB[h->cabac_init_idc][i][0] * s->qscale) >>4 ) + cabac_context_init_PB[h->cabac_init_idc][i][1], 1, 126 );
+
+ if( pre <= 63 )
+ h->cabac_state[i] = 2 * ( 63 - pre ) + 0;
+ else
+ h->cabac_state[i] = 2 * ( pre - 64 ) + 1;
+ }
+
+ for(;;){
+//START_TIMER
+ int ret = decode_mb_cabac(h);
+ int eos;
+//STOP_TIMER("decode_mb_cabac")
+
+ if(ret>=0) hl_decode_mb(h);
+
+ if( ret >= 0 && FRAME_MBAFF ) { //FIXME optimal? or let mb_decode decode 16x32 ?
+ s->mb_y++;
+
+ if(ret>=0) ret = decode_mb_cabac(h);
+
+ if(ret>=0) hl_decode_mb(h);
+ s->mb_y--;
+ }
+ eos = get_cabac_terminate( &h->cabac );
+
+ if( ret < 0 || h->cabac.bytestream > h->cabac.bytestream_end + 2) {
+ av_log(h->s.avctx, AV_LOG_ERROR, "error while decoding MB %d %d, bytestream (%d)\n", s->mb_x, s->mb_y, h->cabac.bytestream_end - h->cabac.bytestream);
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_ERROR|DC_ERROR|MV_ERROR)&part_mask);
+ return -1;
+ }
+
+ if( ++s->mb_x >= s->mb_width ) {
+ s->mb_x = 0;
+ ff_draw_horiz_band(s, 16*s->mb_y, 16);
+ ++s->mb_y;
+ if(FRAME_MBAFF) {
+ ++s->mb_y;
+ }
+ }
+
+ if( eos || s->mb_y >= s->mb_height ) {
+ tprintf("slice end %d %d\n", get_bits_count(&s->gb), s->gb.size_in_bits);
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, (AC_END|DC_END|MV_END)&part_mask);
+ return 0;
+ }
+ }
+
+ } else {
+ for(;;){
+ int ret = decode_mb_cavlc(h);
+
+ if(ret>=0) hl_decode_mb(h);
+
+ if(ret>=0 && FRAME_MBAFF){ //FIXME optimal? or let mb_decode decode 16x32 ?
+ s->mb_y++;
+ ret = decode_mb_cavlc(h);
+
+ if(ret>=0) hl_decode_mb(h);
+ s->mb_y--;
+ }
+
+ if(ret<0){
+ av_log(h->s.avctx, AV_LOG_ERROR, "error while decoding MB %d %d\n", s->mb_x, s->mb_y);
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_ERROR|DC_ERROR|MV_ERROR)&part_mask);
+
+ return -1;
+ }
+
+ if(++s->mb_x >= s->mb_width){
+ s->mb_x=0;
+ ff_draw_horiz_band(s, 16*s->mb_y, 16);
+ ++s->mb_y;
+ if(FRAME_MBAFF) {
+ ++s->mb_y;
+ }
+ if(s->mb_y >= s->mb_height){
+ tprintf("slice end %d %d\n", get_bits_count(&s->gb), s->gb.size_in_bits);
+
+ if(get_bits_count(&s->gb) == s->gb.size_in_bits ) {
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, (AC_END|DC_END|MV_END)&part_mask);
+
+ return 0;
+ }else{
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END)&part_mask);
+
+ return -1;
+ }
+ }
+ }
+
+ if(get_bits_count(&s->gb) >= s->gb.size_in_bits && s->mb_skip_run<=0){
+ tprintf("slice end %d %d\n", get_bits_count(&s->gb), s->gb.size_in_bits);
+ if(get_bits_count(&s->gb) == s->gb.size_in_bits ){
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, (AC_END|DC_END|MV_END)&part_mask);
+
+ return 0;
+ }else{
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_ERROR|DC_ERROR|MV_ERROR)&part_mask);
+
+ return -1;
+ }
+ }
+ }
+ }
+
+#if 0
+ for(;s->mb_y < s->mb_height; s->mb_y++){
+ for(;s->mb_x < s->mb_width; s->mb_x++){
+ int ret= decode_mb(h);
+
+ hl_decode_mb(h);
+
+ if(ret<0){
+ av_log(s->avctx, AV_LOG_ERROR, "error while decoding MB %d %d\n", s->mb_x, s->mb_y);
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_ERROR|DC_ERROR|MV_ERROR)&part_mask);
+
+ return -1;
+ }
+
+ if(++s->mb_x >= s->mb_width){
+ s->mb_x=0;
+ if(++s->mb_y >= s->mb_height){
+ if(get_bits_count(s->gb) == s->gb.size_in_bits){
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, (AC_END|DC_END|MV_END)&part_mask);
+
+ return 0;
+ }else{
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END)&part_mask);
+
+ return -1;
+ }
+ }
+ }
+
+ if(get_bits_count(s->?gb) >= s->gb?.size_in_bits){
+ if(get_bits_count(s->gb) == s->gb.size_in_bits){
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, (AC_END|DC_END|MV_END)&part_mask);
+
+ return 0;
+ }else{
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_ERROR|DC_ERROR|MV_ERROR)&part_mask);
+
+ return -1;
+ }
+ }
+ }
+ s->mb_x=0;
+ ff_draw_horiz_band(s, 16*s->mb_y, 16);
+ }
+#endif
+ return -1; //not reached
+}
+
+static int decode_unregistered_user_data(H264Context *h, int size){
+ MpegEncContext * const s = &h->s;
+ uint8_t user_data[16+256];
+ int e, build, i;
+
+ if(size<16)
+ return -1;
+
+ for(i=0; i<sizeof(user_data)-1 && i<size; i++){
+ user_data[i]= get_bits(&s->gb, 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(s->avctx->debug & FF_DEBUG_BUGS)
+ av_log(s->avctx, AV_LOG_DEBUG, "user data:\"%s\"\n", user_data+16);
+
+ for(; i<size; i++)
+ skip_bits(&s->gb, 8);
+
+ return 0;
+}
+
+static int decode_sei(H264Context *h){
+ MpegEncContext * const s = &h->s;
+
+ while(get_bits_count(&s->gb) + 16 < s->gb.size_in_bits){
+ int size, type;
+
+ type=0;
+ do{
+ type+= show_bits(&s->gb, 8);
+ }while(get_bits(&s->gb, 8) == 255);
+
+ size=0;
+ do{
+ size+= show_bits(&s->gb, 8);
+ }while(get_bits(&s->gb, 8) == 255);
+
+ switch(type){
+ case 5:
+ if(decode_unregistered_user_data(h, size) < 0)
+ return -1;
+ break;
+ default:
+ skip_bits(&s->gb, 8*size);
+ }
+
+ //FIXME check bits here
+ align_get_bits(&s->gb);
+ }
+
+ return 0;
+}
+
+static inline void decode_hrd_parameters(H264Context *h, SPS *sps){
+ MpegEncContext * const s = &h->s;
+ int cpb_count, i;
+ cpb_count = get_ue_golomb(&s->gb) + 1;
+ get_bits(&s->gb, 4); /* bit_rate_scale */
+ get_bits(&s->gb, 4); /* cpb_size_scale */
+ for(i=0; i<cpb_count; i++){
+ get_ue_golomb(&s->gb); /* bit_rate_value_minus1 */
+ get_ue_golomb(&s->gb); /* cpb_size_value_minus1 */
+ get_bits1(&s->gb); /* cbr_flag */
+ }
+ get_bits(&s->gb, 5); /* initial_cpb_removal_delay_length_minus1 */
+ get_bits(&s->gb, 5); /* cpb_removal_delay_length_minus1 */
+ get_bits(&s->gb, 5); /* dpb_output_delay_length_minus1 */
+ get_bits(&s->gb, 5); /* time_offset_length */
+}
+
+static inline int decode_vui_parameters(H264Context *h, SPS *sps){
+ MpegEncContext * const s = &h->s;
+ int aspect_ratio_info_present_flag, aspect_ratio_idc;
+ int nal_hrd_parameters_present_flag, vcl_hrd_parameters_present_flag;
+
+ aspect_ratio_info_present_flag= get_bits1(&s->gb);
+
+ if( aspect_ratio_info_present_flag ) {
+ aspect_ratio_idc= get_bits(&s->gb, 8);
+ if( aspect_ratio_idc == EXTENDED_SAR ) {
+ sps->sar.num= get_bits(&s->gb, 16);
+ sps->sar.den= get_bits(&s->gb, 16);
+ }else if(aspect_ratio_idc < 14){
+ sps->sar= pixel_aspect[aspect_ratio_idc];
+ }else{
+ av_log(h->s.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(&s->gb)){ /* overscan_info_present_flag */
+ get_bits1(&s->gb); /* overscan_appropriate_flag */
+ }
+
+ if(get_bits1(&s->gb)){ /* video_signal_type_present_flag */
+ get_bits(&s->gb, 3); /* video_format */
+ get_bits1(&s->gb); /* video_full_range_flag */
+ if(get_bits1(&s->gb)){ /* colour_description_present_flag */
+ get_bits(&s->gb, 8); /* colour_primaries */
+ get_bits(&s->gb, 8); /* transfer_characteristics */
+ get_bits(&s->gb, 8); /* matrix_coefficients */
+ }
+ }
+
+ if(get_bits1(&s->gb)){ /* chroma_location_info_present_flag */
+ get_ue_golomb(&s->gb); /* chroma_sample_location_type_top_field */
+ get_ue_golomb(&s->gb); /* chroma_sample_location_type_bottom_field */
+ }
+
+ sps->timing_info_present_flag = get_bits1(&s->gb);
+ if(sps->timing_info_present_flag){
+ sps->num_units_in_tick = get_bits_long(&s->gb, 32);
+ sps->time_scale = get_bits_long(&s->gb, 32);
+ sps->fixed_frame_rate_flag = get_bits1(&s->gb);
+ }
+
+ nal_hrd_parameters_present_flag = get_bits1(&s->gb);
+ if(nal_hrd_parameters_present_flag)
+ decode_hrd_parameters(h, sps);
+ vcl_hrd_parameters_present_flag = get_bits1(&s->gb);
+ if(vcl_hrd_parameters_present_flag)
+ decode_hrd_parameters(h, sps);
+ if(nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag)
+ get_bits1(&s->gb); /* low_delay_hrd_flag */
+ get_bits1(&s->gb); /* pic_struct_present_flag */
+
+ sps->bitstream_restriction_flag = get_bits1(&s->gb);
+ if(sps->bitstream_restriction_flag){
+ get_bits1(&s->gb); /* motion_vectors_over_pic_boundaries_flag */
+ get_ue_golomb(&s->gb); /* max_bytes_per_pic_denom */
+ get_ue_golomb(&s->gb); /* max_bits_per_mb_denom */
+ get_ue_golomb(&s->gb); /* log2_max_mv_length_horizontal */
+ get_ue_golomb(&s->gb); /* log2_max_mv_length_vertical */
+ sps->num_reorder_frames = get_ue_golomb(&s->gb);
+ get_ue_golomb(&s->gb); /* max_dec_frame_buffering */
+ }
+
+ return 0;
+}
+
+static void decode_scaling_list(H264Context *h, uint8_t *factors, int size,
+ const uint8_t *jvt_list, const uint8_t *fallback_list){
+ MpegEncContext * const s = &h->s;
+ int i, last = 8, next = 8;
+ const uint8_t *scan = size == 16 ? zigzag_scan : zigzag_scan8x8;
+ if(!get_bits1(&s->gb)) /* matrix not written, we use the predicted one */
+ memcpy(factors, fallback_list, size*sizeof(uint8_t));
+ else
+ for(i=0;i<size;i++){
+ if(next)
+ next = (last + get_se_golomb(&s->gb)) & 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]){
+ MpegEncContext * const s = &h->s;
+ 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[1] : default_scaling8[1]
+ };
+ if(get_bits1(&s->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[1],64,default_scaling8[1],fallback[3]); // Inter, Y
+ }
+ } else if(fallback_sps) {
+ memcpy(scaling_matrix4, sps->scaling_matrix4, 6*16*sizeof(uint8_t));
+ memcpy(scaling_matrix8, sps->scaling_matrix8, 2*64*sizeof(uint8_t));
+ }
+}
+
+static inline int decode_seq_parameter_set(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ int profile_idc, level_idc;
+ int sps_id, i;
+ SPS *sps;
+
+ profile_idc= get_bits(&s->gb, 8);
+ get_bits1(&s->gb); //constraint_set0_flag
+ get_bits1(&s->gb); //constraint_set1_flag
+ get_bits1(&s->gb); //constraint_set2_flag
+ get_bits1(&s->gb); //constraint_set3_flag
+ get_bits(&s->gb, 4); // reserved
+ level_idc= get_bits(&s->gb, 8);
+ sps_id= get_ue_golomb(&s->gb);
+
+ sps= &h->sps_buffer[ sps_id ];
+ sps->profile_idc= profile_idc;
+ sps->level_idc= level_idc;
+
+ if(sps->profile_idc >= 100){ //high profile
+ if(get_ue_golomb(&s->gb) == 3) //chroma_format_idc
+ get_bits1(&s->gb); //residual_color_transform_flag
+ get_ue_golomb(&s->gb); //bit_depth_luma_minus8
+ get_ue_golomb(&s->gb); //bit_depth_chroma_minus8
+ sps->transform_bypass = get_bits1(&s->gb);
+ decode_scaling_matrices(h, sps, NULL, 1, sps->scaling_matrix4, sps->scaling_matrix8);
+ }else
+ sps->scaling_matrix_present = 0;
+
+ sps->log2_max_frame_num= get_ue_golomb(&s->gb) + 4;
+ sps->poc_type= get_ue_golomb(&s->gb);
+
+ if(sps->poc_type == 0){ //FIXME #define
+ sps->log2_max_poc_lsb= get_ue_golomb(&s->gb) + 4;
+ } else if(sps->poc_type == 1){//FIXME #define
+ sps->delta_pic_order_always_zero_flag= get_bits1(&s->gb);
+ sps->offset_for_non_ref_pic= get_se_golomb(&s->gb);
+ sps->offset_for_top_to_bottom_field= get_se_golomb(&s->gb);
+ sps->poc_cycle_length= get_ue_golomb(&s->gb);
+
+ for(i=0; i<sps->poc_cycle_length; i++)
+ sps->offset_for_ref_frame[i]= get_se_golomb(&s->gb);
+ }
+ if(sps->poc_type > 2){
+ av_log(h->s.avctx, AV_LOG_ERROR, "illegal POC type %d\n", sps->poc_type);
+ return -1;
+ }
+
+ sps->ref_frame_count= get_ue_golomb(&s->gb);
+ if(sps->ref_frame_count > MAX_PICTURE_COUNT-2){
+ av_log(h->s.avctx, AV_LOG_ERROR, "too many reference frames\n");
+ }
+ sps->gaps_in_frame_num_allowed_flag= get_bits1(&s->gb);
+ sps->mb_width= get_ue_golomb(&s->gb) + 1;
+ sps->mb_height= get_ue_golomb(&s->gb) + 1;
+ if((unsigned)sps->mb_width >= INT_MAX/16 || (unsigned)sps->mb_height >= INT_MAX/16 ||
+ avcodec_check_dimensions(NULL, 16*sps->mb_width, 16*sps->mb_height))
+ return -1;
+
+ sps->frame_mbs_only_flag= get_bits1(&s->gb);
+ if(!sps->frame_mbs_only_flag)
+ sps->mb_aff= get_bits1(&s->gb);
+ else
+ sps->mb_aff= 0;
+
+ sps->direct_8x8_inference_flag= get_bits1(&s->gb);
+
+#ifndef ALLOW_INTERLACE
+ if(sps->mb_aff)
+ av_log(h->s.avctx, AV_LOG_ERROR, "MBAFF support not included; enable it at compile-time.\n");
+#endif
+ if(!sps->direct_8x8_inference_flag && sps->mb_aff)
+ av_log(h->s.avctx, AV_LOG_ERROR, "MBAFF + !direct_8x8_inference is not implemented\n");
+
+ sps->crop= get_bits1(&s->gb);
+ if(sps->crop){
+ sps->crop_left = get_ue_golomb(&s->gb);
+ sps->crop_right = get_ue_golomb(&s->gb);
+ sps->crop_top = get_ue_golomb(&s->gb);
+ sps->crop_bottom= get_ue_golomb(&s->gb);
+ if(sps->crop_left || sps->crop_top){
+ av_log(h->s.avctx, AV_LOG_ERROR, "insane cropping not completely supported, this could look slightly wrong ...\n");
+ }
+ }else{
+ sps->crop_left =
+ sps->crop_right =
+ sps->crop_top =
+ sps->crop_bottom= 0;
+ }
+
+ sps->vui_parameters_present_flag= get_bits1(&s->gb);
+ if( sps->vui_parameters_present_flag )
+ decode_vui_parameters(h, sps);
+
+ if(s->avctx->debug&FF_DEBUG_PICT_INFO){
+ av_log(h->s.avctx, AV_LOG_DEBUG, "sps:%d profile:%d/%d poc:%d ref:%d %dx%d %s %s crop:%d/%d/%d/%d %s\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" : ""
+ );
+ }
+ return 0;
+}
+
+static inline int decode_picture_parameter_set(H264Context *h, int bit_length){
+ MpegEncContext * const s = &h->s;
+ int pps_id= get_ue_golomb(&s->gb);
+ PPS *pps= &h->pps_buffer[pps_id];
+
+ pps->sps_id= get_ue_golomb(&s->gb);
+ pps->cabac= get_bits1(&s->gb);
+ pps->pic_order_present= get_bits1(&s->gb);
+ pps->slice_group_count= get_ue_golomb(&s->gb) + 1;
+ if(pps->slice_group_count > 1 ){
+ pps->mb_slice_group_map_type= get_ue_golomb(&s->gb);
+ av_log(h->s.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(&s->gb) + 1;
+ pps->ref_count[1]= get_ue_golomb(&s->gb) + 1;
+ if(pps->ref_count[0] > 32 || pps->ref_count[1] > 32){
+ av_log(h->s.avctx, AV_LOG_ERROR, "reference overflow (pps)\n");
+ return -1;
+ }
+
+ pps->weighted_pred= get_bits1(&s->gb);
+ pps->weighted_bipred_idc= get_bits(&s->gb, 2);
+ pps->init_qp= get_se_golomb(&s->gb) + 26;
+ pps->init_qs= get_se_golomb(&s->gb) + 26;
+ pps->chroma_qp_index_offset= get_se_golomb(&s->gb);
+ pps->deblocking_filter_parameters_present= get_bits1(&s->gb);
+ pps->constrained_intra_pred= get_bits1(&s->gb);
+ pps->redundant_pic_cnt_present = get_bits1(&s->gb);
+
+ pps->transform_8x8_mode= 0;
+ h->dequant_coeff_pps= -1; //contents of sps/pps can change even if id doesn't, so reinit
+ memset(pps->scaling_matrix4, 16, 6*16*sizeof(uint8_t));
+ memset(pps->scaling_matrix8, 16, 2*64*sizeof(uint8_t));
+
+ if(get_bits_count(&s->gb) < bit_length){
+ pps->transform_8x8_mode= get_bits1(&s->gb);
+ decode_scaling_matrices(h, &h->sps_buffer[pps->sps_id], pps, 0, pps->scaling_matrix4, pps->scaling_matrix8);
+ get_se_golomb(&s->gb); //second_chroma_qp_index_offset
+ }
+
+ if(s->avctx->debug&FF_DEBUG_PICT_INFO){
+ av_log(h->s.avctx, AV_LOG_DEBUG, "pps:%d sps:%d %s slice_groups:%d ref:%d/%d %s qp:%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,
+ pps->deblocking_filter_parameters_present ? "LPAR" : "",
+ pps->constrained_intra_pred ? "CONSTR" : "",
+ pps->redundant_pic_cnt_present ? "REDU" : "",
+ pps->transform_8x8_mode ? "8x8DCT" : ""
+ );
+ }
+
+ return 0;
+}
+
+/**
+ * finds 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(H264Context *h, const uint8_t *buf, int buf_size){
+ int i;
+ uint32_t state;
+ ParseContext *pc = &(h->s.parse_context);
+//printf("first %02X%02X%02X%02X\n", buf[0], buf[1],buf[2],buf[3]);
+// mb_addr= pc->mb_addr - 1;
+ state= pc->state;
+ for(i=0; i<=buf_size; i++){
+ if((state&0xFFFFFF1F) == 0x101 || (state&0xFFFFFF1F) == 0x102 || (state&0xFFFFFF1F) == 0x105){
+ tprintf("find_frame_end new startcode = %08x, frame_start_found = %d, pos = %d\n", state, pc->frame_start_found, i);
+ if(pc->frame_start_found){
+ // If there isn't one more byte in the buffer
+ // the test on first_mb_in_slice cannot be done yet
+ // do it at next call.
+ if (i >= buf_size) break;
+ if (buf[i] & 0x80) {
+ // first_mb_in_slice is 0, probably the first nal of a new
+ // slice
+ tprintf("find_frame_end frame_end_found, state = %08x, pos = %d\n", state, i);
+ pc->state=-1;
+ pc->frame_start_found= 0;
+ return i-4;
+ }
+ }
+ pc->frame_start_found = 1;
+ }
+ if((state&0xFFFFFF1F) == 0x107 || (state&0xFFFFFF1F) == 0x108 || (state&0xFFFFFF1F) == 0x109){
+ if(pc->frame_start_found){
+ pc->state=-1;
+ pc->frame_start_found= 0;
+ return i-4;
+ }
+ }
+ if (i<buf_size)
+ state= (state<<8) | buf[i];
+ }
+
+ pc->state= state;
+ return END_NOT_FOUND;
+}
+
+#ifdef CONFIG_H264_PARSER
+static int h264_parse(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size)
+{
+ H264Context *h = s->priv_data;
+ ParseContext *pc = &h->s.parse_context;
+ int next;
+
+ next= find_frame_end(h, buf, buf_size);
+
+ if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) {
+ *poutbuf = NULL;
+ *poutbuf_size = 0;
+ return buf_size;
+ }
+
+ *poutbuf = (uint8_t *)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 (i<buf_size)
+ state= (state<<8) | buf[i];
+ }
+ return 0;
+}
+#endif /* CONFIG_H264_PARSER */
+
+static int decode_nal_units(H264Context *h, uint8_t *buf, int buf_size){
+ MpegEncContext * const s = &h->s;
+ AVCodecContext * const avctx= s->avctx;
+ int buf_index=0;
+#if 0
+ int i;
+ for(i=0; i<50; i++){
+ av_log(NULL, AV_LOG_ERROR,"%02X ", buf[i]);
+ }
+#endif
+ h->slice_num = 0;
+ s->current_picture_ptr= NULL;
+ for(;;){
+ int consumed;
+ int dst_length;
+ int bit_length;
+ uint8_t *ptr;
+ int i, nalsize = 0;
+
+ if(h->is_avc) {
+ if(buf_index >= buf_size) break;
+ nalsize = 0;
+ for(i = 0; i < h->nal_length_size; i++)
+ nalsize = (nalsize << 8) | buf[buf_index++];
+ if(nalsize <= 1){
+ if(nalsize == 1){
+ buf_index++;
+ continue;
+ }else{
+ av_log(h->s.avctx, AV_LOG_ERROR, "AVC: nal size %d\n", nalsize);
+ break;
+ }
+ }
+ } else {
+ // start code prefix search
+ for(; buf_index + 3 < buf_size; buf_index++){
+ // this should allways 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) break;
+
+ buf_index+=3;
+ }
+
+ ptr= decode_nal(h, buf + buf_index, &dst_length, &consumed, h->is_avc ? nalsize : buf_size - buf_index);
+ while(ptr[dst_length - 1] == 0 && dst_length > 1)
+ dst_length--;
+ bit_length= 8*dst_length - decode_rbsp_trailing(ptr + dst_length - 1);
+
+ if(s->avctx->debug&FF_DEBUG_STARTCODE){
+ av_log(h->s.avctx, AV_LOG_DEBUG, "NAL %d at %d/%d length %d\n", h->nal_unit_type, buf_index, buf_size, dst_length);
+ }
+
+ if (h->is_avc && (nalsize != consumed))
+ av_log(h->s.avctx, AV_LOG_ERROR, "AVC: Consumed only %d bytes instead of %d\n", consumed, nalsize);
+
+ buf_index += consumed;
+
+ if( (s->hurry_up == 1 && h->nal_ref_idc == 0) //FIXME dont discard SEI id
+ ||(avctx->skip_frame >= AVDISCARD_NONREF && h->nal_ref_idc == 0))
+ continue;
+
+ switch(h->nal_unit_type){
+ case NAL_IDR_SLICE:
+ idr(h); //FIXME ensure we don't loose some frames if there is reordering
+ case NAL_SLICE:
+ init_get_bits(&s->gb, ptr, bit_length);
+ h->intra_gb_ptr=
+ h->inter_gb_ptr= &s->gb;
+ s->data_partitioning = 0;
+
+ if(decode_slice_header(h) < 0){
+ av_log(h->s.avctx, AV_LOG_ERROR, "decode_slice_header error\n");
+ break;
+ }
+ s->current_picture_ptr->key_frame= (h->nal_unit_type == NAL_IDR_SLICE);
+ if(h->redundant_pic_count==0 && s->hurry_up < 5
+ && (avctx->skip_frame < AVDISCARD_NONREF || h->nal_ref_idc)
+ && (avctx->skip_frame < AVDISCARD_BIDIR || h->slice_type!=B_TYPE)
+ && (avctx->skip_frame < AVDISCARD_NONKEY || h->slice_type==I_TYPE)
+ && avctx->skip_frame < AVDISCARD_ALL)
+ decode_slice(h);
+ break;
+ case NAL_DPA:
+ init_get_bits(&s->gb, ptr, bit_length);
+ h->intra_gb_ptr=
+ h->inter_gb_ptr= NULL;
+ s->data_partitioning = 1;
+
+ if(decode_slice_header(h) < 0){
+ av_log(h->s.avctx, AV_LOG_ERROR, "decode_slice_header error\n");
+ }
+ break;
+ case NAL_DPB:
+ init_get_bits(&h->intra_gb, ptr, bit_length);
+ h->intra_gb_ptr= &h->intra_gb;
+ break;
+ case NAL_DPC:
+ init_get_bits(&h->inter_gb, ptr, bit_length);
+ h->inter_gb_ptr= &h->inter_gb;
+
+ if(h->redundant_pic_count==0 && h->intra_gb_ptr && s->data_partitioning
+ && s->hurry_up < 5
+ && (avctx->skip_frame < AVDISCARD_NONREF || h->nal_ref_idc)
+ && (avctx->skip_frame < AVDISCARD_BIDIR || h->slice_type!=B_TYPE)
+ && (avctx->skip_frame < AVDISCARD_NONKEY || h->slice_type==I_TYPE)
+ && avctx->skip_frame < AVDISCARD_ALL)
+ decode_slice(h);
+ break;
+ case NAL_SEI:
+ init_get_bits(&s->gb, ptr, bit_length);
+ decode_sei(h);
+ break;
+ case NAL_SPS:
+ init_get_bits(&s->gb, ptr, bit_length);
+ decode_seq_parameter_set(h);
+
+ if(s->flags& CODEC_FLAG_LOW_DELAY)
+ s->low_delay=1;
+
+ if(avctx->has_b_frames < 2)
+ avctx->has_b_frames= !s->low_delay;
+ break;
+ case NAL_PPS:
+ init_get_bits(&s->gb, ptr, bit_length);
+
+ 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;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "Unknown NAL code: %d\n", h->nal_unit_type);
+ }
+ }
+
+ if(!s->current_picture_ptr) return buf_index; //no frame
+
+ s->current_picture_ptr->qscale_type= FF_QSCALE_TYPE_H264;
+ s->current_picture_ptr->pict_type= s->pict_type;
+
+ h->prev_frame_num_offset= h->frame_num_offset;
+ h->prev_frame_num= h->frame_num;
+ if(s->current_picture_ptr->reference){
+ h->prev_poc_msb= h->poc_msb;
+ h->prev_poc_lsb= h->poc_lsb;
+ }
+ if(s->current_picture_ptr->reference)
+ execute_ref_pic_marking(h, h->mmco, h->mmco_index);
+
+ ff_er_frame_end(s);
+
+ MPV_frame_end(s);
+
+ return buf_index;
+}
+
+/**
+ * returns the number of bytes consumed for building the current frame
+ */
+static int get_consumed_bytes(MpegEncContext *s, int pos, int buf_size){
+ if(s->flags&CODEC_FLAG_TRUNCATED){
+ pos -= s->parse_context.last_index;
+ if(pos<0) pos=0; // FIXME remove (unneeded?)
+
+ return pos;
+ }else{
+ if(pos==0) pos=1; //avoid infinite loops (i doubt thats needed but ...)
+ if(pos+10>buf_size) pos=buf_size; // oops ;)
+
+ return pos;
+ }
+}
+
+static int decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ H264Context *h = avctx->priv_data;
+ MpegEncContext *s = &h->s;
+ AVFrame *pict = data;
+ int buf_index;
+
+ s->flags= avctx->flags;
+ s->flags2= avctx->flags2;
+
+ /* no supplementary picture */
+ if (buf_size == 0) {
+ return 0;
+ }
+
+ if(s->flags&CODEC_FLAG_TRUNCATED){
+ int next= find_frame_end(h, buf, buf_size);
+
+ if( ff_combine_frame(&s->parse_context, next, &buf, &buf_size) < 0 )
+ return buf_size;
+//printf("next:%d buf_size:%d last_index:%d\n", next, buf_size, s->parse_context.last_index);
+ }
+
+ if(h->is_avc && !h->got_avcC) {
+ int i, cnt, nalsize;
+ unsigned char *p = avctx->extradata;
+ if(avctx->extradata_size < 7) {
+ av_log(avctx, AV_LOG_ERROR, "avcC too short\n");
+ return -1;
+ }
+ if(*p != 1) {
+ av_log(avctx, AV_LOG_ERROR, "Unknown avcC version %d\n", *p);
+ 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 = BE_16(p) + 2;
+ if(decode_nal_units(h, p, nalsize) < 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 = BE_16(p) + 2;
+ if(decode_nal_units(h, p, nalsize) != nalsize) {
+ 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 use to parse all other nals
+ h->nal_length_size = ((*(((char*)(avctx->extradata))+4))&0x03)+1;
+ // Do not reparse avcC
+ h->got_avcC = 1;
+ }
+
+ if(!h->is_avc && s->avctx->extradata_size && s->picture_number==0){
+ if(decode_nal_units(h, s->avctx->extradata, s->avctx->extradata_size) < 0)
+ return -1;
+ }
+
+ buf_index=decode_nal_units(h, buf, buf_size);
+ if(buf_index < 0)
+ return -1;
+
+ //FIXME do something with unavailable reference frames
+
+// if(ret==FRAME_SKIPPED) return get_consumed_bytes(s, buf_index, buf_size);
+ if(!s->current_picture_ptr){
+ av_log(h->s.avctx, AV_LOG_DEBUG, "error, NO frame\n");
+ return -1;
+ }
+
+ {
+ Picture *out = s->current_picture_ptr;
+#if 0 //decode order
+ *data_size = sizeof(AVFrame);
+#else
+ /* Sort B-frames into display order */
+ Picture *cur = s->current_picture_ptr;
+ Picture *prev = h->delayed_output_pic;
+ int i, pics, cross_idr, out_of_order, out_idx;
+
+ if(h->sps.bitstream_restriction_flag
+ && s->avctx->has_b_frames < h->sps.num_reorder_frames){
+ s->avctx->has_b_frames = h->sps.num_reorder_frames;
+ s->low_delay = 0;
+ }
+
+ pics = 0;
+ while(h->delayed_pic[pics]) pics++;
+ h->delayed_pic[pics++] = cur;
+ if(cur->reference == 0)
+ cur->reference = 1;
+
+ cross_idr = 0;
+ for(i=0; h->delayed_pic[i]; i++)
+ if(h->delayed_pic[i]->key_frame || h->delayed_pic[i]->poc==0)
+ cross_idr = 1;
+
+ out = h->delayed_pic[0];
+ out_idx = 0;
+ for(i=1; h->delayed_pic[i] && !h->delayed_pic[i]->key_frame; i++)
+ if(h->delayed_pic[i]->poc < out->poc){
+ out = h->delayed_pic[i];
+ out_idx = i;
+ }
+
+ out_of_order = !cross_idr && prev && out->poc < prev->poc;
+ if(h->sps.bitstream_restriction_flag && s->avctx->has_b_frames >= h->sps.num_reorder_frames)
+ { }
+ else if(prev && pics <= s->avctx->has_b_frames)
+ out = prev;
+ else if((out_of_order && pics-1 == s->avctx->has_b_frames && pics < 15)
+ || (s->low_delay &&
+ ((!cross_idr && prev && out->poc > prev->poc + 2)
+ || cur->pict_type == B_TYPE)))
+ {
+ s->low_delay = 0;
+ s->avctx->has_b_frames++;
+ out = prev;
+ }
+ else if(out_of_order)
+ out = prev;
+
+ if(out_of_order || pics > s->avctx->has_b_frames){
+ for(i=out_idx; h->delayed_pic[i]; i++)
+ h->delayed_pic[i] = h->delayed_pic[i+1];
+ }
+
+ if(prev == out)
+ *data_size = 0;
+ else
+ *data_size = sizeof(AVFrame);
+ if(prev && prev != out && prev->reference == 1)
+ prev->reference = 0;
+ h->delayed_output_pic = out;
+#endif
+
+ if(out)
+ *pict= *(AVFrame*)out;
+ else
+ av_log(avctx, AV_LOG_DEBUG, "no picture\n");
+ }
+
+ assert(pict->data[0] || !*data_size);
+ ff_print_debug_info(s, pict);
+//printf("out %d\n", (int)pict->data[0]);
+#if 0 //?
+
+ /* Return the Picture timestamp as the frame number */
+ /* we substract 1 because it is added on utils.c */
+ avctx->frame_number = s->picture_number - 1;
+#endif
+ return get_consumed_bytes(s, buf_index, buf_size);
+}
+#if 0
+static inline void fill_mb_avail(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ const int mb_xy= s->mb_x + s->mb_y*s->mb_stride;
+
+ if(s->mb_y){
+ h->mb_avail[0]= s->mb_x && h->slice_table[mb_xy - s->mb_stride - 1] == h->slice_num;
+ h->mb_avail[1]= h->slice_table[mb_xy - s->mb_stride ] == h->slice_num;
+ h->mb_avail[2]= s->mb_x+1 < s->mb_width && h->slice_table[mb_xy - s->mb_stride + 1] == h->slice_num;
+ }else{
+ h->mb_avail[0]=
+ h->mb_avail[1]=
+ h->mb_avail[2]= 0;
+ }
+ h->mb_avail[3]= s->mb_x && h->slice_table[mb_xy - 1] == h->slice_num;
+ h->mb_avail[4]= 1; //FIXME move out
+ h->mb_avail[5]= 0; //FIXME move out
+}
+#endif
+
+#if 0 //selftest
+#define COUNT 8000
+#define SIZE (COUNT*40)
+int main(){
+ int i;
+ uint8_t temp[SIZE];
+ PutBitContext pb;
+ GetBitContext gb;
+// int int_temp[10000];
+ DSPContext dsp;
+ AVCodecContext avctx;
+
+ dsputil_init(&dsp, &avctx);
+
+ init_put_bits(&pb, temp, SIZE);
+ printf("testing unsigned exp golomb\n");
+ for(i=0; i<COUNT; i++){
+ START_TIMER
+ set_ue_golomb(&pb, i);
+ STOP_TIMER("set_ue_golomb");
+ }
+ flush_put_bits(&pb);
+
+ init_get_bits(&gb, temp, 8*SIZE);
+ for(i=0; i<COUNT; i++){
+ int j, s;
+
+ s= show_bits(&gb, 24);
+
+ START_TIMER
+ j= get_ue_golomb(&gb);
+ if(j != i){
+ printf("missmatch! at %d (%d should be %d) bits:%6X\n", i, j, i, s);
+// return -1;
+ }
+ STOP_TIMER("get_ue_golomb");
+ }
+
+
+ init_put_bits(&pb, temp, SIZE);
+ printf("testing signed exp golomb\n");
+ for(i=0; i<COUNT; i++){
+ START_TIMER
+ set_se_golomb(&pb, i - COUNT/2);
+ STOP_TIMER("set_se_golomb");
+ }
+ flush_put_bits(&pb);
+
+ init_get_bits(&gb, temp, 8*SIZE);
+ for(i=0; i<COUNT; i++){
+ int j, s;
+
+ s= show_bits(&gb, 24);
+
+ START_TIMER
+ j= get_se_golomb(&gb);
+ if(j != i - COUNT/2){
+ printf("missmatch! at %d (%d should be %d) bits:%6X\n", i, j, i, s);
+// return -1;
+ }
+ STOP_TIMER("get_se_golomb");
+ }
+
+ printf("testing 4x4 (I)DCT\n");
+
+ DCTELEM block[16];
+ uint8_t src[16], ref[16];
+ uint64_t error= 0, max_error=0;
+
+ for(i=0; i<COUNT; i++){
+ int j;
+// printf("%d %d %d\n", r1, r2, (r2-r1)*16);
+ for(j=0; j<16; j++){
+ ref[j]= random()%255;
+ src[j]= random()%255;
+ }
+
+ h264_diff_dct_c(block, src, ref, 4);
+
+ //normalize
+ for(j=0; j<16; j++){
+// printf("%d ", block[j]);
+ block[j]= block[j]*4;
+ if(j&1) block[j]= (block[j]*4 + 2)/5;
+ if(j&4) block[j]= (block[j]*4 + 2)/5;
+ }
+// printf("\n");
+
+ s->dsp.h264_idct_add(ref, block, 4);
+/* for(j=0; j<16; j++){
+ printf("%d ", ref[j]);
+ }
+ printf("\n");*/
+
+ for(j=0; j<16; j++){
+ int diff= FFABS(src[j] - ref[j]);
+
+ error+= diff*diff;
+ max_error= FFMAX(max_error, diff);
+ }
+ }
+ printf("error=%f max_error=%d\n", ((float)error)/COUNT/16, (int)max_error );
+#if 0
+ printf("testing quantizer\n");
+ for(qp=0; qp<52; qp++){
+ for(i=0; i<16; i++)
+ src1_block[i]= src2_block[i]= random()%255;
+
+ }
+#endif
+ printf("Testing NAL layer\n");
+
+ uint8_t bitstream[COUNT];
+ uint8_t nal[COUNT*2];
+ H264Context h;
+ memset(&h, 0, sizeof(H264Context));
+
+ for(i=0; i<COUNT; i++){
+ int zeros= i;
+ int nal_length;
+ int consumed;
+ int out_length;
+ uint8_t *out;
+ int j;
+
+ for(j=0; j<COUNT; j++){
+ bitstream[j]= (random() % 255) + 1;
+ }
+
+ for(j=0; j<zeros; j++){
+ int pos= random() % COUNT;
+ while(bitstream[pos] == 0){
+ pos++;
+ pos %= COUNT;
+ }
+ bitstream[pos]=0;
+ }
+
+ START_TIMER
+
+ nal_length= encode_nal(&h, nal, bitstream, COUNT, COUNT*2);
+ if(nal_length<0){
+ printf("encoding failed\n");
+ return -1;
+ }
+
+ out= decode_nal(&h, nal, &out_length, &consumed, nal_length);
+
+ STOP_TIMER("NAL")
+
+ if(out_length != COUNT){
+ printf("incorrect length %d %d\n", out_length, COUNT);
+ return -1;
+ }
+
+ if(consumed != nal_length){
+ printf("incorrect consumed length %d %d\n", nal_length, consumed);
+ return -1;
+ }
+
+ if(memcmp(bitstream, out, COUNT)){
+ printf("missmatch\n");
+ return -1;
+ }
+ }
+
+ printf("Testing RBSP\n");
+
+
+ return 0;
+}
+#endif
+
+
+static int decode_end(AVCodecContext *avctx)
+{
+ H264Context *h = avctx->priv_data;
+ MpegEncContext *s = &h->s;
+
+ av_freep(&h->rbsp_buffer);
+ free_tables(h); //FIXME cleanup init stuff perhaps
+ MPV_common_end(s);
+
+// memset(h, 0, sizeof(H264Context));
+
+ return 0;
+}
+
+
+AVCodec h264_decoder = {
+ "h264",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_H264,
+ sizeof(H264Context),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame,
+ /*CODEC_CAP_DRAW_HORIZ_BAND |*/ CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY,
+ .flush= flush_dpb,
+};
+
+#ifdef CONFIG_H264_PARSER
+AVCodecParser h264_parser = {
+ { CODEC_ID_H264 },
+ sizeof(H264Context),
+ NULL,
+ h264_parse,
+ ff_parse_close,
+ h264_split,
+};
+#endif
+
+#include "svq3.c"
diff --git a/contrib/ffmpeg/libavcodec/h264data.h b/contrib/ffmpeg/libavcodec/h264data.h
new file mode 100644
index 000000000..2dea3580f
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/h264data.h
@@ -0,0 +1,1314 @@
+/*
+ * H26L/H264/AVC/JVT/14496-10/... encoder/decoder
+ * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/**
+ * @file h264data.h
+ * @brief
+ * H264 / AVC / MPEG4 part10 codec data table
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#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
+
+#define LEFT_DC_PRED 9
+#define TOP_DC_PRED 10
+#define DC_128_PRED 11
+
+
+#define DC_PRED8x8 0
+#define HOR_PRED8x8 1
+#define VERT_PRED8x8 2
+#define PLANE_PRED8x8 3
+
+#define LEFT_DC_PRED8x8 4
+#define TOP_DC_PRED8x8 5
+#define DC_128_PRED8x8 6
+
+#define EXTENDED_SAR 255
+
+static const AVRational pixel_aspect[14]={
+ {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},
+};
+
+static const uint8_t golomb_to_pict_type[5]=
+{P_TYPE, B_TYPE, I_TYPE, SP_TYPE, SI_TYPE};
+
+static const uint8_t pict_type_to_golomb[7]=
+{-1, 2, 0, 1, -1, 4, 3};
+
+static const uint8_t chroma_qp[52]={
+ 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,29,30,31,32,32,33,34,34,35,35,36,36,37,37,
+ 37,38,38,38,39,39,39,39
+
+};
+
+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 intra4x4_cbp_to_golomb[48]={
+ 3, 29, 30, 17, 31, 18, 37, 8, 32, 38, 19, 9, 20, 10, 11, 2,
+ 16, 33, 34, 21, 35, 22, 39, 4, 36, 40, 23, 5, 24, 6, 7, 1,
+ 41, 42, 43, 25, 44, 26, 46, 12, 45, 47, 27, 13, 28, 14, 15, 0
+};
+
+static const uint8_t inter_cbp_to_golomb[48]={
+ 0, 2, 3, 7, 4, 8, 17, 13, 5, 18, 9, 14, 10, 15, 16, 11,
+ 1, 32, 33, 36, 34, 37, 44, 40, 35, 45, 38, 41, 39, 42, 43, 19,
+ 6, 24, 25, 20, 26, 21, 46, 28, 27, 47, 22, 29, 23, 30, 31, 12
+};
+
+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 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 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},
+};
+
+/*
+o-o o-o
+ / / /
+o-o o-o
+ ,---'
+o-o o-o
+ / / /
+o-o o-o
+*/
+
+static const uint8_t scan8[16 + 2*4]={
+ 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,
+ 1+1*8, 2+1*8,
+ 1+2*8, 2+2*8,
+ 1+4*8, 2+4*8,
+ 1+5*8, 2+5*8,
+};
+
+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 field_scan[16]={
+ 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, //FIXME
+};
+
+static const uint8_t zigzag_scan8x8[64]={
+ 0+0*8, 1+0*8, 0+1*8, 0+2*8,
+ 1+1*8, 2+0*8, 3+0*8, 2+1*8,
+ 1+2*8, 0+3*8, 0+4*8, 1+3*8,
+ 2+2*8, 3+1*8, 4+0*8, 5+0*8,
+ 4+1*8, 3+2*8, 2+3*8, 1+4*8,
+ 0+5*8, 0+6*8, 1+5*8, 2+4*8,
+ 3+3*8, 4+2*8, 5+1*8, 6+0*8,
+ 7+0*8, 6+1*8, 5+2*8, 4+3*8,
+ 3+4*8, 2+5*8, 1+6*8, 0+7*8,
+ 1+7*8, 2+6*8, 3+5*8, 4+4*8,
+ 5+3*8, 6+2*8, 7+1*8, 7+2*8,
+ 6+3*8, 5+4*8, 4+5*8, 3+6*8,
+ 2+7*8, 3+7*8, 4+6*8, 5+5*8,
+ 6+4*8, 7+3*8, 7+4*8, 6+5*8,
+ 5+6*8, 4+7*8, 5+7*8, 6+6*8,
+ 7+5*8, 7+6*8, 6+7*8, 7+7*8,
+};
+
+// zigzag_scan8x8_cavlc[i] = zigzag_scan8x8[(i/4) + 16*(i%4)]
+static const uint8_t zigzag_scan8x8_cavlc[64]={
+ 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]={
+ 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]={
+ 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,
+};
+
+#define MB_TYPE_REF0 MB_TYPE_ACPRED //dirty but it fits in 16bit
+#define MB_TYPE_8x8DCT 0x01000000
+#define IS_REF0(a) ((a)&MB_TYPE_REF0)
+#define IS_8x8DCT(a) ((a)&MB_TYPE_8x8DCT)
+
+
+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 , 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 rem6[52]={
+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[52]={
+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,
+};
+
+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 const int 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 int dequant8_coeff_init_scan[16] = {
+ 0,3,4,3, 3,1,5,1, 4,5,2,5, 3,1,5,1
+};
+static const int 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},
+};
+
+#define QUANT_SHIFT 22
+
+static const int quant_coeff[52][16]={
+ { 419430,258111,419430,258111,258111,167772,258111,167772,419430,258111,419430,258111,258111,167772,258111,167772,},
+ { 381300,239675,381300,239675,239675,149131,239675,149131,381300,239675,381300,239675,239675,149131,239675,149131,},
+ { 322639,209715,322639,209715,209715,134218,209715,134218,322639,209715,322639,209715,209715,134218,209715,134218,},
+ { 299593,186414,299593,186414,186414,116711,186414,116711,299593,186414,299593,186414,186414,116711,186414,116711,},
+ { 262144,167772,262144,167772,167772,107374,167772,107374,262144,167772,262144,167772,167772,107374,167772,107374,},
+ { 233017,145889,233017,145889,145889, 92564,145889, 92564,233017,145889,233017,145889,145889, 92564,145889, 92564,},
+ { 209715,129056,209715,129056,129056, 83886,129056, 83886,209715,129056,209715,129056,129056, 83886,129056, 83886,},
+ { 190650,119837,190650,119837,119837, 74565,119837, 74565,190650,119837,190650,119837,119837, 74565,119837, 74565,},
+ { 161319,104858,161319,104858,104858, 67109,104858, 67109,161319,104858,161319,104858,104858, 67109,104858, 67109,},
+ { 149797, 93207,149797, 93207, 93207, 58356, 93207, 58356,149797, 93207,149797, 93207, 93207, 58356, 93207, 58356,},
+ { 131072, 83886,131072, 83886, 83886, 53687, 83886, 53687,131072, 83886,131072, 83886, 83886, 53687, 83886, 53687,},
+ { 116508, 72944,116508, 72944, 72944, 46282, 72944, 46282,116508, 72944,116508, 72944, 72944, 46282, 72944, 46282,},
+ { 104858, 64528,104858, 64528, 64528, 41943, 64528, 41943,104858, 64528,104858, 64528, 64528, 41943, 64528, 41943,},
+ { 95325, 59919, 95325, 59919, 59919, 37283, 59919, 37283, 95325, 59919, 95325, 59919, 59919, 37283, 59919, 37283,},
+ { 80660, 52429, 80660, 52429, 52429, 33554, 52429, 33554, 80660, 52429, 80660, 52429, 52429, 33554, 52429, 33554,},
+ { 74898, 46603, 74898, 46603, 46603, 29178, 46603, 29178, 74898, 46603, 74898, 46603, 46603, 29178, 46603, 29178,},
+ { 65536, 41943, 65536, 41943, 41943, 26844, 41943, 26844, 65536, 41943, 65536, 41943, 41943, 26844, 41943, 26844,},
+ { 58254, 36472, 58254, 36472, 36472, 23141, 36472, 23141, 58254, 36472, 58254, 36472, 36472, 23141, 36472, 23141,},
+ { 52429, 32264, 52429, 32264, 32264, 20972, 32264, 20972, 52429, 32264, 52429, 32264, 32264, 20972, 32264, 20972,},
+ { 47663, 29959, 47663, 29959, 29959, 18641, 29959, 18641, 47663, 29959, 47663, 29959, 29959, 18641, 29959, 18641,},
+ { 40330, 26214, 40330, 26214, 26214, 16777, 26214, 16777, 40330, 26214, 40330, 26214, 26214, 16777, 26214, 16777,},
+ { 37449, 23302, 37449, 23302, 23302, 14589, 23302, 14589, 37449, 23302, 37449, 23302, 23302, 14589, 23302, 14589,},
+ { 32768, 20972, 32768, 20972, 20972, 13422, 20972, 13422, 32768, 20972, 32768, 20972, 20972, 13422, 20972, 13422,},
+ { 29127, 18236, 29127, 18236, 18236, 11570, 18236, 11570, 29127, 18236, 29127, 18236, 18236, 11570, 18236, 11570,},
+ { 26214, 16132, 26214, 16132, 16132, 10486, 16132, 10486, 26214, 16132, 26214, 16132, 16132, 10486, 16132, 10486,},
+ { 23831, 14980, 23831, 14980, 14980, 9321, 14980, 9321, 23831, 14980, 23831, 14980, 14980, 9321, 14980, 9321,},
+ { 20165, 13107, 20165, 13107, 13107, 8389, 13107, 8389, 20165, 13107, 20165, 13107, 13107, 8389, 13107, 8389,},
+ { 18725, 11651, 18725, 11651, 11651, 7294, 11651, 7294, 18725, 11651, 18725, 11651, 11651, 7294, 11651, 7294,},
+ { 16384, 10486, 16384, 10486, 10486, 6711, 10486, 6711, 16384, 10486, 16384, 10486, 10486, 6711, 10486, 6711,},
+ { 14564, 9118, 14564, 9118, 9118, 5785, 9118, 5785, 14564, 9118, 14564, 9118, 9118, 5785, 9118, 5785,},
+ { 13107, 8066, 13107, 8066, 8066, 5243, 8066, 5243, 13107, 8066, 13107, 8066, 8066, 5243, 8066, 5243,},
+ { 11916, 7490, 11916, 7490, 7490, 4660, 7490, 4660, 11916, 7490, 11916, 7490, 7490, 4660, 7490, 4660,},
+ { 10082, 6554, 10082, 6554, 6554, 4194, 6554, 4194, 10082, 6554, 10082, 6554, 6554, 4194, 6554, 4194,},
+ { 9362, 5825, 9362, 5825, 5825, 3647, 5825, 3647, 9362, 5825, 9362, 5825, 5825, 3647, 5825, 3647,},
+ { 8192, 5243, 8192, 5243, 5243, 3355, 5243, 3355, 8192, 5243, 8192, 5243, 5243, 3355, 5243, 3355,},
+ { 7282, 4559, 7282, 4559, 4559, 2893, 4559, 2893, 7282, 4559, 7282, 4559, 4559, 2893, 4559, 2893,},
+ { 6554, 4033, 6554, 4033, 4033, 2621, 4033, 2621, 6554, 4033, 6554, 4033, 4033, 2621, 4033, 2621,},
+ { 5958, 3745, 5958, 3745, 3745, 2330, 3745, 2330, 5958, 3745, 5958, 3745, 3745, 2330, 3745, 2330,},
+ { 5041, 3277, 5041, 3277, 3277, 2097, 3277, 2097, 5041, 3277, 5041, 3277, 3277, 2097, 3277, 2097,},
+ { 4681, 2913, 4681, 2913, 2913, 1824, 2913, 1824, 4681, 2913, 4681, 2913, 2913, 1824, 2913, 1824,},
+ { 4096, 2621, 4096, 2621, 2621, 1678, 2621, 1678, 4096, 2621, 4096, 2621, 2621, 1678, 2621, 1678,},
+ { 3641, 2280, 3641, 2280, 2280, 1446, 2280, 1446, 3641, 2280, 3641, 2280, 2280, 1446, 2280, 1446,},
+ { 3277, 2016, 3277, 2016, 2016, 1311, 2016, 1311, 3277, 2016, 3277, 2016, 2016, 1311, 2016, 1311,},
+ { 2979, 1872, 2979, 1872, 1872, 1165, 1872, 1165, 2979, 1872, 2979, 1872, 1872, 1165, 1872, 1165,},
+ { 2521, 1638, 2521, 1638, 1638, 1049, 1638, 1049, 2521, 1638, 2521, 1638, 1638, 1049, 1638, 1049,},
+ { 2341, 1456, 2341, 1456, 1456, 912, 1456, 912, 2341, 1456, 2341, 1456, 1456, 912, 1456, 912,},
+ { 2048, 1311, 2048, 1311, 1311, 839, 1311, 839, 2048, 1311, 2048, 1311, 1311, 839, 1311, 839,},
+ { 1820, 1140, 1820, 1140, 1140, 723, 1140, 723, 1820, 1140, 1820, 1140, 1140, 723, 1140, 723,},
+ { 1638, 1008, 1638, 1008, 1008, 655, 1008, 655, 1638, 1008, 1638, 1008, 1008, 655, 1008, 655,},
+ { 1489, 936, 1489, 936, 936, 583, 936, 583, 1489, 936, 1489, 936, 936, 583, 936, 583,},
+ { 1260, 819, 1260, 819, 819, 524, 819, 524, 1260, 819, 1260, 819, 819, 524, 819, 524,},
+ { 1170, 728, 1170, 728, 728, 456, 728, 456, 1170, 728, 1170, 728, 728, 456, 728, 456,},
+};
+
+
+/* Deblocking filter (p153) */
+static const int 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 int 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 int tc0_table[52*3][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, 0 }, { 0, 0, 0 },
+ { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
+ { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
+ { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
+ { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
+ { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
+ { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
+ { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 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, 1 }, { 0, 0, 1 }, { 0, 0, 1 }, { 0, 1, 1 }, { 0, 1, 1 }, { 1, 1, 1 },
+ { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 2 }, { 1, 1, 2 }, { 1, 1, 2 },
+ { 1, 1, 2 }, { 1, 2, 3 }, { 1, 2, 3 }, { 2, 2, 3 }, { 2, 2, 4 }, { 2, 3, 4 },
+ { 2, 3, 4 }, { 3, 3, 5 }, { 3, 4, 6 }, { 3, 4, 6 }, { 4, 5, 7 }, { 4, 5, 8 },
+ { 4, 6, 9 }, { 5, 7,10 }, { 6, 8,11 }, { 6, 8,13 }, { 7,10,14 }, { 8,11,16 },
+ { 9,12,18 }, {10,13,20 }, {11,15,23 }, {13,17,25 },
+ {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 },
+ {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 },
+ {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 },
+ {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 },
+ {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 },
+ {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 },
+ {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 },
+ {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 },
+ {13,17,25 }, {13,17,25 }, {13,17,25 }, {13,17,25 },
+};
+
+/* Cabac pre state table */
+
+static const int cabac_context_init_I[460][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 }
+};
+
+static const int cabac_context_init_PB[3][460][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 },
+ },
+
+ /* 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 },
+ },
+
+ /* 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 },
+ }
+};
diff --git a/contrib/ffmpeg/libavcodec/h264idct.c b/contrib/ffmpeg/libavcodec/h264idct.c
new file mode 100644
index 000000000..3506418ad
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/h264idct.c
@@ -0,0 +1,168 @@
+/*
+ * H.264 IDCT
+ * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/**
+ * @file h264-idct.c
+ * H.264 IDCT.
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#include "dsputil.h"
+
+static always_inline void idct_internal(uint8_t *dst, DCTELEM *block, int stride, int block_stride, int shift, int add){
+ int i;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ block[0] += 1<<(shift-1);
+
+ for(i=0; i<4; i++){
+ const int z0= block[0 + block_stride*i] + block[2 + block_stride*i];
+ const int z1= block[0 + block_stride*i] - block[2 + block_stride*i];
+ const int z2= (block[1 + block_stride*i]>>1) - block[3 + block_stride*i];
+ const int z3= block[1 + block_stride*i] + (block[3 + block_stride*i]>>1);
+
+ block[0 + block_stride*i]= z0 + z3;
+ block[1 + block_stride*i]= z1 + z2;
+ block[2 + block_stride*i]= z1 - z2;
+ block[3 + block_stride*i]= z0 - z3;
+ }
+
+ for(i=0; i<4; i++){
+ const int z0= block[i + block_stride*0] + block[i + block_stride*2];
+ const int z1= block[i + block_stride*0] - block[i + block_stride*2];
+ const int z2= (block[i + block_stride*1]>>1) - block[i + block_stride*3];
+ const int z3= block[i + block_stride*1] + (block[i + block_stride*3]>>1);
+
+ dst[i + 0*stride]= cm[ add*dst[i + 0*stride] + ((z0 + z3) >> shift) ];
+ dst[i + 1*stride]= cm[ add*dst[i + 1*stride] + ((z1 + z2) >> shift) ];
+ dst[i + 2*stride]= cm[ add*dst[i + 2*stride] + ((z1 - z2) >> shift) ];
+ dst[i + 3*stride]= cm[ add*dst[i + 3*stride] + ((z0 - z3) >> shift) ];
+ }
+}
+
+void ff_h264_idct_add_c(uint8_t *dst, DCTELEM *block, int stride){
+ idct_internal(dst, block, stride, 4, 6, 1);
+}
+
+void ff_h264_lowres_idct_add_c(uint8_t *dst, int stride, DCTELEM *block){
+ idct_internal(dst, block, stride, 8, 3, 1);
+}
+
+void ff_h264_lowres_idct_put_c(uint8_t *dst, int stride, DCTELEM *block){
+ idct_internal(dst, block, stride, 8, 3, 0);
+}
+
+void ff_h264_idct8_add_c(uint8_t *dst, DCTELEM *block, int stride){
+ int i;
+ DCTELEM (*src)[8] = (DCTELEM(*)[8])block;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ block[0] += 32;
+
+ for( i = 0; i < 8; i++ )
+ {
+ const int a0 = src[i][0] + src[i][4];
+ const int a2 = src[i][0] - src[i][4];
+ const int a4 = (src[i][2]>>1) - src[i][6];
+ const int a6 = (src[i][6]>>1) + src[i][2];
+
+ const int b0 = a0 + a6;
+ const int b2 = a2 + a4;
+ const int b4 = a2 - a4;
+ const int b6 = a0 - a6;
+
+ const int a1 = -src[i][3] + src[i][5] - src[i][7] - (src[i][7]>>1);
+ const int a3 = src[i][1] + src[i][7] - src[i][3] - (src[i][3]>>1);
+ const int a5 = -src[i][1] + src[i][7] + src[i][5] + (src[i][5]>>1);
+ const int a7 = src[i][3] + src[i][5] + src[i][1] + (src[i][1]>>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);
+
+ src[i][0] = b0 + b7;
+ src[i][7] = b0 - b7;
+ src[i][1] = b2 + b5;
+ src[i][6] = b2 - b5;
+ src[i][2] = b4 + b3;
+ src[i][5] = b4 - b3;
+ src[i][3] = b6 + b1;
+ src[i][4] = b6 - b1;
+ }
+ for( i = 0; i < 8; i++ )
+ {
+ const int a0 = src[0][i] + src[4][i];
+ const int a2 = src[0][i] - src[4][i];
+ const int a4 = (src[2][i]>>1) - src[6][i];
+ const int a6 = (src[6][i]>>1) + src[2][i];
+
+ const int b0 = a0 + a6;
+ const int b2 = a2 + a4;
+ const int b4 = a2 - a4;
+ const int b6 = a0 - a6;
+
+ const int a1 = -src[3][i] + src[5][i] - src[7][i] - (src[7][i]>>1);
+ const int a3 = src[1][i] + src[7][i] - src[3][i] - (src[3][i]>>1);
+ const int a5 = -src[1][i] + src[7][i] + src[5][i] + (src[5][i]>>1);
+ const int a7 = src[3][i] + src[5][i] + src[1][i] + (src[1][i]>>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] = cm[ dst[i + 0*stride] + ((b0 + b7) >> 6) ];
+ dst[i + 1*stride] = cm[ dst[i + 1*stride] + ((b2 + b5) >> 6) ];
+ dst[i + 2*stride] = cm[ dst[i + 2*stride] + ((b4 + b3) >> 6) ];
+ dst[i + 3*stride] = cm[ dst[i + 3*stride] + ((b6 + b1) >> 6) ];
+ dst[i + 4*stride] = cm[ dst[i + 4*stride] + ((b6 - b1) >> 6) ];
+ dst[i + 5*stride] = cm[ dst[i + 5*stride] + ((b4 - b3) >> 6) ];
+ dst[i + 6*stride] = cm[ dst[i + 6*stride] + ((b2 - b5) >> 6) ];
+ dst[i + 7*stride] = cm[ dst[i + 7*stride] + ((b0 - b7) >> 6) ];
+ }
+}
+
+// assumes all AC coefs are 0
+void ff_h264_idct_dc_add_c(uint8_t *dst, DCTELEM *block, int stride){
+ int i, j;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+ int dc = (block[0] + 32) >> 6;
+ for( j = 0; j < 4; j++ )
+ {
+ for( i = 0; i < 4; i++ )
+ dst[i] = cm[ dst[i] + dc ];
+ dst += stride;
+ }
+}
+
+void ff_h264_idct8_dc_add_c(uint8_t *dst, DCTELEM *block, int stride){
+ int i, j;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+ int dc = (block[0] + 32) >> 6;
+ for( j = 0; j < 8; j++ )
+ {
+ for( i = 0; i < 8; i++ )
+ dst[i] = cm[ dst[i] + dc ];
+ dst += stride;
+ }
+}
diff --git a/contrib/ffmpeg/libavcodec/huffyuv.c b/contrib/ffmpeg/libavcodec/huffyuv.c
new file mode 100644
index 000000000..0aefd6d72
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/huffyuv.c
@@ -0,0 +1,1290 @@
+/*
+ * huffyuv codec for libavcodec
+ *
+ * Copyright (c) 2002-2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * see http://www.pcisys.net/~melanson/codecs/huffyuv.txt for a description of
+ * the algorithm used
+ */
+
+/**
+ * @file huffyuv.c
+ * huffyuv codec for libavcodec.
+ */
+
+#include "common.h"
+#include "bitstream.h"
+#include "avcodec.h"
+#include "dsputil.h"
+
+#define VLC_BITS 11
+
+#ifdef WORDS_BIGENDIAN
+#define B 3
+#define G 2
+#define R 1
+#else
+#define B 0
+#define G 1
+#define R 2
+#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];
+ VLC vlc[3];
+ AVFrame picture;
+ uint8_t *bitstream_buffer;
+ unsigned int bitstream_buffer_size;
+ DSPContext dsp;
+}HYuvContext;
+
+static const unsigned char classic_shift_luma[] = {
+ 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
+};
+
+static const unsigned char classic_shift_chroma[] = {
+ 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
+};
+
+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 inline int add_left_prediction(uint8_t *dst, uint8_t *src, int w, int acc){
+ int i;
+
+ for(i=0; i<w-1; i++){
+ acc+= src[i];
+ dst[i]= acc;
+ i++;
+ acc+= src[i];
+ dst[i]= acc;
+ }
+
+ for(; i<w; i++){
+ acc+= src[i];
+ dst[i]= acc;
+ }
+
+ return acc;
+}
+
+static inline void add_median_prediction(uint8_t *dst, uint8_t *src1, uint8_t *diff, int w, int *left, int *left_top){
+ 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)&0xFF) + diff[i];
+ lt= src1[i];
+ dst[i]= l;
+ }
+
+ *left= l;
+ *left_top= lt;
+}
+
+static inline void add_left_prediction_bgr32(uint8_t *dst, 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<w; i++){
+ b+= src[4*i+B];
+ g+= src[4*i+G];
+ r+= src[4*i+R];
+
+ dst[4*i+B]= b;
+ dst[4*i+G]= g;
+ dst[4*i+R]= r;
+ }
+
+ *red= r;
+ *green= g;
+ *blue= b;
+}
+
+static inline int sub_left_prediction(HYuvContext *s, uint8_t *dst, 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 void 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);
+//printf("%d %d\n", val, repeat);
+ while (repeat--)
+ dst[i++] = val;
+ }
+}
+
+static int generate_bits_table(uint32_t *dst, 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;
+}
+
+#ifdef CONFIG_ENCODERS
+static void generate_len_table(uint8_t *dst, uint64_t *stats, int size){
+ uint64_t counts[2*size];
+ int up[2*size];
+ int offset, i, next;
+
+ for(offset=1; ; offset<<=1){
+ for(i=0; i<size; i++){
+ counts[i]= stats[i] + offset - 1;
+ }
+
+ for(next=size; next<size*2; next++){
+ uint64_t min1, min2;
+ int min1_i, min2_i;
+
+ min1=min2= INT64_MAX;
+ min1_i= min2_i=-1;
+
+ for(i=0; i<next; i++){
+ if(min2 > counts[i]){
+ if(min1 > counts[i]){
+ min2= min1;
+ min2_i= min1_i;
+ min1= counts[i];
+ min1_i= i;
+ }else{
+ min2= counts[i];
+ min2_i= i;
+ }
+ }
+ }
+
+ if(min2==INT64_MAX) break;
+
+ counts[next]= min1 + min2;
+ counts[min1_i]=
+ counts[min2_i]= INT64_MAX;
+ up[min1_i]=
+ up[min2_i]= next;
+ up[next]= -1;
+ }
+
+ for(i=0; i<size; i++){
+ int len;
+ int index=i;
+
+ for(len=0; up[index] != -1; len++)
+ index= up[index];
+
+ if(len >= 32) break;
+
+ dst[i]= len;
+ }
+ if(i==size) break;
+ }
+}
+#endif /* CONFIG_ENCODERS */
+
+static int read_huffman_tables(HYuvContext *s, uint8_t *src, int length){
+ GetBitContext gb;
+ int i;
+
+ init_get_bits(&gb, src, length*8);
+
+ for(i=0; i<3; i++){
+ read_len_table(s->len[i], &gb);
+
+ if(generate_bits_table(s->bits[i], s->len[i])<0){
+ return -1;
+ }
+#if 0
+for(j=0; j<256; j++){
+printf("%6X, %2d, %3d\n", s->bits[i][j], s->len[i][j], j);
+}
+#endif
+ free_vlc(&s->vlc[i]);
+ init_vlc(&s->vlc[i], VLC_BITS, 256, s->len[i], 1, 1, s->bits[i], 4, 4, 0);
+ }
+
+ return (get_bits_count(&gb)+7)/8;
+}
+
+static int read_old_huffman_tables(HYuvContext *s){
+#if 1
+ GetBitContext gb;
+ int i;
+
+ init_get_bits(&gb, classic_shift_luma, sizeof(classic_shift_luma)*8);
+ read_len_table(s->len[0], &gb);
+ init_get_bits(&gb, classic_shift_chroma, sizeof(classic_shift_chroma)*8);
+ read_len_table(s->len[1], &gb);
+
+ 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++){
+ free_vlc(&s->vlc[i]);
+ init_vlc(&s->vlc[i], VLC_BITS, 256, s->len[i], 1, 1, s->bits[i], 4, 4, 0);
+ }
+
+ return 0;
+#else
+ av_log(s->avctx, AV_LOG_DEBUG, "v1 huffyuv is not supported \n");
+ return -1;
+#endif
+}
+
+static void 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);
+ }
+ }else{
+ s->temp[0]= av_malloc(4*s->width + 16);
+ }
+}
+
+static int common_init(AVCodecContext *avctx){
+ HYuvContext *s = avctx->priv_data;
+
+ s->avctx= avctx;
+ s->flags= avctx->flags;
+
+ dsputil_init(&s->dsp, avctx);
+
+ s->width= avctx->width;
+ s->height= avctx->height;
+ assert(s->width>0 && s->height>0);
+
+ return 0;
+}
+
+#ifdef CONFIG_DECODERS
+static int decode_init(AVCodecContext *avctx)
+{
+ HYuvContext *s = avctx->priv_data;
+
+ common_init(avctx);
+ memset(s->vlc, 0, 3*sizeof(VLC));
+
+ avctx->coded_frame= &s->picture;
+ s->interlaced= s->height > 288;
+
+s->bgr32=1;
+//if(avctx->extradata)
+// printf("extradata:%X, extradata_size:%d\n", *(uint32_t*)avctx->extradata, avctx->extradata_size);
+ if(avctx->extradata_size){
+ if((avctx->bits_per_sample&7) && avctx->bits_per_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;
+
+ 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_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) < 0)
+ return -1;
+ }else{
+ switch(avctx->bits_per_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_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_sample & ~7;
+ s->context= 0;
+
+ if(read_old_huffman_tables(s) < 0)
+ return -1;
+ }
+
+ switch(s->bitstream_bpp){
+ case 12:
+ avctx->pix_fmt = PIX_FMT_YUV420P;
+ break;
+ case 16:
+ if(s->yuy2){
+ avctx->pix_fmt = PIX_FMT_YUV422;
+ }else{
+ avctx->pix_fmt = PIX_FMT_YUV422P;
+ }
+ break;
+ case 24:
+ case 32:
+ if(s->bgr32){
+ avctx->pix_fmt = PIX_FMT_RGBA32;
+ }else{
+ avctx->pix_fmt = PIX_FMT_BGR24;
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ alloc_temp(s);
+
+// av_log(NULL, AV_LOG_DEBUG, "pred:%d bpp:%d hbpp:%d il:%d\n", s->predictor, s->bitstream_bpp, avctx->bits_per_sample, s->interlaced);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_ENCODERS
+static int store_table(HYuvContext *s, 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++;
+
+ assert(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 int encode_init(AVCodecContext *avctx)
+{
+ HYuvContext *s = avctx->priv_data;
+ int i, j;
+
+ 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
+ s->version=2;
+
+ avctx->coded_frame= &s->picture;
+
+ switch(avctx->pix_fmt){
+ case PIX_FMT_YUV420P:
+ s->bitstream_bpp= 12;
+ break;
+ case PIX_FMT_YUV422P:
+ s->bitstream_bpp= 16;
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "format not supported\n");
+ return -1;
+ }
+ avctx->bits_per_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 -1;
+ }
+ }else s->context= 0;
+
+ if(avctx->codec->id==CODEC_ID_HUFFYUV){
+ if(avctx->pix_fmt==PIX_FMT_YUV420P){
+ av_log(avctx, AV_LOG_ERROR, "Error: YV12 is not supported by huffyuv; use vcodec=ffvhuff or format=422p\n");
+ return -1;
+ }
+ 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 -1;
+ }
+ if(s->interlaced != ( s->height > 288 ))
+ av_log(avctx, AV_LOG_INFO, "using huffyuv 2.2.0 or newer interlacing flag\n");
+ }
+
+ ((uint8_t*)avctx->extradata)[0]= s->predictor;
+ ((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++){
+ generate_len_table(s->len[i], s->stats[i], 256);
+
+ if(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;
+ }
+
+// printf("pred:%d bpp:%d hbpp:%d il:%d\n", s->predictor, s->bitstream_bpp, avctx->bits_per_sample, s->interlaced);
+
+ alloc_temp(s);
+
+ s->picture_number=0;
+
+ return 0;
+}
+#endif /* CONFIG_ENCODERS */
+
+static void decode_422_bitstream(HYuvContext *s, int count){
+ int i;
+
+ count/=2;
+
+ for(i=0; i<count; i++){
+ s->temp[0][2*i ]= get_vlc2(&s->gb, s->vlc[0].table, VLC_BITS, 3);
+ s->temp[1][ i ]= get_vlc2(&s->gb, s->vlc[1].table, VLC_BITS, 3);
+ s->temp[0][2*i+1]= get_vlc2(&s->gb, s->vlc[0].table, VLC_BITS, 3);
+ s->temp[2][ i ]= get_vlc2(&s->gb, s->vlc[2].table, VLC_BITS, 3);
+ }
+}
+
+static void decode_gray_bitstream(HYuvContext *s, int count){
+ int i;
+
+ count/=2;
+
+ for(i=0; i<count; i++){
+ s->temp[0][2*i ]= get_vlc2(&s->gb, s->vlc[0].table, VLC_BITS, 3);
+ s->temp[0][2*i+1]= get_vlc2(&s->gb, s->vlc[0].table, VLC_BITS, 3);
+ }
+}
+
+#ifdef CONFIG_ENCODERS
+static int encode_422_bitstream(HYuvContext *s, int count){
+ int i;
+
+ 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;
+ }
+
+ count/=2;
+ if(s->flags&CODEC_FLAG_PASS1){
+ for(i=0; i<count; i++){
+ s->stats[0][ s->temp[0][2*i ] ]++;
+ s->stats[1][ s->temp[1][ i ] ]++;
+ s->stats[0][ s->temp[0][2*i+1] ]++;
+ s->stats[2][ s->temp[2][ i ] ]++;
+ }
+ }
+ if(s->avctx->flags2&CODEC_FLAG2_NO_OUTPUT)
+ return 0;
+ if(s->context){
+ for(i=0; i<count; i++){
+ s->stats[0][ s->temp[0][2*i ] ]++;
+ put_bits(&s->pb, s->len[0][ s->temp[0][2*i ] ], s->bits[0][ s->temp[0][2*i ] ]);
+ s->stats[1][ s->temp[1][ i ] ]++;
+ put_bits(&s->pb, s->len[1][ s->temp[1][ i ] ], s->bits[1][ s->temp[1][ i ] ]);
+ s->stats[0][ s->temp[0][2*i+1] ]++;
+ put_bits(&s->pb, s->len[0][ s->temp[0][2*i+1] ], s->bits[0][ s->temp[0][2*i+1] ]);
+ s->stats[2][ s->temp[2][ i ] ]++;
+ put_bits(&s->pb, s->len[2][ s->temp[2][ i ] ], s->bits[2][ s->temp[2][ i ] ]);
+ }
+ }else{
+ for(i=0; i<count; i++){
+ put_bits(&s->pb, s->len[0][ s->temp[0][2*i ] ], s->bits[0][ s->temp[0][2*i ] ]);
+ put_bits(&s->pb, s->len[1][ s->temp[1][ i ] ], s->bits[1][ s->temp[1][ i ] ]);
+ put_bits(&s->pb, s->len[0][ s->temp[0][2*i+1] ], s->bits[0][ s->temp[0][2*i+1] ]);
+ put_bits(&s->pb, s->len[2][ s->temp[2][ i ] ], s->bits[2][ s->temp[2][ i ] ]);
+ }
+ }
+ 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;
+ }
+
+ count/=2;
+ if(s->flags&CODEC_FLAG_PASS1){
+ for(i=0; i<count; i++){
+ s->stats[0][ s->temp[0][2*i ] ]++;
+ s->stats[0][ s->temp[0][2*i+1] ]++;
+ }
+ }
+ if(s->avctx->flags2&CODEC_FLAG2_NO_OUTPUT)
+ return 0;
+
+ if(s->context){
+ for(i=0; i<count; i++){
+ s->stats[0][ s->temp[0][2*i ] ]++;
+ put_bits(&s->pb, s->len[0][ s->temp[0][2*i ] ], s->bits[0][ s->temp[0][2*i ] ]);
+ s->stats[0][ s->temp[0][2*i+1] ]++;
+ put_bits(&s->pb, s->len[0][ s->temp[0][2*i+1] ], s->bits[0][ s->temp[0][2*i+1] ]);
+ }
+ }else{
+ for(i=0; i<count; i++){
+ put_bits(&s->pb, s->len[0][ s->temp[0][2*i ] ], s->bits[0][ s->temp[0][2*i ] ]);
+ put_bits(&s->pb, s->len[0][ s->temp[0][2*i+1] ], s->bits[0][ s->temp[0][2*i+1] ]);
+ }
+ }
+ return 0;
+}
+#endif /* CONFIG_ENCODERS */
+
+static void decode_bgr_bitstream(HYuvContext *s, int count){
+ int i;
+
+ if(s->decorrelate){
+ if(s->bitstream_bpp==24){
+ for(i=0; i<count; i++){
+ 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{
+ for(i=0; i<count; i++){
+ 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];
+ get_vlc2(&s->gb, s->vlc[2].table, VLC_BITS, 3); //?!
+ }
+ }
+ }else{
+ if(s->bitstream_bpp==24){
+ for(i=0; i<count; i++){
+ 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);
+ }
+ }else{
+ for(i=0; i<count; i++){
+ 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);
+ get_vlc2(&s->gb, s->vlc[2].table, VLC_BITS, 3); //?!
+ }
+ }
+ }
+}
+
+#ifdef CONFIG_DECODERS
+static void draw_slice(HYuvContext *s, int y){
+ int h, cy;
+ int offset[4];
+
+ 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] = s->picture.linesize[0]*y;
+ offset[1] = s->picture.linesize[1]*cy;
+ offset[2] = s->picture.linesize[2]*cy;
+ offset[3] = 0;
+ emms_c();
+
+ s->avctx->draw_horiz_band(s->avctx, &s->picture, offset, y, 3, h);
+
+ s->last_slice_end= y + h;
+}
+
+static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_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;
+ AVFrame * const p= &s->picture;
+ int table_size= 0;
+
+ AVFrame *picture = data;
+
+ s->bitstream_buffer= av_fast_realloc(s->bitstream_buffer, &s->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+
+ s->dsp.bswap_buf((uint32_t*)s->bitstream_buffer, (uint32_t*)buf, buf_size/4);
+
+ if(p->data[0])
+ avctx->release_buffer(avctx, p);
+
+ p->reference= 0;
+ if(avctx->get_buffer(avctx, p) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ if(s->context){
+ table_size = read_huffman_tables(s, s->bitstream_buffer, buf_size);
+ if(table_size < 0)
+ return -1;
+ }
+
+ if((unsigned)(buf_size-table_size) >= INT_MAX/8)
+ return -1;
+
+ 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 -1;
+ }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= add_left_prediction(p->data[0] + 2, s->temp[0], width-2, lefty);
+ if(!(s->flags&CODEC_FLAG_GRAY)){
+ leftu= add_left_prediction(p->data[1] + 1, s->temp[1], width2-1, leftu);
+ leftv= add_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= add_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, 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= add_left_prediction(ydst, s->temp[0], width, lefty);
+ if(!(s->flags&CODEC_FLAG_GRAY)){
+ leftu= add_left_prediction(udst, s->temp[1], width2, leftu);
+ leftv= add_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, height);
+
+ break;
+ case MEDIAN:
+ /* first line except first 2 pixels is left predicted */
+ decode_422_bitstream(s, width-2);
+ lefty= add_left_prediction(p->data[0] + 2, s->temp[0], width-2, lefty);
+ if(!(s->flags&CODEC_FLAG_GRAY)){
+ leftu= add_left_prediction(p->data[1] + 1, s->temp[1], width2-1, leftu);
+ leftv= add_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= add_left_prediction(p->data[0] + p->linesize[0], s->temp[0], width, lefty);
+ if(!(s->flags&CODEC_FLAG_GRAY)){
+ leftu= add_left_prediction(p->data[1] + p->linesize[2], s->temp[1], width2, leftu);
+ leftv= add_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= add_left_prediction(p->data[0] + fake_ystride, s->temp[0], 4, lefty);
+ if(!(s->flags&CODEC_FLAG_GRAY)){
+ leftu= add_left_prediction(p->data[1] + fake_ustride, s->temp[1], 2, leftu);
+ leftv= add_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);
+ add_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];
+ add_median_prediction(p->data[1] + fake_ustride+2, p->data[1]+2, s->temp[1], width2-2, &leftu, &lefttopu);
+ add_median_prediction(p->data[2] + fake_vstride+2, p->data[2]+2, s->temp[2], width2-2, &leftv, &lefttopv);
+ }
+ y++; cy++;
+
+ for(; y<height; y++,cy++){
+ uint8_t *ydst, *udst, *vdst;
+
+ if(s->bitstream_bpp==12){
+ while(2*cy > y){
+ decode_gray_bitstream(s, width);
+ ydst= p->data[0] + p->linesize[0]*y;
+ add_median_prediction(ydst, ydst - fake_ystride, s->temp[0], width, &lefty, &lefttopy);
+ y++;
+ }
+ if(y>=height) break;
+ }
+ draw_slice(s, 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;
+
+ add_median_prediction(ydst, ydst - fake_ystride, s->temp[0], width, &lefty, &lefttopy);
+ if(!(s->flags&CODEC_FLAG_GRAY)){
+ add_median_prediction(udst, udst - fake_ustride, s->temp[1], width2, &leftu, &lefttopu);
+ add_median_prediction(vdst, vdst - fake_vstride, s->temp[2], width2, &leftv, &lefttopv);
+ }
+ }
+
+ draw_slice(s, height);
+ break;
+ }
+ }
+ }else{
+ int y;
+ int leftr, leftg, leftb;
+ const int last_line= (height-1)*p->linesize[0];
+
+ if(s->bitstream_bpp==32){
+ skip_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);
+ skip_bits(&s->gb, 8);
+ }
+
+ if(s->bgr32){
+ switch(s->predictor){
+ case LEFT:
+ case PLANE:
+ decode_bgr_bitstream(s, width-1);
+ add_left_prediction_bgr32(p->data[0] + last_line+4, s->temp[0], width-1, &leftr, &leftg, &leftb);
+
+ for(y=s->height-2; y>=0; y--){ //yes its stored upside down
+ decode_bgr_bitstream(s, width);
+
+ add_left_prediction_bgr32(p->data[0] + p->linesize[0]*y, s->temp[0], width, &leftr, &leftg, &leftb);
+ if(s->predictor == PLANE){
+ 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);
+ }
+ }
+ }
+ draw_slice(s, height); // just 1 large slice as this is not possible in reverse order
+ 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 -1;
+ }
+ }
+ emms_c();
+
+ *picture= *p;
+ *data_size = sizeof(AVFrame);
+
+ return (get_bits_count(&s->gb)+31)/32*4 + table_size;
+}
+#endif
+
+static int common_end(HYuvContext *s){
+ int i;
+
+ for(i=0; i<3; i++){
+ av_freep(&s->temp[i]);
+ }
+ return 0;
+}
+
+#ifdef CONFIG_DECODERS
+static int decode_end(AVCodecContext *avctx)
+{
+ HYuvContext *s = avctx->priv_data;
+ int i;
+
+ common_end(s);
+ av_freep(&s->bitstream_buffer);
+
+ for(i=0; i<3; i++){
+ free_vlc(&s->vlc[i]);
+ }
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_ENCODERS
+static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
+ HYuvContext *s = avctx->priv_data;
+ AVFrame *pict = 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;
+
+ *p = *pict;
+ p->pict_type= FF_I_TYPE;
+ p->key_frame= 1;
+
+ if(s->context){
+ for(i=0; i<3; i++){
+ generate_len_table(s->len[i], s->stats[i], 256);
+ if(generate_bits_table(s->bits[i], s->len[i])<0)
+ return -1;
+ size+= store_table(s, s->len[i], &buf[size]);
+ }
+
+ for(i=0; i<3; i++)
+ for(j=0; j<256; j++)
+ s->stats[i][j] >>= 1;
+ }
+
+ init_put_bits(&s->pb, buf+size, buf_size-size);
+
+ if(avctx->pix_fmt == PIX_FMT_YUV422P || avctx->pix_fmt == 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]+2, width-2 , lefty);
+ leftu= sub_left_prediction(s, s->temp[1], p->data[1]+1, width2-1, leftu);
+ leftv= sub_left_prediction(s, s->temp[2], p->data[2]+1, width2-1, leftv);
+
+ encode_422_bitstream(s, 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, 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, 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, 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, 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, width);
+ }
+ }
+ }else{
+ av_log(avctx, AV_LOG_ERROR, "Format not supported!\n");
+ }
+ emms_c();
+
+ size+= (put_bits_count(&s->pb)+31)/8;
+ 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++;
+ }
+ }
+ if(!(s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT)){
+ flush_put_bits(&s->pb);
+ s->dsp.bswap_buf((uint32_t*)buf, (uint32_t*)buf, size);
+ avctx->stats_out[0] = '\0';
+ }
+
+ s->picture_number++;
+
+ return size*4;
+}
+
+static int encode_end(AVCodecContext *avctx)
+{
+ HYuvContext *s = avctx->priv_data;
+
+ common_end(s);
+
+ av_freep(&avctx->extradata);
+ av_freep(&avctx->stats_out);
+
+ return 0;
+}
+#endif /* CONFIG_ENCODERS */
+
+#ifdef CONFIG_DECODERS
+AVCodec huffyuv_decoder = {
+ "huffyuv",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_HUFFYUV,
+ sizeof(HYuvContext),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame,
+ CODEC_CAP_DR1 | CODEC_CAP_DRAW_HORIZ_BAND,
+ NULL
+};
+
+AVCodec ffvhuff_decoder = {
+ "ffvhuff",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_FFVHUFF,
+ sizeof(HYuvContext),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame,
+ CODEC_CAP_DR1 | CODEC_CAP_DRAW_HORIZ_BAND,
+ NULL
+};
+#endif
+
+#ifdef CONFIG_ENCODERS
+
+AVCodec huffyuv_encoder = {
+ "huffyuv",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_HUFFYUV,
+ sizeof(HYuvContext),
+ encode_init,
+ encode_frame,
+ encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV422P, -1},
+};
+
+AVCodec ffvhuff_encoder = {
+ "ffvhuff",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_FFVHUFF,
+ sizeof(HYuvContext),
+ encode_init,
+ encode_frame,
+ encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV422P, -1},
+};
+
+#endif //CONFIG_ENCODERS
diff --git a/contrib/ffmpeg/libavcodec/i386/cavsdsp_mmx.c b/contrib/ffmpeg/libavcodec/i386/cavsdsp_mmx.c
new file mode 100644
index 000000000..51d519a5c
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/cavsdsp_mmx.c
@@ -0,0 +1,518 @@
+/*
+ * Chinese AVS video (AVS1-P2, JiZhun profile) decoder.
+ * Copyright (c) 2006 Stefan Gehrer <stefan.gehrer@gmx.de>
+ *
+ * MMX optimised DSP functions, based on H.264 optimisations 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "../dsputil.h"
+#include "common.h"
+
+DECLARE_ALIGNED_8(static const uint64_t,ff_pw_4 ) = 0x0004000400040004ULL;
+DECLARE_ALIGNED_8(static const uint64_t,ff_pw_5 ) = 0x0005000500050005ULL;
+DECLARE_ALIGNED_8(static const uint64_t,ff_pw_7 ) = 0x0007000700070007ULL;
+DECLARE_ALIGNED_8(static const uint64_t,ff_pw_42) = 0x002A002A002A002AULL;
+DECLARE_ALIGNED_8(static const uint64_t,ff_pw_64) = 0x0040004000400040ULL;
+DECLARE_ALIGNED_8(static const uint64_t,ff_pw_96) = 0x0060006000600060ULL;
+
+/*****************************************************************************
+ *
+ * inverse transform
+ *
+ ****************************************************************************/
+
+#define SUMSUB_BA( a, b ) \
+ "paddw "#b", "#a" \n\t"\
+ "paddw "#b", "#b" \n\t"\
+ "psubw "#a", "#b" \n\t"
+
+#define SBUTTERFLY(a,b,t,n)\
+ "movq " #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) /* a=aebf t=cgdh */\
+ SBUTTERFLY(c,d,b,wd) /* c=imjn b=kolp */\
+ SBUTTERFLY(a,c,d,dq) /* a=aeim d=bfjn */\
+ SBUTTERFLY(t,b,c,dq) /* t=cgko c=dhlp */
+
+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);
+
+ 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);
+
+ 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"
+ );
+ }
+
+ add_pixels_clamped_mmx(b2, dst, stride);
+
+ /* clear block */
+ asm volatile(
+ "pxor %%mm7, %%mm7 \n\t"
+ "movq %%mm7, (%0) \n\t"
+ "movq %%mm7, 8(%0) \n\t"
+ "movq %%mm7, 16(%0) \n\t"
+ "movq %%mm7, 24(%0) \n\t"
+ "movq %%mm7, 32(%0) \n\t"
+ "movq %%mm7, 40(%0) \n\t"
+ "movq %%mm7, 48(%0) \n\t"
+ "movq %%mm7, 56(%0) \n\t"
+ "movq %%mm7, 64(%0) \n\t"
+ "movq %%mm7, 72(%0) \n\t"
+ "movq %%mm7, 80(%0) \n\t"
+ "movq %%mm7, 88(%0) \n\t"
+ "movq %%mm7, 96(%0) \n\t"
+ "movq %%mm7, 104(%0) \n\t"
+ "movq %%mm7, 112(%0) \n\t"
+ "movq %%mm7, 120(%0) \n\t"
+ :: "r" (block)
+ );
+}
+
+/*****************************************************************************
+ *
+ * motion compensation
+ *
+ ****************************************************************************/
+
+/* vertical filter [-1 -2 96 42 -7 0] */
+#define QPEL_CAVSV1(A,B,C,D,E,F,OP) \
+ "movd (%0), "#F" \n\t"\
+ "movq "#C", %%mm6 \n\t"\
+ "pmullw %5, %%mm6 \n\t"\
+ "movq "#D", %%mm7 \n\t"\
+ "pmullw %6, %%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) \
+ "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) \
+ "movd (%0), "#F" \n\t"\
+ "movq "#C", %%mm6 \n\t"\
+ "pmullw %6, %%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)\
+ VOP(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP)\
+ VOP(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP)\
+ VOP(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP)\
+ VOP(%%mm4, %%mm5, %%mm0, %%mm1, %%mm2, %%mm3, OP)\
+ VOP(%%mm5, %%mm0, %%mm1, %%mm2, %%mm3, %%mm4, OP)\
+ VOP(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP)\
+ VOP(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP)\
+ \
+ : "+a"(src), "+c"(dst)\
+ : "S"((long)srcStride), "D"((long)dstStride), "m"(ADD), "m"(MUL1), "m"(MUL2)\
+ : "memory"\
+ );\
+ if(h==16){\
+ asm volatile(\
+ VOP(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP)\
+ VOP(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP)\
+ VOP(%%mm4, %%mm5, %%mm0, %%mm1, %%mm2, %%mm3, OP)\
+ VOP(%%mm5, %%mm0, %%mm1, %%mm2, %%mm3, %%mm4, OP)\
+ VOP(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP)\
+ VOP(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP)\
+ VOP(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP)\
+ VOP(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP)\
+ \
+ : "+a"(src), "+c"(dst)\
+ : "S"((long)srcStride), "D"((long)dstStride), "m"(ADD), "m"(MUL1), "m"(MUL2)\
+ : "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"((long)srcStride), "S"((long)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, int 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, int 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, int 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, int 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_MMX2_OP(a,b,temp, size) \
+"mov" #size " " #b ", " #temp " \n\t"\
+"pavgb " #temp ", " #a " \n\t"\
+"mov" #size " " #a ", " #b " \n\t"
+
+QPEL_CAVS(put_, PUT_OP, 3dnow)
+QPEL_CAVS(avg_, AVG_3DNOW_OP, 3dnow)
+QPEL_CAVS(put_, PUT_OP, mmx2)
+QPEL_CAVS(avg_, AVG_MMX2_OP, mmx2)
+
+CAVS_MC(put_, 8, 3dnow)
+CAVS_MC(put_, 16,3dnow)
+CAVS_MC(avg_, 8, 3dnow)
+CAVS_MC(avg_, 16,3dnow)
+CAVS_MC(put_, 8, mmx2)
+CAVS_MC(put_, 16,mmx2)
+CAVS_MC(avg_, 8, mmx2)
+CAVS_MC(avg_, 16,mmx2)
+
+void ff_put_cavs_qpel8_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride);
+void ff_avg_cavs_qpel8_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride);
+void ff_put_cavs_qpel16_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride);
+void ff_avg_cavs_qpel16_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride);
+
+void ff_cavsdsp_init_mmx2(DSPContext* c, AVCodecContext *avctx) {
+#define dspfunc(PFX, IDX, NUM) \
+ c->PFX ## _pixels_tab[IDX][ 0] = ff_ ## PFX ## NUM ## _mc00_mmx2; \
+ c->PFX ## _pixels_tab[IDX][ 2] = ff_ ## PFX ## NUM ## _mc20_mmx2; \
+ c->PFX ## _pixels_tab[IDX][ 4] = ff_ ## PFX ## NUM ## _mc01_mmx2; \
+ c->PFX ## _pixels_tab[IDX][ 8] = ff_ ## PFX ## NUM ## _mc02_mmx2; \
+ c->PFX ## _pixels_tab[IDX][12] = ff_ ## PFX ## NUM ## _mc03_mmx2; \
+
+ 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;
+}
+
+void ff_cavsdsp_init_3dnow(DSPContext* c, AVCodecContext *avctx) {
+#define dspfunc(PFX, IDX, NUM) \
+ c->PFX ## _pixels_tab[IDX][ 0] = ff_ ## PFX ## NUM ## _mc00_mmx2; \
+ 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;
+}
diff --git a/contrib/ffmpeg/libavcodec/i386/cputest.c b/contrib/ffmpeg/libavcodec/i386/cputest.c
new file mode 100644
index 000000000..262786b71
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/cputest.c
@@ -0,0 +1,126 @@
+/*
+ * CPU detection code, extracted from mmx.h
+ * (c)1997-99 by H. Dietz and R. Fisher
+ * Converted to C and improved by 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 <stdlib.h>
+#include "../dsputil.h"
+
+#undef printf
+
+#ifdef ARCH_X86_64
+# define REG_b "rbx"
+# define REG_S "rsi"
+#else
+# define REG_b "ebx"
+# define REG_S "esi"
+#endif
+
+/* ebx saving is necessary for PIC. gcc seems unable to see it alone */
+#define cpuid(index,eax,ebx,ecx,edx)\
+ __asm __volatile\
+ ("mov %%"REG_b", %%"REG_S"\n\t"\
+ "cpuid\n\t"\
+ "xchg %%"REG_b", %%"REG_S\
+ : "=a" (eax), "=S" (ebx),\
+ "=c" (ecx), "=d" (edx)\
+ : "0" (index));
+
+/* Function to test if multimedia instructions are supported... */
+int mm_support(void)
+{
+ int rval = 0;
+ int eax, ebx, ecx, edx;
+ int max_std_level, max_ext_level, std_caps=0, ext_caps=0;
+ long a, c;
+
+ __asm__ __volatile__ (
+ /* See if CPUID instruction is supported ... */
+ /* ... Get copies of EFLAGS into eax and ecx */
+ "pushf\n\t"
+ "pop %0\n\t"
+ "mov %0, %1\n\t"
+
+ /* ... Toggle the ID bit in one copy and store */
+ /* to the EFLAGS reg */
+ "xor $0x200000, %0\n\t"
+ "push %0\n\t"
+ "popf\n\t"
+
+ /* ... Get the (hopefully modified) EFLAGS */
+ "pushf\n\t"
+ "pop %0\n\t"
+ : "=a" (a), "=c" (c)
+ :
+ : "cc"
+ );
+
+ if (a == c)
+ return 0; /* CPUID not supported */
+
+ cpuid(0, max_std_level, ebx, ecx, edx);
+
+ if(max_std_level >= 1){
+ cpuid(1, eax, ebx, ecx, std_caps);
+ if (std_caps & (1<<23))
+ rval |= MM_MMX;
+ if (std_caps & (1<<25))
+ rval |= MM_MMXEXT | MM_SSE;
+ if (std_caps & (1<<26))
+ rval |= MM_SSE2;
+ if (ecx & 1)
+ rval |= MM_SSE3;
+ }
+
+ cpuid(0x80000000, max_ext_level, ebx, ecx, edx);
+
+ if(max_ext_level >= 0x80000001){
+ cpuid(0x80000001, eax, ebx, ecx, ext_caps);
+ if (ext_caps & (1<<31))
+ rval |= MM_3DNOW;
+ if (ext_caps & (1<<30))
+ rval |= MM_3DNOWEXT;
+ if (ext_caps & (1<<23))
+ rval |= MM_MMX;
+ if (ext_caps & (1<<22))
+ rval |= MM_MMXEXT;
+ }
+
+#if 0
+ av_log(NULL, AV_LOG_DEBUG, "%s%s%s%s%s%s\n",
+ (rval&MM_MMX) ? "MMX ":"",
+ (rval&MM_MMXEXT) ? "MMX2 ":"",
+ (rval&MM_SSE) ? "SSE ":"",
+ (rval&MM_SSE2) ? "SSE2 ":"",
+ (rval&MM_3DNOW) ? "3DNow ":"",
+ (rval&MM_3DNOWEXT) ? "3DNowExt ":"");
+#endif
+ return rval;
+}
+
+#ifdef __TEST__
+int main ( void )
+{
+ int mm_flags;
+ mm_flags = mm_support();
+ printf("mm_support = 0x%08X\n",mm_flags);
+ return 0;
+}
+#endif
diff --git a/contrib/ffmpeg/libavcodec/i386/dsputil_h264_template_mmx.c b/contrib/ffmpeg/libavcodec/i386/dsputil_h264_template_mmx.c
new file mode 100644
index 000000000..e09a1007e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/dsputil_h264_template_mmx.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2005 Zoltan Hidvegi <hzoli -a- hzoli -d- com>,
+ * 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
+ */
+
+/**
+ * MMX optimized version of (put|avg)_h264_chroma_mc8.
+ * H264_CHROMA_MC8_TMPL must be defined to the desired function name
+ * H264_CHROMA_OP must be defined to empty for put and pavgb/pavgusb for avg
+ * H264_CHROMA_MC8_MV0 must be defined to a (put|avg)_pixels8 function
+ */
+static void H264_CHROMA_MC8_TMPL(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int stride, int h, int x, int y)
+{
+ DECLARE_ALIGNED_8(uint64_t, AA);
+ DECLARE_ALIGNED_8(uint64_t, DD);
+ int i;
+
+ if(y==0 && x==0) {
+ /* no filter needed */
+ H264_CHROMA_MC8_MV0(dst, src, stride, h);
+ return;
+ }
+
+ assert(x<8 && y<8 && x>=0 && y>=0);
+
+ if(y==0 || x==0)
+ {
+ /* 1 dimensional filter only */
+ const int dxy = x ? 1 : stride;
+
+ asm volatile(
+ "movd %0, %%mm5\n\t"
+ "movq %1, %%mm4\n\t"
+ "punpcklwd %%mm5, %%mm5\n\t"
+ "punpckldq %%mm5, %%mm5\n\t" /* mm5 = B = x */
+ "movq %%mm4, %%mm6\n\t"
+ "pxor %%mm7, %%mm7\n\t"
+ "psubw %%mm5, %%mm4\n\t" /* mm4 = A = 8-x */
+ "psrlw $1, %%mm6\n\t" /* mm6 = 4 */
+ :: "rm"(x+y), "m"(ff_pw_8));
+
+ for(i=0; i<h; i++) {
+ asm volatile(
+ /* mm0 = src[0..7], mm1 = src[1..8] */
+ "movq %0, %%mm0\n\t"
+ "movq %1, %%mm2\n\t"
+ :: "m"(src[0]), "m"(src[dxy]));
+
+ asm volatile(
+ /* [mm0,mm1] = A * src[0..7] */
+ /* [mm2,mm3] = B * src[1..8] */
+ "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"
+ "pmullw %%mm4, %%mm0\n\t"
+ "pmullw %%mm4, %%mm1\n\t"
+ "pmullw %%mm5, %%mm2\n\t"
+ "pmullw %%mm5, %%mm3\n\t"
+
+ /* dst[0..7] = (A * src[0..7] + B * src[1..8] + 4) >> 3 */
+ "paddw %%mm6, %%mm0\n\t"
+ "paddw %%mm6, %%mm1\n\t"
+ "paddw %%mm2, %%mm0\n\t"
+ "paddw %%mm3, %%mm1\n\t"
+ "psrlw $3, %%mm0\n\t"
+ "psrlw $3, %%mm1\n\t"
+ "packuswb %%mm1, %%mm0\n\t"
+ H264_CHROMA_OP(%0, %%mm0)
+ "movq %%mm0, %0\n\t"
+ : "=m" (dst[0]));
+
+ src += stride;
+ dst += stride;
+ }
+ return;
+ }
+
+ /* general case, bilinear */
+ asm volatile("movd %2, %%mm4\n\t"
+ "movd %3, %%mm6\n\t"
+ "punpcklwd %%mm4, %%mm4\n\t"
+ "punpcklwd %%mm6, %%mm6\n\t"
+ "punpckldq %%mm4, %%mm4\n\t" /* mm4 = x words */
+ "punpckldq %%mm6, %%mm6\n\t" /* mm6 = y words */
+ "movq %%mm4, %%mm5\n\t"
+ "pmullw %%mm6, %%mm4\n\t" /* mm4 = x * y */
+ "psllw $3, %%mm5\n\t"
+ "psllw $3, %%mm6\n\t"
+ "movq %%mm5, %%mm7\n\t"
+ "paddw %%mm6, %%mm7\n\t"
+ "movq %%mm4, %1\n\t" /* DD = x * y */
+ "psubw %%mm4, %%mm5\n\t" /* mm5 = B = 8x - xy */
+ "psubw %%mm4, %%mm6\n\t" /* mm6 = C = 8y - xy */
+ "paddw %4, %%mm4\n\t"
+ "psubw %%mm7, %%mm4\n\t" /* mm4 = A = xy - (8x+8y) + 64 */
+ "pxor %%mm7, %%mm7\n\t"
+ "movq %%mm4, %0\n\t"
+ : "=m" (AA), "=m" (DD) : "rm" (x), "rm" (y), "m" (ff_pw_64));
+
+ asm volatile(
+ /* mm0 = src[0..7], mm1 = src[1..8] */
+ "movq %0, %%mm0\n\t"
+ "movq %1, %%mm1\n\t"
+ : : "m" (src[0]), "m" (src[1]));
+
+ for(i=0; i<h; i++) {
+ src += stride;
+
+ asm volatile(
+ /* mm2 = A * src[0..3] + B * src[1..4] */
+ /* mm3 = A * src[4..7] + B * src[5..8] */
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "punpckhbw %%mm7, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpcklbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "pmullw %0, %%mm0\n\t"
+ "pmullw %0, %%mm2\n\t"
+ "pmullw %%mm5, %%mm1\n\t"
+ "pmullw %%mm5, %%mm3\n\t"
+ "paddw %%mm1, %%mm2\n\t"
+ "paddw %%mm0, %%mm3\n\t"
+ : : "m" (AA));
+
+ asm volatile(
+ /* [mm2,mm3] += C * src[0..7] */
+ "movq %0, %%mm0\n\t"
+ "movq %%mm0, %%mm1\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpckhbw %%mm7, %%mm1\n\t"
+ "pmullw %%mm6, %%mm0\n\t"
+ "pmullw %%mm6, %%mm1\n\t"
+ "paddw %%mm0, %%mm2\n\t"
+ "paddw %%mm1, %%mm3\n\t"
+ : : "m" (src[0]));
+
+ asm volatile(
+ /* [mm2,mm3] += D * src[1..8] */
+ "movq %1, %%mm1\n\t"
+ "movq %%mm1, %%mm0\n\t"
+ "movq %%mm1, %%mm4\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpckhbw %%mm7, %%mm4\n\t"
+ "pmullw %2, %%mm0\n\t"
+ "pmullw %2, %%mm4\n\t"
+ "paddw %%mm0, %%mm2\n\t"
+ "paddw %%mm4, %%mm3\n\t"
+ "movq %0, %%mm0\n\t"
+ : : "m" (src[0]), "m" (src[1]), "m" (DD));
+
+ asm volatile(
+ /* dst[0..7] = ([mm2,mm3] + 32) >> 6 */
+ "paddw %1, %%mm2\n\t"
+ "paddw %1, %%mm3\n\t"
+ "psrlw $6, %%mm2\n\t"
+ "psrlw $6, %%mm3\n\t"
+ "packuswb %%mm3, %%mm2\n\t"
+ H264_CHROMA_OP(%0, %%mm2)
+ "movq %%mm2, %0\n\t"
+ : "=m" (dst[0]) : "m" (ff_pw_32));
+ dst+= stride;
+ }
+}
+
+static void H264_CHROMA_MC4_TMPL(uint8_t *dst/*align 4*/, uint8_t *src/*align 1*/, int stride, int h, int x, int y)
+{
+ DECLARE_ALIGNED_8(uint64_t, AA);
+ DECLARE_ALIGNED_8(uint64_t, DD);
+ int i;
+
+ /* no special case for mv=(0,0) in 4x*, since it's much less common than in 8x*.
+ * could still save a few cycles, but maybe not worth the complexity. */
+
+ assert(x<8 && y<8 && x>=0 && y>=0);
+
+ asm volatile("movd %2, %%mm4\n\t"
+ "movd %3, %%mm6\n\t"
+ "punpcklwd %%mm4, %%mm4\n\t"
+ "punpcklwd %%mm6, %%mm6\n\t"
+ "punpckldq %%mm4, %%mm4\n\t" /* mm4 = x words */
+ "punpckldq %%mm6, %%mm6\n\t" /* mm6 = y words */
+ "movq %%mm4, %%mm5\n\t"
+ "pmullw %%mm6, %%mm4\n\t" /* mm4 = x * y */
+ "psllw $3, %%mm5\n\t"
+ "psllw $3, %%mm6\n\t"
+ "movq %%mm5, %%mm7\n\t"
+ "paddw %%mm6, %%mm7\n\t"
+ "movq %%mm4, %1\n\t" /* DD = x * y */
+ "psubw %%mm4, %%mm5\n\t" /* mm5 = B = 8x - xy */
+ "psubw %%mm4, %%mm6\n\t" /* mm6 = C = 8y - xy */
+ "paddw %4, %%mm4\n\t"
+ "psubw %%mm7, %%mm4\n\t" /* mm4 = A = xy - (8x+8y) + 64 */
+ "pxor %%mm7, %%mm7\n\t"
+ "movq %%mm4, %0\n\t"
+ : "=m" (AA), "=m" (DD) : "rm" (x), "rm" (y), "m" (ff_pw_64));
+
+ asm volatile(
+ /* mm0 = src[0..3], mm1 = src[1..4] */
+ "movd %0, %%mm0\n\t"
+ "movd %1, %%mm1\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ : : "m" (src[0]), "m" (src[1]));
+
+ for(i=0; i<h; i++) {
+ asm volatile(
+ /* mm2 = A * src[0..3] + B * src[1..4] */
+ "movq %%mm0, %%mm2\n\t"
+ "pmullw %0, %%mm2\n\t"
+ "pmullw %%mm5, %%mm1\n\t"
+ "paddw %%mm1, %%mm2\n\t"
+ : : "m" (AA));
+
+ src += stride;
+ asm volatile(
+ /* mm0 = src[0..3], mm1 = src[1..4] */
+ "movd %0, %%mm0\n\t"
+ "movd %1, %%mm1\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ : : "m" (src[0]), "m" (src[1]));
+
+ asm volatile(
+ /* mm2 += C * src[0..3] + D * src[1..4] */
+ "movq %%mm0, %%mm3\n\t"
+ "movq %%mm1, %%mm4\n\t"
+ "pmullw %%mm6, %%mm3\n\t"
+ "pmullw %0, %%mm4\n\t"
+ "paddw %%mm3, %%mm2\n\t"
+ "paddw %%mm4, %%mm2\n\t"
+ : : "m" (DD));
+
+ asm volatile(
+ /* dst[0..3] = pack((mm2 + 32) >> 6) */
+ "paddw %1, %%mm2\n\t"
+ "psrlw $6, %%mm2\n\t"
+ "packuswb %%mm7, %%mm2\n\t"
+ H264_CHROMA_OP4(%0, %%mm2, %%mm3)
+ "movd %%mm2, %0\n\t"
+ : "=m" (dst[0]) : "m" (ff_pw_32));
+ dst += stride;
+ }
+}
+
+#ifdef H264_CHROMA_MC2_TMPL
+static void H264_CHROMA_MC2_TMPL(uint8_t *dst/*align 2*/, uint8_t *src/*align 1*/, int stride, int h, int x, int y)
+{
+ int CD=((1<<16)-1)*x*y + 8*y;
+ int AB=((8<<16)-8)*x + 64 - CD;
+ int i;
+
+ asm volatile(
+ /* mm5 = {A,B,A,B} */
+ /* mm6 = {C,D,C,D} */
+ "movd %0, %%mm5\n\t"
+ "movd %1, %%mm6\n\t"
+ "punpckldq %%mm5, %%mm5\n\t"
+ "punpckldq %%mm6, %%mm6\n\t"
+ "pxor %%mm7, %%mm7\n\t"
+ :: "r"(AB), "r"(CD));
+
+ asm volatile(
+ /* mm0 = src[0,1,1,2] */
+ "movd %0, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "pshufw $0x94, %%mm0, %%mm0\n\t"
+ :: "m"(src[0]));
+
+ for(i=0; i<h; i++) {
+ asm volatile(
+ /* mm1 = A * src[0,1] + B * src[1,2] */
+ "movq %%mm0, %%mm1\n\t"
+ "pmaddwd %%mm5, %%mm1\n\t"
+ ::);
+
+ src += stride;
+ asm volatile(
+ /* mm0 = src[0,1,1,2] */
+ "movd %0, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "pshufw $0x94, %%mm0, %%mm0\n\t"
+ :: "m"(src[0]));
+
+ asm volatile(
+ /* mm1 += C * src[0,1] + D * src[1,2] */
+ "movq %%mm0, %%mm2\n\t"
+ "pmaddwd %%mm6, %%mm2\n\t"
+ "paddw %%mm2, %%mm1\n\t"
+ ::);
+
+ asm volatile(
+ /* dst[0,1] = pack((mm1 + 32) >> 6) */
+ "paddw %1, %%mm1\n\t"
+ "psrlw $6, %%mm1\n\t"
+ "packssdw %%mm7, %%mm1\n\t"
+ "packuswb %%mm7, %%mm1\n\t"
+ /* writes garbage to the right of dst.
+ * ok because partitions are processed from left to right. */
+ H264_CHROMA_OP4(%0, %%mm1, %%mm3)
+ "movd %%mm1, %0\n\t"
+ : "=m" (dst[0]) : "m" (ff_pw_32));
+ dst += stride;
+ }
+}
+#endif
+
diff --git a/contrib/ffmpeg/libavcodec/i386/dsputil_mmx.c b/contrib/ffmpeg/libavcodec/i386/dsputil_mmx.c
new file mode 100644
index 000000000..5675828a4
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/dsputil_mmx.c
@@ -0,0 +1,3534 @@
+/*
+ * MMX optimized DSP utils
+ * Copyright (c) 2000, 2001 Fabrice Bellard.
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 <nickols_k@mail.ru>
+ */
+
+#include "../dsputil.h"
+#include "../simple_idct.h"
+#include "../mpegvideo.h"
+#include "x86_cpu.h"
+#include "mmx.h"
+
+//#undef NDEBUG
+//#include <assert.h>
+
+extern void ff_idct_xvid_mmx(short *block);
+extern void ff_idct_xvid_mmx2(short *block);
+
+int mm_flags; /* multimedia extension flags */
+
+/* pixel operations */
+static const uint64_t mm_bone attribute_used __attribute__ ((aligned(8))) = 0x0101010101010101ULL;
+static const uint64_t mm_wone attribute_used __attribute__ ((aligned(8))) = 0x0001000100010001ULL;
+static const uint64_t mm_wtwo attribute_used __attribute__ ((aligned(8))) = 0x0002000200020002ULL;
+
+static const uint64_t ff_pdw_80000000[2] attribute_used __attribute__ ((aligned(16))) =
+{0x8000000080000000ULL, 0x8000000080000000ULL};
+
+static const uint64_t ff_pw_20 attribute_used __attribute__ ((aligned(8))) = 0x0014001400140014ULL;
+static const uint64_t ff_pw_3 attribute_used __attribute__ ((aligned(8))) = 0x0003000300030003ULL;
+static const uint64_t ff_pw_4 attribute_used __attribute__ ((aligned(8))) = 0x0004000400040004ULL;
+static const uint64_t ff_pw_5 attribute_used __attribute__ ((aligned(8))) = 0x0005000500050005ULL;
+static const uint64_t ff_pw_8 attribute_used __attribute__ ((aligned(8))) = 0x0008000800080008ULL;
+static const uint64_t ff_pw_16 attribute_used __attribute__ ((aligned(8))) = 0x0010001000100010ULL;
+static const uint64_t ff_pw_32 attribute_used __attribute__ ((aligned(8))) = 0x0020002000200020ULL;
+static const uint64_t ff_pw_64 attribute_used __attribute__ ((aligned(8))) = 0x0040004000400040ULL;
+static const uint64_t ff_pw_15 attribute_used __attribute__ ((aligned(8))) = 0x000F000F000F000FULL;
+
+static const uint64_t ff_pb_1 attribute_used __attribute__ ((aligned(8))) = 0x0101010101010101ULL;
+static const uint64_t ff_pb_3 attribute_used __attribute__ ((aligned(8))) = 0x0303030303030303ULL;
+static const uint64_t ff_pb_7 attribute_used __attribute__ ((aligned(8))) = 0x0707070707070707ULL;
+static const uint64_t ff_pb_3F attribute_used __attribute__ ((aligned(8))) = 0x3F3F3F3F3F3F3F3FULL;
+static const uint64_t ff_pb_A1 attribute_used __attribute__ ((aligned(8))) = 0xA1A1A1A1A1A1A1A1ULL;
+static const uint64_t ff_pb_5F attribute_used __attribute__ ((aligned(8))) = 0x5F5F5F5F5F5F5F5FULL;
+static const uint64_t ff_pb_FC attribute_used __attribute__ ((aligned(8))) = 0xFCFCFCFCFCFCFCFCULL;
+
+#define JUMPALIGN() __asm __volatile (ASMALIGN(3)::)
+#define MOVQ_ZERO(regd) __asm __volatile ("pxor %%" #regd ", %%" #regd ::)
+
+#define MOVQ_WONE(regd) \
+ __asm __volatile ( \
+ "pcmpeqd %%" #regd ", %%" #regd " \n\t" \
+ "psrlw $15, %%" #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"(mm_bone))
+#define MOVQ_WTWO(regd) __asm __volatile ("movq %0, %%" #regd " \n\t" ::"m"(mm_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 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)
+
+#include "dsputil_mmx_rnd.h"
+
+#undef DEF
+#undef SET_RND
+#undef PAVGBP
+#undef PAVGB
+/***********************************/
+/* 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 "dsputil_mmx_rnd.h"
+
+#undef DEF
+#undef SET_RND
+#undef PAVGBP
+#undef PAVGB
+
+/***********************************/
+/* 3Dnow specific */
+
+#define DEF(x) x ## _3dnow
+/* for Athlons PAVGUSB is prefered */
+#define PAVGB "pavgusb"
+
+#include "dsputil_mmx_avg.h"
+
+#undef DEF
+#undef PAVGB
+
+/***********************************/
+/* MMX2 specific */
+
+#define DEF(x) x ## _mmx2
+
+/* Introduced only in MMX2 set */
+#define PAVGB "pavgb"
+
+#include "dsputil_mmx_avg.h"
+
+#undef DEF
+#undef PAVGB
+
+#define SBUTTERFLY(a,b,t,n)\
+ "movq " #a ", " #t " \n\t" /* abcd */\
+ "punpckl" #n " " #b ", " #a " \n\t" /* aebf */\
+ "punpckh" #n " " #b ", " #t " \n\t" /* cgdh */\
+
+/***********************************/
+/* standard MMX */
+
+#ifdef CONFIG_ENCODERS
+static void get_pixels_mmx(DCTELEM *block, const uint8_t *pixels, int line_size)
+{
+ asm volatile(
+ "mov $-128, %%"REG_a" \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ "movq (%0), %%mm0 \n\t"
+ "movq (%0, %2), %%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"
+ "movq %%mm0, (%1, %%"REG_a") \n\t"
+ "movq %%mm1, 8(%1, %%"REG_a") \n\t"
+ "movq %%mm2, 16(%1, %%"REG_a") \n\t"
+ "movq %%mm3, 24(%1, %%"REG_a") \n\t"
+ "add %3, %0 \n\t"
+ "add $32, %%"REG_a" \n\t"
+ "js 1b \n\t"
+ : "+r" (pixels)
+ : "r" (block+64), "r" ((long)line_size), "r" ((long)line_size*2)
+ : "%"REG_a
+ );
+}
+
+static inline void diff_pixels_mmx(DCTELEM *block, const uint8_t *s1, const uint8_t *s2, int stride)
+{
+ asm volatile(
+ "pxor %%mm7, %%mm7 \n\t"
+ "mov $-128, %%"REG_a" \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ "movq (%0), %%mm0 \n\t"
+ "movq (%1), %%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"
+ "psubw %%mm2, %%mm0 \n\t"
+ "psubw %%mm3, %%mm1 \n\t"
+ "movq %%mm0, (%2, %%"REG_a") \n\t"
+ "movq %%mm1, 8(%2, %%"REG_a") \n\t"
+ "add %3, %0 \n\t"
+ "add %3, %1 \n\t"
+ "add $16, %%"REG_a" \n\t"
+ "jnz 1b \n\t"
+ : "+r" (s1), "+r" (s2)
+ : "r" (block+64), "r" ((long)stride)
+ : "%"REG_a
+ );
+}
+#endif //CONFIG_ENCODERS
+
+void put_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size)
+{
+ const DCTELEM *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" ((long)line_size), "r" ((long)line_size*3), "m"(*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" ((long)line_size), "r" ((long)line_size*3), "r"(p)
+ :"memory");
+}
+
+static DECLARE_ALIGNED_8(const unsigned char, vector128[8]) =
+ { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
+
+void put_signed_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size)
+{
+ int i;
+
+ movq_m2r(*vector128, mm1);
+ for (i = 0; i < 8; i++) {
+ movq_m2r(*(block), mm0);
+ packsswb_m2r(*(block + 4), mm0);
+ block += 8;
+ paddb_r2r(mm1, mm0);
+ movq_r2m(mm0, *pixels);
+ pixels += line_size;
+ }
+}
+
+void add_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size)
+{
+ const DCTELEM *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_pixels4_mmx(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ __asm __volatile(
+ "lea (%3, %3), %%"REG_a" \n\t"
+ ASMALIGN(3)
+ "1: \n\t"
+ "movd (%1), %%mm0 \n\t"
+ "movd (%1, %3), %%mm1 \n\t"
+ "movd %%mm0, (%2) \n\t"
+ "movd %%mm1, (%2, %3) \n\t"
+ "add %%"REG_a", %1 \n\t"
+ "add %%"REG_a", %2 \n\t"
+ "movd (%1), %%mm0 \n\t"
+ "movd (%1, %3), %%mm1 \n\t"
+ "movd %%mm0, (%2) \n\t"
+ "movd %%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"((long)line_size)
+ : "%"REG_a, "memory"
+ );
+}
+
+static void put_pixels8_mmx(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ __asm __volatile(
+ "lea (%3, %3), %%"REG_a" \n\t"
+ ASMALIGN(3)
+ "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"((long)line_size)
+ : "%"REG_a, "memory"
+ );
+}
+
+static void put_pixels16_mmx(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ __asm __volatile(
+ "lea (%3, %3), %%"REG_a" \n\t"
+ ASMALIGN(3)
+ "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"((long)line_size)
+ : "%"REG_a, "memory"
+ );
+}
+
+static void clear_blocks_mmx(DCTELEM *blocks)
+{
+ __asm __volatile(
+ "pxor %%mm7, %%mm7 \n\t"
+ "mov $-128*6, %%"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*6)
+ : "%"REG_a
+ );
+}
+
+#ifdef CONFIG_ENCODERS
+static int pix_sum16_mmx(uint8_t * pix, int line_size){
+ const int h=16;
+ int sum;
+ long index= -line_size*h;
+
+ __asm __volatile(
+ "pxor %%mm7, %%mm7 \n\t"
+ "pxor %%mm6, %%mm6 \n\t"
+ "1: \n\t"
+ "movq (%2, %1), %%mm0 \n\t"
+ "movq (%2, %1), %%mm1 \n\t"
+ "movq 8(%2, %1), %%mm2 \n\t"
+ "movq 8(%2, %1), %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpckhbw %%mm7, %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "punpckhbw %%mm7, %%mm3 \n\t"
+ "paddw %%mm0, %%mm1 \n\t"
+ "paddw %%mm2, %%mm3 \n\t"
+ "paddw %%mm1, %%mm3 \n\t"
+ "paddw %%mm3, %%mm6 \n\t"
+ "add %3, %1 \n\t"
+ " js 1b \n\t"
+ "movq %%mm6, %%mm5 \n\t"
+ "psrlq $32, %%mm6 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "movq %%mm6, %%mm5 \n\t"
+ "psrlq $16, %%mm6 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "movd %%mm6, %0 \n\t"
+ "andl $0xFFFF, %0 \n\t"
+ : "=&r" (sum), "+r" (index)
+ : "r" (pix - index), "r" ((long)line_size)
+ );
+
+ return sum;
+}
+#endif //CONFIG_ENCODERS
+
+static void add_bytes_mmx(uint8_t *dst, uint8_t *src, int w){
+ long i=0;
+ asm volatile(
+ "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"
+ "cmp %3, %0 \n\t"
+ " jb 1b \n\t"
+ : "+r" (i)
+ : "r"(src), "r"(dst), "r"((long)w-15)
+ );
+ for(; i<w; i++)
+ dst[i+0] += src[i+0];
+}
+
+#define H263_LOOP_FILTER \
+ "pxor %%mm7, %%mm7 \n\t"\
+ "movq %0, %%mm0 \n\t"\
+ "movq %0, %%mm1 \n\t"\
+ "movq %3, %%mm2 \n\t"\
+ "movq %3, %%mm3 \n\t"\
+ "punpcklbw %%mm7, %%mm0 \n\t"\
+ "punpckhbw %%mm7, %%mm1 \n\t"\
+ "punpcklbw %%mm7, %%mm2 \n\t"\
+ "punpckhbw %%mm7, %%mm3 \n\t"\
+ "psubw %%mm2, %%mm0 \n\t"\
+ "psubw %%mm3, %%mm1 \n\t"\
+ "movq %1, %%mm2 \n\t"\
+ "movq %1, %%mm3 \n\t"\
+ "movq %2, %%mm4 \n\t"\
+ "movq %2, %%mm5 \n\t"\
+ "punpcklbw %%mm7, %%mm2 \n\t"\
+ "punpckhbw %%mm7, %%mm3 \n\t"\
+ "punpcklbw %%mm7, %%mm4 \n\t"\
+ "punpckhbw %%mm7, %%mm5 \n\t"\
+ "psubw %%mm2, %%mm4 \n\t"\
+ "psubw %%mm3, %%mm5 \n\t"\
+ "psllw $2, %%mm4 \n\t"\
+ "psllw $2, %%mm5 \n\t"\
+ "paddw %%mm0, %%mm4 \n\t"\
+ "paddw %%mm1, %%mm5 \n\t"\
+ "pxor %%mm6, %%mm6 \n\t"\
+ "pcmpgtw %%mm4, %%mm6 \n\t"\
+ "pcmpgtw %%mm5, %%mm7 \n\t"\
+ "pxor %%mm6, %%mm4 \n\t"\
+ "pxor %%mm7, %%mm5 \n\t"\
+ "psubw %%mm6, %%mm4 \n\t"\
+ "psubw %%mm7, %%mm5 \n\t"\
+ "psrlw $3, %%mm4 \n\t"\
+ "psrlw $3, %%mm5 \n\t"\
+ "packuswb %%mm5, %%mm4 \n\t"\
+ "packsswb %%mm7, %%mm6 \n\t"\
+ "pxor %%mm7, %%mm7 \n\t"\
+ "movd %4, %%mm2 \n\t"\
+ "punpcklbw %%mm2, %%mm2 \n\t"\
+ "punpcklbw %%mm2, %%mm2 \n\t"\
+ "punpcklbw %%mm2, %%mm2 \n\t"\
+ "psubusb %%mm4, %%mm2 \n\t"\
+ "movq %%mm2, %%mm3 \n\t"\
+ "psubusb %%mm4, %%mm3 \n\t"\
+ "psubb %%mm3, %%mm2 \n\t"\
+ "movq %1, %%mm3 \n\t"\
+ "movq %2, %%mm4 \n\t"\
+ "pxor %%mm6, %%mm3 \n\t"\
+ "pxor %%mm6, %%mm4 \n\t"\
+ "paddusb %%mm2, %%mm3 \n\t"\
+ "psubusb %%mm2, %%mm4 \n\t"\
+ "pxor %%mm6, %%mm3 \n\t"\
+ "pxor %%mm6, %%mm4 \n\t"\
+ "paddusb %%mm2, %%mm2 \n\t"\
+ "packsswb %%mm1, %%mm0 \n\t"\
+ "pcmpgtb %%mm0, %%mm7 \n\t"\
+ "pxor %%mm7, %%mm0 \n\t"\
+ "psubb %%mm7, %%mm0 \n\t"\
+ "movq %%mm0, %%mm1 \n\t"\
+ "psubusb %%mm2, %%mm0 \n\t"\
+ "psubb %%mm0, %%mm1 \n\t"\
+ "pand %5, %%mm1 \n\t"\
+ "psrlw $2, %%mm1 \n\t"\
+ "pxor %%mm7, %%mm1 \n\t"\
+ "psubb %%mm7, %%mm1 \n\t"\
+ "movq %0, %%mm5 \n\t"\
+ "movq %3, %%mm6 \n\t"\
+ "psubb %%mm1, %%mm5 \n\t"\
+ "paddb %%mm1, %%mm6 \n\t"
+
+static void h263_v_loop_filter_mmx(uint8_t *src, int stride, int qscale){
+ const int strength= ff_h263_loop_filter_strength[qscale];
+
+ asm volatile(
+
+ H263_LOOP_FILTER
+
+ "movq %%mm3, %1 \n\t"
+ "movq %%mm4, %2 \n\t"
+ "movq %%mm5, %0 \n\t"
+ "movq %%mm6, %3 \n\t"
+ : "+m" (*(uint64_t*)(src - 2*stride)),
+ "+m" (*(uint64_t*)(src - 1*stride)),
+ "+m" (*(uint64_t*)(src + 0*stride)),
+ "+m" (*(uint64_t*)(src + 1*stride))
+ : "g" (2*strength), "m"(ff_pb_FC)
+ );
+}
+
+static inline void transpose4x4(uint8_t *dst, uint8_t *src, int dst_stride, int src_stride){
+ asm volatile( //FIXME could save 1 instruction if done as 8x4 ...
+ "movd %4, %%mm0 \n\t"
+ "movd %5, %%mm1 \n\t"
+ "movd %6, %%mm2 \n\t"
+ "movd %7, %%mm3 \n\t"
+ "punpcklbw %%mm1, %%mm0 \n\t"
+ "punpcklbw %%mm3, %%mm2 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "punpcklwd %%mm2, %%mm0 \n\t"
+ "punpckhwd %%mm2, %%mm1 \n\t"
+ "movd %%mm0, %0 \n\t"
+ "punpckhdq %%mm0, %%mm0 \n\t"
+ "movd %%mm0, %1 \n\t"
+ "movd %%mm1, %2 \n\t"
+ "punpckhdq %%mm1, %%mm1 \n\t"
+ "movd %%mm1, %3 \n\t"
+
+ : "=m" (*(uint32_t*)(dst + 0*dst_stride)),
+ "=m" (*(uint32_t*)(dst + 1*dst_stride)),
+ "=m" (*(uint32_t*)(dst + 2*dst_stride)),
+ "=m" (*(uint32_t*)(dst + 3*dst_stride))
+ : "m" (*(uint32_t*)(src + 0*src_stride)),
+ "m" (*(uint32_t*)(src + 1*src_stride)),
+ "m" (*(uint32_t*)(src + 2*src_stride)),
+ "m" (*(uint32_t*)(src + 3*src_stride))
+ );
+}
+
+static void h263_h_loop_filter_mmx(uint8_t *src, int stride, int qscale){
+ const int strength= ff_h263_loop_filter_strength[qscale];
+ uint64_t temp[4] __attribute__ ((aligned(8)));
+ uint8_t *btemp= (uint8_t*)temp;
+
+ src -= 2;
+
+ transpose4x4(btemp , src , 8, stride);
+ transpose4x4(btemp+4, src + 4*stride, 8, stride);
+ asm volatile(
+ H263_LOOP_FILTER // 5 3 4 6
+
+ : "+m" (temp[0]),
+ "+m" (temp[1]),
+ "+m" (temp[2]),
+ "+m" (temp[3])
+ : "g" (2*strength), "m"(ff_pb_FC)
+ );
+
+ asm volatile(
+ "movq %%mm5, %%mm1 \n\t"
+ "movq %%mm4, %%mm0 \n\t"
+ "punpcklbw %%mm3, %%mm5 \n\t"
+ "punpcklbw %%mm6, %%mm4 \n\t"
+ "punpckhbw %%mm3, %%mm1 \n\t"
+ "punpckhbw %%mm6, %%mm0 \n\t"
+ "movq %%mm5, %%mm3 \n\t"
+ "movq %%mm1, %%mm6 \n\t"
+ "punpcklwd %%mm4, %%mm5 \n\t"
+ "punpcklwd %%mm0, %%mm1 \n\t"
+ "punpckhwd %%mm4, %%mm3 \n\t"
+ "punpckhwd %%mm0, %%mm6 \n\t"
+ "movd %%mm5, (%0) \n\t"
+ "punpckhdq %%mm5, %%mm5 \n\t"
+ "movd %%mm5, (%0,%2) \n\t"
+ "movd %%mm3, (%0,%2,2) \n\t"
+ "punpckhdq %%mm3, %%mm3 \n\t"
+ "movd %%mm3, (%0,%3) \n\t"
+ "movd %%mm1, (%1) \n\t"
+ "punpckhdq %%mm1, %%mm1 \n\t"
+ "movd %%mm1, (%1,%2) \n\t"
+ "movd %%mm6, (%1,%2,2) \n\t"
+ "punpckhdq %%mm6, %%mm6 \n\t"
+ "movd %%mm6, (%1,%3) \n\t"
+ :: "r" (src),
+ "r" (src + 4*stride),
+ "r" ((long) stride ),
+ "r" ((long)(3*stride))
+ );
+}
+
+#ifdef CONFIG_ENCODERS
+static int pix_norm1_mmx(uint8_t *pix, int line_size) {
+ int tmp;
+ asm volatile (
+ "movl $16,%%ecx\n"
+ "pxor %%mm0,%%mm0\n"
+ "pxor %%mm7,%%mm7\n"
+ "1:\n"
+ "movq (%0),%%mm2\n" /* mm2 = pix[0-7] */
+ "movq 8(%0),%%mm3\n" /* mm3 = pix[8-15] */
+
+ "movq %%mm2,%%mm1\n" /* mm1 = mm2 = pix[0-7] */
+
+ "punpckhbw %%mm0,%%mm1\n" /* mm1 = [pix4-7] */
+ "punpcklbw %%mm0,%%mm2\n" /* mm2 = [pix0-3] */
+
+ "movq %%mm3,%%mm4\n" /* mm4 = mm3 = pix[8-15] */
+ "punpckhbw %%mm0,%%mm3\n" /* mm3 = [pix12-15] */
+ "punpcklbw %%mm0,%%mm4\n" /* mm4 = [pix8-11] */
+
+ "pmaddwd %%mm1,%%mm1\n" /* mm1 = (pix0^2+pix1^2,pix2^2+pix3^2) */
+ "pmaddwd %%mm2,%%mm2\n" /* mm2 = (pix4^2+pix5^2,pix6^2+pix7^2) */
+
+ "pmaddwd %%mm3,%%mm3\n"
+ "pmaddwd %%mm4,%%mm4\n"
+
+ "paddd %%mm1,%%mm2\n" /* mm2 = (pix0^2+pix1^2+pix4^2+pix5^2,
+ pix2^2+pix3^2+pix6^2+pix7^2) */
+ "paddd %%mm3,%%mm4\n"
+ "paddd %%mm2,%%mm7\n"
+
+ "add %2, %0\n"
+ "paddd %%mm4,%%mm7\n"
+ "dec %%ecx\n"
+ "jnz 1b\n"
+
+ "movq %%mm7,%%mm1\n"
+ "psrlq $32, %%mm7\n" /* shift hi dword to lo */
+ "paddd %%mm7,%%mm1\n"
+ "movd %%mm1,%1\n"
+ : "+r" (pix), "=r"(tmp) : "r" ((long)line_size) : "%ecx" );
+ return tmp;
+}
+
+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: substract 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" ((long)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: substract 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" ((long)line_size) , "m" (h)
+ : "%ecx");
+ return tmp;
+}
+
+static int sse16_sse2(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
+ int tmp;
+ asm volatile (
+ "shr $1,%2\n"
+ "pxor %%xmm0,%%xmm0\n" /* mm0 = 0 */
+ "pxor %%xmm7,%%xmm7\n" /* mm7 holds the sum */
+ "1:\n"
+ "movdqu (%0),%%xmm1\n" /* mm1 = pix1[0][0-15] */
+ "movdqu (%1),%%xmm2\n" /* mm2 = pix2[0][0-15] */
+ "movdqu (%0,%4),%%xmm3\n" /* mm3 = pix1[1][0-15] */
+ "movdqu (%1,%4),%%xmm4\n" /* mm4 = pix2[1][0-15] */
+
+ /* todo: mm1-mm2, mm3-mm4 */
+ /* algo: substract mm1 from mm2 with saturation and vice versa */
+ /* OR the results to get absolute difference */
+ "movdqa %%xmm1,%%xmm5\n"
+ "movdqa %%xmm3,%%xmm6\n"
+ "psubusb %%xmm2,%%xmm1\n"
+ "psubusb %%xmm4,%%xmm3\n"
+ "psubusb %%xmm5,%%xmm2\n"
+ "psubusb %%xmm6,%%xmm4\n"
+
+ "por %%xmm1,%%xmm2\n"
+ "por %%xmm3,%%xmm4\n"
+
+ /* now convert to 16-bit vectors so we can square them */
+ "movdqa %%xmm2,%%xmm1\n"
+ "movdqa %%xmm4,%%xmm3\n"
+
+ "punpckhbw %%xmm0,%%xmm2\n"
+ "punpckhbw %%xmm0,%%xmm4\n"
+ "punpcklbw %%xmm0,%%xmm1\n" /* mm1 now spread over (mm1,mm2) */
+ "punpcklbw %%xmm0,%%xmm3\n" /* mm4 now spread over (mm3,mm4) */
+
+ "pmaddwd %%xmm2,%%xmm2\n"
+ "pmaddwd %%xmm4,%%xmm4\n"
+ "pmaddwd %%xmm1,%%xmm1\n"
+ "pmaddwd %%xmm3,%%xmm3\n"
+
+ "lea (%0,%4,2), %0\n" /* pix1 += 2*line_size */
+ "lea (%1,%4,2), %1\n" /* pix2 += 2*line_size */
+
+ "paddd %%xmm2,%%xmm1\n"
+ "paddd %%xmm4,%%xmm3\n"
+ "paddd %%xmm1,%%xmm7\n"
+ "paddd %%xmm3,%%xmm7\n"
+
+ "decl %2\n"
+ "jnz 1b\n"
+
+ "movdqa %%xmm7,%%xmm1\n"
+ "psrldq $8, %%xmm7\n" /* shift hi qword to lo */
+ "paddd %%xmm1,%%xmm7\n"
+ "movdqa %%xmm7,%%xmm1\n"
+ "psrldq $4, %%xmm7\n" /* shift hi dword to lo */
+ "paddd %%xmm1,%%xmm7\n"
+ "movd %%xmm7,%3\n"
+ : "+r" (pix1), "+r" (pix2), "+r"(h), "=r"(tmp)
+ : "r" ((long)line_size));
+ 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" ((long)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" ((long)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;
+
+ assert( (((int)pix) & 7) == 0);
+ assert((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"
+ "subl $2, %%ecx\n"
+ SUM(%%mm0, %%mm1, %%mm4, %%mm5)
+ "1:\n"
+
+ SUM(%%mm4, %%mm5, %%mm0, %%mm1)
+
+ 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" ((long)line_size) , "m" (h)
+ : "%ecx");
+ return tmp & 0xFFFF;
+}
+#undef SUM
+
+static int vsad_intra16_mmx2(void *v, uint8_t * pix, uint8_t * dummy, int line_size, int h) {
+ int tmp;
+
+ assert( (((int)pix) & 7) == 0);
+ assert((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"
+ "subl $2, %%ecx\n"
+ SUM(%%mm0, %%mm1, %%mm4, %%mm5)
+ "1:\n"
+
+ SUM(%%mm4, %%mm5, %%mm0, %%mm1)
+
+ SUM(%%mm0, %%mm1, %%mm4, %%mm5)
+
+ "subl $2, %%ecx\n"
+ "jnz 1b\n"
+
+ "movd %%mm6,%1\n"
+ : "+r" (pix), "=r"(tmp)
+ : "r" ((long)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;
+
+ assert( (((int)pix1) & 7) == 0);
+ assert( (((int)pix2) & 7) == 0);
+ assert((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"
+ "subl $2, %%ecx\n"
+ "psubb %%mm2, %%mm0\n"
+ "psubb %%mm3, %%mm1\n"
+ "pxor %%mm7, %%mm0\n"
+ "pxor %%mm7, %%mm1\n"
+ SUM(%%mm0, %%mm1, %%mm4, %%mm5)
+ "1:\n"
+
+ SUM(%%mm4, %%mm5, %%mm0, %%mm1)
+
+ 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" ((long)line_size) , "m" (h)
+ : "%ecx");
+ return tmp & 0x7FFF;
+}
+#undef SUM
+
+static int vsad16_mmx2(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
+ int tmp;
+
+ assert( (((int)pix1) & 7) == 0);
+ assert( (((int)pix2) & 7) == 0);
+ assert((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"
+ "subl $2, %%ecx\n"
+ "psubb %%mm2, %%mm0\n"
+ "psubb %%mm3, %%mm1\n"
+ "pxor %%mm7, %%mm0\n"
+ "pxor %%mm7, %%mm1\n"
+ SUM(%%mm0, %%mm1, %%mm4, %%mm5)
+ "1:\n"
+
+ SUM(%%mm4, %%mm5, %%mm0, %%mm1)
+
+ SUM(%%mm0, %%mm1, %%mm4, %%mm5)
+
+ "subl $2, %%ecx\n"
+ "jnz 1b\n"
+
+ "movd %%mm6,%2\n"
+ : "+r" (pix1), "+r" (pix2), "=r"(tmp)
+ : "r" ((long)line_size) , "m" (h)
+ : "%ecx");
+ return tmp;
+}
+#undef SUM
+
+static void diff_bytes_mmx(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w){
+ long i=0;
+ 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"((long)w-15)
+ );
+ for(; i<w; i++)
+ dst[i+0] = src1[i+0]-src2[i+0];
+}
+
+static void sub_hfyu_median_prediction_mmx2(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w, int *left, int *left_top){
+ long i=0;
+ uint8_t l, lt;
+
+ asm volatile(
+ "1: \n\t"
+ "movq -1(%1, %0), %%mm0 \n\t" // LT
+ "movq (%1, %0), %%mm1 \n\t" // T
+ "movq -1(%2, %0), %%mm2 \n\t" // L
+ "movq (%2, %0), %%mm3 \n\t" // X
+ "movq %%mm2, %%mm4 \n\t" // L
+ "psubb %%mm0, %%mm2 \n\t"
+ "paddb %%mm1, %%mm2 \n\t" // L + T - LT
+ "movq %%mm4, %%mm5 \n\t" // L
+ "pmaxub %%mm1, %%mm4 \n\t" // max(T, L)
+ "pminub %%mm5, %%mm1 \n\t" // min(T, L)
+ "pminub %%mm2, %%mm4 \n\t"
+ "pmaxub %%mm1, %%mm4 \n\t"
+ "psubb %%mm4, %%mm3 \n\t" // dst - pred
+ "movq %%mm3, (%3, %0) \n\t"
+ "add $8, %0 \n\t"
+ "cmp %4, %0 \n\t"
+ " jb 1b \n\t"
+ : "+r" (i)
+ : "r"(src1), "r"(src2), "r"(dst), "r"((long)w)
+ );
+
+ l= *left;
+ lt= *left_top;
+
+ dst[0]= src2[0] - mid_pred(l, src1[0], (l + src1[0] - lt)&0xFF);
+
+ *left_top= src1[w-1];
+ *left = src2[w-1];
+}
+
+#define LBUTTERFLY2(a1,b1,a2,b2)\
+ "paddw " #b1 ", " #a1 " \n\t"\
+ "paddw " #b2 ", " #a2 " \n\t"\
+ "paddw " #b1 ", " #b1 " \n\t"\
+ "paddw " #b2 ", " #b2 " \n\t"\
+ "psubw " #a1 ", " #b1 " \n\t"\
+ "psubw " #a2 ", " #b2 " \n\t"
+
+#define HADAMARD48\
+ LBUTTERFLY2(%%mm0, %%mm1, %%mm2, %%mm3)\
+ LBUTTERFLY2(%%mm4, %%mm5, %%mm6, %%mm7)\
+ LBUTTERFLY2(%%mm0, %%mm2, %%mm1, %%mm3)\
+ LBUTTERFLY2(%%mm4, %%mm6, %%mm5, %%mm7)\
+ LBUTTERFLY2(%%mm0, %%mm4, %%mm1, %%mm5)\
+ LBUTTERFLY2(%%mm2, %%mm6, %%mm3, %%mm7)\
+
+#define MMABS(a,z)\
+ "pxor " #z ", " #z " \n\t"\
+ "pcmpgtw " #a ", " #z " \n\t"\
+ "pxor " #z ", " #a " \n\t"\
+ "psubw " #z ", " #a " \n\t"
+
+#define MMABS_SUM(a,z, sum)\
+ "pxor " #z ", " #z " \n\t"\
+ "pcmpgtw " #a ", " #z " \n\t"\
+ "pxor " #z ", " #a " \n\t"\
+ "psubw " #z ", " #a " \n\t"\
+ "paddusw " #a ", " #sum " \n\t"
+
+#define MMABS_MMX2(a,z)\
+ "pxor " #z ", " #z " \n\t"\
+ "psubw " #a ", " #z " \n\t"\
+ "pmaxsw " #z ", " #a " \n\t"
+
+#define MMABS_SUM_MMX2(a,z, sum)\
+ "pxor " #z ", " #z " \n\t"\
+ "psubw " #a ", " #z " \n\t"\
+ "pmaxsw " #z ", " #a " \n\t"\
+ "paddusw " #a ", " #sum " \n\t"
+
+#define TRANSPOSE4(a,b,c,d,t)\
+ SBUTTERFLY(a,b,t,wd) /* a=aebf t=cgdh */\
+ SBUTTERFLY(c,d,b,wd) /* c=imjn b=kolp */\
+ SBUTTERFLY(a,c,d,dq) /* a=aeim d=bfjn */\
+ SBUTTERFLY(t,b,c,dq) /* t=cgko c=dhlp */
+
+#define LOAD4(o, a, b, c, d)\
+ "movq "#o"(%1), " #a " \n\t"\
+ "movq "#o"+16(%1), " #b " \n\t"\
+ "movq "#o"+32(%1), " #c " \n\t"\
+ "movq "#o"+48(%1), " #d " \n\t"
+
+#define STORE4(o, a, b, c, d)\
+ "movq "#a", "#o"(%1) \n\t"\
+ "movq "#b", "#o"+16(%1) \n\t"\
+ "movq "#c", "#o"+32(%1) \n\t"\
+ "movq "#d", "#o"+48(%1) \n\t"\
+
+static int hadamard8_diff_mmx(void *s, uint8_t *src1, uint8_t *src2, int stride, int h){
+ DECLARE_ALIGNED_8(uint64_t, temp[16]);
+ int sum=0;
+
+ assert(h==8);
+
+ diff_pixels_mmx((DCTELEM*)temp, src1, src2, stride);
+
+ asm volatile(
+ LOAD4(0 , %%mm0, %%mm1, %%mm2, %%mm3)
+ LOAD4(64, %%mm4, %%mm5, %%mm6, %%mm7)
+
+ HADAMARD48
+
+ "movq %%mm7, 112(%1) \n\t"
+
+ TRANSPOSE4(%%mm0, %%mm1, %%mm2, %%mm3, %%mm7)
+ STORE4(0 , %%mm0, %%mm3, %%mm7, %%mm2)
+
+ "movq 112(%1), %%mm7 \n\t"
+ TRANSPOSE4(%%mm4, %%mm5, %%mm6, %%mm7, %%mm0)
+ STORE4(64, %%mm4, %%mm7, %%mm0, %%mm6)
+
+ LOAD4(8 , %%mm0, %%mm1, %%mm2, %%mm3)
+ LOAD4(72, %%mm4, %%mm5, %%mm6, %%mm7)
+
+ HADAMARD48
+
+ "movq %%mm7, 120(%1) \n\t"
+
+ TRANSPOSE4(%%mm0, %%mm1, %%mm2, %%mm3, %%mm7)
+ STORE4(8 , %%mm0, %%mm3, %%mm7, %%mm2)
+
+ "movq 120(%1), %%mm7 \n\t"
+ TRANSPOSE4(%%mm4, %%mm5, %%mm6, %%mm7, %%mm0)
+ "movq %%mm7, %%mm5 \n\t"//FIXME remove
+ "movq %%mm6, %%mm7 \n\t"
+ "movq %%mm0, %%mm6 \n\t"
+// STORE4(72, %%mm4, %%mm7, %%mm0, %%mm6) //FIXME remove
+
+ LOAD4(64, %%mm0, %%mm1, %%mm2, %%mm3)
+// LOAD4(72, %%mm4, %%mm5, %%mm6, %%mm7)
+
+ HADAMARD48
+ "movq %%mm7, 64(%1) \n\t"
+ MMABS(%%mm0, %%mm7)
+ MMABS_SUM(%%mm1, %%mm7, %%mm0)
+ MMABS_SUM(%%mm2, %%mm7, %%mm0)
+ MMABS_SUM(%%mm3, %%mm7, %%mm0)
+ MMABS_SUM(%%mm4, %%mm7, %%mm0)
+ MMABS_SUM(%%mm5, %%mm7, %%mm0)
+ MMABS_SUM(%%mm6, %%mm7, %%mm0)
+ "movq 64(%1), %%mm1 \n\t"
+ MMABS_SUM(%%mm1, %%mm7, %%mm0)
+ "movq %%mm0, 64(%1) \n\t"
+
+ LOAD4(0 , %%mm0, %%mm1, %%mm2, %%mm3)
+ LOAD4(8 , %%mm4, %%mm5, %%mm6, %%mm7)
+
+ HADAMARD48
+ "movq %%mm7, (%1) \n\t"
+ MMABS(%%mm0, %%mm7)
+ MMABS_SUM(%%mm1, %%mm7, %%mm0)
+ MMABS_SUM(%%mm2, %%mm7, %%mm0)
+ MMABS_SUM(%%mm3, %%mm7, %%mm0)
+ MMABS_SUM(%%mm4, %%mm7, %%mm0)
+ MMABS_SUM(%%mm5, %%mm7, %%mm0)
+ MMABS_SUM(%%mm6, %%mm7, %%mm0)
+ "movq (%1), %%mm1 \n\t"
+ MMABS_SUM(%%mm1, %%mm7, %%mm0)
+ "movq 64(%1), %%mm1 \n\t"
+ MMABS_SUM(%%mm1, %%mm7, %%mm0)
+
+ "movq %%mm0, %%mm1 \n\t"
+ "psrlq $32, %%mm0 \n\t"
+ "paddusw %%mm1, %%mm0 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "psrlq $16, %%mm0 \n\t"
+ "paddusw %%mm1, %%mm0 \n\t"
+ "movd %%mm0, %0 \n\t"
+
+ : "=r" (sum)
+ : "r"(temp)
+ );
+ return sum&0xFFFF;
+}
+
+static int hadamard8_diff_mmx2(void *s, uint8_t *src1, uint8_t *src2, int stride, int h){
+ DECLARE_ALIGNED_8(uint64_t, temp[16]);
+ int sum=0;
+
+ assert(h==8);
+
+ diff_pixels_mmx((DCTELEM*)temp, src1, src2, stride);
+
+ asm volatile(
+ LOAD4(0 , %%mm0, %%mm1, %%mm2, %%mm3)
+ LOAD4(64, %%mm4, %%mm5, %%mm6, %%mm7)
+
+ HADAMARD48
+
+ "movq %%mm7, 112(%1) \n\t"
+
+ TRANSPOSE4(%%mm0, %%mm1, %%mm2, %%mm3, %%mm7)
+ STORE4(0 , %%mm0, %%mm3, %%mm7, %%mm2)
+
+ "movq 112(%1), %%mm7 \n\t"
+ TRANSPOSE4(%%mm4, %%mm5, %%mm6, %%mm7, %%mm0)
+ STORE4(64, %%mm4, %%mm7, %%mm0, %%mm6)
+
+ LOAD4(8 , %%mm0, %%mm1, %%mm2, %%mm3)
+ LOAD4(72, %%mm4, %%mm5, %%mm6, %%mm7)
+
+ HADAMARD48
+
+ "movq %%mm7, 120(%1) \n\t"
+
+ TRANSPOSE4(%%mm0, %%mm1, %%mm2, %%mm3, %%mm7)
+ STORE4(8 , %%mm0, %%mm3, %%mm7, %%mm2)
+
+ "movq 120(%1), %%mm7 \n\t"
+ TRANSPOSE4(%%mm4, %%mm5, %%mm6, %%mm7, %%mm0)
+ "movq %%mm7, %%mm5 \n\t"//FIXME remove
+ "movq %%mm6, %%mm7 \n\t"
+ "movq %%mm0, %%mm6 \n\t"
+// STORE4(72, %%mm4, %%mm7, %%mm0, %%mm6) //FIXME remove
+
+ LOAD4(64, %%mm0, %%mm1, %%mm2, %%mm3)
+// LOAD4(72, %%mm4, %%mm5, %%mm6, %%mm7)
+
+ HADAMARD48
+ "movq %%mm7, 64(%1) \n\t"
+ MMABS_MMX2(%%mm0, %%mm7)
+ MMABS_SUM_MMX2(%%mm1, %%mm7, %%mm0)
+ MMABS_SUM_MMX2(%%mm2, %%mm7, %%mm0)
+ MMABS_SUM_MMX2(%%mm3, %%mm7, %%mm0)
+ MMABS_SUM_MMX2(%%mm4, %%mm7, %%mm0)
+ MMABS_SUM_MMX2(%%mm5, %%mm7, %%mm0)
+ MMABS_SUM_MMX2(%%mm6, %%mm7, %%mm0)
+ "movq 64(%1), %%mm1 \n\t"
+ MMABS_SUM_MMX2(%%mm1, %%mm7, %%mm0)
+ "movq %%mm0, 64(%1) \n\t"
+
+ LOAD4(0 , %%mm0, %%mm1, %%mm2, %%mm3)
+ LOAD4(8 , %%mm4, %%mm5, %%mm6, %%mm7)
+
+ HADAMARD48
+ "movq %%mm7, (%1) \n\t"
+ MMABS_MMX2(%%mm0, %%mm7)
+ MMABS_SUM_MMX2(%%mm1, %%mm7, %%mm0)
+ MMABS_SUM_MMX2(%%mm2, %%mm7, %%mm0)
+ MMABS_SUM_MMX2(%%mm3, %%mm7, %%mm0)
+ MMABS_SUM_MMX2(%%mm4, %%mm7, %%mm0)
+ MMABS_SUM_MMX2(%%mm5, %%mm7, %%mm0)
+ MMABS_SUM_MMX2(%%mm6, %%mm7, %%mm0)
+ "movq (%1), %%mm1 \n\t"
+ MMABS_SUM_MMX2(%%mm1, %%mm7, %%mm0)
+ "movq 64(%1), %%mm1 \n\t"
+ MMABS_SUM_MMX2(%%mm1, %%mm7, %%mm0)
+
+ "pshufw $0x0E, %%mm0, %%mm1 \n\t"
+ "paddusw %%mm1, %%mm0 \n\t"
+ "pshufw $0x01, %%mm0, %%mm1 \n\t"
+ "paddusw %%mm1, %%mm0 \n\t"
+ "movd %%mm0, %0 \n\t"
+
+ : "=r" (sum)
+ : "r"(temp)
+ );
+ return sum&0xFFFF;
+}
+
+
+WARPER8_16_SQ(hadamard8_diff_mmx, hadamard8_diff16_mmx)
+WARPER8_16_SQ(hadamard8_diff_mmx2, hadamard8_diff16_mmx2)
+#endif //CONFIG_ENCODERS
+
+#define put_no_rnd_pixels8_mmx(a,b,c,d) put_pixels8_mmx(a,b,c,d)
+#define put_no_rnd_pixels16_mmx(a,b,c,d) put_pixels16_mmx(a,b,c,d)
+
+#define QPEL_V_LOW(m3,m4,m5,m6, pw_20, pw_3, rnd, in0, in1, in2, in7, out, OP)\
+ "paddw " #m4 ", " #m3 " \n\t" /* x1 */\
+ "movq "MANGLE(ff_pw_20)", %%mm4 \n\t" /* 20 */\
+ "pmullw " #m3 ", %%mm4 \n\t" /* 20x1 */\
+ "movq "#in7", " #m3 " \n\t" /* d */\
+ "movq "#in0", %%mm5 \n\t" /* D */\
+ "paddw " #m3 ", %%mm5 \n\t" /* x4 */\
+ "psubw %%mm5, %%mm4 \n\t" /* 20x1 - x4 */\
+ "movq "#in1", %%mm5 \n\t" /* C */\
+ "movq "#in2", %%mm6 \n\t" /* B */\
+ "paddw " #m6 ", %%mm5 \n\t" /* x3 */\
+ "paddw " #m5 ", %%mm6 \n\t" /* x2 */\
+ "paddw %%mm6, %%mm6 \n\t" /* 2x2 */\
+ "psubw %%mm6, %%mm5 \n\t" /* -2x2 + x3 */\
+ "pmullw "MANGLE(ff_pw_3)", %%mm5 \n\t" /* -6x2 + 3x3 */\
+ "paddw " #rnd ", %%mm4 \n\t" /* x2 */\
+ "paddw %%mm4, %%mm5 \n\t" /* 20x1 - 6x2 + 3x3 - x4 */\
+ "psraw $5, %%mm5 \n\t"\
+ "packuswb %%mm5, %%mm5 \n\t"\
+ OP(%%mm5, out, %%mm7, d)
+
+#define QPEL_BASE(OPNAME, ROUNDER, RND, OP_MMX2, OP_3DNOW)\
+static void OPNAME ## mpeg4_qpel16_h_lowpass_mmx2(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\
+ uint64_t temp;\
+\
+ asm volatile(\
+ "pxor %%mm7, %%mm7 \n\t"\
+ "1: \n\t"\
+ "movq (%0), %%mm0 \n\t" /* ABCDEFGH */\
+ "movq %%mm0, %%mm1 \n\t" /* ABCDEFGH */\
+ "movq %%mm0, %%mm2 \n\t" /* ABCDEFGH */\
+ "punpcklbw %%mm7, %%mm0 \n\t" /* 0A0B0C0D */\
+ "punpckhbw %%mm7, %%mm1 \n\t" /* 0E0F0G0H */\
+ "pshufw $0x90, %%mm0, %%mm5 \n\t" /* 0A0A0B0C */\
+ "pshufw $0x41, %%mm0, %%mm6 \n\t" /* 0B0A0A0B */\
+ "movq %%mm2, %%mm3 \n\t" /* ABCDEFGH */\
+ "movq %%mm2, %%mm4 \n\t" /* ABCDEFGH */\
+ "psllq $8, %%mm2 \n\t" /* 0ABCDEFG */\
+ "psllq $16, %%mm3 \n\t" /* 00ABCDEF */\
+ "psllq $24, %%mm4 \n\t" /* 000ABCDE */\
+ "punpckhbw %%mm7, %%mm2 \n\t" /* 0D0E0F0G */\
+ "punpckhbw %%mm7, %%mm3 \n\t" /* 0C0D0E0F */\
+ "punpckhbw %%mm7, %%mm4 \n\t" /* 0B0C0D0E */\
+ "paddw %%mm3, %%mm5 \n\t" /* b */\
+ "paddw %%mm2, %%mm6 \n\t" /* c */\
+ "paddw %%mm5, %%mm5 \n\t" /* 2b */\
+ "psubw %%mm5, %%mm6 \n\t" /* c - 2b */\
+ "pshufw $0x06, %%mm0, %%mm5 \n\t" /* 0C0B0A0A */\
+ "pmullw "MANGLE(ff_pw_3)", %%mm6 \n\t" /* 3c - 6b */\
+ "paddw %%mm4, %%mm0 \n\t" /* a */\
+ "paddw %%mm1, %%mm5 \n\t" /* d */\
+ "pmullw "MANGLE(ff_pw_20)", %%mm0 \n\t" /* 20a */\
+ "psubw %%mm5, %%mm0 \n\t" /* 20a - d */\
+ "paddw %6, %%mm6 \n\t"\
+ "paddw %%mm6, %%mm0 \n\t" /* 20a - 6b + 3c - d */\
+ "psraw $5, %%mm0 \n\t"\
+ "movq %%mm0, %5 \n\t"\
+ /* mm1=EFGH, mm2=DEFG, mm3=CDEF, mm4=BCDE, mm7=0 */\
+ \
+ "movq 5(%0), %%mm0 \n\t" /* FGHIJKLM */\
+ "movq %%mm0, %%mm5 \n\t" /* FGHIJKLM */\
+ "movq %%mm0, %%mm6 \n\t" /* FGHIJKLM */\
+ "psrlq $8, %%mm0 \n\t" /* GHIJKLM0 */\
+ "psrlq $16, %%mm5 \n\t" /* HIJKLM00 */\
+ "punpcklbw %%mm7, %%mm0 \n\t" /* 0G0H0I0J */\
+ "punpcklbw %%mm7, %%mm5 \n\t" /* 0H0I0J0K */\
+ "paddw %%mm0, %%mm2 \n\t" /* b */\
+ "paddw %%mm5, %%mm3 \n\t" /* c */\
+ "paddw %%mm2, %%mm2 \n\t" /* 2b */\
+ "psubw %%mm2, %%mm3 \n\t" /* c - 2b */\
+ "movq %%mm6, %%mm2 \n\t" /* FGHIJKLM */\
+ "psrlq $24, %%mm6 \n\t" /* IJKLM000 */\
+ "punpcklbw %%mm7, %%mm2 \n\t" /* 0F0G0H0I */\
+ "punpcklbw %%mm7, %%mm6 \n\t" /* 0I0J0K0L */\
+ "pmullw "MANGLE(ff_pw_3)", %%mm3 \n\t" /* 3c - 6b */\
+ "paddw %%mm2, %%mm1 \n\t" /* a */\
+ "paddw %%mm6, %%mm4 \n\t" /* d */\
+ "pmullw "MANGLE(ff_pw_20)", %%mm1 \n\t" /* 20a */\
+ "psubw %%mm4, %%mm3 \n\t" /* - 6b +3c - d */\
+ "paddw %6, %%mm1 \n\t"\
+ "paddw %%mm1, %%mm3 \n\t" /* 20a - 6b +3c - d */\
+ "psraw $5, %%mm3 \n\t"\
+ "movq %5, %%mm1 \n\t"\
+ "packuswb %%mm3, %%mm1 \n\t"\
+ OP_MMX2(%%mm1, (%1),%%mm4, q)\
+ /* mm0= GHIJ, mm2=FGHI, mm5=HIJK, mm6=IJKL, mm7=0 */\
+ \
+ "movq 9(%0), %%mm1 \n\t" /* JKLMNOPQ */\
+ "movq %%mm1, %%mm4 \n\t" /* JKLMNOPQ */\
+ "movq %%mm1, %%mm3 \n\t" /* JKLMNOPQ */\
+ "psrlq $8, %%mm1 \n\t" /* KLMNOPQ0 */\
+ "psrlq $16, %%mm4 \n\t" /* LMNOPQ00 */\
+ "punpcklbw %%mm7, %%mm1 \n\t" /* 0K0L0M0N */\
+ "punpcklbw %%mm7, %%mm4 \n\t" /* 0L0M0N0O */\
+ "paddw %%mm1, %%mm5 \n\t" /* b */\
+ "paddw %%mm4, %%mm0 \n\t" /* c */\
+ "paddw %%mm5, %%mm5 \n\t" /* 2b */\
+ "psubw %%mm5, %%mm0 \n\t" /* c - 2b */\
+ "movq %%mm3, %%mm5 \n\t" /* JKLMNOPQ */\
+ "psrlq $24, %%mm3 \n\t" /* MNOPQ000 */\
+ "pmullw "MANGLE(ff_pw_3)", %%mm0 \n\t" /* 3c - 6b */\
+ "punpcklbw %%mm7, %%mm3 \n\t" /* 0M0N0O0P */\
+ "paddw %%mm3, %%mm2 \n\t" /* d */\
+ "psubw %%mm2, %%mm0 \n\t" /* -6b + 3c - d */\
+ "movq %%mm5, %%mm2 \n\t" /* JKLMNOPQ */\
+ "punpcklbw %%mm7, %%mm2 \n\t" /* 0J0K0L0M */\
+ "punpckhbw %%mm7, %%mm5 \n\t" /* 0N0O0P0Q */\
+ "paddw %%mm2, %%mm6 \n\t" /* a */\
+ "pmullw "MANGLE(ff_pw_20)", %%mm6 \n\t" /* 20a */\
+ "paddw %6, %%mm0 \n\t"\
+ "paddw %%mm6, %%mm0 \n\t" /* 20a - 6b + 3c - d */\
+ "psraw $5, %%mm0 \n\t"\
+ /* mm1=KLMN, mm2=JKLM, mm3=MNOP, mm4=LMNO, mm5=NOPQ mm7=0 */\
+ \
+ "paddw %%mm5, %%mm3 \n\t" /* a */\
+ "pshufw $0xF9, %%mm5, %%mm6 \n\t" /* 0O0P0Q0Q */\
+ "paddw %%mm4, %%mm6 \n\t" /* b */\
+ "pshufw $0xBE, %%mm5, %%mm4 \n\t" /* 0P0Q0Q0P */\
+ "pshufw $0x6F, %%mm5, %%mm5 \n\t" /* 0Q0Q0P0O */\
+ "paddw %%mm1, %%mm4 \n\t" /* c */\
+ "paddw %%mm2, %%mm5 \n\t" /* d */\
+ "paddw %%mm6, %%mm6 \n\t" /* 2b */\
+ "psubw %%mm6, %%mm4 \n\t" /* c - 2b */\
+ "pmullw "MANGLE(ff_pw_20)", %%mm3 \n\t" /* 20a */\
+ "pmullw "MANGLE(ff_pw_3)", %%mm4 \n\t" /* 3c - 6b */\
+ "psubw %%mm5, %%mm3 \n\t" /* -6b + 3c - d */\
+ "paddw %6, %%mm4 \n\t"\
+ "paddw %%mm3, %%mm4 \n\t" /* 20a - 6b + 3c - d */\
+ "psraw $5, %%mm4 \n\t"\
+ "packuswb %%mm4, %%mm0 \n\t"\
+ OP_MMX2(%%mm0, 8(%1), %%mm4, 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"((long)srcStride), "S"((long)dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(temp), "m"(ROUNDER)\
+ : "memory"\
+ );\
+}\
+\
+static void OPNAME ## mpeg4_qpel16_h_lowpass_3dnow(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\
+ int i;\
+ int16_t temp[16];\
+ /* quick HACK, XXX FIXME MUST be optimized */\
+ for(i=0; i<h; i++)\
+ {\
+ temp[ 0]= (src[ 0]+src[ 1])*20 - (src[ 0]+src[ 2])*6 + (src[ 1]+src[ 3])*3 - (src[ 2]+src[ 4]);\
+ temp[ 1]= (src[ 1]+src[ 2])*20 - (src[ 0]+src[ 3])*6 + (src[ 0]+src[ 4])*3 - (src[ 1]+src[ 5]);\
+ temp[ 2]= (src[ 2]+src[ 3])*20 - (src[ 1]+src[ 4])*6 + (src[ 0]+src[ 5])*3 - (src[ 0]+src[ 6]);\
+ temp[ 3]= (src[ 3]+src[ 4])*20 - (src[ 2]+src[ 5])*6 + (src[ 1]+src[ 6])*3 - (src[ 0]+src[ 7]);\
+ temp[ 4]= (src[ 4]+src[ 5])*20 - (src[ 3]+src[ 6])*6 + (src[ 2]+src[ 7])*3 - (src[ 1]+src[ 8]);\
+ temp[ 5]= (src[ 5]+src[ 6])*20 - (src[ 4]+src[ 7])*6 + (src[ 3]+src[ 8])*3 - (src[ 2]+src[ 9]);\
+ temp[ 6]= (src[ 6]+src[ 7])*20 - (src[ 5]+src[ 8])*6 + (src[ 4]+src[ 9])*3 - (src[ 3]+src[10]);\
+ temp[ 7]= (src[ 7]+src[ 8])*20 - (src[ 6]+src[ 9])*6 + (src[ 5]+src[10])*3 - (src[ 4]+src[11]);\
+ temp[ 8]= (src[ 8]+src[ 9])*20 - (src[ 7]+src[10])*6 + (src[ 6]+src[11])*3 - (src[ 5]+src[12]);\
+ temp[ 9]= (src[ 9]+src[10])*20 - (src[ 8]+src[11])*6 + (src[ 7]+src[12])*3 - (src[ 6]+src[13]);\
+ temp[10]= (src[10]+src[11])*20 - (src[ 9]+src[12])*6 + (src[ 8]+src[13])*3 - (src[ 7]+src[14]);\
+ temp[11]= (src[11]+src[12])*20 - (src[10]+src[13])*6 + (src[ 9]+src[14])*3 - (src[ 8]+src[15]);\
+ temp[12]= (src[12]+src[13])*20 - (src[11]+src[14])*6 + (src[10]+src[15])*3 - (src[ 9]+src[16]);\
+ temp[13]= (src[13]+src[14])*20 - (src[12]+src[15])*6 + (src[11]+src[16])*3 - (src[10]+src[16]);\
+ temp[14]= (src[14]+src[15])*20 - (src[13]+src[16])*6 + (src[12]+src[16])*3 - (src[11]+src[15]);\
+ temp[15]= (src[15]+src[16])*20 - (src[14]+src[16])*6 + (src[13]+src[15])*3 - (src[12]+src[14]);\
+ asm volatile(\
+ "movq (%0), %%mm0 \n\t"\
+ "movq 8(%0), %%mm1 \n\t"\
+ "paddw %2, %%mm0 \n\t"\
+ "paddw %2, %%mm1 \n\t"\
+ "psraw $5, %%mm0 \n\t"\
+ "psraw $5, %%mm1 \n\t"\
+ "packuswb %%mm1, %%mm0 \n\t"\
+ OP_3DNOW(%%mm0, (%1), %%mm1, q)\
+ "movq 16(%0), %%mm0 \n\t"\
+ "movq 24(%0), %%mm1 \n\t"\
+ "paddw %2, %%mm0 \n\t"\
+ "paddw %2, %%mm1 \n\t"\
+ "psraw $5, %%mm0 \n\t"\
+ "psraw $5, %%mm1 \n\t"\
+ "packuswb %%mm1, %%mm0 \n\t"\
+ OP_3DNOW(%%mm0, 8(%1), %%mm1, q)\
+ :: "r"(temp), "r"(dst), "m"(ROUNDER)\
+ : "memory"\
+ );\
+ dst+=dstStride;\
+ src+=srcStride;\
+ }\
+}\
+\
+static void OPNAME ## mpeg4_qpel8_h_lowpass_mmx2(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\
+ uint64_t temp;\
+\
+ asm volatile(\
+ "pxor %%mm7, %%mm7 \n\t"\
+ "1: \n\t"\
+ "movq (%0), %%mm0 \n\t" /* ABCDEFGH */\
+ "movq %%mm0, %%mm1 \n\t" /* ABCDEFGH */\
+ "movq %%mm0, %%mm2 \n\t" /* ABCDEFGH */\
+ "punpcklbw %%mm7, %%mm0 \n\t" /* 0A0B0C0D */\
+ "punpckhbw %%mm7, %%mm1 \n\t" /* 0E0F0G0H */\
+ "pshufw $0x90, %%mm0, %%mm5 \n\t" /* 0A0A0B0C */\
+ "pshufw $0x41, %%mm0, %%mm6 \n\t" /* 0B0A0A0B */\
+ "movq %%mm2, %%mm3 \n\t" /* ABCDEFGH */\
+ "movq %%mm2, %%mm4 \n\t" /* ABCDEFGH */\
+ "psllq $8, %%mm2 \n\t" /* 0ABCDEFG */\
+ "psllq $16, %%mm3 \n\t" /* 00ABCDEF */\
+ "psllq $24, %%mm4 \n\t" /* 000ABCDE */\
+ "punpckhbw %%mm7, %%mm2 \n\t" /* 0D0E0F0G */\
+ "punpckhbw %%mm7, %%mm3 \n\t" /* 0C0D0E0F */\
+ "punpckhbw %%mm7, %%mm4 \n\t" /* 0B0C0D0E */\
+ "paddw %%mm3, %%mm5 \n\t" /* b */\
+ "paddw %%mm2, %%mm6 \n\t" /* c */\
+ "paddw %%mm5, %%mm5 \n\t" /* 2b */\
+ "psubw %%mm5, %%mm6 \n\t" /* c - 2b */\
+ "pshufw $0x06, %%mm0, %%mm5 \n\t" /* 0C0B0A0A */\
+ "pmullw "MANGLE(ff_pw_3)", %%mm6 \n\t" /* 3c - 6b */\
+ "paddw %%mm4, %%mm0 \n\t" /* a */\
+ "paddw %%mm1, %%mm5 \n\t" /* d */\
+ "pmullw "MANGLE(ff_pw_20)", %%mm0 \n\t" /* 20a */\
+ "psubw %%mm5, %%mm0 \n\t" /* 20a - d */\
+ "paddw %6, %%mm6 \n\t"\
+ "paddw %%mm6, %%mm0 \n\t" /* 20a - 6b + 3c - d */\
+ "psraw $5, %%mm0 \n\t"\
+ /* mm1=EFGH, mm2=DEFG, mm3=CDEF, mm4=BCDE, mm7=0 */\
+ \
+ "movd 5(%0), %%mm5 \n\t" /* FGHI */\
+ "punpcklbw %%mm7, %%mm5 \n\t" /* 0F0G0H0I */\
+ "pshufw $0xF9, %%mm5, %%mm6 \n\t" /* 0G0H0I0I */\
+ "paddw %%mm5, %%mm1 \n\t" /* a */\
+ "paddw %%mm6, %%mm2 \n\t" /* b */\
+ "pshufw $0xBE, %%mm5, %%mm6 \n\t" /* 0H0I0I0H */\
+ "pshufw $0x6F, %%mm5, %%mm5 \n\t" /* 0I0I0H0G */\
+ "paddw %%mm6, %%mm3 \n\t" /* c */\
+ "paddw %%mm5, %%mm4 \n\t" /* d */\
+ "paddw %%mm2, %%mm2 \n\t" /* 2b */\
+ "psubw %%mm2, %%mm3 \n\t" /* c - 2b */\
+ "pmullw "MANGLE(ff_pw_20)", %%mm1 \n\t" /* 20a */\
+ "pmullw "MANGLE(ff_pw_3)", %%mm3 \n\t" /* 3c - 6b */\
+ "psubw %%mm4, %%mm3 \n\t" /* -6b + 3c - d */\
+ "paddw %6, %%mm1 \n\t"\
+ "paddw %%mm1, %%mm3 \n\t" /* 20a - 6b + 3c - d */\
+ "psraw $5, %%mm3 \n\t"\
+ "packuswb %%mm3, %%mm0 \n\t"\
+ OP_MMX2(%%mm0, (%1), %%mm4, 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)\
+ : "S"((long)srcStride), "D"((long)dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(temp), "m"(ROUNDER)\
+ : "memory"\
+ );\
+}\
+\
+static void OPNAME ## mpeg4_qpel8_h_lowpass_3dnow(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\
+ int i;\
+ int16_t temp[8];\
+ /* quick HACK, XXX FIXME MUST be optimized */\
+ for(i=0; i<h; i++)\
+ {\
+ temp[ 0]= (src[ 0]+src[ 1])*20 - (src[ 0]+src[ 2])*6 + (src[ 1]+src[ 3])*3 - (src[ 2]+src[ 4]);\
+ temp[ 1]= (src[ 1]+src[ 2])*20 - (src[ 0]+src[ 3])*6 + (src[ 0]+src[ 4])*3 - (src[ 1]+src[ 5]);\
+ temp[ 2]= (src[ 2]+src[ 3])*20 - (src[ 1]+src[ 4])*6 + (src[ 0]+src[ 5])*3 - (src[ 0]+src[ 6]);\
+ temp[ 3]= (src[ 3]+src[ 4])*20 - (src[ 2]+src[ 5])*6 + (src[ 1]+src[ 6])*3 - (src[ 0]+src[ 7]);\
+ temp[ 4]= (src[ 4]+src[ 5])*20 - (src[ 3]+src[ 6])*6 + (src[ 2]+src[ 7])*3 - (src[ 1]+src[ 8]);\
+ temp[ 5]= (src[ 5]+src[ 6])*20 - (src[ 4]+src[ 7])*6 + (src[ 3]+src[ 8])*3 - (src[ 2]+src[ 8]);\
+ temp[ 6]= (src[ 6]+src[ 7])*20 - (src[ 5]+src[ 8])*6 + (src[ 4]+src[ 8])*3 - (src[ 3]+src[ 7]);\
+ temp[ 7]= (src[ 7]+src[ 8])*20 - (src[ 6]+src[ 8])*6 + (src[ 5]+src[ 7])*3 - (src[ 4]+src[ 6]);\
+ asm volatile(\
+ "movq (%0), %%mm0 \n\t"\
+ "movq 8(%0), %%mm1 \n\t"\
+ "paddw %2, %%mm0 \n\t"\
+ "paddw %2, %%mm1 \n\t"\
+ "psraw $5, %%mm0 \n\t"\
+ "psraw $5, %%mm1 \n\t"\
+ "packuswb %%mm1, %%mm0 \n\t"\
+ OP_3DNOW(%%mm0, (%1), %%mm1, q)\
+ :: "r"(temp), "r"(dst), "m"(ROUNDER)\
+ :"memory"\
+ );\
+ dst+=dstStride;\
+ src+=srcStride;\
+ }\
+}
+
+#define QPEL_OP(OPNAME, ROUNDER, RND, OP, MMX)\
+\
+static void OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ uint64_t temp[17*4];\
+ uint64_t *temp_ptr= temp;\
+ int count= 17;\
+\
+ /*FIXME unroll */\
+ asm volatile(\
+ "pxor %%mm7, %%mm7 \n\t"\
+ "1: \n\t"\
+ "movq (%0), %%mm0 \n\t"\
+ "movq (%0), %%mm1 \n\t"\
+ "movq 8(%0), %%mm2 \n\t"\
+ "movq 8(%0), %%mm3 \n\t"\
+ "punpcklbw %%mm7, %%mm0 \n\t"\
+ "punpckhbw %%mm7, %%mm1 \n\t"\
+ "punpcklbw %%mm7, %%mm2 \n\t"\
+ "punpckhbw %%mm7, %%mm3 \n\t"\
+ "movq %%mm0, (%1) \n\t"\
+ "movq %%mm1, 17*8(%1) \n\t"\
+ "movq %%mm2, 2*17*8(%1) \n\t"\
+ "movq %%mm3, 3*17*8(%1) \n\t"\
+ "add $8, %1 \n\t"\
+ "add %3, %0 \n\t"\
+ "decl %2 \n\t"\
+ " jnz 1b \n\t"\
+ : "+r" (src), "+r" (temp_ptr), "+r"(count)\
+ : "r" ((long)srcStride)\
+ : "memory"\
+ );\
+ \
+ temp_ptr= temp;\
+ count=4;\
+ \
+/*FIXME reorder for speed */\
+ asm volatile(\
+ /*"pxor %%mm7, %%mm7 \n\t"*/\
+ "1: \n\t"\
+ "movq (%0), %%mm0 \n\t"\
+ "movq 8(%0), %%mm1 \n\t"\
+ "movq 16(%0), %%mm2 \n\t"\
+ "movq 24(%0), %%mm3 \n\t"\
+ QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 16(%0), 8(%0), (%0), 32(%0), (%1), OP)\
+ QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 8(%0), (%0), (%0), 40(%0), (%1, %3), OP)\
+ "add %4, %1 \n\t"\
+ QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, (%0), (%0), 8(%0), 48(%0), (%1), OP)\
+ \
+ QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, (%0), 8(%0), 16(%0), 56(%0), (%1, %3), OP)\
+ "add %4, %1 \n\t"\
+ QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 8(%0), 16(%0), 24(%0), 64(%0), (%1), OP)\
+ QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 16(%0), 24(%0), 32(%0), 72(%0), (%1, %3), OP)\
+ "add %4, %1 \n\t"\
+ QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 24(%0), 32(%0), 40(%0), 80(%0), (%1), OP)\
+ QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 32(%0), 40(%0), 48(%0), 88(%0), (%1, %3), OP)\
+ "add %4, %1 \n\t"\
+ QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 40(%0), 48(%0), 56(%0), 96(%0), (%1), OP)\
+ QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 48(%0), 56(%0), 64(%0),104(%0), (%1, %3), OP)\
+ "add %4, %1 \n\t"\
+ QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 56(%0), 64(%0), 72(%0),112(%0), (%1), OP)\
+ QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 64(%0), 72(%0), 80(%0),120(%0), (%1, %3), OP)\
+ "add %4, %1 \n\t"\
+ QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 72(%0), 80(%0), 88(%0),128(%0), (%1), OP)\
+ \
+ QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 80(%0), 88(%0), 96(%0),128(%0), (%1, %3), OP)\
+ "add %4, %1 \n\t" \
+ QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 88(%0), 96(%0),104(%0),120(%0), (%1), OP)\
+ QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 96(%0),104(%0),112(%0),112(%0), (%1, %3), OP)\
+ \
+ "add $136, %0 \n\t"\
+ "add %6, %1 \n\t"\
+ "decl %2 \n\t"\
+ " jnz 1b \n\t"\
+ \
+ : "+r"(temp_ptr), "+r"(dst), "+g"(count)\
+ : "r"((long)dstStride), "r"(2*(long)dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(ROUNDER), "g"(4-14*(long)dstStride)\
+ :"memory"\
+ );\
+}\
+\
+static void OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ uint64_t temp[9*2];\
+ uint64_t *temp_ptr= temp;\
+ int count= 9;\
+\
+ /*FIXME unroll */\
+ asm volatile(\
+ "pxor %%mm7, %%mm7 \n\t"\
+ "1: \n\t"\
+ "movq (%0), %%mm0 \n\t"\
+ "movq (%0), %%mm1 \n\t"\
+ "punpcklbw %%mm7, %%mm0 \n\t"\
+ "punpckhbw %%mm7, %%mm1 \n\t"\
+ "movq %%mm0, (%1) \n\t"\
+ "movq %%mm1, 9*8(%1) \n\t"\
+ "add $8, %1 \n\t"\
+ "add %3, %0 \n\t"\
+ "decl %2 \n\t"\
+ " jnz 1b \n\t"\
+ : "+r" (src), "+r" (temp_ptr), "+r"(count)\
+ : "r" ((long)srcStride)\
+ : "memory"\
+ );\
+ \
+ temp_ptr= temp;\
+ count=2;\
+ \
+/*FIXME reorder for speed */\
+ asm volatile(\
+ /*"pxor %%mm7, %%mm7 \n\t"*/\
+ "1: \n\t"\
+ "movq (%0), %%mm0 \n\t"\
+ "movq 8(%0), %%mm1 \n\t"\
+ "movq 16(%0), %%mm2 \n\t"\
+ "movq 24(%0), %%mm3 \n\t"\
+ QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 16(%0), 8(%0), (%0), 32(%0), (%1), OP)\
+ QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 8(%0), (%0), (%0), 40(%0), (%1, %3), OP)\
+ "add %4, %1 \n\t"\
+ QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, (%0), (%0), 8(%0), 48(%0), (%1), OP)\
+ \
+ QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, (%0), 8(%0), 16(%0), 56(%0), (%1, %3), OP)\
+ "add %4, %1 \n\t"\
+ QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 8(%0), 16(%0), 24(%0), 64(%0), (%1), OP)\
+ \
+ QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 16(%0), 24(%0), 32(%0), 64(%0), (%1, %3), OP)\
+ "add %4, %1 \n\t"\
+ QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 24(%0), 32(%0), 40(%0), 56(%0), (%1), OP)\
+ QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 32(%0), 40(%0), 48(%0), 48(%0), (%1, %3), OP)\
+ \
+ "add $72, %0 \n\t"\
+ "add %6, %1 \n\t"\
+ "decl %2 \n\t"\
+ " jnz 1b \n\t"\
+ \
+ : "+r"(temp_ptr), "+r"(dst), "+g"(count)\
+ : "r"((long)dstStride), "r"(2*(long)dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(ROUNDER), "g"(4-6*(long)dstStride)\
+ : "memory"\
+ );\
+}\
+\
+static void OPNAME ## qpel8_mc00_ ## MMX (uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## pixels8_mmx(dst, src, stride, 8);\
+}\
+\
+static void OPNAME ## qpel8_mc10_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t temp[8];\
+ uint8_t * const half= (uint8_t*)temp;\
+ put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, stride, 8);\
+ OPNAME ## pixels8_l2_ ## MMX(dst, src, half, stride, stride, 8);\
+}\
+\
+static void OPNAME ## qpel8_mc20_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## mpeg4_qpel8_h_lowpass_ ## MMX(dst, src, stride, stride, 8);\
+}\
+\
+static void OPNAME ## qpel8_mc30_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t temp[8];\
+ uint8_t * const half= (uint8_t*)temp;\
+ put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, stride, 8);\
+ OPNAME ## pixels8_l2_ ## MMX(dst, src+1, half, stride, stride, 8);\
+}\
+\
+static void OPNAME ## qpel8_mc01_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t temp[8];\
+ uint8_t * const half= (uint8_t*)temp;\
+ put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, 8, stride);\
+ OPNAME ## pixels8_l2_ ## MMX(dst, src, half, stride, stride, 8);\
+}\
+\
+static void OPNAME ## qpel8_mc02_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, src, stride, stride);\
+}\
+\
+static void OPNAME ## qpel8_mc03_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t temp[8];\
+ uint8_t * const half= (uint8_t*)temp;\
+ put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, 8, stride);\
+ OPNAME ## pixels8_l2_ ## MMX(dst, src+stride, half, stride, stride, 8);\
+}\
+static void OPNAME ## qpel8_mc11_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[8 + 9];\
+ uint8_t * const halfH= ((uint8_t*)half) + 64;\
+ uint8_t * const halfHV= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
+ put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, stride, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, stride, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc31_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[8 + 9];\
+ uint8_t * const halfH= ((uint8_t*)half) + 64;\
+ uint8_t * const halfHV= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
+ put ## RND ## pixels8_l2_ ## MMX(halfH, src+1, halfH, 8, stride, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, stride, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc13_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[8 + 9];\
+ uint8_t * const halfH= ((uint8_t*)half) + 64;\
+ uint8_t * const halfHV= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
+ put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, stride, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l2_ ## MMX(dst, halfH+8, halfHV, stride, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc33_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[8 + 9];\
+ uint8_t * const halfH= ((uint8_t*)half) + 64;\
+ uint8_t * const halfHV= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
+ put ## RND ## pixels8_l2_ ## MMX(halfH, src+1, halfH, 8, stride, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l2_ ## MMX(dst, halfH+8, halfHV, stride, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc21_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[8 + 9];\
+ uint8_t * const halfH= ((uint8_t*)half) + 64;\
+ uint8_t * const halfHV= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, stride, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc23_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[8 + 9];\
+ uint8_t * const halfH= ((uint8_t*)half) + 64;\
+ uint8_t * const halfHV= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l2_ ## MMX(dst, halfH+8, halfHV, stride, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc12_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[8 + 9];\
+ uint8_t * const halfH= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
+ put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, stride, 9);\
+ OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);\
+}\
+static void OPNAME ## qpel8_mc32_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[8 + 9];\
+ uint8_t * const halfH= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
+ put ## RND ## pixels8_l2_ ## MMX(halfH, src+1, halfH, 8, stride, 9);\
+ OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);\
+}\
+static void OPNAME ## qpel8_mc22_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[9];\
+ uint8_t * const halfH= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
+ OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);\
+}\
+static void OPNAME ## qpel16_mc00_ ## MMX (uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## pixels16_mmx(dst, src, stride, 16);\
+}\
+\
+static void OPNAME ## qpel16_mc10_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t temp[32];\
+ uint8_t * const half= (uint8_t*)temp;\
+ put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, stride, 16);\
+ OPNAME ## pixels16_l2_ ## MMX(dst, src, half, stride, stride, 16);\
+}\
+\
+static void OPNAME ## qpel16_mc20_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## mpeg4_qpel16_h_lowpass_ ## MMX(dst, src, stride, stride, 16);\
+}\
+\
+static void OPNAME ## qpel16_mc30_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t temp[32];\
+ uint8_t * const half= (uint8_t*)temp;\
+ put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, stride, 16);\
+ OPNAME ## pixels16_l2_ ## MMX(dst, src+1, half, stride, stride, 16);\
+}\
+\
+static void OPNAME ## qpel16_mc01_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t temp[32];\
+ uint8_t * const half= (uint8_t*)temp;\
+ put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, stride);\
+ OPNAME ## pixels16_l2_ ## MMX(dst, src, half, stride, stride, 16);\
+}\
+\
+static void OPNAME ## qpel16_mc02_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, src, stride, stride);\
+}\
+\
+static void OPNAME ## qpel16_mc03_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t temp[32];\
+ uint8_t * const half= (uint8_t*)temp;\
+ put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, stride);\
+ OPNAME ## pixels16_l2_ ## MMX(dst, src+stride, half, stride, stride, 16);\
+}\
+static void OPNAME ## qpel16_mc11_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[16*2 + 17*2];\
+ uint8_t * const halfH= ((uint8_t*)half) + 256;\
+ uint8_t * const halfHV= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
+ put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, stride, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, stride, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc31_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[16*2 + 17*2];\
+ uint8_t * const halfH= ((uint8_t*)half) + 256;\
+ uint8_t * const halfHV= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
+ put ## RND ## pixels16_l2_ ## MMX(halfH, src+1, halfH, 16, stride, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, stride, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc13_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[16*2 + 17*2];\
+ uint8_t * const halfH= ((uint8_t*)half) + 256;\
+ uint8_t * const halfHV= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
+ put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, stride, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l2_ ## MMX(dst, halfH+16, halfHV, stride, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc33_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[16*2 + 17*2];\
+ uint8_t * const halfH= ((uint8_t*)half) + 256;\
+ uint8_t * const halfHV= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
+ put ## RND ## pixels16_l2_ ## MMX(halfH, src+1, halfH, 16, stride, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l2_ ## MMX(dst, halfH+16, halfHV, stride, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc21_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[16*2 + 17*2];\
+ uint8_t * const halfH= ((uint8_t*)half) + 256;\
+ uint8_t * const halfHV= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, stride, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc23_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[16*2 + 17*2];\
+ uint8_t * const halfH= ((uint8_t*)half) + 256;\
+ uint8_t * const halfHV= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l2_ ## MMX(dst, halfH+16, halfHV, stride, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc12_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[17*2];\
+ uint8_t * const halfH= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
+ put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, stride, 17);\
+ OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);\
+}\
+static void OPNAME ## qpel16_mc32_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[17*2];\
+ uint8_t * const halfH= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
+ put ## RND ## pixels16_l2_ ## MMX(halfH, src+1, halfH, 16, stride, 17);\
+ OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);\
+}\
+static void OPNAME ## qpel16_mc22_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t half[17*2];\
+ uint8_t * const halfH= ((uint8_t*)half);\
+ put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
+ OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);\
+}
+
+#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_MMX2_OP(a,b,temp, size) \
+"mov" #size " " #b ", " #temp " \n\t"\
+"pavgb " #temp ", " #a " \n\t"\
+"mov" #size " " #a ", " #b " \n\t"
+
+QPEL_BASE(put_ , ff_pw_16, _ , PUT_OP, PUT_OP)
+QPEL_BASE(avg_ , ff_pw_16, _ , AVG_MMX2_OP, AVG_3DNOW_OP)
+QPEL_BASE(put_no_rnd_, ff_pw_15, _no_rnd_, PUT_OP, PUT_OP)
+QPEL_OP(put_ , ff_pw_16, _ , PUT_OP, 3dnow)
+QPEL_OP(avg_ , ff_pw_16, _ , AVG_3DNOW_OP, 3dnow)
+QPEL_OP(put_no_rnd_, ff_pw_15, _no_rnd_, PUT_OP, 3dnow)
+QPEL_OP(put_ , ff_pw_16, _ , PUT_OP, mmx2)
+QPEL_OP(avg_ , ff_pw_16, _ , AVG_MMX2_OP, mmx2)
+QPEL_OP(put_no_rnd_, ff_pw_15, _no_rnd_, PUT_OP, mmx2)
+
+/***********************************/
+/* bilinear qpel: not compliant to any spec, only for -lavdopts fast */
+
+#define QPEL_2TAP_XY(OPNAME, SIZE, MMX, XY, HPEL)\
+static void OPNAME ## 2tap_qpel ## SIZE ## _mc ## XY ## _ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## pixels ## SIZE ## HPEL(dst, src, stride, SIZE);\
+}
+#define QPEL_2TAP_L3(OPNAME, SIZE, MMX, XY, S0, S1, S2)\
+static void OPNAME ## 2tap_qpel ## SIZE ## _mc ## XY ## _ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## 2tap_qpel ## SIZE ## _l3_ ## MMX(dst, src+S0, stride, SIZE, S1, S2);\
+}
+
+#define QPEL_2TAP(OPNAME, SIZE, MMX)\
+QPEL_2TAP_XY(OPNAME, SIZE, MMX, 20, _x2_ ## MMX)\
+QPEL_2TAP_XY(OPNAME, SIZE, MMX, 02, _y2_ ## MMX)\
+QPEL_2TAP_XY(OPNAME, SIZE, MMX, 22, _xy2_mmx)\
+static const qpel_mc_func OPNAME ## 2tap_qpel ## SIZE ## _mc00_ ## MMX =\
+ OPNAME ## qpel ## SIZE ## _mc00_ ## MMX;\
+static const qpel_mc_func OPNAME ## 2tap_qpel ## SIZE ## _mc21_ ## MMX =\
+ OPNAME ## 2tap_qpel ## SIZE ## _mc20_ ## MMX;\
+static const qpel_mc_func OPNAME ## 2tap_qpel ## SIZE ## _mc12_ ## MMX =\
+ OPNAME ## 2tap_qpel ## SIZE ## _mc02_ ## MMX;\
+static void OPNAME ## 2tap_qpel ## SIZE ## _mc32_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## pixels ## SIZE ## _y2_ ## MMX(dst, src+1, stride, SIZE);\
+}\
+static void OPNAME ## 2tap_qpel ## SIZE ## _mc23_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## pixels ## SIZE ## _x2_ ## MMX(dst, src+stride, stride, SIZE);\
+}\
+QPEL_2TAP_L3(OPNAME, SIZE, MMX, 10, 0, 1, 0)\
+QPEL_2TAP_L3(OPNAME, SIZE, MMX, 30, 1, -1, 0)\
+QPEL_2TAP_L3(OPNAME, SIZE, MMX, 01, 0, stride, 0)\
+QPEL_2TAP_L3(OPNAME, SIZE, MMX, 03, stride, -stride, 0)\
+QPEL_2TAP_L3(OPNAME, SIZE, MMX, 11, 0, stride, 1)\
+QPEL_2TAP_L3(OPNAME, SIZE, MMX, 31, 1, stride, -1)\
+QPEL_2TAP_L3(OPNAME, SIZE, MMX, 13, stride, -stride, 1)\
+QPEL_2TAP_L3(OPNAME, SIZE, MMX, 33, stride+1, -stride, -1)\
+
+QPEL_2TAP(put_, 16, mmx2)
+QPEL_2TAP(avg_, 16, mmx2)
+QPEL_2TAP(put_, 8, mmx2)
+QPEL_2TAP(avg_, 8, mmx2)
+QPEL_2TAP(put_, 16, 3dnow)
+QPEL_2TAP(avg_, 16, 3dnow)
+QPEL_2TAP(put_, 8, 3dnow)
+QPEL_2TAP(avg_, 8, 3dnow)
+
+
+#if 0
+static void just_return() { return; }
+#endif
+
+#define SET_QPEL_FUNC(postfix1, postfix2) \
+ c->put_ ## postfix1 = put_ ## postfix2;\
+ c->put_no_rnd_ ## postfix1 = put_no_rnd_ ## postfix2;\
+ c->avg_ ## postfix1 = avg_ ## postfix2;
+
+static void gmc_mmx(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){
+ 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;
+ uint8_t edge_buf[(h+1)*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);
+ 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 )
+ {
+ //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( (unsigned)ix >= width-w ||
+ (unsigned)iy >= height-h )
+ {
+ ff_emulated_edge_mc(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<<shift)
+ );
+
+ for(x=0; x<w; x+=4){
+ uint16_t dx4[4] = { oxs - dxys + dxxs*(x+0),
+ oxs - dxys + dxxs*(x+1),
+ oxs - dxys + dxxs*(x+2),
+ oxs - dxys + dxxs*(x+3) };
+ uint16_t dy4[4] = { oys - dyys + dyxs*(x+0),
+ oys - dyys + dyxs*(x+1),
+ oys - dyys + dyxs*(x+2),
+ oys - dyys + dyxs*(x+3) };
+
+ for(y=0; y<h; y++){
+ asm volatile(
+ "movq %0, %%mm4 \n\t"
+ "movq %1, %%mm5 \n\t"
+ "paddw %2, %%mm4 \n\t"
+ "paddw %3, %%mm5 \n\t"
+ "movq %%mm4, %0 \n\t"
+ "movq %%mm5, %1 \n\t"
+ "psrlw $12, %%mm4 \n\t"
+ "psrlw $12, %%mm5 \n\t"
+ : "+m"(*dx4), "+m"(*dy4)
+ : "m"(*dxy4), "m"(*dyy4)
+ );
+
+ asm volatile(
+ "movq %%mm6, %%mm2 \n\t"
+ "movq %%mm6, %%mm1 \n\t"
+ "psubw %%mm4, %%mm2 \n\t"
+ "psubw %%mm5, %%mm1 \n\t"
+ "movq %%mm2, %%mm0 \n\t"
+ "movq %%mm4, %%mm3 \n\t"
+ "pmullw %%mm1, %%mm0 \n\t" // (s-dx)*(s-dy)
+ "pmullw %%mm5, %%mm3 \n\t" // dx*dy
+ "pmullw %%mm5, %%mm2 \n\t" // (s-dx)*dy
+ "pmullw %%mm4, %%mm1 \n\t" // dx*(s-dy)
+
+ "movd %4, %%mm5 \n\t"
+ "movd %3, %%mm4 \n\t"
+ "punpcklbw %%mm7, %%mm5 \n\t"
+ "punpcklbw %%mm7, %%mm4 \n\t"
+ "pmullw %%mm5, %%mm3 \n\t" // src[1,1] * dx*dy
+ "pmullw %%mm4, %%mm2 \n\t" // src[0,1] * (s-dx)*dy
+
+ "movd %2, %%mm5 \n\t"
+ "movd %1, %%mm4 \n\t"
+ "punpcklbw %%mm7, %%mm5 \n\t"
+ "punpcklbw %%mm7, %%mm4 \n\t"
+ "pmullw %%mm5, %%mm1 \n\t" // src[1,0] * dx*(s-dy)
+ "pmullw %%mm4, %%mm0 \n\t" // src[0,0] * (s-dx)*(s-dy)
+ "paddw %5, %%mm1 \n\t"
+ "paddw %%mm3, %%mm2 \n\t"
+ "paddw %%mm1, %%mm0 \n\t"
+ "paddw %%mm2, %%mm0 \n\t"
+
+ "psrlw %6, %%mm0 \n\t"
+ "packuswb %%mm0, %%mm0 \n\t"
+ "movd %%mm0, %0 \n\t"
+
+ : "=m"(dst[x+y*stride])
+ : "m"(src[0]), "m"(src[1]),
+ "m"(src[stride]), "m"(src[stride+1]),
+ "m"(*r4), "m"(shift2)
+ );
+ src += stride;
+ }
+ src += 4-h*stride;
+ }
+}
+
+#ifdef CONFIG_ENCODERS
+static int try_8x8basis_mmx(int16_t rem[64], int16_t weight[64], int16_t basis[64], int scale){
+ long i=0;
+
+ assert(FFABS(scale) < 256);
+ scale<<= 16 + 1 - BASIS_SHIFT + RECON_SHIFT;
+
+ asm volatile(
+ "pcmpeqw %%mm6, %%mm6 \n\t" // -1w
+ "psrlw $15, %%mm6 \n\t" // 1w
+ "pxor %%mm7, %%mm7 \n\t"
+ "movd %4, %%mm5 \n\t"
+ "punpcklwd %%mm5, %%mm5 \n\t"
+ "punpcklwd %%mm5, %%mm5 \n\t"
+ "1: \n\t"
+ "movq (%1, %0), %%mm0 \n\t"
+ "movq 8(%1, %0), %%mm1 \n\t"
+ "pmulhw %%mm5, %%mm0 \n\t"
+ "pmulhw %%mm5, %%mm1 \n\t"
+ "paddw %%mm6, %%mm0 \n\t"
+ "paddw %%mm6, %%mm1 \n\t"
+ "psraw $1, %%mm0 \n\t"
+ "psraw $1, %%mm1 \n\t"
+ "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"
+ "movq %%mm7, %%mm6 \n\t"
+ "psrlq $32, %%mm7 \n\t"
+ "paddd %%mm6, %%mm7 \n\t"
+ "psrld $2, %%mm7 \n\t"
+ "movd %%mm7, %0 \n\t"
+
+ : "+r" (i)
+ : "r"(basis), "r"(rem), "r"(weight), "g"(scale)
+ );
+ return i;
+}
+
+static void add_8x8basis_mmx(int16_t rem[64], int16_t basis[64], int scale){
+ long i=0;
+
+ if(FFABS(scale) < 256){
+ scale<<= 16 + 1 - BASIS_SHIFT + RECON_SHIFT;
+ asm volatile(
+ "pcmpeqw %%mm6, %%mm6 \n\t" // -1w
+ "psrlw $15, %%mm6 \n\t" // 1w
+ "movd %3, %%mm5 \n\t"
+ "punpcklwd %%mm5, %%mm5 \n\t"
+ "punpcklwd %%mm5, %%mm5 \n\t"
+ "1: \n\t"
+ "movq (%1, %0), %%mm0 \n\t"
+ "movq 8(%1, %0), %%mm1 \n\t"
+ "pmulhw %%mm5, %%mm0 \n\t"
+ "pmulhw %%mm5, %%mm1 \n\t"
+ "paddw %%mm6, %%mm0 \n\t"
+ "paddw %%mm6, %%mm1 \n\t"
+ "psraw $1, %%mm0 \n\t"
+ "psraw $1, %%mm1 \n\t"
+ "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);
+ }
+ }
+}
+#endif /* CONFIG_ENCODERS */
+
+#define PREFETCH(name, op) \
+static void name(void *mem, int stride, int h){\
+ const uint8_t *p= mem;\
+ do{\
+ asm volatile(#op" %0" :: "m"(*p));\
+ p+= stride;\
+ }while(--h);\
+}
+PREFETCH(prefetch_mmx2, prefetcht0)
+PREFETCH(prefetch_3dnow, prefetch)
+#undef PREFETCH
+
+#include "h264dsp_mmx.c"
+
+/* AVS specific */
+void ff_cavsdsp_init_mmx2(DSPContext* c, AVCodecContext *avctx);
+
+void ff_put_cavs_qpel8_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride) {
+ put_pixels8_mmx(dst, src, stride, 8);
+}
+void ff_avg_cavs_qpel8_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride) {
+ avg_pixels8_mmx(dst, src, stride, 8);
+}
+void ff_put_cavs_qpel16_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride) {
+ put_pixels16_mmx(dst, src, stride, 16);
+}
+void ff_avg_cavs_qpel16_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride) {
+ avg_pixels16_mmx(dst, src, stride, 16);
+}
+
+/* external functions, from idct_mmx.c */
+void ff_mmx_idct(DCTELEM *block);
+void ff_mmxext_idct(DCTELEM *block);
+
+void ff_vp3_idct_sse2(int16_t *input_data);
+void ff_vp3_idct_mmx(int16_t *data);
+void ff_vp3_dsp_init_mmx(void);
+
+/* XXX: those functions should be suppressed ASAP when all IDCTs are
+ converted */
+#ifdef CONFIG_GPL
+static void ff_libmpeg2mmx_idct_put(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ff_mmx_idct (block);
+ put_pixels_clamped_mmx(block, dest, line_size);
+}
+static void ff_libmpeg2mmx_idct_add(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ff_mmx_idct (block);
+ add_pixels_clamped_mmx(block, dest, line_size);
+}
+static void ff_libmpeg2mmx2_idct_put(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ff_mmxext_idct (block);
+ put_pixels_clamped_mmx(block, dest, line_size);
+}
+static void ff_libmpeg2mmx2_idct_add(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ff_mmxext_idct (block);
+ add_pixels_clamped_mmx(block, dest, line_size);
+}
+#endif
+static void ff_vp3_idct_put_sse2(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ff_vp3_idct_sse2(block);
+ put_signed_pixels_clamped_mmx(block, dest, line_size);
+}
+static void ff_vp3_idct_add_sse2(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ff_vp3_idct_sse2(block);
+ add_pixels_clamped_mmx(block, dest, line_size);
+}
+static void ff_vp3_idct_put_mmx(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ff_vp3_idct_mmx(block);
+ put_signed_pixels_clamped_mmx(block, dest, line_size);
+}
+static void ff_vp3_idct_add_mmx(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ff_vp3_idct_mmx(block);
+ add_pixels_clamped_mmx(block, dest, line_size);
+}
+static void ff_idct_xvid_mmx_put(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ff_idct_xvid_mmx (block);
+ put_pixels_clamped_mmx(block, dest, line_size);
+}
+static void ff_idct_xvid_mmx_add(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ff_idct_xvid_mmx (block);
+ add_pixels_clamped_mmx(block, dest, line_size);
+}
+static void ff_idct_xvid_mmx2_put(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ff_idct_xvid_mmx2 (block);
+ put_pixels_clamped_mmx(block, dest, line_size);
+}
+static void ff_idct_xvid_mmx2_add(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ff_idct_xvid_mmx2 (block);
+ add_pixels_clamped_mmx(block, dest, line_size);
+}
+
+static void vorbis_inverse_coupling_3dnow(float *mag, float *ang, int blocksize)
+{
+ int i;
+ asm volatile("pxor %%mm7, %%mm7":);
+ for(i=0; i<blocksize; i+=2) {
+ asm volatile(
+ "movq %0, %%mm0 \n\t"
+ "movq %1, %%mm1 \n\t"
+ "movq %%mm0, %%mm2 \n\t"
+ "movq %%mm1, %%mm3 \n\t"
+ "pfcmpge %%mm7, %%mm2 \n\t" // m <= 0.0
+ "pfcmpge %%mm7, %%mm3 \n\t" // a <= 0.0
+ "pslld $31, %%mm2 \n\t" // keep only the sign bit
+ "pxor %%mm2, %%mm1 \n\t"
+ "movq %%mm3, %%mm4 \n\t"
+ "pand %%mm1, %%mm3 \n\t"
+ "pandn %%mm1, %%mm4 \n\t"
+ "pfadd %%mm0, %%mm3 \n\t" // a = m + ((a<0) & (a ^ sign(m)))
+ "pfsub %%mm4, %%mm0 \n\t" // m = m + ((a>0) & (a ^ sign(m)))
+ "movq %%mm3, %1 \n\t"
+ "movq %%mm0, %0 \n\t"
+ :"+m"(mag[i]), "+m"(ang[i])
+ ::"memory"
+ );
+ }
+ asm volatile("femms");
+}
+static void vorbis_inverse_coupling_sse(float *mag, float *ang, int blocksize)
+{
+ int i;
+
+ asm volatile(
+ "movaps %0, %%xmm5 \n\t"
+ ::"m"(ff_pdw_80000000[0])
+ );
+ for(i=0; i<blocksize; i+=4) {
+ asm volatile(
+ "movaps %0, %%xmm0 \n\t"
+ "movaps %1, %%xmm1 \n\t"
+ "xorps %%xmm2, %%xmm2 \n\t"
+ "xorps %%xmm3, %%xmm3 \n\t"
+ "cmpleps %%xmm0, %%xmm2 \n\t" // m <= 0.0
+ "cmpleps %%xmm1, %%xmm3 \n\t" // a <= 0.0
+ "andps %%xmm5, %%xmm2 \n\t" // keep only the sign bit
+ "xorps %%xmm2, %%xmm1 \n\t"
+ "movaps %%xmm3, %%xmm4 \n\t"
+ "andps %%xmm1, %%xmm3 \n\t"
+ "andnps %%xmm1, %%xmm4 \n\t"
+ "addps %%xmm0, %%xmm3 \n\t" // a = m + ((a<0) & (a ^ sign(m)))
+ "subps %%xmm4, %%xmm0 \n\t" // m = m + ((a>0) & (a ^ sign(m)))
+ "movaps %%xmm3, %1 \n\t"
+ "movaps %%xmm0, %0 \n\t"
+ :"+m"(mag[i]), "+m"(ang[i])
+ ::"memory"
+ );
+ }
+}
+
+static void vector_fmul_3dnow(float *dst, const float *src, int len){
+ long i = (len-4)*4;
+ asm volatile(
+ "1: \n\t"
+ "movq (%1,%0), %%mm0 \n\t"
+ "movq 8(%1,%0), %%mm1 \n\t"
+ "pfmul (%2,%0), %%mm0 \n\t"
+ "pfmul 8(%2,%0), %%mm1 \n\t"
+ "movq %%mm0, (%1,%0) \n\t"
+ "movq %%mm1, 8(%1,%0) \n\t"
+ "sub $16, %0 \n\t"
+ "jge 1b \n\t"
+ "femms \n\t"
+ :"+r"(i)
+ :"r"(dst), "r"(src)
+ :"memory"
+ );
+}
+static void vector_fmul_sse(float *dst, const float *src, int len){
+ long i = (len-8)*4;
+ asm volatile(
+ "1: \n\t"
+ "movaps (%1,%0), %%xmm0 \n\t"
+ "movaps 16(%1,%0), %%xmm1 \n\t"
+ "mulps (%2,%0), %%xmm0 \n\t"
+ "mulps 16(%2,%0), %%xmm1 \n\t"
+ "movaps %%xmm0, (%1,%0) \n\t"
+ "movaps %%xmm1, 16(%1,%0) \n\t"
+ "sub $32, %0 \n\t"
+ "jge 1b \n\t"
+ :"+r"(i)
+ :"r"(dst), "r"(src)
+ :"memory"
+ );
+}
+
+static void vector_fmul_reverse_3dnow2(float *dst, const float *src0, const float *src1, int len){
+ long i = len*4-16;
+ asm volatile(
+ "1: \n\t"
+ "pswapd 8(%1), %%mm0 \n\t"
+ "pswapd (%1), %%mm1 \n\t"
+ "pfmul (%3,%0), %%mm0 \n\t"
+ "pfmul 8(%3,%0), %%mm1 \n\t"
+ "movq %%mm0, (%2,%0) \n\t"
+ "movq %%mm1, 8(%2,%0) \n\t"
+ "add $16, %1 \n\t"
+ "sub $16, %0 \n\t"
+ "jge 1b \n\t"
+ :"+r"(i), "+r"(src1)
+ :"r"(dst), "r"(src0)
+ );
+ asm volatile("femms");
+}
+static void vector_fmul_reverse_sse(float *dst, const float *src0, const float *src1, int len){
+ long i = len*4-32;
+ asm volatile(
+ "1: \n\t"
+ "movaps 16(%1), %%xmm0 \n\t"
+ "movaps (%1), %%xmm1 \n\t"
+ "shufps $0x1b, %%xmm0, %%xmm0 \n\t"
+ "shufps $0x1b, %%xmm1, %%xmm1 \n\t"
+ "mulps (%3,%0), %%xmm0 \n\t"
+ "mulps 16(%3,%0), %%xmm1 \n\t"
+ "movaps %%xmm0, (%2,%0) \n\t"
+ "movaps %%xmm1, 16(%2,%0) \n\t"
+ "add $32, %1 \n\t"
+ "sub $32, %0 \n\t"
+ "jge 1b \n\t"
+ :"+r"(i), "+r"(src1)
+ :"r"(dst), "r"(src0)
+ );
+}
+
+static void vector_fmul_add_add_3dnow(float *dst, const float *src0, const float *src1,
+ const float *src2, int src3, int len, int step){
+ long i = (len-4)*4;
+ if(step == 2 && src3 == 0){
+ dst += (len-4)*2;
+ asm volatile(
+ "1: \n\t"
+ "movq (%2,%0), %%mm0 \n\t"
+ "movq 8(%2,%0), %%mm1 \n\t"
+ "pfmul (%3,%0), %%mm0 \n\t"
+ "pfmul 8(%3,%0), %%mm1 \n\t"
+ "pfadd (%4,%0), %%mm0 \n\t"
+ "pfadd 8(%4,%0), %%mm1 \n\t"
+ "movd %%mm0, (%1) \n\t"
+ "movd %%mm1, 16(%1) \n\t"
+ "psrlq $32, %%mm0 \n\t"
+ "psrlq $32, %%mm1 \n\t"
+ "movd %%mm0, 8(%1) \n\t"
+ "movd %%mm1, 24(%1) \n\t"
+ "sub $32, %1 \n\t"
+ "sub $16, %0 \n\t"
+ "jge 1b \n\t"
+ :"+r"(i), "+r"(dst)
+ :"r"(src0), "r"(src1), "r"(src2)
+ :"memory"
+ );
+ }
+ else if(step == 1 && src3 == 0){
+ asm volatile(
+ "1: \n\t"
+ "movq (%2,%0), %%mm0 \n\t"
+ "movq 8(%2,%0), %%mm1 \n\t"
+ "pfmul (%3,%0), %%mm0 \n\t"
+ "pfmul 8(%3,%0), %%mm1 \n\t"
+ "pfadd (%4,%0), %%mm0 \n\t"
+ "pfadd 8(%4,%0), %%mm1 \n\t"
+ "movq %%mm0, (%1,%0) \n\t"
+ "movq %%mm1, 8(%1,%0) \n\t"
+ "sub $16, %0 \n\t"
+ "jge 1b \n\t"
+ :"+r"(i)
+ :"r"(dst), "r"(src0), "r"(src1), "r"(src2)
+ :"memory"
+ );
+ }
+ else
+ ff_vector_fmul_add_add_c(dst, src0, src1, src2, src3, len, step);
+ asm volatile("femms");
+}
+static void vector_fmul_add_add_sse(float *dst, const float *src0, const float *src1,
+ const float *src2, int src3, int len, int step){
+ long i = (len-8)*4;
+ if(step == 2 && src3 == 0){
+ dst += (len-8)*2;
+ asm volatile(
+ "1: \n\t"
+ "movaps (%2,%0), %%xmm0 \n\t"
+ "movaps 16(%2,%0), %%xmm1 \n\t"
+ "mulps (%3,%0), %%xmm0 \n\t"
+ "mulps 16(%3,%0), %%xmm1 \n\t"
+ "addps (%4,%0), %%xmm0 \n\t"
+ "addps 16(%4,%0), %%xmm1 \n\t"
+ "movss %%xmm0, (%1) \n\t"
+ "movss %%xmm1, 32(%1) \n\t"
+ "movhlps %%xmm0, %%xmm2 \n\t"
+ "movhlps %%xmm1, %%xmm3 \n\t"
+ "movss %%xmm2, 16(%1) \n\t"
+ "movss %%xmm3, 48(%1) \n\t"
+ "shufps $0xb1, %%xmm0, %%xmm0 \n\t"
+ "shufps $0xb1, %%xmm1, %%xmm1 \n\t"
+ "movss %%xmm0, 8(%1) \n\t"
+ "movss %%xmm1, 40(%1) \n\t"
+ "movhlps %%xmm0, %%xmm2 \n\t"
+ "movhlps %%xmm1, %%xmm3 \n\t"
+ "movss %%xmm2, 24(%1) \n\t"
+ "movss %%xmm3, 56(%1) \n\t"
+ "sub $64, %1 \n\t"
+ "sub $32, %0 \n\t"
+ "jge 1b \n\t"
+ :"+r"(i), "+r"(dst)
+ :"r"(src0), "r"(src1), "r"(src2)
+ :"memory"
+ );
+ }
+ else if(step == 1 && src3 == 0){
+ asm volatile(
+ "1: \n\t"
+ "movaps (%2,%0), %%xmm0 \n\t"
+ "movaps 16(%2,%0), %%xmm1 \n\t"
+ "mulps (%3,%0), %%xmm0 \n\t"
+ "mulps 16(%3,%0), %%xmm1 \n\t"
+ "addps (%4,%0), %%xmm0 \n\t"
+ "addps 16(%4,%0), %%xmm1 \n\t"
+ "movaps %%xmm0, (%1,%0) \n\t"
+ "movaps %%xmm1, 16(%1,%0) \n\t"
+ "sub $32, %0 \n\t"
+ "jge 1b \n\t"
+ :"+r"(i)
+ :"r"(dst), "r"(src0), "r"(src1), "r"(src2)
+ :"memory"
+ );
+ }
+ else
+ ff_vector_fmul_add_add_c(dst, src0, src1, src2, src3, len, step);
+}
+
+static void float_to_int16_3dnow(int16_t *dst, const float *src, int len){
+ // not bit-exact: pf2id uses different rounding than C and SSE
+ int i;
+ for(i=0; i<len; i+=4) {
+ asm volatile(
+ "pf2id %1, %%mm0 \n\t"
+ "pf2id %2, %%mm1 \n\t"
+ "packssdw %%mm1, %%mm0 \n\t"
+ "movq %%mm0, %0 \n\t"
+ :"=m"(dst[i])
+ :"m"(src[i]), "m"(src[i+2])
+ );
+ }
+ asm volatile("femms");
+}
+static void float_to_int16_sse(int16_t *dst, const float *src, int len){
+ int i;
+ for(i=0; i<len; i+=4) {
+ asm volatile(
+ "cvtps2pi %1, %%mm0 \n\t"
+ "cvtps2pi %2, %%mm1 \n\t"
+ "packssdw %%mm1, %%mm0 \n\t"
+ "movq %%mm0, %0 \n\t"
+ :"=m"(dst[i])
+ :"m"(src[i]), "m"(src[i+2])
+ );
+ }
+ asm volatile("emms");
+}
+
+#ifdef CONFIG_SNOW_ENCODER
+extern void ff_snow_horizontal_compose97i_sse2(DWTELEM *b, int width);
+extern void ff_snow_horizontal_compose97i_mmx(DWTELEM *b, int width);
+extern void ff_snow_vertical_compose97i_sse2(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, DWTELEM *b3, DWTELEM *b4, DWTELEM *b5, int width);
+extern void ff_snow_vertical_compose97i_mmx(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, DWTELEM *b3, DWTELEM *b4, DWTELEM *b5, int width);
+extern void ff_snow_inner_add_yblock_sse2(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);
+extern void ff_snow_inner_add_yblock_mmx(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);
+#endif
+
+void dsputil_init_mmx(DSPContext* c, AVCodecContext *avctx)
+{
+ mm_flags = mm_support();
+
+ if (avctx->dsp_mask) {
+ if (avctx->dsp_mask & FF_MM_FORCE)
+ mm_flags |= (avctx->dsp_mask & 0xffff);
+ else
+ mm_flags &= ~(avctx->dsp_mask & 0xffff);
+ }
+
+#if 0
+ av_log(avctx, AV_LOG_INFO, "libavcodec: CPU flags:");
+ if (mm_flags & MM_MMX)
+ av_log(avctx, AV_LOG_INFO, " mmx");
+ if (mm_flags & MM_MMXEXT)
+ av_log(avctx, AV_LOG_INFO, " mmxext");
+ if (mm_flags & MM_3DNOW)
+ av_log(avctx, AV_LOG_INFO, " 3dnow");
+ if (mm_flags & MM_SSE)
+ av_log(avctx, AV_LOG_INFO, " sse");
+ if (mm_flags & MM_SSE2)
+ av_log(avctx, AV_LOG_INFO, " sse2");
+ av_log(avctx, AV_LOG_INFO, "\n");
+#endif
+
+ if (mm_flags & MM_MMX) {
+ const int idct_algo= avctx->idct_algo;
+
+#ifdef CONFIG_ENCODERS
+ const int dct_algo = avctx->dct_algo;
+ if(dct_algo==FF_DCT_AUTO || dct_algo==FF_DCT_MMX){
+ if(mm_flags & MM_SSE2){
+ c->fdct = ff_fdct_sse2;
+ }else if(mm_flags & MM_MMXEXT){
+ c->fdct = ff_fdct_mmx2;
+ }else{
+ c->fdct = ff_fdct_mmx;
+ }
+ }
+#endif //CONFIG_ENCODERS
+ if(avctx->lowres==0){
+ 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;
+#ifdef CONFIG_GPL
+ }else if(idct_algo==FF_IDCT_LIBMPEG2MMX){
+ if(mm_flags & MM_MMXEXT){
+ c->idct_put= ff_libmpeg2mmx2_idct_put;
+ c->idct_add= ff_libmpeg2mmx2_idct_add;
+ c->idct = ff_mmxext_idct;
+ }else{
+ c->idct_put= ff_libmpeg2mmx_idct_put;
+ c->idct_add= ff_libmpeg2mmx_idct_add;
+ c->idct = ff_mmx_idct;
+ }
+ c->idct_permutation_type= FF_LIBMPEG2_IDCT_PERM;
+#endif
+ }else if(idct_algo==FF_IDCT_VP3 &&
+ avctx->codec->id!=CODEC_ID_THEORA &&
+ !(avctx->flags & CODEC_FLAG_BITEXACT)){
+ if(mm_flags & MM_SSE2){
+ c->idct_put= ff_vp3_idct_put_sse2;
+ c->idct_add= ff_vp3_idct_add_sse2;
+ c->idct = ff_vp3_idct_sse2;
+ c->idct_permutation_type= FF_TRANSPOSE_IDCT_PERM;
+ }else{
+ ff_vp3_dsp_init_mmx();
+ c->idct_put= ff_vp3_idct_put_mmx;
+ c->idct_add= ff_vp3_idct_add_mmx;
+ c->idct = ff_vp3_idct_mmx;
+ c->idct_permutation_type= FF_PARTTRANS_IDCT_PERM;
+ }
+ }else if(idct_algo==FF_IDCT_CAVS){
+ c->idct_permutation_type= FF_TRANSPOSE_IDCT_PERM;
+ }else if(idct_algo==FF_IDCT_XVIDMMX){
+ if(mm_flags & MM_MMXEXT){
+ c->idct_put= ff_idct_xvid_mmx2_put;
+ c->idct_add= ff_idct_xvid_mmx2_add;
+ c->idct = ff_idct_xvid_mmx2;
+ }else{
+ c->idct_put= ff_idct_xvid_mmx_put;
+ c->idct_add= ff_idct_xvid_mmx_add;
+ c->idct = ff_idct_xvid_mmx;
+ }
+ }
+ }
+
+#ifdef CONFIG_ENCODERS
+ c->get_pixels = get_pixels_mmx;
+ c->diff_pixels = diff_pixels_mmx;
+#endif //CONFIG_ENCODERS
+ c->put_pixels_clamped = put_pixels_clamped_mmx;
+ c->put_signed_pixels_clamped = put_signed_pixels_clamped_mmx;
+ c->add_pixels_clamped = add_pixels_clamped_mmx;
+ c->clear_blocks = clear_blocks_mmx;
+#ifdef CONFIG_ENCODERS
+ c->pix_sum = pix_sum16_mmx;
+#endif //CONFIG_ENCODERS
+
+ c->put_pixels_tab[0][0] = put_pixels16_mmx;
+ c->put_pixels_tab[0][1] = put_pixels16_x2_mmx;
+ c->put_pixels_tab[0][2] = put_pixels16_y2_mmx;
+ c->put_pixels_tab[0][3] = put_pixels16_xy2_mmx;
+
+ c->put_no_rnd_pixels_tab[0][0] = put_pixels16_mmx;
+ c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_mmx;
+ c->put_no_rnd_pixels_tab[0][2] = put_no_rnd_pixels16_y2_mmx;
+ c->put_no_rnd_pixels_tab[0][3] = put_no_rnd_pixels16_xy2_mmx;
+
+ c->avg_pixels_tab[0][0] = avg_pixels16_mmx;
+ c->avg_pixels_tab[0][1] = avg_pixels16_x2_mmx;
+ c->avg_pixels_tab[0][2] = avg_pixels16_y2_mmx;
+ c->avg_pixels_tab[0][3] = avg_pixels16_xy2_mmx;
+
+ c->avg_no_rnd_pixels_tab[0][0] = avg_no_rnd_pixels16_mmx;
+ c->avg_no_rnd_pixels_tab[0][1] = avg_no_rnd_pixels16_x2_mmx;
+ c->avg_no_rnd_pixels_tab[0][2] = avg_no_rnd_pixels16_y2_mmx;
+ c->avg_no_rnd_pixels_tab[0][3] = avg_no_rnd_pixels16_xy2_mmx;
+
+ c->put_pixels_tab[1][0] = put_pixels8_mmx;
+ c->put_pixels_tab[1][1] = put_pixels8_x2_mmx;
+ c->put_pixels_tab[1][2] = put_pixels8_y2_mmx;
+ c->put_pixels_tab[1][3] = put_pixels8_xy2_mmx;
+
+ c->put_no_rnd_pixels_tab[1][0] = put_pixels8_mmx;
+ c->put_no_rnd_pixels_tab[1][1] = put_no_rnd_pixels8_x2_mmx;
+ c->put_no_rnd_pixels_tab[1][2] = put_no_rnd_pixels8_y2_mmx;
+ c->put_no_rnd_pixels_tab[1][3] = put_no_rnd_pixels8_xy2_mmx;
+
+ c->avg_pixels_tab[1][0] = avg_pixels8_mmx;
+ c->avg_pixels_tab[1][1] = avg_pixels8_x2_mmx;
+ c->avg_pixels_tab[1][2] = avg_pixels8_y2_mmx;
+ c->avg_pixels_tab[1][3] = avg_pixels8_xy2_mmx;
+
+ c->avg_no_rnd_pixels_tab[1][0] = avg_no_rnd_pixels8_mmx;
+ c->avg_no_rnd_pixels_tab[1][1] = avg_no_rnd_pixels8_x2_mmx;
+ c->avg_no_rnd_pixels_tab[1][2] = avg_no_rnd_pixels8_y2_mmx;
+ c->avg_no_rnd_pixels_tab[1][3] = avg_no_rnd_pixels8_xy2_mmx;
+
+ c->gmc= gmc_mmx;
+
+ c->add_bytes= add_bytes_mmx;
+#ifdef CONFIG_ENCODERS
+ c->diff_bytes= diff_bytes_mmx;
+
+ c->hadamard8_diff[0]= hadamard8_diff16_mmx;
+ c->hadamard8_diff[1]= hadamard8_diff_mmx;
+
+ c->pix_norm1 = pix_norm1_mmx;
+ c->sse[0] = (mm_flags & MM_SSE2) ? sse16_sse2 : 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;
+
+#endif //CONFIG_ENCODERS
+
+ c->h263_v_loop_filter= h263_v_loop_filter_mmx;
+ c->h263_h_loop_filter= h263_h_loop_filter_mmx;
+ c->put_h264_chroma_pixels_tab[0]= put_h264_chroma_mc8_mmx;
+ c->put_h264_chroma_pixels_tab[1]= put_h264_chroma_mc4_mmx;
+
+ c->h264_idct_dc_add=
+ c->h264_idct_add= ff_h264_idct_add_mmx;
+ c->h264_idct8_dc_add=
+ c->h264_idct8_add= ff_h264_idct8_add_mmx;
+
+ if (mm_flags & MM_MMXEXT) {
+ c->prefetch = prefetch_mmx2;
+
+ c->put_pixels_tab[0][1] = put_pixels16_x2_mmx2;
+ c->put_pixels_tab[0][2] = put_pixels16_y2_mmx2;
+
+ c->avg_pixels_tab[0][0] = avg_pixels16_mmx2;
+ c->avg_pixels_tab[0][1] = avg_pixels16_x2_mmx2;
+ c->avg_pixels_tab[0][2] = avg_pixels16_y2_mmx2;
+
+ c->put_pixels_tab[1][1] = put_pixels8_x2_mmx2;
+ c->put_pixels_tab[1][2] = put_pixels8_y2_mmx2;
+
+ c->avg_pixels_tab[1][0] = avg_pixels8_mmx2;
+ c->avg_pixels_tab[1][1] = avg_pixels8_x2_mmx2;
+ c->avg_pixels_tab[1][2] = avg_pixels8_y2_mmx2;
+
+#ifdef CONFIG_ENCODERS
+ c->hadamard8_diff[0]= hadamard8_diff16_mmx2;
+ c->hadamard8_diff[1]= hadamard8_diff_mmx2;
+ c->vsad[4]= vsad_intra16_mmx2;
+#endif //CONFIG_ENCODERS
+
+ c->h264_idct_dc_add= ff_h264_idct_dc_add_mmx2;
+ c->h264_idct8_dc_add= ff_h264_idct8_dc_add_mmx2;
+
+ if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
+ c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_mmx2;
+ c->put_no_rnd_pixels_tab[0][2] = put_no_rnd_pixels16_y2_mmx2;
+ c->put_no_rnd_pixels_tab[1][1] = put_no_rnd_pixels8_x2_mmx2;
+ c->put_no_rnd_pixels_tab[1][2] = put_no_rnd_pixels8_y2_mmx2;
+ c->avg_pixels_tab[0][3] = avg_pixels16_xy2_mmx2;
+ c->avg_pixels_tab[1][3] = avg_pixels8_xy2_mmx2;
+#ifdef CONFIG_ENCODERS
+ c->vsad[0] = vsad16_mmx2;
+#endif //CONFIG_ENCODERS
+ }
+
+#if 1
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 0], qpel16_mc00_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 1], qpel16_mc10_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 2], qpel16_mc20_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 3], qpel16_mc30_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 4], qpel16_mc01_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 5], qpel16_mc11_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 6], qpel16_mc21_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 7], qpel16_mc31_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 8], qpel16_mc02_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 9], qpel16_mc12_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][10], qpel16_mc22_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][11], qpel16_mc32_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][12], qpel16_mc03_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][13], qpel16_mc13_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][14], qpel16_mc23_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][15], qpel16_mc33_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 0], qpel8_mc00_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 1], qpel8_mc10_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 2], qpel8_mc20_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 3], qpel8_mc30_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 4], qpel8_mc01_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 5], qpel8_mc11_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 6], qpel8_mc21_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 7], qpel8_mc31_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 8], qpel8_mc02_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 9], qpel8_mc12_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][10], qpel8_mc22_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][11], qpel8_mc32_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][12], qpel8_mc03_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][13], qpel8_mc13_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][14], qpel8_mc23_mmx2)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][15], qpel8_mc33_mmx2)
+#endif
+
+//FIXME 3dnow too
+#define dspfunc(PFX, IDX, NUM) \
+ c->PFX ## _pixels_tab[IDX][ 0] = PFX ## NUM ## _mc00_mmx2; \
+ c->PFX ## _pixels_tab[IDX][ 1] = PFX ## NUM ## _mc10_mmx2; \
+ c->PFX ## _pixels_tab[IDX][ 2] = PFX ## NUM ## _mc20_mmx2; \
+ c->PFX ## _pixels_tab[IDX][ 3] = PFX ## NUM ## _mc30_mmx2; \
+ c->PFX ## _pixels_tab[IDX][ 4] = PFX ## NUM ## _mc01_mmx2; \
+ c->PFX ## _pixels_tab[IDX][ 5] = PFX ## NUM ## _mc11_mmx2; \
+ c->PFX ## _pixels_tab[IDX][ 6] = PFX ## NUM ## _mc21_mmx2; \
+ c->PFX ## _pixels_tab[IDX][ 7] = PFX ## NUM ## _mc31_mmx2; \
+ c->PFX ## _pixels_tab[IDX][ 8] = PFX ## NUM ## _mc02_mmx2; \
+ c->PFX ## _pixels_tab[IDX][ 9] = PFX ## NUM ## _mc12_mmx2; \
+ c->PFX ## _pixels_tab[IDX][10] = PFX ## NUM ## _mc22_mmx2; \
+ c->PFX ## _pixels_tab[IDX][11] = PFX ## NUM ## _mc32_mmx2; \
+ c->PFX ## _pixels_tab[IDX][12] = PFX ## NUM ## _mc03_mmx2; \
+ c->PFX ## _pixels_tab[IDX][13] = PFX ## NUM ## _mc13_mmx2; \
+ c->PFX ## _pixels_tab[IDX][14] = PFX ## NUM ## _mc23_mmx2; \
+ c->PFX ## _pixels_tab[IDX][15] = PFX ## NUM ## _mc33_mmx2
+
+ dspfunc(put_h264_qpel, 0, 16);
+ dspfunc(put_h264_qpel, 1, 8);
+ dspfunc(put_h264_qpel, 2, 4);
+ dspfunc(avg_h264_qpel, 0, 16);
+ dspfunc(avg_h264_qpel, 1, 8);
+ dspfunc(avg_h264_qpel, 2, 4);
+
+ dspfunc(put_2tap_qpel, 0, 16);
+ dspfunc(put_2tap_qpel, 1, 8);
+ dspfunc(avg_2tap_qpel, 0, 16);
+ dspfunc(avg_2tap_qpel, 1, 8);
+#undef dspfunc
+
+ c->avg_h264_chroma_pixels_tab[0]= avg_h264_chroma_mc8_mmx2;
+ c->avg_h264_chroma_pixels_tab[1]= avg_h264_chroma_mc4_mmx2;
+ c->avg_h264_chroma_pixels_tab[2]= avg_h264_chroma_mc2_mmx2;
+ c->put_h264_chroma_pixels_tab[2]= put_h264_chroma_mc2_mmx2;
+ c->h264_v_loop_filter_luma= h264_v_loop_filter_luma_mmx2;
+ c->h264_h_loop_filter_luma= h264_h_loop_filter_luma_mmx2;
+ c->h264_v_loop_filter_chroma= h264_v_loop_filter_chroma_mmx2;
+ c->h264_h_loop_filter_chroma= h264_h_loop_filter_chroma_mmx2;
+ c->h264_v_loop_filter_chroma_intra= h264_v_loop_filter_chroma_intra_mmx2;
+ c->h264_h_loop_filter_chroma_intra= h264_h_loop_filter_chroma_intra_mmx2;
+ c->h264_loop_filter_strength= h264_loop_filter_strength_mmx2;
+
+ c->weight_h264_pixels_tab[0]= ff_h264_weight_16x16_mmx2;
+ c->weight_h264_pixels_tab[1]= ff_h264_weight_16x8_mmx2;
+ c->weight_h264_pixels_tab[2]= ff_h264_weight_8x16_mmx2;
+ c->weight_h264_pixels_tab[3]= ff_h264_weight_8x8_mmx2;
+ c->weight_h264_pixels_tab[4]= ff_h264_weight_8x4_mmx2;
+ c->weight_h264_pixels_tab[5]= ff_h264_weight_4x8_mmx2;
+ c->weight_h264_pixels_tab[6]= ff_h264_weight_4x4_mmx2;
+ c->weight_h264_pixels_tab[7]= ff_h264_weight_4x2_mmx2;
+
+ c->biweight_h264_pixels_tab[0]= ff_h264_biweight_16x16_mmx2;
+ c->biweight_h264_pixels_tab[1]= ff_h264_biweight_16x8_mmx2;
+ c->biweight_h264_pixels_tab[2]= ff_h264_biweight_8x16_mmx2;
+ c->biweight_h264_pixels_tab[3]= ff_h264_biweight_8x8_mmx2;
+ c->biweight_h264_pixels_tab[4]= ff_h264_biweight_8x4_mmx2;
+ c->biweight_h264_pixels_tab[5]= ff_h264_biweight_4x8_mmx2;
+ c->biweight_h264_pixels_tab[6]= ff_h264_biweight_4x4_mmx2;
+ c->biweight_h264_pixels_tab[7]= ff_h264_biweight_4x2_mmx2;
+
+#ifdef CONFIG_CAVS_DECODER
+ ff_cavsdsp_init_mmx2(c, avctx);
+#endif
+
+#ifdef CONFIG_ENCODERS
+ c->sub_hfyu_median_prediction= sub_hfyu_median_prediction_mmx2;
+#endif //CONFIG_ENCODERS
+ } else if (mm_flags & MM_3DNOW) {
+ c->prefetch = prefetch_3dnow;
+
+ c->put_pixels_tab[0][1] = put_pixels16_x2_3dnow;
+ c->put_pixels_tab[0][2] = put_pixels16_y2_3dnow;
+
+ c->avg_pixels_tab[0][0] = avg_pixels16_3dnow;
+ c->avg_pixels_tab[0][1] = avg_pixels16_x2_3dnow;
+ c->avg_pixels_tab[0][2] = avg_pixels16_y2_3dnow;
+
+ c->put_pixels_tab[1][1] = put_pixels8_x2_3dnow;
+ c->put_pixels_tab[1][2] = put_pixels8_y2_3dnow;
+
+ c->avg_pixels_tab[1][0] = avg_pixels8_3dnow;
+ c->avg_pixels_tab[1][1] = avg_pixels8_x2_3dnow;
+ c->avg_pixels_tab[1][2] = avg_pixels8_y2_3dnow;
+
+ if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
+ c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_3dnow;
+ c->put_no_rnd_pixels_tab[0][2] = put_no_rnd_pixels16_y2_3dnow;
+ c->put_no_rnd_pixels_tab[1][1] = put_no_rnd_pixels8_x2_3dnow;
+ c->put_no_rnd_pixels_tab[1][2] = put_no_rnd_pixels8_y2_3dnow;
+ c->avg_pixels_tab[0][3] = avg_pixels16_xy2_3dnow;
+ c->avg_pixels_tab[1][3] = avg_pixels8_xy2_3dnow;
+ }
+
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 0], qpel16_mc00_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 1], qpel16_mc10_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 2], qpel16_mc20_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 3], qpel16_mc30_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 4], qpel16_mc01_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 5], qpel16_mc11_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 6], qpel16_mc21_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 7], qpel16_mc31_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 8], qpel16_mc02_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][ 9], qpel16_mc12_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][10], qpel16_mc22_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][11], qpel16_mc32_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][12], qpel16_mc03_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][13], qpel16_mc13_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][14], qpel16_mc23_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[0][15], qpel16_mc33_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 0], qpel8_mc00_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 1], qpel8_mc10_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 2], qpel8_mc20_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 3], qpel8_mc30_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 4], qpel8_mc01_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 5], qpel8_mc11_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 6], qpel8_mc21_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 7], qpel8_mc31_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 8], qpel8_mc02_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][ 9], qpel8_mc12_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][10], qpel8_mc22_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][11], qpel8_mc32_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][12], qpel8_mc03_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][13], qpel8_mc13_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][14], qpel8_mc23_3dnow)
+ SET_QPEL_FUNC(qpel_pixels_tab[1][15], qpel8_mc33_3dnow)
+
+#define dspfunc(PFX, IDX, NUM) \
+ c->PFX ## _pixels_tab[IDX][ 0] = PFX ## NUM ## _mc00_3dnow; \
+ c->PFX ## _pixels_tab[IDX][ 1] = PFX ## NUM ## _mc10_3dnow; \
+ c->PFX ## _pixels_tab[IDX][ 2] = PFX ## NUM ## _mc20_3dnow; \
+ c->PFX ## _pixels_tab[IDX][ 3] = PFX ## NUM ## _mc30_3dnow; \
+ c->PFX ## _pixels_tab[IDX][ 4] = PFX ## NUM ## _mc01_3dnow; \
+ c->PFX ## _pixels_tab[IDX][ 5] = PFX ## NUM ## _mc11_3dnow; \
+ c->PFX ## _pixels_tab[IDX][ 6] = PFX ## NUM ## _mc21_3dnow; \
+ c->PFX ## _pixels_tab[IDX][ 7] = PFX ## NUM ## _mc31_3dnow; \
+ c->PFX ## _pixels_tab[IDX][ 8] = PFX ## NUM ## _mc02_3dnow; \
+ c->PFX ## _pixels_tab[IDX][ 9] = PFX ## NUM ## _mc12_3dnow; \
+ c->PFX ## _pixels_tab[IDX][10] = PFX ## NUM ## _mc22_3dnow; \
+ c->PFX ## _pixels_tab[IDX][11] = PFX ## NUM ## _mc32_3dnow; \
+ c->PFX ## _pixels_tab[IDX][12] = PFX ## NUM ## _mc03_3dnow; \
+ c->PFX ## _pixels_tab[IDX][13] = PFX ## NUM ## _mc13_3dnow; \
+ c->PFX ## _pixels_tab[IDX][14] = PFX ## NUM ## _mc23_3dnow; \
+ c->PFX ## _pixels_tab[IDX][15] = PFX ## NUM ## _mc33_3dnow
+
+ dspfunc(put_h264_qpel, 0, 16);
+ dspfunc(put_h264_qpel, 1, 8);
+ dspfunc(put_h264_qpel, 2, 4);
+ dspfunc(avg_h264_qpel, 0, 16);
+ dspfunc(avg_h264_qpel, 1, 8);
+ dspfunc(avg_h264_qpel, 2, 4);
+
+ dspfunc(put_2tap_qpel, 0, 16);
+ dspfunc(put_2tap_qpel, 1, 8);
+ dspfunc(avg_2tap_qpel, 0, 16);
+ dspfunc(avg_2tap_qpel, 1, 8);
+
+ c->avg_h264_chroma_pixels_tab[0]= avg_h264_chroma_mc8_3dnow;
+ c->avg_h264_chroma_pixels_tab[1]= avg_h264_chroma_mc4_3dnow;
+ }
+
+#ifdef CONFIG_SNOW_ENCODER
+ if(mm_flags & MM_SSE2){
+ c->horizontal_compose97i = ff_snow_horizontal_compose97i_sse2;
+ c->vertical_compose97i = ff_snow_vertical_compose97i_sse2;
+ c->inner_add_yblock = ff_snow_inner_add_yblock_sse2;
+ }
+ else{
+ c->horizontal_compose97i = ff_snow_horizontal_compose97i_mmx;
+ c->vertical_compose97i = ff_snow_vertical_compose97i_mmx;
+ c->inner_add_yblock = ff_snow_inner_add_yblock_mmx;
+ }
+#endif
+
+ if(mm_flags & MM_3DNOW){
+ c->vorbis_inverse_coupling = vorbis_inverse_coupling_3dnow;
+ c->vector_fmul = vector_fmul_3dnow;
+ if(!(avctx->flags & CODEC_FLAG_BITEXACT))
+ c->float_to_int16 = float_to_int16_3dnow;
+ }
+ if(mm_flags & MM_3DNOWEXT)
+ c->vector_fmul_reverse = vector_fmul_reverse_3dnow2;
+ if(mm_flags & MM_SSE){
+ c->vorbis_inverse_coupling = vorbis_inverse_coupling_sse;
+ c->vector_fmul = vector_fmul_sse;
+ c->float_to_int16 = float_to_int16_sse;
+ c->vector_fmul_reverse = vector_fmul_reverse_sse;
+ c->vector_fmul_add_add = vector_fmul_add_add_sse;
+ }
+ if(mm_flags & MM_3DNOW)
+ c->vector_fmul_add_add = vector_fmul_add_add_3dnow; // faster than sse
+ }
+
+#ifdef CONFIG_ENCODERS
+ dsputil_init_pix_mmx(c, avctx);
+#endif //CONFIG_ENCODERS
+#if 0
+ // for speed testing
+ get_pixels = just_return;
+ put_pixels_clamped = just_return;
+ add_pixels_clamped = just_return;
+
+ pix_abs16x16 = just_return;
+ pix_abs16x16_x2 = just_return;
+ pix_abs16x16_y2 = just_return;
+ pix_abs16x16_xy2 = just_return;
+
+ put_pixels_tab[0] = just_return;
+ put_pixels_tab[1] = just_return;
+ put_pixels_tab[2] = just_return;
+ put_pixels_tab[3] = just_return;
+
+ put_no_rnd_pixels_tab[0] = just_return;
+ put_no_rnd_pixels_tab[1] = just_return;
+ put_no_rnd_pixels_tab[2] = just_return;
+ put_no_rnd_pixels_tab[3] = just_return;
+
+ avg_pixels_tab[0] = just_return;
+ avg_pixels_tab[1] = just_return;
+ avg_pixels_tab[2] = just_return;
+ avg_pixels_tab[3] = just_return;
+
+ avg_no_rnd_pixels_tab[0] = just_return;
+ avg_no_rnd_pixels_tab[1] = just_return;
+ avg_no_rnd_pixels_tab[2] = just_return;
+ avg_no_rnd_pixels_tab[3] = just_return;
+
+ //av_fdct = just_return;
+ //ff_idct = just_return;
+#endif
+}
diff --git a/contrib/ffmpeg/libavcodec/i386/dsputil_mmx_avg.h b/contrib/ffmpeg/libavcodec/i386/dsputil_mmx_avg.h
new file mode 100644
index 000000000..b365cea57
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/dsputil_mmx_avg.h
@@ -0,0 +1,870 @@
+/*
+ * DSP utils : average functions are compiled twice for 3dnow/mmx2
+ * 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 <nickols_k@mail.ru>
+ * mostly rewritten by Michael Niedermayer <michaelni@gmx.at>
+ * and improved by Zdenek Kabelac <kabi@users.sf.net>
+ */
+
+/* XXX: we use explicit registers to avoid a gcc 2.95.2 register asm
+ clobber bug - now it will work with 2.95.2 and also with -fPIC
+ */
+static void DEF(put_pixels8_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ __asm __volatile(
+ "lea (%3, %3), %%"REG_a" \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"
+ "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"
+ PAVGB" 1(%1), %%mm0 \n\t"
+ PAVGB" 1(%1, %3), %%mm1 \n\t"
+ "add %%"REG_a", %1 \n\t"
+ "movq %%mm0, (%2) \n\t"
+ "movq %%mm1, (%2, %3) \n\t"
+ "add %%"REG_a", %2 \n\t"
+ "subl $4, %0 \n\t"
+ "jnz 1b \n\t"
+ :"+g"(h), "+S"(pixels), "+D"(block)
+ :"r" ((long)line_size)
+ :"%"REG_a, "memory");
+}
+
+static void DEF(put_pixels4_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
+{
+ __asm __volatile(
+ "testl $1, %0 \n\t"
+ " jz 1f \n\t"
+ "movd (%1), %%mm0 \n\t"
+ "movd (%2), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ "add $4, %2 \n\t"
+ PAVGB" %%mm1, %%mm0 \n\t"
+ "movd %%mm0, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "decl %0 \n\t"
+ "1: \n\t"
+ "movd (%1), %%mm0 \n\t"
+ "add %4, %1 \n\t"
+ "movd (%1), %%mm1 \n\t"
+ "movd (%2), %%mm2 \n\t"
+ "movd 4(%2), %%mm3 \n\t"
+ "add %4, %1 \n\t"
+ PAVGB" %%mm2, %%mm0 \n\t"
+ PAVGB" %%mm3, %%mm1 \n\t"
+ "movd %%mm0, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "movd %%mm1, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "movd (%1), %%mm0 \n\t"
+ "add %4, %1 \n\t"
+ "movd (%1), %%mm1 \n\t"
+ "movd 8(%2), %%mm2 \n\t"
+ "movd 12(%2), %%mm3 \n\t"
+ "add %4, %1 \n\t"
+ PAVGB" %%mm2, %%mm0 \n\t"
+ PAVGB" %%mm3, %%mm1 \n\t"
+ "movd %%mm0, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "movd %%mm1, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "add $16, %2 \n\t"
+ "subl $4, %0 \n\t"
+ "jnz 1b \n\t"
+#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cant be used
+ :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#else
+ :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#endif
+ :"S"((long)src1Stride), "D"((long)dstStride)
+ :"memory");
+}
+
+
+static void DEF(put_pixels8_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
+{
+ __asm __volatile(
+ "testl $1, %0 \n\t"
+ " jz 1f \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq (%2), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ "add $8, %2 \n\t"
+ PAVGB" %%mm1, %%mm0 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "decl %0 \n\t"
+ "1: \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "add %4, %1 \n\t"
+ "movq (%1), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ PAVGB" (%2), %%mm0 \n\t"
+ PAVGB" 8(%2), %%mm1 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "movq %%mm1, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "add %4, %1 \n\t"
+ "movq (%1), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ PAVGB" 16(%2), %%mm0 \n\t"
+ PAVGB" 24(%2), %%mm1 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "movq %%mm1, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "add $32, %2 \n\t"
+ "subl $4, %0 \n\t"
+ "jnz 1b \n\t"
+#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cant be used
+ :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#else
+ :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#endif
+ :"S"((long)src1Stride), "D"((long)dstStride)
+ :"memory");
+//the following should be used, though better not with gcc ...
+/* :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
+ :"r"(src1Stride), "r"(dstStride)
+ :"memory");*/
+}
+
+static void DEF(put_no_rnd_pixels8_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
+{
+ __asm __volatile(
+ "pcmpeqb %%mm6, %%mm6 \n\t"
+ "testl $1, %0 \n\t"
+ " jz 1f \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq (%2), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ "add $8, %2 \n\t"
+ "pxor %%mm6, %%mm0 \n\t"
+ "pxor %%mm6, %%mm1 \n\t"
+ PAVGB" %%mm1, %%mm0 \n\t"
+ "pxor %%mm6, %%mm0 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "decl %0 \n\t"
+ "1: \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "add %4, %1 \n\t"
+ "movq (%1), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ "movq (%2), %%mm2 \n\t"
+ "movq 8(%2), %%mm3 \n\t"
+ "pxor %%mm6, %%mm0 \n\t"
+ "pxor %%mm6, %%mm1 \n\t"
+ "pxor %%mm6, %%mm2 \n\t"
+ "pxor %%mm6, %%mm3 \n\t"
+ PAVGB" %%mm2, %%mm0 \n\t"
+ PAVGB" %%mm3, %%mm1 \n\t"
+ "pxor %%mm6, %%mm0 \n\t"
+ "pxor %%mm6, %%mm1 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "movq %%mm1, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "add %4, %1 \n\t"
+ "movq (%1), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ "movq 16(%2), %%mm2 \n\t"
+ "movq 24(%2), %%mm3 \n\t"
+ "pxor %%mm6, %%mm0 \n\t"
+ "pxor %%mm6, %%mm1 \n\t"
+ "pxor %%mm6, %%mm2 \n\t"
+ "pxor %%mm6, %%mm3 \n\t"
+ PAVGB" %%mm2, %%mm0 \n\t"
+ PAVGB" %%mm3, %%mm1 \n\t"
+ "pxor %%mm6, %%mm0 \n\t"
+ "pxor %%mm6, %%mm1 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "movq %%mm1, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "add $32, %2 \n\t"
+ "subl $4, %0 \n\t"
+ "jnz 1b \n\t"
+#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cant be used
+ :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#else
+ :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#endif
+ :"S"((long)src1Stride), "D"((long)dstStride)
+ :"memory");
+//the following should be used, though better not with gcc ...
+/* :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
+ :"r"(src1Stride), "r"(dstStride)
+ :"memory");*/
+}
+
+static void DEF(avg_pixels4_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
+{
+ __asm __volatile(
+ "testl $1, %0 \n\t"
+ " jz 1f \n\t"
+ "movd (%1), %%mm0 \n\t"
+ "movd (%2), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ "add $4, %2 \n\t"
+ PAVGB" %%mm1, %%mm0 \n\t"
+ PAVGB" (%3), %%mm0 \n\t"
+ "movd %%mm0, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "decl %0 \n\t"
+ "1: \n\t"
+ "movd (%1), %%mm0 \n\t"
+ "add %4, %1 \n\t"
+ "movd (%1), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ PAVGB" (%2), %%mm0 \n\t"
+ PAVGB" 4(%2), %%mm1 \n\t"
+ PAVGB" (%3), %%mm0 \n\t"
+ "movd %%mm0, (%3) \n\t"
+ "add %5, %3 \n\t"
+ PAVGB" (%3), %%mm1 \n\t"
+ "movd %%mm1, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "movd (%1), %%mm0 \n\t"
+ "add %4, %1 \n\t"
+ "movd (%1), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ PAVGB" 8(%2), %%mm0 \n\t"
+ PAVGB" 12(%2), %%mm1 \n\t"
+ PAVGB" (%3), %%mm0 \n\t"
+ "movd %%mm0, (%3) \n\t"
+ "add %5, %3 \n\t"
+ PAVGB" (%3), %%mm1 \n\t"
+ "movd %%mm1, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "add $16, %2 \n\t"
+ "subl $4, %0 \n\t"
+ "jnz 1b \n\t"
+#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cant be used
+ :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#else
+ :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#endif
+ :"S"((long)src1Stride), "D"((long)dstStride)
+ :"memory");
+}
+
+
+static void DEF(avg_pixels8_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
+{
+ __asm __volatile(
+ "testl $1, %0 \n\t"
+ " jz 1f \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq (%2), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ "add $8, %2 \n\t"
+ PAVGB" %%mm1, %%mm0 \n\t"
+ PAVGB" (%3), %%mm0 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "decl %0 \n\t"
+ "1: \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "add %4, %1 \n\t"
+ "movq (%1), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ PAVGB" (%2), %%mm0 \n\t"
+ PAVGB" 8(%2), %%mm1 \n\t"
+ PAVGB" (%3), %%mm0 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "add %5, %3 \n\t"
+ PAVGB" (%3), %%mm1 \n\t"
+ "movq %%mm1, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "add %4, %1 \n\t"
+ "movq (%1), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ PAVGB" 16(%2), %%mm0 \n\t"
+ PAVGB" 24(%2), %%mm1 \n\t"
+ PAVGB" (%3), %%mm0 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "add %5, %3 \n\t"
+ PAVGB" (%3), %%mm1 \n\t"
+ "movq %%mm1, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "add $32, %2 \n\t"
+ "subl $4, %0 \n\t"
+ "jnz 1b \n\t"
+#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cant be used
+ :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#else
+ :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#endif
+ :"S"((long)src1Stride), "D"((long)dstStride)
+ :"memory");
+//the following should be used, though better not with gcc ...
+/* :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
+ :"r"(src1Stride), "r"(dstStride)
+ :"memory");*/
+}
+
+static void DEF(put_pixels16_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ __asm __volatile(
+ "lea (%3, %3), %%"REG_a" \n\t"
+ "1: \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq (%1, %3), %%mm1 \n\t"
+ "movq 8(%1), %%mm2 \n\t"
+ "movq 8(%1, %3), %%mm3 \n\t"
+ PAVGB" 1(%1), %%mm0 \n\t"
+ PAVGB" 1(%1, %3), %%mm1 \n\t"
+ PAVGB" 9(%1), %%mm2 \n\t"
+ PAVGB" 9(%1, %3), %%mm3 \n\t"
+ "movq %%mm0, (%2) \n\t"
+ "movq %%mm1, (%2, %3) \n\t"
+ "movq %%mm2, 8(%2) \n\t"
+ "movq %%mm3, 8(%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 8(%1), %%mm2 \n\t"
+ "movq 8(%1, %3), %%mm3 \n\t"
+ PAVGB" 1(%1), %%mm0 \n\t"
+ PAVGB" 1(%1, %3), %%mm1 \n\t"
+ PAVGB" 9(%1), %%mm2 \n\t"
+ PAVGB" 9(%1, %3), %%mm3 \n\t"
+ "add %%"REG_a", %1 \n\t"
+ "movq %%mm0, (%2) \n\t"
+ "movq %%mm1, (%2, %3) \n\t"
+ "movq %%mm2, 8(%2) \n\t"
+ "movq %%mm3, 8(%2, %3) \n\t"
+ "add %%"REG_a", %2 \n\t"
+ "subl $4, %0 \n\t"
+ "jnz 1b \n\t"
+ :"+g"(h), "+S"(pixels), "+D"(block)
+ :"r" ((long)line_size)
+ :"%"REG_a, "memory");
+}
+
+static void DEF(put_pixels16_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
+{
+ __asm __volatile(
+ "testl $1, %0 \n\t"
+ " jz 1f \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq 8(%1), %%mm1 \n\t"
+ PAVGB" (%2), %%mm0 \n\t"
+ PAVGB" 8(%2), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ "add $16, %2 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "movq %%mm1, 8(%3) \n\t"
+ "add %5, %3 \n\t"
+ "decl %0 \n\t"
+ "1: \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq 8(%1), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ PAVGB" (%2), %%mm0 \n\t"
+ PAVGB" 8(%2), %%mm1 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "movq %%mm1, 8(%3) \n\t"
+ "add %5, %3 \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq 8(%1), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ PAVGB" 16(%2), %%mm0 \n\t"
+ PAVGB" 24(%2), %%mm1 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "movq %%mm1, 8(%3) \n\t"
+ "add %5, %3 \n\t"
+ "add $32, %2 \n\t"
+ "subl $2, %0 \n\t"
+ "jnz 1b \n\t"
+#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cant be used
+ :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#else
+ :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#endif
+ :"S"((long)src1Stride), "D"((long)dstStride)
+ :"memory");
+//the following should be used, though better not with gcc ...
+/* :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
+ :"r"(src1Stride), "r"(dstStride)
+ :"memory");*/
+}
+
+static void DEF(avg_pixels16_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
+{
+ __asm __volatile(
+ "testl $1, %0 \n\t"
+ " jz 1f \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq 8(%1), %%mm1 \n\t"
+ PAVGB" (%2), %%mm0 \n\t"
+ PAVGB" 8(%2), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ "add $16, %2 \n\t"
+ PAVGB" (%3), %%mm0 \n\t"
+ PAVGB" 8(%3), %%mm1 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "movq %%mm1, 8(%3) \n\t"
+ "add %5, %3 \n\t"
+ "decl %0 \n\t"
+ "1: \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq 8(%1), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ PAVGB" (%2), %%mm0 \n\t"
+ PAVGB" 8(%2), %%mm1 \n\t"
+ PAVGB" (%3), %%mm0 \n\t"
+ PAVGB" 8(%3), %%mm1 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "movq %%mm1, 8(%3) \n\t"
+ "add %5, %3 \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq 8(%1), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ PAVGB" 16(%2), %%mm0 \n\t"
+ PAVGB" 24(%2), %%mm1 \n\t"
+ PAVGB" (%3), %%mm0 \n\t"
+ PAVGB" 8(%3), %%mm1 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "movq %%mm1, 8(%3) \n\t"
+ "add %5, %3 \n\t"
+ "add $32, %2 \n\t"
+ "subl $2, %0 \n\t"
+ "jnz 1b \n\t"
+#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cant be used
+ :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#else
+ :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#endif
+ :"S"((long)src1Stride), "D"((long)dstStride)
+ :"memory");
+//the following should be used, though better not with gcc ...
+/* :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
+ :"r"(src1Stride), "r"(dstStride)
+ :"memory");*/
+}
+
+static void DEF(put_no_rnd_pixels16_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
+{
+ __asm __volatile(
+ "pcmpeqb %%mm6, %%mm6 \n\t"
+ "testl $1, %0 \n\t"
+ " jz 1f \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq 8(%1), %%mm1 \n\t"
+ "movq (%2), %%mm2 \n\t"
+ "movq 8(%2), %%mm3 \n\t"
+ "pxor %%mm6, %%mm0 \n\t"
+ "pxor %%mm6, %%mm1 \n\t"
+ "pxor %%mm6, %%mm2 \n\t"
+ "pxor %%mm6, %%mm3 \n\t"
+ PAVGB" %%mm2, %%mm0 \n\t"
+ PAVGB" %%mm3, %%mm1 \n\t"
+ "pxor %%mm6, %%mm0 \n\t"
+ "pxor %%mm6, %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ "add $16, %2 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "movq %%mm1, 8(%3) \n\t"
+ "add %5, %3 \n\t"
+ "decl %0 \n\t"
+ "1: \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq 8(%1), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ "movq (%2), %%mm2 \n\t"
+ "movq 8(%2), %%mm3 \n\t"
+ "pxor %%mm6, %%mm0 \n\t"
+ "pxor %%mm6, %%mm1 \n\t"
+ "pxor %%mm6, %%mm2 \n\t"
+ "pxor %%mm6, %%mm3 \n\t"
+ PAVGB" %%mm2, %%mm0 \n\t"
+ PAVGB" %%mm3, %%mm1 \n\t"
+ "pxor %%mm6, %%mm0 \n\t"
+ "pxor %%mm6, %%mm1 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "movq %%mm1, 8(%3) \n\t"
+ "add %5, %3 \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq 8(%1), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ "movq 16(%2), %%mm2 \n\t"
+ "movq 24(%2), %%mm3 \n\t"
+ "pxor %%mm6, %%mm0 \n\t"
+ "pxor %%mm6, %%mm1 \n\t"
+ "pxor %%mm6, %%mm2 \n\t"
+ "pxor %%mm6, %%mm3 \n\t"
+ PAVGB" %%mm2, %%mm0 \n\t"
+ PAVGB" %%mm3, %%mm1 \n\t"
+ "pxor %%mm6, %%mm0 \n\t"
+ "pxor %%mm6, %%mm1 \n\t"
+ "movq %%mm0, (%3) \n\t"
+ "movq %%mm1, 8(%3) \n\t"
+ "add %5, %3 \n\t"
+ "add $32, %2 \n\t"
+ "subl $2, %0 \n\t"
+ "jnz 1b \n\t"
+#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cant be used
+ :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#else
+ :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#endif
+ :"S"((long)src1Stride), "D"((long)dstStride)
+ :"memory");
+//the following should be used, though better not with gcc ...
+/* :"+g"(h), "+r"(src1), "+r"(src2), "+r"(dst)
+ :"r"(src1Stride), "r"(dstStride)
+ :"memory");*/
+}
+
+/* GL: this function does incorrect rounding if overflow */
+static void DEF(put_no_rnd_pixels8_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ MOVQ_BONE(mm6);
+ __asm __volatile(
+ "lea (%3, %3), %%"REG_a" \n\t"
+ "1: \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq (%1, %3), %%mm2 \n\t"
+ "movq 1(%1), %%mm1 \n\t"
+ "movq 1(%1, %3), %%mm3 \n\t"
+ "add %%"REG_a", %1 \n\t"
+ "psubusb %%mm6, %%mm0 \n\t"
+ "psubusb %%mm6, %%mm2 \n\t"
+ PAVGB" %%mm1, %%mm0 \n\t"
+ PAVGB" %%mm3, %%mm2 \n\t"
+ "movq %%mm0, (%2) \n\t"
+ "movq %%mm2, (%2, %3) \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"
+ "add %%"REG_a", %2 \n\t"
+ "add %%"REG_a", %1 \n\t"
+ "psubusb %%mm6, %%mm0 \n\t"
+ "psubusb %%mm6, %%mm2 \n\t"
+ PAVGB" %%mm1, %%mm0 \n\t"
+ PAVGB" %%mm3, %%mm2 \n\t"
+ "movq %%mm0, (%2) \n\t"
+ "movq %%mm2, (%2, %3) \n\t"
+ "add %%"REG_a", %2 \n\t"
+ "subl $4, %0 \n\t"
+ "jnz 1b \n\t"
+ :"+g"(h), "+S"(pixels), "+D"(block)
+ :"r" ((long)line_size)
+ :"%"REG_a, "memory");
+}
+
+static void DEF(put_pixels8_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ __asm __volatile(
+ "lea (%3, %3), %%"REG_a" \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "sub %3, %2 \n\t"
+ "1: \n\t"
+ "movq (%1, %3), %%mm1 \n\t"
+ "movq (%1, %%"REG_a"), %%mm2 \n\t"
+ "add %%"REG_a", %1 \n\t"
+ PAVGB" %%mm1, %%mm0 \n\t"
+ PAVGB" %%mm2, %%mm1 \n\t"
+ "movq %%mm0, (%2, %3) \n\t"
+ "movq %%mm1, (%2, %%"REG_a") \n\t"
+ "movq (%1, %3), %%mm1 \n\t"
+ "movq (%1, %%"REG_a"), %%mm0 \n\t"
+ "add %%"REG_a", %2 \n\t"
+ "add %%"REG_a", %1 \n\t"
+ PAVGB" %%mm1, %%mm2 \n\t"
+ PAVGB" %%mm0, %%mm1 \n\t"
+ "movq %%mm2, (%2, %3) \n\t"
+ "movq %%mm1, (%2, %%"REG_a") \n\t"
+ "add %%"REG_a", %2 \n\t"
+ "subl $4, %0 \n\t"
+ "jnz 1b \n\t"
+ :"+g"(h), "+S"(pixels), "+D" (block)
+ :"r" ((long)line_size)
+ :"%"REG_a, "memory");
+}
+
+/* GL: this function does incorrect rounding if overflow */
+static void DEF(put_no_rnd_pixels8_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ MOVQ_BONE(mm6);
+ __asm __volatile(
+ "lea (%3, %3), %%"REG_a" \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "sub %3, %2 \n\t"
+ "1: \n\t"
+ "movq (%1, %3), %%mm1 \n\t"
+ "movq (%1, %%"REG_a"), %%mm2 \n\t"
+ "add %%"REG_a", %1 \n\t"
+ "psubusb %%mm6, %%mm1 \n\t"
+ PAVGB" %%mm1, %%mm0 \n\t"
+ PAVGB" %%mm2, %%mm1 \n\t"
+ "movq %%mm0, (%2, %3) \n\t"
+ "movq %%mm1, (%2, %%"REG_a") \n\t"
+ "movq (%1, %3), %%mm1 \n\t"
+ "movq (%1, %%"REG_a"), %%mm0 \n\t"
+ "add %%"REG_a", %2 \n\t"
+ "add %%"REG_a", %1 \n\t"
+ "psubusb %%mm6, %%mm1 \n\t"
+ PAVGB" %%mm1, %%mm2 \n\t"
+ PAVGB" %%mm0, %%mm1 \n\t"
+ "movq %%mm2, (%2, %3) \n\t"
+ "movq %%mm1, (%2, %%"REG_a") \n\t"
+ "add %%"REG_a", %2 \n\t"
+ "subl $4, %0 \n\t"
+ "jnz 1b \n\t"
+ :"+g"(h), "+S"(pixels), "+D" (block)
+ :"r" ((long)line_size)
+ :"%"REG_a, "memory");
+}
+
+static void DEF(avg_pixels8)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ __asm __volatile(
+ "lea (%3, %3), %%"REG_a" \n\t"
+ "1: \n\t"
+ "movq (%2), %%mm0 \n\t"
+ "movq (%2, %3), %%mm1 \n\t"
+ PAVGB" (%1), %%mm0 \n\t"
+ PAVGB" (%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 (%2), %%mm0 \n\t"
+ "movq (%2, %3), %%mm1 \n\t"
+ PAVGB" (%1), %%mm0 \n\t"
+ PAVGB" (%1, %3), %%mm1 \n\t"
+ "add %%"REG_a", %1 \n\t"
+ "movq %%mm0, (%2) \n\t"
+ "movq %%mm1, (%2, %3) \n\t"
+ "add %%"REG_a", %2 \n\t"
+ "subl $4, %0 \n\t"
+ "jnz 1b \n\t"
+ :"+g"(h), "+S"(pixels), "+D"(block)
+ :"r" ((long)line_size)
+ :"%"REG_a, "memory");
+}
+
+static void DEF(avg_pixels8_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ __asm __volatile(
+ "lea (%3, %3), %%"REG_a" \n\t"
+ "1: \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq (%1, %3), %%mm2 \n\t"
+ PAVGB" 1(%1), %%mm0 \n\t"
+ PAVGB" 1(%1, %3), %%mm2 \n\t"
+ PAVGB" (%2), %%mm0 \n\t"
+ PAVGB" (%2, %3), %%mm2 \n\t"
+ "add %%"REG_a", %1 \n\t"
+ "movq %%mm0, (%2) \n\t"
+ "movq %%mm2, (%2, %3) \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq (%1, %3), %%mm2 \n\t"
+ PAVGB" 1(%1), %%mm0 \n\t"
+ PAVGB" 1(%1, %3), %%mm2 \n\t"
+ "add %%"REG_a", %2 \n\t"
+ "add %%"REG_a", %1 \n\t"
+ PAVGB" (%2), %%mm0 \n\t"
+ PAVGB" (%2, %3), %%mm2 \n\t"
+ "movq %%mm0, (%2) \n\t"
+ "movq %%mm2, (%2, %3) \n\t"
+ "add %%"REG_a", %2 \n\t"
+ "subl $4, %0 \n\t"
+ "jnz 1b \n\t"
+ :"+g"(h), "+S"(pixels), "+D"(block)
+ :"r" ((long)line_size)
+ :"%"REG_a, "memory");
+}
+
+static void DEF(avg_pixels8_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ __asm __volatile(
+ "lea (%3, %3), %%"REG_a" \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "sub %3, %2 \n\t"
+ "1: \n\t"
+ "movq (%1, %3), %%mm1 \n\t"
+ "movq (%1, %%"REG_a"), %%mm2 \n\t"
+ "add %%"REG_a", %1 \n\t"
+ PAVGB" %%mm1, %%mm0 \n\t"
+ PAVGB" %%mm2, %%mm1 \n\t"
+ "movq (%2, %3), %%mm3 \n\t"
+ "movq (%2, %%"REG_a"), %%mm4 \n\t"
+ PAVGB" %%mm3, %%mm0 \n\t"
+ PAVGB" %%mm4, %%mm1 \n\t"
+ "movq %%mm0, (%2, %3) \n\t"
+ "movq %%mm1, (%2, %%"REG_a") \n\t"
+ "movq (%1, %3), %%mm1 \n\t"
+ "movq (%1, %%"REG_a"), %%mm0 \n\t"
+ PAVGB" %%mm1, %%mm2 \n\t"
+ PAVGB" %%mm0, %%mm1 \n\t"
+ "add %%"REG_a", %2 \n\t"
+ "add %%"REG_a", %1 \n\t"
+ "movq (%2, %3), %%mm3 \n\t"
+ "movq (%2, %%"REG_a"), %%mm4 \n\t"
+ PAVGB" %%mm3, %%mm2 \n\t"
+ PAVGB" %%mm4, %%mm1 \n\t"
+ "movq %%mm2, (%2, %3) \n\t"
+ "movq %%mm1, (%2, %%"REG_a") \n\t"
+ "add %%"REG_a", %2 \n\t"
+ "subl $4, %0 \n\t"
+ "jnz 1b \n\t"
+ :"+g"(h), "+S"(pixels), "+D"(block)
+ :"r" ((long)line_size)
+ :"%"REG_a, "memory");
+}
+
+// Note this is not correctly rounded, but this function is only used for b frames so it doesnt matter
+static void DEF(avg_pixels8_xy2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ MOVQ_BONE(mm6);
+ __asm __volatile(
+ "lea (%3, %3), %%"REG_a" \n\t"
+ "movq (%1), %%mm0 \n\t"
+ PAVGB" 1(%1), %%mm0 \n\t"
+ ASMALIGN(3)
+ "1: \n\t"
+ "movq (%1, %%"REG_a"), %%mm2 \n\t"
+ "movq (%1, %3), %%mm1 \n\t"
+ "psubusb %%mm6, %%mm2 \n\t"
+ PAVGB" 1(%1, %3), %%mm1 \n\t"
+ PAVGB" 1(%1, %%"REG_a"), %%mm2 \n\t"
+ "add %%"REG_a", %1 \n\t"
+ PAVGB" %%mm1, %%mm0 \n\t"
+ PAVGB" %%mm2, %%mm1 \n\t"
+ PAVGB" (%2), %%mm0 \n\t"
+ PAVGB" (%2, %3), %%mm1 \n\t"
+ "movq %%mm0, (%2) \n\t"
+ "movq %%mm1, (%2, %3) \n\t"
+ "movq (%1, %3), %%mm1 \n\t"
+ "movq (%1, %%"REG_a"), %%mm0 \n\t"
+ PAVGB" 1(%1, %3), %%mm1 \n\t"
+ PAVGB" 1(%1, %%"REG_a"), %%mm0 \n\t"
+ "add %%"REG_a", %2 \n\t"
+ "add %%"REG_a", %1 \n\t"
+ PAVGB" %%mm1, %%mm2 \n\t"
+ PAVGB" %%mm0, %%mm1 \n\t"
+ PAVGB" (%2), %%mm2 \n\t"
+ PAVGB" (%2, %3), %%mm1 \n\t"
+ "movq %%mm2, (%2) \n\t"
+ "movq %%mm1, (%2, %3) \n\t"
+ "add %%"REG_a", %2 \n\t"
+ "subl $4, %0 \n\t"
+ "jnz 1b \n\t"
+ :"+g"(h), "+S"(pixels), "+D"(block)
+ :"r" ((long)line_size)
+ :"%"REG_a, "memory");
+}
+
+//FIXME the following could be optimized too ...
+static void DEF(put_no_rnd_pixels16_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
+ DEF(put_no_rnd_pixels8_x2)(block , pixels , line_size, h);
+ DEF(put_no_rnd_pixels8_x2)(block+8, pixels+8, line_size, h);
+}
+static void DEF(put_pixels16_y2)(uint8_t *block, const uint8_t *pixels, int 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_no_rnd_pixels16_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
+ DEF(put_no_rnd_pixels8_y2)(block , pixels , line_size, h);
+ DEF(put_no_rnd_pixels8_y2)(block+8, pixels+8, line_size, h);
+}
+static void DEF(avg_pixels16)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
+ DEF(avg_pixels8)(block , pixels , line_size, h);
+ DEF(avg_pixels8)(block+8, pixels+8, line_size, h);
+}
+static void DEF(avg_pixels16_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h){
+ DEF(avg_pixels8_x2)(block , pixels , line_size, h);
+ DEF(avg_pixels8_x2)(block+8, pixels+8, line_size, h);
+}
+static void DEF(avg_pixels16_y2)(uint8_t *block, const uint8_t *pixels, int 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, int line_size, int h){
+ DEF(avg_pixels8_xy2)(block , pixels , line_size, h);
+ DEF(avg_pixels8_xy2)(block+8, pixels+8, line_size, h);
+}
+
+#define QPEL_2TAP_L3(OPNAME) \
+static void DEF(OPNAME ## 2tap_qpel16_l3)(uint8_t *dst, uint8_t *src, int stride, int h, int off1, int off2){\
+ asm volatile(\
+ "1: \n\t"\
+ "movq (%1,%2), %%mm0 \n\t"\
+ "movq 8(%1,%2), %%mm1 \n\t"\
+ PAVGB" (%1,%3), %%mm0 \n\t"\
+ PAVGB" 8(%1,%3), %%mm1 \n\t"\
+ PAVGB" (%1), %%mm0 \n\t"\
+ PAVGB" 8(%1), %%mm1 \n\t"\
+ STORE_OP( (%1,%4),%%mm0)\
+ STORE_OP(8(%1,%4),%%mm1)\
+ "movq %%mm0, (%1,%4) \n\t"\
+ "movq %%mm1, 8(%1,%4) \n\t"\
+ "add %5, %1 \n\t"\
+ "decl %0 \n\t"\
+ "jnz 1b \n\t"\
+ :"+g"(h), "+r"(src)\
+ :"r"((long)off1), "r"((long)off2),\
+ "r"((long)(dst-src)), "r"((long)stride)\
+ :"memory"\
+ );\
+}\
+static void DEF(OPNAME ## 2tap_qpel8_l3)(uint8_t *dst, uint8_t *src, int stride, int h, int off1, int off2){\
+ asm volatile(\
+ "1: \n\t"\
+ "movq (%1,%2), %%mm0 \n\t"\
+ PAVGB" (%1,%3), %%mm0 \n\t"\
+ PAVGB" (%1), %%mm0 \n\t"\
+ STORE_OP((%1,%4),%%mm0)\
+ "movq %%mm0, (%1,%4) \n\t"\
+ "add %5, %1 \n\t"\
+ "decl %0 \n\t"\
+ "jnz 1b \n\t"\
+ :"+g"(h), "+r"(src)\
+ :"r"((long)off1), "r"((long)off2),\
+ "r"((long)(dst-src)), "r"((long)stride)\
+ :"memory"\
+ );\
+}
+
+#define STORE_OP(a,b) PAVGB" "#a","#b" \n\t"
+QPEL_2TAP_L3(avg_)
+#undef STORE_OP
+#define STORE_OP(a,b)
+QPEL_2TAP_L3(put_)
+#undef STORE_OP
+#undef QPEL_2TAP_L3
diff --git a/contrib/ffmpeg/libavcodec/i386/dsputil_mmx_rnd.h b/contrib/ffmpeg/libavcodec/i386/dsputil_mmx_rnd.h
new file mode 100644
index 000000000..f53b34662
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/dsputil_mmx_rnd.h
@@ -0,0 +1,592 @@
+/*
+ * DSP utils mmx functions are compiled twice for rnd/no_rnd
+ * Copyright (c) 2000, 2001 Fabrice Bellard.
+ * Copyright (c) 2003-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 <nickols_k@mail.ru>
+ * mostly rewritten by Michael Niedermayer <michaelni@gmx.at>
+ * and improved by Zdenek Kabelac <kabi@users.sf.net>
+ */
+
+// put_pixels
+static void DEF(put, pixels8_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ MOVQ_BFE(mm6);
+ __asm __volatile(
+ "lea (%3, %3), %%"REG_a" \n\t"
+ ASMALIGN(3)
+ "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"((long)line_size)
+ :REG_a, "memory");
+}
+
+static void attribute_unused DEF(put, pixels8_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
+{
+ MOVQ_BFE(mm6);
+ __asm __volatile(
+ "testl $1, %0 \n\t"
+ " jz 1f \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq (%2), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ "add $8, %2 \n\t"
+ PAVGB(%%mm0, %%mm1, %%mm4, %%mm6)
+ "movq %%mm4, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "decl %0 \n\t"
+ ASMALIGN(3)
+ "1: \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq (%2), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ "movq (%1), %%mm2 \n\t"
+ "movq 8(%2), %%mm3 \n\t"
+ "add %4, %1 \n\t"
+ PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5)
+ "movq %%mm4, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "movq %%mm5, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq 16(%2), %%mm1 \n\t"
+ "add %4, %1 \n\t"
+ "movq (%1), %%mm2 \n\t"
+ "movq 24(%2), %%mm3 \n\t"
+ "add %4, %1 \n\t"
+ "add $32, %2 \n\t"
+ PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5)
+ "movq %%mm4, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "movq %%mm5, (%3) \n\t"
+ "add %5, %3 \n\t"
+ "subl $4, %0 \n\t"
+ "jnz 1b \n\t"
+#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cant be used
+ :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#else
+ :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#endif
+ :"S"((long)src1Stride), "D"((long)dstStride)
+ :"memory");
+}
+
+static void DEF(put, pixels16_x2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ MOVQ_BFE(mm6);
+ __asm __volatile(
+ "lea (%3, %3), %%"REG_a" \n\t"
+ ASMALIGN(3)
+ "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"((long)line_size)
+ :REG_a, "memory");
+}
+
+static void attribute_unused DEF(put, pixels16_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
+{
+ MOVQ_BFE(mm6);
+ __asm __volatile(
+ "testl $1, %0 \n\t"
+ " jz 1f \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq (%2), %%mm1 \n\t"
+ "movq 8(%1), %%mm2 \n\t"
+ "movq 8(%2), %%mm3 \n\t"
+ "add %4, %1 \n\t"
+ "add $16, %2 \n\t"
+ PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5)
+ "movq %%mm4, (%3) \n\t"
+ "movq %%mm5, 8(%3) \n\t"
+ "add %5, %3 \n\t"
+ "decl %0 \n\t"
+ ASMALIGN(3)
+ "1: \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq (%2), %%mm1 \n\t"
+ "movq 8(%1), %%mm2 \n\t"
+ "movq 8(%2), %%mm3 \n\t"
+ "add %4, %1 \n\t"
+ PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5)
+ "movq %%mm4, (%3) \n\t"
+ "movq %%mm5, 8(%3) \n\t"
+ "add %5, %3 \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq 16(%2), %%mm1 \n\t"
+ "movq 8(%1), %%mm2 \n\t"
+ "movq 24(%2), %%mm3 \n\t"
+ "add %4, %1 \n\t"
+ PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5)
+ "movq %%mm4, (%3) \n\t"
+ "movq %%mm5, 8(%3) \n\t"
+ "add %5, %3 \n\t"
+ "add $32, %2 \n\t"
+ "subl $2, %0 \n\t"
+ "jnz 1b \n\t"
+#ifdef PIC //Note "+bm" and "+mb" are buggy too (with gcc 3.2.2 at least) and cant be used
+ :"+m"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#else
+ :"+b"(h), "+a"(src1), "+c"(src2), "+d"(dst)
+#endif
+ :"S"((long)src1Stride), "D"((long)dstStride)
+ :"memory");
+}
+
+static void DEF(put, pixels8_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ MOVQ_BFE(mm6);
+ __asm __volatile(
+ "lea (%3, %3), %%"REG_a" \n\t"
+ "movq (%1), %%mm0 \n\t"
+ ASMALIGN(3)
+ "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"((long)line_size)
+ :REG_a, "memory");
+}
+
+static void DEF(put, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, int 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"
+ ASMALIGN(3)
+ "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"((long)line_size)
+ :REG_a, "memory");
+}
+
+// avg_pixels
+static void attribute_unused DEF(avg, pixels4)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ MOVQ_BFE(mm6);
+ JUMPALIGN();
+ do {
+ __asm __volatile(
+ "movd %0, %%mm0 \n\t"
+ "movd %1, %%mm1 \n\t"
+ PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
+ "movd %%mm2, %0 \n\t"
+ :"+m"(*block)
+ :"m"(*pixels)
+ :"memory");
+ pixels += line_size;
+ block += line_size;
+ }
+ while (--h);
+}
+
+// in case more speed is needed - unroling would certainly help
+static void DEF(avg, pixels8)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ MOVQ_BFE(mm6);
+ JUMPALIGN();
+ do {
+ __asm __volatile(
+ "movq %0, %%mm0 \n\t"
+ "movq %1, %%mm1 \n\t"
+ PAVGB(%%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, int line_size, int h)
+{
+ MOVQ_BFE(mm6);
+ JUMPALIGN();
+ do {
+ __asm __volatile(
+ "movq %0, %%mm0 \n\t"
+ "movq %1, %%mm1 \n\t"
+ PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
+ "movq %%mm2, %0 \n\t"
+ "movq 8%0, %%mm0 \n\t"
+ "movq 8%1, %%mm1 \n\t"
+ PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
+ "movq %%mm2, 8%0 \n\t"
+ :"+m"(*block)
+ :"m"(*pixels)
+ :"memory");
+ pixels += line_size;
+ block += line_size;
+ }
+ while (--h);
+}
+
+static void DEF(avg, pixels8_x2)(uint8_t *block, const uint8_t *pixels, int 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)
+ PAVGB(%%mm3, %%mm2, %%mm0, %%mm6)
+ "movq %%mm0, %0 \n\t"
+ :"+m"(*block)
+ :"m"(*pixels)
+ :"memory");
+ pixels += line_size;
+ block += line_size;
+ } while (--h);
+}
+
+static __attribute__((unused)) void DEF(avg, pixels8_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
+{
+ MOVQ_BFE(mm6);
+ JUMPALIGN();
+ do {
+ __asm __volatile(
+ "movq %1, %%mm0 \n\t"
+ "movq %2, %%mm1 \n\t"
+ "movq %0, %%mm3 \n\t"
+ PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
+ PAVGB(%%mm3, %%mm2, %%mm0, %%mm6)
+ "movq %%mm0, %0 \n\t"
+ :"+m"(*dst)
+ :"m"(*src1), "m"(*src2)
+ :"memory");
+ dst += dstStride;
+ src1 += src1Stride;
+ src2 += 8;
+ } while (--h);
+}
+
+static void DEF(avg, pixels16_x2)(uint8_t *block, const uint8_t *pixels, int 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)
+ PAVGB(%%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)
+ PAVGB(%%mm3, %%mm2, %%mm0, %%mm6)
+ "movq %%mm0, 8%0 \n\t"
+ :"+m"(*block)
+ :"m"(*pixels)
+ :"memory");
+ pixels += line_size;
+ block += line_size;
+ } while (--h);
+}
+
+static __attribute__((unused)) void DEF(avg, pixels16_l2)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h)
+{
+ MOVQ_BFE(mm6);
+ JUMPALIGN();
+ do {
+ __asm __volatile(
+ "movq %1, %%mm0 \n\t"
+ "movq %2, %%mm1 \n\t"
+ "movq %0, %%mm3 \n\t"
+ PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
+ PAVGB(%%mm3, %%mm2, %%mm0, %%mm6)
+ "movq %%mm0, %0 \n\t"
+ "movq 8%1, %%mm0 \n\t"
+ "movq 8%2, %%mm1 \n\t"
+ "movq 8%0, %%mm3 \n\t"
+ PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)
+ PAVGB(%%mm3, %%mm2, %%mm0, %%mm6)
+ "movq %%mm0, 8%0 \n\t"
+ :"+m"(*dst)
+ :"m"(*src1), "m"(*src2)
+ :"memory");
+ dst += dstStride;
+ src1 += src1Stride;
+ src2 += 16;
+ } while (--h);
+}
+
+static void DEF(avg, pixels8_y2)(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ MOVQ_BFE(mm6);
+ __asm __volatile(
+ "lea (%3, %3), %%"REG_a" \n\t"
+ "movq (%1), %%mm0 \n\t"
+ ASMALIGN(3)
+ "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"
+ PAVGB(%%mm3, %%mm4, %%mm0, %%mm6)
+ "movq (%2, %3), %%mm3 \n\t"
+ PAVGB(%%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"
+ PAVGB(%%mm3, %%mm4, %%mm2, %%mm6)
+ "movq (%2, %3), %%mm3 \n\t"
+ PAVGB(%%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"((long)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, int 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"
+ ASMALIGN(3)
+ "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"
+ PAVGB(%%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"
+ PAVGB(%%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"((long)line_size)
+ :REG_a, "memory");
+}
+
+//FIXME optimize
+static void DEF(put, pixels16_y2)(uint8_t *block, const uint8_t *pixels, int 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, int 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, int 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, int 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/contrib/ffmpeg/libavcodec/i386/fdct_mmx.c b/contrib/ffmpeg/libavcodec/i386/fdct_mmx.c
new file mode 100644
index 000000000..2ffbfecf6
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/fdct_mmx.c
@@ -0,0 +1,566 @@
+/*
+ * MMX optimized forward DCT
+ * The gcc porting is Copyright (c) 2001 Fabrice Bellard.
+ * cleanup/optimizations are Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ * 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 "common.h"
+#include "../dsputil.h"
+#include "mmx.h"
+
+#define ATTR_ALIGN(align) __attribute__ ((__aligned__ (align)))
+
+//////////////////////////////////////////////////////////////////////
+//
+// 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))
+
+//concatenated table, for forward DCT transformation
+static const int16_t fdct_tg_all_16[] ATTR_ALIGN(8) = {
+ 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
+};
+
+static const int16_t ocos_4_16[4] ATTR_ALIGN(8) = {
+ 23170, 23170, 23170, 23170, //cos * (2<<15) + 0.5
+};
+
+static const int64_t fdct_one_corr ATTR_ALIGN(8) = 0x0001000100010001LL;
+
+static const int32_t fdct_r_row[2] ATTR_ALIGN(8) = {RND_FRW_ROW, RND_FRW_ROW };
+
+static struct
+{
+ const int32_t fdct_r_row_sse2[4] ATTR_ALIGN(16);
+} fdct_r_row_sse2 ATTR_ALIGN(16)=
+{{
+ RND_FRW_ROW, RND_FRW_ROW, RND_FRW_ROW, RND_FRW_ROW
+}};
+//static const long fdct_r_row_sse2[4] ATTR_ALIGN(16) = {RND_FRW_ROW, RND_FRW_ROW, RND_FRW_ROW, RND_FRW_ROW};
+
+static const int16_t tab_frw_01234567[] ATTR_ALIGN(8) = { // 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 struct
+{
+ const int16_t tab_frw_01234567_sse2[256] ATTR_ALIGN(16);
+} tab_frw_01234567_sse2 ATTR_ALIGN(16) =
+{{
+//static const int16_t tab_frw_01234567_sse2[] ATTR_ALIGN(16) = { // 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
+}};
+
+
+static always_inline void fdct_col(const int16_t *in, int16_t *out, int offset)
+{
+ movq_m2r(*(in + offset + 1 * 8), mm0);
+ movq_m2r(*(in + offset + 6 * 8), mm1);
+ movq_r2r(mm0, mm2);
+ movq_m2r(*(in + offset + 2 * 8), mm3);
+ paddsw_r2r(mm1, mm0);
+ movq_m2r(*(in + offset + 5 * 8), mm4);
+ psllw_i2r(SHIFT_FRW_COL, mm0);
+ movq_m2r(*(in + offset + 0 * 8), mm5);
+ paddsw_r2r(mm3, mm4);
+ paddsw_m2r(*(in + offset + 7 * 8), mm5);
+ psllw_i2r(SHIFT_FRW_COL, mm4);
+ movq_r2r(mm0, mm6);
+ psubsw_r2r(mm1, mm2);
+ movq_m2r(*(fdct_tg_all_16 + 4), mm1);
+ psubsw_r2r(mm4, mm0);
+ movq_m2r(*(in + offset + 3 * 8), mm7);
+ pmulhw_r2r(mm0, mm1);
+ paddsw_m2r(*(in + offset + 4 * 8), mm7);
+ psllw_i2r(SHIFT_FRW_COL, mm5);
+ paddsw_r2r(mm4, mm6);
+ psllw_i2r(SHIFT_FRW_COL, mm7);
+ movq_r2r(mm5, mm4);
+ psubsw_r2r(mm7, mm5);
+ paddsw_r2r(mm5, mm1);
+ paddsw_r2r(mm7, mm4);
+ por_m2r(fdct_one_corr, mm1);
+ psllw_i2r(SHIFT_FRW_COL + 1, mm2);
+ pmulhw_m2r(*(fdct_tg_all_16 + 4), mm5);
+ movq_r2r(mm4, mm7);
+ psubsw_m2r(*(in + offset + 5 * 8), mm3);
+ psubsw_r2r(mm6, mm4);
+ movq_r2m(mm1, *(out + offset + 2 * 8));
+ paddsw_r2r(mm6, mm7);
+ movq_m2r(*(in + offset + 3 * 8), mm1);
+ psllw_i2r(SHIFT_FRW_COL + 1, mm3);
+ psubsw_m2r(*(in + offset + 4 * 8), mm1);
+ movq_r2r(mm2, mm6);
+ movq_r2m(mm4, *(out + offset + 4 * 8));
+ paddsw_r2r(mm3, mm2);
+ pmulhw_m2r(*ocos_4_16, mm2);
+ psubsw_r2r(mm3, mm6);
+ pmulhw_m2r(*ocos_4_16, mm6);
+ psubsw_r2r(mm0, mm5);
+ por_m2r(fdct_one_corr, mm5);
+ psllw_i2r(SHIFT_FRW_COL, mm1);
+ por_m2r(fdct_one_corr, mm2);
+ movq_r2r(mm1, mm4);
+ movq_m2r(*(in + offset + 0 * 8), mm3);
+ paddsw_r2r(mm6, mm1);
+ psubsw_m2r(*(in + offset + 7 * 8), mm3);
+ psubsw_r2r(mm6, mm4);
+ movq_m2r(*(fdct_tg_all_16 + 0), mm0);
+ psllw_i2r(SHIFT_FRW_COL, mm3);
+ movq_m2r(*(fdct_tg_all_16 + 8), mm6);
+ pmulhw_r2r(mm1, mm0);
+ movq_r2m(mm7, *(out + offset + 0 * 8));
+ pmulhw_r2r(mm4, mm6);
+ movq_r2m(mm5, *(out + offset + 6 * 8));
+ movq_r2r(mm3, mm7);
+ movq_m2r(*(fdct_tg_all_16 + 8), mm5);
+ psubsw_r2r(mm2, mm7);
+ paddsw_r2r(mm2, mm3);
+ pmulhw_r2r(mm7, mm5);
+ paddsw_r2r(mm3, mm0);
+ paddsw_r2r(mm4, mm6);
+ pmulhw_m2r(*(fdct_tg_all_16 + 0), mm3);
+ por_m2r(fdct_one_corr, mm0);
+ paddsw_r2r(mm7, mm5);
+ psubsw_r2r(mm6, mm7);
+ movq_r2m(mm0, *(out + offset + 1 * 8));
+ paddsw_r2r(mm4, mm5);
+ movq_r2m(mm7, *(out + offset + 3 * 8));
+ psubsw_r2r(mm1, mm3);
+ movq_r2m(mm5, *(out + offset + 5 * 8));
+ movq_r2m(mm3, *(out + offset + 7 * 8));
+}
+
+
+static 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)
+ );
+}
+
+static always_inline void fdct_row_mmx2(const int16_t *in, int16_t *out, const int16_t *table)
+{
+ pshufw_m2r(*(in + 4), mm5, 0x1B);
+ movq_m2r(*(in + 0), mm0);
+ movq_r2r(mm0, mm1);
+ paddsw_r2r(mm5, mm0);
+ psubsw_r2r(mm5, mm1);
+ movq_r2r(mm0, mm2);
+ punpckldq_r2r(mm1, mm0);
+ punpckhdq_r2r(mm1, mm2);
+ movq_m2r(*(table + 0), mm1);
+ movq_m2r(*(table + 4), mm3);
+ movq_m2r(*(table + 8), mm4);
+ movq_m2r(*(table + 12), mm5);
+ movq_m2r(*(table + 16), mm6);
+ movq_m2r(*(table + 20), mm7);
+ pmaddwd_r2r(mm0, mm1);
+ pmaddwd_r2r(mm2, mm3);
+ pmaddwd_r2r(mm0, mm4);
+ pmaddwd_r2r(mm2, mm5);
+ pmaddwd_r2r(mm0, mm6);
+ pmaddwd_r2r(mm2, mm7);
+ pmaddwd_m2r(*(table + 24), mm0);
+ pmaddwd_m2r(*(table + 28), mm2);
+ paddd_r2r(mm1, mm3);
+ paddd_r2r(mm4, mm5);
+ paddd_r2r(mm6, mm7);
+ paddd_r2r(mm0, mm2);
+ movq_m2r(*fdct_r_row, mm0);
+ paddd_r2r(mm0, mm3);
+ paddd_r2r(mm0, mm5);
+ paddd_r2r(mm0, mm7);
+ paddd_r2r(mm0, mm2);
+ psrad_i2r(SHIFT_FRW_ROW, mm3);
+ psrad_i2r(SHIFT_FRW_ROW, mm5);
+ psrad_i2r(SHIFT_FRW_ROW, mm7);
+ psrad_i2r(SHIFT_FRW_ROW, mm2);
+ packssdw_r2r(mm5, mm3);
+ packssdw_r2r(mm2, mm7);
+ movq_r2m(mm3, *(out + 0));
+ movq_r2m(mm7, *(out + 4));
+}
+
+static always_inline void fdct_row_mmx(const int16_t *in, int16_t *out, const int16_t *table)
+{
+//FIXME reorder (i dont have a old mmx only cpu here to benchmark ...)
+ movd_m2r(*(in + 6), mm1);
+ punpcklwd_m2r(*(in + 4), mm1);
+ movq_r2r(mm1, mm2);
+ psrlq_i2r(0x20, mm1);
+ movq_m2r(*(in + 0), mm0);
+ punpcklwd_r2r(mm2, mm1);
+ movq_r2r(mm0, mm5);
+ paddsw_r2r(mm1, mm0);
+ psubsw_r2r(mm1, mm5);
+ movq_r2r(mm0, mm2);
+ punpckldq_r2r(mm5, mm0);
+ punpckhdq_r2r(mm5, mm2);
+ movq_m2r(*(table + 0), mm1);
+ movq_m2r(*(table + 4), mm3);
+ movq_m2r(*(table + 8), mm4);
+ movq_m2r(*(table + 12), mm5);
+ movq_m2r(*(table + 16), mm6);
+ movq_m2r(*(table + 20), mm7);
+ pmaddwd_r2r(mm0, mm1);
+ pmaddwd_r2r(mm2, mm3);
+ pmaddwd_r2r(mm0, mm4);
+ pmaddwd_r2r(mm2, mm5);
+ pmaddwd_r2r(mm0, mm6);
+ pmaddwd_r2r(mm2, mm7);
+ pmaddwd_m2r(*(table + 24), mm0);
+ pmaddwd_m2r(*(table + 28), mm2);
+ paddd_r2r(mm1, mm3);
+ paddd_r2r(mm4, mm5);
+ paddd_r2r(mm6, mm7);
+ paddd_r2r(mm0, mm2);
+ movq_m2r(*fdct_r_row, mm0);
+ paddd_r2r(mm0, mm3);
+ paddd_r2r(mm0, mm5);
+ paddd_r2r(mm0, mm7);
+ paddd_r2r(mm0, mm2);
+ psrad_i2r(SHIFT_FRW_ROW, mm3);
+ psrad_i2r(SHIFT_FRW_ROW, mm5);
+ psrad_i2r(SHIFT_FRW_ROW, mm7);
+ psrad_i2r(SHIFT_FRW_ROW, mm2);
+ packssdw_r2r(mm5, mm3);
+ packssdw_r2r(mm2, mm7);
+ movq_r2m(mm3, *(out + 0));
+ movq_r2m(mm7, *(out + 4));
+}
+
+void ff_fdct_mmx(int16_t *block)
+{
+ int64_t align_tmp[16] ATTR_ALIGN(8);
+ int16_t * block1= (int16_t*)align_tmp;
+ const int16_t *table= tab_frw_01234567;
+ int i;
+
+ fdct_col(block, block1, 0);
+ fdct_col(block, block1, 4);
+
+ for(i=8;i>0;i--) {
+ fdct_row_mmx(block1, block, table);
+ block1 += 8;
+ table += 32;
+ block += 8;
+ }
+}
+
+void ff_fdct_mmx2(int16_t *block)
+{
+ int64_t align_tmp[16] ATTR_ALIGN(8);
+ int16_t *block1= (int16_t*)align_tmp;
+ const int16_t *table= tab_frw_01234567;
+ int i;
+
+ fdct_col(block, block1, 0);
+ fdct_col(block, block1, 4);
+
+ for(i=8;i>0;i--) {
+ fdct_row_mmx2(block1, block, table);
+ block1 += 8;
+ table += 32;
+ block += 8;
+ }
+}
+
+void ff_fdct_sse2(int16_t *block)
+{
+ int64_t align_tmp[16] ATTR_ALIGN(16);
+ int16_t * const block1= (int16_t*)align_tmp;
+
+ fdct_col(block, block1, 0);
+ fdct_col(block, block1, 4);
+
+ fdct_row_sse2(block1, block);
+}
+
diff --git a/contrib/ffmpeg/libavcodec/i386/fft_3dn.c b/contrib/ffmpeg/libavcodec/i386/fft_3dn.c
new file mode 100644
index 000000000..8087f1932
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/fft_3dn.c
@@ -0,0 +1,125 @@
+/*
+ * FFT/MDCT transform with 3DNow! optimizations
+ * Copyright (c) 2006 Zuxy MENG Jie, Loren Merritt
+ * Based on fft_sse.c 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 "../dsputil.h"
+
+static const int p1m1[2] __attribute__((aligned(8))) =
+ { 0, 1 << 31 };
+
+static const int m1p1[2] __attribute__((aligned(8))) =
+ { 1 << 31, 0 };
+
+void ff_fft_calc_3dn(FFTContext *s, FFTComplex *z)
+{
+ int ln = s->nbits;
+ long i, j;
+ long nblocks, nloops;
+ FFTComplex *p, *cptr;
+
+ asm volatile(
+ /* FEMMS is not a must here but recommended by AMD */
+ "femms \n\t"
+ "movq %0, %%mm7 \n\t"
+ ::"m"(*(s->inverse ? m1p1 : p1m1))
+ );
+
+ i = 8 << ln;
+ asm volatile(
+ "1: \n\t"
+ "sub $32, %0 \n\t"
+ "movq (%0,%1), %%mm0 \n\t"
+ "movq 16(%0,%1), %%mm1 \n\t"
+ "movq 8(%0,%1), %%mm2 \n\t"
+ "movq 24(%0,%1), %%mm3 \n\t"
+ "movq %%mm0, %%mm4 \n\t"
+ "movq %%mm1, %%mm5 \n\t"
+ "pfadd %%mm2, %%mm0 \n\t"
+ "pfadd %%mm3, %%mm1 \n\t"
+ "pfsub %%mm2, %%mm4 \n\t"
+ "pfsub %%mm3, %%mm5 \n\t"
+ "movq %%mm0, %%mm2 \n\t"
+ "punpckldq %%mm5, %%mm6 \n\t"
+ "punpckhdq %%mm6, %%mm5 \n\t"
+ "movq %%mm4, %%mm3 \n\t"
+ "pxor %%mm7, %%mm5 \n\t"
+ "pfadd %%mm1, %%mm0 \n\t"
+ "pfadd %%mm5, %%mm4 \n\t"
+ "pfsub %%mm1, %%mm2 \n\t"
+ "pfsub %%mm5, %%mm3 \n\t"
+ "movq %%mm0, (%0,%1) \n\t"
+ "movq %%mm4, 8(%0,%1) \n\t"
+ "movq %%mm2, 16(%0,%1) \n\t"
+ "movq %%mm3, 24(%0,%1) \n\t"
+ "jg 1b \n\t"
+ :"+r"(i)
+ :"r"(z)
+ );
+ /* pass 2 .. ln-1 */
+
+ nblocks = 1 << (ln-3);
+ nloops = 1 << 2;
+ cptr = s->exptab1;
+ do {
+ p = z;
+ j = nblocks;
+ do {
+ i = nloops*8;
+ asm volatile(
+ "1: \n\t"
+ "sub $16, %0 \n\t"
+ "movq (%1,%0), %%mm0 \n\t"
+ "movq 8(%1,%0), %%mm1 \n\t"
+ "movq (%2,%0), %%mm2 \n\t"
+ "movq 8(%2,%0), %%mm3 \n\t"
+ "movq %%mm2, %%mm4 \n\t"
+ "movq %%mm3, %%mm5 \n\t"
+ "punpckldq %%mm2, %%mm2 \n\t"
+ "punpckldq %%mm3, %%mm3 \n\t"
+ "punpckhdq %%mm4, %%mm4 \n\t"
+ "punpckhdq %%mm5, %%mm5 \n\t"
+ "pfmul (%3,%0,2), %%mm2 \n\t" // cre*re cim*re
+ "pfmul 8(%3,%0,2), %%mm3 \n\t"
+ "pfmul 16(%3,%0,2), %%mm4 \n\t" // -cim*im cre*im
+ "pfmul 24(%3,%0,2), %%mm5 \n\t"
+ "pfadd %%mm2, %%mm4 \n\t" // cre*re-cim*im cim*re+cre*im
+ "pfadd %%mm3, %%mm5 \n\t"
+ "movq %%mm0, %%mm2 \n\t"
+ "movq %%mm1, %%mm3 \n\t"
+ "pfadd %%mm4, %%mm0 \n\t"
+ "pfadd %%mm5, %%mm1 \n\t"
+ "pfsub %%mm4, %%mm2 \n\t"
+ "pfsub %%mm5, %%mm3 \n\t"
+ "movq %%mm0, (%1,%0) \n\t"
+ "movq %%mm1, 8(%1,%0) \n\t"
+ "movq %%mm2, (%2,%0) \n\t"
+ "movq %%mm3, 8(%2,%0) \n\t"
+ "jg 1b \n\t"
+ :"+r"(i)
+ :"r"(p), "r"(p + nloops), "r"(cptr)
+ );
+ p += nloops*2;
+ } while (--j);
+ cptr += nloops*2;
+ nblocks >>= 1;
+ nloops <<= 1;
+ } while (nblocks != 0);
+ asm volatile("femms");
+}
diff --git a/contrib/ffmpeg/libavcodec/i386/fft_3dn2.c b/contrib/ffmpeg/libavcodec/i386/fft_3dn2.c
new file mode 100644
index 000000000..a4fe5f0b6
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/fft_3dn2.c
@@ -0,0 +1,210 @@
+/*
+ * FFT/MDCT transform with Extended 3DNow! optimizations
+ * Copyright (c) 2006 Zuxy MENG Jie, Loren Merritt
+ * Based on fft_sse.c 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 "../dsputil.h"
+
+static const int p1m1[2] __attribute__((aligned(8))) =
+ { 0, 1 << 31 };
+
+static const int m1p1[2] __attribute__((aligned(8))) =
+ { 1 << 31, 0 };
+
+void ff_fft_calc_3dn2(FFTContext *s, FFTComplex *z)
+{
+ int ln = s->nbits;
+ long i, j;
+ long nblocks, nloops;
+ FFTComplex *p, *cptr;
+
+ asm volatile(
+ /* FEMMS is not a must here but recommended by AMD */
+ "femms \n\t"
+ "movq %0, %%mm7 \n\t"
+ ::"m"(*(s->inverse ? m1p1 : p1m1))
+ );
+
+ i = 8 << ln;
+ asm volatile(
+ "1: \n\t"
+ "sub $32, %0 \n\t"
+ "movq (%0,%1), %%mm0 \n\t"
+ "movq 16(%0,%1), %%mm1 \n\t"
+ "movq 8(%0,%1), %%mm2 \n\t"
+ "movq 24(%0,%1), %%mm3 \n\t"
+ "movq %%mm0, %%mm4 \n\t"
+ "movq %%mm1, %%mm5 \n\t"
+ "pfadd %%mm2, %%mm0 \n\t"
+ "pfadd %%mm3, %%mm1 \n\t"
+ "pfsub %%mm2, %%mm4 \n\t"
+ "pfsub %%mm3, %%mm5 \n\t"
+ "movq %%mm0, %%mm2 \n\t"
+ "pswapd %%mm5, %%mm5 \n\t"
+ "movq %%mm4, %%mm3 \n\t"
+ "pxor %%mm7, %%mm5 \n\t"
+ "pfadd %%mm1, %%mm0 \n\t"
+ "pfadd %%mm5, %%mm4 \n\t"
+ "pfsub %%mm1, %%mm2 \n\t"
+ "pfsub %%mm5, %%mm3 \n\t"
+ "movq %%mm0, (%0,%1) \n\t"
+ "movq %%mm4, 8(%0,%1) \n\t"
+ "movq %%mm2, 16(%0,%1) \n\t"
+ "movq %%mm3, 24(%0,%1) \n\t"
+ "jg 1b \n\t"
+ :"+r"(i)
+ :"r"(z)
+ );
+ /* pass 2 .. ln-1 */
+
+ nblocks = 1 << (ln-3);
+ nloops = 1 << 2;
+ cptr = s->exptab1;
+ do {
+ p = z;
+ j = nblocks;
+ do {
+ i = nloops*8;
+ asm volatile(
+ "1: \n\t"
+ "sub $16, %0 \n\t"
+ "movq (%1,%0), %%mm0 \n\t"
+ "movq 8(%1,%0), %%mm1 \n\t"
+ "movq (%2,%0), %%mm2 \n\t"
+ "movq 8(%2,%0), %%mm3 \n\t"
+ "movq (%3,%0,2), %%mm4 \n\t"
+ "movq 8(%3,%0,2), %%mm5 \n\t"
+ "pswapd %%mm4, %%mm6 \n\t" // no need for cptr[2] & cptr[3]
+ "pswapd %%mm5, %%mm7 \n\t"
+ "pfmul %%mm2, %%mm4 \n\t" // cre*re cim*im
+ "pfmul %%mm3, %%mm5 \n\t"
+ "pfmul %%mm2, %%mm6 \n\t" // cim*re cre*im
+ "pfmul %%mm3, %%mm7 \n\t"
+ "pfpnacc %%mm6, %%mm4 \n\t" // cre*re-cim*im cim*re+cre*im
+ "pfpnacc %%mm7, %%mm5 \n\t"
+ "movq %%mm0, %%mm2 \n\t"
+ "movq %%mm1, %%mm3 \n\t"
+ "pfadd %%mm4, %%mm0 \n\t"
+ "pfadd %%mm5, %%mm1 \n\t"
+ "pfsub %%mm4, %%mm2 \n\t"
+ "pfsub %%mm5, %%mm3 \n\t"
+ "movq %%mm0, (%1,%0) \n\t"
+ "movq %%mm1, 8(%1,%0) \n\t"
+ "movq %%mm2, (%2,%0) \n\t"
+ "movq %%mm3, 8(%2,%0) \n\t"
+ "jg 1b \n\t"
+ :"+r"(i)
+ :"r"(p), "r"(p + nloops), "r"(cptr)
+ );
+ p += nloops*2;
+ } while (--j);
+ cptr += nloops*2;
+ nblocks >>= 1;
+ nloops <<= 1;
+ } while (nblocks != 0);
+ asm volatile("femms");
+}
+
+void ff_imdct_calc_3dn2(MDCTContext *s, FFTSample *output,
+ const FFTSample *input, FFTSample *tmp)
+{
+ long k, n8, n4, n2, n;
+ const uint16_t *revtab = s->fft.revtab;
+ const FFTSample *tcos = s->tcos;
+ const FFTSample *tsin = s->tsin;
+ const FFTSample *in1, *in2;
+ FFTComplex *z = (FFTComplex *)tmp;
+
+ n = 1 << s->nbits;
+ n2 = n >> 1;
+ n4 = n >> 2;
+ n8 = n >> 3;
+
+ /* pre rotation */
+ in1 = input;
+ in2 = input + n2 - 1;
+ for(k = 0; k < n4; k++) {
+ // FIXME a single block is faster, but gcc 2.95 and 3.4.x on 32bit can't compile it
+ asm volatile(
+ "movd %0, %%mm0 \n\t"
+ "movd %2, %%mm1 \n\t"
+ "punpckldq %1, %%mm0 \n\t"
+ "punpckldq %3, %%mm1 \n\t"
+ "movq %%mm0, %%mm2 \n\t"
+ "pfmul %%mm1, %%mm0 \n\t"
+ "pswapd %%mm1, %%mm1 \n\t"
+ "pfmul %%mm1, %%mm2 \n\t"
+ "pfpnacc %%mm2, %%mm0 \n\t"
+ ::"m"(in2[-2*k]), "m"(in1[2*k]),
+ "m"(tcos[k]), "m"(tsin[k])
+ );
+ asm volatile(
+ "movq %%mm0, %0 \n\t"
+ :"=m"(z[revtab[k]])
+ );
+ }
+
+ ff_fft_calc(&s->fft, z);
+
+ /* post rotation + reordering */
+ for(k = 0; k < n4; k++) {
+ asm volatile(
+ "movq %0, %%mm0 \n\t"
+ "movd %1, %%mm1 \n\t"
+ "punpckldq %2, %%mm1 \n\t"
+ "movq %%mm0, %%mm2 \n\t"
+ "pfmul %%mm1, %%mm0 \n\t"
+ "pswapd %%mm1, %%mm1 \n\t"
+ "pfmul %%mm1, %%mm2 \n\t"
+ "pfpnacc %%mm2, %%mm0 \n\t"
+ "movq %%mm0, %0 \n\t"
+ :"+m"(z[k])
+ :"m"(tcos[k]), "m"(tsin[k])
+ );
+ }
+
+ k = n-8;
+ asm volatile("movd %0, %%mm7" ::"r"(1<<31));
+ asm volatile(
+ "1: \n\t"
+ "movq (%4,%0), %%mm0 \n\t" // z[n8+k]
+ "neg %0 \n\t"
+ "pswapd -8(%4,%0), %%mm1 \n\t" // z[n8-1-k]
+ "movq %%mm0, %%mm2 \n\t"
+ "pxor %%mm7, %%mm2 \n\t"
+ "punpckldq %%mm1, %%mm2 \n\t"
+ "pswapd %%mm2, %%mm3 \n\t"
+ "punpckhdq %%mm1, %%mm0 \n\t"
+ "pswapd %%mm0, %%mm4 \n\t"
+ "pxor %%mm7, %%mm0 \n\t"
+ "pxor %%mm7, %%mm4 \n\t"
+ "movq %%mm3, -8(%3,%0) \n\t" // output[n-2-2*k] = { z[n8-1-k].im, -z[n8+k].re }
+ "movq %%mm4, -8(%2,%0) \n\t" // output[n2-2-2*k]= { -z[n8-1-k].re, z[n8+k].im }
+ "neg %0 \n\t"
+ "movq %%mm0, (%1,%0) \n\t" // output[2*k] = { -z[n8+k].im, z[n8-1-k].re }
+ "movq %%mm2, (%2,%0) \n\t" // output[n2+2*k] = { -z[n8+k].re, z[n8-1-k].im }
+ "sub $8, %0 \n\t"
+ "jge 1b \n\t"
+ :"+r"(k)
+ :"r"(output), "r"(output+n2), "r"(output+n), "r"(z+n8)
+ :"memory"
+ );
+ asm volatile("femms");
+}
+
diff --git a/contrib/ffmpeg/libavcodec/i386/fft_sse.c b/contrib/ffmpeg/libavcodec/i386/fft_sse.c
new file mode 100644
index 000000000..0dc0c61c1
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/fft_sse.c
@@ -0,0 +1,247 @@
+/*
+ * FFT/MDCT transform with SSE optimizations
+ * 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 "../dsputil.h"
+
+static const int p1p1p1m1[4] __attribute__((aligned(16))) =
+ { 0, 0, 0, 1 << 31 };
+
+static const int p1p1m1p1[4] __attribute__((aligned(16))) =
+ { 0, 0, 1 << 31, 0 };
+
+static const int p1p1m1m1[4] __attribute__((aligned(16))) =
+ { 0, 0, 1 << 31, 1 << 31 };
+
+static const int p1m1p1m1[4] __attribute__((aligned(16))) =
+ { 0, 1 << 31, 0, 1 << 31 };
+
+static const int m1m1m1m1[4] __attribute__((aligned(16))) =
+ { 1 << 31, 1 << 31, 1 << 31, 1 << 31 };
+
+#if 0
+static void print_v4sf(const char *str, __m128 a)
+{
+ float *p = (float *)&a;
+ printf("%s: %f %f %f %f\n",
+ str, p[0], p[1], p[2], p[3]);
+}
+#endif
+
+/* XXX: handle reverse case */
+void ff_fft_calc_sse(FFTContext *s, FFTComplex *z)
+{
+ int ln = s->nbits;
+ long i, j;
+ long nblocks, nloops;
+ FFTComplex *p, *cptr;
+
+ asm volatile(
+ "movaps %0, %%xmm4 \n\t"
+ "movaps %1, %%xmm5 \n\t"
+ ::"m"(*p1p1m1m1),
+ "m"(*(s->inverse ? p1p1m1p1 : p1p1p1m1))
+ );
+
+ i = 8 << ln;
+ asm volatile(
+ "1: \n\t"
+ "sub $32, %0 \n\t"
+ /* do the pass 0 butterfly */
+ "movaps (%0,%1), %%xmm0 \n\t"
+ "movaps %%xmm0, %%xmm1 \n\t"
+ "shufps $0x4E, %%xmm0, %%xmm0 \n\t"
+ "xorps %%xmm4, %%xmm1 \n\t"
+ "addps %%xmm1, %%xmm0 \n\t"
+ "movaps 16(%0,%1), %%xmm2 \n\t"
+ "movaps %%xmm2, %%xmm3 \n\t"
+ "shufps $0x4E, %%xmm2, %%xmm2 \n\t"
+ "xorps %%xmm4, %%xmm3 \n\t"
+ "addps %%xmm3, %%xmm2 \n\t"
+ /* multiply third by -i */
+ /* by toggling the sign bit */
+ "shufps $0xB4, %%xmm2, %%xmm2 \n\t"
+ "xorps %%xmm5, %%xmm2 \n\t"
+ /* do the pass 1 butterfly */
+ "movaps %%xmm0, %%xmm1 \n\t"
+ "addps %%xmm2, %%xmm0 \n\t"
+ "subps %%xmm2, %%xmm1 \n\t"
+ "movaps %%xmm0, (%0,%1) \n\t"
+ "movaps %%xmm1, 16(%0,%1) \n\t"
+ "jg 1b \n\t"
+ :"+r"(i)
+ :"r"(z)
+ );
+ /* pass 2 .. ln-1 */
+
+ nblocks = 1 << (ln-3);
+ nloops = 1 << 2;
+ cptr = s->exptab1;
+ do {
+ p = z;
+ j = nblocks;
+ do {
+ i = nloops*8;
+ asm volatile(
+ "1: \n\t"
+ "sub $16, %0 \n\t"
+ "movaps (%2,%0), %%xmm1 \n\t"
+ "movaps (%1,%0), %%xmm0 \n\t"
+ "movaps %%xmm1, %%xmm2 \n\t"
+ "shufps $0xA0, %%xmm1, %%xmm1 \n\t"
+ "shufps $0xF5, %%xmm2, %%xmm2 \n\t"
+ "mulps (%3,%0,2), %%xmm1 \n\t" // cre*re cim*re
+ "mulps 16(%3,%0,2), %%xmm2 \n\t" // -cim*im cre*im
+ "addps %%xmm2, %%xmm1 \n\t"
+ "movaps %%xmm0, %%xmm3 \n\t"
+ "addps %%xmm1, %%xmm0 \n\t"
+ "subps %%xmm1, %%xmm3 \n\t"
+ "movaps %%xmm0, (%1,%0) \n\t"
+ "movaps %%xmm3, (%2,%0) \n\t"
+ "jg 1b \n\t"
+ :"+r"(i)
+ :"r"(p), "r"(p + nloops), "r"(cptr)
+ );
+ p += nloops*2;
+ } while (--j);
+ cptr += nloops*2;
+ nblocks >>= 1;
+ nloops <<= 1;
+ } while (nblocks != 0);
+}
+
+void ff_imdct_calc_sse(MDCTContext *s, FFTSample *output,
+ const FFTSample *input, FFTSample *tmp)
+{
+ long k, n8, n4, n2, n;
+ const uint16_t *revtab = s->fft.revtab;
+ const FFTSample *tcos = s->tcos;
+ const FFTSample *tsin = s->tsin;
+ const FFTSample *in1, *in2;
+ FFTComplex *z = (FFTComplex *)tmp;
+
+ n = 1 << s->nbits;
+ n2 = n >> 1;
+ n4 = n >> 2;
+ n8 = n >> 3;
+
+ asm volatile ("movaps %0, %%xmm7\n\t"::"m"(*p1m1p1m1));
+
+ /* pre rotation */
+ in1 = input;
+ in2 = input + n2 - 4;
+
+ /* Complex multiplication
+ Two complex products per iteration, we could have 4 with 8 xmm
+ registers, 8 with 16 xmm registers.
+ Maybe we should unroll more.
+ */
+ for (k = 0; k < n4; k += 2) {
+ asm volatile (
+ "movaps %0, %%xmm0 \n\t" // xmm0 = r0 X r1 X : in2
+ "movaps %1, %%xmm3 \n\t" // xmm3 = X i1 X i0: in1
+ "movlps %2, %%xmm1 \n\t" // xmm1 = X X R1 R0: tcos
+ "movlps %3, %%xmm2 \n\t" // xmm2 = X X I1 I0: tsin
+ "shufps $95, %%xmm0, %%xmm0 \n\t" // xmm0 = r1 r1 r0 r0
+ "shufps $160,%%xmm3, %%xmm3 \n\t" // xmm3 = i1 i1 i0 i0
+ "unpcklps %%xmm2, %%xmm1 \n\t" // xmm1 = I1 R1 I0 R0
+ "movaps %%xmm1, %%xmm2 \n\t" // xmm2 = I1 R1 I0 R0
+ "xorps %%xmm7, %%xmm2 \n\t" // xmm2 = -I1 R1 -I0 R0
+ "mulps %%xmm1, %%xmm0 \n\t" // xmm0 = rI rR rI rR
+ "shufps $177,%%xmm2, %%xmm2 \n\t" // xmm2 = R1 -I1 R0 -I0
+ "mulps %%xmm2, %%xmm3 \n\t" // xmm3 = Ri -Ii Ri -Ii
+ "addps %%xmm3, %%xmm0 \n\t" // xmm0 = result
+ ::"m"(in2[-2*k]), "m"(in1[2*k]),
+ "m"(tcos[k]), "m"(tsin[k])
+ );
+ /* Should be in the same block, hack for gcc2.95 & gcc3 */
+ asm (
+ "movlps %%xmm0, %0 \n\t"
+ "movhps %%xmm0, %1 \n\t"
+ :"=m"(z[revtab[k]]), "=m"(z[revtab[k + 1]])
+ );
+ }
+
+ ff_fft_calc_sse(&s->fft, z);
+
+ /* Not currently needed, added for safety */
+ asm volatile ("movaps %0, %%xmm7\n\t"::"m"(*p1m1p1m1));
+
+ /* post rotation + reordering */
+ for (k = 0; k < n4; k += 2) {
+ asm (
+ "movaps %0, %%xmm0 \n\t" // xmm0 = i1 r1 i0 r0: z
+ "movlps %1, %%xmm1 \n\t" // xmm1 = X X R1 R0: tcos
+ "movaps %%xmm0, %%xmm3 \n\t" // xmm3 = i1 r1 i0 r0
+ "movlps %2, %%xmm2 \n\t" // xmm2 = X X I1 I0: tsin
+ "shufps $160,%%xmm0, %%xmm0 \n\t" // xmm0 = r1 r1 r0 r0
+ "shufps $245,%%xmm3, %%xmm3 \n\t" // xmm3 = i1 i1 i0 i0
+ "unpcklps %%xmm2, %%xmm1 \n\t" // xmm1 = I1 R1 I0 R0
+ "movaps %%xmm1, %%xmm2 \n\t" // xmm2 = I1 R1 I0 R0
+ "xorps %%xmm7, %%xmm2 \n\t" // xmm2 = -I1 R1 -I0 R0
+ "mulps %%xmm1, %%xmm0 \n\t" // xmm0 = rI rR rI rR
+ "shufps $177,%%xmm2, %%xmm2 \n\t" // xmm2 = R1 -I1 R0 -I0
+ "mulps %%xmm2, %%xmm3 \n\t" // xmm3 = Ri -Ii Ri -Ii
+ "addps %%xmm3, %%xmm0 \n\t" // xmm0 = result
+ "movaps %%xmm0, %0 \n\t"
+ :"+m"(z[k])
+ :"m"(tcos[k]), "m"(tsin[k])
+ );
+ }
+
+ /*
+ Mnemonics:
+ 0 = z[k].re
+ 1 = z[k].im
+ 2 = z[k + 1].re
+ 3 = z[k + 1].im
+ 4 = z[-k - 2].re
+ 5 = z[-k - 2].im
+ 6 = z[-k - 1].re
+ 7 = z[-k - 1].im
+ */
+ k = 16-n;
+ asm volatile("movaps %0, %%xmm7 \n\t"::"m"(*m1m1m1m1));
+ asm volatile(
+ "1: \n\t"
+ "movaps -16(%4,%0), %%xmm1 \n\t" // xmm1 = 4 5 6 7 = z[-2-k]
+ "neg %0 \n\t"
+ "movaps (%4,%0), %%xmm0 \n\t" // xmm0 = 0 1 2 3 = z[k]
+ "xorps %%xmm7, %%xmm0 \n\t" // xmm0 = -0 -1 -2 -3
+ "movaps %%xmm0, %%xmm2 \n\t" // xmm2 = -0 -1 -2 -3
+ "shufps $141,%%xmm1, %%xmm0 \n\t" // xmm0 = -1 -3 4 6
+ "shufps $216,%%xmm1, %%xmm2 \n\t" // xmm2 = -0 -2 5 7
+ "shufps $156,%%xmm0, %%xmm0 \n\t" // xmm0 = -1 6 -3 4 !
+ "shufps $156,%%xmm2, %%xmm2 \n\t" // xmm2 = -0 7 -2 5 !
+ "movaps %%xmm0, (%1,%0) \n\t" // output[2*k]
+ "movaps %%xmm2, (%2,%0) \n\t" // output[n2+2*k]
+ "neg %0 \n\t"
+ "shufps $27, %%xmm0, %%xmm0 \n\t" // xmm0 = 4 -3 6 -1
+ "xorps %%xmm7, %%xmm0 \n\t" // xmm0 = -4 3 -6 1 !
+ "shufps $27, %%xmm2, %%xmm2 \n\t" // xmm2 = 5 -2 7 -0 !
+ "movaps %%xmm0, -16(%2,%0) \n\t" // output[n2-4-2*k]
+ "movaps %%xmm2, -16(%3,%0) \n\t" // output[n-4-2*k]
+ "add $16, %0 \n\t"
+ "jle 1b \n\t"
+ :"+r"(k)
+ :"r"(output), "r"(output+n2), "r"(output+n), "r"(z+n8)
+ :"memory"
+ );
+}
+
diff --git a/contrib/ffmpeg/libavcodec/i386/h264dsp_mmx.c b/contrib/ffmpeg/libavcodec/i386/h264dsp_mmx.c
new file mode 100644
index 000000000..40baf199b
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/h264dsp_mmx.c
@@ -0,0 +1,1513 @@
+/*
+ * 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
+ */
+
+
+/***********************************/
+/* IDCT */
+
+/* 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"
+
+#define SUMSUB_BADC( a, b, c, d ) \
+ "paddw "#b", "#a" \n\t"\
+ "paddw "#d", "#c" \n\t"\
+ "paddw "#b", "#b" \n\t"\
+ "paddw "#d", "#d" \n\t"\
+ "psubw "#a", "#b" \n\t"\
+ "psubw "#c", "#d" \n\t"
+
+#define SUMSUBD2_AB( a, b, t ) \
+ "movq "#b", "#t" \n\t"\
+ "psraw $1 , "#b" \n\t"\
+ "paddw "#a", "#b" \n\t"\
+ "psraw $1 , "#a" \n\t"\
+ "psubw "#t", "#a" \n\t"
+
+#define IDCT4_1D( s02, s13, d02, d13, t ) \
+ SUMSUB_BA ( s02, d02 )\
+ SUMSUBD2_AB( s13, d13, t )\
+ SUMSUB_BADC( d13, s02, s13, d02 )
+
+#define TRANSPOSE4(a,b,c,d,t)\
+ SBUTTERFLY(a,b,t,wd) /* a=aebf t=cgdh */\
+ SBUTTERFLY(c,d,b,wd) /* c=imjn b=kolp */\
+ SBUTTERFLY(a,c,d,dq) /* a=aeim d=bfjn */\
+ SBUTTERFLY(t,b,c,dq) /* t=cgko c=dhlp */
+
+#define STORE_DIFF_4P( p, t, z ) \
+ "psraw $6, "#p" \n\t"\
+ "movd (%0), "#t" \n\t"\
+ "punpcklbw "#z", "#t" \n\t"\
+ "paddsw "#t", "#p" \n\t"\
+ "packuswb "#z", "#p" \n\t"\
+ "movd "#p", (%0) \n\t"
+
+static void ff_h264_idct_add_mmx(uint8_t *dst, int16_t *block, int stride)
+{
+ /* Load dct coeffs */
+ asm volatile(
+ "movq (%0), %%mm0 \n\t"
+ "movq 8(%0), %%mm1 \n\t"
+ "movq 16(%0), %%mm2 \n\t"
+ "movq 24(%0), %%mm3 \n\t"
+ :: "r"(block) );
+
+ asm volatile(
+ /* mm1=s02+s13 mm2=s02-s13 mm4=d02+d13 mm0=d02-d13 */
+ IDCT4_1D( %%mm2, %%mm1, %%mm0, %%mm3, %%mm4 )
+
+ "movq %0, %%mm6 \n\t"
+ /* in: 1,4,0,2 out: 1,2,3,0 */
+ TRANSPOSE4( %%mm3, %%mm1, %%mm0, %%mm2, %%mm4 )
+
+ "paddw %%mm6, %%mm3 \n\t"
+
+ /* mm2=s02+s13 mm3=s02-s13 mm4=d02+d13 mm1=d02-d13 */
+ IDCT4_1D( %%mm4, %%mm2, %%mm3, %%mm0, %%mm1 )
+
+ "pxor %%mm7, %%mm7 \n\t"
+ :: "m"(ff_pw_32));
+
+ asm volatile(
+ STORE_DIFF_4P( %%mm0, %%mm1, %%mm7)
+ "add %1, %0 \n\t"
+ STORE_DIFF_4P( %%mm2, %%mm1, %%mm7)
+ "add %1, %0 \n\t"
+ STORE_DIFF_4P( %%mm3, %%mm1, %%mm7)
+ "add %1, %0 \n\t"
+ STORE_DIFF_4P( %%mm4, %%mm1, %%mm7)
+ : "+r"(dst)
+ : "r" ((long)stride)
+ );
+}
+
+static inline void h264_idct8_1d(int16_t *block)
+{
+ asm volatile(
+ "movq 112(%0), %%mm7 \n\t"
+ "movq 80(%0), %%mm5 \n\t"
+ "movq 48(%0), %%mm3 \n\t"
+ "movq 16(%0), %%mm1 \n\t"
+
+ "movq %%mm7, %%mm4 \n\t"
+ "movq %%mm3, %%mm6 \n\t"
+ "movq %%mm5, %%mm0 \n\t"
+ "movq %%mm7, %%mm2 \n\t"
+ "psraw $1, %%mm4 \n\t"
+ "psraw $1, %%mm6 \n\t"
+ "psubw %%mm7, %%mm0 \n\t"
+ "psubw %%mm6, %%mm2 \n\t"
+ "psubw %%mm4, %%mm0 \n\t"
+ "psubw %%mm3, %%mm2 \n\t"
+ "psubw %%mm3, %%mm0 \n\t"
+ "paddw %%mm1, %%mm2 \n\t"
+
+ "movq %%mm5, %%mm4 \n\t"
+ "movq %%mm1, %%mm6 \n\t"
+ "psraw $1, %%mm4 \n\t"
+ "psraw $1, %%mm6 \n\t"
+ "paddw %%mm5, %%mm4 \n\t"
+ "paddw %%mm1, %%mm6 \n\t"
+ "paddw %%mm7, %%mm4 \n\t"
+ "paddw %%mm5, %%mm6 \n\t"
+ "psubw %%mm1, %%mm4 \n\t"
+ "paddw %%mm3, %%mm6 \n\t"
+
+ "movq %%mm0, %%mm1 \n\t"
+ "movq %%mm4, %%mm3 \n\t"
+ "movq %%mm2, %%mm5 \n\t"
+ "movq %%mm6, %%mm7 \n\t"
+ "psraw $2, %%mm6 \n\t"
+ "psraw $2, %%mm3 \n\t"
+ "psraw $2, %%mm5 \n\t"
+ "psraw $2, %%mm0 \n\t"
+ "paddw %%mm6, %%mm1 \n\t"
+ "paddw %%mm2, %%mm3 \n\t"
+ "psubw %%mm4, %%mm5 \n\t"
+ "psubw %%mm0, %%mm7 \n\t"
+
+ "movq 32(%0), %%mm2 \n\t"
+ "movq 96(%0), %%mm6 \n\t"
+ "movq %%mm2, %%mm4 \n\t"
+ "movq %%mm6, %%mm0 \n\t"
+ "psraw $1, %%mm4 \n\t"
+ "psraw $1, %%mm6 \n\t"
+ "psubw %%mm0, %%mm4 \n\t"
+ "paddw %%mm2, %%mm6 \n\t"
+
+ "movq (%0), %%mm2 \n\t"
+ "movq 64(%0), %%mm0 \n\t"
+ SUMSUB_BA( %%mm0, %%mm2 )
+ SUMSUB_BA( %%mm6, %%mm0 )
+ SUMSUB_BA( %%mm4, %%mm2 )
+ SUMSUB_BA( %%mm7, %%mm6 )
+ SUMSUB_BA( %%mm5, %%mm4 )
+ SUMSUB_BA( %%mm3, %%mm2 )
+ SUMSUB_BA( %%mm1, %%mm0 )
+ :: "r"(block)
+ );
+}
+
+static void ff_h264_idct8_add_mmx(uint8_t *dst, int16_t *block, int stride)
+{
+ int i;
+ int16_t __attribute__ ((aligned(8))) b2[64];
+
+ block[0] += 32;
+
+ for(i=0; i<2; i++){
+ DECLARE_ALIGNED_8(uint64_t, tmp);
+
+ h264_idct8_1d(block+4*i);
+
+ asm volatile(
+ "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++){
+ h264_idct8_1d(b2+4*i);
+
+ asm volatile(
+ "psraw $6, %%mm7 \n\t"
+ "psraw $6, %%mm6 \n\t"
+ "psraw $6, %%mm5 \n\t"
+ "psraw $6, %%mm4 \n\t"
+ "psraw $6, %%mm3 \n\t"
+ "psraw $6, %%mm2 \n\t"
+ "psraw $6, %%mm1 \n\t"
+ "psraw $6, %%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"
+ );
+ }
+
+ add_pixels_clamped_mmx(b2, dst, stride);
+}
+
+static void ff_h264_idct_dc_add_mmx2(uint8_t *dst, int16_t *block, int stride)
+{
+ int dc = (block[0] + 32) >> 6;
+ 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*)(dst+0*stride)),
+ "+m"(*(uint32_t*)(dst+1*stride)),
+ "+m"(*(uint32_t*)(dst+2*stride)),
+ "+m"(*(uint32_t*)(dst+3*stride))
+ );
+}
+
+static void ff_h264_idct8_dc_add_mmx2(uint8_t *dst, int16_t *block, int stride)
+{
+ int dc = (block[0] + 32) >> 6;
+ int y;
+ 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)
+ );
+ for(y=2; y--; dst += 4*stride){
+ 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"(*(uint64_t*)(dst+0*stride)),
+ "+m"(*(uint64_t*)(dst+1*stride)),
+ "+m"(*(uint64_t*)(dst+2*stride)),
+ "+m"(*(uint64_t*)(dst+3*stride))
+ );
+ }
+}
+
+
+/***********************************/
+/* deblocking */
+
+// out: o = |x-y|>a
+// clobbers: t
+#define DIFF_GT_MMX(x,y,a,o,t)\
+ "movq "#y", "#t" \n\t"\
+ "movq "#x", "#o" \n\t"\
+ "psubusb "#x", "#t" \n\t"\
+ "psubusb "#y", "#o" \n\t"\
+ "por "#t", "#o" \n\t"\
+ "psubusb "#a", "#o" \n\t"
+
+// out: o = |x-y|>a
+// clobbers: t
+#define DIFF_GT2_MMX(x,y,a,o,t)\
+ "movq "#y", "#t" \n\t"\
+ "movq "#x", "#o" \n\t"\
+ "psubusb "#x", "#t" \n\t"\
+ "psubusb "#y", "#o" \n\t"\
+ "psubusb "#a", "#t" \n\t"\
+ "psubusb "#a", "#o" \n\t"\
+ "pcmpeqb "#t", "#o" \n\t"\
+
+// in: mm0=p1 mm1=p0 mm2=q0 mm3=q1
+// out: mm5=beta-1, mm7=mask
+// clobbers: mm4,mm6
+#define H264_DEBLOCK_MASK(alpha1, beta1) \
+ "pshufw $0, "#alpha1", %%mm4 \n\t"\
+ "pshufw $0, "#beta1 ", %%mm5 \n\t"\
+ "packuswb %%mm4, %%mm4 \n\t"\
+ "packuswb %%mm5, %%mm5 \n\t"\
+ DIFF_GT_MMX(%%mm1, %%mm2, %%mm4, %%mm7, %%mm6) /* |p0-q0| > alpha-1 */\
+ DIFF_GT_MMX(%%mm0, %%mm1, %%mm5, %%mm4, %%mm6) /* |p1-p0| > beta-1 */\
+ "por %%mm4, %%mm7 \n\t"\
+ DIFF_GT_MMX(%%mm3, %%mm2, %%mm5, %%mm4, %%mm6) /* |q1-q0| > beta-1 */\
+ "por %%mm4, %%mm7 \n\t"\
+ "pxor %%mm6, %%mm6 \n\t"\
+ "pcmpeqb %%mm6, %%mm7 \n\t"
+
+// in: mm0=p1 mm1=p0 mm2=q0 mm3=q1 mm7=(tc&mask)
+// out: mm1=p0' mm2=q0'
+// clobbers: mm0,3-6
+#define H264_DEBLOCK_P0_Q0(pb_01, pb_3f)\
+ "movq %%mm1 , %%mm5 \n\t"\
+ "pxor %%mm2 , %%mm5 \n\t" /* p0^q0*/\
+ "pand "#pb_01" , %%mm5 \n\t" /* (p0^q0)&1*/\
+ "pcmpeqb %%mm4 , %%mm4 \n\t"\
+ "pxor %%mm4 , %%mm3 \n\t"\
+ "pavgb %%mm0 , %%mm3 \n\t" /* (p1 - q1 + 256)>>1*/\
+ "pavgb "MANGLE(ff_pb_3)" , %%mm3 \n\t" /*(((p1 - q1 + 256)>>1)+4)>>1 = 64+2+(p1-q1)>>2*/\
+ "pxor %%mm1 , %%mm4 \n\t"\
+ "pavgb %%mm2 , %%mm4 \n\t" /* (q0 - p0 + 256)>>1*/\
+ "pavgb %%mm5 , %%mm3 \n\t"\
+ "paddusb %%mm4 , %%mm3 \n\t" /* d+128+33*/\
+ "movq "MANGLE(ff_pb_A1)" , %%mm6 \n\t"\
+ "psubusb %%mm3 , %%mm6 \n\t"\
+ "psubusb "MANGLE(ff_pb_A1)" , %%mm3 \n\t"\
+ "pminub %%mm7 , %%mm6 \n\t"\
+ "pminub %%mm7 , %%mm3 \n\t"\
+ "psubusb %%mm6 , %%mm1 \n\t"\
+ "psubusb %%mm3 , %%mm2 \n\t"\
+ "paddusb %%mm3 , %%mm1 \n\t"\
+ "paddusb %%mm6 , %%mm2 \n\t"
+
+// in: mm0=p1 mm1=p0 mm2=q0 mm3=q1 mm7=(tc&mask) %8=mm_bone
+// out: (q1addr) = clip( (q2+((p0+q0+1)>>1))>>1, q1-tc0, q1+tc0 )
+// clobbers: q2, tmp, tc0
+#define H264_DEBLOCK_Q1(p1, q2, q2addr, q1addr, tc0, tmp)\
+ "movq %%mm1, "#tmp" \n\t"\
+ "pavgb %%mm2, "#tmp" \n\t"\
+ "pavgb "#tmp", "#q2" \n\t" /* avg(p2,avg(p0,q0)) */\
+ "pxor "q2addr", "#tmp" \n\t"\
+ "pand %8, "#tmp" \n\t" /* (p2^avg(p0,q0))&1 */\
+ "psubusb "#tmp", "#q2" \n\t" /* (p2+((p0+q0+1)>>1))>>1 */\
+ "movq "#p1", "#tmp" \n\t"\
+ "psubusb "#tc0", "#tmp" \n\t"\
+ "paddusb "#p1", "#tc0" \n\t"\
+ "pmaxub "#tmp", "#q2" \n\t"\
+ "pminub "#tc0", "#q2" \n\t"\
+ "movq "#q2", "q1addr" \n\t"
+
+static inline void h264_loop_filter_luma_mmx2(uint8_t *pix, int stride, int alpha1, int beta1, int8_t *tc0)
+{
+ DECLARE_ALIGNED_8(uint64_t, tmp0[2]);
+
+ asm volatile(
+ "movq (%1,%3), %%mm0 \n\t" //p1
+ "movq (%1,%3,2), %%mm1 \n\t" //p0
+ "movq (%2), %%mm2 \n\t" //q0
+ "movq (%2,%3), %%mm3 \n\t" //q1
+ H264_DEBLOCK_MASK(%6, %7)
+
+ "movd %5, %%mm4 \n\t"
+ "punpcklbw %%mm4, %%mm4 \n\t"
+ "punpcklwd %%mm4, %%mm4 \n\t"
+ "pcmpeqb %%mm3, %%mm3 \n\t"
+ "movq %%mm4, %%mm6 \n\t"
+ "pcmpgtb %%mm3, %%mm4 \n\t"
+ "movq %%mm6, 8+%0 \n\t"
+ "pand %%mm4, %%mm7 \n\t"
+ "movq %%mm7, %0 \n\t"
+
+ /* filter p1 */
+ "movq (%1), %%mm3 \n\t" //p2
+ DIFF_GT2_MMX(%%mm1, %%mm3, %%mm5, %%mm6, %%mm4) // |p2-p0|>beta-1
+ "pand %%mm7, %%mm6 \n\t" // mask & |p2-p0|<beta
+ "pand 8+%0, %%mm7 \n\t" // mask & tc0
+ "movq %%mm7, %%mm4 \n\t"
+ "psubb %%mm6, %%mm7 \n\t"
+ "pand %%mm4, %%mm6 \n\t" // mask & |p2-p0|<beta & tc0
+ H264_DEBLOCK_Q1(%%mm0, %%mm3, "(%1)", "(%1,%3)", %%mm6, %%mm4)
+
+ /* filter q1 */
+ "movq (%2,%3,2), %%mm4 \n\t" //q2
+ DIFF_GT2_MMX(%%mm2, %%mm4, %%mm5, %%mm6, %%mm3) // |q2-q0|>beta-1
+ "pand %0, %%mm6 \n\t"
+ "movq 8+%0, %%mm5 \n\t" // can be merged with the and below but is slower then
+ "pand %%mm6, %%mm5 \n\t"
+ "psubb %%mm6, %%mm7 \n\t"
+ "movq (%2,%3), %%mm3 \n\t"
+ H264_DEBLOCK_Q1(%%mm3, %%mm4, "(%2,%3,2)", "(%2,%3)", %%mm5, %%mm6)
+
+ /* filter p0, q0 */
+ H264_DEBLOCK_P0_Q0(%8, unused)
+ "movq %%mm1, (%1,%3,2) \n\t"
+ "movq %%mm2, (%2) \n\t"
+
+ : "=m"(*tmp0)
+ : "r"(pix-3*stride), "r"(pix), "r"((long)stride),
+ "m"(*tmp0/*unused*/), "m"(*(uint32_t*)tc0), "m"(alpha1), "m"(beta1),
+ "m"(mm_bone)
+ );
+}
+
+static void h264_v_loop_filter_luma_mmx2(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0)
+{
+ if((tc0[0] & tc0[1]) >= 0)
+ h264_loop_filter_luma_mmx2(pix, stride, alpha-1, beta-1, tc0);
+ if((tc0[2] & tc0[3]) >= 0)
+ h264_loop_filter_luma_mmx2(pix+8, stride, alpha-1, beta-1, tc0+2);
+}
+static void h264_h_loop_filter_luma_mmx2(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0)
+{
+ //FIXME: could cut some load/stores by merging transpose with filter
+ // also, it only needs to transpose 6x8
+ DECLARE_ALIGNED_8(uint8_t, trans[8*8]);
+ int i;
+ for(i=0; i<2; i++, pix+=8*stride, tc0+=2) {
+ if((tc0[0] & tc0[1]) < 0)
+ continue;
+ transpose4x4(trans, pix-4, 8, stride);
+ transpose4x4(trans +4*8, pix, 8, stride);
+ transpose4x4(trans+4, pix-4+4*stride, 8, stride);
+ transpose4x4(trans+4+4*8, pix +4*stride, 8, stride);
+ h264_loop_filter_luma_mmx2(trans+4*8, 8, alpha-1, beta-1, tc0);
+ transpose4x4(pix-2, trans +2*8, stride, 8);
+ transpose4x4(pix-2+4*stride, trans+4+2*8, stride, 8);
+ }
+}
+
+static inline void h264_loop_filter_chroma_mmx2(uint8_t *pix, int stride, int alpha1, int beta1, int8_t *tc0)
+{
+ asm volatile(
+ "movq (%0), %%mm0 \n\t" //p1
+ "movq (%0,%2), %%mm1 \n\t" //p0
+ "movq (%1), %%mm2 \n\t" //q0
+ "movq (%1,%2), %%mm3 \n\t" //q1
+ H264_DEBLOCK_MASK(%4, %5)
+ "movd %3, %%mm6 \n\t"
+ "punpcklbw %%mm6, %%mm6 \n\t"
+ "pand %%mm6, %%mm7 \n\t" // mm7 = tc&mask
+ H264_DEBLOCK_P0_Q0(%6, %7)
+ "movq %%mm1, (%0,%2) \n\t"
+ "movq %%mm2, (%1) \n\t"
+
+ :: "r"(pix-2*stride), "r"(pix), "r"((long)stride),
+ "r"(*(uint32_t*)tc0),
+ "m"(alpha1), "m"(beta1), "m"(mm_bone), "m"(ff_pb_3F)
+ );
+}
+
+static void h264_v_loop_filter_chroma_mmx2(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0)
+{
+ h264_loop_filter_chroma_mmx2(pix, stride, alpha-1, beta-1, tc0);
+}
+
+static void h264_h_loop_filter_chroma_mmx2(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0)
+{
+ //FIXME: could cut some load/stores by merging transpose with filter
+ DECLARE_ALIGNED_8(uint8_t, trans[8*4]);
+ transpose4x4(trans, pix-2, 8, stride);
+ transpose4x4(trans+4, pix-2+4*stride, 8, stride);
+ h264_loop_filter_chroma_mmx2(trans+2*8, 8, alpha-1, beta-1, tc0);
+ transpose4x4(pix-2, trans, stride, 8);
+ transpose4x4(pix-2+4*stride, trans+4, stride, 8);
+}
+
+// p0 = (p0 + q1 + 2*p1 + 2) >> 2
+#define H264_FILTER_CHROMA4(p0, p1, q1, one) \
+ "movq "#p0", %%mm4 \n\t"\
+ "pxor "#q1", %%mm4 \n\t"\
+ "pand "#one", %%mm4 \n\t" /* mm4 = (p0^q1)&1 */\
+ "pavgb "#q1", "#p0" \n\t"\
+ "psubusb %%mm4, "#p0" \n\t"\
+ "pavgb "#p1", "#p0" \n\t" /* dst = avg(p1, avg(p0,q1) - ((p0^q1)&1)) */\
+
+static inline void h264_loop_filter_chroma_intra_mmx2(uint8_t *pix, int stride, int alpha1, int beta1)
+{
+ asm volatile(
+ "movq (%0), %%mm0 \n\t"
+ "movq (%0,%2), %%mm1 \n\t"
+ "movq (%1), %%mm2 \n\t"
+ "movq (%1,%2), %%mm3 \n\t"
+ H264_DEBLOCK_MASK(%3, %4)
+ "movq %%mm1, %%mm5 \n\t"
+ "movq %%mm2, %%mm6 \n\t"
+ H264_FILTER_CHROMA4(%%mm1, %%mm0, %%mm3, %5) //p0'
+ H264_FILTER_CHROMA4(%%mm2, %%mm3, %%mm0, %5) //q0'
+ "psubb %%mm5, %%mm1 \n\t"
+ "psubb %%mm6, %%mm2 \n\t"
+ "pand %%mm7, %%mm1 \n\t"
+ "pand %%mm7, %%mm2 \n\t"
+ "paddb %%mm5, %%mm1 \n\t"
+ "paddb %%mm6, %%mm2 \n\t"
+ "movq %%mm1, (%0,%2) \n\t"
+ "movq %%mm2, (%1) \n\t"
+ :: "r"(pix-2*stride), "r"(pix), "r"((long)stride),
+ "m"(alpha1), "m"(beta1), "m"(mm_bone)
+ );
+}
+
+static void h264_v_loop_filter_chroma_intra_mmx2(uint8_t *pix, int stride, int alpha, int beta)
+{
+ h264_loop_filter_chroma_intra_mmx2(pix, stride, alpha-1, beta-1);
+}
+
+static void h264_h_loop_filter_chroma_intra_mmx2(uint8_t *pix, int stride, int alpha, int beta)
+{
+ //FIXME: could cut some load/stores by merging transpose with filter
+ DECLARE_ALIGNED_8(uint8_t, trans[8*4]);
+ transpose4x4(trans, pix-2, 8, stride);
+ transpose4x4(trans+4, pix-2+4*stride, 8, stride);
+ h264_loop_filter_chroma_intra_mmx2(trans+2*8, 8, alpha-1, beta-1);
+ transpose4x4(pix-2, trans, stride, 8);
+ transpose4x4(pix-2+4*stride, trans+4, stride, 8);
+}
+
+static void h264_loop_filter_strength_mmx2( 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 dir;
+ asm volatile(
+ "pxor %%mm7, %%mm7 \n\t"
+ "movq %0, %%mm6 \n\t"
+ "movq %1, %%mm5 \n\t"
+ "movq %2, %%mm4 \n\t"
+ ::"m"(ff_pb_1), "m"(ff_pb_3), "m"(ff_pb_7)
+ );
+ // could do a special case for dir==0 && edges==1, but it only reduces the
+ // average filter time by 1.2%
+ for( dir=1; dir>=0; dir-- ) {
+ const int d_idx = dir ? -8 : -1;
+ const int mask_mv = dir ? mask_mv1 : mask_mv0;
+ DECLARE_ALIGNED_8(const uint64_t, mask_dir) = dir ? 0 : 0xffffffffffffffffULL;
+ int b_idx, edge, l;
+ for( b_idx=12, edge=0; edge<edges; edge+=step, b_idx+=8*step ) {
+ asm volatile(
+ "pand %0, %%mm0 \n\t"
+ ::"m"(mask_dir)
+ );
+ if(!(mask_mv & edge)) {
+ asm volatile("pxor %%mm0, %%mm0 \n\t":);
+ for( l = bidir; l >= 0; l-- ) {
+ asm volatile(
+ "movd %0, %%mm1 \n\t"
+ "punpckldq %1, %%mm1 \n\t"
+ "movq %%mm1, %%mm2 \n\t"
+ "psrlw $7, %%mm2 \n\t"
+ "pand %%mm6, %%mm2 \n\t"
+ "por %%mm2, %%mm1 \n\t" // ref_cache with -2 mapped to -1
+ "punpckldq %%mm1, %%mm2 \n\t"
+ "pcmpeqb %%mm2, %%mm1 \n\t"
+ "paddb %%mm6, %%mm1 \n\t"
+ "punpckhbw %%mm7, %%mm1 \n\t" // ref[b] != ref[bn]
+ "por %%mm1, %%mm0 \n\t"
+
+ "movq %2, %%mm1 \n\t"
+ "movq %3, %%mm2 \n\t"
+ "psubw %4, %%mm1 \n\t"
+ "psubw %5, %%mm2 \n\t"
+ "packsswb %%mm2, %%mm1 \n\t"
+ "paddb %%mm5, %%mm1 \n\t"
+ "pminub %%mm4, %%mm1 \n\t"
+ "pcmpeqb %%mm4, %%mm1 \n\t" // abs(mv[b] - mv[bn]) >= limit
+ "por %%mm1, %%mm0 \n\t"
+ ::"m"(ref[l][b_idx]),
+ "m"(ref[l][b_idx+d_idx]),
+ "m"(mv[l][b_idx][0]),
+ "m"(mv[l][b_idx+2][0]),
+ "m"(mv[l][b_idx+d_idx][0]),
+ "m"(mv[l][b_idx+d_idx+2][0])
+ );
+ }
+ }
+ asm volatile(
+ "movd %0, %%mm1 \n\t"
+ "por %1, %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "pcmpgtw %%mm7, %%mm1 \n\t" // nnz[b] || nnz[bn]
+ ::"m"(nnz[b_idx]),
+ "m"(nnz[b_idx+d_idx])
+ );
+ asm volatile(
+ "pcmpeqw %%mm7, %%mm0 \n\t"
+ "pcmpeqw %%mm7, %%mm0 \n\t"
+ "psrlw $15, %%mm0 \n\t" // nonzero -> 1
+ "psrlw $14, %%mm1 \n\t"
+ "movq %%mm0, %%mm2 \n\t"
+ "por %%mm1, %%mm2 \n\t"
+ "psrlw $1, %%mm1 \n\t"
+ "pandn %%mm2, %%mm1 \n\t"
+ "movq %%mm1, %0 \n\t"
+ :"=m"(*bS[dir][edge])
+ ::"memory"
+ );
+ }
+ edges = 4;
+ step = 1;
+ }
+ asm volatile(
+ "movq (%0), %%mm0 \n\t"
+ "movq 8(%0), %%mm1 \n\t"
+ "movq 16(%0), %%mm2 \n\t"
+ "movq 24(%0), %%mm3 \n\t"
+ TRANSPOSE4(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4)
+ "movq %%mm0, (%0) \n\t"
+ "movq %%mm3, 8(%0) \n\t"
+ "movq %%mm4, 16(%0) \n\t"
+ "movq %%mm2, 24(%0) \n\t"
+ ::"r"(bS[0])
+ :"memory"
+ );
+}
+
+/***********************************/
+/* motion compensation */
+
+#define QPEL_H264V(A,B,C,D,E,F,OP)\
+ "movd (%0), "#F" \n\t"\
+ "movq "#C", %%mm6 \n\t"\
+ "paddw "#D", %%mm6 \n\t"\
+ "psllw $2, %%mm6 \n\t"\
+ "psubw "#B", %%mm6 \n\t"\
+ "psubw "#E", %%mm6 \n\t"\
+ "pmullw %4, %%mm6 \n\t"\
+ "add %2, %0 \n\t"\
+ "punpcklbw %%mm7, "#F" \n\t"\
+ "paddw %5, "#A" \n\t"\
+ "paddw "#F", "#A" \n\t"\
+ "paddw "#A", %%mm6 \n\t"\
+ "psraw $5, %%mm6 \n\t"\
+ "packuswb %%mm6, %%mm6 \n\t"\
+ OP(%%mm6, (%1), A, d)\
+ "add %3, %1 \n\t"
+
+#define QPEL_H264HV(A,B,C,D,E,F,OF)\
+ "movd (%0), "#F" \n\t"\
+ "movq "#C", %%mm6 \n\t"\
+ "paddw "#D", %%mm6 \n\t"\
+ "psllw $2, %%mm6 \n\t"\
+ "psubw "#B", %%mm6 \n\t"\
+ "psubw "#E", %%mm6 \n\t"\
+ "pmullw %3, %%mm6 \n\t"\
+ "add %2, %0 \n\t"\
+ "punpcklbw %%mm7, "#F" \n\t"\
+ "paddw "#F", "#A" \n\t"\
+ "paddw "#A", %%mm6 \n\t"\
+ "movq %%mm6, "#OF"(%1) \n\t"
+
+#define QPEL_H264(OPNAME, OP, MMX)\
+static void OPNAME ## h264_qpel4_h_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ int h=4;\
+\
+ asm volatile(\
+ "pxor %%mm7, %%mm7 \n\t"\
+ "movq %5, %%mm4 \n\t"\
+ "movq %6, %%mm5 \n\t"\
+ "1: \n\t"\
+ "movd -1(%0), %%mm1 \n\t"\
+ "movd (%0), %%mm2 \n\t"\
+ "movd 1(%0), %%mm3 \n\t"\
+ "movd 2(%0), %%mm0 \n\t"\
+ "punpcklbw %%mm7, %%mm1 \n\t"\
+ "punpcklbw %%mm7, %%mm2 \n\t"\
+ "punpcklbw %%mm7, %%mm3 \n\t"\
+ "punpcklbw %%mm7, %%mm0 \n\t"\
+ "paddw %%mm0, %%mm1 \n\t"\
+ "paddw %%mm3, %%mm2 \n\t"\
+ "movd -2(%0), %%mm0 \n\t"\
+ "movd 3(%0), %%mm3 \n\t"\
+ "punpcklbw %%mm7, %%mm0 \n\t"\
+ "punpcklbw %%mm7, %%mm3 \n\t"\
+ "paddw %%mm3, %%mm0 \n\t"\
+ "psllw $2, %%mm2 \n\t"\
+ "psubw %%mm1, %%mm2 \n\t"\
+ "pmullw %%mm4, %%mm2 \n\t"\
+ "paddw %%mm5, %%mm0 \n\t"\
+ "paddw %%mm2, %%mm0 \n\t"\
+ "psraw $5, %%mm0 \n\t"\
+ "packuswb %%mm0, %%mm0 \n\t"\
+ OP(%%mm0, (%1),%%mm6, d)\
+ "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"((long)srcStride), "S"((long)dstStride), "m"(ff_pw_5), "m"(ff_pw_16)\
+ : "memory"\
+ );\
+}\
+static void OPNAME ## h264_qpel4_h_lowpass_l2_ ## MMX(uint8_t *dst, uint8_t *src, uint8_t *src2, int dstStride, int src2Stride){\
+ int h=4;\
+ asm volatile(\
+ "pxor %%mm7, %%mm7 \n\t"\
+ "movq %0, %%mm4 \n\t"\
+ "movq %1, %%mm5 \n\t"\
+ :: "m"(ff_pw_5), "m"(ff_pw_16)\
+ );\
+ do{\
+ asm volatile(\
+ "movd -1(%0), %%mm1 \n\t"\
+ "movd (%0), %%mm2 \n\t"\
+ "movd 1(%0), %%mm3 \n\t"\
+ "movd 2(%0), %%mm0 \n\t"\
+ "punpcklbw %%mm7, %%mm1 \n\t"\
+ "punpcklbw %%mm7, %%mm2 \n\t"\
+ "punpcklbw %%mm7, %%mm3 \n\t"\
+ "punpcklbw %%mm7, %%mm0 \n\t"\
+ "paddw %%mm0, %%mm1 \n\t"\
+ "paddw %%mm3, %%mm2 \n\t"\
+ "movd -2(%0), %%mm0 \n\t"\
+ "movd 3(%0), %%mm3 \n\t"\
+ "punpcklbw %%mm7, %%mm0 \n\t"\
+ "punpcklbw %%mm7, %%mm3 \n\t"\
+ "paddw %%mm3, %%mm0 \n\t"\
+ "psllw $2, %%mm2 \n\t"\
+ "psubw %%mm1, %%mm2 \n\t"\
+ "pmullw %%mm4, %%mm2 \n\t"\
+ "paddw %%mm5, %%mm0 \n\t"\
+ "paddw %%mm2, %%mm0 \n\t"\
+ "movd (%2), %%mm3 \n\t"\
+ "psraw $5, %%mm0 \n\t"\
+ "packuswb %%mm0, %%mm0 \n\t"\
+ PAVGB" %%mm3, %%mm0 \n\t"\
+ OP(%%mm0, (%1),%%mm6, d)\
+ "add %4, %0 \n\t"\
+ "add %4, %1 \n\t"\
+ "add %3, %2 \n\t"\
+ : "+a"(src), "+c"(dst), "+d"(src2)\
+ : "D"((long)src2Stride), "S"((long)dstStride)\
+ : "memory"\
+ );\
+ }while(--h);\
+}\
+static void OPNAME ## h264_qpel4_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ src -= 2*srcStride;\
+ 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"\
+ QPEL_H264V(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP)\
+ QPEL_H264V(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP)\
+ QPEL_H264V(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP)\
+ QPEL_H264V(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP)\
+ \
+ : "+a"(src), "+c"(dst)\
+ : "S"((long)srcStride), "D"((long)dstStride), "m"(ff_pw_5), "m"(ff_pw_16)\
+ : "memory"\
+ );\
+}\
+static void OPNAME ## h264_qpel4_hv_lowpass_ ## MMX(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride){\
+ int h=4;\
+ int w=3;\
+ src -= 2*srcStride+2;\
+ 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"\
+ QPEL_H264HV(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, 0*8*3)\
+ QPEL_H264HV(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, 1*8*3)\
+ QPEL_H264HV(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, 2*8*3)\
+ QPEL_H264HV(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, 3*8*3)\
+ \
+ : "+a"(src)\
+ : "c"(tmp), "S"((long)srcStride), "m"(ff_pw_5)\
+ : "memory"\
+ );\
+ tmp += 4;\
+ src += 4 - 9*srcStride;\
+ }\
+ tmp -= 3*4;\
+ asm volatile(\
+ "movq %4, %%mm6 \n\t"\
+ "1: \n\t"\
+ "movq (%0), %%mm0 \n\t"\
+ "paddw 10(%0), %%mm0 \n\t"\
+ "movq 2(%0), %%mm1 \n\t"\
+ "paddw 8(%0), %%mm1 \n\t"\
+ "movq 4(%0), %%mm2 \n\t"\
+ "paddw 6(%0), %%mm2 \n\t"\
+ "psubw %%mm1, %%mm0 \n\t"/*a-b (abccba)*/\
+ "psraw $2, %%mm0 \n\t"/*(a-b)/4 */\
+ "psubw %%mm1, %%mm0 \n\t"/*(a-b)/4-b */\
+ "paddsw %%mm2, %%mm0 \n\t"\
+ "psraw $2, %%mm0 \n\t"/*((a-b)/4-b+c)/4 */\
+ "paddw %%mm6, %%mm2 \n\t"\
+ "paddw %%mm2, %%mm0 \n\t"/*(a-5*b+20*c)/16 +32 */\
+ "psraw $6, %%mm0 \n\t"\
+ "packuswb %%mm0, %%mm0 \n\t"\
+ OP(%%mm0, (%1),%%mm7, d)\
+ "add $24, %0 \n\t"\
+ "add %3, %1 \n\t"\
+ "decl %2 \n\t"\
+ " jnz 1b \n\t"\
+ : "+a"(tmp), "+c"(dst), "+m"(h)\
+ : "S"((long)dstStride), "m"(ff_pw_32)\
+ : "memory"\
+ );\
+}\
+\
+static void OPNAME ## h264_qpel8_h_lowpass_ ## 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"\
+ "psllw $2, %%mm0 \n\t"\
+ "psllw $2, %%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"\
+ "pmullw %%mm6, %%mm0 \n\t"\
+ "pmullw %%mm6, %%mm1 \n\t"\
+ "movd -2(%0), %%mm2 \n\t"\
+ "movd 7(%0), %%mm5 \n\t"\
+ "punpcklbw %%mm7, %%mm2 \n\t"\
+ "punpcklbw %%mm7, %%mm5 \n\t"\
+ "paddw %%mm3, %%mm2 \n\t"\
+ "paddw %%mm5, %%mm4 \n\t"\
+ "movq %6, %%mm5 \n\t"\
+ "paddw %%mm5, %%mm2 \n\t"\
+ "paddw %%mm5, %%mm4 \n\t"\
+ "paddw %%mm2, %%mm0 \n\t"\
+ "paddw %%mm4, %%mm1 \n\t"\
+ "psraw $5, %%mm0 \n\t"\
+ "psraw $5, %%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"((long)srcStride), "S"((long)dstStride), "m"(ff_pw_5), "m"(ff_pw_16)\
+ : "memory"\
+ );\
+}\
+\
+static void OPNAME ## h264_qpel8_h_lowpass_l2_ ## MMX(uint8_t *dst, uint8_t *src, uint8_t *src2, int dstStride, int src2Stride){\
+ int h=8;\
+ asm volatile(\
+ "pxor %%mm7, %%mm7 \n\t"\
+ "movq %0, %%mm6 \n\t"\
+ :: "m"(ff_pw_5)\
+ );\
+ do{\
+ asm volatile(\
+ "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"\
+ "psllw $2, %%mm0 \n\t"\
+ "psllw $2, %%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"\
+ "pmullw %%mm6, %%mm0 \n\t"\
+ "pmullw %%mm6, %%mm1 \n\t"\
+ "movd -2(%0), %%mm2 \n\t"\
+ "movd 7(%0), %%mm5 \n\t"\
+ "punpcklbw %%mm7, %%mm2 \n\t"\
+ "punpcklbw %%mm7, %%mm5 \n\t"\
+ "paddw %%mm3, %%mm2 \n\t"\
+ "paddw %%mm5, %%mm4 \n\t"\
+ "movq %5, %%mm5 \n\t"\
+ "paddw %%mm5, %%mm2 \n\t"\
+ "paddw %%mm5, %%mm4 \n\t"\
+ "paddw %%mm2, %%mm0 \n\t"\
+ "paddw %%mm4, %%mm1 \n\t"\
+ "psraw $5, %%mm0 \n\t"\
+ "psraw $5, %%mm1 \n\t"\
+ "movq (%2), %%mm4 \n\t"\
+ "packuswb %%mm1, %%mm0 \n\t"\
+ PAVGB" %%mm4, %%mm0 \n\t"\
+ OP(%%mm0, (%1),%%mm5, q)\
+ "add %4, %0 \n\t"\
+ "add %4, %1 \n\t"\
+ "add %3, %2 \n\t"\
+ : "+a"(src), "+c"(dst), "+d"(src2)\
+ : "D"((long)src2Stride), "S"((long)dstStride),\
+ "m"(ff_pw_16)\
+ : "memory"\
+ );\
+ }while(--h);\
+}\
+\
+static inline void OPNAME ## h264_qpel8or16_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\
+ 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"\
+ QPEL_H264V(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP)\
+ QPEL_H264V(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP)\
+ QPEL_H264V(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP)\
+ QPEL_H264V(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP)\
+ QPEL_H264V(%%mm4, %%mm5, %%mm0, %%mm1, %%mm2, %%mm3, OP)\
+ QPEL_H264V(%%mm5, %%mm0, %%mm1, %%mm2, %%mm3, %%mm4, OP)\
+ QPEL_H264V(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP)\
+ QPEL_H264V(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP)\
+ \
+ : "+a"(src), "+c"(dst)\
+ : "S"((long)srcStride), "D"((long)dstStride), "m"(ff_pw_5), "m"(ff_pw_16)\
+ : "memory"\
+ );\
+ if(h==16){\
+ asm volatile(\
+ QPEL_H264V(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP)\
+ QPEL_H264V(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP)\
+ QPEL_H264V(%%mm4, %%mm5, %%mm0, %%mm1, %%mm2, %%mm3, OP)\
+ QPEL_H264V(%%mm5, %%mm0, %%mm1, %%mm2, %%mm3, %%mm4, OP)\
+ QPEL_H264V(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP)\
+ QPEL_H264V(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP)\
+ QPEL_H264V(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP)\
+ QPEL_H264V(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP)\
+ \
+ : "+a"(src), "+c"(dst)\
+ : "S"((long)srcStride), "D"((long)dstStride), "m"(ff_pw_5), "m"(ff_pw_16)\
+ : "memory"\
+ );\
+ }\
+ src += 4-(h+5)*srcStride;\
+ dst += 4-h*dstStride;\
+ }\
+}\
+static inline void OPNAME ## h264_qpel8or16_hv_lowpass_ ## MMX(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride, int size){\
+ int h = size;\
+ int w = (size+8)>>2;\
+ src -= 2*srcStride+2;\
+ 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"\
+ QPEL_H264HV(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, 0*48)\
+ QPEL_H264HV(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, 1*48)\
+ QPEL_H264HV(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, 2*48)\
+ QPEL_H264HV(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, 3*48)\
+ QPEL_H264HV(%%mm4, %%mm5, %%mm0, %%mm1, %%mm2, %%mm3, 4*48)\
+ QPEL_H264HV(%%mm5, %%mm0, %%mm1, %%mm2, %%mm3, %%mm4, 5*48)\
+ QPEL_H264HV(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, 6*48)\
+ QPEL_H264HV(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, 7*48)\
+ : "+a"(src)\
+ : "c"(tmp), "S"((long)srcStride), "m"(ff_pw_5)\
+ : "memory"\
+ );\
+ if(size==16){\
+ asm volatile(\
+ QPEL_H264HV(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, 8*48)\
+ QPEL_H264HV(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, 9*48)\
+ QPEL_H264HV(%%mm4, %%mm5, %%mm0, %%mm1, %%mm2, %%mm3, 10*48)\
+ QPEL_H264HV(%%mm5, %%mm0, %%mm1, %%mm2, %%mm3, %%mm4, 11*48)\
+ QPEL_H264HV(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, 12*48)\
+ QPEL_H264HV(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, 13*48)\
+ QPEL_H264HV(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, 14*48)\
+ QPEL_H264HV(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, 15*48)\
+ : "+a"(src)\
+ : "c"(tmp), "S"((long)srcStride), "m"(ff_pw_5)\
+ : "memory"\
+ );\
+ }\
+ tmp += 4;\
+ src += 4 - (size+5)*srcStride;\
+ }\
+ tmp -= size+8;\
+ w = size>>4;\
+ do{\
+ h = size;\
+ asm volatile(\
+ "movq %4, %%mm6 \n\t"\
+ "1: \n\t"\
+ "movq (%0), %%mm0 \n\t"\
+ "movq 8(%0), %%mm3 \n\t"\
+ "movq 2(%0), %%mm1 \n\t"\
+ "movq 10(%0), %%mm4 \n\t"\
+ "paddw %%mm4, %%mm0 \n\t"\
+ "paddw %%mm3, %%mm1 \n\t"\
+ "paddw 18(%0), %%mm3 \n\t"\
+ "paddw 16(%0), %%mm4 \n\t"\
+ "movq 4(%0), %%mm2 \n\t"\
+ "movq 12(%0), %%mm5 \n\t"\
+ "paddw 6(%0), %%mm2 \n\t"\
+ "paddw 14(%0), %%mm5 \n\t"\
+ "psubw %%mm1, %%mm0 \n\t"\
+ "psubw %%mm4, %%mm3 \n\t"\
+ "psraw $2, %%mm0 \n\t"\
+ "psraw $2, %%mm3 \n\t"\
+ "psubw %%mm1, %%mm0 \n\t"\
+ "psubw %%mm4, %%mm3 \n\t"\
+ "paddsw %%mm2, %%mm0 \n\t"\
+ "paddsw %%mm5, %%mm3 \n\t"\
+ "psraw $2, %%mm0 \n\t"\
+ "psraw $2, %%mm3 \n\t"\
+ "paddw %%mm6, %%mm2 \n\t"\
+ "paddw %%mm6, %%mm5 \n\t"\
+ "paddw %%mm2, %%mm0 \n\t"\
+ "paddw %%mm5, %%mm3 \n\t"\
+ "psraw $6, %%mm0 \n\t"\
+ "psraw $6, %%mm3 \n\t"\
+ "packuswb %%mm3, %%mm0 \n\t"\
+ OP(%%mm0, (%1),%%mm7, q)\
+ "add $48, %0 \n\t"\
+ "add %3, %1 \n\t"\
+ "decl %2 \n\t"\
+ " jnz 1b \n\t"\
+ : "+a"(tmp), "+c"(dst), "+m"(h)\
+ : "S"((long)dstStride), "m"(ff_pw_32)\
+ : "memory"\
+ );\
+ tmp += 8 - size*24;\
+ dst += 8 - size*dstStride;\
+ }while(w--);\
+}\
+\
+static void OPNAME ## h264_qpel8_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ OPNAME ## h264_qpel8or16_v_lowpass_ ## MMX(dst , src , dstStride, srcStride, 8);\
+}\
+static void OPNAME ## h264_qpel16_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ OPNAME ## h264_qpel8or16_v_lowpass_ ## MMX(dst , src , dstStride, srcStride, 16);\
+ OPNAME ## h264_qpel8or16_v_lowpass_ ## MMX(dst+8, src+8, dstStride, srcStride, 16);\
+}\
+\
+static void OPNAME ## h264_qpel16_h_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ OPNAME ## h264_qpel8_h_lowpass_ ## MMX(dst , src , dstStride, srcStride);\
+ OPNAME ## h264_qpel8_h_lowpass_ ## MMX(dst+8, src+8, dstStride, srcStride);\
+ src += 8*srcStride;\
+ dst += 8*dstStride;\
+ OPNAME ## h264_qpel8_h_lowpass_ ## MMX(dst , src , dstStride, srcStride);\
+ OPNAME ## h264_qpel8_h_lowpass_ ## MMX(dst+8, src+8, dstStride, srcStride);\
+}\
+\
+static void OPNAME ## h264_qpel16_h_lowpass_l2_ ## MMX(uint8_t *dst, uint8_t *src, uint8_t *src2, int dstStride, int src2Stride){\
+ OPNAME ## h264_qpel8_h_lowpass_l2_ ## MMX(dst , src , src2 , dstStride, src2Stride);\
+ OPNAME ## h264_qpel8_h_lowpass_l2_ ## MMX(dst+8, src+8, src2+8, dstStride, src2Stride);\
+ src += 8*dstStride;\
+ dst += 8*dstStride;\
+ src2 += 8*src2Stride;\
+ OPNAME ## h264_qpel8_h_lowpass_l2_ ## MMX(dst , src , src2 , dstStride, src2Stride);\
+ OPNAME ## h264_qpel8_h_lowpass_l2_ ## MMX(dst+8, src+8, src2+8, dstStride, src2Stride);\
+}\
+\
+static void OPNAME ## h264_qpel8_hv_lowpass_ ## MMX(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride){\
+ OPNAME ## h264_qpel8or16_hv_lowpass_ ## MMX(dst , tmp , src , dstStride, tmpStride, srcStride, 8);\
+}\
+\
+static void OPNAME ## h264_qpel16_hv_lowpass_ ## MMX(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride){\
+ OPNAME ## h264_qpel8or16_hv_lowpass_ ## MMX(dst , tmp , src , dstStride, tmpStride, srcStride, 16);\
+}\
+\
+static void OPNAME ## pixels4_l2_shift5_ ## MMX(uint8_t *dst, int16_t *src16, uint8_t *src8, int dstStride, int src8Stride, int h)\
+{\
+ asm volatile(\
+ "movq %5, %%mm6 \n\t"\
+ "movq (%1), %%mm0 \n\t"\
+ "movq 24(%1), %%mm1 \n\t"\
+ "paddw %%mm6, %%mm0 \n\t"\
+ "paddw %%mm6, %%mm1 \n\t"\
+ "psraw $5, %%mm0 \n\t"\
+ "psraw $5, %%mm1 \n\t"\
+ "packuswb %%mm0, %%mm0 \n\t"\
+ "packuswb %%mm1, %%mm1 \n\t"\
+ PAVGB" (%0), %%mm0 \n\t"\
+ PAVGB" (%0,%3), %%mm1 \n\t"\
+ OP(%%mm0, (%2), %%mm4, d)\
+ OP(%%mm1, (%2,%4), %%mm5, d)\
+ "lea (%0,%3,2), %0 \n\t"\
+ "lea (%2,%4,2), %2 \n\t"\
+ "movq 48(%1), %%mm0 \n\t"\
+ "movq 72(%1), %%mm1 \n\t"\
+ "paddw %%mm6, %%mm0 \n\t"\
+ "paddw %%mm6, %%mm1 \n\t"\
+ "psraw $5, %%mm0 \n\t"\
+ "psraw $5, %%mm1 \n\t"\
+ "packuswb %%mm0, %%mm0 \n\t"\
+ "packuswb %%mm1, %%mm1 \n\t"\
+ PAVGB" (%0), %%mm0 \n\t"\
+ PAVGB" (%0,%3), %%mm1 \n\t"\
+ OP(%%mm0, (%2), %%mm4, d)\
+ OP(%%mm1, (%2,%4), %%mm5, d)\
+ :"+a"(src8), "+c"(src16), "+d"(dst)\
+ :"S"((long)src8Stride), "D"((long)dstStride), "m"(ff_pw_16)\
+ :"memory");\
+}\
+static void OPNAME ## pixels8_l2_shift5_ ## MMX(uint8_t *dst, int16_t *src16, uint8_t *src8, int dstStride, int src8Stride, int h)\
+{\
+ asm volatile(\
+ "movq %0, %%mm6 \n\t"\
+ ::"m"(ff_pw_16)\
+ );\
+ while(h--){\
+ asm volatile(\
+ "movq (%1), %%mm0 \n\t"\
+ "movq 8(%1), %%mm1 \n\t"\
+ "paddw %%mm6, %%mm0 \n\t"\
+ "paddw %%mm6, %%mm1 \n\t"\
+ "psraw $5, %%mm0 \n\t"\
+ "psraw $5, %%mm1 \n\t"\
+ "packuswb %%mm1, %%mm0 \n\t"\
+ PAVGB" (%0), %%mm0 \n\t"\
+ OP(%%mm0, (%2), %%mm5, q)\
+ ::"a"(src8), "c"(src16), "d"(dst)\
+ :"memory");\
+ src8 += src8Stride;\
+ src16 += 24;\
+ dst += dstStride;\
+ }\
+}\
+static void OPNAME ## pixels16_l2_shift5_ ## MMX(uint8_t *dst, int16_t *src16, uint8_t *src8, int dstStride, int src8Stride, int h)\
+{\
+ OPNAME ## pixels8_l2_shift5_ ## MMX(dst , src16 , src8 , dstStride, src8Stride, h);\
+ OPNAME ## pixels8_l2_shift5_ ## MMX(dst+8, src16+8, src8+8, dstStride, src8Stride, h);\
+}\
+
+
+#define H264_MC(OPNAME, SIZE, MMX) \
+static void OPNAME ## h264_qpel ## SIZE ## _mc00_ ## MMX (uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## pixels ## SIZE ## _mmx(dst, src, stride, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc10_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ 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, int stride){\
+ 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, int stride){\
+ OPNAME ## h264_qpel ## SIZE ## _h_lowpass_l2_ ## MMX(dst, src, src+1, stride, stride);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc01_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t temp[SIZE*SIZE/8];\
+ uint8_t * const half= (uint8_t*)temp;\
+ put_h264_qpel ## SIZE ## _v_lowpass_ ## MMX(half, src, SIZE, stride);\
+ OPNAME ## pixels ## SIZE ## _l2_ ## MMX(dst, src, half, stride, stride, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc02_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ 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, int stride){\
+ uint64_t temp[SIZE*SIZE/8];\
+ uint8_t * const half= (uint8_t*)temp;\
+ put_h264_qpel ## SIZE ## _v_lowpass_ ## MMX(half, src, SIZE, stride);\
+ OPNAME ## pixels ## SIZE ## _l2_ ## MMX(dst, src+stride, half, stride, stride, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc11_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t temp[SIZE*SIZE/8];\
+ uint8_t * const halfV= (uint8_t*)temp;\
+ put_h264_qpel ## SIZE ## _v_lowpass_ ## MMX(halfV, src, SIZE, stride);\
+ OPNAME ## h264_qpel ## SIZE ## _h_lowpass_l2_ ## MMX(dst, src, halfV, stride, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc31_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t temp[SIZE*SIZE/8];\
+ uint8_t * const halfV= (uint8_t*)temp;\
+ put_h264_qpel ## SIZE ## _v_lowpass_ ## MMX(halfV, src+1, SIZE, stride);\
+ OPNAME ## h264_qpel ## SIZE ## _h_lowpass_l2_ ## MMX(dst, src, halfV, stride, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc13_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t temp[SIZE*SIZE/8];\
+ uint8_t * const halfV= (uint8_t*)temp;\
+ put_h264_qpel ## SIZE ## _v_lowpass_ ## MMX(halfV, src, SIZE, stride);\
+ OPNAME ## h264_qpel ## SIZE ## _h_lowpass_l2_ ## MMX(dst, src+stride, halfV, stride, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc33_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t temp[SIZE*SIZE/8];\
+ uint8_t * const halfV= (uint8_t*)temp;\
+ put_h264_qpel ## SIZE ## _v_lowpass_ ## MMX(halfV, src+1, SIZE, stride);\
+ OPNAME ## h264_qpel ## SIZE ## _h_lowpass_l2_ ## MMX(dst, src+stride, halfV, stride, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc22_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t temp[SIZE*(SIZE<8?12:24)/4];\
+ int16_t * const tmp= (int16_t*)temp;\
+ OPNAME ## h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(dst, tmp, src, stride, SIZE, stride);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc21_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t temp[SIZE*(SIZE<8?12:24)/4 + SIZE*SIZE/8];\
+ uint8_t * const halfHV= (uint8_t*)temp;\
+ int16_t * const tmp= ((int16_t*)temp) + SIZE*SIZE/2;\
+ put_h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(halfHV, tmp, src, SIZE, SIZE, stride);\
+ 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, int stride){\
+ uint64_t temp[SIZE*(SIZE<8?12:24)/4 + SIZE*SIZE/8];\
+ uint8_t * const halfHV= (uint8_t*)temp;\
+ int16_t * const tmp= ((int16_t*)temp) + SIZE*SIZE/2;\
+ put_h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(halfHV, tmp, src, SIZE, SIZE, stride);\
+ 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, int stride){\
+ uint64_t temp[SIZE*(SIZE<8?12:24)/4 + SIZE*SIZE/8];\
+ int16_t * const halfV= ((int16_t*)temp) + SIZE*SIZE/2;\
+ uint8_t * const halfHV= ((uint8_t*)temp);\
+ put_h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(halfHV, halfV, src, SIZE, SIZE, stride);\
+ OPNAME ## pixels ## SIZE ## _l2_shift5_ ## MMX(dst, halfV+2, halfHV, stride, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc32_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
+ uint64_t temp[SIZE*(SIZE<8?12:24)/4 + SIZE*SIZE/8];\
+ int16_t * const halfV= ((int16_t*)temp) + SIZE*SIZE/2;\
+ uint8_t * const halfHV= ((uint8_t*)temp);\
+ put_h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(halfHV, halfV, src, SIZE, SIZE, stride);\
+ OPNAME ## pixels ## SIZE ## _l2_shift5_ ## MMX(dst, halfV+3, halfHV, stride, SIZE, SIZE);\
+}\
+
+
+#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_MMX2_OP(a,b,temp, size) \
+"mov" #size " " #b ", " #temp " \n\t"\
+"pavgb " #temp ", " #a " \n\t"\
+"mov" #size " " #a ", " #b " \n\t"
+
+#define PAVGB "pavgusb"
+QPEL_H264(put_, PUT_OP, 3dnow)
+QPEL_H264(avg_, AVG_3DNOW_OP, 3dnow)
+#undef PAVGB
+#define PAVGB "pavgb"
+QPEL_H264(put_, PUT_OP, mmx2)
+QPEL_H264(avg_, AVG_MMX2_OP, mmx2)
+#undef PAVGB
+
+H264_MC(put_, 4, 3dnow)
+H264_MC(put_, 8, 3dnow)
+H264_MC(put_, 16,3dnow)
+H264_MC(avg_, 4, 3dnow)
+H264_MC(avg_, 8, 3dnow)
+H264_MC(avg_, 16,3dnow)
+H264_MC(put_, 4, mmx2)
+H264_MC(put_, 8, mmx2)
+H264_MC(put_, 16,mmx2)
+H264_MC(avg_, 4, mmx2)
+H264_MC(avg_, 8, mmx2)
+H264_MC(avg_, 16,mmx2)
+
+
+#define H264_CHROMA_OP(S,D)
+#define H264_CHROMA_OP4(S,D,T)
+#define H264_CHROMA_MC8_TMPL put_h264_chroma_mc8_mmx
+#define H264_CHROMA_MC4_TMPL put_h264_chroma_mc4_mmx
+#define H264_CHROMA_MC2_TMPL put_h264_chroma_mc2_mmx2
+#define H264_CHROMA_MC8_MV0 put_pixels8_mmx
+#include "dsputil_h264_template_mmx.c"
+#undef H264_CHROMA_OP
+#undef H264_CHROMA_OP4
+#undef H264_CHROMA_MC8_TMPL
+#undef H264_CHROMA_MC4_TMPL
+#undef H264_CHROMA_MC2_TMPL
+#undef H264_CHROMA_MC8_MV0
+
+#define H264_CHROMA_OP(S,D) "pavgb " #S ", " #D " \n\t"
+#define H264_CHROMA_OP4(S,D,T) "movd " #S ", " #T " \n\t"\
+ "pavgb " #T ", " #D " \n\t"
+#define H264_CHROMA_MC8_TMPL avg_h264_chroma_mc8_mmx2
+#define H264_CHROMA_MC4_TMPL avg_h264_chroma_mc4_mmx2
+#define H264_CHROMA_MC2_TMPL avg_h264_chroma_mc2_mmx2
+#define H264_CHROMA_MC8_MV0 avg_pixels8_mmx2
+#include "dsputil_h264_template_mmx.c"
+#undef H264_CHROMA_OP
+#undef H264_CHROMA_OP4
+#undef H264_CHROMA_MC8_TMPL
+#undef H264_CHROMA_MC4_TMPL
+#undef H264_CHROMA_MC2_TMPL
+#undef H264_CHROMA_MC8_MV0
+
+#define H264_CHROMA_OP(S,D) "pavgusb " #S ", " #D " \n\t"
+#define H264_CHROMA_OP4(S,D,T) "movd " #S ", " #T " \n\t"\
+ "pavgusb " #T ", " #D " \n\t"
+#define H264_CHROMA_MC8_TMPL avg_h264_chroma_mc8_3dnow
+#define H264_CHROMA_MC4_TMPL avg_h264_chroma_mc4_3dnow
+#define H264_CHROMA_MC8_MV0 avg_pixels8_3dnow
+#include "dsputil_h264_template_mmx.c"
+#undef H264_CHROMA_OP
+#undef H264_CHROMA_OP4
+#undef H264_CHROMA_MC8_TMPL
+#undef H264_CHROMA_MC4_TMPL
+#undef H264_CHROMA_MC8_MV0
+
+/***********************************/
+/* weighted prediction */
+
+static inline void ff_h264_weight_WxH_mmx2(uint8_t *dst, int stride, int log2_denom, int weight, int offset, int w, int h)
+{
+ int x, y;
+ offset <<= log2_denom;
+ offset += (1 << log2_denom) >> 1;
+ asm volatile(
+ "movd %0, %%mm4 \n\t"
+ "movd %1, %%mm5 \n\t"
+ "movd %2, %%mm6 \n\t"
+ "pshufw $0, %%mm4, %%mm4 \n\t"
+ "pshufw $0, %%mm5, %%mm5 \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+ :: "g"(weight), "g"(offset), "g"(log2_denom)
+ );
+ for(y=0; y<h; y+=2){
+ for(x=0; x<w; x+=4){
+ asm volatile(
+ "movd %0, %%mm0 \n\t"
+ "movd %1, %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "pmullw %%mm4, %%mm0 \n\t"
+ "pmullw %%mm4, %%mm1 \n\t"
+ "paddsw %%mm5, %%mm0 \n\t"
+ "paddsw %%mm5, %%mm1 \n\t"
+ "psraw %%mm6, %%mm0 \n\t"
+ "psraw %%mm6, %%mm1 \n\t"
+ "packuswb %%mm7, %%mm0 \n\t"
+ "packuswb %%mm7, %%mm1 \n\t"
+ "movd %%mm0, %0 \n\t"
+ "movd %%mm1, %1 \n\t"
+ : "+m"(*(uint32_t*)(dst+x)),
+ "+m"(*(uint32_t*)(dst+x+stride))
+ );
+ }
+ dst += 2*stride;
+ }
+}
+
+static inline void ff_h264_biweight_WxH_mmx2(uint8_t *dst, uint8_t *src, int stride, int log2_denom, int weightd, int weights, int offset, int w, int h)
+{
+ int x, y;
+ offset = ((offset + 1) | 1) << log2_denom;
+ asm volatile(
+ "movd %0, %%mm3 \n\t"
+ "movd %1, %%mm4 \n\t"
+ "movd %2, %%mm5 \n\t"
+ "movd %3, %%mm6 \n\t"
+ "pshufw $0, %%mm3, %%mm3 \n\t"
+ "pshufw $0, %%mm4, %%mm4 \n\t"
+ "pshufw $0, %%mm5, %%mm5 \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+ :: "g"(weightd), "g"(weights), "g"(offset), "g"(log2_denom+1)
+ );
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x+=4){
+ asm volatile(
+ "movd %0, %%mm0 \n\t"
+ "movd %1, %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "pmullw %%mm3, %%mm0 \n\t"
+ "pmullw %%mm4, %%mm1 \n\t"
+ "paddsw %%mm1, %%mm0 \n\t"
+ "paddsw %%mm5, %%mm0 \n\t"
+ "psraw %%mm6, %%mm0 \n\t"
+ "packuswb %%mm0, %%mm0 \n\t"
+ "movd %%mm0, %0 \n\t"
+ : "+m"(*(uint32_t*)(dst+x))
+ : "m"(*(uint32_t*)(src+x))
+ );
+ }
+ src += stride;
+ dst += stride;
+ }
+}
+
+#define H264_WEIGHT(W,H) \
+static void ff_h264_biweight_ ## W ## x ## H ## _mmx2(uint8_t *dst, uint8_t *src, int stride, int log2_denom, int weightd, int weights, int offset){ \
+ ff_h264_biweight_WxH_mmx2(dst, src, stride, log2_denom, weightd, weights, offset, W, H); \
+} \
+static void ff_h264_weight_ ## W ## x ## H ## _mmx2(uint8_t *dst, int stride, int log2_denom, int weight, int offset){ \
+ ff_h264_weight_WxH_mmx2(dst, stride, log2_denom, weight, offset, W, H); \
+}
+
+H264_WEIGHT(16,16)
+H264_WEIGHT(16, 8)
+H264_WEIGHT( 8,16)
+H264_WEIGHT( 8, 8)
+H264_WEIGHT( 8, 4)
+H264_WEIGHT( 4, 8)
+H264_WEIGHT( 4, 4)
+H264_WEIGHT( 4, 2)
+
diff --git a/contrib/ffmpeg/libavcodec/i386/idct_mmx.c b/contrib/ffmpeg/libavcodec/i386/idct_mmx.c
new file mode 100644
index 000000000..ba595845a
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/idct_mmx.c
@@ -0,0 +1,597 @@
+/*
+ * idct_mmx.c
+ * Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
+ *
+ * mpeg2dec 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mpeg2dec is distributed in the hope that 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "common.h"
+#include "../dsputil.h"
+
+#include "mmx.h"
+
+#define ATTR_ALIGN(align) __attribute__ ((__aligned__ (align)))
+
+#define ROW_SHIFT 11
+#define COL_SHIFT 6
+
+#define round(bias) ((int)(((bias)+0.5) * (1<<ROW_SHIFT)))
+#define rounder(bias) {round (bias), round (bias)}
+
+#if 0
+/* C row IDCT - its just here to document the MMXEXT and MMX versions */
+static inline void idct_row (int16_t * row, int offset,
+ int16_t * table, int32_t * rounder)
+{
+ int C1, C2, C3, C4, C5, C6, C7;
+ int a0, a1, a2, a3, b0, b1, b2, b3;
+
+ row += offset;
+
+ C1 = table[1];
+ C2 = table[2];
+ C3 = table[3];
+ C4 = table[4];
+ C5 = table[5];
+ C6 = table[6];
+ C7 = table[7];
+
+ a0 = C4*row[0] + C2*row[2] + C4*row[4] + C6*row[6] + *rounder;
+ a1 = C4*row[0] + C6*row[2] - C4*row[4] - C2*row[6] + *rounder;
+ a2 = C4*row[0] - C6*row[2] - C4*row[4] + C2*row[6] + *rounder;
+ a3 = C4*row[0] - C2*row[2] + C4*row[4] - C6*row[6] + *rounder;
+
+ b0 = C1*row[1] + C3*row[3] + C5*row[5] + C7*row[7];
+ b1 = C3*row[1] - C7*row[3] - C1*row[5] - C5*row[7];
+ b2 = C5*row[1] - C1*row[3] + C7*row[5] + C3*row[7];
+ b3 = C7*row[1] - C5*row[3] + C3*row[5] - C1*row[7];
+
+ 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;
+}
+#endif
+
+
+/* MMXEXT row IDCT */
+
+#define mmxext_table(c1,c2,c3,c4,c5,c6,c7) { c4, c2, -c4, -c2, \
+ c4, c6, c4, c6, \
+ c1, c3, -c1, -c5, \
+ c5, c7, c3, -c7, \
+ c4, -c6, c4, -c6, \
+ -c4, c2, c4, -c2, \
+ c5, -c1, c3, -c1, \
+ c7, c3, c7, -c5 }
+
+static inline void mmxext_row_head (int16_t * row, int offset, const int16_t * table)
+{
+ movq_m2r (*(row+offset), mm2); // mm2 = x6 x4 x2 x0
+
+ movq_m2r (*(row+offset+4), mm5); // mm5 = x7 x5 x3 x1
+ movq_r2r (mm2, mm0); // mm0 = x6 x4 x2 x0
+
+ movq_m2r (*table, mm3); // mm3 = -C2 -C4 C2 C4
+ movq_r2r (mm5, mm6); // mm6 = x7 x5 x3 x1
+
+ movq_m2r (*(table+4), mm4); // mm4 = C6 C4 C6 C4
+ pmaddwd_r2r (mm0, mm3); // mm3 = -C4*x4-C2*x6 C4*x0+C2*x2
+
+ pshufw_r2r (mm2, mm2, 0x4e); // mm2 = x2 x0 x6 x4
+}
+
+static inline void mmxext_row (const int16_t * table, const int32_t * rounder)
+{
+ movq_m2r (*(table+8), mm1); // mm1 = -C5 -C1 C3 C1
+ pmaddwd_r2r (mm2, mm4); // mm4 = C4*x0+C6*x2 C4*x4+C6*x6
+
+ pmaddwd_m2r (*(table+16), mm0); // mm0 = C4*x4-C6*x6 C4*x0-C6*x2
+ pshufw_r2r (mm6, mm6, 0x4e); // mm6 = x3 x1 x7 x5
+
+ movq_m2r (*(table+12), mm7); // mm7 = -C7 C3 C7 C5
+ pmaddwd_r2r (mm5, mm1); // mm1 = -C1*x5-C5*x7 C1*x1+C3*x3
+
+ paddd_m2r (*rounder, mm3); // mm3 += rounder
+ pmaddwd_r2r (mm6, mm7); // mm7 = C3*x1-C7*x3 C5*x5+C7*x7
+
+ pmaddwd_m2r (*(table+20), mm2); // mm2 = C4*x0-C2*x2 -C4*x4+C2*x6
+ paddd_r2r (mm4, mm3); // mm3 = a1 a0 + rounder
+
+ pmaddwd_m2r (*(table+24), mm5); // mm5 = C3*x5-C1*x7 C5*x1-C1*x3
+ movq_r2r (mm3, mm4); // mm4 = a1 a0 + rounder
+
+ pmaddwd_m2r (*(table+28), mm6); // mm6 = C7*x1-C5*x3 C7*x5+C3*x7
+ paddd_r2r (mm7, mm1); // mm1 = b1 b0
+
+ paddd_m2r (*rounder, mm0); // mm0 += rounder
+ psubd_r2r (mm1, mm3); // mm3 = a1-b1 a0-b0 + rounder
+
+ psrad_i2r (ROW_SHIFT, mm3); // mm3 = y6 y7
+ paddd_r2r (mm4, mm1); // mm1 = a1+b1 a0+b0 + rounder
+
+ paddd_r2r (mm2, mm0); // mm0 = a3 a2 + rounder
+ psrad_i2r (ROW_SHIFT, mm1); // mm1 = y1 y0
+
+ paddd_r2r (mm6, mm5); // mm5 = b3 b2
+ movq_r2r (mm0, mm4); // mm4 = a3 a2 + rounder
+
+ paddd_r2r (mm5, mm0); // mm0 = a3+b3 a2+b2 + rounder
+ psubd_r2r (mm5, mm4); // mm4 = a3-b3 a2-b2 + rounder
+}
+
+static inline void mmxext_row_tail (int16_t * row, int store)
+{
+ psrad_i2r (ROW_SHIFT, mm0); // mm0 = y3 y2
+
+ psrad_i2r (ROW_SHIFT, mm4); // mm4 = y4 y5
+
+ packssdw_r2r (mm0, mm1); // mm1 = y3 y2 y1 y0
+
+ packssdw_r2r (mm3, mm4); // mm4 = y6 y7 y4 y5
+
+ movq_r2m (mm1, *(row+store)); // save y3 y2 y1 y0
+ pshufw_r2r (mm4, mm4, 0xb1); // mm4 = y7 y6 y5 y4
+
+ /* slot */
+
+ movq_r2m (mm4, *(row+store+4)); // save y7 y6 y5 y4
+}
+
+static inline void mmxext_row_mid (int16_t * row, int store,
+ int offset, const int16_t * table)
+{
+ movq_m2r (*(row+offset), mm2); // mm2 = x6 x4 x2 x0
+ psrad_i2r (ROW_SHIFT, mm0); // mm0 = y3 y2
+
+ movq_m2r (*(row+offset+4), mm5); // mm5 = x7 x5 x3 x1
+ psrad_i2r (ROW_SHIFT, mm4); // mm4 = y4 y5
+
+ packssdw_r2r (mm0, mm1); // mm1 = y3 y2 y1 y0
+ movq_r2r (mm5, mm6); // mm6 = x7 x5 x3 x1
+
+ packssdw_r2r (mm3, mm4); // mm4 = y6 y7 y4 y5
+ movq_r2r (mm2, mm0); // mm0 = x6 x4 x2 x0
+
+ movq_r2m (mm1, *(row+store)); // save y3 y2 y1 y0
+ pshufw_r2r (mm4, mm4, 0xb1); // mm4 = y7 y6 y5 y4
+
+ movq_m2r (*table, mm3); // mm3 = -C2 -C4 C2 C4
+ movq_r2m (mm4, *(row+store+4)); // save y7 y6 y5 y4
+
+ pmaddwd_r2r (mm0, mm3); // mm3 = -C4*x4-C2*x6 C4*x0+C2*x2
+
+ movq_m2r (*(table+4), mm4); // mm4 = C6 C4 C6 C4
+ pshufw_r2r (mm2, mm2, 0x4e); // mm2 = x2 x0 x6 x4
+}
+
+
+/* MMX row IDCT */
+
+#define mmx_table(c1,c2,c3,c4,c5,c6,c7) { c4, c2, c4, c6, \
+ c4, c6, -c4, -c2, \
+ c1, c3, c3, -c7, \
+ c5, c7, -c1, -c5, \
+ c4, -c6, c4, -c2, \
+ -c4, c2, c4, -c6, \
+ c5, -c1, c7, -c5, \
+ c7, c3, c3, -c1 }
+
+static inline void mmx_row_head (int16_t * row, int offset, const int16_t * table)
+{
+ movq_m2r (*(row+offset), mm2); // mm2 = x6 x4 x2 x0
+
+ movq_m2r (*(row+offset+4), mm5); // mm5 = x7 x5 x3 x1
+ movq_r2r (mm2, mm0); // mm0 = x6 x4 x2 x0
+
+ movq_m2r (*table, mm3); // mm3 = C6 C4 C2 C4
+ movq_r2r (mm5, mm6); // mm6 = x7 x5 x3 x1
+
+ punpckldq_r2r (mm0, mm0); // mm0 = x2 x0 x2 x0
+
+ movq_m2r (*(table+4), mm4); // mm4 = -C2 -C4 C6 C4
+ pmaddwd_r2r (mm0, mm3); // mm3 = C4*x0+C6*x2 C4*x0+C2*x2
+
+ movq_m2r (*(table+8), mm1); // mm1 = -C7 C3 C3 C1
+ punpckhdq_r2r (mm2, mm2); // mm2 = x6 x4 x6 x4
+}
+
+static inline void mmx_row (const int16_t * table, const int32_t * rounder)
+{
+ pmaddwd_r2r (mm2, mm4); // mm4 = -C4*x4-C2*x6 C4*x4+C6*x6
+ punpckldq_r2r (mm5, mm5); // mm5 = x3 x1 x3 x1
+
+ pmaddwd_m2r (*(table+16), mm0); // mm0 = C4*x0-C2*x2 C4*x0-C6*x2
+ punpckhdq_r2r (mm6, mm6); // mm6 = x7 x5 x7 x5
+
+ movq_m2r (*(table+12), mm7); // mm7 = -C5 -C1 C7 C5
+ pmaddwd_r2r (mm5, mm1); // mm1 = C3*x1-C7*x3 C1*x1+C3*x3
+
+ paddd_m2r (*rounder, mm3); // mm3 += rounder
+ pmaddwd_r2r (mm6, mm7); // mm7 = -C1*x5-C5*x7 C5*x5+C7*x7
+
+ pmaddwd_m2r (*(table+20), mm2); // mm2 = C4*x4-C6*x6 -C4*x4+C2*x6
+ paddd_r2r (mm4, mm3); // mm3 = a1 a0 + rounder
+
+ pmaddwd_m2r (*(table+24), mm5); // mm5 = C7*x1-C5*x3 C5*x1-C1*x3
+ movq_r2r (mm3, mm4); // mm4 = a1 a0 + rounder
+
+ pmaddwd_m2r (*(table+28), mm6); // mm6 = C3*x5-C1*x7 C7*x5+C3*x7
+ paddd_r2r (mm7, mm1); // mm1 = b1 b0
+
+ paddd_m2r (*rounder, mm0); // mm0 += rounder
+ psubd_r2r (mm1, mm3); // mm3 = a1-b1 a0-b0 + rounder
+
+ psrad_i2r (ROW_SHIFT, mm3); // mm3 = y6 y7
+ paddd_r2r (mm4, mm1); // mm1 = a1+b1 a0+b0 + rounder
+
+ paddd_r2r (mm2, mm0); // mm0 = a3 a2 + rounder
+ psrad_i2r (ROW_SHIFT, mm1); // mm1 = y1 y0
+
+ paddd_r2r (mm6, mm5); // mm5 = b3 b2
+ movq_r2r (mm0, mm7); // mm7 = a3 a2 + rounder
+
+ paddd_r2r (mm5, mm0); // mm0 = a3+b3 a2+b2 + rounder
+ psubd_r2r (mm5, mm7); // mm7 = a3-b3 a2-b2 + rounder
+}
+
+static inline void mmx_row_tail (int16_t * row, int store)
+{
+ psrad_i2r (ROW_SHIFT, mm0); // mm0 = y3 y2
+
+ psrad_i2r (ROW_SHIFT, mm7); // mm7 = y4 y5
+
+ packssdw_r2r (mm0, mm1); // mm1 = y3 y2 y1 y0
+
+ packssdw_r2r (mm3, mm7); // mm7 = y6 y7 y4 y5
+
+ movq_r2m (mm1, *(row+store)); // save y3 y2 y1 y0
+ movq_r2r (mm7, mm4); // mm4 = y6 y7 y4 y5
+
+ pslld_i2r (16, mm7); // mm7 = y7 0 y5 0
+
+ psrld_i2r (16, mm4); // mm4 = 0 y6 0 y4
+
+ por_r2r (mm4, mm7); // mm7 = y7 y6 y5 y4
+
+ /* slot */
+
+ movq_r2m (mm7, *(row+store+4)); // save y7 y6 y5 y4
+}
+
+static inline void mmx_row_mid (int16_t * row, int store,
+ int offset, const int16_t * table)
+{
+ movq_m2r (*(row+offset), mm2); // mm2 = x6 x4 x2 x0
+ psrad_i2r (ROW_SHIFT, mm0); // mm0 = y3 y2
+
+ movq_m2r (*(row+offset+4), mm5); // mm5 = x7 x5 x3 x1
+ psrad_i2r (ROW_SHIFT, mm7); // mm7 = y4 y5
+
+ packssdw_r2r (mm0, mm1); // mm1 = y3 y2 y1 y0
+ movq_r2r (mm5, mm6); // mm6 = x7 x5 x3 x1
+
+ packssdw_r2r (mm3, mm7); // mm7 = y6 y7 y4 y5
+ movq_r2r (mm2, mm0); // mm0 = x6 x4 x2 x0
+
+ movq_r2m (mm1, *(row+store)); // save y3 y2 y1 y0
+ movq_r2r (mm7, mm1); // mm1 = y6 y7 y4 y5
+
+ punpckldq_r2r (mm0, mm0); // mm0 = x2 x0 x2 x0
+ psrld_i2r (16, mm7); // mm7 = 0 y6 0 y4
+
+ movq_m2r (*table, mm3); // mm3 = C6 C4 C2 C4
+ pslld_i2r (16, mm1); // mm1 = y7 0 y5 0
+
+ movq_m2r (*(table+4), mm4); // mm4 = -C2 -C4 C6 C4
+ por_r2r (mm1, mm7); // mm7 = y7 y6 y5 y4
+
+ movq_m2r (*(table+8), mm1); // mm1 = -C7 C3 C3 C1
+ punpckhdq_r2r (mm2, mm2); // mm2 = x6 x4 x6 x4
+
+ movq_r2m (mm7, *(row+store+4)); // save y7 y6 y5 y4
+ pmaddwd_r2r (mm0, mm3); // mm3 = C4*x0+C6*x2 C4*x0+C2*x2
+}
+
+
+#if 0
+// C column IDCT - its just here to document the MMXEXT and MMX versions
+static inline void idct_col (int16_t * col, int offset)
+{
+/* multiplication - as implemented on mmx */
+#define F(c,x) (((c) * (x)) >> 16)
+
+/* saturation - it helps us handle torture test cases */
+#define S(x) (((x)>32767) ? 32767 : ((x)<-32768) ? -32768 : (x))
+
+ int16_t x0, x1, x2, x3, x4, x5, x6, x7;
+ int16_t y0, y1, y2, y3, y4, y5, y6, y7;
+ int16_t a0, a1, a2, a3, b0, b1, b2, b3;
+ int16_t u04, v04, u26, v26, u17, v17, u35, v35, u12, v12;
+
+ col += offset;
+
+ x0 = col[0*8];
+ x1 = col[1*8];
+ x2 = col[2*8];
+ x3 = col[3*8];
+ x4 = col[4*8];
+ x5 = col[5*8];
+ x6 = col[6*8];
+ x7 = col[7*8];
+
+ u04 = S (x0 + x4);
+ v04 = S (x0 - x4);
+ u26 = S (F (T2, x6) + x2);
+ v26 = S (F (T2, x2) - x6);
+
+ a0 = S (u04 + u26);
+ a1 = S (v04 + v26);
+ a2 = S (v04 - v26);
+ a3 = S (u04 - u26);
+
+ u17 = S (F (T1, x7) + x1);
+ v17 = S (F (T1, x1) - x7);
+ u35 = S (F (T3, x5) + x3);
+ v35 = S (F (T3, x3) - x5);
+
+ b0 = S (u17 + u35);
+ b3 = S (v17 - v35);
+ u12 = S (u17 - u35);
+ v12 = S (v17 + v35);
+ u12 = S (2 * F (C4, u12));
+ v12 = S (2 * F (C4, v12));
+ b1 = S (u12 + v12);
+ b2 = S (u12 - v12);
+
+ y0 = S (a0 + b0) >> COL_SHIFT;
+ y1 = S (a1 + b1) >> COL_SHIFT;
+ y2 = S (a2 + b2) >> COL_SHIFT;
+ y3 = S (a3 + b3) >> COL_SHIFT;
+
+ y4 = S (a3 - b3) >> COL_SHIFT;
+ y5 = S (a2 - b2) >> COL_SHIFT;
+ y6 = S (a1 - b1) >> COL_SHIFT;
+ y7 = S (a0 - b0) >> COL_SHIFT;
+
+ col[0*8] = y0;
+ col[1*8] = y1;
+ col[2*8] = y2;
+ col[3*8] = y3;
+ col[4*8] = y4;
+ col[5*8] = y5;
+ col[6*8] = y6;
+ col[7*8] = y7;
+}
+#endif
+
+
+// MMX column IDCT
+static inline void idct_col (int16_t * col, int offset)
+{
+#define T1 13036
+#define T2 27146
+#define T3 43790
+#define C4 23170
+
+ static const short _T1[] ATTR_ALIGN(8) = {T1,T1,T1,T1};
+ static const short _T2[] ATTR_ALIGN(8) = {T2,T2,T2,T2};
+ static const short _T3[] ATTR_ALIGN(8) = {T3,T3,T3,T3};
+ static const short _C4[] ATTR_ALIGN(8) = {C4,C4,C4,C4};
+
+ /* column code adapted from peter gubanov */
+ /* http://www.elecard.com/peter/idct.shtml */
+
+ movq_m2r (*_T1, mm0); // mm0 = T1
+
+ movq_m2r (*(col+offset+1*8), mm1); // mm1 = x1
+ movq_r2r (mm0, mm2); // mm2 = T1
+
+ movq_m2r (*(col+offset+7*8), mm4); // mm4 = x7
+ pmulhw_r2r (mm1, mm0); // mm0 = T1*x1
+
+ movq_m2r (*_T3, mm5); // mm5 = T3
+ pmulhw_r2r (mm4, mm2); // mm2 = T1*x7
+
+ movq_m2r (*(col+offset+5*8), mm6); // mm6 = x5
+ movq_r2r (mm5, mm7); // mm7 = T3-1
+
+ movq_m2r (*(col+offset+3*8), mm3); // mm3 = x3
+ psubsw_r2r (mm4, mm0); // mm0 = v17
+
+ movq_m2r (*_T2, mm4); // mm4 = T2
+ pmulhw_r2r (mm3, mm5); // mm5 = (T3-1)*x3
+
+ paddsw_r2r (mm2, mm1); // mm1 = u17
+ pmulhw_r2r (mm6, mm7); // mm7 = (T3-1)*x5
+
+ /* slot */
+
+ movq_r2r (mm4, mm2); // mm2 = T2
+ paddsw_r2r (mm3, mm5); // mm5 = T3*x3
+
+ pmulhw_m2r (*(col+offset+2*8), mm4);// mm4 = T2*x2
+ paddsw_r2r (mm6, mm7); // mm7 = T3*x5
+
+ psubsw_r2r (mm6, mm5); // mm5 = v35
+ paddsw_r2r (mm3, mm7); // mm7 = u35
+
+ movq_m2r (*(col+offset+6*8), mm3); // mm3 = x6
+ movq_r2r (mm0, mm6); // mm6 = v17
+
+ pmulhw_r2r (mm3, mm2); // mm2 = T2*x6
+ psubsw_r2r (mm5, mm0); // mm0 = b3
+
+ psubsw_r2r (mm3, mm4); // mm4 = v26
+ paddsw_r2r (mm6, mm5); // mm5 = v12
+
+ movq_r2m (mm0, *(col+offset+3*8)); // save b3 in scratch0
+ movq_r2r (mm1, mm6); // mm6 = u17
+
+ paddsw_m2r (*(col+offset+2*8), mm2);// mm2 = u26
+ paddsw_r2r (mm7, mm6); // mm6 = b0
+
+ psubsw_r2r (mm7, mm1); // mm1 = u12
+ movq_r2r (mm1, mm7); // mm7 = u12
+
+ movq_m2r (*(col+offset+0*8), mm3); // mm3 = x0
+ paddsw_r2r (mm5, mm1); // mm1 = u12+v12
+
+ movq_m2r (*_C4, mm0); // mm0 = C4/2
+ psubsw_r2r (mm5, mm7); // mm7 = u12-v12
+
+ movq_r2m (mm6, *(col+offset+5*8)); // save b0 in scratch1
+ pmulhw_r2r (mm0, mm1); // mm1 = b1/2
+
+ movq_r2r (mm4, mm6); // mm6 = v26
+ pmulhw_r2r (mm0, mm7); // mm7 = b2/2
+
+ movq_m2r (*(col+offset+4*8), mm5); // mm5 = x4
+ movq_r2r (mm3, mm0); // mm0 = x0
+
+ psubsw_r2r (mm5, mm3); // mm3 = v04
+ paddsw_r2r (mm5, mm0); // mm0 = u04
+
+ paddsw_r2r (mm3, mm4); // mm4 = a1
+ movq_r2r (mm0, mm5); // mm5 = u04
+
+ psubsw_r2r (mm6, mm3); // mm3 = a2
+ paddsw_r2r (mm2, mm5); // mm5 = a0
+
+ paddsw_r2r (mm1, mm1); // mm1 = b1
+ psubsw_r2r (mm2, mm0); // mm0 = a3
+
+ paddsw_r2r (mm7, mm7); // mm7 = b2
+ movq_r2r (mm3, mm2); // mm2 = a2
+
+ movq_r2r (mm4, mm6); // mm6 = a1
+ paddsw_r2r (mm7, mm3); // mm3 = a2+b2
+
+ psraw_i2r (COL_SHIFT, mm3); // mm3 = y2
+ paddsw_r2r (mm1, mm4); // mm4 = a1+b1
+
+ psraw_i2r (COL_SHIFT, mm4); // mm4 = y1
+ psubsw_r2r (mm1, mm6); // mm6 = a1-b1
+
+ movq_m2r (*(col+offset+5*8), mm1); // mm1 = b0
+ psubsw_r2r (mm7, mm2); // mm2 = a2-b2
+
+ psraw_i2r (COL_SHIFT, mm6); // mm6 = y6
+ movq_r2r (mm5, mm7); // mm7 = a0
+
+ movq_r2m (mm4, *(col+offset+1*8)); // save y1
+ psraw_i2r (COL_SHIFT, mm2); // mm2 = y5
+
+ movq_r2m (mm3, *(col+offset+2*8)); // save y2
+ paddsw_r2r (mm1, mm5); // mm5 = a0+b0
+
+ movq_m2r (*(col+offset+3*8), mm4); // mm4 = b3
+ psubsw_r2r (mm1, mm7); // mm7 = a0-b0
+
+ psraw_i2r (COL_SHIFT, mm5); // mm5 = y0
+ movq_r2r (mm0, mm3); // mm3 = a3
+
+ movq_r2m (mm2, *(col+offset+5*8)); // save y5
+ psubsw_r2r (mm4, mm3); // mm3 = a3-b3
+
+ psraw_i2r (COL_SHIFT, mm7); // mm7 = y7
+ paddsw_r2r (mm0, mm4); // mm4 = a3+b3
+
+ movq_r2m (mm5, *(col+offset+0*8)); // save y0
+ psraw_i2r (COL_SHIFT, mm3); // mm3 = y4
+
+ movq_r2m (mm6, *(col+offset+6*8)); // save y6
+ psraw_i2r (COL_SHIFT, mm4); // mm4 = y3
+
+ movq_r2m (mm7, *(col+offset+7*8)); // save y7
+
+ movq_r2m (mm3, *(col+offset+4*8)); // save y4
+
+ movq_r2m (mm4, *(col+offset+3*8)); // save y3
+
+#undef T1
+#undef T2
+#undef T3
+#undef C4
+}
+
+static const int32_t rounder0[] ATTR_ALIGN(8) =
+ rounder ((1 << (COL_SHIFT - 1)) - 0.5);
+static const int32_t rounder4[] ATTR_ALIGN(8) = rounder (0);
+static const int32_t rounder1[] ATTR_ALIGN(8) =
+ rounder (1.25683487303); /* C1*(C1/C4+C1+C7)/2 */
+static const int32_t rounder7[] ATTR_ALIGN(8) =
+ rounder (-0.25); /* C1*(C7/C4+C7-C1)/2 */
+static const int32_t rounder2[] ATTR_ALIGN(8) =
+ rounder (0.60355339059); /* C2 * (C6+C2)/2 */
+static const int32_t rounder6[] ATTR_ALIGN(8) =
+ rounder (-0.25); /* C2 * (C6-C2)/2 */
+static const int32_t rounder3[] ATTR_ALIGN(8) =
+ rounder (0.087788325588); /* C3*(-C3/C4+C3+C5)/2 */
+static const int32_t rounder5[] ATTR_ALIGN(8) =
+ rounder (-0.441341716183); /* C3*(-C5/C4+C5-C3)/2 */
+
+#undef COL_SHIFT
+#undef ROW_SHIFT
+
+#define declare_idct(idct,table,idct_row_head,idct_row,idct_row_tail,idct_row_mid) \
+void idct (int16_t * block) \
+{ \
+ static const int16_t table04[] ATTR_ALIGN(16) = \
+ table (22725, 21407, 19266, 16384, 12873, 8867, 4520); \
+ static const int16_t table17[] ATTR_ALIGN(16) = \
+ table (31521, 29692, 26722, 22725, 17855, 12299, 6270); \
+ static const int16_t table26[] ATTR_ALIGN(16) = \
+ table (29692, 27969, 25172, 21407, 16819, 11585, 5906); \
+ static const int16_t table35[] ATTR_ALIGN(16) = \
+ table (26722, 25172, 22654, 19266, 15137, 10426, 5315); \
+ \
+ idct_row_head (block, 0*8, table04); \
+ idct_row (table04, rounder0); \
+ idct_row_mid (block, 0*8, 4*8, table04); \
+ idct_row (table04, rounder4); \
+ idct_row_mid (block, 4*8, 1*8, table17); \
+ idct_row (table17, rounder1); \
+ idct_row_mid (block, 1*8, 7*8, table17); \
+ idct_row (table17, rounder7); \
+ idct_row_mid (block, 7*8, 2*8, table26); \
+ idct_row (table26, rounder2); \
+ idct_row_mid (block, 2*8, 6*8, table26); \
+ idct_row (table26, rounder6); \
+ idct_row_mid (block, 6*8, 3*8, table35); \
+ idct_row (table35, rounder3); \
+ idct_row_mid (block, 3*8, 5*8, table35); \
+ idct_row (table35, rounder5); \
+ idct_row_tail (block, 5*8); \
+ \
+ idct_col (block, 0); \
+ idct_col (block, 4); \
+}
+
+void ff_mmx_idct(DCTELEM *block);
+void ff_mmxext_idct(DCTELEM *block);
+
+declare_idct (ff_mmxext_idct, mmxext_table,
+ mmxext_row_head, mmxext_row, mmxext_row_tail, mmxext_row_mid)
+
+declare_idct (ff_mmx_idct, mmx_table,
+ mmx_row_head, mmx_row, mmx_row_tail, mmx_row_mid)
+
diff --git a/contrib/ffmpeg/libavcodec/i386/idct_mmx_xvid.c b/contrib/ffmpeg/libavcodec/i386/idct_mmx_xvid.c
new file mode 100644
index 000000000..43eb329cc
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/idct_mmx_xvid.c
@@ -0,0 +1,535 @@
+///****************************************************************************
+// *
+// * XVID MPEG-4 VIDEO CODEC
+// * - MMX and XMM forward discrete cosine transform -
+// *
+// * Copyright(C) 2001 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
+// *
+// * $Id: idct_mmx_xvid.c,v 1.1.2.1 2006/12/02 01:19:55 dgp85 Exp $
+// *
+// ***************************************************************************/
+
+// ****************************************************************************
+//
+// 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 <peter@elecard.net.ru>
+// Rounding trick Copyright(C) 2000 Michel Lespinasse <walken@zoy.org>
+//
+// 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
+
+
+#include <inttypes.h>
+#include "../avcodec.h"
+
+//=============================================================================
+// 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)
+//-----------------------------------------------------------------------------
+
+
+static const int16_t tg_1_16[4*4] attribute_used __attribute__ ((aligned(8))) = {
+ 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
+
+static const int32_t rounder_0[2*8] attribute_used __attribute__ ((aligned(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
+static const int16_t tab_i_04_mmx[32*4] attribute_used __attribute__ ((aligned(8))) = {
+ 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
+static const int16_t tab_i_04_xmm[32*4] attribute_used __attribute__ ((aligned(8))) = {
+ 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_mmx2(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));
+}
+
diff --git a/contrib/ffmpeg/libavcodec/i386/mathops.h b/contrib/ffmpeg/libavcodec/i386/mathops.h
new file mode 100644
index 000000000..3553a4025
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/mathops.h
@@ -0,0 +1,41 @@
+/*
+ * simple math operations
+ * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> 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
+ */
+
+#ifdef FRAC_BITS
+# define MULL(ra, rb) \
+ ({ int rt, dummy; asm (\
+ "imull %3 \n\t"\
+ "shrdl %4, %%edx, %%eax \n\t"\
+ : "=a"(rt), "=d"(dummy)\
+ : "a" (ra), "rm" (rb), "i"(FRAC_BITS));\
+ rt; })
+#endif
+
+#define MULH(ra, rb) \
+ ({ int rt, dummy;\
+ asm ("imull %3\n\t" : "=d"(rt), "=a"(dummy): "a" (ra), "rm" (rb));\
+ rt; })
+
+#define MUL64(ra, rb) \
+ ({ int64_t rt;\
+ asm ("imull %2\n\t" : "=A"(rt) : "a" (ra), "g" (rb));\
+ rt; })
+
diff --git a/contrib/ffmpeg/libavcodec/i386/mmx.h b/contrib/ffmpeg/libavcodec/i386/mmx.h
new file mode 100644
index 000000000..41aae6c21
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/mmx.h
@@ -0,0 +1,283 @@
+/*
+ * mmx.h
+ * Copyright (C) 1997-2001 H. Dietz and R. Fisher
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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_I386MMX_H
+#define AVCODEC_I386MMX_H
+
+/*
+ * The type of an value that fits in an MMX register (note that long
+ * long constant values MUST be suffixed by LL and unsigned long long
+ * values by ULL, lest they be truncated by the compiler)
+ */
+
+typedef union {
+ long long q; /* Quadword (64-bit) value */
+ unsigned long long uq; /* Unsigned Quadword */
+ int d[2]; /* 2 Doubleword (32-bit) values */
+ unsigned int ud[2]; /* 2 Unsigned Doubleword */
+ short w[4]; /* 4 Word (16-bit) values */
+ unsigned short uw[4]; /* 4 Unsigned Word */
+ char b[8]; /* 8 Byte (8-bit) values */
+ unsigned char ub[8]; /* 8 Unsigned Byte */
+ float s[2]; /* Single-precision (32-bit) value */
+} mmx_t; /* On an 8-byte (64-bit) boundary */
+
+
+#define mmx_i2r(op,imm,reg) \
+ __asm__ __volatile__ (#op " %0, %%" #reg \
+ : /* nothing */ \
+ : "i" (imm) )
+
+#define mmx_m2r(op,mem,reg) \
+ __asm__ __volatile__ (#op " %0, %%" #reg \
+ : /* nothing */ \
+ : "m" (mem))
+
+#define mmx_r2m(op,reg,mem) \
+ __asm__ __volatile__ (#op " %%" #reg ", %0" \
+ : "=m" (mem) \
+ : /* nothing */ )
+
+#define mmx_r2r(op,regs,regd) \
+ __asm__ __volatile__ (#op " %" #regs ", %" #regd)
+
+
+#define emms() __asm__ __volatile__ ("emms")
+
+#define movd_m2r(var,reg) mmx_m2r (movd, var, reg)
+#define movd_r2m(reg,var) mmx_r2m (movd, reg, var)
+#define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd)
+
+#define movq_m2r(var,reg) mmx_m2r (movq, var, reg)
+#define movq_r2m(reg,var) mmx_r2m (movq, reg, var)
+#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd)
+
+#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg)
+#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd)
+#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg)
+#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd)
+
+#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg)
+#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd)
+
+#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg)
+#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd)
+#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg)
+#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd)
+#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg)
+#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd)
+
+#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg)
+#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd)
+#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg)
+#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd)
+
+#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg)
+#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd)
+#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg)
+#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd)
+
+#define pand_m2r(var,reg) mmx_m2r (pand, var, reg)
+#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd)
+
+#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg)
+#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd)
+
+#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg)
+#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd)
+#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg)
+#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd)
+#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg)
+#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd)
+
+#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg)
+#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd)
+#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg)
+#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd)
+#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg)
+#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd)
+
+#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg)
+#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd)
+
+#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg)
+#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd)
+
+#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg)
+#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd)
+
+#define por_m2r(var,reg) mmx_m2r (por, var, reg)
+#define por_r2r(regs,regd) mmx_r2r (por, regs, regd)
+
+#define pslld_i2r(imm,reg) mmx_i2r (pslld, imm, reg)
+#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg)
+#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd)
+#define psllq_i2r(imm,reg) mmx_i2r (psllq, imm, reg)
+#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg)
+#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd)
+#define psllw_i2r(imm,reg) mmx_i2r (psllw, imm, reg)
+#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg)
+#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd)
+
+#define psrad_i2r(imm,reg) mmx_i2r (psrad, imm, reg)
+#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg)
+#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd)
+#define psraw_i2r(imm,reg) mmx_i2r (psraw, imm, reg)
+#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg)
+#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd)
+
+#define psrld_i2r(imm,reg) mmx_i2r (psrld, imm, reg)
+#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg)
+#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd)
+#define psrlq_i2r(imm,reg) mmx_i2r (psrlq, imm, reg)
+#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg)
+#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd)
+#define psrlw_i2r(imm,reg) mmx_i2r (psrlw, imm, reg)
+#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg)
+#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd)
+
+#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg)
+#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd)
+#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg)
+#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd)
+#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg)
+#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd)
+
+#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg)
+#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd)
+#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg)
+#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd)
+
+#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg)
+#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd)
+#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg)
+#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd)
+
+#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg)
+#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd)
+#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg)
+#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd)
+#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg)
+#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd)
+
+#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg)
+#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd)
+#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg)
+#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd)
+#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg)
+#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd)
+
+#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg)
+#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd)
+
+
+/* 3DNOW extensions */
+
+#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg)
+#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd)
+
+
+/* AMD MMX extensions - also available in intel SSE */
+
+
+#define mmx_m2ri(op,mem,reg,imm) \
+ __asm__ __volatile__ (#op " %1, %0, %%" #reg \
+ : /* nothing */ \
+ : "m" (mem), "i" (imm))
+#define mmx_r2ri(op,regs,regd,imm) \
+ __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \
+ : /* nothing */ \
+ : "i" (imm) )
+
+#define mmx_fetch(mem,hint) \
+ __asm__ __volatile__ ("prefetch" #hint " %0" \
+ : /* nothing */ \
+ : "m" (mem))
+
+
+#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg)
+
+#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var)
+
+#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg)
+#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd)
+#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg)
+#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd)
+
+#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm)
+
+#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm)
+
+#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg)
+#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd)
+
+#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg)
+#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd)
+
+#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg)
+#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd)
+
+#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg)
+#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd)
+
+#define pmovmskb(mmreg,reg) \
+ __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg)
+
+#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg)
+#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd)
+
+#define prefetcht0(mem) mmx_fetch (mem, t0)
+#define prefetcht1(mem) mmx_fetch (mem, t1)
+#define prefetcht2(mem) mmx_fetch (mem, t2)
+#define prefetchnta(mem) mmx_fetch (mem, nta)
+
+#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg)
+#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd)
+
+#define pshufw_m2r(var,reg,imm) mmx_m2ri(pshufw, var, reg, imm)
+#define pshufw_r2r(regs,regd,imm) mmx_r2ri(pshufw, regs, regd, imm)
+
+#define sfence() __asm__ __volatile__ ("sfence\n\t")
+
+/* SSE2 */
+#define pshufhw_m2r(var,reg,imm) mmx_m2ri(pshufhw, var, reg, imm)
+#define pshufhw_r2r(regs,regd,imm) mmx_r2ri(pshufhw, regs, regd, imm)
+#define pshuflw_m2r(var,reg,imm) mmx_m2ri(pshuflw, var, reg, imm)
+#define pshuflw_r2r(regs,regd,imm) mmx_r2ri(pshuflw, regs, regd, imm)
+
+#define pshufd_r2r(regs,regd,imm) mmx_r2ri(pshufd, regs, regd, imm)
+
+#define movdqa_m2r(var,reg) mmx_m2r (movdqa, var, reg)
+#define movdqa_r2m(reg,var) mmx_r2m (movdqa, reg, var)
+#define movdqa_r2r(regs,regd) mmx_r2r (movdqa, regs, regd)
+#define movdqu_m2r(var,reg) mmx_m2r (movdqu, var, reg)
+#define movdqu_r2m(reg,var) mmx_r2m (movdqu, reg, var)
+#define movdqu_r2r(regs,regd) mmx_r2r (movdqu, regs, regd)
+
+#define pmullw_r2m(reg,var) mmx_r2m (pmullw, reg, var)
+
+#define pslldq_i2r(imm,reg) mmx_i2r (pslldq, imm, reg)
+#define psrldq_i2r(imm,reg) mmx_i2r (psrldq, imm, reg)
+
+#define punpcklqdq_r2r(regs,regd) mmx_r2r (punpcklqdq, regs, regd)
+#define punpckhqdq_r2r(regs,regd) mmx_r2r (punpckhqdq, regs, regd)
+
+
+#endif /* AVCODEC_I386MMX_H */
diff --git a/contrib/ffmpeg/libavcodec/i386/motion_est_mmx.c b/contrib/ffmpeg/libavcodec/i386/motion_est_mmx.c
new file mode 100644
index 000000000..e33870e0f
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/motion_est_mmx.c
@@ -0,0 +1,408 @@
+/*
+ * MMX optimized motion estimation
+ * 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
+ *
+ * mostly by Michael Niedermayer <michaelni@gmx.at>
+ */
+#include "../dsputil.h"
+#include "x86_cpu.h"
+
+static const __attribute__ ((aligned(8))) uint64_t round_tab[3]={
+0x0000000000000000ULL,
+0x0001000100010001ULL,
+0x0002000200020002ULL,
+};
+
+static attribute_used __attribute__ ((aligned(8))) uint64_t bone= 0x0101010101010101LL;
+
+static inline void sad8_1_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h)
+{
+ long len= -(stride*h);
+ asm volatile(
+ ASMALIGN(4)
+ "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" ((long)stride)
+ );
+}
+
+static inline void sad8_1_mmx2(uint8_t *blk1, uint8_t *blk2, int stride, int h)
+{
+ long len= -(stride*h);
+ asm volatile(
+ ASMALIGN(4)
+ "1: \n\t"
+ "movq (%1, %%"REG_a"), %%mm0 \n\t"
+ "movq (%2, %%"REG_a"), %%mm2 \n\t"
+ "psadbw %%mm2, %%mm0 \n\t"
+ "add %3, %%"REG_a" \n\t"
+ "movq (%1, %%"REG_a"), %%mm1 \n\t"
+ "movq (%2, %%"REG_a"), %%mm3 \n\t"
+ "psadbw %%mm1, %%mm3 \n\t"
+ "paddw %%mm3, %%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" ((long)stride)
+ );
+}
+
+static inline void sad8_2_mmx2(uint8_t *blk1a, uint8_t *blk1b, uint8_t *blk2, int stride, int h)
+{
+ long len= -(stride*h);
+ asm volatile(
+ ASMALIGN(4)
+ "1: \n\t"
+ "movq (%1, %%"REG_a"), %%mm0 \n\t"
+ "movq (%2, %%"REG_a"), %%mm2 \n\t"
+ "pavgb %%mm2, %%mm0 \n\t"
+ "movq (%3, %%"REG_a"), %%mm2 \n\t"
+ "psadbw %%mm2, %%mm0 \n\t"
+ "add %4, %%"REG_a" \n\t"
+ "movq (%1, %%"REG_a"), %%mm1 \n\t"
+ "movq (%2, %%"REG_a"), %%mm3 \n\t"
+ "pavgb %%mm1, %%mm3 \n\t"
+ "movq (%3, %%"REG_a"), %%mm1 \n\t"
+ "psadbw %%mm1, %%mm3 \n\t"
+ "paddw %%mm3, %%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" ((long)stride)
+ );
+}
+
+static inline void sad8_4_mmx2(uint8_t *blk1, uint8_t *blk2, int stride, int h)
+{ //FIXME reuse src
+ long len= -(stride*h);
+ asm volatile(
+ ASMALIGN(4)
+ "movq "MANGLE(bone)", %%mm5 \n\t"
+ "1: \n\t"
+ "movq (%1, %%"REG_a"), %%mm0 \n\t"
+ "movq (%2, %%"REG_a"), %%mm2 \n\t"
+ "movq 1(%1, %%"REG_a"), %%mm1 \n\t"
+ "movq 1(%2, %%"REG_a"), %%mm3 \n\t"
+ "pavgb %%mm2, %%mm0 \n\t"
+ "pavgb %%mm1, %%mm3 \n\t"
+ "psubusb %%mm5, %%mm3 \n\t"
+ "pavgb %%mm3, %%mm0 \n\t"
+ "movq (%3, %%"REG_a"), %%mm2 \n\t"
+ "psadbw %%mm2, %%mm0 \n\t"
+ "add %4, %%"REG_a" \n\t"
+ "movq (%1, %%"REG_a"), %%mm1 \n\t"
+ "movq (%2, %%"REG_a"), %%mm3 \n\t"
+ "movq 1(%1, %%"REG_a"), %%mm2 \n\t"
+ "movq 1(%2, %%"REG_a"), %%mm4 \n\t"
+ "pavgb %%mm3, %%mm1 \n\t"
+ "pavgb %%mm4, %%mm2 \n\t"
+ "psubusb %%mm5, %%mm2 \n\t"
+ "pavgb %%mm1, %%mm2 \n\t"
+ "movq (%3, %%"REG_a"), %%mm1 \n\t"
+ "psadbw %%mm1, %%mm2 \n\t"
+ "paddw %%mm2, %%mm0 \n\t"
+ "paddw %%mm0, %%mm6 \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" ((long)stride)
+ );
+}
+
+static inline void sad8_2_mmx(uint8_t *blk1a, uint8_t *blk1b, uint8_t *blk2, int stride, int h)
+{
+ long len= -(stride*h);
+ asm volatile(
+ ASMALIGN(4)
+ "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" ((long)stride)
+ );
+}
+
+static inline void sad8_4_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h)
+{
+ long len= -(stride*h);
+ asm volatile(
+ ASMALIGN(4)
+ "1: \n\t"
+ "movq (%1, %%"REG_a"), %%mm0 \n\t"
+ "movq (%2, %%"REG_a"), %%mm1 \n\t"
+ "movq %%mm0, %%mm4 \n\t"
+ "movq %%mm1, %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "punpckhbw %%mm7, %%mm4 \n\t"
+ "punpckhbw %%mm7, %%mm2 \n\t"
+ "paddw %%mm1, %%mm0 \n\t"
+ "paddw %%mm2, %%mm4 \n\t"
+ "movq 1(%1, %%"REG_a"), %%mm2 \n\t"
+ "movq 1(%2, %%"REG_a"), %%mm3 \n\t"
+ "movq %%mm2, %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "punpckhbw %%mm7, %%mm1 \n\t"
+ "paddw %%mm0, %%mm2 \n\t"
+ "paddw %%mm4, %%mm1 \n\t"
+ "movq %%mm3, %%mm4 \n\t"
+ "punpcklbw %%mm7, %%mm3 \n\t"
+ "punpckhbw %%mm7, %%mm4 \n\t"
+ "paddw %%mm3, %%mm2 \n\t"
+ "paddw %%mm4, %%mm1 \n\t"
+ "movq (%3, %%"REG_a"), %%mm3 \n\t"
+ "movq (%3, %%"REG_a"), %%mm4 \n\t"
+ "paddw %%mm5, %%mm2 \n\t"
+ "paddw %%mm5, %%mm1 \n\t"
+ "psrlw $2, %%mm2 \n\t"
+ "psrlw $2, %%mm1 \n\t"
+ "packuswb %%mm1, %%mm2 \n\t"
+ "psubusb %%mm2, %%mm3 \n\t"
+ "psubusb %%mm4, %%mm2 \n\t"
+ "por %%mm3, %%mm2 \n\t"
+ "movq %%mm2, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpckhbw %%mm7, %%mm2 \n\t"
+ "paddw %%mm2, %%mm0 \n\t"
+ "paddw %%mm0, %%mm6 \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" ((long)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_mmx2(void)
+{
+ int ret;
+ asm volatile(
+ "movd %%mm6, %0 \n\t"
+ : "=r" (ret)
+ );
+ return ret;
+}
+
+
+#define PIX_SAD(suf)\
+static int sad8_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\
+{\
+ assert(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)\
+{\
+ assert(h==8);\
+ asm volatile("pxor %%mm7, %%mm7 \n\t"\
+ "pxor %%mm6, %%mm6 \n\t"\
+ "movq %0, %%mm5 \n\t"\
+ :: "m"(round_tab[1]) \
+ );\
+\
+ sad8_2_ ## suf(blk1, blk1+1, blk2, stride, 8);\
+\
+ return sum_ ## suf();\
+}\
+\
+static int sad8_y2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\
+{\
+ assert(h==8);\
+ asm volatile("pxor %%mm7, %%mm7 \n\t"\
+ "pxor %%mm6, %%mm6 \n\t"\
+ "movq %0, %%mm5 \n\t"\
+ :: "m"(round_tab[1]) \
+ );\
+\
+ sad8_2_ ## suf(blk1, blk1+stride, blk2, stride, 8);\
+\
+ return sum_ ## suf();\
+}\
+\
+static int sad8_xy2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\
+{\
+ assert(h==8);\
+ asm volatile("pxor %%mm7, %%mm7 \n\t"\
+ "pxor %%mm6, %%mm6 \n\t"\
+ "movq %0, %%mm5 \n\t"\
+ :: "m"(round_tab[2]) \
+ );\
+\
+ 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_2_ ## suf(blk1 , blk1+1, blk2 , stride, h);\
+ sad8_2_ ## suf(blk1+8, blk1+9, 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_2_ ## suf(blk1 , blk1+stride, blk2 , stride, h);\
+ sad8_2_ ## suf(blk1+8, blk1+stride+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"\
+ "movq %0, %%mm5 \n\t"\
+ :: "m"(round_tab[2]) \
+ );\
+\
+ sad8_4_ ## suf(blk1 , blk2 , stride, h);\
+ sad8_4_ ## suf(blk1+8, blk2+8, stride, h);\
+\
+ return sum_ ## suf();\
+}\
+
+PIX_SAD(mmx)
+PIX_SAD(mmx2)
+
+void dsputil_init_pix_mmx(DSPContext* c, AVCodecContext *avctx)
+{
+ if (mm_flags & MM_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 & MM_MMXEXT) {
+ c->pix_abs[0][0] = sad16_mmx2;
+ c->pix_abs[1][0] = sad8_mmx2;
+
+ c->sad[0]= sad16_mmx2;
+ c->sad[1]= sad8_mmx2;
+
+ if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
+ c->pix_abs[0][1] = sad16_x2_mmx2;
+ c->pix_abs[0][2] = sad16_y2_mmx2;
+ c->pix_abs[0][3] = sad16_xy2_mmx2;
+ c->pix_abs[1][1] = sad8_x2_mmx2;
+ c->pix_abs[1][2] = sad8_y2_mmx2;
+ c->pix_abs[1][3] = sad8_xy2_mmx2;
+ }
+ }
+}
diff --git a/contrib/ffmpeg/libavcodec/i386/mpegvideo_mmx.c b/contrib/ffmpeg/libavcodec/i386/mpegvideo_mmx.c
new file mode 100644
index 000000000..1b7b1c19f
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/mpegvideo_mmx.c
@@ -0,0 +1,725 @@
+/*
+ * 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
+ *
+ * Optimized for ia32 cpus by Nick Kurshev <nickols_k@mail.ru>
+ * h263, mpeg1, mpeg2 dequantizer & draw_edges by Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#include "../dsputil.h"
+#include "../mpegvideo.h"
+#include "../avcodec.h"
+#include "x86_cpu.h"
+
+extern uint16_t inv_zigzag_direct16[64];
+
+static const unsigned long long int mm_wabs __attribute__ ((aligned(8))) = 0xffffffffffffffffULL;
+static const unsigned long long int mm_wone __attribute__ ((aligned(8))) = 0x0001000100010001ULL;
+
+
+static void dct_unquantize_h263_intra_mmx(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale)
+{
+ long level, qmul, qadd, nCoeffs;
+
+ qmul = qscale << 1;
+
+ assert(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] ];
+//printf("%d %d ", qmul, qadd);
+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"
+ ASMALIGN(4)
+ "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), "g"(qmul), "g" (qadd), "r" (2*(-nCoeffs))
+ : "memory"
+ );
+ block[0]= level;
+}
+
+
+static void dct_unquantize_h263_inter_mmx(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale)
+{
+ long 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] ];
+//printf("%d %d ", qmul, qadd);
+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"
+ ASMALIGN(4)
+ "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), "g"(qmul), "g" (qadd), "r" (2*(-nCoeffs))
+ : "memory"
+ );
+}
+
+
+/*
+ NK:
+ Note: looking at PARANOID:
+ "enable all paranoid tests for rounding, overflows, etc..."
+
+#ifdef PARANOID
+ if (level < -2048 || level > 2047)
+ fprintf(stderr, "unquant error %d %d\n", i, level);
+#endif
+ We can suppose that result of two multiplications can't be greate of 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,
+ DCTELEM *block, int n, int qscale)
+{
+ long nCoeffs;
+ const uint16_t *quant_matrix;
+ int block0;
+
+ assert(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"
+ ASMALIGN(4)
+ "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), "g" (qscale), "g" (-2*nCoeffs)
+ : "%"REG_a, "memory"
+ );
+ block[0]= block0;
+}
+
+static void dct_unquantize_mpeg1_inter_mmx(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale)
+{
+ long nCoeffs;
+ const uint16_t *quant_matrix;
+
+ assert(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"
+ ASMALIGN(4)
+ "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), "g" (qscale), "g" (-2*nCoeffs)
+ : "%"REG_a, "memory"
+ );
+}
+
+static void dct_unquantize_mpeg2_intra_mmx(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale)
+{
+ long nCoeffs;
+ const uint16_t *quant_matrix;
+ int block0;
+
+ assert(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"
+ ASMALIGN(4)
+ "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), "g" (qscale), "g" (-2*nCoeffs)
+ : "%"REG_a, "memory"
+ );
+ block[0]= block0;
+ //Note, we dont do mismatch control for intra as errors cannot accumulate
+}
+
+static void dct_unquantize_mpeg2_inter_mmx(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale)
+{
+ long nCoeffs;
+ const uint16_t *quant_matrix;
+
+ assert(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"
+ ASMALIGN(4)
+ "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), "g" (qscale), "r" (-2*nCoeffs)
+ : "%"REG_a, "memory"
+ );
+}
+
+/* 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)
+{
+ 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" ((long)wrap), "r" ((long)width), "r" (ptr + wrap*height)
+ );
+ }
+ else
+ {
+ 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" ((long)wrap), "r" ((long)width), "r" (ptr + wrap*height)
+ );
+ }
+
+ for(i=0;i<w;i+=4) {
+ /* top and bottom (and hopefully also the corners) */
+ 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" ((long)buf - (long)ptr - w), "r" ((long)-wrap), "r" ((long)-wrap*3), "r" (ptr+width+2*w)
+ );
+ 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" ((long)last_line - (long)ptr - w), "r" ((long)wrap), "r" ((long)wrap*3), "r" (ptr+width+2*w)
+ );
+ }
+}
+
+static void denoise_dct_mmx(MpegEncContext *s, DCTELEM *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, DCTELEM *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)
+ );
+}
+
+#undef HAVE_MMX2
+#define RENAME(a) a ## _MMX
+#define RENAMEl(a) a ## _mmx
+#include "mpegvideo_mmx_template.c"
+
+#define HAVE_MMX2
+#undef RENAME
+#undef RENAMEl
+#define RENAME(a) a ## _MMX2
+#define RENAMEl(a) a ## _mmx2
+#include "mpegvideo_mmx_template.c"
+
+#undef RENAME
+#undef RENAMEl
+#define RENAME(a) a ## _SSE2
+#define RENAMEl(a) a ## _sse2
+#include "mpegvideo_mmx_template.c"
+
+void MPV_common_init_mmx(MpegEncContext *s)
+{
+ if (mm_flags & MM_MMX) {
+ const int dct_algo = s->avctx->dct_algo;
+
+ 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;
+
+ draw_edges = draw_edges_mmx;
+
+ if (mm_flags & MM_SSE2) {
+ s->denoise_dct= denoise_dct_sse2;
+ } else {
+ s->denoise_dct= denoise_dct_mmx;
+ }
+
+ if(dct_algo==FF_DCT_AUTO || dct_algo==FF_DCT_MMX){
+ if(mm_flags & MM_SSE2){
+ s->dct_quantize= dct_quantize_SSE2;
+ } else if(mm_flags & MM_MMXEXT){
+ s->dct_quantize= dct_quantize_MMX2;
+ } else {
+ s->dct_quantize= dct_quantize_MMX;
+ }
+ }
+ }
+}
diff --git a/contrib/ffmpeg/libavcodec/i386/mpegvideo_mmx_template.c b/contrib/ffmpeg/libavcodec/i386/mpegvideo_mmx_template.c
new file mode 100644
index 000000000..d59b6efd9
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/mpegvideo_mmx_template.c
@@ -0,0 +1,348 @@
+/*
+ * MPEG video MMX templates
+ *
+ * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 SPREADW
+#undef PMAXW
+#undef PMAX
+#ifdef HAVE_MMX2
+#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
+
+static int RENAME(dct_quantize)(MpegEncContext *s,
+ DCTELEM *block, int n,
+ int qscale, int *overflow)
+{
+ long last_non_zero_p1;
+ int level=0, q; //=0 is cuz gcc says uninitalized ...
+ const uint16_t *qmat, *bias;
+ DECLARE_ALIGNED_8(int16_t, temp_block[64]);
+
+ assert((7&(int)(&temp_block[0])) == 0); //did gcc align it correctly?
+
+ //s->fdct (block);
+ RENAMEl(ff_fdct) (block); //cant 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;
+ else
+ q = s->c_dc_scale;
+ /* note: block[0] is assumed to be positive */
+ if (!s->h263_aic) {
+#if 1
+ asm volatile (
+ "mul %%ecx \n\t"
+ : "=d" (level), "=a"(dummy)
+ : "a" ((block[0]>>2) + q), "c" (ff_inverse[q<<1])
+ );
+#else
+ asm volatile (
+ "xorl %%edx, %%edx \n\t"
+ "divw %%cx \n\t"
+ "movzwl %%ax, %%eax \n\t"
+ : "=a" (level)
+ : "a" ((block[0]>>2) + q), "c" (q<<1)
+ : "%edx"
+ );
+#endif
+ } 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;
+ bias = s->q_intra_matrix16[qscale][1];
+ qmat = s->q_intra_matrix16[qscale][0];
+ } 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", %%mm3 \n\t" // last_non_zero_p1
+ SPREADW(%%mm3)
+ "pxor %%mm7, %%mm7 \n\t" // 0
+ "pxor %%mm4, %%mm4 \n\t" // 0
+ "movq (%2), %%mm5 \n\t" // qmat[0]
+ "pxor %%mm6, %%mm6 \n\t"
+ "psubw (%3), %%mm6 \n\t" // -bias[0]
+ "mov $-128, %%"REG_a" \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ "pxor %%mm1, %%mm1 \n\t" // 0
+ "movq (%1, %%"REG_a"), %%mm0 \n\t" // block[i]
+ "pcmpgtw %%mm0, %%mm1 \n\t" // block[i] <= 0 ? 0xFF : 0x00
+ "pxor %%mm1, %%mm0 \n\t"
+ "psubw %%mm1, %%mm0 \n\t" // ABS(block[i])
+ "psubusw %%mm6, %%mm0 \n\t" // ABS(block[i]) + bias[0]
+ "pmulhw %%mm5, %%mm0 \n\t" // (ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16
+ "por %%mm0, %%mm4 \n\t"
+ "pxor %%mm1, %%mm0 \n\t"
+ "psubw %%mm1, %%mm0 \n\t" // out=((ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16)*sign(block[i])
+ "movq %%mm0, (%5, %%"REG_a") \n\t"
+ "pcmpeqw %%mm7, %%mm0 \n\t" // out==0 ? 0xFF : 0x00
+ "movq (%4, %%"REG_a"), %%mm1 \n\t"
+ "movq %%mm7, (%1, %%"REG_a") \n\t" // 0
+ "pandn %%mm1, %%mm0 \n\t"
+ PMAXW(%%mm0, %%mm3)
+ "add $8, %%"REG_a" \n\t"
+ " js 1b \n\t"
+ PMAX(%%mm3, %%mm0)
+ "movd %%mm3, %%"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" (inv_zigzag_direct16+64), "r" (temp_block+64)
+ );
+ // note the asm is split cuz gcc doesnt like that many operands ...
+ asm volatile(
+ "movd %1, %%mm1 \n\t" // max_qcoeff
+ SPREADW(%%mm1)
+ "psubusw %%mm1, %%mm4 \n\t"
+ "packuswb %%mm4, %%mm4 \n\t"
+ "movd %%mm4, %0 \n\t" // *overflow
+ : "=g" (*overflow)
+ : "g" (s->max_qcoeff)
+ );
+ }else{ // FMT_H263
+ asm volatile(
+ "movd %%"REG_a", %%mm3 \n\t" // last_non_zero_p1
+ SPREADW(%%mm3)
+ "pxor %%mm7, %%mm7 \n\t" // 0
+ "pxor %%mm4, %%mm4 \n\t" // 0
+ "mov $-128, %%"REG_a" \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ "pxor %%mm1, %%mm1 \n\t" // 0
+ "movq (%1, %%"REG_a"), %%mm0 \n\t" // block[i]
+ "pcmpgtw %%mm0, %%mm1 \n\t" // block[i] <= 0 ? 0xFF : 0x00
+ "pxor %%mm1, %%mm0 \n\t"
+ "psubw %%mm1, %%mm0 \n\t" // ABS(block[i])
+ "movq (%3, %%"REG_a"), %%mm6 \n\t" // bias[0]
+ "paddusw %%mm6, %%mm0 \n\t" // ABS(block[i]) + bias[0]
+ "movq (%2, %%"REG_a"), %%mm5 \n\t" // qmat[i]
+ "pmulhw %%mm5, %%mm0 \n\t" // (ABS(block[i])*qmat[0] + bias[0]*qmat[0])>>16
+ "por %%mm0, %%mm4 \n\t"
+ "pxor %%mm1, %%mm0 \n\t"
+ "psubw %%mm1, %%mm0 \n\t" // out=((ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16)*sign(block[i])
+ "movq %%mm0, (%5, %%"REG_a") \n\t"
+ "pcmpeqw %%mm7, %%mm0 \n\t" // out==0 ? 0xFF : 0x00
+ "movq (%4, %%"REG_a"), %%mm1 \n\t"
+ "movq %%mm7, (%1, %%"REG_a") \n\t" // 0
+ "pandn %%mm1, %%mm0 \n\t"
+ PMAXW(%%mm0, %%mm3)
+ "add $8, %%"REG_a" \n\t"
+ " js 1b \n\t"
+ PMAX(%%mm3, %%mm0)
+ "movd %%mm3, %%"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" (inv_zigzag_direct16+64), "r" (temp_block+64)
+ );
+ // note the asm is split cuz gcc doesnt like that many operands ...
+ asm volatile(
+ "movd %1, %%mm1 \n\t" // max_qcoeff
+ SPREADW(%%mm1)
+ "psubusw %%mm1, %%mm4 \n\t"
+ "packuswb %%mm4, %%mm4 \n\t"
+ "movd %%mm4, %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:
+/*
+ for(i=0; i<last_non_zero_p1; i++)
+ {
+ int j= zigzag_direct_noperm[i];
+ block[block_permute_op(j)]= temp_block[j];
+ }
+*/
+
+ return last_non_zero_p1 - 1;
+}
diff --git a/contrib/ffmpeg/libavcodec/i386/simple_idct_mmx.c b/contrib/ffmpeg/libavcodec/i386/simple_idct_mmx.c
new file mode 100644
index 000000000..525ef34f7
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/simple_idct_mmx.c
@@ -0,0 +1,1294 @@
+/*
+ * Simple IDCT MMX
+ *
+ * Copyright (c) 2001, 2002 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * 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 "../simple_idct.h"
+
+/*
+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
+#if 0
+#define C4 16384 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
+#else
+#define C4 16383 //cos(i*M_PI/16)*sqrt(2)*(1<<14) - 0.5
+#endif
+#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
+
+static const uint64_t attribute_used __attribute__((aligned(8))) wm1010= 0xFFFF0000FFFF0000ULL;
+static const uint64_t attribute_used __attribute__((aligned(8))) d40000= 0x0000000000040000ULL;
+
+static const int16_t __attribute__((aligned(8))) 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)<<ROW_SHIFT :)
+// 0, 0, 0, 0,
+// 0, 0, 0, 0,
+
+ C4, C4, C4, C4,
+ C4, -C4, C4, -C4,
+
+ C2, C6, C2, C6,
+ C6, -C2, C6, -C2,
+
+ C1, C3, C1, C3,
+ C5, C7, C5, C7,
+
+ C3, -C7, C3, -C7,
+-C1, -C5, -C1, -C5,
+
+ C5, -C1, C5, -C1,
+ C7, C3, C7, C3,
+
+ C7, -C5, C7, -C5,
+ C3, -C1, C3, -C1
+};
+
+#if 0
+static void unused_var_killer(){
+ int a= wm1010 + d40000;
+ temp[0]=a;
+}
+
+static void inline idctCol (int16_t * col, int16_t *input)
+{
+#undef C0
+#undef C1
+#undef C2
+#undef C3
+#undef C4
+#undef C5
+#undef C6
+#undef C7
+ int a0, a1, a2, a3, b0, b1, b2, b3;
+ const int C0 = 23170; //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
+ const int C1 = 22725; //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
+ const int C2 = 21407; //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
+ const int C3 = 19266; //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
+ const int C4 = 16383; //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
+ const int C5 = 12873; //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
+ const int C6 = 8867; //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
+ const int C7 = 4520; //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
+/*
+ if( !(col[8*1] | col[8*2] |col[8*3] |col[8*4] |col[8*5] |col[8*6] | col[8*7])) {
+ col[8*0] = col[8*1] = col[8*2] = col[8*3] = col[8*4] =
+ col[8*5] = col[8*6] = col[8*7] = col[8*0]<<3;
+ return;
+ }*/
+
+col[8*0] = input[8*0 + 0];
+col[8*1] = input[8*2 + 0];
+col[8*2] = input[8*0 + 1];
+col[8*3] = input[8*2 + 1];
+col[8*4] = input[8*4 + 0];
+col[8*5] = input[8*6 + 0];
+col[8*6] = input[8*4 + 1];
+col[8*7] = input[8*6 + 1];
+
+ a0 = C4*col[8*0] + C2*col[8*2] + C4*col[8*4] + C6*col[8*6] + (1<<(COL_SHIFT-1));
+ a1 = C4*col[8*0] + C6*col[8*2] - C4*col[8*4] - C2*col[8*6] + (1<<(COL_SHIFT-1));
+ a2 = C4*col[8*0] - C6*col[8*2] - C4*col[8*4] + C2*col[8*6] + (1<<(COL_SHIFT-1));
+ a3 = C4*col[8*0] - C2*col[8*2] + C4*col[8*4] - C6*col[8*6] + (1<<(COL_SHIFT-1));
+
+ b0 = C1*col[8*1] + C3*col[8*3] + C5*col[8*5] + C7*col[8*7];
+ b1 = C3*col[8*1] - C7*col[8*3] - C1*col[8*5] - C5*col[8*7];
+ b2 = C5*col[8*1] - C1*col[8*3] + C7*col[8*5] + C3*col[8*7];
+ b3 = C7*col[8*1] - C5*col[8*3] + C3*col[8*5] - C1*col[8*7];
+
+ col[8*0] = (a0 + b0) >> COL_SHIFT;
+ col[8*1] = (a1 + b1) >> COL_SHIFT;
+ col[8*2] = (a2 + b2) >> COL_SHIFT;
+ col[8*3] = (a3 + b3) >> COL_SHIFT;
+ col[8*4] = (a3 - b3) >> COL_SHIFT;
+ col[8*5] = (a2 - b2) >> COL_SHIFT;
+ col[8*6] = (a1 - b1) >> COL_SHIFT;
+ col[8*7] = (a0 - b0) >> COL_SHIFT;
+}
+
+static void inline idctRow (int16_t * output, int16_t * input)
+{
+ int16_t row[8];
+
+ int a0, a1, a2, a3, b0, b1, b2, b3;
+ const int C0 = 23170; //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
+ const int C1 = 22725; //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
+ const int C2 = 21407; //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
+ const int C3 = 19266; //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
+ const int C4 = 16383; //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
+ const int C5 = 12873; //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
+ const int C6 = 8867; //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
+ const int C7 = 4520; //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
+
+row[0] = input[0];
+row[2] = input[1];
+row[4] = input[4];
+row[6] = input[5];
+row[1] = input[8];
+row[3] = input[9];
+row[5] = input[12];
+row[7] = input[13];
+
+ if( !(row[1] | row[2] |row[3] |row[4] |row[5] |row[6] | row[7]) ) {
+ row[0] = row[1] = row[2] = row[3] = row[4] =
+ row[5] = row[6] = row[7] = row[0]<<3;
+ output[0] = row[0];
+ output[2] = row[1];
+ output[4] = row[2];
+ output[6] = row[3];
+ output[8] = row[4];
+ output[10] = row[5];
+ output[12] = row[6];
+ output[14] = row[7];
+ return;
+ }
+
+ a0 = C4*row[0] + C2*row[2] + C4*row[4] + C6*row[6] + (1<<(ROW_SHIFT-1));
+ a1 = C4*row[0] + C6*row[2] - C4*row[4] - C2*row[6] + (1<<(ROW_SHIFT-1));
+ a2 = C4*row[0] - C6*row[2] - C4*row[4] + C2*row[6] + (1<<(ROW_SHIFT-1));
+ a3 = C4*row[0] - C2*row[2] + C4*row[4] - C6*row[6] + (1<<(ROW_SHIFT-1));
+
+ b0 = C1*row[1] + C3*row[3] + C5*row[5] + C7*row[7];
+ b1 = C3*row[1] - C7*row[3] - C1*row[5] - C5*row[7];
+ b2 = C5*row[1] - C1*row[3] + C7*row[5] + C3*row[7];
+ b3 = C7*row[1] - C5*row[3] + C3*row[5] - C1*row[7];
+
+ 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;
+
+ output[0] = row[0];
+ output[2] = row[1];
+ output[4] = row[2];
+ output[6] = row[3];
+ output[8] = row[4];
+ output[10] = row[5];
+ output[12] = row[6];
+ output[14] = row[7];
+}
+#endif
+
+static inline void idct(int16_t *block)
+{
+ int64_t __attribute__((aligned(8))) align_tmp[16];
+ int16_t * const temp= (int16_t*)align_tmp;
+
+ asm volatile(
+#if 0 //Alternative, simpler variant
+
+#define ROW_IDCT(src0, src4, src1, src5, dst, rounder, shift) \
+ "movq " #src0 ", %%mm0 \n\t" /* R4 R0 r4 r0 */\
+ "movq " #src4 ", %%mm1 \n\t" /* R6 R2 r6 r2 */\
+ "movq " #src1 ", %%mm2 \n\t" /* R3 R1 r3 r1 */\
+ "movq " #src5 ", %%mm3 \n\t" /* R7 R5 r7 r5 */\
+ "movq 16(%2), %%mm4 \n\t" /* C4 C4 C4 C4 */\
+ "pmaddwd %%mm0, %%mm4 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 24(%2), %%mm5 \n\t" /* -C4 C4 -C4 C4 */\
+ "pmaddwd %%mm5, %%mm0 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq 32(%2), %%mm5 \n\t" /* C6 C2 C6 C2 */\
+ "pmaddwd %%mm1, %%mm5 \n\t" /* C6R6+C2R2 C6r6+C2r2 */\
+ "movq 40(%2), %%mm6 \n\t" /* -C2 C6 -C2 C6 */\
+ "pmaddwd %%mm6, %%mm1 \n\t" /* -C2R6+C6R2 -C2r6+C6r2 */\
+ "movq 48(%2), %%mm7 \n\t" /* C3 C1 C3 C1 */\
+ "pmaddwd %%mm2, %%mm7 \n\t" /* C3R3+C1R1 C3r3+C1r1 */\
+ #rounder ", %%mm4 \n\t"\
+ "movq %%mm4, %%mm6 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "paddd %%mm5, %%mm4 \n\t" /* A0 a0 */\
+ "psubd %%mm5, %%mm6 \n\t" /* A3 a3 */\
+ "movq 56(%2), %%mm5 \n\t" /* C7 C5 C7 C5 */\
+ "pmaddwd %%mm3, %%mm5 \n\t" /* C7R7+C5R5 C7r7+C5r5 */\
+ #rounder ", %%mm0 \n\t"\
+ "paddd %%mm0, %%mm1 \n\t" /* A1 a1 */\
+ "paddd %%mm0, %%mm0 \n\t" \
+ "psubd %%mm1, %%mm0 \n\t" /* A2 a2 */\
+ "pmaddwd 64(%2), %%mm2 \n\t" /* -C7R3+C3R1 -C7r3+C3r1 */\
+ "paddd %%mm5, %%mm7 \n\t" /* B0 b0 */\
+ "movq 72(%2), %%mm5 \n\t" /* -C5 -C1 -C5 -C1 */\
+ "pmaddwd %%mm3, %%mm5 \n\t" /* -C5R7-C1R5 -C5r7-C1r5 */\
+ "paddd %%mm4, %%mm7 \n\t" /* A0+B0 a0+b0 */\
+ "paddd %%mm4, %%mm4 \n\t" /* 2A0 2a0 */\
+ "psubd %%mm7, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "paddd %%mm2, %%mm5 \n\t" /* B1 b1 */\
+ "psrad $" #shift ", %%mm7 \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "movq %%mm1, %%mm2 \n\t" /* A1 a1 */\
+ "paddd %%mm5, %%mm1 \n\t" /* A1+B1 a1+b1 */\
+ "psubd %%mm5, %%mm2 \n\t" /* A1-B1 a1-b1 */\
+ "psrad $" #shift ", %%mm1 \n\t"\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "packssdw %%mm1, %%mm7 \n\t" /* A1+B1 a1+b1 A0+B0 a0+b0 */\
+ "packssdw %%mm4, %%mm2 \n\t" /* A0-B0 a0-b0 A1-B1 a1-b1 */\
+ "movq %%mm7, " #dst " \n\t"\
+ "movq " #src1 ", %%mm1 \n\t" /* R3 R1 r3 r1 */\
+ "movq 80(%2), %%mm4 \n\t" /* -C1 C5 -C1 C5 */\
+ "movq %%mm2, 24+" #dst " \n\t"\
+ "pmaddwd %%mm1, %%mm4 \n\t" /* -C1R3+C5R1 -C1r3+C5r1 */\
+ "movq 88(%2), %%mm7 \n\t" /* C3 C7 C3 C7 */\
+ "pmaddwd 96(%2), %%mm1 \n\t" /* -C5R3+C7R1 -C5r3+C7r1 */\
+ "pmaddwd %%mm3, %%mm7 \n\t" /* C3R7+C7R5 C3r7+C7r5 */\
+ "movq %%mm0, %%mm2 \n\t" /* A2 a2 */\
+ "pmaddwd 104(%2), %%mm3 \n\t" /* -C1R7+C3R5 -C1r7+C3r5 */\
+ "paddd %%mm7, %%mm4 \n\t" /* B2 b2 */\
+ "paddd %%mm4, %%mm2 \n\t" /* A2+B2 a2+b2 */\
+ "psubd %%mm4, %%mm0 \n\t" /* a2-B2 a2-b2 */\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "psrad $" #shift ", %%mm0 \n\t"\
+ "movq %%mm6, %%mm4 \n\t" /* A3 a3 */\
+ "paddd %%mm1, %%mm3 \n\t" /* B3 b3 */\
+ "paddd %%mm3, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "psubd %%mm3, %%mm4 \n\t" /* a3-B3 a3-b3 */\
+ "psrad $" #shift ", %%mm6 \n\t"\
+ "packssdw %%mm6, %%mm2 \n\t" /* A3+B3 a3+b3 A2+B2 a2+b2 */\
+ "movq %%mm2, 8+" #dst " \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "packssdw %%mm0, %%mm4 \n\t" /* A2-B2 a2-b2 A3-B3 a3-b3 */\
+ "movq %%mm4, 16+" #dst " \n\t"\
+
+#define COL_IDCT(src0, src4, src1, src5, dst, shift) \
+ "movq " #src0 ", %%mm0 \n\t" /* R4 R0 r4 r0 */\
+ "movq " #src4 ", %%mm1 \n\t" /* R6 R2 r6 r2 */\
+ "movq " #src1 ", %%mm2 \n\t" /* R3 R1 r3 r1 */\
+ "movq " #src5 ", %%mm3 \n\t" /* R7 R5 r7 r5 */\
+ "movq 16(%2), %%mm4 \n\t" /* C4 C4 C4 C4 */\
+ "pmaddwd %%mm0, %%mm4 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 24(%2), %%mm5 \n\t" /* -C4 C4 -C4 C4 */\
+ "pmaddwd %%mm5, %%mm0 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq 32(%2), %%mm5 \n\t" /* C6 C2 C6 C2 */\
+ "pmaddwd %%mm1, %%mm5 \n\t" /* C6R6+C2R2 C6r6+C2r2 */\
+ "movq 40(%2), %%mm6 \n\t" /* -C2 C6 -C2 C6 */\
+ "pmaddwd %%mm6, %%mm1 \n\t" /* -C2R6+C6R2 -C2r6+C6r2 */\
+ "movq %%mm4, %%mm6 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 48(%2), %%mm7 \n\t" /* C3 C1 C3 C1 */\
+ "pmaddwd %%mm2, %%mm7 \n\t" /* C3R3+C1R1 C3r3+C1r1 */\
+ "paddd %%mm5, %%mm4 \n\t" /* A0 a0 */\
+ "psubd %%mm5, %%mm6 \n\t" /* A3 a3 */\
+ "movq %%mm0, %%mm5 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "paddd %%mm1, %%mm0 \n\t" /* A1 a1 */\
+ "psubd %%mm1, %%mm5 \n\t" /* A2 a2 */\
+ "movq 56(%2), %%mm1 \n\t" /* C7 C5 C7 C5 */\
+ "pmaddwd %%mm3, %%mm1 \n\t" /* C7R7+C5R5 C7r7+C5r5 */\
+ "pmaddwd 64(%2), %%mm2 \n\t" /* -C7R3+C3R1 -C7r3+C3r1 */\
+ "paddd %%mm1, %%mm7 \n\t" /* B0 b0 */\
+ "movq 72(%2), %%mm1 \n\t" /* -C5 -C1 -C5 -C1 */\
+ "pmaddwd %%mm3, %%mm1 \n\t" /* -C5R7-C1R5 -C5r7-C1r5 */\
+ "paddd %%mm4, %%mm7 \n\t" /* A0+B0 a0+b0 */\
+ "paddd %%mm4, %%mm4 \n\t" /* 2A0 2a0 */\
+ "psubd %%mm7, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "paddd %%mm2, %%mm1 \n\t" /* B1 b1 */\
+ "psrad $" #shift ", %%mm7 \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "movq %%mm0, %%mm2 \n\t" /* A1 a1 */\
+ "paddd %%mm1, %%mm0 \n\t" /* A1+B1 a1+b1 */\
+ "psubd %%mm1, %%mm2 \n\t" /* A1-B1 a1-b1 */\
+ "psrad $" #shift ", %%mm0 \n\t"\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "packssdw %%mm7, %%mm7 \n\t" /* A0+B0 a0+b0 */\
+ "movd %%mm7, " #dst " \n\t"\
+ "packssdw %%mm0, %%mm0 \n\t" /* A1+B1 a1+b1 */\
+ "movd %%mm0, 16+" #dst " \n\t"\
+ "packssdw %%mm2, %%mm2 \n\t" /* A1-B1 a1-b1 */\
+ "movd %%mm2, 96+" #dst " \n\t"\
+ "packssdw %%mm4, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "movd %%mm4, 112+" #dst " \n\t"\
+ "movq " #src1 ", %%mm0 \n\t" /* R3 R1 r3 r1 */\
+ "movq 80(%2), %%mm4 \n\t" /* -C1 C5 -C1 C5 */\
+ "pmaddwd %%mm0, %%mm4 \n\t" /* -C1R3+C5R1 -C1r3+C5r1 */\
+ "movq 88(%2), %%mm7 \n\t" /* C3 C7 C3 C7 */\
+ "pmaddwd 96(%2), %%mm0 \n\t" /* -C5R3+C7R1 -C5r3+C7r1 */\
+ "pmaddwd %%mm3, %%mm7 \n\t" /* C3R7+C7R5 C3r7+C7r5 */\
+ "movq %%mm5, %%mm2 \n\t" /* A2 a2 */\
+ "pmaddwd 104(%2), %%mm3 \n\t" /* -C1R7+C3R5 -C1r7+C3r5 */\
+ "paddd %%mm7, %%mm4 \n\t" /* B2 b2 */\
+ "paddd %%mm4, %%mm2 \n\t" /* A2+B2 a2+b2 */\
+ "psubd %%mm4, %%mm5 \n\t" /* a2-B2 a2-b2 */\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "psrad $" #shift ", %%mm5 \n\t"\
+ "movq %%mm6, %%mm4 \n\t" /* A3 a3 */\
+ "paddd %%mm0, %%mm3 \n\t" /* B3 b3 */\
+ "paddd %%mm3, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "psubd %%mm3, %%mm4 \n\t" /* a3-B3 a3-b3 */\
+ "psrad $" #shift ", %%mm6 \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "packssdw %%mm2, %%mm2 \n\t" /* A2+B2 a2+b2 */\
+ "packssdw %%mm6, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "movd %%mm2, 32+" #dst " \n\t"\
+ "packssdw %%mm4, %%mm4 \n\t" /* A3-B3 a3-b3 */\
+ "packssdw %%mm5, %%mm5 \n\t" /* A2-B2 a2-b2 */\
+ "movd %%mm6, 48+" #dst " \n\t"\
+ "movd %%mm4, 64+" #dst " \n\t"\
+ "movd %%mm5, 80+" #dst " \n\t"\
+
+
+#define DC_COND_ROW_IDCT(src0, src4, src1, src5, dst, rounder, shift) \
+ "movq " #src0 ", %%mm0 \n\t" /* R4 R0 r4 r0 */\
+ "movq " #src4 ", %%mm1 \n\t" /* R6 R2 r6 r2 */\
+ "movq " #src1 ", %%mm2 \n\t" /* R3 R1 r3 r1 */\
+ "movq " #src5 ", %%mm3 \n\t" /* R7 R5 r7 r5 */\
+ "movq "MANGLE(wm1010)", %%mm4 \n\t"\
+ "pand %%mm0, %%mm4 \n\t"\
+ "por %%mm1, %%mm4 \n\t"\
+ "por %%mm2, %%mm4 \n\t"\
+ "por %%mm3, %%mm4 \n\t"\
+ "packssdw %%mm4,%%mm4 \n\t"\
+ "movd %%mm4, %%eax \n\t"\
+ "orl %%eax, %%eax \n\t"\
+ "jz 1f \n\t"\
+ "movq 16(%2), %%mm4 \n\t" /* C4 C4 C4 C4 */\
+ "pmaddwd %%mm0, %%mm4 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 24(%2), %%mm5 \n\t" /* -C4 C4 -C4 C4 */\
+ "pmaddwd %%mm5, %%mm0 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq 32(%2), %%mm5 \n\t" /* C6 C2 C6 C2 */\
+ "pmaddwd %%mm1, %%mm5 \n\t" /* C6R6+C2R2 C6r6+C2r2 */\
+ "movq 40(%2), %%mm6 \n\t" /* -C2 C6 -C2 C6 */\
+ "pmaddwd %%mm6, %%mm1 \n\t" /* -C2R6+C6R2 -C2r6+C6r2 */\
+ "movq 48(%2), %%mm7 \n\t" /* C3 C1 C3 C1 */\
+ "pmaddwd %%mm2, %%mm7 \n\t" /* C3R3+C1R1 C3r3+C1r1 */\
+ #rounder ", %%mm4 \n\t"\
+ "movq %%mm4, %%mm6 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "paddd %%mm5, %%mm4 \n\t" /* A0 a0 */\
+ "psubd %%mm5, %%mm6 \n\t" /* A3 a3 */\
+ "movq 56(%2), %%mm5 \n\t" /* C7 C5 C7 C5 */\
+ "pmaddwd %%mm3, %%mm5 \n\t" /* C7R7+C5R5 C7r7+C5r5 */\
+ #rounder ", %%mm0 \n\t"\
+ "paddd %%mm0, %%mm1 \n\t" /* A1 a1 */\
+ "paddd %%mm0, %%mm0 \n\t" \
+ "psubd %%mm1, %%mm0 \n\t" /* A2 a2 */\
+ "pmaddwd 64(%2), %%mm2 \n\t" /* -C7R3+C3R1 -C7r3+C3r1 */\
+ "paddd %%mm5, %%mm7 \n\t" /* B0 b0 */\
+ "movq 72(%2), %%mm5 \n\t" /* -C5 -C1 -C5 -C1 */\
+ "pmaddwd %%mm3, %%mm5 \n\t" /* -C5R7-C1R5 -C5r7-C1r5 */\
+ "paddd %%mm4, %%mm7 \n\t" /* A0+B0 a0+b0 */\
+ "paddd %%mm4, %%mm4 \n\t" /* 2A0 2a0 */\
+ "psubd %%mm7, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "paddd %%mm2, %%mm5 \n\t" /* B1 b1 */\
+ "psrad $" #shift ", %%mm7 \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "movq %%mm1, %%mm2 \n\t" /* A1 a1 */\
+ "paddd %%mm5, %%mm1 \n\t" /* A1+B1 a1+b1 */\
+ "psubd %%mm5, %%mm2 \n\t" /* A1-B1 a1-b1 */\
+ "psrad $" #shift ", %%mm1 \n\t"\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "packssdw %%mm1, %%mm7 \n\t" /* A1+B1 a1+b1 A0+B0 a0+b0 */\
+ "packssdw %%mm4, %%mm2 \n\t" /* A0-B0 a0-b0 A1-B1 a1-b1 */\
+ "movq %%mm7, " #dst " \n\t"\
+ "movq " #src1 ", %%mm1 \n\t" /* R3 R1 r3 r1 */\
+ "movq 80(%2), %%mm4 \n\t" /* -C1 C5 -C1 C5 */\
+ "movq %%mm2, 24+" #dst " \n\t"\
+ "pmaddwd %%mm1, %%mm4 \n\t" /* -C1R3+C5R1 -C1r3+C5r1 */\
+ "movq 88(%2), %%mm7 \n\t" /* C3 C7 C3 C7 */\
+ "pmaddwd 96(%2), %%mm1 \n\t" /* -C5R3+C7R1 -C5r3+C7r1 */\
+ "pmaddwd %%mm3, %%mm7 \n\t" /* C3R7+C7R5 C3r7+C7r5 */\
+ "movq %%mm0, %%mm2 \n\t" /* A2 a2 */\
+ "pmaddwd 104(%2), %%mm3 \n\t" /* -C1R7+C3R5 -C1r7+C3r5 */\
+ "paddd %%mm7, %%mm4 \n\t" /* B2 b2 */\
+ "paddd %%mm4, %%mm2 \n\t" /* A2+B2 a2+b2 */\
+ "psubd %%mm4, %%mm0 \n\t" /* a2-B2 a2-b2 */\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "psrad $" #shift ", %%mm0 \n\t"\
+ "movq %%mm6, %%mm4 \n\t" /* A3 a3 */\
+ "paddd %%mm1, %%mm3 \n\t" /* B3 b3 */\
+ "paddd %%mm3, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "psubd %%mm3, %%mm4 \n\t" /* a3-B3 a3-b3 */\
+ "psrad $" #shift ", %%mm6 \n\t"\
+ "packssdw %%mm6, %%mm2 \n\t" /* A3+B3 a3+b3 A2+B2 a2+b2 */\
+ "movq %%mm2, 8+" #dst " \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "packssdw %%mm0, %%mm4 \n\t" /* A2-B2 a2-b2 A3-B3 a3-b3 */\
+ "movq %%mm4, 16+" #dst " \n\t"\
+ "jmp 2f \n\t"\
+ "1: \n\t"\
+ "pslld $16, %%mm0 \n\t"\
+ "#paddd "MANGLE(d40000)", %%mm0 \n\t"\
+ "psrad $13, %%mm0 \n\t"\
+ "packssdw %%mm0, %%mm0 \n\t"\
+ "movq %%mm0, " #dst " \n\t"\
+ "movq %%mm0, 8+" #dst " \n\t"\
+ "movq %%mm0, 16+" #dst " \n\t"\
+ "movq %%mm0, 24+" #dst " \n\t"\
+ "2: \n\t"
+
+
+//IDCT( src0, src4, src1, src5, dst, rounder, shift)
+ROW_IDCT( (%0), 8(%0), 16(%0), 24(%0), 0(%1),paddd 8(%2), 11)
+/*ROW_IDCT( 32(%0), 40(%0), 48(%0), 56(%0), 32(%1), paddd (%2), 11)
+ROW_IDCT( 64(%0), 72(%0), 80(%0), 88(%0), 64(%1), paddd (%2), 11)
+ROW_IDCT( 96(%0),104(%0),112(%0),120(%0), 96(%1), paddd (%2), 11)*/
+
+DC_COND_ROW_IDCT( 32(%0), 40(%0), 48(%0), 56(%0), 32(%1),paddd (%2), 11)
+DC_COND_ROW_IDCT( 64(%0), 72(%0), 80(%0), 88(%0), 64(%1),paddd (%2), 11)
+DC_COND_ROW_IDCT( 96(%0),104(%0),112(%0),120(%0), 96(%1),paddd (%2), 11)
+
+
+//IDCT( src0, src4, src1, src5, dst, shift)
+COL_IDCT( (%1), 64(%1), 32(%1), 96(%1), 0(%0), 20)
+COL_IDCT( 8(%1), 72(%1), 40(%1), 104(%1), 4(%0), 20)
+COL_IDCT( 16(%1), 80(%1), 48(%1), 112(%1), 8(%0), 20)
+COL_IDCT( 24(%1), 88(%1), 56(%1), 120(%1), 12(%0), 20)
+
+#else
+
+#define DC_COND_IDCT(src0, src4, src1, src5, dst, rounder, shift) \
+ "movq " #src0 ", %%mm0 \n\t" /* R4 R0 r4 r0 */\
+ "movq " #src4 ", %%mm1 \n\t" /* R6 R2 r6 r2 */\
+ "movq " #src1 ", %%mm2 \n\t" /* R3 R1 r3 r1 */\
+ "movq " #src5 ", %%mm3 \n\t" /* R7 R5 r7 r5 */\
+ "movq "MANGLE(wm1010)", %%mm4 \n\t"\
+ "pand %%mm0, %%mm4 \n\t"\
+ "por %%mm1, %%mm4 \n\t"\
+ "por %%mm2, %%mm4 \n\t"\
+ "por %%mm3, %%mm4 \n\t"\
+ "packssdw %%mm4,%%mm4 \n\t"\
+ "movd %%mm4, %%eax \n\t"\
+ "orl %%eax, %%eax \n\t"\
+ "jz 1f \n\t"\
+ "movq 16(%2), %%mm4 \n\t" /* C4 C4 C4 C4 */\
+ "pmaddwd %%mm0, %%mm4 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 24(%2), %%mm5 \n\t" /* -C4 C4 -C4 C4 */\
+ "pmaddwd %%mm5, %%mm0 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq 32(%2), %%mm5 \n\t" /* C6 C2 C6 C2 */\
+ "pmaddwd %%mm1, %%mm5 \n\t" /* C6R6+C2R2 C6r6+C2r2 */\
+ "movq 40(%2), %%mm6 \n\t" /* -C2 C6 -C2 C6 */\
+ "pmaddwd %%mm6, %%mm1 \n\t" /* -C2R6+C6R2 -C2r6+C6r2 */\
+ "movq 48(%2), %%mm7 \n\t" /* C3 C1 C3 C1 */\
+ "pmaddwd %%mm2, %%mm7 \n\t" /* C3R3+C1R1 C3r3+C1r1 */\
+ #rounder ", %%mm4 \n\t"\
+ "movq %%mm4, %%mm6 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "paddd %%mm5, %%mm4 \n\t" /* A0 a0 */\
+ "psubd %%mm5, %%mm6 \n\t" /* A3 a3 */\
+ "movq 56(%2), %%mm5 \n\t" /* C7 C5 C7 C5 */\
+ "pmaddwd %%mm3, %%mm5 \n\t" /* C7R7+C5R5 C7r7+C5r5 */\
+ #rounder ", %%mm0 \n\t"\
+ "paddd %%mm0, %%mm1 \n\t" /* A1 a1 */\
+ "paddd %%mm0, %%mm0 \n\t" \
+ "psubd %%mm1, %%mm0 \n\t" /* A2 a2 */\
+ "pmaddwd 64(%2), %%mm2 \n\t" /* -C7R3+C3R1 -C7r3+C3r1 */\
+ "paddd %%mm5, %%mm7 \n\t" /* B0 b0 */\
+ "movq 72(%2), %%mm5 \n\t" /* -C5 -C1 -C5 -C1 */\
+ "pmaddwd %%mm3, %%mm5 \n\t" /* -C5R7-C1R5 -C5r7-C1r5 */\
+ "paddd %%mm4, %%mm7 \n\t" /* A0+B0 a0+b0 */\
+ "paddd %%mm4, %%mm4 \n\t" /* 2A0 2a0 */\
+ "psubd %%mm7, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "paddd %%mm2, %%mm5 \n\t" /* B1 b1 */\
+ "psrad $" #shift ", %%mm7 \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "movq %%mm1, %%mm2 \n\t" /* A1 a1 */\
+ "paddd %%mm5, %%mm1 \n\t" /* A1+B1 a1+b1 */\
+ "psubd %%mm5, %%mm2 \n\t" /* A1-B1 a1-b1 */\
+ "psrad $" #shift ", %%mm1 \n\t"\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "packssdw %%mm1, %%mm7 \n\t" /* A1+B1 a1+b1 A0+B0 a0+b0 */\
+ "packssdw %%mm4, %%mm2 \n\t" /* A0-B0 a0-b0 A1-B1 a1-b1 */\
+ "movq %%mm7, " #dst " \n\t"\
+ "movq " #src1 ", %%mm1 \n\t" /* R3 R1 r3 r1 */\
+ "movq 80(%2), %%mm4 \n\t" /* -C1 C5 -C1 C5 */\
+ "movq %%mm2, 24+" #dst " \n\t"\
+ "pmaddwd %%mm1, %%mm4 \n\t" /* -C1R3+C5R1 -C1r3+C5r1 */\
+ "movq 88(%2), %%mm7 \n\t" /* C3 C7 C3 C7 */\
+ "pmaddwd 96(%2), %%mm1 \n\t" /* -C5R3+C7R1 -C5r3+C7r1 */\
+ "pmaddwd %%mm3, %%mm7 \n\t" /* C3R7+C7R5 C3r7+C7r5 */\
+ "movq %%mm0, %%mm2 \n\t" /* A2 a2 */\
+ "pmaddwd 104(%2), %%mm3 \n\t" /* -C1R7+C3R5 -C1r7+C3r5 */\
+ "paddd %%mm7, %%mm4 \n\t" /* B2 b2 */\
+ "paddd %%mm4, %%mm2 \n\t" /* A2+B2 a2+b2 */\
+ "psubd %%mm4, %%mm0 \n\t" /* a2-B2 a2-b2 */\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "psrad $" #shift ", %%mm0 \n\t"\
+ "movq %%mm6, %%mm4 \n\t" /* A3 a3 */\
+ "paddd %%mm1, %%mm3 \n\t" /* B3 b3 */\
+ "paddd %%mm3, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "psubd %%mm3, %%mm4 \n\t" /* a3-B3 a3-b3 */\
+ "psrad $" #shift ", %%mm6 \n\t"\
+ "packssdw %%mm6, %%mm2 \n\t" /* A3+B3 a3+b3 A2+B2 a2+b2 */\
+ "movq %%mm2, 8+" #dst " \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "packssdw %%mm0, %%mm4 \n\t" /* A2-B2 a2-b2 A3-B3 a3-b3 */\
+ "movq %%mm4, 16+" #dst " \n\t"\
+ "jmp 2f \n\t"\
+ "1: \n\t"\
+ "pslld $16, %%mm0 \n\t"\
+ "paddd "MANGLE(d40000)", %%mm0 \n\t"\
+ "psrad $13, %%mm0 \n\t"\
+ "packssdw %%mm0, %%mm0 \n\t"\
+ "movq %%mm0, " #dst " \n\t"\
+ "movq %%mm0, 8+" #dst " \n\t"\
+ "movq %%mm0, 16+" #dst " \n\t"\
+ "movq %%mm0, 24+" #dst " \n\t"\
+ "2: \n\t"
+
+#define Z_COND_IDCT(src0, src4, src1, src5, dst, rounder, shift, bt) \
+ "movq " #src0 ", %%mm0 \n\t" /* R4 R0 r4 r0 */\
+ "movq " #src4 ", %%mm1 \n\t" /* R6 R2 r6 r2 */\
+ "movq " #src1 ", %%mm2 \n\t" /* R3 R1 r3 r1 */\
+ "movq " #src5 ", %%mm3 \n\t" /* R7 R5 r7 r5 */\
+ "movq %%mm0, %%mm4 \n\t"\
+ "por %%mm1, %%mm4 \n\t"\
+ "por %%mm2, %%mm4 \n\t"\
+ "por %%mm3, %%mm4 \n\t"\
+ "packssdw %%mm4,%%mm4 \n\t"\
+ "movd %%mm4, %%eax \n\t"\
+ "orl %%eax, %%eax \n\t"\
+ "jz " #bt " \n\t"\
+ "movq 16(%2), %%mm4 \n\t" /* C4 C4 C4 C4 */\
+ "pmaddwd %%mm0, %%mm4 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 24(%2), %%mm5 \n\t" /* -C4 C4 -C4 C4 */\
+ "pmaddwd %%mm5, %%mm0 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq 32(%2), %%mm5 \n\t" /* C6 C2 C6 C2 */\
+ "pmaddwd %%mm1, %%mm5 \n\t" /* C6R6+C2R2 C6r6+C2r2 */\
+ "movq 40(%2), %%mm6 \n\t" /* -C2 C6 -C2 C6 */\
+ "pmaddwd %%mm6, %%mm1 \n\t" /* -C2R6+C6R2 -C2r6+C6r2 */\
+ "movq 48(%2), %%mm7 \n\t" /* C3 C1 C3 C1 */\
+ "pmaddwd %%mm2, %%mm7 \n\t" /* C3R3+C1R1 C3r3+C1r1 */\
+ #rounder ", %%mm4 \n\t"\
+ "movq %%mm4, %%mm6 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "paddd %%mm5, %%mm4 \n\t" /* A0 a0 */\
+ "psubd %%mm5, %%mm6 \n\t" /* A3 a3 */\
+ "movq 56(%2), %%mm5 \n\t" /* C7 C5 C7 C5 */\
+ "pmaddwd %%mm3, %%mm5 \n\t" /* C7R7+C5R5 C7r7+C5r5 */\
+ #rounder ", %%mm0 \n\t"\
+ "paddd %%mm0, %%mm1 \n\t" /* A1 a1 */\
+ "paddd %%mm0, %%mm0 \n\t" \
+ "psubd %%mm1, %%mm0 \n\t" /* A2 a2 */\
+ "pmaddwd 64(%2), %%mm2 \n\t" /* -C7R3+C3R1 -C7r3+C3r1 */\
+ "paddd %%mm5, %%mm7 \n\t" /* B0 b0 */\
+ "movq 72(%2), %%mm5 \n\t" /* -C5 -C1 -C5 -C1 */\
+ "pmaddwd %%mm3, %%mm5 \n\t" /* -C5R7-C1R5 -C5r7-C1r5 */\
+ "paddd %%mm4, %%mm7 \n\t" /* A0+B0 a0+b0 */\
+ "paddd %%mm4, %%mm4 \n\t" /* 2A0 2a0 */\
+ "psubd %%mm7, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "paddd %%mm2, %%mm5 \n\t" /* B1 b1 */\
+ "psrad $" #shift ", %%mm7 \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "movq %%mm1, %%mm2 \n\t" /* A1 a1 */\
+ "paddd %%mm5, %%mm1 \n\t" /* A1+B1 a1+b1 */\
+ "psubd %%mm5, %%mm2 \n\t" /* A1-B1 a1-b1 */\
+ "psrad $" #shift ", %%mm1 \n\t"\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "packssdw %%mm1, %%mm7 \n\t" /* A1+B1 a1+b1 A0+B0 a0+b0 */\
+ "packssdw %%mm4, %%mm2 \n\t" /* A0-B0 a0-b0 A1-B1 a1-b1 */\
+ "movq %%mm7, " #dst " \n\t"\
+ "movq " #src1 ", %%mm1 \n\t" /* R3 R1 r3 r1 */\
+ "movq 80(%2), %%mm4 \n\t" /* -C1 C5 -C1 C5 */\
+ "movq %%mm2, 24+" #dst " \n\t"\
+ "pmaddwd %%mm1, %%mm4 \n\t" /* -C1R3+C5R1 -C1r3+C5r1 */\
+ "movq 88(%2), %%mm7 \n\t" /* C3 C7 C3 C7 */\
+ "pmaddwd 96(%2), %%mm1 \n\t" /* -C5R3+C7R1 -C5r3+C7r1 */\
+ "pmaddwd %%mm3, %%mm7 \n\t" /* C3R7+C7R5 C3r7+C7r5 */\
+ "movq %%mm0, %%mm2 \n\t" /* A2 a2 */\
+ "pmaddwd 104(%2), %%mm3 \n\t" /* -C1R7+C3R5 -C1r7+C3r5 */\
+ "paddd %%mm7, %%mm4 \n\t" /* B2 b2 */\
+ "paddd %%mm4, %%mm2 \n\t" /* A2+B2 a2+b2 */\
+ "psubd %%mm4, %%mm0 \n\t" /* a2-B2 a2-b2 */\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "psrad $" #shift ", %%mm0 \n\t"\
+ "movq %%mm6, %%mm4 \n\t" /* A3 a3 */\
+ "paddd %%mm1, %%mm3 \n\t" /* B3 b3 */\
+ "paddd %%mm3, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "psubd %%mm3, %%mm4 \n\t" /* a3-B3 a3-b3 */\
+ "psrad $" #shift ", %%mm6 \n\t"\
+ "packssdw %%mm6, %%mm2 \n\t" /* A3+B3 a3+b3 A2+B2 a2+b2 */\
+ "movq %%mm2, 8+" #dst " \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "packssdw %%mm0, %%mm4 \n\t" /* A2-B2 a2-b2 A3-B3 a3-b3 */\
+ "movq %%mm4, 16+" #dst " \n\t"\
+
+#define ROW_IDCT(src0, src4, src1, src5, dst, rounder, shift) \
+ "movq " #src0 ", %%mm0 \n\t" /* R4 R0 r4 r0 */\
+ "movq " #src4 ", %%mm1 \n\t" /* R6 R2 r6 r2 */\
+ "movq " #src1 ", %%mm2 \n\t" /* R3 R1 r3 r1 */\
+ "movq " #src5 ", %%mm3 \n\t" /* R7 R5 r7 r5 */\
+ "movq 16(%2), %%mm4 \n\t" /* C4 C4 C4 C4 */\
+ "pmaddwd %%mm0, %%mm4 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 24(%2), %%mm5 \n\t" /* -C4 C4 -C4 C4 */\
+ "pmaddwd %%mm5, %%mm0 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq 32(%2), %%mm5 \n\t" /* C6 C2 C6 C2 */\
+ "pmaddwd %%mm1, %%mm5 \n\t" /* C6R6+C2R2 C6r6+C2r2 */\
+ "movq 40(%2), %%mm6 \n\t" /* -C2 C6 -C2 C6 */\
+ "pmaddwd %%mm6, %%mm1 \n\t" /* -C2R6+C6R2 -C2r6+C6r2 */\
+ "movq 48(%2), %%mm7 \n\t" /* C3 C1 C3 C1 */\
+ "pmaddwd %%mm2, %%mm7 \n\t" /* C3R3+C1R1 C3r3+C1r1 */\
+ #rounder ", %%mm4 \n\t"\
+ "movq %%mm4, %%mm6 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "paddd %%mm5, %%mm4 \n\t" /* A0 a0 */\
+ "psubd %%mm5, %%mm6 \n\t" /* A3 a3 */\
+ "movq 56(%2), %%mm5 \n\t" /* C7 C5 C7 C5 */\
+ "pmaddwd %%mm3, %%mm5 \n\t" /* C7R7+C5R5 C7r7+C5r5 */\
+ #rounder ", %%mm0 \n\t"\
+ "paddd %%mm0, %%mm1 \n\t" /* A1 a1 */\
+ "paddd %%mm0, %%mm0 \n\t" \
+ "psubd %%mm1, %%mm0 \n\t" /* A2 a2 */\
+ "pmaddwd 64(%2), %%mm2 \n\t" /* -C7R3+C3R1 -C7r3+C3r1 */\
+ "paddd %%mm5, %%mm7 \n\t" /* B0 b0 */\
+ "movq 72(%2), %%mm5 \n\t" /* -C5 -C1 -C5 -C1 */\
+ "pmaddwd %%mm3, %%mm5 \n\t" /* -C5R7-C1R5 -C5r7-C1r5 */\
+ "paddd %%mm4, %%mm7 \n\t" /* A0+B0 a0+b0 */\
+ "paddd %%mm4, %%mm4 \n\t" /* 2A0 2a0 */\
+ "psubd %%mm7, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "paddd %%mm2, %%mm5 \n\t" /* B1 b1 */\
+ "psrad $" #shift ", %%mm7 \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "movq %%mm1, %%mm2 \n\t" /* A1 a1 */\
+ "paddd %%mm5, %%mm1 \n\t" /* A1+B1 a1+b1 */\
+ "psubd %%mm5, %%mm2 \n\t" /* A1-B1 a1-b1 */\
+ "psrad $" #shift ", %%mm1 \n\t"\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "packssdw %%mm1, %%mm7 \n\t" /* A1+B1 a1+b1 A0+B0 a0+b0 */\
+ "packssdw %%mm4, %%mm2 \n\t" /* A0-B0 a0-b0 A1-B1 a1-b1 */\
+ "movq %%mm7, " #dst " \n\t"\
+ "movq " #src1 ", %%mm1 \n\t" /* R3 R1 r3 r1 */\
+ "movq 80(%2), %%mm4 \n\t" /* -C1 C5 -C1 C5 */\
+ "movq %%mm2, 24+" #dst " \n\t"\
+ "pmaddwd %%mm1, %%mm4 \n\t" /* -C1R3+C5R1 -C1r3+C5r1 */\
+ "movq 88(%2), %%mm7 \n\t" /* C3 C7 C3 C7 */\
+ "pmaddwd 96(%2), %%mm1 \n\t" /* -C5R3+C7R1 -C5r3+C7r1 */\
+ "pmaddwd %%mm3, %%mm7 \n\t" /* C3R7+C7R5 C3r7+C7r5 */\
+ "movq %%mm0, %%mm2 \n\t" /* A2 a2 */\
+ "pmaddwd 104(%2), %%mm3 \n\t" /* -C1R7+C3R5 -C1r7+C3r5 */\
+ "paddd %%mm7, %%mm4 \n\t" /* B2 b2 */\
+ "paddd %%mm4, %%mm2 \n\t" /* A2+B2 a2+b2 */\
+ "psubd %%mm4, %%mm0 \n\t" /* a2-B2 a2-b2 */\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "psrad $" #shift ", %%mm0 \n\t"\
+ "movq %%mm6, %%mm4 \n\t" /* A3 a3 */\
+ "paddd %%mm1, %%mm3 \n\t" /* B3 b3 */\
+ "paddd %%mm3, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "psubd %%mm3, %%mm4 \n\t" /* a3-B3 a3-b3 */\
+ "psrad $" #shift ", %%mm6 \n\t"\
+ "packssdw %%mm6, %%mm2 \n\t" /* A3+B3 a3+b3 A2+B2 a2+b2 */\
+ "movq %%mm2, 8+" #dst " \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "packssdw %%mm0, %%mm4 \n\t" /* A2-B2 a2-b2 A3-B3 a3-b3 */\
+ "movq %%mm4, 16+" #dst " \n\t"\
+
+//IDCT( src0, src4, src1, src5, dst, rounder, shift)
+DC_COND_IDCT( 0(%0), 8(%0), 16(%0), 24(%0), 0(%1),paddd 8(%2), 11)
+Z_COND_IDCT( 32(%0), 40(%0), 48(%0), 56(%0), 32(%1),paddd (%2), 11, 4f)
+Z_COND_IDCT( 64(%0), 72(%0), 80(%0), 88(%0), 64(%1),paddd (%2), 11, 2f)
+Z_COND_IDCT( 96(%0),104(%0),112(%0),120(%0), 96(%1),paddd (%2), 11, 1f)
+
+#undef IDCT
+#define IDCT(src0, src4, src1, src5, dst, shift) \
+ "movq " #src0 ", %%mm0 \n\t" /* R4 R0 r4 r0 */\
+ "movq " #src4 ", %%mm1 \n\t" /* R6 R2 r6 r2 */\
+ "movq " #src1 ", %%mm2 \n\t" /* R3 R1 r3 r1 */\
+ "movq " #src5 ", %%mm3 \n\t" /* R7 R5 r7 r5 */\
+ "movq 16(%2), %%mm4 \n\t" /* C4 C4 C4 C4 */\
+ "pmaddwd %%mm0, %%mm4 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 24(%2), %%mm5 \n\t" /* -C4 C4 -C4 C4 */\
+ "pmaddwd %%mm5, %%mm0 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq 32(%2), %%mm5 \n\t" /* C6 C2 C6 C2 */\
+ "pmaddwd %%mm1, %%mm5 \n\t" /* C6R6+C2R2 C6r6+C2r2 */\
+ "movq 40(%2), %%mm6 \n\t" /* -C2 C6 -C2 C6 */\
+ "pmaddwd %%mm6, %%mm1 \n\t" /* -C2R6+C6R2 -C2r6+C6r2 */\
+ "movq %%mm4, %%mm6 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 48(%2), %%mm7 \n\t" /* C3 C1 C3 C1 */\
+ "pmaddwd %%mm2, %%mm7 \n\t" /* C3R3+C1R1 C3r3+C1r1 */\
+ "paddd %%mm5, %%mm4 \n\t" /* A0 a0 */\
+ "psubd %%mm5, %%mm6 \n\t" /* A3 a3 */\
+ "movq %%mm0, %%mm5 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "paddd %%mm1, %%mm0 \n\t" /* A1 a1 */\
+ "psubd %%mm1, %%mm5 \n\t" /* A2 a2 */\
+ "movq 56(%2), %%mm1 \n\t" /* C7 C5 C7 C5 */\
+ "pmaddwd %%mm3, %%mm1 \n\t" /* C7R7+C5R5 C7r7+C5r5 */\
+ "pmaddwd 64(%2), %%mm2 \n\t" /* -C7R3+C3R1 -C7r3+C3r1 */\
+ "paddd %%mm1, %%mm7 \n\t" /* B0 b0 */\
+ "movq 72(%2), %%mm1 \n\t" /* -C5 -C1 -C5 -C1 */\
+ "pmaddwd %%mm3, %%mm1 \n\t" /* -C5R7-C1R5 -C5r7-C1r5 */\
+ "paddd %%mm4, %%mm7 \n\t" /* A0+B0 a0+b0 */\
+ "paddd %%mm4, %%mm4 \n\t" /* 2A0 2a0 */\
+ "psubd %%mm7, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "paddd %%mm2, %%mm1 \n\t" /* B1 b1 */\
+ "psrad $" #shift ", %%mm7 \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "movq %%mm0, %%mm2 \n\t" /* A1 a1 */\
+ "paddd %%mm1, %%mm0 \n\t" /* A1+B1 a1+b1 */\
+ "psubd %%mm1, %%mm2 \n\t" /* A1-B1 a1-b1 */\
+ "psrad $" #shift ", %%mm0 \n\t"\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "packssdw %%mm7, %%mm7 \n\t" /* A0+B0 a0+b0 */\
+ "movd %%mm7, " #dst " \n\t"\
+ "packssdw %%mm0, %%mm0 \n\t" /* A1+B1 a1+b1 */\
+ "movd %%mm0, 16+" #dst " \n\t"\
+ "packssdw %%mm2, %%mm2 \n\t" /* A1-B1 a1-b1 */\
+ "movd %%mm2, 96+" #dst " \n\t"\
+ "packssdw %%mm4, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "movd %%mm4, 112+" #dst " \n\t"\
+ "movq " #src1 ", %%mm0 \n\t" /* R3 R1 r3 r1 */\
+ "movq 80(%2), %%mm4 \n\t" /* -C1 C5 -C1 C5 */\
+ "pmaddwd %%mm0, %%mm4 \n\t" /* -C1R3+C5R1 -C1r3+C5r1 */\
+ "movq 88(%2), %%mm7 \n\t" /* C3 C7 C3 C7 */\
+ "pmaddwd 96(%2), %%mm0 \n\t" /* -C5R3+C7R1 -C5r3+C7r1 */\
+ "pmaddwd %%mm3, %%mm7 \n\t" /* C3R7+C7R5 C3r7+C7r5 */\
+ "movq %%mm5, %%mm2 \n\t" /* A2 a2 */\
+ "pmaddwd 104(%2), %%mm3 \n\t" /* -C1R7+C3R5 -C1r7+C3r5 */\
+ "paddd %%mm7, %%mm4 \n\t" /* B2 b2 */\
+ "paddd %%mm4, %%mm2 \n\t" /* A2+B2 a2+b2 */\
+ "psubd %%mm4, %%mm5 \n\t" /* a2-B2 a2-b2 */\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "psrad $" #shift ", %%mm5 \n\t"\
+ "movq %%mm6, %%mm4 \n\t" /* A3 a3 */\
+ "paddd %%mm0, %%mm3 \n\t" /* B3 b3 */\
+ "paddd %%mm3, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "psubd %%mm3, %%mm4 \n\t" /* a3-B3 a3-b3 */\
+ "psrad $" #shift ", %%mm6 \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "packssdw %%mm2, %%mm2 \n\t" /* A2+B2 a2+b2 */\
+ "packssdw %%mm6, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "movd %%mm2, 32+" #dst " \n\t"\
+ "packssdw %%mm4, %%mm4 \n\t" /* A3-B3 a3-b3 */\
+ "packssdw %%mm5, %%mm5 \n\t" /* A2-B2 a2-b2 */\
+ "movd %%mm6, 48+" #dst " \n\t"\
+ "movd %%mm4, 64+" #dst " \n\t"\
+ "movd %%mm5, 80+" #dst " \n\t"
+
+
+//IDCT( src0, src4, src1, src5, dst, shift)
+IDCT( (%1), 64(%1), 32(%1), 96(%1), 0(%0), 20)
+IDCT( 8(%1), 72(%1), 40(%1), 104(%1), 4(%0), 20)
+IDCT( 16(%1), 80(%1), 48(%1), 112(%1), 8(%0), 20)
+IDCT( 24(%1), 88(%1), 56(%1), 120(%1), 12(%0), 20)
+ "jmp 9f \n\t"
+
+ "#" ASMALIGN(4) \
+ "4: \n\t"
+Z_COND_IDCT( 64(%0), 72(%0), 80(%0), 88(%0), 64(%1),paddd (%2), 11, 6f)
+Z_COND_IDCT( 96(%0),104(%0),112(%0),120(%0), 96(%1),paddd (%2), 11, 5f)
+
+#undef IDCT
+#define IDCT(src0, src4, src1, src5, dst, shift) \
+ "movq " #src0 ", %%mm0 \n\t" /* R4 R0 r4 r0 */\
+ "movq " #src4 ", %%mm1 \n\t" /* R6 R2 r6 r2 */\
+ "movq " #src5 ", %%mm3 \n\t" /* R7 R5 r7 r5 */\
+ "movq 16(%2), %%mm4 \n\t" /* C4 C4 C4 C4 */\
+ "pmaddwd %%mm0, %%mm4 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 24(%2), %%mm5 \n\t" /* -C4 C4 -C4 C4 */\
+ "pmaddwd %%mm5, %%mm0 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq 32(%2), %%mm5 \n\t" /* C6 C2 C6 C2 */\
+ "pmaddwd %%mm1, %%mm5 \n\t" /* C6R6+C2R2 C6r6+C2r2 */\
+ "movq 40(%2), %%mm6 \n\t" /* -C2 C6 -C2 C6 */\
+ "pmaddwd %%mm6, %%mm1 \n\t" /* -C2R6+C6R2 -C2r6+C6r2 */\
+ "movq %%mm4, %%mm6 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "paddd %%mm5, %%mm4 \n\t" /* A0 a0 */\
+ "psubd %%mm5, %%mm6 \n\t" /* A3 a3 */\
+ "movq %%mm0, %%mm5 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "paddd %%mm1, %%mm0 \n\t" /* A1 a1 */\
+ "psubd %%mm1, %%mm5 \n\t" /* A2 a2 */\
+ "movq 56(%2), %%mm1 \n\t" /* C7 C5 C7 C5 */\
+ "pmaddwd %%mm3, %%mm1 \n\t" /* C7R7+C5R5 C7r7+C5r5 */\
+ "movq 72(%2), %%mm7 \n\t" /* -C5 -C1 -C5 -C1 */\
+ "pmaddwd %%mm3, %%mm7 \n\t" /* -C5R7-C1R5 -C5r7-C1r5 */\
+ "paddd %%mm4, %%mm1 \n\t" /* A0+B0 a0+b0 */\
+ "paddd %%mm4, %%mm4 \n\t" /* 2A0 2a0 */\
+ "psubd %%mm1, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "psrad $" #shift ", %%mm1 \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "movq %%mm0, %%mm2 \n\t" /* A1 a1 */\
+ "paddd %%mm7, %%mm0 \n\t" /* A1+B1 a1+b1 */\
+ "psubd %%mm7, %%mm2 \n\t" /* A1-B1 a1-b1 */\
+ "psrad $" #shift ", %%mm0 \n\t"\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "packssdw %%mm1, %%mm1 \n\t" /* A0+B0 a0+b0 */\
+ "movd %%mm1, " #dst " \n\t"\
+ "packssdw %%mm0, %%mm0 \n\t" /* A1+B1 a1+b1 */\
+ "movd %%mm0, 16+" #dst " \n\t"\
+ "packssdw %%mm2, %%mm2 \n\t" /* A1-B1 a1-b1 */\
+ "movd %%mm2, 96+" #dst " \n\t"\
+ "packssdw %%mm4, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "movd %%mm4, 112+" #dst " \n\t"\
+ "movq 88(%2), %%mm1 \n\t" /* C3 C7 C3 C7 */\
+ "pmaddwd %%mm3, %%mm1 \n\t" /* C3R7+C7R5 C3r7+C7r5 */\
+ "movq %%mm5, %%mm2 \n\t" /* A2 a2 */\
+ "pmaddwd 104(%2), %%mm3 \n\t" /* -C1R7+C3R5 -C1r7+C3r5 */\
+ "paddd %%mm1, %%mm2 \n\t" /* A2+B2 a2+b2 */\
+ "psubd %%mm1, %%mm5 \n\t" /* a2-B2 a2-b2 */\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "psrad $" #shift ", %%mm5 \n\t"\
+ "movq %%mm6, %%mm1 \n\t" /* A3 a3 */\
+ "paddd %%mm3, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "psubd %%mm3, %%mm1 \n\t" /* a3-B3 a3-b3 */\
+ "psrad $" #shift ", %%mm6 \n\t"\
+ "psrad $" #shift ", %%mm1 \n\t"\
+ "packssdw %%mm2, %%mm2 \n\t" /* A2+B2 a2+b2 */\
+ "packssdw %%mm6, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "movd %%mm2, 32+" #dst " \n\t"\
+ "packssdw %%mm1, %%mm1 \n\t" /* A3-B3 a3-b3 */\
+ "packssdw %%mm5, %%mm5 \n\t" /* A2-B2 a2-b2 */\
+ "movd %%mm6, 48+" #dst " \n\t"\
+ "movd %%mm1, 64+" #dst " \n\t"\
+ "movd %%mm5, 80+" #dst " \n\t"
+
+//IDCT( src0, src4, src1, src5, dst, shift)
+IDCT( (%1), 64(%1), 32(%1), 96(%1), 0(%0), 20)
+IDCT( 8(%1), 72(%1), 40(%1), 104(%1), 4(%0), 20)
+IDCT( 16(%1), 80(%1), 48(%1), 112(%1), 8(%0), 20)
+IDCT( 24(%1), 88(%1), 56(%1), 120(%1), 12(%0), 20)
+ "jmp 9f \n\t"
+
+ "#" ASMALIGN(4) \
+ "6: \n\t"
+Z_COND_IDCT( 96(%0),104(%0),112(%0),120(%0), 96(%1),paddd (%2), 11, 7f)
+
+#undef IDCT
+#define IDCT(src0, src4, src1, src5, dst, shift) \
+ "movq " #src0 ", %%mm0 \n\t" /* R4 R0 r4 r0 */\
+ "movq " #src5 ", %%mm3 \n\t" /* R7 R5 r7 r5 */\
+ "movq 16(%2), %%mm4 \n\t" /* C4 C4 C4 C4 */\
+ "pmaddwd %%mm0, %%mm4 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 24(%2), %%mm5 \n\t" /* -C4 C4 -C4 C4 */\
+ "pmaddwd %%mm5, %%mm0 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq %%mm4, %%mm6 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq %%mm0, %%mm5 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq 56(%2), %%mm1 \n\t" /* C7 C5 C7 C5 */\
+ "pmaddwd %%mm3, %%mm1 \n\t" /* C7R7+C5R5 C7r7+C5r5 */\
+ "movq 72(%2), %%mm7 \n\t" /* -C5 -C1 -C5 -C1 */\
+ "pmaddwd %%mm3, %%mm7 \n\t" /* -C5R7-C1R5 -C5r7-C1r5 */\
+ "paddd %%mm4, %%mm1 \n\t" /* A0+B0 a0+b0 */\
+ "paddd %%mm4, %%mm4 \n\t" /* 2A0 2a0 */\
+ "psubd %%mm1, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "psrad $" #shift ", %%mm1 \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "movq %%mm0, %%mm2 \n\t" /* A1 a1 */\
+ "paddd %%mm7, %%mm0 \n\t" /* A1+B1 a1+b1 */\
+ "psubd %%mm7, %%mm2 \n\t" /* A1-B1 a1-b1 */\
+ "psrad $" #shift ", %%mm0 \n\t"\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "packssdw %%mm1, %%mm1 \n\t" /* A0+B0 a0+b0 */\
+ "movd %%mm1, " #dst " \n\t"\
+ "packssdw %%mm0, %%mm0 \n\t" /* A1+B1 a1+b1 */\
+ "movd %%mm0, 16+" #dst " \n\t"\
+ "packssdw %%mm2, %%mm2 \n\t" /* A1-B1 a1-b1 */\
+ "movd %%mm2, 96+" #dst " \n\t"\
+ "packssdw %%mm4, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "movd %%mm4, 112+" #dst " \n\t"\
+ "movq 88(%2), %%mm1 \n\t" /* C3 C7 C3 C7 */\
+ "pmaddwd %%mm3, %%mm1 \n\t" /* C3R7+C7R5 C3r7+C7r5 */\
+ "movq %%mm5, %%mm2 \n\t" /* A2 a2 */\
+ "pmaddwd 104(%2), %%mm3 \n\t" /* -C1R7+C3R5 -C1r7+C3r5 */\
+ "paddd %%mm1, %%mm2 \n\t" /* A2+B2 a2+b2 */\
+ "psubd %%mm1, %%mm5 \n\t" /* a2-B2 a2-b2 */\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "psrad $" #shift ", %%mm5 \n\t"\
+ "movq %%mm6, %%mm1 \n\t" /* A3 a3 */\
+ "paddd %%mm3, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "psubd %%mm3, %%mm1 \n\t" /* a3-B3 a3-b3 */\
+ "psrad $" #shift ", %%mm6 \n\t"\
+ "psrad $" #shift ", %%mm1 \n\t"\
+ "packssdw %%mm2, %%mm2 \n\t" /* A2+B2 a2+b2 */\
+ "packssdw %%mm6, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "movd %%mm2, 32+" #dst " \n\t"\
+ "packssdw %%mm1, %%mm1 \n\t" /* A3-B3 a3-b3 */\
+ "packssdw %%mm5, %%mm5 \n\t" /* A2-B2 a2-b2 */\
+ "movd %%mm6, 48+" #dst " \n\t"\
+ "movd %%mm1, 64+" #dst " \n\t"\
+ "movd %%mm5, 80+" #dst " \n\t"
+
+
+//IDCT( src0, src4, src1, src5, dst, shift)
+IDCT( (%1), 64(%1), 32(%1), 96(%1), 0(%0), 20)
+IDCT( 8(%1), 72(%1), 40(%1), 104(%1), 4(%0), 20)
+IDCT( 16(%1), 80(%1), 48(%1), 112(%1), 8(%0), 20)
+IDCT( 24(%1), 88(%1), 56(%1), 120(%1), 12(%0), 20)
+ "jmp 9f \n\t"
+
+ "#" ASMALIGN(4) \
+ "2: \n\t"
+Z_COND_IDCT( 96(%0),104(%0),112(%0),120(%0), 96(%1),paddd (%2), 11, 3f)
+
+#undef IDCT
+#define IDCT(src0, src4, src1, src5, dst, shift) \
+ "movq " #src0 ", %%mm0 \n\t" /* R4 R0 r4 r0 */\
+ "movq " #src1 ", %%mm2 \n\t" /* R3 R1 r3 r1 */\
+ "movq " #src5 ", %%mm3 \n\t" /* R7 R5 r7 r5 */\
+ "movq 16(%2), %%mm4 \n\t" /* C4 C4 C4 C4 */\
+ "pmaddwd %%mm0, %%mm4 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 24(%2), %%mm5 \n\t" /* -C4 C4 -C4 C4 */\
+ "pmaddwd %%mm5, %%mm0 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq %%mm4, %%mm6 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 48(%2), %%mm7 \n\t" /* C3 C1 C3 C1 */\
+ "pmaddwd %%mm2, %%mm7 \n\t" /* C3R3+C1R1 C3r3+C1r1 */\
+ "movq %%mm0, %%mm5 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq 56(%2), %%mm1 \n\t" /* C7 C5 C7 C5 */\
+ "pmaddwd %%mm3, %%mm1 \n\t" /* C7R7+C5R5 C7r7+C5r5 */\
+ "pmaddwd 64(%2), %%mm2 \n\t" /* -C7R3+C3R1 -C7r3+C3r1 */\
+ "paddd %%mm1, %%mm7 \n\t" /* B0 b0 */\
+ "movq 72(%2), %%mm1 \n\t" /* -C5 -C1 -C5 -C1 */\
+ "pmaddwd %%mm3, %%mm1 \n\t" /* -C5R7-C1R5 -C5r7-C1r5 */\
+ "paddd %%mm4, %%mm7 \n\t" /* A0+B0 a0+b0 */\
+ "paddd %%mm4, %%mm4 \n\t" /* 2A0 2a0 */\
+ "psubd %%mm7, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "paddd %%mm2, %%mm1 \n\t" /* B1 b1 */\
+ "psrad $" #shift ", %%mm7 \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "movq %%mm0, %%mm2 \n\t" /* A1 a1 */\
+ "paddd %%mm1, %%mm0 \n\t" /* A1+B1 a1+b1 */\
+ "psubd %%mm1, %%mm2 \n\t" /* A1-B1 a1-b1 */\
+ "psrad $" #shift ", %%mm0 \n\t"\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "packssdw %%mm7, %%mm7 \n\t" /* A0+B0 a0+b0 */\
+ "movd %%mm7, " #dst " \n\t"\
+ "packssdw %%mm0, %%mm0 \n\t" /* A1+B1 a1+b1 */\
+ "movd %%mm0, 16+" #dst " \n\t"\
+ "packssdw %%mm2, %%mm2 \n\t" /* A1-B1 a1-b1 */\
+ "movd %%mm2, 96+" #dst " \n\t"\
+ "packssdw %%mm4, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "movd %%mm4, 112+" #dst " \n\t"\
+ "movq " #src1 ", %%mm0 \n\t" /* R3 R1 r3 r1 */\
+ "movq 80(%2), %%mm4 \n\t" /* -C1 C5 -C1 C5 */\
+ "pmaddwd %%mm0, %%mm4 \n\t" /* -C1R3+C5R1 -C1r3+C5r1 */\
+ "movq 88(%2), %%mm7 \n\t" /* C3 C7 C3 C7 */\
+ "pmaddwd 96(%2), %%mm0 \n\t" /* -C5R3+C7R1 -C5r3+C7r1 */\
+ "pmaddwd %%mm3, %%mm7 \n\t" /* C3R7+C7R5 C3r7+C7r5 */\
+ "movq %%mm5, %%mm2 \n\t" /* A2 a2 */\
+ "pmaddwd 104(%2), %%mm3 \n\t" /* -C1R7+C3R5 -C1r7+C3r5 */\
+ "paddd %%mm7, %%mm4 \n\t" /* B2 b2 */\
+ "paddd %%mm4, %%mm2 \n\t" /* A2+B2 a2+b2 */\
+ "psubd %%mm4, %%mm5 \n\t" /* a2-B2 a2-b2 */\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "psrad $" #shift ", %%mm5 \n\t"\
+ "movq %%mm6, %%mm4 \n\t" /* A3 a3 */\
+ "paddd %%mm0, %%mm3 \n\t" /* B3 b3 */\
+ "paddd %%mm3, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "psubd %%mm3, %%mm4 \n\t" /* a3-B3 a3-b3 */\
+ "psrad $" #shift ", %%mm6 \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "packssdw %%mm2, %%mm2 \n\t" /* A2+B2 a2+b2 */\
+ "packssdw %%mm6, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "movd %%mm2, 32+" #dst " \n\t"\
+ "packssdw %%mm4, %%mm4 \n\t" /* A3-B3 a3-b3 */\
+ "packssdw %%mm5, %%mm5 \n\t" /* A2-B2 a2-b2 */\
+ "movd %%mm6, 48+" #dst " \n\t"\
+ "movd %%mm4, 64+" #dst " \n\t"\
+ "movd %%mm5, 80+" #dst " \n\t"
+
+//IDCT( src0, src4, src1, src5, dst, shift)
+IDCT( (%1), 64(%1), 32(%1), 96(%1), 0(%0), 20)
+IDCT( 8(%1), 72(%1), 40(%1), 104(%1), 4(%0), 20)
+IDCT( 16(%1), 80(%1), 48(%1), 112(%1), 8(%0), 20)
+IDCT( 24(%1), 88(%1), 56(%1), 120(%1), 12(%0), 20)
+ "jmp 9f \n\t"
+
+ "#" ASMALIGN(4) \
+ "3: \n\t"
+#undef IDCT
+#define IDCT(src0, src4, src1, src5, dst, shift) \
+ "movq " #src0 ", %%mm0 \n\t" /* R4 R0 r4 r0 */\
+ "movq " #src1 ", %%mm2 \n\t" /* R3 R1 r3 r1 */\
+ "movq 16(%2), %%mm4 \n\t" /* C4 C4 C4 C4 */\
+ "pmaddwd %%mm0, %%mm4 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 24(%2), %%mm5 \n\t" /* -C4 C4 -C4 C4 */\
+ "pmaddwd %%mm5, %%mm0 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq %%mm4, %%mm6 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 48(%2), %%mm7 \n\t" /* C3 C1 C3 C1 */\
+ "pmaddwd %%mm2, %%mm7 \n\t" /* C3R3+C1R1 C3r3+C1r1 */\
+ "movq %%mm0, %%mm5 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq 64(%2), %%mm3 \n\t"\
+ "pmaddwd %%mm2, %%mm3 \n\t" /* -C7R3+C3R1 -C7r3+C3r1 */\
+ "paddd %%mm4, %%mm7 \n\t" /* A0+B0 a0+b0 */\
+ "paddd %%mm4, %%mm4 \n\t" /* 2A0 2a0 */\
+ "psubd %%mm7, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "psrad $" #shift ", %%mm7 \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "movq %%mm0, %%mm1 \n\t" /* A1 a1 */\
+ "paddd %%mm3, %%mm0 \n\t" /* A1+B1 a1+b1 */\
+ "psubd %%mm3, %%mm1 \n\t" /* A1-B1 a1-b1 */\
+ "psrad $" #shift ", %%mm0 \n\t"\
+ "psrad $" #shift ", %%mm1 \n\t"\
+ "packssdw %%mm7, %%mm7 \n\t" /* A0+B0 a0+b0 */\
+ "movd %%mm7, " #dst " \n\t"\
+ "packssdw %%mm0, %%mm0 \n\t" /* A1+B1 a1+b1 */\
+ "movd %%mm0, 16+" #dst " \n\t"\
+ "packssdw %%mm1, %%mm1 \n\t" /* A1-B1 a1-b1 */\
+ "movd %%mm1, 96+" #dst " \n\t"\
+ "packssdw %%mm4, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "movd %%mm4, 112+" #dst " \n\t"\
+ "movq 80(%2), %%mm4 \n\t" /* -C1 C5 -C1 C5 */\
+ "pmaddwd %%mm2, %%mm4 \n\t" /* -C1R3+C5R1 -C1r3+C5r1 */\
+ "pmaddwd 96(%2), %%mm2 \n\t" /* -C5R3+C7R1 -C5r3+C7r1 */\
+ "movq %%mm5, %%mm1 \n\t" /* A2 a2 */\
+ "paddd %%mm4, %%mm1 \n\t" /* A2+B2 a2+b2 */\
+ "psubd %%mm4, %%mm5 \n\t" /* a2-B2 a2-b2 */\
+ "psrad $" #shift ", %%mm1 \n\t"\
+ "psrad $" #shift ", %%mm5 \n\t"\
+ "movq %%mm6, %%mm4 \n\t" /* A3 a3 */\
+ "paddd %%mm2, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "psubd %%mm2, %%mm4 \n\t" /* a3-B3 a3-b3 */\
+ "psrad $" #shift ", %%mm6 \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "packssdw %%mm1, %%mm1 \n\t" /* A2+B2 a2+b2 */\
+ "packssdw %%mm6, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "movd %%mm1, 32+" #dst " \n\t"\
+ "packssdw %%mm4, %%mm4 \n\t" /* A3-B3 a3-b3 */\
+ "packssdw %%mm5, %%mm5 \n\t" /* A2-B2 a2-b2 */\
+ "movd %%mm6, 48+" #dst " \n\t"\
+ "movd %%mm4, 64+" #dst " \n\t"\
+ "movd %%mm5, 80+" #dst " \n\t"
+
+
+//IDCT( src0, src4, src1, src5, dst, shift)
+IDCT( (%1), 64(%1), 32(%1), 96(%1), 0(%0), 20)
+IDCT( 8(%1), 72(%1), 40(%1), 104(%1), 4(%0), 20)
+IDCT( 16(%1), 80(%1), 48(%1), 112(%1), 8(%0), 20)
+IDCT( 24(%1), 88(%1), 56(%1), 120(%1), 12(%0), 20)
+ "jmp 9f \n\t"
+
+ "#" ASMALIGN(4) \
+ "5: \n\t"
+#undef IDCT
+#define IDCT(src0, src4, src1, src5, dst, shift) \
+ "movq " #src0 ", %%mm0 \n\t" /* R4 R0 r4 r0 */\
+ "movq " #src4 ", %%mm1 \n\t" /* R6 R2 r6 r2 */\
+ "movq 16(%2), %%mm4 \n\t" /* C4 C4 C4 C4 */\
+ "pmaddwd %%mm0, %%mm4 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 24(%2), %%mm5 \n\t" /* -C4 C4 -C4 C4 */\
+ "pmaddwd %%mm5, %%mm0 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq 32(%2), %%mm5 \n\t" /* C6 C2 C6 C2 */\
+ "pmaddwd %%mm1, %%mm5 \n\t" /* C6R6+C2R2 C6r6+C2r2 */\
+ "movq 40(%2), %%mm6 \n\t" /* -C2 C6 -C2 C6 */\
+ "pmaddwd %%mm6, %%mm1 \n\t" /* -C2R6+C6R2 -C2r6+C6r2 */\
+ "movq %%mm4, %%mm6 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "paddd %%mm5, %%mm4 \n\t" /* A0 a0 */\
+ "psubd %%mm5, %%mm6 \n\t" /* A3 a3 */\
+ "movq %%mm0, %%mm5 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "paddd %%mm1, %%mm0 \n\t" /* A1 a1 */\
+ "psubd %%mm1, %%mm5 \n\t" /* A2 a2 */\
+ "movq 8+" #src0 ", %%mm2 \n\t" /* R4 R0 r4 r0 */\
+ "movq 8+" #src4 ", %%mm3 \n\t" /* R6 R2 r6 r2 */\
+ "movq 16(%2), %%mm1 \n\t" /* C4 C4 C4 C4 */\
+ "pmaddwd %%mm2, %%mm1 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 24(%2), %%mm7 \n\t" /* -C4 C4 -C4 C4 */\
+ "pmaddwd %%mm7, %%mm2 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq 32(%2), %%mm7 \n\t" /* C6 C2 C6 C2 */\
+ "pmaddwd %%mm3, %%mm7 \n\t" /* C6R6+C2R2 C6r6+C2r2 */\
+ "pmaddwd 40(%2), %%mm3 \n\t" /* -C2R6+C6R2 -C2r6+C6r2 */\
+ "paddd %%mm1, %%mm7 \n\t" /* A0 a0 */\
+ "paddd %%mm1, %%mm1 \n\t" /* 2C0 2c0 */\
+ "psubd %%mm7, %%mm1 \n\t" /* A3 a3 */\
+ "paddd %%mm2, %%mm3 \n\t" /* A1 a1 */\
+ "paddd %%mm2, %%mm2 \n\t" /* 2C1 2c1 */\
+ "psubd %%mm3, %%mm2 \n\t" /* A2 a2 */\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "psrad $" #shift ", %%mm7 \n\t"\
+ "psrad $" #shift ", %%mm3 \n\t"\
+ "packssdw %%mm7, %%mm4 \n\t" /* A0 a0 */\
+ "movq %%mm4, " #dst " \n\t"\
+ "psrad $" #shift ", %%mm0 \n\t"\
+ "packssdw %%mm3, %%mm0 \n\t" /* A1 a1 */\
+ "movq %%mm0, 16+" #dst " \n\t"\
+ "movq %%mm0, 96+" #dst " \n\t"\
+ "movq %%mm4, 112+" #dst " \n\t"\
+ "psrad $" #shift ", %%mm5 \n\t"\
+ "psrad $" #shift ", %%mm6 \n\t"\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "packssdw %%mm2, %%mm5 \n\t" /* A2-B2 a2-b2 */\
+ "movq %%mm5, 32+" #dst " \n\t"\
+ "psrad $" #shift ", %%mm1 \n\t"\
+ "packssdw %%mm1, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "movq %%mm6, 48+" #dst " \n\t"\
+ "movq %%mm6, 64+" #dst " \n\t"\
+ "movq %%mm5, 80+" #dst " \n\t"
+
+
+//IDCT( src0, src4, src1, src5, dst, shift)
+IDCT( 0(%1), 64(%1), 32(%1), 96(%1), 0(%0), 20)
+//IDCT( 8(%1), 72(%1), 40(%1), 104(%1), 4(%0), 20)
+IDCT( 16(%1), 80(%1), 48(%1), 112(%1), 8(%0), 20)
+//IDCT( 24(%1), 88(%1), 56(%1), 120(%1), 12(%0), 20)
+ "jmp 9f \n\t"
+
+
+ "#" ASMALIGN(4) \
+ "1: \n\t"
+#undef IDCT
+#define IDCT(src0, src4, src1, src5, dst, shift) \
+ "movq " #src0 ", %%mm0 \n\t" /* R4 R0 r4 r0 */\
+ "movq " #src4 ", %%mm1 \n\t" /* R6 R2 r6 r2 */\
+ "movq " #src1 ", %%mm2 \n\t" /* R3 R1 r3 r1 */\
+ "movq 16(%2), %%mm4 \n\t" /* C4 C4 C4 C4 */\
+ "pmaddwd %%mm0, %%mm4 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 24(%2), %%mm5 \n\t" /* -C4 C4 -C4 C4 */\
+ "pmaddwd %%mm5, %%mm0 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq 32(%2), %%mm5 \n\t" /* C6 C2 C6 C2 */\
+ "pmaddwd %%mm1, %%mm5 \n\t" /* C6R6+C2R2 C6r6+C2r2 */\
+ "movq 40(%2), %%mm6 \n\t" /* -C2 C6 -C2 C6 */\
+ "pmaddwd %%mm6, %%mm1 \n\t" /* -C2R6+C6R2 -C2r6+C6r2 */\
+ "movq %%mm4, %%mm6 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 48(%2), %%mm7 \n\t" /* C3 C1 C3 C1 */\
+ "pmaddwd %%mm2, %%mm7 \n\t" /* C3R3+C1R1 C3r3+C1r1 */\
+ "paddd %%mm5, %%mm4 \n\t" /* A0 a0 */\
+ "psubd %%mm5, %%mm6 \n\t" /* A3 a3 */\
+ "movq %%mm0, %%mm5 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "paddd %%mm1, %%mm0 \n\t" /* A1 a1 */\
+ "psubd %%mm1, %%mm5 \n\t" /* A2 a2 */\
+ "movq 64(%2), %%mm1 \n\t"\
+ "pmaddwd %%mm2, %%mm1 \n\t" /* -C7R3+C3R1 -C7r3+C3r1 */\
+ "paddd %%mm4, %%mm7 \n\t" /* A0+B0 a0+b0 */\
+ "paddd %%mm4, %%mm4 \n\t" /* 2A0 2a0 */\
+ "psubd %%mm7, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "psrad $" #shift ", %%mm7 \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "movq %%mm0, %%mm3 \n\t" /* A1 a1 */\
+ "paddd %%mm1, %%mm0 \n\t" /* A1+B1 a1+b1 */\
+ "psubd %%mm1, %%mm3 \n\t" /* A1-B1 a1-b1 */\
+ "psrad $" #shift ", %%mm0 \n\t"\
+ "psrad $" #shift ", %%mm3 \n\t"\
+ "packssdw %%mm7, %%mm7 \n\t" /* A0+B0 a0+b0 */\
+ "movd %%mm7, " #dst " \n\t"\
+ "packssdw %%mm0, %%mm0 \n\t" /* A1+B1 a1+b1 */\
+ "movd %%mm0, 16+" #dst " \n\t"\
+ "packssdw %%mm3, %%mm3 \n\t" /* A1-B1 a1-b1 */\
+ "movd %%mm3, 96+" #dst " \n\t"\
+ "packssdw %%mm4, %%mm4 \n\t" /* A0-B0 a0-b0 */\
+ "movd %%mm4, 112+" #dst " \n\t"\
+ "movq 80(%2), %%mm4 \n\t" /* -C1 C5 -C1 C5 */\
+ "pmaddwd %%mm2, %%mm4 \n\t" /* -C1R3+C5R1 -C1r3+C5r1 */\
+ "pmaddwd 96(%2), %%mm2 \n\t" /* -C5R3+C7R1 -C5r3+C7r1 */\
+ "movq %%mm5, %%mm3 \n\t" /* A2 a2 */\
+ "paddd %%mm4, %%mm3 \n\t" /* A2+B2 a2+b2 */\
+ "psubd %%mm4, %%mm5 \n\t" /* a2-B2 a2-b2 */\
+ "psrad $" #shift ", %%mm3 \n\t"\
+ "psrad $" #shift ", %%mm5 \n\t"\
+ "movq %%mm6, %%mm4 \n\t" /* A3 a3 */\
+ "paddd %%mm2, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "psubd %%mm2, %%mm4 \n\t" /* a3-B3 a3-b3 */\
+ "psrad $" #shift ", %%mm6 \n\t"\
+ "packssdw %%mm3, %%mm3 \n\t" /* A2+B2 a2+b2 */\
+ "movd %%mm3, 32+" #dst " \n\t"\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "packssdw %%mm6, %%mm6 \n\t" /* A3+B3 a3+b3 */\
+ "movd %%mm6, 48+" #dst " \n\t"\
+ "packssdw %%mm4, %%mm4 \n\t" /* A3-B3 a3-b3 */\
+ "packssdw %%mm5, %%mm5 \n\t" /* A2-B2 a2-b2 */\
+ "movd %%mm4, 64+" #dst " \n\t"\
+ "movd %%mm5, 80+" #dst " \n\t"
+
+
+//IDCT( src0, src4, src1, src5, dst, shift)
+IDCT( (%1), 64(%1), 32(%1), 96(%1), 0(%0), 20)
+IDCT( 8(%1), 72(%1), 40(%1), 104(%1), 4(%0), 20)
+IDCT( 16(%1), 80(%1), 48(%1), 112(%1), 8(%0), 20)
+IDCT( 24(%1), 88(%1), 56(%1), 120(%1), 12(%0), 20)
+ "jmp 9f \n\t"
+
+
+ "#" ASMALIGN(4)
+ "7: \n\t"
+#undef IDCT
+#define IDCT(src0, src4, src1, src5, dst, shift) \
+ "movq " #src0 ", %%mm0 \n\t" /* R4 R0 r4 r0 */\
+ "movq 16(%2), %%mm4 \n\t" /* C4 C4 C4 C4 */\
+ "pmaddwd %%mm0, %%mm4 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 24(%2), %%mm5 \n\t" /* -C4 C4 -C4 C4 */\
+ "pmaddwd %%mm5, %%mm0 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "psrad $" #shift ", %%mm4 \n\t"\
+ "psrad $" #shift ", %%mm0 \n\t"\
+ "movq 8+" #src0 ", %%mm2 \n\t" /* R4 R0 r4 r0 */\
+ "movq 16(%2), %%mm1 \n\t" /* C4 C4 C4 C4 */\
+ "pmaddwd %%mm2, %%mm1 \n\t" /* C4R4+C4R0 C4r4+C4r0 */\
+ "movq 24(%2), %%mm7 \n\t" /* -C4 C4 -C4 C4 */\
+ "pmaddwd %%mm7, %%mm2 \n\t" /* -C4R4+C4R0 -C4r4+C4r0 */\
+ "movq 32(%2), %%mm7 \n\t" /* C6 C2 C6 C2 */\
+ "psrad $" #shift ", %%mm1 \n\t"\
+ "packssdw %%mm1, %%mm4 \n\t" /* A0 a0 */\
+ "movq %%mm4, " #dst " \n\t"\
+ "psrad $" #shift ", %%mm2 \n\t"\
+ "packssdw %%mm2, %%mm0 \n\t" /* A1 a1 */\
+ "movq %%mm0, 16+" #dst " \n\t"\
+ "movq %%mm0, 96+" #dst " \n\t"\
+ "movq %%mm4, 112+" #dst " \n\t"\
+ "movq %%mm0, 32+" #dst " \n\t"\
+ "movq %%mm4, 48+" #dst " \n\t"\
+ "movq %%mm4, 64+" #dst " \n\t"\
+ "movq %%mm0, 80+" #dst " \n\t"
+
+//IDCT( src0, src4, src1, src5, dst, shift)
+IDCT( 0(%1), 64(%1), 32(%1), 96(%1), 0(%0), 20)
+//IDCT( 8(%1), 72(%1), 40(%1), 104(%1), 4(%0), 20)
+IDCT( 16(%1), 80(%1), 48(%1), 112(%1), 8(%0), 20)
+//IDCT( 24(%1), 88(%1), 56(%1), 120(%1), 12(%0), 20)
+
+
+#endif
+
+/*
+Input
+ 00 40 04 44 20 60 24 64
+ 10 30 14 34 50 70 54 74
+ 01 41 03 43 21 61 23 63
+ 11 31 13 33 51 71 53 73
+ 02 42 06 46 22 62 26 66
+ 12 32 16 36 52 72 56 76
+ 05 45 07 47 25 65 27 67
+ 15 35 17 37 55 75 57 77
+
+Temp
+ 00 04 10 14 20 24 30 34
+ 40 44 50 54 60 64 70 74
+ 01 03 11 13 21 23 31 33
+ 41 43 51 53 61 63 71 73
+ 02 06 12 16 22 26 32 36
+ 42 46 52 56 62 66 72 76
+ 05 07 15 17 25 27 35 37
+ 45 47 55 57 65 67 75 77
+*/
+
+"9: \n\t"
+ :: "r" (block), "r" (temp), "r" (coeffs)
+ : "%eax"
+ );
+}
+
+void ff_simple_idct_mmx(int16_t *block)
+{
+ idct(block);
+}
+
+//FIXME merge add/put into the idct
+
+void ff_simple_idct_put_mmx(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ idct(block);
+ put_pixels_clamped_mmx(block, dest, line_size);
+}
+void ff_simple_idct_add_mmx(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ idct(block);
+ add_pixels_clamped_mmx(block, dest, line_size);
+}
diff --git a/contrib/ffmpeg/libavcodec/i386/snowdsp_mmx.c b/contrib/ffmpeg/libavcodec/i386/snowdsp_mmx.c
new file mode 100644
index 000000000..718202632
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/snowdsp_mmx.c
@@ -0,0 +1,921 @@
+/*
+ * MMX and SSE2 optimized snow DSP utils
+ * Copyright (c) 2005-2006 Robert Edele <yartrebo@earthlink.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 "../snow.h"
+#include "x86_cpu.h"
+
+void ff_snow_horizontal_compose97i_sse2(DWTELEM *b, int width){
+ const int w2= (width+1)>>1;
+ // SSE2 code runs faster with pointers aligned on a 32-byte boundary.
+ DWTELEM temp_buf[(width>>1) + 4];
+ DWTELEM * const temp = temp_buf + 4 - (((int)temp_buf & 0xF) >> 2);
+ const int w_l= (width>>1);
+ const int w_r= w2 - 1;
+ int i;
+
+ { // Lift 0
+ DWTELEM * const ref = b + w2 - 1;
+ DWTELEM 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"
+ "pslld $31, %%xmm7 \n\t"
+ "psrld $29, %%xmm7 \n\t"
+ ::);
+ for(; i<w_l-7; i+=8){
+ asm volatile(
+ "movdqu (%1), %%xmm1 \n\t"
+ "movdqu 16(%1), %%xmm5 \n\t"
+ "movdqu 4(%1), %%xmm2 \n\t"
+ "movdqu 20(%1), %%xmm6 \n\t"
+ "paddd %%xmm1, %%xmm2 \n\t"
+ "paddd %%xmm5, %%xmm6 \n\t"
+ "movdqa %%xmm2, %%xmm0 \n\t"
+ "movdqa %%xmm6, %%xmm4 \n\t"
+ "paddd %%xmm2, %%xmm2 \n\t"
+ "paddd %%xmm6, %%xmm6 \n\t"
+ "paddd %%xmm0, %%xmm2 \n\t"
+ "paddd %%xmm4, %%xmm6 \n\t"
+ "paddd %%xmm7, %%xmm2 \n\t"
+ "paddd %%xmm7, %%xmm6 \n\t"
+ "psrad $3, %%xmm2 \n\t"
+ "psrad $3, %%xmm6 \n\t"
+ "movdqa (%0), %%xmm0 \n\t"
+ "movdqa 16(%0), %%xmm4 \n\t"
+ "psubd %%xmm2, %%xmm0 \n\t"
+ "psubd %%xmm6, %%xmm4 \n\t"
+ "movdqa %%xmm0, (%0) \n\t"
+ "movdqa %%xmm4, 16(%0) \n\t"
+ :: "r"(&b[i]), "r"(&ref[i])
+ : "memory"
+ );
+ }
+ snow_horizontal_compose_lift_lead_out(i, b, b, ref, width, w_l, 0, W_DM, W_DO, W_DS);
+ b[0] = b_0 - ((W_DM * 2 * ref[1]+W_DO)>>W_DS);
+ }
+
+ { // Lift 1
+ DWTELEM * const dst = b+w2;
+
+ i = 0;
+ for(; (((long)&dst[i]) & 0xF) && i<w_r; i++){
+ dst[i] = dst[i] - (b[i] + b[i + 1]);
+ }
+ for(; i<w_r-7; i+=8){
+ asm volatile(
+ "movdqu (%1), %%xmm1 \n\t"
+ "movdqu 16(%1), %%xmm5 \n\t"
+ "movdqu 4(%1), %%xmm2 \n\t"
+ "movdqu 20(%1), %%xmm6 \n\t"
+ "paddd %%xmm1, %%xmm2 \n\t"
+ "paddd %%xmm5, %%xmm6 \n\t"
+ "movdqa (%0), %%xmm0 \n\t"
+ "movdqa 16(%0), %%xmm4 \n\t"
+ "psubd %%xmm2, %%xmm0 \n\t"
+ "psubd %%xmm6, %%xmm4 \n\t"
+ "movdqa %%xmm0, (%0) \n\t"
+ "movdqa %%xmm4, 16(%0) \n\t"
+ :: "r"(&dst[i]), "r"(&b[i])
+ : "memory"
+ );
+ }
+ snow_horizontal_compose_lift_lead_out(i, dst, dst, b, width, w_r, 1, W_CM, W_CO, W_CS);
+ }
+
+ { // Lift 2
+ DWTELEM * const ref = b+w2 - 1;
+ DWTELEM b_0 = b[0];
+
+ i = 0;
+ asm volatile(
+ "pslld $1, %%xmm7 \n\t" /* xmm7 already holds a '4' from 2 lifts ago. */
+ ::);
+ for(; i<w_l-7; i+=8){
+ asm volatile(
+ "movdqu (%1), %%xmm1 \n\t"
+ "movdqu 16(%1), %%xmm5 \n\t"
+ "movdqu 4(%1), %%xmm0 \n\t"
+ "movdqu 20(%1), %%xmm4 \n\t"
+ "paddd %%xmm1, %%xmm0 \n\t"
+ "paddd %%xmm5, %%xmm4 \n\t"
+ "movdqa %%xmm7, %%xmm1 \n\t"
+ "movdqa %%xmm7, %%xmm5 \n\t"
+ "psubd %%xmm0, %%xmm1 \n\t"
+ "psubd %%xmm4, %%xmm5 \n\t"
+ "movdqa (%0), %%xmm0 \n\t"
+ "movdqa 16(%0), %%xmm4 \n\t"
+ "pslld $2, %%xmm0 \n\t"
+ "pslld $2, %%xmm4 \n\t"
+ "psubd %%xmm0, %%xmm1 \n\t"
+ "psubd %%xmm4, %%xmm5 \n\t"
+ "psrad $4, %%xmm1 \n\t"
+ "psrad $4, %%xmm5 \n\t"
+ "movdqa (%0), %%xmm0 \n\t"
+ "movdqa 16(%0), %%xmm4 \n\t"
+ "psubd %%xmm1, %%xmm0 \n\t"
+ "psubd %%xmm5, %%xmm4 \n\t"
+ "movdqa %%xmm0, (%0) \n\t"
+ "movdqa %%xmm4, 16(%0) \n\t"
+ :: "r"(&b[i]), "r"(&ref[i])
+ : "memory"
+ );
+ }
+ snow_horizontal_compose_liftS_lead_out(i, b, b, ref, width, w_l);
+ b[0] = b_0 - (((-2 * ref[1] + W_BO) - 4 * b_0) >> W_BS);
+ }
+
+ { // Lift 3
+ DWTELEM * const src = b+w2;
+
+ i = 0;
+ for(; (((long)&temp[i]) & 0xF) && i<w_r; i++){
+ temp[i] = src[i] - ((-W_AM*(b[i] + b[i+1]))>>W_AS);
+ }
+ for(; i<w_r-7; i+=8){
+ asm volatile(
+ "movdqu 4(%1), %%xmm2 \n\t"
+ "movdqu 20(%1), %%xmm6 \n\t"
+ "paddd (%1), %%xmm2 \n\t"
+ "paddd 16(%1), %%xmm6 \n\t"
+ "movdqa %%xmm2, %%xmm0 \n\t"
+ "movdqa %%xmm6, %%xmm4 \n\t"
+ "pslld $2, %%xmm2 \n\t"
+ "pslld $2, %%xmm6 \n\t"
+ "psubd %%xmm2, %%xmm0 \n\t"
+ "psubd %%xmm6, %%xmm4 \n\t"
+ "psrad $1, %%xmm0 \n\t"
+ "psrad $1, %%xmm4 \n\t"
+ "movdqu (%0), %%xmm2 \n\t"
+ "movdqu 16(%0), %%xmm6 \n\t"
+ "psubd %%xmm0, %%xmm2 \n\t"
+ "psubd %%xmm4, %%xmm6 \n\t"
+ "movdqa %%xmm2, (%2) \n\t"
+ "movdqa %%xmm6, 16(%2) \n\t"
+ :: "r"(&src[i]), "r"(&b[i]), "r"(&temp[i])
+ : "memory"
+ );
+ }
+ snow_horizontal_compose_lift_lead_out(i, temp, src, b, width, w_r, 1, -W_AM, W_AO, W_AS);
+ }
+
+ {
+ snow_interleave_line_header(&i, width, b, temp);
+
+ for (; (i & 0x1E) != 0x1E; i-=2){
+ b[i+1] = temp[i>>1];
+ b[i] = b[i>>1];
+ }
+ for (i-=30; i>=0; i-=32){
+ 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"
+ "punpckldq (%2), %%xmm0 \n\t"
+ "punpckldq 16(%2), %%xmm2 \n\t"
+ "punpckldq 32(%2), %%xmm4 \n\t"
+ "punpckldq 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"
+ "punpckhdq (%2), %%xmm1 \n\t"
+ "punpckhdq 16(%2), %%xmm3 \n\t"
+ "punpckhdq 32(%2), %%xmm5 \n\t"
+ "punpckhdq 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"
+ );
+ }
+ }
+}
+
+void ff_snow_horizontal_compose97i_mmx(DWTELEM *b, int width){
+ const int w2= (width+1)>>1;
+ DWTELEM temp[width >> 1];
+ const int w_l= (width>>1);
+ const int w_r= w2 - 1;
+ int i;
+
+ { // Lift 0
+ DWTELEM * const ref = b + w2 - 1;
+
+ i = 1;
+ b[0] = b[0] - ((W_DM * 2 * ref[1]+W_DO)>>W_DS);
+ asm volatile(
+ "pcmpeqd %%mm7, %%mm7 \n\t"
+ "pslld $31, %%mm7 \n\t"
+ "psrld $29, %%mm7 \n\t"
+ ::);
+ for(; i<w_l-3; i+=4){
+ asm volatile(
+ "movq (%1), %%mm2 \n\t"
+ "movq 8(%1), %%mm6 \n\t"
+ "paddd 4(%1), %%mm2 \n\t"
+ "paddd 12(%1), %%mm6 \n\t"
+ "movq %%mm2, %%mm0 \n\t"
+ "movq %%mm6, %%mm4 \n\t"
+ "paddd %%mm2, %%mm2 \n\t"
+ "paddd %%mm6, %%mm6 \n\t"
+ "paddd %%mm0, %%mm2 \n\t"
+ "paddd %%mm4, %%mm6 \n\t"
+ "paddd %%mm7, %%mm2 \n\t"
+ "paddd %%mm7, %%mm6 \n\t"
+ "psrad $3, %%mm2 \n\t"
+ "psrad $3, %%mm6 \n\t"
+ "movq (%0), %%mm0 \n\t"
+ "movq 8(%0), %%mm4 \n\t"
+ "psubd %%mm2, %%mm0 \n\t"
+ "psubd %%mm6, %%mm4 \n\t"
+ "movq %%mm0, (%0) \n\t"
+ "movq %%mm4, 8(%0) \n\t"
+ :: "r"(&b[i]), "r"(&ref[i])
+ : "memory"
+ );
+ }
+ snow_horizontal_compose_lift_lead_out(i, b, b, ref, width, w_l, 0, W_DM, W_DO, W_DS);
+ }
+
+ { // Lift 1
+ DWTELEM * const dst = b+w2;
+
+ i = 0;
+ for(; i<w_r-3; i+=4){
+ asm volatile(
+ "movq (%1), %%mm2 \n\t"
+ "movq 8(%1), %%mm6 \n\t"
+ "paddd 4(%1), %%mm2 \n\t"
+ "paddd 12(%1), %%mm6 \n\t"
+ "movq (%0), %%mm0 \n\t"
+ "movq 8(%0), %%mm4 \n\t"
+ "psubd %%mm2, %%mm0 \n\t"
+ "psubd %%mm6, %%mm4 \n\t"
+ "movq %%mm0, (%0) \n\t"
+ "movq %%mm4, 8(%0) \n\t"
+ :: "r"(&dst[i]), "r"(&b[i])
+ : "memory"
+ );
+ }
+ snow_horizontal_compose_lift_lead_out(i, dst, dst, b, width, w_r, 1, W_CM, W_CO, W_CS);
+ }
+
+ { // Lift 2
+ DWTELEM * const ref = b+w2 - 1;
+
+ i = 1;
+ b[0] = b[0] - (((-2 * ref[1] + W_BO) - 4 * b[0]) >> W_BS);
+ asm volatile(
+ "pslld $1, %%mm7 \n\t" /* xmm7 already holds a '4' from 2 lifts ago. */
+ ::);
+ for(; i<w_l-3; i+=4){
+ asm volatile(
+ "movq (%1), %%mm0 \n\t"
+ "movq 8(%1), %%mm4 \n\t"
+ "paddd 4(%1), %%mm0 \n\t"
+ "paddd 12(%1), %%mm4 \n\t"
+ "movq %%mm7, %%mm1 \n\t"
+ "movq %%mm7, %%mm5 \n\t"
+ "psubd %%mm0, %%mm1 \n\t"
+ "psubd %%mm4, %%mm5 \n\t"
+ "movq (%0), %%mm0 \n\t"
+ "movq 8(%0), %%mm4 \n\t"
+ "pslld $2, %%mm0 \n\t"
+ "pslld $2, %%mm4 \n\t"
+ "psubd %%mm0, %%mm1 \n\t"
+ "psubd %%mm4, %%mm5 \n\t"
+ "psrad $4, %%mm1 \n\t"
+ "psrad $4, %%mm5 \n\t"
+ "movq (%0), %%mm0 \n\t"
+ "movq 8(%0), %%mm4 \n\t"
+ "psubd %%mm1, %%mm0 \n\t"
+ "psubd %%mm5, %%mm4 \n\t"
+ "movq %%mm0, (%0) \n\t"
+ "movq %%mm4, 8(%0) \n\t"
+ :: "r"(&b[i]), "r"(&ref[i])
+ : "memory"
+ );
+ }
+ snow_horizontal_compose_liftS_lead_out(i, b, b, ref, width, w_l);
+ }
+
+ { // Lift 3
+ DWTELEM * const src = b+w2;
+ i = 0;
+
+ for(; i<w_r-3; i+=4){
+ asm volatile(
+ "movq 4(%1), %%mm2 \n\t"
+ "movq 12(%1), %%mm6 \n\t"
+ "paddd (%1), %%mm2 \n\t"
+ "paddd 8(%1), %%mm6 \n\t"
+ "movq %%mm2, %%mm0 \n\t"
+ "movq %%mm6, %%mm4 \n\t"
+ "pslld $2, %%mm2 \n\t"
+ "pslld $2, %%mm6 \n\t"
+ "psubd %%mm2, %%mm0 \n\t"
+ "psubd %%mm6, %%mm4 \n\t"
+ "psrad $1, %%mm0 \n\t"
+ "psrad $1, %%mm4 \n\t"
+ "movq (%0), %%mm2 \n\t"
+ "movq 8(%0), %%mm6 \n\t"
+ "psubd %%mm0, %%mm2 \n\t"
+ "psubd %%mm4, %%mm6 \n\t"
+ "movq %%mm2, (%2) \n\t"
+ "movq %%mm6, 8(%2) \n\t"
+ :: "r"(&src[i]), "r"(&b[i]), "r"(&temp[i])
+ : "memory"
+ );
+ }
+ snow_horizontal_compose_lift_lead_out(i, temp, src, b, width, w_r, 1, -W_AM, W_AO, W_AS);
+ }
+
+ {
+ snow_interleave_line_header(&i, width, b, temp);
+
+ for (; (i & 0xE) != 0xE; i-=2){
+ b[i+1] = temp[i>>1];
+ b[i] = b[i>>1];
+ }
+ for (i-=14; i>=0; i-=16){
+ 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"
+ "punpckldq (%2), %%mm0 \n\t"
+ "punpckldq 8(%2), %%mm2 \n\t"
+ "punpckldq 16(%2), %%mm4 \n\t"
+ "punpckldq 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"
+ "punpckhdq (%2), %%mm1 \n\t"
+ "punpckhdq 8(%2), %%mm3 \n\t"
+ "punpckhdq 16(%2), %%mm5 \n\t"
+ "punpckhdq 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"
+ );
+ }
+ }
+}
+
+#define snow_vertical_compose_sse2_load_add(op,r,t0,t1,t2,t3)\
+ ""op" (%%"r",%%"REG_d",4), %%"t0" \n\t"\
+ ""op" 16(%%"r",%%"REG_d",4), %%"t1" \n\t"\
+ ""op" 32(%%"r",%%"REG_d",4), %%"t2" \n\t"\
+ ""op" 48(%%"r",%%"REG_d",4), %%"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("paddd",r,t0,t1,t2,t3)
+
+#define snow_vertical_compose_sse2_sub(s0,s1,s2,s3,t0,t1,t2,t3)\
+ "psubd %%"s0", %%"t0" \n\t"\
+ "psubd %%"s1", %%"t1" \n\t"\
+ "psubd %%"s2", %%"t2" \n\t"\
+ "psubd %%"s3", %%"t3" \n\t"
+
+#define snow_vertical_compose_sse2_store(w,s0,s1,s2,s3)\
+ "movdqa %%"s0", (%%"w",%%"REG_d",4) \n\t"\
+ "movdqa %%"s1", 16(%%"w",%%"REG_d",4) \n\t"\
+ "movdqa %%"s2", 32(%%"w",%%"REG_d",4) \n\t"\
+ "movdqa %%"s3", 48(%%"w",%%"REG_d",4) \n\t"
+
+#define snow_vertical_compose_sse2_sra(n,t0,t1,t2,t3)\
+ "psrad $"n", %%"t0" \n\t"\
+ "psrad $"n", %%"t1" \n\t"\
+ "psrad $"n", %%"t2" \n\t"\
+ "psrad $"n", %%"t3" \n\t"
+
+#define snow_vertical_compose_sse2_r2r_add(s0,s1,s2,s3,t0,t1,t2,t3)\
+ "paddd %%"s0", %%"t0" \n\t"\
+ "paddd %%"s1", %%"t1" \n\t"\
+ "paddd %%"s2", %%"t2" \n\t"\
+ "paddd %%"s3", %%"t3" \n\t"
+
+#define snow_vertical_compose_sse2_sll(n,t0,t1,t2,t3)\
+ "pslld $"n", %%"t0" \n\t"\
+ "pslld $"n", %%"t1" \n\t"\
+ "pslld $"n", %%"t2" \n\t"\
+ "pslld $"n", %%"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"
+
+void ff_snow_vertical_compose97i_sse2(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, DWTELEM *b3, DWTELEM *b4, DWTELEM *b5, int width){
+ long i = width;
+
+ while(i & 0xF)
+ {
+ 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;
+ }
+
+ asm volatile (
+ "jmp 2f \n\t"
+ "1: \n\t"
+
+ "mov %6, %%"REG_a" \n\t"
+ "mov %4, %%"REG_S" \n\t"
+
+ snow_vertical_compose_sse2_load(REG_S,"xmm0","xmm2","xmm4","xmm6")
+ snow_vertical_compose_sse2_add(REG_a,"xmm0","xmm2","xmm4","xmm6")
+ snow_vertical_compose_sse2_move("xmm0","xmm2","xmm4","xmm6","xmm1","xmm3","xmm5","xmm7")
+ snow_vertical_compose_sse2_sll("1","xmm0","xmm2","xmm4","xmm6")\
+ snow_vertical_compose_sse2_r2r_add("xmm1","xmm3","xmm5","xmm7","xmm0","xmm2","xmm4","xmm6")
+
+ "pcmpeqd %%xmm1, %%xmm1 \n\t"
+ "pslld $31, %%xmm1 \n\t"
+ "psrld $29, %%xmm1 \n\t"
+ "mov %5, %%"REG_a" \n\t"
+
+ snow_vertical_compose_sse2_r2r_add("xmm1","xmm1","xmm1","xmm1","xmm0","xmm2","xmm4","xmm6")
+ snow_vertical_compose_sse2_sra("3","xmm0","xmm2","xmm4","xmm6")
+ snow_vertical_compose_sse2_load(REG_a,"xmm1","xmm3","xmm5","xmm7")
+ snow_vertical_compose_sse2_sub("xmm0","xmm2","xmm4","xmm6","xmm1","xmm3","xmm5","xmm7")
+ snow_vertical_compose_sse2_store(REG_a,"xmm1","xmm3","xmm5","xmm7")
+ "mov %3, %%"REG_c" \n\t"
+ snow_vertical_compose_sse2_load(REG_S,"xmm0","xmm2","xmm4","xmm6")
+ snow_vertical_compose_sse2_add(REG_c,"xmm1","xmm3","xmm5","xmm7")
+ snow_vertical_compose_sse2_sub("xmm1","xmm3","xmm5","xmm7","xmm0","xmm2","xmm4","xmm6")
+ snow_vertical_compose_sse2_store(REG_S,"xmm0","xmm2","xmm4","xmm6")
+ "mov %2, %%"REG_a" \n\t"
+ snow_vertical_compose_sse2_load(REG_c,"xmm1","xmm3","xmm5","xmm7")
+ snow_vertical_compose_sse2_add(REG_a,"xmm0","xmm2","xmm4","xmm6")
+ snow_vertical_compose_sse2_sll("2","xmm1","xmm3","xmm5","xmm7")\
+ snow_vertical_compose_sse2_r2r_add("xmm1","xmm3","xmm5","xmm7","xmm0","xmm2","xmm4","xmm6")
+
+ "pcmpeqd %%xmm1, %%xmm1 \n\t"
+ "pslld $31, %%xmm1 \n\t"
+ "psrld $28, %%xmm1 \n\t"
+ "mov %1, %%"REG_S" \n\t"
+
+ snow_vertical_compose_sse2_r2r_add("xmm1","xmm1","xmm1","xmm1","xmm0","xmm2","xmm4","xmm6")
+ snow_vertical_compose_sse2_sra("4","xmm0","xmm2","xmm4","xmm6")
+ snow_vertical_compose_sse2_add(REG_c,"xmm0","xmm2","xmm4","xmm6")
+ snow_vertical_compose_sse2_store(REG_c,"xmm0","xmm2","xmm4","xmm6")
+ snow_vertical_compose_sse2_add(REG_S,"xmm0","xmm2","xmm4","xmm6")
+ snow_vertical_compose_sse2_move("xmm0","xmm2","xmm4","xmm6","xmm1","xmm3","xmm5","xmm7")
+ snow_vertical_compose_sse2_sll("1","xmm0","xmm2","xmm4","xmm6")\
+ snow_vertical_compose_sse2_r2r_add("xmm1","xmm3","xmm5","xmm7","xmm0","xmm2","xmm4","xmm6")
+ snow_vertical_compose_sse2_sra("1","xmm0","xmm2","xmm4","xmm6")
+ snow_vertical_compose_sse2_add(REG_a,"xmm0","xmm2","xmm4","xmm6")
+ snow_vertical_compose_sse2_store(REG_a,"xmm0","xmm2","xmm4","xmm6")
+
+ "2: \n\t"
+ "sub $16, %%"REG_d" \n\t"
+ "jge 1b \n\t"
+ :"+d"(i)
+ :
+ "m"(b0),"m"(b1),"m"(b2),"m"(b3),"m"(b4),"m"(b5):
+ "%"REG_a"","%"REG_S"","%"REG_c"");
+}
+
+#define snow_vertical_compose_mmx_load_add(op,r,t0,t1,t2,t3)\
+ ""op" (%%"r",%%"REG_d",4), %%"t0" \n\t"\
+ ""op" 8(%%"r",%%"REG_d",4), %%"t1" \n\t"\
+ ""op" 16(%%"r",%%"REG_d",4), %%"t2" \n\t"\
+ ""op" 24(%%"r",%%"REG_d",4), %%"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("paddd",r,t0,t1,t2,t3)
+
+#define snow_vertical_compose_mmx_sub(s0,s1,s2,s3,t0,t1,t2,t3)\
+ snow_vertical_compose_sse2_sub(s0,s1,s2,s3,t0,t1,t2,t3)
+
+#define snow_vertical_compose_mmx_store(w,s0,s1,s2,s3)\
+ "movq %%"s0", (%%"w",%%"REG_d",4) \n\t"\
+ "movq %%"s1", 8(%%"w",%%"REG_d",4) \n\t"\
+ "movq %%"s2", 16(%%"w",%%"REG_d",4) \n\t"\
+ "movq %%"s3", 24(%%"w",%%"REG_d",4) \n\t"
+
+#define snow_vertical_compose_mmx_sra(n,t0,t1,t2,t3)\
+ snow_vertical_compose_sse2_sra(n,t0,t1,t2,t3)
+
+#define snow_vertical_compose_mmx_r2r_add(s0,s1,s2,s3,t0,t1,t2,t3)\
+ snow_vertical_compose_sse2_r2r_add(s0,s1,s2,s3,t0,t1,t2,t3)
+
+#define snow_vertical_compose_mmx_sll(n,t0,t1,t2,t3)\
+ snow_vertical_compose_sse2_sll(n,t0,t1,t2,t3)
+
+#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"
+
+void ff_snow_vertical_compose97i_mmx(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, DWTELEM *b3, DWTELEM *b4, DWTELEM *b5, int width){
+ long i = width;
+ while(i & 0x7)
+ {
+ 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;
+ }
+
+ asm volatile(
+ "jmp 2f \n\t"
+ "1: \n\t"
+
+ "mov %6, %%"REG_a" \n\t"
+ "mov %4, %%"REG_S" \n\t"
+
+ snow_vertical_compose_mmx_load(REG_S,"mm0","mm2","mm4","mm6")
+ snow_vertical_compose_mmx_add(REG_a,"mm0","mm2","mm4","mm6")
+ snow_vertical_compose_mmx_move("mm0","mm2","mm4","mm6","mm1","mm3","mm5","mm7")
+ snow_vertical_compose_mmx_sll("1","mm0","mm2","mm4","mm6")
+ snow_vertical_compose_mmx_r2r_add("mm1","mm3","mm5","mm7","mm0","mm2","mm4","mm6")
+
+ "pcmpeqd %%mm1, %%mm1 \n\t"
+ "pslld $31, %%mm1 \n\t"
+ "psrld $29, %%mm1 \n\t"
+ "mov %5, %%"REG_a" \n\t"
+
+ snow_vertical_compose_mmx_r2r_add("mm1","mm1","mm1","mm1","mm0","mm2","mm4","mm6")
+ snow_vertical_compose_mmx_sra("3","mm0","mm2","mm4","mm6")
+ snow_vertical_compose_mmx_load(REG_a,"mm1","mm3","mm5","mm7")
+ snow_vertical_compose_mmx_sub("mm0","mm2","mm4","mm6","mm1","mm3","mm5","mm7")
+ snow_vertical_compose_mmx_store(REG_a,"mm1","mm3","mm5","mm7")
+ "mov %3, %%"REG_c" \n\t"
+ snow_vertical_compose_mmx_load(REG_S,"mm0","mm2","mm4","mm6")
+ snow_vertical_compose_mmx_add(REG_c,"mm1","mm3","mm5","mm7")
+ snow_vertical_compose_mmx_sub("mm1","mm3","mm5","mm7","mm0","mm2","mm4","mm6")
+ snow_vertical_compose_mmx_store(REG_S,"mm0","mm2","mm4","mm6")
+ "mov %2, %%"REG_a" \n\t"
+ snow_vertical_compose_mmx_load(REG_c,"mm1","mm3","mm5","mm7")
+ snow_vertical_compose_mmx_add(REG_a,"mm0","mm2","mm4","mm6")
+ snow_vertical_compose_mmx_sll("2","mm1","mm3","mm5","mm7")
+ snow_vertical_compose_mmx_r2r_add("mm1","mm3","mm5","mm7","mm0","mm2","mm4","mm6")
+
+ "pcmpeqd %%mm1, %%mm1 \n\t"
+ "pslld $31, %%mm1 \n\t"
+ "psrld $28, %%mm1 \n\t"
+ "mov %1, %%"REG_S" \n\t"
+
+ snow_vertical_compose_mmx_r2r_add("mm1","mm1","mm1","mm1","mm0","mm2","mm4","mm6")
+ snow_vertical_compose_mmx_sra("4","mm0","mm2","mm4","mm6")
+ snow_vertical_compose_mmx_add(REG_c,"mm0","mm2","mm4","mm6")
+ snow_vertical_compose_mmx_store(REG_c,"mm0","mm2","mm4","mm6")
+ snow_vertical_compose_mmx_add(REG_S,"mm0","mm2","mm4","mm6")
+ snow_vertical_compose_mmx_move("mm0","mm2","mm4","mm6","mm1","mm3","mm5","mm7")
+ snow_vertical_compose_mmx_sll("1","mm0","mm2","mm4","mm6")
+ snow_vertical_compose_mmx_r2r_add("mm1","mm3","mm5","mm7","mm0","mm2","mm4","mm6")
+ snow_vertical_compose_mmx_sra("1","mm0","mm2","mm4","mm6")
+ snow_vertical_compose_mmx_add(REG_a,"mm0","mm2","mm4","mm6")
+ snow_vertical_compose_mmx_store(REG_a,"mm0","mm2","mm4","mm6")
+
+ "2: \n\t"
+ "sub $8, %%"REG_d" \n\t"
+ "jge 1b \n\t"
+ :"+d"(i)
+ :
+ "m"(b0),"m"(b1),"m"(b2),"m"(b3),"m"(b4),"m"(b5):
+ "%"REG_a"","%"REG_S"","%"REG_c"");
+}
+
+#define snow_inner_add_yblock_sse2_header \
+ DWTELEM * * dst_array = sb->line + src_y;\
+ long 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"\
+ "pslld $31, %%xmm3 \n\t"\
+ "psrld $24, %%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"((long)(src_x<<2)),"m"(obmc),"a"(block),"m"((long)b_h),"m"((long)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 $"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 $"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(uint8_t *obmc, const long obmc_stride, uint8_t * * block, int b_w, long b_h,
+ int src_x, int src_y, long 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(uint8_t *obmc, const long obmc_stride, uint8_t * * block, int b_w, long b_h,
+ int src_x, int src_y, long 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"
+ "movdqa %%xmm1, %%xmm0 \n\t"
+ "movdqa %%xmm5, %%xmm4 \n\t"
+ "punpcklwd %%xmm7, %%xmm0 \n\t"
+ "paddd (%%"REG_D"), %%xmm0 \n\t"
+ "punpckhwd %%xmm7, %%xmm1 \n\t"
+ "paddd 16(%%"REG_D"), %%xmm1 \n\t"
+ "punpcklwd %%xmm7, %%xmm4 \n\t"
+ "paddd 32(%%"REG_D"), %%xmm4 \n\t"
+ "punpckhwd %%xmm7, %%xmm5 \n\t"
+ "paddd 48(%%"REG_D"), %%xmm5 \n\t"
+ "paddd %%xmm3, %%xmm0 \n\t"
+ "paddd %%xmm3, %%xmm1 \n\t"
+ "paddd %%xmm3, %%xmm4 \n\t"
+ "paddd %%xmm3, %%xmm5 \n\t"
+ "psrad $8, %%xmm0 \n\t" /* FRAC_BITS. */
+ "psrad $8, %%xmm1 \n\t" /* FRAC_BITS. */
+ "psrad $8, %%xmm4 \n\t" /* FRAC_BITS. */
+ "psrad $8, %%xmm5 \n\t" /* FRAC_BITS. */
+
+ "packssdw %%xmm1, %%xmm0 \n\t"
+ "packssdw %%xmm5, %%xmm4 \n\t"
+ "packuswb %%xmm4, %%xmm0 \n\t"
+
+ "movdqu %%xmm0, (%%"REG_d") \n\t"
+
+snow_inner_add_yblock_sse2_end_16
+}
+
+#define snow_inner_add_yblock_mmx_header \
+ DWTELEM * * dst_array = sb->line + src_y;\
+ long 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"\
+ "pslld $31, %%mm3 \n\t"\
+ "psrld $24, %%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"\
+ "movq %%mm1, %%mm0 \n\t"\
+ "movq %%mm5, %%mm4 \n\t"\
+ "punpcklwd %%mm7, %%mm0 \n\t"\
+ "paddd "read_offset"(%%"REG_D"), %%mm0 \n\t"\
+ "punpckhwd %%mm7, %%mm1 \n\t"\
+ "paddd "read_offset"+8(%%"REG_D"), %%mm1 \n\t"\
+ "punpcklwd %%mm7, %%mm4 \n\t"\
+ "paddd "read_offset"+16(%%"REG_D"), %%mm4 \n\t"\
+ "punpckhwd %%mm7, %%mm5 \n\t"\
+ "paddd "read_offset"+24(%%"REG_D"), %%mm5 \n\t"\
+ "paddd %%mm3, %%mm0 \n\t"\
+ "paddd %%mm3, %%mm1 \n\t"\
+ "paddd %%mm3, %%mm4 \n\t"\
+ "paddd %%mm3, %%mm5 \n\t"\
+ "psrad $8, %%mm0 \n\t"\
+ "psrad $8, %%mm1 \n\t"\
+ "psrad $8, %%mm4 \n\t"\
+ "psrad $8, %%mm5 \n\t"\
+\
+ "packssdw %%mm1, %%mm0 \n\t"\
+ "packssdw %%mm5, %%mm4 \n\t"\
+ "packuswb %%mm4, %%mm0 \n\t"\
+ "movq %%mm0, "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 $"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"((long)(src_x<<2)),"m"(obmc),"a"(block),"m"((long)b_h),"m"((long)src_stride):\
+ "%"REG_c"","%"REG_S"","%"REG_D"","%"REG_d"");
+
+static void inner_add_yblock_bw_8_obmc_16_mmx(uint8_t *obmc, const long obmc_stride, uint8_t * * block, int b_w, long b_h,
+ int src_x, int src_y, long 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(uint8_t *obmc, const long obmc_stride, uint8_t * * block, int b_w, long b_h,
+ int src_x, int src_y, long 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("32", "8")
+snow_inner_add_yblock_mmx_end("32")
+}
+
+void ff_snow_inner_add_yblock_sse2(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);
+}
+
+void ff_snow_inner_add_yblock_mmx(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);
+}
diff --git a/contrib/ffmpeg/libavcodec/i386/vp3dsp_mmx.c b/contrib/ffmpeg/libavcodec/i386/vp3dsp_mmx.c
new file mode 100644
index 000000000..f715dc803
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/vp3dsp_mmx.c
@@ -0,0 +1,324 @@
+/*
+ * 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 vp3dsp_mmx.c
+ * MMX-optimized functions cribbed from the original VP3 source code.
+ */
+
+#include "../dsputil.h"
+#include "mmx.h"
+
+#define IdctAdjustBeforeShift 8
+
+/* (12 * 4) 2-byte memory locations ( = 96 bytes total)
+ * idct_constants[0..15] = Mask table (M(I))
+ * idct_constants[16..43] = Cosine table (C(I))
+ * idct_constants[44..47] = 8
+ */
+static uint16_t idct_constants[(4 + 7 + 1) * 4];
+static const uint16_t idct_cosine_table[7] = {
+ 64277, 60547, 54491, 46341, 36410, 25080, 12785
+};
+
+#define r0 mm0
+#define r1 mm1
+#define r2 mm2
+#define r3 mm3
+#define r4 mm4
+#define r5 mm5
+#define r6 mm6
+#define r7 mm7
+
+/* from original comments: The Macro does IDct on 4 1-D Dcts */
+#define BeginIDCT() { \
+ movq_m2r(*I(3), r2); \
+ movq_m2r(*C(3), r6); \
+ movq_r2r(r2, r4); \
+ movq_m2r(*J(5), r7); \
+ pmulhw_r2r(r6, r4); /* r4 = c3*i3 - i3 */ \
+ movq_m2r(*C(5), r1); \
+ pmulhw_r2r(r7, r6); /* r6 = c3*i5 - i5 */ \
+ movq_r2r(r1, r5); \
+ pmulhw_r2r(r2, r1); /* r1 = c5*i3 - i3 */ \
+ movq_m2r(*I(1), r3); \
+ pmulhw_r2r(r7, r5); /* r5 = c5*i5 - i5 */ \
+ movq_m2r(*C(1), r0); /* (all registers are in use) */ \
+ paddw_r2r(r2, r4); /* r4 = c3*i3 */ \
+ paddw_r2r(r7, r6); /* r6 = c3*i5 */ \
+ paddw_r2r(r1, r2); /* r2 = c5*i3 */ \
+ movq_m2r(*J(7), r1); \
+ paddw_r2r(r5, r7); /* r7 = c5*i5 */ \
+ movq_r2r(r0, r5); /* r5 = c1 */ \
+ pmulhw_r2r(r3, r0); /* r0 = c1*i1 - i1 */ \
+ paddsw_r2r(r7, r4); /* r4 = C = c3*i3 + c5*i5 */ \
+ pmulhw_r2r(r1, r5); /* r5 = c1*i7 - i7 */ \
+ movq_m2r(*C(7), r7); \
+ psubsw_r2r(r2, r6); /* r6 = D = c3*i5 - c5*i3 */ \
+ paddw_r2r(r3, r0); /* r0 = c1*i1 */ \
+ pmulhw_r2r(r7, r3); /* r3 = c7*i1 */ \
+ movq_m2r(*I(2), r2); \
+ pmulhw_r2r(r1, r7); /* r7 = c7*i7 */ \
+ paddw_r2r(r1, r5); /* r5 = c1*i7 */ \
+ movq_r2r(r2, r1); /* r1 = i2 */ \
+ pmulhw_m2r(*C(2), r2); /* r2 = c2*i2 - i2 */ \
+ psubsw_r2r(r5, r3); /* r3 = B = c7*i1 - c1*i7 */ \
+ movq_m2r(*J(6), r5); \
+ paddsw_r2r(r7, r0); /* r0 = A = c1*i1 + c7*i7 */ \
+ movq_r2r(r5, r7); /* r7 = i6 */ \
+ psubsw_r2r(r4, r0); /* r0 = A - C */ \
+ pmulhw_m2r(*C(2), r5); /* r5 = c2*i6 - i6 */ \
+ paddw_r2r(r1, r2); /* r2 = c2*i2 */ \
+ pmulhw_m2r(*C(6), r1); /* r1 = c6*i2 */ \
+ paddsw_r2r(r4, r4); /* r4 = C + C */ \
+ paddsw_r2r(r0, r4); /* r4 = C. = A + C */ \
+ psubsw_r2r(r6, r3); /* r3 = B - D */ \
+ paddw_r2r(r7, r5); /* r5 = c2*i6 */ \
+ paddsw_r2r(r6, r6); /* r6 = D + D */ \
+ pmulhw_m2r(*C(6), r7); /* r7 = c6*i6 */ \
+ paddsw_r2r(r3, r6); /* r6 = D. = B + D */ \
+ movq_r2m(r4, *I(1)); /* save C. at I(1) */ \
+ psubsw_r2r(r5, r1); /* r1 = H = c6*i2 - c2*i6 */ \
+ movq_m2r(*C(4), r4); \
+ movq_r2r(r3, r5); /* r5 = B - D */ \
+ pmulhw_r2r(r4, r3); /* r3 = (c4 - 1) * (B - D) */ \
+ paddsw_r2r(r2, r7); /* r7 = G = c6*i6 + c2*i2 */ \
+ movq_r2m(r6, *I(2)); /* save D. at I(2) */ \
+ movq_r2r(r0, r2); /* r2 = A - C */ \
+ movq_m2r(*I(0), r6); \
+ pmulhw_r2r(r4, r0); /* r0 = (c4 - 1) * (A - C) */ \
+ paddw_r2r(r3, r5); /* r5 = B. = c4 * (B - D) */ \
+ movq_m2r(*J(4), r3); \
+ psubsw_r2r(r1, r5); /* r5 = B.. = B. - H */ \
+ paddw_r2r(r0, r2); /* r0 = A. = c4 * (A - C) */ \
+ psubsw_r2r(r3, r6); /* r6 = i0 - i4 */ \
+ movq_r2r(r6, r0); \
+ pmulhw_r2r(r4, r6); /* r6 = (c4 - 1) * (i0 - i4) */ \
+ paddsw_r2r(r3, r3); /* r3 = i4 + i4 */ \
+ paddsw_r2r(r1, r1); /* r1 = H + H */ \
+ paddsw_r2r(r0, r3); /* r3 = i0 + i4 */ \
+ paddsw_r2r(r5, r1); /* r1 = H. = B + H */ \
+ pmulhw_r2r(r3, r4); /* r4 = (c4 - 1) * (i0 + i4) */ \
+ paddsw_r2r(r0, r6); /* r6 = F = c4 * (i0 - i4) */ \
+ psubsw_r2r(r2, r6); /* r6 = F. = F - A. */ \
+ paddsw_r2r(r2, r2); /* r2 = A. + A. */ \
+ movq_m2r(*I(1), r0); /* r0 = C. */ \
+ paddsw_r2r(r6, r2); /* r2 = A.. = F + A. */ \
+ paddw_r2r(r3, r4); /* r4 = E = c4 * (i0 + i4) */ \
+ psubsw_r2r(r1, r2); /* r2 = R2 = A.. - H. */ \
+}
+
+/* RowIDCT gets ready to transpose */
+#define RowIDCT() { \
+ \
+ BeginIDCT(); \
+ \
+ movq_m2r(*I(2), r3); /* r3 = D. */ \
+ psubsw_r2r(r7, r4); /* r4 = E. = E - G */ \
+ paddsw_r2r(r1, r1); /* r1 = H. + H. */ \
+ paddsw_r2r(r7, r7); /* r7 = G + G */ \
+ paddsw_r2r(r2, r1); /* r1 = R1 = A.. + H. */ \
+ paddsw_r2r(r4, r7); /* r7 = G. = E + G */ \
+ psubsw_r2r(r3, r4); /* r4 = R4 = E. - D. */ \
+ paddsw_r2r(r3, r3); \
+ psubsw_r2r(r5, r6); /* r6 = R6 = F. - B.. */ \
+ paddsw_r2r(r5, r5); \
+ paddsw_r2r(r4, r3); /* r3 = R3 = E. + D. */ \
+ paddsw_r2r(r6, r5); /* r5 = R5 = F. + B.. */ \
+ psubsw_r2r(r0, r7); /* r7 = R7 = G. - C. */ \
+ paddsw_r2r(r0, r0); \
+ movq_r2m(r1, *I(1)); /* save R1 */ \
+ paddsw_r2r(r7, r0); /* r0 = R0 = G. + C. */ \
+}
+
+/* Column IDCT normalizes and stores final results */
+#define ColumnIDCT() { \
+ \
+ BeginIDCT(); \
+ \
+ paddsw_m2r(*Eight, r2); /* adjust R2 (and R1) for shift */ \
+ paddsw_r2r(r1, r1); /* r1 = H. + H. */ \
+ paddsw_r2r(r2, r1); /* r1 = R1 = A.. + H. */ \
+ psraw_i2r(4, r2); /* r2 = NR2 */ \
+ psubsw_r2r(r7, r4); /* r4 = E. = E - G */ \
+ psraw_i2r(4, r1); /* r1 = NR1 */ \
+ movq_m2r(*I(2), r3); /* r3 = D. */ \
+ paddsw_r2r(r7, r7); /* r7 = G + G */ \
+ movq_r2m(r2, *I(2)); /* store NR2 at I2 */ \
+ paddsw_r2r(r4, r7); /* r7 = G. = E + G */ \
+ movq_r2m(r1, *I(1)); /* store NR1 at I1 */ \
+ psubsw_r2r(r3, r4); /* r4 = R4 = E. - D. */ \
+ paddsw_m2r(*Eight, r4); /* adjust R4 (and R3) for shift */ \
+ paddsw_r2r(r3, r3); /* r3 = D. + D. */ \
+ paddsw_r2r(r4, r3); /* r3 = R3 = E. + D. */ \
+ psraw_i2r(4, r4); /* r4 = NR4 */ \
+ psubsw_r2r(r5, r6); /* r6 = R6 = F. - B.. */ \
+ psraw_i2r(4, r3); /* r3 = NR3 */ \
+ paddsw_m2r(*Eight, r6); /* adjust R6 (and R5) for shift */ \
+ paddsw_r2r(r5, r5); /* r5 = B.. + B.. */ \
+ paddsw_r2r(r6, r5); /* r5 = R5 = F. + B.. */ \
+ psraw_i2r(4, r6); /* r6 = NR6 */ \
+ movq_r2m(r4, *J(4)); /* store NR4 at J4 */ \
+ psraw_i2r(4, r5); /* r5 = NR5 */ \
+ movq_r2m(r3, *I(3)); /* store NR3 at I3 */ \
+ psubsw_r2r(r0, r7); /* r7 = R7 = G. - C. */ \
+ paddsw_m2r(*Eight, r7); /* adjust R7 (and R0) for shift */ \
+ paddsw_r2r(r0, r0); /* r0 = C. + C. */ \
+ paddsw_r2r(r7, r0); /* r0 = R0 = G. + C. */ \
+ psraw_i2r(4, r7); /* r7 = NR7 */ \
+ movq_r2m(r6, *J(6)); /* store NR6 at J6 */ \
+ psraw_i2r(4, r0); /* r0 = NR0 */ \
+ movq_r2m(r5, *J(5)); /* store NR5 at J5 */ \
+ movq_r2m(r7, *J(7)); /* store NR7 at J7 */ \
+ movq_r2m(r0, *I(0)); /* store NR0 at I0 */ \
+}
+
+/* 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. */
+
+#define Transpose() { \
+ movq_r2r(r4, r1); /* r1 = e3 e2 e1 e0 */ \
+ punpcklwd_r2r(r5, r4); /* r4 = f1 e1 f0 e0 */ \
+ movq_r2m(r0, *I(0)); /* save a3 a2 a1 a0 */ \
+ punpckhwd_r2r(r5, r1); /* r1 = f3 e3 f2 e2 */ \
+ movq_r2r(r6, r0); /* r0 = g3 g2 g1 g0 */ \
+ punpcklwd_r2r(r7, r6); /* r6 = h1 g1 h0 g0 */ \
+ movq_r2r(r4, r5); /* r5 = f1 e1 f0 e0 */ \
+ punpckldq_r2r(r6, r4); /* r4 = h0 g0 f0 e0 = R4 */ \
+ punpckhdq_r2r(r6, r5); /* r5 = h1 g1 f1 e1 = R5 */ \
+ movq_r2r(r1, r6); /* r6 = f3 e3 f2 e2 */ \
+ movq_r2m(r4, *J(4)); \
+ punpckhwd_r2r(r7, r0); /* r0 = h3 g3 h2 g2 */ \
+ movq_r2m(r5, *J(5)); \
+ punpckhdq_r2r(r0, r6); /* r6 = h3 g3 f3 e3 = R7 */ \
+ movq_m2r(*I(0), r4); /* r4 = a3 a2 a1 a0 */ \
+ punpckldq_r2r(r0, r1); /* r1 = h2 g2 f2 e2 = R6 */ \
+ movq_m2r(*I(1), r5); /* r5 = b3 b2 b1 b0 */ \
+ movq_r2r(r4, r0); /* r0 = a3 a2 a1 a0 */ \
+ movq_r2m(r6, *J(7)); \
+ punpcklwd_r2r(r5, r0); /* r0 = b1 a1 b0 a0 */ \
+ movq_r2m(r1, *J(6)); \
+ punpckhwd_r2r(r5, r4); /* r4 = b3 a3 b2 a2 */ \
+ movq_r2r(r2, r5); /* r5 = c3 c2 c1 c0 */ \
+ punpcklwd_r2r(r3, r2); /* r2 = d1 c1 d0 c0 */ \
+ movq_r2r(r0, r1); /* r1 = b1 a1 b0 a0 */ \
+ punpckldq_r2r(r2, r0); /* r0 = d0 c0 b0 a0 = R0 */ \
+ punpckhdq_r2r(r2, r1); /* r1 = d1 c1 b1 a1 = R1 */ \
+ movq_r2r(r4, r2); /* r2 = b3 a3 b2 a2 */ \
+ movq_r2m(r0, *I(0)); \
+ punpckhwd_r2r(r3, r5); /* r5 = d3 c3 d2 c2 */ \
+ movq_r2m(r1, *I(1)); \
+ punpckhdq_r2r(r5, r4); /* r4 = d3 c3 b3 a3 = R3 */ \
+ punpckldq_r2r(r5, r2); /* r2 = d2 c2 b2 a2 = R2 */ \
+ movq_r2m(r4, *I(3)); \
+ movq_r2m(r2, *I(2)); \
+}
+
+void ff_vp3_dsp_init_mmx(void)
+{
+ int j = 16;
+ uint16_t *p;
+
+ j = 1;
+ do {
+ p = idct_constants + ((j + 3) << 2);
+ p[0] = p[1] = p[2] = p[3] = idct_cosine_table[j - 1];
+ } while (++j <= 7);
+
+ idct_constants[44] = idct_constants[45] =
+ idct_constants[46] = idct_constants[47] = IdctAdjustBeforeShift;
+}
+
+void ff_vp3_idct_mmx(int16_t *output_data)
+{
+ /* 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 C(x) (idct_constants + 16 + (x - 1) * 4)
+#define Eight (idct_constants + 44)
+
+ /* at this point, function has completed dequantization + dezigzag +
+ * partial transposition; now do the idct itself */
+#define I(K) (output_data + K * 8)
+#define J(K) (output_data + ((K - 4) * 8) + 4)
+
+ RowIDCT();
+ Transpose();
+
+#undef I
+#undef J
+#define I(K) (output_data + (K * 8) + 32)
+#define J(K) (output_data + ((K - 4) * 8) + 36)
+
+ RowIDCT();
+ Transpose();
+
+#undef I
+#undef J
+#define I(K) (output_data + K * 8)
+#define J(K) (output_data + K * 8)
+
+ ColumnIDCT();
+
+#undef I
+#undef J
+#define I(K) (output_data + (K * 8) + 4)
+#define J(K) (output_data + (K * 8) + 4)
+
+ ColumnIDCT();
+
+#undef I
+#undef J
+
+}
diff --git a/contrib/ffmpeg/libavcodec/i386/vp3dsp_sse2.c b/contrib/ffmpeg/libavcodec/i386/vp3dsp_sse2.c
new file mode 100644
index 000000000..bd2911d59
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/i386/vp3dsp_sse2.c
@@ -0,0 +1,827 @@
+/*
+ * 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 vp3dsp_sse2.c
+ * SSE2-optimized functions cribbed from the original VP3 source code.
+ */
+
+#include "../dsputil.h"
+#include "mmx.h"
+
+static DECLARE_ALIGNED_16(const unsigned short, SSE2_dequant_const[]) =
+{
+ 0,65535,65535,0,0,0,0,0, // 0x0000 0000 0000 0000 0000 FFFF FFFF 0000
+ 0,0,0,0,65535,65535,0,0, // 0x0000 0000 FFFF FFFF 0000 0000 0000 0000
+ 65535,65535,65535,0,0,0,0,0,// 0x0000 0000 0000 0000 0000 FFFF FFFF FFFF
+ 0,0,0,65535,0,0,0,0, // 0x0000 0000 0000 0000 FFFF 0000 0000 0000
+ 0,0,0,65535,65535,0,0,0, // 0x0000 0000 0000 FFFF FFFF 0000 0000 0000
+ 65535,0,0,0,0,65535,0,0, // 0x0000 0000 FFFF 0000 0000 0000 0000 FFFF
+ 0,0,65535,65535, 0,0,0,0 // 0x0000 0000 0000 0000 FFFF FFFF 0000 0000
+};
+
+static DECLARE_ALIGNED_16(const unsigned int, eight_data[]) =
+{
+ 0x00080008,
+ 0x00080008,
+ 0x00080008,
+ 0x00080008
+};
+
+static DECLARE_ALIGNED_16(const unsigned short, SSE2_idct_data[7 * 8]) =
+{
+ 64277,64277,64277,64277,64277,64277,64277,64277,
+ 60547,60547,60547,60547,60547,60547,60547,60547,
+ 54491,54491,54491,54491,54491,54491,54491,54491,
+ 46341,46341,46341,46341,46341,46341,46341,46341,
+ 36410,36410,36410,36410,36410,36410,36410,36410,
+ 25080,25080,25080,25080,25080,25080,25080,25080,
+ 12785,12785,12785,12785,12785,12785,12785,12785
+};
+
+
+#define SSE2_Column_IDCT() { \
+ \
+ movdqu_m2r(*I(3), xmm2); /* xmm2 = i3 */ \
+ movdqu_m2r(*C(3), xmm6); /* xmm6 = c3 */ \
+ \
+ movdqu_r2r(xmm2, xmm4); /* xmm4 = i3 */ \
+ movdqu_m2r(*I(5), xmm7); /* xmm7 = i5 */ \
+ \
+ pmulhw_r2r(xmm6, xmm4); /* xmm4 = c3 * i3 - i3 */ \
+ movdqu_m2r(*C(5), xmm1); /* xmm1 = c5 */ \
+ \
+ pmulhw_r2r(xmm7, xmm6); /* xmm6 = c3 * i5 - i5 */ \
+ movdqu_r2r(xmm1, xmm5); /* xmm5 = c5 */ \
+ \
+ pmulhw_r2r(xmm2, xmm1); /* xmm1 = c5 * i3 - i3 */ \
+ movdqu_m2r(*I(1), xmm3); /* xmm3 = i1 */ \
+ \
+ pmulhw_r2r(xmm7, xmm5); /* xmm5 = c5 * i5 - i5 */ \
+ movdqu_m2r(*C(1), xmm0); /* xmm0 = c1 */ \
+ \
+ /* all registers are in use */ \
+ \
+ paddw_r2r(xmm2, xmm4); /* xmm4 = c3 * i3 */ \
+ paddw_r2r(xmm7, xmm6); /* xmm6 = c3 * i5 */ \
+ \
+ paddw_r2r(xmm1, xmm2); /* xmm2 = c5 * i3 */ \
+ movdqu_m2r(*I(7), xmm1); /* xmm1 = i7 */ \
+ \
+ paddw_r2r(xmm5, xmm7); /* xmm7 = c5 * i5 */ \
+ movdqu_r2r(xmm0, xmm5); /* xmm5 = c1 */ \
+ \
+ pmulhw_r2r(xmm3, xmm0); /* xmm0 = c1 * i1 - i1 */ \
+ paddsw_r2r(xmm7, xmm4); /* xmm4 = c3 * i3 + c5 * i5 = C */ \
+ \
+ pmulhw_r2r(xmm1, xmm5); /* xmm5 = c1 * i7 - i7 */ \
+ movdqu_m2r(*C(7), xmm7); /* xmm7 = c7 */ \
+ \
+ psubsw_r2r(xmm2, xmm6); /* xmm6 = c3 * i5 - c5 * i3 = D */ \
+ paddw_r2r(xmm3, xmm0); /* xmm0 = c1 * i1 */ \
+ \
+ pmulhw_r2r(xmm7, xmm3); /* xmm3 = c7 * i1 */ \
+ movdqu_m2r(*I(2), xmm2); /* xmm2 = i2 */ \
+ \
+ pmulhw_r2r(xmm1, xmm7); /* xmm7 = c7 * i7 */ \
+ paddw_r2r(xmm1, xmm5); /* xmm5 = c1 * i7 */ \
+ \
+ movdqu_r2r(xmm2, xmm1); /* xmm1 = i2 */ \
+ pmulhw_m2r(*C(2), xmm2); /* xmm2 = i2 * c2 -i2 */ \
+ \
+ psubsw_r2r(xmm5, xmm3); /* xmm3 = c7 * i1 - c1 * i7 = B */ \
+ movdqu_m2r(*I(6), xmm5); /* xmm5 = i6 */ \
+ \
+ paddsw_r2r(xmm7, xmm0); /* xmm0 = c1 * i1 + c7 * i7 = A */ \
+ movdqu_r2r(xmm5, xmm7); /* xmm7 = i6 */ \
+ \
+ psubsw_r2r(xmm4, xmm0); /* xmm0 = A - C */ \
+ pmulhw_m2r(*C(2), xmm5); /* xmm5 = c2 * i6 - i6 */ \
+ \
+ paddw_r2r(xmm1, xmm2); /* xmm2 = i2 * c2 */ \
+ pmulhw_m2r(*C(6), xmm1); /* xmm1 = c6 * i2 */ \
+ \
+ paddsw_r2r(xmm4, xmm4); /* xmm4 = C + C */ \
+ paddsw_r2r(xmm0, xmm4); /* xmm4 = A + C = C. */ \
+ \
+ psubsw_r2r(xmm6, xmm3); /* xmm3 = B - D */ \
+ paddw_r2r(xmm7, xmm5); /* xmm5 = c2 * i6 */ \
+ \
+ paddsw_r2r(xmm6, xmm6); /* xmm6 = D + D */ \
+ pmulhw_m2r(*C(6), xmm7); /* xmm7 = c6 * i6 */ \
+ \
+ paddsw_r2r(xmm3, xmm6); /* xmm6 = B + D = D. */ \
+ movdqu_r2m(xmm4, *I(1)); /* Save C. at I(1) */ \
+ \
+ psubsw_r2r(xmm5, xmm1); /* xmm1 = c6 * i2 - c2 * i6 = H */ \
+ movdqu_m2r(*C(4), xmm4); /* xmm4 = c4 */ \
+ \
+ movdqu_r2r(xmm3, xmm5); /* xmm5 = B - D */ \
+ pmulhw_r2r(xmm4, xmm3); /* xmm3 = ( c4 -1 ) * ( B - D ) */ \
+ \
+ paddsw_r2r(xmm2, xmm7); /* xmm7 = c2 * i2 + c6 * i6 = G */ \
+ movdqu_r2m(xmm6, *I(2)); /* Save D. at I(2) */ \
+ \
+ movdqu_r2r(xmm0, xmm2); /* xmm2 = A - C */ \
+ movdqu_m2r(*I(0), xmm6); /* xmm6 = i0 */ \
+ \
+ pmulhw_r2r(xmm4, xmm0); /* xmm0 = ( c4 - 1 ) * ( A - C ) = A. */ \
+ paddw_r2r(xmm3, xmm5); /* xmm5 = c4 * ( B - D ) = B. */ \
+ \
+ movdqu_m2r(*I(4), xmm3); /* xmm3 = i4 */ \
+ psubsw_r2r(xmm1, xmm5); /* xmm5 = B. - H = B.. */ \
+ \
+ paddw_r2r(xmm0, xmm2); /* xmm2 = c4 * ( A - C) = A. */ \
+ psubsw_r2r(xmm3, xmm6); /* xmm6 = i0 - i4 */ \
+ \
+ movdqu_r2r(xmm6, xmm0); /* xmm0 = i0 - i4 */ \
+ pmulhw_r2r(xmm4, xmm6); /* xmm6 = (c4 - 1) * (i0 - i4) = F */ \
+ \
+ paddsw_r2r(xmm3, xmm3); /* xmm3 = i4 + i4 */ \
+ paddsw_r2r(xmm1, xmm1); /* xmm1 = H + H */ \
+ \
+ paddsw_r2r(xmm0, xmm3); /* xmm3 = i0 + i4 */ \
+ paddsw_r2r(xmm5, xmm1); /* xmm1 = B. + H = H. */ \
+ \
+ pmulhw_r2r(xmm3, xmm4); /* xmm4 = ( c4 - 1 ) * ( i0 + i4 ) */ \
+ paddw_r2r(xmm0, xmm6); /* xmm6 = c4 * ( i0 - i4 ) */ \
+ \
+ psubsw_r2r(xmm2, xmm6); /* xmm6 = F - A. = F. */ \
+ paddsw_r2r(xmm2, xmm2); /* xmm2 = A. + A. */ \
+ \
+ movdqu_m2r(*I(1), xmm0); /* Load C. from I(1) */ \
+ paddsw_r2r(xmm6, xmm2); /* xmm2 = F + A. = A.. */ \
+ \
+ paddw_r2r(xmm3, xmm4); /* xmm4 = c4 * ( i0 + i4 ) = 3 */ \
+ psubsw_r2r(xmm1, xmm2); /* xmm2 = A.. - H. = R2 */ \
+ \
+ paddsw_m2r(*Eight, xmm2); /* Adjust R2 and R1 before shifting */ \
+ paddsw_r2r(xmm1, xmm1); /* xmm1 = H. + H. */ \
+ \
+ paddsw_r2r(xmm2, xmm1); /* xmm1 = A.. + H. = R1 */ \
+ psraw_i2r(4, xmm2); /* xmm2 = op2 */ \
+ \
+ psubsw_r2r(xmm7, xmm4); /* xmm4 = E - G = E. */ \
+ psraw_i2r(4, xmm1); /* xmm1 = op1 */ \
+ \
+ movdqu_m2r(*I(2), xmm3); /* Load D. from I(2) */ \
+ paddsw_r2r(xmm7, xmm7); /* xmm7 = G + G */ \
+ \
+ movdqu_r2m(xmm2, *O(2)); /* Write out op2 */ \
+ paddsw_r2r(xmm4, xmm7); /* xmm7 = E + G = G. */ \
+ \
+ movdqu_r2m(xmm1, *O(1)); /* Write out op1 */ \
+ psubsw_r2r(xmm3, xmm4); /* xmm4 = E. - D. = R4 */ \
+ \
+ paddsw_m2r(*Eight, xmm4); /* Adjust R4 and R3 before shifting */ \
+ paddsw_r2r(xmm3, xmm3); /* xmm3 = D. + D. */ \
+ \
+ paddsw_r2r(xmm4, xmm3); /* xmm3 = E. + D. = R3 */ \
+ psraw_i2r(4, xmm4); /* xmm4 = op4 */ \
+ \
+ psubsw_r2r(xmm5, xmm6); /* xmm6 = F. - B..= R6 */ \
+ psraw_i2r(4, xmm3); /* xmm3 = op3 */ \
+ \
+ paddsw_m2r(*Eight, xmm6); /* Adjust R6 and R5 before shifting */ \
+ paddsw_r2r(xmm5, xmm5); /* xmm5 = B.. + B.. */ \
+ \
+ paddsw_r2r(xmm6, xmm5); /* xmm5 = F. + B.. = R5 */ \
+ psraw_i2r(4, xmm6); /* xmm6 = op6 */ \
+ \
+ movdqu_r2m(xmm4, *O(4)); /* Write out op4 */ \
+ psraw_i2r(4, xmm5); /* xmm5 = op5 */ \
+ \
+ movdqu_r2m(xmm3, *O(3)); /* Write out op3 */ \
+ psubsw_r2r(xmm0, xmm7); /* xmm7 = G. - C. = R7 */ \
+ \
+ paddsw_m2r(*Eight, xmm7); /* Adjust R7 and R0 before shifting */ \
+ paddsw_r2r(xmm0, xmm0); /* xmm0 = C. + C. */ \
+ \
+ paddsw_r2r(xmm7, xmm0); /* xmm0 = G. + C. */ \
+ psraw_i2r(4, xmm7); /* xmm7 = op7 */ \
+ \
+ movdqu_r2m(xmm6, *O(6)); /* Write out op6 */ \
+ psraw_i2r(4, xmm0); /* xmm0 = op0 */ \
+ \
+ movdqu_r2m(xmm5, *O(5)); /* Write out op5 */ \
+ movdqu_r2m(xmm7, *O(7)); /* Write out op7 */ \
+ \
+ movdqu_r2m(xmm0, *O(0)); /* Write out op0 */ \
+ \
+} /* End of SSE2_Column_IDCT macro */
+
+
+#define SSE2_Row_IDCT() { \
+ \
+ movdqu_m2r(*I(3), xmm2); /* xmm2 = i3 */ \
+ movdqu_m2r(*C(3), xmm6); /* xmm6 = c3 */ \
+ \
+ movdqu_r2r(xmm2, xmm4); /* xmm4 = i3 */ \
+ movdqu_m2r(*I(5), xmm7); /* xmm7 = i5 */ \
+ \
+ pmulhw_r2r(xmm6, xmm4); /* xmm4 = c3 * i3 - i3 */ \
+ movdqu_m2r(*C(5), xmm1); /* xmm1 = c5 */ \
+ \
+ pmulhw_r2r(xmm7, xmm6); /* xmm6 = c3 * i5 - i5 */ \
+ movdqu_r2r(xmm1, xmm5); /* xmm5 = c5 */ \
+ \
+ pmulhw_r2r(xmm2, xmm1); /* xmm1 = c5 * i3 - i3 */ \
+ movdqu_m2r(*I(1), xmm3); /* xmm3 = i1 */ \
+ \
+ pmulhw_r2r(xmm7, xmm5); /* xmm5 = c5 * i5 - i5 */ \
+ movdqu_m2r(*C(1), xmm0); /* xmm0 = c1 */ \
+ \
+ /* all registers are in use */ \
+ \
+ paddw_r2r(xmm2, xmm4); /* xmm4 = c3 * i3 */ \
+ paddw_r2r(xmm7, xmm6); /* xmm6 = c3 * i5 */ \
+ \
+ paddw_r2r(xmm1, xmm2); /* xmm2 = c5 * i3 */ \
+ movdqu_m2r(*I(7), xmm1); /* xmm1 = i7 */ \
+ \
+ paddw_r2r(xmm5, xmm7); /* xmm7 = c5 * i5 */ \
+ movdqu_r2r(xmm0, xmm5); /* xmm5 = c1 */ \
+ \
+ pmulhw_r2r(xmm3, xmm0); /* xmm0 = c1 * i1 - i1 */ \
+ paddsw_r2r(xmm7, xmm4); /* xmm4 = c3 * i3 + c5 * i5 = C */ \
+ \
+ pmulhw_r2r(xmm1, xmm5); /* xmm5 = c1 * i7 - i7 */ \
+ movdqu_m2r(*C(7), xmm7); /* xmm7 = c7 */ \
+ \
+ psubsw_r2r(xmm2, xmm6); /* xmm6 = c3 * i5 - c5 * i3 = D */ \
+ paddw_r2r(xmm3, xmm0); /* xmm0 = c1 * i1 */ \
+ \
+ pmulhw_r2r(xmm7, xmm3); /* xmm3 = c7 * i1 */ \
+ movdqu_m2r(*I(2), xmm2); /* xmm2 = i2 */ \
+ \
+ pmulhw_r2r(xmm1, xmm7); /* xmm7 = c7 * i7 */ \
+ paddw_r2r(xmm1, xmm5); /* xmm5 = c1 * i7 */ \
+ \
+ movdqu_r2r(xmm2, xmm1); /* xmm1 = i2 */ \
+ pmulhw_m2r(*C(2), xmm2); /* xmm2 = i2 * c2 -i2 */ \
+ \
+ psubsw_r2r(xmm5, xmm3); /* xmm3 = c7 * i1 - c1 * i7 = B */ \
+ movdqu_m2r(*I(6), xmm5); /* xmm5 = i6 */ \
+ \
+ paddsw_r2r(xmm7, xmm0); /* xmm0 = c1 * i1 + c7 * i7 = A */ \
+ movdqu_r2r(xmm5, xmm7); /* xmm7 = i6 */ \
+ \
+ psubsw_r2r(xmm4, xmm0); /* xmm0 = A - C */ \
+ pmulhw_m2r(*C(2), xmm5); /* xmm5 = c2 * i6 - i6 */ \
+ \
+ paddw_r2r(xmm1, xmm2); /* xmm2 = i2 * c2 */ \
+ pmulhw_m2r(*C(6), xmm1); /* xmm1 = c6 * i2 */ \
+ \
+ paddsw_r2r(xmm4, xmm4); /* xmm4 = C + C */ \
+ paddsw_r2r(xmm0, xmm4); /* xmm4 = A + C = C. */ \
+ \
+ psubsw_r2r(xmm6, xmm3); /* xmm3 = B - D */ \
+ paddw_r2r(xmm7, xmm5); /* xmm5 = c2 * i6 */ \
+ \
+ paddsw_r2r(xmm6, xmm6); /* xmm6 = D + D */ \
+ pmulhw_m2r(*C(6), xmm7); /* xmm7 = c6 * i6 */ \
+ \
+ paddsw_r2r(xmm3, xmm6); /* xmm6 = B + D = D. */ \
+ movdqu_r2m(xmm4, *I(1)); /* Save C. at I(1) */ \
+ \
+ psubsw_r2r(xmm5, xmm1); /* xmm1 = c6 * i2 - c2 * i6 = H */ \
+ movdqu_m2r(*C(4), xmm4); /* xmm4 = c4 */ \
+ \
+ movdqu_r2r(xmm3, xmm5); /* xmm5 = B - D */ \
+ pmulhw_r2r(xmm4, xmm3); /* xmm3 = ( c4 -1 ) * ( B - D ) */ \
+ \
+ paddsw_r2r(xmm2, xmm7); /* xmm7 = c2 * i2 + c6 * i6 = G */ \
+ movdqu_r2m(xmm6, *I(2)); /* Save D. at I(2) */ \
+ \
+ movdqu_r2r(xmm0, xmm2); /* xmm2 = A - C */ \
+ movdqu_m2r(*I(0), xmm6); /* xmm6 = i0 */ \
+ \
+ pmulhw_r2r(xmm4, xmm0); /* xmm0 = ( c4 - 1 ) * ( A - C ) = A. */ \
+ paddw_r2r(xmm3, xmm5); /* xmm5 = c4 * ( B - D ) = B. */ \
+ \
+ movdqu_m2r(*I(4), xmm3); /* xmm3 = i4 */ \
+ psubsw_r2r(xmm1, xmm5); /* xmm5 = B. - H = B.. */ \
+ \
+ paddw_r2r(xmm0, xmm2); /* xmm2 = c4 * ( A - C) = A. */ \
+ psubsw_r2r(xmm3, xmm6); /* xmm6 = i0 - i4 */ \
+ \
+ movdqu_r2r(xmm6, xmm0); /* xmm0 = i0 - i4 */ \
+ pmulhw_r2r(xmm4, xmm6); /* xmm6 = ( c4 - 1 ) * ( i0 - i4 ) = F */ \
+ \
+ paddsw_r2r(xmm3, xmm3); /* xmm3 = i4 + i4 */ \
+ paddsw_r2r(xmm1, xmm1); /* xmm1 = H + H */ \
+ \
+ paddsw_r2r(xmm0, xmm3); /* xmm3 = i0 + i4 */ \
+ paddsw_r2r(xmm5, xmm1); /* xmm1 = B. + H = H. */ \
+ \
+ pmulhw_r2r(xmm3, xmm4); /* xmm4 = ( c4 - 1 ) * ( i0 + i4 ) */ \
+ paddw_r2r(xmm0, xmm6); /* xmm6 = c4 * ( i0 - i4 ) */ \
+ \
+ psubsw_r2r(xmm2, xmm6); /* xmm6 = F - A. = F. */ \
+ paddsw_r2r(xmm2, xmm2); /* xmm2 = A. + A. */ \
+ \
+ movdqu_m2r(*I(1), xmm0); /* Load C. from I(1) */ \
+ paddsw_r2r(xmm6, xmm2); /* xmm2 = F + A. = A.. */ \
+ \
+ paddw_r2r(xmm3, xmm4); /* xmm4 = c4 * ( i0 + i4 ) = 3 */ \
+ psubsw_r2r(xmm1, xmm2); /* xmm2 = A.. - H. = R2 */ \
+ \
+ paddsw_r2r(xmm1, xmm1); /* xmm1 = H. + H. */ \
+ paddsw_r2r(xmm2, xmm1); /* xmm1 = A.. + H. = R1 */ \
+ \
+ psubsw_r2r(xmm7, xmm4); /* xmm4 = E - G = E. */ \
+ \
+ movdqu_m2r(*I(2), xmm3); /* Load D. from I(2) */ \
+ paddsw_r2r(xmm7, xmm7); /* xmm7 = G + G */ \
+ \
+ movdqu_r2m(xmm2, *I(2)); /* Write out op2 */ \
+ paddsw_r2r(xmm4, xmm7); /* xmm7 = E + G = G. */ \
+ \
+ movdqu_r2m(xmm1, *I(1)); /* Write out op1 */ \
+ psubsw_r2r(xmm3, xmm4); /* xmm4 = E. - D. = R4 */ \
+ \
+ paddsw_r2r(xmm3, xmm3); /* xmm3 = D. + D. */ \
+ \
+ paddsw_r2r(xmm4, xmm3); /* xmm3 = E. + D. = R3 */ \
+ \
+ psubsw_r2r(xmm5, xmm6); /* xmm6 = F. - B..= R6 */ \
+ \
+ paddsw_r2r(xmm5, xmm5); /* xmm5 = B.. + B.. */ \
+ \
+ paddsw_r2r(xmm6, xmm5); /* xmm5 = F. + B.. = R5 */ \
+ \
+ movdqu_r2m(xmm4, *I(4)); /* Write out op4 */ \
+ \
+ movdqu_r2m(xmm3, *I(3)); /* Write out op3 */ \
+ psubsw_r2r(xmm0, xmm7); /* xmm7 = G. - C. = R7 */ \
+ \
+ paddsw_r2r(xmm0, xmm0); /* xmm0 = C. + C. */ \
+ \
+ paddsw_r2r(xmm7, xmm0); /* xmm0 = G. + C. */ \
+ \
+ movdqu_r2m(xmm6, *I(6)); /* Write out op6 */ \
+ \
+ movdqu_r2m(xmm5, *I(5)); /* Write out op5 */ \
+ movdqu_r2m(xmm7, *I(7)); /* Write out op7 */ \
+ \
+ movdqu_r2m(xmm0, *I(0)); /* Write out op0 */ \
+ \
+} /* End of SSE2_Row_IDCT macro */
+
+
+#define SSE2_Transpose() { \
+ \
+ movdqu_m2r(*I(4), xmm4); /* xmm4=e7e6e5e4e3e2e1e0 */ \
+ movdqu_m2r(*I(5), xmm0); /* xmm4=f7f6f5f4f3f2f1f0 */ \
+ \
+ movdqu_r2r(xmm4, xmm5); /* make a copy */ \
+ punpcklwd_r2r(xmm0, xmm4); /* xmm4=f3e3f2e2f1e1f0e0 */ \
+ \
+ punpckhwd_r2r(xmm0, xmm5); /* xmm5=f7e7f6e6f5e5f4e4 */ \
+ movdqu_m2r(*I(6), xmm6); /* xmm6=g7g6g5g4g3g2g1g0 */ \
+ \
+ movdqu_m2r(*I(7), xmm0); /* xmm0=h7h6h5h4h3h2h1h0 */ \
+ movdqu_r2r(xmm6, xmm7); /* make a copy */ \
+ \
+ punpcklwd_r2r(xmm0, xmm6); /* xmm6=h3g3h3g2h1g1h0g0 */ \
+ punpckhwd_r2r(xmm0, xmm7); /* xmm7=h7g7h6g6h5g5h4g4 */ \
+ \
+ movdqu_r2r(xmm4, xmm3); /* make a copy */ \
+ punpckldq_r2r(xmm6, xmm4); /* xmm4=h1g1f1e1h0g0f0e0 */ \
+ \
+ punpckhdq_r2r(xmm6, xmm3); /* xmm3=h3g3g3e3h2g2f2e2 */ \
+ movdqu_r2m(xmm3, *I(6)); /* save h3g3g3e3h2g2f2e2 */ \
+ /* Free xmm6 */ \
+ movdqu_r2r(xmm5, xmm6); /* make a copy */ \
+ punpckldq_r2r(xmm7, xmm5); /* xmm5=h5g5f5e5h4g4f4e4 */ \
+ \
+ punpckhdq_r2r(xmm7, xmm6); /* xmm6=h7g7f7e7h6g6f6e6 */ \
+ movdqu_m2r(*I(0), xmm0); /* xmm0=a7a6a5a4a3a2a1a0 */ \
+ /* Free xmm7 */ \
+ movdqu_m2r(*I(1), xmm1); /* xmm1=b7b6b5b4b3b2b1b0 */ \
+ movdqu_r2r(xmm0, xmm7); /* make a copy */ \
+ \
+ punpcklwd_r2r(xmm1, xmm0); /* xmm0=b3a3b2a2b1a1b0a0 */ \
+ punpckhwd_r2r(xmm1, xmm7); /* xmm7=b7a7b6a6b5a5b4a4 */ \
+ /* Free xmm1 */ \
+ movdqu_m2r(*I(2), xmm2); /* xmm2=c7c6c5c4c3c2c1c0 */ \
+ movdqu_m2r(*I(3), xmm3); /* xmm3=d7d6d5d4d3d2d1d0 */ \
+ \
+ movdqu_r2r(xmm2, xmm1); /* make a copy */ \
+ punpcklwd_r2r(xmm3, xmm2); /* xmm2=d3c3d2c2d1c1d0c0 */ \
+ \
+ punpckhwd_r2r(xmm3, xmm1); /* xmm1=d7c7d6c6d5c5d4c4 */ \
+ movdqu_r2r(xmm0, xmm3); /* make a copy */ \
+ \
+ punpckldq_r2r(xmm2, xmm0); /* xmm0=d1c1b1a1d0c0b0a0 */ \
+ punpckhdq_r2r(xmm2, xmm3); /* xmm3=d3c3b3a3d2c2b2a2 */ \
+ /* Free xmm2 */ \
+ movdqu_r2r(xmm7, xmm2); /* make a copy */ \
+ punpckldq_r2r(xmm1, xmm2); /* xmm2=d5c5b5a5d4c4b4a4 */ \
+ \
+ punpckhdq_r2r(xmm1, xmm7); /* xmm7=d7c7b7a7d6c6b6a6 */ \
+ movdqu_r2r(xmm0, xmm1); /* make a copy */ \
+ \
+ punpcklqdq_r2r(xmm4, xmm0); /* xmm0=h0g0f0e0d0c0b0a0 */ \
+ punpckhqdq_r2r(xmm4, xmm1); /* xmm1=h1g1g1e1d1c1b1a1 */ \
+ \
+ movdqu_r2m(xmm0, *I(0)); /* save I(0) */ \
+ movdqu_r2m(xmm1, *I(1)); /* save I(1) */ \
+ \
+ movdqu_m2r(*I(6), xmm0); /* load h3g3g3e3h2g2f2e2 */ \
+ movdqu_r2r(xmm3, xmm1); /* make a copy */ \
+ \
+ punpcklqdq_r2r(xmm0, xmm1); /* xmm1=h2g2f2e2d2c2b2a2 */ \
+ punpckhqdq_r2r(xmm0, xmm3); /* xmm3=h3g3f3e3d3c3b3a3 */ \
+ \
+ movdqu_r2r(xmm2, xmm4); /* make a copy */ \
+ punpcklqdq_r2r(xmm5, xmm4); /* xmm4=h4g4f4e4d4c4b4a4 */ \
+ \
+ punpckhqdq_r2r(xmm5, xmm2); /* xmm2=h5g5f5e5d5c5b5a5 */ \
+ movdqu_r2m(xmm1, *I(2)); /* save I(2) */ \
+ \
+ movdqu_r2m(xmm3, *I(3)); /* save I(3) */ \
+ movdqu_r2m(xmm4, *I(4)); /* save I(4) */ \
+ \
+ movdqu_r2m(xmm2, *I(5)); /* save I(5) */ \
+ movdqu_r2r(xmm7, xmm5); /* make a copy */ \
+ \
+ punpcklqdq_r2r(xmm6, xmm5); /* xmm5=h6g6f6e6d6c6b6a6 */ \
+ punpckhqdq_r2r(xmm6, xmm7); /* xmm7=h7g7f7e7d7c7b7a7 */ \
+ \
+ movdqu_r2m(xmm5, *I(6)); /* save I(6) */ \
+ movdqu_r2m(xmm7, *I(7)); /* save I(7) */ \
+ \
+} /* End of Transpose Macro */
+
+
+#define SSE2_Dequantize() { \
+ movdqu_m2r(*(eax), xmm0); \
+ \
+ pmullw_m2r(*(ebx), xmm0); /* xmm0 = 07 06 05 04 03 02 01 00 */ \
+ movdqu_m2r(*(eax + 16), xmm1); \
+ \
+ pmullw_m2r(*(ebx + 16), xmm1); /* xmm1 = 17 16 15 14 13 12 11 10 */ \
+ pshuflw_r2r(xmm0, xmm3, 0x078); /* xmm3 = 07 06 05 04 01 03 02 00 */ \
+ \
+ movdqu_r2r(xmm1, xmm2); /* xmm2 = 17 16 15 14 13 12 11 10 */ \
+ movdqu_m2r(*(ecx), xmm7); /* xmm7 = -- -- -- -- -- FF FF -- */ \
+ \
+ movdqu_m2r(*(eax + 32), xmm4); \
+ movdqu_m2r(*(eax + 64), xmm5); \
+ \
+ pmullw_m2r(*(ebx + 32), xmm4); /* xmm4 = 27 26 25 24 23 22 21 20 */ \
+ pmullw_m2r(*(ebx + 64), xmm5); /* xmm5 = 47 46 45 44 43 42 41 40 */ \
+ \
+ movdqu_m2r(*(ecx + 16), xmm6); /* xmm6 = -- -- FF FF -- -- -- -- */ \
+ pand_r2r(xmm2, xmm7); /* xmm7 = -- -- -- -- -- 12 11 -- */ \
+ \
+ pand_r2r(xmm4, xmm6); /* xmm6 = -- -- 25 24 -- -- -- -- */ \
+ pxor_r2r(xmm7, xmm2); /* xmm2 = 17 16 15 14 13 -- -- 10 */ \
+ \
+ pxor_r2r(xmm6, xmm4); /* xmm4 = 27 26 -- -- 23 22 21 20 */ \
+ pslldq_i2r(4, xmm7); /* xmm7 = -- -- -- 12 11 -- -- -- */ \
+ \
+ pslldq_i2r(2, xmm6); /* xmm6 = -- 25 24 -- -- -- -- -- */ \
+ por_r2r(xmm6, xmm7); /* xmm7 = -- 25 24 12 11 -- -- -- */ \
+ \
+ movdqu_m2r(*(ecx + 32), xmm0); /* xmm0 = -- -- -- -- -- FF FF FF */ \
+ movdqu_m2r(*(ecx + 48), xmm6); /* xmm6 = -- -- -- -- FF -- -- -- */ \
+ \
+ pand_r2r(xmm3, xmm0); /* xmm0 = -- -- -- -- -- 03 02 00 */ \
+ pand_r2r(xmm5, xmm6); /* xmm6 = -- -- -- -- 43 -- -- -- */ \
+ \
+ pxor_r2r(xmm0, xmm3); /* xmm3 = 07 06 05 04 01 -- -- -- */ \
+ pxor_r2r(xmm6, xmm5); /* xmm5 = 47 46 45 44 -- 42 41 40 */ \
+ \
+ por_r2r(xmm7, xmm0); /* xmm0 = -- 25 24 12 11 03 02 00 */ \
+ pslldq_i2r(8, xmm6); /* xmm6 = 43 -- -- -- -- -- -- -- */ \
+ \
+ por_r2r(xmm6, xmm0); /* xmm0 = 43 25 24 12 11 03 02 00 */ \
+ /* 02345 in use */ \
+ \
+ movdqu_m2r(*(ecx + 64 ), xmm1); /* xmm1 = -- -- -- FF FF -- -- -- */ \
+ pshuflw_r2r(xmm5, xmm5, 0x0B4); /* xmm5 = 47 46 45 44 42 -- 41 40 */ \
+ \
+ movdqu_r2r(xmm1, xmm7); /* xmm7 = -- -- -- FF FF -- -- -- */ \
+ movdqu_r2r(xmm1, xmm6); /* xmm6 = -- -- -- FF FF -- -- -- */ \
+ \
+ movdqu_r2m(xmm0, *(eax)); /* write 43 25 24 12 11 03 02 00 */ \
+ pshufhw_r2r(xmm4, xmm4, 0x0C2); /* xmm4 = 27 -- -- 26 23 22 21 20 */ \
+ \
+ pand_r2r(xmm4, xmm7); /* xmm7 = -- -- -- 26 23 -- -- -- */ \
+ pand_r2r(xmm5, xmm1); /* xmm1 = -- -- -- 44 42 -- -- -- */ \
+ \
+ pxor_r2r(xmm7, xmm4); /* xmm4 = 27 -- -- -- -- 22 21 20 */ \
+ pxor_r2r(xmm1, xmm5); /* xmm5 = 47 46 45 -- -- -- 41 40 */ \
+ \
+ pshuflw_r2r(xmm2, xmm2, 0x0C6); /* xmm2 = 17 16 15 14 13 10 -- -- */ \
+ movdqu_r2r(xmm6, xmm0); /* xmm0 = -- -- -- FF FF -- -- -- */ \
+ \
+ pslldq_i2r(2, xmm7); /* xmm7 = -- -- 26 23 -- -- -- -- */ \
+ pslldq_i2r(6, xmm1); /* xmm1 = 44 42 -- -- -- -- -- -- */ \
+ \
+ psrldq_i2r(2, xmm0); /* xmm0 = -- -- -- -- FF FF -- -- */ \
+ pand_r2r(xmm3, xmm6); /* xmm6 = -- -- -- 04 01 -- -- -- */ \
+ \
+ pand_r2r(xmm2, xmm0); /* xmm0 = -- -- -- -- 13 10 -- -- */ \
+ pxor_r2r(xmm6, xmm3); /* xmm3 = 07 06 05 -- -- -- -- -- */ \
+ \
+ pxor_r2r(xmm0, xmm2); /* xmm2 = 17 16 15 14 -- -- -- -- */ \
+ psrldq_i2r(6, xmm6); /* xmm0 = -- -- -- -- -- -- 04 01 */ \
+ \
+ por_r2r(xmm7, xmm1); /* xmm1 = 44 42 26 23 -- -- -- -- */ \
+ por_r2r(xmm6, xmm0); /* xmm1 = -- -- -- -- 13 10 04 01 */ \
+ /* 12345 in use */ \
+ por_r2r(xmm0, xmm1); /* xmm1 = 44 42 26 23 13 10 04 01 */ \
+ pshuflw_r2r(xmm4, xmm4, 0x093); /* xmm4 = 27 -- -- -- 22 21 20 -- */ \
+ \
+ pshufhw_r2r(xmm4, xmm4, 0x093); /* xmm4 = -- -- -- 27 22 21 20 -- */ \
+ movdqu_r2m(xmm1, *(eax + 16)); /* write 44 42 26 23 13 10 04 01 */ \
+ \
+ pshufhw_r2r(xmm3, xmm3, 0x0D2); /* xmm3 = 07 05 -- 06 -- -- -- -- */ \
+ movdqu_m2r(*(ecx + 64), xmm0); /* xmm0 = -- -- -- FF FF -- -- -- */ \
+ \
+ pand_r2r(xmm3, xmm0); /* xmm0 = -- -- -- 06 -- -- -- -- */ \
+ psrldq_i2r(12, xmm3); /* xmm3 = -- -- -- -- -- -- 07 05 */ \
+ \
+ psrldq_i2r(8, xmm0); /* xmm0 = -- -- -- -- -- -- -- 06 */ \
+ \
+ movdqu_m2r(*(ecx + 64), xmm6); /* xmm6 = -- -- -- FF FF -- -- -- */ \
+ movdqu_m2r(*(ecx + 96), xmm7); /* xmm7 = -- -- -- -- FF FF -- -- */ \
+ \
+ pand_r2r(xmm4, xmm6); /* xmm6 = -- -- -- 27 22 -- -- -- */ \
+ pxor_r2r(xmm6, xmm4); /* xmm4 = -- -- -- -- -- 21 20 -- */ \
+ \
+ por_r2r(xmm6, xmm3); /* xmm3 = -- -- -- 27 22 -- 07 05 */ \
+ pand_r2r(xmm4, xmm7); /* xmm7 = -- -- -- -- -- 21 -- -- */ \
+ \
+ por_r2r(xmm7, xmm0); /* xmm0 = -- -- -- -- -- 21 -- 06 */ \
+ pxor_r2r(xmm7, xmm4); /* xmm4 = -- -- -- -- -- -- 20 -- */ \
+ \
+ movdqu_m2r(*(ecx + 16 ), xmm6); /* xmm6 = -- -- FF FF -- -- -- -- */ \
+ movdqu_m2r(*(ecx + 64 ), xmm1); /* xmm1 = -- -- -- FF FF -- -- -- */ \
+ \
+ pand_r2r(xmm2, xmm6); /* xmm6 = -- -- 15 14 -- -- -- -- */ \
+ pand_r2r(xmm6, xmm1); /* xmm1 = -- -- -- 14 -- -- -- -- */ \
+ \
+ pxor_r2r(xmm6, xmm2); /* xmm2 = 17 16 -- -- -- -- -- -- */ \
+ pxor_r2r(xmm1, xmm6); /* xmm6 = -- -- 15 -- -- -- -- -- */ \
+ \
+ psrldq_i2r(4, xmm1); /* xmm1 = -- -- -- -- -- 14 -- -- */ \
+ \
+ psrldq_i2r(8, xmm6); /* xmm6 = -- -- -- -- -- -- 15 -- */ \
+ por_r2r(xmm1, xmm3); /* xmm3 = -- -- -- 27 22 14 07 05 */ \
+ \
+ por_r2r(xmm6, xmm0); /* xmm0 = -- -- -- -- -- 21 15 06 */ \
+ pshufhw_r2r(xmm5, xmm5, 0x0E1); /* xmm5 = 47 46 -- 45 -- -- 41 40 */ \
+ \
+ movdqu_m2r(*(ecx + 64), xmm1); /* xmm1 = -- -- -- FF FF -- -- -- */ \
+ pshuflw_r2r(xmm5, xmm5, 0x072); /* xmm5 = 47 46 -- 45 41 -- 40 -- */ \
+ \
+ movdqu_r2r(xmm1, xmm6); /* xmm6 = -- -- -- FF FF -- -- -- */ \
+ pand_r2r(xmm5, xmm1); /* xmm1 = -- -- -- 45 41 -- -- -- */ \
+ \
+ pxor_r2r(xmm1, xmm5); /* xmm5 = 47 46 -- -- -- -- 40 -- */ \
+ pslldq_i2r(4, xmm1); /* xmm1 = -- 45 41 -- -- -- -- -- */ \
+ \
+ pshufd_r2r(xmm5, xmm5, 0x09C); /* xmm5 = -- -- -- -- 47 46 40 -- */ \
+ por_r2r(xmm1, xmm3); /* xmm3 = -- 45 41 27 22 14 07 05 */ \
+ \
+ movdqu_m2r(*(eax + 96), xmm1); /* xmm1 = 67 66 65 64 63 62 61 60 */ \
+ pmullw_m2r(*(ebx + 96), xmm1); \
+ \
+ movdqu_m2r(*(ecx), xmm7); /* xmm7 = -- -- -- -- -- FF FF -- */ \
+ \
+ psrldq_i2r(8, xmm6); /* xmm6 = -- -- -- -- -- -- -- FF */ \
+ pand_r2r(xmm5, xmm7); /* xmm7 = -- -- -- -- -- 46 40 -- */ \
+ \
+ pand_r2r(xmm1, xmm6); /* xmm6 = -- -- -- -- -- -- -- 60 */ \
+ pxor_r2r(xmm7, xmm5); /* xmm5 = -- -- -- -- 47 -- -- -- */ \
+ \
+ pxor_r2r(xmm6, xmm1); /* xmm1 = 67 66 65 64 63 62 61 -- */ \
+ pslldq_i2r(2, xmm5); /* xmm5 = -- -- -- 47 -- -- -- -- */ \
+ \
+ pslldq_i2r(14, xmm6); /* xmm6 = 60 -- -- -- -- -- -- -- */ \
+ por_r2r(xmm5, xmm4); /* xmm4 = -- -- -- 47 -- -- 20 -- */ \
+ \
+ por_r2r(xmm6, xmm3); /* xmm3 = 60 45 41 27 22 14 07 05 */ \
+ pslldq_i2r(6, xmm7); /* xmm7 = -- -- 46 40 -- -- -- -- */ \
+ \
+ movdqu_r2m(xmm3, *(eax+32)); /* write 60 45 41 27 22 14 07 05 */ \
+ por_r2r(xmm7, xmm0); /* xmm0 = -- -- 46 40 -- 21 15 06 */ \
+ /* 0, 1, 2, 4 in use */ \
+ movdqu_m2r(*(eax + 48), xmm3); /* xmm3 = 37 36 35 34 33 32 31 30 */ \
+ movdqu_m2r(*(eax + 80), xmm5); /* xmm5 = 57 56 55 54 53 52 51 50 */ \
+ \
+ pmullw_m2r(*(ebx + 48), xmm3); \
+ pmullw_m2r(*(ebx + 80), xmm5); \
+ \
+ movdqu_m2r(*(ecx + 64), xmm6); /* xmm6 = -- -- -- FF FF -- -- -- */ \
+ movdqu_m2r(*(ecx + 64), xmm7); /* xmm7 = -- -- -- FF FF -- -- -- */ \
+ \
+ psrldq_i2r(8, xmm6); /* xmm6 = -- -- -- -- -- -- -- FF */ \
+ pslldq_i2r(8, xmm7); /* xmm7 = FF -- -- -- -- -- -- -- */ \
+ \
+ pand_r2r(xmm3, xmm6); /* xmm6 = -- -- -- -- -- -- -- 30 */ \
+ pand_r2r(xmm5, xmm7); /* xmm7 = 57 -- -- -- -- -- -- -- */ \
+ \
+ pxor_r2r(xmm6, xmm3); /* xmm3 = 37 36 35 34 33 32 31 -- */ \
+ pxor_r2r(xmm7, xmm5); /* xmm5 = __ 56 55 54 53 52 51 50 */ \
+ \
+ pslldq_i2r(6, xmm6); /* xmm6 = -- -- -- -- 30 -- -- -- */ \
+ psrldq_i2r(2, xmm7); /* xmm7 = -- 57 -- -- -- -- -- -- */ \
+ \
+ por_r2r(xmm7, xmm6); /* xmm6 = -- 57 -- -- 30 -- -- -- */ \
+ movdqu_m2r(*(ecx), xmm7); /* xmm7 = -- -- -- -- -- FF FF -- */ \
+ \
+ por_r2r(xmm6, xmm0); /* xmm0 = -- 57 46 40 30 21 15 06 */ \
+ psrldq_i2r(2, xmm7); /* xmm7 = -- -- -- -- -- -- FF FF */ \
+ \
+ movdqu_r2r(xmm2, xmm6); /* xmm6 = 17 16 -- -- -- -- -- -- */ \
+ pand_r2r(xmm1, xmm7); /* xmm7 = -- -- -- -- -- -- 61 -- */ \
+ \
+ pslldq_i2r(2, xmm6); /* xmm6 = 16 -- -- -- -- -- -- -- */ \
+ psrldq_i2r(14, xmm2); /* xmm2 = -- -- -- -- -- -- -- 17 */ \
+ \
+ pxor_r2r(xmm7, xmm1); /* xmm1 = 67 66 65 64 63 62 -- -- */ \
+ pslldq_i2r(12, xmm7); /* xmm7 = 61 -- -- -- -- -- -- -- */ \
+ \
+ psrldq_i2r(14, xmm6); /* xmm6 = -- -- -- -- -- -- -- 16 */ \
+ por_r2r(xmm6, xmm4); /* xmm4 = -- -- -- 47 -- -- 20 16 */ \
+ \
+ por_r2r(xmm7, xmm0); /* xmm0 = 61 57 46 40 30 21 15 06 */ \
+ movdqu_m2r(*(ecx), xmm6); /* xmm6 = -- -- -- -- -- FF FF -- */ \
+ \
+ psrldq_i2r(2, xmm6); /* xmm6 = -- -- -- -- -- -- FF FF */ \
+ movdqu_r2m(xmm0, *(eax+48)); /* write 61 57 46 40 30 21 15 06 */ \
+ /* 1, 2, 3, 4, 5 in use */\
+ movdqu_m2r(*(ecx), xmm0); /* xmm0 = -- -- -- -- -- FF FF -- */ \
+ pand_r2r(xmm3, xmm6); /* xmm6 = -- -- -- -- -- -- 31 -- */ \
+ \
+ movdqu_r2r(xmm3, xmm7); /* xmm7 = 37 36 35 34 33 32 31 -- */ \
+ pxor_r2r(xmm6, xmm3); /* xmm3 = 37 36 35 34 33 32 -- -- */ \
+ \
+ pslldq_i2r(2, xmm3); /* xmm3 = 36 35 34 33 32 -- -- -- */ \
+ pand_r2r(xmm1, xmm0); /* xmm0 = -- -- -- -- -- 62 -- -- */ \
+ \
+ psrldq_i2r(14, xmm7); /* xmm7 = -- -- -- -- -- -- -- 37 */ \
+ pxor_r2r(xmm0, xmm1); /* xmm1 = 67 66 65 64 63 -- -- -- */ \
+ \
+ por_r2r(xmm7, xmm6); /* xmm6 = -- -- -- -- -- -- 31 37 */ \
+ movdqu_m2r(*(ecx + 64), xmm7); /* xmm7 = -- -- -- FF FF -- -- -- */ \
+ \
+ pshuflw_r2r(xmm6, xmm6, 0x01E); /* xmm6 = -- -- -- -- 37 31 -- -- */ \
+ pslldq_i2r(6, xmm7); /* xmm7 = FF FF -- -- -- -- -- -- */ \
+ \
+ por_r2r(xmm6, xmm4); /* xmm4 = -- -- -- 47 37 31 20 16 */ \
+ pand_r2r(xmm5, xmm7); /* xmm7 = -- 56 -- -- -- -- -- -- */ \
+ \
+ pslldq_i2r(8, xmm0); /* xmm0 = -- 62 -- -- -- -- -- -- */ \
+ pxor_r2r(xmm7, xmm5); /* xmm5 = -- -- 55 54 53 52 51 50 */ \
+ \
+ psrldq_i2r(2, xmm7); /* xmm7 = -- -- 56 -- -- -- -- -- */ \
+ \
+ pshufhw_r2r(xmm3, xmm3, 0x087); /* xmm3 = 35 33 34 36 32 -- -- -- */ \
+ por_r2r(xmm7, xmm0); /* xmm0 = -- 62 56 -- -- -- -- -- */ \
+ \
+ movdqu_m2r(*(eax + 112), xmm7); /* xmm7 = 77 76 75 74 73 72 71 70 */ \
+ pmullw_m2r(*(ebx + 112), xmm7); \
+ \
+ movdqu_m2r(*(ecx + 64), xmm6); /* xmm6 = -- -- -- FF FF -- -- -- */ \
+ por_r2r(xmm0, xmm4); /* xmm4 = -- 62 56 47 37 31 20 16 */ \
+ \
+ pshuflw_r2r(xmm7, xmm7, 0x0E1); /* xmm7 = 77 76 75 74 73 72 70 71 */ \
+ psrldq_i2r(8, xmm6); /* xmm6 = -- -- -- -- -- -- -- FF */ \
+ \
+ movdqu_m2r(*(ecx + 64), xmm0); /* xmm0 = -- -- -- FF FF -- -- -- */ \
+ pand_r2r(xmm7, xmm6); /* xmm6 = -- -- -- -- -- -- -- 71 */ \
+ \
+ pand_r2r(xmm3, xmm0); /* xmm0 = -- -- -- 36 32 -- -- -- */ \
+ pxor_r2r(xmm6, xmm7); /* xmm7 = 77 76 75 74 73 72 70 -- */ \
+ \
+ pxor_r2r(xmm0, xmm3); /* xmm3 = 35 33 34 -- -- -- -- -- */ \
+ pslldq_i2r(14, xmm6); /* xmm6 = 71 -- -- -- -- -- -- -- */ \
+ \
+ psrldq_i2r(4, xmm0); /* xmm0 = -- -- -- -- -- 36 32 -- */ \
+ por_r2r(xmm6, xmm4); /* xmm4 = 71 62 56 47 37 31 20 16 */ \
+ \
+ por_r2r(xmm0, xmm2); /* xmm2 = -- -- -- -- -- 36 32 17 */ \
+ movdqu_r2m(xmm4, *(eax + 64)); /* write 71 62 56 47 37 31 20 16 */ \
+ /* 1, 2, 3, 5, 7 in use */ \
+ movdqu_m2r(*(ecx + 80), xmm6); /* xmm6 = -- -- FF -- -- -- -- FF */ \
+ pshufhw_r2r(xmm7, xmm7, 0x0D2); /* xmm7 = 77 75 74 76 73 72 70 __ */ \
+ \
+ movdqu_m2r(*(ecx), xmm4); /* xmm4 = -- -- -- -- -- FF FF -- */ \
+ movdqu_m2r(*(ecx+48), xmm0); /* xmm0 = -- -- -- -- FF -- -- -- */ \
+ \
+ pand_r2r(xmm5, xmm6); /* xmm6 = -- -- 55 -- -- -- -- 50 */ \
+ pand_r2r(xmm7, xmm4); /* xmm4 = -- -- -- -- -- 72 70 -- */ \
+ \
+ pand_r2r(xmm1, xmm0); /* xmm0 = -- -- -- -- 63 -- -- -- */ \
+ pxor_r2r(xmm6, xmm5); /* xmm5 = -- -- -- 54 53 52 51 -- */ \
+ \
+ pxor_r2r(xmm4, xmm7); /* xmm7 = 77 75 74 76 73 -- -- -- */ \
+ pxor_r2r(xmm0, xmm1); /* xmm1 = 67 66 65 64 -- -- -- -- */ \
+ \
+ pshuflw_r2r(xmm6, xmm6, 0x02B); /* xmm6 = -- -- 55 -- 50 -- -- -- */ \
+ pslldq_i2r(10, xmm4); /* xmm4 = 72 20 -- -- -- -- -- -- */ \
+ \
+ pshufhw_r2r(xmm6, xmm6, 0x0B1); /* xmm6 = -- -- -- 55 50 -- -- -- */ \
+ pslldq_i2r(4, xmm0); /* xmm0 = -- -- 63 -- -- -- -- -- */ \
+ \
+ por_r2r(xmm4, xmm6); /* xmm6 = 72 70 -- 55 50 -- -- -- */ \
+ por_r2r(xmm0, xmm2); /* xmm2 = -- -- 63 -- -- 36 32 17 */ \
+ \
+ por_r2r(xmm6, xmm2); /* xmm2 = 72 70 64 55 50 36 32 17 */ \
+ pshufhw_r2r(xmm1, xmm1, 0x0C9); /* xmm1 = 67 64 66 65 -- -- -- -- */ \
+ \
+ movdqu_r2r(xmm3, xmm6); /* xmm6 = 35 33 34 -- -- -- -- -- */ \
+ movdqu_r2m(xmm2, *(eax+80)); /* write 72 70 64 55 50 36 32 17 */ \
+ \
+ psrldq_i2r(12, xmm6); /* xmm6 = -- -- -- -- -- -- 35 33 */ \
+ pslldq_i2r(4, xmm3); /* xmm3 = 34 -- -- -- -- -- -- -- */ \
+ \
+ pshuflw_r2r(xmm5, xmm5, 0x04E); /* xmm5 = -- -- -- 54 51 -- 53 52 */ \
+ movdqu_r2r(xmm7, xmm4); /* xmm4 = 77 75 74 76 73 -- -- -- */ \
+ \
+ movdqu_r2r(xmm5, xmm2); /* xmm2 = -- -- -- 54 51 -- 53 52 */ \
+ psrldq_i2r(10, xmm7); /* xmm7 = -- -- -- -- -- 77 75 74 */ \
+ \
+ pslldq_i2r(6, xmm4); /* xmm4 = 76 73 -- -- -- -- -- -- */ \
+ pslldq_i2r(12, xmm2); /* xmm2 = 53 52 -- -- -- -- -- -- */ \
+ \
+ movdqu_r2r(xmm1, xmm0); /* xmm0 = 67 64 66 65 -- -- -- -- */ \
+ psrldq_i2r(12, xmm1); /* xmm1 = -- -- -- -- -- -- 67 64 */ \
+ \
+ psrldq_i2r(6, xmm5); /* xmm5 = -- -- -- -- -- -- 54 51 */ \
+ psrldq_i2r(14, xmm3); /* xmm3 = -- -- -- -- -- -- -- 34 */ \
+ \
+ pslldq_i2r(10, xmm7); /* xmm7 = 77 75 74 -- -- -- -- -- */ \
+ por_r2r(xmm6, xmm4); /* xmm4 = 76 73 -- -- -- -- 35 33 */ \
+ \
+ psrldq_i2r(10, xmm2); /* xmm2 = -- -- -- -- -- 53 52 -- */ \
+ pslldq_i2r(4, xmm0); /* xmm0 = 66 65 -- -- -- -- -- -- */ \
+ \
+ pslldq_i2r(8, xmm1); /* xmm1 = -- -- 67 64 -- -- -- -- */ \
+ por_r2r(xmm7, xmm3); /* xmm3 = 77 75 74 -- -- -- -- 34 */ \
+ \
+ psrldq_i2r(6, xmm0); /* xmm0 = -- -- -- 66 65 -- -- -- */ \
+ pslldq_i2r(4, xmm5); /* xmm5 = -- -- -- -- 54 51 -- -- */ \
+ \
+ por_r2r(xmm1, xmm4); /* xmm4 = 76 73 67 64 -- -- 35 33 */ \
+ por_r2r(xmm2, xmm3); /* xmm3 = 77 75 74 -- -- 53 52 34 */ \
+ \
+ por_r2r(xmm5, xmm4); /* xmm4 = 76 73 67 64 54 51 35 33 */ \
+ por_r2r(xmm0, xmm3); /* xmm3 = 77 75 74 66 65 53 52 34 */ \
+ \
+ movdqu_r2m(xmm4, *(eax+96)); /* write 76 73 67 64 54 51 35 33 */ \
+ movdqu_r2m(xmm3, *(eax+112)); /* write 77 75 74 66 65 53 52 34 */ \
+ \
+} /* end of SSE2_Dequantize Macro */
+
+
+void ff_vp3_idct_sse2(int16_t *input_data)
+{
+ unsigned char *input_bytes = (unsigned char *)input_data;
+ unsigned char *output_data_bytes = (unsigned char *)input_data;
+ unsigned char *idct_data_bytes = (unsigned char *)SSE2_idct_data;
+ unsigned char *Eight = (unsigned char *)eight_data;
+
+#define eax input_bytes
+//#define ebx dequant_matrix_bytes
+#define ecx dequant_const_bytes
+#define edx idct_data_bytes
+
+#define I(i) (eax + 16 * i)
+#define O(i) (ebx + 16 * i)
+#define C(i) (edx + 16 * (i-1))
+
+ // SSE2_Dequantize();
+
+#undef ebx
+#define ebx output_data_bytes
+
+ SSE2_Row_IDCT();
+
+ SSE2_Transpose();
+
+ SSE2_Column_IDCT();
+}
diff --git a/contrib/ffmpeg/libavcodec/idcinvideo.c b/contrib/ffmpeg/libavcodec/idcinvideo.c
new file mode 100644
index 000000000..112da7bc6
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/idcinvideo.c
@@ -0,0 +1,272 @@
+/*
+ * 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 idcinvideo.c
+ * 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 ffmpeg'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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.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_t;
+
+typedef struct IdcinContext {
+
+ AVCodecContext *avctx;
+ DSPContext dsp;
+ AVFrame frame;
+
+ unsigned char *buf;
+ int size;
+
+ hnode_t huff_nodes[256][HUF_TOKENS*2];
+ int num_huff_nodes[256];
+
+} IdcinContext;
+
+/*
+ * Find the lowest probability node in a Huffman table, and mark it as
+ * being assigned to a higher probability.
+ * Returns the node index of the lowest unused node, or -1 if all nodes
+ * are used.
+ */
+static int huff_smallest_node(hnode_t *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 void huff_build_tree(IdcinContext *s, int prev) {
+ hnode_t *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 int idcin_decode_init(AVCodecContext *avctx)
+{
+ IdcinContext *s = (IdcinContext *)avctx->priv_data;
+ int i, j, histogram_index = 0;
+ unsigned char *histograms;
+
+ s->avctx = avctx;
+ avctx->pix_fmt = PIX_FMT_PAL8;
+ avctx->has_b_frames = 0;
+ dsputil_init(&s->dsp, avctx);
+
+ /* 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);
+ }
+
+ s->frame.data[0] = NULL;
+
+ return 0;
+}
+
+static void idcin_decode_vlcs(IdcinContext *s)
+{
+ hnode_t *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 < (s->frame.linesize[0] * s->avctx->height);
+ y += s->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;
+ }
+ bit_pos = 8;
+ v = s->buf[dat_pos++];
+ }
+
+ node_num = hnodes[node_num].children[v & 0x01];
+ v = v >> 1;
+ bit_pos--;
+ }
+
+ s->frame.data[0][x] = node_num;
+ prev = node_num;
+ }
+ }
+}
+
+static int idcin_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ IdcinContext *s = (IdcinContext *)avctx->priv_data;
+ AVPaletteControl *palette_control = avctx->palctrl;
+
+ s->buf = buf;
+ s->size = buf_size;
+
+ if (s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ if (avctx->get_buffer(avctx, &s->frame)) {
+ av_log(avctx, AV_LOG_ERROR, " Id CIN Video: get_buffer() failed\n");
+ return -1;
+ }
+
+ idcin_decode_vlcs(s);
+
+ /* make the palette available on the way out */
+ memcpy(s->frame.data[1], palette_control->palette, PALETTE_COUNT * 4);
+ /* If palette changed inform application*/
+ if (palette_control->palette_changed) {
+ palette_control->palette_changed = 0;
+ s->frame.palette_has_changed = 1;
+ }
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = s->frame;
+
+ /* report that the buffer was completely consumed */
+ return buf_size;
+}
+
+static int idcin_decode_end(AVCodecContext *avctx)
+{
+ IdcinContext *s = (IdcinContext *)avctx->priv_data;
+
+ if (s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ return 0;
+}
+
+AVCodec idcin_decoder = {
+ "idcinvideo",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_IDCIN,
+ sizeof(IdcinContext),
+ idcin_decode_init,
+ NULL,
+ idcin_decode_end,
+ idcin_decode_frame,
+ CODEC_CAP_DR1,
+};
+
diff --git a/contrib/ffmpeg/libavcodec/imc.c b/contrib/ffmpeg/libavcodec/imc.c
new file mode 100644
index 000000000..7360b6409
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/imc.c
@@ -0,0 +1,813 @@
+/*
+ * 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.c IMC - Intel Music Coder
+ * A mdct based codec using a 256 points large transform
+ * divied into 32 bands with some mix of scale factors.
+ * Only mono is supported.
+ *
+ */
+
+
+#include <math.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#define ALT_BITSTREAM_READER
+#include "avcodec.h"
+#include "bitstream.h"
+#include "dsputil.h"
+
+#include "imcdata.h"
+
+#define IMC_FRAME_ID 0x21
+#define BANDS 32
+#define COEFFS 256
+
+typedef struct {
+ 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];
+
+ /** MDCT tables */
+ //@{
+ float mdct_sine_window[COEFFS];
+ float post_cos[COEFFS];
+ float post_sin[COEFFS];
+ float pre_coef1[COEFFS];
+ float pre_coef2[COEFFS];
+ float last_fft_im[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 sqrt_tab[30];
+ GetBitContext gb;
+ VLC huffman_vlc[4][4];
+ int decoder_reset;
+ float one_div_log2;
+
+ DSPContext dsp;
+ FFTContext fft;
+ DECLARE_ALIGNED_16(FFTComplex, samples[COEFFS/2]);
+ DECLARE_ALIGNED_16(float, out_samples[COEFFS]);
+} IMCContext;
+
+
+static int imc_decode_init(AVCodecContext * avctx)
+{
+ int i, j;
+ IMCContext *q = avctx->priv_data;
+ double r1, r2;
+
+ q->decoder_reset = 1;
+
+ for(i = 0; i < BANDS; i++)
+ q->old_floor[i] = 1.0;
+
+ /* Build mdct window, a simple sine window normalized with sqrt(2) */
+ for(i = 0; i < COEFFS; i++)
+ q->mdct_sine_window[i] = sin((i + 0.5) / 512.0 * M_PI) * sqrt(2.0);
+ for(i = 0; i < COEFFS/2; i++){
+ q->post_cos[i] = cos(i / 256.0 * M_PI);
+ q->post_sin[i] = 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);
+ }
+
+ q->last_fft_im[i] = 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++) {
+ init_vlc (&q->huffman_vlc[i][j], 9, imc_huffman_sizes[i],
+ imc_huffman_lens[i][j], 1, 1,
+ imc_huffman_bits[i][j], 2, 2, 1);
+ }
+ }
+ q->one_div_log2 = 1/log(2);
+
+ ff_fft_init(&q->fft, 7, 1);
+ dsputil_init(&q->dsp, avctx);
+ 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 < 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) * imc_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 > 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) * imc_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] = &q->huffman_vlc[s][0];
+ hufftab[1] = &q->huffman_vlc[s][1];
+ hufftab[2] = &q->huffman_vlc[s][2];
+ hufftab[3] = &q->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 / pow (2, levlCoeffBuf[0] * 0.18945); // 0.18945 = log2(10) * 0.05703125
+ flcoeffs2[0] = log(flcoeffs1[0])/log(2);
+ 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, 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, q->flcoeffs1[i]);
+
+ for(i = 0; i < BANDS-1; i++) {
+ q->flcoeffs4[i] = q->flcoeffs3[i] - log(q->flcoeffs5[i])/log(2);
+ }
+ q->flcoeffs4[BANDS - 1] = limit;
+
+ highest = highest * 0.25;
+
+ for(i = 0; i < BANDS; i++) {
+ indx = -1;
+ if ((band_tab[i+1] - band_tab[i]) == q->bandWidthT[i])
+ indx = 0;
+
+ if ((band_tab[i+1] - band_tab[i]) > q->bandWidthT[i])
+ indx = 1;
+
+ if (((band_tab[i+1] - band_tab[i])/2) >= q->bandWidthT[i])
+ indx = 2;
+
+ if (indx == -1)
+ return -1;
+
+ q->flcoeffs4[i] = q->flcoeffs4[i] + xTab[(indx*2 + (q->flcoeffs1[i] < highest)) * 2 + flag];
+ }
+
+ if (stream_format_code & 0x2) {
+ q->flcoeffs4[0] = limit;
+ q->flcoeffs4[1] = limit;
+ q->flcoeffs4[2] = limit;
+ q->flcoeffs4[3] = limit;
+ }
+
+ for(i = (stream_format_code & 0x2)?4:0; i < BANDS-1; i++) {
+ iacc += q->bandWidthT[i];
+ summa += q->bandWidthT[i] * q->flcoeffs4[i];
+ }
+ q->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 = clip((int)((q->flcoeffs4[j] * 0.5) - summa + 0.5), 0, 6);
+
+ q->bitsBandT[j] = cwlen;
+ summer += q->bandWidthT[j] * cwlen;
+
+ if (cwlen > 0)
+ iacc += q->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++)
+ q->CWlengthT[j] = q->bitsBandT[i];
+ }
+
+ if (freebits > summer) {
+ for(i = 0; i < BANDS; i++) {
+ workT[i] = (q->bitsBandT[i] == 6) ? -1.e20 : (q->bitsBandT[i] * -2 + q->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 (++(q->bitsBandT[found_indx]) == 6)
+ workT[found_indx] = -1.e20;
+
+ for(j = band_tab[found_indx]; j < band_tab[found_indx+1] && (freebits > summer); j++){
+ q->CWlengthT[j]++;
+ summer++;
+ }
+ }
+ }while (freebits > summer);
+ }
+ if (freebits < summer) {
+ for(i = 0; i < BANDS; i++) {
+ workT[i] = q->bitsBandT[i] ? (q->bitsBandT[i] * -2 + q->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 (!(--q->bitsBandT[low_indx]))
+ workT[low_indx] = 1.e20;
+
+ for(j = band_tab[low_indx]; j < band_tab[low_indx+1] && (freebits < summer); j++){
+ if(q->CWlengthT[j] > 0){
+ q->CWlengthT[j]--;
+ summer--;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static void imc_get_skip_coeff(IMCContext* q) {
+ int i, j;
+
+ memset(q->skipFlagBits, 0, sizeof(q->skipFlagBits));
+ memset(q->skipFlagCount, 0, sizeof(q->skipFlagCount));
+ for(i = 0; i < BANDS; i++) {
+ if (!q->bandFlagsBuf[i] || !q->bandWidthT[i])
+ continue;
+
+ if (!q->skipFlagRaw[i]) {
+ q->skipFlagBits[i] = band_tab[i+1] - band_tab[i];
+
+ for(j = band_tab[i]; j < band_tab[i+1]; j++) {
+ if ((q->skipFlags[j] = get_bits(&q->gb,1)))
+ q->skipFlagCount[i]++;
+ }
+ } else {
+ for(j = band_tab[i]; j < (band_tab[i+1]-1); j += 2) {
+ if(!get_bits1(&q->gb)){//0
+ q->skipFlagBits[i]++;
+ q->skipFlags[j]=1;
+ q->skipFlags[j+1]=1;
+ q->skipFlagCount[i] += 2;
+ }else{
+ if(get_bits1(&q->gb)){//11
+ q->skipFlagBits[i] +=2;
+ q->skipFlags[j]=0;
+ q->skipFlags[j+1]=1;
+ q->skipFlagCount[i]++;
+ }else{
+ q->skipFlagBits[i] +=3;
+ q->skipFlags[j+1]=0;
+ if(!get_bits1(&q->gb)){//100
+ q->skipFlags[j]=1;
+ q->skipFlagCount[i]++;
+ }else{//101
+ q->skipFlags[j]=0;
+ }
+ }
+ }
+ }
+
+ if (j < band_tab[i+1]) {
+ q->skipFlagBits[i]++;
+ if ((q->skipFlags[j] = get_bits(&q->gb,1)))
+ q->skipFlagCount[i]++;
+ }
+ }
+ }
+}
+
+/**
+ * Increase highest' band coefficient sizes as some bits won't be used
+ */
+static void imc_adjust_bit_allocation (IMCContext* q, 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] = (q->bitsBandT[i] == 6) ? -1.e20 : (q->bitsBandT[i] * -2 + q->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 (++(q->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 (!q->skipFlags[j] && (q->CWlengthT[j] < 6)) {
+ q->CWlengthT[j]++;
+ corrected++;
+ }
+ }
+ }
+ }
+}
+
+static void imc_imdct256(IMCContext *q) {
+ int i;
+ float re, im;
+
+ /* prerotation */
+ for(i=0; i < COEFFS/2; i++){
+ q->samples[i].re = -(q->pre_coef1[i] * q->CWdecoded[COEFFS-1-i*2]) -
+ (q->pre_coef2[i] * q->CWdecoded[i*2]);
+ q->samples[i].im = (q->pre_coef2[i] * q->CWdecoded[COEFFS-1-i*2]) -
+ (q->pre_coef1[i] * q->CWdecoded[i*2]);
+ }
+
+ /* FFT */
+ ff_fft_permute(&q->fft, q->samples);
+ ff_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]);
+ q->out_samples[i*2] = (q->mdct_sine_window[COEFFS-1-i*2] * q->last_fft_im[i]) + (q->mdct_sine_window[i*2] * re);
+ q->out_samples[COEFFS-1-i*2] = (q->mdct_sine_window[i*2] * q->last_fft_im[i]) - (q->mdct_sine_window[COEFFS-1-i*2] * re);
+ q->last_fft_im[i] = im;
+ }
+}
+
+static int inverse_quant_coeff (IMCContext* q, 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++) {
+ q->CWdecoded[j] = 0;
+ cw_len = q->CWlengthT[j];
+
+ if (cw_len <= 0 || q->skipFlags[j])
+ continue;
+
+ max_size = 1 << cw_len;
+ middle_value = max_size >> 1;
+
+ if (q->codewords[j] >= max_size || q->codewords[j] < 0)
+ return -1;
+
+ if (cw_len >= 4){
+ quantizer = imc_quantizer2[(stream_format_code & 2) >> 1];
+ if (q->codewords[j] >= middle_value)
+ q->CWdecoded[j] = quantizer[q->codewords[j] - 8] * q->flcoeffs6[i];
+ else
+ q->CWdecoded[j] = -quantizer[max_size - q->codewords[j] - 8 - 1] * q->flcoeffs6[i];
+ }else{
+ quantizer = imc_quantizer1[((stream_format_code & 2) >> 1) | (q->bandFlagsBuf[i] << 1)];
+ if (q->codewords[j] >= middle_value)
+ q->CWdecoded[j] = quantizer[q->codewords[j] - 1] * q->flcoeffs6[i];
+ else
+ q->CWdecoded[j] = -quantizer[max_size - 2 - q->codewords[j]] * q->flcoeffs6[i];
+ }
+ }
+ }
+ return 0;
+}
+
+
+static int imc_get_coeffs (IMCContext* q) {
+ int i, j, cw_len, cw;
+
+ for(i = 0; i < BANDS; i++) {
+ if(!q->sumLenArr[i]) continue;
+ if (q->bandFlagsBuf[i] || q->bandWidthT[i]) {
+ for(j = band_tab[i]; j < band_tab[i+1]; j++) {
+ cw_len = q->CWlengthT[j];
+ cw = 0;
+
+ if (get_bits_count(&q->gb) + cw_len > 512){
+//av_log(NULL,0,"Band %i coeff %i cw_len %i\n",i,j,cw_len);
+ return -1;
+ }
+
+ if(cw_len && (!q->bandFlagsBuf[i] || !q->skipFlags[j]))
+ cw = get_bits(&q->gb, cw_len);
+
+ q->codewords[j] = cw;
+ }
+ }
+ }
+ return 0;
+}
+
+static int imc_decode_frame(AVCodecContext * avctx,
+ void *data, int *data_size,
+ uint8_t * buf, int buf_size)
+{
+
+ IMCContext *q = avctx->priv_data;
+
+ int stream_format_code;
+ int imc_hdr, i, j;
+ int flag;
+ int bits, summer;
+ int counter, bitscount;
+ uint16_t *buf16 = (uint16_t *) buf;
+
+ /* FIXME: input should not be modified */
+ for(i = 0; i < FFMIN(buf_size, avctx->block_align) / 2; i++)
+ buf16[i] = bswap_16(buf16[i]);
+
+ init_get_bits(&q->gb, buf, 512);
+
+ /* Check the frame header */
+ imc_hdr = get_bits(&q->gb, 9);
+ if (imc_hdr != IMC_FRAME_ID) {
+ av_log(avctx, AV_LOG_ERROR, "imc frame header check failed!\n");
+ av_log(avctx, AV_LOG_ERROR, "got %x instead of 0x21.\n", imc_hdr);
+ return -1;
+ }
+ stream_format_code = get_bits(&q->gb, 3);
+
+ if(stream_format_code & 1){
+ av_log(avctx, AV_LOG_ERROR, "Stream code format %X is not supported\n", stream_format_code);
+ return -1;
+ }
+
+// av_log(avctx, AV_LOG_DEBUG, "stream_format_code = %d\n", stream_format_code);
+
+ if (stream_format_code & 0x04)
+ q->decoder_reset = 1;
+
+ if(q->decoder_reset) {
+ memset(q->out_samples, 0, sizeof(q->out_samples));
+ for(i = 0; i < BANDS; i++)q->old_floor[i] = 1.0;
+ for(i = 0; i < COEFFS; i++)q->CWdecoded[i] = 0;
+ q->decoder_reset = 0;
+ }
+
+ flag = get_bits1(&q->gb);
+ imc_read_level_coeffs(q, stream_format_code, q->levlCoeffBuf);
+
+ if (stream_format_code & 0x4)
+ imc_decode_level_coefficients(q, q->levlCoeffBuf, q->flcoeffs1, q->flcoeffs2);
+ else
+ imc_decode_level_coefficients2(q, q->levlCoeffBuf, q->old_floor, q->flcoeffs1, q->flcoeffs2);
+
+ memcpy(q->old_floor, q->flcoeffs1, 32 * sizeof(float));
+
+ counter = 0;
+ for (i=0 ; i<BANDS ; i++) {
+ if (q->levlCoeffBuf[i] == 16) {
+ q->bandWidthT[i] = 0;
+ counter++;
+ } else
+ q->bandWidthT[i] = band_tab[i+1] - band_tab[i];
+ }
+ memset(q->bandFlagsBuf, 0, BANDS * sizeof(int));
+ for(i = 0; i < BANDS-1; i++) {
+ if (q->bandWidthT[i])
+ q->bandFlagsBuf[i] = get_bits1(&q->gb);
+ }
+
+ imc_calculate_coeffs(q, q->flcoeffs1, q->flcoeffs2, q->bandWidthT, q->flcoeffs3, q->flcoeffs5);
+
+ bitscount = 0;
+ /* first 4 bands will be assigned 5 bits per coefficient */
+ if (stream_format_code & 0x2) {
+ bitscount += 15;
+
+ q->bitsBandT[0] = 5;
+ q->CWlengthT[0] = 5;
+ q->CWlengthT[1] = 5;
+ q->CWlengthT[2] = 5;
+ for(i = 1; i < 4; i++){
+ bits = (q->levlCoeffBuf[i] == 16) ? 0 : 5;
+ q->bitsBandT[i] = bits;
+ for(j = band_tab[i]; j < band_tab[i+1]; j++) {
+ q->CWlengthT[j] = bits;
+ bitscount += bits;
+ }
+ }
+ }
+
+ if(bit_allocation (q, stream_format_code, 512 - bitscount - get_bits_count(&q->gb), flag) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Bit allocations failed\n");
+ q->decoder_reset = 1;
+ return -1;
+ }
+
+ for(i = 0; i < BANDS; i++) {
+ q->sumLenArr[i] = 0;
+ q->skipFlagRaw[i] = 0;
+ for(j = band_tab[i]; j < band_tab[i+1]; j++)
+ q->sumLenArr[i] += q->CWlengthT[j];
+ if (q->bandFlagsBuf[i])
+ if( (((band_tab[i+1] - band_tab[i]) * 1.5) > q->sumLenArr[i]) && (q->sumLenArr[i] > 0))
+ q->skipFlagRaw[i] = 1;
+ }
+
+ imc_get_skip_coeff(q);
+
+ for(i = 0; i < BANDS; i++) {
+ q->flcoeffs6[i] = q->flcoeffs1[i];
+ /* band has flag set and at least one coded coefficient */
+ if (q->bandFlagsBuf[i] && (band_tab[i+1] - band_tab[i]) != q->skipFlagCount[i]){
+ q->flcoeffs6[i] *= q->sqrt_tab[band_tab[i+1] - band_tab[i]] /
+ q->sqrt_tab[(band_tab[i+1] - band_tab[i] - q->skipFlagCount[i])];
+ }
+ }
+
+ /* calculate bits left, bits needed and adjust bit allocation */
+ bits = summer = 0;
+
+ for(i = 0; i < BANDS; i++) {
+ if (q->bandFlagsBuf[i]) {
+ for(j = band_tab[i]; j < band_tab[i+1]; j++) {
+ if(q->skipFlags[j]) {
+ summer += q->CWlengthT[j];
+ q->CWlengthT[j] = 0;
+ }
+ }
+ bits += q->skipFlagBits[i];
+ summer -= q->skipFlagBits[i];
+ }
+ }
+ imc_adjust_bit_allocation(q, summer);
+
+ for(i = 0; i < BANDS; i++) {
+ q->sumLenArr[i] = 0;
+
+ for(j = band_tab[i]; j < band_tab[i+1]; j++)
+ if (!q->skipFlags[j])
+ q->sumLenArr[i] += q->CWlengthT[j];
+ }
+
+ memset(q->codewords, 0, sizeof(q->codewords));
+
+ if(imc_get_coeffs(q) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Read coefficients failed\n");
+ q->decoder_reset = 1;
+ return 0;
+ }
+
+ if(inverse_quant_coeff(q, stream_format_code) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Inverse quantization of coefficients failed\n");
+ q->decoder_reset = 1;
+ return 0;
+ }
+
+ memset(q->skipFlags, 0, sizeof(q->skipFlags));
+
+ imc_imdct256(q);
+
+ q->dsp.float_to_int16(data, q->out_samples, COEFFS);
+
+ *data_size = COEFFS * sizeof(int16_t);
+
+ return avctx->block_align;
+}
+
+
+static int imc_decode_close(AVCodecContext * avctx)
+{
+ IMCContext *q = avctx->priv_data;
+
+ ff_fft_end(&q->fft);
+ return 0;
+}
+
+
+AVCodec imc_decoder = {
+ .name = "imc",
+ .type = CODEC_TYPE_AUDIO,
+ .id = CODEC_ID_IMC,
+ .priv_data_size = sizeof(IMCContext),
+ .init = imc_decode_init,
+ .close = imc_decode_close,
+ .decode = imc_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/imcdata.h b/contrib/ffmpeg/libavcodec/imcdata.h
new file mode 100644
index 000000000..92ed275f1
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/imcdata.h
@@ -0,0 +1,164 @@
+/*
+ * 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
+ *
+ */
+
+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 *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 },
+ }
+};
+
diff --git a/contrib/ffmpeg/libavcodec/imgconvert.c b/contrib/ffmpeg/libavcodec/imgconvert.c
new file mode 100644
index 000000000..d5b4cdca0
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/imgconvert.c
@@ -0,0 +1,2842 @@
+/*
+ * Misc image convertion 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 imgconvert.c
+ * Misc image convertion 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"
+
+#ifdef USE_FASTMEMCPY
+#include "libvo/fastmemcpy.h"
+#endif
+
+#ifdef HAVE_MMX
+#include "i386/mmx.h"
+#endif
+
+#define xglue(x, y) x ## y
+#define glue(x, y) xglue(x, y)
+
+#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 */
+
+#define FF_PIXEL_PLANAR 0 /* each channel has one component in AVPicture */
+#define FF_PIXEL_PACKED 1 /* only one components containing all the channels */
+#define FF_PIXEL_PALETTE 2 /* one components containing indexes for a palette */
+
+typedef struct PixFmtInfo {
+ const char *name;
+ uint8_t nb_channels; /* number of channels (including alpha) */
+ uint8_t color_type; /* color type (see FF_COLOR_xxx constants) */
+ uint8_t pixel_type; /* pixel storage type (see FF_PIXEL_xxx constants) */
+ uint8_t is_alpha : 1; /* true if alpha can be specified */
+ uint8_t x_chroma_shift; /* X chroma subsampling factor is 2 ^ shift */
+ uint8_t y_chroma_shift; /* Y chroma subsampling factor is 2 ^ shift */
+ uint8_t depth; /* bit depth of the color components */
+} PixFmtInfo;
+
+/* this table gives more information about formats */
+static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
+ /* YUV formats */
+ [PIX_FMT_YUV420P] = {
+ .name = "yuv420p",
+ .nb_channels = 3,
+ .color_type = FF_COLOR_YUV,
+ .pixel_type = FF_PIXEL_PLANAR,
+ .depth = 8,
+ .x_chroma_shift = 1, .y_chroma_shift = 1,
+ },
+ [PIX_FMT_YUV422P] = {
+ .name = "yuv422p",
+ .nb_channels = 3,
+ .color_type = FF_COLOR_YUV,
+ .pixel_type = FF_PIXEL_PLANAR,
+ .depth = 8,
+ .x_chroma_shift = 1, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_YUV444P] = {
+ .name = "yuv444p",
+ .nb_channels = 3,
+ .color_type = FF_COLOR_YUV,
+ .pixel_type = FF_PIXEL_PLANAR,
+ .depth = 8,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_YUV422] = {
+ .name = "yuv422",
+ .nb_channels = 1,
+ .color_type = FF_COLOR_YUV,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 8,
+ .x_chroma_shift = 1, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_UYVY422] = {
+ .name = "uyvy422",
+ .nb_channels = 1,
+ .color_type = FF_COLOR_YUV,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 8,
+ .x_chroma_shift = 1, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_YUV410P] = {
+ .name = "yuv410p",
+ .nb_channels = 3,
+ .color_type = FF_COLOR_YUV,
+ .pixel_type = FF_PIXEL_PLANAR,
+ .depth = 8,
+ .x_chroma_shift = 2, .y_chroma_shift = 2,
+ },
+ [PIX_FMT_YUV411P] = {
+ .name = "yuv411p",
+ .nb_channels = 3,
+ .color_type = FF_COLOR_YUV,
+ .pixel_type = FF_PIXEL_PLANAR,
+ .depth = 8,
+ .x_chroma_shift = 2, .y_chroma_shift = 0,
+ },
+
+ /* JPEG YUV */
+ [PIX_FMT_YUVJ420P] = {
+ .name = "yuvj420p",
+ .nb_channels = 3,
+ .color_type = FF_COLOR_YUV_JPEG,
+ .pixel_type = FF_PIXEL_PLANAR,
+ .depth = 8,
+ .x_chroma_shift = 1, .y_chroma_shift = 1,
+ },
+ [PIX_FMT_YUVJ422P] = {
+ .name = "yuvj422p",
+ .nb_channels = 3,
+ .color_type = FF_COLOR_YUV_JPEG,
+ .pixel_type = FF_PIXEL_PLANAR,
+ .depth = 8,
+ .x_chroma_shift = 1, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_YUVJ444P] = {
+ .name = "yuvj444p",
+ .nb_channels = 3,
+ .color_type = FF_COLOR_YUV_JPEG,
+ .pixel_type = FF_PIXEL_PLANAR,
+ .depth = 8,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+
+ /* RGB formats */
+ [PIX_FMT_RGB24] = {
+ .name = "rgb24",
+ .nb_channels = 3,
+ .color_type = FF_COLOR_RGB,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 8,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_BGR24] = {
+ .name = "bgr24",
+ .nb_channels = 3,
+ .color_type = FF_COLOR_RGB,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 8,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_RGBA32] = {
+ .name = "rgba32",
+ .nb_channels = 4, .is_alpha = 1,
+ .color_type = FF_COLOR_RGB,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 8,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_RGB565] = {
+ .name = "rgb565",
+ .nb_channels = 3,
+ .color_type = FF_COLOR_RGB,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 5,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_RGB555] = {
+ .name = "rgb555",
+ .nb_channels = 3,
+ .color_type = FF_COLOR_RGB,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 5,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+
+ /* gray / mono formats */
+ [PIX_FMT_GRAY16BE] = {
+ .name = "gray16be",
+ .nb_channels = 1,
+ .color_type = FF_COLOR_GRAY,
+ .pixel_type = FF_PIXEL_PLANAR,
+ .depth = 16,
+ },
+ [PIX_FMT_GRAY16LE] = {
+ .name = "gray16le",
+ .nb_channels = 1,
+ .color_type = FF_COLOR_GRAY,
+ .pixel_type = FF_PIXEL_PLANAR,
+ .depth = 16,
+ },
+ [PIX_FMT_GRAY8] = {
+ .name = "gray",
+ .nb_channels = 1,
+ .color_type = FF_COLOR_GRAY,
+ .pixel_type = FF_PIXEL_PLANAR,
+ .depth = 8,
+ },
+ [PIX_FMT_MONOWHITE] = {
+ .name = "monow",
+ .nb_channels = 1,
+ .color_type = FF_COLOR_GRAY,
+ .pixel_type = FF_PIXEL_PLANAR,
+ .depth = 1,
+ },
+ [PIX_FMT_MONOBLACK] = {
+ .name = "monob",
+ .nb_channels = 1,
+ .color_type = FF_COLOR_GRAY,
+ .pixel_type = FF_PIXEL_PLANAR,
+ .depth = 1,
+ },
+
+ /* paletted formats */
+ [PIX_FMT_PAL8] = {
+ .name = "pal8",
+ .nb_channels = 4, .is_alpha = 1,
+ .color_type = FF_COLOR_RGB,
+ .pixel_type = FF_PIXEL_PALETTE,
+ .depth = 8,
+ },
+ [PIX_FMT_XVMC_MPEG2_MC] = {
+ .name = "xvmcmc",
+ },
+ [PIX_FMT_XVMC_MPEG2_IDCT] = {
+ .name = "xvmcidct",
+ },
+ [PIX_FMT_UYVY411] = {
+ .name = "uyvy411",
+ .nb_channels = 1,
+ .color_type = FF_COLOR_YUV,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 8,
+ .x_chroma_shift = 2, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_BGR32] = {
+ .name = "bgr32",
+ .nb_channels = 4, .is_alpha = 1,
+ .color_type = FF_COLOR_RGB,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 8,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_BGR565] = {
+ .name = "bgr565",
+ .nb_channels = 3,
+ .color_type = FF_COLOR_RGB,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 5,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_BGR555] = {
+ .name = "bgr555",
+ .nb_channels = 3,
+ .color_type = FF_COLOR_RGB,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 5,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_RGB8] = {
+ .name = "rgb8",
+ .nb_channels = 1,
+ .color_type = FF_COLOR_RGB,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 8,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_RGB4] = {
+ .name = "rgb4",
+ .nb_channels = 1,
+ .color_type = FF_COLOR_RGB,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 4,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_RGB4_BYTE] = {
+ .name = "rgb4_byte",
+ .nb_channels = 1,
+ .color_type = FF_COLOR_RGB,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 8,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_BGR8] = {
+ .name = "bgr8",
+ .nb_channels = 1,
+ .color_type = FF_COLOR_RGB,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 8,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_BGR4] = {
+ .name = "bgr4",
+ .nb_channels = 1,
+ .color_type = FF_COLOR_RGB,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 4,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_BGR4_BYTE] = {
+ .name = "bgr4_byte",
+ .nb_channels = 1,
+ .color_type = FF_COLOR_RGB,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 8,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_NV12] = {
+ .name = "nv12",
+ .nb_channels = 2,
+ .color_type = FF_COLOR_YUV,
+ .pixel_type = FF_PIXEL_PLANAR,
+ .depth = 8,
+ .x_chroma_shift = 1, .y_chroma_shift = 1,
+ },
+ [PIX_FMT_NV21] = {
+ .name = "nv12",
+ .nb_channels = 2,
+ .color_type = FF_COLOR_YUV,
+ .pixel_type = FF_PIXEL_PLANAR,
+ .depth = 8,
+ .x_chroma_shift = 1, .y_chroma_shift = 1,
+ },
+
+ [PIX_FMT_BGR32_1] = {
+ .name = "bgr32_1",
+ .nb_channels = 4, .is_alpha = 1,
+ .color_type = FF_COLOR_RGB,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 8,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+ [PIX_FMT_RGB32_1] = {
+ .name = "rgb32_1",
+ .nb_channels = 4, .is_alpha = 1,
+ .color_type = FF_COLOR_RGB,
+ .pixel_type = FF_PIXEL_PACKED,
+ .depth = 8,
+ .x_chroma_shift = 0, .y_chroma_shift = 0,
+ },
+};
+
+void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift)
+{
+ *h_shift = pix_fmt_info[pix_fmt].x_chroma_shift;
+ *v_shift = pix_fmt_info[pix_fmt].y_chroma_shift;
+}
+
+const char *avcodec_get_pix_fmt_name(int pix_fmt)
+{
+ if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB)
+ return "???";
+ else
+ return pix_fmt_info[pix_fmt].name;
+}
+
+enum PixelFormat avcodec_get_pix_fmt(const char* name)
+{
+ int i;
+
+ for (i=0; i < PIX_FMT_NB; i++)
+ if (!strcmp(pix_fmt_info[i].name, name))
+ break;
+ return i;
+}
+
+/* Picture field are filled with 'ptr' addresses. Also return size */
+int avpicture_fill(AVPicture *picture, uint8_t *ptr,
+ int pix_fmt, int width, int height)
+{
+ int size, w2, h2, size2;
+ const PixFmtInfo *pinfo;
+
+ if(avcodec_check_dimensions(NULL, width, height))
+ goto fail;
+
+ pinfo = &pix_fmt_info[pix_fmt];
+ size = width * height;
+ switch(pix_fmt) {
+ case PIX_FMT_YUV420P:
+ case PIX_FMT_YUV422P:
+ case PIX_FMT_YUV444P:
+ case PIX_FMT_YUV410P:
+ case PIX_FMT_YUV411P:
+ case PIX_FMT_YUVJ420P:
+ case PIX_FMT_YUVJ422P:
+ case PIX_FMT_YUVJ444P:
+ w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
+ h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
+ size2 = w2 * h2;
+ picture->data[0] = ptr;
+ picture->data[1] = picture->data[0] + size;
+ picture->data[2] = picture->data[1] + size2;
+ picture->linesize[0] = width;
+ picture->linesize[1] = w2;
+ picture->linesize[2] = w2;
+ return size + 2 * size2;
+ case PIX_FMT_NV12:
+ case PIX_FMT_NV21:
+ w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
+ h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
+ size2 = w2 * h2 * 2;
+ picture->data[0] = ptr;
+ picture->data[1] = picture->data[0] + size;
+ picture->data[2] = NULL;
+ picture->linesize[0] = width;
+ picture->linesize[1] = w2;
+ picture->linesize[2] = 0;
+ return size + 2 * size2;
+ case PIX_FMT_RGB24:
+ case PIX_FMT_BGR24:
+ picture->data[0] = ptr;
+ picture->data[1] = NULL;
+ picture->data[2] = NULL;
+ picture->linesize[0] = width * 3;
+ return size * 3;
+ case PIX_FMT_RGBA32:
+ case PIX_FMT_BGR32:
+ case PIX_FMT_RGB32_1:
+ case PIX_FMT_BGR32_1:
+ picture->data[0] = ptr;
+ picture->data[1] = NULL;
+ picture->data[2] = NULL;
+ picture->linesize[0] = width * 4;
+ return size * 4;
+ case PIX_FMT_GRAY16BE:
+ case PIX_FMT_GRAY16LE:
+ case PIX_FMT_BGR555:
+ case PIX_FMT_BGR565:
+ case PIX_FMT_RGB555:
+ case PIX_FMT_RGB565:
+ case PIX_FMT_YUV422:
+ picture->data[0] = ptr;
+ picture->data[1] = NULL;
+ picture->data[2] = NULL;
+ picture->linesize[0] = width * 2;
+ return size * 2;
+ case PIX_FMT_UYVY422:
+ picture->data[0] = ptr;
+ picture->data[1] = NULL;
+ picture->data[2] = NULL;
+ picture->linesize[0] = width * 2;
+ return size * 2;
+ case PIX_FMT_UYVY411:
+ picture->data[0] = ptr;
+ picture->data[1] = NULL;
+ picture->data[2] = NULL;
+ picture->linesize[0] = width + width/2;
+ return size + size/2;
+ case PIX_FMT_RGB8:
+ case PIX_FMT_BGR8:
+ case PIX_FMT_RGB4_BYTE:
+ case PIX_FMT_BGR4_BYTE:
+ case PIX_FMT_GRAY8:
+ picture->data[0] = ptr;
+ picture->data[1] = NULL;
+ picture->data[2] = NULL;
+ picture->linesize[0] = width;
+ return size;
+ case PIX_FMT_RGB4:
+ case PIX_FMT_BGR4:
+ picture->data[0] = ptr;
+ picture->data[1] = NULL;
+ picture->data[2] = NULL;
+ picture->linesize[0] = width / 2;
+ return size / 2;
+ case PIX_FMT_MONOWHITE:
+ case PIX_FMT_MONOBLACK:
+ picture->data[0] = ptr;
+ picture->data[1] = NULL;
+ picture->data[2] = NULL;
+ picture->linesize[0] = (width + 7) >> 3;
+ return picture->linesize[0] * height;
+ case PIX_FMT_PAL8:
+ size2 = (size + 3) & ~3;
+ picture->data[0] = ptr;
+ picture->data[1] = ptr + size2; /* palette is stored here as 256 32 bit words */
+ picture->data[2] = NULL;
+ picture->linesize[0] = width;
+ picture->linesize[1] = 4;
+ return size2 + 256 * 4;
+ default:
+fail:
+ picture->data[0] = NULL;
+ picture->data[1] = NULL;
+ picture->data[2] = NULL;
+ picture->data[3] = NULL;
+ return -1;
+ }
+}
+
+int avpicture_layout(const AVPicture* src, int pix_fmt, int width, int height,
+ unsigned char *dest, int dest_size)
+{
+ const PixFmtInfo* pf = &pix_fmt_info[pix_fmt];
+ int i, j, w, h, data_planes;
+ const unsigned char* s;
+ int size = avpicture_get_size(pix_fmt, width, height);
+
+ if (size > dest_size || size < 0)
+ return -1;
+
+ if (pf->pixel_type == FF_PIXEL_PACKED || pf->pixel_type == FF_PIXEL_PALETTE) {
+ if (pix_fmt == PIX_FMT_YUV422 ||
+ pix_fmt == PIX_FMT_UYVY422 ||
+ pix_fmt == PIX_FMT_BGR565 ||
+ pix_fmt == PIX_FMT_BGR555 ||
+ pix_fmt == PIX_FMT_RGB565 ||
+ pix_fmt == PIX_FMT_RGB555)
+ w = width * 2;
+ else if (pix_fmt == PIX_FMT_UYVY411)
+ w = width + width/2;
+ else if (pix_fmt == PIX_FMT_PAL8)
+ w = width;
+ else
+ w = width * (pf->depth * pf->nb_channels / 8);
+
+ data_planes = 1;
+ h = height;
+ } else {
+ data_planes = pf->nb_channels;
+ w = (width*pf->depth + 7)/8;
+ h = height;
+ }
+
+ for (i=0; i<data_planes; i++) {
+ if (i == 1) {
+ w = width >> pf->x_chroma_shift;
+ h = height >> pf->y_chroma_shift;
+ }
+ s = src->data[i];
+ for(j=0; j<h; j++) {
+ memcpy(dest, s, w);
+ dest += w;
+ s += src->linesize[i];
+ }
+ }
+
+ if (pf->pixel_type == FF_PIXEL_PALETTE)
+ memcpy((unsigned char *)(((size_t)dest + 3) & ~3), src->data[1], 256 * 4);
+
+ return size;
+}
+
+int avpicture_get_size(int pix_fmt, int width, int height)
+{
+ AVPicture dummy_pict;
+ return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height);
+}
+
+/**
+ * compute the loss when converting from a pixel format to another
+ */
+int avcodec_get_pix_fmt_loss(int dst_pix_fmt, int src_pix_fmt,
+ int has_alpha)
+{
+ const PixFmtInfo *pf, *ps;
+ int loss;
+
+ ps = &pix_fmt_info[src_pix_fmt];
+ pf = &pix_fmt_info[dst_pix_fmt];
+
+ /* compute loss */
+ loss = 0;
+ pf = &pix_fmt_info[dst_pix_fmt];
+ if (pf->depth < ps->depth ||
+ (dst_pix_fmt == PIX_FMT_RGB555 && src_pix_fmt == PIX_FMT_RGB565))
+ loss |= FF_LOSS_DEPTH;
+ if (pf->x_chroma_shift > ps->x_chroma_shift ||
+ pf->y_chroma_shift > ps->y_chroma_shift)
+ loss |= FF_LOSS_RESOLUTION;
+ switch(pf->color_type) {
+ case FF_COLOR_RGB:
+ if (ps->color_type != FF_COLOR_RGB &&
+ ps->color_type != FF_COLOR_GRAY)
+ loss |= FF_LOSS_COLORSPACE;
+ break;
+ case FF_COLOR_GRAY:
+ if (ps->color_type != FF_COLOR_GRAY)
+ loss |= FF_LOSS_COLORSPACE;
+ break;
+ case FF_COLOR_YUV:
+ if (ps->color_type != FF_COLOR_YUV)
+ loss |= FF_LOSS_COLORSPACE;
+ break;
+ case FF_COLOR_YUV_JPEG:
+ if (ps->color_type != FF_COLOR_YUV_JPEG &&
+ ps->color_type != FF_COLOR_YUV &&
+ ps->color_type != FF_COLOR_GRAY)
+ loss |= FF_LOSS_COLORSPACE;
+ break;
+ default:
+ /* fail safe test */
+ if (ps->color_type != pf->color_type)
+ loss |= FF_LOSS_COLORSPACE;
+ break;
+ }
+ if (pf->color_type == FF_COLOR_GRAY &&
+ ps->color_type != FF_COLOR_GRAY)
+ loss |= FF_LOSS_CHROMA;
+ if (!pf->is_alpha && (ps->is_alpha && has_alpha))
+ loss |= FF_LOSS_ALPHA;
+ if (pf->pixel_type == FF_PIXEL_PALETTE &&
+ (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY))
+ loss |= FF_LOSS_COLORQUANT;
+ return loss;
+}
+
+static int avg_bits_per_pixel(int pix_fmt)
+{
+ int bits;
+ const PixFmtInfo *pf;
+
+ pf = &pix_fmt_info[pix_fmt];
+ switch(pf->pixel_type) {
+ case FF_PIXEL_PACKED:
+ switch(pix_fmt) {
+ case PIX_FMT_YUV422:
+ case PIX_FMT_UYVY422:
+ case PIX_FMT_RGB565:
+ case PIX_FMT_RGB555:
+ case PIX_FMT_BGR565:
+ case PIX_FMT_BGR555:
+ bits = 16;
+ break;
+ case PIX_FMT_UYVY411:
+ bits = 12;
+ break;
+ default:
+ bits = pf->depth * pf->nb_channels;
+ break;
+ }
+ break;
+ case FF_PIXEL_PLANAR:
+ if (pf->x_chroma_shift == 0 && pf->y_chroma_shift == 0) {
+ bits = pf->depth * pf->nb_channels;
+ } else {
+ bits = pf->depth + ((2 * pf->depth) >>
+ (pf->x_chroma_shift + pf->y_chroma_shift));
+ }
+ break;
+ case FF_PIXEL_PALETTE:
+ bits = 8;
+ break;
+ default:
+ bits = -1;
+ break;
+ }
+ return bits;
+}
+
+static int avcodec_find_best_pix_fmt1(int pix_fmt_mask,
+ int src_pix_fmt,
+ int has_alpha,
+ int loss_mask)
+{
+ int dist, i, loss, min_dist, dst_pix_fmt;
+
+ /* find exact color match with smallest size */
+ dst_pix_fmt = -1;
+ min_dist = 0x7fffffff;
+ for(i = 0;i < PIX_FMT_NB; i++) {
+ if (pix_fmt_mask & (1 << i)) {
+ loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask;
+ if (loss == 0) {
+ dist = avg_bits_per_pixel(i);
+ if (dist < min_dist) {
+ min_dist = dist;
+ dst_pix_fmt = i;
+ }
+ }
+ }
+ }
+ return dst_pix_fmt;
+}
+
+/**
+ * find best pixel format to convert to. Return -1 if none found
+ */
+int avcodec_find_best_pix_fmt(int pix_fmt_mask, int src_pix_fmt,
+ int has_alpha, int *loss_ptr)
+{
+ int dst_pix_fmt, loss_mask, i;
+ static const int loss_mask_order[] = {
+ ~0, /* no loss first */
+ ~FF_LOSS_ALPHA,
+ ~FF_LOSS_RESOLUTION,
+ ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION),
+ ~FF_LOSS_COLORQUANT,
+ ~FF_LOSS_DEPTH,
+ 0,
+ };
+
+ /* try with successive loss */
+ i = 0;
+ for(;;) {
+ loss_mask = loss_mask_order[i++];
+ dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt,
+ has_alpha, loss_mask);
+ if (dst_pix_fmt >= 0)
+ goto found;
+ if (loss_mask == 0)
+ break;
+ }
+ return -1;
+ found:
+ if (loss_ptr)
+ *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
+ return dst_pix_fmt;
+}
+
+void ff_img_copy_plane(uint8_t *dst, int dst_wrap,
+ const uint8_t *src, int src_wrap,
+ int width, int height)
+{
+ if((!dst) || (!src))
+ return;
+ for(;height > 0; height--) {
+ memcpy(dst, src, width);
+ dst += dst_wrap;
+ src += src_wrap;
+ }
+}
+
+/**
+ * Copy image 'src' to 'dst'.
+ */
+void img_copy(AVPicture *dst, const AVPicture *src,
+ int pix_fmt, int width, int height)
+{
+ int bwidth, bits, i;
+ const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
+
+ pf = &pix_fmt_info[pix_fmt];
+ switch(pf->pixel_type) {
+ case FF_PIXEL_PACKED:
+ switch(pix_fmt) {
+ case PIX_FMT_YUV422:
+ case PIX_FMT_UYVY422:
+ case PIX_FMT_RGB565:
+ case PIX_FMT_RGB555:
+ case PIX_FMT_BGR565:
+ case PIX_FMT_BGR555:
+ bits = 16;
+ break;
+ case PIX_FMT_UYVY411:
+ bits = 12;
+ break;
+ default:
+ bits = pf->depth * pf->nb_channels;
+ break;
+ }
+ bwidth = (width * bits + 7) >> 3;
+ ff_img_copy_plane(dst->data[0], dst->linesize[0],
+ src->data[0], src->linesize[0],
+ bwidth, height);
+ break;
+ case FF_PIXEL_PLANAR:
+ for(i = 0; i < pf->nb_channels; i++) {
+ int w, h;
+ w = width;
+ h = height;
+ if (i == 1 || i == 2) {
+ w >>= pf->x_chroma_shift;
+ h >>= pf->y_chroma_shift;
+ }
+ bwidth = (w * pf->depth + 7) >> 3;
+ ff_img_copy_plane(dst->data[i], dst->linesize[i],
+ src->data[i], src->linesize[i],
+ bwidth, h);
+ }
+ break;
+ case FF_PIXEL_PALETTE:
+ ff_img_copy_plane(dst->data[0], dst->linesize[0],
+ src->data[0], src->linesize[0],
+ width, height);
+ /* copy the palette */
+ ff_img_copy_plane(dst->data[1], dst->linesize[1],
+ src->data[1], src->linesize[1],
+ 4, 256);
+ break;
+ }
+}
+
+/* XXX: totally non optimized */
+
+static void yuv422_to_yuv420p(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ const uint8_t *p, *p1;
+ uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
+ int w;
+
+ p1 = src->data[0];
+ lum1 = dst->data[0];
+ cb1 = dst->data[1];
+ cr1 = dst->data[2];
+
+ for(;height >= 1; height -= 2) {
+ p = p1;
+ lum = lum1;
+ cb = cb1;
+ cr = cr1;
+ for(w = width; w >= 2; w -= 2) {
+ lum[0] = p[0];
+ cb[0] = p[1];
+ lum[1] = p[2];
+ cr[0] = p[3];
+ p += 4;
+ lum += 2;
+ cb++;
+ cr++;
+ }
+ if (w) {
+ lum[0] = p[0];
+ cb[0] = p[1];
+ cr[0] = p[3];
+ cb++;
+ cr++;
+ }
+ p1 += src->linesize[0];
+ lum1 += dst->linesize[0];
+ if (height>1) {
+ p = p1;
+ lum = lum1;
+ for(w = width; w >= 2; w -= 2) {
+ lum[0] = p[0];
+ lum[1] = p[2];
+ p += 4;
+ lum += 2;
+ }
+ if (w) {
+ lum[0] = p[0];
+ }
+ p1 += src->linesize[0];
+ lum1 += dst->linesize[0];
+ }
+ cb1 += dst->linesize[1];
+ cr1 += dst->linesize[2];
+ }
+}
+
+static void uyvy422_to_yuv420p(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ const uint8_t *p, *p1;
+ uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
+ int w;
+
+ p1 = src->data[0];
+
+ lum1 = dst->data[0];
+ cb1 = dst->data[1];
+ cr1 = dst->data[2];
+
+ for(;height >= 1; height -= 2) {
+ p = p1;
+ lum = lum1;
+ cb = cb1;
+ cr = cr1;
+ for(w = width; w >= 2; w -= 2) {
+ lum[0] = p[1];
+ cb[0] = p[0];
+ lum[1] = p[3];
+ cr[0] = p[2];
+ p += 4;
+ lum += 2;
+ cb++;
+ cr++;
+ }
+ if (w) {
+ lum[0] = p[1];
+ cb[0] = p[0];
+ cr[0] = p[2];
+ cb++;
+ cr++;
+ }
+ p1 += src->linesize[0];
+ lum1 += dst->linesize[0];
+ if (height>1) {
+ p = p1;
+ lum = lum1;
+ for(w = width; w >= 2; w -= 2) {
+ lum[0] = p[1];
+ lum[1] = p[3];
+ p += 4;
+ lum += 2;
+ }
+ if (w) {
+ lum[0] = p[1];
+ }
+ p1 += src->linesize[0];
+ lum1 += dst->linesize[0];
+ }
+ cb1 += dst->linesize[1];
+ cr1 += dst->linesize[2];
+ }
+}
+
+
+static void uyvy422_to_yuv422p(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ const uint8_t *p, *p1;
+ uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
+ int w;
+
+ p1 = src->data[0];
+ lum1 = dst->data[0];
+ cb1 = dst->data[1];
+ cr1 = dst->data[2];
+ for(;height > 0; height--) {
+ p = p1;
+ lum = lum1;
+ cb = cb1;
+ cr = cr1;
+ for(w = width; w >= 2; w -= 2) {
+ lum[0] = p[1];
+ cb[0] = p[0];
+ lum[1] = p[3];
+ cr[0] = p[2];
+ p += 4;
+ lum += 2;
+ cb++;
+ cr++;
+ }
+ p1 += src->linesize[0];
+ lum1 += dst->linesize[0];
+ cb1 += dst->linesize[1];
+ cr1 += dst->linesize[2];
+ }
+}
+
+
+static void yuv422_to_yuv422p(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ const uint8_t *p, *p1;
+ uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
+ int w;
+
+ p1 = src->data[0];
+ lum1 = dst->data[0];
+ cb1 = dst->data[1];
+ cr1 = dst->data[2];
+ for(;height > 0; height--) {
+ p = p1;
+ lum = lum1;
+ cb = cb1;
+ cr = cr1;
+ for(w = width; w >= 2; w -= 2) {
+ lum[0] = p[0];
+ cb[0] = p[1];
+ lum[1] = p[2];
+ cr[0] = p[3];
+ p += 4;
+ lum += 2;
+ cb++;
+ cr++;
+ }
+ p1 += src->linesize[0];
+ lum1 += dst->linesize[0];
+ cb1 += dst->linesize[1];
+ cr1 += dst->linesize[2];
+ }
+}
+
+static void yuv422p_to_yuv422(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ uint8_t *p, *p1;
+ const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
+ int w;
+
+ p1 = dst->data[0];
+ lum1 = src->data[0];
+ cb1 = src->data[1];
+ cr1 = src->data[2];
+ for(;height > 0; height--) {
+ p = p1;
+ lum = lum1;
+ cb = cb1;
+ cr = cr1;
+ for(w = width; w >= 2; w -= 2) {
+ p[0] = lum[0];
+ p[1] = cb[0];
+ p[2] = lum[1];
+ p[3] = cr[0];
+ p += 4;
+ lum += 2;
+ cb++;
+ cr++;
+ }
+ p1 += dst->linesize[0];
+ lum1 += src->linesize[0];
+ cb1 += src->linesize[1];
+ cr1 += src->linesize[2];
+ }
+}
+
+static void yuv422p_to_uyvy422(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ uint8_t *p, *p1;
+ const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
+ int w;
+
+ p1 = dst->data[0];
+ lum1 = src->data[0];
+ cb1 = src->data[1];
+ cr1 = src->data[2];
+ for(;height > 0; height--) {
+ p = p1;
+ lum = lum1;
+ cb = cb1;
+ cr = cr1;
+ for(w = width; w >= 2; w -= 2) {
+ p[1] = lum[0];
+ p[0] = cb[0];
+ p[3] = lum[1];
+ p[2] = cr[0];
+ p += 4;
+ lum += 2;
+ cb++;
+ cr++;
+ }
+ p1 += dst->linesize[0];
+ lum1 += src->linesize[0];
+ cb1 += src->linesize[1];
+ cr1 += src->linesize[2];
+ }
+}
+
+static void uyvy411_to_yuv411p(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ const uint8_t *p, *p1;
+ uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
+ int w;
+
+ p1 = src->data[0];
+ lum1 = dst->data[0];
+ cb1 = dst->data[1];
+ cr1 = dst->data[2];
+ for(;height > 0; height--) {
+ p = p1;
+ lum = lum1;
+ cb = cb1;
+ cr = cr1;
+ for(w = width; w >= 4; w -= 4) {
+ cb[0] = p[0];
+ lum[0] = p[1];
+ lum[1] = p[2];
+ cr[0] = p[3];
+ lum[2] = p[4];
+ lum[3] = p[5];
+ p += 6;
+ lum += 4;
+ cb++;
+ cr++;
+ }
+ p1 += src->linesize[0];
+ lum1 += dst->linesize[0];
+ cb1 += dst->linesize[1];
+ cr1 += dst->linesize[2];
+ }
+}
+
+
+static void yuv420p_to_yuv422(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ int w, h;
+ uint8_t *line1, *line2, *linesrc = dst->data[0];
+ uint8_t *lum1, *lum2, *lumsrc = src->data[0];
+ uint8_t *cb1, *cb2 = src->data[1];
+ uint8_t *cr1, *cr2 = src->data[2];
+
+ for(h = height / 2; h--;) {
+ line1 = linesrc;
+ line2 = linesrc + dst->linesize[0];
+
+ lum1 = lumsrc;
+ lum2 = lumsrc + src->linesize[0];
+
+ cb1 = cb2;
+ cr1 = cr2;
+
+ for(w = width / 2; w--;) {
+ *line1++ = *lum1++; *line2++ = *lum2++;
+ *line1++ = *line2++ = *cb1++;
+ *line1++ = *lum1++; *line2++ = *lum2++;
+ *line1++ = *line2++ = *cr1++;
+ }
+
+ linesrc += dst->linesize[0] * 2;
+ lumsrc += src->linesize[0] * 2;
+ cb2 += src->linesize[1];
+ cr2 += src->linesize[2];
+ }
+}
+
+static void yuv420p_to_uyvy422(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ int w, h;
+ uint8_t *line1, *line2, *linesrc = dst->data[0];
+ uint8_t *lum1, *lum2, *lumsrc = src->data[0];
+ uint8_t *cb1, *cb2 = src->data[1];
+ uint8_t *cr1, *cr2 = src->data[2];
+
+ for(h = height / 2; h--;) {
+ line1 = linesrc;
+ line2 = linesrc + dst->linesize[0];
+
+ lum1 = lumsrc;
+ lum2 = lumsrc + src->linesize[0];
+
+ cb1 = cb2;
+ cr1 = cr2;
+
+ for(w = width / 2; w--;) {
+ *line1++ = *line2++ = *cb1++;
+ *line1++ = *lum1++; *line2++ = *lum2++;
+ *line1++ = *line2++ = *cr1++;
+ *line1++ = *lum1++; *line2++ = *lum2++;
+ }
+
+ linesrc += dst->linesize[0] * 2;
+ lumsrc += src->linesize[0] * 2;
+ cb2 += src->linesize[1];
+ cr2 += src->linesize[2];
+ }
+}
+
+#define SCALEBITS 10
+#define ONE_HALF (1 << (SCALEBITS - 1))
+#define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
+
+#define YUV_TO_RGB1_CCIR(cb1, cr1)\
+{\
+ cb = (cb1) - 128;\
+ cr = (cr1) - 128;\
+ r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;\
+ g_add = - FIX(0.34414*255.0/224.0) * cb - FIX(0.71414*255.0/224.0) * cr + \
+ ONE_HALF;\
+ b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;\
+}
+
+#define YUV_TO_RGB2_CCIR(r, g, b, y1)\
+{\
+ y = ((y1) - 16) * FIX(255.0/219.0);\
+ r = cm[(y + r_add) >> SCALEBITS];\
+ g = cm[(y + g_add) >> SCALEBITS];\
+ b = cm[(y + b_add) >> SCALEBITS];\
+}
+
+#define YUV_TO_RGB1(cb1, cr1)\
+{\
+ cb = (cb1) - 128;\
+ cr = (cr1) - 128;\
+ r_add = FIX(1.40200) * cr + ONE_HALF;\
+ g_add = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;\
+ b_add = FIX(1.77200) * cb + ONE_HALF;\
+}
+
+#define YUV_TO_RGB2(r, g, b, y1)\
+{\
+ y = (y1) << SCALEBITS;\
+ r = cm[(y + r_add) >> SCALEBITS];\
+ g = cm[(y + g_add) >> SCALEBITS];\
+ b = cm[(y + b_add) >> SCALEBITS];\
+}
+
+#define Y_CCIR_TO_JPEG(y)\
+ cm[((y) * FIX(255.0/219.0) + (ONE_HALF - 16 * FIX(255.0/219.0))) >> SCALEBITS]
+
+#define Y_JPEG_TO_CCIR(y)\
+ (((y) * FIX(219.0/255.0) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
+
+#define C_CCIR_TO_JPEG(y)\
+ cm[(((y) - 128) * FIX(127.0/112.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS]
+
+/* NOTE: the clamp is really necessary! */
+static inline int C_JPEG_TO_CCIR(int y) {
+ y = (((y - 128) * FIX(112.0/127.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS);
+ if (y < 16)
+ y = 16;
+ return y;
+}
+
+
+#define RGB_TO_Y(r, g, b) \
+((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \
+ FIX(0.11400) * (b) + ONE_HALF) >> SCALEBITS)
+
+#define RGB_TO_U(r1, g1, b1, shift)\
+(((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \
+ FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
+
+#define RGB_TO_V(r1, g1, b1, shift)\
+(((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \
+ FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
+
+#define RGB_TO_Y_CCIR(r, g, b) \
+((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
+ FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
+
+#define RGB_TO_U_CCIR(r1, g1, b1, shift)\
+(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \
+ FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
+
+#define RGB_TO_V_CCIR(r1, g1, b1, shift)\
+(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \
+ FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
+
+static uint8_t y_ccir_to_jpeg[256];
+static uint8_t y_jpeg_to_ccir[256];
+static uint8_t c_ccir_to_jpeg[256];
+static uint8_t c_jpeg_to_ccir[256];
+
+/* init various conversion tables */
+static void img_convert_init(void)
+{
+ int i;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ for(i = 0;i < 256; i++) {
+ y_ccir_to_jpeg[i] = Y_CCIR_TO_JPEG(i);
+ y_jpeg_to_ccir[i] = Y_JPEG_TO_CCIR(i);
+ c_ccir_to_jpeg[i] = C_CCIR_TO_JPEG(i);
+ c_jpeg_to_ccir[i] = C_JPEG_TO_CCIR(i);
+ }
+}
+
+/* apply to each pixel the given table */
+static void img_apply_table(uint8_t *dst, int dst_wrap,
+ const uint8_t *src, int src_wrap,
+ int width, int height, const uint8_t *table1)
+{
+ int n;
+ const uint8_t *s;
+ uint8_t *d;
+ const uint8_t *table;
+
+ table = table1;
+ for(;height > 0; height--) {
+ s = src;
+ d = dst;
+ n = width;
+ while (n >= 4) {
+ d[0] = table[s[0]];
+ d[1] = table[s[1]];
+ d[2] = table[s[2]];
+ d[3] = table[s[3]];
+ d += 4;
+ s += 4;
+ n -= 4;
+ }
+ while (n > 0) {
+ d[0] = table[s[0]];
+ d++;
+ s++;
+ n--;
+ }
+ dst += dst_wrap;
+ src += src_wrap;
+ }
+}
+
+/* XXX: use generic filter ? */
+/* XXX: in most cases, the sampling position is incorrect */
+
+/* 4x1 -> 1x1 */
+static void shrink41(uint8_t *dst, int dst_wrap,
+ const uint8_t *src, int src_wrap,
+ int width, int height)
+{
+ int w;
+ const uint8_t *s;
+ uint8_t *d;
+
+ for(;height > 0; height--) {
+ s = src;
+ d = dst;
+ for(w = width;w > 0; w--) {
+ d[0] = (s[0] + s[1] + s[2] + s[3] + 2) >> 2;
+ s += 4;
+ d++;
+ }
+ src += src_wrap;
+ dst += dst_wrap;
+ }
+}
+
+/* 2x1 -> 1x1 */
+static void shrink21(uint8_t *dst, int dst_wrap,
+ const uint8_t *src, int src_wrap,
+ int width, int height)
+{
+ int w;
+ const uint8_t *s;
+ uint8_t *d;
+
+ for(;height > 0; height--) {
+ s = src;
+ d = dst;
+ for(w = width;w > 0; w--) {
+ d[0] = (s[0] + s[1]) >> 1;
+ s += 2;
+ d++;
+ }
+ src += src_wrap;
+ dst += dst_wrap;
+ }
+}
+
+/* 1x2 -> 1x1 */
+static void shrink12(uint8_t *dst, int dst_wrap,
+ const uint8_t *src, int src_wrap,
+ int width, int height)
+{
+ int w;
+ uint8_t *d;
+ const uint8_t *s1, *s2;
+
+ for(;height > 0; height--) {
+ s1 = src;
+ s2 = s1 + src_wrap;
+ d = dst;
+ for(w = width;w >= 4; w-=4) {
+ d[0] = (s1[0] + s2[0]) >> 1;
+ d[1] = (s1[1] + s2[1]) >> 1;
+ d[2] = (s1[2] + s2[2]) >> 1;
+ d[3] = (s1[3] + s2[3]) >> 1;
+ s1 += 4;
+ s2 += 4;
+ d += 4;
+ }
+ for(;w > 0; w--) {
+ d[0] = (s1[0] + s2[0]) >> 1;
+ s1++;
+ s2++;
+ d++;
+ }
+ src += 2 * src_wrap;
+ dst += dst_wrap;
+ }
+}
+
+/* 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;
+ }
+}
+
+static void grow21_line(uint8_t *dst, const uint8_t *src,
+ int width)
+{
+ int w;
+ const uint8_t *s1;
+ uint8_t *d;
+
+ s1 = src;
+ d = dst;
+ for(w = width;w >= 4; w-=4) {
+ d[1] = d[0] = s1[0];
+ d[3] = d[2] = s1[1];
+ s1 += 2;
+ d += 4;
+ }
+ for(;w >= 2; w -= 2) {
+ d[1] = d[0] = s1[0];
+ s1 ++;
+ d += 2;
+ }
+ /* only needed if width is not a multiple of two */
+ /* XXX: veryfy that */
+ if (w) {
+ d[0] = s1[0];
+ }
+}
+
+static void grow41_line(uint8_t *dst, const uint8_t *src,
+ int width)
+{
+ int w, v;
+ const uint8_t *s1;
+ uint8_t *d;
+
+ s1 = src;
+ d = dst;
+ for(w = width;w >= 4; w-=4) {
+ v = s1[0];
+ d[0] = v;
+ d[1] = v;
+ d[2] = v;
+ d[3] = v;
+ s1 ++;
+ d += 4;
+ }
+}
+
+/* 1x1 -> 2x1 */
+static void grow21(uint8_t *dst, int dst_wrap,
+ const uint8_t *src, int src_wrap,
+ int width, int height)
+{
+ for(;height > 0; height--) {
+ grow21_line(dst, src, width);
+ src += src_wrap;
+ dst += dst_wrap;
+ }
+}
+
+/* 1x1 -> 2x2 */
+static void grow22(uint8_t *dst, int dst_wrap,
+ const uint8_t *src, int src_wrap,
+ int width, int height)
+{
+ for(;height > 0; height--) {
+ grow21_line(dst, src, width);
+ if (height%2)
+ src += src_wrap;
+ dst += dst_wrap;
+ }
+}
+
+/* 1x1 -> 4x1 */
+static void grow41(uint8_t *dst, int dst_wrap,
+ const uint8_t *src, int src_wrap,
+ int width, int height)
+{
+ for(;height > 0; height--) {
+ grow41_line(dst, src, width);
+ src += src_wrap;
+ dst += dst_wrap;
+ }
+}
+
+/* 1x1 -> 4x4 */
+static void grow44(uint8_t *dst, int dst_wrap,
+ const uint8_t *src, int src_wrap,
+ int width, int height)
+{
+ for(;height > 0; height--) {
+ grow41_line(dst, src, width);
+ if ((height & 3) == 1)
+ src += src_wrap;
+ dst += dst_wrap;
+ }
+}
+
+/* 1x2 -> 2x1 */
+static void conv411(uint8_t *dst, int dst_wrap,
+ const uint8_t *src, int src_wrap,
+ int width, int height)
+{
+ int w, c;
+ const uint8_t *s1, *s2;
+ uint8_t *d;
+
+ width>>=1;
+
+ for(;height > 0; height--) {
+ s1 = src;
+ s2 = src + src_wrap;
+ d = dst;
+ for(w = width;w > 0; w--) {
+ c = (s1[0] + s2[0]) >> 1;
+ d[0] = c;
+ d[1] = c;
+ s1++;
+ s2++;
+ d += 2;
+ }
+ src += src_wrap * 2;
+ dst += dst_wrap;
+ }
+}
+
+/* XXX: add jpeg quantize code */
+
+#define TRANSP_INDEX (6*6*6)
+
+/* this is maybe slow, but allows for extensions */
+static inline unsigned char gif_clut_index(uint8_t r, uint8_t g, uint8_t b)
+{
+ return ((((r)/47)%6)*6*6+(((g)/47)%6)*6+(((b)/47)%6));
+}
+
+static void build_rgb_palette(uint8_t *palette, int has_alpha)
+{
+ uint32_t *pal;
+ static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff };
+ int i, r, g, b;
+
+ pal = (uint32_t *)palette;
+ i = 0;
+ for(r = 0; r < 6; r++) {
+ for(g = 0; g < 6; g++) {
+ for(b = 0; b < 6; b++) {
+ pal[i++] = (0xff << 24) | (pal_value[r] << 16) |
+ (pal_value[g] << 8) | pal_value[b];
+ }
+ }
+ }
+ if (has_alpha)
+ pal[i++] = 0;
+ while (i < 256)
+ pal[i++] = 0xff000000;
+}
+
+/* copy bit n to bits 0 ... n - 1 */
+static inline unsigned int bitcopy_n(unsigned int a, int n)
+{
+ int mask;
+ mask = (1 << n) - 1;
+ return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask);
+}
+
+/* rgb555 handling */
+
+#define RGB_NAME rgb555
+
+#define RGB_IN(r, g, b, s)\
+{\
+ unsigned int v = ((const uint16_t *)(s))[0];\
+ r = bitcopy_n(v >> (10 - 3), 3);\
+ g = bitcopy_n(v >> (5 - 3), 3);\
+ b = bitcopy_n(v << 3, 3);\
+}
+
+
+#define RGB_OUT(d, r, g, b)\
+{\
+ ((uint16_t *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);\
+}
+
+#define BPP 2
+
+#include "imgconvert_template.h"
+
+/* rgb565 handling */
+
+#define RGB_NAME rgb565
+
+#define RGB_IN(r, g, b, s)\
+{\
+ unsigned int v = ((const uint16_t *)(s))[0];\
+ r = bitcopy_n(v >> (11 - 3), 3);\
+ g = bitcopy_n(v >> (5 - 2), 2);\
+ b = bitcopy_n(v << 3, 3);\
+}
+
+#define RGB_OUT(d, r, g, b)\
+{\
+ ((uint16_t *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\
+}
+
+#define BPP 2
+
+#include "imgconvert_template.h"
+
+/* bgr24 handling */
+
+#define RGB_NAME bgr24
+
+#define RGB_IN(r, g, b, s)\
+{\
+ b = (s)[0];\
+ g = (s)[1];\
+ r = (s)[2];\
+}
+
+#define RGB_OUT(d, r, g, b)\
+{\
+ (d)[0] = b;\
+ (d)[1] = g;\
+ (d)[2] = r;\
+}
+
+#define BPP 3
+
+#include "imgconvert_template.h"
+
+#undef RGB_IN
+#undef RGB_OUT
+#undef BPP
+
+/* rgb24 handling */
+
+#define RGB_NAME rgb24
+#define FMT_RGB24
+
+#define RGB_IN(r, g, b, s)\
+{\
+ r = (s)[0];\
+ g = (s)[1];\
+ b = (s)[2];\
+}
+
+#define RGB_OUT(d, r, g, b)\
+{\
+ (d)[0] = r;\
+ (d)[1] = g;\
+ (d)[2] = b;\
+}
+
+#define BPP 3
+
+#include "imgconvert_template.h"
+
+/* rgba32 handling */
+
+#define RGB_NAME rgba32
+#define FMT_RGBA32
+
+#define RGB_IN(r, g, b, s)\
+{\
+ unsigned int v = ((const uint32_t *)(s))[0];\
+ r = (v >> 16) & 0xff;\
+ g = (v >> 8) & 0xff;\
+ b = v & 0xff;\
+}
+
+#define RGBA_IN(r, g, b, a, s)\
+{\
+ unsigned int v = ((const uint32_t *)(s))[0];\
+ a = (v >> 24) & 0xff;\
+ r = (v >> 16) & 0xff;\
+ g = (v >> 8) & 0xff;\
+ b = v & 0xff;\
+}
+
+#define RGBA_OUT(d, r, g, b, a)\
+{\
+ ((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;\
+}
+
+#define BPP 4
+
+#include "imgconvert_template.h"
+
+static void mono_to_gray(AVPicture *dst, const AVPicture *src,
+ int width, int height, int xor_mask)
+{
+ const unsigned char *p;
+ unsigned char *q;
+ int v, dst_wrap, src_wrap;
+ int y, w;
+
+ p = src->data[0];
+ src_wrap = src->linesize[0] - ((width + 7) >> 3);
+
+ q = dst->data[0];
+ dst_wrap = dst->linesize[0] - width;
+ for(y=0;y<height;y++) {
+ w = width;
+ while (w >= 8) {
+ v = *p++ ^ xor_mask;
+ q[0] = -(v >> 7);
+ q[1] = -((v >> 6) & 1);
+ q[2] = -((v >> 5) & 1);
+ q[3] = -((v >> 4) & 1);
+ q[4] = -((v >> 3) & 1);
+ q[5] = -((v >> 2) & 1);
+ q[6] = -((v >> 1) & 1);
+ q[7] = -((v >> 0) & 1);
+ w -= 8;
+ q += 8;
+ }
+ if (w > 0) {
+ v = *p++ ^ xor_mask;
+ do {
+ q[0] = -((v >> 7) & 1);
+ q++;
+ v <<= 1;
+ } while (--w);
+ }
+ p += src_wrap;
+ q += dst_wrap;
+ }
+}
+
+static void monowhite_to_gray(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ mono_to_gray(dst, src, width, height, 0xff);
+}
+
+static void monoblack_to_gray(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ mono_to_gray(dst, src, width, height, 0x00);
+}
+
+static void gray_to_mono(AVPicture *dst, const AVPicture *src,
+ int width, int height, int xor_mask)
+{
+ int n;
+ const uint8_t *s;
+ uint8_t *d;
+ int j, b, v, n1, src_wrap, dst_wrap, y;
+
+ s = src->data[0];
+ src_wrap = src->linesize[0] - width;
+
+ d = dst->data[0];
+ dst_wrap = dst->linesize[0] - ((width + 7) >> 3);
+
+ for(y=0;y<height;y++) {
+ n = width;
+ while (n >= 8) {
+ v = 0;
+ for(j=0;j<8;j++) {
+ b = s[0];
+ s++;
+ v = (v << 1) | (b >> 7);
+ }
+ d[0] = v ^ xor_mask;
+ d++;
+ n -= 8;
+ }
+ if (n > 0) {
+ n1 = n;
+ v = 0;
+ while (n > 0) {
+ b = s[0];
+ s++;
+ v = (v << 1) | (b >> 7);
+ n--;
+ }
+ d[0] = (v << (8 - (n1 & 7))) ^ xor_mask;
+ d++;
+ }
+ s += src_wrap;
+ d += dst_wrap;
+ }
+}
+
+static void gray_to_monowhite(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ gray_to_mono(dst, src, width, height, 0xff);
+}
+
+static void gray_to_monoblack(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ gray_to_mono(dst, src, width, height, 0x00);
+}
+
+static void gray_to_gray16(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ int x, y, src_wrap, dst_wrap;
+ uint8_t *s, *d;
+ s = src->data[0];
+ src_wrap = src->linesize[0] - width;
+ d = dst->data[0];
+ dst_wrap = dst->linesize[0] - width * 2;
+ for(y=0; y<height; y++){
+ for(x=0; x<width; x++){
+ *d++ = *s;
+ *d++ = *s++;
+ }
+ s += src_wrap;
+ d += dst_wrap;
+ }
+}
+
+static void gray16_to_gray(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ int x, y, src_wrap, dst_wrap;
+ uint8_t *s, *d;
+ s = src->data[0];
+ src_wrap = src->linesize[0] - width * 2;
+ d = dst->data[0];
+ dst_wrap = dst->linesize[0] - width;
+ for(y=0; y<height; y++){
+ for(x=0; x<width; x++){
+ *d++ = *s;
+ s += 2;
+ }
+ s += src_wrap;
+ d += dst_wrap;
+ }
+}
+
+static void gray16be_to_gray(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ gray16_to_gray(dst, src, width, height);
+}
+
+static void gray16le_to_gray(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ gray16_to_gray(dst, src + 1, width, height);
+}
+
+static void gray16_to_gray16(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ int x, y, src_wrap, dst_wrap;
+ uint16_t *s, *d;
+ s = src->data[0];
+ src_wrap = (src->linesize[0] - width * 2)/2;
+ d = dst->data[0];
+ dst_wrap = (dst->linesize[0] - width * 2)/2;
+ for(y=0; y<height; y++){
+ for(x=0; x<width; x++){
+ *d++ = bswap_16(*s++);
+ }
+ s += src_wrap;
+ d += dst_wrap;
+ }
+}
+
+
+typedef struct ConvertEntry {
+ void (*convert)(AVPicture *dst,
+ const AVPicture *src, int width, int height);
+} ConvertEntry;
+
+/* Add each new convertion function in this table. In order to be able
+ to convert from any format to any format, the following constraints
+ must be satisfied:
+
+ - all FF_COLOR_RGB formats must convert to and from PIX_FMT_RGB24
+
+ - all FF_COLOR_GRAY formats must convert to and from PIX_FMT_GRAY8
+
+ - all FF_COLOR_RGB formats with alpha must convert to and from PIX_FMT_RGBA32
+
+ - PIX_FMT_YUV444P and PIX_FMT_YUVJ444P must convert to and from
+ PIX_FMT_RGB24.
+
+ - PIX_FMT_422 must convert to and from PIX_FMT_422P.
+
+ The other conversion functions are just optimisations for common cases.
+*/
+static const ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = {
+ [PIX_FMT_YUV420P] = {
+ [PIX_FMT_YUV422] = {
+ .convert = yuv420p_to_yuv422,
+ },
+ [PIX_FMT_RGB555] = {
+ .convert = yuv420p_to_rgb555
+ },
+ [PIX_FMT_RGB565] = {
+ .convert = yuv420p_to_rgb565
+ },
+ [PIX_FMT_BGR24] = {
+ .convert = yuv420p_to_bgr24
+ },
+ [PIX_FMT_RGB24] = {
+ .convert = yuv420p_to_rgb24
+ },
+ [PIX_FMT_RGBA32] = {
+ .convert = yuv420p_to_rgba32
+ },
+ [PIX_FMT_UYVY422] = {
+ .convert = yuv420p_to_uyvy422,
+ },
+ },
+ [PIX_FMT_YUV422P] = {
+ [PIX_FMT_YUV422] = {
+ .convert = yuv422p_to_yuv422,
+ },
+ [PIX_FMT_UYVY422] = {
+ .convert = yuv422p_to_uyvy422,
+ },
+ },
+ [PIX_FMT_YUV444P] = {
+ [PIX_FMT_RGB24] = {
+ .convert = yuv444p_to_rgb24
+ },
+ },
+ [PIX_FMT_YUVJ420P] = {
+ [PIX_FMT_RGB555] = {
+ .convert = yuvj420p_to_rgb555
+ },
+ [PIX_FMT_RGB565] = {
+ .convert = yuvj420p_to_rgb565
+ },
+ [PIX_FMT_BGR24] = {
+ .convert = yuvj420p_to_bgr24
+ },
+ [PIX_FMT_RGB24] = {
+ .convert = yuvj420p_to_rgb24
+ },
+ [PIX_FMT_RGBA32] = {
+ .convert = yuvj420p_to_rgba32
+ },
+ },
+ [PIX_FMT_YUVJ444P] = {
+ [PIX_FMT_RGB24] = {
+ .convert = yuvj444p_to_rgb24
+ },
+ },
+ [PIX_FMT_YUV422] = {
+ [PIX_FMT_YUV420P] = {
+ .convert = yuv422_to_yuv420p,
+ },
+ [PIX_FMT_YUV422P] = {
+ .convert = yuv422_to_yuv422p,
+ },
+ },
+ [PIX_FMT_UYVY422] = {
+ [PIX_FMT_YUV420P] = {
+ .convert = uyvy422_to_yuv420p,
+ },
+ [PIX_FMT_YUV422P] = {
+ .convert = uyvy422_to_yuv422p,
+ },
+ },
+ [PIX_FMT_RGB24] = {
+ [PIX_FMT_YUV420P] = {
+ .convert = rgb24_to_yuv420p
+ },
+ [PIX_FMT_RGB565] = {
+ .convert = rgb24_to_rgb565
+ },
+ [PIX_FMT_RGB555] = {
+ .convert = rgb24_to_rgb555
+ },
+ [PIX_FMT_RGBA32] = {
+ .convert = rgb24_to_rgba32
+ },
+ [PIX_FMT_BGR24] = {
+ .convert = rgb24_to_bgr24
+ },
+ [PIX_FMT_GRAY8] = {
+ .convert = rgb24_to_gray
+ },
+ [PIX_FMT_PAL8] = {
+ .convert = rgb24_to_pal8
+ },
+ [PIX_FMT_YUV444P] = {
+ .convert = rgb24_to_yuv444p
+ },
+ [PIX_FMT_YUVJ420P] = {
+ .convert = rgb24_to_yuvj420p
+ },
+ [PIX_FMT_YUVJ444P] = {
+ .convert = rgb24_to_yuvj444p
+ },
+ },
+ [PIX_FMT_RGBA32] = {
+ [PIX_FMT_RGB24] = {
+ .convert = rgba32_to_rgb24
+ },
+ [PIX_FMT_BGR24] = {
+ .convert = rgba32_to_bgr24
+ },
+ [PIX_FMT_RGB565] = {
+ .convert = rgba32_to_rgb565
+ },
+ [PIX_FMT_RGB555] = {
+ .convert = rgba32_to_rgb555
+ },
+ [PIX_FMT_PAL8] = {
+ .convert = rgba32_to_pal8
+ },
+ [PIX_FMT_YUV420P] = {
+ .convert = rgba32_to_yuv420p
+ },
+ [PIX_FMT_GRAY8] = {
+ .convert = rgba32_to_gray
+ },
+ },
+ [PIX_FMT_BGR24] = {
+ [PIX_FMT_RGBA32] = {
+ .convert = bgr24_to_rgba32
+ },
+ [PIX_FMT_RGB24] = {
+ .convert = bgr24_to_rgb24
+ },
+ [PIX_FMT_YUV420P] = {
+ .convert = bgr24_to_yuv420p
+ },
+ [PIX_FMT_GRAY8] = {
+ .convert = bgr24_to_gray
+ },
+ },
+ [PIX_FMT_RGB555] = {
+ [PIX_FMT_RGB24] = {
+ .convert = rgb555_to_rgb24
+ },
+ [PIX_FMT_RGBA32] = {
+ .convert = rgb555_to_rgba32
+ },
+ [PIX_FMT_YUV420P] = {
+ .convert = rgb555_to_yuv420p
+ },
+ [PIX_FMT_GRAY8] = {
+ .convert = rgb555_to_gray
+ },
+ },
+ [PIX_FMT_RGB565] = {
+ [PIX_FMT_RGBA32] = {
+ .convert = rgb565_to_rgba32
+ },
+ [PIX_FMT_RGB24] = {
+ .convert = rgb565_to_rgb24
+ },
+ [PIX_FMT_YUV420P] = {
+ .convert = rgb565_to_yuv420p
+ },
+ [PIX_FMT_GRAY8] = {
+ .convert = rgb565_to_gray
+ },
+ },
+ [PIX_FMT_GRAY16BE] = {
+ [PIX_FMT_GRAY8] = {
+ .convert = gray16be_to_gray
+ },
+ [PIX_FMT_GRAY16LE] = {
+ .convert = gray16_to_gray16
+ },
+ },
+ [PIX_FMT_GRAY16LE] = {
+ [PIX_FMT_GRAY8] = {
+ .convert = gray16le_to_gray
+ },
+ [PIX_FMT_GRAY16BE] = {
+ .convert = gray16_to_gray16
+ },
+ },
+ [PIX_FMT_GRAY8] = {
+ [PIX_FMT_RGB555] = {
+ .convert = gray_to_rgb555
+ },
+ [PIX_FMT_RGB565] = {
+ .convert = gray_to_rgb565
+ },
+ [PIX_FMT_RGB24] = {
+ .convert = gray_to_rgb24
+ },
+ [PIX_FMT_BGR24] = {
+ .convert = gray_to_bgr24
+ },
+ [PIX_FMT_RGBA32] = {
+ .convert = gray_to_rgba32
+ },
+ [PIX_FMT_MONOWHITE] = {
+ .convert = gray_to_monowhite
+ },
+ [PIX_FMT_MONOBLACK] = {
+ .convert = gray_to_monoblack
+ },
+ [PIX_FMT_GRAY16LE] = {
+ .convert = gray_to_gray16
+ },
+ [PIX_FMT_GRAY16BE] = {
+ .convert = gray_to_gray16
+ },
+ },
+ [PIX_FMT_MONOWHITE] = {
+ [PIX_FMT_GRAY8] = {
+ .convert = monowhite_to_gray
+ },
+ },
+ [PIX_FMT_MONOBLACK] = {
+ [PIX_FMT_GRAY8] = {
+ .convert = monoblack_to_gray
+ },
+ },
+ [PIX_FMT_PAL8] = {
+ [PIX_FMT_RGB555] = {
+ .convert = pal8_to_rgb555
+ },
+ [PIX_FMT_RGB565] = {
+ .convert = pal8_to_rgb565
+ },
+ [PIX_FMT_BGR24] = {
+ .convert = pal8_to_bgr24
+ },
+ [PIX_FMT_RGB24] = {
+ .convert = pal8_to_rgb24
+ },
+ [PIX_FMT_RGBA32] = {
+ .convert = pal8_to_rgba32
+ },
+ },
+ [PIX_FMT_UYVY411] = {
+ [PIX_FMT_YUV411P] = {
+ .convert = uyvy411_to_yuv411p,
+ },
+ },
+
+};
+
+int avpicture_alloc(AVPicture *picture,
+ int pix_fmt, int width, int height)
+{
+ int size;
+ void *ptr;
+
+ size = avpicture_get_size(pix_fmt, width, height);
+ if(size<0)
+ goto fail;
+ ptr = av_malloc(size);
+ if (!ptr)
+ goto fail;
+ avpicture_fill(picture, ptr, pix_fmt, width, height);
+ return 0;
+ fail:
+ memset(picture, 0, sizeof(AVPicture));
+ return -1;
+}
+
+void avpicture_free(AVPicture *picture)
+{
+ av_free(picture->data[0]);
+}
+
+/* return true if yuv planar */
+static inline int is_yuv_planar(const PixFmtInfo *ps)
+{
+ return (ps->color_type == FF_COLOR_YUV ||
+ ps->color_type == FF_COLOR_YUV_JPEG) &&
+ ps->pixel_type == FF_PIXEL_PLANAR;
+}
+
+/**
+ * Crop image top and left side
+ */
+int img_crop(AVPicture *dst, const AVPicture *src,
+ int pix_fmt, int top_band, int left_band)
+{
+ int y_shift;
+ int x_shift;
+
+ if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB || !is_yuv_planar(&pix_fmt_info[pix_fmt]))
+ return -1;
+
+ y_shift = pix_fmt_info[pix_fmt].y_chroma_shift;
+ x_shift = pix_fmt_info[pix_fmt].x_chroma_shift;
+
+ 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);
+
+ dst->linesize[0] = src->linesize[0];
+ dst->linesize[1] = src->linesize[1];
+ dst->linesize[2] = src->linesize[2];
+ return 0;
+}
+
+/**
+ * Pad image
+ */
+int img_pad(AVPicture *dst, const AVPicture *src, int height, int width, int pix_fmt,
+ int padtop, int padbottom, int padleft, int padright, int *color)
+{
+ uint8_t *optr, *iptr;
+ int y_shift;
+ int x_shift;
+ int yheight;
+ int i, y;
+
+ if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB || !is_yuv_planar(&pix_fmt_info[pix_fmt]))
+ return -1;
+
+ for (i = 0; i < 3; i++) {
+ x_shift = i ? pix_fmt_info[pix_fmt].x_chroma_shift : 0;
+ y_shift = i ? pix_fmt_info[pix_fmt].y_chroma_shift : 0;
+
+ if (padtop || padleft) {
+ memset(dst->data[i], color[i], dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
+ }
+
+ if (padleft || padright || src) {
+ if (src) { /* first line */
+ iptr = src->data[i];
+ optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift);
+ memcpy(optr, iptr, src->linesize[i]);
+ 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);
+ if (src) {
+ memcpy(optr + ((padleft + padright) >> x_shift), iptr, src->linesize[i]);
+ 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;
+}
+
+#ifndef CONFIG_SWSCALER
+/* XXX: always use linesize. Return -1 if not supported */
+int img_convert(AVPicture *dst, int dst_pix_fmt,
+ const AVPicture *src, int src_pix_fmt,
+ int src_width, int src_height)
+{
+ static int inited;
+ int i, ret, dst_width, dst_height, int_pix_fmt;
+ const PixFmtInfo *src_pix, *dst_pix;
+ const ConvertEntry *ce;
+ AVPicture tmp1, *tmp = &tmp1;
+
+ if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB ||
+ dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB)
+ return -1;
+ if (src_width <= 0 || src_height <= 0)
+ return 0;
+
+ if (!inited) {
+ inited = 1;
+ img_convert_init();
+ }
+
+ dst_width = src_width;
+ dst_height = src_height;
+
+ dst_pix = &pix_fmt_info[dst_pix_fmt];
+ src_pix = &pix_fmt_info[src_pix_fmt];
+ if (src_pix_fmt == dst_pix_fmt) {
+ /* no conversion needed: just copy */
+ img_copy(dst, src, dst_pix_fmt, dst_width, dst_height);
+ return 0;
+ }
+
+ ce = &convert_table[src_pix_fmt][dst_pix_fmt];
+ if (ce->convert) {
+ /* specific conversion routine */
+ ce->convert(dst, src, dst_width, dst_height);
+ return 0;
+ }
+
+ /* gray to YUV */
+ if (is_yuv_planar(dst_pix) &&
+ src_pix_fmt == PIX_FMT_GRAY8) {
+ int w, h, y;
+ uint8_t *d;
+
+ if (dst_pix->color_type == FF_COLOR_YUV_JPEG) {
+ ff_img_copy_plane(dst->data[0], dst->linesize[0],
+ src->data[0], src->linesize[0],
+ dst_width, dst_height);
+ } else {
+ img_apply_table(dst->data[0], dst->linesize[0],
+ src->data[0], src->linesize[0],
+ dst_width, dst_height,
+ y_jpeg_to_ccir);
+ }
+ /* fill U and V with 128 */
+ w = dst_width;
+ h = dst_height;
+ w >>= dst_pix->x_chroma_shift;
+ h >>= dst_pix->y_chroma_shift;
+ for(i = 1; i <= 2; i++) {
+ d = dst->data[i];
+ for(y = 0; y< h; y++) {
+ memset(d, 128, w);
+ d += dst->linesize[i];
+ }
+ }
+ return 0;
+ }
+
+ /* YUV to gray */
+ if (is_yuv_planar(src_pix) &&
+ dst_pix_fmt == PIX_FMT_GRAY8) {
+ if (src_pix->color_type == FF_COLOR_YUV_JPEG) {
+ ff_img_copy_plane(dst->data[0], dst->linesize[0],
+ src->data[0], src->linesize[0],
+ dst_width, dst_height);
+ } else {
+ img_apply_table(dst->data[0], dst->linesize[0],
+ src->data[0], src->linesize[0],
+ dst_width, dst_height,
+ y_ccir_to_jpeg);
+ }
+ return 0;
+ }
+
+ /* YUV to YUV planar */
+ if (is_yuv_planar(dst_pix) && is_yuv_planar(src_pix)) {
+ int x_shift, y_shift, w, h, xy_shift;
+ void (*resize_func)(uint8_t *dst, int dst_wrap,
+ const uint8_t *src, int src_wrap,
+ int width, int height);
+
+ /* compute chroma size of the smallest dimensions */
+ w = dst_width;
+ h = dst_height;
+ if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift)
+ w >>= dst_pix->x_chroma_shift;
+ else
+ w >>= src_pix->x_chroma_shift;
+ if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift)
+ h >>= dst_pix->y_chroma_shift;
+ else
+ h >>= src_pix->y_chroma_shift;
+
+ x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift);
+ y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift);
+ xy_shift = ((x_shift & 0xf) << 4) | (y_shift & 0xf);
+ /* there must be filters for conversion at least from and to
+ YUV444 format */
+ switch(xy_shift) {
+ case 0x00:
+ resize_func = ff_img_copy_plane;
+ break;
+ case 0x10:
+ resize_func = shrink21;
+ break;
+ case 0x20:
+ resize_func = shrink41;
+ break;
+ case 0x01:
+ resize_func = shrink12;
+ break;
+ case 0x11:
+ resize_func = ff_shrink22;
+ break;
+ case 0x22:
+ resize_func = ff_shrink44;
+ break;
+ case 0xf0:
+ resize_func = grow21;
+ break;
+ case 0xe0:
+ resize_func = grow41;
+ break;
+ case 0xff:
+ resize_func = grow22;
+ break;
+ case 0xee:
+ resize_func = grow44;
+ break;
+ case 0xf1:
+ resize_func = conv411;
+ break;
+ default:
+ /* currently not handled */
+ goto no_chroma_filter;
+ }
+
+ ff_img_copy_plane(dst->data[0], dst->linesize[0],
+ src->data[0], src->linesize[0],
+ dst_width, dst_height);
+
+ for(i = 1;i <= 2; i++)
+ resize_func(dst->data[i], dst->linesize[i],
+ src->data[i], src->linesize[i],
+ dst_width>>dst_pix->x_chroma_shift, dst_height>>dst_pix->y_chroma_shift);
+ /* if yuv color space conversion is needed, we do it here on
+ the destination image */
+ if (dst_pix->color_type != src_pix->color_type) {
+ const uint8_t *y_table, *c_table;
+ if (dst_pix->color_type == FF_COLOR_YUV) {
+ y_table = y_jpeg_to_ccir;
+ c_table = c_jpeg_to_ccir;
+ } else {
+ y_table = y_ccir_to_jpeg;
+ c_table = c_ccir_to_jpeg;
+ }
+ img_apply_table(dst->data[0], dst->linesize[0],
+ dst->data[0], dst->linesize[0],
+ dst_width, dst_height,
+ y_table);
+
+ for(i = 1;i <= 2; i++)
+ img_apply_table(dst->data[i], dst->linesize[i],
+ dst->data[i], dst->linesize[i],
+ dst_width>>dst_pix->x_chroma_shift,
+ dst_height>>dst_pix->y_chroma_shift,
+ c_table);
+ }
+ return 0;
+ }
+ no_chroma_filter:
+
+ /* try to use an intermediate format */
+ if (src_pix_fmt == PIX_FMT_YUV422 ||
+ dst_pix_fmt == PIX_FMT_YUV422) {
+ /* specific case: convert to YUV422P first */
+ int_pix_fmt = PIX_FMT_YUV422P;
+ } else if (src_pix_fmt == PIX_FMT_UYVY422 ||
+ dst_pix_fmt == PIX_FMT_UYVY422) {
+ /* specific case: convert to YUV422P first */
+ int_pix_fmt = PIX_FMT_YUV422P;
+ } else if (src_pix_fmt == PIX_FMT_UYVY411 ||
+ dst_pix_fmt == PIX_FMT_UYVY411) {
+ /* specific case: convert to YUV411P first */
+ int_pix_fmt = PIX_FMT_YUV411P;
+ } else if ((src_pix->color_type == FF_COLOR_GRAY &&
+ src_pix_fmt != PIX_FMT_GRAY8) ||
+ (dst_pix->color_type == FF_COLOR_GRAY &&
+ dst_pix_fmt != PIX_FMT_GRAY8)) {
+ /* gray8 is the normalized format */
+ int_pix_fmt = PIX_FMT_GRAY8;
+ } else if ((is_yuv_planar(src_pix) &&
+ src_pix_fmt != PIX_FMT_YUV444P &&
+ src_pix_fmt != PIX_FMT_YUVJ444P)) {
+ /* yuv444 is the normalized format */
+ if (src_pix->color_type == FF_COLOR_YUV_JPEG)
+ int_pix_fmt = PIX_FMT_YUVJ444P;
+ else
+ int_pix_fmt = PIX_FMT_YUV444P;
+ } else if ((is_yuv_planar(dst_pix) &&
+ dst_pix_fmt != PIX_FMT_YUV444P &&
+ dst_pix_fmt != PIX_FMT_YUVJ444P)) {
+ /* yuv444 is the normalized format */
+ if (dst_pix->color_type == FF_COLOR_YUV_JPEG)
+ int_pix_fmt = PIX_FMT_YUVJ444P;
+ else
+ int_pix_fmt = PIX_FMT_YUV444P;
+ } else {
+ /* the two formats are rgb or gray8 or yuv[j]444p */
+ if (src_pix->is_alpha && dst_pix->is_alpha)
+ int_pix_fmt = PIX_FMT_RGBA32;
+ else
+ int_pix_fmt = PIX_FMT_RGB24;
+ }
+ if (avpicture_alloc(tmp, int_pix_fmt, dst_width, dst_height) < 0)
+ return -1;
+ ret = -1;
+ if (img_convert(tmp, int_pix_fmt,
+ src, src_pix_fmt, src_width, src_height) < 0)
+ goto fail1;
+ if (img_convert(dst, dst_pix_fmt,
+ tmp, int_pix_fmt, dst_width, dst_height) < 0)
+ goto fail1;
+ ret = 0;
+ fail1:
+ avpicture_free(tmp);
+ return ret;
+}
+#endif
+
+/* NOTE: we scan all the pixels to have an exact information */
+static int get_alpha_info_pal8(const AVPicture *src, int width, int height)
+{
+ const unsigned char *p;
+ int src_wrap, ret, x, y;
+ unsigned int a;
+ uint32_t *palette = (uint32_t *)src->data[1];
+
+ p = src->data[0];
+ src_wrap = src->linesize[0] - width;
+ ret = 0;
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ a = palette[p[0]] >> 24;
+ if (a == 0x00) {
+ ret |= FF_ALPHA_TRANSP;
+ } else if (a != 0xff) {
+ ret |= FF_ALPHA_SEMI_TRANSP;
+ }
+ p++;
+ }
+ p += src_wrap;
+ }
+ return ret;
+}
+
+/**
+ * Tell if an image really has transparent alpha values.
+ * @return ored mask of FF_ALPHA_xxx constants
+ */
+int img_get_alpha_info(const AVPicture *src,
+ int pix_fmt, int width, int height)
+{
+ const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
+ int ret;
+
+ pf = &pix_fmt_info[pix_fmt];
+ /* no alpha can be represented in format */
+ if (!pf->is_alpha)
+ return 0;
+ switch(pix_fmt) {
+ case PIX_FMT_RGBA32:
+ ret = get_alpha_info_rgba32(src, width, height);
+ break;
+ case PIX_FMT_PAL8:
+ ret = get_alpha_info_pal8(src, width, height);
+ break;
+ default:
+ /* we do not know, so everything is indicated */
+ ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP;
+ break;
+ }
+ return ret;
+}
+
+#ifdef HAVE_MMX
+#define DEINT_INPLACE_LINE_LUM \
+ movd_m2r(lum_m4[0],mm0);\
+ movd_m2r(lum_m3[0],mm1);\
+ movd_m2r(lum_m2[0],mm2);\
+ movd_m2r(lum_m1[0],mm3);\
+ movd_m2r(lum[0],mm4);\
+ punpcklbw_r2r(mm7,mm0);\
+ movd_r2m(mm2,lum_m4[0]);\
+ punpcklbw_r2r(mm7,mm1);\
+ punpcklbw_r2r(mm7,mm2);\
+ punpcklbw_r2r(mm7,mm3);\
+ punpcklbw_r2r(mm7,mm4);\
+ paddw_r2r(mm3,mm1);\
+ psllw_i2r(1,mm2);\
+ paddw_r2r(mm4,mm0);\
+ psllw_i2r(2,mm1);\
+ paddw_r2r(mm6,mm2);\
+ paddw_r2r(mm2,mm1);\
+ psubusw_r2r(mm0,mm1);\
+ psrlw_i2r(3,mm1);\
+ packuswb_r2r(mm7,mm1);\
+ movd_r2m(mm1,lum_m2[0]);
+
+#define DEINT_LINE_LUM \
+ movd_m2r(lum_m4[0],mm0);\
+ movd_m2r(lum_m3[0],mm1);\
+ movd_m2r(lum_m2[0],mm2);\
+ movd_m2r(lum_m1[0],mm3);\
+ movd_m2r(lum[0],mm4);\
+ punpcklbw_r2r(mm7,mm0);\
+ punpcklbw_r2r(mm7,mm1);\
+ punpcklbw_r2r(mm7,mm2);\
+ punpcklbw_r2r(mm7,mm3);\
+ punpcklbw_r2r(mm7,mm4);\
+ paddw_r2r(mm3,mm1);\
+ psllw_i2r(1,mm2);\
+ paddw_r2r(mm4,mm0);\
+ psllw_i2r(2,mm1);\
+ paddw_r2r(mm6,mm2);\
+ paddw_r2r(mm2,mm1);\
+ psubusw_r2r(mm0,mm1);\
+ psrlw_i2r(3,mm1);\
+ packuswb_r2r(mm7,mm1);\
+ movd_r2m(mm1,dst[0]);
+#endif
+
+/* filter parameters: [-1 4 2 4 -1] // 8 */
+static void deinterlace_line(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)
+{
+#ifndef HAVE_MMX
+ 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++;
+ }
+#else
+
+ {
+ mmx_t rounder;
+ rounder.uw[0]=4;
+ rounder.uw[1]=4;
+ rounder.uw[2]=4;
+ rounder.uw[3]=4;
+ pxor_r2r(mm7,mm7);
+ movq_m2r(rounder,mm6);
+ }
+ for (;size > 3; size-=4) {
+ DEINT_LINE_LUM
+ lum_m4+=4;
+ lum_m3+=4;
+ lum_m2+=4;
+ lum_m1+=4;
+ lum+=4;
+ dst+=4;
+ }
+#endif
+}
+static void deinterlace_line_inplace(uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum,
+ int size)
+{
+#ifndef HAVE_MMX
+ 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++;
+ }
+#else
+
+ {
+ mmx_t rounder;
+ rounder.uw[0]=4;
+ rounder.uw[1]=4;
+ rounder.uw[2]=4;
+ rounder.uw[3]=4;
+ pxor_r2r(mm7,mm7);
+ movq_m2r(rounder,mm6);
+ }
+ for (;size > 3; size-=4) {
+ DEINT_INPLACE_LINE_LUM
+ lum_m4+=4;
+ lum_m3+=4;
+ lum_m2+=4;
+ lum_m1+=4;
+ lum+=4;
+ }
+#endif
+}
+
+/* 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 = (uint8_t*)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);
+}
+
+
+/* deinterlace - if not supported return -1 */
+int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
+ int pix_fmt, int width, int height)
+{
+ int i;
+
+ if (pix_fmt != PIX_FMT_YUV420P &&
+ pix_fmt != PIX_FMT_YUV422P &&
+ pix_fmt != PIX_FMT_YUV444P &&
+ pix_fmt != PIX_FMT_YUV411P)
+ return -1;
+ if ((width & 3) != 0 || (height & 3) != 0)
+ return -1;
+
+ for(i=0;i<3;i++) {
+ if (i == 1) {
+ switch(pix_fmt) {
+ case PIX_FMT_YUV420P:
+ width >>= 1;
+ height >>= 1;
+ break;
+ case PIX_FMT_YUV422P:
+ width >>= 1;
+ break;
+ case PIX_FMT_YUV411P:
+ width >>= 2;
+ break;
+ default:
+ 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);
+ }
+ }
+#ifdef HAVE_MMX
+ emms();
+#endif
+ return 0;
+}
+
+#undef FIX
diff --git a/contrib/ffmpeg/libavcodec/imgconvert_template.h b/contrib/ffmpeg/libavcodec/imgconvert_template.h
new file mode 100644
index 000000000..4cc898bab
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/imgconvert_template.h
@@ -0,0 +1,875 @@
+/*
+ * Templates for image convertion 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
+ */
+
+#ifndef RGB_OUT
+#define RGB_OUT(d, r, g, b) RGBA_OUT(d, r, g, b, 0xff)
+#endif
+
+static void glue(yuv420p_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ const uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr;
+ uint8_t *d, *d1, *d2;
+ int w, y, cb, cr, r_add, g_add, b_add, width2;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+ unsigned int r, g, b;
+
+ d = dst->data[0];
+ y1_ptr = src->data[0];
+ cb_ptr = src->data[1];
+ cr_ptr = src->data[2];
+ width2 = (width + 1) >> 1;
+ for(;height >= 2; height -= 2) {
+ d1 = d;
+ d2 = d + dst->linesize[0];
+ y2_ptr = y1_ptr + src->linesize[0];
+ for(w = width; w >= 2; w -= 2) {
+ YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]);
+ /* output 4 pixels */
+ YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
+ RGB_OUT(d1, r, g, b);
+
+ YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[1]);
+ RGB_OUT(d1 + BPP, r, g, b);
+
+ YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[0]);
+ RGB_OUT(d2, r, g, b);
+
+ YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[1]);
+ RGB_OUT(d2 + BPP, r, g, b);
+
+ d1 += 2 * BPP;
+ d2 += 2 * BPP;
+
+ y1_ptr += 2;
+ y2_ptr += 2;
+ cb_ptr++;
+ cr_ptr++;
+ }
+ /* handle odd width */
+ if (w) {
+ YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]);
+ YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
+ RGB_OUT(d1, r, g, b);
+
+ YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[0]);
+ RGB_OUT(d2, r, g, b);
+ d1 += BPP;
+ d2 += BPP;
+ y1_ptr++;
+ y2_ptr++;
+ cb_ptr++;
+ cr_ptr++;
+ }
+ d += 2 * dst->linesize[0];
+ y1_ptr += 2 * src->linesize[0] - width;
+ cb_ptr += src->linesize[1] - width2;
+ cr_ptr += src->linesize[2] - width2;
+ }
+ /* handle odd height */
+ if (height) {
+ d1 = d;
+ for(w = width; w >= 2; w -= 2) {
+ YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]);
+ /* output 2 pixels */
+ YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
+ RGB_OUT(d1, r, g, b);
+
+ YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[1]);
+ RGB_OUT(d1 + BPP, r, g, b);
+
+ d1 += 2 * BPP;
+
+ y1_ptr += 2;
+ cb_ptr++;
+ cr_ptr++;
+ }
+ /* handle width */
+ if (w) {
+ YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]);
+ /* output 2 pixels */
+ YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
+ RGB_OUT(d1, r, g, b);
+ d1 += BPP;
+
+ y1_ptr++;
+ cb_ptr++;
+ cr_ptr++;
+ }
+ }
+}
+
+static void glue(yuvj420p_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ const uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr;
+ uint8_t *d, *d1, *d2;
+ int w, y, cb, cr, r_add, g_add, b_add, width2;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+ unsigned int r, g, b;
+
+ d = dst->data[0];
+ y1_ptr = src->data[0];
+ cb_ptr = src->data[1];
+ cr_ptr = src->data[2];
+ width2 = (width + 1) >> 1;
+ for(;height >= 2; height -= 2) {
+ d1 = d;
+ d2 = d + dst->linesize[0];
+ y2_ptr = y1_ptr + src->linesize[0];
+ for(w = width; w >= 2; w -= 2) {
+ YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]);
+ /* output 4 pixels */
+ YUV_TO_RGB2(r, g, b, y1_ptr[0]);
+ RGB_OUT(d1, r, g, b);
+
+ YUV_TO_RGB2(r, g, b, y1_ptr[1]);
+ RGB_OUT(d1 + BPP, r, g, b);
+
+ YUV_TO_RGB2(r, g, b, y2_ptr[0]);
+ RGB_OUT(d2, r, g, b);
+
+ YUV_TO_RGB2(r, g, b, y2_ptr[1]);
+ RGB_OUT(d2 + BPP, r, g, b);
+
+ d1 += 2 * BPP;
+ d2 += 2 * BPP;
+
+ y1_ptr += 2;
+ y2_ptr += 2;
+ cb_ptr++;
+ cr_ptr++;
+ }
+ /* handle odd width */
+ if (w) {
+ YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]);
+ YUV_TO_RGB2(r, g, b, y1_ptr[0]);
+ RGB_OUT(d1, r, g, b);
+
+ YUV_TO_RGB2(r, g, b, y2_ptr[0]);
+ RGB_OUT(d2, r, g, b);
+ d1 += BPP;
+ d2 += BPP;
+ y1_ptr++;
+ y2_ptr++;
+ cb_ptr++;
+ cr_ptr++;
+ }
+ d += 2 * dst->linesize[0];
+ y1_ptr += 2 * src->linesize[0] - width;
+ cb_ptr += src->linesize[1] - width2;
+ cr_ptr += src->linesize[2] - width2;
+ }
+ /* handle odd height */
+ if (height) {
+ d1 = d;
+ for(w = width; w >= 2; w -= 2) {
+ YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]);
+ /* output 2 pixels */
+ YUV_TO_RGB2(r, g, b, y1_ptr[0]);
+ RGB_OUT(d1, r, g, b);
+
+ YUV_TO_RGB2(r, g, b, y1_ptr[1]);
+ RGB_OUT(d1 + BPP, r, g, b);
+
+ d1 += 2 * BPP;
+
+ y1_ptr += 2;
+ cb_ptr++;
+ cr_ptr++;
+ }
+ /* handle width */
+ if (w) {
+ YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]);
+ /* output 2 pixels */
+ YUV_TO_RGB2(r, g, b, y1_ptr[0]);
+ RGB_OUT(d1, r, g, b);
+ d1 += BPP;
+
+ y1_ptr++;
+ cb_ptr++;
+ cr_ptr++;
+ }
+ }
+}
+
+static void glue(RGB_NAME, _to_yuv420p)(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ int wrap, wrap3, width2;
+ int r, g, b, r1, g1, b1, w;
+ uint8_t *lum, *cb, *cr;
+ const uint8_t *p;
+
+ lum = dst->data[0];
+ cb = dst->data[1];
+ cr = dst->data[2];
+
+ width2 = (width + 1) >> 1;
+ wrap = dst->linesize[0];
+ wrap3 = src->linesize[0];
+ p = src->data[0];
+ for(;height>=2;height -= 2) {
+ for(w = width; w >= 2; w -= 2) {
+ RGB_IN(r, g, b, p);
+ r1 = r;
+ g1 = g;
+ b1 = b;
+ lum[0] = RGB_TO_Y_CCIR(r, g, b);
+
+ RGB_IN(r, g, b, p + BPP);
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[1] = RGB_TO_Y_CCIR(r, g, b);
+ p += wrap3;
+ lum += wrap;
+
+ RGB_IN(r, g, b, p);
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[0] = RGB_TO_Y_CCIR(r, g, b);
+
+ RGB_IN(r, g, b, p + BPP);
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[1] = RGB_TO_Y_CCIR(r, g, b);
+
+ cb[0] = RGB_TO_U_CCIR(r1, g1, b1, 2);
+ cr[0] = RGB_TO_V_CCIR(r1, g1, b1, 2);
+
+ cb++;
+ cr++;
+ p += -wrap3 + 2 * BPP;
+ lum += -wrap + 2;
+ }
+ if (w) {
+ RGB_IN(r, g, b, p);
+ r1 = r;
+ g1 = g;
+ b1 = b;
+ lum[0] = RGB_TO_Y_CCIR(r, g, b);
+ p += wrap3;
+ lum += wrap;
+ RGB_IN(r, g, b, p);
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[0] = RGB_TO_Y_CCIR(r, g, b);
+ cb[0] = RGB_TO_U_CCIR(r1, g1, b1, 1);
+ cr[0] = RGB_TO_V_CCIR(r1, g1, b1, 1);
+ cb++;
+ cr++;
+ p += -wrap3 + BPP;
+ lum += -wrap + 1;
+ }
+ p += wrap3 + (wrap3 - width * BPP);
+ lum += wrap + (wrap - width);
+ cb += dst->linesize[1] - width2;
+ cr += dst->linesize[2] - width2;
+ }
+ /* handle odd height */
+ if (height) {
+ for(w = width; w >= 2; w -= 2) {
+ RGB_IN(r, g, b, p);
+ r1 = r;
+ g1 = g;
+ b1 = b;
+ lum[0] = RGB_TO_Y_CCIR(r, g, b);
+
+ RGB_IN(r, g, b, p + BPP);
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[1] = RGB_TO_Y_CCIR(r, g, b);
+ cb[0] = RGB_TO_U_CCIR(r1, g1, b1, 1);
+ cr[0] = RGB_TO_V_CCIR(r1, g1, b1, 1);
+ cb++;
+ cr++;
+ p += 2 * BPP;
+ lum += 2;
+ }
+ if (w) {
+ RGB_IN(r, g, b, p);
+ lum[0] = RGB_TO_Y_CCIR(r, g, b);
+ cb[0] = RGB_TO_U_CCIR(r, g, b, 0);
+ cr[0] = RGB_TO_V_CCIR(r, g, b, 0);
+ }
+ }
+}
+
+static void glue(RGB_NAME, _to_gray)(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ const unsigned char *p;
+ unsigned char *q;
+ int r, g, b, dst_wrap, src_wrap;
+ int x, y;
+
+ p = src->data[0];
+ src_wrap = src->linesize[0] - BPP * width;
+
+ q = dst->data[0];
+ dst_wrap = dst->linesize[0] - width;
+
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ RGB_IN(r, g, b, p);
+ q[0] = RGB_TO_Y(r, g, b);
+ q++;
+ p += BPP;
+ }
+ p += src_wrap;
+ q += dst_wrap;
+ }
+}
+
+static void glue(gray_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ const unsigned char *p;
+ unsigned char *q;
+ int r, dst_wrap, src_wrap;
+ int x, y;
+
+ p = src->data[0];
+ src_wrap = src->linesize[0] - width;
+
+ q = dst->data[0];
+ dst_wrap = dst->linesize[0] - BPP * width;
+
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ r = p[0];
+ RGB_OUT(q, r, r, r);
+ q += BPP;
+ p ++;
+ }
+ p += src_wrap;
+ q += dst_wrap;
+ }
+}
+
+static void glue(pal8_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ const unsigned char *p;
+ unsigned char *q;
+ int r, g, b, dst_wrap, src_wrap;
+ int x, y;
+ uint32_t v;
+ const uint32_t *palette;
+
+ p = src->data[0];
+ src_wrap = src->linesize[0] - width;
+ palette = (uint32_t *)src->data[1];
+
+ q = dst->data[0];
+ dst_wrap = dst->linesize[0] - BPP * width;
+
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ v = palette[p[0]];
+ r = (v >> 16) & 0xff;
+ g = (v >> 8) & 0xff;
+ b = (v) & 0xff;
+#ifdef RGBA_OUT
+ {
+ int a;
+ a = (v >> 24) & 0xff;
+ RGBA_OUT(q, r, g, b, a);
+ }
+#else
+ RGB_OUT(q, r, g, b);
+#endif
+ q += BPP;
+ p ++;
+ }
+ p += src_wrap;
+ q += dst_wrap;
+ }
+}
+
+// RGB24 has optimised routines
+#if !defined(FMT_RGBA32) && !defined(FMT_RGB24)
+/* alpha support */
+
+static void glue(rgba32_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ const uint8_t *s;
+ uint8_t *d;
+ int src_wrap, dst_wrap, j, y;
+ unsigned int v, r, g, b;
+#ifdef RGBA_OUT
+ unsigned int a;
+#endif
+
+ s = src->data[0];
+ src_wrap = src->linesize[0] - width * 4;
+
+ d = dst->data[0];
+ dst_wrap = dst->linesize[0] - width * BPP;
+
+ for(y=0;y<height;y++) {
+ for(j = 0;j < width; j++) {
+ v = ((const uint32_t *)(s))[0];
+ r = (v >> 16) & 0xff;
+ g = (v >> 8) & 0xff;
+ b = v & 0xff;
+#ifdef RGBA_OUT
+ a = (v >> 24) & 0xff;
+ RGBA_OUT(d, r, g, b, a);
+#else
+ RGB_OUT(d, r, g, b);
+#endif
+ s += 4;
+ d += BPP;
+ }
+ s += src_wrap;
+ d += dst_wrap;
+ }
+}
+
+static void glue(RGB_NAME, _to_rgba32)(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ const uint8_t *s;
+ uint8_t *d;
+ int src_wrap, dst_wrap, j, y;
+ unsigned int r, g, b;
+#ifdef RGBA_IN
+ unsigned int a;
+#endif
+
+ s = src->data[0];
+ src_wrap = src->linesize[0] - width * BPP;
+
+ d = dst->data[0];
+ dst_wrap = dst->linesize[0] - width * 4;
+
+ for(y=0;y<height;y++) {
+ for(j = 0;j < width; j++) {
+#ifdef RGBA_IN
+ RGBA_IN(r, g, b, a, s);
+ ((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;
+#else
+ RGB_IN(r, g, b, s);
+ ((uint32_t *)(d))[0] = (0xff << 24) | (r << 16) | (g << 8) | b;
+#endif
+ d += 4;
+ s += BPP;
+ }
+ s += src_wrap;
+ d += dst_wrap;
+ }
+}
+
+#endif /* !defined(FMT_RGBA32) */
+
+#ifndef FMT_RGB24
+
+static void glue(rgb24_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ const uint8_t *s;
+ uint8_t *d;
+ int src_wrap, dst_wrap, j, y;
+ unsigned int r, g, b;
+
+ s = src->data[0];
+ src_wrap = src->linesize[0] - width * 3;
+
+ d = dst->data[0];
+ dst_wrap = dst->linesize[0] - width * BPP;
+
+ for(y=0;y<height;y++) {
+ for(j = 0;j < width; j++) {
+ r = s[0];
+ g = s[1];
+ b = s[2];
+ RGB_OUT(d, r, g, b);
+ s += 3;
+ d += BPP;
+ }
+ s += src_wrap;
+ d += dst_wrap;
+ }
+}
+
+static void glue(RGB_NAME, _to_rgb24)(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ const uint8_t *s;
+ uint8_t *d;
+ int src_wrap, dst_wrap, j, y;
+ unsigned int r, g , b;
+
+ s = src->data[0];
+ src_wrap = src->linesize[0] - width * BPP;
+
+ d = dst->data[0];
+ dst_wrap = dst->linesize[0] - width * 3;
+
+ for(y=0;y<height;y++) {
+ for(j = 0;j < width; j++) {
+ RGB_IN(r, g, b, s)
+ d[0] = r;
+ d[1] = g;
+ d[2] = b;
+ d += 3;
+ s += BPP;
+ }
+ s += src_wrap;
+ d += dst_wrap;
+ }
+}
+
+#endif /* !FMT_RGB24 */
+
+#ifdef FMT_RGB24
+
+static void yuv444p_to_rgb24(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ const uint8_t *y1_ptr, *cb_ptr, *cr_ptr;
+ uint8_t *d, *d1;
+ int w, y, cb, cr, r_add, g_add, b_add;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+ unsigned int r, g, b;
+
+ d = dst->data[0];
+ y1_ptr = src->data[0];
+ cb_ptr = src->data[1];
+ cr_ptr = src->data[2];
+ for(;height > 0; height --) {
+ d1 = d;
+ for(w = width; w > 0; w--) {
+ YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]);
+
+ YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
+ RGB_OUT(d1, r, g, b);
+ d1 += BPP;
+
+ y1_ptr++;
+ cb_ptr++;
+ cr_ptr++;
+ }
+ d += dst->linesize[0];
+ y1_ptr += src->linesize[0] - width;
+ cb_ptr += src->linesize[1] - width;
+ cr_ptr += src->linesize[2] - width;
+ }
+}
+
+static void yuvj444p_to_rgb24(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ const uint8_t *y1_ptr, *cb_ptr, *cr_ptr;
+ uint8_t *d, *d1;
+ int w, y, cb, cr, r_add, g_add, b_add;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+ unsigned int r, g, b;
+
+ d = dst->data[0];
+ y1_ptr = src->data[0];
+ cb_ptr = src->data[1];
+ cr_ptr = src->data[2];
+ for(;height > 0; height --) {
+ d1 = d;
+ for(w = width; w > 0; w--) {
+ YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]);
+
+ YUV_TO_RGB2(r, g, b, y1_ptr[0]);
+ RGB_OUT(d1, r, g, b);
+ d1 += BPP;
+
+ y1_ptr++;
+ cb_ptr++;
+ cr_ptr++;
+ }
+ d += dst->linesize[0];
+ y1_ptr += src->linesize[0] - width;
+ cb_ptr += src->linesize[1] - width;
+ cr_ptr += src->linesize[2] - width;
+ }
+}
+
+static void rgb24_to_yuv444p(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ int src_wrap, x, y;
+ int r, g, b;
+ uint8_t *lum, *cb, *cr;
+ const uint8_t *p;
+
+ lum = dst->data[0];
+ cb = dst->data[1];
+ cr = dst->data[2];
+
+ src_wrap = src->linesize[0] - width * BPP;
+ p = src->data[0];
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ RGB_IN(r, g, b, p);
+ lum[0] = RGB_TO_Y_CCIR(r, g, b);
+ cb[0] = RGB_TO_U_CCIR(r, g, b, 0);
+ cr[0] = RGB_TO_V_CCIR(r, g, b, 0);
+ p += BPP;
+ cb++;
+ cr++;
+ lum++;
+ }
+ p += src_wrap;
+ lum += dst->linesize[0] - width;
+ cb += dst->linesize[1] - width;
+ cr += dst->linesize[2] - width;
+ }
+}
+
+static void rgb24_to_yuvj420p(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ int wrap, wrap3, width2;
+ int r, g, b, r1, g1, b1, w;
+ uint8_t *lum, *cb, *cr;
+ const uint8_t *p;
+
+ lum = dst->data[0];
+ cb = dst->data[1];
+ cr = dst->data[2];
+
+ width2 = (width + 1) >> 1;
+ wrap = dst->linesize[0];
+ wrap3 = src->linesize[0];
+ p = src->data[0];
+ for(;height>=2;height -= 2) {
+ for(w = width; w >= 2; w -= 2) {
+ RGB_IN(r, g, b, p);
+ r1 = r;
+ g1 = g;
+ b1 = b;
+ lum[0] = RGB_TO_Y(r, g, b);
+
+ RGB_IN(r, g, b, p + BPP);
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[1] = RGB_TO_Y(r, g, b);
+ p += wrap3;
+ lum += wrap;
+
+ RGB_IN(r, g, b, p);
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[0] = RGB_TO_Y(r, g, b);
+
+ RGB_IN(r, g, b, p + BPP);
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[1] = RGB_TO_Y(r, g, b);
+
+ cb[0] = RGB_TO_U(r1, g1, b1, 2);
+ cr[0] = RGB_TO_V(r1, g1, b1, 2);
+
+ cb++;
+ cr++;
+ p += -wrap3 + 2 * BPP;
+ lum += -wrap + 2;
+ }
+ if (w) {
+ RGB_IN(r, g, b, p);
+ r1 = r;
+ g1 = g;
+ b1 = b;
+ lum[0] = RGB_TO_Y(r, g, b);
+ p += wrap3;
+ lum += wrap;
+ RGB_IN(r, g, b, p);
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[0] = RGB_TO_Y(r, g, b);
+ cb[0] = RGB_TO_U(r1, g1, b1, 1);
+ cr[0] = RGB_TO_V(r1, g1, b1, 1);
+ cb++;
+ cr++;
+ p += -wrap3 + BPP;
+ lum += -wrap + 1;
+ }
+ p += wrap3 + (wrap3 - width * BPP);
+ lum += wrap + (wrap - width);
+ cb += dst->linesize[1] - width2;
+ cr += dst->linesize[2] - width2;
+ }
+ /* handle odd height */
+ if (height) {
+ for(w = width; w >= 2; w -= 2) {
+ RGB_IN(r, g, b, p);
+ r1 = r;
+ g1 = g;
+ b1 = b;
+ lum[0] = RGB_TO_Y(r, g, b);
+
+ RGB_IN(r, g, b, p + BPP);
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[1] = RGB_TO_Y(r, g, b);
+ cb[0] = RGB_TO_U(r1, g1, b1, 1);
+ cr[0] = RGB_TO_V(r1, g1, b1, 1);
+ cb++;
+ cr++;
+ p += 2 * BPP;
+ lum += 2;
+ }
+ if (w) {
+ RGB_IN(r, g, b, p);
+ lum[0] = RGB_TO_Y(r, g, b);
+ cb[0] = RGB_TO_U(r, g, b, 0);
+ cr[0] = RGB_TO_V(r, g, b, 0);
+ }
+ }
+}
+
+static void rgb24_to_yuvj444p(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ int src_wrap, x, y;
+ int r, g, b;
+ uint8_t *lum, *cb, *cr;
+ const uint8_t *p;
+
+ lum = dst->data[0];
+ cb = dst->data[1];
+ cr = dst->data[2];
+
+ src_wrap = src->linesize[0] - width * BPP;
+ p = src->data[0];
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ RGB_IN(r, g, b, p);
+ lum[0] = RGB_TO_Y(r, g, b);
+ cb[0] = RGB_TO_U(r, g, b, 0);
+ cr[0] = RGB_TO_V(r, g, b, 0);
+ p += BPP;
+ cb++;
+ cr++;
+ lum++;
+ }
+ p += src_wrap;
+ lum += dst->linesize[0] - width;
+ cb += dst->linesize[1] - width;
+ cr += dst->linesize[2] - width;
+ }
+}
+
+#endif /* FMT_RGB24 */
+
+#if defined(FMT_RGB24) || defined(FMT_RGBA32)
+
+static void glue(RGB_NAME, _to_pal8)(AVPicture *dst, const AVPicture *src,
+ int width, int height)
+{
+ const unsigned char *p;
+ unsigned char *q;
+ int dst_wrap, src_wrap;
+ int x, y, has_alpha;
+ unsigned int r, g, b;
+
+ p = src->data[0];
+ src_wrap = src->linesize[0] - BPP * width;
+
+ q = dst->data[0];
+ dst_wrap = dst->linesize[0] - width;
+ has_alpha = 0;
+
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+#ifdef RGBA_IN
+ {
+ unsigned int a;
+ RGBA_IN(r, g, b, a, p);
+ /* crude approximation for alpha ! */
+ if (a < 0x80) {
+ has_alpha = 1;
+ q[0] = TRANSP_INDEX;
+ } else {
+ q[0] = gif_clut_index(r, g, b);
+ }
+ }
+#else
+ RGB_IN(r, g, b, p);
+ q[0] = gif_clut_index(r, g, b);
+#endif
+ q++;
+ p += BPP;
+ }
+ p += src_wrap;
+ q += dst_wrap;
+ }
+
+ build_rgb_palette(dst->data[1], has_alpha);
+}
+
+#endif /* defined(FMT_RGB24) || defined(FMT_RGBA32) */
+
+#ifdef RGBA_IN
+
+static int glue(get_alpha_info_, RGB_NAME)(const AVPicture *src,
+ int width, int height)
+{
+ const unsigned char *p;
+ int src_wrap, ret, x, y;
+ unsigned int r, g, b, a;
+
+ p = src->data[0];
+ src_wrap = src->linesize[0] - BPP * width;
+ ret = 0;
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ RGBA_IN(r, g, b, a, p);
+ if (a == 0x00) {
+ ret |= FF_ALPHA_TRANSP;
+ } else if (a != 0xff) {
+ ret |= FF_ALPHA_SEMI_TRANSP;
+ }
+ p += BPP;
+ }
+ p += src_wrap;
+ }
+ return ret;
+}
+
+#endif /* RGBA_IN */
+
+#undef RGB_IN
+#undef RGBA_IN
+#undef RGB_OUT
+#undef RGBA_OUT
+#undef BPP
+#undef RGB_NAME
+#undef FMT_RGB24
+#undef FMT_RGBA32
diff --git a/contrib/ffmpeg/libavcodec/imgresample.c b/contrib/ffmpeg/libavcodec/imgresample.c
new file mode 100644
index 000000000..ce1a05ce4
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/imgresample.c
@@ -0,0 +1,947 @@
+/*
+ * High quality image resampling with polyphase filters
+ * 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 imgresample.c
+ * High quality image resampling with polyphase filters .
+ */
+
+#include "avcodec.h"
+#include "swscale.h"
+#include "dsputil.h"
+
+#ifdef USE_FASTMEMCPY
+#include "libvo/fastmemcpy.h"
+#endif
+
+#define NB_COMPONENTS 3
+
+#define PHASE_BITS 4
+#define NB_PHASES (1 << PHASE_BITS)
+#define NB_TAPS 4
+#define FCENTER 1 /* index of the center of the filter */
+//#define TEST 1 /* Test it */
+
+#define POS_FRAC_BITS 16
+#define POS_FRAC (1 << POS_FRAC_BITS)
+/* 6 bits precision is needed for MMX */
+#define FILTER_BITS 8
+
+#define LINE_BUF_HEIGHT (NB_TAPS * 4)
+
+struct SwsContext {
+ struct ImgReSampleContext *resampling_ctx;
+ enum PixelFormat src_pix_fmt, dst_pix_fmt;
+};
+
+struct ImgReSampleContext {
+ int iwidth, iheight, owidth, oheight;
+ int topBand, bottomBand, leftBand, rightBand;
+ int padtop, padbottom, padleft, padright;
+ int pad_owidth, pad_oheight;
+ int h_incr, v_incr;
+ DECLARE_ALIGNED_8(int16_t, h_filters[NB_PHASES][NB_TAPS]); /* horizontal filters */
+ DECLARE_ALIGNED_8(int16_t, v_filters[NB_PHASES][NB_TAPS]); /* vertical filters */
+ uint8_t *line_buf;
+};
+
+void av_build_filter(int16_t *filter, double factor, int tap_count, int phase_count, int scale, int type);
+
+static inline int get_phase(int pos)
+{
+ return ((pos) >> (POS_FRAC_BITS - PHASE_BITS)) & ((1 << PHASE_BITS) - 1);
+}
+
+/* This function must be optimized */
+static void h_resample_fast(uint8_t *dst, int dst_width, const uint8_t *src,
+ int src_width, int src_start, int src_incr,
+ int16_t *filters)
+{
+ int src_pos, phase, sum, i;
+ const uint8_t *s;
+ int16_t *filter;
+
+ src_pos = src_start;
+ for(i=0;i<dst_width;i++) {
+#ifdef TEST
+ /* test */
+ if ((src_pos >> POS_FRAC_BITS) < 0 ||
+ (src_pos >> POS_FRAC_BITS) > (src_width - NB_TAPS))
+ av_abort();
+#endif
+ s = src + (src_pos >> POS_FRAC_BITS);
+ phase = get_phase(src_pos);
+ filter = filters + phase * NB_TAPS;
+#if NB_TAPS == 4
+ sum = s[0] * filter[0] +
+ s[1] * filter[1] +
+ s[2] * filter[2] +
+ s[3] * filter[3];
+#else
+ {
+ int j;
+ sum = 0;
+ for(j=0;j<NB_TAPS;j++)
+ sum += s[j] * filter[j];
+ }
+#endif
+ sum = sum >> FILTER_BITS;
+ if (sum < 0)
+ sum = 0;
+ else if (sum > 255)
+ sum = 255;
+ dst[0] = sum;
+ src_pos += src_incr;
+ dst++;
+ }
+}
+
+/* This function must be optimized */
+static void v_resample(uint8_t *dst, int dst_width, const uint8_t *src,
+ int wrap, int16_t *filter)
+{
+ int sum, i;
+ const uint8_t *s;
+
+ s = src;
+ for(i=0;i<dst_width;i++) {
+#if NB_TAPS == 4
+ sum = s[0 * wrap] * filter[0] +
+ s[1 * wrap] * filter[1] +
+ s[2 * wrap] * filter[2] +
+ s[3 * wrap] * filter[3];
+#else
+ {
+ int j;
+ uint8_t *s1 = s;
+
+ sum = 0;
+ for(j=0;j<NB_TAPS;j++) {
+ sum += s1[0] * filter[j];
+ s1 += wrap;
+ }
+ }
+#endif
+ sum = sum >> FILTER_BITS;
+ if (sum < 0)
+ sum = 0;
+ else if (sum > 255)
+ sum = 255;
+ dst[0] = sum;
+ dst++;
+ s++;
+ }
+}
+
+#ifdef HAVE_MMX
+
+#include "i386/mmx.h"
+
+#define FILTER4(reg) \
+{\
+ s = src + (src_pos >> POS_FRAC_BITS);\
+ phase = get_phase(src_pos);\
+ filter = filters + phase * NB_TAPS;\
+ movq_m2r(*s, reg);\
+ punpcklbw_r2r(mm7, reg);\
+ movq_m2r(*filter, mm6);\
+ pmaddwd_r2r(reg, mm6);\
+ movq_r2r(mm6, reg);\
+ psrlq_i2r(32, reg);\
+ paddd_r2r(mm6, reg);\
+ psrad_i2r(FILTER_BITS, reg);\
+ src_pos += src_incr;\
+}
+
+#define DUMP(reg) movq_r2m(reg, tmp); printf(#reg "=%016"PRIx64"\n", tmp.uq);
+
+/* XXX: do four pixels at a time */
+static void h_resample_fast4_mmx(uint8_t *dst, int dst_width,
+ const uint8_t *src, int src_width,
+ int src_start, int src_incr, int16_t *filters)
+{
+ int src_pos, phase;
+ const uint8_t *s;
+ int16_t *filter;
+ mmx_t tmp;
+
+ src_pos = src_start;
+ pxor_r2r(mm7, mm7);
+
+ while (dst_width >= 4) {
+
+ FILTER4(mm0);
+ FILTER4(mm1);
+ FILTER4(mm2);
+ FILTER4(mm3);
+
+ packuswb_r2r(mm7, mm0);
+ packuswb_r2r(mm7, mm1);
+ packuswb_r2r(mm7, mm3);
+ packuswb_r2r(mm7, mm2);
+ movq_r2m(mm0, tmp);
+ dst[0] = tmp.ub[0];
+ movq_r2m(mm1, tmp);
+ dst[1] = tmp.ub[0];
+ movq_r2m(mm2, tmp);
+ dst[2] = tmp.ub[0];
+ movq_r2m(mm3, tmp);
+ dst[3] = tmp.ub[0];
+ dst += 4;
+ dst_width -= 4;
+ }
+ while (dst_width > 0) {
+ FILTER4(mm0);
+ packuswb_r2r(mm7, mm0);
+ movq_r2m(mm0, tmp);
+ dst[0] = tmp.ub[0];
+ dst++;
+ dst_width--;
+ }
+ emms();
+}
+
+static void v_resample4_mmx(uint8_t *dst, int dst_width, const uint8_t *src,
+ int wrap, int16_t *filter)
+{
+ int sum, i, v;
+ const uint8_t *s;
+ mmx_t tmp;
+ mmx_t coefs[4];
+
+ for(i=0;i<4;i++) {
+ v = filter[i];
+ coefs[i].uw[0] = v;
+ coefs[i].uw[1] = v;
+ coefs[i].uw[2] = v;
+ coefs[i].uw[3] = v;
+ }
+
+ pxor_r2r(mm7, mm7);
+ s = src;
+ while (dst_width >= 4) {
+ movq_m2r(s[0 * wrap], mm0);
+ punpcklbw_r2r(mm7, mm0);
+ movq_m2r(s[1 * wrap], mm1);
+ punpcklbw_r2r(mm7, mm1);
+ movq_m2r(s[2 * wrap], mm2);
+ punpcklbw_r2r(mm7, mm2);
+ movq_m2r(s[3 * wrap], mm3);
+ punpcklbw_r2r(mm7, mm3);
+
+ pmullw_m2r(coefs[0], mm0);
+ pmullw_m2r(coefs[1], mm1);
+ pmullw_m2r(coefs[2], mm2);
+ pmullw_m2r(coefs[3], mm3);
+
+ paddw_r2r(mm1, mm0);
+ paddw_r2r(mm3, mm2);
+ paddw_r2r(mm2, mm0);
+ psraw_i2r(FILTER_BITS, mm0);
+
+ packuswb_r2r(mm7, mm0);
+ movq_r2m(mm0, tmp);
+
+ *(uint32_t *)dst = tmp.ud[0];
+ dst += 4;
+ s += 4;
+ dst_width -= 4;
+ }
+ while (dst_width > 0) {
+ sum = s[0 * wrap] * filter[0] +
+ s[1 * wrap] * filter[1] +
+ s[2 * wrap] * filter[2] +
+ s[3 * wrap] * filter[3];
+ sum = sum >> FILTER_BITS;
+ if (sum < 0)
+ sum = 0;
+ else if (sum > 255)
+ sum = 255;
+ dst[0] = sum;
+ dst++;
+ s++;
+ dst_width--;
+ }
+ emms();
+}
+#endif
+
+#ifdef HAVE_ALTIVEC
+typedef union {
+ vector unsigned char v;
+ unsigned char c[16];
+} vec_uc_t;
+
+typedef union {
+ vector signed short v;
+ signed short s[8];
+} vec_ss_t;
+
+void v_resample16_altivec(uint8_t *dst, int dst_width, const uint8_t *src,
+ int wrap, int16_t *filter)
+{
+ int sum, i;
+ const uint8_t *s;
+ vector unsigned char *tv, tmp, dstv, zero;
+ vec_ss_t srchv[4], srclv[4], fv[4];
+ vector signed short zeros, sumhv, sumlv;
+ s = src;
+
+ for(i=0;i<4;i++)
+ {
+ /*
+ The vec_madds later on does an implicit >>15 on the result.
+ Since FILTER_BITS is 8, and we have 15 bits of magnitude in
+ a signed short, we have just enough bits to pre-shift our
+ filter constants <<7 to compensate for vec_madds.
+ */
+ fv[i].s[0] = filter[i] << (15-FILTER_BITS);
+ fv[i].v = vec_splat(fv[i].v, 0);
+ }
+
+ zero = vec_splat_u8(0);
+ zeros = vec_splat_s16(0);
+
+
+ /*
+ When we're resampling, we'd ideally like both our input buffers,
+ and output buffers to be 16-byte aligned, so we can do both aligned
+ reads and writes. Sadly we can't always have this at the moment, so
+ we opt for aligned writes, as unaligned writes have a huge overhead.
+ To do this, do enough scalar resamples to get dst 16-byte aligned.
+ */
+ i = (-(int)dst) & 0xf;
+ while(i>0) {
+ sum = s[0 * wrap] * filter[0] +
+ s[1 * wrap] * filter[1] +
+ s[2 * wrap] * filter[2] +
+ s[3 * wrap] * filter[3];
+ sum = sum >> FILTER_BITS;
+ if (sum<0) sum = 0; else if (sum>255) sum=255;
+ dst[0] = sum;
+ dst++;
+ s++;
+ dst_width--;
+ i--;
+ }
+
+ /* Do our altivec resampling on 16 pixels at once. */
+ while(dst_width>=16) {
+ /*
+ Read 16 (potentially unaligned) bytes from each of
+ 4 lines into 4 vectors, and split them into shorts.
+ Interleave the multipy/accumulate for the resample
+ filter with the loads to hide the 3 cycle latency
+ the vec_madds have.
+ */
+ tv = (vector unsigned char *) &s[0 * wrap];
+ tmp = vec_perm(tv[0], tv[1], vec_lvsl(0, &s[i * wrap]));
+ srchv[0].v = (vector signed short) vec_mergeh(zero, tmp);
+ srclv[0].v = (vector signed short) vec_mergel(zero, tmp);
+ sumhv = vec_madds(srchv[0].v, fv[0].v, zeros);
+ sumlv = vec_madds(srclv[0].v, fv[0].v, zeros);
+
+ tv = (vector unsigned char *) &s[1 * wrap];
+ tmp = vec_perm(tv[0], tv[1], vec_lvsl(0, &s[1 * wrap]));
+ srchv[1].v = (vector signed short) vec_mergeh(zero, tmp);
+ srclv[1].v = (vector signed short) vec_mergel(zero, tmp);
+ sumhv = vec_madds(srchv[1].v, fv[1].v, sumhv);
+ sumlv = vec_madds(srclv[1].v, fv[1].v, sumlv);
+
+ tv = (vector unsigned char *) &s[2 * wrap];
+ tmp = vec_perm(tv[0], tv[1], vec_lvsl(0, &s[2 * wrap]));
+ srchv[2].v = (vector signed short) vec_mergeh(zero, tmp);
+ srclv[2].v = (vector signed short) vec_mergel(zero, tmp);
+ sumhv = vec_madds(srchv[2].v, fv[2].v, sumhv);
+ sumlv = vec_madds(srclv[2].v, fv[2].v, sumlv);
+
+ tv = (vector unsigned char *) &s[3 * wrap];
+ tmp = vec_perm(tv[0], tv[1], vec_lvsl(0, &s[3 * wrap]));
+ srchv[3].v = (vector signed short) vec_mergeh(zero, tmp);
+ srclv[3].v = (vector signed short) vec_mergel(zero, tmp);
+ sumhv = vec_madds(srchv[3].v, fv[3].v, sumhv);
+ sumlv = vec_madds(srclv[3].v, fv[3].v, sumlv);
+
+ /*
+ Pack the results into our destination vector,
+ and do an aligned write of that back to memory.
+ */
+ dstv = vec_packsu(sumhv, sumlv) ;
+ vec_st(dstv, 0, (vector unsigned char *) dst);
+
+ dst+=16;
+ s+=16;
+ dst_width-=16;
+ }
+
+ /*
+ If there are any leftover pixels, resample them
+ with the slow scalar method.
+ */
+ while(dst_width>0) {
+ sum = s[0 * wrap] * filter[0] +
+ s[1 * wrap] * filter[1] +
+ s[2 * wrap] * filter[2] +
+ s[3 * wrap] * filter[3];
+ sum = sum >> FILTER_BITS;
+ if (sum<0) sum = 0; else if (sum>255) sum=255;
+ dst[0] = sum;
+ dst++;
+ s++;
+ dst_width--;
+ }
+}
+#endif
+
+/* slow version to handle limit cases. Does not need optimisation */
+static void h_resample_slow(uint8_t *dst, int dst_width,
+ const uint8_t *src, int src_width,
+ int src_start, int src_incr, int16_t *filters)
+{
+ int src_pos, phase, sum, j, v, i;
+ const uint8_t *s, *src_end;
+ int16_t *filter;
+
+ src_end = src + src_width;
+ src_pos = src_start;
+ for(i=0;i<dst_width;i++) {
+ s = src + (src_pos >> POS_FRAC_BITS);
+ phase = get_phase(src_pos);
+ filter = filters + phase * NB_TAPS;
+ sum = 0;
+ for(j=0;j<NB_TAPS;j++) {
+ if (s < src)
+ v = src[0];
+ else if (s >= src_end)
+ v = src_end[-1];
+ else
+ v = s[0];
+ sum += v * filter[j];
+ s++;
+ }
+ sum = sum >> FILTER_BITS;
+ if (sum < 0)
+ sum = 0;
+ else if (sum > 255)
+ sum = 255;
+ dst[0] = sum;
+ src_pos += src_incr;
+ dst++;
+ }
+}
+
+static void h_resample(uint8_t *dst, int dst_width, const uint8_t *src,
+ int src_width, int src_start, int src_incr,
+ int16_t *filters)
+{
+ int n, src_end;
+
+ if (src_start < 0) {
+ n = (0 - src_start + src_incr - 1) / src_incr;
+ h_resample_slow(dst, n, src, src_width, src_start, src_incr, filters);
+ dst += n;
+ dst_width -= n;
+ src_start += n * src_incr;
+ }
+ src_end = src_start + dst_width * src_incr;
+ if (src_end > ((src_width - NB_TAPS) << POS_FRAC_BITS)) {
+ n = (((src_width - NB_TAPS + 1) << POS_FRAC_BITS) - 1 - src_start) /
+ src_incr;
+ } else {
+ n = dst_width;
+ }
+#ifdef HAVE_MMX
+ if ((mm_flags & MM_MMX) && NB_TAPS == 4)
+ h_resample_fast4_mmx(dst, n,
+ src, src_width, src_start, src_incr, filters);
+ else
+#endif
+ h_resample_fast(dst, n,
+ src, src_width, src_start, src_incr, filters);
+ if (n < dst_width) {
+ dst += n;
+ dst_width -= n;
+ src_start += n * src_incr;
+ h_resample_slow(dst, dst_width,
+ src, src_width, src_start, src_incr, filters);
+ }
+}
+
+static void component_resample(ImgReSampleContext *s,
+ uint8_t *output, int owrap, int owidth, int oheight,
+ uint8_t *input, int iwrap, int iwidth, int iheight)
+{
+ int src_y, src_y1, last_src_y, ring_y, phase_y, y1, y;
+ uint8_t *new_line, *src_line;
+
+ last_src_y = - FCENTER - 1;
+ /* position of the bottom of the filter in the source image */
+ src_y = (last_src_y + NB_TAPS) * POS_FRAC;
+ ring_y = NB_TAPS; /* position in ring buffer */
+ for(y=0;y<oheight;y++) {
+ /* apply horizontal filter on new lines from input if needed */
+ src_y1 = src_y >> POS_FRAC_BITS;
+ while (last_src_y < src_y1) {
+ if (++ring_y >= LINE_BUF_HEIGHT + NB_TAPS)
+ ring_y = NB_TAPS;
+ last_src_y++;
+ /* handle limit conditions : replicate line (slightly
+ inefficient because we filter multiple times) */
+ y1 = last_src_y;
+ if (y1 < 0) {
+ y1 = 0;
+ } else if (y1 >= iheight) {
+ y1 = iheight - 1;
+ }
+ src_line = input + y1 * iwrap;
+ new_line = s->line_buf + ring_y * owidth;
+ /* apply filter and handle limit cases correctly */
+ h_resample(new_line, owidth,
+ src_line, iwidth, - FCENTER * POS_FRAC, s->h_incr,
+ &s->h_filters[0][0]);
+ /* handle ring buffer wraping */
+ if (ring_y >= LINE_BUF_HEIGHT) {
+ memcpy(s->line_buf + (ring_y - LINE_BUF_HEIGHT) * owidth,
+ new_line, owidth);
+ }
+ }
+ /* apply vertical filter */
+ phase_y = get_phase(src_y);
+#ifdef HAVE_MMX
+ /* desactivated MMX because loss of precision */
+ if ((mm_flags & MM_MMX) && NB_TAPS == 4 && 0)
+ v_resample4_mmx(output, owidth,
+ s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
+ &s->v_filters[phase_y][0]);
+ else
+#endif
+#ifdef HAVE_ALTIVEC
+ if ((mm_flags & MM_ALTIVEC) && NB_TAPS == 4 && FILTER_BITS <= 6)
+ v_resample16_altivec(output, owidth,
+ s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
+ &s->v_filters[phase_y][0]);
+ else
+#endif
+ v_resample(output, owidth,
+ s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
+ &s->v_filters[phase_y][0]);
+
+ src_y += s->v_incr;
+
+ output += owrap;
+ }
+}
+
+ImgReSampleContext *img_resample_init(int owidth, int oheight,
+ int iwidth, int iheight)
+{
+ return img_resample_full_init(owidth, oheight, iwidth, iheight,
+ 0, 0, 0, 0, 0, 0, 0, 0);
+}
+
+ImgReSampleContext *img_resample_full_init(int owidth, int oheight,
+ int iwidth, int iheight,
+ int topBand, int bottomBand,
+ int leftBand, int rightBand,
+ int padtop, int padbottom,
+ int padleft, int padright)
+{
+ ImgReSampleContext *s;
+
+ if (!owidth || !oheight || !iwidth || !iheight)
+ return NULL;
+
+ s = av_mallocz(sizeof(ImgReSampleContext));
+ if (!s)
+ return NULL;
+ if((unsigned)owidth >= UINT_MAX / (LINE_BUF_HEIGHT + NB_TAPS))
+ return NULL;
+ s->line_buf = av_mallocz(owidth * (LINE_BUF_HEIGHT + NB_TAPS));
+ if (!s->line_buf)
+ goto fail;
+
+ s->owidth = owidth;
+ s->oheight = oheight;
+ s->iwidth = iwidth;
+ s->iheight = iheight;
+
+ s->topBand = topBand;
+ s->bottomBand = bottomBand;
+ s->leftBand = leftBand;
+ s->rightBand = rightBand;
+
+ s->padtop = padtop;
+ s->padbottom = padbottom;
+ s->padleft = padleft;
+ s->padright = padright;
+
+ s->pad_owidth = owidth - (padleft + padright);
+ s->pad_oheight = oheight - (padtop + padbottom);
+
+ s->h_incr = ((iwidth - leftBand - rightBand) * POS_FRAC) / s->pad_owidth;
+ s->v_incr = ((iheight - topBand - bottomBand) * POS_FRAC) / s->pad_oheight;
+
+ av_build_filter(&s->h_filters[0][0], (float) s->pad_owidth /
+ (float) (iwidth - leftBand - rightBand), NB_TAPS, NB_PHASES, 1<<FILTER_BITS, 0);
+ av_build_filter(&s->v_filters[0][0], (float) s->pad_oheight /
+ (float) (iheight - topBand - bottomBand), NB_TAPS, NB_PHASES, 1<<FILTER_BITS, 0);
+
+ return s;
+fail:
+ av_free(s);
+ return NULL;
+}
+
+void img_resample(ImgReSampleContext *s,
+ AVPicture *output, const AVPicture *input)
+{
+ int i, shift;
+ uint8_t* optr;
+
+ for (i=0;i<3;i++) {
+ shift = (i == 0) ? 0 : 1;
+
+ optr = output->data[i] + (((output->linesize[i] *
+ s->padtop) + s->padleft) >> shift);
+
+ component_resample(s, optr, output->linesize[i],
+ s->pad_owidth >> shift, s->pad_oheight >> shift,
+ input->data[i] + (input->linesize[i] *
+ (s->topBand >> shift)) + (s->leftBand >> shift),
+ input->linesize[i], ((s->iwidth - s->leftBand -
+ s->rightBand) >> shift),
+ (s->iheight - s->topBand - s->bottomBand) >> shift);
+ }
+}
+
+void img_resample_close(ImgReSampleContext *s)
+{
+ av_free(s->line_buf);
+ av_free(s);
+}
+
+struct SwsContext *sws_getContext(int srcW, int srcH, int srcFormat,
+ int dstW, int dstH, int dstFormat,
+ int flags, SwsFilter *srcFilter,
+ SwsFilter *dstFilter, double *param)
+{
+ struct SwsContext *ctx;
+
+ ctx = av_malloc(sizeof(struct SwsContext));
+ if (ctx == NULL) {
+ av_log(NULL, AV_LOG_ERROR, "Cannot allocate a resampling context!\n");
+
+ return NULL;
+ }
+
+ if ((srcH != dstH) || (srcW != dstW)) {
+ if ((srcFormat != PIX_FMT_YUV420P) || (dstFormat != PIX_FMT_YUV420P)) {
+ av_log(NULL, AV_LOG_INFO, "PIX_FMT_YUV420P will be used as an intermediate format for rescaling\n");
+ }
+ ctx->resampling_ctx = img_resample_init(dstW, dstH, srcW, srcH);
+ } else {
+ ctx->resampling_ctx = av_malloc(sizeof(ImgReSampleContext));
+ ctx->resampling_ctx->iheight = srcH;
+ ctx->resampling_ctx->iwidth = srcW;
+ ctx->resampling_ctx->oheight = dstH;
+ ctx->resampling_ctx->owidth = dstW;
+ }
+ ctx->src_pix_fmt = srcFormat;
+ ctx->dst_pix_fmt = dstFormat;
+
+ return ctx;
+}
+
+void sws_freeContext(struct SwsContext *ctx)
+{
+ if ((ctx->resampling_ctx->iwidth != ctx->resampling_ctx->owidth) ||
+ (ctx->resampling_ctx->iheight != ctx->resampling_ctx->oheight)) {
+ img_resample_close(ctx->resampling_ctx);
+ } else {
+ av_free(ctx->resampling_ctx);
+ }
+ av_free(ctx);
+}
+
+
+/**
+ * Checks if context is valid or reallocs a new one instead.
+ * If context is NULL, just calls sws_getContext() to get a new one.
+ * Otherwise, checks if the parameters are the same already saved in context.
+ * If that is the case, returns the current context.
+ * Otherwise, frees context and gets a new one.
+ *
+ * Be warned that srcFilter, dstFilter are not checked, they are
+ * asumed to remain valid.
+ */
+struct SwsContext *sws_getCachedContext(struct SwsContext *ctx,
+ int srcW, int srcH, int srcFormat,
+ int dstW, int dstH, int dstFormat, int flags,
+ SwsFilter *srcFilter, SwsFilter *dstFilter, double *param)
+{
+ if (ctx != NULL) {
+ if ((ctx->resampling_ctx->iwidth != srcW) ||
+ (ctx->resampling_ctx->iheight != srcH) ||
+ (ctx->src_pix_fmt != srcFormat) ||
+ (ctx->resampling_ctx->owidth != dstW) ||
+ (ctx->resampling_ctx->oheight != dstH) ||
+ (ctx->dst_pix_fmt != dstFormat))
+ {
+ sws_freeContext(ctx);
+ ctx = NULL;
+ }
+ }
+ if (ctx == NULL) {
+ return sws_getContext(srcW, srcH, srcFormat,
+ dstW, dstH, dstFormat, flags,
+ srcFilter, dstFilter, param);
+ }
+ return ctx;
+}
+
+int sws_scale(struct SwsContext *ctx, uint8_t* src[], int srcStride[],
+ int srcSliceY, int srcSliceH, uint8_t* dst[], int dstStride[])
+{
+ AVPicture src_pict, dst_pict;
+ int i, res = 0;
+ AVPicture picture_format_temp;
+ AVPicture picture_resample_temp, *formatted_picture, *resampled_picture;
+ uint8_t *buf1 = NULL, *buf2 = NULL;
+ enum PixelFormat current_pix_fmt;
+
+ for (i = 0; i < 4; i++) {
+ src_pict.data[i] = src[i];
+ src_pict.linesize[i] = srcStride[i];
+ dst_pict.data[i] = dst[i];
+ dst_pict.linesize[i] = dstStride[i];
+ }
+ if ((ctx->resampling_ctx->iwidth != ctx->resampling_ctx->owidth) ||
+ (ctx->resampling_ctx->iheight != ctx->resampling_ctx->oheight)) {
+ /* We have to rescale the picture, but only YUV420P rescaling is supported... */
+
+ if (ctx->src_pix_fmt != PIX_FMT_YUV420P) {
+ int size;
+
+ /* create temporary picture for rescaling input*/
+ size = avpicture_get_size(PIX_FMT_YUV420P, ctx->resampling_ctx->iwidth, ctx->resampling_ctx->iheight);
+ buf1 = av_malloc(size);
+ if (!buf1) {
+ res = -1;
+ goto the_end;
+ }
+ formatted_picture = &picture_format_temp;
+ avpicture_fill((AVPicture*)formatted_picture, buf1,
+ PIX_FMT_YUV420P, ctx->resampling_ctx->iwidth, ctx->resampling_ctx->iheight);
+
+ if (img_convert((AVPicture*)formatted_picture, PIX_FMT_YUV420P,
+ &src_pict, ctx->src_pix_fmt,
+ ctx->resampling_ctx->iwidth, ctx->resampling_ctx->iheight) < 0) {
+
+ av_log(NULL, AV_LOG_ERROR, "pixel format conversion not handled\n");
+ res = -1;
+ goto the_end;
+ }
+ } else {
+ formatted_picture = &src_pict;
+ }
+
+ if (ctx->dst_pix_fmt != PIX_FMT_YUV420P) {
+ int size;
+
+ /* create temporary picture for rescaling output*/
+ size = avpicture_get_size(PIX_FMT_YUV420P, ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight);
+ buf2 = av_malloc(size);
+ if (!buf2) {
+ res = -1;
+ goto the_end;
+ }
+ resampled_picture = &picture_resample_temp;
+ avpicture_fill((AVPicture*)resampled_picture, buf2,
+ PIX_FMT_YUV420P, ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight);
+
+ } else {
+ resampled_picture = &dst_pict;
+ }
+
+ /* ...and finally rescale!!! */
+ img_resample(ctx->resampling_ctx, resampled_picture, formatted_picture);
+ current_pix_fmt = PIX_FMT_YUV420P;
+ } else {
+ resampled_picture = &src_pict;
+ current_pix_fmt = ctx->src_pix_fmt;
+ }
+
+ if (current_pix_fmt != ctx->dst_pix_fmt) {
+ if (img_convert(&dst_pict, ctx->dst_pix_fmt,
+ resampled_picture, current_pix_fmt,
+ ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight) < 0) {
+
+ av_log(NULL, AV_LOG_ERROR, "pixel format conversion not handled\n");
+
+ res = -1;
+ goto the_end;
+ }
+ } else if (resampled_picture != &dst_pict) {
+ img_copy(&dst_pict, resampled_picture, current_pix_fmt,
+ ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight);
+ }
+
+the_end:
+ av_free(buf1);
+ av_free(buf2);
+ return res;
+}
+
+
+#ifdef TEST
+#include <stdio.h>
+
+/* input */
+#define XSIZE 256
+#define YSIZE 256
+uint8_t img[XSIZE * YSIZE];
+
+/* output */
+#define XSIZE1 512
+#define YSIZE1 512
+uint8_t img1[XSIZE1 * YSIZE1];
+uint8_t img2[XSIZE1 * YSIZE1];
+
+void save_pgm(const char *filename, uint8_t *img, int xsize, int ysize)
+{
+#undef fprintf
+ FILE *f;
+ f=fopen(filename,"w");
+ fprintf(f,"P5\n%d %d\n%d\n", xsize, ysize, 255);
+ fwrite(img,1, xsize * ysize,f);
+ fclose(f);
+#define fprintf please_use_av_log
+}
+
+static void dump_filter(int16_t *filter)
+{
+ int i, ph;
+
+ for(ph=0;ph<NB_PHASES;ph++) {
+ av_log(NULL, AV_LOG_INFO, "%2d: ", ph);
+ for(i=0;i<NB_TAPS;i++) {
+ av_log(NULL, AV_LOG_INFO, " %5.2f", filter[ph * NB_TAPS + i] / 256.0);
+ }
+ av_log(NULL, AV_LOG_INFO, "\n");
+ }
+}
+
+#ifdef HAVE_MMX
+int mm_flags;
+#endif
+
+int main(int argc, char **argv)
+{
+ int x, y, v, i, xsize, ysize;
+ ImgReSampleContext *s;
+ float fact, factors[] = { 1/2.0, 3.0/4.0, 1.0, 4.0/3.0, 16.0/9.0, 2.0 };
+ char buf[256];
+
+ /* build test image */
+ for(y=0;y<YSIZE;y++) {
+ for(x=0;x<XSIZE;x++) {
+ if (x < XSIZE/2 && y < YSIZE/2) {
+ if (x < XSIZE/4 && y < YSIZE/4) {
+ if ((x % 10) <= 6 &&
+ (y % 10) <= 6)
+ v = 0xff;
+ else
+ v = 0x00;
+ } else if (x < XSIZE/4) {
+ if (x & 1)
+ v = 0xff;
+ else
+ v = 0;
+ } else if (y < XSIZE/4) {
+ if (y & 1)
+ v = 0xff;
+ else
+ v = 0;
+ } else {
+ if (y < YSIZE*3/8) {
+ if ((y+x) & 1)
+ v = 0xff;
+ else
+ v = 0;
+ } else {
+ if (((x+3) % 4) <= 1 &&
+ ((y+3) % 4) <= 1)
+ v = 0xff;
+ else
+ v = 0x00;
+ }
+ }
+ } else if (x < XSIZE/2) {
+ v = ((x - (XSIZE/2)) * 255) / (XSIZE/2);
+ } else if (y < XSIZE/2) {
+ v = ((y - (XSIZE/2)) * 255) / (XSIZE/2);
+ } else {
+ v = ((x + y - XSIZE) * 255) / XSIZE;
+ }
+ img[(YSIZE - y) * XSIZE + (XSIZE - x)] = v;
+ }
+ }
+ save_pgm("/tmp/in.pgm", img, XSIZE, YSIZE);
+ for(i=0;i<sizeof(factors)/sizeof(float);i++) {
+ fact = factors[i];
+ xsize = (int)(XSIZE * fact);
+ ysize = (int)((YSIZE - 100) * fact);
+ s = img_resample_full_init(xsize, ysize, XSIZE, YSIZE, 50 ,50, 0, 0, 0, 0, 0, 0);
+ av_log(NULL, AV_LOG_INFO, "Factor=%0.2f\n", fact);
+ dump_filter(&s->h_filters[0][0]);
+ component_resample(s, img1, xsize, xsize, ysize,
+ img + 50 * XSIZE, XSIZE, XSIZE, YSIZE - 100);
+ img_resample_close(s);
+
+ snprintf(buf, sizeof(buf), "/tmp/out%d.pgm", i);
+ save_pgm(buf, img1, xsize, ysize);
+ }
+
+ /* mmx test */
+#ifdef HAVE_MMX
+ av_log(NULL, AV_LOG_INFO, "MMX test\n");
+ fact = 0.72;
+ xsize = (int)(XSIZE * fact);
+ ysize = (int)(YSIZE * fact);
+ mm_flags = MM_MMX;
+ s = img_resample_init(xsize, ysize, XSIZE, YSIZE);
+ component_resample(s, img1, xsize, xsize, ysize,
+ img, XSIZE, XSIZE, YSIZE);
+
+ mm_flags = 0;
+ s = img_resample_init(xsize, ysize, XSIZE, YSIZE);
+ component_resample(s, img2, xsize, xsize, ysize,
+ img, XSIZE, XSIZE, YSIZE);
+ if (memcmp(img1, img2, xsize * ysize) != 0) {
+ av_log(NULL, AV_LOG_ERROR, "mmx error\n");
+ exit(1);
+ }
+ av_log(NULL, AV_LOG_INFO, "MMX OK\n");
+#endif
+ return 0;
+}
+
+#endif
diff --git a/contrib/ffmpeg/libavcodec/indeo2.c b/contrib/ffmpeg/libavcodec/indeo2.c
new file mode 100644
index 000000000..f3917ff3a
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/indeo2.c
@@ -0,0 +1,221 @@
+/*
+ * 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 indeo2.c
+ * Intel Indeo 2 decoder.
+ */
+#define ALT_BITSTREAM_READER_LE
+#include "avcodec.h"
+#include "bitstream.h"
+#include "indeo2data.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 -1;
+
+ /* 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 -1;
+ 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 -1;
+ 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= clip_uint8(t);
+ dst[out] = t;
+ out++;
+ t = dst[out - stride] + (table[(c * 2) + 1] - 128);
+ t= 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 -1;
+
+ 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= clip_uint8(t);
+ dst[out] = t;
+ out++;
+ t = dst[out] + (((table[(c * 2) + 1] - 128)*3) >> 2);
+ t= clip_uint8(t);
+ dst[out] = t;
+ out++;
+ }
+ }
+ dst += stride;
+ }
+ return 0;
+}
+
+static int ir2_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ Ir2Context * const s = avctx->priv_data;
+ AVFrame *picture = data;
+ AVFrame * const p= (AVFrame*)&s->picture;
+ int start;
+
+ if(p->data[0])
+ avctx->release_buffer(avctx, p);
+
+ p->reference = 1;
+ p->buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
+ if (avctx->reget_buffer(avctx, p)) {
+ av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+ return -1;
+ }
+
+ s->decode_delta = buf[18];
+
+ /* decide whether frame uses deltas or not */
+#ifndef ALT_BITSTREAM_READER_LE
+ for (i = 0; i < buf_size; i++)
+ buf[i] = ff_reverse[buf[i]];
+#endif
+ start = 48; /* hardcoded for now */
+
+ init_get_bits(&s->gb, buf + start, buf_size - start);
+
+ if (s->decode_delta) { /* intraframe */
+ ir2_decode_plane(s, avctx->width, avctx->height,
+ s->picture.data[0], s->picture.linesize[0], ir2_luma_table);
+ /* swapped U and V */
+ ir2_decode_plane(s, avctx->width >> 2, avctx->height >> 2,
+ s->picture.data[2], s->picture.linesize[2], ir2_luma_table);
+ ir2_decode_plane(s, avctx->width >> 2, avctx->height >> 2,
+ s->picture.data[1], s->picture.linesize[1], ir2_luma_table);
+ } else { /* interframe */
+ ir2_decode_plane_inter(s, avctx->width, avctx->height,
+ s->picture.data[0], s->picture.linesize[0], ir2_luma_table);
+ /* swapped U and V */
+ ir2_decode_plane_inter(s, avctx->width >> 2, avctx->height >> 2,
+ s->picture.data[2], s->picture.linesize[2], ir2_luma_table);
+ ir2_decode_plane_inter(s, avctx->width >> 2, avctx->height >> 2,
+ s->picture.data[1], s->picture.linesize[1], ir2_luma_table);
+ }
+
+ *picture= *(AVFrame*)&s->picture;
+ *data_size = sizeof(AVPicture);
+
+ return buf_size;
+}
+
+static int ir2_decode_init(AVCodecContext *avctx){
+ Ir2Context * const ic = avctx->priv_data;
+
+ ic->avctx = avctx;
+
+ avctx->pix_fmt= PIX_FMT_YUV410P;
+
+ if (!ir2_vlc.table)
+ init_vlc(&ir2_vlc, CODE_VLC_BITS, IR2_CODES,
+ &ir2_codes[0][1], 4, 2,
+#ifdef ALT_BITSTREAM_READER_LE
+ &ir2_codes[0][0], 4, 2, INIT_VLC_USE_STATIC | INIT_VLC_LE);
+#else
+ &ir2_codes[0][0], 4, 2, INIT_VLC_USE_STATIC);
+#endif
+
+ return 0;
+}
+
+AVCodec indeo2_decoder = {
+ "indeo2",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_INDEO2,
+ sizeof(Ir2Context),
+ ir2_decode_init,
+ NULL,
+ NULL,
+ ir2_decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/indeo2data.h b/contrib/ffmpeg/libavcodec/indeo2data.h
new file mode 100644
index 000000000..71d250af7
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/indeo2data.h
@@ -0,0 +1,134 @@
+/*
+ * 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
+ */
+
+#define IR2_CODES 143
+static const uint16_t ir2_codes[IR2_CODES][2] = {
+#ifdef ALT_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
+};
diff --git a/contrib/ffmpeg/libavcodec/indeo3.c b/contrib/ffmpeg/libavcodec/indeo3.c
new file mode 100644
index 000000000..33dcff820
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/indeo3.c
@@ -0,0 +1,1153 @@
+/*
+ * Intel Indeo 3 (IV31, IV32, etc.) video decoder for ffmpeg
+ * written, produced, and directed by Alan Smithee
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+#include "indeo3data.h"
+
+typedef struct
+{
+ unsigned char *Ybuf;
+ unsigned char *Ubuf;
+ unsigned char *Vbuf;
+ unsigned char *the_buf;
+ unsigned int the_buf_size;
+ unsigned short y_w, y_h;
+ unsigned short uv_w, uv_h;
+} YUVBufs;
+
+typedef struct Indeo3DecodeContext {
+ AVCodecContext *avctx;
+ int width, height;
+ AVFrame frame;
+
+ YUVBufs iv_frame[2];
+ YUVBufs *cur_frame;
+ YUVBufs *ref_frame;
+
+ unsigned char *ModPred;
+ unsigned short *corrector_type;
+} Indeo3DecodeContext;
+
+static int corrector_type_0[24] = {
+ 195, 159, 133, 115, 101, 93, 87, 77,
+ 195, 159, 133, 115, 101, 93, 87, 77,
+ 128, 79, 79, 79, 79, 79, 79, 79
+};
+
+static int corrector_type_2[8] = { 9, 7, 6, 8, 5, 4, 3, 2 };
+
+static void build_modpred(Indeo3DecodeContext *s)
+{
+ int i, j;
+
+ s->ModPred = (unsigned char *) av_malloc (8 * 128);
+
+ for (i=0; i < 128; ++i) {
+ s->ModPred[i+0*128] = (i > 126) ? 254 : 2*((i + 1) - ((i + 1) % 2));
+ s->ModPred[i+1*128] = (i == 7) ? 20 : ((i == 119 || i == 120)
+ ? 236 : 2*((i + 2) - ((i + 1) % 3)));
+ s->ModPred[i+2*128] = (i > 125) ? 248 : 2*((i + 2) - ((i + 2) % 4));
+ s->ModPred[i+3*128] = 2*((i + 1) - ((i - 3) % 5));
+ s->ModPred[i+4*128] = (i == 8) ? 20 : 2*((i + 1) - ((i - 3) % 6));
+ s->ModPred[i+5*128] = 2*((i + 4) - ((i + 3) % 7));
+ s->ModPred[i+6*128] = (i > 123) ? 240 : 2*((i + 4) - ((i + 4) % 8));
+ s->ModPred[i+7*128] = 2*((i + 5) - ((i + 4) % 9));
+ }
+
+ s->corrector_type = (unsigned short *) av_malloc (24 * 256 * sizeof(unsigned short));
+
+ for (i=0; i < 24; ++i) {
+ for (j=0; j < 256; ++j) {
+ s->corrector_type[i*256+j] = (j < corrector_type_0[i])
+ ? 1 : ((j < 248 || (i == 16 && j == 248))
+ ? 0 : corrector_type_2[j - 248]);
+ }
+ }
+}
+
+static void iv_Decode_Chunk(Indeo3DecodeContext *s, unsigned char *cur,
+ unsigned char *ref, int width, int height, unsigned char *buf1,
+ long fflags2, unsigned char *hdr,
+ unsigned char *buf2, int min_width_160);
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+/* ---------------------------------------------------------------------- */
+static void iv_alloc_frames(Indeo3DecodeContext *s)
+{
+ int luma_width, luma_height, luma_pixels, chroma_width, chroma_height,
+ chroma_pixels, i;
+ unsigned int bufsize;
+
+ luma_width = (s->width + 3) & (~3);
+ luma_height = (s->height + 3) & (~3);
+
+ s->iv_frame[0].y_w = s->iv_frame[0].y_h =
+ s->iv_frame[0].the_buf_size = 0;
+ s->iv_frame[1].y_w = s->iv_frame[1].y_h =
+ s->iv_frame[1].the_buf_size = 0;
+ s->iv_frame[1].the_buf = NULL;
+
+ chroma_width = ((luma_width >> 2) + 3) & (~3);
+ chroma_height = ((luma_height>> 2) + 3) & (~3);
+ luma_pixels = luma_width * luma_height;
+ chroma_pixels = chroma_width * chroma_height;
+
+ bufsize = luma_pixels * 2 + luma_width * 3 +
+ (chroma_pixels + chroma_width) * 4;
+
+ if((s->iv_frame[0].the_buf =
+ (s->iv_frame[0].the_buf_size == 0 ? av_malloc(bufsize) :
+ av_realloc(s->iv_frame[0].the_buf, bufsize))) == NULL)
+ return;
+ s->iv_frame[0].y_w = s->iv_frame[1].y_w = luma_width;
+ s->iv_frame[0].y_h = s->iv_frame[1].y_h = luma_height;
+ s->iv_frame[0].uv_w = s->iv_frame[1].uv_w = chroma_width;
+ s->iv_frame[0].uv_h = s->iv_frame[1].uv_h = chroma_height;
+ s->iv_frame[0].the_buf_size = bufsize;
+
+ s->iv_frame[0].Ybuf = s->iv_frame[0].the_buf + luma_width;
+ i = luma_pixels + luma_width * 2;
+ s->iv_frame[1].Ybuf = s->iv_frame[0].the_buf + i;
+ i += (luma_pixels + luma_width);
+ s->iv_frame[0].Ubuf = s->iv_frame[0].the_buf + i;
+ i += (chroma_pixels + chroma_width);
+ s->iv_frame[1].Ubuf = s->iv_frame[0].the_buf + i;
+ i += (chroma_pixels + chroma_width);
+ s->iv_frame[0].Vbuf = s->iv_frame[0].the_buf + i;
+ i += (chroma_pixels + chroma_width);
+ s->iv_frame[1].Vbuf = s->iv_frame[0].the_buf + i;
+
+ for(i = 1; i <= luma_width; i++)
+ s->iv_frame[0].Ybuf[-i] = s->iv_frame[1].Ybuf[-i] =
+ s->iv_frame[0].Ubuf[-i] = 0x80;
+
+ for(i = 1; i <= chroma_width; i++) {
+ s->iv_frame[1].Ubuf[-i] = 0x80;
+ s->iv_frame[0].Vbuf[-i] = 0x80;
+ s->iv_frame[1].Vbuf[-i] = 0x80;
+ s->iv_frame[1].Vbuf[chroma_pixels+i-1] = 0x80;
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+static void iv_free_func(Indeo3DecodeContext *s)
+{
+ int i;
+
+ for(i = 0 ; i < 2 ; i++) {
+ if(s->iv_frame[i].the_buf != NULL)
+ av_free(s->iv_frame[i].the_buf);
+ s->iv_frame[i].Ybuf = s->iv_frame[i].Ubuf =
+ s->iv_frame[i].Vbuf = NULL;
+ s->iv_frame[i].the_buf = NULL;
+ s->iv_frame[i].the_buf_size = 0;
+ s->iv_frame[i].y_w = s->iv_frame[i].y_h = 0;
+ s->iv_frame[i].uv_w = s->iv_frame[i].uv_h = 0;
+ }
+
+ av_free(s->ModPred);
+ av_free(s->corrector_type);
+}
+
+/* ---------------------------------------------------------------------- */
+static unsigned long iv_decode_frame(Indeo3DecodeContext *s,
+ unsigned char *buf, int buf_size)
+{
+ unsigned int hdr_width, hdr_height,
+ chroma_width, chroma_height;
+ unsigned long fflags1, fflags2, fflags3, offs1, offs2, offs3, offs;
+ unsigned char *hdr_pos, *buf_pos;
+
+ buf_pos = buf;
+ buf_pos += 18;
+
+ fflags1 = le2me_16(*(uint16_t *)buf_pos);
+ buf_pos += 2;
+ fflags3 = le2me_32(*(uint32_t *)buf_pos);
+ buf_pos += 4;
+ fflags2 = *buf_pos++;
+ buf_pos += 3;
+ hdr_height = le2me_16(*(uint16_t *)buf_pos);
+ buf_pos += 2;
+ hdr_width = le2me_16(*(uint16_t *)buf_pos);
+
+ if(avcodec_check_dimensions(NULL, hdr_width, hdr_height))
+ return -1;
+
+ buf_pos += 2;
+ chroma_height = ((hdr_height >> 2) + 3) & 0x7ffc;
+ chroma_width = ((hdr_width >> 2) + 3) & 0x7ffc;
+ offs1 = le2me_32(*(uint32_t *)buf_pos);
+ buf_pos += 4;
+ offs2 = le2me_32(*(uint32_t *)buf_pos);
+ buf_pos += 4;
+ offs3 = le2me_32(*(uint32_t *)buf_pos);
+ buf_pos += 8;
+ hdr_pos = buf_pos;
+ if(fflags3 == 0x80) return 4;
+
+ if(fflags1 & 0x200) {
+ s->cur_frame = s->iv_frame + 1;
+ s->ref_frame = s->iv_frame;
+ } else {
+ s->cur_frame = s->iv_frame;
+ s->ref_frame = s->iv_frame + 1;
+ }
+
+ buf_pos = buf + 16 + offs1;
+ offs = le2me_32(*(uint32_t *)buf_pos);
+ buf_pos += 4;
+
+ iv_Decode_Chunk(s, s->cur_frame->Ybuf, s->ref_frame->Ybuf, hdr_width,
+ hdr_height, buf_pos + offs * 2, fflags2, hdr_pos, buf_pos,
+ min(hdr_width, 160));
+
+ if (!(s->avctx->flags & CODEC_FLAG_GRAY))
+ {
+
+ buf_pos = buf + 16 + offs2;
+ offs = le2me_32(*(uint32_t *)buf_pos);
+ buf_pos += 4;
+
+ iv_Decode_Chunk(s, s->cur_frame->Vbuf, s->ref_frame->Vbuf, chroma_width,
+ chroma_height, buf_pos + offs * 2, fflags2, hdr_pos, buf_pos,
+ min(chroma_width, 40));
+
+ buf_pos = buf + 16 + offs3;
+ offs = le2me_32(*(uint32_t *)buf_pos);
+ buf_pos += 4;
+
+ iv_Decode_Chunk(s, s->cur_frame->Ubuf, s->ref_frame->Ubuf, chroma_width,
+ chroma_height, buf_pos + offs * 2, fflags2, hdr_pos, buf_pos,
+ min(chroma_width, 40));
+
+ }
+
+ return 8;
+}
+
+typedef struct {
+ long xpos;
+ long ypos;
+ long width;
+ long height;
+ long split_flag;
+ long split_direction;
+ long usl7;
+} ustr_t;
+
+/* ---------------------------------------------------------------------- */
+
+#define LV1_CHECK(buf1,rle_v3,lv1,lp2) \
+ if((lv1 & 0x80) != 0) { \
+ if(rle_v3 != 0) \
+ rle_v3 = 0; \
+ else { \
+ rle_v3 = 1; \
+ buf1 -= 2; \
+ } \
+ } \
+ lp2 = 4;
+
+
+#define RLE_V3_CHECK(buf1,rle_v1,rle_v2,rle_v3) \
+ if(rle_v3 == 0) { \
+ rle_v2 = *buf1; \
+ rle_v1 = 1; \
+ if(rle_v2 > 32) { \
+ rle_v2 -= 32; \
+ rle_v1 = 0; \
+ } \
+ rle_v3 = 1; \
+ } \
+ buf1--;
+
+
+#define LP2_CHECK(buf1,rle_v3,lp2) \
+ if(lp2 == 0 && rle_v3 != 0) \
+ rle_v3 = 0; \
+ else { \
+ buf1--; \
+ rle_v3 = 1; \
+ }
+
+
+#define RLE_V2_CHECK(buf1,rle_v2, rle_v3,lp2) \
+ rle_v2--; \
+ if(rle_v2 == 0) { \
+ rle_v3 = 0; \
+ buf1 += 2; \
+ } \
+ lp2 = 4;
+
+static void iv_Decode_Chunk(Indeo3DecodeContext *s,
+ unsigned char *cur, unsigned char *ref, int width, int height,
+ unsigned char *buf1, long fflags2, unsigned char *hdr,
+ unsigned char *buf2, int min_width_160)
+{
+ unsigned char bit_buf;
+ unsigned long bit_pos, lv, lv1, lv2;
+ long *width_tbl, width_tbl_arr[10];
+ signed char *ref_vectors;
+ unsigned char *cur_frm_pos, *ref_frm_pos, *cp, *cp2;
+ uint32_t *cur_lp, *ref_lp;
+ const uint32_t *correction_lp[2], *correctionloworder_lp[2], *correctionhighorder_lp[2];
+ unsigned short *correction_type_sp[2];
+ ustr_t strip_tbl[20], *strip;
+ int i, j, k, lp1, lp2, flag1, cmd, blks_width, blks_height, region_160_width,
+ rle_v1, rle_v2, rle_v3;
+ unsigned short res;
+
+ bit_buf = 0;
+ ref_vectors = NULL;
+
+ width_tbl = width_tbl_arr + 1;
+ i = (width < 0 ? width + 3 : width)/4;
+ for(j = -1; j < 8; j++)
+ width_tbl[j] = i * j;
+
+ strip = strip_tbl;
+
+ for(region_160_width = 0; region_160_width < (width - min_width_160); region_160_width += min_width_160);
+
+ strip->ypos = strip->xpos = 0;
+ for(strip->width = min_width_160; width > strip->width; strip->width *= 2);
+ strip->height = height;
+ strip->split_direction = 0;
+ strip->split_flag = 0;
+ strip->usl7 = 0;
+
+ bit_pos = 0;
+
+ rle_v1 = rle_v2 = rle_v3 = 0;
+
+ while(strip >= strip_tbl) {
+ if(bit_pos <= 0) {
+ bit_pos = 8;
+ bit_buf = *buf1++;
+ }
+
+ bit_pos -= 2;
+ cmd = (bit_buf >> bit_pos) & 0x03;
+
+ if(cmd == 0) {
+ strip++;
+ memcpy(strip, strip-1, sizeof(ustr_t));
+ strip->split_flag = 1;
+ strip->split_direction = 0;
+ strip->height = (strip->height > 8 ? ((strip->height+8)>>4)<<3 : 4);
+ continue;
+ } else if(cmd == 1) {
+ strip++;
+ memcpy(strip, strip-1, sizeof(ustr_t));
+ strip->split_flag = 1;
+ strip->split_direction = 1;
+ strip->width = (strip->width > 8 ? ((strip->width+8)>>4)<<3 : 4);
+ continue;
+ } else if(cmd == 2) {
+ if(strip->usl7 == 0) {
+ strip->usl7 = 1;
+ ref_vectors = NULL;
+ continue;
+ }
+ } else if(cmd == 3) {
+ if(strip->usl7 == 0) {
+ strip->usl7 = 1;
+ ref_vectors = (signed char*)buf2 + (*buf1 * 2);
+ buf1++;
+ continue;
+ }
+ }
+
+ cur_frm_pos = cur + width * strip->ypos + strip->xpos;
+
+ if((blks_width = strip->width) < 0)
+ blks_width += 3;
+ blks_width >>= 2;
+ blks_height = strip->height;
+
+ if(ref_vectors != NULL) {
+ ref_frm_pos = ref + (ref_vectors[0] + strip->ypos) * width +
+ ref_vectors[1] + strip->xpos;
+ } else
+ ref_frm_pos = cur_frm_pos - width_tbl[4];
+
+ if(cmd == 2) {
+ if(bit_pos <= 0) {
+ bit_pos = 8;
+ bit_buf = *buf1++;
+ }
+
+ bit_pos -= 2;
+ cmd = (bit_buf >> bit_pos) & 0x03;
+
+ if(cmd == 0 || ref_vectors != NULL) {
+ for(lp1 = 0; lp1 < blks_width; lp1++) {
+ for(i = 0, j = 0; i < blks_height; i++, j += width_tbl[1])
+ ((uint32_t *)cur_frm_pos)[j] = ((uint32_t *)ref_frm_pos)[j];
+ cur_frm_pos += 4;
+ ref_frm_pos += 4;
+ }
+ } else if(cmd != 1)
+ return;
+ } else {
+ k = *buf1 >> 4;
+ j = *buf1 & 0x0f;
+ buf1++;
+ lv = j + fflags2;
+
+ if((lv - 8) <= 7 && (k == 0 || k == 3 || k == 10)) {
+ cp2 = s->ModPred + ((lv - 8) << 7);
+ cp = ref_frm_pos;
+ for(i = 0; i < blks_width << 2; i++) {
+ int v = *cp >> 1;
+ *(cp++) = cp2[v];
+ }
+ }
+
+ if(k == 1 || k == 4) {
+ lv = (hdr[j] & 0xf) + fflags2;
+ correction_type_sp[0] = s->corrector_type + (lv << 8);
+ correction_lp[0] = correction + (lv << 8);
+ lv = (hdr[j] >> 4) + fflags2;
+ correction_lp[1] = correction + (lv << 8);
+ correction_type_sp[1] = s->corrector_type + (lv << 8);
+ } else {
+ correctionloworder_lp[0] = correctionloworder_lp[1] = correctionloworder + (lv << 8);
+ correctionhighorder_lp[0] = correctionhighorder_lp[1] = correctionhighorder + (lv << 8);
+ correction_type_sp[0] = correction_type_sp[1] = s->corrector_type + (lv << 8);
+ correction_lp[0] = correction_lp[1] = correction + (lv << 8);
+ }
+
+ switch(k) {
+ case 1:
+ case 0: /********** CASE 0 **********/
+ for( ; blks_height > 0; blks_height -= 4) {
+ for(lp1 = 0; lp1 < blks_width; lp1++) {
+ for(lp2 = 0; lp2 < 4; ) {
+ k = *buf1++;
+ cur_lp = ((uint32_t *)cur_frm_pos) + width_tbl[lp2];
+ ref_lp = ((uint32_t *)ref_frm_pos) + width_tbl[lp2];
+
+ switch(correction_type_sp[0][k]) {
+ case 0:
+ *cur_lp = le2me_32(((le2me_32(*ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
+ lp2++;
+ break;
+ case 1:
+ res = ((le2me_16(((unsigned short *)(ref_lp))[0]) >> 1) + correction_lp[lp2 & 0x01][*buf1]) << 1;
+ ((unsigned short *)cur_lp)[0] = le2me_16(res);
+ res = ((le2me_16(((unsigned short *)(ref_lp))[1]) >> 1) + correction_lp[lp2 & 0x01][k]) << 1;
+ ((unsigned short *)cur_lp)[1] = le2me_16(res);
+ buf1++;
+ lp2++;
+ break;
+ case 2:
+ if(lp2 == 0) {
+ for(i = 0, j = 0; i < 2; i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ lp2 += 2;
+ }
+ break;
+ case 3:
+ if(lp2 < 2) {
+ for(i = 0, j = 0; i < (3 - lp2); i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ lp2 = 3;
+ }
+ break;
+ case 8:
+ if(lp2 == 0) {
+ RLE_V3_CHECK(buf1,rle_v1,rle_v2,rle_v3)
+
+ if(rle_v1 == 1 || ref_vectors != NULL) {
+ for(i = 0, j = 0; i < 4; i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ }
+
+ RLE_V2_CHECK(buf1,rle_v2, rle_v3,lp2)
+ break;
+ } else {
+ rle_v1 = 1;
+ rle_v2 = *buf1 - 1;
+ }
+ case 5:
+ LP2_CHECK(buf1,rle_v3,lp2)
+ case 4:
+ for(i = 0, j = 0; i < (4 - lp2); i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ lp2 = 4;
+ break;
+
+ case 7:
+ if(rle_v3 != 0)
+ rle_v3 = 0;
+ else {
+ buf1--;
+ rle_v3 = 1;
+ }
+ case 6:
+ if(ref_vectors != NULL) {
+ for(i = 0, j = 0; i < 4; i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ }
+ lp2 = 4;
+ break;
+
+ case 9:
+ lv1 = *buf1++;
+ lv = (lv1 & 0x7F) << 1;
+ lv += (lv << 8);
+ lv += (lv << 16);
+ for(i = 0, j = 0; i < 4; i++, j += width_tbl[1])
+ cur_lp[j] = lv;
+
+ LV1_CHECK(buf1,rle_v3,lv1,lp2)
+ break;
+ default:
+ return;
+ }
+ }
+
+ cur_frm_pos += 4;
+ ref_frm_pos += 4;
+ }
+
+ cur_frm_pos += ((width - blks_width) * 4);
+ ref_frm_pos += ((width - blks_width) * 4);
+ }
+ break;
+
+ case 4:
+ case 3: /********** CASE 3 **********/
+ if(ref_vectors != NULL)
+ return;
+ flag1 = 1;
+
+ for( ; blks_height > 0; blks_height -= 8) {
+ for(lp1 = 0; lp1 < blks_width; lp1++) {
+ for(lp2 = 0; lp2 < 4; ) {
+ k = *buf1++;
+
+ cur_lp = ((uint32_t *)cur_frm_pos) + width_tbl[lp2 * 2];
+ ref_lp = ((uint32_t *)cur_frm_pos) + width_tbl[(lp2 * 2) - 1];
+
+ switch(correction_type_sp[lp2 & 0x01][k]) {
+ case 0:
+ cur_lp[width_tbl[1]] = le2me_32(((le2me_32(*ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
+ if(lp2 > 0 || flag1 == 0 || strip->ypos != 0)
+ cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
+ else
+ cur_lp[0] = le2me_32(((le2me_32(*ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
+ lp2++;
+ break;
+
+ case 1:
+ res = ((le2me_16(((unsigned short *)ref_lp)[0]) >> 1) + correction_lp[lp2 & 0x01][*buf1]) << 1;
+ ((unsigned short *)cur_lp)[width_tbl[2]] = le2me_16(res);
+ res = ((le2me_16(((unsigned short *)ref_lp)[1]) >> 1) + correction_lp[lp2 & 0x01][k]) << 1;
+ ((unsigned short *)cur_lp)[width_tbl[2]+1] = le2me_16(res);
+
+ if(lp2 > 0 || flag1 == 0 || strip->ypos != 0)
+ cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
+ else
+ cur_lp[0] = cur_lp[width_tbl[1]];
+ buf1++;
+ lp2++;
+ break;
+
+ case 2:
+ if(lp2 == 0) {
+ for(i = 0, j = 0; i < 4; i++, j += width_tbl[1])
+ cur_lp[j] = *ref_lp;
+ lp2 += 2;
+ }
+ break;
+
+ case 3:
+ if(lp2 < 2) {
+ for(i = 0, j = 0; i < 6 - (lp2 * 2); i++, j += width_tbl[1])
+ cur_lp[j] = *ref_lp;
+ lp2 = 3;
+ }
+ break;
+
+ case 6:
+ lp2 = 4;
+ break;
+
+ case 7:
+ if(rle_v3 != 0)
+ rle_v3 = 0;
+ else {
+ buf1--;
+ rle_v3 = 1;
+ }
+ lp2 = 4;
+ break;
+
+ case 8:
+ if(lp2 == 0) {
+ RLE_V3_CHECK(buf1,rle_v1,rle_v2,rle_v3)
+
+ if(rle_v1 == 1) {
+ for(i = 0, j = 0; i < 8; i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ }
+
+ RLE_V2_CHECK(buf1,rle_v2, rle_v3,lp2)
+ break;
+ } else {
+ rle_v2 = (*buf1) - 1;
+ rle_v1 = 1;
+ }
+ case 5:
+ LP2_CHECK(buf1,rle_v3,lp2)
+ case 4:
+ for(i = 0, j = 0; i < 8 - (lp2 * 2); i++, j += width_tbl[1])
+ cur_lp[j] = *ref_lp;
+ lp2 = 4;
+ break;
+
+ case 9:
+ av_log(s->avctx, AV_LOG_ERROR, "UNTESTED.\n");
+ lv1 = *buf1++;
+ lv = (lv1 & 0x7F) << 1;
+ lv += (lv << 8);
+ lv += (lv << 16);
+
+ for(i = 0, j = 0; i < 4; i++, j += width_tbl[1])
+ cur_lp[j] = lv;
+
+ LV1_CHECK(buf1,rle_v3,lv1,lp2)
+ break;
+
+ default:
+ return;
+ }
+ }
+
+ cur_frm_pos += 4;
+ }
+
+ cur_frm_pos += (((width * 2) - blks_width) * 4);
+ flag1 = 0;
+ }
+ break;
+
+ case 10: /********** CASE 10 **********/
+ if(ref_vectors == NULL) {
+ flag1 = 1;
+
+ for( ; blks_height > 0; blks_height -= 8) {
+ for(lp1 = 0; lp1 < blks_width; lp1 += 2) {
+ for(lp2 = 0; lp2 < 4; ) {
+ k = *buf1++;
+ cur_lp = ((uint32_t *)cur_frm_pos) + width_tbl[lp2 * 2];
+ ref_lp = ((uint32_t *)cur_frm_pos) + width_tbl[(lp2 * 2) - 1];
+ lv1 = ref_lp[0];
+ lv2 = ref_lp[1];
+ if(lp2 == 0 && flag1 != 0) {
+#ifdef WORDS_BIGENDIAN
+ lv1 = lv1 & 0xFF00FF00;
+ lv1 = (lv1 >> 8) | lv1;
+ lv2 = lv2 & 0xFF00FF00;
+ lv2 = (lv2 >> 8) | lv2;
+#else
+ lv1 = lv1 & 0x00FF00FF;
+ lv1 = (lv1 << 8) | lv1;
+ lv2 = lv2 & 0x00FF00FF;
+ lv2 = (lv2 << 8) | lv2;
+#endif
+ }
+
+ switch(correction_type_sp[lp2 & 0x01][k]) {
+ case 0:
+ cur_lp[width_tbl[1]] = le2me_32(((le2me_32(lv1) >> 1) + correctionloworder_lp[lp2 & 0x01][k]) << 1);
+ cur_lp[width_tbl[1]+1] = le2me_32(((le2me_32(lv2) >> 1) + correctionhighorder_lp[lp2 & 0x01][k]) << 1);
+ if(lp2 > 0 || strip->ypos != 0 || flag1 == 0) {
+ cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
+ cur_lp[1] = ((cur_lp[-width_tbl[1]+1] >> 1) + (cur_lp[width_tbl[1]+1] >> 1)) & 0xFEFEFEFE;
+ } else {
+ cur_lp[0] = cur_lp[width_tbl[1]];
+ cur_lp[1] = cur_lp[width_tbl[1]+1];
+ }
+ lp2++;
+ break;
+
+ case 1:
+ cur_lp[width_tbl[1]] = le2me_32(((le2me_32(lv1) >> 1) + correctionloworder_lp[lp2 & 0x01][*buf1]) << 1);
+ cur_lp[width_tbl[1]+1] = le2me_32(((le2me_32(lv2) >> 1) + correctionloworder_lp[lp2 & 0x01][k]) << 1);
+ if(lp2 > 0 || strip->ypos != 0 || flag1 == 0) {
+ cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
+ cur_lp[1] = ((cur_lp[-width_tbl[1]+1] >> 1) + (cur_lp[width_tbl[1]+1] >> 1)) & 0xFEFEFEFE;
+ } else {
+ cur_lp[0] = cur_lp[width_tbl[1]];
+ cur_lp[1] = cur_lp[width_tbl[1]+1];
+ }
+ buf1++;
+ lp2++;
+ break;
+
+ case 2:
+ if(lp2 == 0) {
+ if(flag1 != 0) {
+ for(i = 0, j = width_tbl[1]; i < 3; i++, j += width_tbl[1]) {
+ cur_lp[j] = lv1;
+ cur_lp[j+1] = lv2;
+ }
+ cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
+ cur_lp[1] = ((cur_lp[-width_tbl[1]+1] >> 1) + (cur_lp[width_tbl[1]+1] >> 1)) & 0xFEFEFEFE;
+ } else {
+ for(i = 0, j = 0; i < 4; i++, j += width_tbl[1]) {
+ cur_lp[j] = lv1;
+ cur_lp[j+1] = lv2;
+ }
+ }
+ lp2 += 2;
+ }
+ break;
+
+ case 3:
+ if(lp2 < 2) {
+ if(lp2 == 0 && flag1 != 0) {
+ for(i = 0, j = width_tbl[1]; i < 5; i++, j += width_tbl[1]) {
+ cur_lp[j] = lv1;
+ cur_lp[j+1] = lv2;
+ }
+ cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
+ cur_lp[1] = ((cur_lp[-width_tbl[1]+1] >> 1) + (cur_lp[width_tbl[1]+1] >> 1)) & 0xFEFEFEFE;
+ } else {
+ for(i = 0, j = 0; i < 6 - (lp2 * 2); i++, j += width_tbl[1]) {
+ cur_lp[j] = lv1;
+ cur_lp[j+1] = lv2;
+ }
+ }
+ lp2 = 3;
+ }
+ break;
+
+ case 8:
+ if(lp2 == 0) {
+ RLE_V3_CHECK(buf1,rle_v1,rle_v2,rle_v3)
+ if(rle_v1 == 1) {
+ if(flag1 != 0) {
+ for(i = 0, j = width_tbl[1]; i < 7; i++, j += width_tbl[1]) {
+ cur_lp[j] = lv1;
+ cur_lp[j+1] = lv2;
+ }
+ cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
+ cur_lp[1] = ((cur_lp[-width_tbl[1]+1] >> 1) + (cur_lp[width_tbl[1]+1] >> 1)) & 0xFEFEFEFE;
+ } else {
+ for(i = 0, j = 0; i < 8; i++, j += width_tbl[1]) {
+ cur_lp[j] = lv1;
+ cur_lp[j+1] = lv2;
+ }
+ }
+ }
+ RLE_V2_CHECK(buf1,rle_v2, rle_v3,lp2)
+ break;
+ } else {
+ rle_v1 = 1;
+ rle_v2 = (*buf1) - 1;
+ }
+ case 5:
+ LP2_CHECK(buf1,rle_v3,lp2)
+ case 4:
+ if(lp2 == 0 && flag1 != 0) {
+ for(i = 0, j = width_tbl[1]; i < 7; i++, j += width_tbl[1]) {
+ cur_lp[j] = lv1;
+ cur_lp[j+1] = lv2;
+ }
+ cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
+ cur_lp[1] = ((cur_lp[-width_tbl[1]+1] >> 1) + (cur_lp[width_tbl[1]+1] >> 1)) & 0xFEFEFEFE;
+ } else {
+ for(i = 0, j = 0; i < 8 - (lp2 * 2); i++, j += width_tbl[1]) {
+ cur_lp[j] = lv1;
+ cur_lp[j+1] = lv2;
+ }
+ }
+ lp2 = 4;
+ break;
+
+ case 6:
+ lp2 = 4;
+ break;
+
+ case 7:
+ if(lp2 == 0) {
+ if(rle_v3 != 0)
+ rle_v3 = 0;
+ else {
+ buf1--;
+ rle_v3 = 1;
+ }
+ lp2 = 4;
+ }
+ break;
+
+ case 9:
+ av_log(s->avctx, AV_LOG_ERROR, "UNTESTED.\n");
+ lv1 = *buf1;
+ lv = (lv1 & 0x7F) << 1;
+ lv += (lv << 8);
+ lv += (lv << 16);
+ for(i = 0, j = 0; i < 8; i++, j += width_tbl[1])
+ cur_lp[j] = lv;
+ LV1_CHECK(buf1,rle_v3,lv1,lp2)
+ break;
+
+ default:
+ return;
+ }
+ }
+
+ cur_frm_pos += 8;
+ }
+
+ cur_frm_pos += (((width * 2) - blks_width) * 4);
+ flag1 = 0;
+ }
+ } else {
+ for( ; blks_height > 0; blks_height -= 8) {
+ for(lp1 = 0; lp1 < blks_width; lp1 += 2) {
+ for(lp2 = 0; lp2 < 4; ) {
+ k = *buf1++;
+ cur_lp = ((uint32_t *)cur_frm_pos) + width_tbl[lp2 * 2];
+ ref_lp = ((uint32_t *)ref_frm_pos) + width_tbl[lp2 * 2];
+
+ switch(correction_type_sp[lp2 & 0x01][k]) {
+ case 0:
+ lv1 = correctionloworder_lp[lp2 & 0x01][k];
+ lv2 = correctionhighorder_lp[lp2 & 0x01][k];
+ cur_lp[0] = le2me_32(((le2me_32(ref_lp[0]) >> 1) + lv1) << 1);
+ cur_lp[1] = le2me_32(((le2me_32(ref_lp[1]) >> 1) + lv2) << 1);
+ cur_lp[width_tbl[1]] = le2me_32(((le2me_32(ref_lp[width_tbl[1]]) >> 1) + lv1) << 1);
+ cur_lp[width_tbl[1]+1] = le2me_32(((le2me_32(ref_lp[width_tbl[1]+1]) >> 1) + lv2) << 1);
+ lp2++;
+ break;
+
+ case 1:
+ lv1 = correctionloworder_lp[lp2 & 0x01][*buf1++];
+ lv2 = correctionloworder_lp[lp2 & 0x01][k];
+ cur_lp[0] = le2me_32(((le2me_32(ref_lp[0]) >> 1) + lv1) << 1);
+ cur_lp[1] = le2me_32(((le2me_32(ref_lp[1]) >> 1) + lv2) << 1);
+ cur_lp[width_tbl[1]] = le2me_32(((le2me_32(ref_lp[width_tbl[1]]) >> 1) + lv1) << 1);
+ cur_lp[width_tbl[1]+1] = le2me_32(((le2me_32(ref_lp[width_tbl[1]+1]) >> 1) + lv2) << 1);
+ lp2++;
+ break;
+
+ case 2:
+ if(lp2 == 0) {
+ for(i = 0, j = 0; i < 4; i++, j += width_tbl[1]) {
+ cur_lp[j] = ref_lp[j];
+ cur_lp[j+1] = ref_lp[j+1];
+ }
+ lp2 += 2;
+ }
+ break;
+
+ case 3:
+ if(lp2 < 2) {
+ for(i = 0, j = 0; i < 6 - (lp2 * 2); i++, j += width_tbl[1]) {
+ cur_lp[j] = ref_lp[j];
+ cur_lp[j+1] = ref_lp[j+1];
+ }
+ lp2 = 3;
+ }
+ break;
+
+ case 8:
+ if(lp2 == 0) {
+ RLE_V3_CHECK(buf1,rle_v1,rle_v2,rle_v3)
+ for(i = 0, j = 0; i < 8; i++, j += width_tbl[1]) {
+ ((uint32_t *)cur_frm_pos)[j] = ((uint32_t *)ref_frm_pos)[j];
+ ((uint32_t *)cur_frm_pos)[j+1] = ((uint32_t *)ref_frm_pos)[j+1];
+ }
+ RLE_V2_CHECK(buf1,rle_v2, rle_v3,lp2)
+ break;
+ } else {
+ rle_v1 = 1;
+ rle_v2 = (*buf1) - 1;
+ }
+ case 5:
+ case 7:
+ LP2_CHECK(buf1,rle_v3,lp2)
+ case 6:
+ case 4:
+ for(i = 0, j = 0; i < 8 - (lp2 * 2); i++, j += width_tbl[1]) {
+ cur_lp[j] = ref_lp[j];
+ cur_lp[j+1] = ref_lp[j+1];
+ }
+ lp2 = 4;
+ break;
+
+ case 9:
+ av_log(s->avctx, AV_LOG_ERROR, "UNTESTED.\n");
+ lv1 = *buf1;
+ lv = (lv1 & 0x7F) << 1;
+ lv += (lv << 8);
+ lv += (lv << 16);
+ for(i = 0, j = 0; i < 8; i++, j += width_tbl[1])
+ ((uint32_t *)cur_frm_pos)[j] = ((uint32_t *)cur_frm_pos)[j+1] = lv;
+ LV1_CHECK(buf1,rle_v3,lv1,lp2)
+ break;
+
+ default:
+ return;
+ }
+ }
+
+ cur_frm_pos += 8;
+ ref_frm_pos += 8;
+ }
+
+ cur_frm_pos += (((width * 2) - blks_width) * 4);
+ ref_frm_pos += (((width * 2) - blks_width) * 4);
+ }
+ }
+ break;
+
+ case 11: /********** CASE 11 **********/
+ if(ref_vectors == NULL)
+ return;
+
+ for( ; blks_height > 0; blks_height -= 8) {
+ for(lp1 = 0; lp1 < blks_width; lp1++) {
+ for(lp2 = 0; lp2 < 4; ) {
+ k = *buf1++;
+ cur_lp = ((uint32_t *)cur_frm_pos) + width_tbl[lp2 * 2];
+ ref_lp = ((uint32_t *)ref_frm_pos) + width_tbl[lp2 * 2];
+
+ switch(correction_type_sp[lp2 & 0x01][k]) {
+ case 0:
+ cur_lp[0] = le2me_32(((le2me_32(*ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
+ cur_lp[width_tbl[1]] = le2me_32(((le2me_32(ref_lp[width_tbl[1]]) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
+ lp2++;
+ break;
+
+ case 1:
+ lv1 = (unsigned short)(correction_lp[lp2 & 0x01][*buf1++]);
+ lv2 = (unsigned short)(correction_lp[lp2 & 0x01][k]);
+ res = (unsigned short)(((le2me_16(((unsigned short *)ref_lp)[0]) >> 1) + lv1) << 1);
+ ((unsigned short *)cur_lp)[0] = le2me_16(res);
+ res = (unsigned short)(((le2me_16(((unsigned short *)ref_lp)[1]) >> 1) + lv2) << 1);
+ ((unsigned short *)cur_lp)[1] = le2me_16(res);
+ res = (unsigned short)(((le2me_16(((unsigned short *)ref_lp)[width_tbl[2]]) >> 1) + lv1) << 1);
+ ((unsigned short *)cur_lp)[width_tbl[2]] = le2me_16(res);
+ res = (unsigned short)(((le2me_16(((unsigned short *)ref_lp)[width_tbl[2]+1]) >> 1) + lv2) << 1);
+ ((unsigned short *)cur_lp)[width_tbl[2]+1] = le2me_16(res);
+ lp2++;
+ break;
+
+ case 2:
+ if(lp2 == 0) {
+ for(i = 0, j = 0; i < 4; i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ lp2 += 2;
+ }
+ break;
+
+ case 3:
+ if(lp2 < 2) {
+ for(i = 0, j = 0; i < 6 - (lp2 * 2); i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ lp2 = 3;
+ }
+ break;
+
+ case 8:
+ if(lp2 == 0) {
+ RLE_V3_CHECK(buf1,rle_v1,rle_v2,rle_v3)
+
+ for(i = 0, j = 0; i < 8; i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+
+ RLE_V2_CHECK(buf1,rle_v2, rle_v3,lp2)
+ break;
+ } else {
+ rle_v1 = 1;
+ rle_v2 = (*buf1) - 1;
+ }
+ case 5:
+ case 7:
+ LP2_CHECK(buf1,rle_v3,lp2)
+ case 4:
+ case 6:
+ for(i = 0, j = 0; i < 8 - (lp2 * 2); i++, j += width_tbl[1])
+ cur_lp[j] = ref_lp[j];
+ lp2 = 4;
+ break;
+
+ case 9:
+ av_log(s->avctx, AV_LOG_ERROR, "UNTESTED.\n");
+ lv1 = *buf1++;
+ lv = (lv1 & 0x7F) << 1;
+ lv += (lv << 8);
+ lv += (lv << 16);
+ for(i = 0, j = 0; i < 4; i++, j += width_tbl[1])
+ cur_lp[j] = lv;
+ LV1_CHECK(buf1,rle_v3,lv1,lp2)
+ break;
+
+ default:
+ return;
+ }
+ }
+
+ cur_frm_pos += 4;
+ ref_frm_pos += 4;
+ }
+
+ cur_frm_pos += (((width * 2) - blks_width) * 4);
+ ref_frm_pos += (((width * 2) - blks_width) * 4);
+ }
+ break;
+
+ default:
+ return;
+ }
+ }
+
+ if(strip < strip_tbl)
+ return;
+
+ for( ; strip >= strip_tbl; strip--) {
+ if(strip->split_flag != 0) {
+ strip->split_flag = 0;
+ strip->usl7 = (strip-1)->usl7;
+
+ if(strip->split_direction) {
+ strip->xpos += strip->width;
+ strip->width = (strip-1)->width - strip->width;
+ if(region_160_width <= strip->xpos && width < strip->width + strip->xpos)
+ strip->width = width - strip->xpos;
+ } else {
+ strip->ypos += strip->height;
+ strip->height = (strip-1)->height - strip->height;
+ }
+ break;
+ }
+ }
+ }
+}
+
+static int indeo3_decode_init(AVCodecContext *avctx)
+{
+ Indeo3DecodeContext *s = avctx->priv_data;
+
+ s->avctx = avctx;
+ s->width = avctx->width;
+ s->height = avctx->height;
+ avctx->pix_fmt = PIX_FMT_YUV410P;
+ avctx->has_b_frames = 0;
+
+ build_modpred(s);
+ iv_alloc_frames(s);
+
+ return 0;
+}
+
+static int indeo3_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ unsigned char *buf, int buf_size)
+{
+ Indeo3DecodeContext *s=avctx->priv_data;
+ unsigned char *src, *dest;
+ int y;
+
+ iv_decode_frame(s, buf, buf_size);
+
+ if(s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ s->frame.reference = 0;
+ if(avctx->get_buffer(avctx, &s->frame) < 0) {
+ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ src = s->cur_frame->Ybuf;
+ dest = s->frame.data[0];
+ for (y = 0; y < s->height; y++) {
+ memcpy(dest, src, s->cur_frame->y_w);
+ src += s->cur_frame->y_w;
+ dest += s->frame.linesize[0];
+ }
+
+ if (!(s->avctx->flags & CODEC_FLAG_GRAY))
+ {
+ src = s->cur_frame->Ubuf;
+ dest = s->frame.data[1];
+ for (y = 0; y < s->height / 4; y++) {
+ memcpy(dest, src, s->cur_frame->uv_w);
+ src += s->cur_frame->uv_w;
+ dest += s->frame.linesize[1];
+ }
+
+ src = s->cur_frame->Vbuf;
+ dest = s->frame.data[2];
+ for (y = 0; y < s->height / 4; y++) {
+ memcpy(dest, src, s->cur_frame->uv_w);
+ src += s->cur_frame->uv_w;
+ dest += s->frame.linesize[2];
+ }
+ }
+
+ *data_size=sizeof(AVFrame);
+ *(AVFrame*)data= s->frame;
+
+ return buf_size;
+}
+
+static int indeo3_decode_end(AVCodecContext *avctx)
+{
+ Indeo3DecodeContext *s = avctx->priv_data;
+
+ iv_free_func(s);
+
+ return 0;
+}
+
+AVCodec indeo3_decoder = {
+ "indeo3",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_INDEO3,
+ sizeof(Indeo3DecodeContext),
+ indeo3_decode_init,
+ NULL,
+ indeo3_decode_end,
+ indeo3_decode_frame,
+ 0,
+ NULL
+};
diff --git a/contrib/ffmpeg/libavcodec/indeo3data.h b/contrib/ffmpeg/libavcodec/indeo3data.h
new file mode 100644
index 000000000..e69a09f0e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/indeo3data.h
@@ -0,0 +1,2335 @@
+/*
+ * Intel Indeo 3 (IV31, IV32, etc.) video decoder for ffmpeg
+ * written, produced, and directed by Alan Smithee
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 uint32_t correction[] = {
+ 0x00000000, 0x00000202, 0xfffffdfe, 0x000002ff, 0xfffffd01, 0xffffff03, 0x000000fd, 0x00000404,
+ 0xfffffbfc, 0x00000501, 0xfffffaff, 0x00000105, 0xfffffefb, 0x000003fc, 0xfffffc04, 0x000005fe,
+ 0xfffffa02, 0xfffffe06, 0x000001fa, 0x00000904, 0xfffff6fc, 0x00000409, 0xfffffbf7, 0x00000909,
+ 0xfffff6f7, 0x00000a01, 0xfffff5ff, 0x0000010a, 0xfffffef6, 0x000007fb, 0xfffff805, 0xfffffb08,
+ 0x000004f8, 0x00000f09, 0xfffff0f7, 0x0000090f, 0xfffff6f1, 0x00000bfd, 0xfffff403, 0xfffffd0c,
+ 0x000002f4, 0x00001004, 0xffffeffc, 0x00000410, 0xfffffbf0, 0x00001010, 0xffffeff0, 0x00001200,
+ 0xffffee00, 0x00000012, 0xffffffee, 0x00000bf4, 0xfffff40c, 0x00000ff7, 0xfffff009, 0xfffff710,
+ 0x000008f0, 0x00001b0b, 0xffffe4f5, 0x00000b1b, 0xfffff4e5, 0x00001c13, 0xffffe3ed, 0x0000131c,
+ 0xffffece4, 0x000015fa, 0xffffea06, 0xfffffa16, 0x000005ea, 0x00001d04, 0xffffe2fc, 0x0000041d,
+ 0xfffffbe3, 0x00001e1e, 0xffffe1e2, 0x000020fe, 0xffffdf02, 0xfffffe21, 0x000001df, 0x000016ee,
+ 0xffffe912, 0xffffee17, 0x000011e9, 0x00001df1, 0xffffe20f, 0xfffff11e, 0x00000ee2, 0x00002e16,
+ 0xffffd1ea, 0x0000162e, 0xffffe9d2, 0x00002f0d, 0xffffd0f3, 0x00000d2f, 0xfffff2d1, 0x00003123,
+ 0xffffcedd, 0x00002331, 0xffffdccf, 0x000028f5, 0xffffd70b, 0xfffff529, 0x00000ad7, 0x00003304,
+ 0xffffccfc, 0x00000433, 0xfffffbcd, 0x00003636, 0xffffc9ca, 0x000021de, 0xffffde22, 0x000029e3,
+ 0xffffd61d, 0xffffe32a, 0x00001cd6, 0x00003bfa, 0xffffc406, 0xfffffa3c, 0x000005c4, 0x00004c1b,
+ 0xffffb3e5, 0x00001b4c, 0xffffe4b4, 0x00004d2b, 0xffffb2d5, 0x00002b4d, 0xffffd4b3, 0x000036e8,
+ 0xffffc918, 0xffffe837, 0x000017c9, 0x00004f0e, 0xffffb0f2, 0x00000e4f, 0xfffff1b1, 0x0000533f,
+ 0xffffacc1, 0x00003f53, 0xffffc0ad, 0x000049ec, 0xffffb614, 0xffffec4a, 0x000013b6, 0x00005802,
+ 0xffffa7fe, 0x00000258, 0xfffffda8, 0x00005d5d, 0xffffa2a3, 0x00003ccc, 0xffffc334, 0xffffcc3d,
+ 0x000033c3, 0x00007834, 0xffff87cc, 0x00003478, 0xffffcb88, 0x00004ad3, 0xffffb52d, 0xffffd34b,
+ 0x00002cb5, 0x00007d4b, 0xffff82b5, 0x00004b7d, 0xffffb483, 0x00007a21, 0xffff85df, 0x0000217a,
+ 0xffffde86, 0x000066f3, 0xffff990d, 0xfffff367, 0x00000c99, 0x00005fd8, 0xffffa028, 0xffffd860,
+ 0x000027a0, 0x00007ede, 0xffff8122, 0xffffde7f, 0x00002181, 0x000058a7, 0xffffa759, 0x000068b2,
+ 0xffff974e, 0xffffb269, 0x00004d97, 0x00000c0c, 0xfffff3f4, 0x00001717, 0xffffe8e9, 0x00002a2a,
+ 0xffffd5d6, 0x00004949, 0xffffb6b7, 0x00000000, 0x02020000, 0xfdfe0000, 0x02ff0000, 0xfd010000,
+ 0xff030000, 0x00fd0000, 0x00000202, 0x02020202, 0xfdfe0202, 0x02ff0202, 0xfd010202, 0xff030202,
+ 0x00fd0202, 0xfffffdfe, 0x0201fdfe, 0xfdfdfdfe, 0x02fefdfe, 0xfd00fdfe, 0xff02fdfe, 0x00fcfdfe,
+ 0x000002ff, 0x020202ff, 0xfdfe02ff, 0x02ff02ff, 0xfd0102ff, 0xff0302ff, 0x00fd02ff, 0xfffffd01,
+ 0x0201fd01, 0xfdfdfd01, 0x02fefd01, 0xfd00fd01, 0xff02fd01, 0x00fcfd01, 0xffffff03, 0x0201ff03,
+ 0xfdfdff03, 0x02feff03, 0xfd00ff03, 0xff02ff03, 0x00fcff03, 0x000000fd, 0x020200fd, 0xfdfe00fd,
+ 0x02ff00fd, 0xfd0100fd, 0xff0300fd, 0x00fd00fd, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000303, 0xfffffcfd, 0x000003ff, 0xfffffc01, 0xffffff04, 0x000000fc, 0x00000707,
+ 0xfffff8f9, 0x00000802, 0xfffff7fe, 0x00000208, 0xfffffdf8, 0x000008fe, 0xfffff702, 0xfffffe09,
+ 0x000001f7, 0x000005fa, 0xfffffa06, 0x00000d06, 0xfffff2fa, 0x0000060d, 0xfffff9f3, 0x00000d0d,
+ 0xfffff2f3, 0x00000e01, 0xfffff1ff, 0x0000010e, 0xfffffef2, 0x00000bf8, 0xfffff408, 0xfffff80c,
+ 0x000007f4, 0x0000170e, 0xffffe8f2, 0x00000e17, 0xfffff1e9, 0x000011fb, 0xffffee05, 0xfffffb12,
+ 0x000004ee, 0x00001806, 0xffffe7fa, 0x00000618, 0xfffff9e8, 0x00001818, 0xffffe7e8, 0x00001aff,
+ 0xffffe501, 0xffffff1b, 0x000000e5, 0x000010ef, 0xffffef11, 0x000016f3, 0xffffe90d, 0xfffff317,
+ 0x00000ce9, 0x00002810, 0xffffd7f0, 0x00001028, 0xffffefd8, 0x0000291c, 0xffffd6e4, 0x00001c29,
+ 0xffffe3d7, 0x000020f7, 0xffffdf09, 0xfffff721, 0x000008df, 0x00002b06, 0xffffd4fa, 0x0000062b,
+ 0xfffff9d5, 0x00002e2e, 0xffffd1d2, 0x000031fc, 0xffffce04, 0xfffffc32, 0x000003ce, 0x000021e5,
+ 0xffffde1b, 0xffffe522, 0x00001ade, 0x00002cea, 0xffffd316, 0xffffea2d, 0x000015d3, 0x00004522,
+ 0xffffbade, 0x00002245, 0xffffddbb, 0x00004613, 0xffffb9ed, 0x00001346, 0xffffecba, 0x00004935,
+ 0xffffb6cb, 0x00003549, 0xffffcab7, 0x00003def, 0xffffc211, 0xffffef3e, 0x000010c2, 0x00004d05,
+ 0xffffb2fb, 0x0000054d, 0xfffffab3, 0x00005252, 0xffffadae, 0x000032cd, 0xffffcd33, 0x00003fd5,
+ 0xffffc02b, 0xffffd540, 0x00002ac0, 0x000059f6, 0xffffa60a, 0xfffff65a, 0x000009a6, 0x00007229,
+ 0xffff8dd7, 0x00002972, 0xffffd68e, 0x00007440, 0xffff8bc0, 0x00004074, 0xffffbf8c, 0x000051db,
+ 0xffffae25, 0xffffdb52, 0x000024ae, 0x00007716, 0xffff88ea, 0x00001677, 0xffffe989, 0x00007c5f,
+ 0xffff83a1, 0x00005f7c, 0xffffa084, 0x00006ee2, 0xffff911e, 0xffffe26f, 0x00001d91, 0x00005bb2,
+ 0xffffa44e, 0xffffb25c, 0x00004da4, 0x000070bc, 0xffff8f44, 0xffffbc71, 0x0000438f, 0x00001212,
+ 0xffffedee, 0x00002222, 0xffffddde, 0x00003f3f, 0xffffc0c1, 0x00006d6d, 0xffff9293, 0x00000000,
+ 0x03030000, 0xfcfd0000, 0x03ff0000, 0xfc010000, 0xff040000, 0x00fc0000, 0x07070000, 0xf8f90000,
+ 0x00000303, 0x03030303, 0xfcfd0303, 0x03ff0303, 0xfc010303, 0xff040303, 0x00fc0303, 0x07070303,
+ 0xf8f90303, 0xfffffcfd, 0x0302fcfd, 0xfcfcfcfd, 0x03fefcfd, 0xfc00fcfd, 0xff03fcfd, 0x00fbfcfd,
+ 0x0706fcfd, 0xf8f8fcfd, 0x000003ff, 0x030303ff, 0xfcfd03ff, 0x03ff03ff, 0xfc0103ff, 0xff0403ff,
+ 0x00fc03ff, 0x070703ff, 0xf8f903ff, 0xfffffc01, 0x0302fc01, 0xfcfcfc01, 0x03fefc01, 0xfc00fc01,
+ 0xff03fc01, 0x00fbfc01, 0x0706fc01, 0xf8f8fc01, 0xffffff04, 0x0302ff04, 0xfcfcff04, 0x03feff04,
+ 0xfc00ff04, 0xff03ff04, 0x00fbff04, 0x0706ff04, 0xf8f8ff04, 0x000000fc, 0x030300fc, 0xfcfd00fc,
+ 0x03ff00fc, 0xfc0100fc, 0xff0400fc, 0x00fc00fc, 0x070700fc, 0xf8f900fc, 0x00000707, 0x03030707,
+ 0xfcfd0707, 0x03ff0707, 0xfc010707, 0xff040707, 0x00fc0707, 0x07070707, 0xf8f90707, 0xfffff8f9,
+ 0x0302f8f9, 0xfcfcf8f9, 0x03fef8f9, 0xfc00f8f9, 0xff03f8f9, 0x00fbf8f9, 0x0706f8f9, 0xf8f8f8f9,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000404, 0xfffffbfc, 0x000004ff, 0xfffffb01, 0xffffff05, 0x000000fb, 0x00000a03,
+ 0xfffff5fd, 0x0000030a, 0xfffffcf6, 0x00000909, 0xfffff6f7, 0x000006f9, 0xfffff907, 0x00000bfd,
+ 0xfffff403, 0xfffffd0c, 0x000002f4, 0x00001108, 0xffffeef8, 0x00000811, 0xfffff7ef, 0x00001111,
+ 0xffffeeef, 0x00001301, 0xffffecff, 0x00000113, 0xfffffeed, 0x00000ff5, 0xfffff00b, 0xfffff510,
+ 0x00000af0, 0x000016fa, 0xffffe906, 0xfffffa17, 0x000005e9, 0x00001f12, 0xffffe0ee, 0x0000121f,
+ 0xffffede1, 0x00002008, 0xffffdff8, 0x00000820, 0xfffff7e0, 0x00002121, 0xffffdedf, 0x000023ff,
+ 0xffffdc01, 0xffffff24, 0x000000dc, 0x000016e9, 0xffffe917, 0x00001eef, 0xffffe111, 0xffffef1f,
+ 0x000010e1, 0x00003615, 0xffffc9eb, 0x00001536, 0xffffeaca, 0x00003725, 0xffffc8db, 0x00002537,
+ 0xffffdac9, 0x00002bf4, 0xffffd40c, 0xfffff42c, 0x00000bd4, 0x00003908, 0xffffc6f8, 0x00000839,
+ 0xfffff7c7, 0x00003d3d, 0xffffc2c3, 0x000041fb, 0xffffbe05, 0xfffffb42, 0x000004be, 0x00002cdc,
+ 0xffffd324, 0xffffdc2d, 0x000023d3, 0x00003be3, 0xffffc41d, 0xffffe33c, 0x00001cc4, 0x00005c2d,
+ 0xffffa3d3, 0x00002d5c, 0xffffd2a4, 0x00005d19, 0xffffa2e7, 0x0000195d, 0xffffe6a3, 0x00006147,
+ 0xffff9eb9, 0x00004761, 0xffffb89f, 0x000052ea, 0xffffad16, 0xffffea53, 0x000015ad, 0x00006607,
+ 0xffff99f9, 0x00000766, 0xfffff89a, 0x00006d6d, 0xffff9293, 0x000043bc, 0xffffbc44, 0x000054c7,
+ 0xffffab39, 0xffffc755, 0x000038ab, 0x000077f3, 0xffff880d, 0xfffff378, 0x00000c88, 0x00006dcf,
+ 0xffff9231, 0xffffcf6e, 0x00003092, 0x00007a98, 0xffff8568, 0xffff987b, 0x00006785, 0x00001818,
+ 0xffffe7e8, 0x00002e2e, 0xffffd1d2, 0x00005454, 0xffffabac, 0x00000000, 0x04040000, 0xfbfc0000,
+ 0x04ff0000, 0xfb010000, 0xff050000, 0x00fb0000, 0x0a030000, 0xf5fd0000, 0x030a0000, 0x00000404,
+ 0x04040404, 0xfbfc0404, 0x04ff0404, 0xfb010404, 0xff050404, 0x00fb0404, 0x0a030404, 0xf5fd0404,
+ 0x030a0404, 0xfffffbfc, 0x0403fbfc, 0xfbfbfbfc, 0x04fefbfc, 0xfb00fbfc, 0xff04fbfc, 0x00fafbfc,
+ 0x0a02fbfc, 0xf5fcfbfc, 0x0309fbfc, 0x000004ff, 0x040404ff, 0xfbfc04ff, 0x04ff04ff, 0xfb0104ff,
+ 0xff0504ff, 0x00fb04ff, 0x0a0304ff, 0xf5fd04ff, 0x030a04ff, 0xfffffb01, 0x0403fb01, 0xfbfbfb01,
+ 0x04fefb01, 0xfb00fb01, 0xff04fb01, 0x00fafb01, 0x0a02fb01, 0xf5fcfb01, 0x0309fb01, 0xffffff05,
+ 0x0403ff05, 0xfbfbff05, 0x04feff05, 0xfb00ff05, 0xff04ff05, 0x00faff05, 0x0a02ff05, 0xf5fcff05,
+ 0x0309ff05, 0x000000fb, 0x040400fb, 0xfbfc00fb, 0x04ff00fb, 0xfb0100fb, 0xff0500fb, 0x00fb00fb,
+ 0x0a0300fb, 0xf5fd00fb, 0x030a00fb, 0x00000a03, 0x04040a03, 0xfbfc0a03, 0x04ff0a03, 0xfb010a03,
+ 0xff050a03, 0x00fb0a03, 0x0a030a03, 0xf5fd0a03, 0x030a0a03, 0xfffff5fd, 0x0403f5fd, 0xfbfbf5fd,
+ 0x04fef5fd, 0xfb00f5fd, 0xff04f5fd, 0x00faf5fd, 0x0a02f5fd, 0xf5fcf5fd, 0x0309f5fd, 0x0000030a,
+ 0x0404030a, 0xfbfc030a, 0x04ff030a, 0xfb01030a, 0xff05030a, 0x00fb030a, 0x0a03030a, 0xf5fd030a,
+ 0x030a030a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000505, 0xfffffafb, 0x000006fe, 0xfffff902, 0xfffffe07, 0x000001f9, 0x00000b0b,
+ 0xfffff4f5, 0x00000d03, 0xfffff2fd, 0x0000030d, 0xfffffcf3, 0x000008f7, 0xfffff709, 0x00000efc,
+ 0xfffff104, 0xfffffc0f, 0x000003f1, 0x0000160b, 0xffffe9f5, 0x00000b16, 0xfffff4ea, 0x00001515,
+ 0xffffeaeb, 0x00001802, 0xffffe7fe, 0x00000218, 0xfffffde8, 0x000013f2, 0xffffec0e, 0xfffff214,
+ 0x00000dec, 0x00002617, 0xffffd9e9, 0x00001726, 0xffffe8da, 0x00001cf8, 0xffffe308, 0xfffff81d,
+ 0x000007e3, 0x0000270b, 0xffffd8f5, 0x00000b27, 0xfffff4d9, 0x00002929, 0xffffd6d7, 0x00002cff,
+ 0xffffd301, 0xffffff2d, 0x000000d3, 0x00001ce3, 0xffffe31d, 0x000026ea, 0xffffd916, 0xffffea27,
+ 0x000015d9, 0x0000431b, 0xffffbce5, 0x00001b43, 0xffffe4bd, 0x0000452f, 0xffffbad1, 0x00002f45,
+ 0xffffd0bb, 0x000037f1, 0xffffc80f, 0xfffff138, 0x00000ec8, 0x0000470b, 0xffffb8f5, 0x00000b47,
+ 0xfffff4b9, 0x00004c4c, 0xffffb3b4, 0x000052fa, 0xffffad06, 0xfffffa53, 0x000005ad, 0x000038d3,
+ 0xffffc72d, 0xffffd339, 0x00002cc7, 0x00004adc, 0xffffb524, 0xffffdc4b, 0x000023b5, 0x00007338,
+ 0xffff8cc8, 0x00003873, 0xffffc78d, 0x0000751f, 0xffff8ae1, 0x00001f75, 0xffffe08b, 0x00007a58,
+ 0xffff85a8, 0x0000587a, 0xffffa786, 0x000067e4, 0xffff981c, 0xffffe468, 0x00001b98, 0x000054ab,
+ 0xffffab55, 0x000069b8, 0xffff9648, 0xffffb86a, 0x00004796, 0x00001e1e, 0xffffe1e2, 0x00003a3a,
+ 0xffffc5c6, 0x00006969, 0xffff9697, 0x00000000, 0x05050000, 0xfafb0000, 0x06fe0000, 0xf9020000,
+ 0xfe070000, 0x01f90000, 0x0b0b0000, 0xf4f50000, 0x0d030000, 0xf2fd0000, 0x00000505, 0x05050505,
+ 0xfafb0505, 0x06fe0505, 0xf9020505, 0xfe070505, 0x01f90505, 0x0b0b0505, 0xf4f50505, 0x0d030505,
+ 0xf2fd0505, 0xfffffafb, 0x0504fafb, 0xfafafafb, 0x06fdfafb, 0xf901fafb, 0xfe06fafb, 0x01f8fafb,
+ 0x0b0afafb, 0xf4f4fafb, 0x0d02fafb, 0xf2fcfafb, 0x000006fe, 0x050506fe, 0xfafb06fe, 0x06fe06fe,
+ 0xf90206fe, 0xfe0706fe, 0x01f906fe, 0x0b0b06fe, 0xf4f506fe, 0x0d0306fe, 0xf2fd06fe, 0xfffff902,
+ 0x0504f902, 0xfafaf902, 0x06fdf902, 0xf901f902, 0xfe06f902, 0x01f8f902, 0x0b0af902, 0xf4f4f902,
+ 0x0d02f902, 0xf2fcf902, 0xfffffe07, 0x0504fe07, 0xfafafe07, 0x06fdfe07, 0xf901fe07, 0xfe06fe07,
+ 0x01f8fe07, 0x0b0afe07, 0xf4f4fe07, 0x0d02fe07, 0xf2fcfe07, 0x000001f9, 0x050501f9, 0xfafb01f9,
+ 0x06fe01f9, 0xf90201f9, 0xfe0701f9, 0x01f901f9, 0x0b0b01f9, 0xf4f501f9, 0x0d0301f9, 0xf2fd01f9,
+ 0x00000b0b, 0x05050b0b, 0xfafb0b0b, 0x06fe0b0b, 0xf9020b0b, 0xfe070b0b, 0x01f90b0b, 0x0b0b0b0b,
+ 0xf4f50b0b, 0x0d030b0b, 0xf2fd0b0b, 0xfffff4f5, 0x0504f4f5, 0xfafaf4f5, 0x06fdf4f5, 0xf901f4f5,
+ 0xfe06f4f5, 0x01f8f4f5, 0x0b0af4f5, 0xf4f4f4f5, 0x0d02f4f5, 0xf2fcf4f5, 0x00000d03, 0x05050d03,
+ 0xfafb0d03, 0x06fe0d03, 0xf9020d03, 0xfe070d03, 0x01f90d03, 0x0b0b0d03, 0xf4f50d03, 0x0d030d03,
+ 0xf2fd0d03, 0xfffff2fd, 0x0504f2fd, 0xfafaf2fd, 0x06fdf2fd, 0xf901f2fd, 0xfe06f2fd, 0x01f8f2fd,
+ 0x0b0af2fd, 0xf4f4f2fd, 0x0d02f2fd, 0xf2fcf2fd, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000606, 0xfffff9fa, 0x000007fe, 0xfffff802, 0xfffffe08, 0x000001f8, 0x00000d0d,
+ 0xfffff2f3, 0x00000f04, 0xfffff0fc, 0x0000040f, 0xfffffbf1, 0x00000af5, 0xfffff50b, 0x000011fb,
+ 0xffffee05, 0xfffffb12, 0x000004ee, 0x00001a0d, 0xffffe5f3, 0x00000d1a, 0xfffff2e6, 0x00001a1a,
+ 0xffffe5e6, 0x00001d02, 0xffffe2fe, 0x0000021d, 0xfffffde3, 0x000017f0, 0xffffe810, 0xfffff018,
+ 0x00000fe8, 0x00002e1c, 0xffffd1e4, 0x00001c2e, 0xffffe3d2, 0x000022f7, 0xffffdd09, 0xfffff723,
+ 0x000008dd, 0x00002f0d, 0xffffd0f3, 0x00000d2f, 0xfffff2d1, 0x00003131, 0xffffcecf, 0x000035ff,
+ 0xffffca01, 0xffffff36, 0x000000ca, 0x000022dd, 0xffffdd23, 0x00002ee6, 0xffffd11a, 0xffffe62f,
+ 0x000019d1, 0x00005120, 0xffffaee0, 0x00002051, 0xffffdfaf, 0x00005338, 0xffffacc8, 0x00003853,
+ 0xffffc7ad, 0x000042ee, 0xffffbd12, 0xffffee43, 0x000011bd, 0x0000560d, 0xffffa9f3, 0x00000d56,
+ 0xfffff2aa, 0x00005b5b, 0xffffa4a5, 0x000062f9, 0xffff9d07, 0xfffff963, 0x0000069d, 0x000043ca,
+ 0xffffbc36, 0xffffca44, 0x000035bc, 0x000059d4, 0xffffa62c, 0xffffd45a, 0x00002ba6, 0x00007bdf,
+ 0xffff8421, 0xffffdf7c, 0x00002084, 0x00006699, 0xffff9967, 0x00007eaa, 0xffff8156, 0xffffaa7f,
+ 0x00005581, 0x00002525, 0xffffdadb, 0x00004545, 0xffffbabb, 0x00000000, 0x06060000, 0xf9fa0000,
+ 0x07fe0000, 0xf8020000, 0xfe080000, 0x01f80000, 0x0d0d0000, 0xf2f30000, 0x0f040000, 0xf0fc0000,
+ 0x040f0000, 0x00000606, 0x06060606, 0xf9fa0606, 0x07fe0606, 0xf8020606, 0xfe080606, 0x01f80606,
+ 0x0d0d0606, 0xf2f30606, 0x0f040606, 0xf0fc0606, 0x040f0606, 0xfffff9fa, 0x0605f9fa, 0xf9f9f9fa,
+ 0x07fdf9fa, 0xf801f9fa, 0xfe07f9fa, 0x01f7f9fa, 0x0d0cf9fa, 0xf2f2f9fa, 0x0f03f9fa, 0xf0fbf9fa,
+ 0x040ef9fa, 0x000007fe, 0x060607fe, 0xf9fa07fe, 0x07fe07fe, 0xf80207fe, 0xfe0807fe, 0x01f807fe,
+ 0x0d0d07fe, 0xf2f307fe, 0x0f0407fe, 0xf0fc07fe, 0x040f07fe, 0xfffff802, 0x0605f802, 0xf9f9f802,
+ 0x07fdf802, 0xf801f802, 0xfe07f802, 0x01f7f802, 0x0d0cf802, 0xf2f2f802, 0x0f03f802, 0xf0fbf802,
+ 0x040ef802, 0xfffffe08, 0x0605fe08, 0xf9f9fe08, 0x07fdfe08, 0xf801fe08, 0xfe07fe08, 0x01f7fe08,
+ 0x0d0cfe08, 0xf2f2fe08, 0x0f03fe08, 0xf0fbfe08, 0x040efe08, 0x000001f8, 0x060601f8, 0xf9fa01f8,
+ 0x07fe01f8, 0xf80201f8, 0xfe0801f8, 0x01f801f8, 0x0d0d01f8, 0xf2f301f8, 0x0f0401f8, 0xf0fc01f8,
+ 0x040f01f8, 0x00000d0d, 0x06060d0d, 0xf9fa0d0d, 0x07fe0d0d, 0xf8020d0d, 0xfe080d0d, 0x01f80d0d,
+ 0x0d0d0d0d, 0xf2f30d0d, 0x0f040d0d, 0xf0fc0d0d, 0x040f0d0d, 0xfffff2f3, 0x0605f2f3, 0xf9f9f2f3,
+ 0x07fdf2f3, 0xf801f2f3, 0xfe07f2f3, 0x01f7f2f3, 0x0d0cf2f3, 0xf2f2f2f3, 0x0f03f2f3, 0xf0fbf2f3,
+ 0x040ef2f3, 0x00000f04, 0x06060f04, 0xf9fa0f04, 0x07fe0f04, 0xf8020f04, 0xfe080f04, 0x01f80f04,
+ 0x0d0d0f04, 0xf2f30f04, 0x0f040f04, 0xf0fc0f04, 0x040f0f04, 0xfffff0fc, 0x0605f0fc, 0xf9f9f0fc,
+ 0x07fdf0fc, 0xf801f0fc, 0xfe07f0fc, 0x01f7f0fc, 0x0d0cf0fc, 0xf2f2f0fc, 0x0f03f0fc, 0xf0fbf0fc,
+ 0x040ef0fc, 0x0000040f, 0x0606040f, 0xf9fa040f, 0x07fe040f, 0xf802040f, 0xfe08040f, 0x01f8040f,
+ 0x0d0d040f, 0xf2f3040f, 0x0f04040f, 0xf0fc040f, 0x040f040f, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000707, 0xfffff8f9, 0x000009fd, 0xfffff603, 0xfffffd0a, 0x000002f6, 0x00001010,
+ 0xffffeff0, 0x00001205, 0xffffedfb, 0x00000512, 0xfffffaee, 0x00000cf3, 0xfffff30d, 0x000014fa,
+ 0xffffeb06, 0xfffffa15, 0x000005eb, 0x00001e0f, 0xffffe1f1, 0x00000f1e, 0xfffff0e2, 0x00001e1e,
+ 0xffffe1e2, 0x00002202, 0xffffddfe, 0x00000222, 0xfffffdde, 0x00001bed, 0xffffe413, 0xffffed1c,
+ 0x000012e4, 0x00003620, 0xffffc9e0, 0x00002036, 0xffffdfca, 0x000028f5, 0xffffd70b, 0xfffff529,
+ 0x00000ad7, 0x0000370f, 0xffffc8f1, 0x00000f37, 0xfffff0c9, 0x00003939, 0xffffc6c7, 0x00003eff,
+ 0xffffc101, 0xffffff3f, 0x000000c1, 0x000027d8, 0xffffd828, 0x000036e2, 0xffffc91e, 0xffffe237,
+ 0x00001dc9, 0x00005e25, 0xffffa1db, 0x0000255e, 0xffffdaa2, 0x00006041, 0xffff9fbf, 0x00004160,
+ 0xffffbea0, 0x00004deb, 0xffffb215, 0xffffeb4e, 0x000014b2, 0x0000640f, 0xffff9bf1, 0x00000f64,
+ 0xfffff09c, 0x00006a6a, 0xffff9596, 0x000073f8, 0xffff8c08, 0xfffff874, 0x0000078c, 0x00004ec1,
+ 0xffffb13f, 0xffffc14f, 0x00003eb1, 0x000068cd, 0xffff9733, 0xffffcd69, 0x00003297, 0x00007788,
+ 0xffff8878, 0x00002b2b, 0xffffd4d5, 0x00005050, 0xffffafb0, 0x00000000, 0x07070000, 0xf8f90000,
+ 0x09fd0000, 0xf6030000, 0xfd0a0000, 0x02f60000, 0x10100000, 0xeff00000, 0x12050000, 0xedfb0000,
+ 0x05120000, 0x00000707, 0x07070707, 0xf8f90707, 0x09fd0707, 0xf6030707, 0xfd0a0707, 0x02f60707,
+ 0x10100707, 0xeff00707, 0x12050707, 0xedfb0707, 0x05120707, 0xfffff8f9, 0x0706f8f9, 0xf8f8f8f9,
+ 0x09fcf8f9, 0xf602f8f9, 0xfd09f8f9, 0x02f5f8f9, 0x100ff8f9, 0xefeff8f9, 0x1204f8f9, 0xedfaf8f9,
+ 0x0511f8f9, 0x000009fd, 0x070709fd, 0xf8f909fd, 0x09fd09fd, 0xf60309fd, 0xfd0a09fd, 0x02f609fd,
+ 0x101009fd, 0xeff009fd, 0x120509fd, 0xedfb09fd, 0x051209fd, 0xfffff603, 0x0706f603, 0xf8f8f603,
+ 0x09fcf603, 0xf602f603, 0xfd09f603, 0x02f5f603, 0x100ff603, 0xefeff603, 0x1204f603, 0xedfaf603,
+ 0x0511f603, 0xfffffd0a, 0x0706fd0a, 0xf8f8fd0a, 0x09fcfd0a, 0xf602fd0a, 0xfd09fd0a, 0x02f5fd0a,
+ 0x100ffd0a, 0xefeffd0a, 0x1204fd0a, 0xedfafd0a, 0x0511fd0a, 0x000002f6, 0x070702f6, 0xf8f902f6,
+ 0x09fd02f6, 0xf60302f6, 0xfd0a02f6, 0x02f602f6, 0x101002f6, 0xeff002f6, 0x120502f6, 0xedfb02f6,
+ 0x051202f6, 0x00001010, 0x07071010, 0xf8f91010, 0x09fd1010, 0xf6031010, 0xfd0a1010, 0x02f61010,
+ 0x10101010, 0xeff01010, 0x12051010, 0xedfb1010, 0x05121010, 0xffffeff0, 0x0706eff0, 0xf8f8eff0,
+ 0x09fceff0, 0xf602eff0, 0xfd09eff0, 0x02f5eff0, 0x100feff0, 0xefefeff0, 0x1204eff0, 0xedfaeff0,
+ 0x0511eff0, 0x00001205, 0x07071205, 0xf8f91205, 0x09fd1205, 0xf6031205, 0xfd0a1205, 0x02f61205,
+ 0x10101205, 0xeff01205, 0x12051205, 0xedfb1205, 0x05121205, 0xffffedfb, 0x0706edfb, 0xf8f8edfb,
+ 0x09fcedfb, 0xf602edfb, 0xfd09edfb, 0x02f5edfb, 0x100fedfb, 0xefefedfb, 0x1204edfb, 0xedfaedfb,
+ 0x0511edfb, 0x00000512, 0x07070512, 0xf8f90512, 0x09fd0512, 0xf6030512, 0xfd0a0512, 0x02f60512,
+ 0x10100512, 0xeff00512, 0x12050512, 0xedfb0512, 0x05120512, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000808, 0xfffff7f8, 0x00000afd, 0xfffff503, 0xfffffd0b, 0x000002f5, 0x00001212,
+ 0xffffedee, 0x00001405, 0xffffebfb, 0x00000514, 0xfffffaec, 0x00000ef1, 0xfffff10f, 0x000017f9,
+ 0xffffe807, 0xfffff918, 0x000006e8, 0x00002311, 0xffffdcef, 0x00001123, 0xffffeedd, 0x00002222,
+ 0xffffddde, 0x00002603, 0xffffd9fd, 0x00000326, 0xfffffcda, 0x00001fea, 0xffffe016, 0xffffea20,
+ 0x000015e0, 0x00003d25, 0xffffc2db, 0x0000253d, 0xffffdac3, 0x00002ef3, 0xffffd10d, 0xfffff32f,
+ 0x00000cd1, 0x00003f11, 0xffffc0ef, 0x0000113f, 0xffffeec1, 0x00004141, 0xffffbebf, 0x000047ff,
+ 0xffffb801, 0xffffff48, 0x000000b8, 0x00002dd2, 0xffffd22e, 0x00003edd, 0xffffc123, 0xffffdd3f,
+ 0x000022c1, 0x00006b2b, 0xffff94d5, 0x00002b6b, 0xffffd495, 0x00006e4b, 0xffff91b5, 0x00004b6e,
+ 0xffffb492, 0x000058e8, 0xffffa718, 0xffffe859, 0x000017a7, 0x00007211, 0xffff8def, 0x00001172,
+ 0xffffee8e, 0x00007979, 0xffff8687, 0x00005ab8, 0xffffa548, 0xffffb85b, 0x000047a5, 0x000077c6,
+ 0xffff883a, 0xffffc678, 0x00003988, 0x00003131, 0xffffcecf, 0x00005c5c, 0xffffa3a4, 0x00000000,
+ 0x08080000, 0xf7f80000, 0x0afd0000, 0xf5030000, 0xfd0b0000, 0x02f50000, 0x12120000, 0xedee0000,
+ 0x14050000, 0xebfb0000, 0x05140000, 0x00000808, 0x08080808, 0xf7f80808, 0x0afd0808, 0xf5030808,
+ 0xfd0b0808, 0x02f50808, 0x12120808, 0xedee0808, 0x14050808, 0xebfb0808, 0x05140808, 0xfffff7f8,
+ 0x0807f7f8, 0xf7f7f7f8, 0x0afcf7f8, 0xf502f7f8, 0xfd0af7f8, 0x02f4f7f8, 0x1211f7f8, 0xededf7f8,
+ 0x1404f7f8, 0xebfaf7f8, 0x0513f7f8, 0x00000afd, 0x08080afd, 0xf7f80afd, 0x0afd0afd, 0xf5030afd,
+ 0xfd0b0afd, 0x02f50afd, 0x12120afd, 0xedee0afd, 0x14050afd, 0xebfb0afd, 0x05140afd, 0xfffff503,
+ 0x0807f503, 0xf7f7f503, 0x0afcf503, 0xf502f503, 0xfd0af503, 0x02f4f503, 0x1211f503, 0xededf503,
+ 0x1404f503, 0xebfaf503, 0x0513f503, 0xfffffd0b, 0x0807fd0b, 0xf7f7fd0b, 0x0afcfd0b, 0xf502fd0b,
+ 0xfd0afd0b, 0x02f4fd0b, 0x1211fd0b, 0xededfd0b, 0x1404fd0b, 0xebfafd0b, 0x0513fd0b, 0x000002f5,
+ 0x080802f5, 0xf7f802f5, 0x0afd02f5, 0xf50302f5, 0xfd0b02f5, 0x02f502f5, 0x121202f5, 0xedee02f5,
+ 0x140502f5, 0xebfb02f5, 0x051402f5, 0x00001212, 0x08081212, 0xf7f81212, 0x0afd1212, 0xf5031212,
+ 0xfd0b1212, 0x02f51212, 0x12121212, 0xedee1212, 0x14051212, 0xebfb1212, 0x05141212, 0xffffedee,
+ 0x0807edee, 0xf7f7edee, 0x0afcedee, 0xf502edee, 0xfd0aedee, 0x02f4edee, 0x1211edee, 0xedededee,
+ 0x1404edee, 0xebfaedee, 0x0513edee, 0x00001405, 0x08081405, 0xf7f81405, 0x0afd1405, 0xf5031405,
+ 0xfd0b1405, 0x02f51405, 0x12121405, 0xedee1405, 0x14051405, 0xebfb1405, 0x05141405, 0xffffebfb,
+ 0x0807ebfb, 0xf7f7ebfb, 0x0afcebfb, 0xf502ebfb, 0xfd0aebfb, 0x02f4ebfb, 0x1211ebfb, 0xededebfb,
+ 0x1404ebfb, 0xebfaebfb, 0x0513ebfb, 0x00000514, 0x08080514, 0xf7f80514, 0x0afd0514, 0xf5030514,
+ 0xfd0b0514, 0x02f50514, 0x12120514, 0xedee0514, 0x14050514, 0xebfb0514, 0x05140514, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000909, 0xfffff6f7, 0x00000bfd, 0xfffff403, 0xfffffd0c, 0x000002f4, 0x00001414,
+ 0xffffebec, 0x00001706, 0xffffe8fa, 0x00000617, 0xfffff9e9, 0x000010ef, 0xffffef11, 0x00001af9,
+ 0xffffe507, 0xfffff91b, 0x000006e5, 0x00002713, 0xffffd8ed, 0x00001327, 0xffffecd9, 0x00002727,
+ 0xffffd8d9, 0x00002b03, 0xffffd4fd, 0x0000032b, 0xfffffcd5, 0x000023e8, 0xffffdc18, 0xffffe824,
+ 0x000017dc, 0x0000452a, 0xffffbad6, 0x00002a45, 0xffffd5bb, 0x000034f2, 0xffffcb0e, 0xfffff235,
+ 0x00000dcb, 0x00004713, 0xffffb8ed, 0x00001347, 0xffffecb9, 0x00004949, 0xffffb6b7, 0x00004ffe,
+ 0xffffb002, 0xfffffe50, 0x000001b0, 0x000033cc, 0xffffcc34, 0x000045d9, 0xffffba27, 0xffffd946,
+ 0x000026ba, 0x00007930, 0xffff86d0, 0x00003079, 0xffffcf87, 0x00007c54, 0xffff83ac, 0x0000547c,
+ 0xffffab84, 0x000063e5, 0xffff9c1b, 0xffffe564, 0x00001a9c, 0x000065af, 0xffff9a51, 0xffffaf66,
+ 0x0000509a, 0x00003737, 0xffffc8c9, 0x00006868, 0xffff9798, 0x00000000, 0x09090000, 0xf6f70000,
+ 0x0bfd0000, 0xf4030000, 0xfd0c0000, 0x02f40000, 0x14140000, 0xebec0000, 0x17060000, 0xe8fa0000,
+ 0x06170000, 0xf9e90000, 0x00000909, 0x09090909, 0xf6f70909, 0x0bfd0909, 0xf4030909, 0xfd0c0909,
+ 0x02f40909, 0x14140909, 0xebec0909, 0x17060909, 0xe8fa0909, 0x06170909, 0xf9e90909, 0xfffff6f7,
+ 0x0908f6f7, 0xf6f6f6f7, 0x0bfcf6f7, 0xf402f6f7, 0xfd0bf6f7, 0x02f3f6f7, 0x1413f6f7, 0xebebf6f7,
+ 0x1705f6f7, 0xe8f9f6f7, 0x0616f6f7, 0xf9e8f6f7, 0x00000bfd, 0x09090bfd, 0xf6f70bfd, 0x0bfd0bfd,
+ 0xf4030bfd, 0xfd0c0bfd, 0x02f40bfd, 0x14140bfd, 0xebec0bfd, 0x17060bfd, 0xe8fa0bfd, 0x06170bfd,
+ 0xf9e90bfd, 0xfffff403, 0x0908f403, 0xf6f6f403, 0x0bfcf403, 0xf402f403, 0xfd0bf403, 0x02f3f403,
+ 0x1413f403, 0xebebf403, 0x1705f403, 0xe8f9f403, 0x0616f403, 0xf9e8f403, 0xfffffd0c, 0x0908fd0c,
+ 0xf6f6fd0c, 0x0bfcfd0c, 0xf402fd0c, 0xfd0bfd0c, 0x02f3fd0c, 0x1413fd0c, 0xebebfd0c, 0x1705fd0c,
+ 0xe8f9fd0c, 0x0616fd0c, 0xf9e8fd0c, 0x000002f4, 0x090902f4, 0xf6f702f4, 0x0bfd02f4, 0xf40302f4,
+ 0xfd0c02f4, 0x02f402f4, 0x141402f4, 0xebec02f4, 0x170602f4, 0xe8fa02f4, 0x061702f4, 0xf9e902f4,
+ 0x00001414, 0x09091414, 0xf6f71414, 0x0bfd1414, 0xf4031414, 0xfd0c1414, 0x02f41414, 0x14141414,
+ 0xebec1414, 0x17061414, 0xe8fa1414, 0x06171414, 0xf9e91414, 0xffffebec, 0x0908ebec, 0xf6f6ebec,
+ 0x0bfcebec, 0xf402ebec, 0xfd0bebec, 0x02f3ebec, 0x1413ebec, 0xebebebec, 0x1705ebec, 0xe8f9ebec,
+ 0x0616ebec, 0xf9e8ebec, 0x00001706, 0x09091706, 0xf6f71706, 0x0bfd1706, 0xf4031706, 0xfd0c1706,
+ 0x02f41706, 0x14141706, 0xebec1706, 0x17061706, 0xe8fa1706, 0x06171706, 0xf9e91706, 0xffffe8fa,
+ 0x0908e8fa, 0xf6f6e8fa, 0x0bfce8fa, 0xf402e8fa, 0xfd0be8fa, 0x02f3e8fa, 0x1413e8fa, 0xebebe8fa,
+ 0x1705e8fa, 0xe8f9e8fa, 0x0616e8fa, 0xf9e8e8fa, 0x00000617, 0x09090617, 0xf6f70617, 0x0bfd0617,
+ 0xf4030617, 0xfd0c0617, 0x02f40617, 0x14140617, 0xebec0617, 0x17060617, 0xe8fa0617, 0x06170617,
+ 0xf9e90617, 0xfffff9e9, 0x0908f9e9, 0xf6f6f9e9, 0x0bfcf9e9, 0xf402f9e9, 0xfd0bf9e9, 0x02f3f9e9,
+ 0x1413f9e9, 0xebebf9e9, 0x1705f9e9, 0xe8f9f9e9, 0x0616f9e9, 0xf9e8f9e9, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000202, 0xfffffdfe, 0x00000200, 0xfffffe00, 0x00000002, 0xfffffffe, 0x00000404,
+ 0xfffffbfc, 0x00000400, 0xfffffc00, 0x00000004, 0xfffffffc, 0x000003fc, 0xfffffc04, 0x000005fe,
+ 0xfffffa02, 0xfffffe06, 0x000001fa, 0x00000804, 0xfffff7fc, 0x00000408, 0xfffffbf8, 0x00000808,
+ 0xfffff7f8, 0x00000a00, 0xfffff600, 0x0000000a, 0xfffffff6, 0x000007fc, 0xfffff804, 0xfffffc08,
+ 0x000003f8, 0x00000e08, 0xfffff1f8, 0x0000080e, 0xfffff7f2, 0x00000bfe, 0xfffff402, 0xfffffe0c,
+ 0x000001f4, 0x00001004, 0xffffeffc, 0x00000410, 0xfffffbf0, 0x00001010, 0xffffeff0, 0x00001200,
+ 0xffffee00, 0x00000012, 0xffffffee, 0x00000bf4, 0xfffff40c, 0x00000ff8, 0xfffff008, 0xfffff810,
+ 0x000007f0, 0x00001a0a, 0xffffe5f6, 0x00000a1a, 0xfffff5e6, 0x00001c12, 0xffffe3ee, 0x0000121c,
+ 0xffffede4, 0x000015fa, 0xffffea06, 0xfffffa16, 0x000005ea, 0x00001c04, 0xffffe3fc, 0x0000041c,
+ 0xfffffbe4, 0x00001e1e, 0xffffe1e2, 0x00001ffe, 0xffffe002, 0xfffffe20, 0x000001e0, 0x000015ee,
+ 0xffffea12, 0xffffee16, 0x000011ea, 0x00001df2, 0xffffe20e, 0xfffff21e, 0x00000de2, 0x00002e16,
+ 0xffffd1ea, 0x0000162e, 0xffffe9d2, 0x00002e0c, 0xffffd1f4, 0x00000c2e, 0xfffff3d2, 0x00003022,
+ 0xffffcfde, 0x00002230, 0xffffddd0, 0x000027f6, 0xffffd80a, 0xfffff628, 0x000009d8, 0x00003204,
+ 0xffffcdfc, 0x00000432, 0xfffffbce, 0x00003636, 0xffffc9ca, 0x000021de, 0xffffde22, 0x000029e4,
+ 0xffffd61c, 0xffffe42a, 0x00001bd6, 0x00003bfa, 0xffffc406, 0xfffffa3c, 0x000005c4, 0x00004c1a,
+ 0xffffb3e6, 0x00001a4c, 0xffffe5b4, 0x00004c2a, 0xffffb3d6, 0x00002a4c, 0xffffd5b4, 0x000035e8,
+ 0xffffca18, 0xffffe836, 0x000017ca, 0x00004e0e, 0xffffb1f2, 0x00000e4e, 0xfffff1b2, 0x0000523e,
+ 0xffffadc2, 0x00003e52, 0xffffc1ae, 0x000049ec, 0xffffb614, 0xffffec4a, 0x000013b6, 0x00005802,
+ 0xffffa7fe, 0x00000258, 0xfffffda8, 0x00005c5c, 0xffffa3a4, 0x00003bcc, 0xffffc434, 0xffffcc3c,
+ 0x000033c4, 0x00007634, 0xffff89cc, 0x00003476, 0xffffcb8a, 0x000049d4, 0xffffb62c, 0xffffd44a,
+ 0x00002bb6, 0x0000764a, 0xffff89b6, 0x00004a76, 0xffffb58a, 0x00007620, 0xffff89e0, 0x00002076,
+ 0xffffdf8a, 0x000065f4, 0xffff9a0c, 0xfffff466, 0x00000b9a, 0x00005fd8, 0xffffa028, 0xffffd860,
+ 0x000027a0, 0x000075de, 0xffff8a22, 0xffffde76, 0x0000218a, 0x000057a8, 0xffffa858, 0x000067b2,
+ 0xffff984e, 0xffffb268, 0x00004d98, 0x00000c0c, 0xfffff3f4, 0x00001616, 0xffffe9ea, 0x00002a2a,
+ 0xffffd5d6, 0x00004848, 0xffffb7b8, 0x00000000, 0x02020000, 0xfdfe0000, 0x02000000, 0xfe000000,
+ 0x00020000, 0xfffe0000, 0x00000202, 0x02020202, 0xfdfe0202, 0x02000202, 0xfe000202, 0x00020202,
+ 0xfffe0202, 0xfffffdfe, 0x0201fdfe, 0xfdfdfdfe, 0x01fffdfe, 0xfdfffdfe, 0x0001fdfe, 0xfffdfdfe,
+ 0x00000200, 0x02020200, 0xfdfe0200, 0x02000200, 0xfe000200, 0x00020200, 0xfffe0200, 0xfffffe00,
+ 0x0201fe00, 0xfdfdfe00, 0x01fffe00, 0xfdfffe00, 0x0001fe00, 0xfffdfe00, 0x00000002, 0x02020002,
+ 0xfdfe0002, 0x02000002, 0xfe000002, 0x00020002, 0xfffe0002, 0xfffffffe, 0x0201fffe, 0xfdfdfffe,
+ 0x01fffffe, 0xfdfffffe, 0x0001fffe, 0xfffdfffe, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000303, 0xfffffcfd, 0x00000300, 0xfffffd00, 0x00000003, 0xfffffffd, 0x00000606,
+ 0xfffff9fa, 0x00000903, 0xfffff6fd, 0x00000309, 0xfffffcf7, 0x000008fd, 0xfffff703, 0xfffffd09,
+ 0x000002f7, 0x000005fa, 0xfffffa06, 0x00000c06, 0xfffff3fa, 0x0000060c, 0xfffff9f4, 0x00000c0c,
+ 0xfffff3f4, 0x00000f00, 0xfffff100, 0x0000000f, 0xfffffff1, 0x00000bf7, 0xfffff409, 0xfffff70c,
+ 0x000008f4, 0x0000180f, 0xffffe7f1, 0x00000f18, 0xfffff0e8, 0x000011fa, 0xffffee06, 0xfffffa12,
+ 0x000005ee, 0x00001806, 0xffffe7fa, 0x00000618, 0xfffff9e8, 0x00001818, 0xffffe7e8, 0x00001b00,
+ 0xffffe500, 0x0000001b, 0xffffffe5, 0x000011ee, 0xffffee12, 0x000017f4, 0xffffe80c, 0xfffff418,
+ 0x00000be8, 0x0000270f, 0xffffd8f1, 0x00000f27, 0xfffff0d9, 0x00002a1b, 0xffffd5e5, 0x00001b2a,
+ 0xffffe4d6, 0x000020f7, 0xffffdf09, 0xfffff721, 0x000008df, 0x00002a06, 0xffffd5fa, 0x0000062a,
+ 0xfffff9d6, 0x00002d2d, 0xffffd2d3, 0x000032fd, 0xffffcd03, 0xfffffd33, 0x000002cd, 0x000020e5,
+ 0xffffdf1b, 0xffffe521, 0x00001adf, 0x00002ceb, 0xffffd315, 0xffffeb2d, 0x000014d3, 0x00004521,
+ 0xffffbadf, 0x00002145, 0xffffdebb, 0x00004512, 0xffffbaee, 0x00001245, 0xffffedbb, 0x00004836,
+ 0xffffb7ca, 0x00003648, 0xffffc9b8, 0x00003eee, 0xffffc112, 0xffffee3f, 0x000011c1, 0x00004e06,
+ 0xffffb1fa, 0x0000064e, 0xfffff9b2, 0x00005151, 0xffffaeaf, 0x000032cd, 0xffffcd33, 0x00003ed6,
+ 0xffffc12a, 0xffffd63f, 0x000029c1, 0x000059f7, 0xffffa609, 0xfffff75a, 0x000008a6, 0x0000722a,
+ 0xffff8dd6, 0x00002a72, 0xffffd58e, 0x0000753f, 0xffff8ac1, 0x00003f75, 0xffffc08b, 0x000050dc,
+ 0xffffaf24, 0xffffdc51, 0x000023af, 0x00007815, 0xffff87eb, 0x00001578, 0xffffea88, 0x00007b60,
+ 0xffff84a0, 0x0000607b, 0xffff9f85, 0x00006ee2, 0xffff911e, 0xffffe26f, 0x00001d91, 0x00005cb2,
+ 0xffffa34e, 0xffffb25d, 0x00004da3, 0x000071bb, 0xffff8e45, 0xffffbb72, 0x0000448e, 0x00001212,
+ 0xffffedee, 0x00002121, 0xffffdedf, 0x00003f3f, 0xffffc0c1, 0x00006c6c, 0xffff9394, 0x00000000,
+ 0x03030000, 0xfcfd0000, 0x03000000, 0xfd000000, 0x00030000, 0xfffd0000, 0x06060000, 0xf9fa0000,
+ 0x00000303, 0x03030303, 0xfcfd0303, 0x03000303, 0xfd000303, 0x00030303, 0xfffd0303, 0x06060303,
+ 0xf9fa0303, 0xfffffcfd, 0x0302fcfd, 0xfcfcfcfd, 0x02fffcfd, 0xfcfffcfd, 0x0002fcfd, 0xfffcfcfd,
+ 0x0605fcfd, 0xf9f9fcfd, 0x00000300, 0x03030300, 0xfcfd0300, 0x03000300, 0xfd000300, 0x00030300,
+ 0xfffd0300, 0x06060300, 0xf9fa0300, 0xfffffd00, 0x0302fd00, 0xfcfcfd00, 0x02fffd00, 0xfcfffd00,
+ 0x0002fd00, 0xfffcfd00, 0x0605fd00, 0xf9f9fd00, 0x00000003, 0x03030003, 0xfcfd0003, 0x03000003,
+ 0xfd000003, 0x00030003, 0xfffd0003, 0x06060003, 0xf9fa0003, 0xfffffffd, 0x0302fffd, 0xfcfcfffd,
+ 0x02fffffd, 0xfcfffffd, 0x0002fffd, 0xfffcfffd, 0x0605fffd, 0xf9f9fffd, 0x00000606, 0x03030606,
+ 0xfcfd0606, 0x03000606, 0xfd000606, 0x00030606, 0xfffd0606, 0x06060606, 0xf9fa0606, 0xfffff9fa,
+ 0x0302f9fa, 0xfcfcf9fa, 0x02fff9fa, 0xfcfff9fa, 0x0002f9fa, 0xfffcf9fa, 0x0605f9fa, 0xf9f9f9fa,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000404, 0xfffffbfc, 0x00000400, 0xfffffc00, 0x00000004, 0xfffffffc, 0x00000804,
+ 0xfffff7fc, 0x00000408, 0xfffffbf8, 0x00000808, 0xfffff7f8, 0x000007f8, 0xfffff808, 0x00000bfc,
+ 0xfffff404, 0xfffffc0c, 0x000003f4, 0x00001008, 0xffffeff8, 0x00000810, 0xfffff7f0, 0x00001010,
+ 0xffffeff0, 0x00001400, 0xffffec00, 0x00000014, 0xffffffec, 0x00000ff4, 0xfffff00c, 0xfffff410,
+ 0x00000bf0, 0x000017fc, 0xffffe804, 0xfffffc18, 0x000003e8, 0x00002010, 0xffffdff0, 0x00001020,
+ 0xffffefe0, 0x00002008, 0xffffdff8, 0x00000820, 0xfffff7e0, 0x00002020, 0xffffdfe0, 0x00002400,
+ 0xffffdc00, 0x00000024, 0xffffffdc, 0x000017e8, 0xffffe818, 0x00001ff0, 0xffffe010, 0xfffff020,
+ 0x00000fe0, 0x00003414, 0xffffcbec, 0x00001434, 0xffffebcc, 0x00003824, 0xffffc7dc, 0x00002438,
+ 0xffffdbc8, 0x00002bf4, 0xffffd40c, 0xfffff42c, 0x00000bd4, 0x00003808, 0xffffc7f8, 0x00000838,
+ 0xfffff7c8, 0x00003c3c, 0xffffc3c4, 0x00003ffc, 0xffffc004, 0xfffffc40, 0x000003c0, 0x00002bdc,
+ 0xffffd424, 0xffffdc2c, 0x000023d4, 0x00003be4, 0xffffc41c, 0xffffe43c, 0x00001bc4, 0x00005c2c,
+ 0xffffa3d4, 0x00002c5c, 0xffffd3a4, 0x00005c18, 0xffffa3e8, 0x0000185c, 0xffffe7a4, 0x00006048,
+ 0xffff9fb8, 0x00004860, 0xffffb7a0, 0x000053ec, 0xffffac14, 0xffffec54, 0x000013ac, 0x00006408,
+ 0xffff9bf8, 0x00000864, 0xfffff79c, 0x00006c6c, 0xffff9394, 0x000043bc, 0xffffbc44, 0x000053c8,
+ 0xffffac38, 0xffffc854, 0x000037ac, 0x000077f4, 0xffff880c, 0xfffff478, 0x00000b88, 0x00006bd0,
+ 0xffff9430, 0xffffd06c, 0x00002f94, 0x00007b98, 0xffff8468, 0xffff987c, 0x00006784, 0x00001818,
+ 0xffffe7e8, 0x00002c2c, 0xffffd3d4, 0x00005454, 0xffffabac, 0x00000000, 0x04040000, 0xfbfc0000,
+ 0x04000000, 0xfc000000, 0x00040000, 0xfffc0000, 0x08040000, 0xf7fc0000, 0x04080000, 0x00000404,
+ 0x04040404, 0xfbfc0404, 0x04000404, 0xfc000404, 0x00040404, 0xfffc0404, 0x08040404, 0xf7fc0404,
+ 0x04080404, 0xfffffbfc, 0x0403fbfc, 0xfbfbfbfc, 0x03fffbfc, 0xfbfffbfc, 0x0003fbfc, 0xfffbfbfc,
+ 0x0803fbfc, 0xf7fbfbfc, 0x0407fbfc, 0x00000400, 0x04040400, 0xfbfc0400, 0x04000400, 0xfc000400,
+ 0x00040400, 0xfffc0400, 0x08040400, 0xf7fc0400, 0x04080400, 0xfffffc00, 0x0403fc00, 0xfbfbfc00,
+ 0x03fffc00, 0xfbfffc00, 0x0003fc00, 0xfffbfc00, 0x0803fc00, 0xf7fbfc00, 0x0407fc00, 0x00000004,
+ 0x04040004, 0xfbfc0004, 0x04000004, 0xfc000004, 0x00040004, 0xfffc0004, 0x08040004, 0xf7fc0004,
+ 0x04080004, 0xfffffffc, 0x0403fffc, 0xfbfbfffc, 0x03fffffc, 0xfbfffffc, 0x0003fffc, 0xfffbfffc,
+ 0x0803fffc, 0xf7fbfffc, 0x0407fffc, 0x00000804, 0x04040804, 0xfbfc0804, 0x04000804, 0xfc000804,
+ 0x00040804, 0xfffc0804, 0x08040804, 0xf7fc0804, 0x04080804, 0xfffff7fc, 0x0403f7fc, 0xfbfbf7fc,
+ 0x03fff7fc, 0xfbfff7fc, 0x0003f7fc, 0xfffbf7fc, 0x0803f7fc, 0xf7fbf7fc, 0x0407f7fc, 0x00000408,
+ 0x04040408, 0xfbfc0408, 0x04000408, 0xfc000408, 0x00040408, 0xfffc0408, 0x08040408, 0xf7fc0408,
+ 0x04080408, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000505, 0xfffffafb, 0x00000500, 0xfffffb00, 0x00000005, 0xfffffffb, 0x00000a0a,
+ 0xfffff5f6, 0x00000f05, 0xfffff0fb, 0x0000050f, 0xfffffaf1, 0x000009f6, 0xfffff60a, 0x00000efb,
+ 0xfffff105, 0xfffffb0f, 0x000004f1, 0x0000140a, 0xffffebf6, 0x00000a14, 0xfffff5ec, 0x00001414,
+ 0xffffebec, 0x00001900, 0xffffe700, 0x00000019, 0xffffffe7, 0x000013f1, 0xffffec0f, 0xfffff114,
+ 0x00000eec, 0x00002819, 0xffffd7e7, 0x00001928, 0xffffe6d8, 0x00001df6, 0xffffe20a, 0xfffff61e,
+ 0x000009e2, 0x0000280a, 0xffffd7f6, 0x00000a28, 0xfffff5d8, 0x00002828, 0xffffd7d8, 0x00002d00,
+ 0xffffd300, 0x0000002d, 0xffffffd3, 0x00001de2, 0xffffe21e, 0x000027ec, 0xffffd814, 0xffffec28,
+ 0x000013d8, 0x00004119, 0xffffbee7, 0x00001941, 0xffffe6bf, 0x0000462d, 0xffffb9d3, 0x00002d46,
+ 0xffffd2ba, 0x000036f1, 0xffffc90f, 0xfffff137, 0x00000ec9, 0x0000460a, 0xffffb9f6, 0x00000a46,
+ 0xfffff5ba, 0x00004b4b, 0xffffb4b5, 0x000054fb, 0xffffab05, 0xfffffb55, 0x000004ab, 0x000036d3,
+ 0xffffc92d, 0xffffd337, 0x00002cc9, 0x00004add, 0xffffb523, 0xffffdd4b, 0x000022b5, 0x00007337,
+ 0xffff8cc9, 0x00003773, 0xffffc88d, 0x0000731e, 0xffff8ce2, 0x00001e73, 0xffffe18d, 0x0000785a,
+ 0xffff87a6, 0x00005a78, 0xffffa588, 0x000068e2, 0xffff971e, 0xffffe269, 0x00001d97, 0x000054ab,
+ 0xffffab55, 0x000068ba, 0xffff9746, 0xffffba69, 0x00004597, 0x00001e1e, 0xffffe1e2, 0x00003c3c,
+ 0xffffc3c4, 0x00006969, 0xffff9697, 0x00000000, 0x05050000, 0xfafb0000, 0x05000000, 0xfb000000,
+ 0x00050000, 0xfffb0000, 0x0a0a0000, 0xf5f60000, 0x0f050000, 0xf0fb0000, 0x00000505, 0x05050505,
+ 0xfafb0505, 0x05000505, 0xfb000505, 0x00050505, 0xfffb0505, 0x0a0a0505, 0xf5f60505, 0x0f050505,
+ 0xf0fb0505, 0xfffffafb, 0x0504fafb, 0xfafafafb, 0x04fffafb, 0xfafffafb, 0x0004fafb, 0xfffafafb,
+ 0x0a09fafb, 0xf5f5fafb, 0x0f04fafb, 0xf0fafafb, 0x00000500, 0x05050500, 0xfafb0500, 0x05000500,
+ 0xfb000500, 0x00050500, 0xfffb0500, 0x0a0a0500, 0xf5f60500, 0x0f050500, 0xf0fb0500, 0xfffffb00,
+ 0x0504fb00, 0xfafafb00, 0x04fffb00, 0xfafffb00, 0x0004fb00, 0xfffafb00, 0x0a09fb00, 0xf5f5fb00,
+ 0x0f04fb00, 0xf0fafb00, 0x00000005, 0x05050005, 0xfafb0005, 0x05000005, 0xfb000005, 0x00050005,
+ 0xfffb0005, 0x0a0a0005, 0xf5f60005, 0x0f050005, 0xf0fb0005, 0xfffffffb, 0x0504fffb, 0xfafafffb,
+ 0x04fffffb, 0xfafffffb, 0x0004fffb, 0xfffafffb, 0x0a09fffb, 0xf5f5fffb, 0x0f04fffb, 0xf0fafffb,
+ 0x00000a0a, 0x05050a0a, 0xfafb0a0a, 0x05000a0a, 0xfb000a0a, 0x00050a0a, 0xfffb0a0a, 0x0a0a0a0a,
+ 0xf5f60a0a, 0x0f050a0a, 0xf0fb0a0a, 0xfffff5f6, 0x0504f5f6, 0xfafaf5f6, 0x04fff5f6, 0xfafff5f6,
+ 0x0004f5f6, 0xfffaf5f6, 0x0a09f5f6, 0xf5f5f5f6, 0x0f04f5f6, 0xf0faf5f6, 0x00000f05, 0x05050f05,
+ 0xfafb0f05, 0x05000f05, 0xfb000f05, 0x00050f05, 0xfffb0f05, 0x0a0a0f05, 0xf5f60f05, 0x0f050f05,
+ 0xf0fb0f05, 0xfffff0fb, 0x0504f0fb, 0xfafaf0fb, 0x04fff0fb, 0xfafff0fb, 0x0004f0fb, 0xfffaf0fb,
+ 0x0a09f0fb, 0xf5f5f0fb, 0x0f04f0fb, 0xf0faf0fb, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000606, 0xfffff9fa, 0x00000600, 0xfffffa00, 0x00000006, 0xfffffffa, 0x00000c0c,
+ 0xfffff3f4, 0x00000c06, 0xfffff3fa, 0x0000060c, 0xfffff9f4, 0x00000bf4, 0xfffff40c, 0x000011fa,
+ 0xffffee06, 0xfffffa12, 0x000005ee, 0x0000180c, 0xffffe7f4, 0x00000c18, 0xfffff3e8, 0x00001818,
+ 0xffffe7e8, 0x00001e00, 0xffffe200, 0x0000001e, 0xffffffe2, 0x000017ee, 0xffffe812, 0xffffee18,
+ 0x000011e8, 0x0000301e, 0xffffcfe2, 0x00001e30, 0xffffe1d0, 0x000023fa, 0xffffdc06, 0xfffffa24,
+ 0x000005dc, 0x0000300c, 0xffffcff4, 0x00000c30, 0xfffff3d0, 0x00003030, 0xffffcfd0, 0x00003600,
+ 0xffffca00, 0x00000036, 0xffffffca, 0x000023dc, 0xffffdc24, 0x00002fe8, 0xffffd018, 0xffffe830,
+ 0x000017d0, 0x00004e1e, 0xffffb1e2, 0x00001e4e, 0xffffe1b2, 0x00005436, 0xffffabca, 0x00003654,
+ 0xffffc9ac, 0x000041ee, 0xffffbe12, 0xffffee42, 0x000011be, 0x0000540c, 0xffffabf4, 0x00000c54,
+ 0xfffff3ac, 0x00005a5a, 0xffffa5a6, 0x00005ffa, 0xffffa006, 0xfffffa60, 0x000005a0, 0x000041ca,
+ 0xffffbe36, 0xffffca42, 0x000035be, 0x000059d6, 0xffffa62a, 0xffffd65a, 0x000029a6, 0x00007de2,
+ 0xffff821e, 0xffffe27e, 0x00001d82, 0x0000659a, 0xffff9a66, 0x00007dac, 0xffff8254, 0xffffac7e,
+ 0x00005382, 0x00002424, 0xffffdbdc, 0x00004242, 0xffffbdbe, 0x00000000, 0x06060000, 0xf9fa0000,
+ 0x06000000, 0xfa000000, 0x00060000, 0xfffa0000, 0x0c0c0000, 0xf3f40000, 0x0c060000, 0xf3fa0000,
+ 0x060c0000, 0x00000606, 0x06060606, 0xf9fa0606, 0x06000606, 0xfa000606, 0x00060606, 0xfffa0606,
+ 0x0c0c0606, 0xf3f40606, 0x0c060606, 0xf3fa0606, 0x060c0606, 0xfffff9fa, 0x0605f9fa, 0xf9f9f9fa,
+ 0x05fff9fa, 0xf9fff9fa, 0x0005f9fa, 0xfff9f9fa, 0x0c0bf9fa, 0xf3f3f9fa, 0x0c05f9fa, 0xf3f9f9fa,
+ 0x060bf9fa, 0x00000600, 0x06060600, 0xf9fa0600, 0x06000600, 0xfa000600, 0x00060600, 0xfffa0600,
+ 0x0c0c0600, 0xf3f40600, 0x0c060600, 0xf3fa0600, 0x060c0600, 0xfffffa00, 0x0605fa00, 0xf9f9fa00,
+ 0x05fffa00, 0xf9fffa00, 0x0005fa00, 0xfff9fa00, 0x0c0bfa00, 0xf3f3fa00, 0x0c05fa00, 0xf3f9fa00,
+ 0x060bfa00, 0x00000006, 0x06060006, 0xf9fa0006, 0x06000006, 0xfa000006, 0x00060006, 0xfffa0006,
+ 0x0c0c0006, 0xf3f40006, 0x0c060006, 0xf3fa0006, 0x060c0006, 0xfffffffa, 0x0605fffa, 0xf9f9fffa,
+ 0x05fffffa, 0xf9fffffa, 0x0005fffa, 0xfff9fffa, 0x0c0bfffa, 0xf3f3fffa, 0x0c05fffa, 0xf3f9fffa,
+ 0x060bfffa, 0x00000c0c, 0x06060c0c, 0xf9fa0c0c, 0x06000c0c, 0xfa000c0c, 0x00060c0c, 0xfffa0c0c,
+ 0x0c0c0c0c, 0xf3f40c0c, 0x0c060c0c, 0xf3fa0c0c, 0x060c0c0c, 0xfffff3f4, 0x0605f3f4, 0xf9f9f3f4,
+ 0x05fff3f4, 0xf9fff3f4, 0x0005f3f4, 0xfff9f3f4, 0x0c0bf3f4, 0xf3f3f3f4, 0x0c05f3f4, 0xf3f9f3f4,
+ 0x060bf3f4, 0x00000c06, 0x06060c06, 0xf9fa0c06, 0x06000c06, 0xfa000c06, 0x00060c06, 0xfffa0c06,
+ 0x0c0c0c06, 0xf3f40c06, 0x0c060c06, 0xf3fa0c06, 0x060c0c06, 0xfffff3fa, 0x0605f3fa, 0xf9f9f3fa,
+ 0x05fff3fa, 0xf9fff3fa, 0x0005f3fa, 0xfff9f3fa, 0x0c0bf3fa, 0xf3f3f3fa, 0x0c05f3fa, 0xf3f9f3fa,
+ 0x060bf3fa, 0x0000060c, 0x0606060c, 0xf9fa060c, 0x0600060c, 0xfa00060c, 0x0006060c, 0xfffa060c,
+ 0x0c0c060c, 0xf3f4060c, 0x0c06060c, 0xf3fa060c, 0x060c060c, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000707, 0xfffff8f9, 0x00000700, 0xfffff900, 0x00000007, 0xfffffff9, 0x00000e0e,
+ 0xfffff1f2, 0x00001507, 0xffffeaf9, 0x00000715, 0xfffff8eb, 0x00000df2, 0xfffff20e, 0x000014f9,
+ 0xffffeb07, 0xfffff915, 0x000006eb, 0x00001c0e, 0xffffe3f2, 0x00000e1c, 0xfffff1e4, 0x00001c1c,
+ 0xffffe3e4, 0x00002300, 0xffffdd00, 0x00000023, 0xffffffdd, 0x00001beb, 0xffffe415, 0xffffeb1c,
+ 0x000014e4, 0x00003823, 0xffffc7dd, 0x00002338, 0xffffdcc8, 0x000029f2, 0xffffd60e, 0xfffff22a,
+ 0x00000dd6, 0x0000380e, 0xffffc7f2, 0x00000e38, 0xfffff1c8, 0x00003838, 0xffffc7c8, 0x00003f00,
+ 0xffffc100, 0x0000003f, 0xffffffc1, 0x000029d6, 0xffffd62a, 0x000037e4, 0xffffc81c, 0xffffe438,
+ 0x00001bc8, 0x00005b23, 0xffffa4dd, 0x0000235b, 0xffffdca5, 0x0000623f, 0xffff9dc1, 0x00003f62,
+ 0xffffc09e, 0x00004ceb, 0xffffb315, 0xffffeb4d, 0x000014b3, 0x0000620e, 0xffff9df2, 0x00000e62,
+ 0xfffff19e, 0x00006969, 0xffff9697, 0x000076f9, 0xffff8907, 0xfffff977, 0x00000689, 0x00004cc1,
+ 0xffffb33f, 0xffffc14d, 0x00003eb3, 0x000068cf, 0xffff9731, 0xffffcf69, 0x00003097, 0x00007689,
+ 0xffff8977, 0x00002a2a, 0xffffd5d6, 0x00004d4d, 0xffffb2b3, 0x00000000, 0x07070000, 0xf8f90000,
+ 0x07000000, 0xf9000000, 0x00070000, 0xfff90000, 0x0e0e0000, 0xf1f20000, 0x15070000, 0xeaf90000,
+ 0x07150000, 0x00000707, 0x07070707, 0xf8f90707, 0x07000707, 0xf9000707, 0x00070707, 0xfff90707,
+ 0x0e0e0707, 0xf1f20707, 0x15070707, 0xeaf90707, 0x07150707, 0xfffff8f9, 0x0706f8f9, 0xf8f8f8f9,
+ 0x06fff8f9, 0xf8fff8f9, 0x0006f8f9, 0xfff8f8f9, 0x0e0df8f9, 0xf1f1f8f9, 0x1506f8f9, 0xeaf8f8f9,
+ 0x0714f8f9, 0x00000700, 0x07070700, 0xf8f90700, 0x07000700, 0xf9000700, 0x00070700, 0xfff90700,
+ 0x0e0e0700, 0xf1f20700, 0x15070700, 0xeaf90700, 0x07150700, 0xfffff900, 0x0706f900, 0xf8f8f900,
+ 0x06fff900, 0xf8fff900, 0x0006f900, 0xfff8f900, 0x0e0df900, 0xf1f1f900, 0x1506f900, 0xeaf8f900,
+ 0x0714f900, 0x00000007, 0x07070007, 0xf8f90007, 0x07000007, 0xf9000007, 0x00070007, 0xfff90007,
+ 0x0e0e0007, 0xf1f20007, 0x15070007, 0xeaf90007, 0x07150007, 0xfffffff9, 0x0706fff9, 0xf8f8fff9,
+ 0x06fffff9, 0xf8fffff9, 0x0006fff9, 0xfff8fff9, 0x0e0dfff9, 0xf1f1fff9, 0x1506fff9, 0xeaf8fff9,
+ 0x0714fff9, 0x00000e0e, 0x07070e0e, 0xf8f90e0e, 0x07000e0e, 0xf9000e0e, 0x00070e0e, 0xfff90e0e,
+ 0x0e0e0e0e, 0xf1f20e0e, 0x15070e0e, 0xeaf90e0e, 0x07150e0e, 0xfffff1f2, 0x0706f1f2, 0xf8f8f1f2,
+ 0x06fff1f2, 0xf8fff1f2, 0x0006f1f2, 0xfff8f1f2, 0x0e0df1f2, 0xf1f1f1f2, 0x1506f1f2, 0xeaf8f1f2,
+ 0x0714f1f2, 0x00001507, 0x07071507, 0xf8f91507, 0x07001507, 0xf9001507, 0x00071507, 0xfff91507,
+ 0x0e0e1507, 0xf1f21507, 0x15071507, 0xeaf91507, 0x07151507, 0xffffeaf9, 0x0706eaf9, 0xf8f8eaf9,
+ 0x06ffeaf9, 0xf8ffeaf9, 0x0006eaf9, 0xfff8eaf9, 0x0e0deaf9, 0xf1f1eaf9, 0x1506eaf9, 0xeaf8eaf9,
+ 0x0714eaf9, 0x00000715, 0x07070715, 0xf8f90715, 0x07000715, 0xf9000715, 0x00070715, 0xfff90715,
+ 0x0e0e0715, 0xf1f20715, 0x15070715, 0xeaf90715, 0x07150715, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000808, 0xfffff7f8, 0x00000800, 0xfffff800, 0x00000008, 0xfffffff8, 0x00001010,
+ 0xffffeff0, 0x00001008, 0xffffeff8, 0x00000810, 0xfffff7f0, 0x00000ff0, 0xfffff010, 0x000017f8,
+ 0xffffe808, 0xfffff818, 0x000007e8, 0x00002010, 0xffffdff0, 0x00001020, 0xffffefe0, 0x00002020,
+ 0xffffdfe0, 0x00002800, 0xffffd800, 0x00000028, 0xffffffd8, 0x00001fe8, 0xffffe018, 0xffffe820,
+ 0x000017e0, 0x00004028, 0xffffbfd8, 0x00002840, 0xffffd7c0, 0x00002ff0, 0xffffd010, 0xfffff030,
+ 0x00000fd0, 0x00004010, 0xffffbff0, 0x00001040, 0xffffefc0, 0x00004040, 0xffffbfc0, 0x00004800,
+ 0xffffb800, 0x00000048, 0xffffffb8, 0x00002fd0, 0xffffd030, 0x00003fe0, 0xffffc020, 0xffffe040,
+ 0x00001fc0, 0x00006828, 0xffff97d8, 0x00002868, 0xffffd798, 0x00007048, 0xffff8fb8, 0x00004870,
+ 0xffffb790, 0x000057e8, 0xffffa818, 0xffffe858, 0x000017a8, 0x00007010, 0xffff8ff0, 0x00001070,
+ 0xffffef90, 0x00007878, 0xffff8788, 0x000057b8, 0xffffa848, 0xffffb858, 0x000047a8, 0x000077c8,
+ 0xffff8838, 0xffffc878, 0x00003788, 0x00003030, 0xffffcfd0, 0x00005858, 0xffffa7a8, 0x00000000,
+ 0x08080000, 0xf7f80000, 0x08000000, 0xf8000000, 0x00080000, 0xfff80000, 0x10100000, 0xeff00000,
+ 0x10080000, 0xeff80000, 0x08100000, 0x00000808, 0x08080808, 0xf7f80808, 0x08000808, 0xf8000808,
+ 0x00080808, 0xfff80808, 0x10100808, 0xeff00808, 0x10080808, 0xeff80808, 0x08100808, 0xfffff7f8,
+ 0x0807f7f8, 0xf7f7f7f8, 0x07fff7f8, 0xf7fff7f8, 0x0007f7f8, 0xfff7f7f8, 0x100ff7f8, 0xefeff7f8,
+ 0x1007f7f8, 0xeff7f7f8, 0x080ff7f8, 0x00000800, 0x08080800, 0xf7f80800, 0x08000800, 0xf8000800,
+ 0x00080800, 0xfff80800, 0x10100800, 0xeff00800, 0x10080800, 0xeff80800, 0x08100800, 0xfffff800,
+ 0x0807f800, 0xf7f7f800, 0x07fff800, 0xf7fff800, 0x0007f800, 0xfff7f800, 0x100ff800, 0xefeff800,
+ 0x1007f800, 0xeff7f800, 0x080ff800, 0x00000008, 0x08080008, 0xf7f80008, 0x08000008, 0xf8000008,
+ 0x00080008, 0xfff80008, 0x10100008, 0xeff00008, 0x10080008, 0xeff80008, 0x08100008, 0xfffffff8,
+ 0x0807fff8, 0xf7f7fff8, 0x07fffff8, 0xf7fffff8, 0x0007fff8, 0xfff7fff8, 0x100ffff8, 0xefeffff8,
+ 0x1007fff8, 0xeff7fff8, 0x080ffff8, 0x00001010, 0x08081010, 0xf7f81010, 0x08001010, 0xf8001010,
+ 0x00081010, 0xfff81010, 0x10101010, 0xeff01010, 0x10081010, 0xeff81010, 0x08101010, 0xffffeff0,
+ 0x0807eff0, 0xf7f7eff0, 0x07ffeff0, 0xf7ffeff0, 0x0007eff0, 0xfff7eff0, 0x100feff0, 0xefefeff0,
+ 0x1007eff0, 0xeff7eff0, 0x080feff0, 0x00001008, 0x08081008, 0xf7f81008, 0x08001008, 0xf8001008,
+ 0x00081008, 0xfff81008, 0x10101008, 0xeff01008, 0x10081008, 0xeff81008, 0x08101008, 0xffffeff8,
+ 0x0807eff8, 0xf7f7eff8, 0x07ffeff8, 0xf7ffeff8, 0x0007eff8, 0xfff7eff8, 0x100feff8, 0xefefeff8,
+ 0x1007eff8, 0xeff7eff8, 0x080feff8, 0x00000810, 0x08080810, 0xf7f80810, 0x08000810, 0xf8000810,
+ 0x00080810, 0xfff80810, 0x10100810, 0xeff00810, 0x10080810, 0xeff80810, 0x08100810, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000909, 0xfffff6f7, 0x00000900, 0xfffff700, 0x00000009, 0xfffffff7, 0x00001212,
+ 0xffffedee, 0x00001b09, 0xffffe4f7, 0x0000091b, 0xfffff6e5, 0x000011ee, 0xffffee12, 0x00001af7,
+ 0xffffe509, 0xfffff71b, 0x000008e5, 0x00002412, 0xffffdbee, 0x00001224, 0xffffeddc, 0x00002424,
+ 0xffffdbdc, 0x00002d00, 0xffffd300, 0x0000002d, 0xffffffd3, 0x000023e5, 0xffffdc1b, 0xffffe524,
+ 0x00001adc, 0x0000482d, 0xffffb7d3, 0x00002d48, 0xffffd2b8, 0x000035ee, 0xffffca12, 0xffffee36,
+ 0x000011ca, 0x00004812, 0xffffb7ee, 0x00001248, 0xffffedb8, 0x00004848, 0xffffb7b8, 0x00005100,
+ 0xffffaf00, 0x00000051, 0xffffffaf, 0x000035ca, 0xffffca36, 0x000047dc, 0xffffb824, 0xffffdc48,
+ 0x000023b8, 0x0000752d, 0xffff8ad3, 0x00002d75, 0xffffd28b, 0x00007e51, 0xffff81af, 0x0000517e,
+ 0xffffae82, 0x000062e5, 0xffff9d1b, 0xffffe563, 0x00001a9d, 0x000062af, 0xffff9d51, 0xffffaf63,
+ 0x0000509d, 0x00003636, 0xffffc9ca, 0x00006c6c, 0xffff9394, 0x00000000, 0x09090000, 0xf6f70000,
+ 0x09000000, 0xf7000000, 0x00090000, 0xfff70000, 0x12120000, 0xedee0000, 0x1b090000, 0xe4f70000,
+ 0x091b0000, 0xf6e50000, 0x00000909, 0x09090909, 0xf6f70909, 0x09000909, 0xf7000909, 0x00090909,
+ 0xfff70909, 0x12120909, 0xedee0909, 0x1b090909, 0xe4f70909, 0x091b0909, 0xf6e50909, 0xfffff6f7,
+ 0x0908f6f7, 0xf6f6f6f7, 0x08fff6f7, 0xf6fff6f7, 0x0008f6f7, 0xfff6f6f7, 0x1211f6f7, 0xededf6f7,
+ 0x1b08f6f7, 0xe4f6f6f7, 0x091af6f7, 0xf6e4f6f7, 0x00000900, 0x09090900, 0xf6f70900, 0x09000900,
+ 0xf7000900, 0x00090900, 0xfff70900, 0x12120900, 0xedee0900, 0x1b090900, 0xe4f70900, 0x091b0900,
+ 0xf6e50900, 0xfffff700, 0x0908f700, 0xf6f6f700, 0x08fff700, 0xf6fff700, 0x0008f700, 0xfff6f700,
+ 0x1211f700, 0xededf700, 0x1b08f700, 0xe4f6f700, 0x091af700, 0xf6e4f700, 0x00000009, 0x09090009,
+ 0xf6f70009, 0x09000009, 0xf7000009, 0x00090009, 0xfff70009, 0x12120009, 0xedee0009, 0x1b090009,
+ 0xe4f70009, 0x091b0009, 0xf6e50009, 0xfffffff7, 0x0908fff7, 0xf6f6fff7, 0x08fffff7, 0xf6fffff7,
+ 0x0008fff7, 0xfff6fff7, 0x1211fff7, 0xededfff7, 0x1b08fff7, 0xe4f6fff7, 0x091afff7, 0xf6e4fff7,
+ 0x00001212, 0x09091212, 0xf6f71212, 0x09001212, 0xf7001212, 0x00091212, 0xfff71212, 0x12121212,
+ 0xedee1212, 0x1b091212, 0xe4f71212, 0x091b1212, 0xf6e51212, 0xffffedee, 0x0908edee, 0xf6f6edee,
+ 0x08ffedee, 0xf6ffedee, 0x0008edee, 0xfff6edee, 0x1211edee, 0xedededee, 0x1b08edee, 0xe4f6edee,
+ 0x091aedee, 0xf6e4edee, 0x00001b09, 0x09091b09, 0xf6f71b09, 0x09001b09, 0xf7001b09, 0x00091b09,
+ 0xfff71b09, 0x12121b09, 0xedee1b09, 0x1b091b09, 0xe4f71b09, 0x091b1b09, 0xf6e51b09, 0xffffe4f7,
+ 0x0908e4f7, 0xf6f6e4f7, 0x08ffe4f7, 0xf6ffe4f7, 0x0008e4f7, 0xfff6e4f7, 0x1211e4f7, 0xedede4f7,
+ 0x1b08e4f7, 0xe4f6e4f7, 0x091ae4f7, 0xf6e4e4f7, 0x0000091b, 0x0909091b, 0xf6f7091b, 0x0900091b,
+ 0xf700091b, 0x0009091b, 0xfff7091b, 0x1212091b, 0xedee091b, 0x1b09091b, 0xe4f7091b, 0x091b091b,
+ 0xf6e5091b, 0xfffff6e5, 0x0908f6e5, 0xf6f6f6e5, 0x08fff6e5, 0xf6fff6e5, 0x0008f6e5, 0xfff6f6e5,
+ 0x1211f6e5, 0xededf6e5, 0x1b08f6e5, 0xe4f6f6e5, 0x091af6e5, 0xf6e4f6e5, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000202, 0xfffffdfe, 0x00000300, 0xfffffd00, 0x00000003, 0xfffffffd, 0x00000606,
+ 0xfffff9fa, 0x00000700, 0xfffff900, 0x00000007, 0xfffffff9, 0x000004fb, 0xfffffb05, 0xfffffb05,
+ 0x000004fb, 0x00000b06, 0xfffff4fa, 0x0000060b, 0xfffff9f5, 0x00000800, 0xfffff800, 0x00000008,
+ 0xfffffff8, 0x00000b0b, 0xfffff4f5, 0x00000c00, 0xfffff400, 0x0000000c, 0xfffffff4, 0x0000110c,
+ 0xffffeef4, 0x00000c11, 0xfffff3ef, 0x00001111, 0xffffeeef, 0x00001206, 0xffffedfa, 0x00000612,
+ 0xfffff9ee, 0x00000af8, 0xfffff508, 0xfffff80b, 0x000007f5, 0x00000f00, 0xfffff100, 0x0000000f,
+ 0xfffffff1, 0x00001400, 0xffffec00, 0x00000014, 0xffffffec, 0x00001912, 0xffffe6ee, 0x00001219,
+ 0xffffede7, 0x0000190b, 0xffffe6f5, 0x00000b19, 0xfffff4e7, 0x00001919, 0xffffe6e7, 0x00000df2,
+ 0xfffff20e, 0xfffff20e, 0x00000df2, 0x00001a00, 0xffffe600, 0x0000001a, 0xffffffe6, 0x000011f5,
+ 0xffffee0b, 0xfffff512, 0x00000aee, 0x000015f9, 0xffffea07, 0xfffff916, 0x000006ea, 0x0000221a,
+ 0xffffdde6, 0x00001a22, 0xffffe5de, 0x00002212, 0xffffddee, 0x00001222, 0xffffedde, 0x00002222,
+ 0xffffddde, 0x0000230b, 0xffffdcf5, 0x00000b23, 0xfffff4dd, 0x00001d00, 0xffffe300, 0x0000001d,
+ 0xffffffe3, 0x000015ed, 0xffffea13, 0xffffed16, 0x000012ea, 0x000019f1, 0xffffe60f, 0xfffff11a,
+ 0x00000ee6, 0x00002500, 0xffffdb00, 0x00000025, 0xffffffdb, 0x00002c1b, 0xffffd3e5, 0x00001b2c,
+ 0xffffe4d4, 0x00002c24, 0xffffd3dc, 0x0000242c, 0xffffdbd4, 0x00002c12, 0xffffd3ee, 0x0000122c,
+ 0xffffedd4, 0x000020f6, 0xffffdf0a, 0xfffff621, 0x000009df, 0x00002d2d, 0xffffd2d3, 0x00000000,
+ 0x00000000, 0x00000202, 0xfffffdfe, 0x00000300, 0xfffffd00, 0x00000003, 0xfffffffd, 0x00000606,
+ 0xfffff9fa, 0x00000700, 0xfffff900, 0x02020000, 0x02020202, 0x0201fdfe, 0x02020300, 0x0201fd00,
+ 0x02020003, 0x0201fffd, 0x02020606, 0x0201f9fa, 0x02020700, 0x0201f900, 0xfdfe0000, 0xfdfe0202,
+ 0xfdfdfdfe, 0xfdfe0300, 0xfdfdfd00, 0xfdfe0003, 0xfdfdfffd, 0xfdfe0606, 0xfdfdf9fa, 0xfdfe0700,
+ 0xfdfdf900, 0x03000000, 0x03000202, 0x02fffdfe, 0x03000300, 0x02fffd00, 0x03000003, 0x02fffffd,
+ 0x03000606, 0x02fff9fa, 0x03000700, 0x02fff900, 0xfd000000, 0xfd000202, 0xfcfffdfe, 0xfd000300,
+ 0xfcfffd00, 0xfd000003, 0xfcfffffd, 0xfd000606, 0xfcfff9fa, 0xfd000700, 0xfcfff900, 0x00030000,
+ 0x00030202, 0x0002fdfe, 0x00030300, 0x0002fd00, 0x00030003, 0x0002fffd, 0x00030606, 0x0002f9fa,
+ 0x00030700, 0x0002f900, 0xfffd0000, 0xfffd0202, 0xfffcfdfe, 0xfffd0300, 0xfffcfd00, 0xfffd0003,
+ 0xfffcfffd, 0xfffd0606, 0xfffcf9fa, 0xfffd0700, 0xfffcf900, 0x06060000, 0x06060202, 0x0605fdfe,
+ 0x06060300, 0x0605fd00, 0x06060003, 0x0605fffd, 0x06060606, 0x0605f9fa, 0x06060700, 0x0605f900,
+ 0xf9fa0000, 0xf9fa0202, 0xf9f9fdfe, 0xf9fa0300, 0xf9f9fd00, 0xf9fa0003, 0xf9f9fffd, 0xf9fa0606,
+ 0xf9f9f9fa, 0xf9fa0700, 0xf9f9f900, 0x07000000, 0x07000202, 0x06fffdfe, 0x07000300, 0x06fffd00,
+ 0x07000003, 0x06fffffd, 0x07000606, 0x06fff9fa, 0x07000700, 0x06fff900, 0xf9000000, 0xf9000202,
+ 0xf8fffdfe, 0xf9000300, 0xf8fffd00, 0xf9000003, 0xf8fffffd, 0xf9000606, 0xf8fff9fa, 0xf9000700,
+ 0xf8fff900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000200, 0xfffffe00, 0x00000002, 0xfffffffe, 0x00000202, 0xfffffdfe, 0x00000606,
+ 0xfffff9fa, 0x00000600, 0xfffffa00, 0x00000006, 0xfffffffa, 0x000003fc, 0xfffffc04, 0xfffffa0a,
+ 0x000005f6, 0xfffff400, 0x00000c00, 0xfffff3fa, 0xfffff406, 0x00000bfa, 0x00000c06, 0xfffffff2,
+ 0x0000000e, 0x00000c0c, 0xfffff3f4, 0xffffee00, 0x00001200, 0xfffff40e, 0x00000bf2, 0xfffff9ee,
+ 0xfffffa12, 0x000005ee, 0x00000612, 0xffffedf6, 0xffffee0a, 0x000011f6, 0x0000120a, 0xffffffea,
+ 0x00000016, 0xffffe800, 0x00001800, 0xfffff3ea, 0xfffff416, 0x00000bea, 0x00000c16, 0xffffe7f8,
+ 0xffffe808, 0x000017f8, 0x00001808, 0xfffff9e6, 0xfffffa1a, 0x000005e6, 0x0000061a, 0xffffffe4,
+ 0x0000001c, 0x00001414, 0xffffebec, 0xffffe5f2, 0x00001a0e, 0xfffff3e2, 0x00000c1e, 0xffffdff6,
+ 0x0000200a, 0xffffdfee, 0x00002012, 0xffffe5e6, 0x00001a1a, 0xffffebde, 0x00001422, 0xfffff3da,
+ 0x00000c26, 0xffffdfe0, 0x00002020, 0x00002020, 0xffffd7ea, 0xffffddde, 0x00002222, 0x00000000,
+ 0x00000200, 0xfffffe00, 0x00000002, 0xfffffffe, 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa,
+ 0x00000600, 0xfffffa00, 0x00000006, 0xfffffffa, 0x02000000, 0x02000200, 0x01fffe00, 0x02000002,
+ 0x01fffffe, 0x02000202, 0x01fffdfe, 0x02000606, 0x01fff9fa, 0x02000600, 0x01fffa00, 0x02000006,
+ 0x01fffffa, 0xfe000000, 0xfe000200, 0xfdfffe00, 0xfe000002, 0xfdfffffe, 0xfe000202, 0xfdfffdfe,
+ 0xfe000606, 0xfdfff9fa, 0xfe000600, 0xfdfffa00, 0xfe000006, 0xfdfffffa, 0x00020000, 0x00020200,
+ 0x0001fe00, 0x00020002, 0x0001fffe, 0x00020202, 0x0001fdfe, 0x00020606, 0x0001f9fa, 0x00020600,
+ 0x0001fa00, 0x00020006, 0x0001fffa, 0xfffe0000, 0xfffe0200, 0xfffdfe00, 0xfffe0002, 0xfffdfffe,
+ 0xfffe0202, 0xfffdfdfe, 0xfffe0606, 0xfffdf9fa, 0xfffe0600, 0xfffdfa00, 0xfffe0006, 0xfffdfffa,
+ 0x02020000, 0x02020200, 0x0201fe00, 0x02020002, 0x0201fffe, 0x02020202, 0x0201fdfe, 0x02020606,
+ 0x0201f9fa, 0x02020600, 0x0201fa00, 0x02020006, 0x0201fffa, 0xfdfe0000, 0xfdfe0200, 0xfdfdfe00,
+ 0xfdfe0002, 0xfdfdfffe, 0xfdfe0202, 0xfdfdfdfe, 0xfdfe0606, 0xfdfdf9fa, 0xfdfe0600, 0xfdfdfa00,
+ 0xfdfe0006, 0xfdfdfffa, 0x06060000, 0x06060200, 0x0605fe00, 0x06060002, 0x0605fffe, 0x06060202,
+ 0x0605fdfe, 0x06060606, 0x0605f9fa, 0x06060600, 0x0605fa00, 0x06060006, 0x0605fffa, 0xf9fa0000,
+ 0xf9fa0200, 0xf9f9fe00, 0xf9fa0002, 0xf9f9fffe, 0xf9fa0202, 0xf9f9fdfe, 0xf9fa0606, 0xf9f9f9fa,
+ 0xf9fa0600, 0xf9f9fa00, 0xf9fa0006, 0xf9f9fffa, 0x06000000, 0x06000200, 0x05fffe00, 0x06000002,
+ 0x05fffffe, 0x06000202, 0x05fffdfe, 0x06000606, 0x05fff9fa, 0x06000600, 0x05fffa00, 0x06000006,
+ 0x05fffffa, 0xfa000000, 0xfa000200, 0xf9fffe00, 0xfa000002, 0xf9fffffe, 0xfa000202, 0xf9fffdfe,
+ 0xfa000606, 0xf9fff9fa, 0xfa000600, 0xf9fffa00, 0xfa000006, 0xf9fffffa, 0x00060000, 0x00060200,
+ 0x0005fe00, 0x00060002, 0x0005fffe, 0x00060202, 0x0005fdfe, 0x00060606, 0x0005f9fa, 0x00060600,
+ 0x0005fa00, 0x00060006, 0x0005fffa, 0xfffa0000, 0xfffa0200, 0xfff9fe00, 0xfffa0002, 0xfff9fffe,
+ 0xfffa0202, 0xfff9fdfe, 0xfffa0606, 0xfff9f9fa, 0xfffa0600, 0xfff9fa00, 0xfffa0006, 0xfff9fffa,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000200, 0xfffffe00, 0x00000002, 0xfffffffe, 0x00000404, 0xfffffbfc, 0x00000a0a,
+ 0xfffff5f6, 0x00000a00, 0xfffff600, 0x0000000a, 0xfffffff6, 0x000005fa, 0xfffffa06, 0xfffff80e,
+ 0x000007f2, 0xffffffee, 0x00000012, 0xfffff00a, 0x00000ff6, 0xffffe800, 0x00001800, 0xfffff7e8,
+ 0xfffff818, 0x000007e8, 0x00000818, 0x00001212, 0xffffedee, 0xfffff014, 0x00000fec, 0xffffe5f2,
+ 0xffffe60e, 0x000019f2, 0x00001a0e, 0xffffffe2, 0x0000001e, 0xffffde00, 0x00002200, 0xfffff7de,
+ 0xfffff822, 0x000007de, 0x00000822, 0xffffede2, 0xffffee1e, 0x000011e2, 0x0000121e, 0xffffddf6,
+ 0xffffde0a, 0x000021f6, 0x0000220a, 0xffffddec, 0x00002214, 0xffffffd8, 0x00000028, 0x00001e1e,
+ 0xffffe1e2, 0xffffedd8, 0x00001228, 0xffffd400, 0x00002c00, 0xffffd3f0, 0x00002c10, 0xffffdbdc,
+ 0xffffdbdc, 0x00002424, 0xffffd3e6, 0x00002c1a, 0xffffe5d2, 0x00001a2e, 0xffffedcc, 0x00001234,
+ 0xffffc9ec, 0xffffd3d4, 0x00002c2c, 0xffffc9e0, 0xffffd1d2, 0xffffd1d2, 0x00002e2e, 0x00000000,
+ 0x00000200, 0xfffffe00, 0x00000002, 0xfffffffe, 0x00000404, 0xfffffbfc, 0x00000a0a, 0xfffff5f6,
+ 0x00000a00, 0xfffff600, 0x0000000a, 0xfffffff6, 0x02000000, 0x02000200, 0x01fffe00, 0x02000002,
+ 0x01fffffe, 0x02000404, 0x01fffbfc, 0x02000a0a, 0x01fff5f6, 0x02000a00, 0x01fff600, 0x0200000a,
+ 0x01fffff6, 0xfe000000, 0xfe000200, 0xfdfffe00, 0xfe000002, 0xfdfffffe, 0xfe000404, 0xfdfffbfc,
+ 0xfe000a0a, 0xfdfff5f6, 0xfe000a00, 0xfdfff600, 0xfe00000a, 0xfdfffff6, 0x00020000, 0x00020200,
+ 0x0001fe00, 0x00020002, 0x0001fffe, 0x00020404, 0x0001fbfc, 0x00020a0a, 0x0001f5f6, 0x00020a00,
+ 0x0001f600, 0x0002000a, 0x0001fff6, 0xfffe0000, 0xfffe0200, 0xfffdfe00, 0xfffe0002, 0xfffdfffe,
+ 0xfffe0404, 0xfffdfbfc, 0xfffe0a0a, 0xfffdf5f6, 0xfffe0a00, 0xfffdf600, 0xfffe000a, 0xfffdfff6,
+ 0x04040000, 0x04040200, 0x0403fe00, 0x04040002, 0x0403fffe, 0x04040404, 0x0403fbfc, 0x04040a0a,
+ 0x0403f5f6, 0x04040a00, 0x0403f600, 0x0404000a, 0x0403fff6, 0xfbfc0000, 0xfbfc0200, 0xfbfbfe00,
+ 0xfbfc0002, 0xfbfbfffe, 0xfbfc0404, 0xfbfbfbfc, 0xfbfc0a0a, 0xfbfbf5f6, 0xfbfc0a00, 0xfbfbf600,
+ 0xfbfc000a, 0xfbfbfff6, 0x0a0a0000, 0x0a0a0200, 0x0a09fe00, 0x0a0a0002, 0x0a09fffe, 0x0a0a0404,
+ 0x0a09fbfc, 0x0a0a0a0a, 0x0a09f5f6, 0x0a0a0a00, 0x0a09f600, 0x0a0a000a, 0x0a09fff6, 0xf5f60000,
+ 0xf5f60200, 0xf5f5fe00, 0xf5f60002, 0xf5f5fffe, 0xf5f60404, 0xf5f5fbfc, 0xf5f60a0a, 0xf5f5f5f6,
+ 0xf5f60a00, 0xf5f5f600, 0xf5f6000a, 0xf5f5fff6, 0x0a000000, 0x0a000200, 0x09fffe00, 0x0a000002,
+ 0x09fffffe, 0x0a000404, 0x09fffbfc, 0x0a000a0a, 0x09fff5f6, 0x0a000a00, 0x09fff600, 0x0a00000a,
+ 0x09fffff6, 0xf6000000, 0xf6000200, 0xf5fffe00, 0xf6000002, 0xf5fffffe, 0xf6000404, 0xf5fffbfc,
+ 0xf6000a0a, 0xf5fff5f6, 0xf6000a00, 0xf5fff600, 0xf600000a, 0xf5fffff6, 0x000a0000, 0x000a0200,
+ 0x0009fe00, 0x000a0002, 0x0009fffe, 0x000a0404, 0x0009fbfc, 0x000a0a0a, 0x0009f5f6, 0x000a0a00,
+ 0x0009f600, 0x000a000a, 0x0009fff6, 0xfff60000, 0xfff60200, 0xfff5fe00, 0xfff60002, 0xfff5fffe,
+ 0xfff60404, 0xfff5fbfc, 0xfff60a0a, 0xfff5f5f6, 0xfff60a00, 0xfff5f600, 0xfff6000a, 0xfff5fff6,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000400, 0xfffffc00, 0x00000004, 0xfffffffc, 0x00000404, 0xfffffbfc, 0x00000c0c,
+ 0xfffff3f4, 0x00000c00, 0xfffff400, 0x0000000c, 0xfffffff4, 0x000007f8, 0xfffff808, 0xfffff008,
+ 0x00000ff8, 0xffffe800, 0x00001800, 0xfffff7e8, 0xfffff818, 0x000007e8, 0x00000818, 0xfffff014,
+ 0x00000fec, 0xffffffe4, 0x0000001c, 0xffffe7f0, 0xffffe810, 0x000017f0, 0x00001810, 0xffffe000,
+ 0x00002000, 0xffffefe4, 0xfffff01c, 0x00000fe4, 0x0000101c, 0xffffdff8, 0xffffe008, 0xfffff7e0,
+ 0xfffff820, 0x000007e0, 0x00000820, 0x00001ff8, 0x00002008, 0x00001818, 0xffffe7e8, 0xffffe818,
+ 0x000017e8, 0xffffdfec, 0x00002014, 0xffffffd8, 0x00000028, 0xffffefd8, 0x00001028, 0xffffd400,
+ 0xffffd400, 0xffffffd4, 0x0000002c, 0x00002c00, 0x00002c00, 0xffffdfe0, 0x00002020, 0xffffd3f0,
+ 0x00002c10, 0xffffd3e8, 0xffffe7d4, 0x0000182c, 0x00002c18, 0xffffefd0, 0x00001030, 0xffffdbdc,
+ 0xffffdbdc, 0x00002424, 0x00002424, 0xffffcbec, 0x00002828, 0xffffd7d8, 0xffffcbe0, 0x00000000,
+ 0x00000400, 0xfffffc00, 0x00000004, 0xfffffffc, 0x00000404, 0xfffffbfc, 0x00000c0c, 0xfffff3f4,
+ 0x00000c00, 0xfffff400, 0x0000000c, 0xfffffff4, 0x04000000, 0x04000400, 0x03fffc00, 0x04000004,
+ 0x03fffffc, 0x04000404, 0x03fffbfc, 0x04000c0c, 0x03fff3f4, 0x04000c00, 0x03fff400, 0x0400000c,
+ 0x03fffff4, 0xfc000000, 0xfc000400, 0xfbfffc00, 0xfc000004, 0xfbfffffc, 0xfc000404, 0xfbfffbfc,
+ 0xfc000c0c, 0xfbfff3f4, 0xfc000c00, 0xfbfff400, 0xfc00000c, 0xfbfffff4, 0x00040000, 0x00040400,
+ 0x0003fc00, 0x00040004, 0x0003fffc, 0x00040404, 0x0003fbfc, 0x00040c0c, 0x0003f3f4, 0x00040c00,
+ 0x0003f400, 0x0004000c, 0x0003fff4, 0xfffc0000, 0xfffc0400, 0xfffbfc00, 0xfffc0004, 0xfffbfffc,
+ 0xfffc0404, 0xfffbfbfc, 0xfffc0c0c, 0xfffbf3f4, 0xfffc0c00, 0xfffbf400, 0xfffc000c, 0xfffbfff4,
+ 0x04040000, 0x04040400, 0x0403fc00, 0x04040004, 0x0403fffc, 0x04040404, 0x0403fbfc, 0x04040c0c,
+ 0x0403f3f4, 0x04040c00, 0x0403f400, 0x0404000c, 0x0403fff4, 0xfbfc0000, 0xfbfc0400, 0xfbfbfc00,
+ 0xfbfc0004, 0xfbfbfffc, 0xfbfc0404, 0xfbfbfbfc, 0xfbfc0c0c, 0xfbfbf3f4, 0xfbfc0c00, 0xfbfbf400,
+ 0xfbfc000c, 0xfbfbfff4, 0x0c0c0000, 0x0c0c0400, 0x0c0bfc00, 0x0c0c0004, 0x0c0bfffc, 0x0c0c0404,
+ 0x0c0bfbfc, 0x0c0c0c0c, 0x0c0bf3f4, 0x0c0c0c00, 0x0c0bf400, 0x0c0c000c, 0x0c0bfff4, 0xf3f40000,
+ 0xf3f40400, 0xf3f3fc00, 0xf3f40004, 0xf3f3fffc, 0xf3f40404, 0xf3f3fbfc, 0xf3f40c0c, 0xf3f3f3f4,
+ 0xf3f40c00, 0xf3f3f400, 0xf3f4000c, 0xf3f3fff4, 0x0c000000, 0x0c000400, 0x0bfffc00, 0x0c000004,
+ 0x0bfffffc, 0x0c000404, 0x0bfffbfc, 0x0c000c0c, 0x0bfff3f4, 0x0c000c00, 0x0bfff400, 0x0c00000c,
+ 0x0bfffff4, 0xf4000000, 0xf4000400, 0xf3fffc00, 0xf4000004, 0xf3fffffc, 0xf4000404, 0xf3fffbfc,
+ 0xf4000c0c, 0xf3fff3f4, 0xf4000c00, 0xf3fff400, 0xf400000c, 0xf3fffff4, 0x000c0000, 0x000c0400,
+ 0x000bfc00, 0x000c0004, 0x000bfffc, 0x000c0404, 0x000bfbfc, 0x000c0c0c, 0x000bf3f4, 0x000c0c00,
+ 0x000bf400, 0x000c000c, 0x000bfff4, 0xfff40000, 0xfff40400, 0xfff3fc00, 0xfff40004, 0xfff3fffc,
+ 0xfff40404, 0xfff3fbfc, 0xfff40c0c, 0xfff3f3f4, 0xfff40c00, 0xfff3f400, 0xfff4000c, 0xfff3fff4,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa, 0x00000c0c, 0xfffff3f4, 0x00001414,
+ 0xffffebec, 0x00002020, 0xffffdfe0, 0x00002e2e, 0xffffd1d2, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa, 0x00000c0c, 0xfffff3f4, 0x00001414, 0xffffebec,
+ 0x00002020, 0xffffdfe0, 0x00002e2e, 0xffffd1d2, 0x02020000, 0x02020202, 0x0201fdfe, 0x02020606,
+ 0x0201f9fa, 0x02020c0c, 0x0201f3f4, 0x02021414, 0x0201ebec, 0x02022020, 0x0201dfe0, 0x02022e2e,
+ 0x0201d1d2, 0xfdfe0000, 0xfdfe0202, 0xfdfdfdfe, 0xfdfe0606, 0xfdfdf9fa, 0xfdfe0c0c, 0xfdfdf3f4,
+ 0xfdfe1414, 0xfdfdebec, 0xfdfe2020, 0xfdfddfe0, 0xfdfe2e2e, 0xfdfdd1d2, 0x06060000, 0x06060202,
+ 0x0605fdfe, 0x06060606, 0x0605f9fa, 0x06060c0c, 0x0605f3f4, 0x06061414, 0x0605ebec, 0x06062020,
+ 0x0605dfe0, 0x06062e2e, 0x0605d1d2, 0xf9fa0000, 0xf9fa0202, 0xf9f9fdfe, 0xf9fa0606, 0xf9f9f9fa,
+ 0xf9fa0c0c, 0xf9f9f3f4, 0xf9fa1414, 0xf9f9ebec, 0xf9fa2020, 0xf9f9dfe0, 0xf9fa2e2e, 0xf9f9d1d2,
+ 0x0c0c0000, 0x0c0c0202, 0x0c0bfdfe, 0x0c0c0606, 0x0c0bf9fa, 0x0c0c0c0c, 0x0c0bf3f4, 0x0c0c1414,
+ 0x0c0bebec, 0x0c0c2020, 0x0c0bdfe0, 0x0c0c2e2e, 0x0c0bd1d2, 0xf3f40000, 0xf3f40202, 0xf3f3fdfe,
+ 0xf3f40606, 0xf3f3f9fa, 0xf3f40c0c, 0xf3f3f3f4, 0xf3f41414, 0xf3f3ebec, 0xf3f42020, 0xf3f3dfe0,
+ 0xf3f42e2e, 0xf3f3d1d2, 0x14140000, 0x14140202, 0x1413fdfe, 0x14140606, 0x1413f9fa, 0x14140c0c,
+ 0x1413f3f4, 0x14141414, 0x1413ebec, 0x14142020, 0x1413dfe0, 0x14142e2e, 0x1413d1d2, 0xebec0000,
+ 0xebec0202, 0xebebfdfe, 0xebec0606, 0xebebf9fa, 0xebec0c0c, 0xebebf3f4, 0xebec1414, 0xebebebec,
+ 0xebec2020, 0xebebdfe0, 0xebec2e2e, 0xebebd1d2, 0x20200000, 0x20200202, 0x201ffdfe, 0x20200606,
+ 0x201ff9fa, 0x20200c0c, 0x201ff3f4, 0x20201414, 0x201febec, 0x20202020, 0x201fdfe0, 0x20202e2e,
+ 0x201fd1d2, 0xdfe00000, 0xdfe00202, 0xdfdffdfe, 0xdfe00606, 0xdfdff9fa, 0xdfe00c0c, 0xdfdff3f4,
+ 0xdfe01414, 0xdfdfebec, 0xdfe02020, 0xdfdfdfe0, 0xdfe02e2e, 0xdfdfd1d2, 0x2e2e0000, 0x2e2e0202,
+ 0x2e2dfdfe, 0x2e2e0606, 0x2e2df9fa, 0x2e2e0c0c, 0x2e2df3f4, 0x2e2e1414, 0x2e2debec, 0x2e2e2020,
+ 0x2e2ddfe0, 0x2e2e2e2e, 0x2e2dd1d2, 0xd1d20000, 0xd1d20202, 0xd1d1fdfe, 0xd1d20606, 0xd1d1f9fa,
+ 0xd1d20c0c, 0xd1d1f3f4, 0xd1d21414, 0xd1d1ebec, 0xd1d22020, 0xd1d1dfe0, 0xd1d22e2e, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa, 0x00000c0c, 0xfffff3f4, 0x00001414,
+ 0xffffebec, 0x00002020, 0xffffdfe0, 0x00002e2e, 0xffffd1d2, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa, 0x00000c0c, 0xfffff3f4, 0x00001414, 0xffffebec,
+ 0x00002020, 0xffffdfe0, 0x00002e2e, 0xffffd1d2, 0x02020000, 0x02020202, 0x0201fdfe, 0x02020606,
+ 0x0201f9fa, 0x02020c0c, 0x0201f3f4, 0x02021414, 0x0201ebec, 0x02022020, 0x0201dfe0, 0x02022e2e,
+ 0x0201d1d2, 0xfdfe0000, 0xfdfe0202, 0xfdfdfdfe, 0xfdfe0606, 0xfdfdf9fa, 0xfdfe0c0c, 0xfdfdf3f4,
+ 0xfdfe1414, 0xfdfdebec, 0xfdfe2020, 0xfdfddfe0, 0xfdfe2e2e, 0xfdfdd1d2, 0x06060000, 0x06060202,
+ 0x0605fdfe, 0x06060606, 0x0605f9fa, 0x06060c0c, 0x0605f3f4, 0x06061414, 0x0605ebec, 0x06062020,
+ 0x0605dfe0, 0x06062e2e, 0x0605d1d2, 0xf9fa0000, 0xf9fa0202, 0xf9f9fdfe, 0xf9fa0606, 0xf9f9f9fa,
+ 0xf9fa0c0c, 0xf9f9f3f4, 0xf9fa1414, 0xf9f9ebec, 0xf9fa2020, 0xf9f9dfe0, 0xf9fa2e2e, 0xf9f9d1d2,
+ 0x0c0c0000, 0x0c0c0202, 0x0c0bfdfe, 0x0c0c0606, 0x0c0bf9fa, 0x0c0c0c0c, 0x0c0bf3f4, 0x0c0c1414,
+ 0x0c0bebec, 0x0c0c2020, 0x0c0bdfe0, 0x0c0c2e2e, 0x0c0bd1d2, 0xf3f40000, 0xf3f40202, 0xf3f3fdfe,
+ 0xf3f40606, 0xf3f3f9fa, 0xf3f40c0c, 0xf3f3f3f4, 0xf3f41414, 0xf3f3ebec, 0xf3f42020, 0xf3f3dfe0,
+ 0xf3f42e2e, 0xf3f3d1d2, 0x14140000, 0x14140202, 0x1413fdfe, 0x14140606, 0x1413f9fa, 0x14140c0c,
+ 0x1413f3f4, 0x14141414, 0x1413ebec, 0x14142020, 0x1413dfe0, 0x14142e2e, 0x1413d1d2, 0xebec0000,
+ 0xebec0202, 0xebebfdfe, 0xebec0606, 0xebebf9fa, 0xebec0c0c, 0xebebf3f4, 0xebec1414, 0xebebebec,
+ 0xebec2020, 0xebebdfe0, 0xebec2e2e, 0xebebd1d2, 0x20200000, 0x20200202, 0x201ffdfe, 0x20200606,
+ 0x201ff9fa, 0x20200c0c, 0x201ff3f4, 0x20201414, 0x201febec, 0x20202020, 0x201fdfe0, 0x20202e2e,
+ 0x201fd1d2, 0xdfe00000, 0xdfe00202, 0xdfdffdfe, 0xdfe00606, 0xdfdff9fa, 0xdfe00c0c, 0xdfdff3f4,
+ 0xdfe01414, 0xdfdfebec, 0xdfe02020, 0xdfdfdfe0, 0xdfe02e2e, 0xdfdfd1d2, 0x2e2e0000, 0x2e2e0202,
+ 0x2e2dfdfe, 0x2e2e0606, 0x2e2df9fa, 0x2e2e0c0c, 0x2e2df3f4, 0x2e2e1414, 0x2e2debec, 0x2e2e2020,
+ 0x2e2ddfe0, 0x2e2e2e2e, 0x2e2dd1d2, 0xd1d20000, 0xd1d20202, 0xd1d1fdfe, 0xd1d20606, 0xd1d1f9fa,
+ 0xd1d20c0c, 0xd1d1f3f4, 0xd1d21414, 0xd1d1ebec, 0xd1d22020, 0xd1d1dfe0, 0xd1d22e2e, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa, 0x00000c0c, 0xfffff3f4, 0x00001414,
+ 0xffffebec, 0x00002020, 0xffffdfe0, 0x00002e2e, 0xffffd1d2, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa, 0x00000c0c, 0xfffff3f4, 0x00001414, 0xffffebec,
+ 0x00002020, 0xffffdfe0, 0x00002e2e, 0xffffd1d2, 0x02020000, 0x02020202, 0x0201fdfe, 0x02020606,
+ 0x0201f9fa, 0x02020c0c, 0x0201f3f4, 0x02021414, 0x0201ebec, 0x02022020, 0x0201dfe0, 0x02022e2e,
+ 0x0201d1d2, 0xfdfe0000, 0xfdfe0202, 0xfdfdfdfe, 0xfdfe0606, 0xfdfdf9fa, 0xfdfe0c0c, 0xfdfdf3f4,
+ 0xfdfe1414, 0xfdfdebec, 0xfdfe2020, 0xfdfddfe0, 0xfdfe2e2e, 0xfdfdd1d2, 0x06060000, 0x06060202,
+ 0x0605fdfe, 0x06060606, 0x0605f9fa, 0x06060c0c, 0x0605f3f4, 0x06061414, 0x0605ebec, 0x06062020,
+ 0x0605dfe0, 0x06062e2e, 0x0605d1d2, 0xf9fa0000, 0xf9fa0202, 0xf9f9fdfe, 0xf9fa0606, 0xf9f9f9fa,
+ 0xf9fa0c0c, 0xf9f9f3f4, 0xf9fa1414, 0xf9f9ebec, 0xf9fa2020, 0xf9f9dfe0, 0xf9fa2e2e, 0xf9f9d1d2,
+ 0x0c0c0000, 0x0c0c0202, 0x0c0bfdfe, 0x0c0c0606, 0x0c0bf9fa, 0x0c0c0c0c, 0x0c0bf3f4, 0x0c0c1414,
+ 0x0c0bebec, 0x0c0c2020, 0x0c0bdfe0, 0x0c0c2e2e, 0x0c0bd1d2, 0xf3f40000, 0xf3f40202, 0xf3f3fdfe,
+ 0xf3f40606, 0xf3f3f9fa, 0xf3f40c0c, 0xf3f3f3f4, 0xf3f41414, 0xf3f3ebec, 0xf3f42020, 0xf3f3dfe0,
+ 0xf3f42e2e, 0xf3f3d1d2, 0x14140000, 0x14140202, 0x1413fdfe, 0x14140606, 0x1413f9fa, 0x14140c0c,
+ 0x1413f3f4, 0x14141414, 0x1413ebec, 0x14142020, 0x1413dfe0, 0x14142e2e, 0x1413d1d2, 0xebec0000,
+ 0xebec0202, 0xebebfdfe, 0xebec0606, 0xebebf9fa, 0xebec0c0c, 0xebebf3f4, 0xebec1414, 0xebebebec,
+ 0xebec2020, 0xebebdfe0, 0xebec2e2e, 0xebebd1d2, 0x20200000, 0x20200202, 0x201ffdfe, 0x20200606,
+ 0x201ff9fa, 0x20200c0c, 0x201ff3f4, 0x20201414, 0x201febec, 0x20202020, 0x201fdfe0, 0x20202e2e,
+ 0x201fd1d2, 0xdfe00000, 0xdfe00202, 0xdfdffdfe, 0xdfe00606, 0xdfdff9fa, 0xdfe00c0c, 0xdfdff3f4,
+ 0xdfe01414, 0xdfdfebec, 0xdfe02020, 0xdfdfdfe0, 0xdfe02e2e, 0xdfdfd1d2, 0x2e2e0000, 0x2e2e0202,
+ 0x2e2dfdfe, 0x2e2e0606, 0x2e2df9fa, 0x2e2e0c0c, 0x2e2df3f4, 0x2e2e1414, 0x2e2debec, 0x2e2e2020,
+ 0x2e2ddfe0, 0x2e2e2e2e, 0x2e2dd1d2, 0xd1d20000, 0xd1d20202, 0xd1d1fdfe, 0xd1d20606, 0xd1d1f9fa,
+ 0xd1d20c0c, 0xd1d1f3f4, 0xd1d21414, 0xd1d1ebec, 0xd1d22020, 0xd1d1dfe0, 0xd1d22e2e, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa, 0x00000c0c, 0xfffff3f4, 0x00001414,
+ 0xffffebec, 0x00002020, 0xffffdfe0, 0x00002e2e, 0xffffd1d2, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000202, 0xfffffdfe, 0x00000606, 0xfffff9fa, 0x00000c0c, 0xfffff3f4, 0x00001414, 0xffffebec,
+ 0x00002020, 0xffffdfe0, 0x00002e2e, 0xffffd1d2, 0x02020000, 0x02020202, 0x0201fdfe, 0x02020606,
+ 0x0201f9fa, 0x02020c0c, 0x0201f3f4, 0x02021414, 0x0201ebec, 0x02022020, 0x0201dfe0, 0x02022e2e,
+ 0x0201d1d2, 0xfdfe0000, 0xfdfe0202, 0xfdfdfdfe, 0xfdfe0606, 0xfdfdf9fa, 0xfdfe0c0c, 0xfdfdf3f4,
+ 0xfdfe1414, 0xfdfdebec, 0xfdfe2020, 0xfdfddfe0, 0xfdfe2e2e, 0xfdfdd1d2, 0x06060000, 0x06060202,
+ 0x0605fdfe, 0x06060606, 0x0605f9fa, 0x06060c0c, 0x0605f3f4, 0x06061414, 0x0605ebec, 0x06062020,
+ 0x0605dfe0, 0x06062e2e, 0x0605d1d2, 0xf9fa0000, 0xf9fa0202, 0xf9f9fdfe, 0xf9fa0606, 0xf9f9f9fa,
+ 0xf9fa0c0c, 0xf9f9f3f4, 0xf9fa1414, 0xf9f9ebec, 0xf9fa2020, 0xf9f9dfe0, 0xf9fa2e2e, 0xf9f9d1d2,
+ 0x0c0c0000, 0x0c0c0202, 0x0c0bfdfe, 0x0c0c0606, 0x0c0bf9fa, 0x0c0c0c0c, 0x0c0bf3f4, 0x0c0c1414,
+ 0x0c0bebec, 0x0c0c2020, 0x0c0bdfe0, 0x0c0c2e2e, 0x0c0bd1d2, 0xf3f40000, 0xf3f40202, 0xf3f3fdfe,
+ 0xf3f40606, 0xf3f3f9fa, 0xf3f40c0c, 0xf3f3f3f4, 0xf3f41414, 0xf3f3ebec, 0xf3f42020, 0xf3f3dfe0,
+ 0xf3f42e2e, 0xf3f3d1d2, 0x14140000, 0x14140202, 0x1413fdfe, 0x14140606, 0x1413f9fa, 0x14140c0c,
+ 0x1413f3f4, 0x14141414, 0x1413ebec, 0x14142020, 0x1413dfe0, 0x14142e2e, 0x1413d1d2, 0xebec0000,
+ 0xebec0202, 0xebebfdfe, 0xebec0606, 0xebebf9fa, 0xebec0c0c, 0xebebf3f4, 0xebec1414, 0xebebebec,
+ 0xebec2020, 0xebebdfe0, 0xebec2e2e, 0xebebd1d2, 0x20200000, 0x20200202, 0x201ffdfe, 0x20200606,
+ 0x201ff9fa, 0x20200c0c, 0x201ff3f4, 0x20201414, 0x201febec, 0x20202020, 0x201fdfe0, 0x20202e2e,
+ 0x201fd1d2, 0xdfe00000, 0xdfe00202, 0xdfdffdfe, 0xdfe00606, 0xdfdff9fa, 0xdfe00c0c, 0xdfdff3f4,
+ 0xdfe01414, 0xdfdfebec, 0xdfe02020, 0xdfdfdfe0, 0xdfe02e2e, 0xdfdfd1d2, 0x2e2e0000, 0x2e2e0202,
+ 0x2e2dfdfe, 0x2e2e0606, 0x2e2df9fa, 0x2e2e0c0c, 0x2e2df3f4, 0x2e2e1414, 0x2e2debec, 0x2e2e2020,
+ 0x2e2ddfe0, 0x2e2e2e2e, 0x2e2dd1d2, 0xd1d20000, 0xd1d20202, 0xd1d1fdfe, 0xd1d20606, 0xd1d1f9fa,
+ 0xd1d20c0c, 0xd1d1f3f4, 0xd1d21414, 0xd1d1ebec, 0xd1d22020, 0xd1d1dfe0, 0xd1d22e2e, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
+
+
+static const uint32_t correctionloworder[] = {
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x0302feff, 0xfcfd0101, 0xfeff0303, 0x0100fcfd, 0x04040404,
+ 0xfbfbfbfc, 0x05050101, 0xfafafeff, 0x01010505, 0xfefefafb, 0x0403fbfc, 0xfbfc0404, 0x0605fdfe,
+ 0xf9fa0202, 0xfdfe0606, 0x0201f9fa, 0x09090404, 0xf6f6fbfc, 0x04040909, 0xfbfbf6f7, 0x09090909,
+ 0xf6f6f6f7, 0x0a0a0101, 0xf5f5feff, 0x01010a0a, 0xfefef5f6, 0x0807fafb, 0xf7f80505, 0xfafb0808,
+ 0x0504f7f8, 0x0f0f0909, 0xf0f0f6f7, 0x09090f0f, 0xf6f6f0f1, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c,
+ 0x0302f3f4, 0x10100404, 0xefeffbfc, 0x04041010, 0xfbfbeff0, 0x10101010, 0xefefeff0, 0x12120000,
+ 0xedee0000, 0x00001212, 0xffffedee, 0x0c0bf3f4, 0xf3f40c0c, 0x100ff6f7, 0xeff00909, 0xf6f71010,
+ 0x0908eff0, 0x1b1b0b0b, 0xe4e4f4f5, 0x0b0b1b1b, 0xf4f4e4e5, 0x1c1c1313, 0xe3e3eced, 0x13131c1c,
+ 0xecece3e4, 0x1615f9fa, 0xe9ea0606, 0xf9fa1616, 0x0605e9ea, 0x1d1d0404, 0xe2e2fbfc, 0x04041d1d,
+ 0xfbfbe2e3, 0x1e1e1e1e, 0xe1e1e1e2, 0x2120fdfe, 0xdedf0202, 0xfdfe2121, 0x0201dedf, 0x1716edee,
+ 0xe8e91212, 0xedee1717, 0x1211e8e9, 0x1e1df0f1, 0xe1e20f0f, 0xf0f11e1e, 0x0f0ee1e2, 0x2e2e1616,
+ 0xd1d1e9ea, 0x16162e2e, 0xe9e9d1d2, 0x2f2f0d0d, 0xd0d0f2f3, 0x0d0d2f2f, 0xf2f2d0d1, 0x31312323,
+ 0xcecedcdd, 0x23233131, 0xdcdccecf, 0x2928f4f5, 0xd6d70b0b, 0xf4f52929, 0x0b0ad6d7, 0x33330404,
+ 0xccccfbfc, 0x04043333, 0xfbfbcccd, 0x36363636, 0xc9c9c9ca, 0x2221ddde, 0xddde2222, 0x2a29e2e3,
+ 0xd5d61d1d, 0xe2e32a2a, 0x1d1cd5d6, 0x3c3bf9fa, 0xc3c40606, 0xf9fa3c3c, 0x0605c3c4, 0x4c4c1b1b,
+ 0xb3b3e4e5, 0x1b1b4c4c, 0xe4e4b3b4, 0x4d4d2b2b, 0xb2b2d4d5, 0x2b2b4d4d, 0xd4d4b2b3, 0x3736e7e8,
+ 0xc8c91818, 0xe7e83737, 0x1817c8c9, 0x4f4f0e0e, 0xb0b0f1f2, 0x0e0e4f4f, 0xf1f1b0b1, 0x53533f3f,
+ 0xacacc0c1, 0x3f3f5353, 0xc0c0acad, 0x4a49ebec, 0xb5b61414, 0xebec4a4a, 0x1413b5b6, 0x58580202,
+ 0xa7a7fdfe, 0x02025858, 0xfdfda7a8, 0x5d5d5d5d, 0xa2a2a2a3, 0x3d3ccbcc, 0xc2c33434, 0xcbcc3d3d,
+ 0x3433c2c3, 0x78783434, 0x8787cbcc, 0x34347878, 0xcbcb8788, 0x4b4ad2d3, 0xb4b52d2d, 0xd2d34b4b,
+ 0x2d2cb4b5, 0x7d7d4b4b, 0x8282b4b5, 0x4b4b7d7d, 0xb4b48283, 0x7a7a2121, 0x8585dedf, 0x21217a7a,
+ 0xdede8586, 0x6766f2f3, 0x98990d0d, 0xf2f36767, 0x0d0c9899, 0x605fd7d8, 0x9fa02828, 0xd7d86060,
+ 0x28279fa0, 0x7f7eddde, 0x80812222, 0xddde7f7f, 0x22218081, 0x5958a6a7, 0xa6a75959, 0x6968b1b2,
+ 0x96974e4e, 0xb1b26969, 0x4e4d9697, 0x0c0c0c0c, 0xf3f3f3f4, 0x17171717, 0xe8e8e8e9, 0x2a2a2a2a,
+ 0xd5d5d5d6, 0x49494949, 0xb6b6b6b7, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0x0302feff, 0x0302feff, 0x0302feff, 0x0302feff, 0x0302feff, 0x0302feff, 0x0302feff, 0xfcfd0101,
+ 0xfcfd0101, 0xfcfd0101, 0xfcfd0101, 0xfcfd0101, 0xfcfd0101, 0xfcfd0101, 0xfeff0303, 0xfeff0303,
+ 0xfeff0303, 0xfeff0303, 0xfeff0303, 0xfeff0303, 0xfeff0303, 0x0100fcfd, 0x0100fcfd, 0x0100fcfd,
+ 0x0100fcfd, 0x0100fcfd, 0x0100fcfd, 0x0100fcfd, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x03030303, 0xfcfcfcfd, 0x0403feff, 0xfbfc0101, 0xfeff0404, 0x0100fbfc, 0x07070707,
+ 0xf8f8f8f9, 0x08080202, 0xf7f7fdfe, 0x02020808, 0xfdfdf7f8, 0x0908fdfe, 0xf6f70202, 0xfdfe0909,
+ 0x0201f6f7, 0x0605f9fa, 0xf9fa0606, 0x0d0d0606, 0xf2f2f9fa, 0x06060d0d, 0xf9f9f2f3, 0x0d0d0d0d,
+ 0xf2f2f2f3, 0x0e0e0101, 0xf1f1feff, 0x01010e0e, 0xfefef1f2, 0x0c0bf7f8, 0xf3f40808, 0xf7f80c0c,
+ 0x0807f3f4, 0x17170e0e, 0xe8e8f1f2, 0x0e0e1717, 0xf1f1e8e9, 0x1211fafb, 0xedee0505, 0xfafb1212,
+ 0x0504edee, 0x18180606, 0xe7e7f9fa, 0x06061818, 0xf9f9e7e8, 0x18181818, 0xe7e7e7e8, 0x1b1afeff,
+ 0xe4e50101, 0xfeff1b1b, 0x0100e4e5, 0x1110eeef, 0xeeef1111, 0x1716f2f3, 0xe8e90d0d, 0xf2f31717,
+ 0x0d0ce8e9, 0x28281010, 0xd7d7eff0, 0x10102828, 0xefefd7d8, 0x29291c1c, 0xd6d6e3e4, 0x1c1c2929,
+ 0xe3e3d6d7, 0x2120f6f7, 0xdedf0909, 0xf6f72121, 0x0908dedf, 0x2b2b0606, 0xd4d4f9fa, 0x06062b2b,
+ 0xf9f9d4d5, 0x2e2e2e2e, 0xd1d1d1d2, 0x3231fbfc, 0xcdce0404, 0xfbfc3232, 0x0403cdce, 0x2221e4e5,
+ 0xddde1b1b, 0xe4e52222, 0x1b1addde, 0x2d2ce9ea, 0xd2d31616, 0xe9ea2d2d, 0x1615d2d3, 0x45452222,
+ 0xbabaddde, 0x22224545, 0xddddbabb, 0x46461313, 0xb9b9eced, 0x13134646, 0xececb9ba, 0x49493535,
+ 0xb6b6cacb, 0x35354949, 0xcacab6b7, 0x3e3deeef, 0xc1c21111, 0xeeef3e3e, 0x1110c1c2, 0x4d4d0505,
+ 0xb2b2fafb, 0x05054d4d, 0xfafab2b3, 0x52525252, 0xadadadae, 0x3332cccd, 0xcccd3333, 0x403fd4d5,
+ 0xbfc02b2b, 0xd4d54040, 0x2b2abfc0, 0x5a59f5f6, 0xa5a60a0a, 0xf5f65a5a, 0x0a09a5a6, 0x72722929,
+ 0x8d8dd6d7, 0x29297272, 0xd6d68d8e, 0x74744040, 0x8b8bbfc0, 0x40407474, 0xbfbf8b8c, 0x5251dadb,
+ 0xadae2525, 0xdadb5252, 0x2524adae, 0x77771616, 0x8888e9ea, 0x16167777, 0xe9e98889, 0x7c7c5f5f,
+ 0x8383a0a1, 0x5f5f7c7c, 0xa0a08384, 0x6f6ee1e2, 0x90911e1e, 0xe1e26f6f, 0x1e1d9091, 0x5c5bb1b2,
+ 0xa3a44e4e, 0xb1b25c5c, 0x4e4da3a4, 0x7170bbbc, 0x8e8f4444, 0xbbbc7171, 0x44438e8f, 0x12121212,
+ 0xedededee, 0x22222222, 0xddddddde, 0x3f3f3f3f, 0xc0c0c0c1, 0x6d6d6d6d, 0x92929293, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x03030303, 0x03030303, 0x03030303, 0x03030303, 0x03030303, 0x03030303, 0x03030303, 0x03030303,
+ 0x03030303, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd,
+ 0xfcfcfcfd, 0xfcfcfcfd, 0x0403feff, 0x0403feff, 0x0403feff, 0x0403feff, 0x0403feff, 0x0403feff,
+ 0x0403feff, 0x0403feff, 0x0403feff, 0xfbfc0101, 0xfbfc0101, 0xfbfc0101, 0xfbfc0101, 0xfbfc0101,
+ 0xfbfc0101, 0xfbfc0101, 0xfbfc0101, 0xfbfc0101, 0xfeff0404, 0xfeff0404, 0xfeff0404, 0xfeff0404,
+ 0xfeff0404, 0xfeff0404, 0xfeff0404, 0xfeff0404, 0xfeff0404, 0x0100fbfc, 0x0100fbfc, 0x0100fbfc,
+ 0x0100fbfc, 0x0100fbfc, 0x0100fbfc, 0x0100fbfc, 0x0100fbfc, 0x0100fbfc, 0x07070707, 0x07070707,
+ 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0xf8f8f8f9,
+ 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x04040404, 0xfbfbfbfc, 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb, 0x0a0a0303,
+ 0xf5f5fcfd, 0x03030a0a, 0xfcfcf5f6, 0x09090909, 0xf6f6f6f7, 0x0706f8f9, 0xf8f90707, 0x0c0bfcfd,
+ 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x11110808, 0xeeeef7f8, 0x08081111, 0xf7f7eeef, 0x11111111,
+ 0xeeeeeeef, 0x13130101, 0xececfeff, 0x01011313, 0xfefeeced, 0x100ff4f5, 0xeff00b0b, 0xf4f51010,
+ 0x0b0aeff0, 0x1716f9fa, 0xe8e90606, 0xf9fa1717, 0x0605e8e9, 0x1f1f1212, 0xe0e0edee, 0x12121f1f,
+ 0xedede0e1, 0x20200808, 0xdfdff7f8, 0x08082020, 0xf7f7dfe0, 0x21212121, 0xdedededf, 0x2423feff,
+ 0xdbdc0101, 0xfeff2424, 0x0100dbdc, 0x1716e8e9, 0xe8e91717, 0x1f1eeeef, 0xe0e11111, 0xeeef1f1f,
+ 0x1110e0e1, 0x36361515, 0xc9c9eaeb, 0x15153636, 0xeaeac9ca, 0x37372525, 0xc8c8dadb, 0x25253737,
+ 0xdadac8c9, 0x2c2bf3f4, 0xd3d40c0c, 0xf3f42c2c, 0x0c0bd3d4, 0x39390808, 0xc6c6f7f8, 0x08083939,
+ 0xf7f7c6c7, 0x3d3d3d3d, 0xc2c2c2c3, 0x4241fafb, 0xbdbe0505, 0xfafb4242, 0x0504bdbe, 0x2d2cdbdc,
+ 0xd2d32424, 0xdbdc2d2d, 0x2423d2d3, 0x3c3be2e3, 0xc3c41d1d, 0xe2e33c3c, 0x1d1cc3c4, 0x5c5c2d2d,
+ 0xa3a3d2d3, 0x2d2d5c5c, 0xd2d2a3a4, 0x5d5d1919, 0xa2a2e6e7, 0x19195d5d, 0xe6e6a2a3, 0x61614747,
+ 0x9e9eb8b9, 0x47476161, 0xb8b89e9f, 0x5352e9ea, 0xacad1616, 0xe9ea5353, 0x1615acad, 0x66660707,
+ 0x9999f8f9, 0x07076666, 0xf8f8999a, 0x6d6d6d6d, 0x92929293, 0x4443bbbc, 0xbbbc4444, 0x5554c6c7,
+ 0xaaab3939, 0xc6c75555, 0x3938aaab, 0x7877f2f3, 0x87880d0d, 0xf2f37878, 0x0d0c8788, 0x6e6dcecf,
+ 0x91923131, 0xcecf6e6e, 0x31309192, 0x7b7a9798, 0x84856868, 0x97987b7b, 0x68678485, 0x18181818,
+ 0xe7e7e7e8, 0x2e2e2e2e, 0xd1d1d1d2, 0x54545454, 0xabababac, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04040404,
+ 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404,
+ 0x04040404, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc,
+ 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0x0504feff, 0x0504feff, 0x0504feff, 0x0504feff, 0x0504feff,
+ 0x0504feff, 0x0504feff, 0x0504feff, 0x0504feff, 0x0504feff, 0xfafb0101, 0xfafb0101, 0xfafb0101,
+ 0xfafb0101, 0xfafb0101, 0xfafb0101, 0xfafb0101, 0xfafb0101, 0xfafb0101, 0xfafb0101, 0xfeff0505,
+ 0xfeff0505, 0xfeff0505, 0xfeff0505, 0xfeff0505, 0xfeff0505, 0xfeff0505, 0xfeff0505, 0xfeff0505,
+ 0xfeff0505, 0x0100fafb, 0x0100fafb, 0x0100fafb, 0x0100fafb, 0x0100fafb, 0x0100fafb, 0x0100fafb,
+ 0x0100fafb, 0x0100fafb, 0x0100fafb, 0x0a0a0303, 0x0a0a0303, 0x0a0a0303, 0x0a0a0303, 0x0a0a0303,
+ 0x0a0a0303, 0x0a0a0303, 0x0a0a0303, 0x0a0a0303, 0x0a0a0303, 0xf5f5fcfd, 0xf5f5fcfd, 0xf5f5fcfd,
+ 0xf5f5fcfd, 0xf5f5fcfd, 0xf5f5fcfd, 0xf5f5fcfd, 0xf5f5fcfd, 0xf5f5fcfd, 0xf5f5fcfd, 0x03030a0a,
+ 0x03030a0a, 0x03030a0a, 0x03030a0a, 0x03030a0a, 0x03030a0a, 0x03030a0a, 0x03030a0a, 0x03030a0a,
+ 0x03030a0a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x05050505, 0xfafafafb, 0x0706fdfe, 0xf8f90202, 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b,
+ 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd, 0x03030d0d, 0xfcfcf2f3, 0x0908f6f7, 0xf6f70909, 0x0f0efbfc,
+ 0xf0f10404, 0xfbfc0f0f, 0x0403f0f1, 0x16160b0b, 0xe9e9f4f5, 0x0b0b1616, 0xf4f4e9ea, 0x15151515,
+ 0xeaeaeaeb, 0x18180202, 0xe7e7fdfe, 0x02021818, 0xfdfde7e8, 0x1413f1f2, 0xebec0e0e, 0xf1f21414,
+ 0x0e0debec, 0x26261717, 0xd9d9e8e9, 0x17172626, 0xe8e8d9da, 0x1d1cf7f8, 0xe2e30808, 0xf7f81d1d,
+ 0x0807e2e3, 0x27270b0b, 0xd8d8f4f5, 0x0b0b2727, 0xf4f4d8d9, 0x29292929, 0xd6d6d6d7, 0x2d2cfeff,
+ 0xd2d30101, 0xfeff2d2d, 0x0100d2d3, 0x1d1ce2e3, 0xe2e31d1d, 0x2726e9ea, 0xd8d91616, 0xe9ea2727,
+ 0x1615d8d9, 0x43431b1b, 0xbcbce4e5, 0x1b1b4343, 0xe4e4bcbd, 0x45452f2f, 0xbabad0d1, 0x2f2f4545,
+ 0xd0d0babb, 0x3837f0f1, 0xc7c80f0f, 0xf0f13838, 0x0f0ec7c8, 0x47470b0b, 0xb8b8f4f5, 0x0b0b4747,
+ 0xf4f4b8b9, 0x4c4c4c4c, 0xb3b3b3b4, 0x5352f9fa, 0xacad0606, 0xf9fa5353, 0x0605acad, 0x3938d2d3,
+ 0xc6c72d2d, 0xd2d33939, 0x2d2cc6c7, 0x4b4adbdc, 0xb4b52424, 0xdbdc4b4b, 0x2423b4b5, 0x73733838,
+ 0x8c8cc7c8, 0x38387373, 0xc7c78c8d, 0x75751f1f, 0x8a8ae0e1, 0x1f1f7575, 0xe0e08a8b, 0x7a7a5858,
+ 0x8585a7a8, 0x58587a7a, 0xa7a78586, 0x6867e3e4, 0x97981c1c, 0xe3e46868, 0x1c1b9798, 0x5554aaab,
+ 0xaaab5555, 0x6a69b7b8, 0x95964848, 0xb7b86a6a, 0x48479596, 0x1e1e1e1e, 0xe1e1e1e2, 0x3a3a3a3a,
+ 0xc5c5c5c6, 0x69696969, 0x96969697, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x05050505, 0x05050505,
+ 0x05050505, 0x05050505, 0x05050505, 0x05050505, 0x05050505, 0x05050505, 0x05050505, 0x05050505,
+ 0x05050505, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb,
+ 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0x0706fdfe, 0x0706fdfe, 0x0706fdfe, 0x0706fdfe,
+ 0x0706fdfe, 0x0706fdfe, 0x0706fdfe, 0x0706fdfe, 0x0706fdfe, 0x0706fdfe, 0x0706fdfe, 0xf8f90202,
+ 0xf8f90202, 0xf8f90202, 0xf8f90202, 0xf8f90202, 0xf8f90202, 0xf8f90202, 0xf8f90202, 0xf8f90202,
+ 0xf8f90202, 0xf8f90202, 0xfdfe0707, 0xfdfe0707, 0xfdfe0707, 0xfdfe0707, 0xfdfe0707, 0xfdfe0707,
+ 0xfdfe0707, 0xfdfe0707, 0xfdfe0707, 0xfdfe0707, 0xfdfe0707, 0x0201f8f9, 0x0201f8f9, 0x0201f8f9,
+ 0x0201f8f9, 0x0201f8f9, 0x0201f8f9, 0x0201f8f9, 0x0201f8f9, 0x0201f8f9, 0x0201f8f9, 0x0201f8f9,
+ 0x0b0b0b0b, 0x0b0b0b0b, 0x0b0b0b0b, 0x0b0b0b0b, 0x0b0b0b0b, 0x0b0b0b0b, 0x0b0b0b0b, 0x0b0b0b0b,
+ 0x0b0b0b0b, 0x0b0b0b0b, 0x0b0b0b0b, 0xf4f4f4f5, 0xf4f4f4f5, 0xf4f4f4f5, 0xf4f4f4f5, 0xf4f4f4f5,
+ 0xf4f4f4f5, 0xf4f4f4f5, 0xf4f4f4f5, 0xf4f4f4f5, 0xf4f4f4f5, 0xf4f4f4f5, 0x0d0d0303, 0x0d0d0303,
+ 0x0d0d0303, 0x0d0d0303, 0x0d0d0303, 0x0d0d0303, 0x0d0d0303, 0x0d0d0303, 0x0d0d0303, 0x0d0d0303,
+ 0x0d0d0303, 0xf2f2fcfd, 0xf2f2fcfd, 0xf2f2fcfd, 0xf2f2fcfd, 0xf2f2fcfd, 0xf2f2fcfd, 0xf2f2fcfd,
+ 0xf2f2fcfd, 0xf2f2fcfd, 0xf2f2fcfd, 0xf2f2fcfd, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x06060606, 0xf9f9f9fa, 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8, 0x0d0d0d0d,
+ 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc, 0x04040f0f, 0xfbfbf0f1, 0x0b0af4f5, 0xf4f50b0b, 0x1211fafb,
+ 0xedee0505, 0xfafb1212, 0x0504edee, 0x1a1a0d0d, 0xe5e5f2f3, 0x0d0d1a1a, 0xf2f2e5e6, 0x1a1a1a1a,
+ 0xe5e5e5e6, 0x1d1d0202, 0xe2e2fdfe, 0x02021d1d, 0xfdfde2e3, 0x1817eff0, 0xe7e81010, 0xeff01818,
+ 0x100fe7e8, 0x2e2e1c1c, 0xd1d1e3e4, 0x1c1c2e2e, 0xe3e3d1d2, 0x2322f6f7, 0xdcdd0909, 0xf6f72323,
+ 0x0908dcdd, 0x2f2f0d0d, 0xd0d0f2f3, 0x0d0d2f2f, 0xf2f2d0d1, 0x31313131, 0xcecececf, 0x3635feff,
+ 0xc9ca0101, 0xfeff3636, 0x0100c9ca, 0x2322dcdd, 0xdcdd2323, 0x2f2ee5e6, 0xd0d11a1a, 0xe5e62f2f,
+ 0x1a19d0d1, 0x51512020, 0xaeaedfe0, 0x20205151, 0xdfdfaeaf, 0x53533838, 0xacacc7c8, 0x38385353,
+ 0xc7c7acad, 0x4342edee, 0xbcbd1212, 0xedee4343, 0x1211bcbd, 0x56560d0d, 0xa9a9f2f3, 0x0d0d5656,
+ 0xf2f2a9aa, 0x5b5b5b5b, 0xa4a4a4a5, 0x6362f8f9, 0x9c9d0707, 0xf8f96363, 0x07069c9d, 0x4443c9ca,
+ 0xbbbc3636, 0xc9ca4444, 0x3635bbbc, 0x5a59d3d4, 0xa5a62c2c, 0xd3d45a5a, 0x2c2ba5a6, 0x7c7bdedf,
+ 0x83842121, 0xdedf7c7c, 0x21208384, 0x67669899, 0x98996767, 0x7f7ea9aa, 0x80815656, 0xa9aa7f7f,
+ 0x56558081, 0x25252525, 0xdadadadb, 0x45454545, 0xbabababb, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0x0807fdfe, 0x0807fdfe, 0x0807fdfe, 0x0807fdfe, 0x0807fdfe, 0x0807fdfe, 0x0807fdfe,
+ 0x0807fdfe, 0x0807fdfe, 0x0807fdfe, 0x0807fdfe, 0x0807fdfe, 0xf7f80202, 0xf7f80202, 0xf7f80202,
+ 0xf7f80202, 0xf7f80202, 0xf7f80202, 0xf7f80202, 0xf7f80202, 0xf7f80202, 0xf7f80202, 0xf7f80202,
+ 0xf7f80202, 0xfdfe0808, 0xfdfe0808, 0xfdfe0808, 0xfdfe0808, 0xfdfe0808, 0xfdfe0808, 0xfdfe0808,
+ 0xfdfe0808, 0xfdfe0808, 0xfdfe0808, 0xfdfe0808, 0xfdfe0808, 0x0201f7f8, 0x0201f7f8, 0x0201f7f8,
+ 0x0201f7f8, 0x0201f7f8, 0x0201f7f8, 0x0201f7f8, 0x0201f7f8, 0x0201f7f8, 0x0201f7f8, 0x0201f7f8,
+ 0x0201f7f8, 0x0d0d0d0d, 0x0d0d0d0d, 0x0d0d0d0d, 0x0d0d0d0d, 0x0d0d0d0d, 0x0d0d0d0d, 0x0d0d0d0d,
+ 0x0d0d0d0d, 0x0d0d0d0d, 0x0d0d0d0d, 0x0d0d0d0d, 0x0d0d0d0d, 0xf2f2f2f3, 0xf2f2f2f3, 0xf2f2f2f3,
+ 0xf2f2f2f3, 0xf2f2f2f3, 0xf2f2f2f3, 0xf2f2f2f3, 0xf2f2f2f3, 0xf2f2f2f3, 0xf2f2f2f3, 0xf2f2f2f3,
+ 0xf2f2f2f3, 0x0f0f0404, 0x0f0f0404, 0x0f0f0404, 0x0f0f0404, 0x0f0f0404, 0x0f0f0404, 0x0f0f0404,
+ 0x0f0f0404, 0x0f0f0404, 0x0f0f0404, 0x0f0f0404, 0x0f0f0404, 0xf0f0fbfc, 0xf0f0fbfc, 0xf0f0fbfc,
+ 0xf0f0fbfc, 0xf0f0fbfc, 0xf0f0fbfc, 0xf0f0fbfc, 0xf0f0fbfc, 0xf0f0fbfc, 0xf0f0fbfc, 0xf0f0fbfc,
+ 0xf0f0fbfc, 0x04040f0f, 0x04040f0f, 0x04040f0f, 0x04040f0f, 0x04040f0f, 0x04040f0f, 0x04040f0f,
+ 0x04040f0f, 0x04040f0f, 0x04040f0f, 0x04040f0f, 0x04040f0f, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x07070707, 0xf8f8f8f9, 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6, 0x10101010,
+ 0xefefeff0, 0x12120505, 0xededfafb, 0x05051212, 0xfafaedee, 0x0d0cf2f3, 0xf2f30d0d, 0x1514f9fa,
+ 0xeaeb0606, 0xf9fa1515, 0x0605eaeb, 0x1e1e0f0f, 0xe1e1f0f1, 0x0f0f1e1e, 0xf0f0e1e2, 0x1e1e1e1e,
+ 0xe1e1e1e2, 0x22220202, 0xddddfdfe, 0x02022222, 0xfdfdddde, 0x1c1beced, 0xe3e41313, 0xeced1c1c,
+ 0x1312e3e4, 0x36362020, 0xc9c9dfe0, 0x20203636, 0xdfdfc9ca, 0x2928f4f5, 0xd6d70b0b, 0xf4f52929,
+ 0x0b0ad6d7, 0x37370f0f, 0xc8c8f0f1, 0x0f0f3737, 0xf0f0c8c9, 0x39393939, 0xc6c6c6c7, 0x3f3efeff,
+ 0xc0c10101, 0xfeff3f3f, 0x0100c0c1, 0x2827d7d8, 0xd7d82828, 0x3736e1e2, 0xc8c91e1e, 0xe1e23737,
+ 0x1e1dc8c9, 0x5e5e2525, 0xa1a1dadb, 0x25255e5e, 0xdadaa1a2, 0x60604141, 0x9f9fbebf, 0x41416060,
+ 0xbebe9fa0, 0x4e4deaeb, 0xb1b21515, 0xeaeb4e4e, 0x1514b1b2, 0x64640f0f, 0x9b9bf0f1, 0x0f0f6464,
+ 0xf0f09b9c, 0x6a6a6a6a, 0x95959596, 0x7473f7f8, 0x8b8c0808, 0xf7f87474, 0x08078b8c, 0x4f4ec0c1,
+ 0xb0b13f3f, 0xc0c14f4f, 0x3f3eb0b1, 0x6968cccd, 0x96973333, 0xcccd6969, 0x33329697, 0x78778788,
+ 0x87887878, 0x2b2b2b2b, 0xd4d4d4d5, 0x50505050, 0xafafafb0, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707,
+ 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9,
+ 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9,
+ 0xf8f8f8f9, 0x0a09fcfd, 0x0a09fcfd, 0x0a09fcfd, 0x0a09fcfd, 0x0a09fcfd, 0x0a09fcfd, 0x0a09fcfd,
+ 0x0a09fcfd, 0x0a09fcfd, 0x0a09fcfd, 0x0a09fcfd, 0x0a09fcfd, 0xf5f60303, 0xf5f60303, 0xf5f60303,
+ 0xf5f60303, 0xf5f60303, 0xf5f60303, 0xf5f60303, 0xf5f60303, 0xf5f60303, 0xf5f60303, 0xf5f60303,
+ 0xf5f60303, 0xfcfd0a0a, 0xfcfd0a0a, 0xfcfd0a0a, 0xfcfd0a0a, 0xfcfd0a0a, 0xfcfd0a0a, 0xfcfd0a0a,
+ 0xfcfd0a0a, 0xfcfd0a0a, 0xfcfd0a0a, 0xfcfd0a0a, 0xfcfd0a0a, 0x0302f5f6, 0x0302f5f6, 0x0302f5f6,
+ 0x0302f5f6, 0x0302f5f6, 0x0302f5f6, 0x0302f5f6, 0x0302f5f6, 0x0302f5f6, 0x0302f5f6, 0x0302f5f6,
+ 0x0302f5f6, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0xefefeff0, 0xefefeff0, 0xefefeff0,
+ 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0,
+ 0xefefeff0, 0x12120505, 0x12120505, 0x12120505, 0x12120505, 0x12120505, 0x12120505, 0x12120505,
+ 0x12120505, 0x12120505, 0x12120505, 0x12120505, 0x12120505, 0xededfafb, 0xededfafb, 0xededfafb,
+ 0xededfafb, 0xededfafb, 0xededfafb, 0xededfafb, 0xededfafb, 0xededfafb, 0xededfafb, 0xededfafb,
+ 0xededfafb, 0x05051212, 0x05051212, 0x05051212, 0x05051212, 0x05051212, 0x05051212, 0x05051212,
+ 0x05051212, 0x05051212, 0x05051212, 0x05051212, 0x05051212, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303, 0xfcfd0b0b, 0x0302f4f5, 0x12121212,
+ 0xedededee, 0x14140505, 0xebebfafb, 0x05051414, 0xfafaebec, 0x0f0ef0f1, 0xf0f10f0f, 0x1817f8f9,
+ 0xe7e80707, 0xf8f91818, 0x0706e7e8, 0x23231111, 0xdcdceeef, 0x11112323, 0xeeeedcdd, 0x22222222,
+ 0xddddddde, 0x26260303, 0xd9d9fcfd, 0x03032626, 0xfcfcd9da, 0x201fe9ea, 0xdfe01616, 0xe9ea2020,
+ 0x1615dfe0, 0x3d3d2525, 0xc2c2dadb, 0x25253d3d, 0xdadac2c3, 0x2f2ef2f3, 0xd0d10d0d, 0xf2f32f2f,
+ 0x0d0cd0d1, 0x3f3f1111, 0xc0c0eeef, 0x11113f3f, 0xeeeec0c1, 0x41414141, 0xbebebebf, 0x4847feff,
+ 0xb7b80101, 0xfeff4848, 0x0100b7b8, 0x2e2dd1d2, 0xd1d22e2e, 0x3f3edcdd, 0xc0c12323, 0xdcdd3f3f,
+ 0x2322c0c1, 0x6b6b2b2b, 0x9494d4d5, 0x2b2b6b6b, 0xd4d49495, 0x6e6e4b4b, 0x9191b4b5, 0x4b4b6e6e,
+ 0xb4b49192, 0x5958e7e8, 0xa6a71818, 0xe7e85959, 0x1817a6a7, 0x72721111, 0x8d8deeef, 0x11117272,
+ 0xeeee8d8e, 0x79797979, 0x86868687, 0x5b5ab7b8, 0xa4a54848, 0xb7b85b5b, 0x4847a4a5, 0x7877c5c6,
+ 0x87883a3a, 0xc5c67878, 0x3a398788, 0x31313131, 0xcecececf, 0x5c5c5c5c, 0xa3a3a3a4, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0x08080808,
+ 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0xf7f7f7f8,
+ 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8,
+ 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0x0b0afcfd, 0x0b0afcfd, 0x0b0afcfd, 0x0b0afcfd, 0x0b0afcfd,
+ 0x0b0afcfd, 0x0b0afcfd, 0x0b0afcfd, 0x0b0afcfd, 0x0b0afcfd, 0x0b0afcfd, 0x0b0afcfd, 0xf4f50303,
+ 0xf4f50303, 0xf4f50303, 0xf4f50303, 0xf4f50303, 0xf4f50303, 0xf4f50303, 0xf4f50303, 0xf4f50303,
+ 0xf4f50303, 0xf4f50303, 0xf4f50303, 0xfcfd0b0b, 0xfcfd0b0b, 0xfcfd0b0b, 0xfcfd0b0b, 0xfcfd0b0b,
+ 0xfcfd0b0b, 0xfcfd0b0b, 0xfcfd0b0b, 0xfcfd0b0b, 0xfcfd0b0b, 0xfcfd0b0b, 0xfcfd0b0b, 0x0302f4f5,
+ 0x0302f4f5, 0x0302f4f5, 0x0302f4f5, 0x0302f4f5, 0x0302f4f5, 0x0302f4f5, 0x0302f4f5, 0x0302f4f5,
+ 0x0302f4f5, 0x0302f4f5, 0x0302f4f5, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212,
+ 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0xedededee,
+ 0xedededee, 0xedededee, 0xedededee, 0xedededee, 0xedededee, 0xedededee, 0xedededee, 0xedededee,
+ 0xedededee, 0xedededee, 0xedededee, 0x14140505, 0x14140505, 0x14140505, 0x14140505, 0x14140505,
+ 0x14140505, 0x14140505, 0x14140505, 0x14140505, 0x14140505, 0x14140505, 0x14140505, 0xebebfafb,
+ 0xebebfafb, 0xebebfafb, 0xebebfafb, 0xebebfafb, 0xebebfafb, 0xebebfafb, 0xebebfafb, 0xebebfafb,
+ 0xebebfafb, 0xebebfafb, 0xebebfafb, 0x05051414, 0x05051414, 0x05051414, 0x05051414, 0x05051414,
+ 0x05051414, 0x05051414, 0x05051414, 0x05051414, 0x05051414, 0x05051414, 0x05051414, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414,
+ 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x1110eeef, 0xeeef1111, 0x1b1af8f9,
+ 0xe4e50707, 0xf8f91b1b, 0x0706e4e5, 0x27271313, 0xd8d8eced, 0x13132727, 0xececd8d9, 0x27272727,
+ 0xd8d8d8d9, 0x2b2b0303, 0xd4d4fcfd, 0x03032b2b, 0xfcfcd4d5, 0x2423e7e8, 0xdbdc1818, 0xe7e82424,
+ 0x1817dbdc, 0x45452a2a, 0xbabad5d6, 0x2a2a4545, 0xd5d5babb, 0x3534f1f2, 0xcacb0e0e, 0xf1f23535,
+ 0x0e0dcacb, 0x47471313, 0xb8b8eced, 0x13134747, 0xececb8b9, 0x49494949, 0xb6b6b6b7, 0x504ffdfe,
+ 0xafb00202, 0xfdfe5050, 0x0201afb0, 0x3433cbcc, 0xcbcc3434, 0x4645d8d9, 0xb9ba2727, 0xd8d94646,
+ 0x2726b9ba, 0x79793030, 0x8686cfd0, 0x30307979, 0xcfcf8687, 0x7c7c5454, 0x8383abac, 0x54547c7c,
+ 0xabab8384, 0x6463e4e5, 0x9b9c1b1b, 0xe4e56464, 0x1b1a9b9c, 0x6665aeaf, 0x999a5151, 0xaeaf6666,
+ 0x5150999a, 0x37373737, 0xc8c8c8c9, 0x68686868, 0x97979798, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909,
+ 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0xf6f6f6f7,
+ 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7,
+ 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0x0c0bfcfd, 0x0c0bfcfd, 0x0c0bfcfd, 0x0c0bfcfd,
+ 0x0c0bfcfd, 0x0c0bfcfd, 0x0c0bfcfd, 0x0c0bfcfd, 0x0c0bfcfd, 0x0c0bfcfd, 0x0c0bfcfd, 0x0c0bfcfd,
+ 0x0c0bfcfd, 0xf3f40303, 0xf3f40303, 0xf3f40303, 0xf3f40303, 0xf3f40303, 0xf3f40303, 0xf3f40303,
+ 0xf3f40303, 0xf3f40303, 0xf3f40303, 0xf3f40303, 0xf3f40303, 0xf3f40303, 0xfcfd0c0c, 0xfcfd0c0c,
+ 0xfcfd0c0c, 0xfcfd0c0c, 0xfcfd0c0c, 0xfcfd0c0c, 0xfcfd0c0c, 0xfcfd0c0c, 0xfcfd0c0c, 0xfcfd0c0c,
+ 0xfcfd0c0c, 0xfcfd0c0c, 0xfcfd0c0c, 0x0302f3f4, 0x0302f3f4, 0x0302f3f4, 0x0302f3f4, 0x0302f3f4,
+ 0x0302f3f4, 0x0302f3f4, 0x0302f3f4, 0x0302f3f4, 0x0302f3f4, 0x0302f3f4, 0x0302f3f4, 0x0302f3f4,
+ 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414,
+ 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0xebebebec, 0xebebebec, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0x17170606, 0x17170606, 0x17170606, 0x17170606, 0x17170606, 0x17170606,
+ 0x17170606, 0x17170606, 0x17170606, 0x17170606, 0x17170606, 0x17170606, 0x17170606, 0xe8e8f9fa,
+ 0xe8e8f9fa, 0xe8e8f9fa, 0xe8e8f9fa, 0xe8e8f9fa, 0xe8e8f9fa, 0xe8e8f9fa, 0xe8e8f9fa, 0xe8e8f9fa,
+ 0xe8e8f9fa, 0xe8e8f9fa, 0xe8e8f9fa, 0xe8e8f9fa, 0x06061717, 0x06061717, 0x06061717, 0x06061717,
+ 0x06061717, 0x06061717, 0x06061717, 0x06061717, 0x06061717, 0x06061717, 0x06061717, 0x06061717,
+ 0x06061717, 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9,
+ 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9, 0xf9f9e8e9, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404,
+ 0xfbfbfbfc, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x0403fbfc, 0xfbfc0404, 0x0605fdfe,
+ 0xf9fa0202, 0xfdfe0606, 0x0201f9fa, 0x08080404, 0xf7f7fbfc, 0x04040808, 0xfbfbf7f8, 0x08080808,
+ 0xf7f7f7f8, 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x0807fbfc, 0xf7f80404, 0xfbfc0808,
+ 0x0403f7f8, 0x0e0e0808, 0xf1f1f7f8, 0x08080e0e, 0xf7f7f1f2, 0x0c0bfdfe, 0xf3f40202, 0xfdfe0c0c,
+ 0x0201f3f4, 0x10100404, 0xefeffbfc, 0x04041010, 0xfbfbeff0, 0x10101010, 0xefefeff0, 0x12120000,
+ 0xedee0000, 0x00001212, 0xffffedee, 0x0c0bf3f4, 0xf3f40c0c, 0x100ff7f8, 0xeff00808, 0xf7f81010,
+ 0x0807eff0, 0x1a1a0a0a, 0xe5e5f5f6, 0x0a0a1a1a, 0xf5f5e5e6, 0x1c1c1212, 0xe3e3edee, 0x12121c1c,
+ 0xedede3e4, 0x1615f9fa, 0xe9ea0606, 0xf9fa1616, 0x0605e9ea, 0x1c1c0404, 0xe3e3fbfc, 0x04041c1c,
+ 0xfbfbe3e4, 0x1e1e1e1e, 0xe1e1e1e2, 0x201ffdfe, 0xdfe00202, 0xfdfe2020, 0x0201dfe0, 0x1615edee,
+ 0xe9ea1212, 0xedee1616, 0x1211e9ea, 0x1e1df1f2, 0xe1e20e0e, 0xf1f21e1e, 0x0e0de1e2, 0x2e2e1616,
+ 0xd1d1e9ea, 0x16162e2e, 0xe9e9d1d2, 0x2e2e0c0c, 0xd1d1f3f4, 0x0c0c2e2e, 0xf3f3d1d2, 0x30302222,
+ 0xcfcfddde, 0x22223030, 0xddddcfd0, 0x2827f5f6, 0xd7d80a0a, 0xf5f62828, 0x0a09d7d8, 0x32320404,
+ 0xcdcdfbfc, 0x04043232, 0xfbfbcdce, 0x36363636, 0xc9c9c9ca, 0x2221ddde, 0xddde2222, 0x2a29e3e4,
+ 0xd5d61c1c, 0xe3e42a2a, 0x1c1bd5d6, 0x3c3bf9fa, 0xc3c40606, 0xf9fa3c3c, 0x0605c3c4, 0x4c4c1a1a,
+ 0xb3b3e5e6, 0x1a1a4c4c, 0xe5e5b3b4, 0x4c4c2a2a, 0xb3b3d5d6, 0x2a2a4c4c, 0xd5d5b3b4, 0x3635e7e8,
+ 0xc9ca1818, 0xe7e83636, 0x1817c9ca, 0x4e4e0e0e, 0xb1b1f1f2, 0x0e0e4e4e, 0xf1f1b1b2, 0x52523e3e,
+ 0xadadc1c2, 0x3e3e5252, 0xc1c1adae, 0x4a49ebec, 0xb5b61414, 0xebec4a4a, 0x1413b5b6, 0x58580202,
+ 0xa7a7fdfe, 0x02025858, 0xfdfda7a8, 0x5c5c5c5c, 0xa3a3a3a4, 0x3c3bcbcc, 0xc3c43434, 0xcbcc3c3c,
+ 0x3433c3c4, 0x76763434, 0x8989cbcc, 0x34347676, 0xcbcb898a, 0x4a49d3d4, 0xb5b62c2c, 0xd3d44a4a,
+ 0x2c2bb5b6, 0x76764a4a, 0x8989b5b6, 0x4a4a7676, 0xb5b5898a, 0x76762020, 0x8989dfe0, 0x20207676,
+ 0xdfdf898a, 0x6665f3f4, 0x999a0c0c, 0xf3f46666, 0x0c0b999a, 0x605fd7d8, 0x9fa02828, 0xd7d86060,
+ 0x28279fa0, 0x7675ddde, 0x898a2222, 0xddde7676, 0x2221898a, 0x5857a7a8, 0xa7a85858, 0x6867b1b2,
+ 0x97984e4e, 0xb1b26868, 0x4e4d9798, 0x0c0c0c0c, 0xf3f3f3f4, 0x16161616, 0xe9e9e9ea, 0x2a2a2a2a,
+ 0xd5d5d5d6, 0x48484848, 0xb7b7b7b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0xfdfe0000,
+ 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0x00000202, 0x00000202,
+ 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe,
+ 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x03030303, 0xfcfcfcfd, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606,
+ 0xf9f9f9fa, 0x09090303, 0xf6f6fcfd, 0x03030909, 0xfcfcf6f7, 0x0908fcfd, 0xf6f70303, 0xfcfd0909,
+ 0x0302f6f7, 0x0605f9fa, 0xf9fa0606, 0x0c0c0606, 0xf3f3f9fa, 0x06060c0c, 0xf9f9f3f4, 0x0c0c0c0c,
+ 0xf3f3f3f4, 0x0f0f0000, 0xf0f10000, 0x00000f0f, 0xfffff0f1, 0x0c0bf6f7, 0xf3f40909, 0xf6f70c0c,
+ 0x0908f3f4, 0x18180f0f, 0xe7e7f0f1, 0x0f0f1818, 0xf0f0e7e8, 0x1211f9fa, 0xedee0606, 0xf9fa1212,
+ 0x0605edee, 0x18180606, 0xe7e7f9fa, 0x06061818, 0xf9f9e7e8, 0x18181818, 0xe7e7e7e8, 0x1b1b0000,
+ 0xe4e50000, 0x00001b1b, 0xffffe4e5, 0x1211edee, 0xedee1212, 0x1817f3f4, 0xe7e80c0c, 0xf3f41818,
+ 0x0c0be7e8, 0x27270f0f, 0xd8d8f0f1, 0x0f0f2727, 0xf0f0d8d9, 0x2a2a1b1b, 0xd5d5e4e5, 0x1b1b2a2a,
+ 0xe4e4d5d6, 0x2120f6f7, 0xdedf0909, 0xf6f72121, 0x0908dedf, 0x2a2a0606, 0xd5d5f9fa, 0x06062a2a,
+ 0xf9f9d5d6, 0x2d2d2d2d, 0xd2d2d2d3, 0x3332fcfd, 0xcccd0303, 0xfcfd3333, 0x0302cccd, 0x2120e4e5,
+ 0xdedf1b1b, 0xe4e52121, 0x1b1adedf, 0x2d2ceaeb, 0xd2d31515, 0xeaeb2d2d, 0x1514d2d3, 0x45452121,
+ 0xbabadedf, 0x21214545, 0xdedebabb, 0x45451212, 0xbabaedee, 0x12124545, 0xededbabb, 0x48483636,
+ 0xb7b7c9ca, 0x36364848, 0xc9c9b7b8, 0x3f3eedee, 0xc0c11212, 0xedee3f3f, 0x1211c0c1, 0x4e4e0606,
+ 0xb1b1f9fa, 0x06064e4e, 0xf9f9b1b2, 0x51515151, 0xaeaeaeaf, 0x3332cccd, 0xcccd3333, 0x3f3ed5d6,
+ 0xc0c12a2a, 0xd5d63f3f, 0x2a29c0c1, 0x5a59f6f7, 0xa5a60909, 0xf6f75a5a, 0x0908a5a6, 0x72722a2a,
+ 0x8d8dd5d6, 0x2a2a7272, 0xd5d58d8e, 0x75753f3f, 0x8a8ac0c1, 0x3f3f7575, 0xc0c08a8b, 0x5150dbdc,
+ 0xaeaf2424, 0xdbdc5151, 0x2423aeaf, 0x78781515, 0x8787eaeb, 0x15157878, 0xeaea8788, 0x7b7b6060,
+ 0x84849fa0, 0x60607b7b, 0x9f9f8485, 0x6f6ee1e2, 0x90911e1e, 0xe1e26f6f, 0x1e1d9091, 0x5d5cb1b2,
+ 0xa2a34e4e, 0xb1b25d5d, 0x4e4da2a3, 0x7271babb, 0x8d8e4545, 0xbabb7272, 0x45448d8e, 0x12121212,
+ 0xedededee, 0x21212121, 0xdedededf, 0x3f3f3f3f, 0xc0c0c0c1, 0x6c6c6c6c, 0x93939394, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x03030303, 0x03030303, 0x03030303, 0x03030303, 0x03030303, 0x03030303, 0x03030303, 0x03030303,
+ 0x03030303, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd, 0xfcfcfcfd,
+ 0xfcfcfcfd, 0xfcfcfcfd, 0x03030000, 0x03030000, 0x03030000, 0x03030000, 0x03030000, 0x03030000,
+ 0x03030000, 0x03030000, 0x03030000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000,
+ 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0x00000303, 0x00000303, 0x00000303, 0x00000303,
+ 0x00000303, 0x00000303, 0x00000303, 0x00000303, 0x00000303, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd,
+ 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x04040404, 0xfbfbfbfc, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x08080404,
+ 0xf7f7fbfc, 0x04040808, 0xfbfbf7f8, 0x08080808, 0xf7f7f7f8, 0x0807f7f8, 0xf7f80808, 0x0c0bfbfc,
+ 0xf3f40404, 0xfbfc0c0c, 0x0403f3f4, 0x10100808, 0xefeff7f8, 0x08081010, 0xf7f7eff0, 0x10101010,
+ 0xefefeff0, 0x14140000, 0xebec0000, 0x00001414, 0xffffebec, 0x100ff3f4, 0xeff00c0c, 0xf3f41010,
+ 0x0c0beff0, 0x1817fbfc, 0xe7e80404, 0xfbfc1818, 0x0403e7e8, 0x20201010, 0xdfdfeff0, 0x10102020,
+ 0xefefdfe0, 0x20200808, 0xdfdff7f8, 0x08082020, 0xf7f7dfe0, 0x20202020, 0xdfdfdfe0, 0x24240000,
+ 0xdbdc0000, 0x00002424, 0xffffdbdc, 0x1817e7e8, 0xe7e81818, 0x201feff0, 0xdfe01010, 0xeff02020,
+ 0x100fdfe0, 0x34341414, 0xcbcbebec, 0x14143434, 0xebebcbcc, 0x38382424, 0xc7c7dbdc, 0x24243838,
+ 0xdbdbc7c8, 0x2c2bf3f4, 0xd3d40c0c, 0xf3f42c2c, 0x0c0bd3d4, 0x38380808, 0xc7c7f7f8, 0x08083838,
+ 0xf7f7c7c8, 0x3c3c3c3c, 0xc3c3c3c4, 0x403ffbfc, 0xbfc00404, 0xfbfc4040, 0x0403bfc0, 0x2c2bdbdc,
+ 0xd3d42424, 0xdbdc2c2c, 0x2423d3d4, 0x3c3be3e4, 0xc3c41c1c, 0xe3e43c3c, 0x1c1bc3c4, 0x5c5c2c2c,
+ 0xa3a3d3d4, 0x2c2c5c5c, 0xd3d3a3a4, 0x5c5c1818, 0xa3a3e7e8, 0x18185c5c, 0xe7e7a3a4, 0x60604848,
+ 0x9f9fb7b8, 0x48486060, 0xb7b79fa0, 0x5453ebec, 0xabac1414, 0xebec5454, 0x1413abac, 0x64640808,
+ 0x9b9bf7f8, 0x08086464, 0xf7f79b9c, 0x6c6c6c6c, 0x93939394, 0x4443bbbc, 0xbbbc4444, 0x5453c7c8,
+ 0xabac3838, 0xc7c85454, 0x3837abac, 0x7877f3f4, 0x87880c0c, 0xf3f47878, 0x0c0b8788, 0x6c6bcfd0,
+ 0x93943030, 0xcfd06c6c, 0x302f9394, 0x7c7b9798, 0x83846868, 0x97987c7c, 0x68678384, 0x18181818,
+ 0xe7e7e7e8, 0x2c2c2c2c, 0xd3d3d3d4, 0x54545454, 0xabababac, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04040404,
+ 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404,
+ 0x04040404, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc,
+ 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0x04040000, 0x04040000, 0x04040000, 0x04040000, 0x04040000,
+ 0x04040000, 0x04040000, 0x04040000, 0x04040000, 0x04040000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000,
+ 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0x00000404,
+ 0x00000404, 0x00000404, 0x00000404, 0x00000404, 0x00000404, 0x00000404, 0x00000404, 0x00000404,
+ 0x00000404, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc,
+ 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0x08080404, 0x08080404, 0x08080404, 0x08080404, 0x08080404,
+ 0x08080404, 0x08080404, 0x08080404, 0x08080404, 0x08080404, 0xf7f7fbfc, 0xf7f7fbfc, 0xf7f7fbfc,
+ 0xf7f7fbfc, 0xf7f7fbfc, 0xf7f7fbfc, 0xf7f7fbfc, 0xf7f7fbfc, 0xf7f7fbfc, 0xf7f7fbfc, 0x04040808,
+ 0x04040808, 0x04040808, 0x04040808, 0x04040808, 0x04040808, 0x04040808, 0x04040808, 0x04040808,
+ 0x04040808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x05050505, 0xfafafafb, 0x05050000, 0xfafb0000, 0x00000505, 0xfffffafb, 0x0a0a0a0a,
+ 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb, 0x05050f0f, 0xfafaf0f1, 0x0a09f5f6, 0xf5f60a0a, 0x0f0efafb,
+ 0xf0f10505, 0xfafb0f0f, 0x0504f0f1, 0x14140a0a, 0xebebf5f6, 0x0a0a1414, 0xf5f5ebec, 0x14141414,
+ 0xebebebec, 0x19190000, 0xe6e70000, 0x00001919, 0xffffe6e7, 0x1413f0f1, 0xebec0f0f, 0xf0f11414,
+ 0x0f0eebec, 0x28281919, 0xd7d7e6e7, 0x19192828, 0xe6e6d7d8, 0x1e1df5f6, 0xe1e20a0a, 0xf5f61e1e,
+ 0x0a09e1e2, 0x28280a0a, 0xd7d7f5f6, 0x0a0a2828, 0xf5f5d7d8, 0x28282828, 0xd7d7d7d8, 0x2d2d0000,
+ 0xd2d30000, 0x00002d2d, 0xffffd2d3, 0x1e1de1e2, 0xe1e21e1e, 0x2827ebec, 0xd7d81414, 0xebec2828,
+ 0x1413d7d8, 0x41411919, 0xbebee6e7, 0x19194141, 0xe6e6bebf, 0x46462d2d, 0xb9b9d2d3, 0x2d2d4646,
+ 0xd2d2b9ba, 0x3736f0f1, 0xc8c90f0f, 0xf0f13737, 0x0f0ec8c9, 0x46460a0a, 0xb9b9f5f6, 0x0a0a4646,
+ 0xf5f5b9ba, 0x4b4b4b4b, 0xb4b4b4b5, 0x5554fafb, 0xaaab0505, 0xfafb5555, 0x0504aaab, 0x3736d2d3,
+ 0xc8c92d2d, 0xd2d33737, 0x2d2cc8c9, 0x4b4adcdd, 0xb4b52323, 0xdcdd4b4b, 0x2322b4b5, 0x73733737,
+ 0x8c8cc8c9, 0x37377373, 0xc8c88c8d, 0x73731e1e, 0x8c8ce1e2, 0x1e1e7373, 0xe1e18c8d, 0x78785a5a,
+ 0x8787a5a6, 0x5a5a7878, 0xa5a58788, 0x6968e1e2, 0x96971e1e, 0xe1e26969, 0x1e1d9697, 0x5554aaab,
+ 0xaaab5555, 0x6968b9ba, 0x96974646, 0xb9ba6969, 0x46459697, 0x1e1e1e1e, 0xe1e1e1e2, 0x3c3c3c3c,
+ 0xc3c3c3c4, 0x69696969, 0x96969697, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x05050505, 0x05050505,
+ 0x05050505, 0x05050505, 0x05050505, 0x05050505, 0x05050505, 0x05050505, 0x05050505, 0x05050505,
+ 0x05050505, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb,
+ 0xfafafafb, 0xfafafafb, 0xfafafafb, 0xfafafafb, 0x05050000, 0x05050000, 0x05050000, 0x05050000,
+ 0x05050000, 0x05050000, 0x05050000, 0x05050000, 0x05050000, 0x05050000, 0x05050000, 0xfafb0000,
+ 0xfafb0000, 0xfafb0000, 0xfafb0000, 0xfafb0000, 0xfafb0000, 0xfafb0000, 0xfafb0000, 0xfafb0000,
+ 0xfafb0000, 0xfafb0000, 0x00000505, 0x00000505, 0x00000505, 0x00000505, 0x00000505, 0x00000505,
+ 0x00000505, 0x00000505, 0x00000505, 0x00000505, 0x00000505, 0xfffffafb, 0xfffffafb, 0xfffffafb,
+ 0xfffffafb, 0xfffffafb, 0xfffffafb, 0xfffffafb, 0xfffffafb, 0xfffffafb, 0xfffffafb, 0xfffffafb,
+ 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a,
+ 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6,
+ 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0x0f0f0505, 0x0f0f0505,
+ 0x0f0f0505, 0x0f0f0505, 0x0f0f0505, 0x0f0f0505, 0x0f0f0505, 0x0f0f0505, 0x0f0f0505, 0x0f0f0505,
+ 0x0f0f0505, 0xf0f0fafb, 0xf0f0fafb, 0xf0f0fafb, 0xf0f0fafb, 0xf0f0fafb, 0xf0f0fafb, 0xf0f0fafb,
+ 0xf0f0fafb, 0xf0f0fafb, 0xf0f0fafb, 0xf0f0fafb, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x0c0c0c0c,
+ 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa, 0x06060c0c, 0xf9f9f3f4, 0x0c0bf3f4, 0xf3f40c0c, 0x1211f9fa,
+ 0xedee0606, 0xf9fa1212, 0x0605edee, 0x18180c0c, 0xe7e7f3f4, 0x0c0c1818, 0xf3f3e7e8, 0x18181818,
+ 0xe7e7e7e8, 0x1e1e0000, 0xe1e20000, 0x00001e1e, 0xffffe1e2, 0x1817edee, 0xe7e81212, 0xedee1818,
+ 0x1211e7e8, 0x30301e1e, 0xcfcfe1e2, 0x1e1e3030, 0xe1e1cfd0, 0x2423f9fa, 0xdbdc0606, 0xf9fa2424,
+ 0x0605dbdc, 0x30300c0c, 0xcfcff3f4, 0x0c0c3030, 0xf3f3cfd0, 0x30303030, 0xcfcfcfd0, 0x36360000,
+ 0xc9ca0000, 0x00003636, 0xffffc9ca, 0x2423dbdc, 0xdbdc2424, 0x302fe7e8, 0xcfd01818, 0xe7e83030,
+ 0x1817cfd0, 0x4e4e1e1e, 0xb1b1e1e2, 0x1e1e4e4e, 0xe1e1b1b2, 0x54543636, 0xababc9ca, 0x36365454,
+ 0xc9c9abac, 0x4241edee, 0xbdbe1212, 0xedee4242, 0x1211bdbe, 0x54540c0c, 0xababf3f4, 0x0c0c5454,
+ 0xf3f3abac, 0x5a5a5a5a, 0xa5a5a5a6, 0x605ff9fa, 0x9fa00606, 0xf9fa6060, 0x06059fa0, 0x4241c9ca,
+ 0xbdbe3636, 0xc9ca4242, 0x3635bdbe, 0x5a59d5d6, 0xa5a62a2a, 0xd5d65a5a, 0x2a29a5a6, 0x7e7de1e2,
+ 0x81821e1e, 0xe1e27e7e, 0x1e1d8182, 0x6665999a, 0x999a6666, 0x7e7dabac, 0x81825454, 0xabac7e7e,
+ 0x54538182, 0x24242424, 0xdbdbdbdc, 0x42424242, 0xbdbdbdbe, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0x06060000,
+ 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000,
+ 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000,
+ 0xf9fa0000, 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0x00000606,
+ 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa,
+ 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa,
+ 0xfffff9fa, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0x0c0c0606, 0x0c0c0606, 0x0c0c0606, 0x0c0c0606, 0x0c0c0606, 0x0c0c0606, 0x0c0c0606,
+ 0x0c0c0606, 0x0c0c0606, 0x0c0c0606, 0x0c0c0606, 0x0c0c0606, 0xf3f3f9fa, 0xf3f3f9fa, 0xf3f3f9fa,
+ 0xf3f3f9fa, 0xf3f3f9fa, 0xf3f3f9fa, 0xf3f3f9fa, 0xf3f3f9fa, 0xf3f3f9fa, 0xf3f3f9fa, 0xf3f3f9fa,
+ 0xf3f3f9fa, 0x06060c0c, 0x06060c0c, 0x06060c0c, 0x06060c0c, 0x06060c0c, 0x06060c0c, 0x06060c0c,
+ 0x06060c0c, 0x06060c0c, 0x06060c0c, 0x06060c0c, 0x06060c0c, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x07070707, 0xf8f8f8f9, 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9, 0x0e0e0e0e,
+ 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9, 0x07071515, 0xf8f8eaeb, 0x0e0df1f2, 0xf1f20e0e, 0x1514f8f9,
+ 0xeaeb0707, 0xf8f91515, 0x0706eaeb, 0x1c1c0e0e, 0xe3e3f1f2, 0x0e0e1c1c, 0xf1f1e3e4, 0x1c1c1c1c,
+ 0xe3e3e3e4, 0x23230000, 0xdcdd0000, 0x00002323, 0xffffdcdd, 0x1c1beaeb, 0xe3e41515, 0xeaeb1c1c,
+ 0x1514e3e4, 0x38382323, 0xc7c7dcdd, 0x23233838, 0xdcdcc7c8, 0x2a29f1f2, 0xd5d60e0e, 0xf1f22a2a,
+ 0x0e0dd5d6, 0x38380e0e, 0xc7c7f1f2, 0x0e0e3838, 0xf1f1c7c8, 0x38383838, 0xc7c7c7c8, 0x3f3f0000,
+ 0xc0c10000, 0x00003f3f, 0xffffc0c1, 0x2a29d5d6, 0xd5d62a2a, 0x3837e3e4, 0xc7c81c1c, 0xe3e43838,
+ 0x1c1bc7c8, 0x5b5b2323, 0xa4a4dcdd, 0x23235b5b, 0xdcdca4a5, 0x62623f3f, 0x9d9dc0c1, 0x3f3f6262,
+ 0xc0c09d9e, 0x4d4ceaeb, 0xb2b31515, 0xeaeb4d4d, 0x1514b2b3, 0x62620e0e, 0x9d9df1f2, 0x0e0e6262,
+ 0xf1f19d9e, 0x69696969, 0x96969697, 0x7776f8f9, 0x88890707, 0xf8f97777, 0x07068889, 0x4d4cc0c1,
+ 0xb2b33f3f, 0xc0c14d4d, 0x3f3eb2b3, 0x6968cecf, 0x96973131, 0xcecf6969, 0x31309697, 0x77768889,
+ 0x88897777, 0x2a2a2a2a, 0xd5d5d5d6, 0x4d4d4d4d, 0xb2b2b2b3, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707,
+ 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0x07070707, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9,
+ 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9, 0xf8f8f8f9,
+ 0xf8f8f8f9, 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0x07070000,
+ 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0xf8f90000, 0xf8f90000, 0xf8f90000,
+ 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000,
+ 0xf8f90000, 0x00000707, 0x00000707, 0x00000707, 0x00000707, 0x00000707, 0x00000707, 0x00000707,
+ 0x00000707, 0x00000707, 0x00000707, 0x00000707, 0x00000707, 0xfffff8f9, 0xfffff8f9, 0xfffff8f9,
+ 0xfffff8f9, 0xfffff8f9, 0xfffff8f9, 0xfffff8f9, 0xfffff8f9, 0xfffff8f9, 0xfffff8f9, 0xfffff8f9,
+ 0xfffff8f9, 0x0e0e0e0e, 0x0e0e0e0e, 0x0e0e0e0e, 0x0e0e0e0e, 0x0e0e0e0e, 0x0e0e0e0e, 0x0e0e0e0e,
+ 0x0e0e0e0e, 0x0e0e0e0e, 0x0e0e0e0e, 0x0e0e0e0e, 0x0e0e0e0e, 0xf1f1f1f2, 0xf1f1f1f2, 0xf1f1f1f2,
+ 0xf1f1f1f2, 0xf1f1f1f2, 0xf1f1f1f2, 0xf1f1f1f2, 0xf1f1f1f2, 0xf1f1f1f2, 0xf1f1f1f2, 0xf1f1f1f2,
+ 0xf1f1f1f2, 0x15150707, 0x15150707, 0x15150707, 0x15150707, 0x15150707, 0x15150707, 0x15150707,
+ 0x15150707, 0x15150707, 0x15150707, 0x15150707, 0x15150707, 0xeaeaf8f9, 0xeaeaf8f9, 0xeaeaf8f9,
+ 0xeaeaf8f9, 0xeaeaf8f9, 0xeaeaf8f9, 0xeaeaf8f9, 0xeaeaf8f9, 0xeaeaf8f9, 0xeaeaf8f9, 0xeaeaf8f9,
+ 0xeaeaf8f9, 0x07071515, 0x07071515, 0x07071515, 0x07071515, 0x07071515, 0x07071515, 0x07071515,
+ 0x07071515, 0x07071515, 0x07071515, 0x07071515, 0x07071515, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000, 0x00000808, 0xfffff7f8, 0x10101010,
+ 0xefefeff0, 0x10100808, 0xefeff7f8, 0x08081010, 0xf7f7eff0, 0x100feff0, 0xeff01010, 0x1817f7f8,
+ 0xe7e80808, 0xf7f81818, 0x0807e7e8, 0x20201010, 0xdfdfeff0, 0x10102020, 0xefefdfe0, 0x20202020,
+ 0xdfdfdfe0, 0x28280000, 0xd7d80000, 0x00002828, 0xffffd7d8, 0x201fe7e8, 0xdfe01818, 0xe7e82020,
+ 0x1817dfe0, 0x40402828, 0xbfbfd7d8, 0x28284040, 0xd7d7bfc0, 0x302feff0, 0xcfd01010, 0xeff03030,
+ 0x100fcfd0, 0x40401010, 0xbfbfeff0, 0x10104040, 0xefefbfc0, 0x40404040, 0xbfbfbfc0, 0x48480000,
+ 0xb7b80000, 0x00004848, 0xffffb7b8, 0x302fcfd0, 0xcfd03030, 0x403fdfe0, 0xbfc02020, 0xdfe04040,
+ 0x201fbfc0, 0x68682828, 0x9797d7d8, 0x28286868, 0xd7d79798, 0x70704848, 0x8f8fb7b8, 0x48487070,
+ 0xb7b78f90, 0x5857e7e8, 0xa7a81818, 0xe7e85858, 0x1817a7a8, 0x70701010, 0x8f8feff0, 0x10107070,
+ 0xefef8f90, 0x78787878, 0x87878788, 0x5857b7b8, 0xa7a84848, 0xb7b85858, 0x4847a7a8, 0x7877c7c8,
+ 0x87883838, 0xc7c87878, 0x38378788, 0x30303030, 0xcfcfcfd0, 0x58585858, 0xa7a7a7a8, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0x08080808,
+ 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0x08080808, 0xf7f7f7f8,
+ 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8,
+ 0xf7f7f7f8, 0xf7f7f7f8, 0xf7f7f7f8, 0x08080000, 0x08080000, 0x08080000, 0x08080000, 0x08080000,
+ 0x08080000, 0x08080000, 0x08080000, 0x08080000, 0x08080000, 0x08080000, 0x08080000, 0xf7f80000,
+ 0xf7f80000, 0xf7f80000, 0xf7f80000, 0xf7f80000, 0xf7f80000, 0xf7f80000, 0xf7f80000, 0xf7f80000,
+ 0xf7f80000, 0xf7f80000, 0xf7f80000, 0x00000808, 0x00000808, 0x00000808, 0x00000808, 0x00000808,
+ 0x00000808, 0x00000808, 0x00000808, 0x00000808, 0x00000808, 0x00000808, 0x00000808, 0xfffff7f8,
+ 0xfffff7f8, 0xfffff7f8, 0xfffff7f8, 0xfffff7f8, 0xfffff7f8, 0xfffff7f8, 0xfffff7f8, 0xfffff7f8,
+ 0xfffff7f8, 0xfffff7f8, 0xfffff7f8, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0x10101010, 0xefefeff0,
+ 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0, 0xefefeff0,
+ 0xefefeff0, 0xefefeff0, 0xefefeff0, 0x10100808, 0x10100808, 0x10100808, 0x10100808, 0x10100808,
+ 0x10100808, 0x10100808, 0x10100808, 0x10100808, 0x10100808, 0x10100808, 0x10100808, 0xefeff7f8,
+ 0xefeff7f8, 0xefeff7f8, 0xefeff7f8, 0xefeff7f8, 0xefeff7f8, 0xefeff7f8, 0xefeff7f8, 0xefeff7f8,
+ 0xefeff7f8, 0xefeff7f8, 0xefeff7f8, 0x08081010, 0x08081010, 0x08081010, 0x08081010, 0x08081010,
+ 0x08081010, 0x08081010, 0x08081010, 0x08081010, 0x08081010, 0x08081010, 0x08081010, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212,
+ 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x1211edee, 0xedee1212, 0x1b1af6f7,
+ 0xe4e50909, 0xf6f71b1b, 0x0908e4e5, 0x24241212, 0xdbdbedee, 0x12122424, 0xededdbdc, 0x24242424,
+ 0xdbdbdbdc, 0x2d2d0000, 0xd2d30000, 0x00002d2d, 0xffffd2d3, 0x2423e4e5, 0xdbdc1b1b, 0xe4e52424,
+ 0x1b1adbdc, 0x48482d2d, 0xb7b7d2d3, 0x2d2d4848, 0xd2d2b7b8, 0x3635edee, 0xc9ca1212, 0xedee3636,
+ 0x1211c9ca, 0x48481212, 0xb7b7edee, 0x12124848, 0xededb7b8, 0x48484848, 0xb7b7b7b8, 0x51510000,
+ 0xaeaf0000, 0x00005151, 0xffffaeaf, 0x3635c9ca, 0xc9ca3636, 0x4847dbdc, 0xb7b82424, 0xdbdc4848,
+ 0x2423b7b8, 0x75752d2d, 0x8a8ad2d3, 0x2d2d7575, 0xd2d28a8b, 0x7e7e5151, 0x8181aeaf, 0x51517e7e,
+ 0xaeae8182, 0x6362e4e5, 0x9c9d1b1b, 0xe4e56363, 0x1b1a9c9d, 0x6362aeaf, 0x9c9d5151, 0xaeaf6363,
+ 0x51509c9d, 0x36363636, 0xc9c9c9ca, 0x6c6c6c6c, 0x93939394, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909,
+ 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0xf6f6f6f7,
+ 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7,
+ 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0xf6f6f6f7, 0x09090000, 0x09090000, 0x09090000, 0x09090000,
+ 0x09090000, 0x09090000, 0x09090000, 0x09090000, 0x09090000, 0x09090000, 0x09090000, 0x09090000,
+ 0x09090000, 0xf6f70000, 0xf6f70000, 0xf6f70000, 0xf6f70000, 0xf6f70000, 0xf6f70000, 0xf6f70000,
+ 0xf6f70000, 0xf6f70000, 0xf6f70000, 0xf6f70000, 0xf6f70000, 0xf6f70000, 0x00000909, 0x00000909,
+ 0x00000909, 0x00000909, 0x00000909, 0x00000909, 0x00000909, 0x00000909, 0x00000909, 0x00000909,
+ 0x00000909, 0x00000909, 0x00000909, 0xfffff6f7, 0xfffff6f7, 0xfffff6f7, 0xfffff6f7, 0xfffff6f7,
+ 0xfffff6f7, 0xfffff6f7, 0xfffff6f7, 0xfffff6f7, 0xfffff6f7, 0xfffff6f7, 0xfffff6f7, 0xfffff6f7,
+ 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212,
+ 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0xedededee, 0xedededee, 0xedededee,
+ 0xedededee, 0xedededee, 0xedededee, 0xedededee, 0xedededee, 0xedededee, 0xedededee, 0xedededee,
+ 0xedededee, 0xedededee, 0x1b1b0909, 0x1b1b0909, 0x1b1b0909, 0x1b1b0909, 0x1b1b0909, 0x1b1b0909,
+ 0x1b1b0909, 0x1b1b0909, 0x1b1b0909, 0x1b1b0909, 0x1b1b0909, 0x1b1b0909, 0x1b1b0909, 0xe4e4f6f7,
+ 0xe4e4f6f7, 0xe4e4f6f7, 0xe4e4f6f7, 0xe4e4f6f7, 0xe4e4f6f7, 0xe4e4f6f7, 0xe4e4f6f7, 0xe4e4f6f7,
+ 0xe4e4f6f7, 0xe4e4f6f7, 0xe4e4f6f7, 0xe4e4f6f7, 0x09091b1b, 0x09091b1b, 0x09091b1b, 0x09091b1b,
+ 0x09091b1b, 0x09091b1b, 0x09091b1b, 0x09091b1b, 0x09091b1b, 0x09091b1b, 0x09091b1b, 0x09091b1b,
+ 0x09091b1b, 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5,
+ 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5, 0xf6f6e4e5, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606,
+ 0xf9f9f9fa, 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9, 0x0504fafb, 0xfafb0505, 0xfafb0505,
+ 0x0504fafb, 0x0b0b0606, 0xf4f4f9fa, 0x06060b0b, 0xf9f9f4f5, 0x08080000, 0xf7f80000, 0x00000808,
+ 0xfffff7f8, 0x0b0b0b0b, 0xf4f4f4f5, 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x11110c0c,
+ 0xeeeef3f4, 0x0c0c1111, 0xf3f3eeef, 0x11111111, 0xeeeeeeef, 0x12120606, 0xededf9fa, 0x06061212,
+ 0xf9f9edee, 0x0b0af7f8, 0xf4f50808, 0xf7f80b0b, 0x0807f4f5, 0x0f0f0000, 0xf0f10000, 0x00000f0f,
+ 0xfffff0f1, 0x14140000, 0xebec0000, 0x00001414, 0xffffebec, 0x19191212, 0xe6e6edee, 0x12121919,
+ 0xedede6e7, 0x19190b0b, 0xe6e6f4f5, 0x0b0b1919, 0xf4f4e6e7, 0x19191919, 0xe6e6e6e7, 0x0e0df1f2,
+ 0xf1f20e0e, 0xf1f20e0e, 0x0e0df1f2, 0x1a1a0000, 0xe5e60000, 0x00001a1a, 0xffffe5e6, 0x1211f4f5,
+ 0xedee0b0b, 0xf4f51212, 0x0b0aedee, 0x1615f8f9, 0xe9ea0707, 0xf8f91616, 0x0706e9ea, 0x22221a1a,
+ 0xdddde5e6, 0x1a1a2222, 0xe5e5ddde, 0x22221212, 0xddddedee, 0x12122222, 0xededddde, 0x22222222,
+ 0xddddddde, 0x23230b0b, 0xdcdcf4f5, 0x0b0b2323, 0xf4f4dcdd, 0x1d1d0000, 0xe2e30000, 0x00001d1d,
+ 0xffffe2e3, 0x1615eced, 0xe9ea1313, 0xeced1616, 0x1312e9ea, 0x1a19f0f1, 0xe5e60f0f, 0xf0f11a1a,
+ 0x0f0ee5e6, 0x25250000, 0xdadb0000, 0x00002525, 0xffffdadb, 0x2c2c1b1b, 0xd3d3e4e5, 0x1b1b2c2c,
+ 0xe4e4d3d4, 0x2c2c2424, 0xd3d3dbdc, 0x24242c2c, 0xdbdbd3d4, 0x2c2c1212, 0xd3d3edee, 0x12122c2c,
+ 0xededd3d4, 0x2120f5f6, 0xdedf0a0a, 0xf5f62121, 0x0a09dedf, 0x2d2d2d2d, 0xd2d2d2d3, 0x00000000,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606,
+ 0xf9f9f9fa, 0x07070000, 0xf8f90000, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x03030000, 0xfcfd0000,
+ 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x07070000, 0xf8f90000, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x07070000,
+ 0xf8f90000, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd,
+ 0x06060606, 0xf9f9f9fa, 0x07070000, 0xf8f90000, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x03030000,
+ 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x07070000, 0xf8f90000, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa,
+ 0x07070000, 0xf8f90000, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x03030000, 0xfcfd0000, 0x00000303,
+ 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x07070000, 0xf8f90000, 0x00000000, 0x02020202, 0xfdfdfdfe,
+ 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x07070000, 0xf8f90000,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606,
+ 0xf9f9f9fa, 0x07070000, 0xf8f90000, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x03030000, 0xfcfd0000,
+ 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x07070000, 0xf8f90000, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x07070000,
+ 0xf8f90000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x0403fbfc, 0xfbfc0404, 0xf9fa0a0a,
+ 0x0605f5f6, 0xf3f40000, 0x0c0c0000, 0xf3f3f9fa, 0xf3f40606, 0x0c0bf9fa, 0x0c0c0606, 0xfffff1f2,
+ 0x00000e0e, 0x0c0c0c0c, 0xf3f3f3f4, 0xedee0000, 0x12120000, 0xf3f40e0e, 0x0c0bf1f2, 0xf9f9edee,
+ 0xf9fa1212, 0x0605edee, 0x06061212, 0xededf5f6, 0xedee0a0a, 0x1211f5f6, 0x12120a0a, 0xffffe9ea,
+ 0x00001616, 0xe7e80000, 0x18180000, 0xf3f3e9ea, 0xf3f41616, 0x0c0be9ea, 0x0c0c1616, 0xe7e7f7f8,
+ 0xe7e80808, 0x1817f7f8, 0x18180808, 0xf9f9e5e6, 0xf9fa1a1a, 0x0605e5e6, 0x06061a1a, 0xffffe3e4,
+ 0x00001c1c, 0x14141414, 0xebebebec, 0xe5e5f1f2, 0x1a1a0e0e, 0xf3f3e1e2, 0x0c0c1e1e, 0xdfdff5f6,
+ 0x20200a0a, 0xdfdfedee, 0x20201212, 0xe5e5e5e6, 0x1a1a1a1a, 0xebebddde, 0x14142222, 0xf3f3d9da,
+ 0x0c0c2626, 0xdfdfdfe0, 0x20202020, 0x20202020, 0xd7d7e9ea, 0xddddddde, 0x22222222, 0x00000000,
+ 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202,
+ 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606,
+ 0xfffff9fa, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe,
+ 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x00000000, 0x02020000,
+ 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x06060000,
+ 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa,
+ 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x00000000, 0x02020000, 0xfdfe0000,
+ 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000,
+ 0x00000606, 0xfffff9fa, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x00000000,
+ 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202,
+ 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606,
+ 0xfffff9fa, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe,
+ 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x00000000, 0x02020000,
+ 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x06060000,
+ 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a,
+ 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x0605f9fa, 0xf9fa0606, 0xf7f80e0e,
+ 0x0807f1f2, 0xffffedee, 0x00001212, 0xeff00a0a, 0x100ff5f6, 0xe7e80000, 0x18180000, 0xf7f7e7e8,
+ 0xf7f81818, 0x0807e7e8, 0x08081818, 0x12121212, 0xedededee, 0xeff01414, 0x100febec, 0xe5e5f1f2,
+ 0xe5e60e0e, 0x1a19f1f2, 0x1a1a0e0e, 0xffffe1e2, 0x00001e1e, 0xddde0000, 0x22220000, 0xf7f7ddde,
+ 0xf7f82222, 0x0807ddde, 0x08082222, 0xedede1e2, 0xedee1e1e, 0x1211e1e2, 0x12121e1e, 0xddddf5f6,
+ 0xddde0a0a, 0x2221f5f6, 0x22220a0a, 0xddddebec, 0x22221414, 0xffffd7d8, 0x00002828, 0x1e1e1e1e,
+ 0xe1e1e1e2, 0xededd7d8, 0x12122828, 0xd3d40000, 0x2c2c0000, 0xd3d3eff0, 0x2c2c1010, 0xdbdbdbdc,
+ 0xdbdbdbdc, 0x24242424, 0xd3d3e5e6, 0x2c2c1a1a, 0xe5e5d1d2, 0x1a1a2e2e, 0xededcbcc, 0x12123434,
+ 0xc9c9ebec, 0xd3d3d3d4, 0x2c2c2c2c, 0xc9c9dfe0, 0xd1d1d1d2, 0xd1d1d1d2, 0x2e2e2e2e, 0x00000000,
+ 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6,
+ 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202,
+ 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a,
+ 0xfffff5f6, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc,
+ 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x00000000, 0x02020000,
+ 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000,
+ 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe,
+ 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6,
+ 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a,
+ 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x00000000, 0x02020000, 0xfdfe0000,
+ 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000,
+ 0x00000a0a, 0xfffff5f6, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404,
+ 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x00000000,
+ 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6,
+ 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202,
+ 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a,
+ 0xfffff5f6, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc,
+ 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x00000000, 0x02020000,
+ 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000,
+ 0xf5f60000, 0x00000a0a, 0xfffff5f6, 0x00000000, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe,
+ 0x04040404, 0xfbfbfbfc, 0x0a0a0a0a, 0xf5f5f5f6, 0x0a0a0000, 0xf5f60000, 0x00000a0a, 0xfffff5f6,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c,
+ 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x0807f7f8, 0xf7f80808, 0xeff00808,
+ 0x100ff7f8, 0xe7e80000, 0x18180000, 0xf7f7e7e8, 0xf7f81818, 0x0807e7e8, 0x08081818, 0xeff01414,
+ 0x100febec, 0xffffe3e4, 0x00001c1c, 0xe7e7eff0, 0xe7e81010, 0x1817eff0, 0x18181010, 0xdfe00000,
+ 0x20200000, 0xefefe3e4, 0xeff01c1c, 0x100fe3e4, 0x10101c1c, 0xdfdff7f8, 0xdfe00808, 0xf7f7dfe0,
+ 0xf7f82020, 0x0807dfe0, 0x08082020, 0x201ff7f8, 0x20200808, 0x18181818, 0xe7e7e7e8, 0xe7e81818,
+ 0x1817e7e8, 0xdfdfebec, 0x20201414, 0xffffd7d8, 0x00002828, 0xefefd7d8, 0x10102828, 0xd3d40000,
+ 0xd3d40000, 0xffffd3d4, 0x00002c2c, 0x2c2c0000, 0x2c2c0000, 0xdfdfdfe0, 0x20202020, 0xd3d3eff0,
+ 0x2c2c1010, 0xd3d3e7e8, 0xe7e7d3d4, 0x18182c2c, 0x2c2c1818, 0xefefcfd0, 0x10103030, 0xdbdbdbdc,
+ 0xdbdbdbdc, 0x24242424, 0x24242424, 0xcbcbebec, 0x28282828, 0xd7d7d7d8, 0xcbcbdfe0, 0x00000000,
+ 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404,
+ 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c,
+ 0xfffff3f4, 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x00000000, 0x04040000,
+ 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000,
+ 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc,
+ 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4,
+ 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c,
+ 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x00000000, 0x04040000, 0xfbfc0000,
+ 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000,
+ 0x00000c0c, 0xfffff3f4, 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404,
+ 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x00000000,
+ 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404,
+ 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c,
+ 0xfffff3f4, 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x00000000, 0x04040000,
+ 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000,
+ 0xf3f40000, 0x00000c0c, 0xfffff3f4, 0x00000000, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc,
+ 0x04040404, 0xfbfbfbfc, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0000, 0xf3f40000, 0x00000c0c, 0xfffff3f4,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414,
+ 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec,
+ 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e,
+ 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020,
+ 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414,
+ 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe,
+ 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0,
+ 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c,
+ 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec,
+ 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e,
+ 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020,
+ 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414,
+ 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec,
+ 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e,
+ 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020,
+ 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414,
+ 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe,
+ 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0,
+ 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c,
+ 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec,
+ 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e,
+ 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020,
+ 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414,
+ 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec,
+ 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e,
+ 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020,
+ 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414,
+ 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe,
+ 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0,
+ 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c,
+ 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec,
+ 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e,
+ 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020,
+ 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414,
+ 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec,
+ 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e,
+ 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020,
+ 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414,
+ 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe,
+ 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0,
+ 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c,
+ 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec,
+ 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606,
+ 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e,
+ 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020,
+ 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x06060606, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x14141414, 0xebebebec, 0x20202020, 0xdfdfdfe0, 0x2e2e2e2e, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
+
+
+static const uint32_t correctionhighorder[] = {
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x0302feff, 0xfcfd0101,
+ 0xfeff0303, 0x0100fcfd, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x0302feff, 0xfcfd0101, 0xfeff0303,
+ 0x0100fcfd, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x0302feff, 0xfcfd0101, 0xfeff0303, 0x0100fcfd,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x0302feff, 0xfcfd0101, 0xfeff0303, 0x0100fcfd, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x0302feff, 0xfcfd0101, 0xfeff0303, 0x0100fcfd, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x0302feff, 0xfcfd0101, 0xfeff0303, 0x0100fcfd, 0x00000000, 0x02020202, 0xfdfdfdfe,
+ 0x0302feff, 0xfcfd0101, 0xfeff0303, 0x0100fcfd, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x03030303, 0xfcfcfcfd, 0x0403feff, 0xfbfc0101, 0xfeff0404, 0x0100fbfc, 0x07070707, 0xf8f8f8f9,
+ 0x00000000, 0x03030303, 0xfcfcfcfd, 0x0403feff, 0xfbfc0101, 0xfeff0404, 0x0100fbfc, 0x07070707,
+ 0xf8f8f8f9, 0x00000000, 0x03030303, 0xfcfcfcfd, 0x0403feff, 0xfbfc0101, 0xfeff0404, 0x0100fbfc,
+ 0x07070707, 0xf8f8f8f9, 0x00000000, 0x03030303, 0xfcfcfcfd, 0x0403feff, 0xfbfc0101, 0xfeff0404,
+ 0x0100fbfc, 0x07070707, 0xf8f8f8f9, 0x00000000, 0x03030303, 0xfcfcfcfd, 0x0403feff, 0xfbfc0101,
+ 0xfeff0404, 0x0100fbfc, 0x07070707, 0xf8f8f8f9, 0x00000000, 0x03030303, 0xfcfcfcfd, 0x0403feff,
+ 0xfbfc0101, 0xfeff0404, 0x0100fbfc, 0x07070707, 0xf8f8f8f9, 0x00000000, 0x03030303, 0xfcfcfcfd,
+ 0x0403feff, 0xfbfc0101, 0xfeff0404, 0x0100fbfc, 0x07070707, 0xf8f8f8f9, 0x00000000, 0x03030303,
+ 0xfcfcfcfd, 0x0403feff, 0xfbfc0101, 0xfeff0404, 0x0100fbfc, 0x07070707, 0xf8f8f8f9, 0x00000000,
+ 0x03030303, 0xfcfcfcfd, 0x0403feff, 0xfbfc0101, 0xfeff0404, 0x0100fbfc, 0x07070707, 0xf8f8f8f9,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x04040404, 0xfbfbfbfc,
+ 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb, 0x0a0a0303, 0xf5f5fcfd, 0x03030a0a, 0x00000000,
+ 0x04040404, 0xfbfbfbfc, 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb, 0x0a0a0303, 0xf5f5fcfd,
+ 0x03030a0a, 0x00000000, 0x04040404, 0xfbfbfbfc, 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb,
+ 0x0a0a0303, 0xf5f5fcfd, 0x03030a0a, 0x00000000, 0x04040404, 0xfbfbfbfc, 0x0504feff, 0xfafb0101,
+ 0xfeff0505, 0x0100fafb, 0x0a0a0303, 0xf5f5fcfd, 0x03030a0a, 0x00000000, 0x04040404, 0xfbfbfbfc,
+ 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb, 0x0a0a0303, 0xf5f5fcfd, 0x03030a0a, 0x00000000,
+ 0x04040404, 0xfbfbfbfc, 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb, 0x0a0a0303, 0xf5f5fcfd,
+ 0x03030a0a, 0x00000000, 0x04040404, 0xfbfbfbfc, 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb,
+ 0x0a0a0303, 0xf5f5fcfd, 0x03030a0a, 0x00000000, 0x04040404, 0xfbfbfbfc, 0x0504feff, 0xfafb0101,
+ 0xfeff0505, 0x0100fafb, 0x0a0a0303, 0xf5f5fcfd, 0x03030a0a, 0x00000000, 0x04040404, 0xfbfbfbfc,
+ 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb, 0x0a0a0303, 0xf5f5fcfd, 0x03030a0a, 0x00000000,
+ 0x04040404, 0xfbfbfbfc, 0x0504feff, 0xfafb0101, 0xfeff0505, 0x0100fafb, 0x0a0a0303, 0xf5f5fcfd,
+ 0x03030a0a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x05050505, 0xfafafafb, 0x0706fdfe, 0xf8f90202,
+ 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd, 0x00000000, 0x05050505,
+ 0xfafafafb, 0x0706fdfe, 0xf8f90202, 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303,
+ 0xf2f2fcfd, 0x00000000, 0x05050505, 0xfafafafb, 0x0706fdfe, 0xf8f90202, 0xfdfe0707, 0x0201f8f9,
+ 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd, 0x00000000, 0x05050505, 0xfafafafb, 0x0706fdfe,
+ 0xf8f90202, 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd, 0x00000000,
+ 0x05050505, 0xfafafafb, 0x0706fdfe, 0xf8f90202, 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b, 0xf4f4f4f5,
+ 0x0d0d0303, 0xf2f2fcfd, 0x00000000, 0x05050505, 0xfafafafb, 0x0706fdfe, 0xf8f90202, 0xfdfe0707,
+ 0x0201f8f9, 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd, 0x00000000, 0x05050505, 0xfafafafb,
+ 0x0706fdfe, 0xf8f90202, 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd,
+ 0x00000000, 0x05050505, 0xfafafafb, 0x0706fdfe, 0xf8f90202, 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b,
+ 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd, 0x00000000, 0x05050505, 0xfafafafb, 0x0706fdfe, 0xf8f90202,
+ 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd, 0x00000000, 0x05050505,
+ 0xfafafafb, 0x0706fdfe, 0xf8f90202, 0xfdfe0707, 0x0201f8f9, 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303,
+ 0xf2f2fcfd, 0x00000000, 0x05050505, 0xfafafafb, 0x0706fdfe, 0xf8f90202, 0xfdfe0707, 0x0201f8f9,
+ 0x0b0b0b0b, 0xf4f4f4f5, 0x0d0d0303, 0xf2f2fcfd, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8, 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc,
+ 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8,
+ 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc, 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8, 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc,
+ 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8,
+ 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc, 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8, 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc,
+ 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8,
+ 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc, 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8, 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc,
+ 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8,
+ 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc, 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8, 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc,
+ 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8,
+ 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc, 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8, 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc,
+ 0x04040f0f, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x0807fdfe, 0xf7f80202, 0xfdfe0808, 0x0201f7f8,
+ 0x0d0d0d0d, 0xf2f2f2f3, 0x0f0f0404, 0xf0f0fbfc, 0x04040f0f, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6, 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb,
+ 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6,
+ 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb, 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6, 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb,
+ 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6,
+ 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb, 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6, 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb,
+ 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6,
+ 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb, 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6, 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb,
+ 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6,
+ 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb, 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6, 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb,
+ 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6,
+ 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb, 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6, 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb,
+ 0x05051212, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x0a09fcfd, 0xf5f60303, 0xfcfd0a0a, 0x0302f5f6,
+ 0x10101010, 0xefefeff0, 0x12120505, 0xededfafb, 0x05051212, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303, 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee,
+ 0x14140505, 0xebebfafb, 0x05051414, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303,
+ 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee, 0x14140505, 0xebebfafb, 0x05051414, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303, 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee,
+ 0x14140505, 0xebebfafb, 0x05051414, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303,
+ 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee, 0x14140505, 0xebebfafb, 0x05051414, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303, 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee,
+ 0x14140505, 0xebebfafb, 0x05051414, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303,
+ 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee, 0x14140505, 0xebebfafb, 0x05051414, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303, 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee,
+ 0x14140505, 0xebebfafb, 0x05051414, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303,
+ 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee, 0x14140505, 0xebebfafb, 0x05051414, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303, 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee,
+ 0x14140505, 0xebebfafb, 0x05051414, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303,
+ 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee, 0x14140505, 0xebebfafb, 0x05051414, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303, 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee,
+ 0x14140505, 0xebebfafb, 0x05051414, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x0b0afcfd, 0xf4f50303,
+ 0xfcfd0b0b, 0x0302f4f5, 0x12121212, 0xedededee, 0x14140505, 0xebebfafb, 0x05051414, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x09090909, 0xf6f6f6f7,
+ 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa,
+ 0x06061717, 0xf9f9e8e9, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c,
+ 0x0302f3f4, 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x00000000,
+ 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414, 0xebebebec,
+ 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd,
+ 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717,
+ 0xf9f9e8e9, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4,
+ 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x00000000, 0x09090909,
+ 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414, 0xebebebec, 0x17170606,
+ 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303,
+ 0xfcfd0c0c, 0x0302f3f4, 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9,
+ 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414,
+ 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x00000000, 0x09090909, 0xf6f6f6f7,
+ 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa,
+ 0x06061717, 0xf9f9e8e9, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c,
+ 0x0302f3f4, 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x00000000,
+ 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414, 0xebebebec,
+ 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd,
+ 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4, 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717,
+ 0xf9f9e8e9, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x0c0bfcfd, 0xf3f40303, 0xfcfd0c0c, 0x0302f3f4,
+ 0x14141414, 0xebebebec, 0x17170606, 0xe8e8f9fa, 0x06061717, 0xf9f9e8e9, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x02020000, 0xfdfe0000,
+ 0x00000202, 0xfffffdfe, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x02020000, 0xfdfe0000, 0x00000202,
+ 0xfffffdfe, 0x00000000, 0x02020202, 0xfdfdfdfe, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe,
+ 0x00000000, 0x02020202, 0xfdfdfdfe, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x00000000,
+ 0x02020202, 0xfdfdfdfe, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x00000000, 0x02020202,
+ 0xfdfdfdfe, 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x00000000, 0x02020202, 0xfdfdfdfe,
+ 0x02020000, 0xfdfe0000, 0x00000202, 0xfffffdfe, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x03030303, 0xfcfcfcfd, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa,
+ 0x00000000, 0x03030303, 0xfcfcfcfd, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606,
+ 0xf9f9f9fa, 0x00000000, 0x03030303, 0xfcfcfcfd, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd,
+ 0x06060606, 0xf9f9f9fa, 0x00000000, 0x03030303, 0xfcfcfcfd, 0x03030000, 0xfcfd0000, 0x00000303,
+ 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x00000000, 0x03030303, 0xfcfcfcfd, 0x03030000, 0xfcfd0000,
+ 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x00000000, 0x03030303, 0xfcfcfcfd, 0x03030000,
+ 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x00000000, 0x03030303, 0xfcfcfcfd,
+ 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x00000000, 0x03030303,
+ 0xfcfcfcfd, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa, 0x00000000,
+ 0x03030303, 0xfcfcfcfd, 0x03030000, 0xfcfd0000, 0x00000303, 0xfffffcfd, 0x06060606, 0xf9f9f9fa,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x04040404, 0xfbfbfbfc,
+ 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x08080404, 0xf7f7fbfc, 0x04040808, 0x00000000,
+ 0x04040404, 0xfbfbfbfc, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x08080404, 0xf7f7fbfc,
+ 0x04040808, 0x00000000, 0x04040404, 0xfbfbfbfc, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc,
+ 0x08080404, 0xf7f7fbfc, 0x04040808, 0x00000000, 0x04040404, 0xfbfbfbfc, 0x04040000, 0xfbfc0000,
+ 0x00000404, 0xfffffbfc, 0x08080404, 0xf7f7fbfc, 0x04040808, 0x00000000, 0x04040404, 0xfbfbfbfc,
+ 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x08080404, 0xf7f7fbfc, 0x04040808, 0x00000000,
+ 0x04040404, 0xfbfbfbfc, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x08080404, 0xf7f7fbfc,
+ 0x04040808, 0x00000000, 0x04040404, 0xfbfbfbfc, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc,
+ 0x08080404, 0xf7f7fbfc, 0x04040808, 0x00000000, 0x04040404, 0xfbfbfbfc, 0x04040000, 0xfbfc0000,
+ 0x00000404, 0xfffffbfc, 0x08080404, 0xf7f7fbfc, 0x04040808, 0x00000000, 0x04040404, 0xfbfbfbfc,
+ 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x08080404, 0xf7f7fbfc, 0x04040808, 0x00000000,
+ 0x04040404, 0xfbfbfbfc, 0x04040000, 0xfbfc0000, 0x00000404, 0xfffffbfc, 0x08080404, 0xf7f7fbfc,
+ 0x04040808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x05050505, 0xfafafafb, 0x05050000, 0xfafb0000,
+ 0x00000505, 0xfffffafb, 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb, 0x00000000, 0x05050505,
+ 0xfafafafb, 0x05050000, 0xfafb0000, 0x00000505, 0xfffffafb, 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505,
+ 0xf0f0fafb, 0x00000000, 0x05050505, 0xfafafafb, 0x05050000, 0xfafb0000, 0x00000505, 0xfffffafb,
+ 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb, 0x00000000, 0x05050505, 0xfafafafb, 0x05050000,
+ 0xfafb0000, 0x00000505, 0xfffffafb, 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb, 0x00000000,
+ 0x05050505, 0xfafafafb, 0x05050000, 0xfafb0000, 0x00000505, 0xfffffafb, 0x0a0a0a0a, 0xf5f5f5f6,
+ 0x0f0f0505, 0xf0f0fafb, 0x00000000, 0x05050505, 0xfafafafb, 0x05050000, 0xfafb0000, 0x00000505,
+ 0xfffffafb, 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb, 0x00000000, 0x05050505, 0xfafafafb,
+ 0x05050000, 0xfafb0000, 0x00000505, 0xfffffafb, 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb,
+ 0x00000000, 0x05050505, 0xfafafafb, 0x05050000, 0xfafb0000, 0x00000505, 0xfffffafb, 0x0a0a0a0a,
+ 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb, 0x00000000, 0x05050505, 0xfafafafb, 0x05050000, 0xfafb0000,
+ 0x00000505, 0xfffffafb, 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb, 0x00000000, 0x05050505,
+ 0xfafafafb, 0x05050000, 0xfafb0000, 0x00000505, 0xfffffafb, 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505,
+ 0xf0f0fafb, 0x00000000, 0x05050505, 0xfafafafb, 0x05050000, 0xfafb0000, 0x00000505, 0xfffffafb,
+ 0x0a0a0a0a, 0xf5f5f5f6, 0x0f0f0505, 0xf0f0fafb, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa,
+ 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa, 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa,
+ 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa, 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa,
+ 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa, 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa,
+ 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa, 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa,
+ 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa, 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa,
+ 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa, 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa,
+ 0x06060c0c, 0x00000000, 0x06060606, 0xf9f9f9fa, 0x06060000, 0xf9fa0000, 0x00000606, 0xfffff9fa,
+ 0x0c0c0c0c, 0xf3f3f3f4, 0x0c0c0606, 0xf3f3f9fa, 0x06060c0c, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9, 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9,
+ 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9,
+ 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9, 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9, 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9,
+ 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9,
+ 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9, 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9, 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9,
+ 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9,
+ 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9, 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9, 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9,
+ 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9,
+ 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9, 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9, 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9,
+ 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9,
+ 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9, 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9,
+ 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9, 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9,
+ 0x07071515, 0x00000000, 0x07070707, 0xf8f8f8f9, 0x07070000, 0xf8f90000, 0x00000707, 0xfffff8f9,
+ 0x0e0e0e0e, 0xf1f1f1f2, 0x15150707, 0xeaeaf8f9, 0x07071515, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000, 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0,
+ 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000,
+ 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0, 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000, 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0,
+ 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000,
+ 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0, 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000, 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0,
+ 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000,
+ 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0, 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000, 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0,
+ 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000,
+ 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0, 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000, 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0,
+ 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000,
+ 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0, 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000,
+ 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000, 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0,
+ 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000, 0x08080808, 0xf7f7f7f8, 0x08080000, 0xf7f80000,
+ 0x00000808, 0xfffff7f8, 0x10101010, 0xefefeff0, 0x10100808, 0xefeff7f8, 0x08081010, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000, 0x09090909, 0xf6f6f6f7,
+ 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7,
+ 0x09091b1b, 0xf6f6e4e5, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909,
+ 0xfffff6f7, 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x00000000,
+ 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212, 0xedededee,
+ 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000,
+ 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b,
+ 0xf6f6e4e5, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7,
+ 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x00000000, 0x09090909,
+ 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212, 0xedededee, 0x1b1b0909,
+ 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000,
+ 0x00000909, 0xfffff6f7, 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5,
+ 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212,
+ 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x00000000, 0x09090909, 0xf6f6f6f7,
+ 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7,
+ 0x09091b1b, 0xf6f6e4e5, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909,
+ 0xfffff6f7, 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x00000000,
+ 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212, 0xedededee,
+ 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000,
+ 0xf6f70000, 0x00000909, 0xfffff6f7, 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b,
+ 0xf6f6e4e5, 0x00000000, 0x09090909, 0xf6f6f6f7, 0x09090000, 0xf6f70000, 0x00000909, 0xfffff6f7,
+ 0x12121212, 0xedededee, 0x1b1b0909, 0xe4e4f6f7, 0x09091b1b, 0xf6f6e4e5, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0xfdfdfdfe, 0x03030000, 0x03030000, 0x03030000, 0x03030000, 0x03030000, 0x03030000, 0x03030000,
+ 0x03030000, 0x03030000, 0x03030000, 0x03030000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000,
+ 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0xfcfd0000, 0x00000303,
+ 0x00000303, 0x00000303, 0x00000303, 0x00000303, 0x00000303, 0x00000303, 0x00000303, 0x00000303,
+ 0x00000303, 0x00000303, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd,
+ 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0xfffffcfd, 0x06060606, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0x07070000,
+ 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0x07070000, 0xf8f90000, 0xf8f90000,
+ 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000, 0xf8f90000,
+ 0xf8f90000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02020000, 0x02020000, 0x02020000, 0x02020000,
+ 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000,
+ 0x02020000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000,
+ 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0x00000202, 0x00000202,
+ 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202,
+ 0x00000202, 0x00000202, 0x00000202, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe,
+ 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe,
+ 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0xfdfdfdfe, 0xfdfdfdfe, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0x06060000, 0x06060000, 0x06060000, 0x06060000,
+ 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0x06060000, 0x06060000,
+ 0x06060000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000,
+ 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0xf9fa0000, 0x00000606, 0x00000606,
+ 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0x00000606, 0x00000606,
+ 0x00000606, 0x00000606, 0x00000606, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa,
+ 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa, 0xfffff9fa,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02020000, 0x02020000, 0x02020000, 0x02020000,
+ 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000, 0x02020000,
+ 0x02020000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000,
+ 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0xfdfe0000, 0x00000202, 0x00000202,
+ 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202, 0x00000202,
+ 0x00000202, 0x00000202, 0x00000202, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe,
+ 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe, 0xfffffdfe,
+ 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404,
+ 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc,
+ 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc,
+ 0xfbfbfbfc, 0xfbfbfbfc, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a,
+ 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0xf5f5f5f6,
+ 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6,
+ 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0xf5f5f5f6, 0x0a0a0000, 0x0a0a0000, 0x0a0a0000, 0x0a0a0000,
+ 0x0a0a0000, 0x0a0a0000, 0x0a0a0000, 0x0a0a0000, 0x0a0a0000, 0x0a0a0000, 0x0a0a0000, 0x0a0a0000,
+ 0x0a0a0000, 0xf5f60000, 0xf5f60000, 0xf5f60000, 0xf5f60000, 0xf5f60000, 0xf5f60000, 0xf5f60000,
+ 0xf5f60000, 0xf5f60000, 0xf5f60000, 0xf5f60000, 0xf5f60000, 0xf5f60000, 0x00000a0a, 0x00000a0a,
+ 0x00000a0a, 0x00000a0a, 0x00000a0a, 0x00000a0a, 0x00000a0a, 0x00000a0a, 0x00000a0a, 0x00000a0a,
+ 0x00000a0a, 0x00000a0a, 0x00000a0a, 0xfffff5f6, 0xfffff5f6, 0xfffff5f6, 0xfffff5f6, 0xfffff5f6,
+ 0xfffff5f6, 0xfffff5f6, 0xfffff5f6, 0xfffff5f6, 0xfffff5f6, 0xfffff5f6, 0xfffff5f6, 0xfffff5f6,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04040000, 0x04040000, 0x04040000, 0x04040000,
+ 0x04040000, 0x04040000, 0x04040000, 0x04040000, 0x04040000, 0x04040000, 0x04040000, 0x04040000,
+ 0x04040000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000,
+ 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0xfbfc0000, 0x00000404, 0x00000404,
+ 0x00000404, 0x00000404, 0x00000404, 0x00000404, 0x00000404, 0x00000404, 0x00000404, 0x00000404,
+ 0x00000404, 0x00000404, 0x00000404, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc,
+ 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc, 0xfffffbfc,
+ 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404,
+ 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0x04040404, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc,
+ 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc, 0xfbfbfbfc,
+ 0xfbfbfbfc, 0xfbfbfbfc, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0x0c0c0000, 0x0c0c0000, 0x0c0c0000, 0x0c0c0000,
+ 0x0c0c0000, 0x0c0c0000, 0x0c0c0000, 0x0c0c0000, 0x0c0c0000, 0x0c0c0000, 0x0c0c0000, 0x0c0c0000,
+ 0x0c0c0000, 0xf3f40000, 0xf3f40000, 0xf3f40000, 0xf3f40000, 0xf3f40000, 0xf3f40000, 0xf3f40000,
+ 0xf3f40000, 0xf3f40000, 0xf3f40000, 0xf3f40000, 0xf3f40000, 0xf3f40000, 0x00000c0c, 0x00000c0c,
+ 0x00000c0c, 0x00000c0c, 0x00000c0c, 0x00000c0c, 0x00000c0c, 0x00000c0c, 0x00000c0c, 0x00000c0c,
+ 0x00000c0c, 0x00000c0c, 0x00000c0c, 0xfffff3f4, 0xfffff3f4, 0xfffff3f4, 0xfffff3f4, 0xfffff3f4,
+ 0xfffff3f4, 0xfffff3f4, 0xfffff3f4, 0xfffff3f4, 0xfffff3f4, 0xfffff3f4, 0xfffff3f4, 0xfffff3f4,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414,
+ 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0x20202020, 0x20202020, 0x20202020, 0x20202020,
+ 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020,
+ 0x20202020, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0,
+ 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0x2e2e2e2e, 0x2e2e2e2e,
+ 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e,
+ 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2,
+ 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414,
+ 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0x20202020, 0x20202020, 0x20202020, 0x20202020,
+ 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020,
+ 0x20202020, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0,
+ 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0x2e2e2e2e, 0x2e2e2e2e,
+ 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e,
+ 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2,
+ 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414,
+ 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0x20202020, 0x20202020, 0x20202020, 0x20202020,
+ 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020,
+ 0x20202020, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0,
+ 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0x2e2e2e2e, 0x2e2e2e2e,
+ 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e,
+ 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2,
+ 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
+ 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0x02020202, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe,
+ 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0xfdfdfdfe, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa, 0xf9f9f9fa,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,
+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4, 0xf3f3f3f4,
+ 0xf3f3f3f4, 0xf3f3f3f4, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414,
+ 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0x14141414, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec,
+ 0xebebebec, 0xebebebec, 0xebebebec, 0xebebebec, 0x20202020, 0x20202020, 0x20202020, 0x20202020,
+ 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020, 0x20202020,
+ 0x20202020, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0,
+ 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0xdfdfdfe0, 0x2e2e2e2e, 0x2e2e2e2e,
+ 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e,
+ 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2,
+ 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2, 0xd1d1d1d2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
diff --git a/contrib/ffmpeg/libavcodec/interplayvideo.c b/contrib/ffmpeg/libavcodec/interplayvideo.c
new file mode 100644
index 000000000..95059c365
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/interplayvideo.c
@@ -0,0 +1,964 @@
+/*
+ * 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 interplayvideo.c
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.h"
+
+#define PALETTE_COUNT 256
+
+/* debugging support */
+#define DEBUG_INTERPLAY 0
+#if DEBUG_INTERPLAY
+#define debug_interplay(x,...) av_log(NULL, AV_LOG_DEBUG, x, __VA_ARGS__)
+#else
+static inline void debug_interplay(const char *format, ...) { }
+#endif
+
+typedef struct IpvideoContext {
+
+ AVCodecContext *avctx;
+ DSPContext dsp;
+ AVFrame second_last_frame;
+ AVFrame last_frame;
+ AVFrame current_frame;
+ unsigned char *decoding_map;
+ int decoding_map_size;
+
+ unsigned char *buf;
+ int size;
+
+ unsigned char *stream_ptr;
+ unsigned char *stream_end;
+ unsigned char *pixel_ptr;
+ int line_inc;
+ int stride;
+ int upper_motion_limit_offset;
+
+} IpvideoContext;
+
+#define CHECK_STREAM_PTR(n) \
+ if ((s->stream_ptr + n) > s->stream_end) { \
+ av_log(s->avctx, AV_LOG_ERROR, "Interplay video warning: stream_ptr out of bounds (%p >= %p)\n", \
+ s->stream_ptr + n, s->stream_end); \
+ return -1; \
+ }
+
+#define COPY_FROM_CURRENT() \
+ motion_offset = current_offset; \
+ motion_offset += y * s->stride; \
+ motion_offset += x; \
+ if (motion_offset < 0) { \
+ av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset < 0 (%d)\n", motion_offset); \
+ return -1; \
+ } else if (motion_offset > s->upper_motion_limit_offset) { \
+ av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset above limit (%d >= %d)\n", \
+ motion_offset, s->upper_motion_limit_offset); \
+ return -1; \
+ } \
+ s->dsp.put_pixels_tab[0][0](s->pixel_ptr, \
+ s->current_frame.data[0] + motion_offset, s->stride, 8);
+
+#define COPY_FROM_PREVIOUS() \
+ motion_offset = current_offset; \
+ motion_offset += y * s->stride; \
+ motion_offset += x; \
+ if (motion_offset < 0) { \
+ av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset < 0 (%d)\n", motion_offset); \
+ return -1; \
+ } else if (motion_offset > s->upper_motion_limit_offset) { \
+ av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset above limit (%d >= %d)\n", \
+ motion_offset, s->upper_motion_limit_offset); \
+ return -1; \
+ } \
+ s->dsp.put_pixels_tab[0][0](s->pixel_ptr, \
+ s->last_frame.data[0] + motion_offset, s->stride, 8);
+
+#define COPY_FROM_SECOND_LAST() \
+ motion_offset = current_offset; \
+ motion_offset += y * s->stride; \
+ motion_offset += x; \
+ if (motion_offset < 0) { \
+ av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset < 0 (%d)\n", motion_offset); \
+ return -1; \
+ } else if (motion_offset > s->upper_motion_limit_offset) { \
+ av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset above limit (%d >= %d)\n", \
+ motion_offset, s->upper_motion_limit_offset); \
+ return -1; \
+ } \
+ s->dsp.put_pixels_tab[0][0](s->pixel_ptr, \
+ s->second_last_frame.data[0] + motion_offset, s->stride, 8);
+
+static int ipvideo_decode_block_opcode_0x0(IpvideoContext *s)
+{
+ int x, y;
+ int motion_offset;
+ int current_offset = s->pixel_ptr - s->current_frame.data[0];
+
+ /* copy a block from the previous frame */
+ x = y = 0;
+ COPY_FROM_PREVIOUS();
+
+ /* report success */
+ return 0;
+}
+
+static int ipvideo_decode_block_opcode_0x1(IpvideoContext *s)
+{
+ int x, y;
+ int motion_offset;
+ int current_offset = s->pixel_ptr - s->current_frame.data[0];
+
+ /* copy block from 2 frames ago */
+ x = y = 0;
+ COPY_FROM_SECOND_LAST();
+
+ /* report success */
+ return 0;
+}
+
+static int ipvideo_decode_block_opcode_0x2(IpvideoContext *s)
+{
+ unsigned char B;
+ int x, y;
+ int motion_offset;
+ int current_offset = s->pixel_ptr - s->current_frame.data[0];
+
+ /* copy block from 2 frames ago using a motion vector; need 1 more byte */
+ CHECK_STREAM_PTR(1);
+ B = *s->stream_ptr++;
+
+ if (B < 56) {
+ x = 8 + (B % 7);
+ y = B / 7;
+ } else {
+ x = -14 + ((B - 56) % 29);
+ y = 8 + ((B - 56) / 29);
+ }
+
+ debug_interplay (" motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
+ COPY_FROM_SECOND_LAST();
+
+ /* report success */
+ return 0;
+}
+
+static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s)
+{
+ unsigned char B;
+ int x, y;
+ int motion_offset;
+ int current_offset = s->pixel_ptr - s->current_frame.data[0];
+
+ /* copy 8x8 block from current frame from an up/left block */
+
+ /* need 1 more byte for motion */
+ CHECK_STREAM_PTR(1);
+ B = *s->stream_ptr++;
+
+ if (B < 56) {
+ x = -(8 + (B % 7));
+ y = -(B / 7);
+ } else {
+ x = -(-14 + ((B - 56) % 29));
+ y = -( 8 + ((B - 56) / 29));
+ }
+
+ debug_interplay (" motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
+ COPY_FROM_CURRENT();
+
+ /* report success */
+ return 0;
+}
+
+static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s)
+{
+ int x, y;
+ unsigned char B, BL, BH;
+ int motion_offset;
+ int current_offset = s->pixel_ptr - s->current_frame.data[0];
+
+ /* copy a block from the previous frame; need 1 more byte */
+ CHECK_STREAM_PTR(1);
+
+ B = *s->stream_ptr++;
+ BL = B & 0x0F;
+ BH = (B >> 4) & 0x0F;
+ x = -8 + BL;
+ y = -8 + BH;
+
+ debug_interplay (" motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
+ COPY_FROM_PREVIOUS();
+
+ /* report success */
+ return 0;
+}
+
+static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s)
+{
+ signed char x, y;
+ int motion_offset;
+ int current_offset = s->pixel_ptr - s->current_frame.data[0];
+
+ /* copy a block from the previous frame using an expanded range;
+ * need 2 more bytes */
+ CHECK_STREAM_PTR(2);
+
+ x = *s->stream_ptr++;
+ y = *s->stream_ptr++;
+
+ debug_interplay (" motion bytes = %d, %d\n", x, y);
+ COPY_FROM_PREVIOUS();
+
+ /* report success */
+ return 0;
+}
+
+static int ipvideo_decode_block_opcode_0x6(IpvideoContext *s)
+{
+ /* mystery opcode? skip multiple blocks? */
+ av_log(s->avctx, AV_LOG_ERROR, " Interplay video: Help! Mystery opcode 0x6 seen\n");
+
+ /* report success */
+ return 0;
+}
+
+static int ipvideo_decode_block_opcode_0x7(IpvideoContext *s)
+{
+ int x, y;
+ unsigned char P0, P1;
+ unsigned char B[8];
+ unsigned int flags;
+ int bitmask;
+
+ /* 2-color encoding */
+ CHECK_STREAM_PTR(2);
+
+ P0 = *s->stream_ptr++;
+ P1 = *s->stream_ptr++;
+
+ if (P0 <= P1) {
+
+ /* need 8 more bytes from the stream */
+ CHECK_STREAM_PTR(8);
+ for (y = 0; y < 8; y++)
+ B[y] = *s->stream_ptr++;
+
+ for (y = 0; y < 8; y++) {
+ flags = B[y];
+ for (x = 0x01; x <= 0x80; x <<= 1) {
+ if (flags & x)
+ *s->pixel_ptr++ = P1;
+ else
+ *s->pixel_ptr++ = P0;
+ }
+ s->pixel_ptr += s->line_inc;
+ }
+
+ } else {
+
+ /* need 2 more bytes from the stream */
+ CHECK_STREAM_PTR(2);
+ B[0] = *s->stream_ptr++;
+ B[1] = *s->stream_ptr++;
+
+ flags = (B[1] << 8) | B[0];
+ bitmask = 0x0001;
+ for (y = 0; y < 8; y += 2) {
+ for (x = 0; x < 8; x += 2, bitmask <<= 1) {
+ if (flags & bitmask) {
+ *(s->pixel_ptr + x) = P1;
+ *(s->pixel_ptr + x + 1) = P1;
+ *(s->pixel_ptr + s->stride + x) = P1;
+ *(s->pixel_ptr + s->stride + x + 1) = P1;
+ } else {
+ *(s->pixel_ptr + x) = P0;
+ *(s->pixel_ptr + x + 1) = P0;
+ *(s->pixel_ptr + s->stride + x) = P0;
+ *(s->pixel_ptr + s->stride + x + 1) = P0;
+ }
+ }
+ s->pixel_ptr += s->stride * 2;
+ }
+ }
+
+ /* report success */
+ return 0;
+}
+
+static int ipvideo_decode_block_opcode_0x8(IpvideoContext *s)
+{
+ int x, y;
+ unsigned char P[8];
+ unsigned char B[8];
+ unsigned int flags = 0;
+ unsigned int bitmask = 0;
+ unsigned char P0 = 0, P1 = 0;
+ int lower_half = 0;
+
+ /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
+ * either top and bottom or left and right halves */
+ CHECK_STREAM_PTR(2);
+
+ P[0] = *s->stream_ptr++;
+ P[1] = *s->stream_ptr++;
+
+ if (P[0] <= P[1]) {
+
+ /* need 12 more bytes */
+ CHECK_STREAM_PTR(12);
+ B[0] = *s->stream_ptr++; B[1] = *s->stream_ptr++;
+ P[2] = *s->stream_ptr++; P[3] = *s->stream_ptr++;
+ B[2] = *s->stream_ptr++; B[3] = *s->stream_ptr++;
+ P[4] = *s->stream_ptr++; P[5] = *s->stream_ptr++;
+ B[4] = *s->stream_ptr++; B[5] = *s->stream_ptr++;
+ P[6] = *s->stream_ptr++; P[7] = *s->stream_ptr++;
+ B[6] = *s->stream_ptr++; B[7] = *s->stream_ptr++;
+
+ for (y = 0; y < 8; y++) {
+
+ /* time to reload flags? */
+ if (y == 0) {
+ flags =
+ ((B[0] & 0xF0) << 4) | ((B[4] & 0xF0) << 8) |
+ ((B[0] & 0x0F) ) | ((B[4] & 0x0F) << 4) |
+ ((B[1] & 0xF0) << 20) | ((B[5] & 0xF0) << 24) |
+ ((B[1] & 0x0F) << 16) | ((B[5] & 0x0F) << 20);
+ bitmask = 0x00000001;
+ lower_half = 0; /* still on top half */
+ } else if (y == 4) {
+ flags =
+ ((B[2] & 0xF0) << 4) | ((B[6] & 0xF0) << 8) |
+ ((B[2] & 0x0F) ) | ((B[6] & 0x0F) << 4) |
+ ((B[3] & 0xF0) << 20) | ((B[7] & 0xF0) << 24) |
+ ((B[3] & 0x0F) << 16) | ((B[7] & 0x0F) << 20);
+ bitmask = 0x00000001;
+ lower_half = 2;
+ }
+
+ for (x = 0; x < 8; x++, bitmask <<= 1) {
+ /* get the pixel values ready for this quadrant */
+ if (x == 0) {
+ P0 = P[lower_half + 0];
+ P1 = P[lower_half + 1];
+ } else if (x == 4) {
+ P0 = P[lower_half + 4];
+ P1 = P[lower_half + 5];
+ }
+
+ if (flags & bitmask)
+ *s->pixel_ptr++ = P1;
+ else
+ *s->pixel_ptr++ = P0;
+ }
+ s->pixel_ptr += s->line_inc;
+ }
+
+ } else {
+
+ /* need 10 more bytes */
+ CHECK_STREAM_PTR(10);
+ B[0] = *s->stream_ptr++; B[1] = *s->stream_ptr++;
+ B[2] = *s->stream_ptr++; B[3] = *s->stream_ptr++;
+ P[2] = *s->stream_ptr++; P[3] = *s->stream_ptr++;
+ B[4] = *s->stream_ptr++; B[5] = *s->stream_ptr++;
+ B[6] = *s->stream_ptr++; B[7] = *s->stream_ptr++;
+
+ if (P[2] <= P[3]) {
+
+ /* vertical split; left & right halves are 2-color encoded */
+
+ for (y = 0; y < 8; y++) {
+
+ /* time to reload flags? */
+ if (y == 0) {
+ flags =
+ ((B[0] & 0xF0) << 4) | ((B[4] & 0xF0) << 8) |
+ ((B[0] & 0x0F) ) | ((B[4] & 0x0F) << 4) |
+ ((B[1] & 0xF0) << 20) | ((B[5] & 0xF0) << 24) |
+ ((B[1] & 0x0F) << 16) | ((B[5] & 0x0F) << 20);
+ bitmask = 0x00000001;
+ } else if (y == 4) {
+ flags =
+ ((B[2] & 0xF0) << 4) | ((B[6] & 0xF0) << 8) |
+ ((B[2] & 0x0F) ) | ((B[6] & 0x0F) << 4) |
+ ((B[3] & 0xF0) << 20) | ((B[7] & 0xF0) << 24) |
+ ((B[3] & 0x0F) << 16) | ((B[7] & 0x0F) << 20);
+ bitmask = 0x00000001;
+ }
+
+ for (x = 0; x < 8; x++, bitmask <<= 1) {
+ /* get the pixel values ready for this half */
+ if (x == 0) {
+ P0 = P[0];
+ P1 = P[1];
+ } else if (x == 4) {
+ P0 = P[2];
+ P1 = P[3];
+ }
+
+ if (flags & bitmask)
+ *s->pixel_ptr++ = P1;
+ else
+ *s->pixel_ptr++ = P0;
+ }
+ s->pixel_ptr += s->line_inc;
+ }
+
+ } else {
+
+ /* horizontal split; top & bottom halves are 2-color encoded */
+
+ for (y = 0; y < 8; y++) {
+
+ flags = B[y];
+ if (y == 0) {
+ P0 = P[0];
+ P1 = P[1];
+ } else if (y == 4) {
+ P0 = P[2];
+ P1 = P[3];
+ }
+
+ for (bitmask = 0x01; bitmask <= 0x80; bitmask <<= 1) {
+
+ if (flags & bitmask)
+ *s->pixel_ptr++ = P1;
+ else
+ *s->pixel_ptr++ = P0;
+ }
+ s->pixel_ptr += s->line_inc;
+ }
+ }
+ }
+
+ /* report success */
+ return 0;
+}
+
+static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s)
+{
+ int x, y;
+ unsigned char P[4];
+ unsigned char B[4];
+ unsigned int flags = 0;
+ int shifter = 0;
+ unsigned char pix;
+
+ /* 4-color encoding */
+ CHECK_STREAM_PTR(4);
+
+ for (y = 0; y < 4; y++)
+ P[y] = *s->stream_ptr++;
+
+ if ((P[0] <= P[1]) && (P[2] <= P[3])) {
+
+ /* 1 of 4 colors for each pixel, need 16 more bytes */
+ CHECK_STREAM_PTR(16);
+
+ for (y = 0; y < 8; y++) {
+ /* get the next set of 8 2-bit flags */
+ flags = (s->stream_ptr[1] << 8) | s->stream_ptr[0];
+ s->stream_ptr += 2;
+ for (x = 0, shifter = 0; x < 8; x++, shifter += 2) {
+ *s->pixel_ptr++ = P[(flags >> shifter) & 0x03];
+ }
+ s->pixel_ptr += s->line_inc;
+ }
+
+ } else if ((P[0] <= P[1]) && (P[2] > P[3])) {
+
+ /* 1 of 4 colors for each 2x2 block, need 4 more bytes */
+ CHECK_STREAM_PTR(4);
+
+ B[0] = *s->stream_ptr++;
+ B[1] = *s->stream_ptr++;
+ B[2] = *s->stream_ptr++;
+ B[3] = *s->stream_ptr++;
+ flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
+ shifter = 0;
+
+ for (y = 0; y < 8; y += 2) {
+ for (x = 0; x < 8; x += 2, shifter += 2) {
+ pix = P[(flags >> shifter) & 0x03];
+ *(s->pixel_ptr + x) = pix;
+ *(s->pixel_ptr + x + 1) = pix;
+ *(s->pixel_ptr + s->stride + x) = pix;
+ *(s->pixel_ptr + s->stride + x + 1) = pix;
+ }
+ s->pixel_ptr += s->stride * 2;
+ }
+
+ } else if ((P[0] > P[1]) && (P[2] <= P[3])) {
+
+ /* 1 of 4 colors for each 2x1 block, need 8 more bytes */
+ CHECK_STREAM_PTR(8);
+
+ for (y = 0; y < 8; y++) {
+ /* time to reload flags? */
+ if ((y == 0) || (y == 4)) {
+ B[0] = *s->stream_ptr++;
+ B[1] = *s->stream_ptr++;
+ B[2] = *s->stream_ptr++;
+ B[3] = *s->stream_ptr++;
+ flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
+ shifter = 0;
+ }
+ for (x = 0; x < 8; x += 2, shifter += 2) {
+ pix = P[(flags >> shifter) & 0x03];
+ *(s->pixel_ptr + x) = pix;
+ *(s->pixel_ptr + x + 1) = pix;
+ }
+ s->pixel_ptr += s->stride;
+ }
+
+ } else {
+
+ /* 1 of 4 colors for each 1x2 block, need 8 more bytes */
+ CHECK_STREAM_PTR(8);
+
+ for (y = 0; y < 8; y += 2) {
+ /* time to reload flags? */
+ if ((y == 0) || (y == 4)) {
+ B[0] = *s->stream_ptr++;
+ B[1] = *s->stream_ptr++;
+ B[2] = *s->stream_ptr++;
+ B[3] = *s->stream_ptr++;
+ flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
+ shifter = 0;
+ }
+ for (x = 0; x < 8; x++, shifter += 2) {
+ pix = P[(flags >> shifter) & 0x03];
+ *(s->pixel_ptr + x) = pix;
+ *(s->pixel_ptr + s->stride + x) = pix;
+ }
+ s->pixel_ptr += s->stride * 2;
+ }
+ }
+
+ /* report success */
+ return 0;
+}
+
+static int ipvideo_decode_block_opcode_0xA(IpvideoContext *s)
+{
+ int x, y;
+ unsigned char P[16];
+ unsigned char B[16];
+ int flags = 0;
+ int shifter = 0;
+ int index;
+ int split;
+ int lower_half;
+
+ /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
+ * either top and bottom or left and right halves */
+ CHECK_STREAM_PTR(4);
+
+ for (y = 0; y < 4; y++)
+ P[y] = *s->stream_ptr++;
+
+ if (P[0] <= P[1]) {
+
+ /* 4-color encoding for each quadrant; need 28 more bytes */
+ CHECK_STREAM_PTR(28);
+
+ for (y = 0; y < 4; y++)
+ B[y] = *s->stream_ptr++;
+ for (y = 4; y < 16; y += 4) {
+ for (x = y; x < y + 4; x++)
+ P[x] = *s->stream_ptr++;
+ for (x = y; x < y + 4; x++)
+ B[x] = *s->stream_ptr++;
+ }
+
+ for (y = 0; y < 8; y++) {
+
+ lower_half = (y >= 4) ? 4 : 0;
+ flags = (B[y + 8] << 8) | B[y];
+
+ for (x = 0, shifter = 0; x < 8; x++, shifter += 2) {
+ split = (x >= 4) ? 8 : 0;
+ index = split + lower_half + ((flags >> shifter) & 0x03);
+ *s->pixel_ptr++ = P[index];
+ }
+
+ s->pixel_ptr += s->line_inc;
+ }
+
+ } else {
+
+ /* 4-color encoding for either left and right or top and bottom
+ * halves; need 20 more bytes */
+ CHECK_STREAM_PTR(20);
+
+ for (y = 0; y < 8; y++)
+ B[y] = *s->stream_ptr++;
+ for (y = 4; y < 8; y++)
+ P[y] = *s->stream_ptr++;
+ for (y = 8; y < 16; y++)
+ B[y] = *s->stream_ptr++;
+
+ if (P[4] <= P[5]) {
+
+ /* block is divided into left and right halves */
+ for (y = 0; y < 8; y++) {
+
+ flags = (B[y + 8] << 8) | B[y];
+ split = 0;
+
+ for (x = 0, shifter = 0; x < 8; x++, shifter += 2) {
+ if (x == 4)
+ split = 4;
+ *s->pixel_ptr++ = P[split + ((flags >> shifter) & 0x03)];
+ }
+
+ s->pixel_ptr += s->line_inc;
+ }
+
+ } else {
+
+ /* block is divided into top and bottom halves */
+ split = 0;
+ for (y = 0; y < 8; y++) {
+
+ flags = (B[y * 2 + 1] << 8) | B[y * 2];
+ if (y == 4)
+ split = 4;
+
+ for (x = 0, shifter = 0; x < 8; x++, shifter += 2)
+ *s->pixel_ptr++ = P[split + ((flags >> shifter) & 0x03)];
+
+ s->pixel_ptr += s->line_inc;
+ }
+ }
+ }
+
+ /* report success */
+ return 0;
+}
+
+static int ipvideo_decode_block_opcode_0xB(IpvideoContext *s)
+{
+ int x, y;
+
+ /* 64-color encoding (each pixel in block is a different color) */
+ CHECK_STREAM_PTR(64);
+
+ for (y = 0; y < 8; y++) {
+ for (x = 0; x < 8; x++) {
+ *s->pixel_ptr++ = *s->stream_ptr++;
+ }
+ s->pixel_ptr += s->line_inc;
+ }
+
+ /* report success */
+ return 0;
+}
+
+static int ipvideo_decode_block_opcode_0xC(IpvideoContext *s)
+{
+ int x, y;
+ unsigned char pix;
+
+ /* 16-color block encoding: each 2x2 block is a different color */
+ CHECK_STREAM_PTR(16);
+
+ for (y = 0; y < 8; y += 2) {
+ for (x = 0; x < 8; x += 2) {
+ pix = *s->stream_ptr++;
+ *(s->pixel_ptr + x) = pix;
+ *(s->pixel_ptr + x + 1) = pix;
+ *(s->pixel_ptr + s->stride + x) = pix;
+ *(s->pixel_ptr + s->stride + x + 1) = pix;
+ }
+ s->pixel_ptr += s->stride * 2;
+ }
+
+ /* report success */
+ return 0;
+}
+
+static int ipvideo_decode_block_opcode_0xD(IpvideoContext *s)
+{
+ int x, y;
+ unsigned char P[4];
+ unsigned char index = 0;
+
+ /* 4-color block encoding: each 4x4 block is a different color */
+ CHECK_STREAM_PTR(4);
+
+ for (y = 0; y < 4; y++)
+ P[y] = *s->stream_ptr++;
+
+ for (y = 0; y < 8; y++) {
+ if (y < 4)
+ index = 0;
+ else
+ index = 2;
+
+ for (x = 0; x < 8; x++) {
+ if (x == 4)
+ index++;
+ *s->pixel_ptr++ = P[index];
+ }
+ s->pixel_ptr += s->line_inc;
+ }
+
+ /* report success */
+ return 0;
+}
+
+static int ipvideo_decode_block_opcode_0xE(IpvideoContext *s)
+{
+ int x, y;
+ unsigned char pix;
+
+ /* 1-color encoding: the whole block is 1 solid color */
+ CHECK_STREAM_PTR(1);
+ pix = *s->stream_ptr++;
+
+ for (y = 0; y < 8; y++) {
+ for (x = 0; x < 8; x++) {
+ *s->pixel_ptr++ = pix;
+ }
+ s->pixel_ptr += s->line_inc;
+ }
+
+ /* report success */
+ return 0;
+}
+
+static int ipvideo_decode_block_opcode_0xF(IpvideoContext *s)
+{
+ int x, y;
+ unsigned char sample0, sample1;
+
+ /* dithered encoding */
+ CHECK_STREAM_PTR(2);
+ sample0 = *s->stream_ptr++;
+ sample1 = *s->stream_ptr++;
+
+ for (y = 0; y < 8; y++) {
+ for (x = 0; x < 8; x += 2) {
+ if (y & 1) {
+ *s->pixel_ptr++ = sample1;
+ *s->pixel_ptr++ = sample0;
+ } else {
+ *s->pixel_ptr++ = sample0;
+ *s->pixel_ptr++ = sample1;
+ }
+ }
+ s->pixel_ptr += s->line_inc;
+ }
+
+ /* report success */
+ return 0;
+}
+
+static int (*ipvideo_decode_block[16])(IpvideoContext *s);
+
+static void ipvideo_decode_opcodes(IpvideoContext *s)
+{
+ int x, y;
+ int index = 0;
+ unsigned char opcode;
+ int ret;
+ int code_counts[16];
+ static int frame = 0;
+
+ debug_interplay("------------------ frame %d\n", frame);
+ frame++;
+
+ for (x = 0; x < 16; x++)
+ code_counts[x] = 0;
+
+ /* this is PAL8, so make the palette available */
+ memcpy(s->current_frame.data[1], s->avctx->palctrl->palette, PALETTE_COUNT * 4);
+
+ s->stride = s->current_frame.linesize[0];
+ s->stream_ptr = s->buf + 14; /* data starts 14 bytes in */
+ s->stream_end = s->buf + s->size;
+ s->line_inc = s->stride - 8;
+ s->upper_motion_limit_offset = (s->avctx->height - 8) * s->stride
+ + s->avctx->width - 8;
+ s->dsp = s->dsp;
+
+ for (y = 0; y < (s->stride * s->avctx->height); y += s->stride * 8) {
+ for (x = y; x < y + s->avctx->width; x += 8) {
+ /* bottom nibble first, then top nibble (which makes it
+ * hard to use a GetBitcontext) */
+ if (index & 1)
+ opcode = s->decoding_map[index >> 1] >> 4;
+ else
+ opcode = s->decoding_map[index >> 1] & 0xF;
+ index++;
+
+ debug_interplay(" block @ (%3d, %3d): encoding 0x%X, data ptr @ %p\n",
+ x - y, y / s->stride, opcode, s->stream_ptr);
+ code_counts[opcode]++;
+
+ s->pixel_ptr = s->current_frame.data[0] + x;
+ ret = ipvideo_decode_block[opcode](s);
+ if (ret != 0) {
+ av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode problem on frame %d, @ block (%d, %d)\n",
+ frame, x - y, y / s->stride);
+ return;
+ }
+ }
+ }
+ if ((s->stream_ptr != s->stream_end) &&
+ (s->stream_ptr + 1 != s->stream_end)) {
+ av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode finished with %td bytes left over\n",
+ s->stream_end - s->stream_ptr);
+ }
+}
+
+static int ipvideo_decode_init(AVCodecContext *avctx)
+{
+ IpvideoContext *s = avctx->priv_data;
+
+ s->avctx = avctx;
+
+ if (s->avctx->palctrl == NULL) {
+ av_log(avctx, AV_LOG_ERROR, " Interplay video: palette expected.\n");
+ return -1;
+ }
+
+ avctx->pix_fmt = PIX_FMT_PAL8;
+ avctx->has_b_frames = 0;
+ dsputil_init(&s->dsp, avctx);
+
+ /* decoding map contains 4 bits of information per 8x8 block */
+ s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2);
+
+ /* assign block decode functions */
+ ipvideo_decode_block[0x0] = ipvideo_decode_block_opcode_0x0;
+ ipvideo_decode_block[0x1] = ipvideo_decode_block_opcode_0x1;
+ ipvideo_decode_block[0x2] = ipvideo_decode_block_opcode_0x2;
+ ipvideo_decode_block[0x3] = ipvideo_decode_block_opcode_0x3;
+ ipvideo_decode_block[0x4] = ipvideo_decode_block_opcode_0x4;
+ ipvideo_decode_block[0x5] = ipvideo_decode_block_opcode_0x5;
+ ipvideo_decode_block[0x6] = ipvideo_decode_block_opcode_0x6;
+ ipvideo_decode_block[0x7] = ipvideo_decode_block_opcode_0x7;
+ ipvideo_decode_block[0x8] = ipvideo_decode_block_opcode_0x8;
+ ipvideo_decode_block[0x9] = ipvideo_decode_block_opcode_0x9;
+ ipvideo_decode_block[0xA] = ipvideo_decode_block_opcode_0xA;
+ ipvideo_decode_block[0xB] = ipvideo_decode_block_opcode_0xB;
+ ipvideo_decode_block[0xC] = ipvideo_decode_block_opcode_0xC;
+ ipvideo_decode_block[0xD] = ipvideo_decode_block_opcode_0xD;
+ ipvideo_decode_block[0xE] = ipvideo_decode_block_opcode_0xE;
+ ipvideo_decode_block[0xF] = ipvideo_decode_block_opcode_0xF;
+
+ s->current_frame.data[0] = s->last_frame.data[0] =
+ s->second_last_frame.data[0] = NULL;
+
+ return 0;
+}
+
+static int ipvideo_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ IpvideoContext *s = avctx->priv_data;
+ AVPaletteControl *palette_control = avctx->palctrl;
+
+ /* 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;
+
+ s->decoding_map = buf;
+ s->buf = buf + s->decoding_map_size;
+ s->size = buf_size - s->decoding_map_size;
+
+ s->current_frame.reference = 3;
+ if (avctx->get_buffer(avctx, &s->current_frame)) {
+ av_log(avctx, AV_LOG_ERROR, " Interplay Video: get_buffer() failed\n");
+ return -1;
+ }
+
+ ipvideo_decode_opcodes(s);
+
+ if (palette_control->palette_changed) {
+ palette_control->palette_changed = 0;
+ s->current_frame.palette_has_changed = 1;
+ }
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = s->current_frame;
+
+ /* shuffle frames */
+ if (s->second_last_frame.data[0])
+ avctx->release_buffer(avctx, &s->second_last_frame);
+ s->second_last_frame = s->last_frame;
+ s->last_frame = s->current_frame;
+ s->current_frame.data[0] = NULL; /* catch any access attempts */
+
+ /* report that the buffer was completely consumed */
+ return buf_size;
+}
+
+static int ipvideo_decode_end(AVCodecContext *avctx)
+{
+ IpvideoContext *s = avctx->priv_data;
+
+ /* release the last frame */
+ if (s->last_frame.data[0])
+ avctx->release_buffer(avctx, &s->last_frame);
+ if (s->second_last_frame.data[0])
+ avctx->release_buffer(avctx, &s->second_last_frame);
+
+ return 0;
+}
+
+AVCodec interplay_video_decoder = {
+ "interplayvideo",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_INTERPLAY_VIDEO,
+ sizeof(IpvideoContext),
+ ipvideo_decode_init,
+ NULL,
+ ipvideo_decode_end,
+ ipvideo_decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/jfdctfst.c b/contrib/ffmpeg/libavcodec/jfdctfst.c
new file mode 100644
index 000000000..38424563d
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/jfdctfst.c
@@ -0,0 +1,338 @@
+/*
+ * jfdctfst.c
+ *
+ * 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 jfdctfst.c
+ * Independent JPEG Group's fast AAN dct.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "common.h"
+#include "dsputil.h"
+
+#define DCTSIZE 8
+#define GLOBAL(x) x
+#define RIGHT_SHIFT(x, n) ((x) >> (n))
+#define SHIFT_TEMPS
+
+/*
+ * 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 DCTELEM variable by an int32_t constant, and immediately
+ * descale to yield a DCTELEM result.
+ */
+
+#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
+
+static always_inline void row_fdct(DCTELEM * data){
+ int_fast16_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ int_fast16_t tmp10, tmp11, tmp12, tmp13;
+ int_fast16_t z1, z2, z3, z4, z5, z11, z13;
+ DCTELEM *dataptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* 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)
+fdct_ifast (DCTELEM * data)
+{
+ int_fast16_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ int_fast16_t tmp10, tmp11, tmp12, tmp13;
+ int_fast16_t z1, z2, z3, z4, z5, z11, z13;
+ DCTELEM *dataptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ 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)
+fdct_ifast248 (DCTELEM * data)
+{
+ int_fast16_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ int_fast16_t tmp10, tmp11, tmp12, tmp13;
+ int_fast16_t z1;
+ DCTELEM *dataptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ 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/contrib/ffmpeg/libavcodec/jfdctint.c b/contrib/ffmpeg/libavcodec/jfdctint.c
new file mode 100644
index 000000000..58f3a1446
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/jfdctint.c
@@ -0,0 +1,406 @@
+/*
+ * jfdctint.c
+ *
+ * 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 jfdctint.c
+ * Independent JPEG Group's slow & accurate dct.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "common.h"
+#include "dsputil.h"
+
+#define SHIFT_TEMPS
+#define DCTSIZE 8
+#define BITS_IN_JSAMPLE 8
+#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
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#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.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define CONST_BITS 13
+#define PASS1_BITS 4 /* set this to 2 if 16x16 multiplies are faster */
+#else
+#define CONST_BITS 13
+#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
+#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 always_inline void row_fdct(DCTELEM * data){
+ int_fast32_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ int_fast32_t tmp10, tmp11, tmp12, tmp13;
+ int_fast32_t z1, z2, z3, z4, z5;
+ DCTELEM *dataptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* 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] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS);
+ dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS);
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+ dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
+ CONST_BITS-PASS1_BITS);
+ dataptr[6] = (DCTELEM) 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] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS);
+ dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS);
+ dataptr[1] = (DCTELEM) 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)
+ff_jpeg_fdct_islow (DCTELEM * data)
+{
+ int_fast32_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ int_fast32_t tmp10, tmp11, tmp12, tmp13;
+ int_fast32_t z1, z2, z3, z4, z5;
+ DCTELEM *dataptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ 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] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS);
+ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS);
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*6] = (DCTELEM) 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[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3,
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4,
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3,
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4,
+ CONST_BITS+PASS1_BITS);
+
+ 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 colums
+ * you do even part two times.
+ */
+GLOBAL(void)
+ff_fdct248_islow (DCTELEM * data)
+{
+ int_fast32_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ int_fast32_t tmp10, tmp11, tmp12, tmp13;
+ int_fast32_t z1;
+ DCTELEM *dataptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ 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] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS);
+ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS);
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065),
+ CONST_BITS+PASS1_BITS);
+
+ tmp10 = tmp4 + tmp7;
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp5 - tmp6;
+ tmp13 = tmp4 - tmp7;
+
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS);
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065),
+ CONST_BITS+PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
diff --git a/contrib/ffmpeg/libavcodec/jpeg_ls.c b/contrib/ffmpeg/libavcodec/jpeg_ls.c
new file mode 100644
index 000000000..1b4df2b1a
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/jpeg_ls.c
@@ -0,0 +1,855 @@
+/*
+ * JPEG-LS encoder and 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
+ */
+
+#include "golomb.h"
+
+/**
+ * @file jpeg_ls.c
+ * JPEG-LS encoder and decoder.
+ */
+
+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[3];
+}JLSState;
+
+static const uint8_t log2_run[32]={
+ 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
+};
+
+/*
+* 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
+
+/********** Functions for both encoder and decoder **********/
+
+/**
+ * Calculate initial JPEG-LS parameters
+ */
+static void ls_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++);
+
+ if(state->bpp < 8)
+ state->limit = 16 + 2 * state->bpp - state->qbpp;
+ else
+ state->limit = (4 * state->bpp) - state->qbpp;
+
+ for(i = 0; i < 367; i++) {
+ state->A[i] = FFMAX((state->range + 32) >> 6, 2);
+ state->N[i] = 1;
+ }
+
+}
+
+/**
+ * Calculate quantized gradient value, used for context determination
+ */
+static inline int 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;
+ }
+}
+
+/**
+ * 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;
+}
+
+/**
+ * Calculate JPEG-LS codec values
+ */
+static void reset_ls_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 + 6*s->near), s->T2, s->maxval);
+ }
+
+ if(s->reset==0 || reset_all) s->reset= 64;
+// av_log(NULL, AV_LOG_DEBUG, "[JPEG-LS RESET] T=%i,%i,%i\n", s->T1, s->T2, s->T3);
+}
+
+
+/********** Decoder-specific functions **********/
+
+/**
+ * Decode LSE block with initialization parameters
+ */
+static int decode_lse(MJpegDecodeContext *s)
+{
+ int len, id;
+
+ /* XXX: verify len field validity */
+ len = get_bits(&s->gb, 16);
+ 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);
+
+// reset_ls_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_log(s->avctx, AV_LOG_DEBUG, "ID=%i, T=%i,%i,%i\n", id, s->t1, s->t2, s->t3);
+
+ return 0;
+}
+
+static void inline 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 update_state_regular(JLSState *state, int Q, int err){
+ state->A[Q] += FFABS(err);
+ err *= state->twonear;
+ state->B[Q] += err;
+
+ 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;
+}
+
+/**
+ * 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= 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;
+ downscale_state(state, Q);
+
+ return ret;
+}
+
+#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))
+/**
+ * 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 << 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 << 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 = log2_run[state->run_index[comp]];
+ if(r)
+ r = get_bits_long(&s->gb, r);
+ 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, 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 = quantize(state, D0) * 81 + quantize(state, D1) * 9 + quantize(state, D2);
+ pred = mid_pred(Ra, Ra + Rb - Rc, Rb);
+
+ if(context < 0){
+ context = -context;
+ sign = 1;
+ }else{
+ sign = 0;
+ }
+
+ if(sign){
+ pred = clip(pred - state->C[context], 0, state->maxval);
+ err = -ls_get_code_regular(&s->gb, state, context);
+ } else {
+ pred = 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 = clip(pred, 0, state->maxval);
+ }
+
+ pred &= state->maxval;
+ W(dst, x, pred);
+ x += stride;
+ }
+}
+
+static int ls_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;
+ reset_ls_coding_parameters(state, 0);
+ ls_init_state(state);
+
+ if(s->bits <= 8)
+ shift = point_transform + (8 - s->bits);
+ else
+ shift = point_transform + (16 - s->bits);
+
+// 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 */
+ off = s->cur_scan - 1;
+ stride = (s->nb_components > 1) ? 3 : 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};
+ memset(cur, 0, s->picture.linesize[0]);
+ width = s->width * 3;
+ for(i = 0; i < s->height; i++) {
+ for(j = 0; j < 3; j++) {
+ ls_decode_line(state, s, last + j, cur + j, Rc[j], width, 3, 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 = 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;
+}
+
+#if defined(CONFIG_ENCODERS) && defined(CONFIG_JPEGLS_ENCODER)
+/********** Encoder-specific functions **********/
+
+/**
+ * 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);
+
+ 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;
+
+ 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 << log2_run[state->run_index[comp]])){
+ put_bits(pb, 1, 1);
+ run -= 1 << 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(log2_run[state->run_index[comp]])
+ put_bits(pb, 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 = clip(pred + err * state->twonear, 0, state->maxval);
+ else
+ Ra = 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, log2_run[state->run_index[comp]]);
+
+ if(state->run_index[comp] > 0)
+ state->run_index[comp]--;
+ } else { /* regular mode */
+ int context;
+
+ context = quantize(state, D0) * 81 + quantize(state, D1) * 9 + quantize(state, D2);
+ pred = mid_pred(Ra, Ra + Rb - Rc, Rb);
+
+ if(context < 0){
+ context = -context;
+ sign = 1;
+ pred = clip(pred - state->C[context], 0, state->maxval);
+ err = pred - R(cur, x);
+ }else{
+ sign = 0;
+ pred = 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 = clip(pred + err * state->twonear, 0, state->maxval);
+ else
+ Ra = 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;
+ memset(&state2, 0, sizeof(JLSState));
+ state2.bpp = state->bpp;
+ state2.near = state->near;
+ reset_ls_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, unsigned char *buf, int buf_size, void *data){
+ JpeglsContext * const s = avctx->priv_data;
+ AVFrame *pict = data;
+ AVFrame * const p= (AVFrame*)&s->picture;
+ const int near = avctx->prediction_method;
+ PutBitContext pb, pb2;
+ GetBitContext gb;
+ uint8_t *buf2, *zero, *cur, *last;
+ JLSState *state;
+ int i, size;
+ int comps;
+
+ buf2 = av_malloc(buf_size);
+
+ init_put_bits(&pb, buf, buf_size);
+ init_put_bits(&pb2, buf2, buf_size);
+
+ *p = *pict;
+ p->pict_type= FF_I_TYPE;
+ p->key_frame= 1;
+
+ if(avctx->pix_fmt == PIX_FMT_GRAY8 || avctx->pix_fmt == PIX_FMT_GRAY16)
+ comps = 1;
+ else
+ comps = 3;
+
+ /* 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 == 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 == PIX_FMT_GRAY16) ? 16 : 8;
+ reset_ls_coding_parameters(state, 0);
+ ls_init_state(state);
+
+ ls_store_lse(state, &pb);
+
+ zero = av_mallocz(p->linesize[0]);
+ last = zero;
+ cur = p->data[0];
+ if(avctx->pix_fmt == 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 == 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 == 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 == 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_free(zero);
+ av_free(state);
+
+ flush_put_bits(&pb2);
+ /* do escape coding */
+ size = put_bits_count(&pb2) >> 3;
+ init_get_bits(&gb, buf2, size);
+ while(get_bits_count(&gb) < size * 8){
+ 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);
+ }
+ }
+ align_put_bits(&pb);
+ av_free(buf2);
+
+ /* End of image */
+ put_marker(&pb, EOI);
+ flush_put_bits(&pb);
+
+ emms_c();
+
+ return put_bits_count(&pb) >> 3;
+}
+
+static int encode_init_ls(AVCodecContext *ctx) {
+ JpeglsContext *c = (JpeglsContext*)ctx->priv_data;
+
+ c->avctx = ctx;
+ ctx->coded_frame = &c->picture;
+
+ if(ctx->pix_fmt != PIX_FMT_GRAY8 && ctx->pix_fmt != PIX_FMT_GRAY16 && ctx->pix_fmt != PIX_FMT_RGB24 && ctx->pix_fmt != PIX_FMT_BGR24){
+ av_log(ctx, AV_LOG_ERROR, "Only grayscale and RGB24/BGR24 images are supported\n");
+ return -1;
+ }
+ return 0;
+}
+
+AVCodec jpegls_encoder = { //FIXME avoid MPV_* lossless jpeg shouldnt need them
+ "jpegls",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_JPEGLS,
+ sizeof(JpeglsContext),
+ encode_init_ls,
+ encode_picture_ls,
+ NULL,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_BGR24, PIX_FMT_RGB24, PIX_FMT_GRAY8, PIX_FMT_GRAY16, -1},
+};
+#endif
diff --git a/contrib/ffmpeg/libavcodec/jrevdct.c b/contrib/ffmpeg/libavcodec/jrevdct.c
new file mode 100644
index 000000000..f055cc1ac
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/jrevdct.c
@@ -0,0 +1,1159 @@
+/*
+ * jrevdct.c
+ *
+ * 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 jrevdct.c
+ * Independent JPEG Group's LLM idct.
+ */
+
+#include "common.h"
+#include "dsputil.h"
+
+#define EIGHT_BIT_SAMPLES
+
+#define DCTSIZE 8
+#define DCTSIZE2 64
+
+#define GLOBAL
+
+#define RIGHT_SHIFT(x, n) ((x) >> (n))
+
+typedef DCTELEM 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 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 DCTELEM *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. */
+ DCTELEM dcval = (DCTELEM) (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] = (DCTELEM) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
+ dataptr[7] = (DCTELEM) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
+ dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
+ dataptr[6] = (DCTELEM) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
+ dataptr[2] = (DCTELEM) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
+ dataptr[5] = (DCTELEM) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (DCTELEM) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
+ dataptr[4] = (DCTELEM) 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 */
+ z1 = d7;
+ 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;
+ z2 = d5;
+ 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] = (DCTELEM) DESCALE(tmp10 + tmp3,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp10 - tmp3,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp2,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp11 - tmp2,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp12 + tmp1,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12 - tmp1,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp13 + tmp0,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp13 - tmp0,
+ CONST_BITS+PASS1_BITS+3);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+#undef DCTSIZE
+#define DCTSIZE 4
+#define DCTSTRIDE 8
+
+void 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 DCTELEM *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. */
+ DCTELEM dcval = (DCTELEM) (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] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS);
+ dataptr[1] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS);
+ dataptr[2] = (DCTELEM) DESCALE(tmp12, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (DCTELEM) 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 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 j_rev_dct1(DCTBLOCK data){
+ data[0] = (data[0] + 4)>>3;
+}
+
+#undef FIX
+#undef CONST_BITS
diff --git a/contrib/ffmpeg/libavcodec/kmvc.c b/contrib/ffmpeg/libavcodec/kmvc.c
new file mode 100644
index 000000000..e8f39fca1
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/kmvc.c
@@ -0,0 +1,417 @@
+/*
+ * 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 kmvc.c
+ * Karl Morton's Video Codec decoder
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "common.h"
+#include "avcodec.h"
+
+#define KMVC_KEYFRAME 0x80
+#define KMVC_PALETTE 0x40
+#define KMVC_METHOD 0x0F
+
+/*
+ * Decoder context
+ */
+typedef struct KmvcContext {
+ AVCodecContext *avctx;
+ AVFrame pic;
+
+ int setpal;
+ int palsize;
+ uint32_t pal[256];
+ uint8_t *cur, *prev;
+ uint8_t *frm0, *frm1;
+} KmvcContext;
+
+typedef struct BitBuf {
+ int bits;
+ int bitbuf;
+} BitBuf;
+
+#define BLK(data, x, y) data[(x) + (y) * 320]
+
+#define kmvc_init_getbits(bb, src) bb.bits = 7; bb.bitbuf = *src++;
+
+#define kmvc_getbit(bb, src, res) {\
+ res = 0; \
+ if (bb.bitbuf & (1 << bb.bits)) res = 1; \
+ bb.bits--; \
+ if(bb.bits == -1) { \
+ bb.bitbuf = *src++; \
+ bb.bits = 7; \
+ } \
+}
+
+static void kmvc_decode_intra_8x8(KmvcContext * ctx, uint8_t * src, 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, src);
+
+ for (by = 0; by < h; by += 8)
+ for (bx = 0; bx < w; bx += 8) {
+ kmvc_getbit(bb, src, res);
+ if (!res) { // fill whole 8x8 block
+ val = *src++;
+ 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, src, res);
+ if (!res) {
+ kmvc_getbit(bb, src, res);
+ if (!res) { // fill whole 4x4 block
+ val = *src++;
+ for (j = 0; j < 16; j++)
+ BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = val;
+ } else { // copy block from already decoded place
+ val = *src++;
+ mx = val & 0xF;
+ my = val >> 4;
+ 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, src, res);
+ if (!res) {
+ kmvc_getbit(bb, src, res);
+ if (!res) { // fill whole 2x2 block
+ val = *src++;
+ 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 = *src++;
+ mx = val & 0xF;
+ my = val >> 4;
+ 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) = *src++;
+ BLK(ctx->cur, l1x + 1, l1y) = *src++;
+ BLK(ctx->cur, l1x, l1y + 1) = *src++;
+ BLK(ctx->cur, l1x + 1, l1y + 1) = *src++;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static void kmvc_decode_inter_8x8(KmvcContext * ctx, uint8_t * src, 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, src);
+
+ for (by = 0; by < h; by += 8)
+ for (bx = 0; bx < w; bx += 8) {
+ kmvc_getbit(bb, src, res);
+ if (!res) {
+ kmvc_getbit(bb, src, res);
+ if (!res) { // fill whole 8x8 block
+ val = *src++;
+ 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
+ for (i = 0; i < 4; i++) {
+ l0x = bx + (i & 1) * 4;
+ l0y = by + (i & 2) * 2;
+ kmvc_getbit(bb, src, res);
+ if (!res) {
+ kmvc_getbit(bb, src, res);
+ if (!res) { // fill whole 4x4 block
+ val = *src++;
+ for (j = 0; j < 16; j++)
+ BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = val;
+ } else { // copy block
+ val = *src++;
+ mx = (val & 0xF) - 8;
+ my = (val >> 4) - 8;
+ 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, src, res);
+ if (!res) {
+ kmvc_getbit(bb, src, res);
+ if (!res) { // fill whole 2x2 block
+ val = *src++;
+ 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 = *src++;
+ mx = (val & 0xF) - 8;
+ my = (val >> 4) - 8;
+ 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) = *src++;
+ BLK(ctx->cur, l1x + 1, l1y) = *src++;
+ BLK(ctx->cur, l1x, l1y + 1) = *src++;
+ BLK(ctx->cur, l1x + 1, l1y + 1) = *src++;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static int decode_frame(AVCodecContext * avctx, void *data, int *data_size, uint8_t * buf,
+ int buf_size)
+{
+ KmvcContext *const ctx = (KmvcContext *) avctx->priv_data;
+ uint8_t *out, *src;
+ int i;
+ int header;
+ int blocksize;
+
+ if (ctx->pic.data[0])
+ avctx->release_buffer(avctx, &ctx->pic);
+
+ ctx->pic.reference = 1;
+ ctx->pic.buffer_hints = FF_BUFFER_HINTS_VALID;
+ if (avctx->get_buffer(avctx, &ctx->pic) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ header = *buf++;
+
+ /* blocksize 127 is really palette change event */
+ if (buf[0] == 127) {
+ buf += 3;
+ for (i = 0; i < 127; i++) {
+ ctx->pal[i + (header & 0x81)] = (buf[0] << 16) | (buf[1] << 8) | buf[2];
+ buf += 4;
+ }
+ buf -= 127 * 4 + 3;
+ }
+
+ if (header & KMVC_KEYFRAME) {
+ ctx->pic.key_frame = 1;
+ ctx->pic.pict_type = FF_I_TYPE;
+ } else {
+ ctx->pic.key_frame = 0;
+ ctx->pic.pict_type = FF_P_TYPE;
+ }
+
+ /* if palette has been changed, copy it from palctrl */
+ if (ctx->avctx->palctrl && ctx->avctx->palctrl->palette_changed) {
+ memcpy(ctx->pal, ctx->avctx->palctrl->palette, AVPALETTE_SIZE);
+ ctx->setpal = 1;
+ ctx->avctx->palctrl->palette_changed = 0;
+ }
+
+ if (header & KMVC_PALETTE) {
+ ctx->pic.palette_has_changed = 1;
+ // palette starts from index 1 and has 127 entries
+ for (i = 1; i <= ctx->palsize; i++) {
+ ctx->pal[i] = (buf[0] << 16) | (buf[1] << 8) | buf[2];
+ buf += 3;
+ }
+ }
+
+ if (ctx->setpal) {
+ ctx->setpal = 0;
+ ctx->pic.palette_has_changed = 1;
+ }
+
+ /* make the palette available on the way out */
+ memcpy(ctx->pic.data[1], ctx->pal, 1024);
+
+ blocksize = *buf++;
+
+ if (blocksize != 8 && blocksize != 127) {
+ av_log(avctx, AV_LOG_ERROR, "Block size = %i\n", blocksize);
+ return -1;
+ }
+ 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, buf, avctx->width, avctx->height);
+ break;
+ case 4:
+ kmvc_decode_inter_8x8(ctx, buf, avctx->width, avctx->height);
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "Unknown compression method %i\n", header & KMVC_METHOD);
+ return -1;
+ }
+
+ out = ctx->pic.data[0];
+ src = ctx->cur;
+ for (i = 0; i < avctx->height; i++) {
+ memcpy(out, src, avctx->width);
+ src += 320;
+ out += ctx->pic.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;
+ }
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame *) data = ctx->pic;
+
+ /* always report that the buffer was completely consumed */
+ return buf_size;
+}
+
+
+
+/*
+ * Init kmvc decoder
+ */
+static int decode_init(AVCodecContext * avctx)
+{
+ KmvcContext *const c = (KmvcContext *) avctx->priv_data;
+ int i;
+
+ c->avctx = avctx;
+ avctx->has_b_frames = 0;
+
+ c->pic.data[0] = NULL;
+
+ if (avctx->width > 320 || avctx->height > 200) {
+ av_log(avctx, AV_LOG_ERROR, "KMVC supports frames <= 320x200\n");
+ return -1;
+ }
+
+ 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] = i * 0x10101;
+ }
+
+ if (avctx->extradata_size < 12) {
+ av_log(NULL, 0, "Extradata missing, decoding may not work properly...\n");
+ c->palsize = 127;
+ } else {
+ c->palsize = LE_16(avctx->extradata + 10);
+ }
+
+ if (avctx->extradata_size == 1036) { // palette in extradata
+ uint8_t *src = avctx->extradata + 12;
+ for (i = 0; i < 256; i++) {
+ c->pal[i] = LE_32(src);
+ src += 4;
+ }
+ c->setpal = 1;
+ if (c->avctx->palctrl) {
+ c->avctx->palctrl->palette_changed = 0;
+ }
+ }
+
+ avctx->pix_fmt = PIX_FMT_PAL8;
+
+ return 0;
+}
+
+
+
+/*
+ * Uninit kmvc decoder
+ */
+static int decode_end(AVCodecContext * avctx)
+{
+ KmvcContext *const c = (KmvcContext *) avctx->priv_data;
+
+ av_freep(&c->frm0);
+ av_freep(&c->frm1);
+ if (c->pic.data[0])
+ avctx->release_buffer(avctx, &c->pic);
+
+ return 0;
+}
+
+AVCodec kmvc_decoder = {
+ "kmvc",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_KMVC,
+ sizeof(KmvcContext),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame
+};
diff --git a/contrib/ffmpeg/libavcodec/lcl.c b/contrib/ffmpeg/libavcodec/lcl.c
new file mode 100644
index 000000000..b02ea1543
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/lcl.c
@@ -0,0 +1,928 @@
+/*
+ * 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.c
+ * 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 <stdio.h>
+#include <stdlib.h>
+
+#include "common.h"
+#include "bitstream.h"
+#include "avcodec.h"
+
+#ifdef CONFIG_ZLIB
+#include <zlib.h>
+#endif
+
+
+#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
+
+#define FOURCC_MSZH mmioFOURCC('M','S','Z','H')
+#define FOURCC_ZLIB mmioFOURCC('Z','L','I','B')
+
+/*
+ * Decoder context
+ */
+typedef struct LclContext {
+
+ AVCodecContext *avctx;
+ AVFrame pic;
+ PutBitContext pb;
+
+ // Image type
+ int imgtype;
+ // Compression type
+ int compression;
+ // Flags
+ int flags;
+ // Decompressed data size
+ unsigned int decomp_size;
+ // Decompression buffer
+ unsigned char* decomp_buf;
+ // Maximum compressed data size
+ unsigned int max_comp_size;
+ // Compression buffer
+ unsigned char* comp_buf;
+#ifdef CONFIG_ZLIB
+ z_stream zstream;
+#endif
+} LclContext;
+
+
+/*
+ *
+ * Helper functions
+ *
+ */
+static inline unsigned char fix (int pix14)
+{
+ int tmp;
+
+ tmp = (pix14 + 0x80000) >> 20;
+ if (tmp < 0)
+ return 0;
+ if (tmp > 255)
+ return 255;
+ return tmp;
+}
+
+
+
+static inline unsigned char get_b (unsigned char yq, signed char bq)
+{
+ return fix((yq << 20) + bq * 1858076);
+}
+
+
+
+static inline unsigned char get_g (unsigned char yq, signed char bq, signed char rq)
+{
+ return fix((yq << 20) - bq * 360857 - rq * 748830);
+}
+
+
+
+static inline unsigned char get_r (unsigned char yq, signed char rq)
+{
+ return fix((yq << 20) + rq * 1470103);
+}
+
+
+
+static unsigned int mszh_decomp(unsigned char * srcptr, int srclen, unsigned char * destptr, unsigned int destsize)
+{
+ unsigned char *destptr_bak = destptr;
+ unsigned char *destptr_end = destptr + destsize;
+ unsigned char mask = 0;
+ unsigned char maskbit = 0;
+ unsigned int ofs, cnt;
+
+ while ((srclen > 0) && (destptr < destptr_end)) {
+ if (maskbit == 0) {
+ mask = *(srcptr++);
+ maskbit = 8;
+ srclen--;
+ continue;
+ }
+ if ((mask & (1 << (--maskbit))) == 0) {
+ if (destptr + 4 > destptr_end)
+ break;
+ *(int*)destptr = *(int*)srcptr;
+ srclen -= 4;
+ destptr += 4;
+ srcptr += 4;
+ } else {
+ ofs = *(srcptr++);
+ cnt = *(srcptr++);
+ ofs += cnt * 256;;
+ cnt = ((cnt >> 3) & 0x1f) + 1;
+ ofs &= 0x7ff;
+ srclen -= 2;
+ cnt *= 4;
+ if (destptr + cnt > destptr_end) {
+ cnt = destptr_end - destptr;
+ }
+ for (; cnt > 0; cnt--) {
+ *(destptr) = *(destptr - ofs);
+ destptr++;
+ }
+ }
+ }
+
+ return (destptr - destptr_bak);
+}
+
+
+
+#ifdef CONFIG_DECODERS
+/*
+ *
+ * Decode a frame
+ *
+ */
+static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size)
+{
+ LclContext * const c = (LclContext *)avctx->priv_data;
+ unsigned char *encoded = (unsigned char *)buf;
+ unsigned int pixel_ptr;
+ int row, col;
+ unsigned char *outptr;
+ 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;
+ unsigned int mthread_inlen, mthread_outlen;
+#ifdef CONFIG_ZLIB
+ int zret; // Zlib return code
+#endif
+ unsigned int len = buf_size;
+
+ if(c->pic.data[0])
+ avctx->release_buffer(avctx, &c->pic);
+
+ c->pic.reference = 0;
+ c->pic.buffer_hints = FF_BUFFER_HINTS_VALID;
+ if(avctx->get_buffer(avctx, &c->pic) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ outptr = c->pic.data[0]; // Output image pointer
+
+ /* Decompress frame */
+ switch (avctx->codec_id) {
+ case CODEC_ID_MSZH:
+ switch (c->compression) {
+ case COMP_MSZH:
+ if (c->flags & FLAG_MULTITHREAD) {
+ mthread_inlen = *((unsigned int*)encoded);
+ mthread_outlen = *((unsigned int*)(encoded+4));
+ if (mthread_outlen > c->decomp_size) // this should not happen
+ 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 -1;
+ }
+ mszh_dlen = mszh_decomp(encoded + 8 + mthread_inlen, len - 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 -1;
+ }
+ 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 -1;
+ }
+ encoded = c->decomp_buf;
+ len = mszh_dlen;
+ }
+ break;
+ case COMP_MSZH_NOCOMP:
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "BUG! Unknown MSZH compression in frame decoder.\n");
+ return -1;
+ }
+ break;
+ case CODEC_ID_ZLIB:
+#ifdef CONFIG_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))
+ break;
+ zret = inflateReset(&(c->zstream));
+ if (zret != Z_OK) {
+ av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret);
+ return -1;
+ }
+ if (c->flags & FLAG_MULTITHREAD) {
+ mthread_inlen = *((unsigned int*)encoded);
+ mthread_outlen = *((unsigned int*)(encoded+4));
+ if (mthread_outlen > c->decomp_size)
+ mthread_outlen = c->decomp_size;
+ c->zstream.next_in = encoded + 8;
+ c->zstream.avail_in = mthread_inlen;
+ c->zstream.next_out = c->decomp_buf;
+ c->zstream.avail_out = c->decomp_size;
+ zret = inflate(&(c->zstream), Z_FINISH);
+ if ((zret != Z_OK) && (zret != Z_STREAM_END)) {
+ av_log(avctx, AV_LOG_ERROR, "Mthread1 inflate error: %d\n", zret);
+ return -1;
+ }
+ if (mthread_outlen != (unsigned int)(c->zstream.total_out)) {
+ av_log(avctx, AV_LOG_ERROR, "Mthread1 decoded size differs (%u != %lu)\n",
+ mthread_outlen, c->zstream.total_out);
+ return -1;
+ }
+ zret = inflateReset(&(c->zstream));
+ if (zret != Z_OK) {
+ av_log(avctx, AV_LOG_ERROR, "Mthread2 inflate reset error: %d\n", zret);
+ return -1;
+ }
+ c->zstream.next_in = encoded + 8 + mthread_inlen;
+ c->zstream.avail_in = len - mthread_inlen;
+ c->zstream.next_out = c->decomp_buf + mthread_outlen;
+ c->zstream.avail_out = c->decomp_size - mthread_outlen;
+ zret = inflate(&(c->zstream), Z_FINISH);
+ if ((zret != Z_OK) && (zret != Z_STREAM_END)) {
+ av_log(avctx, AV_LOG_ERROR, "Mthread2 inflate error: %d\n", zret);
+ return -1;
+ }
+ if (mthread_outlen != (unsigned int)(c->zstream.total_out)) {
+ av_log(avctx, AV_LOG_ERROR, "Mthread2 decoded size differs (%d != %lu)\n",
+ mthread_outlen, c->zstream.total_out);
+ return -1;
+ }
+ } else {
+ c->zstream.next_in = 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);
+ if ((zret != Z_OK) && (zret != Z_STREAM_END)) {
+ av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", zret);
+ return -1;
+ }
+ if (c->decomp_size != (unsigned int)(c->zstream.total_out)) {
+ av_log(avctx, AV_LOG_ERROR, "Decoded size differs (%d != %lu)\n",
+ c->decomp_size, c->zstream.total_out);
+ return -1;
+ }
+ }
+ encoded = c->decomp_buf;
+ len = c->decomp_size;;
+#else
+ av_log(avctx, AV_LOG_ERROR, "BUG! Zlib support not compiled in frame decoder.\n");
+ return -1;
+#endif
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "BUG! Unknown codec in frame decoder compression switch.\n");
+ return -1;
+ }
+
+
+ /* Apply PNG filter */
+ if ((avctx->codec_id == 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 = encoded[pixel_ptr++];
+ uqvq+=(encoded[pixel_ptr++] << 8);
+ for (col = 1; col < width; col++) {
+ encoded[pixel_ptr] = yq -= encoded[pixel_ptr];
+ uqvq -= (encoded[pixel_ptr+1] | (encoded[pixel_ptr+2]<<8));
+ encoded[pixel_ptr+1] = (uqvq) & 0xff;
+ encoded[pixel_ptr+2] = ((uqvq)>>8) & 0xff;
+ 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 -1;
+ }
+ }
+
+ /* Convert colorspace */
+ switch (c->imgtype) {
+ case IMGTYPE_YUV111:
+ for (row = height - 1; row >= 0; row--) {
+ pixel_ptr = row * c->pic.linesize[0];
+ for (col = 0; col < width; col++) {
+ outptr[pixel_ptr++] = get_b(encoded[0], encoded[1]);
+ outptr[pixel_ptr++] = get_g(encoded[0], encoded[1], encoded[2]);
+ outptr[pixel_ptr++] = get_r(encoded[0], encoded[2]);
+ encoded += 3;
+ }
+ }
+ break;
+ case IMGTYPE_YUV422:
+ for (row = height - 1; row >= 0; row--) {
+ pixel_ptr = row * c->pic.linesize[0];
+ for (col = 0; col < width/4; col++) {
+ outptr[pixel_ptr++] = get_b(encoded[0], encoded[4]);
+ outptr[pixel_ptr++] = get_g(encoded[0], encoded[4], encoded[6]);
+ outptr[pixel_ptr++] = get_r(encoded[0], encoded[6]);
+ outptr[pixel_ptr++] = get_b(encoded[1], encoded[4]);
+ outptr[pixel_ptr++] = get_g(encoded[1], encoded[4], encoded[6]);
+ outptr[pixel_ptr++] = get_r(encoded[1], encoded[6]);
+ outptr[pixel_ptr++] = get_b(encoded[2], encoded[5]);
+ outptr[pixel_ptr++] = get_g(encoded[2], encoded[5], encoded[7]);
+ outptr[pixel_ptr++] = get_r(encoded[2], encoded[7]);
+ outptr[pixel_ptr++] = get_b(encoded[3], encoded[5]);
+ outptr[pixel_ptr++] = get_g(encoded[3], encoded[5], encoded[7]);
+ outptr[pixel_ptr++] = get_r(encoded[3], encoded[7]);
+ encoded += 8;
+ }
+ }
+ break;
+ case IMGTYPE_RGB24:
+ for (row = height - 1; row >= 0; row--) {
+ pixel_ptr = row * c->pic.linesize[0];
+ for (col = 0; col < width; col++) {
+ outptr[pixel_ptr++] = encoded[0];
+ outptr[pixel_ptr++] = encoded[1];
+ outptr[pixel_ptr++] = encoded[2];
+ encoded += 3;
+ }
+ }
+ break;
+ case IMGTYPE_YUV411:
+ for (row = height - 1; row >= 0; row--) {
+ pixel_ptr = row * c->pic.linesize[0];
+ for (col = 0; col < width/4; col++) {
+ outptr[pixel_ptr++] = get_b(encoded[0], encoded[4]);
+ outptr[pixel_ptr++] = get_g(encoded[0], encoded[4], encoded[5]);
+ outptr[pixel_ptr++] = get_r(encoded[0], encoded[5]);
+ outptr[pixel_ptr++] = get_b(encoded[1], encoded[4]);
+ outptr[pixel_ptr++] = get_g(encoded[1], encoded[4], encoded[5]);
+ outptr[pixel_ptr++] = get_r(encoded[1], encoded[5]);
+ outptr[pixel_ptr++] = get_b(encoded[2], encoded[4]);
+ outptr[pixel_ptr++] = get_g(encoded[2], encoded[4], encoded[5]);
+ outptr[pixel_ptr++] = get_r(encoded[2], encoded[5]);
+ outptr[pixel_ptr++] = get_b(encoded[3], encoded[4]);
+ outptr[pixel_ptr++] = get_g(encoded[3], encoded[4], encoded[5]);
+ outptr[pixel_ptr++] = get_r(encoded[3], encoded[5]);
+ encoded += 6;
+ }
+ }
+ break;
+ case IMGTYPE_YUV211:
+ for (row = height - 1; row >= 0; row--) {
+ pixel_ptr = row * c->pic.linesize[0];
+ for (col = 0; col < width/2; col++) {
+ outptr[pixel_ptr++] = get_b(encoded[0], encoded[2]);
+ outptr[pixel_ptr++] = get_g(encoded[0], encoded[2], encoded[3]);
+ outptr[pixel_ptr++] = get_r(encoded[0], encoded[3]);
+ outptr[pixel_ptr++] = get_b(encoded[1], encoded[2]);
+ outptr[pixel_ptr++] = get_g(encoded[1], encoded[2], encoded[3]);
+ outptr[pixel_ptr++] = get_r(encoded[1], encoded[3]);
+ encoded += 4;
+ }
+ }
+ break;
+ case IMGTYPE_YUV420:
+ for (row = height / 2 - 1; row >= 0; row--) {
+ pixel_ptr = 2 * row * c->pic.linesize[0];
+ for (col = 0; col < width/2; col++) {
+ outptr[pixel_ptr] = get_b(encoded[0], encoded[4]);
+ outptr[pixel_ptr+1] = get_g(encoded[0], encoded[4], encoded[5]);
+ outptr[pixel_ptr+2] = get_r(encoded[0], encoded[5]);
+ outptr[pixel_ptr+3] = get_b(encoded[1], encoded[4]);
+ outptr[pixel_ptr+4] = get_g(encoded[1], encoded[4], encoded[5]);
+ outptr[pixel_ptr+5] = get_r(encoded[1], encoded[5]);
+ outptr[pixel_ptr-c->pic.linesize[0]] = get_b(encoded[2], encoded[4]);
+ outptr[pixel_ptr-c->pic.linesize[0]+1] = get_g(encoded[2], encoded[4], encoded[5]);
+ outptr[pixel_ptr-c->pic.linesize[0]+2] = get_r(encoded[2], encoded[5]);
+ outptr[pixel_ptr-c->pic.linesize[0]+3] = get_b(encoded[3], encoded[4]);
+ outptr[pixel_ptr-c->pic.linesize[0]+4] = get_g(encoded[3], encoded[4], encoded[5]);
+ outptr[pixel_ptr-c->pic.linesize[0]+5] = get_r(encoded[3], encoded[5]);
+ pixel_ptr += 6;
+ encoded += 6;
+ }
+ }
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "BUG! Unknown imagetype in image decoder.\n");
+ return -1;
+ }
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = c->pic;
+
+ /* always report that the buffer was completely consumed */
+ return buf_size;
+}
+#endif
+
+#ifdef CONFIG_ENCODERS
+/*
+ *
+ * Encode a frame
+ *
+ */
+static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
+ LclContext *c = avctx->priv_data;
+ AVFrame *pict = data;
+ AVFrame * const p = &c->pic;
+ int i;
+ int zret; // Zlib return code
+
+#ifndef CONFIG_ZLIB
+ av_log(avctx, AV_LOG_ERROR, "Zlib support not compiled in.\n");
+ return -1;
+#else
+
+ init_put_bits(&c->pb, buf, buf_size);
+
+ *p = *pict;
+ p->pict_type= FF_I_TYPE;
+ p->key_frame= 1;
+
+ if(avctx->pix_fmt != 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 = c->comp_buf;
+ c->zstream.avail_out = c->max_comp_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;
+ }
+
+ for (i = 0; i < c->zstream.total_out; i++)
+ put_bits(&c->pb, 8, c->comp_buf[i]);
+ flush_put_bits(&c->pb);
+
+ return c->zstream.total_out;
+#endif
+}
+#endif /* CONFIG_ENCODERS */
+
+#ifdef CONFIG_DECODERS
+/*
+ *
+ * Init lcl decoder
+ *
+ */
+static int decode_init(AVCodecContext *avctx)
+{
+ LclContext * const c = (LclContext *)avctx->priv_data;
+ unsigned int basesize = avctx->width * avctx->height;
+ unsigned int max_basesize = ((avctx->width + 3) & ~3) * ((avctx->height + 3) & ~3);
+ unsigned int max_decomp_size;
+ int zret; // Zlib return code
+
+ c->avctx = avctx;
+ avctx->has_b_frames = 0;
+
+ c->pic.data[0] = NULL;
+
+#ifdef CONFIG_ZLIB
+ // Needed if zlib unused or init aborted before inflateInit
+ memset(&(c->zstream), 0, sizeof(z_stream));
+#endif
+
+ if (avctx->extradata_size < 8) {
+ av_log(avctx, AV_LOG_ERROR, "Extradata size too small.\n");
+ return 1;
+ }
+
+ if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
+ return 1;
+ }
+
+ /* Check codec type */
+ if (((avctx->codec_id == CODEC_ID_MSZH) && (*((char *)avctx->extradata + 7) != CODEC_MSZH)) ||
+ ((avctx->codec_id == CODEC_ID_ZLIB) && (*((char *)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 = *((char *)avctx->extradata + 4)) {
+ case IMGTYPE_YUV111:
+ c->decomp_size = basesize * 3;
+ max_decomp_size = max_basesize * 3;
+ av_log(avctx, AV_LOG_INFO, "Image type is YUV 1:1:1.\n");
+ break;
+ case IMGTYPE_YUV422:
+ c->decomp_size = basesize * 2;
+ max_decomp_size = max_basesize * 2;
+ av_log(avctx, AV_LOG_INFO, "Image type is YUV 4:2:2.\n");
+ break;
+ case IMGTYPE_RGB24:
+ c->decomp_size = basesize * 3;
+ max_decomp_size = max_basesize * 3;
+ av_log(avctx, AV_LOG_INFO, "Image type is RGB 24.\n");
+ break;
+ case IMGTYPE_YUV411:
+ c->decomp_size = basesize / 2 * 3;
+ max_decomp_size = max_basesize / 2 * 3;
+ av_log(avctx, AV_LOG_INFO, "Image type is YUV 4:1:1.\n");
+ break;
+ case IMGTYPE_YUV211:
+ c->decomp_size = basesize * 2;
+ max_decomp_size = max_basesize * 2;
+ av_log(avctx, AV_LOG_INFO, "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;
+ av_log(avctx, AV_LOG_INFO, "Image type is YUV 4:2:0.\n");
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "Unsupported image format %d.\n", c->imgtype);
+ return 1;
+ }
+
+ /* Detect compression method */
+ c->compression = *((char *)avctx->extradata + 5);
+ switch (avctx->codec_id) {
+ case CODEC_ID_MSZH:
+ switch (c->compression) {
+ case COMP_MSZH:
+ av_log(avctx, AV_LOG_INFO, "Compression enabled.\n");
+ break;
+ case COMP_MSZH_NOCOMP:
+ c->decomp_size = 0;
+ av_log(avctx, AV_LOG_INFO, "No compression.\n");
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "Unsupported compression format for MSZH (%d).\n", c->compression);
+ return 1;
+ }
+ break;
+ case CODEC_ID_ZLIB:
+#ifdef CONFIG_ZLIB
+ switch (c->compression) {
+ case COMP_ZLIB_HISPEED:
+ av_log(avctx, AV_LOG_INFO, "High speed compression.\n");
+ break;
+ case COMP_ZLIB_HICOMP:
+ av_log(avctx, AV_LOG_INFO, "High compression.\n");
+ break;
+ case COMP_ZLIB_NORMAL:
+ av_log(avctx, AV_LOG_INFO, "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 1;
+ }
+ av_log(avctx, AV_LOG_INFO, "Compression level for ZLIB: (%d).\n", c->compression);
+ }
+#else
+ av_log(avctx, AV_LOG_ERROR, "Zlib support not compiled.\n");
+ return 1;
+#endif
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "BUG! Unknown codec in compression switch.\n");
+ return 1;
+ }
+
+ /* 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 1;
+ }
+ }
+
+ /* Detect flags */
+ c->flags = *((char *)avctx->extradata + 6);
+ if (c->flags & FLAG_MULTITHREAD)
+ av_log(avctx, AV_LOG_INFO, "Multithread encoder flag set.\n");
+ if (c->flags & FLAG_NULLFRAME)
+ av_log(avctx, AV_LOG_INFO, "Nullframe insertion flag set.\n");
+ if ((avctx->codec_id == CODEC_ID_ZLIB) && (c->flags & FLAG_PNGFILTER))
+ av_log(avctx, AV_LOG_INFO, "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 (avctx->codec_id == CODEC_ID_ZLIB) {
+#ifdef CONFIG_ZLIB
+ 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 1;
+ }
+#else
+ av_log(avctx, AV_LOG_ERROR, "Zlib support not compiled.\n");
+ return 1;
+#endif
+ }
+
+ avctx->pix_fmt = PIX_FMT_BGR24;
+
+ return 0;
+}
+#endif /* CONFIG_DECODERS */
+
+#ifdef CONFIG_ENCODERS
+/*
+ *
+ * Init lcl encoder
+ *
+ */
+static int encode_init(AVCodecContext *avctx)
+{
+ LclContext *c = avctx->priv_data;
+ int zret; // Zlib return code
+
+#ifndef CONFIG_ZLIB
+ av_log(avctx, AV_LOG_ERROR, "Zlib support not compiled.\n");
+ return 1;
+#else
+
+ c->avctx= avctx;
+
+ assert(avctx->width && avctx->height);
+
+ avctx->extradata= av_mallocz(8);
+ avctx->coded_frame= &c->pic;
+
+ // Will be user settable someday
+ c->compression = 6;
+ c->flags = 0;
+
+ switch(avctx->pix_fmt){
+ case PIX_FMT_BGR24:
+ c->imgtype = IMGTYPE_RGB24;
+ c->decomp_size = avctx->width * avctx->height * 3;
+ avctx->bits_per_sample= 24;
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "Format %d not supported\n", avctx->pix_fmt);
+ return -1;
+ }
+
+ ((uint8_t*)avctx->extradata)[0]= 4;
+ ((uint8_t*)avctx->extradata)[1]= 0;
+ ((uint8_t*)avctx->extradata)[2]= 0;
+ ((uint8_t*)avctx->extradata)[3]= 0;
+ ((uint8_t*)avctx->extradata)[4]= c->imgtype;
+ ((uint8_t*)avctx->extradata)[5]= c->compression;
+ ((uint8_t*)avctx->extradata)[6]= c->flags;
+ ((uint8_t*)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;
+ }
+
+ /* Conservative upper bound taken from zlib v1.2.1 source */
+ c->max_comp_size = c->decomp_size + ((c->decomp_size + 7) >> 3) +
+ ((c->decomp_size + 63) >> 6) + 11;
+ if ((c->comp_buf = av_malloc(c->max_comp_size)) == NULL) {
+ av_log(avctx, AV_LOG_ERROR, "Can't allocate compression buffer.\n");
+ return 1;
+ }
+
+ return 0;
+#endif
+}
+#endif /* CONFIG_ENCODERS */
+
+
+
+#ifdef CONFIG_DECODERS
+/*
+ *
+ * Uninit lcl decoder
+ *
+ */
+static int decode_end(AVCodecContext *avctx)
+{
+ LclContext * const c = (LclContext *)avctx->priv_data;
+
+ if (c->pic.data[0])
+ avctx->release_buffer(avctx, &c->pic);
+#ifdef CONFIG_ZLIB
+ inflateEnd(&(c->zstream));
+#endif
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_ENCODERS
+/*
+ *
+ * Uninit lcl encoder
+ *
+ */
+static int encode_end(AVCodecContext *avctx)
+{
+ LclContext *c = avctx->priv_data;
+
+ av_freep(&avctx->extradata);
+ av_freep(&c->comp_buf);
+#ifdef CONFIG_ZLIB
+ deflateEnd(&(c->zstream));
+#endif
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_MSZH_DECODER
+AVCodec mszh_decoder = {
+ "mszh",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MSZH,
+ sizeof(LclContext),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
+#endif
+
+#ifdef CONFIG_ZLIB_DECODER
+AVCodec zlib_decoder = {
+ "zlib",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_ZLIB,
+ sizeof(LclContext),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
+#endif
+
+#ifdef CONFIG_ENCODERS
+
+AVCodec zlib_encoder = {
+ "zlib",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_ZLIB,
+ sizeof(LclContext),
+ encode_init,
+ encode_frame,
+ encode_end,
+};
+
+#endif //CONFIG_ENCODERS
diff --git a/contrib/ffmpeg/libavcodec/liba52/a52.h b/contrib/ffmpeg/libavcodec/liba52/a52.h
new file mode 100644
index 000000000..f2ea5f836
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/liba52/a52.h
@@ -0,0 +1,73 @@
+/*
+ * a52.h
+ * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * a52dec is distributed in the hope that 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef A52_H
+#define A52_H
+
+#include "../avcodec.h"
+
+#undef malloc
+#undef free
+#undef realloc
+
+#if defined(LIBA52_FIXED)
+typedef int32_t sample_t;
+typedef int32_t level_t;
+#elif defined(LIBA52_DOUBLE)
+typedef double sample_t;
+typedef double level_t;
+#else
+typedef float sample_t;
+typedef float level_t;
+#endif
+
+typedef struct a52_state_s a52_state_t;
+
+#define A52_CHANNEL 0
+#define A52_MONO 1
+#define A52_STEREO 2
+#define A52_3F 3
+#define A52_2F1R 4
+#define A52_3F1R 5
+#define A52_2F2R 6
+#define A52_3F2R 7
+#define A52_CHANNEL1 8
+#define A52_CHANNEL2 9
+#define A52_DOLBY 10
+#define A52_CHANNEL_MASK 15
+
+#define A52_LFE 16
+#define A52_ADJUST_LEVEL 32
+
+a52_state_t * a52_init (uint32_t mm_accel);
+sample_t * a52_samples (a52_state_t * state);
+int a52_syncinfo (uint8_t * buf, int * flags,
+ int * sample_rate, int * bit_rate);
+int a52_frame (a52_state_t * state, uint8_t * buf, int * flags,
+ level_t * level, sample_t bias);
+void a52_dynrng (a52_state_t * state,
+ level_t (* call) (level_t, void *), void * data);
+int a52_block (a52_state_t * state);
+void a52_free (a52_state_t * state);
+
+#endif /* A52_H */
diff --git a/contrib/ffmpeg/libavcodec/liba52/a52_internal.h b/contrib/ffmpeg/libavcodec/liba52/a52_internal.h
new file mode 100644
index 000000000..49fd4ef99
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/liba52/a52_internal.h
@@ -0,0 +1,162 @@
+/*
+ * a52_internal.h
+ * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * a52dec is distributed in the hope that 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+typedef struct {
+ uint8_t bai; /* fine SNR offset, fast gain */
+ uint8_t deltbae; /* delta bit allocation exists */
+ int8_t deltba[50]; /* per-band delta bit allocation */
+} ba_t;
+
+typedef struct {
+ uint8_t exp[256]; /* decoded channel exponents */
+ int8_t bap[256]; /* derived channel bit allocation */
+} expbap_t;
+
+struct a52_state_s {
+ uint8_t fscod; /* sample rate */
+ uint8_t halfrate; /* halfrate factor */
+ uint8_t acmod; /* coded channels */
+ uint8_t lfeon; /* coded lfe channel */
+ level_t clev; /* centre channel mix level */
+ level_t slev; /* surround channels mix level */
+
+ int output; /* type of output */
+ level_t level; /* output level */
+ sample_t bias; /* output bias */
+
+ int dynrnge; /* apply dynamic range */
+ level_t dynrng; /* dynamic range */
+ void * dynrngdata; /* dynamic range callback funtion and data */
+ level_t (* dynrngcall) (level_t range, void * dynrngdata);
+
+ uint8_t chincpl; /* channel coupled */
+ uint8_t phsflginu; /* phase flags in use (stereo only) */
+ uint8_t cplstrtmant; /* coupling channel start mantissa */
+ uint8_t cplendmant; /* coupling channel end mantissa */
+ uint32_t cplbndstrc; /* coupling band structure */
+ level_t cplco[5][18]; /* coupling coordinates */
+
+ /* derived information */
+ uint8_t cplstrtbnd; /* coupling start band (for bit allocation) */
+ uint8_t ncplbnd; /* number of coupling bands */
+
+ uint8_t rematflg; /* stereo rematrixing */
+
+ uint8_t endmant[5]; /* channel end mantissa */
+
+ uint16_t bai; /* bit allocation information */
+
+ uint32_t * buffer_start;
+ uint16_t lfsr_state; /* dither state */
+ uint32_t bits_left;
+ uint32_t current_word;
+
+ uint8_t csnroffst; /* coarse SNR offset */
+ ba_t cplba; /* coupling bit allocation parameters */
+ ba_t ba[5]; /* channel bit allocation parameters */
+ ba_t lfeba; /* lfe bit allocation parameters */
+
+ uint8_t cplfleak; /* coupling fast leak init */
+ uint8_t cplsleak; /* coupling slow leak init */
+
+ expbap_t cpl_expbap;
+ expbap_t fbw_expbap[5];
+ expbap_t lfe_expbap;
+
+ sample_t * samples;
+ int downmixed;
+};
+
+#define LEVEL_PLUS6DB 2.0
+#define LEVEL_PLUS3DB 1.4142135623730951
+#define LEVEL_3DB 0.7071067811865476
+#define LEVEL_45DB 0.5946035575013605
+#define LEVEL_6DB 0.5
+
+#define EXP_REUSE (0)
+#define EXP_D15 (1)
+#define EXP_D25 (2)
+#define EXP_D45 (3)
+
+#define DELTA_BIT_REUSE (0)
+#define DELTA_BIT_NEW (1)
+#define DELTA_BIT_NONE (2)
+#define DELTA_BIT_RESERVED (3)
+
+void a52_bit_allocate (a52_state_t * state, ba_t * ba, int bndstart,
+ int start, int end, int fastleak, int slowleak,
+ expbap_t * expbap);
+
+int a52_downmix_init (int input, int flags, level_t * level,
+ level_t clev, level_t slev);
+int a52_downmix_coeff (level_t * coeff, int acmod, int output, level_t level,
+ level_t clev, level_t slev);
+void a52_downmix (sample_t * samples, int acmod, int output, sample_t bias,
+ level_t clev, level_t slev);
+void a52_upmix (sample_t * samples, int acmod, int output);
+
+void a52_imdct_init (uint32_t mm_accel);
+void a52_imdct_256 (sample_t * data, sample_t * delay, sample_t bias);
+void a52_imdct_512 (sample_t * data, sample_t * delay, sample_t bias);
+//extern void (* a52_imdct_256) (sample_t data[], sample_t delay[], sample_t bias);
+//extern void (* a52_imdct_512) (sample_t data[], sample_t delay[], sample_t bias);
+
+#define ROUND(x) ((int)((x) + ((x) > 0 ? 0.5 : -0.5)))
+
+#ifndef LIBA52_FIXED
+
+typedef sample_t quantizer_t;
+#define SAMPLE(x) (x)
+#define LEVEL(x) (x)
+#define MUL(a,b) ((a) * (b))
+#define MUL_L(a,b) ((a) * (b))
+#define MUL_C(a,b) ((a) * (b))
+#define DIV(a,b) ((a) / (b))
+#define BIAS(x) ((x) + bias)
+
+#else /* LIBA52_FIXED */
+
+typedef int16_t quantizer_t;
+#define SAMPLE(x) (sample_t)((x) * (1 << 30))
+#define LEVEL(x) (level_t)((x) * (1 << 26))
+
+#if 0
+#define MUL(a,b) ((int)(((int64_t)(a) * (b) + (1 << 29)) >> 30))
+#define MUL_L(a,b) ((int)(((int64_t)(a) * (b) + (1 << 25)) >> 26))
+#elif 1
+#define MUL(a,b) \
+({ int32_t _ta=(a), _tb=(b), _tc; \
+ _tc=(_ta & 0xffff)*(_tb >> 16)+(_ta >> 16)*(_tb & 0xffff); (int32_t)(((_tc >> 14))+ (((_ta >> 16)*(_tb >> 16)) << 2 )); })
+#define MUL_L(a,b) \
+({ int32_t _ta=(a), _tb=(b), _tc; \
+ _tc=(_ta & 0xffff)*(_tb >> 16)+(_ta >> 16)*(_tb & 0xffff); (int32_t)((_tc >> 10) + (((_ta >> 16)*(_tb >> 16)) << 6)); })
+#else
+#define MUL(a,b) (((a) >> 15) * ((b) >> 15))
+#define MUL_L(a,b) (((a) >> 13) * ((b) >> 13))
+#endif
+
+#define MUL_C(a,b) MUL_L (a, LEVEL (b))
+#define DIV(a,b) ((((int64_t)LEVEL (a)) << 26) / (b))
+#define BIAS(x) (x)
+
+#endif
diff --git a/contrib/ffmpeg/libavcodec/liba52/a52_util.h b/contrib/ffmpeg/libavcodec/liba52/a52_util.h
new file mode 100644
index 000000000..8ef2cece9
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/liba52/a52_util.h
@@ -0,0 +1,32 @@
+/*
+ * a52_util.h
+ * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * a52dec is distributed in the hope that 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef A52_UTIL_H
+#define A52_UTIL_H
+
+uint16_t a52_crc16_block(uint8_t *data,uint32_t num_bytes);
+
+void* a52_resample_init(uint32_t mm_accel,int flags,int chans);
+extern int (* a52_resample) (float * _f, int16_t * s16);
+
+#endif /* A52_H */
diff --git a/contrib/ffmpeg/libavcodec/liba52/bit_allocate.c b/contrib/ffmpeg/libavcodec/liba52/bit_allocate.c
new file mode 100644
index 000000000..415a08d21
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/liba52/bit_allocate.c
@@ -0,0 +1,260 @@
+/*
+ * bit_allocate.c
+ * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * a52dec is distributed in the hope that 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "a52.h"
+#include "a52_internal.h"
+
+static int hthtab[3][50] = {
+ {0x730, 0x730, 0x7c0, 0x800, 0x820, 0x840, 0x850, 0x850, 0x860, 0x860,
+ 0x860, 0x860, 0x860, 0x870, 0x870, 0x870, 0x880, 0x880, 0x890, 0x890,
+ 0x8a0, 0x8a0, 0x8b0, 0x8b0, 0x8c0, 0x8c0, 0x8d0, 0x8e0, 0x8f0, 0x900,
+ 0x910, 0x910, 0x910, 0x910, 0x900, 0x8f0, 0x8c0, 0x870, 0x820, 0x7e0,
+ 0x7a0, 0x770, 0x760, 0x7a0, 0x7c0, 0x7c0, 0x6e0, 0x400, 0x3c0, 0x3c0},
+ {0x710, 0x710, 0x7a0, 0x7f0, 0x820, 0x830, 0x840, 0x850, 0x850, 0x860,
+ 0x860, 0x860, 0x860, 0x860, 0x870, 0x870, 0x870, 0x880, 0x880, 0x880,
+ 0x890, 0x890, 0x8a0, 0x8a0, 0x8b0, 0x8b0, 0x8c0, 0x8c0, 0x8e0, 0x8f0,
+ 0x900, 0x910, 0x910, 0x910, 0x910, 0x900, 0x8e0, 0x8b0, 0x870, 0x820,
+ 0x7e0, 0x7b0, 0x760, 0x770, 0x7a0, 0x7c0, 0x780, 0x5d0, 0x3c0, 0x3c0},
+ {0x680, 0x680, 0x750, 0x7b0, 0x7e0, 0x810, 0x820, 0x830, 0x840, 0x850,
+ 0x850, 0x850, 0x860, 0x860, 0x860, 0x860, 0x860, 0x860, 0x860, 0x860,
+ 0x870, 0x870, 0x870, 0x870, 0x880, 0x880, 0x880, 0x890, 0x8a0, 0x8b0,
+ 0x8c0, 0x8d0, 0x8e0, 0x8f0, 0x900, 0x910, 0x910, 0x910, 0x900, 0x8f0,
+ 0x8d0, 0x8b0, 0x840, 0x7f0, 0x790, 0x760, 0x7a0, 0x7c0, 0x7b0, 0x720}
+};
+
+static int8_t baptab[305] = {
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, /* 93 padding elems */
+
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 14, 14, 14, 14, 14,
+ 14, 12, 12, 12, 12, 11, 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, 4, 4, -3, -3, 3, 3, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0 /* 148 padding elems */
+};
+
+static int bndtab[30] = {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};
+
+static int8_t latab[256] = {
+ -64, -63, -62, -61, -60, -59, -58, -57, -56, -55, -54, -53,
+ -52, -52, -51, -50, -49, -48, -47, -47, -46, -45, -44, -44,
+ -43, -42, -41, -41, -40, -39, -38, -38, -37, -36, -36, -35,
+ -35, -34, -33, -33, -32, -32, -31, -30, -30, -29, -29, -28,
+ -28, -27, -27, -26, -26, -25, -25, -24, -24, -23, -23, -22,
+ -22, -21, -21, -21, -20, -20, -19, -19, -19, -18, -18, -18,
+ -17, -17, -17, -16, -16, -16, -15, -15, -15, -14, -14, -14,
+ -13, -13, -13, -13, -12, -12, -12, -12, -11, -11, -11, -11,
+ -10, -10, -10, -10, -10, -9, -9, -9, -9, -9, -8, -8,
+ -8, -8, -8, -8, -7, -7, -7, -7, -7, -7, -6, -6,
+ -6, -6, -6, -6, -6, -6, -5, -5, -5, -5, -5, -5,
+ -5, -5, -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, -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, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+
+#define UPDATE_LEAK() \
+do { \
+ fastleak += fdecay; \
+ if (fastleak > psd + fgain) \
+ fastleak = psd + fgain; \
+ slowleak += sdecay; \
+ if (slowleak > psd + sgain) \
+ slowleak = psd + sgain; \
+} while (0)
+
+#define COMPUTE_MASK() \
+do { \
+ if (psd > dbknee) \
+ mask -= (psd - dbknee) >> 2; \
+ if (mask > hth [i >> halfrate]) \
+ mask = hth [i >> halfrate]; \
+ mask -= snroffset + 128 * deltba[i]; \
+ mask = (mask > 0) ? 0 : ((-mask) >> 5); \
+ mask -= floor; \
+} while (0)
+
+void a52_bit_allocate (a52_state_t * state, ba_t * ba, int bndstart,
+ int start, int end, int fastleak, int slowleak,
+ expbap_t * expbap)
+{
+ static int slowgain[4] = {0x540, 0x4d8, 0x478, 0x410};
+ static int dbpbtab[4] = {0xc00, 0x500, 0x300, 0x100};
+ static int floortab[8] = {0x910, 0x950, 0x990, 0x9d0,
+ 0xa10, 0xa90, 0xb10, 0x1400};
+
+ int i, j;
+ uint8_t * exp;
+ int8_t * bap;
+ int fdecay, fgain, sdecay, sgain, dbknee, floor, snroffset;
+ int psd, mask;
+ int8_t * deltba;
+ int * hth;
+ int halfrate;
+
+ halfrate = state->halfrate;
+ fdecay = (63 + 20 * ((state->bai >> 7) & 3)) >> halfrate; /* fdcycod */
+ fgain = 128 + 128 * (ba->bai & 7); /* fgaincod */
+ sdecay = (15 + 2 * (state->bai >> 9)) >> halfrate; /* sdcycod */
+ sgain = slowgain[(state->bai >> 5) & 3]; /* sgaincod */
+ dbknee = dbpbtab[(state->bai >> 3) & 3]; /* dbpbcod */
+ hth = hthtab[state->fscod];
+ /*
+ * if there is no delta bit allocation, make deltba point to an area
+ * known to contain zeroes. baptab+156 here.
+ */
+ deltba = (ba->deltbae == DELTA_BIT_NONE) ? baptab + 156 : ba->deltba;
+ floor = floortab[state->bai & 7]; /* floorcod */
+ snroffset = 960 - 64 * state->csnroffst - 4 * (ba->bai >> 3) + floor;
+ floor >>= 5;
+
+ exp = expbap->exp;
+ bap = expbap->bap;
+
+ i = bndstart;
+ j = start;
+ if (start == 0) { /* not the coupling channel */
+ int lowcomp;
+
+ lowcomp = 0;
+ j = end - 1;
+ do {
+ if (i < j) {
+ if (exp[i+1] == exp[i] - 2)
+ lowcomp = 384;
+ else if (lowcomp && (exp[i+1] > exp[i]))
+ lowcomp -= 64;
+ }
+ psd = 128 * exp[i];
+ mask = psd + fgain + lowcomp;
+ COMPUTE_MASK ();
+ bap[i] = (baptab+156)[mask + 4 * exp[i]];
+ i++;
+ } while ((i < 3) || ((i < 7) && (exp[i] > exp[i-1])));
+ fastleak = psd + fgain;
+ slowleak = psd + sgain;
+
+ while (i < 7) {
+ if (i < j) {
+ if (exp[i+1] == exp[i] - 2)
+ lowcomp = 384;
+ else if (lowcomp && (exp[i+1] > exp[i]))
+ lowcomp -= 64;
+ }
+ psd = 128 * exp[i];
+ UPDATE_LEAK ();
+ mask = ((fastleak + lowcomp < slowleak) ?
+ fastleak + lowcomp : slowleak);
+ COMPUTE_MASK ();
+ bap[i] = (baptab+156)[mask + 4 * exp[i]];
+ i++;
+ }
+
+ if (end == 7) /* lfe channel */
+ return;
+
+ do {
+ if (exp[i+1] == exp[i] - 2)
+ lowcomp = 320;
+ else if (lowcomp && (exp[i+1] > exp[i]))
+ lowcomp -= 64;
+ psd = 128 * exp[i];
+ UPDATE_LEAK ();
+ mask = ((fastleak + lowcomp < slowleak) ?
+ fastleak + lowcomp : slowleak);
+ COMPUTE_MASK ();
+ bap[i] = (baptab+156)[mask + 4 * exp[i]];
+ i++;
+ } while (i < 20);
+
+ while (lowcomp > 128) { /* two iterations maximum */
+ lowcomp -= 128;
+ psd = 128 * exp[i];
+ UPDATE_LEAK ();
+ mask = ((fastleak + lowcomp < slowleak) ?
+ fastleak + lowcomp : slowleak);
+ COMPUTE_MASK ();
+ bap[i] = (baptab+156)[mask + 4 * exp[i]];
+ i++;
+ }
+ j = i;
+ }
+
+ do {
+ int startband, endband;
+
+ startband = j;
+ endband = (bndtab[i-20] < end) ? bndtab[i-20] : end;
+ psd = 128 * exp[j++];
+ while (j < endband) {
+ int next, delta;
+
+ next = 128 * exp[j++];
+ delta = next - psd;
+ switch (delta >> 9) {
+ case -6: case -5: case -4: case -3: case -2:
+ psd = next;
+ break;
+ case -1:
+ psd = next + latab[(-delta) >> 1];
+ break;
+ case 0:
+ psd += latab[delta >> 1];
+ break;
+ }
+ }
+ /* minpsd = -289 */
+ UPDATE_LEAK ();
+ mask = (fastleak < slowleak) ? fastleak : slowleak;
+ COMPUTE_MASK ();
+ i++;
+ j = startband;
+ do {
+ /* max(mask+4*exp)=147=-(minpsd+fgain-deltba-snroffset)>>5+4*exp */
+ /* min(mask+4*exp)=-156=-(sgain-deltba-snroffset)>>5 */
+ bap[j] = (baptab+156)[mask + 4 * exp[j]];
+ } while (++j < endband);
+ } while (j < end);
+}
diff --git a/contrib/ffmpeg/libavcodec/liba52/bitstream.c b/contrib/ffmpeg/libavcodec/liba52/bitstream.c
new file mode 100644
index 000000000..f6b05c5e6
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/liba52/bitstream.c
@@ -0,0 +1,91 @@
+/*
+ * bitstream.c
+ * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * a52dec is distributed in the hope that 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "a52.h"
+#include "a52_internal.h"
+#include "bitstream.h"
+
+#define BUFFER_SIZE 4096
+
+void a52_bitstream_set_ptr (a52_state_t * state, uint8_t * buf)
+{
+ int align;
+
+ align = (long)buf & 3;
+ state->buffer_start = (uint32_t *) (buf - align);
+ state->bits_left = 0;
+ state->current_word = 0;
+ bitstream_get (state, align * 8);
+}
+
+static inline void bitstream_fill_current (a52_state_t * state)
+{
+ uint32_t tmp;
+
+ tmp = *(state->buffer_start++);
+ state->current_word = swab32 (tmp);
+}
+
+/*
+ * The fast paths for _get is in the
+ * bitstream.h header file so it can be inlined.
+ *
+ * The "bottom half" of this routine is suffixed _bh
+ *
+ * -ah
+ */
+
+uint32_t a52_bitstream_get_bh (a52_state_t * state, uint32_t num_bits)
+{
+ uint32_t result;
+
+ num_bits -= state->bits_left;
+ result = ((state->current_word << (32 - state->bits_left)) >>
+ (32 - state->bits_left));
+
+ bitstream_fill_current (state);
+
+ if (num_bits != 0)
+ result = (result << num_bits) | (state->current_word >> (32 - num_bits));
+
+ state->bits_left = 32 - num_bits;
+
+ return result;
+}
+
+int32_t a52_bitstream_get_bh_2 (a52_state_t * state, uint32_t num_bits)
+{
+ int32_t result;
+
+ num_bits -= state->bits_left;
+ result = ((((int32_t)state->current_word) << (32 - state->bits_left)) >>
+ (32 - state->bits_left));
+
+ bitstream_fill_current(state);
+
+ if (num_bits != 0)
+ result = (result << num_bits) | (state->current_word >> (32 - num_bits));
+
+ state->bits_left = 32 - num_bits;
+
+ return result;
+}
diff --git a/contrib/ffmpeg/libavcodec/liba52/bitstream.h b/contrib/ffmpeg/libavcodec/liba52/bitstream.h
new file mode 100644
index 000000000..4a64bf3d9
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/liba52/bitstream.h
@@ -0,0 +1,77 @@
+/*
+ * bitstream.h
+ * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * a52dec is distributed in the hope that 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* (stolen from the kernel) */
+#ifdef WORDS_BIGENDIAN
+
+# define swab32(x) (x)
+
+#else
+
+# if 0 && defined (__i386__)
+
+# define swab32(x) __i386_swab32(x)
+ static inline const uint32_t __i386_swab32(uint32_t x)
+ {
+ __asm__("bswap %0" : "=r" (x) : "0" (x));
+ return x;
+ }
+
+# else
+
+# define swab32(x)\
+((((uint8_t*)&x)[0] << 24) | (((uint8_t*)&x)[1] << 16) | \
+ (((uint8_t*)&x)[2] << 8) | (((uint8_t*)&x)[3]))
+
+# endif
+#endif
+
+void a52_bitstream_set_ptr (a52_state_t * state, uint8_t * buf);
+uint32_t a52_bitstream_get_bh (a52_state_t * state, uint32_t num_bits);
+int32_t a52_bitstream_get_bh_2 (a52_state_t * state, uint32_t num_bits);
+
+static inline uint32_t bitstream_get (a52_state_t * state, uint32_t num_bits)
+{
+ uint32_t result;
+
+ if (num_bits < state->bits_left) {
+ result = (state->current_word << (32 - state->bits_left)) >> (32 - num_bits);
+ state->bits_left -= num_bits;
+ return result;
+ }
+
+ return a52_bitstream_get_bh (state, num_bits);
+}
+
+static inline int32_t bitstream_get_2 (a52_state_t * state, uint32_t num_bits)
+{
+ int32_t result;
+
+ if (num_bits < state->bits_left) {
+ result = (((int32_t)state->current_word) << (32 - state->bits_left)) >> (32 - num_bits);
+ state->bits_left -= num_bits;
+ return result;
+ }
+
+ return a52_bitstream_get_bh_2 (state, num_bits);
+}
diff --git a/contrib/ffmpeg/libavcodec/liba52/crc.c b/contrib/ffmpeg/libavcodec/liba52/crc.c
new file mode 100644
index 000000000..1ec4b085f
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/liba52/crc.c
@@ -0,0 +1,73 @@
+/*
+ * crc.c
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec 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; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that 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 GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+static const uint16_t crc_lut[256] =
+{
+ 0x0000,0x8005,0x800f,0x000a,0x801b,0x001e,0x0014,0x8011,
+ 0x8033,0x0036,0x003c,0x8039,0x0028,0x802d,0x8027,0x0022,
+ 0x8063,0x0066,0x006c,0x8069,0x0078,0x807d,0x8077,0x0072,
+ 0x0050,0x8055,0x805f,0x005a,0x804b,0x004e,0x0044,0x8041,
+ 0x80c3,0x00c6,0x00cc,0x80c9,0x00d8,0x80dd,0x80d7,0x00d2,
+ 0x00f0,0x80f5,0x80ff,0x00fa,0x80eb,0x00ee,0x00e4,0x80e1,
+ 0x00a0,0x80a5,0x80af,0x00aa,0x80bb,0x00be,0x00b4,0x80b1,
+ 0x8093,0x0096,0x009c,0x8099,0x0088,0x808d,0x8087,0x0082,
+ 0x8183,0x0186,0x018c,0x8189,0x0198,0x819d,0x8197,0x0192,
+ 0x01b0,0x81b5,0x81bf,0x01ba,0x81ab,0x01ae,0x01a4,0x81a1,
+ 0x01e0,0x81e5,0x81ef,0x01ea,0x81fb,0x01fe,0x01f4,0x81f1,
+ 0x81d3,0x01d6,0x01dc,0x81d9,0x01c8,0x81cd,0x81c7,0x01c2,
+ 0x0140,0x8145,0x814f,0x014a,0x815b,0x015e,0x0154,0x8151,
+ 0x8173,0x0176,0x017c,0x8179,0x0168,0x816d,0x8167,0x0162,
+ 0x8123,0x0126,0x012c,0x8129,0x0138,0x813d,0x8137,0x0132,
+ 0x0110,0x8115,0x811f,0x011a,0x810b,0x010e,0x0104,0x8101,
+ 0x8303,0x0306,0x030c,0x8309,0x0318,0x831d,0x8317,0x0312,
+ 0x0330,0x8335,0x833f,0x033a,0x832b,0x032e,0x0324,0x8321,
+ 0x0360,0x8365,0x836f,0x036a,0x837b,0x037e,0x0374,0x8371,
+ 0x8353,0x0356,0x035c,0x8359,0x0348,0x834d,0x8347,0x0342,
+ 0x03c0,0x83c5,0x83cf,0x03ca,0x83db,0x03de,0x03d4,0x83d1,
+ 0x83f3,0x03f6,0x03fc,0x83f9,0x03e8,0x83ed,0x83e7,0x03e2,
+ 0x83a3,0x03a6,0x03ac,0x83a9,0x03b8,0x83bd,0x83b7,0x03b2,
+ 0x0390,0x8395,0x839f,0x039a,0x838b,0x038e,0x0384,0x8381,
+ 0x0280,0x8285,0x828f,0x028a,0x829b,0x029e,0x0294,0x8291,
+ 0x82b3,0x02b6,0x02bc,0x82b9,0x02a8,0x82ad,0x82a7,0x02a2,
+ 0x82e3,0x02e6,0x02ec,0x82e9,0x02f8,0x82fd,0x82f7,0x02f2,
+ 0x02d0,0x82d5,0x82df,0x02da,0x82cb,0x02ce,0x02c4,0x82c1,
+ 0x8243,0x0246,0x024c,0x8249,0x0258,0x825d,0x8257,0x0252,
+ 0x0270,0x8275,0x827f,0x027a,0x826b,0x026e,0x0264,0x8261,
+ 0x0220,0x8225,0x822f,0x022a,0x823b,0x023e,0x0234,0x8231,
+ 0x8213,0x0216,0x021c,0x8219,0x0208,0x820d,0x8207,0x0202
+};
+
+uint16_t a52_crc16_block(uint8_t *data,uint32_t num_bytes)
+{
+ uint32_t i;
+ uint16_t state=0;
+
+ for(i=0;i<num_bytes;i++)
+ state = crc_lut[data[i] ^ (state>>8)] ^ (state<<8);
+
+ return state;
+}
diff --git a/contrib/ffmpeg/libavcodec/liba52/downmix.c b/contrib/ffmpeg/libavcodec/liba52/downmix.c
new file mode 100644
index 000000000..7999b7db0
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/liba52/downmix.c
@@ -0,0 +1,679 @@
+/*
+ * downmix.c
+ * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * a52dec is distributed in the hope that 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "a52.h"
+#include "a52_internal.h"
+
+#define CONVERT(acmod,output) (((output) << 3) + (acmod))
+
+int a52_downmix_init (int input, int flags, level_t * level,
+ level_t clev, level_t slev)
+{
+ static uint8_t table[11][8] = {
+ {A52_CHANNEL, A52_DOLBY, A52_STEREO, A52_STEREO,
+ A52_STEREO, A52_STEREO, A52_STEREO, A52_STEREO},
+ {A52_MONO, A52_MONO, A52_MONO, A52_MONO,
+ A52_MONO, A52_MONO, A52_MONO, A52_MONO},
+ {A52_CHANNEL, A52_DOLBY, A52_STEREO, A52_STEREO,
+ A52_STEREO, A52_STEREO, A52_STEREO, A52_STEREO},
+ {A52_CHANNEL, A52_DOLBY, A52_STEREO, A52_3F,
+ A52_STEREO, A52_3F, A52_STEREO, A52_3F},
+ {A52_CHANNEL, A52_DOLBY, A52_STEREO, A52_STEREO,
+ A52_2F1R, A52_2F1R, A52_2F1R, A52_2F1R},
+ {A52_CHANNEL, A52_DOLBY, A52_STEREO, A52_STEREO,
+ A52_2F1R, A52_3F1R, A52_2F1R, A52_3F1R},
+ {A52_CHANNEL, A52_DOLBY, A52_STEREO, A52_3F,
+ A52_2F2R, A52_2F2R, A52_2F2R, A52_2F2R},
+ {A52_CHANNEL, A52_DOLBY, A52_STEREO, A52_3F,
+ A52_2F2R, A52_3F2R, A52_2F2R, A52_3F2R},
+ {A52_CHANNEL1, A52_MONO, A52_MONO, A52_MONO,
+ A52_MONO, A52_MONO, A52_MONO, A52_MONO},
+ {A52_CHANNEL2, A52_MONO, A52_MONO, A52_MONO,
+ A52_MONO, A52_MONO, A52_MONO, A52_MONO},
+ {A52_CHANNEL, A52_DOLBY, A52_STEREO, A52_DOLBY,
+ A52_DOLBY, A52_DOLBY, A52_DOLBY, A52_DOLBY}
+ };
+ int output;
+
+ output = flags & A52_CHANNEL_MASK;
+ if (output > A52_DOLBY)
+ return -1;
+
+ output = table[output][input & 7];
+
+ if (output == A52_STEREO &&
+ (input == A52_DOLBY || (input == A52_3F && clev == LEVEL (LEVEL_3DB))))
+ output = A52_DOLBY;
+
+ if (flags & A52_ADJUST_LEVEL) {
+ level_t adjust;
+
+ switch (CONVERT (input & 7, output)) {
+
+ case CONVERT (A52_3F, A52_MONO):
+ adjust = DIV (LEVEL_3DB, LEVEL (1) + clev);
+ break;
+
+ case CONVERT (A52_STEREO, A52_MONO):
+ case CONVERT (A52_2F2R, A52_2F1R):
+ case CONVERT (A52_3F2R, A52_3F1R):
+ level_3db:
+ adjust = LEVEL (LEVEL_3DB);
+ break;
+
+ case CONVERT (A52_3F2R, A52_2F1R):
+ if (clev < LEVEL (LEVEL_PLUS3DB - 1))
+ goto level_3db;
+ /* break thru */
+ case CONVERT (A52_3F, A52_STEREO):
+ case CONVERT (A52_3F1R, A52_2F1R):
+ case CONVERT (A52_3F1R, A52_2F2R):
+ case CONVERT (A52_3F2R, A52_2F2R):
+ adjust = DIV (1, LEVEL (1) + clev);
+ break;
+
+ case CONVERT (A52_2F1R, A52_MONO):
+ adjust = DIV (LEVEL_PLUS3DB, LEVEL (2) + slev);
+ break;
+
+ case CONVERT (A52_2F1R, A52_STEREO):
+ case CONVERT (A52_3F1R, A52_3F):
+ adjust = DIV (1, LEVEL (1) + MUL_C (slev, LEVEL_3DB));
+ break;
+
+ case CONVERT (A52_3F1R, A52_MONO):
+ adjust = DIV (LEVEL_3DB, LEVEL (1) + clev + MUL_C (slev, 0.5));
+ break;
+
+ case CONVERT (A52_3F1R, A52_STEREO):
+ adjust = DIV (1, LEVEL (1) + clev + MUL_C (slev, LEVEL_3DB));
+ break;
+
+ case CONVERT (A52_2F2R, A52_MONO):
+ adjust = DIV (LEVEL_3DB, LEVEL (1) + slev);
+ break;
+
+ case CONVERT (A52_2F2R, A52_STEREO):
+ case CONVERT (A52_3F2R, A52_3F):
+ adjust = DIV (1, LEVEL (1) + slev);
+ break;
+
+ case CONVERT (A52_3F2R, A52_MONO):
+ adjust = DIV (LEVEL_3DB, LEVEL (1) + clev + slev);
+ break;
+
+ case CONVERT (A52_3F2R, A52_STEREO):
+ adjust = DIV (1, LEVEL (1) + clev + slev);
+ break;
+
+ case CONVERT (A52_MONO, A52_DOLBY):
+ adjust = LEVEL (LEVEL_PLUS3DB);
+ break;
+
+ case CONVERT (A52_3F, A52_DOLBY):
+ case CONVERT (A52_2F1R, A52_DOLBY):
+ adjust = LEVEL (1 / (1 + LEVEL_3DB));
+ break;
+
+ case CONVERT (A52_3F1R, A52_DOLBY):
+ case CONVERT (A52_2F2R, A52_DOLBY):
+ adjust = LEVEL (1 / (1 + 2 * LEVEL_3DB));
+ break;
+
+ case CONVERT (A52_3F2R, A52_DOLBY):
+ adjust = LEVEL (1 / (1 + 3 * LEVEL_3DB));
+ break;
+
+ default:
+ return output;
+ }
+
+ *level = MUL_L (*level, adjust);
+ }
+
+ return output;
+}
+
+int a52_downmix_coeff (level_t * coeff, int acmod, int output, level_t level,
+ level_t clev, level_t slev)
+{
+ level_t level_3db;
+
+ level_3db = MUL_C (level, LEVEL_3DB);
+
+ switch (CONVERT (acmod, output & A52_CHANNEL_MASK)) {
+
+ case CONVERT (A52_CHANNEL, A52_CHANNEL):
+ case CONVERT (A52_MONO, A52_MONO):
+ case CONVERT (A52_STEREO, A52_STEREO):
+ case CONVERT (A52_3F, A52_3F):
+ case CONVERT (A52_2F1R, A52_2F1R):
+ case CONVERT (A52_3F1R, A52_3F1R):
+ case CONVERT (A52_2F2R, A52_2F2R):
+ case CONVERT (A52_3F2R, A52_3F2R):
+ case CONVERT (A52_STEREO, A52_DOLBY):
+ coeff[0] = coeff[1] = coeff[2] = coeff[3] = coeff[4] = level;
+ return 0;
+
+ case CONVERT (A52_CHANNEL, A52_MONO):
+ coeff[0] = coeff[1] = MUL_C (level, LEVEL_6DB);
+ return 3;
+
+ case CONVERT (A52_STEREO, A52_MONO):
+ coeff[0] = coeff[1] = level_3db;
+ return 3;
+
+ case CONVERT (A52_3F, A52_MONO):
+ coeff[0] = coeff[2] = level_3db;
+ coeff[1] = MUL_C (MUL_L (level_3db, clev), LEVEL_PLUS6DB);
+ return 7;
+
+ case CONVERT (A52_2F1R, A52_MONO):
+ coeff[0] = coeff[1] = level_3db;
+ coeff[2] = MUL_L (level_3db, slev);
+ return 7;
+
+ case CONVERT (A52_2F2R, A52_MONO):
+ coeff[0] = coeff[1] = level_3db;
+ coeff[2] = coeff[3] = MUL_L (level_3db, slev);
+ return 15;
+
+ case CONVERT (A52_3F1R, A52_MONO):
+ coeff[0] = coeff[2] = level_3db;
+ coeff[1] = MUL_C (MUL_L (level_3db, clev), LEVEL_PLUS6DB);
+ coeff[3] = MUL_L (level_3db, slev);
+ return 15;
+
+ case CONVERT (A52_3F2R, A52_MONO):
+ coeff[0] = coeff[2] = level_3db;
+ coeff[1] = MUL_C (MUL_L (level_3db, clev), LEVEL_PLUS6DB);
+ coeff[3] = coeff[4] = MUL_L (level_3db, slev);
+ return 31;
+
+ case CONVERT (A52_MONO, A52_DOLBY):
+ coeff[0] = level_3db;
+ return 0;
+
+ case CONVERT (A52_3F, A52_DOLBY):
+ coeff[0] = coeff[2] = coeff[3] = coeff[4] = level;
+ coeff[1] = level_3db;
+ return 7;
+
+ case CONVERT (A52_3F, A52_STEREO):
+ case CONVERT (A52_3F1R, A52_2F1R):
+ case CONVERT (A52_3F2R, A52_2F2R):
+ coeff[0] = coeff[2] = coeff[3] = coeff[4] = level;
+ coeff[1] = MUL_L (level, clev);
+ return 7;
+
+ case CONVERT (A52_2F1R, A52_DOLBY):
+ coeff[0] = coeff[1] = level;
+ coeff[2] = level_3db;
+ return 7;
+
+ case CONVERT (A52_2F1R, A52_STEREO):
+ coeff[0] = coeff[1] = level;
+ coeff[2] = MUL_L (level_3db, slev);
+ return 7;
+
+ case CONVERT (A52_3F1R, A52_DOLBY):
+ coeff[0] = coeff[2] = level;
+ coeff[1] = coeff[3] = level_3db;
+ return 15;
+
+ case CONVERT (A52_3F1R, A52_STEREO):
+ coeff[0] = coeff[2] = level;
+ coeff[1] = MUL_L (level, clev);
+ coeff[3] = MUL_L (level_3db, slev);
+ return 15;
+
+ case CONVERT (A52_2F2R, A52_DOLBY):
+ coeff[0] = coeff[1] = level;
+ coeff[2] = coeff[3] = level_3db;
+ return 15;
+
+ case CONVERT (A52_2F2R, A52_STEREO):
+ coeff[0] = coeff[1] = level;
+ coeff[2] = coeff[3] = MUL_L (level, slev);
+ return 15;
+
+ case CONVERT (A52_3F2R, A52_DOLBY):
+ coeff[0] = coeff[2] = level;
+ coeff[1] = coeff[3] = coeff[4] = level_3db;
+ return 31;
+
+ case CONVERT (A52_3F2R, A52_2F1R):
+ coeff[0] = coeff[2] = level;
+ coeff[1] = MUL_L (level, clev);
+ coeff[3] = coeff[4] = level_3db;
+ return 31;
+
+ case CONVERT (A52_3F2R, A52_STEREO):
+ coeff[0] = coeff[2] = level;
+ coeff[1] = MUL_L (level, clev);
+ coeff[3] = coeff[4] = MUL_L (level, slev);
+ return 31;
+
+ case CONVERT (A52_3F1R, A52_3F):
+ coeff[0] = coeff[1] = coeff[2] = level;
+ coeff[3] = MUL_L (level_3db, slev);
+ return 13;
+
+ case CONVERT (A52_3F2R, A52_3F):
+ coeff[0] = coeff[1] = coeff[2] = level;
+ coeff[3] = coeff[4] = MUL_L (level, slev);
+ return 29;
+
+ case CONVERT (A52_2F2R, A52_2F1R):
+ coeff[0] = coeff[1] = level;
+ coeff[2] = coeff[3] = level_3db;
+ return 12;
+
+ case CONVERT (A52_3F2R, A52_3F1R):
+ coeff[0] = coeff[1] = coeff[2] = level;
+ coeff[3] = coeff[4] = level_3db;
+ return 24;
+
+ case CONVERT (A52_2F1R, A52_2F2R):
+ coeff[0] = coeff[1] = level;
+ coeff[2] = level_3db;
+ return 0;
+
+ case CONVERT (A52_3F1R, A52_2F2R):
+ coeff[0] = coeff[2] = level;
+ coeff[1] = MUL_L (level, clev);
+ coeff[3] = level_3db;
+ return 7;
+
+ case CONVERT (A52_3F1R, A52_3F2R):
+ coeff[0] = coeff[1] = coeff[2] = level;
+ coeff[3] = level_3db;
+ return 0;
+
+ case CONVERT (A52_CHANNEL, A52_CHANNEL1):
+ coeff[0] = level;
+ coeff[1] = 0;
+ return 0;
+
+ case CONVERT (A52_CHANNEL, A52_CHANNEL2):
+ coeff[0] = 0;
+ coeff[1] = level;
+ return 0;
+ }
+
+ return -1; /* NOTREACHED */
+}
+
+static void mix2to1 (sample_t * dest, sample_t * src, sample_t bias)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ dest[i] += BIAS (src[i]);
+}
+
+static void mix3to1 (sample_t * samples, sample_t bias)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ samples[i] += BIAS (samples[i + 256] + samples[i + 512]);
+}
+
+static void mix4to1 (sample_t * samples, sample_t bias)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ samples[i] += BIAS (samples[i + 256] + samples[i + 512] +
+ samples[i + 768]);
+}
+
+static void mix5to1 (sample_t * samples, sample_t bias)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ samples[i] += BIAS (samples[i + 256] + samples[i + 512] +
+ samples[i + 768] + samples[i + 1024]);
+}
+
+static void mix3to2 (sample_t * samples, sample_t bias)
+{
+ int i;
+ sample_t common;
+
+ for (i = 0; i < 256; i++) {
+ common = BIAS (samples[i + 256]);
+ samples[i] += common;
+ samples[i + 256] = samples[i + 512] + common;
+ }
+}
+
+static void mix21to2 (sample_t * left, sample_t * right, sample_t bias)
+{
+ int i;
+ sample_t common;
+
+ for (i = 0; i < 256; i++) {
+ common = BIAS (right[i + 256]);
+ left[i] += common;
+ right[i] += common;
+ }
+}
+
+static void mix21toS (sample_t * samples, sample_t bias)
+{
+ int i;
+ sample_t surround;
+
+ for (i = 0; i < 256; i++) {
+ surround = samples[i + 512];
+ samples[i] += BIAS (-surround);
+ samples[i + 256] += BIAS (surround);
+ }
+}
+
+static void mix31to2 (sample_t * samples, sample_t bias)
+{
+ int i;
+ sample_t common;
+
+ for (i = 0; i < 256; i++) {
+ common = BIAS (samples[i + 256] + samples[i + 768]);
+ samples[i] += common;
+ samples[i + 256] = samples[i + 512] + common;
+ }
+}
+
+static void mix31toS (sample_t * samples, sample_t bias)
+{
+ int i;
+ sample_t common, surround;
+
+ for (i = 0; i < 256; i++) {
+ common = BIAS (samples[i + 256]);
+ surround = samples[i + 768];
+ samples[i] += common - surround;
+ samples[i + 256] = samples[i + 512] + common + surround;
+ }
+}
+
+static void mix22toS (sample_t * samples, sample_t bias)
+{
+ int i;
+ sample_t surround;
+
+ for (i = 0; i < 256; i++) {
+ surround = samples[i + 512] + samples[i + 768];
+ samples[i] += BIAS (-surround);
+ samples[i + 256] += BIAS (surround);
+ }
+}
+
+static void mix32to2 (sample_t * samples, sample_t bias)
+{
+ int i;
+ sample_t common;
+
+ for (i = 0; i < 256; i++) {
+ common = BIAS (samples[i + 256]);
+ samples[i] += common + samples[i + 768];
+ samples[i + 256] = common + samples[i + 512] + samples[i + 1024];
+ }
+}
+
+static void mix32toS (sample_t * samples, sample_t bias)
+{
+ int i;
+ sample_t common, surround;
+
+ for (i = 0; i < 256; i++) {
+ common = BIAS (samples[i + 256]);
+ surround = samples[i + 768] + samples[i + 1024];
+ samples[i] += common - surround;
+ samples[i + 256] = samples[i + 512] + common + surround;
+ }
+}
+
+static void move2to1 (sample_t * src, sample_t * dest, sample_t bias)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ dest[i] = BIAS (src[i] + src[i + 256]);
+}
+
+static void zero (sample_t * samples)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ samples[i] = 0;
+}
+
+void a52_downmix (sample_t * samples, int acmod, int output, sample_t bias,
+ level_t clev, level_t slev)
+{
+ switch (CONVERT (acmod, output & A52_CHANNEL_MASK)) {
+
+ case CONVERT (A52_CHANNEL, A52_CHANNEL2):
+ memcpy (samples, samples + 256, 256 * sizeof (sample_t));
+ break;
+
+ case CONVERT (A52_CHANNEL, A52_MONO):
+ case CONVERT (A52_STEREO, A52_MONO):
+ mix_2to1:
+ mix2to1 (samples, samples + 256, bias);
+ break;
+
+ case CONVERT (A52_2F1R, A52_MONO):
+ if (slev == 0)
+ goto mix_2to1;
+ case CONVERT (A52_3F, A52_MONO):
+ mix_3to1:
+ mix3to1 (samples, bias);
+ break;
+
+ case CONVERT (A52_3F1R, A52_MONO):
+ if (slev == 0)
+ goto mix_3to1;
+ case CONVERT (A52_2F2R, A52_MONO):
+ if (slev == 0)
+ goto mix_2to1;
+ mix4to1 (samples, bias);
+ break;
+
+ case CONVERT (A52_3F2R, A52_MONO):
+ if (slev == 0)
+ goto mix_3to1;
+ mix5to1 (samples, bias);
+ break;
+
+ case CONVERT (A52_MONO, A52_DOLBY):
+ memcpy (samples + 256, samples, 256 * sizeof (sample_t));
+ break;
+
+ case CONVERT (A52_3F, A52_STEREO):
+ case CONVERT (A52_3F, A52_DOLBY):
+ mix_3to2:
+ mix3to2 (samples, bias);
+ break;
+
+ case CONVERT (A52_2F1R, A52_STEREO):
+ if (slev == 0)
+ break;
+ mix21to2 (samples, samples + 256, bias);
+ break;
+
+ case CONVERT (A52_2F1R, A52_DOLBY):
+ mix21toS (samples, bias);
+ break;
+
+ case CONVERT (A52_3F1R, A52_STEREO):
+ if (slev == 0)
+ goto mix_3to2;
+ mix31to2 (samples, bias);
+ break;
+
+ case CONVERT (A52_3F1R, A52_DOLBY):
+ mix31toS (samples, bias);
+ break;
+
+ case CONVERT (A52_2F2R, A52_STEREO):
+ if (slev == 0)
+ break;
+ mix2to1 (samples, samples + 512, bias);
+ mix2to1 (samples + 256, samples + 768, bias);
+ break;
+
+ case CONVERT (A52_2F2R, A52_DOLBY):
+ mix22toS (samples, bias);
+ break;
+
+ case CONVERT (A52_3F2R, A52_STEREO):
+ if (slev == 0)
+ goto mix_3to2;
+ mix32to2 (samples, bias);
+ break;
+
+ case CONVERT (A52_3F2R, A52_DOLBY):
+ mix32toS (samples, bias);
+ break;
+
+ case CONVERT (A52_3F1R, A52_3F):
+ if (slev == 0)
+ break;
+ mix21to2 (samples, samples + 512, bias);
+ break;
+
+ case CONVERT (A52_3F2R, A52_3F):
+ if (slev == 0)
+ break;
+ mix2to1 (samples, samples + 768, bias);
+ mix2to1 (samples + 512, samples + 1024, bias);
+ break;
+
+ case CONVERT (A52_3F1R, A52_2F1R):
+ mix3to2 (samples, bias);
+ memcpy (samples + 512, samples + 768, 256 * sizeof (sample_t));
+ break;
+
+ case CONVERT (A52_2F2R, A52_2F1R):
+ mix2to1 (samples + 512, samples + 768, bias);
+ break;
+
+ case CONVERT (A52_3F2R, A52_2F1R):
+ mix3to2 (samples, bias);
+ move2to1 (samples + 768, samples + 512, bias);
+ break;
+
+ case CONVERT (A52_3F2R, A52_3F1R):
+ mix2to1 (samples + 768, samples + 1024, bias);
+ break;
+
+ case CONVERT (A52_2F1R, A52_2F2R):
+ memcpy (samples + 768, samples + 512, 256 * sizeof (sample_t));
+ break;
+
+ case CONVERT (A52_3F1R, A52_2F2R):
+ mix3to2 (samples, bias);
+ memcpy (samples + 512, samples + 768, 256 * sizeof (sample_t));
+ break;
+
+ case CONVERT (A52_3F2R, A52_2F2R):
+ mix3to2 (samples, bias);
+ memcpy (samples + 512, samples + 768, 256 * sizeof (sample_t));
+ memcpy (samples + 768, samples + 1024, 256 * sizeof (sample_t));
+ break;
+
+ case CONVERT (A52_3F1R, A52_3F2R):
+ memcpy (samples + 1024, samples + 768, 256 * sizeof (sample_t));
+ break;
+ }
+}
+
+void a52_upmix (sample_t * samples, int acmod, int output)
+{
+ switch (CONVERT (acmod, output & A52_CHANNEL_MASK)) {
+
+ case CONVERT (A52_CHANNEL, A52_CHANNEL2):
+ memcpy (samples + 256, samples, 256 * sizeof (sample_t));
+ break;
+
+ case CONVERT (A52_3F2R, A52_MONO):
+ zero (samples + 1024);
+ case CONVERT (A52_3F1R, A52_MONO):
+ case CONVERT (A52_2F2R, A52_MONO):
+ zero (samples + 768);
+ case CONVERT (A52_3F, A52_MONO):
+ case CONVERT (A52_2F1R, A52_MONO):
+ zero (samples + 512);
+ case CONVERT (A52_CHANNEL, A52_MONO):
+ case CONVERT (A52_STEREO, A52_MONO):
+ zero (samples + 256);
+ break;
+
+ case CONVERT (A52_3F2R, A52_STEREO):
+ case CONVERT (A52_3F2R, A52_DOLBY):
+ zero (samples + 1024);
+ case CONVERT (A52_3F1R, A52_STEREO):
+ case CONVERT (A52_3F1R, A52_DOLBY):
+ zero (samples + 768);
+ case CONVERT (A52_3F, A52_STEREO):
+ case CONVERT (A52_3F, A52_DOLBY):
+ mix_3to2:
+ memcpy (samples + 512, samples + 256, 256 * sizeof (sample_t));
+ zero (samples + 256);
+ break;
+
+ case CONVERT (A52_2F2R, A52_STEREO):
+ case CONVERT (A52_2F2R, A52_DOLBY):
+ zero (samples + 768);
+ case CONVERT (A52_2F1R, A52_STEREO):
+ case CONVERT (A52_2F1R, A52_DOLBY):
+ zero (samples + 512);
+ break;
+
+ case CONVERT (A52_3F2R, A52_3F):
+ zero (samples + 1024);
+ case CONVERT (A52_3F1R, A52_3F):
+ case CONVERT (A52_2F2R, A52_2F1R):
+ zero (samples + 768);
+ break;
+
+ case CONVERT (A52_3F2R, A52_3F1R):
+ zero (samples + 1024);
+ break;
+
+ case CONVERT (A52_3F2R, A52_2F1R):
+ zero (samples + 1024);
+ case CONVERT (A52_3F1R, A52_2F1R):
+ mix_31to21:
+ memcpy (samples + 768, samples + 512, 256 * sizeof (sample_t));
+ goto mix_3to2;
+
+ case CONVERT (A52_3F2R, A52_2F2R):
+ memcpy (samples + 1024, samples + 768, 256 * sizeof (sample_t));
+ goto mix_31to21;
+ }
+}
diff --git a/contrib/ffmpeg/libavcodec/liba52/imdct.c b/contrib/ffmpeg/libavcodec/liba52/imdct.c
new file mode 100644
index 000000000..21a2a6565
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/liba52/imdct.c
@@ -0,0 +1,411 @@
+/*
+ * imdct.c
+ * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * The ifft algorithms in this file have been largely inspired by Dan
+ * Bernstein's work, djbfft, available at http://cr.yp.to/djbfft.html
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * a52dec is distributed in the hope that 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "a52.h"
+#include "a52_internal.h"
+#include "mm_accel.h"
+
+typedef struct complex_s {
+ sample_t real;
+ sample_t imag;
+} complex_t;
+
+static uint8_t fftorder[] = {
+ 0,128, 64,192, 32,160,224, 96, 16,144, 80,208,240,112, 48,176,
+ 8,136, 72,200, 40,168,232,104,248,120, 56,184, 24,152,216, 88,
+ 4,132, 68,196, 36,164,228,100, 20,148, 84,212,244,116, 52,180,
+ 252,124, 60,188, 28,156,220, 92, 12,140, 76,204,236,108, 44,172,
+ 2,130, 66,194, 34,162,226, 98, 18,146, 82,210,242,114, 50,178,
+ 10,138, 74,202, 42,170,234,106,250,122, 58,186, 26,154,218, 90,
+ 254,126, 62,190, 30,158,222, 94, 14,142, 78,206,238,110, 46,174,
+ 6,134, 70,198, 38,166,230,102,246,118, 54,182, 22,150,214, 86
+};
+
+/* Root values for IFFT */
+static sample_t roots16[3];
+static sample_t roots32[7];
+static sample_t roots64[15];
+static sample_t roots128[31];
+
+/* Twiddle factors for IMDCT */
+static complex_t pre1[128];
+static complex_t post1[64];
+static complex_t pre2[64];
+static complex_t post2[32];
+
+static sample_t a52_imdct_window[256];
+
+static void (* ifft128) (complex_t * buf);
+static void (* ifft64) (complex_t * buf);
+
+static inline void ifft2 (complex_t * buf)
+{
+ sample_t r, i;
+
+ r = buf[0].real;
+ i = buf[0].imag;
+ buf[0].real += buf[1].real;
+ buf[0].imag += buf[1].imag;
+ buf[1].real = r - buf[1].real;
+ buf[1].imag = i - buf[1].imag;
+}
+
+static inline void ifft4 (complex_t * buf)
+{
+ sample_t tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8;
+
+ tmp1 = buf[0].real + buf[1].real;
+ tmp2 = buf[3].real + buf[2].real;
+ tmp3 = buf[0].imag + buf[1].imag;
+ tmp4 = buf[2].imag + buf[3].imag;
+ tmp5 = buf[0].real - buf[1].real;
+ tmp6 = buf[0].imag - buf[1].imag;
+ tmp7 = buf[2].imag - buf[3].imag;
+ tmp8 = buf[3].real - buf[2].real;
+
+ buf[0].real = tmp1 + tmp2;
+ buf[0].imag = tmp3 + tmp4;
+ buf[2].real = tmp1 - tmp2;
+ buf[2].imag = tmp3 - tmp4;
+ buf[1].real = tmp5 + tmp7;
+ buf[1].imag = tmp6 + tmp8;
+ buf[3].real = tmp5 - tmp7;
+ buf[3].imag = tmp6 - tmp8;
+}
+
+/* basic radix-2 ifft butterfly */
+
+#define BUTTERFLY_0(t0,t1,W0,W1,d0,d1) do { \
+ t0 = MUL (W1, d1) + MUL (W0, d0); \
+ t1 = MUL (W0, d1) - MUL (W1, d0); \
+} while (0)
+
+/* radix-2 ifft butterfly with bias */
+
+#define BUTTERFLY_B(t0,t1,W0,W1,d0,d1) do { \
+ t0 = BIAS (MUL (d1, W1) + MUL (d0, W0)); \
+ t1 = BIAS (MUL (d1, W0) - MUL (d0, W1)); \
+} while (0)
+
+/* the basic split-radix ifft butterfly */
+
+#define BUTTERFLY(a0,a1,a2,a3,wr,wi) do { \
+ BUTTERFLY_0 (tmp5, tmp6, wr, wi, a2.real, a2.imag); \
+ BUTTERFLY_0 (tmp8, tmp7, wr, wi, a3.imag, a3.real); \
+ tmp1 = tmp5 + tmp7; \
+ tmp2 = tmp6 + tmp8; \
+ tmp3 = tmp6 - tmp8; \
+ tmp4 = tmp7 - tmp5; \
+ a2.real = a0.real - tmp1; \
+ a2.imag = a0.imag - tmp2; \
+ a3.real = a1.real - tmp3; \
+ a3.imag = a1.imag - tmp4; \
+ a0.real += tmp1; \
+ a0.imag += tmp2; \
+ a1.real += tmp3; \
+ a1.imag += tmp4; \
+} while (0)
+
+/* split-radix ifft butterfly, specialized for wr=1 wi=0 */
+
+#define BUTTERFLY_ZERO(a0,a1,a2,a3) do { \
+ tmp1 = a2.real + a3.real; \
+ tmp2 = a2.imag + a3.imag; \
+ tmp3 = a2.imag - a3.imag; \
+ tmp4 = a3.real - a2.real; \
+ a2.real = a0.real - tmp1; \
+ a2.imag = a0.imag - tmp2; \
+ a3.real = a1.real - tmp3; \
+ a3.imag = a1.imag - tmp4; \
+ a0.real += tmp1; \
+ a0.imag += tmp2; \
+ a1.real += tmp3; \
+ a1.imag += tmp4; \
+} while (0)
+
+/* split-radix ifft butterfly, specialized for wr=wi */
+
+#define BUTTERFLY_HALF(a0,a1,a2,a3,w) do { \
+ tmp5 = MUL (a2.real + a2.imag, w); \
+ tmp6 = MUL (a2.imag - a2.real, w); \
+ tmp7 = MUL (a3.real - a3.imag, w); \
+ tmp8 = MUL (a3.imag + a3.real, w); \
+ tmp1 = tmp5 + tmp7; \
+ tmp2 = tmp6 + tmp8; \
+ tmp3 = tmp6 - tmp8; \
+ tmp4 = tmp7 - tmp5; \
+ a2.real = a0.real - tmp1; \
+ a2.imag = a0.imag - tmp2; \
+ a3.real = a1.real - tmp3; \
+ a3.imag = a1.imag - tmp4; \
+ a0.real += tmp1; \
+ a0.imag += tmp2; \
+ a1.real += tmp3; \
+ a1.imag += tmp4; \
+} while (0)
+
+static inline void ifft8 (complex_t * buf)
+{
+ sample_t tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8;
+
+ ifft4 (buf);
+ ifft2 (buf + 4);
+ ifft2 (buf + 6);
+ BUTTERFLY_ZERO (buf[0], buf[2], buf[4], buf[6]);
+ BUTTERFLY_HALF (buf[1], buf[3], buf[5], buf[7], roots16[1]);
+}
+
+static void ifft_pass (complex_t * buf, sample_t * weight, int n)
+{
+ complex_t * buf1;
+ complex_t * buf2;
+ complex_t * buf3;
+ sample_t tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8;
+ int i;
+
+ buf++;
+ buf1 = buf + n;
+ buf2 = buf + 2 * n;
+ buf3 = buf + 3 * n;
+
+ BUTTERFLY_ZERO (buf[-1], buf1[-1], buf2[-1], buf3[-1]);
+
+ i = n - 1;
+
+ do {
+ BUTTERFLY (buf[0], buf1[0], buf2[0], buf3[0],
+ weight[0], weight[2*i-n]);
+ buf++;
+ buf1++;
+ buf2++;
+ buf3++;
+ weight++;
+ } while (--i);
+}
+
+static void ifft16 (complex_t * buf)
+{
+ ifft8 (buf);
+ ifft4 (buf + 8);
+ ifft4 (buf + 12);
+ ifft_pass (buf, roots16, 4);
+}
+
+static void ifft32 (complex_t * buf)
+{
+ ifft16 (buf);
+ ifft8 (buf + 16);
+ ifft8 (buf + 24);
+ ifft_pass (buf, roots32, 8);
+}
+
+static void ifft64_c (complex_t * buf)
+{
+ ifft32 (buf);
+ ifft16 (buf + 32);
+ ifft16 (buf + 48);
+ ifft_pass (buf, roots64, 16);
+}
+
+static void ifft128_c (complex_t * buf)
+{
+ ifft32 (buf);
+ ifft16 (buf + 32);
+ ifft16 (buf + 48);
+ ifft_pass (buf, roots64, 16);
+
+ ifft32 (buf + 64);
+ ifft32 (buf + 96);
+ ifft_pass (buf, roots128, 32);
+}
+
+void a52_imdct_512 (sample_t * data, sample_t * delay, sample_t bias)
+{
+ int i, k;
+ sample_t t_r, t_i, a_r, a_i, b_r, b_i, w_1, w_2;
+ const sample_t * window = a52_imdct_window;
+ complex_t buf[128];
+
+ for (i = 0; i < 128; i++) {
+ k = fftorder[i];
+ t_r = pre1[i].real;
+ t_i = pre1[i].imag;
+ BUTTERFLY_0 (buf[i].real, buf[i].imag, t_r, t_i, data[k], data[255-k]);
+ }
+
+ ifft128 (buf);
+
+ /* Post IFFT complex multiply plus IFFT complex conjugate*/
+ /* Window and convert to real valued signal */
+ for (i = 0; i < 64; i++) {
+ /* y[n] = z[n] * (xcos1[n] + j * xsin1[n]) ; */
+ t_r = post1[i].real;
+ t_i = post1[i].imag;
+ BUTTERFLY_0 (a_r, a_i, t_i, t_r, buf[i].imag, buf[i].real);
+ BUTTERFLY_0 (b_r, b_i, t_r, t_i, buf[127-i].imag, buf[127-i].real);
+
+ w_1 = window[2*i];
+ w_2 = window[255-2*i];
+ BUTTERFLY_B (data[255-2*i], data[2*i], w_2, w_1, a_r, delay[2*i]);
+ delay[2*i] = a_i;
+
+ w_1 = window[2*i+1];
+ w_2 = window[254-2*i];
+ BUTTERFLY_B (data[2*i+1], data[254-2*i], w_1, w_2, b_r, delay[2*i+1]);
+ delay[2*i+1] = b_i;
+ }
+}
+
+void a52_imdct_256 (sample_t * data, sample_t * delay, sample_t bias)
+{
+ int i, k;
+ sample_t t_r, t_i, a_r, a_i, b_r, b_i, c_r, c_i, d_r, d_i, w_1, w_2;
+ const sample_t * window = a52_imdct_window;
+ complex_t buf1[64], buf2[64];
+
+ /* Pre IFFT complex multiply plus IFFT cmplx conjugate */
+ for (i = 0; i < 64; i++) {
+ k = fftorder[i];
+ t_r = pre2[i].real;
+ t_i = pre2[i].imag;
+ BUTTERFLY_0 (buf1[i].real, buf1[i].imag, t_r, t_i, data[k], data[254-k]);
+ BUTTERFLY_0 (buf2[i].real, buf2[i].imag, t_r, t_i, data[k+1], data[255-k]);
+ }
+
+ ifft64 (buf1);
+ ifft64 (buf2);
+
+ /* Post IFFT complex multiply */
+ /* Window and convert to real valued signal */
+ for (i = 0; i < 32; i++) {
+ /* y1[n] = z1[n] * (xcos2[n] + j * xs in2[n]) ; */
+ t_r = post2[i].real;
+ t_i = post2[i].imag;
+ BUTTERFLY_0 (a_r, a_i, t_i, t_r, buf1[i].imag, buf1[i].real);
+ BUTTERFLY_0 (b_r, b_i, t_r, t_i, buf1[63-i].imag, buf1[63-i].real);
+ BUTTERFLY_0 (c_r, c_i, t_i, t_r, buf2[i].imag, buf2[i].real);
+ BUTTERFLY_0 (d_r, d_i, t_r, t_i, buf2[63-i].imag, buf2[63-i].real);
+
+ w_1 = window[2*i];
+ w_2 = window[255-2*i];
+ BUTTERFLY_B (data[255-2*i], data[2*i], w_2, w_1, a_r, delay[2*i]);
+ delay[2*i] = c_i;
+
+ w_1 = window[128+2*i];
+ w_2 = window[127-2*i];
+ BUTTERFLY_B (data[128+2*i], data[127-2*i], w_1, w_2, a_i, delay[127-2*i]);
+ delay[127-2*i] = c_r;
+
+ w_1 = window[2*i+1];
+ w_2 = window[254-2*i];
+ BUTTERFLY_B (data[254-2*i], data[2*i+1], w_2, w_1, b_i, delay[2*i+1]);
+ delay[2*i+1] = d_r;
+
+ w_1 = window[129+2*i];
+ w_2 = window[126-2*i];
+ BUTTERFLY_B (data[129+2*i], data[126-2*i], w_1, w_2, b_r, delay[126-2*i]);
+ delay[126-2*i] = d_i;
+ }
+}
+
+static double besselI0 (double x)
+{
+ double bessel = 1;
+ int i = 100;
+
+ do
+ bessel = bessel * x / (i * i) + 1;
+ while (--i);
+ return bessel;
+}
+
+void a52_imdct_init (uint32_t mm_accel)
+{
+ int i, k;
+ double sum;
+ double local_imdct_window[256];
+
+ /* compute imdct window - kaiser-bessel derived window, alpha = 5.0 */
+ sum = 0;
+ for (i = 0; i < 256; i++) {
+ sum += besselI0 (i * (256 - i) * (5 * M_PI / 256) * (5 * M_PI / 256));
+ local_imdct_window[i] = sum;
+ }
+ sum++;
+ for (i = 0; i < 256; i++)
+ a52_imdct_window[i] = SAMPLE (sqrt (local_imdct_window[i] / sum));
+
+ for (i = 0; i < 3; i++)
+ roots16[i] = SAMPLE (cos ((M_PI / 8) * (i + 1)));
+
+ for (i = 0; i < 7; i++)
+ roots32[i] = SAMPLE (cos ((M_PI / 16) * (i + 1)));
+
+ for (i = 0; i < 15; i++)
+ roots64[i] = SAMPLE (cos ((M_PI / 32) * (i + 1)));
+
+ for (i = 0; i < 31; i++)
+ roots128[i] = SAMPLE (cos ((M_PI / 64) * (i + 1)));
+
+ for (i = 0; i < 64; i++) {
+ k = fftorder[i] / 2 + 64;
+ pre1[i].real = SAMPLE (cos ((M_PI / 256) * (k - 0.25)));
+ pre1[i].imag = SAMPLE (sin ((M_PI / 256) * (k - 0.25)));
+ }
+
+ for (i = 64; i < 128; i++) {
+ k = fftorder[i] / 2 + 64;
+ pre1[i].real = SAMPLE (-cos ((M_PI / 256) * (k - 0.25)));
+ pre1[i].imag = SAMPLE (-sin ((M_PI / 256) * (k - 0.25)));
+ }
+
+ for (i = 0; i < 64; i++) {
+ post1[i].real = SAMPLE (cos ((M_PI / 256) * (i + 0.5)));
+ post1[i].imag = SAMPLE (sin ((M_PI / 256) * (i + 0.5)));
+ }
+
+ for (i = 0; i < 64; i++) {
+ k = fftorder[i] / 4;
+ pre2[i].real = SAMPLE (cos ((M_PI / 128) * (k - 0.25)));
+ pre2[i].imag = SAMPLE (sin ((M_PI / 128) * (k - 0.25)));
+ }
+
+ for (i = 0; i < 32; i++) {
+ post2[i].real = SAMPLE (cos ((M_PI / 128) * (i + 0.5)));
+ post2[i].imag = SAMPLE (sin ((M_PI / 128) * (i + 0.5)));
+ }
+
+#ifdef LIBA52_DJBFFT
+ if (mm_accel & MM_ACCEL_DJBFFT) {
+ ifft128 = (void (*) (complex_t *)) fftc4_un128;
+ ifft64 = (void (*) (complex_t *)) fftc4_un64;
+ } else
+#endif
+ {
+ ifft128 = ifft128_c;
+ ifft64 = ifft64_c;
+ }
+}
diff --git a/contrib/ffmpeg/libavcodec/liba52/mm_accel.h b/contrib/ffmpeg/libavcodec/liba52/mm_accel.h
new file mode 100644
index 000000000..9a475f5a2
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/liba52/mm_accel.h
@@ -0,0 +1,42 @@
+/*
+ * mm_accel.h
+ * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * a52dec is distributed in the hope that 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef MM_ACCEL_H
+#define MM_ACCEL_H
+
+/* generic accelerations */
+#define MM_ACCEL_DJBFFT 0x00000001
+
+/* x86 accelerations */
+#define MM_ACCEL_X86_MMX 0x80000000
+#define MM_ACCEL_X86_3DNOW 0x40000000
+#define MM_ACCEL_X86_MMXEXT 0x20000000
+#define MM_ACCEL_X86_SSE 0x10000000
+#define MM_ACCEL_X86_3DNOWEXT 0x08000000
+
+/* PPC accelerations */
+#define MM_ACCEL_PPC_ALTIVEC 0x00010000
+
+uint32_t mm_accel (void);
+
+#endif /* MM_ACCEL_H */
diff --git a/contrib/ffmpeg/libavcodec/liba52/parse.c b/contrib/ffmpeg/libavcodec/liba52/parse.c
new file mode 100644
index 000000000..5a0701564
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/liba52/parse.c
@@ -0,0 +1,939 @@
+/*
+ * parse.c
+ * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * a52dec is distributed in the hope that 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "a52.h"
+#include "a52_internal.h"
+#include "bitstream.h"
+#include "tables.h"
+
+#if defined(HAVE_MEMALIGN) && !defined(__cplusplus)
+/* some systems have memalign() but no declaration for it */
+void * memalign (size_t align, size_t size);
+#else
+/* assume malloc alignment is sufficient */
+#define memalign(align,size) malloc (size)
+#endif
+
+typedef struct {
+ quantizer_t q1[2];
+ quantizer_t q2[2];
+ quantizer_t q4;
+ int q1_ptr;
+ int q2_ptr;
+ int q4_ptr;
+} quantizer_set_t;
+
+static uint8_t halfrate[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3};
+
+a52_state_t * a52_init (uint32_t mm_accel)
+{
+ a52_state_t * state;
+ int i;
+
+ state = (a52_state_t *) malloc (sizeof (a52_state_t));
+ if (state == NULL)
+ return NULL;
+
+ state->samples = (sample_t *) memalign (16, 256 * 12 * sizeof (sample_t));
+ if (state->samples == NULL) {
+ free (state);
+ return NULL;
+ }
+
+ for (i = 0; i < 256 * 12; i++)
+ state->samples[i] = 0;
+
+ state->downmixed = 1;
+
+ state->lfsr_state = 1;
+
+ a52_imdct_init (mm_accel);
+
+ return state;
+}
+
+sample_t * a52_samples (a52_state_t * state)
+{
+ return state->samples;
+}
+
+int a52_syncinfo (uint8_t * buf, int * flags,
+ int * sample_rate, int * bit_rate)
+{
+ static int rate[] = { 32, 40, 48, 56, 64, 80, 96, 112,
+ 128, 160, 192, 224, 256, 320, 384, 448,
+ 512, 576, 640};
+ static uint8_t lfeon[8] = {0x10, 0x10, 0x04, 0x04, 0x04, 0x01, 0x04, 0x01};
+ int frmsizecod;
+ int bitrate;
+ int half;
+ int acmod;
+
+ if ((buf[0] != 0x0b) || (buf[1] != 0x77)) /* syncword */
+ return 0;
+
+ if (buf[5] >= 0x60) /* bsid >= 12 */
+ return 0;
+ half = halfrate[buf[5] >> 3];
+
+ /* acmod, dsurmod and lfeon */
+ acmod = buf[6] >> 5;
+ *flags = ((((buf[6] & 0xf8) == 0x50) ? A52_DOLBY : acmod) |
+ ((buf[6] & lfeon[acmod]) ? A52_LFE : 0));
+
+ frmsizecod = buf[4] & 63;
+ if (frmsizecod >= 38)
+ return 0;
+ bitrate = rate [frmsizecod >> 1];
+ *bit_rate = (bitrate * 1000) >> half;
+
+ switch (buf[4] & 0xc0) {
+ case 0:
+ *sample_rate = 48000 >> half;
+ return 4 * bitrate;
+ case 0x40:
+ *sample_rate = 44100 >> half;
+ return 2 * (320 * bitrate / 147 + (frmsizecod & 1));
+ case 0x80:
+ *sample_rate = 32000 >> half;
+ return 6 * bitrate;
+ default:
+ return 0;
+ }
+}
+
+int a52_frame (a52_state_t * state, uint8_t * buf, int * flags,
+ level_t * level, sample_t bias)
+{
+ static level_t clev[4] = { LEVEL (LEVEL_3DB), LEVEL (LEVEL_45DB),
+ LEVEL (LEVEL_6DB), LEVEL (LEVEL_45DB) };
+ static level_t slev[4] = { LEVEL (LEVEL_3DB), LEVEL (LEVEL_6DB),
+ 0, LEVEL (LEVEL_6DB) };
+ int chaninfo;
+ int acmod;
+
+ state->fscod = buf[4] >> 6;
+ state->halfrate = halfrate[buf[5] >> 3];
+ state->acmod = acmod = buf[6] >> 5;
+
+ a52_bitstream_set_ptr (state, buf + 6);
+ bitstream_get (state, 3); /* skip acmod we already parsed */
+
+ if ((acmod == 2) && (bitstream_get (state, 2) == 2)) /* dsurmod */
+ acmod = A52_DOLBY;
+
+ state->clev = state->slev = 0;
+
+ if ((acmod & 1) && (acmod != 1))
+ state->clev = clev[bitstream_get (state, 2)]; /* cmixlev */
+
+ if (acmod & 4)
+ state->slev = slev[bitstream_get (state, 2)]; /* surmixlev */
+
+ state->lfeon = bitstream_get (state, 1);
+
+ state->output = a52_downmix_init (acmod, *flags, level,
+ state->clev, state->slev);
+ if (state->output < 0)
+ return 1;
+ if (state->lfeon && (*flags & A52_LFE))
+ state->output |= A52_LFE;
+ *flags = state->output;
+ /* the 2* compensates for differences in imdct */
+ state->dynrng = state->level = MUL_C (*level, 2);
+ state->bias = bias;
+ state->dynrnge = 1;
+ state->dynrngcall = NULL;
+ state->cplba.deltbae = DELTA_BIT_NONE;
+ state->ba[0].deltbae = state->ba[1].deltbae = state->ba[2].deltbae =
+ state->ba[3].deltbae = state->ba[4].deltbae = DELTA_BIT_NONE;
+
+ chaninfo = !acmod;
+ do {
+ bitstream_get (state, 5); /* dialnorm */
+ if (bitstream_get (state, 1)) /* compre */
+ bitstream_get (state, 8); /* compr */
+ if (bitstream_get (state, 1)) /* langcode */
+ bitstream_get (state, 8); /* langcod */
+ if (bitstream_get (state, 1)) /* audprodie */
+ bitstream_get (state, 7); /* mixlevel + roomtyp */
+ } while (chaninfo--);
+
+ bitstream_get (state, 2); /* copyrightb + origbs */
+
+ if (bitstream_get (state, 1)) /* timecod1e */
+ bitstream_get (state, 14); /* timecod1 */
+ if (bitstream_get (state, 1)) /* timecod2e */
+ bitstream_get (state, 14); /* timecod2 */
+
+ if (bitstream_get (state, 1)) { /* addbsie */
+ int addbsil;
+
+ addbsil = bitstream_get (state, 6);
+ do {
+ bitstream_get (state, 8); /* addbsi */
+ } while (addbsil--);
+ }
+
+ return 0;
+}
+
+void a52_dynrng (a52_state_t * state,
+ level_t (* call) (level_t, void *), void * data)
+{
+ state->dynrnge = 0;
+ if (call) {
+ state->dynrnge = 1;
+ state->dynrngcall = call;
+ state->dynrngdata = data;
+ }
+}
+
+static int parse_exponents (a52_state_t * state, int expstr, int ngrps,
+ uint8_t exponent, uint8_t * dest)
+{
+ int exps;
+
+ while (ngrps--) {
+ exps = bitstream_get (state, 7);
+
+ exponent += exp_1[exps];
+ if (exponent > 24)
+ return 1;
+
+ switch (expstr) {
+ case EXP_D45:
+ *(dest++) = exponent;
+ *(dest++) = exponent;
+ case EXP_D25:
+ *(dest++) = exponent;
+ case EXP_D15:
+ *(dest++) = exponent;
+ }
+
+ exponent += exp_2[exps];
+ if (exponent > 24)
+ return 1;
+
+ switch (expstr) {
+ case EXP_D45:
+ *(dest++) = exponent;
+ *(dest++) = exponent;
+ case EXP_D25:
+ *(dest++) = exponent;
+ case EXP_D15:
+ *(dest++) = exponent;
+ }
+
+ exponent += exp_3[exps];
+ if (exponent > 24)
+ return 1;
+
+ switch (expstr) {
+ case EXP_D45:
+ *(dest++) = exponent;
+ *(dest++) = exponent;
+ case EXP_D25:
+ *(dest++) = exponent;
+ case EXP_D15:
+ *(dest++) = exponent;
+ }
+ }
+
+ return 0;
+}
+
+static int parse_deltba (a52_state_t * state, int8_t * deltba)
+{
+ int deltnseg, deltlen, delta, j;
+
+ memset (deltba, 0, 50);
+
+ deltnseg = bitstream_get (state, 3);
+ j = 0;
+ do {
+ j += bitstream_get (state, 5);
+ deltlen = bitstream_get (state, 4);
+ delta = bitstream_get (state, 3);
+ delta -= (delta >= 4) ? 3 : 4;
+ if (!deltlen)
+ continue;
+ if (j + deltlen >= 50)
+ return 1;
+ while (deltlen--)
+ deltba[j++] = delta;
+ } while (deltnseg--);
+
+ return 0;
+}
+
+static inline int zero_snr_offsets (int nfchans, a52_state_t * state)
+{
+ int i;
+
+ if ((state->csnroffst) ||
+ (state->chincpl && state->cplba.bai >> 3) || /* cplinu, fsnroffst */
+ (state->lfeon && state->lfeba.bai >> 3)) /* fsnroffst */
+ return 0;
+ for (i = 0; i < nfchans; i++)
+ if (state->ba[i].bai >> 3) /* fsnroffst */
+ return 0;
+ return 1;
+}
+
+static inline int16_t dither_gen (a52_state_t * state)
+{
+ int16_t nstate;
+
+ nstate = dither_lut[state->lfsr_state >> 8] ^ (state->lfsr_state << 8);
+
+ state->lfsr_state = (uint16_t) nstate;
+
+ return (3 * nstate) >> 2;
+}
+
+#ifndef LIBA52_FIXED
+#define COEFF(c,t,l,s,e) (c) = (t) * (s)[e]
+#else
+#define COEFF(c,_t,_l,s,e) do { \
+ quantizer_t t = (_t); \
+ level_t l = (_l); \
+ int shift = e - 5; \
+ sample_t tmp = t * (l >> 16) + ((t * (l & 0xffff)) >> 16); \
+ if (shift >= 0) \
+ (c) = tmp >> shift; \
+ else \
+ (c) = tmp << -shift; \
+} while (0)
+#endif
+
+static void coeff_get (a52_state_t * state, sample_t * coeff,
+ expbap_t * expbap, quantizer_set_t * quant,
+ level_t level, int dither, int end)
+{
+ int i;
+ uint8_t * exp;
+ int8_t * bap;
+
+#ifndef LIBA52_FIXED
+ sample_t factor[25];
+
+ for (i = 0; i <= 24; i++)
+ factor[i] = scale_factor[i] * level;
+#endif
+
+ exp = expbap->exp;
+ bap = expbap->bap;
+
+ for (i = 0; i < end; i++) {
+ int bapi;
+
+ bapi = bap[i];
+ switch (bapi) {
+ case 0:
+ if (dither) {
+ COEFF (coeff[i], dither_gen (state), level, factor, exp[i]);
+ continue;
+ } else {
+ coeff[i] = 0;
+ continue;
+ }
+
+ case -1:
+ if (quant->q1_ptr >= 0) {
+ COEFF (coeff[i], quant->q1[quant->q1_ptr--], level,
+ factor, exp[i]);
+ continue;
+ } else {
+ int code;
+
+ code = bitstream_get (state, 5);
+
+ quant->q1_ptr = 1;
+ quant->q1[0] = q_1_2[code];
+ quant->q1[1] = q_1_1[code];
+ COEFF (coeff[i], q_1_0[code], level, factor, exp[i]);
+ continue;
+ }
+
+ case -2:
+ if (quant->q2_ptr >= 0) {
+ COEFF (coeff[i], quant->q2[quant->q2_ptr--], level,
+ factor, exp[i]);
+ continue;
+ } else {
+ int code;
+
+ code = bitstream_get (state, 7);
+
+ quant->q2_ptr = 1;
+ quant->q2[0] = q_2_2[code];
+ quant->q2[1] = q_2_1[code];
+ COEFF (coeff[i], q_2_0[code], level, factor, exp[i]);
+ continue;
+ }
+
+ case 3:
+ COEFF (coeff[i], q_3[bitstream_get (state, 3)], level,
+ factor, exp[i]);
+ continue;
+
+ case -3:
+ if (quant->q4_ptr == 0) {
+ quant->q4_ptr = -1;
+ COEFF (coeff[i], quant->q4, level, factor, exp[i]);
+ continue;
+ } else {
+ int code;
+
+ code = bitstream_get (state, 7);
+
+ quant->q4_ptr = 0;
+ quant->q4 = q_4_1[code];
+ COEFF (coeff[i], q_4_0[code], level, factor, exp[i]);
+ continue;
+ }
+
+ case 4:
+ COEFF (coeff[i], q_5[bitstream_get (state, 4)], level,
+ factor, exp[i]);
+ continue;
+
+ default:
+ COEFF (coeff[i], bitstream_get_2 (state, bapi) << (16 - bapi),
+ level, factor, exp[i]);
+ }
+ }
+}
+
+static void coeff_get_coupling (a52_state_t * state, int nfchans,
+ level_t * coeff, sample_t (* samples)[256],
+ quantizer_set_t * quant, uint8_t dithflag[5])
+{
+ int cplbndstrc, bnd, i, i_end, ch;
+ uint8_t * exp;
+ int8_t * bap;
+ level_t cplco[5];
+
+ exp = state->cpl_expbap.exp;
+ bap = state->cpl_expbap.bap;
+ bnd = 0;
+ cplbndstrc = state->cplbndstrc;
+ i = state->cplstrtmant;
+ while (i < state->cplendmant) {
+ i_end = i + 12;
+ while (cplbndstrc & 1) {
+ cplbndstrc >>= 1;
+ i_end += 12;
+ }
+ cplbndstrc >>= 1;
+ for (ch = 0; ch < nfchans; ch++)
+ cplco[ch] = MUL_L (state->cplco[ch][bnd], coeff[ch]);
+ bnd++;
+
+ while (i < i_end) {
+ quantizer_t cplcoeff;
+ int bapi;
+
+ bapi = bap[i];
+ switch (bapi) {
+ case 0:
+ for (ch = 0; ch < nfchans; ch++)
+ if ((state->chincpl >> ch) & 1) {
+ if (dithflag[ch])
+#ifndef LIBA52_FIXED
+ samples[ch][i] = (scale_factor[exp[i]] *
+ cplco[ch] * dither_gen (state));
+#else
+ COEFF (samples[ch][i], dither_gen (state),
+ cplco[ch], scale_factor, exp[i]);
+#endif
+ else
+ samples[ch][i] = 0;
+ }
+ i++;
+ continue;
+
+ case -1:
+ if (quant->q1_ptr >= 0) {
+ cplcoeff = quant->q1[quant->q1_ptr--];
+ break;
+ } else {
+ int code;
+
+ code = bitstream_get (state, 5);
+
+ quant->q1_ptr = 1;
+ quant->q1[0] = q_1_2[code];
+ quant->q1[1] = q_1_1[code];
+ cplcoeff = q_1_0[code];
+ break;
+ }
+
+ case -2:
+ if (quant->q2_ptr >= 0) {
+ cplcoeff = quant->q2[quant->q2_ptr--];
+ break;
+ } else {
+ int code;
+
+ code = bitstream_get (state, 7);
+
+ quant->q2_ptr = 1;
+ quant->q2[0] = q_2_2[code];
+ quant->q2[1] = q_2_1[code];
+ cplcoeff = q_2_0[code];
+ break;
+ }
+
+ case 3:
+ cplcoeff = q_3[bitstream_get (state, 3)];
+ break;
+
+ case -3:
+ if (quant->q4_ptr == 0) {
+ quant->q4_ptr = -1;
+ cplcoeff = quant->q4;
+ break;
+ } else {
+ int code;
+
+ code = bitstream_get (state, 7);
+
+ quant->q4_ptr = 0;
+ quant->q4 = q_4_1[code];
+ cplcoeff = q_4_0[code];
+ break;
+ }
+
+ case 4:
+ cplcoeff = q_5[bitstream_get (state, 4)];
+ break;
+
+ default:
+ cplcoeff = bitstream_get_2 (state, bapi) << (16 - bapi);
+ }
+#ifndef LIBA52_FIXED
+ cplcoeff *= scale_factor[exp[i]];
+#endif
+ for (ch = 0; ch < nfchans; ch++)
+ if ((state->chincpl >> ch) & 1)
+#ifndef LIBA52_FIXED
+ samples[ch][i] = cplcoeff * cplco[ch];
+#else
+ COEFF (samples[ch][i], cplcoeff, cplco[ch],
+ scale_factor, exp[i]);
+#endif
+ i++;
+ }
+ }
+}
+
+int a52_block (a52_state_t * state)
+{
+ static const uint8_t nfchans_tbl[] = {2, 1, 2, 3, 3, 4, 4, 5, 1, 1, 2};
+ static int rematrix_band[4] = {25, 37, 61, 253};
+ int i, nfchans, chaninfo;
+ uint8_t cplexpstr, chexpstr[5], lfeexpstr, do_bit_alloc, done_cpl;
+ uint8_t blksw[5], dithflag[5];
+ level_t coeff[5];
+ int chanbias;
+ quantizer_set_t quant;
+ sample_t * samples;
+
+ nfchans = nfchans_tbl[state->acmod];
+
+ for (i = 0; i < nfchans; i++)
+ blksw[i] = bitstream_get (state, 1);
+
+ for (i = 0; i < nfchans; i++)
+ dithflag[i] = bitstream_get (state, 1);
+
+ chaninfo = !state->acmod;
+ do {
+ if (bitstream_get (state, 1)) { /* dynrnge */
+ int dynrng;
+
+ dynrng = bitstream_get_2 (state, 8);
+ if (state->dynrnge) {
+ level_t range;
+
+#if !defined(LIBA52_FIXED)
+ range = ((((dynrng & 0x1f) | 0x20) << 13) *
+ scale_factor[3 - (dynrng >> 5)]);
+#else
+ range = ((dynrng & 0x1f) | 0x20) << (21 + (dynrng >> 5));
+#endif
+ if (state->dynrngcall)
+ range = state->dynrngcall (range, state->dynrngdata);
+ state->dynrng = MUL_L (state->level, range);
+ }
+ }
+ } while (chaninfo--);
+
+ if (bitstream_get (state, 1)) { /* cplstre */
+ state->chincpl = 0;
+ if (bitstream_get (state, 1)) { /* cplinu */
+ static uint8_t bndtab[16] = {31, 35, 37, 39, 41, 42, 43, 44,
+ 45, 45, 46, 46, 47, 47, 48, 48};
+ int cplbegf;
+ int cplendf;
+ int ncplsubnd;
+
+ for (i = 0; i < nfchans; i++)
+ state->chincpl |= bitstream_get (state, 1) << i;
+ switch (state->acmod) {
+ case 0: case 1:
+ return 1;
+ case 2:
+ state->phsflginu = bitstream_get (state, 1);
+ }
+ cplbegf = bitstream_get (state, 4);
+ cplendf = bitstream_get (state, 4);
+
+ if (cplendf + 3 - cplbegf < 0)
+ return 1;
+ state->ncplbnd = ncplsubnd = cplendf + 3 - cplbegf;
+ state->cplstrtbnd = bndtab[cplbegf];
+ state->cplstrtmant = cplbegf * 12 + 37;
+ state->cplendmant = cplendf * 12 + 73;
+
+ state->cplbndstrc = 0;
+ for (i = 0; i < ncplsubnd - 1; i++)
+ if (bitstream_get (state, 1)) {
+ state->cplbndstrc |= 1 << i;
+ state->ncplbnd--;
+ }
+ }
+ }
+
+ if (state->chincpl) { /* cplinu */
+ int j, cplcoe;
+
+ cplcoe = 0;
+ for (i = 0; i < nfchans; i++)
+ if ((state->chincpl) >> i & 1)
+ if (bitstream_get (state, 1)) { /* cplcoe */
+ int mstrcplco, cplcoexp, cplcomant;
+
+ cplcoe = 1;
+ mstrcplco = 3 * bitstream_get (state, 2);
+ for (j = 0; j < state->ncplbnd; j++) {
+ cplcoexp = bitstream_get (state, 4);
+ cplcomant = bitstream_get (state, 4);
+ if (cplcoexp == 15)
+ cplcomant <<= 14;
+ else
+ cplcomant = (cplcomant | 0x10) << 13;
+#ifndef LIBA52_FIXED
+ state->cplco[i][j] =
+ cplcomant * scale_factor[cplcoexp + mstrcplco];
+#else
+ state->cplco[i][j] = (cplcomant << 11) >> (cplcoexp + mstrcplco);
+#endif
+
+ }
+ }
+ if ((state->acmod == 2) && state->phsflginu && cplcoe)
+ for (j = 0; j < state->ncplbnd; j++)
+ if (bitstream_get (state, 1)) /* phsflg */
+ state->cplco[1][j] = -state->cplco[1][j];
+ }
+
+ if ((state->acmod == 2) && (bitstream_get (state, 1))) { /* rematstr */
+ int end;
+
+ state->rematflg = 0;
+ end = (state->chincpl) ? state->cplstrtmant : 253; /* cplinu */
+ i = 0;
+ do
+ state->rematflg |= bitstream_get (state, 1) << i;
+ while (rematrix_band[i++] < end);
+ }
+
+ cplexpstr = EXP_REUSE;
+ lfeexpstr = EXP_REUSE;
+ if (state->chincpl) /* cplinu */
+ cplexpstr = bitstream_get (state, 2);
+ for (i = 0; i < nfchans; i++)
+ chexpstr[i] = bitstream_get (state, 2);
+ if (state->lfeon)
+ lfeexpstr = bitstream_get (state, 1);
+
+ for (i = 0; i < nfchans; i++)
+ if (chexpstr[i] != EXP_REUSE) {
+ if ((state->chincpl >> i) & 1)
+ state->endmant[i] = state->cplstrtmant;
+ else {
+ int chbwcod;
+
+ chbwcod = bitstream_get (state, 6);
+ if (chbwcod > 60)
+ return 1;
+ state->endmant[i] = chbwcod * 3 + 73;
+ }
+ }
+
+ do_bit_alloc = 0;
+
+ if (cplexpstr != EXP_REUSE) {
+ int cplabsexp, ncplgrps;
+
+ do_bit_alloc = 64;
+ ncplgrps = ((state->cplendmant - state->cplstrtmant) /
+ (3 << (cplexpstr - 1)));
+ cplabsexp = bitstream_get (state, 4) << 1;
+ if (parse_exponents (state, cplexpstr, ncplgrps, cplabsexp,
+ state->cpl_expbap.exp + state->cplstrtmant))
+ return 1;
+ }
+ for (i = 0; i < nfchans; i++)
+ if (chexpstr[i] != EXP_REUSE) {
+ int grp_size, nchgrps;
+
+ do_bit_alloc |= 1 << i;
+ grp_size = 3 << (chexpstr[i] - 1);
+ nchgrps = (state->endmant[i] + grp_size - 4) / grp_size;
+ state->fbw_expbap[i].exp[0] = bitstream_get (state, 4);
+ if (parse_exponents (state, chexpstr[i], nchgrps,
+ state->fbw_expbap[i].exp[0],
+ state->fbw_expbap[i].exp + 1))
+ return 1;
+ bitstream_get (state, 2); /* gainrng */
+ }
+ if (lfeexpstr != EXP_REUSE) {
+ do_bit_alloc |= 32;
+ state->lfe_expbap.exp[0] = bitstream_get (state, 4);
+ if (parse_exponents (state, lfeexpstr, 2, state->lfe_expbap.exp[0],
+ state->lfe_expbap.exp + 1))
+ return 1;
+ }
+
+ if (bitstream_get (state, 1)) { /* baie */
+ do_bit_alloc = 127;
+ state->bai = bitstream_get (state, 11);
+ }
+ if (bitstream_get (state, 1)) { /* snroffste */
+ do_bit_alloc = 127;
+ state->csnroffst = bitstream_get (state, 6);
+ if (state->chincpl) /* cplinu */
+ state->cplba.bai = bitstream_get (state, 7);
+ for (i = 0; i < nfchans; i++)
+ state->ba[i].bai = bitstream_get (state, 7);
+ if (state->lfeon)
+ state->lfeba.bai = bitstream_get (state, 7);
+ }
+ if ((state->chincpl) && (bitstream_get (state, 1))) { /* cplleake */
+ do_bit_alloc |= 64;
+ state->cplfleak = 9 - bitstream_get (state, 3);
+ state->cplsleak = 9 - bitstream_get (state, 3);
+ }
+
+ if (bitstream_get (state, 1)) { /* deltbaie */
+ do_bit_alloc = 127;
+ if (state->chincpl) /* cplinu */
+ state->cplba.deltbae = bitstream_get (state, 2);
+ for (i = 0; i < nfchans; i++)
+ state->ba[i].deltbae = bitstream_get (state, 2);
+ if (state->chincpl && /* cplinu */
+ (state->cplba.deltbae == DELTA_BIT_NEW) &&
+ parse_deltba (state, state->cplba.deltba))
+ return 1;
+ for (i = 0; i < nfchans; i++)
+ if ((state->ba[i].deltbae == DELTA_BIT_NEW) &&
+ parse_deltba (state, state->ba[i].deltba))
+ return 1;
+ }
+
+ if (do_bit_alloc) {
+ if (zero_snr_offsets (nfchans, state)) {
+ memset (state->cpl_expbap.bap, 0, sizeof (state->cpl_expbap.bap));
+ for (i = 0; i < nfchans; i++)
+ memset (state->fbw_expbap[i].bap, 0,
+ sizeof (state->fbw_expbap[i].bap));
+ memset (state->lfe_expbap.bap, 0, sizeof (state->lfe_expbap.bap));
+ } else {
+ if (state->chincpl && (do_bit_alloc & 64)) /* cplinu */
+ a52_bit_allocate (state, &state->cplba, state->cplstrtbnd,
+ state->cplstrtmant, state->cplendmant,
+ state->cplfleak << 8, state->cplsleak << 8,
+ &state->cpl_expbap);
+ for (i = 0; i < nfchans; i++)
+ if (do_bit_alloc & (1 << i))
+ a52_bit_allocate (state, state->ba + i, 0, 0,
+ state->endmant[i], 0, 0,
+ state->fbw_expbap +i);
+ if (state->lfeon && (do_bit_alloc & 32)) {
+ state->lfeba.deltbae = DELTA_BIT_NONE;
+ a52_bit_allocate (state, &state->lfeba, 0, 0, 7, 0, 0,
+ &state->lfe_expbap);
+ }
+ }
+ }
+
+ if (bitstream_get (state, 1)) { /* skiple */
+ i = bitstream_get (state, 9); /* skipl */
+ while (i--)
+ bitstream_get (state, 8);
+ }
+
+ samples = state->samples;
+ if (state->output & A52_LFE)
+ samples += 256; /* shift for LFE channel */
+
+ chanbias = a52_downmix_coeff (coeff, state->acmod, state->output,
+ state->dynrng, state->clev, state->slev);
+
+ quant.q1_ptr = quant.q2_ptr = quant.q4_ptr = -1;
+ done_cpl = 0;
+
+ for (i = 0; i < nfchans; i++) {
+ int j;
+
+ coeff_get (state, samples + 256 * i, state->fbw_expbap +i, &quant,
+ coeff[i], dithflag[i], state->endmant[i]);
+
+ if ((state->chincpl >> i) & 1) {
+ if (!done_cpl) {
+ done_cpl = 1;
+ coeff_get_coupling (state, nfchans, coeff,
+ (sample_t (*)[256])samples, &quant,
+ dithflag);
+ }
+ j = state->cplendmant;
+ } else
+ j = state->endmant[i];
+ do
+ (samples + 256 * i)[j] = 0;
+ while (++j < 256);
+ }
+
+ if (state->acmod == 2) {
+ int j, end, band, rematflg;
+
+ end = ((state->endmant[0] < state->endmant[1]) ?
+ state->endmant[0] : state->endmant[1]);
+
+ i = 0;
+ j = 13;
+ rematflg = state->rematflg;
+ do {
+ if (! (rematflg & 1)) {
+ rematflg >>= 1;
+ j = rematrix_band[i++];
+ continue;
+ }
+ rematflg >>= 1;
+ band = rematrix_band[i++];
+ if (band > end)
+ band = end;
+ do {
+ sample_t tmp0, tmp1;
+
+ tmp0 = samples[j];
+ tmp1 = (samples+256)[j];
+ samples[j] = tmp0 + tmp1;
+ (samples+256)[j] = tmp0 - tmp1;
+ } while (++j < band);
+ } while (j < end);
+ }
+
+ if (state->lfeon) {
+ if (state->output & A52_LFE) {
+ coeff_get (state, samples - 256, &state->lfe_expbap, &quant,
+ state->dynrng, 0, 7);
+ for (i = 7; i < 256; i++)
+ (samples-256)[i] = 0;
+ a52_imdct_512 (samples - 256, samples + 1536 - 256, state->bias);
+ } else {
+ /* just skip the LFE coefficients */
+ coeff_get (state, samples + 1280, &state->lfe_expbap, &quant,
+ 0, 0, 7);
+ }
+ }
+
+ i = 0;
+ if (nfchans_tbl[state->output & A52_CHANNEL_MASK] < nfchans)
+ for (i = 1; i < nfchans; i++)
+ if (blksw[i] != blksw[0])
+ break;
+
+ if (i < nfchans) {
+ if (state->downmixed) {
+ state->downmixed = 0;
+ a52_upmix (samples + 1536, state->acmod, state->output);
+ }
+
+ for (i = 0; i < nfchans; i++) {
+ sample_t bias;
+
+ bias = 0;
+ if (!(chanbias & (1 << i)))
+ bias = state->bias;
+
+ if (coeff[i]) {
+ if (blksw[i])
+ a52_imdct_256 (samples + 256 * i, samples + 1536 + 256 * i,
+ bias);
+ else
+ a52_imdct_512 (samples + 256 * i, samples + 1536 + 256 * i,
+ bias);
+ } else {
+ int j;
+
+ for (j = 0; j < 256; j++)
+ (samples + 256 * i)[j] = bias;
+ }
+ }
+
+ a52_downmix (samples, state->acmod, state->output, state->bias,
+ state->clev, state->slev);
+ } else {
+ nfchans = nfchans_tbl[state->output & A52_CHANNEL_MASK];
+
+ a52_downmix (samples, state->acmod, state->output, 0,
+ state->clev, state->slev);
+
+ if (!state->downmixed) {
+ state->downmixed = 1;
+ a52_downmix (samples + 1536, state->acmod, state->output, 0,
+ state->clev, state->slev);
+ }
+
+ if (blksw[0])
+ for (i = 0; i < nfchans; i++)
+ a52_imdct_256 (samples + 256 * i, samples + 1536 + 256 * i,
+ state->bias);
+ else
+ for (i = 0; i < nfchans; i++)
+ a52_imdct_512 (samples + 256 * i, samples + 1536 + 256 * i,
+ state->bias);
+ }
+
+ return 0;
+}
+
+void a52_free (a52_state_t * state)
+{
+ free (state->samples);
+ free (state);
+}
diff --git a/contrib/ffmpeg/libavcodec/liba52/resample.c b/contrib/ffmpeg/libavcodec/liba52/resample.c
new file mode 100644
index 000000000..3f06aba1f
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/liba52/resample.c
@@ -0,0 +1,63 @@
+/*
+ * copyright (C) 2001 Arpad Gereoffy
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * a52dec is distributed in the hope that 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+// a52_resample_init should find the requested converter (from type flags ->
+// given number of channels) and set up some function pointers...
+
+// a52_resample() should do the conversion.
+
+#include "a52.h"
+#include "mm_accel.h"
+#include "config.h"
+#include "../../libpostproc/mangle.h"
+
+int (* a52_resample) (float * _f, int16_t * s16)=NULL;
+
+#include "resample_c.c"
+
+#ifdef ARCH_X86_32
+#include "resample_mmx.c"
+#endif
+
+void* a52_resample_init(uint32_t mm_accel,int flags,int chans){
+void* tmp;
+
+#ifdef ARCH_X86_32
+ if(mm_accel&MM_ACCEL_X86_MMX){
+ tmp=a52_resample_MMX(flags,chans);
+ if(tmp){
+ if(a52_resample==NULL) av_log(NULL, AV_LOG_INFO, "Using MMX optimized resampler\n");
+ a52_resample=tmp;
+ return tmp;
+ }
+ }
+#endif
+
+ tmp=a52_resample_C(flags,chans);
+ if(tmp){
+ if(a52_resample==NULL) av_log(NULL, AV_LOG_INFO, "No accelerated resampler found\n");
+ a52_resample=tmp;
+ return tmp;
+ }
+
+ av_log(NULL, AV_LOG_ERROR, "Unimplemented resampler for mode 0x%X -> %d channels conversion - Contact MPlayer developers!\n", flags, chans);
+ return NULL;
+}
diff --git a/contrib/ffmpeg/libavcodec/liba52/resample_c.c b/contrib/ffmpeg/libavcodec/liba52/resample_c.c
new file mode 100644
index 000000000..905146a7d
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/liba52/resample_c.c
@@ -0,0 +1,203 @@
+/*
+ * this code is based on a52dec/libao/audio_out_oss.c
+ * copyright (C) 2001 Arpad Gereoffy
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * a52dec is distributed in the hope that 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+static inline int16_t convert (int32_t i)
+{
+ if (i > 0x43c07fff)
+ return 32767;
+ else if (i < 0x43bf8000)
+ return -32768;
+ else
+ return i - 0x43c00000;
+}
+
+static int a52_resample_MONO_to_5_C(float * _f, int16_t * s16){
+ int i;
+ int32_t * f = (int32_t *) _f;
+ for (i = 0; i < 256; i++) {
+ s16[5*i] = s16[5*i+1] = s16[5*i+2] = s16[5*i+3] = 0;
+ s16[5*i+4] = convert (f[i]);
+ }
+ return 5*256;
+}
+
+static int a52_resample_MONO_to_1_C(float * _f, int16_t * s16){
+ int i;
+ int32_t * f = (int32_t *) _f;
+ for (i = 0; i < 256; i++) {
+ s16[i] = convert (f[i]);
+ }
+ return 1*256;
+}
+
+static int a52_resample_STEREO_to_2_C(float * _f, int16_t * s16){
+ int i;
+ int32_t * f = (int32_t *) _f;
+ for (i = 0; i < 256; i++) {
+ s16[2*i] = convert (f[i]);
+ s16[2*i+1] = convert (f[i+256]);
+ }
+ return 2*256;
+}
+
+static int a52_resample_3F_to_5_C(float * _f, int16_t * s16){
+ int i;
+ int32_t * f = (int32_t *) _f;
+ for (i = 0; i < 256; i++) {
+ s16[5*i] = convert (f[i]);
+ s16[5*i+1] = convert (f[i+512]);
+ s16[5*i+2] = s16[5*i+3] = 0;
+ s16[5*i+4] = convert (f[i+256]);
+ }
+ return 5*256;
+}
+
+static int a52_resample_2F_2R_to_4_C(float * _f, int16_t * s16){
+ int i;
+ int32_t * f = (int32_t *) _f;
+ for (i = 0; i < 256; i++) {
+ s16[4*i] = convert (f[i]);
+ s16[4*i+1] = convert (f[i+256]);
+ s16[4*i+2] = convert (f[i+512]);
+ s16[4*i+3] = convert (f[i+768]);
+ }
+ return 4*256;
+}
+
+static int a52_resample_3F_2R_to_5_C(float * _f, int16_t * s16){
+ int i;
+ int32_t * f = (int32_t *) _f;
+ for (i = 0; i < 256; i++) {
+ s16[5*i] = convert (f[i]);
+ s16[5*i+1] = convert (f[i+512]);
+ s16[5*i+2] = convert (f[i+768]);
+ s16[5*i+3] = convert (f[i+1024]);
+ s16[5*i+4] = convert (f[i+256]);
+ }
+ return 5*256;
+}
+
+static int a52_resample_MONO_LFE_to_6_C(float * _f, int16_t * s16){
+ int i;
+ int32_t * f = (int32_t *) _f;
+ for (i = 0; i < 256; i++) {
+ s16[6*i] = s16[6*i+1] = s16[6*i+2] = s16[6*i+3] = 0;
+ s16[6*i+4] = convert (f[i+256]);
+ s16[6*i+5] = convert (f[i]);
+ }
+ return 6*256;
+}
+
+static int a52_resample_STEREO_LFE_to_6_C(float * _f, int16_t * s16){
+ int i;
+ int32_t * f = (int32_t *) _f;
+ for (i = 0; i < 256; i++) {
+ s16[6*i] = convert (f[i+256]);
+ s16[6*i+1] = convert (f[i+512]);
+ s16[6*i+2] = s16[6*i+3] = s16[6*i+4] = 0;
+ s16[6*i+5] = convert (f[i]);
+ }
+ return 6*256;
+}
+
+static int a52_resample_3F_LFE_to_6_C(float * _f, int16_t * s16){
+ int i;
+ int32_t * f = (int32_t *) _f;
+ for (i = 0; i < 256; i++) {
+ s16[6*i] = convert (f[i+256]);
+ s16[6*i+1] = convert (f[i+768]);
+ s16[6*i+2] = s16[6*i+3] = 0;
+ s16[6*i+4] = convert (f[i+512]);
+ s16[6*i+5] = convert (f[i]);
+ }
+ return 6*256;
+}
+
+static int a52_resample_2F_2R_LFE_to_6_C(float * _f, int16_t * s16){
+ int i;
+ int32_t * f = (int32_t *) _f;
+ for (i = 0; i < 256; i++) {
+ s16[6*i] = convert (f[i+256]);
+ s16[6*i+1] = convert (f[i+512]);
+ s16[6*i+2] = convert (f[i+768]);
+ s16[6*i+3] = convert (f[i+1024]);
+ s16[6*i+4] = 0;
+ s16[6*i+5] = convert (f[i]);
+ }
+ return 6*256;
+}
+
+static int a52_resample_3F_2R_LFE_to_6_C(float * _f, int16_t * s16){
+ int i;
+ int32_t * f = (int32_t *) _f;
+ for (i = 0; i < 256; i++) {
+ s16[6*i] = convert (f[i+256]);
+ s16[6*i+1] = convert (f[i+768]);
+ s16[6*i+2] = convert (f[i+1024]);
+ s16[6*i+3] = convert (f[i+1280]);
+ s16[6*i+4] = convert (f[i+512]);
+ s16[6*i+5] = convert (f[i]);
+ }
+ return 6*256;
+}
+
+
+static void* a52_resample_C(int flags, int ch){
+ switch (flags) {
+ case A52_MONO:
+ if(ch==5) return a52_resample_MONO_to_5_C;
+ if(ch==1) return a52_resample_MONO_to_1_C;
+ break;
+ case A52_CHANNEL:
+ case A52_STEREO:
+ case A52_DOLBY:
+ if(ch==2) return a52_resample_STEREO_to_2_C;
+ break;
+ case A52_3F:
+ if(ch==5) return a52_resample_3F_to_5_C;
+ break;
+ case A52_2F2R:
+ if(ch==4) return a52_resample_2F_2R_to_4_C;
+ break;
+ case A52_3F2R:
+ if(ch==5) return a52_resample_3F_2R_to_5_C;
+ break;
+ case A52_MONO | A52_LFE:
+ if(ch==6) return a52_resample_MONO_LFE_to_6_C;
+ break;
+ case A52_CHANNEL | A52_LFE:
+ case A52_STEREO | A52_LFE:
+ case A52_DOLBY | A52_LFE:
+ if(ch==6) return a52_resample_STEREO_LFE_to_6_C;
+ break;
+ case A52_3F | A52_LFE:
+ if(ch==6) return a52_resample_3F_LFE_to_6_C;
+ break;
+ case A52_2F2R | A52_LFE:
+ if(ch==6) return a52_resample_2F_2R_LFE_to_6_C;
+ break;
+ case A52_3F2R | A52_LFE:
+ if(ch==6) return a52_resample_3F_2R_LFE_to_6_C;
+ break;
+ }
+ return NULL;
+}
diff --git a/contrib/ffmpeg/libavcodec/liba52/resample_mmx.c b/contrib/ffmpeg/libavcodec/liba52/resample_mmx.c
new file mode 100644
index 000000000..173c804d9
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/liba52/resample_mmx.c
@@ -0,0 +1,537 @@
+/*
+ * resample_mmx.c
+ * Copyright (C) 2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * a52dec is distributed in the hope that 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* optimization TODO / NOTES
+ movntq is slightly faster (0.5% with the current test.c benchmark)
+ (but thats just test.c so that needs to be testd in reallity)
+ and it would mean (C / MMX2 / MMX / 3DNOW) versions
+*/
+
+static uint64_t __attribute__((aligned(8))) attribute_used magicF2W= 0x43c0000043c00000LL;
+static uint64_t __attribute__((aligned(8))) attribute_used wm1010= 0xFFFF0000FFFF0000LL;
+static uint64_t __attribute__((aligned(8))) attribute_used wm0101= 0x0000FFFF0000FFFFLL;
+static uint64_t __attribute__((aligned(8))) attribute_used wm1100= 0xFFFFFFFF00000000LL;
+
+static int a52_resample_MONO_to_5_MMX(float * _f, int16_t * s16){
+ int32_t * f = (int32_t *) _f;
+ asm volatile(
+ "movl $-512, %%esi \n\t"
+ "movq "MANGLE(magicF2W)", %%mm7 \n\t"
+ "movq "MANGLE(wm1100)", %%mm3 \n\t"
+ "movq "MANGLE(wm0101)", %%mm4 \n\t"
+ "movq "MANGLE(wm1010)", %%mm5 \n\t"
+ "pxor %%mm6, %%mm6 \n\t"
+ "1: \n\t"
+ "movq (%1, %%esi, 2), %%mm0 \n\t"
+ "movq 8(%1, %%esi, 2), %%mm1 \n\t"
+ "leal (%%esi, %%esi, 4), %%edi \n\t"
+ "psubd %%mm7, %%mm0 \n\t"
+ "psubd %%mm7, %%mm1 \n\t"
+ "packssdw %%mm1, %%mm0 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "pand %%mm4, %%mm0 \n\t"
+ "pand %%mm5, %%mm1 \n\t"
+ "movq %%mm6, (%0, %%edi) \n\t" // 0 0 0 0
+ "movd %%mm0, 8(%0, %%edi) \n\t" // A 0
+ "pand %%mm3, %%mm0 \n\t"
+ "movd %%mm6, 12(%0, %%edi) \n\t" // 0 0
+ "movd %%mm1, 16(%0, %%edi) \n\t" // 0 B
+ "pand %%mm3, %%mm1 \n\t"
+ "movd %%mm6, 20(%0, %%edi) \n\t" // 0 0
+ "movq %%mm0, 24(%0, %%edi) \n\t" // 0 0 C 0
+ "movq %%mm1, 32(%0, %%edi) \n\t" // 0 0 0 B
+ "addl $8, %%esi \n\t"
+ " jnz 1b \n\t"
+ "emms \n\t"
+ :: "r" (s16+1280), "r" (f+256)
+ :"%esi", "%edi", "memory"
+ );
+ return 5*256;
+}
+
+static int a52_resample_STEREO_to_2_MMX(float * _f, int16_t * s16){
+ int32_t * f = (int32_t *) _f;
+/* benchmark scores are 0.3% better with SSE but we would need to set bias=0 and premultiply it
+#ifdef HAVE_SSE
+ asm volatile(
+ "movl $-1024, %%esi \n\t"
+ "1: \n\t"
+ "cvtps2pi (%1, %%esi), %%mm0 \n\t"
+ "cvtps2pi 1024(%1, %%esi), %%mm2\n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "punpcklwd %%mm2, %%mm0 \n\t"
+ "punpckhwd %%mm2, %%mm1 \n\t"
+ "movq %%mm0, (%0, %%esi) \n\t"
+ "movq %%mm1, 8(%0, %%esi) \n\t"
+ "addl $16, %%esi \n\t"
+ " jnz 1b \n\t"
+ "emms \n\t"
+ :: "r" (s16+512), "r" (f+256)
+ :"%esi", "memory"
+ );*/
+ asm volatile(
+ "movl $-1024, %%esi \n\t"
+ "movq "MANGLE(magicF2W)", %%mm7 \n\t"
+ "1: \n\t"
+ "movq (%1, %%esi), %%mm0 \n\t"
+ "movq 8(%1, %%esi), %%mm1 \n\t"
+ "movq 1024(%1, %%esi), %%mm2 \n\t"
+ "movq 1032(%1, %%esi), %%mm3 \n\t"
+ "psubd %%mm7, %%mm0 \n\t"
+ "psubd %%mm7, %%mm1 \n\t"
+ "psubd %%mm7, %%mm2 \n\t"
+ "psubd %%mm7, %%mm3 \n\t"
+ "packssdw %%mm1, %%mm0 \n\t"
+ "packssdw %%mm3, %%mm2 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "punpcklwd %%mm2, %%mm0 \n\t"
+ "punpckhwd %%mm2, %%mm1 \n\t"
+ "movq %%mm0, (%0, %%esi) \n\t"
+ "movq %%mm1, 8(%0, %%esi) \n\t"
+ "addl $16, %%esi \n\t"
+ " jnz 1b \n\t"
+ "emms \n\t"
+ :: "r" (s16+512), "r" (f+256)
+ :"%esi", "memory"
+ );
+ return 2*256;
+}
+
+static int a52_resample_3F_to_5_MMX(float * _f, int16_t * s16){
+ int32_t * f = (int32_t *) _f;
+ asm volatile(
+ "movl $-1024, %%esi \n\t"
+ "movq "MANGLE(magicF2W)", %%mm7 \n\t"
+ "pxor %%mm6, %%mm6 \n\t"
+ "movq %%mm7, %%mm5 \n\t"
+ "punpckldq %%mm6, %%mm5 \n\t"
+ "1: \n\t"
+ "movd (%1, %%esi), %%mm0 \n\t"
+ "punpckldq 2048(%1, %%esi), %%mm0\n\t"
+ "movd 1024(%1, %%esi), %%mm1 \n\t"
+ "punpckldq 4(%1, %%esi), %%mm1 \n\t"
+ "movd 2052(%1, %%esi), %%mm2 \n\t"
+ "movq %%mm7, %%mm3 \n\t"
+ "punpckldq 1028(%1, %%esi), %%mm3\n\t"
+ "movd 8(%1, %%esi), %%mm4 \n\t"
+ "punpckldq 2056(%1, %%esi), %%mm4\n\t"
+ "leal (%%esi, %%esi, 4), %%edi \n\t"
+ "sarl $1, %%edi \n\t"
+ "psubd %%mm7, %%mm0 \n\t"
+ "psubd %%mm7, %%mm1 \n\t"
+ "psubd %%mm5, %%mm2 \n\t"
+ "psubd %%mm7, %%mm3 \n\t"
+ "psubd %%mm7, %%mm4 \n\t"
+ "packssdw %%mm6, %%mm0 \n\t"
+ "packssdw %%mm2, %%mm1 \n\t"
+ "packssdw %%mm4, %%mm3 \n\t"
+ "movq %%mm0, (%0, %%edi) \n\t"
+ "movq %%mm1, 8(%0, %%edi) \n\t"
+ "movq %%mm3, 16(%0, %%edi) \n\t"
+
+ "movd 1032(%1, %%esi), %%mm1 \n\t"
+ "punpckldq 12(%1, %%esi), %%mm1\n\t"
+ "movd 2060(%1, %%esi), %%mm2 \n\t"
+ "movq %%mm7, %%mm3 \n\t"
+ "punpckldq 1036(%1, %%esi), %%mm3\n\t"
+ "pxor %%mm0, %%mm0 \n\t"
+ "psubd %%mm7, %%mm1 \n\t"
+ "psubd %%mm5, %%mm2 \n\t"
+ "psubd %%mm7, %%mm3 \n\t"
+ "packssdw %%mm1, %%mm0 \n\t"
+ "packssdw %%mm3, %%mm2 \n\t"
+ "movq %%mm0, 24(%0, %%edi) \n\t"
+ "movq %%mm2, 32(%0, %%edi) \n\t"
+
+ "addl $16, %%esi \n\t"
+ " jnz 1b \n\t"
+ "emms \n\t"
+ :: "r" (s16+1280), "r" (f+256)
+ :"%esi", "%edi", "memory"
+ );
+ return 5*256;
+}
+
+static int a52_resample_2F_2R_to_4_MMX(float * _f, int16_t * s16){
+ int32_t * f = (int32_t *) _f;
+ asm volatile(
+ "movl $-1024, %%esi \n\t"
+ "movq "MANGLE(magicF2W)", %%mm7 \n\t"
+ "1: \n\t"
+ "movq (%1, %%esi), %%mm0 \n\t"
+ "movq 8(%1, %%esi), %%mm1 \n\t"
+ "movq 1024(%1, %%esi), %%mm2 \n\t"
+ "movq 1032(%1, %%esi), %%mm3 \n\t"
+ "psubd %%mm7, %%mm0 \n\t"
+ "psubd %%mm7, %%mm1 \n\t"
+ "psubd %%mm7, %%mm2 \n\t"
+ "psubd %%mm7, %%mm3 \n\t"
+ "packssdw %%mm1, %%mm0 \n\t"
+ "packssdw %%mm3, %%mm2 \n\t"
+ "movq 2048(%1, %%esi), %%mm3 \n\t"
+ "movq 2056(%1, %%esi), %%mm4 \n\t"
+ "movq 3072(%1, %%esi), %%mm5 \n\t"
+ "movq 3080(%1, %%esi), %%mm6 \n\t"
+ "psubd %%mm7, %%mm3 \n\t"
+ "psubd %%mm7, %%mm4 \n\t"
+ "psubd %%mm7, %%mm5 \n\t"
+ "psubd %%mm7, %%mm6 \n\t"
+ "packssdw %%mm4, %%mm3 \n\t"
+ "packssdw %%mm6, %%mm5 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "movq %%mm3, %%mm4 \n\t"
+ "punpcklwd %%mm2, %%mm0 \n\t"
+ "punpckhwd %%mm2, %%mm1 \n\t"
+ "punpcklwd %%mm5, %%mm3 \n\t"
+ "punpckhwd %%mm5, %%mm4 \n\t"
+ "movq %%mm0, %%mm2 \n\t"
+ "movq %%mm1, %%mm5 \n\t"
+ "punpckldq %%mm3, %%mm0 \n\t"
+ "punpckhdq %%mm3, %%mm2 \n\t"
+ "punpckldq %%mm4, %%mm1 \n\t"
+ "punpckhdq %%mm4, %%mm5 \n\t"
+ "movq %%mm0, (%0, %%esi,2) \n\t"
+ "movq %%mm2, 8(%0, %%esi,2) \n\t"
+ "movq %%mm1, 16(%0, %%esi,2) \n\t"
+ "movq %%mm5, 24(%0, %%esi,2) \n\t"
+ "addl $16, %%esi \n\t"
+ " jnz 1b \n\t"
+ "emms \n\t"
+ :: "r" (s16+1024), "r" (f+256)
+ :"%esi", "memory"
+ );
+ return 4*256;
+}
+
+static int a52_resample_3F_2R_to_5_MMX(float * _f, int16_t * s16){
+ int32_t * f = (int32_t *) _f;
+ asm volatile(
+ "movl $-1024, %%esi \n\t"
+ "movq "MANGLE(magicF2W)", %%mm7 \n\t"
+ "1: \n\t"
+ "movd (%1, %%esi), %%mm0 \n\t"
+ "punpckldq 2048(%1, %%esi), %%mm0\n\t"
+ "movd 3072(%1, %%esi), %%mm1 \n\t"
+ "punpckldq 4096(%1, %%esi), %%mm1\n\t"
+ "movd 1024(%1, %%esi), %%mm2 \n\t"
+ "punpckldq 4(%1, %%esi), %%mm2 \n\t"
+ "movd 2052(%1, %%esi), %%mm3 \n\t"
+ "punpckldq 3076(%1, %%esi), %%mm3\n\t"
+ "movd 4100(%1, %%esi), %%mm4 \n\t"
+ "punpckldq 1028(%1, %%esi), %%mm4\n\t"
+ "movd 8(%1, %%esi), %%mm5 \n\t"
+ "punpckldq 2056(%1, %%esi), %%mm5\n\t"
+ "leal (%%esi, %%esi, 4), %%edi \n\t"
+ "sarl $1, %%edi \n\t"
+ "psubd %%mm7, %%mm0 \n\t"
+ "psubd %%mm7, %%mm1 \n\t"
+ "psubd %%mm7, %%mm2 \n\t"
+ "psubd %%mm7, %%mm3 \n\t"
+ "psubd %%mm7, %%mm4 \n\t"
+ "psubd %%mm7, %%mm5 \n\t"
+ "packssdw %%mm1, %%mm0 \n\t"
+ "packssdw %%mm3, %%mm2 \n\t"
+ "packssdw %%mm5, %%mm4 \n\t"
+ "movq %%mm0, (%0, %%edi) \n\t"
+ "movq %%mm2, 8(%0, %%edi) \n\t"
+ "movq %%mm4, 16(%0, %%edi) \n\t"
+
+ "movd 3080(%1, %%esi), %%mm0 \n\t"
+ "punpckldq 4104(%1, %%esi), %%mm0\n\t"
+ "movd 1032(%1, %%esi), %%mm1 \n\t"
+ "punpckldq 12(%1, %%esi), %%mm1\n\t"
+ "movd 2060(%1, %%esi), %%mm2 \n\t"
+ "punpckldq 3084(%1, %%esi), %%mm2\n\t"
+ "movd 4108(%1, %%esi), %%mm3 \n\t"
+ "punpckldq 1036(%1, %%esi), %%mm3\n\t"
+ "psubd %%mm7, %%mm0 \n\t"
+ "psubd %%mm7, %%mm1 \n\t"
+ "psubd %%mm7, %%mm2 \n\t"
+ "psubd %%mm7, %%mm3 \n\t"
+ "packssdw %%mm1, %%mm0 \n\t"
+ "packssdw %%mm3, %%mm2 \n\t"
+ "movq %%mm0, 24(%0, %%edi) \n\t"
+ "movq %%mm2, 32(%0, %%edi) \n\t"
+
+ "addl $16, %%esi \n\t"
+ " jnz 1b \n\t"
+ "emms \n\t"
+ :: "r" (s16+1280), "r" (f+256)
+ :"%esi", "%edi", "memory"
+ );
+ return 5*256;
+}
+
+static int a52_resample_MONO_LFE_to_6_MMX(float * _f, int16_t * s16){
+ int32_t * f = (int32_t *) _f;
+ asm volatile(
+ "movl $-1024, %%esi \n\t"
+ "movq "MANGLE(magicF2W)", %%mm7 \n\t"
+ "pxor %%mm6, %%mm6 \n\t"
+ "1: \n\t"
+ "movq 1024(%1, %%esi), %%mm0 \n\t"
+ "movq 1032(%1, %%esi), %%mm1 \n\t"
+ "movq (%1, %%esi), %%mm2 \n\t"
+ "movq 8(%1, %%esi), %%mm3 \n\t"
+ "psubd %%mm7, %%mm0 \n\t"
+ "psubd %%mm7, %%mm1 \n\t"
+ "psubd %%mm7, %%mm2 \n\t"
+ "psubd %%mm7, %%mm3 \n\t"
+ "packssdw %%mm1, %%mm0 \n\t"
+ "packssdw %%mm3, %%mm2 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "punpcklwd %%mm2, %%mm0 \n\t"
+ "punpckhwd %%mm2, %%mm1 \n\t"
+ "leal (%%esi, %%esi, 2), %%edi \n\t"
+ "movq %%mm6, (%0, %%edi) \n\t"
+ "movd %%mm0, 8(%0, %%edi) \n\t"
+ "punpckhdq %%mm0, %%mm0 \n\t"
+ "movq %%mm6, 12(%0, %%edi) \n\t"
+ "movd %%mm0, 20(%0, %%edi) \n\t"
+ "movq %%mm6, 24(%0, %%edi) \n\t"
+ "movd %%mm1, 32(%0, %%edi) \n\t"
+ "punpckhdq %%mm1, %%mm1 \n\t"
+ "movq %%mm6, 36(%0, %%edi) \n\t"
+ "movd %%mm1, 44(%0, %%edi) \n\t"
+ "addl $16, %%esi \n\t"
+ " jnz 1b \n\t"
+ "emms \n\t"
+ :: "r" (s16+1536), "r" (f+256)
+ :"%esi", "%edi", "memory"
+ );
+ return 6*256;
+}
+
+static int a52_resample_STEREO_LFE_to_6_MMX(float * _f, int16_t * s16){
+ int32_t * f = (int32_t *) _f;
+ asm volatile(
+ "movl $-1024, %%esi \n\t"
+ "movq "MANGLE(magicF2W)", %%mm7 \n\t"
+ "pxor %%mm6, %%mm6 \n\t"
+ "1: \n\t"
+ "movq 1024(%1, %%esi), %%mm0 \n\t"
+ "movq 2048(%1, %%esi), %%mm1 \n\t"
+ "movq (%1, %%esi), %%mm5 \n\t"
+ "psubd %%mm7, %%mm0 \n\t"
+ "psubd %%mm7, %%mm1 \n\t"
+ "psubd %%mm7, %%mm5 \n\t"
+ "leal (%%esi, %%esi, 2), %%edi \n\t"
+
+ "pxor %%mm4, %%mm4 \n\t"
+ "packssdw %%mm5, %%mm0 \n\t" // FfAa
+ "packssdw %%mm4, %%mm1 \n\t" // 00Bb
+ "punpckhwd %%mm0, %%mm4 \n\t" // F0f0
+ "punpcklwd %%mm1, %%mm0 \n\t" // BAba
+ "movq %%mm0, %%mm1 \n\t" // BAba
+ "punpckldq %%mm4, %%mm3 \n\t" // f0XX
+ "punpckldq %%mm6, %%mm0 \n\t" // 00ba
+ "punpckhdq %%mm1, %%mm3 \n\t" // BAf0
+
+ "movq %%mm0, (%0, %%edi) \n\t" // 00ba
+ "punpckhdq %%mm4, %%mm0 \n\t" // F000
+ "movq %%mm3, 8(%0, %%edi) \n\t" // BAf0
+ "movq %%mm0, 16(%0, %%edi) \n\t" // F000
+ "addl $8, %%esi \n\t"
+ " jnz 1b \n\t"
+ "emms \n\t"
+ :: "r" (s16+1536), "r" (f+256)
+ :"%esi", "%edi", "memory"
+ );
+ return 6*256;
+}
+
+static int a52_resample_3F_LFE_to_6_MMX(float * _f, int16_t * s16){
+ int32_t * f = (int32_t *) _f;
+ asm volatile(
+ "movl $-1024, %%esi \n\t"
+ "movq "MANGLE(magicF2W)", %%mm7 \n\t"
+ "pxor %%mm6, %%mm6 \n\t"
+ "1: \n\t"
+ "movq 1024(%1, %%esi), %%mm0 \n\t"
+ "movq 3072(%1, %%esi), %%mm1 \n\t"
+ "movq 2048(%1, %%esi), %%mm4 \n\t"
+ "movq (%1, %%esi), %%mm5 \n\t"
+ "psubd %%mm7, %%mm0 \n\t"
+ "psubd %%mm7, %%mm1 \n\t"
+ "psubd %%mm7, %%mm4 \n\t"
+ "psubd %%mm7, %%mm5 \n\t"
+ "leal (%%esi, %%esi, 2), %%edi \n\t"
+
+ "packssdw %%mm4, %%mm0 \n\t" // EeAa
+ "packssdw %%mm5, %%mm1 \n\t" // FfBb
+ "movq %%mm0, %%mm2 \n\t" // EeAa
+ "punpcklwd %%mm1, %%mm0 \n\t" // BAba
+ "punpckhwd %%mm1, %%mm2 \n\t" // FEfe
+ "movq %%mm0, %%mm1 \n\t" // BAba
+ "punpckldq %%mm6, %%mm0 \n\t" // 00ba
+ "punpckhdq %%mm1, %%mm1 \n\t" // BABA
+
+ "movq %%mm0, (%0, %%edi) \n\t"
+ "punpckhdq %%mm2, %%mm0 \n\t" // FE00
+ "punpckldq %%mm1, %%mm2 \n\t" // BAfe
+ "movq %%mm2, 8(%0, %%edi) \n\t"
+ "movq %%mm0, 16(%0, %%edi) \n\t"
+ "addl $8, %%esi \n\t"
+ " jnz 1b \n\t"
+ "emms \n\t"
+ :: "r" (s16+1536), "r" (f+256)
+ :"%esi", "%edi", "memory"
+ );
+ return 6*256;
+}
+
+static int a52_resample_2F_2R_LFE_to_6_MMX(float * _f, int16_t * s16){
+ int32_t * f = (int32_t *) _f;
+ asm volatile(
+ "movl $-1024, %%esi \n\t"
+ "movq "MANGLE(magicF2W)", %%mm7 \n\t"
+// "pxor %%mm6, %%mm6 \n\t"
+ "1: \n\t"
+ "movq 1024(%1, %%esi), %%mm0 \n\t"
+ "movq 2048(%1, %%esi), %%mm1 \n\t"
+ "movq 3072(%1, %%esi), %%mm2 \n\t"
+ "movq 4096(%1, %%esi), %%mm3 \n\t"
+ "movq (%1, %%esi), %%mm5 \n\t"
+ "psubd %%mm7, %%mm0 \n\t"
+ "psubd %%mm7, %%mm1 \n\t"
+ "psubd %%mm7, %%mm2 \n\t"
+ "psubd %%mm7, %%mm3 \n\t"
+ "psubd %%mm7, %%mm5 \n\t"
+ "leal (%%esi, %%esi, 2), %%edi \n\t"
+
+ "packssdw %%mm2, %%mm0 \n\t" // CcAa
+ "packssdw %%mm3, %%mm1 \n\t" // DdBb
+ "packssdw %%mm5, %%mm5 \n\t" // FfFf
+ "movq %%mm0, %%mm2 \n\t" // CcAa
+ "punpcklwd %%mm1, %%mm0 \n\t" // BAba
+ "punpckhwd %%mm1, %%mm2 \n\t" // DCdc
+ "pxor %%mm4, %%mm4 \n\t" // 0000
+ "punpcklwd %%mm5, %%mm4 \n\t" // F0f0
+ "movq %%mm0, %%mm1 \n\t" // BAba
+ "movq %%mm4, %%mm3 \n\t" // F0f0
+ "punpckldq %%mm2, %%mm0 \n\t" // dcba
+ "punpckhdq %%mm1, %%mm1 \n\t" // BABA
+ "punpckldq %%mm1, %%mm4 \n\t" // BAf0
+ "punpckhdq %%mm3, %%mm2 \n\t" // F0DC
+
+ "movq %%mm0, (%0, %%edi) \n\t"
+ "movq %%mm4, 8(%0, %%edi) \n\t"
+ "movq %%mm2, 16(%0, %%edi) \n\t"
+ "addl $8, %%esi \n\t"
+ " jnz 1b \n\t"
+ "emms \n\t"
+ :: "r" (s16+1536), "r" (f+256)
+ :"%esi", "%edi", "memory"
+ );
+ return 6*256;
+}
+
+static int a52_resample_3F_2R_LFE_to_6_MMX(float * _f, int16_t * s16){
+ int32_t * f = (int32_t *) _f;
+ asm volatile(
+ "movl $-1024, %%esi \n\t"
+ "movq "MANGLE(magicF2W)", %%mm7 \n\t"
+// "pxor %%mm6, %%mm6 \n\t"
+ "1: \n\t"
+ "movq 1024(%1, %%esi), %%mm0 \n\t"
+ "movq 3072(%1, %%esi), %%mm1 \n\t"
+ "movq 4096(%1, %%esi), %%mm2 \n\t"
+ "movq 5120(%1, %%esi), %%mm3 \n\t"
+ "movq 2048(%1, %%esi), %%mm4 \n\t"
+ "movq (%1, %%esi), %%mm5 \n\t"
+ "psubd %%mm7, %%mm0 \n\t"
+ "psubd %%mm7, %%mm1 \n\t"
+ "psubd %%mm7, %%mm2 \n\t"
+ "psubd %%mm7, %%mm3 \n\t"
+ "psubd %%mm7, %%mm4 \n\t"
+ "psubd %%mm7, %%mm5 \n\t"
+ "leal (%%esi, %%esi, 2), %%edi \n\t"
+
+ "packssdw %%mm2, %%mm0 \n\t" // CcAa
+ "packssdw %%mm3, %%mm1 \n\t" // DdBb
+ "packssdw %%mm4, %%mm4 \n\t" // EeEe
+ "packssdw %%mm5, %%mm5 \n\t" // FfFf
+ "movq %%mm0, %%mm2 \n\t" // CcAa
+ "punpcklwd %%mm1, %%mm0 \n\t" // BAba
+ "punpckhwd %%mm1, %%mm2 \n\t" // DCdc
+ "punpcklwd %%mm5, %%mm4 \n\t" // FEfe
+ "movq %%mm0, %%mm1 \n\t" // BAba
+ "movq %%mm4, %%mm3 \n\t" // FEfe
+ "punpckldq %%mm2, %%mm0 \n\t" // dcba
+ "punpckhdq %%mm1, %%mm1 \n\t" // BABA
+ "punpckldq %%mm1, %%mm4 \n\t" // BAfe
+ "punpckhdq %%mm3, %%mm2 \n\t" // FEDC
+
+ "movq %%mm0, (%0, %%edi) \n\t"
+ "movq %%mm4, 8(%0, %%edi) \n\t"
+ "movq %%mm2, 16(%0, %%edi) \n\t"
+ "addl $8, %%esi \n\t"
+ " jnz 1b \n\t"
+ "emms \n\t"
+ :: "r" (s16+1536), "r" (f+256)
+ :"%esi", "%edi", "memory"
+ );
+ return 6*256;
+}
+
+
+static void* a52_resample_MMX(int flags, int ch){
+ switch (flags) {
+ case A52_MONO:
+ if(ch==5) return a52_resample_MONO_to_5_MMX;
+ break;
+ case A52_CHANNEL:
+ case A52_STEREO:
+ case A52_DOLBY:
+ if(ch==2) return a52_resample_STEREO_to_2_MMX;
+ break;
+ case A52_3F:
+ if(ch==5) return a52_resample_3F_to_5_MMX;
+ break;
+ case A52_2F2R:
+ if(ch==4) return a52_resample_2F_2R_to_4_MMX;
+ break;
+ case A52_3F2R:
+ if(ch==5) return a52_resample_3F_2R_to_5_MMX;
+ break;
+ case A52_MONO | A52_LFE:
+ if(ch==6) return a52_resample_MONO_LFE_to_6_MMX;
+ break;
+ case A52_CHANNEL | A52_LFE:
+ case A52_STEREO | A52_LFE:
+ case A52_DOLBY | A52_LFE:
+ if(ch==6) return a52_resample_STEREO_LFE_to_6_MMX;
+ break;
+ case A52_3F | A52_LFE:
+ if(ch==6) return a52_resample_3F_LFE_to_6_MMX;
+ break;
+ case A52_2F2R | A52_LFE:
+ if(ch==6) return a52_resample_2F_2R_LFE_to_6_MMX;
+ break;
+ case A52_3F2R | A52_LFE:
+ if(ch==6) return a52_resample_3F_2R_LFE_to_6_MMX;
+ break;
+ }
+ return NULL;
+}
+
+
diff --git a/contrib/ffmpeg/libavcodec/liba52/tables.h b/contrib/ffmpeg/libavcodec/liba52/tables.h
new file mode 100644
index 000000000..7f921c9d0
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/liba52/tables.h
@@ -0,0 +1,246 @@
+/*
+ * tables.h
+ * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * a52dec is distributed in the hope that 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+static const int8_t exp_1[128] = {
+ -2,-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,
+ 25,25,25
+};
+static const int8_t exp_2[128] = {
+ -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,
+ 25,25,25
+};
+static const int8_t exp_3[128] = {
+ -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,
+ 25,25,25
+};
+
+#define Q(x) ROUND (32768.0 * x)
+
+#define Q0 Q (-2/3)
+#define Q1 Q (0)
+#define Q2 Q (2/3)
+
+static const quantizer_t q_1_0[32] = {
+ Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0,
+ Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1,
+ Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2,
+ 0, 0, 0, 0, 0
+};
+
+static const quantizer_t q_1_1[32] = {
+ Q0, Q0, Q0, Q1, Q1, Q1, Q2, Q2, Q2,
+ Q0, Q0, Q0, Q1, Q1, Q1, Q2, Q2, Q2,
+ Q0, Q0, Q0, Q1, Q1, Q1, Q2, Q2, Q2,
+ 0, 0, 0, 0, 0
+};
+
+static const quantizer_t q_1_2[32] = {
+ Q0, Q1, Q2, Q0, Q1, Q2, Q0, Q1, Q2,
+ Q0, Q1, Q2, Q0, Q1, Q2, Q0, Q1, Q2,
+ Q0, Q1, Q2, Q0, Q1, Q2, Q0, Q1, Q2,
+ 0, 0, 0, 0, 0
+};
+
+#undef Q0
+#undef Q1
+#undef Q2
+
+#define Q0 Q (-4/5)
+#define Q1 Q (-2/5)
+#define Q2 Q (0)
+#define Q3 Q (2/5)
+#define Q4 Q (4/5)
+
+static const quantizer_t q_2_0[128] = {
+ Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,
+ Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,
+ Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,
+ Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,
+ Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,
+ 0,0,0
+};
+
+static const quantizer_t q_2_1[128] = {
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
+ 0,0,0
+};
+
+static const quantizer_t q_2_2[128] = {
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ 0,0,0
+};
+
+#undef Q0
+#undef Q1
+#undef Q2
+#undef Q3
+#undef Q4
+
+static const quantizer_t q_3[8] = {
+ Q (-6/7), Q (-4/7), Q (-2/7), Q (0), Q (2/7), Q (4/7), Q (6/7), 0
+};
+
+#define Q0 Q (-10/11)
+#define Q1 Q (-8/11)
+#define Q2 Q (-6/11)
+#define Q3 Q (-4/11)
+#define Q4 Q (-2/11)
+#define Q5 Q (0)
+#define Q6 Q (2/11)
+#define Q7 Q (4/11)
+#define Q8 Q (6/11)
+#define Q9 Q (8/11)
+#define QA Q (10/11)
+
+static const quantizer_t q_4_0[128] = {
+ Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0,
+ Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1,
+ Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2,
+ Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3,
+ Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4,
+ Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5,
+ Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6,
+ Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7,
+ Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8,
+ Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9,
+ QA, QA, QA, QA, QA, QA, QA, QA, QA, QA, QA,
+ 0, 0, 0, 0, 0, 0, 0
+};
+
+static const quantizer_t q_4_1[128] = {
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ 0, 0, 0, 0, 0, 0, 0
+};
+
+#undef Q0
+#undef Q1
+#undef Q2
+#undef Q3
+#undef Q4
+#undef Q5
+#undef Q6
+#undef Q7
+#undef Q8
+#undef Q9
+#undef QA
+
+static const quantizer_t q_5[16] = {
+ Q (-14/15), Q (-12/15), Q (-10/15), Q (-8/15), Q (-6/15),
+ Q (-4/15), Q (-2/15), Q (0), Q (2/15), Q (4/15),
+ Q (6/15), Q (8/15), Q (10/15), Q (12/15), Q (14/15), 0
+};
+
+#ifndef LIBA52_FIXED
+static const sample_t scale_factor[25] = {
+ 0.000030517578125,
+ 0.0000152587890625,
+ 0.00000762939453125,
+ 0.000003814697265625,
+ 0.0000019073486328125,
+ 0.00000095367431640625,
+ 0.000000476837158203125,
+ 0.0000002384185791015625,
+ 0.00000011920928955078125,
+ 0.000000059604644775390625,
+ 0.0000000298023223876953125,
+ 0.00000001490116119384765625,
+ 0.000000007450580596923828125,
+ 0.0000000037252902984619140625,
+ 0.00000000186264514923095703125,
+ 0.000000000931322574615478515625,
+ 0.0000000004656612873077392578125,
+ 0.00000000023283064365386962890625,
+ 0.000000000116415321826934814453125,
+ 0.0000000000582076609134674072265625,
+ 0.00000000002910383045673370361328125,
+ 0.000000000014551915228366851806640625,
+ 0.0000000000072759576141834259033203125,
+ 0.00000000000363797880709171295166015625,
+ 0.000000000001818989403545856475830078125
+};
+#endif
+
+static const uint16_t dither_lut[256] = {
+ 0x0000, 0xa011, 0xe033, 0x4022, 0x6077, 0xc066, 0x8044, 0x2055,
+ 0xc0ee, 0x60ff, 0x20dd, 0x80cc, 0xa099, 0x0088, 0x40aa, 0xe0bb,
+ 0x21cd, 0x81dc, 0xc1fe, 0x61ef, 0x41ba, 0xe1ab, 0xa189, 0x0198,
+ 0xe123, 0x4132, 0x0110, 0xa101, 0x8154, 0x2145, 0x6167, 0xc176,
+ 0x439a, 0xe38b, 0xa3a9, 0x03b8, 0x23ed, 0x83fc, 0xc3de, 0x63cf,
+ 0x8374, 0x2365, 0x6347, 0xc356, 0xe303, 0x4312, 0x0330, 0xa321,
+ 0x6257, 0xc246, 0x8264, 0x2275, 0x0220, 0xa231, 0xe213, 0x4202,
+ 0xa2b9, 0x02a8, 0x428a, 0xe29b, 0xc2ce, 0x62df, 0x22fd, 0x82ec,
+ 0x8734, 0x2725, 0x6707, 0xc716, 0xe743, 0x4752, 0x0770, 0xa761,
+ 0x47da, 0xe7cb, 0xa7e9, 0x07f8, 0x27ad, 0x87bc, 0xc79e, 0x678f,
+ 0xa6f9, 0x06e8, 0x46ca, 0xe6db, 0xc68e, 0x669f, 0x26bd, 0x86ac,
+ 0x6617, 0xc606, 0x8624, 0x2635, 0x0660, 0xa671, 0xe653, 0x4642,
+ 0xc4ae, 0x64bf, 0x249d, 0x848c, 0xa4d9, 0x04c8, 0x44ea, 0xe4fb,
+ 0x0440, 0xa451, 0xe473, 0x4462, 0x6437, 0xc426, 0x8404, 0x2415,
+ 0xe563, 0x4572, 0x0550, 0xa541, 0x8514, 0x2505, 0x6527, 0xc536,
+ 0x258d, 0x859c, 0xc5be, 0x65af, 0x45fa, 0xe5eb, 0xa5c9, 0x05d8,
+ 0xae79, 0x0e68, 0x4e4a, 0xee5b, 0xce0e, 0x6e1f, 0x2e3d, 0x8e2c,
+ 0x6e97, 0xce86, 0x8ea4, 0x2eb5, 0x0ee0, 0xaef1, 0xeed3, 0x4ec2,
+ 0x8fb4, 0x2fa5, 0x6f87, 0xcf96, 0xefc3, 0x4fd2, 0x0ff0, 0xafe1,
+ 0x4f5a, 0xef4b, 0xaf69, 0x0f78, 0x2f2d, 0x8f3c, 0xcf1e, 0x6f0f,
+ 0xede3, 0x4df2, 0x0dd0, 0xadc1, 0x8d94, 0x2d85, 0x6da7, 0xcdb6,
+ 0x2d0d, 0x8d1c, 0xcd3e, 0x6d2f, 0x4d7a, 0xed6b, 0xad49, 0x0d58,
+ 0xcc2e, 0x6c3f, 0x2c1d, 0x8c0c, 0xac59, 0x0c48, 0x4c6a, 0xec7b,
+ 0x0cc0, 0xacd1, 0xecf3, 0x4ce2, 0x6cb7, 0xcca6, 0x8c84, 0x2c95,
+ 0x294d, 0x895c, 0xc97e, 0x696f, 0x493a, 0xe92b, 0xa909, 0x0918,
+ 0xe9a3, 0x49b2, 0x0990, 0xa981, 0x89d4, 0x29c5, 0x69e7, 0xc9f6,
+ 0x0880, 0xa891, 0xe8b3, 0x48a2, 0x68f7, 0xc8e6, 0x88c4, 0x28d5,
+ 0xc86e, 0x687f, 0x285d, 0x884c, 0xa819, 0x0808, 0x482a, 0xe83b,
+ 0x6ad7, 0xcac6, 0x8ae4, 0x2af5, 0x0aa0, 0xaab1, 0xea93, 0x4a82,
+ 0xaa39, 0x0a28, 0x4a0a, 0xea1b, 0xca4e, 0x6a5f, 0x2a7d, 0x8a6c,
+ 0x4b1a, 0xeb0b, 0xab29, 0x0b38, 0x2b6d, 0x8b7c, 0xcb5e, 0x6b4f,
+ 0x8bf4, 0x2be5, 0x6bc7, 0xcbd6, 0xeb83, 0x4b92, 0x0bb0, 0xaba1
+};
diff --git a/contrib/ffmpeg/libavcodec/libgsm.c b/contrib/ffmpeg/libavcodec/libgsm.c
new file mode 100644
index 000000000..7cf59be7a
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/libgsm.c
@@ -0,0 +1,97 @@
+/*
+ * Interface to libgsm for gsm encoding/decoding
+ * Copyright (c) 2005 Alban Bedel <albeu@free.fr>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file libgsm.c
+ * Interface to libgsm for gsm encoding/decoding
+ */
+
+#include "avcodec.h"
+#include <gsm.h>
+
+// gsm.h miss some essential constants
+#define GSM_BLOCK_SIZE 33
+#define GSM_FRAME_SIZE 160
+
+static int libgsm_init(AVCodecContext *avctx) {
+ if (avctx->channels > 1 || avctx->sample_rate != 8000)
+ return -1;
+
+ avctx->frame_size = GSM_FRAME_SIZE;
+ avctx->block_align = GSM_BLOCK_SIZE;
+
+ avctx->priv_data = gsm_create();
+
+ avctx->coded_frame= avcodec_alloc_frame();
+ avctx->coded_frame->key_frame= 1;
+
+ return 0;
+}
+
+static int libgsm_close(AVCodecContext *avctx) {
+ gsm_destroy(avctx->priv_data);
+ avctx->priv_data = NULL;
+ return 0;
+}
+
+static int libgsm_encode_frame(AVCodecContext *avctx,
+ unsigned char *frame, int buf_size, void *data) {
+ // we need a full block
+ if(buf_size < GSM_BLOCK_SIZE) return 0;
+
+ gsm_encode(avctx->priv_data,data,frame);
+
+ return GSM_BLOCK_SIZE;
+}
+
+
+AVCodec libgsm_encoder = {
+ "gsm",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_GSM,
+ 0,
+ libgsm_init,
+ libgsm_encode_frame,
+ libgsm_close,
+};
+
+static int libgsm_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size) {
+
+ if(buf_size < GSM_BLOCK_SIZE) return 0;
+
+ if(gsm_decode(avctx->priv_data,buf,data)) return -1;
+
+ *data_size = GSM_FRAME_SIZE*2;
+ return GSM_BLOCK_SIZE;
+}
+
+AVCodec libgsm_decoder = {
+ "gsm",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_GSM,
+ 0,
+ libgsm_init,
+ NULL,
+ libgsm_close,
+ libgsm_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/loco.c b/contrib/ffmpeg/libavcodec/loco.c
new file mode 100644
index 000000000..2ec850ed0
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/loco.c
@@ -0,0 +1,287 @@
+/*
+ * 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.c
+ * LOCO codec.
+ */
+
+#include "avcodec.h"
+#include "common.h"
+#include "bitstream.h"
+#include "golomb.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;
+ AVFrame pic;
+ 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, uint8_t *buf, int buf_size, int step)
+{
+ RICEContext rc;
+ int val;
+ int i, j;
+
+ 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 *data_size,
+ uint8_t *buf, int buf_size)
+{
+ LOCOContext * const l = avctx->priv_data;
+ AVFrame * const p= (AVFrame*)&l->pic;
+ int decoded;
+
+ if(p->data[0])
+ avctx->release_buffer(avctx, p);
+
+ p->reference = 0;
+ if(avctx->get_buffer(avctx, p) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+ p->key_frame = 1;
+
+ 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);
+ buf += decoded; buf_size -= decoded;
+ decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height,
+ p->linesize[1], buf, buf_size, 1);
+ buf += decoded; buf_size -= 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);
+ buf += decoded; buf_size -= decoded;
+ decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2,
+ p->linesize[2], buf, buf_size, 1);
+ buf += decoded; buf_size -= 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);
+ buf += decoded; buf_size -= 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);
+ buf += decoded; buf_size -= 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_RGBA:
+ decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
+ p->linesize[0], buf, buf_size, 4);
+ buf += decoded; buf_size -= decoded;
+ decoded = loco_decode_plane(l, p->data[0] + 1, avctx->width, avctx->height,
+ p->linesize[0], buf, buf_size, 4);
+ buf += decoded; buf_size -= decoded;
+ decoded = loco_decode_plane(l, p->data[0] + 2, avctx->width, avctx->height,
+ p->linesize[0], buf, buf_size, 4);
+ buf += decoded; buf_size -= decoded;
+ decoded = loco_decode_plane(l, p->data[0] + 3, avctx->width, avctx->height,
+ p->linesize[0], buf, buf_size, 4);
+ break;
+ }
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = l->pic;
+
+ return buf_size;
+}
+
+static 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 -1;
+ }
+ version = LE_32(avctx->extradata);
+ switch(version) {
+ case 1:
+ l->lossy = 0;
+ break;
+ case 2:
+ l->lossy = LE_32(avctx->extradata + 8);
+ break;
+ default:
+ l->lossy = LE_32(avctx->extradata + 8);
+ av_log(avctx, AV_LOG_INFO, "This is LOCO codec version %i, please upload file for study\n", version);
+ }
+
+ l->mode = LE_32(avctx->extradata + 4);
+ switch(l->mode) {
+ case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY:
+ avctx->pix_fmt = PIX_FMT_YUV422P;
+ break;
+ case LOCO_CRGB: case LOCO_RGB:
+ avctx->pix_fmt = PIX_FMT_BGR24;
+ break;
+ case LOCO_CYV12: case LOCO_YV12:
+ avctx->pix_fmt = PIX_FMT_YUV420P;
+ break;
+ case LOCO_CRGBA: case LOCO_RGBA:
+ avctx->pix_fmt = PIX_FMT_RGBA32;
+ break;
+ default:
+ av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode);
+ return -1;
+ }
+ 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 loco_decoder = {
+ "loco",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_LOCO,
+ sizeof(LOCOContext),
+ decode_init,
+ NULL,
+ NULL,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/lzo.c b/contrib/ffmpeg/libavcodec/lzo.c
new file mode 100644
index 000000000..015c80d0d
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/lzo.c
@@ -0,0 +1,226 @@
+/*
+ * LZO 1x decompression
+ * 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 "common.h"
+//! avoid e.g. MPlayers fast_memcpy, it slows things down here
+#undef memcpy
+#include <string.h>
+#include "lzo.h"
+
+//! define if we may write up to 12 bytes beyond the output buffer
+#define OUTBUF_PADDED 1
+//! define if we may read up to 4 bytes beyond the input buffer
+#define INBUF_PADDED 1
+typedef struct LZOContext {
+ uint8_t *in, *in_end;
+ uint8_t *out_start, *out, *out_end;
+ int error;
+} LZOContext;
+
+/**
+ * \brief read one byte from input buffer, avoiding overrun
+ * \return byte read
+ */
+static inline int get_byte(LZOContext *c) {
+ if (c->in < c->in_end)
+ return *c->in++;
+ c->error |= LZO_INPUT_DEPLETED;
+ return 1;
+}
+
+/**
+ * \brief decode a length value in the coding used by lzo
+ * \param x previous byte value
+ * \param mask bits used from x
+ * \return decoded length value
+ */
+static inline int get_len(LZOContext *c, int x, int mask) {
+ int cnt = x & mask;
+ if (!cnt) {
+ while (!(x = get_byte(c))) cnt += 255;
+ cnt += mask + x;
+ }
+ return cnt;
+}
+
+/**
+ * \brief copy bytes from input to output buffer with checking
+ * \param cnt number of bytes to copy, must be > 0
+ */
+static inline void copy(LZOContext *c, int cnt) {
+ register uint8_t *src = c->in;
+ register uint8_t *dst = c->out;
+ if (src + cnt > c->in_end) {
+ cnt = c->in_end - src;
+ c->error |= LZO_INPUT_DEPLETED;
+ }
+ if (dst + cnt > c->out_end) {
+ cnt = c->out_end - dst;
+ c->error |= LZO_OUTPUT_FULL;
+ }
+#if defined(INBUF_PADDED) && defined(OUTBUF_PADDED)
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ src += 4;
+ dst += 4;
+ cnt -= 4;
+ if (cnt > 0)
+#endif
+ memcpy(dst, src, cnt);
+ c->in = src + cnt;
+ c->out = dst + cnt;
+}
+
+/**
+ * \brief copy previously decoded bytes to current position
+ * \param back how many bytes back we start
+ * \param cnt number of bytes to copy, must be > 0
+ *
+ * cnt > back is valid, this will copy the bytes we just copied,
+ * thus creating a repeating pattern with a period length of back.
+ */
+static inline void copy_backptr(LZOContext *c, int back, int cnt) {
+ register uint8_t *src = &c->out[-back];
+ register uint8_t *dst = c->out;
+ if (src < c->out_start) {
+ c->error |= LZO_INVALID_BACKPTR;
+ return;
+ }
+ if (dst + cnt > c->out_end) {
+ cnt = c->out_end - dst;
+ c->error |= LZO_OUTPUT_FULL;
+ }
+ if (back == 1) {
+ memset(dst, *src, cnt);
+ dst += cnt;
+ } else {
+#ifdef OUTBUF_PADDED
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ src += 4;
+ dst += 4;
+ cnt -= 4;
+ if (cnt > 0) {
+ 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];
+ src += 8;
+ dst += 8;
+ cnt -= 8;
+ }
+#endif
+ if (cnt > 0) {
+ int blocklen = back;
+ while (cnt > blocklen) {
+ memcpy(dst, src, blocklen);
+ dst += blocklen;
+ cnt -= blocklen;
+ blocklen <<= 1;
+ }
+ memcpy(dst, src, cnt);
+ }
+ dst += cnt;
+ }
+ c->out = dst;
+}
+
+/**
+ * \brief decode LZO 1x compressed data
+ * \param out output buffer
+ * \param outlen size of output buffer, number of bytes left are returned here
+ * \param in input buffer
+ * \param inlen size of input buffer, number of bytes left are returned here
+ * \return 0 on success, otherwise error flags, see lzo.h
+ *
+ * make sure all buffers are appropriately padded, in must provide
+ * LZO_INPUT_PADDING, out must provide LZO_OUTPUT_PADDING additional bytes
+ */
+int lzo1x_decode(void *out, int *outlen, void *in, int *inlen) {
+ enum {COPY, BACKPTR} state = COPY;
+ int x;
+ LZOContext c;
+ c.in = in;
+ c.in_end = (uint8_t *)in + *inlen;
+ c.out = c.out_start = out;
+ c.out_end = (uint8_t *)out + * outlen;
+ c.error = 0;
+ x = get_byte(&c);
+ if (x > 17) {
+ copy(&c, x - 17);
+ x = get_byte(&c);
+ if (x < 16) c.error |= LZO_ERROR;
+ }
+ while (!c.error) {
+ int cnt, back;
+ if (x >> 4) {
+ if (x >> 6) {
+ cnt = (x >> 5) - 1;
+ back = (get_byte(&c) << 3) + ((x >> 2) & 7) + 1;
+ } else if (x >> 5) {
+ cnt = get_len(&c, x, 31);
+ x = get_byte(&c);
+ back = (get_byte(&c) << 6) + (x >> 2) + 1;
+ } else {
+ cnt = get_len(&c, x, 7);
+ back = (1 << 14) + ((x & 8) << 11);
+ x = get_byte(&c);
+ back += (get_byte(&c) << 6) + (x >> 2);
+ if (back == (1 << 14)) {
+ if (cnt != 1)
+ c.error |= LZO_ERROR;
+ break;
+ }
+ }
+ } else
+ switch (state) {
+ case COPY:
+ cnt = get_len(&c, x, 15);
+ copy(&c, cnt + 3);
+ x = get_byte(&c);
+ if (x >> 4)
+ continue;
+ cnt = 1;
+ back = (1 << 11) + (get_byte(&c) << 2) + (x >> 2) + 1;
+ break;
+ case BACKPTR:
+ cnt = 0;
+ back = (get_byte(&c) << 2) + (x >> 2) + 1;
+ break;
+ }
+ copy_backptr(&c, back, cnt + 2);
+ cnt = x & 3;
+ state = cnt ? BACKPTR : COPY;
+ if (cnt)
+ copy(&c, cnt);
+ x = get_byte(&c);
+ }
+ *inlen = c.in_end - c.in;
+ *outlen = c.out_end - c.out;
+ return c.error;
+}
diff --git a/contrib/ffmpeg/libavcodec/lzo.h b/contrib/ffmpeg/libavcodec/lzo.h
new file mode 100644
index 000000000..4d00dd721
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/lzo.h
@@ -0,0 +1,35 @@
+/*
+ * LZO 1x decompression
+ * 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 _LZO_H
+#define LZO_H
+
+#define LZO_INPUT_DEPLETED 1
+#define LZO_OUTPUT_FULL 2
+#define LZO_INVALID_BACKPTR 4
+#define LZO_ERROR 8
+
+#define LZO_INPUT_PADDING 4
+#define LZO_OUTPUT_PADDING 12
+
+int lzo1x_decode(void *out, int *outlen, void *in, int *inlen);
+
+#endif
diff --git a/contrib/ffmpeg/libavcodec/lzw.c b/contrib/ffmpeg/libavcodec/lzw.c
new file mode 100644
index 000000000..b5bb33a21
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/lzw.c
@@ -0,0 +1,262 @@
+/*
+ * 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 lzw.c
+ * @brief LZW decoding routines
+ * @author Fabrice Bellard
+ * Modified for use in TIFF by Konstantin Shishkov
+ */
+
+#include "avcodec.h"
+#include "lzw.h"
+
+#define LZW_MAXBITS 12
+#define LZW_SIZTABLE (1<<LZW_MAXBITS)
+
+static const uint16_t mask[17] =
+{
+ 0x0000, 0x0001, 0x0003, 0x0007,
+ 0x000F, 0x001F, 0x003F, 0x007F,
+ 0x00FF, 0x01FF, 0x03FF, 0x07FF,
+ 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
+};
+
+struct LZWState {
+ int eob_reached;
+ uint8_t *pbuf, *ebuf;
+ int bbits;
+ unsigned int bbuf;
+
+ int mode; ///< Decoder mode
+ int cursize; ///< The current code size
+ int curmask;
+ int codesize;
+ int clear_code;
+ int end_code;
+ int newcodes; ///< First available code
+ int top_slot; ///< Highest code for current size
+ int top_slot2; ///< Highest possible code for current size (<=top_slot)
+ int slot; ///< Last read code
+ int fc, oc;
+ uint8_t *sp;
+ uint8_t stack[LZW_SIZTABLE];
+ uint8_t suffix[LZW_SIZTABLE];
+ uint16_t prefix[LZW_SIZTABLE];
+ int bs; ///< current buffer size for GIF
+};
+
+/* get one code from stream */
+static int lzw_get_code(struct LZWState * s)
+{
+ int c, sizbuf;
+
+ if(s->mode == FF_LZW_GIF) {
+ while (s->bbits < s->cursize) {
+ if (!s->bs) {
+ sizbuf = *s->pbuf++;
+ s->bs = sizbuf;
+ if(!sizbuf) {
+ s->eob_reached = 1;
+ }
+ }
+ s->bbuf |= (*s->pbuf++) << s->bbits;
+ s->bbits += 8;
+ s->bs--;
+ }
+ c = s->bbuf & s->curmask;
+ s->bbuf >>= s->cursize;
+ } else { // TIFF
+ while (s->bbits < s->cursize) {
+ if (s->pbuf >= s->ebuf) {
+ s->eob_reached = 1;
+ }
+ s->bbuf = (s->bbuf << 8) | (*s->pbuf++);
+ s->bbits += 8;
+ }
+ c = (s->bbuf >> (s->bbits - s->cursize)) & s->curmask;
+ }
+ s->bbits -= s->cursize;
+ return c;
+}
+
+uint8_t* ff_lzw_cur_ptr(LZWState *p)
+{
+ return ((struct LZWState*)p)->pbuf;
+}
+
+void ff_lzw_decode_tail(LZWState *p)
+{
+ struct LZWState *s = (struct LZWState *)p;
+ while(!s->eob_reached)
+ lzw_get_code(s);
+}
+
+void ff_lzw_decode_open(LZWState **p)
+{
+ *p = av_mallocz(sizeof(struct LZWState));
+}
+
+void ff_lzw_decode_close(LZWState **p)
+{
+ av_freep(p);
+}
+
+/**
+ * Initialize LZW decoder
+ * @param s 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, 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->eob_reached = 0;
+ 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 = 0;
+ s->sp = s->stack;
+
+ s->mode = mode;
+ switch(s->mode){
+ case FF_LZW_GIF:
+ s->top_slot2 = s->top_slot;
+ break;
+ case FF_LZW_TIFF:
+ s->top_slot2 = s->top_slot - 1;
+ break;
+ default:
+ return -1;
+ }
+ 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 s 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;
+
+ while (sp > s->stack) {
+ *buf++ = *(--sp);
+ if ((--l) == 0)
+ goto the_end;
+ }
+
+ for (;;) {
+ c = lzw_get_code(s);
+ if (c == s->end_code) {
+ s->end_code = -1;
+ 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;
+ s->top_slot2 = s->top_slot;
+ if(s->mode == FF_LZW_TIFF)
+ s->top_slot2--;
+ while ((c = lzw_get_code(s)) == s->clear_code);
+ if (c == s->end_code) {
+ s->end_code = -1;
+ break;
+ }
+ /* test error */
+ if (c >= s->slot)
+ c = 0;
+ fc = oc = c;
+ *buf++ = c;
+ if ((--l) == 0)
+ break;
+ } else {
+ code = c;
+ if (code >= s->slot) {
+ *sp++ = fc;
+ code = oc;
+ }
+ while (code >= s->newcodes) {
+ *sp++ = s->suffix[code];
+ code = s->prefix[code];
+ }
+ *sp++ = code;
+ if (s->slot < s->top_slot) {
+ s->suffix[s->slot] = fc = code;
+ s->prefix[s->slot++] = oc;
+ oc = c;
+ }
+ if (s->slot >= s->top_slot2) {
+ if (s->cursize < LZW_MAXBITS) {
+ s->top_slot <<= 1;
+ s->top_slot2 = s->top_slot;
+ if(s->mode == FF_LZW_TIFF)
+ s->top_slot2--;
+ s->curmask = mask[++s->cursize];
+ }
+ }
+ while (sp > s->stack) {
+ *buf++ = *(--sp);
+ if ((--l) == 0)
+ goto the_end;
+ }
+ }
+ }
+ the_end:
+ s->sp = sp;
+ s->oc = oc;
+ s->fc = fc;
+ return len - l;
+}
diff --git a/contrib/ffmpeg/libavcodec/lzw.h b/contrib/ffmpeg/libavcodec/lzw.h
new file mode 100644
index 000000000..60f115caf
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/lzw.h
@@ -0,0 +1,49 @@
+/*
+ * 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 lzw.h
+ * @brief LZW decoding routines
+ * @author Fabrice Bellard
+ * Modified for use in TIFF by Konstantin Shishkov
+ */
+
+#ifndef LZW_H
+#define LZW_H
+
+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, uint8_t *buf, int buf_size, int mode);
+int ff_lzw_decode(LZWState *s, uint8_t *buf, int len);
+uint8_t* ff_lzw_cur_ptr(LZWState *lzw);
+void ff_lzw_decode_tail(LZWState *lzw);
+
+#endif
diff --git a/contrib/ffmpeg/libavcodec/mace.c b/contrib/ffmpeg/libavcodec/mace.c
new file mode 100644
index 000000000..95839379a
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mace.c
@@ -0,0 +1,456 @@
+/*
+ * MACE decoder
+ * Copyright (c) 2002 Laszlo Torok <torokl@alpha.dfmk.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 mace.c
+ * MACE decoder.
+ */
+
+#include "avcodec.h"
+
+/*
+ * Adapted to ffmpeg by Francois Revol <revol@free.fr>
+ * (removed 68k REG stuff, changed types, added some statics and consts,
+ * libavcodec api, context stuff, interlaced stereo out).
+ */
+
+static const uint16_t MACEtab1[] = { 0xfff3, 0x0008, 0x004c, 0x00de, 0x00de, 0x004c, 0x0008, 0xfff3 };
+
+static const uint16_t MACEtab3[] = { 0xffee, 0x008c, 0x008c, 0xffee };
+
+static const uint16_t MACEtab2[][8] = {
+ { 0x0025, 0x0074, 0x00CE, 0x014A, 0xFEB5, 0xFF31, 0xFF8B, 0xFFDA },
+ { 0x0027, 0x0079, 0x00D8, 0x015A, 0xFEA5, 0xFF27, 0xFF86, 0xFFD8 },
+ { 0x0029, 0x007F, 0x00E1, 0x0169, 0xFE96, 0xFF1E, 0xFF80, 0xFFD6 },
+ { 0x002A, 0x0084, 0x00EB, 0x0179, 0xFE86, 0xFF14, 0xFF7B, 0xFFD5 },
+ { 0x002C, 0x0089, 0x00F5, 0x0188, 0xFE77, 0xFF0A, 0xFF76, 0xFFD3 },
+ { 0x002E, 0x0090, 0x0100, 0x019A, 0xFE65, 0xFEFF, 0xFF6F, 0xFFD1 },
+ { 0x0030, 0x0096, 0x010B, 0x01AC, 0xFE53, 0xFEF4, 0xFF69, 0xFFCF },
+ { 0x0033, 0x009D, 0x0118, 0x01C1, 0xFE3E, 0xFEE7, 0xFF62, 0xFFCC },
+ { 0x0035, 0x00A5, 0x0125, 0x01D6, 0xFE29, 0xFEDA, 0xFF5A, 0xFFCA },
+ { 0x0037, 0x00AC, 0x0132, 0x01EA, 0xFE15, 0xFECD, 0xFF53, 0xFFC8 },
+ { 0x003A, 0x00B3, 0x013F, 0x01FF, 0xFE00, 0xFEC0, 0xFF4C, 0xFFC5 },
+ { 0x003C, 0x00BB, 0x014D, 0x0216, 0xFDE9, 0xFEB2, 0xFF44, 0xFFC3 },
+ { 0x003F, 0x00C3, 0x015C, 0x022D, 0xFDD2, 0xFEA3, 0xFF3C, 0xFFC0 },
+ { 0x0042, 0x00CD, 0x016C, 0x0247, 0xFDB8, 0xFE93, 0xFF32, 0xFFBD },
+ { 0x0045, 0x00D6, 0x017C, 0x0261, 0xFD9E, 0xFE83, 0xFF29, 0xFFBA },
+ { 0x0048, 0x00DF, 0x018C, 0x027B, 0xFD84, 0xFE73, 0xFF20, 0xFFB7 },
+ { 0x004B, 0x00E9, 0x019E, 0x0297, 0xFD68, 0xFE61, 0xFF16, 0xFFB4 },
+ { 0x004F, 0x00F4, 0x01B1, 0x02B6, 0xFD49, 0xFE4E, 0xFF0B, 0xFFB0 },
+ { 0x0052, 0x00FE, 0x01C5, 0x02D5, 0xFD2A, 0xFE3A, 0xFF01, 0xFFAD },
+ { 0x0056, 0x0109, 0x01D8, 0x02F4, 0xFD0B, 0xFE27, 0xFEF6, 0xFFA9 },
+ { 0x005A, 0x0116, 0x01EF, 0x0318, 0xFCE7, 0xFE10, 0xFEE9, 0xFFA5 },
+ { 0x005E, 0x0122, 0x0204, 0x033A, 0xFCC5, 0xFDFB, 0xFEDD, 0xFFA1 },
+ { 0x0062, 0x012F, 0x021A, 0x035E, 0xFCA1, 0xFDE5, 0xFED0, 0xFF9D },
+ { 0x0066, 0x013C, 0x0232, 0x0385, 0xFC7A, 0xFDCD, 0xFEC3, 0xFF99 },
+ { 0x006B, 0x014B, 0x024C, 0x03AE, 0xFC51, 0xFDB3, 0xFEB4, 0xFF94 },
+ { 0x0070, 0x0159, 0x0266, 0x03D7, 0xFC28, 0xFD99, 0xFEA6, 0xFF8F },
+ { 0x0075, 0x0169, 0x0281, 0x0403, 0xFBFC, 0xFD7E, 0xFE96, 0xFF8A },
+ { 0x007A, 0x0179, 0x029E, 0x0432, 0xFBCD, 0xFD61, 0xFE86, 0xFF85 },
+ { 0x007F, 0x018A, 0x02BD, 0x0463, 0xFB9C, 0xFD42, 0xFE75, 0xFF80 },
+ { 0x0085, 0x019B, 0x02DC, 0x0494, 0xFB6B, 0xFD23, 0xFE64, 0xFF7A },
+ { 0x008B, 0x01AE, 0x02FC, 0x04C8, 0xFB37, 0xFD03, 0xFE51, 0xFF74 },
+ { 0x0091, 0x01C1, 0x031F, 0x0500, 0xFAFF, 0xFCE0, 0xFE3E, 0xFF6E },
+ { 0x0098, 0x01D5, 0x0343, 0x0539, 0xFAC6, 0xFCBC, 0xFE2A, 0xFF67 },
+ { 0x009F, 0x01EA, 0x0368, 0x0575, 0xFA8A, 0xFC97, 0xFE15, 0xFF60 },
+ { 0x00A6, 0x0200, 0x038F, 0x05B3, 0xFA4C, 0xFC70, 0xFDFF, 0xFF59 },
+ { 0x00AD, 0x0217, 0x03B7, 0x05F3, 0xFA0C, 0xFC48, 0xFDE8, 0xFF52 },
+ { 0x00B5, 0x022E, 0x03E1, 0x0636, 0xF9C9, 0xFC1E, 0xFDD1, 0xFF4A },
+ { 0x00BD, 0x0248, 0x040E, 0x067F, 0xF980, 0xFBF1, 0xFDB7, 0xFF42 },
+ { 0x00C5, 0x0262, 0x043D, 0x06CA, 0xF935, 0xFBC2, 0xFD9D, 0xFF3A },
+ { 0x00CE, 0x027D, 0x046D, 0x0717, 0xF8E8, 0xFB92, 0xFD82, 0xFF31 },
+ { 0x00D7, 0x0299, 0x049F, 0x0767, 0xF898, 0xFB60, 0xFD66, 0xFF28 },
+ { 0x00E1, 0x02B7, 0x04D5, 0x07BC, 0xF843, 0xFB2A, 0xFD48, 0xFF1E },
+ { 0x00EB, 0x02D6, 0x050B, 0x0814, 0xF7EB, 0xFAF4, 0xFD29, 0xFF14 },
+ { 0x00F6, 0x02F7, 0x0545, 0x0871, 0xF78E, 0xFABA, 0xFD08, 0xFF09 },
+ { 0x0101, 0x0318, 0x0581, 0x08D1, 0xF72E, 0xFA7E, 0xFCE7, 0xFEFE },
+ { 0x010C, 0x033C, 0x05C0, 0x0935, 0xF6CA, 0xFA3F, 0xFCC3, 0xFEF3 },
+ { 0x0118, 0x0361, 0x0602, 0x099F, 0xF660, 0xF9FD, 0xFC9E, 0xFEE7 },
+ { 0x0125, 0x0387, 0x0646, 0x0A0C, 0xF5F3, 0xF9B9, 0xFC78, 0xFEDA },
+ { 0x0132, 0x03B0, 0x068E, 0x0A80, 0xF57F, 0xF971, 0xFC4F, 0xFECD },
+ { 0x013F, 0x03DA, 0x06D9, 0x0AF7, 0xF508, 0xF926, 0xFC25, 0xFEC0 },
+ { 0x014E, 0x0406, 0x0728, 0x0B75, 0xF48A, 0xF8D7, 0xFBF9, 0xFEB1 },
+ { 0x015D, 0x0434, 0x077A, 0x0BF9, 0xF406, 0xF885, 0xFBCB, 0xFEA2 },
+ { 0x016C, 0x0464, 0x07CF, 0x0C82, 0xF37D, 0xF830, 0xFB9B, 0xFE93 },
+ { 0x017C, 0x0496, 0x0828, 0x0D10, 0xF2EF, 0xF7D7, 0xFB69, 0xFE83 },
+ { 0x018E, 0x04CB, 0x0886, 0x0DA6, 0xF259, 0xF779, 0xFB34, 0xFE71 },
+ { 0x019F, 0x0501, 0x08E6, 0x0E41, 0xF1BE, 0xF719, 0xFAFE, 0xFE60 },
+ { 0x01B2, 0x053B, 0x094C, 0x0EE3, 0xF11C, 0xF6B3, 0xFAC4, 0xFE4D },
+ { 0x01C5, 0x0576, 0x09B6, 0x0F8E, 0xF071, 0xF649, 0xFA89, 0xFE3A },
+ { 0x01D9, 0x05B5, 0x0A26, 0x1040, 0xEFBF, 0xF5D9, 0xFA4A, 0xFE26 },
+ { 0x01EF, 0x05F6, 0x0A9A, 0x10FA, 0xEF05, 0xF565, 0xFA09, 0xFE10 },
+ { 0x0205, 0x063A, 0x0B13, 0x11BC, 0xEE43, 0xF4EC, 0xF9C5, 0xFDFA },
+ { 0x021C, 0x0681, 0x0B91, 0x1285, 0xED7A, 0xF46E, 0xF97E, 0xFDE3 },
+ { 0x0234, 0x06CC, 0x0C15, 0x1359, 0xECA6, 0xF3EA, 0xF933, 0xFDCB },
+ { 0x024D, 0x071A, 0x0CA0, 0x1437, 0xEBC8, 0xF35F, 0xF8E5, 0xFDB2 },
+ { 0x0267, 0x076A, 0x0D2F, 0x151D, 0xEAE2, 0xF2D0, 0xF895, 0xFD98 },
+ { 0x0283, 0x07C0, 0x0DC7, 0x160F, 0xE9F0, 0xF238, 0xF83F, 0xFD7C },
+ { 0x029F, 0x0818, 0x0E63, 0x170A, 0xE8F5, 0xF19C, 0xF7E7, 0xFD60 },
+ { 0x02BD, 0x0874, 0x0F08, 0x1811, 0xE7EE, 0xF0F7, 0xF78B, 0xFD42 },
+ { 0x02DD, 0x08D5, 0x0FB4, 0x1926, 0xE6D9, 0xF04B, 0xF72A, 0xFD22 },
+ { 0x02FE, 0x093A, 0x1067, 0x1A44, 0xE5BB, 0xEF98, 0xF6C5, 0xFD01 },
+ { 0x0320, 0x09A3, 0x1122, 0x1B70, 0xE48F, 0xEEDD, 0xF65C, 0xFCDF },
+ { 0x0344, 0x0A12, 0x11E7, 0x1CAB, 0xE354, 0xEE18, 0xF5ED, 0xFCBB },
+ { 0x0369, 0x0A84, 0x12B2, 0x1DF0, 0xE20F, 0xED4D, 0xF57B, 0xFC96 },
+ { 0x0390, 0x0AFD, 0x1389, 0x1F48, 0xE0B7, 0xEC76, 0xF502, 0xFC6F },
+ { 0x03B8, 0x0B7A, 0x1467, 0x20AC, 0xDF53, 0xEB98, 0xF485, 0xFC47 },
+ { 0x03E3, 0x0BFE, 0x1551, 0x2223, 0xDDDC, 0xEAAE, 0xF401, 0xFC1C },
+ { 0x040F, 0x0C87, 0x1645, 0x23A9, 0xDC56, 0xE9BA, 0xF378, 0xFBF0 },
+ { 0x043E, 0x0D16, 0x1744, 0x2541, 0xDABE, 0xE8BB, 0xF2E9, 0xFBC1 },
+ { 0x046E, 0x0DAB, 0x184C, 0x26E8, 0xD917, 0xE7B3, 0xF254, 0xFB91 },
+ { 0x04A1, 0x0E47, 0x1961, 0x28A4, 0xD75B, 0xE69E, 0xF1B8, 0xFB5E },
+ { 0x04D6, 0x0EEA, 0x1A84, 0x2A75, 0xD58A, 0xE57B, 0xF115, 0xFB29 },
+ { 0x050D, 0x0F95, 0x1BB3, 0x2C5B, 0xD3A4, 0xE44C, 0xF06A, 0xFAF2 },
+ { 0x0547, 0x1046, 0x1CEF, 0x2E55, 0xD1AA, 0xE310, 0xEFB9, 0xFAB8 },
+ { 0x0583, 0x1100, 0x1E3A, 0x3066, 0xCF99, 0xE1C5, 0xEEFF, 0xFA7C },
+ { 0x05C2, 0x11C3, 0x1F94, 0x3292, 0xCD6D, 0xE06B, 0xEE3C, 0xFA3D },
+ { 0x0604, 0x128E, 0x20FC, 0x34D2, 0xCB2D, 0xDF03, 0xED71, 0xF9FB },
+ { 0x0649, 0x1362, 0x2275, 0x372E, 0xC8D1, 0xDD8A, 0xEC9D, 0xF9B6 },
+ { 0x0690, 0x143F, 0x23FF, 0x39A4, 0xC65B, 0xDC00, 0xEBC0, 0xF96F },
+ { 0x06DC, 0x1527, 0x259A, 0x3C37, 0xC3C8, 0xDA65, 0xEAD8, 0xF923 },
+ { 0x072A, 0x1619, 0x2749, 0x3EE8, 0xC117, 0xD8B6, 0xE9E6, 0xF8D5 },
+ { 0x077C, 0x1715, 0x2909, 0x41B6, 0xBE49, 0xD6F6, 0xE8EA, 0xF883 },
+ { 0x07D1, 0x181D, 0x2ADF, 0x44A6, 0xBB59, 0xD520, 0xE7E2, 0xF82E },
+ { 0x082B, 0x1930, 0x2CC7, 0x47B4, 0xB84B, 0xD338, 0xE6CF, 0xF7D4 },
+ { 0x0888, 0x1A50, 0x2EC6, 0x4AE7, 0xB518, 0xD139, 0xE5AF, 0xF777 },
+ { 0x08EA, 0x1B7D, 0x30DE, 0x4E40, 0xB1BF, 0xCF21, 0xE482, 0xF715 },
+ { 0x094F, 0x1CB7, 0x330C, 0x51BE, 0xAE41, 0xCCF3, 0xE348, 0xF6B0 },
+ { 0x09BA, 0x1DFF, 0x3554, 0x5565, 0xAA9A, 0xCAAB, 0xE200, 0xF645 },
+ { 0x0A29, 0x1F55, 0x37B4, 0x5932, 0xA6CD, 0xC84B, 0xE0AA, 0xF5D6 },
+ { 0x0A9D, 0x20BC, 0x3A31, 0x5D2E, 0xA2D1, 0xC5CE, 0xDF43, 0xF562 },
+ { 0x0B16, 0x2231, 0x3CC9, 0x6156, 0x9EA9, 0xC336, 0xDDCE, 0xF4E9 },
+ { 0x0B95, 0x23B8, 0x3F80, 0x65AF, 0x9A50, 0xC07F, 0xDC47, 0xF46A },
+ { 0x0C19, 0x2551, 0x4256, 0x6A39, 0x95C6, 0xBDA9, 0xDAAE, 0xF3E6 },
+ { 0x0CA4, 0x26FB, 0x454C, 0x6EF7, 0x9108, 0xBAB3, 0xD904, 0xF35B },
+ { 0x0D34, 0x28B8, 0x4864, 0x73EB, 0x8C14, 0xB79B, 0xD747, 0xF2CB },
+ { 0x0DCB, 0x2A8A, 0x4B9F, 0x7918, 0x86E7, 0xB460, 0xD575, 0xF234 },
+ { 0x0E68, 0x2C6F, 0x4EFE, 0x7E7E, 0x8181, 0xB101, 0xD390, 0xF197 },
+ { 0x0F0D, 0x2E6B, 0x5285, 0x7FFF, 0x8000, 0xAD7A, 0xD194, 0xF0F2 },
+ { 0x0FB9, 0x307E, 0x5635, 0x7FFF, 0x8000, 0xA9CA, 0xCF81, 0xF046 },
+ { 0x106D, 0x32A7, 0x5A0D, 0x7FFF, 0x8000, 0xA5F2, 0xCD58, 0xEF92 },
+ { 0x1128, 0x34EA, 0x5E12, 0x7FFF, 0x8000, 0xA1ED, 0xCB15, 0xEED7 },
+ { 0x11ED, 0x3747, 0x6245, 0x7FFF, 0x8000, 0x9DBA, 0xC8B8, 0xEE12 },
+ { 0x12B9, 0x39BF, 0x66A8, 0x7FFF, 0x8000, 0x9957, 0xC640, 0xED46 },
+ { 0x138F, 0x3C52, 0x6B3C, 0x7FFF, 0x8000, 0x94C3, 0xC3AD, 0xEC70 },
+ { 0x146F, 0x3F04, 0x7006, 0x7FFF, 0x8000, 0x8FF9, 0xC0FB, 0xEB90 },
+ { 0x1558, 0x41D3, 0x7505, 0x7FFF, 0x8000, 0x8AFA, 0xBE2C, 0xEAA7 },
+ { 0x164C, 0x44C3, 0x7A3E, 0x7FFF, 0x8000, 0x85C1, 0xBB3C, 0xE9B3 },
+ { 0x174B, 0x47D5, 0x7FB3, 0x7FFF, 0x8000, 0x804C, 0xB82A, 0xE8B4 },
+ { 0x1855, 0x4B0A, 0x7FFF, 0x7FFF, 0x8000, 0x8000, 0xB4F5, 0xE7AA },
+ { 0x196B, 0x4E63, 0x7FFF, 0x7FFF, 0x8000, 0x8000, 0xB19C, 0xE694 },
+ { 0x1A8D, 0x51E3, 0x7FFF, 0x7FFF, 0x8000, 0x8000, 0xAE1C, 0xE572 },
+ { 0x1BBD, 0x558B, 0x7FFF, 0x7FFF, 0x8000, 0x8000, 0xAA74, 0xE442 },
+ { 0x1CFA, 0x595C, 0x7FFF, 0x7FFF, 0x8000, 0x8000, 0xA6A3, 0xE305 },
+ { 0x1E45, 0x5D59, 0x7FFF, 0x7FFF, 0x8000, 0x8000, 0xA2A6, 0xE1BA },
+ { 0x1F9F, 0x6184, 0x7FFF, 0x7FFF, 0x8000, 0x8000, 0x9E7B, 0xE060 },
+ { 0x2108, 0x65DE, 0x7FFF, 0x7FFF, 0x8000, 0x8000, 0x9A21, 0xDEF7 },
+ { 0x2281, 0x6A6A, 0x7FFF, 0x7FFF, 0x8000, 0x8000, 0x9595, 0xDD7E },
+ { 0x240C, 0x6F29, 0x7FFF, 0x7FFF, 0x8000, 0x8000, 0x90D6, 0xDBF3 },
+ { 0x25A7, 0x741F, 0x7FFF, 0x7FFF, 0x8000, 0x8000, 0x8BE0, 0xDA58 },
+};
+
+static const uint16_t MACEtab4[][8] = {
+ { 0x0040, 0x00D8, 0xFF27, 0xFFBF, 0, 0, 0, 0 }, { 0x0043, 0x00E2, 0xFF1D, 0xFFBC, 0, 0, 0, 0 },
+ { 0x0046, 0x00EC, 0xFF13, 0xFFB9, 0, 0, 0, 0 }, { 0x004A, 0x00F6, 0xFF09, 0xFFB5, 0, 0, 0, 0 },
+ { 0x004D, 0x0101, 0xFEFE, 0xFFB2, 0, 0, 0, 0 }, { 0x0050, 0x010C, 0xFEF3, 0xFFAF, 0, 0, 0, 0 },
+ { 0x0054, 0x0118, 0xFEE7, 0xFFAB, 0, 0, 0, 0 }, { 0x0058, 0x0126, 0xFED9, 0xFFA7, 0, 0, 0, 0 },
+ { 0x005C, 0x0133, 0xFECC, 0xFFA3, 0, 0, 0, 0 }, { 0x0060, 0x0141, 0xFEBE, 0xFF9F, 0, 0, 0, 0 },
+ { 0x0064, 0x014E, 0xFEB1, 0xFF9B, 0, 0, 0, 0 }, { 0x0068, 0x015E, 0xFEA1, 0xFF97, 0, 0, 0, 0 },
+ { 0x006D, 0x016D, 0xFE92, 0xFF92, 0, 0, 0, 0 }, { 0x0072, 0x017E, 0xFE81, 0xFF8D, 0, 0, 0, 0 },
+ { 0x0077, 0x018F, 0xFE70, 0xFF88, 0, 0, 0, 0 }, { 0x007C, 0x01A0, 0xFE5F, 0xFF83, 0, 0, 0, 0 },
+ { 0x0082, 0x01B2, 0xFE4D, 0xFF7D, 0, 0, 0, 0 }, { 0x0088, 0x01C6, 0xFE39, 0xFF77, 0, 0, 0, 0 },
+ { 0x008E, 0x01DB, 0xFE24, 0xFF71, 0, 0, 0, 0 }, { 0x0094, 0x01EF, 0xFE10, 0xFF6B, 0, 0, 0, 0 },
+ { 0x009B, 0x0207, 0xFDF8, 0xFF64, 0, 0, 0, 0 }, { 0x00A2, 0x021D, 0xFDE2, 0xFF5D, 0, 0, 0, 0 },
+ { 0x00A9, 0x0234, 0xFDCB, 0xFF56, 0, 0, 0, 0 }, { 0x00B0, 0x024E, 0xFDB1, 0xFF4F, 0, 0, 0, 0 },
+ { 0x00B9, 0x0269, 0xFD96, 0xFF46, 0, 0, 0, 0 }, { 0x00C1, 0x0284, 0xFD7B, 0xFF3E, 0, 0, 0, 0 },
+ { 0x00C9, 0x02A1, 0xFD5E, 0xFF36, 0, 0, 0, 0 }, { 0x00D2, 0x02BF, 0xFD40, 0xFF2D, 0, 0, 0, 0 },
+ { 0x00DC, 0x02DF, 0xFD20, 0xFF23, 0, 0, 0, 0 }, { 0x00E6, 0x02FF, 0xFD00, 0xFF19, 0, 0, 0, 0 },
+ { 0x00F0, 0x0321, 0xFCDE, 0xFF0F, 0, 0, 0, 0 }, { 0x00FB, 0x0346, 0xFCB9, 0xFF04, 0, 0, 0, 0 },
+ { 0x0106, 0x036C, 0xFC93, 0xFEF9, 0, 0, 0, 0 }, { 0x0112, 0x0392, 0xFC6D, 0xFEED, 0, 0, 0, 0 },
+ { 0x011E, 0x03BB, 0xFC44, 0xFEE1, 0, 0, 0, 0 }, { 0x012B, 0x03E5, 0xFC1A, 0xFED4, 0, 0, 0, 0 },
+ { 0x0138, 0x0411, 0xFBEE, 0xFEC7, 0, 0, 0, 0 }, { 0x0146, 0x0441, 0xFBBE, 0xFEB9, 0, 0, 0, 0 },
+ { 0x0155, 0x0472, 0xFB8D, 0xFEAA, 0, 0, 0, 0 }, { 0x0164, 0x04A4, 0xFB5B, 0xFE9B, 0, 0, 0, 0 },
+ { 0x0174, 0x04D9, 0xFB26, 0xFE8B, 0, 0, 0, 0 }, { 0x0184, 0x0511, 0xFAEE, 0xFE7B, 0, 0, 0, 0 },
+ { 0x0196, 0x054A, 0xFAB5, 0xFE69, 0, 0, 0, 0 }, { 0x01A8, 0x0587, 0xFA78, 0xFE57, 0, 0, 0, 0 },
+ { 0x01BB, 0x05C6, 0xFA39, 0xFE44, 0, 0, 0, 0 }, { 0x01CE, 0x0608, 0xF9F7, 0xFE31, 0, 0, 0, 0 },
+ { 0x01E3, 0x064D, 0xF9B2, 0xFE1C, 0, 0, 0, 0 }, { 0x01F9, 0x0694, 0xF96B, 0xFE06, 0, 0, 0, 0 },
+ { 0x020F, 0x06E0, 0xF91F, 0xFDF0, 0, 0, 0, 0 }, { 0x0227, 0x072E, 0xF8D1, 0xFDD8, 0, 0, 0, 0 },
+ { 0x0240, 0x0781, 0xF87E, 0xFDBF, 0, 0, 0, 0 }, { 0x0259, 0x07D7, 0xF828, 0xFDA6, 0, 0, 0, 0 },
+ { 0x0274, 0x0831, 0xF7CE, 0xFD8B, 0, 0, 0, 0 }, { 0x0290, 0x088E, 0xF771, 0xFD6F, 0, 0, 0, 0 },
+ { 0x02AE, 0x08F0, 0xF70F, 0xFD51, 0, 0, 0, 0 }, { 0x02CC, 0x0955, 0xF6AA, 0xFD33, 0, 0, 0, 0 },
+ { 0x02EC, 0x09C0, 0xF63F, 0xFD13, 0, 0, 0, 0 }, { 0x030D, 0x0A2F, 0xF5D0, 0xFCF2, 0, 0, 0, 0 },
+ { 0x0330, 0x0AA4, 0xF55B, 0xFCCF, 0, 0, 0, 0 }, { 0x0355, 0x0B1E, 0xF4E1, 0xFCAA, 0, 0, 0, 0 },
+ { 0x037B, 0x0B9D, 0xF462, 0xFC84, 0, 0, 0, 0 }, { 0x03A2, 0x0C20, 0xF3DF, 0xFC5D, 0, 0, 0, 0 },
+ { 0x03CC, 0x0CAB, 0xF354, 0xFC33, 0, 0, 0, 0 }, { 0x03F8, 0x0D3D, 0xF2C2, 0xFC07, 0, 0, 0, 0 },
+ { 0x0425, 0x0DD3, 0xF22C, 0xFBDA, 0, 0, 0, 0 }, { 0x0454, 0x0E72, 0xF18D, 0xFBAB, 0, 0, 0, 0 },
+ { 0x0486, 0x0F16, 0xF0E9, 0xFB79, 0, 0, 0, 0 }, { 0x04B9, 0x0FC3, 0xF03C, 0xFB46, 0, 0, 0, 0 },
+ { 0x04F0, 0x1078, 0xEF87, 0xFB0F, 0, 0, 0, 0 }, { 0x0528, 0x1133, 0xEECC, 0xFAD7, 0, 0, 0, 0 },
+ { 0x0563, 0x11F7, 0xEE08, 0xFA9C, 0, 0, 0, 0 }, { 0x05A1, 0x12C6, 0xED39, 0xFA5E, 0, 0, 0, 0 },
+ { 0x05E1, 0x139B, 0xEC64, 0xFA1E, 0, 0, 0, 0 }, { 0x0624, 0x147C, 0xEB83, 0xF9DB, 0, 0, 0, 0 },
+ { 0x066A, 0x1565, 0xEA9A, 0xF995, 0, 0, 0, 0 }, { 0x06B3, 0x165A, 0xE9A5, 0xF94C, 0, 0, 0, 0 },
+ { 0x0700, 0x175A, 0xE8A5, 0xF8FF, 0, 0, 0, 0 }, { 0x0750, 0x1865, 0xE79A, 0xF8AF, 0, 0, 0, 0 },
+ { 0x07A3, 0x197A, 0xE685, 0xF85C, 0, 0, 0, 0 }, { 0x07FB, 0x1A9D, 0xE562, 0xF804, 0, 0, 0, 0 },
+ { 0x0856, 0x1BCE, 0xE431, 0xF7A9, 0, 0, 0, 0 }, { 0x08B5, 0x1D0C, 0xE2F3, 0xF74A, 0, 0, 0, 0 },
+ { 0x0919, 0x1E57, 0xE1A8, 0xF6E6, 0, 0, 0, 0 }, { 0x0980, 0x1FB2, 0xE04D, 0xF67F, 0, 0, 0, 0 },
+ { 0x09ED, 0x211D, 0xDEE2, 0xF612, 0, 0, 0, 0 }, { 0x0A5F, 0x2296, 0xDD69, 0xF5A0, 0, 0, 0, 0 },
+ { 0x0AD5, 0x2422, 0xDBDD, 0xF52A, 0, 0, 0, 0 }, { 0x0B51, 0x25BF, 0xDA40, 0xF4AE, 0, 0, 0, 0 },
+ { 0x0BD2, 0x276E, 0xD891, 0xF42D, 0, 0, 0, 0 }, { 0x0C5A, 0x2932, 0xD6CD, 0xF3A5, 0, 0, 0, 0 },
+ { 0x0CE7, 0x2B08, 0xD4F7, 0xF318, 0, 0, 0, 0 }, { 0x0D7A, 0x2CF4, 0xD30B, 0xF285, 0, 0, 0, 0 },
+ { 0x0E14, 0x2EF4, 0xD10B, 0xF1EB, 0, 0, 0, 0 }, { 0x0EB5, 0x310C, 0xCEF3, 0xF14A, 0, 0, 0, 0 },
+ { 0x0F5D, 0x333E, 0xCCC1, 0xF0A2, 0, 0, 0, 0 }, { 0x100C, 0x3587, 0xCA78, 0xEFF3, 0, 0, 0, 0 },
+ { 0x10C4, 0x37EB, 0xC814, 0xEF3B, 0, 0, 0, 0 }, { 0x1183, 0x3A69, 0xC596, 0xEE7C, 0, 0, 0, 0 },
+ { 0x124B, 0x3D05, 0xC2FA, 0xEDB4, 0, 0, 0, 0 }, { 0x131C, 0x3FBE, 0xC041, 0xECE3, 0, 0, 0, 0 },
+ { 0x13F7, 0x4296, 0xBD69, 0xEC08, 0, 0, 0, 0 }, { 0x14DB, 0x458F, 0xBA70, 0xEB24, 0, 0, 0, 0 },
+ { 0x15C9, 0x48AA, 0xB755, 0xEA36, 0, 0, 0, 0 }, { 0x16C2, 0x4BE9, 0xB416, 0xE93D, 0, 0, 0, 0 },
+ { 0x17C6, 0x4F4C, 0xB0B3, 0xE839, 0, 0, 0, 0 }, { 0x18D6, 0x52D5, 0xAD2A, 0xE729, 0, 0, 0, 0 },
+ { 0x19F2, 0x5688, 0xA977, 0xE60D, 0, 0, 0, 0 }, { 0x1B1A, 0x5A65, 0xA59A, 0xE4E5, 0, 0, 0, 0 },
+ { 0x1C50, 0x5E6D, 0xA192, 0xE3AF, 0, 0, 0, 0 }, { 0x1D93, 0x62A4, 0x9D5B, 0xE26C, 0, 0, 0, 0 },
+ { 0x1EE5, 0x670C, 0x98F3, 0xE11A, 0, 0, 0, 0 }, { 0x2046, 0x6BA5, 0x945A, 0xDFB9, 0, 0, 0, 0 },
+ { 0x21B7, 0x7072, 0x8F8D, 0xDE48, 0, 0, 0, 0 }, { 0x2338, 0x7578, 0x8A87, 0xDCC7, 0, 0, 0, 0 },
+ { 0x24CB, 0x7AB5, 0x854A, 0xDB34, 0, 0, 0, 0 }, { 0x266F, 0x7FFF, 0x8000, 0xD990, 0, 0, 0, 0 },
+ { 0x2826, 0x7FFF, 0x8000, 0xD7D9, 0, 0, 0, 0 }, { 0x29F1, 0x7FFF, 0x8000, 0xD60E, 0, 0, 0, 0 },
+ { 0x2BD0, 0x7FFF, 0x8000, 0xD42F, 0, 0, 0, 0 }, { 0x2DC5, 0x7FFF, 0x8000, 0xD23A, 0, 0, 0, 0 },
+ { 0x2FD0, 0x7FFF, 0x8000, 0xD02F, 0, 0, 0, 0 }, { 0x31F2, 0x7FFF, 0x8000, 0xCE0D, 0, 0, 0, 0 },
+ { 0x342C, 0x7FFF, 0x8000, 0xCBD3, 0, 0, 0, 0 }, { 0x3681, 0x7FFF, 0x8000, 0xC97E, 0, 0, 0, 0 },
+ { 0x38F0, 0x7FFF, 0x8000, 0xC70F, 0, 0, 0, 0 }, { 0x3B7A, 0x7FFF, 0x8000, 0xC485, 0, 0, 0, 0 },
+ { 0x3E22, 0x7FFF, 0x8000, 0xC1DD, 0, 0, 0, 0 }, { 0x40E7, 0x7FFF, 0x8000, 0xBF18, 0, 0, 0, 0 },
+};
+/* end of constants */
+
+typedef struct MACEContext {
+ short index, lev, factor, prev2, previous, level;
+ short *outPtr;
+} MACEContext;
+
+/* /// "chomp3()" */
+static void chomp3(MACEContext *ctx,
+ uint8_t val,
+ const uint16_t tab1[],
+ const uint16_t tab2[][8],
+ uint32_t numChannels)
+{
+ short current;
+
+ current=(short)tab2[(ctx->index & 0x7f0) >> 4][val];
+ if (current+ctx->lev > 32767) current=32767;
+ else if (current+ctx->lev < -32768) current=-32767;
+ else current+=ctx->lev;
+ ctx->lev=current-(current >> 3);
+// *ctx->outPtr++=current >> 8;
+ *ctx->outPtr=current;
+ ctx->outPtr+=numChannels;
+ if ( ( ctx->index += tab1[val]-(ctx->index>>5) ) < 0 ) ctx->index = 0;
+}
+/* \\\ */
+
+/* /// "Exp1to3()" */
+static void Exp1to3(MACEContext *ctx,
+ uint8_t *inBuffer,
+ void *outBuffer,
+ uint32_t cnt,
+ uint32_t numChannels,
+ uint32_t whichChannel)
+{
+ uint8_t pkt;
+
+/*
+ if (inState) {
+ ctx->index=inState[0];
+ ctx->lev=inState[1];
+ } else
+*/
+ ctx->index=ctx->lev=0;
+
+ inBuffer+=(whichChannel-1)*2;
+
+ ctx->outPtr=outBuffer;
+
+ while (cnt>0) {
+ pkt=inBuffer[0];
+ chomp3(ctx, pkt & 7, MACEtab1, MACEtab2, numChannels);
+ chomp3(ctx,(pkt >> 3) & 3, MACEtab3, MACEtab4, numChannels);
+ chomp3(ctx, pkt >> 5 , MACEtab1, MACEtab2, numChannels);
+ pkt=inBuffer[1];
+ chomp3(ctx, pkt & 7, MACEtab1, MACEtab2, numChannels);
+ chomp3(ctx,(pkt >> 3) & 3, MACEtab3, MACEtab4, numChannels);
+ chomp3(ctx, pkt >> 5 , MACEtab1, MACEtab2, numChannels);
+
+ inBuffer+=numChannels*2;
+ --cnt;
+ }
+
+/*
+ if (outState) {
+ outState[0]=ctx->index;
+ outState[1]=ctx->lev;
+ }
+*/
+}
+/* \\\ */
+
+/* /// "chomp6()" */
+static void chomp6(MACEContext *ctx,
+ uint8_t val,
+ const uint16_t tab1[],
+ const uint16_t tab2[][8],
+ uint32_t numChannels)
+{
+ short current;
+
+ current=(short)tab2[(ctx->index & 0x7f0) >> 4][val];
+
+ if ((ctx->previous^current)>=0) {
+ if (ctx->factor+506>32767) ctx->factor=32767;
+ else ctx->factor+=506;
+ } else {
+ if (ctx->factor-314<-32768) ctx->factor=-32767;
+ else ctx->factor-=314;
+ }
+
+ if (current+ctx->level>32767) current=32767;
+ else if (current+ctx->level<-32768) current=-32767;
+ else current+=ctx->level;
+
+ ctx->level=((current*ctx->factor) >> 15);
+ current>>=1;
+
+// *ctx->outPtr++=(ctx->previous+ctx->prev2-((ctx->prev2-current) >> 2)) >> 8;
+// *ctx->outPtr++=(ctx->previous+current+((ctx->prev2-current) >> 2)) >> 8;
+ *ctx->outPtr=(ctx->previous+ctx->prev2-((ctx->prev2-current) >> 2));
+ ctx->outPtr+=numChannels;
+ *ctx->outPtr=(ctx->previous+current+((ctx->prev2-current) >> 2));
+ ctx->outPtr+=numChannels;
+ ctx->prev2=ctx->previous;
+ ctx->previous=current;
+
+ if( ( ctx->index += tab1[val]-(ctx->index>>5) ) < 0 ) ctx->index = 0;
+}
+/* \\\ */
+
+/* /// "Exp1to6()" */
+static void Exp1to6(MACEContext *ctx,
+ uint8_t *inBuffer,
+ void *outBuffer,
+ uint32_t cnt,
+ uint32_t numChannels,
+ uint32_t whichChannel)
+{
+ uint8_t pkt;
+
+/*
+ if (inState) {
+ ctx->previous=inState[0];
+ ctx->prev2=inState[1];
+ ctx->index=inState[2];
+ ctx->level=inState[3];
+ ctx->factor=inState[4];
+ } else
+*/
+ ctx->previous=ctx->prev2=ctx->index=ctx->level=ctx->factor=0;
+
+ inBuffer+=(whichChannel-1);
+ ctx->outPtr=outBuffer;
+
+ while (cnt>0) {
+ pkt=*inBuffer;
+
+ chomp6(ctx, pkt >> 5 , MACEtab1, MACEtab2, numChannels);
+ chomp6(ctx,(pkt >> 3) & 3, MACEtab3, MACEtab4, numChannels);
+ chomp6(ctx, pkt & 7, MACEtab1, MACEtab2, numChannels);
+
+ inBuffer+=numChannels;
+ --cnt;
+ }
+
+/*
+ if (outState) {
+ outState[0]=ctx->previous;
+ outState[1]=ctx->prev2;
+ outState[2]=ctx->index;
+ outState[3]=ctx->level;
+ outState[4]=ctx->factor;
+ }
+*/
+}
+/* \\\ */
+
+static int mace_decode_init(AVCodecContext * avctx)
+{
+ if (avctx->channels > 2)
+ return -1;
+ return 0;
+}
+
+static int mace_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ short *samples;
+ MACEContext *c = avctx->priv_data;
+
+ samples = (short *)data;
+ switch (avctx->codec->id) {
+ case CODEC_ID_MACE3:
+#ifdef DEBUG
+puts("mace_decode_frame[3]()");
+#endif
+ Exp1to3(c, buf, samples, buf_size / 2 / avctx->channels, avctx->channels, 1);
+ if (avctx->channels == 2)
+ Exp1to3(c, buf, samples+1, buf_size / 2 / 2, 2, 2);
+ *data_size = 2 * 3 * buf_size;
+ break;
+ case CODEC_ID_MACE6:
+#ifdef DEBUG
+puts("mace_decode_frame[6]()");
+#endif
+ Exp1to6(c, buf, samples, buf_size / avctx->channels, avctx->channels, 1);
+ if (avctx->channels == 2)
+ Exp1to6(c, buf, samples+1, buf_size / 2, 2, 2);
+ *data_size = 2 * 6 * buf_size;
+ break;
+ default:
+ return -1;
+ }
+ return buf_size;
+}
+
+AVCodec mace3_decoder = {
+ "mace3",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_MACE3,
+ sizeof(MACEContext),
+ mace_decode_init,
+ NULL,
+ NULL,
+ mace_decode_frame,
+};
+
+AVCodec mace6_decoder = {
+ "mace6",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_MACE6,
+ sizeof(MACEContext),
+ mace_decode_init,
+ NULL,
+ NULL,
+ mace_decode_frame,
+};
+
diff --git a/contrib/ffmpeg/libavcodec/mathops.h b/contrib/ffmpeg/libavcodec/mathops.h
new file mode 100644
index 000000000..9ae34d71b
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mathops.h
@@ -0,0 +1,69 @@
+/*
+ * simple math operations
+ * Copyright (c) 2001, 2002 Fabrice Bellard.
+ * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> 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 MATHOPS_H
+#define MATHOPS_H
+
+#ifdef ARCH_X86_32
+
+#include "i386/mathops.h"
+
+#elif defined(ARCH_ARMV4L)
+
+#include "armv4l/mathops.h"
+
+#elif defined(ARCH_PPC)
+
+#include "ppc/mathops.h"
+
+#endif
+
+/* generic implementation */
+
+#ifndef MULL
+# define MULL(a,b) (((int64_t)(a) * (int64_t)(b)) >> FRAC_BITS)
+#endif
+
+#ifndef MULH
+//gcc 3.4 creates an incredibly bloated mess out of this
+//# define MULH(a,b) (((int64_t)(a) * (int64_t)(b))>>32)
+
+static always_inline int MULH(int a, int b){
+ return ((int64_t)(a) * (int64_t)(b))>>32;
+}
+#endif
+
+#ifndef MUL64
+# define MUL64(a,b) ((int64_t)(a) * (int64_t)(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
+
+#endif //MATHOPS_H
+
diff --git a/contrib/ffmpeg/libavcodec/mdct.c b/contrib/ffmpeg/libavcodec/mdct.c
new file mode 100644
index 000000000..de3275289
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mdct.c
@@ -0,0 +1,177 @@
+/*
+ * 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 "dsputil.h"
+
+/**
+ * @file mdct.c
+ * MDCT/IMDCT transforms.
+ */
+
+/**
+ * init MDCT or IMDCT computation.
+ */
+int ff_mdct_init(MDCTContext *s, int nbits, int inverse)
+{
+ int n, n4, i;
+ float alpha;
+
+ memset(s, 0, sizeof(*s));
+ n = 1 << nbits;
+ s->nbits = nbits;
+ s->n = n;
+ n4 = n >> 2;
+ s->tcos = av_malloc(n4 * sizeof(FFTSample));
+ if (!s->tcos)
+ goto fail;
+ s->tsin = av_malloc(n4 * sizeof(FFTSample));
+ if (!s->tsin)
+ goto fail;
+
+ for(i=0;i<n4;i++) {
+ alpha = 2 * M_PI * (i + 1.0 / 8.0) / n;
+ s->tcos[i] = -cos(alpha);
+ s->tsin[i] = -sin(alpha);
+ }
+ if (ff_fft_init(&s->fft, s->nbits - 2, inverse) < 0)
+ goto fail;
+ return 0;
+ fail:
+ av_freep(&s->tcos);
+ av_freep(&s->tsin);
+ return -1;
+}
+
+/* complex multiplication: p = a * b */
+#define CMUL(pre, pim, are, aim, bre, bim) \
+{\
+ float _are = (are);\
+ float _aim = (aim);\
+ float _bre = (bre);\
+ float _bim = (bim);\
+ (pre) = _are * _bre - _aim * _bim;\
+ (pim) = _are * _bim + _aim * _bre;\
+}
+
+/**
+ * Compute inverse MDCT of size N = 2^nbits
+ * @param output N samples
+ * @param input N/2 samples
+ * @param tmp N/2 samples
+ */
+void ff_imdct_calc(MDCTContext *s, FFTSample *output,
+ const FFTSample *input, FFTSample *tmp)
+{
+ int k, n8, n4, n2, n, j;
+ const uint16_t *revtab = s->fft.revtab;
+ const FFTSample *tcos = s->tcos;
+ const FFTSample *tsin = s->tsin;
+ const FFTSample *in1, *in2;
+ FFTComplex *z = (FFTComplex *)tmp;
+
+ n = 1 << s->nbits;
+ 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;
+ }
+ ff_fft_calc(&s->fft, z);
+
+ /* post rotation + reordering */
+ /* XXX: optimize */
+ for(k = 0; k < n4; k++) {
+ CMUL(z[k].re, z[k].im, z[k].re, z[k].im, tcos[k], tsin[k]);
+ }
+ for(k = 0; k < n8; k++) {
+ output[2*k] = -z[n8 + k].im;
+ output[n2-1-2*k] = z[n8 + k].im;
+
+ output[2*k+1] = z[n8-1-k].re;
+ output[n2-1-2*k-1] = -z[n8-1-k].re;
+
+ output[n2 + 2*k]=-z[k+n8].re;
+ output[n-1- 2*k]=-z[k+n8].re;
+
+ output[n2 + 2*k+1]=z[n8-k-1].im;
+ output[n-2 - 2 * k] = z[n8-k-1].im;
+ }
+}
+
+/**
+ * Compute MDCT of size N = 2^nbits
+ * @param input N samples
+ * @param out N/2 samples
+ * @param tmp temporary storage of N/2 samples
+ */
+void ff_mdct_calc(MDCTContext *s, FFTSample *out,
+ const FFTSample *input, FFTSample *tmp)
+{
+ int i, j, n, n8, n4, n2, n3;
+ FFTSample re, im, re1, im1;
+ const uint16_t *revtab = s->fft.revtab;
+ const FFTSample *tcos = s->tcos;
+ const FFTSample *tsin = s->tsin;
+ FFTComplex *x = (FFTComplex *)tmp;
+
+ n = 1 << s->nbits;
+ n2 = n >> 1;
+ n4 = n >> 2;
+ n8 = n >> 3;
+ n3 = 3 * n4;
+
+ /* pre rotation */
+ for(i=0;i<n8;i++) {
+ re = -input[2*i+3*n4] - input[n3-1-2*i];
+ im = -input[n4+2*i] + input[n4-1-2*i];
+ j = revtab[i];
+ CMUL(x[j].re, x[j].im, re, im, -tcos[i], tsin[i]);
+
+ re = input[2*i] - input[n2-1-2*i];
+ im = -(input[n2+2*i] + input[n-1-2*i]);
+ j = revtab[n8 + i];
+ CMUL(x[j].re, x[j].im, re, im, -tcos[n8 + i], tsin[n8 + i]);
+ }
+
+ ff_fft_calc(&s->fft, x);
+
+ /* post rotation */
+ for(i=0;i<n4;i++) {
+ re = x[i].re;
+ im = x[i].im;
+ CMUL(re1, im1, re, im, -tsin[i], -tcos[i]);
+ out[2*i] = im1;
+ out[n2-1-2*i] = re1;
+ }
+}
+
+void ff_mdct_end(MDCTContext *s)
+{
+ av_freep(&s->tcos);
+ av_freep(&s->tsin);
+ ff_fft_end(&s->fft);
+}
diff --git a/contrib/ffmpeg/libavcodec/mdec.c b/contrib/ffmpeg/libavcodec/mdec.c
new file mode 100644
index 000000000..ee43b2777
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mdec.c
@@ -0,0 +1,270 @@
+/*
+ * PSX MDEC 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
+ *
+ * based upon code from Sebastian Jedruszkiewicz <elf@frogger.rules.pl>
+ */
+
+/**
+ * @file mdec.c
+ * PSX MDEC codec.
+ * This is very similar to intra only MPEG1.
+ */
+
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+//#undef NDEBUG
+//#include <assert.h>
+
+typedef struct MDECContext{
+ AVCodecContext *avctx;
+ DSPContext dsp;
+ AVFrame picture;
+ PutBitContext pb;
+ 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_8(DCTELEM, block[6][64]);
+ DECLARE_ALIGNED_8(uint16_t, intra_matrix[64]);
+ DECLARE_ALIGNED_8(int, q_intra_matrix[64]);
+ uint8_t *bitstream_buffer;
+ unsigned int bitstream_buffer_size;
+ int block_last_index[6];
+} MDECContext;
+
+//very similar to mpeg1
+static inline int mdec_decode_block_intra(MDECContext *a, DCTELEM *block, int n)
+{
+ int level, diff, i, j, run;
+ int component;
+ RLTable *rl = &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 coef */
+ 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 -1;
+ a->last_dc[component]+= diff;
+ block[0] = a->last_dc[component]<<3;
+ }
+
+ i = 0;
+ {
+ OPEN_READER(re, &a->gb);
+ /* now quantify & encode AC coefs */
+ 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-1)|1;
+ 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 -1;
+ }
+
+ block[j] = level;
+ }
+ CLOSE_READER(re, &a->gb);
+ }
+ a->block_last_index[n] = i;
+ return 0;
+}
+
+static inline int decode_mb(MDECContext *a, DCTELEM block[6][64]){
+ int i;
+ const int block_index[6]= {5,4,0,1,2,3};
+
+ a->dsp.clear_blocks(block[0]);
+
+ for(i=0; i<6; i++){
+ if( mdec_decode_block_intra(a, block[ block_index[i] ], block_index[i]) < 0)
+ return -1;
+ }
+ return 0;
+}
+
+static inline void idct_put(MDECContext *a, int mb_x, int mb_y){
+ DCTELEM (*block)[64]= a->block;
+ int linesize= a->picture.linesize[0];
+
+ uint8_t *dest_y = a->picture.data[0] + (mb_y * 16* linesize ) + mb_x * 16;
+ uint8_t *dest_cb = a->picture.data[1] + (mb_y * 8 * a->picture.linesize[1]) + mb_x * 8;
+ uint8_t *dest_cr = a->picture.data[2] + (mb_y * 8 * a->picture.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, a->picture.linesize[1], block[4]);
+ a->dsp.idct_put(dest_cr, a->picture.linesize[2], block[5]);
+ }
+}
+
+static int decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ MDECContext * const a = avctx->priv_data;
+ AVFrame *picture = data;
+ AVFrame * const p= (AVFrame*)&a->picture;
+ int i;
+
+ if(p->data[0])
+ avctx->release_buffer(avctx, p);
+
+ p->reference= 0;
+ if(avctx->get_buffer(avctx, p) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+ p->pict_type= I_TYPE;
+ p->key_frame= 1;
+ a->last_dc[0]=
+ a->last_dc[1]=
+ a->last_dc[2]= 0;
+
+ a->bitstream_buffer= av_fast_realloc(a->bitstream_buffer, &a->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ 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);
+
+// printf("qscale:%d (0x%X), version:%d (0x%X)\n", a->qscale, a->qscale, a->version, a->version);
+
+ 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( decode_mb(a, a->block) <0)
+ return -1;
+
+ idct_put(a, a->mb_x, a->mb_y);
+ }
+ }
+
+// p->quality= (32 + a->inv_qscale/2)/a->inv_qscale;
+// memset(p->qscale_table, p->quality, p->qstride*a->mb_height);
+
+ *picture= *(AVFrame*)&a->picture;
+ *data_size = sizeof(AVPicture);
+
+ emms_c();
+
+ return (get_bits_count(&a->gb)+31)/32*4;
+}
+
+static void mdec_common_init(AVCodecContext *avctx){
+ MDECContext * const a = avctx->priv_data;
+
+ dsputil_init(&a->dsp, avctx);
+
+ a->mb_width = (avctx->coded_width + 15) / 16;
+ a->mb_height = (avctx->coded_height + 15) / 16;
+
+ avctx->coded_frame= (AVFrame*)&a->picture;
+ a->avctx= avctx;
+}
+
+static int decode_init(AVCodecContext *avctx){
+ MDECContext * const a = avctx->priv_data;
+ AVFrame *p= (AVFrame*)&a->picture;
+
+ mdec_common_init(avctx);
+ init_vlcs();
+ ff_init_scantable(a->dsp.idct_permutation, &a->scantable, ff_zigzag_direct);
+/*
+ for(i=0; i<64; i++){
+ int index= ff_zigzag_direct[i];
+ a->intra_matrix[i]= 64*ff_mpeg1_default_intra_matrix[index] / a->inv_qscale;
+ }
+*/
+ p->qstride= a->mb_width;
+ p->qscale_table= av_mallocz( p->qstride * a->mb_height);
+ avctx->pix_fmt= PIX_FMT_YUV420P;
+
+ return 0;
+}
+
+static int decode_end(AVCodecContext *avctx){
+ MDECContext * const a = avctx->priv_data;
+
+ av_freep(&a->bitstream_buffer);
+ av_freep(&a->picture.qscale_table);
+ a->bitstream_buffer_size=0;
+
+ return 0;
+}
+
+AVCodec mdec_decoder = {
+ "mdec",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MDEC,
+ sizeof(MDECContext),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
+
diff --git a/contrib/ffmpeg/libavcodec/mjpeg.c b/contrib/ffmpeg/libavcodec/mjpeg.c
new file mode 100644
index 000000000..3d8383e7b
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mjpeg.c
@@ -0,0 +1,2625 @@
+/*
+ * MJPEG encoder and 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
+ *
+ * Support for external huffman table, various fixes (AVID workaround),
+ * aspecting, new decode_frame mechanism and apple mjpeg-b support
+ * by Alex Beregszaszi <alex@naxine.org>
+ */
+
+/**
+ * @file mjpeg.c
+ * MJPEG encoder and decoder.
+ */
+
+//#define DEBUG
+#include <assert.h>
+
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+#include "bytestream.h"
+
+/* use two quantizer tables (one for luminance and one for chrominance) */
+/* not yet working */
+#undef TWOMATRIXES
+
+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;
+
+/* JPEG marker codes */
+typedef enum {
+ /* start of frame */
+ SOF0 = 0xc0, /* baseline */
+ SOF1 = 0xc1, /* extended sequential, huffman */
+ SOF2 = 0xc2, /* progressive, huffman */
+ SOF3 = 0xc3, /* lossless, huffman */
+
+ SOF5 = 0xc5, /* differential sequential, huffman */
+ SOF6 = 0xc6, /* differential progressive, huffman */
+ SOF7 = 0xc7, /* differential lossless, huffman */
+ JPG = 0xc8, /* reserved for JPEG extension */
+ SOF9 = 0xc9, /* extended sequential, arithmetic */
+ SOF10 = 0xca, /* progressive, arithmetic */
+ SOF11 = 0xcb, /* lossless, arithmetic */
+
+ SOF13 = 0xcd, /* differential sequential, arithmetic */
+ SOF14 = 0xce, /* differential progressive, arithmetic */
+ SOF15 = 0xcf, /* differential lossless, arithmetic */
+
+ DHT = 0xc4, /* define huffman tables */
+
+ DAC = 0xcc, /* define arithmetic-coding conditioning */
+
+ /* restart with modulo 8 count "m" */
+ RST0 = 0xd0,
+ RST1 = 0xd1,
+ RST2 = 0xd2,
+ RST3 = 0xd3,
+ RST4 = 0xd4,
+ RST5 = 0xd5,
+ RST6 = 0xd6,
+ RST7 = 0xd7,
+
+ SOI = 0xd8, /* start of image */
+ EOI = 0xd9, /* end of image */
+ SOS = 0xda, /* start of scan */
+ DQT = 0xdb, /* define quantization tables */
+ DNL = 0xdc, /* define number of lines */
+ DRI = 0xdd, /* define restart interval */
+ DHP = 0xde, /* define hierarchical progression */
+ EXP = 0xdf, /* expand reference components */
+
+ APP0 = 0xe0,
+ APP1 = 0xe1,
+ APP2 = 0xe2,
+ APP3 = 0xe3,
+ APP4 = 0xe4,
+ APP5 = 0xe5,
+ APP6 = 0xe6,
+ APP7 = 0xe7,
+ APP8 = 0xe8,
+ APP9 = 0xe9,
+ APP10 = 0xea,
+ APP11 = 0xeb,
+ APP12 = 0xec,
+ APP13 = 0xed,
+ APP14 = 0xee,
+ APP15 = 0xef,
+
+ JPG0 = 0xf0,
+ JPG1 = 0xf1,
+ JPG2 = 0xf2,
+ JPG3 = 0xf3,
+ JPG4 = 0xf4,
+ JPG5 = 0xf5,
+ JPG6 = 0xf6,
+ SOF48 = 0xf7, ///< JPEG-LS
+ LSE = 0xf8, ///< JPEG-LS extension parameters
+ JPG9 = 0xf9,
+ JPG10 = 0xfa,
+ JPG11 = 0xfb,
+ JPG12 = 0xfc,
+ JPG13 = 0xfd,
+
+ COM = 0xfe, /* comment */
+
+ TEM = 0x01, /* temporary private use for arithmetic coding */
+
+ /* 0x02 -> 0xbf reserved */
+} JPEG_MARKER;
+
+#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.
+ */
+static 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
+};
+static 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! */
+static const uint8_t bits_dc_luminance[17] =
+{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
+static const uint8_t val_dc_luminance[] =
+{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+static const uint8_t bits_dc_chrominance[17] =
+{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
+static const uint8_t val_dc_chrominance[] =
+{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+static const uint8_t bits_ac_luminance[17] =
+{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
+static const uint8_t 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
+};
+
+static const uint8_t bits_ac_chrominance[17] =
+{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
+
+static const uint8_t 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 ? */
+static void 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<nb;j++) {
+ sym = val_table[k++];
+ huff_size[sym] = i;
+ huff_code[sym] = code;
+ code++;
+ }
+ code <<= 1;
+ }
+}
+
+#ifdef CONFIG_ENCODERS
+int mjpeg_init(MpegEncContext *s)
+{
+ MJpegContext *m;
+
+ m = av_malloc(sizeof(MJpegContext));
+ if (!m)
+ return -1;
+
+ s->min_qcoeff=-1023;
+ s->max_qcoeff= 1023;
+
+ /* build all the huffman tables */
+ build_huffman_codes(m->huff_size_dc_luminance,
+ m->huff_code_dc_luminance,
+ bits_dc_luminance,
+ val_dc_luminance);
+ build_huffman_codes(m->huff_size_dc_chrominance,
+ m->huff_code_dc_chrominance,
+ bits_dc_chrominance,
+ val_dc_chrominance);
+ build_huffman_codes(m->huff_size_ac_luminance,
+ m->huff_code_ac_luminance,
+ bits_ac_luminance,
+ val_ac_luminance);
+ build_huffman_codes(m->huff_size_ac_chrominance,
+ m->huff_code_ac_chrominance,
+ bits_ac_chrominance,
+ val_ac_chrominance);
+
+ s->mjpeg_ctx = m;
+ return 0;
+}
+
+void mjpeg_close(MpegEncContext *s)
+{
+ av_free(s->mjpeg_ctx);
+}
+#endif //CONFIG_ENCODERS
+
+#define PREDICT(ret, topleft, top, left, predictor)\
+ switch(predictor){\
+ 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;\
+ }
+
+#ifdef CONFIG_ENCODERS
+static inline void put_marker(PutBitContext *p, int code)
+{
+ put_bits(p, 8, 0xff);
+ put_bits(p, 8, code);
+}
+
+/* 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;i<n;i++)
+ put_bits(p, 8, value_table[i]);
+
+ return n + 17;
+}
+
+static void jpeg_table_header(MpegEncContext *s)
+{
+ PutBitContext *p = &s->pb;
+ 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
+
+ /* huffman table */
+ put_marker(p, DHT);
+ flush_put_bits(p);
+ ptr = pbBufPtr(p);
+ put_bits(p, 16, 0); /* patched later */
+ size = 2;
+ size += put_huffman_table(s, 0, 0, bits_dc_luminance, val_dc_luminance);
+ size += put_huffman_table(s, 0, 1, bits_dc_chrominance, val_dc_chrominance);
+
+ size += put_huffman_table(s, 1, 0, bits_ac_luminance, val_ac_luminance);
+ size += put_huffman_table(s, 1, 1, bits_ac_chrominance, val_ac_chrominance);
+ ptr[0] = size >> 8;
+ ptr[1] = size;
+}
+
+static void jpeg_put_comments(MpegEncContext *s)
+{
+ PutBitContext *p = &s->pb;
+ int size;
+ uint8_t *ptr;
+
+ if (s->aspect_ratio_info /* && !lossless */)
+ {
+ /* JFIF header */
+ put_marker(p, APP0);
+ put_bits(p, 16, 16);
+ ff_put_string(p, "JFIF", 1); /* this puts the trailing zero-byte too */
+ put_bits(p, 16, 0x0201); /* 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 = pbBufPtr(p);
+ put_bits(p, 16, 0); /* patched later */
+ ff_put_string(p, LIBAVCODEC_IDENT, 1);
+ size = strlen(LIBAVCODEC_IDENT)+3;
+ ptr[0] = size >> 8;
+ ptr[1] = size;
+ }
+
+ if( s->avctx->pix_fmt == PIX_FMT_YUV420P
+ ||s->avctx->pix_fmt == PIX_FMT_YUV422P
+ ||s->avctx->pix_fmt == PIX_FMT_YUV444P){
+ put_marker(p, COM);
+ flush_put_bits(p);
+ ptr = pbBufPtr(p);
+ put_bits(p, 16, 0); /* patched later */
+ ff_put_string(p, "CS=ITU601", 1);
+ size = strlen("CS=ITU601")+3;
+ ptr[0] = size >> 8;
+ ptr[1] = size;
+ }
+}
+
+void mjpeg_picture_header(MpegEncContext *s)
+{
+ const int lossless= s->avctx->codec_id != CODEC_ID_MJPEG;
+ const int ls = s->avctx->codec_id == CODEC_ID_JPEGLS;
+
+ assert(!(ls && s->mjpeg_write_tables));
+
+ put_marker(&s->pb, SOI);
+
+ if (!s->mjpeg_data_only_frames)
+ {
+ jpeg_put_comments(s);
+
+ if (s->mjpeg_write_tables) jpeg_table_header(s);
+
+ switch(s->avctx->codec_id){
+ case CODEC_ID_MJPEG: put_marker(&s->pb, SOF0 ); break;
+ case CODEC_ID_LJPEG: put_marker(&s->pb, SOF3 ); break;
+ case CODEC_ID_JPEGLS: put_marker(&s->pb, SOF48); break;
+ default: assert(0);
+ }
+
+ put_bits(&s->pb, 16, 17);
+ if(lossless && s->avctx->pix_fmt == PIX_FMT_RGBA32)
+ 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 && !ls) ? s->avctx->prediction_method+1 : 0); /* Ss (not used) */
+
+ switch(s->avctx->codec_id){
+ case CODEC_ID_MJPEG: put_bits(&s->pb, 8, 63); break; /* Se (not used) */
+ case CODEC_ID_LJPEG: put_bits(&s->pb, 8, 0); break; /* not used */
+ case CODEC_ID_JPEGLS: put_bits(&s->pb, 8, 1); break; /* ILV = line interleaved */
+ default: assert(0);
+ }
+
+ put_bits(&s->pb, 8, 0); /* Ah/Al (not used) */
+
+ //FIXME DC/AC entropy table selectors stuff in jpegls
+}
+
+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;
+
+ assert((size&7) == 0);
+ size >>= 3;
+
+ ff_count=0;
+ for(i=0; i<size && i<align; i++){
+ if(buf[i]==0xFF) ff_count++;
+ }
+ for(; i<size-15; i+=16){
+ int acc, v;
+
+ v= *(uint32_t*)(&buf[i]);
+ acc= (((v & (v>>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(; i<size; i++){
+ if(buf[i]==0xFF) ff_count++;
+ }
+
+ if(ff_count==0) return;
+
+ /* skip put bits */
+ for(i=0; i<ff_count-3; i+=4)
+ put_bits(&s->pb, 32, 0);
+ put_bits(&s->pb, (ff_count-i)*8, 0);
+ flush_put_bits(&s->pb);
+
+ for(i=size-1; ff_count; i--){
+ int v= buf[i];
+
+ if(v==0xFF){
+//printf("%d %d\n", i, ff_count);
+ buf[i+ff_count]= 0;
+ ff_count--;
+ }
+
+ buf[i+ff_count]= v;
+ }
+}
+
+void ff_mjpeg_stuffing(PutBitContext * pbc)
+{
+ int length;
+ length= (-put_bits_count(pbc))&7;
+ if(length) put_bits(pbc, length, (1<<length)-1);
+}
+
+void mjpeg_picture_trailer(MpegEncContext *s)
+{
+ ff_mjpeg_stuffing(&s->pb);
+ flush_put_bits(&s->pb);
+
+ assert((s->header_bits&7)==0);
+
+ escape_FF(s, s->header_bits>>3);
+
+ put_marker(&s->pb, EOI);
+}
+
+static inline void 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_bits(&s->pb, nbits, mant & ((1 << nbits) - 1));
+ }
+}
+
+static void encode_block(MpegEncContext *s, DCTELEM *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) {
+ 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 {
+ 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_bits(&s->pb, nbits, mant & ((1 << nbits) - 1));
+ 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 mjpeg_encode_mb(MpegEncContext *s,
+ DCTELEM block[6][64])
+{
+ int i;
+ 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);
+ }
+}
+
+static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
+ MpegEncContext * const s = avctx->priv_data;
+ MJpegContext * const m = s->mjpeg_ctx;
+ AVFrame *pict = data;
+ const int width= s->width;
+ const int height= s->height;
+ AVFrame * const p= (AVFrame*)&s->current_picture;
+ const int predictor= avctx->prediction_method+1;
+
+ init_put_bits(&s->pb, buf, buf_size);
+
+ *p = *pict;
+ p->pict_type= FF_I_TYPE;
+ p->key_frame= 1;
+
+ mjpeg_picture_header(s);
+
+ s->header_bits= put_bits_count(&s->pb);
+
+ if(avctx->pix_fmt == PIX_FMT_RGBA32){
+ 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++) {
+ 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)
+ mjpeg_encode_dc(s, diff, m->huff_size_dc_luminance, m->huff_code_dc_luminance); //FIXME ugly
+ else
+ mjpeg_encode_dc(s, diff, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance);
+ }
+ }
+ }
+ }else{
+ int mb_x, mb_y, i;
+ 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];
+
+ 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; y<v; y++){
+ for(x=0; x<h; x++){
+ int pred;
+
+ ptr = p->data[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)
+ mjpeg_encode_dc(s, (int8_t)(*ptr - pred), m->huff_size_dc_luminance, m->huff_code_dc_luminance); //FIXME ugly
+ else
+ mjpeg_encode_dc(s, (int8_t)(*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; y<v; y++){
+ for(x=0; x<h; x++){
+ int pred;
+
+ ptr = p->data[i] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap
+//printf("%d %d %d %d %8X\n", mb_x, mb_y, x, y, ptr);
+ PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor);
+
+ if(i==0)
+ mjpeg_encode_dc(s, (int8_t)(*ptr - pred), m->huff_size_dc_luminance, m->huff_code_dc_luminance); //FIXME ugly
+ else
+ mjpeg_encode_dc(s, (int8_t)(*ptr - pred), m->huff_size_dc_chrominance, m->huff_code_dc_chrominance);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ emms_c();
+
+ mjpeg_picture_trailer(s);
+ s->picture_number++;
+
+ flush_put_bits(&s->pb);
+ return pbBufPtr(&s->pb) - s->pb.buf;
+// return (put_bits_count(&f->pb)+7)/8;
+}
+
+#endif //CONFIG_ENCODERS
+
+/******************************************/
+/* decoding */
+
+#define MAX_COMPONENTS 4
+
+typedef struct MJpegDecodeContext {
+ AVCodecContext *avctx;
+ GetBitContext gb;
+ int mpeg_enc_ctx_allocated; /* true if decoding context allocated */
+
+ int start_code; /* current start code */
+ int buffer_size;
+ uint8_t *buffer;
+
+ int16_t quant_matrixes[4][64];
+ VLC vlcs[2][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 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 intervall ?rename
+
+ int width, height;
+ int mb_width, mb_height;
+ int nb_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 */
+ int linesize[MAX_COMPONENTS]; ///< linesize << interlaced
+ int8_t *qscale_table;
+ DECLARE_ALIGNED_8(DCTELEM, block[64]);
+ ScanTable scantable;
+ void (*idct_put)(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/);
+ void (*idct_add)(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/);
+
+ 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 */
+} MJpegDecodeContext;
+
+#include "jpeg_ls.c" //FIXME make jpeg-ls more independant
+
+static int mjpeg_decode_dht(MJpegDecodeContext *s);
+
+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+16];
+ uint16_t huff_code[256+16];
+
+ assert(nb_codes <= 256);
+
+ memset(huff_size, 0, sizeof(huff_size));
+ build_huffman_codes(huff_size, huff_code, bits_table, val_table);
+
+ if(is_ac){
+ memmove(huff_size+16, huff_size, sizeof(uint8_t)*nb_codes);
+ memmove(huff_code+16, huff_code, sizeof(uint16_t)*nb_codes);
+ memset(huff_size, 0, sizeof(uint8_t)*16);
+ memset(huff_code, 0, sizeof(uint16_t)*16);
+ nb_codes += 16;
+ }
+
+ return init_vlc(vlc, 9, nb_codes, huff_size, 1, 1, huff_code, 2, 2, use_static);
+}
+
+static int mjpeg_decode_init(AVCodecContext *avctx)
+{
+ MJpegDecodeContext *s = avctx->priv_data;
+ MpegEncContext s2;
+ memset(s, 0, sizeof(MJpegDecodeContext));
+
+ s->avctx = avctx;
+
+ /* ugly way to get the idct & scantable FIXME */
+ memset(&s2, 0, sizeof(MpegEncContext));
+ s2.avctx= avctx;
+// s2->out_format = FMT_MJPEG;
+ dsputil_init(&s2.dsp, avctx);
+ DCT_common_init(&s2);
+
+ s->scantable= s2.intra_scantable;
+ s->idct_put= s2.dsp.idct_put;
+ s->idct_add= s2.dsp.idct_add;
+
+ s->mpeg_enc_ctx_allocated = 0;
+ s->buffer_size = 0;
+ s->buffer = NULL;
+ s->start_code = -1;
+ s->first_picture = 1;
+ s->org_height = avctx->coded_height;
+
+ build_vlc(&s->vlcs[0][0], bits_dc_luminance, val_dc_luminance, 12, 0, 0);
+ build_vlc(&s->vlcs[0][1], bits_dc_chrominance, val_dc_chrominance, 12, 0, 0);
+ build_vlc(&s->vlcs[1][0], bits_ac_luminance, val_ac_luminance, 251, 0, 1);
+ build_vlc(&s->vlcs[1][1], bits_ac_chrominance, val_ac_chrominance, 251, 0, 1);
+
+ if (avctx->flags & CODEC_FLAG_EXTERN_HUFF)
+ {
+ av_log(avctx, AV_LOG_INFO, "mjpeg: using external huffman table\n");
+ init_get_bits(&s->gb, avctx->extradata, avctx->extradata_size*8);
+ mjpeg_decode_dht(s);
+ /* should check for error - but dunno */
+ }
+
+ return 0;
+}
+
+
+/**
+ * finds 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(ParseContext *pc, const uint8_t *buf, int buf_size){
+ int vop_found, i;
+ uint16_t state;
+
+ vop_found= pc->frame_start_found;
+ state= pc->state;
+
+ i=0;
+ if(!vop_found){
+ for(i=0; i<buf_size; i++){
+ state= (state<<8) | buf[i];
+ if(state == 0xFFD8){
+ i++;
+ vop_found=1;
+ break;
+ }
+ }
+ }
+
+ if(vop_found){
+ /* EOF considered as end of frame */
+ if (buf_size == 0)
+ return 0;
+ for(; i<buf_size; i++){
+ state= (state<<8) | buf[i];
+ if(state == 0xFFD8){
+ pc->frame_start_found=0;
+ pc->state=0;
+ return i-1;
+ }
+ }
+ }
+ pc->frame_start_found= vop_found;
+ pc->state= state;
+ return END_NOT_FOUND;
+}
+
+static int jpeg_parse(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size)
+{
+ ParseContext *pc = s->priv_data;
+ int next;
+
+ next= find_frame_end(pc, buf, buf_size);
+
+ if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) {
+ *poutbuf = NULL;
+ *poutbuf_size = 0;
+ return buf_size;
+ }
+
+ *poutbuf = (uint8_t *)buf;
+ *poutbuf_size = buf_size;
+ return next;
+}
+
+/* quantize tables */
+static int mjpeg_decode_dqt(MJpegDecodeContext *s)
+{
+ int len, index, i, j;
+
+ len = get_bits(&s->gb, 16) - 2;
+
+ while (len >= 65) {
+ /* only 8 bit precision handled */
+ if (get_bits(&s->gb, 4) != 0)
+ {
+ dprintf("dqt: 16bit precision\n");
+ return -1;
+ }
+ index = get_bits(&s->gb, 4);
+ if (index >= 4)
+ return -1;
+ dprintf("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, 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;
+ dprintf("qscale[%d]: %d\n", index, s->qscale[index]);
+ len -= 65;
+ }
+
+ return 0;
+}
+
+/* decode huffman tables and build VLC decoders */
+static int mjpeg_decode_dht(MJpegDecodeContext *s)
+{
+ int len, index, i, class, n, v, code_max;
+ uint8_t bits_table[17];
+ uint8_t val_table[256];
+
+ len = get_bits(&s->gb, 16) - 2;
+
+ while (len > 0) {
+ if (len < 17)
+ return -1;
+ class = get_bits(&s->gb, 4);
+ if (class >= 2)
+ return -1;
+ index = get_bits(&s->gb, 4);
+ if (index >= 4)
+ return -1;
+ 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 -1;
+
+ 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 */
+ free_vlc(&s->vlcs[class][index]);
+ dprintf("class=%d index=%d nb_codes=%d\n",
+ class, index, code_max + 1);
+ if(build_vlc(&s->vlcs[class][index], bits_table, val_table, code_max + 1, 0, class > 0) < 0){
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int mjpeg_decode_sof(MJpegDecodeContext *s)
+{
+ int len, nb_components, i, width, height, pix_fmt_id;
+
+ /* 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;
+ }
+
+ height = get_bits(&s->gb, 16);
+ width = get_bits(&s->gb, 16);
+
+ dprintf("sof0: picture: %dx%d\n", width, height);
+ if(avcodec_check_dimensions(s->avctx, width, height))
+ return -1;
+
+ nb_components = get_bits(&s->gb, 8);
+ if (nb_components <= 0 ||
+ nb_components > MAX_COMPONENTS)
+ return -1;
+ if (s->ls && !(s->bits <= 8 || nb_components == 1)){
+ av_log(s->avctx, AV_LOG_ERROR, "only <= 8 bits/component or 16-bit gray accepted for JPEG-LS\n");
+ return -1;
+ }
+ s->nb_components = nb_components;
+ s->h_max = 1;
+ s->v_max = 1;
+ for(i=0;i<nb_components;i++) {
+ /* component id */
+ s->component_id[i] = get_bits(&s->gb, 8) - 1;
+ s->h_count[i] = get_bits(&s->gb, 4);
+ s->v_count[i] = get_bits(&s->gb, 4);
+ /* compute hmax and vmax (only used in interleaved case) */
+ if (s->h_count[i] > s->h_max)
+ s->h_max = s->h_count[i];
+ if (s->v_count[i] > s->v_max)
+ s->v_max = s->v_count[i];
+ s->quant_index[i] = get_bits(&s->gb, 8);
+ if (s->quant_index[i] >= 4)
+ return -1;
+ dprintf("component %d %d:%d id: %d quant:%d\n", i, s->h_count[i],
+ s->v_count[i], s->component_id[i], s->quant_index[i]);
+ }
+
+ if(s->ls && (s->h_max > 1 || s->v_max > 1)) {
+ av_log(s->avctx, AV_LOG_ERROR, "Subsampling in JPEG-LS is not supported.\n");
+ return -1;
+ }
+
+ if(s->v_max==1 && s->h_max==1 && s->lossless==1) s->rgb=1;
+
+ /* if different size, realloc/alloc picture */
+ /* XXX: also check h_count and v_count */
+ if (width != s->width || height != s->height) {
+ av_freep(&s->qscale_table);
+
+ s->width = width;
+ s->height = height;
+
+ /* 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) ? 1 : 0;
+ s->bottom_field = 0;
+ height *= 2;
+ }
+
+ avcodec_set_dimensions(s->avctx, width, height);
+
+ s->qscale_table= av_mallocz((s->width+15)/16);
+
+ s->first_picture = 0;
+ }
+
+ if(s->interlaced && s->bottom_field)
+ return 0;
+
+ /* XXX: not complete test ! */
+ pix_fmt_id = (s->h_count[0] << 20) | (s->v_count[0] << 16) |
+ (s->h_count[1] << 12) | (s->v_count[1] << 8) |
+ (s->h_count[2] << 4) | s->v_count[2];
+ dprintf("pix fmt id %x\n", pix_fmt_id);
+ switch(pix_fmt_id){
+ case 0x222222:
+ case 0x111111:
+ if(s->rgb){
+ s->avctx->pix_fmt = PIX_FMT_RGBA32;
+ }else if(s->nb_components==3)
+ s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV444P : PIX_FMT_YUVJ444P;
+ else
+ s->avctx->pix_fmt = PIX_FMT_GRAY8;
+ break;
+ case 0x211111:
+ case 0x221212:
+ s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV422P : PIX_FMT_YUVJ422P;
+ break;
+ default:
+ case 0x221111:
+ s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV420P : PIX_FMT_YUVJ420P;
+ break;
+ }
+ if(s->ls){
+ if(s->nb_components > 1)
+ s->avctx->pix_fmt = PIX_FMT_RGB24;
+ else if(s->bits <= 8)
+ s->avctx->pix_fmt = PIX_FMT_GRAY8;
+ else
+ s->avctx->pix_fmt = PIX_FMT_GRAY16;
+ }
+
+ if(s->picture.data[0])
+ s->avctx->release_buffer(s->avctx, &s->picture);
+
+ s->picture.reference= 0;
+ if(s->avctx->get_buffer(s->avctx, &s->picture) < 0){
+ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+ s->picture.pict_type= I_TYPE;
+ s->picture.key_frame= 1;
+
+ for(i=0; i<3; i++){
+ s->linesize[i]= s->picture.linesize[i] << s->interlaced;
+ }
+
+// printf("%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)))
+ {
+ dprintf("decode_sof0: error, len(%d) mismatch\n", len);
+ }
+
+ /* totally blank picture as progressive JPEG will only add details to it */
+ if(s->progressive){
+ memset(s->picture.data[0], 0, s->picture.linesize[0] * s->height);
+ memset(s->picture.data[1], 0, s->picture.linesize[1] * s->height >> (s->v_max - s->v_count[1]));
+ memset(s->picture.data[2], 0, s->picture.linesize[2] * s->height >> (s->v_max - s->v_count[2]));
+ }
+ 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)
+ {
+ dprintf("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, DCTELEM *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) {
+ dprintf("error dc\n");
+ return -1;
+ }
+ 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)
+ for(;;) {
+ UPDATE_CACHE(re, &s->gb);
+ GET_VLC(code, re, &s->gb, s->vlcs[1][ac_index].table, 9, 2)
+
+ /* EOB */
+ if (code == 0x10)
+ break;
+ i += ((unsigned)code) >> 4;
+ if(code != 0x100){
+ code &= 0xf;
+ 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) {
+ if(i == 63){
+ j = s->scantable.permutated[63];
+ block[j] = level * quant_matrix[j];
+ break;
+ }
+ dprintf("error count: %d\n", i);
+ return -1;
+ }
+ j = s->scantable.permutated[i];
+ block[j] = level * quant_matrix[j];
+ }
+ }
+ CLOSE_READER(re, &s->gb)}
+
+ return 0;
+}
+
+/* decode block and dequantize - progressive JPEG version */
+static int decode_block_progressive(MJpegDecodeContext *s, DCTELEM *block,
+ int component, int dc_index, int ac_index, int16_t *quant_matrix,
+ int ss, int se, int Ah, int Al, int *EOBRUN)
+{
+ int code, i, j, level, val, run;
+
+ /* DC coef */
+ if(!ss){
+ val = mjpeg_decode_dc(s, dc_index);
+ if (val == 0xffff) {
+ dprintf("error dc\n");
+ return -1;
+ }
+ val = (val * quant_matrix[0] << Al) + s->last_dc[component];
+ }else
+ val = 0;
+ s->last_dc[component] = val;
+ block[0] = val;
+ if(!se) return 0;
+ /* AC coefs */
+ 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[1][ac_index].table, 9, 2)
+ /* Progressive JPEG use AC coeffs from zero and this decoder sets offset 16 by default */
+ code -= 16;
+ if(code & 0xF) {
+ i += ((unsigned) code) >> 4;
+ code &= 0xf;
+ 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;
+ }
+ dprintf("error count: %d\n", i);
+ return -1;
+ }
+ j = s->scantable.permutated[i];
+ block[j] = level * quant_matrix[j] << Al;
+ }else{
+ run = ((unsigned) code) >> 4;
+ if(run == 0xF){// ZRL - skip 15 coefficients
+ i += 15;
+ }else{
+ val = run;
+ run = (1 << run);
+ UPDATE_CACHE(re, &s->gb);
+ run += (GET_CACHE(re, &s->gb) >> (32 - val)) & (run - 1);
+ if(val)
+ LAST_SKIP_BITS(re, &s->gb, val);
+ *EOBRUN = run - 1;
+ break;
+ }
+ }
+ }
+ CLOSE_READER(re, &s->gb)}
+
+ return 0;
+}
+
+static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int predictor, int point_transform){
+ int i, mb_x, mb_y;
+ uint16_t buffer[32768][4];
+ int left[3], top[3], topleft[3];
+ const int linesize= s->linesize[0];
+ const int mask= (1<<s->bits)-1;
+
+ if((unsigned)s->mb_width > 32768) //dynamic alloc
+ return -1;
+
+ for(i=0; i<3; i++){
+ buffer[0][i]= 1 << (s->bits + point_transform - 1);
+ }
+ for(mb_y = 0; mb_y < s->mb_height; mb_y++) {
+ const int modified_predictor= mb_y ? predictor : 1;
+ 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++) {
+ if (s->restart_interval && !s->restart_count)
+ s->restart_count = s->restart_interval;
+
+ for(i=0;i<3;i++) {
+ int pred;
+
+ topleft[i]= top[i];
+ top[i]= buffer[mb_x][i];
+
+ PREDICT(pred, topleft[i], top[i], left[i], modified_predictor);
+
+ left[i]=
+ buffer[mb_x][i]= mask & (pred + (mjpeg_decode_dc(s, s->dc_index[i]) << 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[4*mb_x+1] = buffer[mb_x][0] - ((buffer[mb_x][1] + buffer[mb_x][2] - 0x200)>>2);
+ ptr[4*mb_x+0] = buffer[mb_x][1] + ptr[4*mb_x+1];
+ ptr[4*mb_x+2] = buffer[mb_x][2] + ptr[4*mb_x+1];
+ }
+ }else if(s->pegasus_rct){
+ for(mb_x = 0; mb_x < s->mb_width; mb_x++) {
+ ptr[4*mb_x+1] = buffer[mb_x][0] - ((buffer[mb_x][1] + buffer[mb_x][2])>>2);
+ ptr[4*mb_x+0] = buffer[mb_x][1] + ptr[4*mb_x+1];
+ ptr[4*mb_x+2] = buffer[mb_x][2] + ptr[4*mb_x+1];
+ }
+ }else{
+ for(mb_x = 0; mb_x < s->mb_width; mb_x++) {
+ ptr[4*mb_x+0] = buffer[mb_x][0];
+ ptr[4*mb_x+1] = buffer[mb_x][1];
+ ptr[4*mb_x+2] = buffer[mb_x][2];
+ }
+ }
+ }
+ return 0;
+}
+
+static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor, int point_transform){
+ int i, mb_x, mb_y;
+ const int 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;
+
+ if(mb_x==0 || mb_y==0 || s->interlaced){
+ for(i=0;i<nb_components;i++) {
+ uint8_t *ptr;
+ 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];
+
+ for(j=0; j<n; j++) {
+ int pred;
+
+ ptr = s->picture.data[c] + (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 << point_transform;
+ }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 (s->interlaced && s->bottom_field)
+ ptr += linesize >> 1;
+ *ptr= pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform);
+
+ if (++x == h) {
+ x = 0;
+ y++;
+ }
+ }
+ }
+ }else{
+ for(i=0;i<nb_components;i++) {
+ uint8_t *ptr;
+ 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];
+
+ for(j=0; j<n; j++) {
+ int pred;
+
+ 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);
+ *ptr= pred + (mjpeg_decode_dc(s, s->dc_index[i]) << 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 int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int ss, int se, int Ah, int Al){
+ int i, mb_x, mb_y;
+ int EOBRUN = 0;
+
+ if(Ah) return 0; /* TODO decode refinement planes too */
+ 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;
+
+ for(i=0;i<nb_components;i++) {
+ uint8_t *ptr;
+ int n, h, v, x, y, c, j;
+ 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++) {
+ memset(s->block, 0, sizeof(s->block));
+ if (!s->progressive && decode_block(s, s->block, i,
+ s->dc_index[i], s->ac_index[i],
+ s->quant_matrixes[ s->quant_index[c] ]) < 0) {
+ dprintf("error y=%d x=%d\n", mb_y, mb_x);
+ return -1;
+ }
+ if (s->progressive && decode_block_progressive(s, s->block, i,
+ s->dc_index[i], s->ac_index[i],
+ s->quant_matrixes[ s->quant_index[c] ], ss, se, Ah, Al, &EOBRUN) < 0) {
+ dprintf("error y=%d x=%d\n", mb_y, mb_x);
+ return -1;
+ }
+// dprintf("mb: %d %d processed\n", mb_y, mb_x);
+ ptr = s->picture.data[c] +
+ (((s->linesize[c] * (v * mb_y + y) * 8) +
+ (h * mb_x + x) * 8) >> s->avctx->lowres);
+ if (s->interlaced && s->bottom_field)
+ ptr += s->linesize[c] >> 1;
+//av_log(NULL, AV_LOG_DEBUG, "%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(!s->progressive)
+ s->idct_put(ptr, s->linesize[c], s->block);
+ else
+ s->idct_add(ptr, s->linesize[c], s->block);
+ if (++x == h) {
+ x = 0;
+ y++;
+ }
+ }
+ }
+ /* (< 1350) buggy workaround for Spectralfan.mov, should be fixed */
+ if (s->restart_interval && (s->restart_interval < 1350) &&
+ !--s->restart_count) {
+ align_get_bits(&s->gb);
+ skip_bits(&s->gb, 16); /* skip RSTn */
+ for (i=0; i<nb_components; i++) /* reset dc */
+ s->last_dc[i] = 1024;
+ }
+ }
+ }
+ return 0;
+}
+
+static int mjpeg_decode_sos(MJpegDecodeContext *s)
+{
+ int len, nb_components, i, h, v, predictor, point_transform;
+ int vmax, hmax, index, id;
+ const int block_size= s->lossless ? 1 : 8;
+ int ilv, prev_shift;
+
+ /* XXX: verify len field validity */
+ len = get_bits(&s->gb, 16);
+ nb_components = get_bits(&s->gb, 8);
+ if (len != 6+2*nb_components)
+ {
+ dprintf("decode_sos: invalid len (%d)\n", len);
+ return -1;
+ }
+ vmax = 0;
+ hmax = 0;
+ for(i=0;i<nb_components;i++) {
+ id = get_bits(&s->gb, 8) - 1;
+ dprintf("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)
+ {
+ dprintf("decode_sos: index(%d) out of components\n", index);
+ return -1;
+ }
+
+ 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 0 //buggy
+ switch(s->start_code)
+ {
+ case SOF0:
+ if (dc_index[i] > 1 || ac_index[i] > 1)
+ goto out_of_range;
+ break;
+ case SOF1:
+ case SOF2:
+ if (dc_index[i] > 3 || ac_index[i] > 3)
+ goto out_of_range;
+ break;
+ case SOF3:
+ if (dc_index[i] > 3 || ac_index[i] != 0)
+ goto out_of_range;
+ break;
+ }
+#endif
+ }
+
+ 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 */
+ prev_shift = get_bits(&s->gb, 4); /* Ah */
+ point_transform= get_bits(&s->gb, 4); /* Al */
+
+ for(i=0;i<nb_components;i++)
+ s->last_dc[i] = 1024;
+
+ 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 %s\n", s->lossless ? "lossless" : "sequencial DCT", s->rgb ? "RGB" : "",
+ predictor, point_transform, ilv, s->bits,
+ s->pegasus_rct ? "PRCT" : (s->rct ? "RCT" : ""));
+
+
+ /* 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);
+
+ if(s->lossless){
+ if(s->ls){
+// for(){
+// reset_ls_coding_parameters(s, 0);
+
+ ls_decode_picture(s, predictor, point_transform, ilv);
+ }else{
+ if(s->rgb){
+ if(ljpeg_decode_rgb_scan(s, predictor, point_transform) < 0)
+ return -1;
+ }else{
+ if(ljpeg_decode_yuv_scan(s, predictor, point_transform) < 0)
+ return -1;
+ }
+ }
+ }else{
+ if(mjpeg_decode_scan(s, nb_components, predictor, ilv, prev_shift, point_transform) < 0)
+ return -1;
+ }
+ emms_c();
+ return 0;
+ out_of_range:
+ dprintf("decode_sos: ac/dc index out of range\n");
+ return -1;
+}
+
+static int mjpeg_decode_dri(MJpegDecodeContext *s)
+{
+ if (get_bits(&s->gb, 16) != 4)
+ return -1;
+ s->restart_interval = get_bits(&s->gb, 16);
+ s->restart_count = 0;
+ dprintf("restart interval: %d\n", s->restart_interval);
+
+ return 0;
+}
+
+static int mjpeg_decode_app(MJpegDecodeContext *s)
+{
+ int len, id;
+
+ len = get_bits(&s->gb, 16);
+ if (len < 5)
+ return -1;
+ if(8*len + get_bits_count(&s->gb) > s->gb.size_in_bits)
+ return -1;
+
+ id = (get_bits(&s->gb, 16) << 16) | get_bits(&s->gb, 16);
+ id = be2me_32(id);
+ 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
+ informations, but it's always present in AVID creates files */
+ if (id == ff_get_fourcc("AVI1"))
+ {
+ /* structure:
+ 4bytes AVI1
+ 1bytes polarity
+ 1bytes always zero
+ 4bytes field_size
+ 4bytes field_size_less_padding
+ */
+ s->buggy_avid = 1;
+// if (s->first_picture)
+// printf("mjpeg: workarounding buggy AVID\n");
+ s->interlace_polarity = get_bits(&s->gb, 8);
+#if 0
+ skip_bits(&s->gb, 8);
+ skip_bits(&s->gb, 32);
+ skip_bits(&s->gb, 32);
+ len -= 10;
+#endif
+// if (s->interlace_polarity)
+// printf("mjpeg: interlace polarity: %d\n", s->interlace_polarity);
+ goto out;
+ }
+
+// len -= 2;
+
+ if (id == ff_get_fourcc("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 == ff_get_fourcc("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 == ff_get_fourcc("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); /* unknwon always 0? */
+ skip_bits(&s->gb, 16); /* unknwon always 0? */
+ skip_bits(&s->gb, 16); /* unknwon 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(&s->gb, 16) << 16) | get_bits(&s->gb, 16);
+ id = be2me_32(id);
+ len -= 4;
+ if (id == ff_get_fourcc("mjpg")) /* Apple MJPEG-A */
+ {
+#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_count(&s->gb) <= s->gb.size_in_bits) {
+ 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, "mjpeg comment: '%s'\n", cbuf);
+
+ /* buggy avid, it puts EOI only at every 10th frame */
+ if (!strcmp(cbuf, "AVID"))
+ {
+ s->buggy_avid = 1;
+ // if (s->first_picture)
+ // printf("mjpeg: workarounding buggy AVID\n");
+ }
+ else if(!strcmp(cbuf, "CS=ITU601")){
+ s->cs_itu601= 1;
+ }
+
+ av_free(cbuf);
+ }
+ }
+
+ return 0;
+}
+
+#if 0
+static int valid_marker_list[] =
+{
+ /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f */
+/* 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,
+/* 2 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 3 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 4 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 5 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 6 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 7 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* a */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* b */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* c */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* d */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* e */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
+}
+#endif
+
+/* return the 8 bit start code value and update the search
+ state. Return -1 if no start code found */
+static int find_marker(uint8_t **pbuf_ptr, uint8_t *buf_end)
+{
+ uint8_t *buf_ptr;
+ unsigned int v, v2;
+ int val;
+#ifdef DEBUG
+ int skipped=0;
+#endif
+
+ 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;
+ }
+#ifdef DEBUG
+ skipped++;
+#endif
+ }
+ val = -1;
+found:
+#ifdef DEBUG
+ dprintf("find_marker skipped %d bytes\n", skipped);
+#endif
+ *pbuf_ptr = buf_ptr;
+ return val;
+}
+
+static int mjpeg_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ MJpegDecodeContext *s = avctx->priv_data;
+ uint8_t *buf_end, *buf_ptr;
+ int start_code;
+ AVFrame *picture = data;
+
+ buf_ptr = buf;
+ buf_end = buf + buf_size;
+ while (buf_ptr < buf_end) {
+ /* find start next marker */
+ start_code = find_marker(&buf_ptr, buf_end);
+ {
+ /* EOF */
+ if (start_code < 0) {
+ goto the_end;
+ } else {
+ dprintf("marker=%x avail_size_in_buf=%d\n", start_code, buf_end - buf_ptr);
+
+ if ((buf_end - buf_ptr) > s->buffer_size)
+ {
+ av_free(s->buffer);
+ s->buffer_size = buf_end-buf_ptr;
+ s->buffer = av_malloc(s->buffer_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ dprintf("buffer too small, expanding to %d bytes\n",
+ s->buffer_size);
+ }
+
+ /* unescape buffer of SOS, use special treatment for JPEG-LS */
+ if (start_code == SOS && !s->ls)
+ {
+ uint8_t *src = buf_ptr;
+ uint8_t *dst = s->buffer;
+
+ while (src<buf_end)
+ {
+ uint8_t x = *(src++);
+
+ *(dst++) = x;
+ if (x == 0xff)
+ {
+ while(src<buf_end && x == 0xff)
+ x = *(src++);
+
+ if (x >= 0xd0 && x <= 0xd7)
+ *(dst++) = x;
+ else if (x)
+ break;
+ }
+ }
+ init_get_bits(&s->gb, s->buffer, (dst - s->buffer)*8);
+
+ dprintf("escaping removed %d bytes\n",
+ (buf_end - buf_ptr) - (dst - s->buffer));
+ }
+ else if(start_code == SOS && s->ls){
+ 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 -= 2;
+ 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);
+
+ init_get_bits(&s->gb, dst, bit_count);
+ }
+ else
+ init_get_bits(&s->gb, buf_ptr, (buf_end - buf_ptr)*8);
+
+ s->start_code = start_code;
+ if(s->avctx->debug & FF_DEBUG_STARTCODE){
+ av_log(s->avctx, AV_LOG_DEBUG, "startcode: %X\n", start_code);
+ }
+
+ /* process markers */
+ if (start_code >= 0xd0 && start_code <= 0xd7) {
+ dprintf("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);
+ }
+
+ switch(start_code) {
+ case SOI:
+ s->restart_interval = 0;
+
+ s->restart_count = 0;
+ /* nothing to do on SOI */
+ break;
+ case DQT:
+ mjpeg_decode_dqt(s);
+ break;
+ case DHT:
+ if(mjpeg_decode_dht(s) < 0){
+ av_log(s->avctx, AV_LOG_ERROR, "huffman table decode error\n");
+ return -1;
+ }
+ break;
+ case SOF0:
+ s->lossless=0;
+ s->progressive=0;
+ if (mjpeg_decode_sof(s) < 0)
+ return -1;
+ break;
+ case SOF2:
+ s->lossless=0;
+ s->progressive=1;
+ if (mjpeg_decode_sof(s) < 0)
+ return -1;
+ break;
+ case SOF3:
+ s->lossless=1;
+ s->progressive=0;
+ if (mjpeg_decode_sof(s) < 0)
+ return -1;
+ break;
+ case SOF48:
+ s->lossless=1;
+ s->ls=1;
+ s->progressive=0;
+ if (mjpeg_decode_sof(s) < 0)
+ return -1;
+ break;
+ case LSE:
+ if (decode_lse(s) < 0)
+ return -1;
+ break;
+ case EOI:
+ s->cur_scan = 0;
+ if ((s->buggy_avid && !s->interlaced) || s->restart_interval)
+ break;
+eoi_parser:
+ {
+ if (s->interlaced) {
+ s->bottom_field ^= 1;
+ /* if not bottom field, do not output image yet */
+ if (s->bottom_field)
+ goto not_the_end;
+ }
+ *picture = s->picture;
+ *data_size = sizeof(AVFrame);
+
+ if(!s->lossless){
+ picture->quality= FFMAX(FFMAX(s->qscale[0], s->qscale[1]), s->qscale[2]);
+ picture->qstride= 0;
+ picture->qscale_table= s->qscale_table;
+ memset(picture->qscale_table, picture->quality, (s->width+15)/16);
+ if(avctx->debug & FF_DEBUG_QP)
+ av_log(s->avctx, AV_LOG_DEBUG, "QP: %d\n", picture->quality);
+ picture->quality*= FF_QP2LAMBDA;
+ }
+
+ goto the_end;
+ }
+ break;
+ case SOS:
+ mjpeg_decode_sos(s);
+ /* buggy avid puts EOI every 10-20th frame */
+ /* if restart period is over process EOI */
+ if ((s->buggy_avid && !s->interlaced) || s->restart_interval)
+ goto eoi_parser;
+ break;
+ case DRI:
+ mjpeg_decode_dri(s);
+ break;
+ case SOF1:
+ case SOF5:
+ case SOF6:
+ case SOF7:
+ case SOF9:
+ case SOF10:
+ case SOF11:
+ case SOF13:
+ case SOF14:
+ case SOF15:
+ case JPG:
+ av_log(s->avctx, AV_LOG_ERROR, "mjpeg: unsupported coding type (%x)\n", start_code);
+ break;
+// default:
+// printf("mjpeg: unsupported marker (%x)\n", start_code);
+// break;
+ }
+
+not_the_end:
+ /* eof process start code */
+ buf_ptr += (get_bits_count(&s->gb)+7)/8;
+ dprintf("marker parser used %d bytes (%d bits)\n",
+ (get_bits_count(&s->gb)+7)/8, get_bits_count(&s->gb));
+ }
+ }
+ }
+the_end:
+ dprintf("mjpeg decode frame unused %d bytes\n", buf_end - buf_ptr);
+// return buf_end - buf_ptr;
+ return buf_ptr - buf;
+}
+
+static int mjpegb_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ MJpegDecodeContext *s = avctx->priv_data;
+ uint8_t *buf_end, *buf_ptr;
+ AVFrame *picture = data;
+ GetBitContext hgb; /* for the header */
+ uint32_t dqt_offs, dht_offs, sof_offs, sos_offs, second_field_offs;
+ uint32_t field_size, sod_offs;
+
+ buf_ptr = buf;
+ buf_end = buf + buf_size;
+
+read_header:
+ /* reset on every SOI */
+ s->restart_interval = 0;
+ s->restart_count = 0;
+ s->mjpb_skiptosod = 0;
+
+ 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) != be2me_32(ff_get_fourcc("mjpg")))
+ {
+ dprintf("not mjpeg-b (bad fourcc)\n");
+ return 0;
+ }
+
+ field_size = get_bits_long(&hgb, 32); /* field size */
+ dprintf("field size: 0x%x\n", field_size);
+ skip_bits(&hgb, 32); /* padded field size */
+ second_field_offs = get_bits_long(&hgb, 32);
+ dprintf("second field offs: 0x%x\n", second_field_offs);
+ if (second_field_offs)
+ s->interlaced = 1;
+
+ dqt_offs = get_bits_long(&hgb, 32);
+ dprintf("dqt offs: 0x%x\n", dqt_offs);
+ if (dqt_offs)
+ {
+ init_get_bits(&s->gb, buf+dqt_offs, (buf_end - (buf+dqt_offs))*8);
+ s->start_code = DQT;
+ mjpeg_decode_dqt(s);
+ }
+
+ dht_offs = get_bits_long(&hgb, 32);
+ dprintf("dht offs: 0x%x\n", dht_offs);
+ if (dht_offs)
+ {
+ init_get_bits(&s->gb, buf+dht_offs, (buf_end - (buf+dht_offs))*8);
+ s->start_code = DHT;
+ mjpeg_decode_dht(s);
+ }
+
+ sof_offs = get_bits_long(&hgb, 32);
+ dprintf("sof offs: 0x%x\n", sof_offs);
+ if (sof_offs)
+ {
+ init_get_bits(&s->gb, buf+sof_offs, (buf_end - (buf+sof_offs))*8);
+ s->start_code = SOF0;
+ if (mjpeg_decode_sof(s) < 0)
+ return -1;
+ }
+
+ sos_offs = get_bits_long(&hgb, 32);
+ dprintf("sos offs: 0x%x\n", sos_offs);
+ sod_offs = get_bits_long(&hgb, 32);
+ dprintf("sod offs: 0x%x\n", sod_offs);
+ if (sos_offs)
+ {
+// init_get_bits(&s->gb, buf+sos_offs, (buf_end - (buf+sos_offs))*8);
+ init_get_bits(&s->gb, buf+sos_offs, field_size*8);
+ s->mjpb_skiptosod = (sod_offs - sos_offs - show_bits(&s->gb, 16));
+ s->start_code = SOS;
+ mjpeg_decode_sos(s);
+ }
+
+ if (s->interlaced) {
+ s->bottom_field ^= 1;
+ /* if not bottom field, do not output image yet */
+ if (s->bottom_field && second_field_offs)
+ {
+ buf_ptr = buf + second_field_offs;
+ second_field_offs = 0;
+ goto read_header;
+ }
+ }
+
+ //XXX FIXME factorize, this looks very similar to the EOI code
+
+ *picture= s->picture;
+ *data_size = sizeof(AVFrame);
+
+ if(!s->lossless){
+ picture->quality= FFMAX(FFMAX(s->qscale[0], s->qscale[1]), s->qscale[2]);
+ picture->qstride= 0;
+ picture->qscale_table= s->qscale_table;
+ memset(picture->qscale_table, picture->quality, (s->width+15)/16);
+ if(avctx->debug & FF_DEBUG_QP)
+ av_log(avctx, AV_LOG_DEBUG, "QP: %d\n", picture->quality);
+ picture->quality*= FF_QP2LAMBDA;
+ }
+
+ return buf_ptr - buf;
+}
+
+#include "sp5x.h"
+
+static int sp5x_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+#if 0
+ MJpegDecodeContext *s = avctx->priv_data;
+#endif
+ const int qscale = 5;
+ uint8_t *buf_ptr, *buf_end, *recoded;
+ int i = 0, j = 0;
+
+ if (!avctx->width || !avctx->height)
+ return -1;
+
+ buf_ptr = buf;
+ buf_end = buf + buf_size;
+
+#if 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));
+ recoded[j+5] = (avctx->coded_height >> 8) & 0xFF;
+ recoded[j+6] = avctx->coded_height & 0xFF;
+ recoded[j+7] = (avctx->coded_width >> 8) & 0xFF;
+ recoded[j+8] = avctx->coded_width & 0xFF;
+ j += sizeof(sp5x_data_sof);
+
+ memcpy(recoded+j, &sp5x_data_sos[0], sizeof(sp5x_data_sos));
+ j += sizeof(sp5x_data_sos);
+
+ for (i = 14; i < buf_size && j < buf_size+1024-2; i++)
+ {
+ recoded[j++] = buf[i];
+ if (buf[i] == 0xff)
+ recoded[j++] = 0;
+ }
+
+ /* EOI */
+ recoded[j++] = 0xFF;
+ recoded[j++] = 0xD9;
+
+ i = mjpeg_decode_frame(avctx, data, data_size, recoded, j);
+
+ av_free(recoded);
+
+#else
+ /* SOF */
+ s->bits = 8;
+ s->width = avctx->coded_width;
+ s->height = avctx->coded_height;
+ s->nb_components = 3;
+ s->component_id[0] = 0;
+ s->h_count[0] = 2;
+ s->v_count[0] = 2;
+ s->quant_index[0] = 0;
+ s->component_id[1] = 1;
+ s->h_count[1] = 1;
+ s->v_count[1] = 1;
+ s->quant_index[1] = 1;
+ s->component_id[2] = 2;
+ s->h_count[2] = 1;
+ s->v_count[2] = 1;
+ s->quant_index[2] = 1;
+ s->h_max = 2;
+ s->v_max = 2;
+
+ s->qscale_table = av_mallocz((s->width+15)/16);
+ avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV420P : PIX_FMT_YUVJ420;
+ s->interlaced = 0;
+
+ s->picture.reference = 0;
+ if (avctx->get_buffer(avctx, &s->picture) < 0)
+ {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ s->picture.pict_type = I_TYPE;
+ s->picture.key_frame = 1;
+
+ for (i = 0; i < 3; i++)
+ s->linesize[i] = s->picture.linesize[i] << s->interlaced;
+
+ /* DQT */
+ for (i = 0; i < 64; i++)
+ {
+ j = s->scantable.permutated[i];
+ s->quant_matrixes[0][j] = sp5x_quant_table[(qscale * 2) + i];
+ }
+ s->qscale[0] = FFMAX(
+ s->quant_matrixes[0][s->scantable.permutated[1]],
+ s->quant_matrixes[0][s->scantable.permutated[8]]) >> 1;
+
+ for (i = 0; i < 64; i++)
+ {
+ j = s->scantable.permutated[i];
+ s->quant_matrixes[1][j] = sp5x_quant_table[(qscale * 2) + 1 + i];
+ }
+ s->qscale[1] = FFMAX(
+ s->quant_matrixes[1][s->scantable.permutated[1]],
+ s->quant_matrixes[1][s->scantable.permutated[8]]) >> 1;
+
+ /* DHT */
+
+ /* SOS */
+ s->comp_index[0] = 0;
+ s->nb_blocks[0] = s->h_count[0] * s->v_count[0];
+ s->h_scount[0] = s->h_count[0];
+ s->v_scount[0] = s->v_count[0];
+ s->dc_index[0] = 0;
+ s->ac_index[0] = 0;
+
+ s->comp_index[1] = 1;
+ s->nb_blocks[1] = s->h_count[1] * s->v_count[1];
+ s->h_scount[1] = s->h_count[1];
+ s->v_scount[1] = s->v_count[1];
+ s->dc_index[1] = 1;
+ s->ac_index[1] = 1;
+
+ s->comp_index[2] = 2;
+ s->nb_blocks[2] = s->h_count[2] * s->v_count[2];
+ s->h_scount[2] = s->h_count[2];
+ s->v_scount[2] = s->v_count[2];
+ s->dc_index[2] = 1;
+ s->ac_index[2] = 1;
+
+ for (i = 0; i < 3; i++)
+ s->last_dc[i] = 1024;
+
+ s->mb_width = (s->width * s->h_max * 8 -1) / (s->h_max * 8);
+ s->mb_height = (s->height * s->v_max * 8 -1) / (s->v_max * 8);
+
+ init_get_bits(&s->gb, buf+14, (buf_size-14)*8);
+
+ return mjpeg_decode_scan(s);
+#endif
+
+ return i;
+}
+
+static int mjpeg_decode_end(AVCodecContext *avctx)
+{
+ MJpegDecodeContext *s = avctx->priv_data;
+ int i, j;
+
+ av_free(s->buffer);
+ av_free(s->qscale_table);
+
+ for(i=0;i<2;i++) {
+ for(j=0;j<4;j++)
+ free_vlc(&s->vlcs[i][j]);
+ }
+ return 0;
+}
+
+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;
+ int i;
+
+ if (avctx->codec_id != 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: /* quant off */
+ case DHT: /* huff off */
+ case SOF0: /* image off */
+ bytestream_put_be32(&poutbufp, i + 46);
+ break;
+ case SOS:
+ bytestream_put_be32(&poutbufp, i + 46); /* scan off */
+ bytestream_put_be32(&poutbufp, i + 46 + BE_16(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 && LE_32(buf + i + 8) == ff_get_fourcc("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;
+}
+
+AVCodec mjpeg_decoder = {
+ "mjpeg",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MJPEG,
+ sizeof(MJpegDecodeContext),
+ mjpeg_decode_init,
+ NULL,
+ mjpeg_decode_end,
+ mjpeg_decode_frame,
+ CODEC_CAP_DR1,
+ NULL
+};
+
+AVCodec mjpegb_decoder = {
+ "mjpegb",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MJPEGB,
+ sizeof(MJpegDecodeContext),
+ mjpeg_decode_init,
+ NULL,
+ mjpeg_decode_end,
+ mjpegb_decode_frame,
+ CODEC_CAP_DR1,
+ NULL
+};
+
+AVCodec sp5x_decoder = {
+ "sp5x",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_SP5X,
+ sizeof(MJpegDecodeContext),
+ mjpeg_decode_init,
+ NULL,
+ mjpeg_decode_end,
+ sp5x_decode_frame,
+ CODEC_CAP_DR1,
+ NULL
+};
+
+#ifdef CONFIG_ENCODERS
+AVCodec ljpeg_encoder = { //FIXME avoid MPV_* lossless jpeg shouldnt need them
+ "ljpeg",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_LJPEG,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ encode_picture_lossless,
+ MPV_encode_end,
+};
+#endif
+
+AVCodecParser mjpeg_parser = {
+ { CODEC_ID_MJPEG },
+ sizeof(ParseContext),
+ NULL,
+ jpeg_parse,
+ ff_parse_close,
+};
+
+AVBitStreamFilter mjpega_dump_header_bsf = {
+ "mjpegadump",
+ 0,
+ mjpega_dump_header,
+};
diff --git a/contrib/ffmpeg/libavcodec/mlib/dsputil_mlib.c b/contrib/ffmpeg/libavcodec/mlib/dsputil_mlib.c
new file mode 100644
index 000000000..b78a54e0e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mlib/dsputil_mlib.c
@@ -0,0 +1,464 @@
+/*
+ * Sun mediaLib optimized DSP utils
+ * 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
+ */
+
+#include "../dsputil.h"
+#include "../mpegvideo.h"
+
+#include <mlib_types.h>
+#include <mlib_status.h>
+#include <mlib_sys.h>
+#include <mlib_algebra.h>
+#include <mlib_video.h>
+
+/* misc */
+
+static void get_pixels_mlib(DCTELEM *restrict block, const uint8_t *pixels, int line_size)
+{
+ int i;
+
+ for (i=0;i<8;i++) {
+ mlib_VectorConvert_S16_U8_Mod((mlib_s16 *)block, (mlib_u8 *)pixels, 8);
+
+ pixels += line_size;
+ block += 8;
+ }
+}
+
+static void diff_pixels_mlib(DCTELEM *restrict block, const uint8_t *s1, const uint8_t *s2, int line_size)
+{
+ int i;
+
+ for (i=0;i<8;i++) {
+ mlib_VectorSub_S16_U8_Mod((mlib_s16 *)block, (mlib_u8 *)s1, (mlib_u8 *)s2, 8);
+
+ s1 += line_size;
+ s2 += line_size;
+ block += 8;
+ }
+}
+
+static void add_pixels_clamped_mlib(const DCTELEM *block, uint8_t *pixels, int line_size)
+{
+ mlib_VideoAddBlock_U8_S16(pixels, (mlib_s16 *)block, line_size);
+}
+
+/* put block, width 16 pixel, height 8/16 */
+
+static void put_pixels16_mlib (uint8_t * dest, const uint8_t * ref,
+ int stride, int height)
+{
+ switch (height) {
+ case 8:
+ mlib_VideoCopyRef_U8_U8_16x8(dest, (uint8_t *)ref, stride);
+ break;
+
+ case 16:
+ mlib_VideoCopyRef_U8_U8_16x16(dest, (uint8_t *)ref, stride);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+static void put_pixels16_x2_mlib (uint8_t * dest, const uint8_t * ref,
+ int stride, int height)
+{
+ switch (height) {
+ case 8:
+ mlib_VideoInterpX_U8_U8_16x8(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 16:
+ mlib_VideoInterpX_U8_U8_16x16(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+static void put_pixels16_y2_mlib (uint8_t * dest, const uint8_t * ref,
+ int stride, int height)
+{
+ switch (height) {
+ case 8:
+ mlib_VideoInterpY_U8_U8_16x8(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 16:
+ mlib_VideoInterpY_U8_U8_16x16(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+static void put_pixels16_xy2_mlib(uint8_t * dest, const uint8_t * ref,
+ int stride, int height)
+{
+ switch (height) {
+ case 8:
+ mlib_VideoInterpXY_U8_U8_16x8(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 16:
+ mlib_VideoInterpXY_U8_U8_16x16(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+/* put block, width 8 pixel, height 4/8/16 */
+
+static void put_pixels8_mlib (uint8_t * dest, const uint8_t * ref,
+ int stride, int height)
+{
+ switch (height) {
+ case 4:
+ mlib_VideoCopyRef_U8_U8_8x4(dest, (uint8_t *)ref, stride);
+ break;
+
+ case 8:
+ mlib_VideoCopyRef_U8_U8_8x8(dest, (uint8_t *)ref, stride);
+ break;
+
+ case 16:
+ mlib_VideoCopyRef_U8_U8_8x16(dest, (uint8_t *)ref, stride);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+static void put_pixels8_x2_mlib (uint8_t * dest, const uint8_t * ref,
+ int stride, int height)
+{
+ switch (height) {
+ case 4:
+ mlib_VideoInterpX_U8_U8_8x4(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 8:
+ mlib_VideoInterpX_U8_U8_8x8(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 16:
+ mlib_VideoInterpX_U8_U8_8x16(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+static void put_pixels8_y2_mlib (uint8_t * dest, const uint8_t * ref,
+ int stride, int height)
+{
+ switch (height) {
+ case 4:
+ mlib_VideoInterpY_U8_U8_8x4(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 8:
+ mlib_VideoInterpY_U8_U8_8x8(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 16:
+ mlib_VideoInterpY_U8_U8_8x16(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+static void put_pixels8_xy2_mlib(uint8_t * dest, const uint8_t * ref,
+ int stride, int height)
+{
+ switch (height) {
+ case 4:
+ mlib_VideoInterpXY_U8_U8_8x4(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 8:
+ mlib_VideoInterpXY_U8_U8_8x8(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 16:
+ mlib_VideoInterpXY_U8_U8_8x16(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+/* average block, width 16 pixel, height 8/16 */
+
+static void avg_pixels16_mlib (uint8_t * dest, const uint8_t * ref,
+ int stride, int height)
+{
+ switch (height) {
+ case 8:
+ mlib_VideoCopyRefAve_U8_U8_16x8(dest, (uint8_t *)ref, stride);
+ break;
+
+ case 16:
+ mlib_VideoCopyRefAve_U8_U8_16x16(dest, (uint8_t *)ref, stride);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+static void avg_pixels16_x2_mlib (uint8_t * dest, const uint8_t * ref,
+ int stride, int height)
+{
+ switch (height) {
+ case 8:
+ mlib_VideoInterpAveX_U8_U8_16x8(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 16:
+ mlib_VideoInterpAveX_U8_U8_16x16(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+static void avg_pixels16_y2_mlib (uint8_t * dest, const uint8_t * ref,
+ int stride, int height)
+{
+ switch (height) {
+ case 8:
+ mlib_VideoInterpAveY_U8_U8_16x8(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 16:
+ mlib_VideoInterpAveY_U8_U8_16x16(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+static void avg_pixels16_xy2_mlib(uint8_t * dest, const uint8_t * ref,
+ int stride, int height)
+{
+ switch (height) {
+ case 8:
+ mlib_VideoInterpAveXY_U8_U8_16x8(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 16:
+ mlib_VideoInterpAveXY_U8_U8_16x16(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+/* average block, width 8 pixel, height 4/8/16 */
+
+static void avg_pixels8_mlib (uint8_t * dest, const uint8_t * ref,
+ int stride, int height)
+{
+ switch (height) {
+ case 4:
+ mlib_VideoCopyRefAve_U8_U8_8x4(dest, (uint8_t *)ref, stride);
+ break;
+
+ case 8:
+ mlib_VideoCopyRefAve_U8_U8_8x8(dest, (uint8_t *)ref, stride);
+ break;
+
+ case 16:
+ mlib_VideoCopyRefAve_U8_U8_8x16(dest, (uint8_t *)ref, stride);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+static void avg_pixels8_x2_mlib (uint8_t * dest, const uint8_t * ref,
+ int stride, int height)
+{
+ switch (height) {
+ case 4:
+ mlib_VideoInterpAveX_U8_U8_8x4(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 8:
+ mlib_VideoInterpAveX_U8_U8_8x8(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 16:
+ mlib_VideoInterpAveX_U8_U8_8x16(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+static void avg_pixels8_y2_mlib (uint8_t * dest, const uint8_t * ref,
+ int stride, int height)
+{
+ switch (height) {
+ case 4:
+ mlib_VideoInterpAveY_U8_U8_8x4(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 8:
+ mlib_VideoInterpAveY_U8_U8_8x8(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 16:
+ mlib_VideoInterpAveY_U8_U8_8x16(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+static void avg_pixels8_xy2_mlib(uint8_t * dest, const uint8_t * ref,
+ int stride, int height)
+{
+ switch (height) {
+ case 4:
+ mlib_VideoInterpAveXY_U8_U8_8x4(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 8:
+ mlib_VideoInterpAveXY_U8_U8_8x8(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ case 16:
+ mlib_VideoInterpAveXY_U8_U8_8x16(dest, (uint8_t *)ref, stride, stride);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+/* swap byte order of a buffer */
+
+static void bswap_buf_mlib(uint32_t *dst, uint32_t *src, int w)
+{
+ mlib_VectorReverseByteOrder_U32_U32(dst, src, w);
+}
+
+/* transformations */
+
+static void ff_idct_put_mlib(uint8_t *dest, int line_size, DCTELEM *data)
+{
+ int i;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ mlib_VideoIDCT8x8_S16_S16 (data, data);
+
+ for(i=0;i<8;i++) {
+ dest[0] = cm[data[0]];
+ dest[1] = cm[data[1]];
+ dest[2] = cm[data[2]];
+ dest[3] = cm[data[3]];
+ dest[4] = cm[data[4]];
+ dest[5] = cm[data[5]];
+ dest[6] = cm[data[6]];
+ dest[7] = cm[data[7]];
+
+ dest += line_size;
+ data += 8;
+ }
+}
+
+static void ff_idct_add_mlib(uint8_t *dest, int line_size, DCTELEM *data)
+{
+ mlib_VideoIDCT8x8_S16_S16 (data, data);
+ mlib_VideoAddBlock_U8_S16(dest, (mlib_s16 *)data, line_size);
+}
+
+static void ff_idct_mlib(DCTELEM *data)
+{
+ mlib_VideoIDCT8x8_S16_S16 (data, data);
+}
+
+static void ff_fdct_mlib(DCTELEM *data)
+{
+ mlib_VideoDCT8x8_S16_S16 (data, data);
+}
+
+void dsputil_init_mlib(DSPContext* c, AVCodecContext *avctx)
+{
+ c->get_pixels = get_pixels_mlib;
+ c->diff_pixels = diff_pixels_mlib;
+ c->add_pixels_clamped = add_pixels_clamped_mlib;
+
+ c->put_pixels_tab[0][0] = put_pixels16_mlib;
+ c->put_pixels_tab[0][1] = put_pixels16_x2_mlib;
+ c->put_pixels_tab[0][2] = put_pixels16_y2_mlib;
+ c->put_pixels_tab[0][3] = put_pixels16_xy2_mlib;
+ c->put_pixels_tab[1][0] = put_pixels8_mlib;
+ c->put_pixels_tab[1][1] = put_pixels8_x2_mlib;
+ c->put_pixels_tab[1][2] = put_pixels8_y2_mlib;
+ c->put_pixels_tab[1][3] = put_pixels8_xy2_mlib;
+
+ c->avg_pixels_tab[0][0] = avg_pixels16_mlib;
+ c->avg_pixels_tab[0][1] = avg_pixels16_x2_mlib;
+ c->avg_pixels_tab[0][2] = avg_pixels16_y2_mlib;
+ c->avg_pixels_tab[0][3] = avg_pixels16_xy2_mlib;
+ c->avg_pixels_tab[1][0] = avg_pixels8_mlib;
+ c->avg_pixels_tab[1][1] = avg_pixels8_x2_mlib;
+ c->avg_pixels_tab[1][2] = avg_pixels8_y2_mlib;
+ c->avg_pixels_tab[1][3] = avg_pixels8_xy2_mlib;
+
+ c->put_no_rnd_pixels_tab[0][0] = put_pixels16_mlib;
+ c->put_no_rnd_pixels_tab[1][0] = put_pixels8_mlib;
+
+ c->bswap_buf = bswap_buf_mlib;
+}
+
+void MPV_common_init_mlib(MpegEncContext *s)
+{
+ if(s->avctx->dct_algo==FF_DCT_AUTO || s->avctx->dct_algo==FF_DCT_MLIB){
+ s->dsp.fdct = ff_fdct_mlib;
+ }
+
+ if(s->avctx->idct_algo==FF_IDCT_AUTO || s->avctx->idct_algo==FF_IDCT_MLIB){
+ s->dsp.idct_put= ff_idct_put_mlib;
+ s->dsp.idct_add= ff_idct_add_mlib;
+ s->dsp.idct = ff_idct_mlib;
+ s->dsp.idct_permutation_type= FF_NO_IDCT_PERM;
+ }
+}
diff --git a/contrib/ffmpeg/libavcodec/mmvideo.c b/contrib/ffmpeg/libavcodec/mmvideo.c
new file mode 100644
index 000000000..07d3f3fc5
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mmvideo.c
@@ -0,0 +1,206 @@
+/*
+ * American Laser Games MM Video Decoder
+ * Copyright (c) 2006 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 mm.c
+ * American Laser Games MM Video Decoder
+ * by Peter Ross (suxen_drol at hotmail dot com)
+ *
+ * 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 "avcodec.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
+
+typedef struct MmContext {
+ AVCodecContext *avctx;
+ AVFrame frame;
+} MmContext;
+
+static int mm_decode_init(AVCodecContext *avctx)
+{
+ MmContext *s = avctx->priv_data;
+
+ s->avctx = avctx;
+
+ if (s->avctx->palctrl == NULL) {
+ av_log(avctx, AV_LOG_ERROR, "mmvideo: palette expected.\n");
+ return -1;
+ }
+
+ avctx->pix_fmt = PIX_FMT_PAL8;
+ avctx->has_b_frames = 0;
+
+ if (avcodec_check_dimensions(avctx, avctx->width, avctx->height))
+ return -1;
+
+ s->frame.reference = 1;
+ if (avctx->get_buffer(avctx, &s->frame)) {
+ av_log(s->avctx, AV_LOG_ERROR, "mmvideo: get_buffer() failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void mm_decode_intra(MmContext * s, int half_horiz, int half_vert, const uint8_t *buf, int buf_size)
+{
+ int i, x, y;
+ i=0; x=0; y=0;
+
+ while(i<buf_size) {
+ int run_length, color;
+
+ if (buf[i] & 0x80) {
+ run_length = 1;
+ color = buf[i];
+ i++;
+ }else{
+ run_length = (buf[i] & 0x7f) + 2;
+ color = buf[i+1];
+ i+=2;
+ }
+
+ 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 += half_vert ? 2 : 1;
+ }
+ }
+}
+
+static void mm_decode_inter(MmContext * s, int half_horiz, int half_vert, const uint8_t *buf, int buf_size)
+{
+ const int data_ptr = 2 + LE_16(&buf[0]);
+ int d, r, y;
+ d = data_ptr; r = 2; y = 0;
+
+ while(r < data_ptr) {
+ int i, j;
+ int length = buf[r] & 0x7f;
+ int x = buf[r+1] + ((buf[r] & 0x80) << 1);
+ r += 2;
+
+ if (length==0) {
+ y += x;
+ continue;
+ }
+
+ for(i=0; i<length; i++) {
+ for(j=0; j<8; j++) {
+ int replace = (buf[r+i] >> (7-j)) & 1;
+ if (replace) {
+ int color = buf[d];
+ 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;
+ }
+ d++;
+ }
+ x += half_horiz ? 2 : 1;
+ }
+ }
+
+ r += length;
+ y += half_vert ? 2 : 1;
+ }
+}
+
+static int mm_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ MmContext *s = avctx->priv_data;
+ AVPaletteControl *palette_control = avctx->palctrl;
+ int type;
+
+ if (palette_control->palette_changed) {
+ memcpy(s->frame.data[1], palette_control->palette, AVPALETTE_SIZE);
+ palette_control->palette_changed = 0;
+ }
+
+ type = LE_16(&buf[0]);
+ buf += MM_PREAMBLE_SIZE;
+ buf_size -= MM_PREAMBLE_SIZE;
+
+ switch(type) {
+ case MM_TYPE_INTRA : mm_decode_intra(s, 0, 0, buf, buf_size); break;
+ case MM_TYPE_INTRA_HH : mm_decode_intra(s, 1, 0, buf, buf_size); break;
+ case MM_TYPE_INTRA_HHV : mm_decode_intra(s, 1, 1, buf, buf_size); break;
+ case MM_TYPE_INTER : mm_decode_inter(s, 0, 0, buf, buf_size); break;
+ case MM_TYPE_INTER_HH : mm_decode_inter(s, 1, 0, buf, buf_size); break;
+ case MM_TYPE_INTER_HHV : mm_decode_inter(s, 1, 1, buf, buf_size); break;
+ default :
+ return -1;
+ }
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = s->frame;
+
+ return buf_size;
+}
+
+static int mm_decode_end(AVCodecContext *avctx)
+{
+ MmContext *s = avctx->priv_data;
+
+ if(s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ return 0;
+}
+
+AVCodec mmvideo_decoder = {
+ "mmvideo",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MMVIDEO,
+ sizeof(MmContext),
+ mm_decode_init,
+ NULL,
+ mm_decode_end,
+ mm_decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/motion_est.c b/contrib/ffmpeg/libavcodec/motion_est.c
new file mode 100644
index 000000000..4dc17b99b
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/motion_est.c
@@ -0,0 +1,2114 @@
+/*
+ * Motion estimation
+ * 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
+ *
+ * new Motion Estimation (X1/EPZS) by Michael Niedermayer <michaelni@gmx.at>
+ */
+
+/**
+ * @file motion_est.c
+ * Motion estimation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+#define SQ(a) ((a)*(a))
+
+#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 inline 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 int 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 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){
+ MotionEstContext * const c= &s->me;
+ const int stride= c->stride;
+ const int uvstride= c->uvstride;
+ const int qpel= flags&FLAG_QPEL;
+ const int chroma= flags&FLAG_CHROMA;
+ 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 ...)
+ if(flags&FLAG_DIRECT){
+ 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{
+ assert((fx>>1) + 16*s->mb_x >= -16);
+ assert((fy>>1) + 16*s->mb_y >= -16);
+ assert((fx>>1) + 16*s->mb_x <= s->width);
+ assert((fy>>1) + 16*s->mb_y <= s->height);
+ assert((bx>>1) + 16*s->mb_x >= -16);
+ assert((by>>1) + 16*s->mb_y >= -16);
+ assert((bx>>1) + 16*s->mb_x <= s->width);
+ assert((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;
+ }else{
+ 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);
+ }
+ }
+#if 0
+ if(full_pel){
+ const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);
+ score_map[index]= d;
+ }
+
+ d += (c->mv_penalty[hx - c->pred_x] + c->mv_penalty[hy - c->pred_y])*c->penalty_factor;
+#endif
+ return d;
+}
+
+#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, int stride, int h){
+}
+
+void ff_init_me(MpegEncContext *s){
+ MotionEstContext * const c= &s->me;
+ c->avctx= s->avctx;
+
+ 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->dsp.avg_pixels_tab;
+ if(s->no_rounding) c->hpel_put= s->dsp.put_no_rnd_pixels_tab;
+ else c->hpel_put= s->dsp.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 dont have yet, and even if we had the motion estimation code doesnt expect it
+ if(s->codec_id != 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 == CODEC_ID_H261){
+ c->sub_motion_search= no_sub_motion_search;
+ }
+
+ c->temp= c->scratchpad;
+}
+
+#if 0
+static int pix_dev(uint8_t * pix, int line_size, int mean)
+{
+ int s, i, j;
+
+ s = 0;
+ for (i = 0; i < 16; i++) {
+ for (j = 0; j < 16; j += 8) {
+ s += FFABS(pix[0]-mean);
+ s += FFABS(pix[1]-mean);
+ s += FFABS(pix[2]-mean);
+ s += FFABS(pix[3]-mean);
+ s += FFABS(pix[4]-mean);
+ s += FFABS(pix[5]-mean);
+ s += FFABS(pix[6]-mean);
+ s += FFABS(pix[7]-mean);
+ pix += 8;
+ }
+ pix += line_size - 16;
+ }
+ return s;
+}
+#endif
+
+static inline void no_motion_search(MpegEncContext * s,
+ int *mx_ptr, int *my_ptr)
+{
+ *mx_ptr = 16 * s->mb_x;
+ *my_ptr = 16 * s->mb_y;
+}
+
+#if 0 /* the use of these functions is inside #if 0 */
+static int full_motion_search(MpegEncContext * s,
+ int *mx_ptr, int *my_ptr, int range,
+ int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
+{
+ int x1, y1, x2, y2, xx, yy, x, y;
+ int mx, my, dmin, d;
+ uint8_t *pix;
+
+ xx = 16 * s->mb_x;
+ yy = 16 * s->mb_y;
+ x1 = xx - range + 1; /* we loose one pixel to avoid boundary pb with half pixel pred */
+ if (x1 < xmin)
+ x1 = xmin;
+ x2 = xx + range - 1;
+ if (x2 > xmax)
+ x2 = xmax;
+ y1 = yy - range + 1;
+ if (y1 < ymin)
+ y1 = ymin;
+ y2 = yy + range - 1;
+ if (y2 > ymax)
+ y2 = ymax;
+ pix = s->new_picture.data[0] + (yy * s->linesize) + xx;
+ dmin = 0x7fffffff;
+ mx = 0;
+ my = 0;
+ for (y = y1; y <= y2; y++) {
+ for (x = x1; x <= x2; x++) {
+ d = s->dsp.pix_abs[0][0](NULL, pix, ref_picture + (y * s->linesize) + x,
+ s->linesize, 16);
+ if (d < dmin ||
+ (d == dmin &&
+ (abs(x - xx) + abs(y - yy)) <
+ (abs(mx - xx) + abs(my - yy)))) {
+ dmin = d;
+ mx = x;
+ my = y;
+ }
+ }
+ }
+
+ *mx_ptr = mx;
+ *my_ptr = my;
+
+#if 0
+ if (*mx_ptr < -(2 * range) || *mx_ptr >= (2 * range) ||
+ *my_ptr < -(2 * range) || *my_ptr >= (2 * range)) {
+ av_log(NULL, AV_LOG_ERROR, "error %d %d\n", *mx_ptr, *my_ptr);
+ }
+#endif
+ return dmin;
+}
+
+
+static int log_motion_search(MpegEncContext * s,
+ int *mx_ptr, int *my_ptr, int range,
+ int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
+{
+ int x1, y1, x2, y2, xx, yy, x, y;
+ int mx, my, dmin, d;
+ uint8_t *pix;
+
+ xx = s->mb_x << 4;
+ yy = s->mb_y << 4;
+
+ /* Left limit */
+ x1 = xx - range;
+ if (x1 < xmin)
+ x1 = xmin;
+
+ /* Right limit */
+ x2 = xx + range;
+ if (x2 > xmax)
+ x2 = xmax;
+
+ /* Upper limit */
+ y1 = yy - range;
+ if (y1 < ymin)
+ y1 = ymin;
+
+ /* Lower limit */
+ y2 = yy + range;
+ if (y2 > ymax)
+ y2 = ymax;
+
+ pix = s->new_picture.data[0] + (yy * s->linesize) + xx;
+ dmin = 0x7fffffff;
+ mx = 0;
+ my = 0;
+
+ do {
+ for (y = y1; y <= y2; y += range) {
+ for (x = x1; x <= x2; x += range) {
+ d = s->dsp.pix_abs[0][0](NULL, pix, ref_picture + (y * s->linesize) + x, s->linesize, 16);
+ if (d < dmin || (d == dmin && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
+ dmin = d;
+ mx = x;
+ my = y;
+ }
+ }
+ }
+
+ range = range >> 1;
+
+ x1 = mx - range;
+ if (x1 < xmin)
+ x1 = xmin;
+
+ x2 = mx + range;
+ if (x2 > xmax)
+ x2 = xmax;
+
+ y1 = my - range;
+ if (y1 < ymin)
+ y1 = ymin;
+
+ y2 = my + range;
+ if (y2 > ymax)
+ y2 = ymax;
+
+ } while (range >= 1);
+
+#ifdef DEBUG
+ av_log(s->avctx, AV_LOG_DEBUG, "log - MX: %d\tMY: %d\n", mx, my);
+#endif
+ *mx_ptr = mx;
+ *my_ptr = my;
+ return dmin;
+}
+
+static int phods_motion_search(MpegEncContext * s,
+ int *mx_ptr, int *my_ptr, int range,
+ int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
+{
+ int x1, y1, x2, y2, xx, yy, x, y, lastx, d;
+ int mx, my, dminx, dminy;
+ uint8_t *pix;
+
+ xx = s->mb_x << 4;
+ yy = s->mb_y << 4;
+
+ /* Left limit */
+ x1 = xx - range;
+ if (x1 < xmin)
+ x1 = xmin;
+
+ /* Right limit */
+ x2 = xx + range;
+ if (x2 > xmax)
+ x2 = xmax;
+
+ /* Upper limit */
+ y1 = yy - range;
+ if (y1 < ymin)
+ y1 = ymin;
+
+ /* Lower limit */
+ y2 = yy + range;
+ if (y2 > ymax)
+ y2 = ymax;
+
+ pix = s->new_picture.data[0] + (yy * s->linesize) + xx;
+ mx = 0;
+ my = 0;
+
+ x = xx;
+ y = yy;
+ do {
+ dminx = 0x7fffffff;
+ dminy = 0x7fffffff;
+
+ lastx = x;
+ for (x = x1; x <= x2; x += range) {
+ d = s->dsp.pix_abs[0][0](NULL, pix, ref_picture + (y * s->linesize) + x, s->linesize, 16);
+ if (d < dminx || (d == dminx && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
+ dminx = d;
+ mx = x;
+ }
+ }
+
+ x = lastx;
+ for (y = y1; y <= y2; y += range) {
+ d = s->dsp.pix_abs[0][0](NULL, pix, ref_picture + (y * s->linesize) + x, s->linesize, 16);
+ if (d < dminy || (d == dminy && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
+ dminy = d;
+ my = y;
+ }
+ }
+
+ range = range >> 1;
+
+ x = mx;
+ y = my;
+ x1 = mx - range;
+ if (x1 < xmin)
+ x1 = xmin;
+
+ x2 = mx + range;
+ if (x2 > xmax)
+ x2 = xmax;
+
+ y1 = my - range;
+ if (y1 < ymin)
+ y1 = ymin;
+
+ y2 = my + range;
+ if (y2 > ymax)
+ y2 = ymax;
+
+ } while (range >= 1);
+
+#ifdef DEBUG
+ av_log(s->avctx, AV_LOG_DEBUG, "phods - MX: %d\tMY: %d\n", mx, my);
+#endif
+
+ /* half pixel search */
+ *mx_ptr = mx;
+ *my_ptr = my;
+ return dminy;
+}
+#endif /* 0 */
+
+#define Z_THRESHOLD 256
+
+#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 inline 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
+
+ assert(flags == 0);
+
+ if(c->skip){
+// printf("S");
+ *mx_ptr = 0;
+ *my_ptr = 0;
+ return dmin;
+ }
+// printf("N");
+
+ 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<<ME_MAP_SHIFT) + mx;
+ const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)];
+ const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)];
+ const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)];
+ const int b= score_map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)];
+ mx<<=1;
+ my<<=1;
+
+
+ pen_x= pred_x + mx;
+ pen_y= pred_y + my;
+
+ ptr-= stride;
+ if(t<=b){
+ CHECK_SAD_HALF_MV(y2 , 0, -1)
+ if(l<=r){
+ CHECK_SAD_HALF_MV(xy2, -1, -1)
+ if(t+r<=b+l){
+ CHECK_SAD_HALF_MV(xy2, +1, -1)
+ ptr+= stride;
+ }else{
+ ptr+= stride;
+ CHECK_SAD_HALF_MV(xy2, -1, +1)
+ }
+ CHECK_SAD_HALF_MV(x2 , -1, 0)
+ }else{
+ CHECK_SAD_HALF_MV(xy2, +1, -1)
+ if(t+l<=b+r){
+ CHECK_SAD_HALF_MV(xy2, -1, -1)
+ ptr+= stride;
+ }else{
+ ptr+= stride;
+ CHECK_SAD_HALF_MV(xy2, +1, +1)
+ }
+ CHECK_SAD_HALF_MV(x2 , +1, 0)
+ }
+ }else{
+ if(l<=r){
+ if(t+l<=b+r){
+ CHECK_SAD_HALF_MV(xy2, -1, -1)
+ ptr+= stride;
+ }else{
+ ptr+= stride;
+ CHECK_SAD_HALF_MV(xy2, +1, +1)
+ }
+ CHECK_SAD_HALF_MV(x2 , -1, 0)
+ CHECK_SAD_HALF_MV(xy2, -1, +1)
+ }else{
+ if(t+r<=b+l){
+ CHECK_SAD_HALF_MV(xy2, +1, -1)
+ ptr+= stride;
+ }else{
+ ptr+= stride;
+ CHECK_SAD_HALF_MV(xy2, -1, +1)
+ }
+ CHECK_SAD_HALF_MV(x2 , +1, 0)
+ CHECK_SAD_HALF_MV(xy2, +1, +1)
+ }
+ CHECK_SAD_HALF_MV(y2 , 0, +1)
+ }
+ mx+=dx;
+ my+=dy;
+
+ }else{
+ mx<<=1;
+ my<<=1;
+ }
+
+ *mx_ptr = mx;
+ *my_ptr = my;
+ return dminh;
+}
+
+static inline void set_p_mv_tables(MpegEncContext * s, int mx, int my, int mv4)
+{
+ const int xy= s->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;
+/*
+ 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->mb_width *16;
+ c->ymax = - y + s->mb_height*16;
+ } 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;
+ }
+}
+
+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;
+ int same=1;
+ const int stride= c->stride;
+ uint8_t *mv_penalty= c->current_mv_penalty;
+
+ 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];
+
+ 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<<shift)) P_LEFT[0] = (c->xmax<<shift);
+
+ /* special case for first line */
+ if (s->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<<shift)) P_TOP[1] = (c->ymax<<shift);
+ if(P_TOPRIGHT[0] < (c->xmin<<shift)) P_TOPRIGHT[0]= (c->xmin<<shift);
+ if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<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= pred_x4 = P_MEDIAN[0];
+ c->pred_y= pred_y4 = P_MEDIAN[1];
+ }
+ P_MV1[0]= mx;
+ P_MV1[1]= my;
+
+ dmin4 = epzs_motion_search4(s, &mx4, &my4, P, block, block, s->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->dsp.put_no_rnd_pixels_tab[1][dxy](dest_y , ref , stride, h);
+ else
+ s->dsp.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.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->dsp.put_no_rnd_pixels_tab[1][dxy](c->scratchpad , s->last_picture.data[1] + offset, s->uvlinesize, 8);
+ s->dsp.put_no_rnd_pixels_tab[1][dxy](c->scratchpad+8 , s->last_picture.data[2] + offset, s->uvlinesize, 8);
+ }else{
+ s->dsp.put_pixels_tab [1][dxy](c->scratchpad , s->last_picture.data[1] + offset, s->uvlinesize, 8);
+ s->dsp.put_pixels_tab [1][dxy](c->scratchpad+8 , s->last_picture.data[2] + offset, s->uvlinesize, 8);
+ }
+
+ dmin_sum += s->dsp.mb_cmp[1](s, s->new_picture.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.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){
+ assert(field_select==0 || field_select==1);
+ assert(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->dsp.put_no_rnd_pixels_tab[size][dxy](c->scratchpad, ref , stride, h);
+ }else{
+ s->dsp.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 void clip_input_mv(MpegEncContext * s, int16_t *mv, int interlaced){
+ int ymax= s->me.ymax>>interlaced;
+ int ymin= s->me.ymin>>interlaced;
+
+ if(mv[0] < s->me.xmin) mv[0] = s->me.xmin;
+ if(mv[0] > s->me.xmax) mv[0] = s->me.xmax;
+ if(mv[1] < ymin) mv[1] = ymin;
+ if(mv[1] > ymax) mv[1] = ymax;
+}
+
+static inline int check_input_motion(MpegEncContext * s, int mb_x, int mb_y, int p_type){
+ MotionEstContext * const c= &s->me;
+ Picture *p= s->current_picture_ptr;
+ int mb_xy= mb_x + mb_y*s->mb_stride;
+ int xy= 2*mb_x + 2*mb_y*s->b8_stride;
+ int mb_type= s->current_picture.mb_type[mb_xy];
+ int flags= c->flags;
+ int shift= (flags&FLAG_QPEL) + 1;
+ int mask= (1<<shift)-1;
+ int x, y, i;
+ int d=0;
+ me_cmp_func cmpf= s->dsp.sse[0];
+ me_cmp_func chroma_cmpf= s->dsp.sse[1];
+
+ if(p_type && USES_LIST(mb_type, 1)){
+ av_log(c->avctx, AV_LOG_ERROR, "backward motion vector in P frame\n");
+ return INT_MAX/2;
+ }
+ assert(IS_INTRA(mb_type) || USES_LIST(mb_type,0) || USES_LIST(mb_type,1));
+
+ for(i=0; i<4; i++){
+ int xy= s->block_index[i];
+ clip_input_mv(s, p->motion_val[0][xy], !!IS_INTERLACED(mb_type));
+ clip_input_mv(s, p->motion_val[1][xy], !!IS_INTERLACED(mb_type));
+ }
+
+ if(IS_INTERLACED(mb_type)){
+ int xy2= xy + s->b8_stride;
+ s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTRA;
+ c->stride<<=1;
+ c->uvstride<<=1;
+
+ if(!(s->flags & CODEC_FLAG_INTERLACED_ME)){
+ av_log(c->avctx, AV_LOG_ERROR, "Interlaced macroblock selected but interlaced motion estimation disabled\n");
+ return INT_MAX/2;
+ }
+
+ if(USES_LIST(mb_type, 0)){
+ int field_select0= p->ref_index[0][xy ];
+ int field_select1= p->ref_index[0][xy2];
+ assert(field_select0==0 ||field_select0==1);
+ assert(field_select1==0 ||field_select1==1);
+ init_interlaced_ref(s, 0);
+
+ if(p_type){
+ s->p_field_select_table[0][mb_xy]= field_select0;
+ s->p_field_select_table[1][mb_xy]= field_select1;
+ *(uint32_t*)s->p_field_mv_table[0][field_select0][mb_xy]= *(uint32_t*)p->motion_val[0][xy ];
+ *(uint32_t*)s->p_field_mv_table[1][field_select1][mb_xy]= *(uint32_t*)p->motion_val[0][xy2];
+ s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTER_I;
+ }else{
+ s->b_field_select_table[0][0][mb_xy]= field_select0;
+ s->b_field_select_table[0][1][mb_xy]= field_select1;
+ *(uint32_t*)s->b_field_mv_table[0][0][field_select0][mb_xy]= *(uint32_t*)p->motion_val[0][xy ];
+ *(uint32_t*)s->b_field_mv_table[0][1][field_select1][mb_xy]= *(uint32_t*)p->motion_val[0][xy2];
+ s->mb_type[mb_xy]= CANDIDATE_MB_TYPE_FORWARD_I;
+ }
+
+ x= p->motion_val[0][xy ][0];
+ y= p->motion_val[0][xy ][1];
+ d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select0, 0, cmpf, chroma_cmpf, flags);
+ x= p->motion_val[0][xy2][0];
+ y= p->motion_val[0][xy2][1];
+ d+= cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select1, 1, cmpf, chroma_cmpf, flags);
+ }
+ if(USES_LIST(mb_type, 1)){
+ int field_select0= p->ref_index[1][xy ];
+ int field_select1= p->ref_index[1][xy2];
+ assert(field_select0==0 ||field_select0==1);
+ assert(field_select1==0 ||field_select1==1);
+ init_interlaced_ref(s, 2);
+
+ s->b_field_select_table[1][0][mb_xy]= field_select0;
+ s->b_field_select_table[1][1][mb_xy]= field_select1;
+ *(uint32_t*)s->b_field_mv_table[1][0][field_select0][mb_xy]= *(uint32_t*)p->motion_val[1][xy ];
+ *(uint32_t*)s->b_field_mv_table[1][1][field_select1][mb_xy]= *(uint32_t*)p->motion_val[1][xy2];
+ if(USES_LIST(mb_type, 0)){
+ s->mb_type[mb_xy]= CANDIDATE_MB_TYPE_BIDIR_I;
+ }else{
+ s->mb_type[mb_xy]= CANDIDATE_MB_TYPE_BACKWARD_I;
+ }
+
+ x= p->motion_val[1][xy ][0];
+ y= p->motion_val[1][xy ][1];
+ d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select0+2, 0, cmpf, chroma_cmpf, flags);
+ x= p->motion_val[1][xy2][0];
+ y= p->motion_val[1][xy2][1];
+ d+= cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select1+2, 1, cmpf, chroma_cmpf, flags);
+ //FIXME bidir scores
+ }
+ c->stride>>=1;
+ c->uvstride>>=1;
+ }else if(IS_8X8(mb_type)){
+ if(!(s->flags & CODEC_FLAG_4MV)){
+ av_log(c->avctx, AV_LOG_ERROR, "4MV macroblock selected but 4MV encoding disabled\n");
+ return INT_MAX/2;
+ }
+ cmpf= s->dsp.sse[1];
+ chroma_cmpf= s->dsp.sse[1];
+ init_mv4_ref(c);
+ for(i=0; i<4; i++){
+ xy= s->block_index[i];
+ x= p->motion_val[0][xy][0];
+ y= p->motion_val[0][xy][1];
+ d+= cmp(s, x>>shift, y>>shift, x&mask, y&mask, 1, 8, i, i, cmpf, chroma_cmpf, flags);
+ }
+ s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTER4V;
+ }else{
+ if(USES_LIST(mb_type, 0)){
+ if(p_type){
+ *(uint32_t*)s->p_mv_table[mb_xy]= *(uint32_t*)p->motion_val[0][xy];
+ s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTER;
+ }else if(USES_LIST(mb_type, 1)){
+ *(uint32_t*)s->b_bidir_forw_mv_table[mb_xy]= *(uint32_t*)p->motion_val[0][xy];
+ *(uint32_t*)s->b_bidir_back_mv_table[mb_xy]= *(uint32_t*)p->motion_val[1][xy];
+ s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_BIDIR;
+ }else{
+ *(uint32_t*)s->b_forw_mv_table[mb_xy]= *(uint32_t*)p->motion_val[0][xy];
+ s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_FORWARD;
+ }
+ x= p->motion_val[0][xy][0];
+ y= p->motion_val[0][xy][1];
+ d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 16, 0, 0, cmpf, chroma_cmpf, flags);
+ }else if(USES_LIST(mb_type, 1)){
+ *(uint32_t*)s->b_back_mv_table[mb_xy]= *(uint32_t*)p->motion_val[1][xy];
+ s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_BACKWARD;
+
+ x= p->motion_val[1][xy][0];
+ y= p->motion_val[1][xy][1];
+ d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 16, 2, 0, cmpf, chroma_cmpf, flags);
+ }else
+ s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTRA;
+ }
+ return d;
+}
+
+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, varc, vard, mx, my, dmin;
+ 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.data, s->last_picture.data, NULL, 16*mb_x, 16*mb_y, 0);
+
+ assert(s->quarter_sample==0 || s->quarter_sample==1);
+ assert(s->linesize == c->stride);
+ assert(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;
+
+ if(c->avctx->me_threshold){
+ vard= check_input_motion(s, mb_x, mb_y, 1);
+
+ if((vard+128)>>8 < c->avctx->me_threshold){
+ int p_score= FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100);
+ int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20;
+ pic->mc_mb_var[s->mb_stride * mb_y + mb_x] = (vard+128)>>8;
+ c->mc_mb_var_sum_temp += (vard+128)>>8;
+ c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score);
+ return;
+ }
+ if((vard+128)>>8 < c->avctx->mb_threshold)
+ mb_type= s->mb_type[mb_x + mb_y*s->mb_stride];
+ }
+
+ switch(s->me_method) {
+ case ME_ZERO:
+ default:
+ no_motion_search(s, &mx, &my);
+ mx-= mb_x*16;
+ my-= mb_y*16;
+ dmin = 0;
+ break;
+#if 0
+ case ME_FULL:
+ dmin = full_motion_search(s, &mx, &my, range, ref_picture);
+ mx-= mb_x*16;
+ my-= mb_y*16;
+ break;
+ case ME_LOG:
+ dmin = log_motion_search(s, &mx, &my, range / 2, ref_picture);
+ mx-= mb_x*16;
+ my-= mb_y*16;
+ break;
+ case ME_PHODS:
+ dmin = phods_motion_search(s, &mx, &my, range / 2, ref_picture);
+ mx-= mb_x*16;
+ my-= mb_y*16;
+ break;
+#endif
+ 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<<shift)) P_LEFT[0] = (c->xmax<<shift);
+
+ if(!s->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<<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]);
+
+ if(s->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;
+// pic->mb_cmp_score[s->mb_stride * mb_y + mb_x] = dmin;
+ c->mc_mb_var_sum_temp += (vard+128)>>8;
+
+#if 0
+ printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n",
+ varc, s->avg_mb_var, sum, vard, mx - xx, my - yy);
+#endif
+ 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= ff_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;
+ }
+ }
+
+// pic->mb_cmp_score[s->mb_stride * mb_y + mb_x] = dmin;
+ 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{
+ int 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);
+ }
+#if 0 //FIXME
+ /* get chroma score */
+ if(c->avctx->mb_cmp&FF_CMP_CHROMA){
+ for(i=1; i<3; i++){
+ uint8_t *dest_c;
+ int mean;
+
+ if(s->out_format == FMT_H263){
+ mean= (s->dc_val[i][mb_x + mb_y*s->b8_stride] + 4)>>3; //FIXME not exact but simple ;)
+ }else{
+ mean= (s->last_dc[i] + 4)>>3;
+ }
+ dest_c = s->new_picture.data[i] + (mb_y * 8 * (s->uvlinesize)) + mb_x * 8;
+
+ mean*= 0x01010101;
+ for(i=0; i<8; i++){
+ *(uint32_t*)(&c->scratchpad[i*s->uvlinesize+ 0]) = mean;
+ *(uint32_t*)(&c->scratchpad[i*s->uvlinesize+ 4]) = mean;
+ }
+
+ intra_score+= s->dsp.mb_cmp[1](s, c->scratchpad, dest_c, s->uvlinesize);
+ }
+ }
+#endif
+ 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.data, s->last_picture.data, NULL, 16*mb_x, 16*mb_y, 0);
+
+ assert(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<<shift)) P_LEFT[0] = (c->xmin<<shift);
+
+ /* special case for first line */
+ if (s->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<<shift)) P_TOP[1] = (c->ymin<<shift);
+ if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift);
+ if(P_TOPRIGHT[1] < (c->ymin<<shift)) P_TOPRIGHT[1]= (c->ymin<<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_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<<shift;
+ s->p_mv_table[xy][1] = my<<shift;
+
+ return dmin;
+}
+
+static int ff_estimate_motion_b(MpegEncContext * s,
+ int mb_x, int mb_y, int16_t (*mv_table)[2], int ref_index, int f_code)
+{
+ MotionEstContext * const c= &s->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:
+ no_motion_search(s, &mx, &my);
+ dmin = 0;
+ mx-= mb_x*16;
+ my-= mb_y*16;
+ break;
+#if 0
+ case ME_FULL:
+ dmin = full_motion_search(s, &mx, &my, range, ref_picture);
+ mx-= mb_x*16;
+ my-= mb_y*16;
+ break;
+ case ME_LOG:
+ dmin = log_motion_search(s, &mx, &my, range / 2, ref_picture);
+ mx-= mb_x*16;
+ my-= mb_y*16;
+ break;
+ case ME_PHODS:
+ dmin = phods_motion_search(s, &mx, &my, range / 2, ref_picture);
+ mx-= mb_x*16;
+ my-= mb_y*16;
+ break;
+#endif
+ 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<<shift);
+ }else{
+ mv_scale= ((s->pb_time - s->pp_time)<<16) / (s->pp_time<<shift);
+ }
+
+ dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, ref_index, s->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= ff_get_mb_score(s, mx, my, 0, ref_index, 0, 16, 1);
+
+//printf("%d %d %d %d//", s->mb_x, s->mb_y, mx, my);
+// 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->dsp.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->dsp.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<<shift;
+ const int ymin= c->ymin<<shift;
+ const int xmax= c->xmax<<shift;
+ const int ymax= c->ymax<<shift;
+ uint8_t map[8][8][8][8];
+
+ memset(map,0,sizeof(map));
+#define BIDIR_MAP(fx,fy,bx,by) \
+ map[(motion_fx+fx)&7][(motion_fy+fy)&7][(motion_bx+bx)&7][(motion_by+by)&7]
+ BIDIR_MAP(0,0,0,0) = 1;
+
+ fbmin= check_bidir_mv(s, motion_fx, motion_fy,
+ motion_bx, motion_by,
+ pred_fx, pred_fy,
+ pred_bx, pred_by,
+ 0, 16);
+
+ if(s->avctx->bidir_refine){
+ int score, end;
+#define CHECK_BIDIR(fx,fy,bx,by)\
+ if( !BIDIR_MAP(fx,fy,bx,by)\
+ &&(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)){\
+ BIDIR_MAP(fx,fy,bx,by) = 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){\
+ 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))
+
+#define CHECK_BIDIRR(a,b,c,d)\
+CHECK_BIDIR2(a,b,c,d)\
+CHECK_BIDIR2(b,c,d,a)\
+CHECK_BIDIR2(c,d,a,b)\
+CHECK_BIDIR2(d,a,b,c)
+
+ do{
+ end=1;
+
+ CHECK_BIDIRR( 0, 0, 0, 1)
+ if(s->avctx->bidir_refine > 1){
+ CHECK_BIDIRR( 0, 0, 1, 1)
+ CHECK_BIDIR2( 0, 1, 0, 1)
+ CHECK_BIDIR2( 1, 0, 1, 0)
+ CHECK_BIDIRR( 0, 0,-1, 1)
+ CHECK_BIDIR2( 0,-1, 0, 1)
+ CHECK_BIDIR2(-1, 0, 1, 0)
+ if(s->avctx->bidir_refine > 2){
+ CHECK_BIDIRR( 0, 1, 1, 1)
+ CHECK_BIDIRR( 0,-1, 1, 1)
+ CHECK_BIDIRR( 0, 1,-1, 1)
+ CHECK_BIDIRR( 0, 1, 1,-1)
+ if(s->avctx->bidir_refine > 3){
+ CHECK_BIDIR2( 1, 1, 1, 1)
+ CHECK_BIDIRR( 1, 1, 1,-1)
+ CHECK_BIDIR2( 1, 1,-1,-1)
+ CHECK_BIDIR2( 1,-1,-1, 1)
+ CHECK_BIDIR2( 1,-1, 1,-1)
+ }
+ }
+ }
+ }while(!end);
+ }
+
+ s->b_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;
+ }
+
+ assert(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] = clip(mv_table[mot_xy - 1][0], xmin<<shift, xmax<<shift);
+ P_LEFT[1] = clip(mv_table[mot_xy - 1][1], ymin<<shift, ymax<<shift);
+
+ /* special case for first line */
+ if (!s->first_slice_line) { //FIXME maybe allow this over thread boundary as its cliped
+ P_TOP[0] = clip(mv_table[mot_xy - mot_stride ][0], xmin<<shift, xmax<<shift);
+ P_TOP[1] = clip(mv_table[mot_xy - mot_stride ][1], ymin<<shift, ymax<<shift);
+ P_TOPRIGHT[0] = clip(mv_table[mot_xy - mot_stride + 1 ][0], xmin<<shift, xmax<<shift);
+ P_TOPRIGHT[1] = clip(mv_table[mot_xy - mot_stride + 1 ][1], ymin<<shift, 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]);
+ }
+
+ dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, mv_table, 1<<(16-shift), 0, 16);
+ if(c->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= ff_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
+
+ s->b_direct_mv_table[mot_xy][0]= mx;
+ s->b_direct_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.data, s->last_picture.data, s->next_picture.data, 16*mb_x, 16*mb_y, 2);
+
+ get_limits(s, 16*mb_x, 16*mb_y);
+
+ c->skip=0;
+ if(c->avctx->me_threshold){
+ int vard= check_input_motion(s, mb_x, mb_y, 0);
+
+ if((vard+128)>>8 < c->avctx->me_threshold){
+// 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_var [s->mb_stride * mb_y + mb_x] = (varc+128)>>8;
+ s->current_picture.mc_mb_var[s->mb_stride * mb_y + mb_x] = (vard+128)>>8;
+/* pic->mb_mean [s->mb_stride * mb_y + mb_x] = (sum+128)>>8;
+ c->mb_var_sum_temp += (varc+128)>>8;*/
+ c->mc_mb_var_sum_temp += (vard+128)>>8;
+/* if (vard <= 64<<8 || vard < varc) {
+ c->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
+ }else{
+ c->scene_change_score+= s->qscale * s->avctx->scenechange_factor;
+ }*/
+ return;
+ }
+ if((vard+128)>>8 < c->avctx->mb_threshold){
+ type= s->mb_type[mb_y*s->mb_stride + mb_x];
+ if(type == CANDIDATE_MB_TYPE_DIRECT){
+ direct_search(s, mb_x, mb_y);
+ }
+ if(type == CANDIDATE_MB_TYPE_FORWARD || type == CANDIDATE_MB_TYPE_BIDIR){
+ c->skip=0;
+ ff_estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, 0, s->f_code);
+ }
+ if(type == CANDIDATE_MB_TYPE_BACKWARD || type == CANDIDATE_MB_TYPE_BIDIR){
+ c->skip=0;
+ ff_estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, 2, s->b_code);
+ }
+ if(type == CANDIDATE_MB_TYPE_FORWARD_I || type == CANDIDATE_MB_TYPE_BIDIR_I){
+ c->skip=0;
+ c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_MV;
+ 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], 1);
+ }
+ if(type == CANDIDATE_MB_TYPE_BACKWARD_I || type == CANDIDATE_MB_TYPE_BIDIR_I){
+ c->skip=0;
+ c->current_mv_penalty= c->mv_penalty[s->b_code] + MAX_MV;
+ 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], 1);
+ }
+ return;
+ }
+ }
+
+ if (s->codec_id == 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;
+//printf(" %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;
+//printf("%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<score){
+ score=bmin;
+ type= CANDIDATE_MB_TYPE_BACKWARD;
+ }
+ if(fbmin<score){
+ score=fbmin;
+ type= CANDIDATE_MB_TYPE_BIDIR;
+ }
+ if(fimin<score){
+ score=fimin;
+ type= CANDIDATE_MB_TYPE_FORWARD_I;
+ }
+ if(bimin<score){
+ score=bimin;
+ type= CANDIDATE_MB_TYPE_BACKWARD_I;
+ }
+
+ 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
+ }
+
+ 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; //dont try direct mode if its invalid for this MB
+#if 0
+ if(s->out_format == FMT_MPEG1)
+ type |= CANDIDATE_MB_TYPE_INTRA;
+#endif
+ }
+
+ 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 == 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; y<s->mb_height; y++){
+ int x;
+ int xy= y*s->mb_stride;
+ for(x=0; x<s->mb_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; j<fcode && j<8; j++){
+ if(s->pict_type==B_TYPE || 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;
+ }
+// printf("%d %d\n", i, score[i]);
+ }
+
+// printf("fcode: %d type: %d\n", i, s->pict_type);
+ return best_fcode;
+/* for(i=0; i<=MAX_FCODE; i++){
+ printf("%d ", mv_num[i]);
+ }
+ printf("\n");*/
+ }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;
+ assert(s->pict_type==P_TYPE);
+
+ range = (((s->out_format == FMT_MPEG1 || s->msmpeg4_version) ? 8 : 16) << f_code);
+
+ assert(range <= 16 || !s->msmpeg4_version);
+ assert(range <=256 || !(s->codec_id == 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;
+
+//printf("%d no:%d %d//\n", clip, noclip, f_code);
+ if(s->flags&CODEC_FLAG_4MV){
+ const int wrap= s->b8_stride;
+
+ /* clip / convert to intra 8x8 type MVs */
+ for(y=0; y<s->mb_height; y++){
+ int xy= y*2*wrap;
+ int i= y*s->mb_stride;
+ int x;
+
+ for(x=0; x<s->mb_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; y<s->mb_height; y++){
+ int x;
+ int xy= y*s->mb_stride;
+ for(x=0; x<s->mb_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/contrib/ffmpeg/libavcodec/motion_est_template.c b/contrib/ffmpeg/libavcodec/motion_est_template.c
new file mode 100644
index 000000000..193a8b24e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/motion_est_template.c
@@ -0,0 +1,1166 @@
+/*
+ * 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_est_template.c
+ * Motion estimation template.
+ */
+
+//lets hope gcc will remove the unused vars ...(gcc 3.2.2 seems to do it ...)
+#define LOAD_COMMON\
+ uint32_t attribute_unused * const score_map= c->score_map;\
+ const int attribute_unused xmin= c->xmin;\
+ const int attribute_unused ymin= c->ymin;\
+ const int attribute_unused xmax= c->xmax;\
+ const int attribute_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(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)\
+}
+
+#if 0
+static int hpel_motion_search)(MpegEncContext * s,
+ int *mx_ptr, int *my_ptr, int dmin,
+ uint8_t *ref_data[3],
+ int size)
+{
+ const int xx = 16 * s->mb_x + 8*(n&1);
+ const int yy = 16 * s->mb_y + 8*(n>>1);
+ const int mx = *mx_ptr;
+ const int my = *my_ptr;
+ const int penalty_factor= c->sub_penalty_factor;
+
+ LOAD_COMMON
+
+ // INIT;
+ //FIXME factorize
+ me_cmp_func cmp, chroma_cmp, cmp_sub, chroma_cmp_sub;
+
+ if(s->no_rounding /*FIXME b_type*/){
+ hpel_put= &s->dsp.put_no_rnd_pixels_tab[size];
+ chroma_hpel_put= &s->dsp.put_no_rnd_pixels_tab[size+1];
+ }else{
+ hpel_put=& s->dsp.put_pixels_tab[size];
+ chroma_hpel_put= &s->dsp.put_pixels_tab[size+1];
+ }
+ cmpf= s->dsp.me_cmp[size];
+ chroma_cmpf= s->dsp.me_cmp[size+1];
+ 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){
+ CMP_HPEL(dmin, 0, 0, mx, my, size);
+ if(mx || my)
+ 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 bx=2*mx, by=2*my;
+ int d= dmin;
+
+ CHECK_HALF_MV(1, 1, mx-1, my-1)
+ CHECK_HALF_MV(0, 1, mx , my-1)
+ CHECK_HALF_MV(1, 1, mx , my-1)
+ CHECK_HALF_MV(1, 0, mx-1, my )
+ CHECK_HALF_MV(1, 0, mx , my )
+ CHECK_HALF_MV(1, 1, mx-1, my )
+ CHECK_HALF_MV(0, 1, mx , my )
+ CHECK_HALF_MV(1, 1, mx , my )
+
+ assert(bx >= xmin*2 || bx <= xmax*2 || by >= ymin*2 || by <= ymax*2);
+
+ *mx_ptr = bx;
+ *my_ptr = by;
+ }else{
+ *mx_ptr =2*mx;
+ *my_ptr =2*my;
+ }
+
+ return dmin;
+}
+
+#else
+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<<ME_MAP_SHIFT) + mx;
+ const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)]
+ + (mv_penalty[bx - pred_x] + mv_penalty[by-2 - pred_y])*c->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<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)]
+ + (mv_penalty[bx - pred_x] + mv_penalty[by+2 - pred_y])*c->penalty_factor;
+
+#if 1
+ int key;
+ int map_generation= c->map_generation;
+#ifndef NDEBUG
+ uint32_t *map= c->map;
+#endif
+ key= ((my-1)<<ME_MAP_MV_BITS) + (mx) + map_generation;
+ assert(map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
+ key= ((my+1)<<ME_MAP_MV_BITS) + (mx) + map_generation;
+ assert(map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
+ key= ((my)<<ME_MAP_MV_BITS) + (mx+1) + map_generation;
+ assert(map[(index+1)&(ME_MAP_SIZE-1)] == key);
+ key= ((my)<<ME_MAP_MV_BITS) + (mx-1) + map_generation;
+ assert(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)
+ }
+ assert(bx >= xmin*2 && bx <= xmax*2 && by >= ymin*2 && by <= ymax*2);
+ }
+
+ *mx_ptr = bx;
+ *my_ptr = by;
+
+ return dmin;
+}
+#endif
+
+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;
+}
+
+inline int ff_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];
+
+// assert(!c->skip);
+// assert(c->avctx->me_sub_cmp != c->avctx->mb_cmp);
+
+ 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;
+}
+
+#define CHECK_QUARTER_MV(dx, dy, x, y)\
+{\
+ const int hx= 4*(x)+(dx);\
+ const int hy= 4*(y)+(dy);\
+ d= cmp(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 int 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_MAP_SHIFT) + mx;
+ const int t= score_map[(index-(1<<ME_MAP_SHIFT) )&(ME_MAP_SIZE-1)];
+ const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)];
+ const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)];
+ const int b= score_map[(index+(1<<ME_MAP_SHIFT) )&(ME_MAP_SIZE-1)];
+ const int c= score_map[(index )&(ME_MAP_SIZE-1)];
+ int best[8];
+ int best_pos[8][2];
+
+ memset(best, 64, sizeof(int)*8);
+#if 1
+ if(s->me.dia_size>=2){
+ const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
+ const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
+ const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
+ const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
+
+ for(ny= -3; ny <= 3; ny++){
+ for(nx= -3; nx <= 3; nx++){
+ //FIXME this could overflow (unlikely though)
+ const int64_t t2= nx*nx*(tr + tl - 2*t) + 4*nx*(tr-tl) + 32*t;
+ const int64_t c2= nx*nx*( r + l - 2*c) + 4*nx*( r- l) + 32*c;
+ const int64_t b2= nx*nx*(br + bl - 2*b) + 4*nx*(br-bl) + 32*b;
+ int score= (ny*ny*(b2 + t2 - 2*c2) + 4*ny*(b2 - t2) + 32*c2 + 512)>>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<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)] == (my<<ME_MAP_MV_BITS) + mx + map_generation && 0){ //FIXME
+ tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
+ }else{
+ tl= cmp(s, mx-1, my-1, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);//FIXME wrong if chroma me is different
+ }
+
+ cxy= 2*tl + (cx + cy)/4 - (cx2 + cy2) - 2*c;
+
+ assert(16*cx2 + 4*cx + 32*c == 32*r);
+ assert(16*cx2 - 4*cx + 32*c == 32*l);
+ assert(16*cy2 + 4*cy + 32*c == 32*b);
+ assert(16*cy2 - 4*cy + 32*c == 32*t);
+ assert(16*cxy + 16*cy2 + 16*cx2 - 4*cy - 4*cx + 32*c == 32*tl);
+
+ for(ny= -3; ny <= 3; ny++){
+ for(nx= -3; nx <= 3; nx++){
+ //FIXME this could overflow (unlikely though)
+ int score= ny*nx*cxy + nx*nx*cx2 + ny*ny*cy2 + nx*cx + ny*cy + 32*c; //FIXME factor
+ int i;
+
+ if((nx&3)==0 && (ny&3)==0) continue;
+
+ score += 32*(mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;
+// if(nx&1) score-=32*c->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<subpel_quality; i++){
+ nx= best_pos[i][0];
+ ny= best_pos[i][1];
+ CHECK_QUARTER_MV(nx&3, ny&3, nx>>2, ny>>2)
+ }
+
+#if 0
+ const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
+ const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
+ const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
+ const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
+// if(l < r && l < t && l < b && l < tl && l < bl && l < tr && l < br && bl < tl){
+ if(tl<br){
+
+// nx= FFMAX(4*mx - bx, bx - 4*mx);
+// ny= FFMAX(4*my - by, by - 4*my);
+
+ static int stats[7][7], count;
+ count++;
+ stats[4*mx - bx + 3][4*my - by + 3]++;
+ if(256*256*256*64 % count ==0){
+ for(i=0; i<49; i++){
+ if((i%7)==0) printf("\n");
+ printf("%6d ", stats[0][i]);
+ }
+ printf("\n");
+ }
+ }
+#endif
+#else
+
+ CHECK_QUARTER_MV(2, 2, mx-1, my-1)
+ CHECK_QUARTER_MV(0, 2, mx , my-1)
+ CHECK_QUARTER_MV(2, 2, mx , my-1)
+ CHECK_QUARTER_MV(2, 0, mx , my )
+ CHECK_QUARTER_MV(2, 2, mx , my )
+ CHECK_QUARTER_MV(0, 2, mx , my )
+ CHECK_QUARTER_MV(2, 2, mx-1, my )
+ CHECK_QUARTER_MV(2, 0, mx-1, my )
+
+ nx= bx;
+ ny= by;
+
+ for(i=0; i<8; i++){
+ int ox[8]= {0, 1, 1, 1, 0,-1,-1,-1};
+ int oy[8]= {1, 1, 0,-1,-1,-1, 0, 1};
+ CHECK_QUARTER_MV((nx + ox[i])&3, (ny + oy[i])&3, (nx + ox[i])>>2, (ny + oy[i])>>2)
+ }
+#endif
+#if 0
+ //outer ring
+ CHECK_QUARTER_MV(1, 3, mx-1, my-1)
+ CHECK_QUARTER_MV(1, 2, mx-1, my-1)
+ CHECK_QUARTER_MV(1, 1, mx-1, my-1)
+ CHECK_QUARTER_MV(2, 1, mx-1, my-1)
+ CHECK_QUARTER_MV(3, 1, mx-1, my-1)
+ CHECK_QUARTER_MV(0, 1, mx , my-1)
+ CHECK_QUARTER_MV(1, 1, mx , my-1)
+ CHECK_QUARTER_MV(2, 1, mx , my-1)
+ CHECK_QUARTER_MV(3, 1, mx , my-1)
+ CHECK_QUARTER_MV(3, 2, mx , my-1)
+ CHECK_QUARTER_MV(3, 3, mx , my-1)
+ CHECK_QUARTER_MV(3, 0, mx , my )
+ CHECK_QUARTER_MV(3, 1, mx , my )
+ CHECK_QUARTER_MV(3, 2, mx , my )
+ CHECK_QUARTER_MV(3, 3, mx , my )
+ CHECK_QUARTER_MV(2, 3, mx , my )
+ CHECK_QUARTER_MV(1, 3, mx , my )
+ CHECK_QUARTER_MV(0, 3, mx , my )
+ CHECK_QUARTER_MV(3, 3, mx-1, my )
+ CHECK_QUARTER_MV(2, 3, mx-1, my )
+ CHECK_QUARTER_MV(1, 3, mx-1, my )
+ CHECK_QUARTER_MV(1, 2, mx-1, my )
+ CHECK_QUARTER_MV(1, 1, mx-1, my )
+ CHECK_QUARTER_MV(1, 0, mx-1, my )
+#endif
+ assert(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 int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
+ const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
+ assert((x) >= xmin);\
+ assert((x) <= xmax);\
+ assert((y) >= ymin);\
+ assert((y) <= ymax);\
+/*printf("check_mv %d %d\n", x, y);*/\
+ 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)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\
+/*printf("score:%d\n", d);*/\
+ COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
+ }\
+}
+
+#define CHECK_CLIPED_MV(ax,ay)\
+{\
+ const int Lx= ax;\
+ const int Ly= ay;\
+ const int Lx2= FFMAX(xmin, FFMIN(Lx, xmax));\
+ const int Ly2= FFMAX(ymin, FFMIN(Ly, ymax));\
+ CHECK_MV(Lx2, Ly2)\
+}
+
+#define CHECK_MV_DIR(x,y,new_dir)\
+{\
+ const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
+ const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
+/*printf("check_mv_dir %d %d %d\n", x, y, new_dir);*/\
+ 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)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\
+/*printf("score:%d\n", d);*/\
+ if(d<dmin){\
+ best[0]=x;\
+ best[1]=y;\
+ dmin=d;\
+ next_dir= new_dir;\
+ }\
+ }\
+}
+
+#define check(x,y,S,v)\
+if( (x)<(xmin<<(S)) ) printf("%d %d %d %d %d xmin" #v, xmin, (x), (y), s->mb_x, s->mb_y);\
+if( (x)>(xmax<<(S)) ) printf("%d %d %d %d %d xmax" #v, xmax, (x), (y), s->mb_x, s->mb_y);\
+if( (y)<(ymin<<(S)) ) printf("%d %d %d %d %d ymin" #v, ymin, (x), (y), s->mb_x, s->mb_y);\
+if( (y)>(ymax<<(S)) ) printf("%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 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
+ int 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 int key= (best[1]<<ME_MAP_MV_BITS) + best[0] + map_generation;
+ const int index= ((best[1]<<ME_MAP_SHIFT) + best[0])&(ME_MAP_SIZE-1);
+ if(map[index]!=key){ //this will be executed only very rarey
+ score_map[index]= cmp(s, best[0], best[1], 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
+ map[index]= key;
+ }
+ }
+
+ for(;;){
+ int d;
+ const int dir= next_dir;
+ const int x= best[0];
+ const int y= best[1];
+ next_dir=-1;
+
+//printf("%d", dir);
+ if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y , 0)
+ if(dir!=3 && y>ymin) CHECK_MV_DIR(x , y-1, 1)
+ if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y , 2)
+ if(dir!=1 && y<ymax) CHECK_MV_DIR(x , y+1, 3)
+
+ if(next_dir==-1){
+ return dmin;
+ }
+ }
+}
+
+static int funny_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
+ int 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; dir<dia_size; dir+=2){
+ int d;
+
+ CHECK_MV(x + dir , y + dia_size - dir);
+ CHECK_MV(x + dia_size - dir, y - dir );
+ CHECK_MV(x - dir , y - dia_size + dir);
+ CHECK_MV(x - dia_size + dir, y + dir );
+ }
+
+ if(x!=best[0] || y!=best[1])
+ dia_size=0;
+#if 0
+{
+int dx, dy, i;
+static int stats[8*8];
+dx= FFABS(x-best[0]);
+dy= FFABS(y-best[1]);
+if(dy>dx){
+ dx^=dy; dy^=dx; dx^=dy;
+}
+stats[dy*8 + dx] ++;
+if(256*256*256*64 % (stats[0]+1)==0){
+ for(i=0; i<64; i++){
+ if((i&7)==0) printf("\n");
+ printf("%8d ", stats[i]);
+ }
+ printf("\n");
+}
+}
+#endif
+ }
+ 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
+ int map_generation= c->map_generation;
+ int x,y,x2,y2, i, j, d;
+ 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},};
+ static const int hex2[6][2]={{-2, 0}, { 2,0}, {-1,-2}, {1,-2}, {-1,2},{1,2}};
+
+ cmpf= s->dsp.me_cmp[size];
+ chroma_cmpf= s->dsp.me_cmp[size+1];
+
+ x= best[0];
+ y= best[1];
+ for(x2=FFMAX(x-15, xmin); x2<=FFMIN(x+15,xmax); x2+=2){
+ CHECK_MV(x2, y);
+ }
+ for(y2=FFMAX(y- 7, ymin); y2<=FFMIN(y+ 7,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<=4; j++){
+ for(i=0; i<16; i++){
+ CHECK_CLIPED_MV(x+hex[i][0]*j, y+hex[i][1]*j);
+ }
+ }
+
+ do{
+ x= best[0];
+ y= best[1];
+ for(i=0; i<6; i++){
+ CHECK_CLIPED_MV(x+hex2[i][0], y+hex2[i][1]);
+ }
+ }while(best[0] != x || best[1] != y);
+
+ do{
+ x= best[0];
+ y= best[1];
+ CHECK_CLIPED_MV(x+1, y);
+ CHECK_CLIPED_MV(x, y+1);
+ CHECK_CLIPED_MV(x-1, y);
+ CHECK_CLIPED_MV(x, y-1);
+ }while(best[0] != x || best[1] != y);
+
+ return dmin;
+}
+
+#define SAB_CHECK_MV(ax,ay)\
+{\
+ const int key= ((ay)<<ME_MAP_MV_BITS) + (ax) + map_generation;\
+ const int index= (((ay)<<ME_MAP_SHIFT) + (ax))&(ME_MAP_SIZE-1);\
+/*printf("sab check %d %d\n", ax, ay);*/\
+ if(map[index]!=key){\
+ d= cmp(s, ax, ay, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
+ map[index]= key;\
+ score_map[index]= d;\
+ d += (mv_penalty[((ax)<<shift)-pred_x] + mv_penalty[((ay)<<shift)-pred_y])*penalty_factor;\
+/*printf("score: %d\n", d);*/\
+ if(d < minima[minima_count-1].height){\
+ int j=0;\
+ \
+ while(d >= 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
+ int map_generation= c->map_generation;
+
+ cmpf= s->dsp.me_cmp[size];
+ chroma_cmpf= s->dsp.me_cmp[size+1];
+
+ for(j=i=0; i<ME_MAP_SIZE; i++){
+ uint32_t key= map[i];
+
+ key += (1<<(ME_MAP_MV_BITS-1)) + (1<<(2*ME_MAP_MV_BITS-1));
+
+ if((key&((-1)<<(2*ME_MAP_MV_BITS))) != map_generation) continue;
+
+ assert(j<MAX_SAB_SIZE); //max j = number of predictors
+
+ minima[j].height= score_map[i];
+ minima[j].x= key & ((1<<ME_MAP_MV_BITS)-1); key>>=ME_MAP_MV_BITS;
+ minima[j].y= key & ((1<<ME_MAP_MV_BITS)-1);
+ minima[j].x-= (1<<(ME_MAP_MV_BITS-1));
+ minima[j].y-= (1<<(ME_MAP_MV_BITS-1));
+ minima[j].checked=0;
+ if(minima[j].x || minima[j].y)
+ minima[j].height+= (mv_penalty[((minima[j].x)<<shift)-pred_x] + mv_penalty[((minima[j].y)<<shift)-pred_y])*penalty_factor;
+
+ j++;
+ }
+
+ qsort(minima, j, sizeof(Minima), minima_cmp);
+
+ for(; j<minima_count; j++){
+ minima[j].height=256*256*256*64;
+ minima[j].checked=0;
+ minima[j].x= minima[j].y=0;
+ }
+
+ for(i=0; i<minima_count; i++){
+ const int x= minima[i].x;
+ const int y= minima[i].y;
+ int d;
+
+ if(minima[i].checked) continue;
+
+ if( 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
+ int 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; dir<end; dir++){
+ int d;
+
+//check(x + dir,y + dia_size - dir,0, a0)
+ CHECK_MV(x + dir , y + dia_size - dir);
+ }
+
+ start= FFMAX(0, x + dia_size - xmax);
+ end = FFMIN(dia_size, y - ymin + 1);
+ for(dir= start; dir<end; dir++){
+ int d;
+
+//check(x + dia_size - dir, y - dir,0, a1)
+ CHECK_MV(x + dia_size - dir, y - dir );
+ }
+
+ start= FFMAX(0, -y + dia_size + ymin );
+ end = FFMIN(dia_size, x - xmin + 1);
+ for(dir= start; dir<end; dir++){
+ int d;
+
+//check(x - dir,y - dia_size + dir,0, a2)
+ CHECK_MV(x - dir , y - dia_size + dir);
+ }
+
+ start= FFMAX(0, -x + dia_size + xmin );
+ end = FFMIN(dia_size, ymax - y + 1);
+ for(dir= start; dir<end; dir++){
+ int d;
+
+//check(x - dia_size + dir, y + dir,0, a3)
+ CHECK_MV(x - dia_size + dir, y + dir );
+ }
+
+ if(x!=best[0] || y!=best[1])
+ dia_size=0;
+#if 0
+{
+int dx, dy, i;
+static int stats[8*8];
+dx= FFABS(x-best[0]);
+dy= FFABS(y-best[1]);
+stats[dy*8 + dx] ++;
+if(256*256*256*64 % (stats[0]+1)==0){
+ for(i=0; i<64; i++){
+ if((i&7)==0) printf("\n");
+ printf("%6d ", stats[i]);
+ }
+ printf("\n");
+}
+}
+#endif
+ }
+ return dmin;
+}
+
+static always_inline int 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;
+ if(c->dia_size==-1)
+ return umh_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
+ return var_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
+}
+
+static 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};
+ int d, dmin;
+ int 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);
+
+ assert(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;
+
+ /* first line */
+ if (s->first_slice_line) {
+ CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
+ CHECK_CLIPED_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_CLIPED_MV((P_MEDIAN[0]>>shift) , (P_MEDIAN[1]>>shift)-1)
+ CHECK_CLIPED_MV((P_MEDIAN[0]>>shift) , (P_MEDIAN[1]>>shift)+1)
+ CHECK_CLIPED_MV((P_MEDIAN[0]>>shift)-1, (P_MEDIAN[1]>>shift) )
+ CHECK_CLIPED_MV((P_MEDIAN[0]>>shift)+1, (P_MEDIAN[1]>>shift) )
+ CHECK_CLIPED_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_CLIPED_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_CLIPED_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_CLIPED_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+1<s->end_mb_y) //FIXME replace at least with last_slice_line
+ CHECK_CLIPED_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<yend; mb_y++){
+ int mb_x;
+ for(mb_x=xstart; mb_x<xend; mb_x++){
+ const int xy= mb_x + 1 + (mb_y + 1)*ref_mv_stride;
+ int mx= (last_mv[xy][0]*ref_mv_scale + (1<<15))>>16;
+ int my= (last_mv[xy][1]*ref_mv_scale + (1<<15))>>16;
+
+ if(mx>xmax || mx<xmin || my>ymax || my<ymin) continue;
+ CHECK_MV(mx,my)
+ }
+ }
+ }
+
+//check(best[0],best[1],0, b0)
+ dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
+
+//check(best[0],best[1],0, b1)
+ *mx_ptr= best[0];
+ *my_ptr= best[1];
+
+// printf("%d %d %d \n", best[0], best[1], dmin);
+ return dmin;
+}
+
+//this function is dedicated to the braindamaged gcc
+inline 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)
+{
+ MotionEstContext * const c= &s->me;
+//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;
+ int 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;
+//printf("%d %d %d %d //",xmin, ymin, xmax, ymax);
+ /* first line */
+ if (s->first_slice_line) {
+ CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
+ CHECK_CLIPED_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_CLIPED_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_CLIPED_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+1<s->end_mb_y) //FIXME replace at least with last_slice_line
+ CHECK_CLIPED_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];
+
+// printf("%d %d %d \n", best[0], best[1], dmin);
+ 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;
+ int 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;
+//printf("%d %d %d %d //",xmin, ymin, xmax, ymax);
+ /* first line */
+ if (s->first_slice_line) {
+ CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
+ CHECK_CLIPED_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_CLIPED_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_CLIPED_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+1<s->end_mb_y) //FIXME replace at least with last_slice_line
+ CHECK_CLIPED_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];
+
+// printf("%d %d %d \n", best[0], best[1], dmin);
+ return dmin;
+}
diff --git a/contrib/ffmpeg/libavcodec/motion_test.c b/contrib/ffmpeg/libavcodec/motion_test.c
new file mode 100644
index 000000000..8540b7483
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/motion_test.c
@@ -0,0 +1,159 @@
+/*
+ * (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.c
+ * motion test.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "dsputil.h"
+
+#include "i386/mmx.h"
+
+#undef printf
+
+int pix_abs16x16_mmx(uint8_t *blk1, uint8_t *blk2, int lx);
+int pix_abs16x16_mmx1(uint8_t *blk1, uint8_t *blk2, int lx);
+int pix_abs16x16_c(uint8_t *blk1, uint8_t *blk2, int lx);
+int pix_abs16x16_x2_mmx(uint8_t *blk1, uint8_t *blk2, int lx);
+int pix_abs16x16_x2_mmx1(uint8_t *blk1, uint8_t *blk2, int lx);
+int pix_abs16x16_x2_c(uint8_t *blk1, uint8_t *blk2, int lx);
+int pix_abs16x16_y2_mmx(uint8_t *blk1, uint8_t *blk2, int lx);
+int pix_abs16x16_y2_mmx1(uint8_t *blk1, uint8_t *blk2, int lx);
+int pix_abs16x16_y2_c(uint8_t *blk1, uint8_t *blk2, int lx);
+int pix_abs16x16_xy2_mmx(uint8_t *blk1, uint8_t *blk2, int lx);
+int pix_abs16x16_xy2_mmx1(uint8_t *blk1, uint8_t *blk2, int lx);
+int pix_abs16x16_xy2_c(uint8_t *blk1, uint8_t *blk2, int lx);
+
+typedef int motion_func(uint8_t *blk1, uint8_t *blk2, int lx);
+
+#define WIDTH 64
+#define HEIGHT 64
+
+uint8_t img1[WIDTH * HEIGHT];
+uint8_t img2[WIDTH * HEIGHT];
+
+void fill_random(uint8_t *tab, int size)
+{
+ int i;
+ for(i=0;i<size;i++) {
+#if 1
+ tab[i] = random() % 256;
+#else
+ tab[i] = i;
+#endif
+ }
+}
+
+void help(void)
+{
+ printf("motion-test [-h]\n"
+ "test motion implementations\n");
+ exit(1);
+}
+
+int64_t gettime(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
+}
+
+#define NB_ITS 500
+
+int dummy;
+
+void test_motion(const char *name,
+ motion_func *test_func, motion_func *ref_func)
+{
+ int x, y, d1, d2, it;
+ uint8_t *ptr;
+ int64_t ti;
+ printf("testing '%s'\n", name);
+
+ /* test correctness */
+ for(it=0;it<20;it++) {
+
+ fill_random(img1, WIDTH * HEIGHT);
+ fill_random(img2, WIDTH * HEIGHT);
+
+ for(y=0;y<HEIGHT-17;y++) {
+ for(x=0;x<WIDTH-17;x++) {
+ ptr = img2 + y * WIDTH + x;
+ d1 = test_func(img1, ptr, WIDTH);
+ d2 = ref_func(img1, ptr, WIDTH);
+ if (d1 != d2) {
+ printf("error: mmx=%d c=%d\n", d1, d2);
+ }
+ }
+ }
+ }
+ emms();
+
+ /* speed test */
+ ti = gettime();
+ d1 = 0;
+ for(it=0;it<NB_ITS;it++) {
+ for(y=0;y<HEIGHT-17;y++) {
+ for(x=0;x<WIDTH-17;x++) {
+ ptr = img2 + y * WIDTH + x;
+ d1 += test_func(img1, ptr, WIDTH);
+ }
+ }
+ }
+ emms();
+ dummy = d1; /* avoid optimisation */
+ ti = gettime() - ti;
+
+ printf(" %0.0f kop/s\n",
+ (double)NB_ITS * (WIDTH - 16) * (HEIGHT - 16) /
+ (double)(ti / 1000.0));
+}
+
+
+int main(int argc, char **argv)
+{
+ int c;
+
+ for(;;) {
+ c = getopt(argc, argv, "h");
+ if (c == -1)
+ break;
+ switch(c) {
+ case 'h':
+ help();
+ break;
+ }
+ }
+
+ printf("ffmpeg motion test\n");
+
+ test_motion("mmx", pix_abs16x16_mmx, pix_abs16x16_c);
+ test_motion("mmx_x2", pix_abs16x16_x2_mmx, pix_abs16x16_x2_c);
+ test_motion("mmx_y2", pix_abs16x16_y2_mmx, pix_abs16x16_y2_c);
+ test_motion("mmx_xy2", pix_abs16x16_xy2_mmx, pix_abs16x16_xy2_c);
+ return 0;
+}
diff --git a/contrib/ffmpeg/libavcodec/mp3lameaudio.c b/contrib/ffmpeg/libavcodec/mp3lameaudio.c
new file mode 100644
index 000000000..d13350265
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mp3lameaudio.c
@@ -0,0 +1,221 @@
+/*
+ * Interface to libmp3lame for mp3 encoding
+ * Copyright (c) 2002 Lennert Buytenhek <buytenh@gnu.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 mp3lameaudio.c
+ * Interface to libmp3lame for mp3 encoding.
+ */
+
+#include "avcodec.h"
+#include "mpegaudio.h"
+#include <lame/lame.h>
+
+#define BUFFER_SIZE (2*MPA_FRAME_SIZE)
+typedef struct Mp3AudioContext {
+ lame_global_flags *gfp;
+ int stereo;
+ uint8_t buffer[BUFFER_SIZE];
+ int buffer_index;
+} Mp3AudioContext;
+
+static int MP3lame_encode_init(AVCodecContext *avctx)
+{
+ Mp3AudioContext *s = avctx->priv_data;
+
+ if (avctx->channels > 2)
+ return -1;
+
+ s->stereo = avctx->channels > 1 ? 1 : 0;
+
+ if ((s->gfp = lame_init()) == NULL)
+ goto err;
+ lame_set_in_samplerate(s->gfp, avctx->sample_rate);
+ lame_set_out_samplerate(s->gfp, avctx->sample_rate);
+ lame_set_num_channels(s->gfp, avctx->channels);
+ /* lame 3.91 dies on quality != 5 */
+ lame_set_quality(s->gfp, 5);
+ /* lame 3.91 doesn't work in mono */
+ lame_set_mode(s->gfp, JOINT_STEREO);
+ lame_set_brate(s->gfp, avctx->bit_rate/1000);
+ if(avctx->flags & CODEC_FLAG_QSCALE) {
+ lame_set_brate(s->gfp, 0);
+ lame_set_VBR(s->gfp, vbr_default);
+ lame_set_VBR_q(s->gfp, avctx->global_quality / (float)FF_QP2LAMBDA);
+ }
+ lame_set_bWriteVbrTag(s->gfp,0);
+ if (lame_init_params(s->gfp) < 0)
+ goto err_close;
+
+ avctx->frame_size = lame_get_framesize(s->gfp);
+
+ avctx->coded_frame= avcodec_alloc_frame();
+ avctx->coded_frame->key_frame= 1;
+
+ return 0;
+
+err_close:
+ lame_close(s->gfp);
+err:
+ return -1;
+}
+
+static const int sSampleRates[3] = {
+ 44100, 48000, 32000
+};
+
+static const int sBitRates[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}
+ },
+};
+
+static const int sSamplesPerFrame[2][3] =
+{
+ { 384, 1152, 1152 },
+ { 384, 1152, 576 }
+};
+
+static const int sBitsPerSlot[3] = {
+ 32,
+ 8,
+ 8
+};
+
+static int mp3len(void *data, int *samplesPerFrame, int *sampleRate)
+{
+ uint8_t *dataTmp = (uint8_t *)data;
+ uint32_t header = ( (uint32_t)dataTmp[0] << 24 ) | ( (uint32_t)dataTmp[1] << 16 ) | ( (uint32_t)dataTmp[2] << 8 ) | (uint32_t)dataTmp[3];
+ int layerID = 3 - ((header >> 17) & 0x03);
+ int bitRateID = ((header >> 12) & 0x0f);
+ int sampleRateID = ((header >> 10) & 0x03);
+ int bitsPerSlot = sBitsPerSlot[layerID];
+ int isPadded = ((header >> 9) & 0x01);
+ static int const mode_tab[4]= {2,3,1,0};
+ int mode= mode_tab[(header >> 19) & 0x03];
+ int mpeg_id= mode>0;
+ int temp0, temp1, bitRate;
+
+ if ( (( header >> 21 ) & 0x7ff) != 0x7ff || mode == 3 || layerID==3 || sampleRateID==3) {
+ return -1;
+ }
+
+ if(!samplesPerFrame) samplesPerFrame= &temp0;
+ if(!sampleRate ) sampleRate = &temp1;
+
+// *isMono = ((header >> 6) & 0x03) == 0x03;
+
+ *sampleRate = sSampleRates[sampleRateID]>>mode;
+ bitRate = sBitRates[mpeg_id][layerID][bitRateID] * 1000;
+ *samplesPerFrame = sSamplesPerFrame[mpeg_id][layerID];
+//av_log(NULL, AV_LOG_DEBUG, "sr:%d br:%d spf:%d l:%d m:%d\n", *sampleRate, bitRate, *samplesPerFrame, layerID, mode);
+
+ return *samplesPerFrame * bitRate / (bitsPerSlot * *sampleRate) + isPadded;
+}
+
+static int MP3lame_encode_frame(AVCodecContext *avctx,
+ unsigned char *frame, int buf_size, void *data)
+{
+ Mp3AudioContext *s = avctx->priv_data;
+ int len;
+ int lame_result;
+
+ /* lame 3.91 dies on '1-channel interleaved' data */
+
+ if(data){
+ if (s->stereo) {
+ lame_result = lame_encode_buffer_interleaved(
+ s->gfp,
+ data,
+ avctx->frame_size,
+ s->buffer + s->buffer_index,
+ BUFFER_SIZE - s->buffer_index
+ );
+ } else {
+ lame_result = lame_encode_buffer(
+ s->gfp,
+ data,
+ data,
+ avctx->frame_size,
+ s->buffer + s->buffer_index,
+ BUFFER_SIZE - s->buffer_index
+ );
+ }
+ }else{
+ lame_result= lame_encode_flush(
+ s->gfp,
+ s->buffer + s->buffer_index,
+ BUFFER_SIZE - s->buffer_index
+ );
+ }
+
+ if(lame_result==-1) {
+ /* output buffer too small */
+ av_log(avctx, AV_LOG_ERROR, "lame: output buffer too small (buffer index: %d, free bytes: %d)\n", s->buffer_index, BUFFER_SIZE - s->buffer_index);
+ return 0;
+ }
+
+ s->buffer_index += lame_result;
+
+ if(s->buffer_index<4)
+ return 0;
+
+ len= mp3len(s->buffer, NULL, NULL);
+//av_log(avctx, AV_LOG_DEBUG, "in:%d packet-len:%d index:%d\n", avctx->frame_size, len, s->buffer_index);
+ if(len <= s->buffer_index){
+ memcpy(frame, s->buffer, len);
+ s->buffer_index -= len;
+
+ memmove(s->buffer, s->buffer+len, s->buffer_index);
+ //FIXME fix the audio codec API, so we dont need the memcpy()
+/*for(i=0; i<len; i++){
+ av_log(avctx, AV_LOG_DEBUG, "%2X ", frame[i]);
+}*/
+ return len;
+ }else
+ return 0;
+}
+
+static int MP3lame_encode_close(AVCodecContext *avctx)
+{
+ Mp3AudioContext *s = avctx->priv_data;
+
+ av_freep(&avctx->coded_frame);
+
+ lame_close(s->gfp);
+ return 0;
+}
+
+
+AVCodec mp3lame_encoder = {
+ "mp3",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_MP3,
+ sizeof(Mp3AudioContext),
+ MP3lame_encode_init,
+ MP3lame_encode_frame,
+ MP3lame_encode_close,
+ .capabilities= CODEC_CAP_DELAY,
+};
diff --git a/contrib/ffmpeg/libavcodec/mpeg12.c b/contrib/ffmpeg/libavcodec/mpeg12.c
new file mode 100644
index 000000000..c392e17af
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mpeg12.c
@@ -0,0 +1,3493 @@
+/*
+ * MPEG1 codec / MPEG2 decoder
+ * Copyright (c) 2000,2001 Fabrice Bellard.
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file mpeg12.c
+ * MPEG1/2 codec
+ */
+
+//#define DEBUG
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+#include "mpeg12data.h"
+
+//#undef NDEBUG
+//#include <assert.h>
+
+
+/* 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
+
+#define DC_VLC_BITS 9
+#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
+#define TEX_VLC_BITS 9
+
+#ifdef CONFIG_ENCODERS
+static void mpeg1_encode_block(MpegEncContext *s,
+ DCTELEM *block,
+ int component);
+static void mpeg1_encode_motion(MpegEncContext *s, int val, int f_or_b_code); // RAL: f_code parameter added
+#endif //CONFIG_ENCODERS
+static inline int mpeg1_decode_block_inter(MpegEncContext *s,
+ DCTELEM *block,
+ int n);
+static inline int mpeg1_decode_block_intra(MpegEncContext *s,
+ DCTELEM *block,
+ int n);
+static inline int mpeg1_fast_decode_block_inter(MpegEncContext *s, DCTELEM *block, int n);
+static inline int mpeg2_decode_block_non_intra(MpegEncContext *s,
+ DCTELEM *block,
+ int n);
+static inline int mpeg2_decode_block_intra(MpegEncContext *s,
+ DCTELEM *block,
+ int n);
+static inline int mpeg2_fast_decode_block_non_intra(MpegEncContext *s, DCTELEM *block, int n);
+static inline int mpeg2_fast_decode_block_intra(MpegEncContext *s, DCTELEM *block, int n);
+static int mpeg_decode_motion(MpegEncContext *s, int fcode, int pred);
+static void exchange_uv(MpegEncContext *s);
+
+#ifdef HAVE_XVMC
+extern int XVMC_field_start(MpegEncContext *s, AVCodecContext *avctx);
+extern int XVMC_field_end(MpegEncContext *s);
+extern void XVMC_pack_pblocks(MpegEncContext *s,int cbp);
+extern void XVMC_init_block(MpegEncContext *s);//set s->block
+#endif
+
+static const enum PixelFormat pixfmt_yuv_420[]= {PIX_FMT_YUV420P,-1};
+static const enum PixelFormat pixfmt_yuv_422[]= {PIX_FMT_YUV422P,-1};
+static const enum PixelFormat pixfmt_yuv_444[]= {PIX_FMT_YUV444P,-1};
+static const enum PixelFormat pixfmt_xvmc_mpg2_420[] = {
+ PIX_FMT_XVMC_MPEG2_IDCT,
+ PIX_FMT_XVMC_MPEG2_MC,
+ -1};
+#ifdef CONFIG_ENCODERS
+static uint8_t (*mv_penalty)[MAX_MV*2+1]= NULL;
+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];
+#endif //CONFIG_ENCODERS
+
+static void init_2d_vlc_rl(RLTable *rl, int use_static)
+{
+ int i;
+
+ init_vlc(&rl->vlc, TEX_VLC_BITS, rl->n + 2,
+ &rl->table_vlc[0][1], 4, 2,
+ &rl->table_vlc[0][0], 4, 2, use_static);
+
+ if(use_static)
+ rl->rl_vlc[0]= av_mallocz_static(rl->vlc.table_size*sizeof(RL_VLC_ELEM));
+ else
+ rl->rl_vlc[0]= av_malloc(rl->vlc.table_size*sizeof(RL_VLC_ELEM));
+
+ 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;
+ }
+}
+
+#ifdef CONFIG_ENCODERS
+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;
+ for(run=0; run<64; run++){
+ int len, bits, code;
+
+ int alevel= FFABS(level);
+ int sign= (level>>31)&1;
+
+ 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 */) {
+ /* store the vlc & sign at once */
+ len= rl->table_vlc[code][1]+1;
+ bits= (rl->table_vlc[code][0]<<1) + sign;
+ } else {
+ len= rl->table_vlc[111/*rl->n*/][1]+6;
+ bits= rl->table_vlc[111/*rl->n*/][0]<<6;
+
+ bits|= run;
+ if (alevel < 128) {
+ bits<<=8; len+=8;
+ bits|= level & 0xff;
+ } else {
+ bits<<=16; len+=16;
+ bits|= level & 0xff;
+ if (level < 0) {
+ bits|= 0x8001 + level + 255;
+ } else {
+ bits|= level & 0xffff;
+ }
+ }
+ }
+
+ uni_ac_vlc_len [UNI_AC_ENC_INDEX(run, i)]= len;
+ }
+ }
+}
+
+
+static int find_frame_rate_index(MpegEncContext *s){
+ int i;
+ int64_t dmin= INT64_MAX;
+ int64_t d;
+
+ for(i=1;i<14;i++) {
+ int64_t n0= 1001LL/ff_frame_rate_tab[i].den*ff_frame_rate_tab[i].num*s->avctx->time_base.num;
+ int64_t n1= 1001LL*s->avctx->time_base.den;
+ if(s->avctx->strict_std_compliance > FF_COMPLIANCE_INOFFICIAL && i>=9) break;
+
+ d = FFABS(n0 - n1);
+ if(d < dmin){
+ dmin=d;
+ s->frame_rate_index= i;
+ }
+ }
+ if(dmin)
+ return -1;
+ else
+ return 0;
+}
+
+static int encode_init(AVCodecContext *avctx)
+{
+ MpegEncContext *s = avctx->priv_data;
+
+ if(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)
+ avctx->profile = s->chroma_format == CHROMA_420 ? 4 : 0;
+
+ if(avctx->level == FF_LEVEL_UNKNOWN)
+ avctx->level = s->chroma_format == CHROMA_420 ? 8 : 5;
+
+ if((avctx->flags2 & CODEC_FLAG2_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;
+ }
+
+ return 0;
+}
+
+static void put_header(MpegEncContext *s, int header)
+{
+ align_put_bits(&s->pb);
+ put_bits(&s->pb, 16, header>>16);
+ put_bits(&s->pb, 16, header&0xFFFF);
+}
+
+/* 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.key_frame) {
+ AVRational framerate= ff_frame_rate_tab[s->frame_rate_index];
+
+ /* mpeg1 header repeated every gop */
+ put_header(s, SEQ_START_CODE);
+
+ put_bits(&s->pb, 12, s->width);
+ put_bits(&s->pb, 12, s->height);
+
+ for(i=1; i<15; i++){
+ float error= aspect_ratio;
+ if(s->codec_id == CODEC_ID_MPEG1VIDEO || i <=1)
+ error-= 1.0/mpeg1_aspect[i];
+ else
+ error-= av_q2d(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 == 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_bits(&s->pb, 18, v & 0x3FFFF);
+ put_bits(&s->pb, 1, 1); /* marker */
+ put_bits(&s->pb, 10, vbv_buffer_size & 0x3FF);
+
+ 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 == 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 == CODEC_ID_MPEG2VIDEO){
+ put_header(s, EXT_START_CODE);
+ put_bits(&s->pb, 4, 1); //seq ext
+
+ put_bits(&s->pb, 1, s->chroma_format == CHROMA_422); //escx
+
+ 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, 0); //horizontal size ext
+ put_bits(&s->pb, 2, 0); //vertical size ext
+ 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, 0); // frame_rate_ext_n
+ put_bits(&s->pb, 5, 0); // frame_rate_ext_d
+ }
+
+ put_header(s, GOP_START_CODE);
+ put_bits(&s->pb, 1, !!(s->avctx->flags & CODEC_FLAG2_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->coded_picture_number + s->avctx->timecode_frame_start;
+
+ s->gop_picture_number = s->current_picture_ptr->coded_picture_number;
+ if (s->avctx->flags2 & CODEC_FLAG2_DROP_FRAME_TIMECODE) {
+ /* only works for NTSC 29.97 */
+ int d = time_code / 17982;
+ int m = time_code % 17982;
+ //if (m < 2) m += 2; /* not needed since -2,-1 / 1798 in C returns 0 */
+ time_code += 18 * d + 2 * ((m - 2) / 1798);
+ }
+ 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, mbAddrIncrTable[run][1],
+ mbAddrIncrTable[run][0]);
+}
+#endif //CONFIG_ENCODERS
+
+static void common_init(MpegEncContext *s)
+{
+
+ s->y_dc_scale_table=
+ s->c_dc_scale_table= 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));
+}
+
+#ifdef CONFIG_ENCODERS
+
+void ff_mpeg1_encode_slice_header(MpegEncContext *s){
+ put_header(s, SLICE_MIN_START_CODE + s->mb_y);
+ put_bits(&s->pb, 5, s->qscale); /* quantizer scale */
+ put_bits(&s->pb, 1, 0); /* slice extra information */
+}
+
+void 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 == P_TYPE || s->pict_type == B_TYPE) {
+ put_bits(&s->pb, 1, 0); /* half pel coordinates */
+ if(s->codec_id == 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 == B_TYPE) {
+ put_bits(&s->pb, 1, 0); /* half pel coordinates */
+ if(s->codec_id == 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 == CODEC_ID_MPEG2VIDEO){
+ put_header(s, EXT_START_CODE);
+ put_bits(&s->pb, 4, 8); //pic ext
+ if (s->pict_type == P_TYPE || s->pict_type == B_TYPE) {
+ 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 == B_TYPE) {
+ 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);
+
+ assert(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->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->flags & CODEC_FLAG_SVCD_SCAN_OFFSET){
+ int i;
+
+ put_header(s, USER_START_CODE);
+ for(i=0; i<sizeof(svcd_scan_offset_placeholder); i++){
+ put_bits(&s->pb, 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 always_inline void mpeg1_encode_mb_internal(MpegEncContext *s,
+ DCTELEM 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;i<mb_block_count;i++) {
+ if (s->block_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->mb_height - 1 && s->codec_id == CODEC_ID_MPEG1VIDEO)) &&
+ ((s->pict_type == P_TYPE && (motion_x | motion_y) == 0) ||
+ (s->pict_type == B_TYPE && 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 == P_TYPE){
+ 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){
+ assert(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 == I_TYPE) {
+ if(s->dquant && cbp){
+ put_mb_modes(s, 2, 1, 0, 0); /* macroblock_type : macroblock_quant = 1 */
+ put_bits(&s->pb, 5, s->qscale);
+ }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_bits(&s->pb, 5, s->qscale);
+ }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 == P_TYPE) {
+ 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_bits(&s->pb, 5, s->qscale);
+ }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_bits(&s->pb, 5, s->qscale);
+ }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{
+ assert(!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_bits(&s->pb, 5, s->qscale);
+ }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, mbPatTable[cbp][1], mbPatTable[cbp][0]);
+ } else {
+ put_bits(&s->pb, mbPatTable[cbp>>2][1], mbPatTable[cbp>>2][0]);
+ put_bits(&s->pb, 2, cbp & 3);
+ }
+ }
+ s->f_count++;
+ } else{
+ static const int mb_type_len[4]={0,3,4,2}; //bak,for,bi
+
+ 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, mb_type_len[s->mv_dir]+3, 2, 1, 0);
+ put_bits(&s->pb, 5, s->qscale);
+ } else {
+ put_mb_modes(s, mb_type_len[s->mv_dir], 3, 1, 0);
+ }
+ }else{ // No coded bloc pattern
+ put_bits(&s->pb, mb_type_len[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{
+ assert(s->mv_type == MV_TYPE_FIELD);
+ assert(!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, mb_type_len[s->mv_dir]+3, 2, 1, 1);
+ put_bits(&s->pb, 5, s->qscale);
+ } else {
+ put_mb_modes(s, mb_type_len[s->mv_dir], 3, 1, 1);
+ }
+ }else{ // No coded bloc pattern
+ put_bits(&s->pb, mb_type_len[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, mbPatTable[cbp][1], mbPatTable[cbp][0]);
+ } else {
+ put_bits(&s->pb, mbPatTable[cbp>>2][1], mbPatTable[cbp>>2][0]);
+ put_bits(&s->pb, 2, cbp & 3);
+ }
+ }
+ }
+ for(i=0;i<mb_block_count;i++) {
+ if (cbp & (1 << (mb_block_count - 1 - i))) {
+ mpeg1_encode_block(s, block[i], i);
+ }
+ }
+ s->mb_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 mpeg1_encode_mb(MpegEncContext *s, DCTELEM 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)
+{
+ int code, bit_size, l, bits, range, sign;
+
+ if (val == 0) {
+ /* zero vector */
+ code = 0;
+ put_bits(&s->pb,
+ mbMotionVectorTable[0][1],
+ mbMotionVectorTable[0][0]);
+ } else {
+ bit_size = f_or_b_code - 1;
+ range = 1 << bit_size;
+ /* modulo encoding */
+ l= INT_BIT - 5 - bit_size;
+ val= (val<<l)>>l;
+
+ 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;
+ }
+
+ assert(code > 0 && code <= 16);
+
+ put_bits(&s->pb,
+ mbMotionVectorTable[code][1],
+ 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;
+
+ common_init(s);
+
+ if(!done){
+ int f_code;
+ int mv;
+ int i;
+
+ done=1;
+ init_rl(&rl_mpeg1, 1);
+ if(s->intra_vlc_format)
+ init_rl(&rl_mpeg2, 1);
+
+ for(i=0; i<64; i++)
+ {
+ mpeg1_max_level[0][i]= rl_mpeg1.max_level[0][i];
+ mpeg1_index_run[0][i]= rl_mpeg1.index_run[0][i];
+ }
+
+ init_uni_ac_vlc(&rl_mpeg1, uni_mpeg1_ac_vlc_len);
+ if(s->intra_vlc_format)
+ init_uni_ac_vlc(&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= vlc_dc_lum_bits[index] + index;
+ code= (vlc_dc_lum_code[index]<<index) + (diff & ((1 << index) - 1));
+ mpeg1_lum_dc_uni[i+255]= bits + (code<<8);
+
+ bits= vlc_dc_chroma_bits[index] + index;
+ code= (vlc_dc_chroma_code[index]<<index) + (diff & ((1 << index) - 1));
+ mpeg1_chr_dc_uni[i+255]= bits + (code<<8);
+ }
+
+ mv_penalty= av_mallocz( sizeof(uint8_t)*(MAX_FCODE+1)*(2*MAX_MV+1) );
+
+ for(f_code=1; f_code<=MAX_FCODE; f_code++){
+ for(mv=-MAX_MV; mv<=MAX_MV; mv++){
+ int len;
+
+ if(mv==0) len= mbMotionVectorTable[0][1];
+ else{
+ int val, bit_size, range, code;
+
+ bit_size = f_code - 1;
+ range = 1 << bit_size;
+
+ val=mv;
+ if (val < 0)
+ val = -val;
+ val--;
+ code = (val >> bit_size) + 1;
+ if(code<17){
+ len= mbMotionVectorTable[code][1] + 1 + bit_size;
+ }else{
+ len= 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<<f_code); mv<(8<<f_code); mv++){
+ fcode_tab[mv+MAX_MV]= f_code;
+ }
+ }
+ }
+ s->me.mv_penalty= mv_penalty;
+ s->fcode_tab= fcode_tab;
+ if(s->codec_id == 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,
+ vlc_dc_lum_bits[index] + index,
+ (vlc_dc_lum_code[index]<<index) + (diff & ((1 << index) - 1)));
+ }else{
+ put_bits(
+ &s->pb,
+ vlc_dc_chroma_bits[index] + index,
+ (vlc_dc_chroma_code[index]<<index) + (diff & ((1 << index) - 1)));
+ }
+ }else{
+ if (component == 0) {
+ put_bits(
+ &s->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,
+ DCTELEM *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] = 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 = 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:
+#if 0
+ if (level != 0)
+ dprintf("level[%d]=%d\n", i, level);
+#endif
+ /* 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 dont 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 == CODEC_ID_MPEG1VIDEO){
+ if (alevel < 128) {
+ put_bits(&s->pb, 8, level & 0xff);
+ } else {
+ if (level < 0) {
+ put_bits(&s->pb, 16, 0x8001 + level + 255);
+ } else {
+ put_bits(&s->pb, 16, level & 0xffff);
+ }
+ }
+ }else{
+ put_bits(&s->pb, 12, level & 0xfff);
+ }
+ }
+ last_non_zero = i;
+ }
+ }
+ /* end of block */
+ put_bits(&s->pb, table_vlc[112][1], table_vlc[112][0]);
+}
+#endif //CONFIG_ENCODERS
+
+/******************************************/
+/* decoding */
+
+static VLC dc_lum_vlc;
+static VLC dc_chroma_vlc;
+static VLC mv_vlc;
+static VLC mbincr_vlc;
+static VLC mb_ptype_vlc;
+static VLC mb_btype_vlc;
+static VLC mb_pat_vlc;
+
+static void init_vlcs(void)
+{
+ static int done = 0;
+
+ if (!done) {
+ done = 1;
+
+ init_vlc(&dc_lum_vlc, DC_VLC_BITS, 12,
+ vlc_dc_lum_bits, 1, 1,
+ vlc_dc_lum_code, 2, 2, 1);
+ init_vlc(&dc_chroma_vlc, DC_VLC_BITS, 12,
+ vlc_dc_chroma_bits, 1, 1,
+ vlc_dc_chroma_code, 2, 2, 1);
+ init_vlc(&mv_vlc, MV_VLC_BITS, 17,
+ &mbMotionVectorTable[0][1], 2, 1,
+ &mbMotionVectorTable[0][0], 2, 1, 1);
+ init_vlc(&mbincr_vlc, MBINCR_VLC_BITS, 36,
+ &mbAddrIncrTable[0][1], 2, 1,
+ &mbAddrIncrTable[0][0], 2, 1, 1);
+ init_vlc(&mb_pat_vlc, MB_PAT_VLC_BITS, 64,
+ &mbPatTable[0][1], 2, 1,
+ &mbPatTable[0][0], 2, 1, 1);
+
+ init_vlc(&mb_ptype_vlc, MB_PTYPE_VLC_BITS, 7,
+ &table_mb_ptype[0][1], 2, 1,
+ &table_mb_ptype[0][0], 2, 1, 1);
+ init_vlc(&mb_btype_vlc, MB_BTYPE_VLC_BITS, 11,
+ &table_mb_btype[0][1], 2, 1,
+ &table_mb_btype[0][0], 2, 1, 1);
+ init_rl(&rl_mpeg1, 1);
+ init_rl(&rl_mpeg2, 1);
+
+ init_2d_vlc_rl(&rl_mpeg1, 1);
+ init_2d_vlc_rl(&rl_mpeg2, 1);
+ }
+}
+
+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;
+ }
+}
+
+/* motion type (for mpeg2) */
+#define MT_FIELD 1
+#define MT_FRAME 2
+#define MT_16X8 2
+#define MT_DMV 3
+
+static int mpeg_decode_mb(MpegEncContext *s,
+ DCTELEM block[12][64])
+{
+ int i, j, k, cbp, val, mb_type, motion_type;
+ const int mb_block_count = 4 + (1<< s->chroma_format);
+
+ dprintf("decode_mb: x=%d y=%d\n", s->mb_x, s->mb_y);
+
+ assert(s->mb_skipped==0);
+
+ if (s->mb_skip_run-- != 0) {
+ if(s->pict_type == I_TYPE){
+ 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 == P_TYPE) {
+ /* 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;
+ 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))
+ return -1;
+
+ /* 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];
+
+ 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 I_TYPE:
+ 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 P_TYPE:
+ 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 B_TYPE:
+ 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;
+ }
+ dprintf("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 a 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;
+#ifdef HAVE_XVMC
+ //one 1 we memcpy blocks in xvmcvideo
+ if(s->avctx->xvmc_acceleration > 1){
+ XVMC_pack_pblocks(s,-1);//inter are always full blocks
+ if(s->swap_uv){
+ exchange_uv(s);
+ }
+ }
+#endif
+
+ if (s->codec_id == 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){
+ assert(mb_type & MB_TYPE_CBP);
+
+ /* compute dct type */
+ if (s->picture_structure == PICT_FRAME && //FIXME add a 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);
+
+ s->mv_dir = MV_DIR_FORWARD;
+ if(s->picture_structure == PICT_FRAME)
+ 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;
+ }
+ 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{
+ assert(mb_type & MB_TYPE_L0L1);
+//FIXME decide if MBs in field pictures are MB_TYPE_INTERLACED
+ /* get additionnal motion vector type */
+ if (s->frame_pred_frame_dct)
+ motion_type = MT_FRAME;
+ else{
+ motion_type = get_bits(&s->gb, 2);
+ }
+
+ /* compute dct type */
+ if (s->picture_structure == PICT_FRAME && //FIXME add a interlaced_dct coded var?
+ !s->frame_pred_frame_dct && 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 = 0;
+ for(i=0;i<2;i++) {
+ if (USES_LIST(mb_type, i)) {
+ s->mv_dir |= (MV_DIR_FORWARD >> i);
+ dprintf("motion_type=%d\n", motion_type);
+ switch(motion_type) {
+ case MT_FRAME: /* or MT_16X8 */
+ if (s->picture_structure == PICT_FRAME) {
+ /* MT_FRAME */
+ mb_type |= MB_TYPE_16x16;
+ s->mv_type = MV_TYPE_16X16;
+ 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 mpeg1 */
+ if (s->full_pel[i]){
+ s->mv[i][0][0] <<= 1;
+ s->mv[i][0][1] <<= 1;
+ }
+ } else {
+ /* MT_16X8 */
+ mb_type |= MB_TYPE_16x8 | MB_TYPE_INTERLACED;
+ s->mv_type = MV_TYPE_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(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;
+ dprintf("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;
+ dprintf("fmy=%d\n", val);
+ }
+ } else {
+ mb_type |= MB_TYPE_16x16 | MB_TYPE_INTERLACED;
+ 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:
+ {
+ int dmx, dmy, mx, my, m;
+
+ 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] >> 1);
+ dmy = get_dmv(s);
+ s->mv_type = MV_TYPE_DMV;
+
+
+ s->last_mv[i][0][1] = my<<1;
+ s->last_mv[i][1][1] = my<<1;
+
+ 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]);
+
+ if(!s->chroma_y_shift){
+ s->dsp.clear_blocks(s->block[6]);
+ }
+
+ cbp = get_vlc2(&s->gb, mb_pat_vlc.table, MB_PAT_VLC_BITS, 1);
+ if (cbp < 0 || ((cbp == 0) && (s->chroma_format < 2)) ){
+ av_log(s->avctx, AV_LOG_ERROR, "invalid cbp at %d %d\n", s->mb_x, s->mb_y);
+ return -1;
+ }
+ if(mb_block_count > 6){
+ cbp<<= mb_block_count-6;
+ cbp |= get_bits(&s->gb, mb_block_count-6);
+ }
+
+#ifdef HAVE_XVMC
+ //on 1 we memcpy blocks in xvmcvideo
+ if(s->avctx->xvmc_acceleration > 1){
+ XVMC_pack_pblocks(s,cbp);
+ if(s->swap_uv){
+ exchange_uv(s);
+ }
+ }
+#endif
+
+ if (s->codec_id == 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;
+}
+
+/* as h263, but only 17 codes */
+static int mpeg_decode_motion(MpegEncContext *s, int fcode, int pred)
+{
+ int code, sign, val, l, 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 */
+ l= INT_BIT - 5 - shift;
+ val = (val<<l)>>l;
+ return val;
+}
+
+static inline int decode_dc(GetBitContext *gb, int component)
+{
+ int code, diff;
+
+ if (component == 0) {
+ code = get_vlc2(gb, dc_lum_vlc.table, DC_VLC_BITS, 2);
+ } else {
+ code = get_vlc2(gb, 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;
+}
+
+static inline int mpeg1_decode_block_intra(MpegEncContext *s,
+ DCTELEM *block,
+ int n)
+{
+ int level, dc, diff, i, j, run;
+ int component;
+ RLTable *rl = &rl_mpeg1;
+ uint8_t * const scantable= s->intra_scantable.permutated;
+ const uint16_t *quant_matrix= s->intra_matrix;
+ const int qscale= s->qscale;
+
+ /* DC coef */
+ 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<<3;
+ dprintf("dc=%d diff=%d\n", dc, diff);
+ i = 0;
+ {
+ OPEN_READER(re, &s->gb);
+ /* now quantify & encode AC coefs */
+ 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;
+}
+
+static inline int mpeg1_decode_block_inter(MpegEncContext *s,
+ DCTELEM *block,
+ int n)
+{
+ int level, i, j, run;
+ RLTable *rl = &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 the first coef. no need to add a 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 coefs */
+ 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;
+}
+
+static inline int mpeg1_fast_decode_block_inter(MpegEncContext *s, DCTELEM *block, int n)
+{
+ int level, i, j, run;
+ RLTable *rl = &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 the first coef. no need to add a 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 coefs */
+ 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,
+ DCTELEM *block,
+ int n)
+{
+ int level, i, j, run;
+ RLTable *rl = &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 the first coef. no need to add a 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 coefs */
+ 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;
+}
+
+static inline int mpeg2_fast_decode_block_non_intra(MpegEncContext *s,
+ DCTELEM *block,
+ int n)
+{
+ int level, i, j, run;
+ RLTable *rl = &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 the first coef. no need to add a 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 coefs */
+ 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,
+ DCTELEM *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 coef */
+ 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);
+ dprintf("dc=%d\n", block[0]);
+ mismatch = block[0] ^ 1;
+ i = 0;
+ if (s->intra_vlc_format)
+ rl = &rl_mpeg2;
+ else
+ rl = &rl_mpeg1;
+
+ {
+ OPEN_READER(re, &s->gb);
+ /* now quantify & encode AC coefs */
+ 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;
+}
+
+static inline int mpeg2_fast_decode_block_intra(MpegEncContext *s,
+ DCTELEM *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 coef */
+ 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 = &rl_mpeg2;
+ else
+ rl = &rl_mpeg1;
+
+ {
+ OPEN_READER(re, &s->gb);
+ /* now quantify & encode AC coefs */
+ 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;
+}
+
+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;
+ AVRational frame_rate_ext; ///< MPEG-2 specific framerate modificator
+
+} Mpeg1Context;
+
+static int mpeg_decode_init(AVCodecContext *avctx)
+{
+ Mpeg1Context *s = avctx->priv_data;
+ MpegEncContext *s2 = &s->mpeg_enc_ctx;
+ int i;
+
+ //we need some parmutation to store
+ //matrixes, until MPV_common_init()
+ //set the real permutatuon
+ for(i=0;i<64;i++)
+ s2->dsp.idct_permutation[i]=i;
+
+ MPV_decode_defaults(s2);
+
+ s->mpeg_enc_ctx.avctx= avctx;
+ s->mpeg_enc_ctx.flags= avctx->flags;
+ s->mpeg_enc_ctx.flags2= avctx->flags2;
+ common_init(&s->mpeg_enc_ctx);
+ 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;
+ 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]];
+ }
+}
+
+//Call this function when we know all parameters
+//it may be called in different places for mpeg1 and mpeg2
+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_aspect_info != s->aspect_ratio_info||
+ 0)
+ {
+
+ if (s1->mpeg_enc_ctx_allocated) {
+ ParseContext pc= s->parse_context;
+ s->parse_context.buffer=0;
+ 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);
+ avctx->bit_rate = s->bit_rate;
+ s1->save_aspect_info = s->aspect_ratio_info;
+
+ //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->sub_id==1){//s->codec_id==avctx->codec_id==CODEC_ID
+ //mpeg1 fps
+ avctx->time_base.den= ff_frame_rate_tab[s->frame_rate_index].num;
+ avctx->time_base.num= ff_frame_rate_tab[s->frame_rate_index].den;
+ //mpeg1 aspect
+ avctx->sample_aspect_ratio= av_d2q(
+ 1.0/mpeg1_aspect[s->aspect_ratio_info], 255);
+
+ }else{//mpeg2
+ //mpeg2 fps
+ av_reduce(
+ &s->avctx->time_base.den,
+ &s->avctx->time_base.num,
+ ff_frame_rate_tab[s->frame_rate_index].num * s1->frame_rate_ext.num,
+ ff_frame_rate_tab[s->frame_rate_index].den * s1->frame_rate_ext.den,
+ 1<<30);
+ //mpeg2 aspect
+ if(s->aspect_ratio_info > 1){
+ if( (s1->pan_scan.width == 0 )||(s1->pan_scan.height == 0) ){
+ s->avctx->sample_aspect_ratio=
+ av_div_q(
+ mpeg2_aspect[s->aspect_ratio_info],
+ (AVRational){s->width, s->height}
+ );
+ }else{
+ s->avctx->sample_aspect_ratio=
+ av_div_q(
+ mpeg2_aspect[s->aspect_ratio_info],
+ (AVRational){s1->pan_scan.width, s1->pan_scan.height}
+ );
+ }
+ }else{
+ s->avctx->sample_aspect_ratio=
+ mpeg2_aspect[s->aspect_ratio_info];
+ }
+ }//mpeg2
+
+ if(avctx->xvmc_acceleration){
+ avctx->pix_fmt = avctx->get_format(avctx,pixfmt_xvmc_mpg2_420);
+ }else{
+ if(s->chroma_format < 2){
+ avctx->pix_fmt = avctx->get_format(avctx,pixfmt_yuv_420);
+ }else
+ if(s->chroma_format == 2){
+ avctx->pix_fmt = avctx->get_format(avctx,pixfmt_yuv_422);
+ }else
+ if(s->chroma_format > 2){
+ avctx->pix_fmt = avctx->get_format(avctx,pixfmt_yuv_444);
+ }
+ }
+ //until then pix_fmt may be changed right after codec init
+ if( avctx->pix_fmt == PIX_FMT_XVMC_MPEG2_IDCT )
+ if( avctx->idct_algo == FF_IDCT_AUTO )
+ avctx->idct_algo = FF_IDCT_SIMPLE;
+
+ //quantization matrixes may need reordering
+ //if dct permutation is changed
+ memcpy(old_permutation,s->dsp.idct_permutation,64*sizeof(uint8_t));
+
+ if (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;
+
+ if(mpeg_decode_postinit(s->avctx) < 0)
+ return -2;
+
+ 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);
+ if (s->pict_type == P_TYPE || s->pict_type == B_TYPE) {
+ s->full_pel[0] = get_bits1(&s->gb);
+ f_code = get_bits(&s->gb, 3);
+ if (f_code == 0 && avctx->error_resilience >= FF_ER_COMPLIANT)
+ return -1;
+ s->mpeg_f_code[0][0] = f_code;
+ s->mpeg_f_code[0][1] = f_code;
+ }
+ if (s->pict_type == B_TYPE) {
+ s->full_pel[1] = get_bits1(&s->gb);
+ f_code = get_bits(&s->gb, 3);
+ if (f_code == 0 && avctx->error_resilience >= FF_ER_COMPLIANT)
+ return -1;
+ s->mpeg_f_code[1][0] = f_code;
+ s->mpeg_f_code[1][1] = f_code;
+ }
+ s->current_picture.pict_type= s->pict_type;
+ s->current_picture.key_frame= s->pict_type == I_TYPE;
+
+ 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;
+ s->first_slice = 1;
+ 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); /* profil 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;
+
+ dprintf("sequence extension\n");
+ s->codec_id= s->avctx->codec_id= CODEC_ID_MPEG2VIDEO;
+ s->avctx->sub_id = 2; /* indicates mpeg2 found */
+
+ 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){
+ skip_bits(&s->gb, 8); /* color primaries */
+ skip_bits(&s->gb, 8); /* transfer_characteristics */
+ skip_bits(&s->gb, 8); /* matrix_coefficients */
+ }
+ w= get_bits(&s->gb, 14);
+ skip_bits(&s->gb, 1); //marker
+ h= get_bits(&s->gb, 14);
+ skip_bits(&s->gb, 1); //marker
+
+ 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 void mpeg_decode_quant_matrix_extension(MpegEncContext *s)
+{
+ int i, v, j;
+
+ dprintf("matrix extension\n");
+
+ if (get_bits1(&s->gb)) {
+ for(i=0;i<64;i++) {
+ v = get_bits(&s->gb, 8);
+ j= s->dsp.idct_permutation[ ff_zigzag_direct[i] ];
+ s->intra_matrix[j] = v;
+ s->chroma_intra_matrix[j] = v;
+ }
+ }
+ if (get_bits1(&s->gb)) {
+ for(i=0;i<64;i++) {
+ v = get_bits(&s->gb, 8);
+ j= s->dsp.idct_permutation[ ff_zigzag_direct[i] ];
+ s->inter_matrix[j] = v;
+ s->chroma_inter_matrix[j] = v;
+ }
+ }
+ if (get_bits1(&s->gb)) {
+ for(i=0;i<64;i++) {
+ v = get_bits(&s->gb, 8);
+ j= s->dsp.idct_permutation[ ff_zigzag_direct[i] ];
+ s->chroma_intra_matrix[j] = v;
+ }
+ }
+ if (get_bits1(&s->gb)) {
+ for(i=0;i<64;i++) {
+ v = get_bits(&s->gb, 8);
+ j= s->dsp.idct_permutation[ ff_zigzag_direct[i] ];
+ s->chroma_inter_matrix[j] = v;
+ }
+ }
+}
+
+static void mpeg_decode_picture_coding_extension(MpegEncContext *s)
+{
+ 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);
+ 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->picture_structure == PICT_FRAME){
+ s->first_field=0;
+ s->v_edge_pos= 16*s->mb_height;
+ }else{
+ s->first_field ^= 1;
+ s->v_edge_pos= 8*s->mb_height;
+ memset(s->mbskip_table, 0, s->mb_stride*s->mb_height);
+ }
+
+ 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 */
+ dprintf("intra_dc_precision=%d\n", s->intra_dc_precision);
+ dprintf("picture_structure=%d\n", s->picture_structure);
+ dprintf("top field first=%d\n", s->top_field_first);
+ dprintf("repeat first field=%d\n", s->repeat_first_field);
+ dprintf("conceal=%d\n", s->concealment_motion_vectors);
+ dprintf("intra_vlc_format=%d\n", s->intra_vlc_format);
+ dprintf("alternate_scan=%d\n", s->alternate_scan);
+ dprintf("frame_pred_frame_dct=%d\n", s->frame_pred_frame_dct);
+ dprintf("progressive_frame=%d\n", s->progressive_frame);
+}
+
+static void mpeg_decode_extension(AVCodecContext *avctx,
+ const uint8_t *buf, int buf_size)
+{
+ Mpeg1Context *s1 = avctx->priv_data;
+ MpegEncContext *s = &s1->mpeg_enc_ctx;
+ int ext_type;
+
+ init_get_bits(&s->gb, buf, buf_size*8);
+
+ ext_type = get_bits(&s->gb, 4);
+ switch(ext_type) {
+ case 0x1:
+ mpeg_decode_sequence_extension(s1);
+ break;
+ case 0x2:
+ mpeg_decode_sequence_display_extension(s1);
+ break;
+ case 0x3:
+ mpeg_decode_quant_matrix_extension(s);
+ break;
+ case 0x7:
+ mpeg_decode_picture_display_extension(s1);
+ break;
+ case 0x8:
+ mpeg_decode_picture_coding_extension(s);
+ break;
+ }
+}
+
+static void exchange_uv(MpegEncContext *s){
+ short * tmp = s->pblocks[4];
+ s->pblocks[4] = s->pblocks[5];
+ s->pblocks[5] = tmp;
+}
+
+static int mpeg_field_start(MpegEncContext *s){
+ AVCodecContext *avctx= s->avctx;
+ Mpeg1Context *s1 = (Mpeg1Context*)s;
+
+ /* start frame decoding */
+ if(s->first_field || s->picture_structure==PICT_FRAME){
+ if(MPV_frame_start(s, avctx) < 0)
+ return -1;
+
+ ff_er_frame_start(s);
+
+ /* first check if we must repeat the frame */
+ s->current_picture_ptr->repeat_pict = 0;
+ if (s->repeat_first_field) {
+ if (s->progressive_sequence) {
+ if (s->top_field_first)
+ s->current_picture_ptr->repeat_pict = 4;
+ else
+ s->current_picture_ptr->repeat_pict = 2;
+ } else if (s->progressive_frame) {
+ s->current_picture_ptr->repeat_pict = 1;
+ }
+ }
+
+ *s->current_picture_ptr->pan_scan= s1->pan_scan;
+ }else{ //second field
+ int i;
+
+ if(!s->current_picture_ptr){
+ av_log(s->avctx, AV_LOG_ERROR, "first field missing\n");
+ return -1;
+ }
+
+ for(i=0; i<4; i++){
+ s->current_picture.data[i] = s->current_picture_ptr->data[i];
+ if(s->picture_structure == PICT_BOTTOM_FIELD){
+ s->current_picture.data[i] += s->current_picture_ptr->linesize[i];
+ }
+ }
+ }
+#ifdef HAVE_XVMC
+// MPV_frame_start will call this function too,
+// but we need to call it on every field
+ if(s->avctx->xvmc_acceleration)
+ XVMC_field_start(s,avctx);
+#endif
+
+ return 0;
+}
+
+#define DECODE_SLICE_ERROR -1
+#define DECODE_SLICE_OK 0
+
+/**
+ * decodes a slice. MpegEncContext.mb_y must be set to the MB row from the startcode
+ * @return DECODE_SLICE_ERROR if the slice is damaged<br>
+ * DECODE_SLICE_OK if this slice is ok<br>
+ */
+static int mpeg_decode_slice(Mpeg1Context *s1, int mb_y,
+ const uint8_t **buf, int buf_size)
+{
+ MpegEncContext *s = &s1->mpeg_enc_ctx;
+ AVCodecContext *avctx= s->avctx;
+ int ret;
+ const int field_pic= s->picture_structure != PICT_FRAME;
+ const int lowres= s->avctx->lowres;
+
+ s->resync_mb_x=
+ s->resync_mb_y= -1;
+
+ if (mb_y<<field_pic >= s->mb_height){
+ av_log(s->avctx, AV_LOG_ERROR, "slice below image (%d >= %d)\n", mb_y, s->mb_height);
+ return -1;
+ }
+
+ init_get_bits(&s->gb, *buf, buf_size*8);
+
+ 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;
+
+ for(;;) {
+ 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;
+ }
+ }
+
+ 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 == I_TYPE ? "I" : (s->pict_type == P_TYPE ? "P" : (s->pict_type == B_TYPE ? "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(;;) {
+#ifdef HAVE_XVMC
+ //one 1 we memcpy blocks in xvmcvideo
+ if(s->avctx->xvmc_acceleration > 1)
+ XVMC_init_block(s);//set s->block
+#endif
+
+ ret = mpeg_decode_mb(s, s->block);
+ s->chroma_qscale= s->qscale;
+
+ dprintf("ret=%d\n", ret);
+ if (ret < 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 = field_pic ? 2*s->b8_stride : s->b8_stride;
+ int xy = s->mb_x*2 + s->mb_y*2*wrap;
+ int motion_x, motion_y, dir, i;
+ if(field_pic && !s->first_field)
+ xy += wrap/2;
+
+ for(i=0; i<2; i++){
+ for(dir=0; dir<2; dir++){
+ if (s->mb_intra || (dir==1 && s->pict_type != B_TYPE)) {
+ 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][xy ]=
+ s->current_picture.ref_index [dir][xy + 1]= s->field_select[dir][i];
+ assert(s->field_select[dir][i]==0 || s->field_select[dir][i]==1);
+ }
+ xy += wrap;
+ }
+ }
+
+ s->dest[0] += 16 >> lowres;
+ s->dest[1] += 16 >> (s->chroma_x_shift + lowres);
+ s->dest[2] += 16 >> (s->chroma_x_shift + lowres);
+
+ MPV_decode_mb(s, s->block);
+
+ if (++s->mb_x >= s->mb_width) {
+ const int mb_size= 16>>s->avctx->lowres;
+
+ ff_draw_horiz_band(s, mb_size*s->mb_y, mb_size);
+
+ s->mb_x = 0;
+ s->mb_y++;
+
+ if(s->mb_y<<field_pic >= s->mb_height){
+ int left= s->gb.size_in_bits - get_bits_count(&s->gb);
+ int is_d10= s->chroma_format==2 && s->pict_type==I_TYPE && 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 < 0 || (left && show_bits(&s->gb, FFMIN(left, 23)) && !is_d10)
+ || (avctx->error_resilience >= FF_ER_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 again increment */
+ 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;
+ }
+ }
+ }
+ }
+eos: // end of slice
+ *buf += get_bits_count(&s->gb)/8 - 1;
+//printf("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= arg;
+ const uint8_t *buf= s->gb.buffer;
+ int mb_y= s->start_mb_y;
+
+ s->error_count= 3*(s->end_mb_y - s->start_mb_y)*s->mb_width;
+
+ for(;;){
+ uint32_t start_code;
+ int ret;
+
+ ret= mpeg_decode_slice((Mpeg1Context*)s, mb_y, &buf, s->gb.buffer_end - buf);
+ emms_c();
+//av_log(c, AV_LOG_DEBUG, "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->error_count);
+ if(ret < 0){
+ if(s->resync_mb_x>=0 && s->resync_mb_y>=0)
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, AC_ERROR|DC_ERROR|MV_ERROR);
+ }else{
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, AC_END|DC_END|MV_END);
+ }
+
+ if(s->mb_y == s->end_mb_y)
+ return 0;
+
+ start_code= -1;
+ buf = ff_find_start_code(buf, s->gb.buffer_end, &start_code);
+ mb_y= start_code - SLICE_MIN_START_CODE;
+ if(mb_y < 0 || mb_y >= s->end_mb_y)
+ return -1;
+ }
+
+ return 0; //not reached
+}
+
+/**
+ * handles slice ends.
+ * @return 1 if it seems to be the last slice of
+ */
+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;
+
+#ifdef HAVE_XVMC
+ if(s->avctx->xvmc_acceleration)
+ XVMC_field_end(s);
+#endif
+ /* end of slice reached */
+ if (/*s->mb_y<<field_pic == s->mb_height &&*/ !s->first_field) {
+ /* end of image */
+
+ s->current_picture_ptr->qscale_type= FF_QSCALE_TYPE_MPEG2;
+
+ ff_er_frame_end(s);
+
+ MPV_frame_end(s);
+
+ if (s->pict_type == B_TYPE || s->low_delay) {
+ *pict= *(AVFrame*)s->current_picture_ptr;
+ ff_print_debug_info(s, pict);
+ } else {
+ 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) {
+ *pict= *(AVFrame*)s->last_picture_ptr;
+ ff_print_debug_info(s, pict);
+ }
+ }
+
+ 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 ||
+ (width % 2) != 0 || (height % 2) != 0)
+ return -1;
+ s->aspect_ratio_info= get_bits(&s->gb, 4);
+ if (s->aspect_ratio_info == 0)
+ 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)) {
+ for(i=0;i<64;i++) {
+ v = get_bits(&s->gb, 8);
+ if(v==0){
+ av_log(s->avctx, AV_LOG_ERROR, "intra matrix damaged\n");
+ return -1;
+ }
+ j = s->dsp.idct_permutation[ ff_zigzag_direct[i] ];
+ s->intra_matrix[j] = v;
+ s->chroma_intra_matrix[j] = v;
+ }
+#ifdef DEBUG
+ dprintf("intra matrix present\n");
+ for(i=0;i<64;i++)
+ dprintf(" %d", s->intra_matrix[s->dsp.idct_permutation[i]]);
+ dprintf("\n");
+#endif
+ } 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)) {
+ for(i=0;i<64;i++) {
+ v = get_bits(&s->gb, 8);
+ if(v==0){
+ av_log(s->avctx, AV_LOG_ERROR, "inter matrix damaged\n");
+ return -1;
+ }
+ j = s->dsp.idct_permutation[ ff_zigzag_direct[i] ];
+ s->inter_matrix[j] = v;
+ s->chroma_inter_matrix[j] = v;
+ }
+#ifdef DEBUG
+ dprintf("non intra matrix present\n");
+ for(i=0;i<64;i++)
+ dprintf(" %d", s->inter_matrix[s->dsp.idct_permutation[i]]);
+ dprintf("\n");
+#endif
+ } 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 mpeg2 parameters so that it emulates mpeg1 */
+ s->progressive_sequence = 1;
+ s->progressive_frame = 1;
+ s->picture_structure = PICT_FRAME;
+ s->frame_pred_frame_dct = 1;
+ s->chroma_format = 1;
+ s->codec_id= s->avctx->codec_id= CODEC_ID_MPEG1VIDEO;
+ avctx->sub_id = 1; /* indicates mpeg1 */
+ s->out_format = FMT_MPEG1;
+ s->swap_uv = 0;//AFAIK VCR2 don't 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 mpeg1 context decoding */
+ s->out_format = FMT_MPEG1;
+ if (s1->mpeg_enc_ctx_allocated) {
+ MPV_common_end(s);
+ }
+ s->width = avctx->coded_width;
+ s->height = avctx->coded_height;
+ avctx->has_b_frames= 0; //true?
+ s->low_delay= 1;
+
+ if(avctx->xvmc_acceleration){
+ avctx->pix_fmt = avctx->get_format(avctx,pixfmt_xvmc_mpg2_420);
+ }else{
+ avctx->pix_fmt = avctx->get_format(avctx,pixfmt_yuv_420);
+ }
+
+ if( avctx->pix_fmt == PIX_FMT_XVMC_MPEG2_IDCT )
+ if( avctx->idct_algo == FF_IDCT_AUTO )
+ avctx->idct_algo = FF_IDCT_SIMPLE;
+
+ if (MPV_common_init(s) < 0)
+ return -1;
+ 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
+ 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->frame_pred_frame_dct = 1;
+ s->chroma_format = 1;
+ s->codec_id= s->avctx->codec_id= CODEC_ID_MPEG2VIDEO;
+ avctx->sub_id = 2; /* indicates mpeg2 */
+ return 0;
+}
+
+
+static void mpeg_decode_user_data(AVCodecContext *avctx,
+ const uint8_t *buf, int buf_size)
+{
+ const uint8_t *p;
+ int len, flags;
+ p = buf;
+ len = buf_size;
+
+ /* we parse the DTG active format information */
+ if (len >= 5 &&
+ p[0] == 'D' && p[1] == 'T' && p[2] == 'G' && p[3] == '1') {
+ flags = p[4];
+ p += 5;
+ len -= 5;
+ if (flags & 0x80) {
+ /* skip event id */
+ if (len < 2)
+ return;
+ p += 2;
+ len -= 2;
+ }
+ if (flags & 0x40) {
+ if (len < 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 drop_frame_flag;
+ int time_code_hours, time_code_minutes;
+ int time_code_seconds, time_code_pictures;
+ int broken_link;
+
+ init_get_bits(&s->gb, buf, buf_size*8);
+
+ drop_frame_flag = get_bits1(&s->gb);
+
+ time_code_hours=get_bits(&s->gb,5);
+ time_code_minutes = get_bits(&s->gb,6);
+ skip_bits1(&s->gb);//marker bit
+ time_code_seconds = get_bits(&s->gb,6);
+ time_code_pictures = get_bits(&s->gb,6);
+
+ /*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)
+ av_log(s->avctx, AV_LOG_DEBUG, "GOP (%2d:%02d:%02d.[%02d]) broken_link=%d\n",
+ time_code_hours, time_code_minutes, time_code_seconds,
+ time_code_pictures, broken_link);
+}
+/**
+ * finds the end of the current frame in the bitstream.
+ * @return the position of the first byte of the next frame, or -1
+ */
+static int mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size)
+{
+ int i;
+ uint32_t state= pc->state;
+
+ i=0;
+ if(!pc->frame_start_found){
+ for(i=0; i<buf_size; i++){
+ i= ff_find_start_code(buf+i, buf+buf_size, &state) - buf - 1;
+ if(state >= SLICE_MIN_START_CODE && state <= SLICE_MAX_START_CODE){
+ i++;
+ pc->frame_start_found=1;
+ break;
+ }
+ }
+ }
+
+ if(pc->frame_start_found){
+ /* EOF considered as end of frame */
+ if (buf_size == 0)
+ return 0;
+ for(; i<buf_size; i++){
+ i= ff_find_start_code(buf+i, buf+buf_size, &state) - buf - 1;
+ if((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;
+ }
+ }
+ }
+ }
+ pc->state= state;
+ return END_NOT_FOUND;
+}
+
+/* handle buffering and image synchronisation */
+static int mpeg_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ Mpeg1Context *s = avctx->priv_data;
+ const uint8_t *buf_end;
+ const uint8_t *buf_ptr;
+ uint32_t start_code;
+ int ret, input_size;
+ AVFrame *picture = data;
+ MpegEncContext *s2 = &s->mpeg_enc_ctx;
+ dprintf("fill_buffer\n");
+
+ if (buf_size == 0) {
+ /* special case for last picture */
+ if (s2->low_delay==0 && s2->next_picture_ptr) {
+ *picture= *(AVFrame*)s2->next_picture_ptr;
+ s2->next_picture_ptr= NULL;
+
+ *data_size = sizeof(AVFrame);
+ }
+ return 0;
+ }
+
+ if(s2->flags&CODEC_FLAG_TRUNCATED){
+ int next= mpeg1_find_frame_end(&s2->parse_context, buf, buf_size);
+
+ if( ff_combine_frame(&s2->parse_context, next, &buf, &buf_size) < 0 )
+ return buf_size;
+ }
+
+ buf_ptr = buf;
+ buf_end = buf + buf_size;
+
+#if 0
+ if (s->repeat_field % 2 == 1) {
+ s->repeat_field++;
+ //fprintf(stderr,"\nRepeating last frame: %d -> %d! pict: %d %d", avctx->frame_number-1, avctx->frame_number,
+ // s2->picture_number, s->repeat_field);
+ if (avctx->flags & CODEC_FLAG_REPEAT_FIELD) {
+ *data_size = sizeof(AVPicture);
+ goto the_end;
+ }
+ }
+#endif
+
+ if(s->mpeg_enc_ctx_allocated==0 && avctx->codec_tag == ff_get_fourcc("VCR2"))
+ vcr2_init_sequence(avctx);
+
+ s->slice_count= 0;
+
+ for(;;) {
+ /* find start next code */
+ start_code = -1;
+ buf_ptr = ff_find_start_code(buf_ptr,buf_end, &start_code);
+ if (start_code > 0x1ff){
+ if(s2->pict_type != B_TYPE || avctx->skip_frame <= AVDISCARD_DEFAULT){
+ if(avctx->thread_count > 1){
+ int i;
+
+ avctx->execute(avctx, slice_decode_thread, (void**)&(s2->thread_context[0]), NULL, s->slice_count);
+ for(i=0; i<s->slice_count; i++)
+ s2->error_count += s2->thread_context[i]->error_count;
+ }
+ if (slice_end(avctx, picture)) {
+ if(s2->last_picture_ptr || s2->low_delay) //FIXME merge with the stuff in mpeg_decode_slice
+ *data_size = sizeof(AVPicture);
+ }
+ }
+ 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 %zd left %d\n", start_code, buf_ptr-buf, input_size);
+ }
+
+ /* prepare data for next start code */
+ switch(start_code) {
+ case SEQ_START_CODE:
+ mpeg1_decode_sequence(avctx, buf_ptr,
+ input_size);
+ break;
+
+ case PICTURE_START_CODE:
+ /* we have a complete image : we try to decompress it */
+ mpeg1_decode_picture(avctx,
+ buf_ptr, input_size);
+ 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;
+ case GOP_START_CODE:
+ s2->first_field=0;
+ mpeg_decode_gop(avctx,
+ buf_ptr, input_size);
+ break;
+ default:
+ if (start_code >= SLICE_MIN_START_CODE &&
+ start_code <= SLICE_MAX_START_CODE) {
+ int mb_y= start_code - SLICE_MIN_START_CODE;
+
+ if(s2->last_picture_ptr==NULL){
+ /* skip b frames if we dont have reference frames */
+ if(s2->pict_type==B_TYPE) break;
+ /* skip P frames if we dont have reference frame no valid header */
+// if(s2->pict_type==P_TYPE && s2->first_field && !s2->first_slice) break;
+ }
+ /* skip b frames if we are in a hurry */
+ if(avctx->hurry_up && s2->pict_type==B_TYPE) break;
+ if( (avctx->skip_frame >= AVDISCARD_NONREF && s2->pict_type==B_TYPE)
+ ||(avctx->skip_frame >= AVDISCARD_NONKEY && s2->pict_type!=I_TYPE)
+ || avctx->skip_frame >= AVDISCARD_ALL)
+ break;
+ /* skip everything if we are in a hurry>=5 */
+ if(avctx->hurry_up>=5) break;
+
+ if (!s->mpeg_enc_ctx_allocated) break;
+
+ if(s2->codec_id == CODEC_ID_MPEG2VIDEO){
+ if(mb_y < avctx->skip_top || mb_y >= s2->mb_height - avctx->skip_bottom)
+ break;
+ }
+
+ if(s2->first_slice){
+ s2->first_slice=0;
+ if(mpeg_field_start(s2) < 0)
+ return -1;
+ }
+
+ if(avctx->thread_count > 1){
+ int threshold= (s2->mb_height*s->slice_count + avctx->thread_count/2) / avctx->thread_count;
+ 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;
+ ff_update_duplicate_context(thread_context, s2);
+ }
+ init_get_bits(&thread_context->gb, buf_ptr, input_size*8);
+ s->slice_count++;
+ }
+ buf_ptr += 2; //FIXME add minimum num of bytes per slice
+ }else{
+ ret = mpeg_decode_slice(s, mb_y, &buf_ptr, input_size);
+ emms_c();
+
+ if(ret < 0){
+ if(s2->resync_mb_x>=0 && s2->resync_mb_y>=0)
+ ff_er_add_slice(s2, s2->resync_mb_x, s2->resync_mb_y, s2->mb_x, s2->mb_y, AC_ERROR|DC_ERROR|MV_ERROR);
+ }else{
+ ff_er_add_slice(s2, s2->resync_mb_x, s2->resync_mb_y, s2->mb_x-1, s2->mb_y, AC_END|DC_END|MV_END);
+ }
+ }
+ }
+ break;
+ }
+ }
+}
+
+static int mpeg_decode_end(AVCodecContext *avctx)
+{
+ Mpeg1Context *s = avctx->priv_data;
+
+ if (s->mpeg_enc_ctx_allocated)
+ MPV_common_end(&s->mpeg_enc_ctx);
+ return 0;
+}
+
+AVCodec mpeg1video_decoder = {
+ "mpeg1video",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MPEG1VIDEO,
+ sizeof(Mpeg1Context),
+ mpeg_decode_init,
+ NULL,
+ mpeg_decode_end,
+ mpeg_decode_frame,
+ CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY,
+ .flush= ff_mpeg_flush,
+};
+
+AVCodec mpeg2video_decoder = {
+ "mpeg2video",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MPEG2VIDEO,
+ sizeof(Mpeg1Context),
+ mpeg_decode_init,
+ NULL,
+ mpeg_decode_end,
+ mpeg_decode_frame,
+ CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY,
+ .flush= ff_mpeg_flush,
+};
+
+//legacy decoder
+AVCodec mpegvideo_decoder = {
+ "mpegvideo",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MPEG2VIDEO,
+ sizeof(Mpeg1Context),
+ mpeg_decode_init,
+ NULL,
+ mpeg_decode_end,
+ mpeg_decode_frame,
+ CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY,
+ .flush= ff_mpeg_flush,
+};
+
+#ifdef CONFIG_ENCODERS
+
+AVCodec mpeg1video_encoder = {
+ "mpeg1video",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MPEG1VIDEO,
+ sizeof(MpegEncContext),
+ encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+ .supported_framerates= ff_frame_rate_tab+1,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+ .capabilities= CODEC_CAP_DELAY,
+};
+
+AVCodec mpeg2video_encoder = {
+ "mpeg2video",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MPEG2VIDEO,
+ sizeof(MpegEncContext),
+ encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+ .supported_framerates= ff_frame_rate_tab+1,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV422P, -1},
+ .capabilities= CODEC_CAP_DELAY,
+};
+#endif
+
+#ifdef HAVE_XVMC
+static int mpeg_mc_decode_init(AVCodecContext *avctx){
+ Mpeg1Context *s;
+
+ if( avctx->thread_count > 1)
+ return -1;
+ if( !(avctx->slice_flags & SLICE_FLAG_CODED_ORDER) )
+ return -1;
+ if( !(avctx->slice_flags & SLICE_FLAG_ALLOW_FIELD) ){
+ dprintf("mpeg12.c: XvMC decoder will work better if SLICE_FLAG_ALLOW_FIELD is set\n");
+ }
+ mpeg_decode_init(avctx);
+ s = avctx->priv_data;
+
+ avctx->pix_fmt = PIX_FMT_XVMC_MPEG2_IDCT;
+ avctx->xvmc_acceleration = 2;//2 - the blocks are packed!
+
+ return 0;
+}
+
+AVCodec mpeg_xvmc_decoder = {
+ "mpegvideo_xvmc",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MPEG2VIDEO_XVMC,
+ sizeof(Mpeg1Context),
+ mpeg_mc_decode_init,
+ NULL,
+ mpeg_decode_end,
+ mpeg_decode_frame,
+ CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED| CODEC_CAP_HWACCEL | CODEC_CAP_DELAY,
+ .flush= ff_mpeg_flush,
+};
+
+#endif
+
+#ifdef CONFIG_MPEGVIDEO_PARSER
+static void mpegvideo_extract_headers(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ const uint8_t *buf, int buf_size)
+{
+ ParseContext1 *pc = s->priv_data;
+ const uint8_t *buf_end;
+ uint32_t start_code;
+ int frame_rate_index, ext_type, bytes_left;
+ int frame_rate_ext_n, frame_rate_ext_d;
+ int picture_structure, top_field_first, repeat_first_field, progressive_frame;
+ int horiz_size_ext, vert_size_ext, bit_rate_ext;
+//FIXME replace the crap with get_bits()
+ s->repeat_pict = 0;
+ buf_end = buf + buf_size;
+ while (buf < buf_end) {
+ start_code= -1;
+ buf= ff_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;
+ }
+ 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];
+ avcodec_set_dimensions(avctx, pc->width, pc->height);
+ frame_rate_index = buf[3] & 0xf;
+ pc->frame_rate.den = avctx->time_base.den = ff_frame_rate_tab[frame_rate_index].num;
+ pc->frame_rate.num = avctx->time_base.num = ff_frame_rate_tab[frame_rate_index].den;
+ avctx->bit_rate = ((buf[4]<<10) | (buf[5]<<2) | (buf[6]>>6))*400;
+ avctx->codec_id = CODEC_ID_MPEG1VIDEO;
+ avctx->sub_id = 1;
+ }
+ 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);
+ avctx->bit_rate += (bit_rate_ext << 18) * 400;
+ avcodec_set_dimensions(avctx, pc->width, pc->height);
+ avctx->time_base.den = pc->frame_rate.den * (frame_rate_ext_n + 1);
+ avctx->time_base.num = pc->frame_rate.num * (frame_rate_ext_d + 1);
+ avctx->codec_id = CODEC_ID_MPEG2VIDEO;
+ avctx->sub_id = 2; /* forces MPEG2 */
+ }
+ break;
+ case 0x8: /* picture coding extension */
+ if (bytes_left >= 5) {
+ picture_structure = buf[2]&3;
+ 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 */
+ if (repeat_first_field) {
+ if (pc->progressive_sequence) {
+ if (top_field_first)
+ s->repeat_pict = 4;
+ else
+ s->repeat_pict = 2;
+ } else if (progressive_frame) {
+ s->repeat_pict = 1;
+ }
+ }
+
+ /* the packet only represents half a frame
+ XXX,FIXME maybe find a different solution */
+ if(picture_structure != 3)
+ s->repeat_pict = -1;
+ }
+ 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: ;
+}
+
+static int mpegvideo_parse(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size)
+{
+ ParseContext1 *pc1 = s->priv_data;
+ ParseContext *pc= &pc1->pc;
+ int next;
+
+ if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){
+ next= buf_size;
+ }else{
+ next= mpeg1_find_frame_end(pc, buf, buf_size);
+
+ if (ff_combine_frame(pc, next, (uint8_t **)&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);
+#if 0
+ printf("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);
+#endif
+
+ *poutbuf = (uint8_t *)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;
+
+ for(i=0; i<buf_size; i++){
+ state= (state<<8) | buf[i];
+ if(state != 0x1B3 && state != 0x1B5 && state < 0x200 && state >= 0x100)
+ return i-3;
+ }
+ return 0;
+}
+
+AVCodecParser mpegvideo_parser = {
+ { CODEC_ID_MPEG1VIDEO, CODEC_ID_MPEG2VIDEO },
+ sizeof(ParseContext1),
+ NULL,
+ mpegvideo_parse,
+ ff_parse1_close,
+ mpegvideo_split,
+};
+#endif /* !CONFIG_MPEGVIDEO_PARSER */
+
+/* this is ugly i know, but the alternative is too make
+ hundreds of vars global and prefix them with ff_mpeg1_
+ which is far uglier. */
+#include "mdec.c"
diff --git a/contrib/ffmpeg/libavcodec/mpeg12data.h b/contrib/ffmpeg/libavcodec/mpeg12data.h
new file mode 100644
index 000000000..6c96a495b
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mpeg12data.h
@@ -0,0 +1,469 @@
+/*
+ * MPEG1 codec / MPEG2 decoder
+ * copyright (c) 2000,2001 Fabrice Bellard
+ * copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file mpeg12data.h
+ * MPEG1/2 tables.
+ */
+
+const uint16_t ff_mpeg1_default_intra_matrix[64] = {
+ 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,
+};
+
+static const uint16_t vlc_dc_lum_code[12] = {
+ 0x4, 0x0, 0x1, 0x5, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe, 0x1ff,
+};
+static const unsigned char vlc_dc_lum_bits[12] = {
+ 3, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, 9,
+};
+
+static const uint16_t vlc_dc_chroma_code[12] = {
+ 0x0, 0x1, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe, 0x3fe, 0x3ff,
+};
+static const unsigned char 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,
+};
+
+static RLTable rl_mpeg1 = {
+ 111,
+ 111,
+ mpeg1_vlc,
+ mpeg1_run,
+ mpeg1_level,
+};
+
+static RLTable rl_mpeg2 = {
+ 111,
+ 111,
+ mpeg2_vlc,
+ mpeg1_run,
+ mpeg1_level,
+};
+
+static const uint8_t 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) */
+};
+
+static const uint8_t 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}
+};
+
+#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 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_frame_rate_tab[] = {
+ { 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},
+};
+
+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,
+};
+
+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 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ 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 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 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 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 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 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 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 *mpeg2_dc_scale_table[4]={
+ ff_mpeg1_dc_scale_table,
+ mpeg2_dc_scale_table1,
+ mpeg2_dc_scale_table2,
+ mpeg2_dc_scale_table3,
+};
+
+static const float 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,
+};
+
+static const AVRational 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},
+};
+
+static const uint8_t svcd_scan_offset_placeholder[14]={
+ 0x10, 0x0E,
+ 0x00, 0x80, 0x81,
+ 0x00, 0x80, 0x81,
+ 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff,
+};
diff --git a/contrib/ffmpeg/libavcodec/mpeg4data.h b/contrib/ffmpeg/libavcodec/mpeg4data.h
new file mode 100644
index 000000000..e199c6a14
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mpeg4data.h
@@ -0,0 +1,423 @@
+/*
+ * copyright (c) 2000,2001 Fabrice Bellard
+ * H263+ support
+ * copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file mpeg4data.h
+ * mpeg4 tables.
+ */
+
+// 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
+
+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,
+};
+
+#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 */
+const uint8_t 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 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 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 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 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,
+};
+
+static RLTable rl_intra = {
+ 102,
+ 67,
+ intra_vlc,
+ intra_run,
+ intra_level,
+};
+
+static const uint16_t inter_rvlc[170][2]={ //note this is identical to the intra rvlc except that its reordered
+{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,
+};
+
+static RLTable 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,
+};
+
+static RLTable rvlc_rl_intra = {
+ 169,
+ 103,
+ intra_rvlc,
+ intra_rvlc_run,
+ intra_rvlc_level,
+};
+
+static const uint16_t 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},
+};
+
+static const uint8_t mb_type_b_tab[4][2] = {
+ {1, 1}, {1, 2}, {1, 3}, {1, 4},
+};
+
+static const AVRational 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},
+};
+
+/* 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
+};
+
+static const uint8_t mpeg4_dc_threshold[8]={
+ 99, 13, 15, 17, 19, 21, 23, 0
+};
diff --git a/contrib/ffmpeg/libavcodec/mpegaudio.c b/contrib/ffmpeg/libavcodec/mpegaudio.c
new file mode 100644
index 000000000..2e5e28a18
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mpegaudio.c
@@ -0,0 +1,801 @@
+/*
+ * 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 mpegaudio.c
+ * The simplest mpeg audio layer 2 encoder.
+ */
+
+#include "avcodec.h"
+#include "bitstream.h"
+#include "mpegaudio.h"
+
+/* currently, cannot change these constants (need to modify
+ quantization stage) */
+#define MUL(a,b) (((int64_t)(a) * (int64_t)(b)) >> FRAC_BITS)
+#define FIX(a) ((int)((a) * (1 << FRAC_BITS)))
+
+#define SAMPLES_BUF_SIZE 4096
+
+typedef struct MpegAudioContext {
+ PutBitContext pb;
+ int nb_channels;
+ int freq, bit_rate;
+ 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 */
+ int64_t nb_samples; /* total number of samples encoded */
+ /* 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 "mpegaudiotab.h"
+
+static 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 > 2)
+ return -1;
+ bitrate = bitrate / 1000;
+ s->nb_channels = channels;
+ s->freq = freq;
+ s->bit_rate = bitrate * 1000;
+ avctx->frame_size = MPA_FRAME_SIZE;
+
+ /* encoding freq */
+ s->lsf = 0;
+ for(i=0;i<3;i++) {
+ if (mpa_freq_tab[i] == freq)
+ break;
+ if ((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 -1;
+ }
+ s->freq_index = i;
+
+ /* encoding bitrate & frequency */
+ for(i=0;i<15;i++) {
+ if (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 -1;
+ }
+ 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 = l2_select_table(bitrate, s->nb_channels, freq, s->lsf);
+
+ /* number of used subbands */
+ s->sblimit = sblimit_table[table];
+ s->alloc_table = alloc_tables[table];
+
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_DEBUG, "%d kb/s, %d Hz, frame_size=%d bits, table=%d, padincr=%x\n",
+ bitrate, freq, s->frame_size, table, s->frame_frac_incr);
+#endif
+
+ for(i=0;i<s->nb_channels;i++)
+ s->samples_offset[i] = 0;
+
+ for(i=0;i<257;i++) {
+ int v;
+ v = 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)(pow(2.0, (3 - i) / 3.0) * (1 << 20));
+ if (v <= 0)
+ v = 1;
+ scale_factor_table[i] = v;
+#ifdef USE_FLOATS
+ scale_factor_inv_table[i] = pow(2.0, -(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) * pow(2.0, (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 = quant_bits[i];
+ if (v < 0)
+ v = -v;
+ else
+ v = v * 3;
+ total_quant_bits[i] = 12 * v;
+ }
+
+ avctx->coded_frame= avcodec_alloc_frame();
+ avctx->coded_frame->key_frame= 1;
+
+ 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, short *samples, int incr)
+{
+ short *p, *q;
+ int sum, offset, i, j;
+ int tmp[64];
+ int tmp1[32];
+ int *out;
+
+ // print_pow1(samples, 1152);
+
+ 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;
+
+ // print_pow(s->sb_samples, 1152);
+}
+
+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<sblimit;j++) {
+ for(i=0;i<3;i++) {
+ /* find the max absolute value */
+ p = &sb_samples[i][0][j];
+ vmax = abs(*p);
+ for(k=1;k<12;k++) {
+ p += SBLIMIT;
+ v = abs(*p);
+ if (v > vmax)
+ vmax = v;
+ }
+ /* compute the scale factor index using log 2 computations */
+ if (vmax > 0) {
+ 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 */
+ }
+
+#if 0
+ printf("%2d:%d in=%x %x %d\n",
+ j, i, vmax, scale_factor_table[index], index);
+#endif
+ /* store the scale factor */
+ assert(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:
+ assert(0); //cant happen
+ code = 0; /* kill warning */
+ }
+
+#if 0
+ printf("%d: %2d %2d %2d %d %d -> %d\n", j,
+ sf[0], sf[1], sf[2], d1, d2, code);
+#endif
+ 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;i<s->sblimit;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;i<s->sblimit;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 = 0x80000000;
+ for(ch=0;ch<s->nb_channels;ch++) {
+ for(i=0;i<s->sblimit;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 0
+ printf("current=%d max=%d max_sb=%d alloc=%d\n",
+ current_frame_size, max_frame_size, max_sb,
+ bit_alloc[max_sb]);
+#endif
+ if (max_sb < 0)
+ break;
+
+ /* find alloc table entry (XXX: not optimal, should use
+ pointer table) */
+ alloc = s->alloc_table;
+ for(i=0;i<max_sb;i++) {
+ alloc += 1 << alloc[0];
+ }
+
+ if (subband_status[max_ch][max_sb] == SB_NOTALLOCATED) {
+ /* nothing was coded for this band: add the necessary bits */
+ incr = 2 + nb_scale_factors[s->scale_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;
+ assert(*padding >= 0);
+
+#if 0
+ for(i=0;i<s->sblimit;i++) {
+ printf("%d ", bit_alloc[i]);
+ }
+ printf("\n");
+#endif
+}
+
+/*
+ * 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;i<s->sblimit;i++) {
+ bit_alloc_bits = s->alloc_table[j];
+ for(ch=0;ch<s->nb_channels;ch++) {
+ put_bits(p, bit_alloc_bits, bit_alloc[ch][i]);
+ }
+ j += 1 << bit_alloc_bits;
+ }
+
+ /* scale codes */
+ for(i=0;i<s->sblimit;i++) {
+ for(ch=0;ch<s->nb_channels;ch++) {
+ if (bit_alloc[ch][i])
+ put_bits(p, 2, s->scale_code[ch][i]);
+ }
+ }
+
+ /* scale factors */
+ for(i=0;i<s->sblimit;i++) {
+ for(ch=0;ch<s->nb_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;i<s->sblimit;i++) {
+ bit_alloc_bits = s->alloc_table[j];
+ for(ch=0;ch<s->nb_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 = 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;
+ assert(q[m] >= 0 && q[m] < steps);
+ }
+ bits = 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]));
+#if 0
+ printf("%d: gr1 %d\n",
+ i, q[0] + steps * (q[1] + steps * q[2]));
+#endif
+ } else {
+#if 0
+ printf("%d: gr3 %d %d %d\n",
+ i, q[0], q[1], q[2]);
+#endif
+ 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;i<padding;i++)
+ put_bits(p, 1, 0);
+
+ /* flush */
+ flush_put_bits(p);
+}
+
+static int MPA_encode_frame(AVCodecContext *avctx,
+ unsigned char *frame, int buf_size, void *data)
+{
+ MpegAudioContext *s = avctx->priv_data;
+ short *samples = data;
+ short smr[MPA_MAX_CHANNELS][SBLIMIT];
+ unsigned char bit_alloc[MPA_MAX_CHANNELS][SBLIMIT];
+ int padding, i;
+
+ for(i=0;i<s->nb_channels;i++) {
+ filter(s, i, samples + i, s->nb_channels);
+ }
+
+ for(i=0;i<s->nb_channels;i++) {
+ compute_scale_factors(s->scale_code[i], s->scale_factors[i],
+ s->sb_samples[i], s->sblimit);
+ }
+ for(i=0;i<s->nb_channels;i++) {
+ psycho_acoustic_model(s, smr[i]);
+ }
+ compute_bit_allocation(s, smr, bit_alloc, &padding);
+
+ init_put_bits(&s->pb, frame, MPA_MAX_CODED_FRAME_SIZE);
+
+ encode_frame(s, bit_alloc, padding);
+
+ s->nb_samples += MPA_FRAME_SIZE;
+ return pbBufPtr(&s->pb) - s->pb.buf;
+}
+
+static int MPA_encode_close(AVCodecContext *avctx)
+{
+ av_freep(&avctx->coded_frame);
+ return 0;
+}
+
+#ifdef CONFIG_MP2_ENCODER
+AVCodec mp2_encoder = {
+ "mp2",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_MP2,
+ sizeof(MpegAudioContext),
+ MPA_encode_init,
+ MPA_encode_frame,
+ MPA_encode_close,
+ NULL,
+};
+#endif // CONFIG_MP2_ENCODER
+
+#undef FIX
diff --git a/contrib/ffmpeg/libavcodec/mpegaudio.h b/contrib/ffmpeg/libavcodec/mpegaudio.h
new file mode 100644
index 000000000..3eadf92a8
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mpegaudio.h
@@ -0,0 +1,106 @@
+/*
+ * 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 mpegaudio.h
+ * mpeg audio declarations for both encoder and decoder.
+ */
+
+/* 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
+
+/* header + layer + bitrate + freq + lsf/mpeg25 */
+#define SAME_HEADER_MASK \
+ (0xffe00000 | (3 << 17) | (0xf << 12) | (3 << 10) | (3 << 19))
+
+/* define USE_HIGHPRECISION to have a bit exact (but slower) mpeg
+ audio decoder */
+
+#ifdef USE_HIGHPRECISION
+#define FRAC_BITS 23 /* fractional bits for sb_samples and dct */
+#define WFRAC_BITS 16 /* fractional bits for window */
+#else
+#define FRAC_BITS 15 /* fractional bits for sb_samples and dct */
+#define WFRAC_BITS 14 /* fractional bits for window */
+#endif
+
+#if defined(USE_HIGHPRECISION) && defined(CONFIG_AUDIO_NONSHORT)
+typedef int32_t OUT_INT;
+#define OUT_MAX INT32_MAX
+#define OUT_MIN INT32_MIN
+#define OUT_SHIFT (WFRAC_BITS + FRAC_BITS - 31)
+#else
+typedef int16_t OUT_INT;
+#define OUT_MAX INT16_MAX
+#define OUT_MIN INT16_MIN
+#define OUT_SHIFT (WFRAC_BITS + FRAC_BITS - 15)
+#endif
+
+#if FRAC_BITS <= 15
+typedef int16_t MPA_INT;
+#else
+typedef int32_t MPA_INT;
+#endif
+
+int l2_select_table(int bitrate, int nb_channels, int freq, int lsf);
+int mpa_decode_header(AVCodecContext *avctx, uint32_t head, int *sample_rate);
+void ff_mpa_synth_init(MPA_INT *window);
+void ff_mpa_synth_filter(MPA_INT *synth_buf_ptr, int *synth_buf_offset,
+ MPA_INT *window, int *dither_state,
+ OUT_INT *samples, int incr,
+ int32_t sb_samples[SBLIMIT]);
+
+extern const uint16_t mpa_bitrate_tab[2][3][15];
+extern const uint16_t mpa_freq_tab[3];
+extern const unsigned char *alloc_tables[5];
+extern const double enwindow[512];
+extern const int sblimit_table[5];
+extern const int quant_steps[17];
+extern const int quant_bits[17];
+extern const int32_t mpa_enwindow[257];
+
+/* 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;
+}
diff --git a/contrib/ffmpeg/libavcodec/mpegaudiodec.c b/contrib/ffmpeg/libavcodec/mpegaudiodec.c
new file mode 100644
index 000000000..54bcee3b0
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mpegaudiodec.c
@@ -0,0 +1,2879 @@
+/*
+ * 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 mpegaudiodec.c
+ * MPEG Audio decoder.
+ */
+
+//#define DEBUG
+#include "avcodec.h"
+#include "bitstream.h"
+#include "dsputil.h"
+
+/*
+ * TODO:
+ * - in low precision mode, use more 16 bit multiplies in synth filter
+ * - test lsf / mpeg25 extensively.
+ */
+
+/* define USE_HIGHPRECISION to have a bit exact (but slower) mpeg
+ audio decoder */
+#ifdef CONFIG_MPEGAUDIO_HP
+# define USE_HIGHPRECISION
+#endif
+
+#include "mpegaudio.h"
+
+#include "mathops.h"
+
+#define FRAC_ONE (1 << FRAC_BITS)
+
+#define FIX(a) ((int)((a) * FRAC_ONE))
+/* WARNING: only correct for posititive numbers */
+#define FIXR(a) ((int)((a) * FRAC_ONE + 0.5))
+#define FRAC_RND(a) (((a) + (FRAC_ONE/2)) >> FRAC_BITS)
+
+#define FIXHR(a) ((int)((a) * (1LL<<32) + 0.5))
+
+/****************/
+
+#define HEADER_SIZE 4
+#define BACKSTEP_SIZE 512
+#define EXTRABYTES 24
+
+struct GranuleDef;
+
+typedef struct MPADecodeContext {
+ DECLARE_ALIGNED_8(uint8_t, last_buf[2*BACKSTEP_SIZE + EXTRABYTES]);
+ int last_buf_size;
+ int frame_size;
+ /* next header (used in free format parsing) */
+ uint32_t free_format_next_header;
+ int error_protection;
+ int layer;
+ int sample_rate;
+ int sample_rate_index; /* between 0 and 8 */
+ int bit_rate;
+ GetBitContext gb;
+ GetBitContext in_gb;
+ int nb_channels;
+ int mode;
+ int mode_ext;
+ int lsf;
+ MPA_INT synth_buf[MPA_MAX_CHANNELS][512 * 2] __attribute__((aligned(16)));
+ int synth_buf_offset[MPA_MAX_CHANNELS];
+ int32_t sb_samples[MPA_MAX_CHANNELS][36][SBLIMIT] __attribute__((aligned(16)));
+ int32_t mdct_buf[MPA_MAX_CHANNELS][SBLIMIT * 18]; /* previous samples, for layer 3 MDCT */
+#ifdef DEBUG
+ int frame_count;
+#endif
+ void (*compute_antialias)(struct MPADecodeContext *s, struct GranuleDef *g);
+ int adu_mode; ///< 0 for standard mp3, 1 for adu formatted mp3
+ int dither_state;
+ int error_resilience;
+} MPADecodeContext;
+
+/**
+ * Context for MP3On4 decoder
+ */
+typedef struct MP3On4DecodeContext {
+ int frames; ///< number of mp3 frames per block (number of mp3 decoder instances)
+ int chan_cfg; ///< channel config number
+ MPADecodeContext *mp3decctx[5]; ///< MPADecodeContext for every decoder instance
+} MP3On4DecodeContext;
+
+/* 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];
+ int32_t sb_hybrid[SBLIMIT * 18]; /* 576 samples */
+} GranuleDef;
+
+#define MODE_EXT_MS_STEREO 2
+#define MODE_EXT_I_STEREO 1
+
+/* layer 3 huffman tables */
+typedef struct HuffTable {
+ int xsize;
+ const uint8_t *bits;
+ const uint16_t *codes;
+} HuffTable;
+
+#include "mpegaudiodectab.h"
+
+static void compute_antialias_integer(MPADecodeContext *s, GranuleDef *g);
+static void compute_antialias_float(MPADecodeContext *s, GranuleDef *g);
+
+/* vlc structure for decoding layer 3 huffman tables */
+static VLC huff_vlc[16];
+static VLC huff_quad_vlc[2];
+/* computed from band_size_long */
+static uint16_t band_index_long[9][23];
+/* XXX: free when all decoders are closed */
+#define TABLE_4_3_SIZE (8191 + 16)*4
+static int8_t *table_4_3_exp;
+static uint32_t *table_4_3_value;
+static uint32_t exp_table[512];
+static uint32_t expval_table[512][16];
+/* intensity stereo coef table */
+static int32_t is_table[2][16];
+static int32_t is_table_lsf[2][2][16];
+static int32_t csa_table[8][4];
+static float csa_table_float[8][4];
+static int32_t mdct_win[8][36];
+
+/* 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(1.0 * (v)), FIXR(0.7937005259 * (v)), FIXR(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 */
+};
+
+static MPA_INT window[512] __attribute__((aligned(16)));
+
+/* 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);
+ assert(e>=1);
+ if (e > 31)
+ return 0;
+ m = (m + (1 << (e-1))) >> e;
+
+ return m;
+}
+
+/* all integer n^(4/3) computation code */
+#define DEV_ORDER 13
+
+#define POW_FRAC_BITS 24
+#define POW_FRAC_ONE (1 << POW_FRAC_BITS)
+#define POW_FIX(a) ((int)((a) * POW_FRAC_ONE))
+#define POW_MULL(a,b) (((int64_t)(a) * (int64_t)(b)) >> POW_FRAC_BITS)
+
+static int dev_4_3_coefs[DEV_ORDER];
+
+#if 0 /* unused */
+static int pow_mult3[3] = {
+ POW_FIX(1.0),
+ POW_FIX(1.25992104989487316476),
+ POW_FIX(1.58740105196819947474),
+};
+#endif
+
+static void int_pow_init(void)
+{
+ int i, a;
+
+ a = POW_FIX(1.0);
+ for(i=0;i<DEV_ORDER;i++) {
+ a = POW_MULL(a, POW_FIX(4.0 / 3.0) - i * POW_FIX(1.0)) / (i + 1);
+ dev_4_3_coefs[i] = a;
+ }
+}
+
+#if 0 /* unused, remove? */
+/* return the mantissa and the binary exponent */
+static int int_pow(int i, int *exp_ptr)
+{
+ int e, er, eq, j;
+ int a, a1;
+
+ /* renormalize */
+ a = i;
+ e = POW_FRAC_BITS;
+ while (a < (1 << (POW_FRAC_BITS - 1))) {
+ a = a << 1;
+ e--;
+ }
+ a -= (1 << POW_FRAC_BITS);
+ a1 = 0;
+ for(j = DEV_ORDER - 1; j >= 0; j--)
+ a1 = POW_MULL(a, dev_4_3_coefs[j] + a1);
+ a = (1 << POW_FRAC_BITS) + a1;
+ /* exponent compute (exact) */
+ e = e * 4;
+ er = e % 3;
+ eq = e / 3;
+ a = POW_MULL(a, pow_mult3[er]);
+ while (a >= 2 * POW_FRAC_ONE) {
+ a = a >> 1;
+ eq++;
+ }
+ /* convert to float */
+ while (a < POW_FRAC_ONE) {
+ a = a << 1;
+ eq--;
+ }
+ /* now POW_FRAC_ONE <= a < 2 * POW_FRAC_ONE */
+#if POW_FRAC_BITS > FRAC_BITS
+ a = (a + (1 << (POW_FRAC_BITS - FRAC_BITS - 1))) >> (POW_FRAC_BITS - FRAC_BITS);
+ /* correct overflow */
+ if (a >= 2 * (1 << FRAC_BITS)) {
+ a = a >> 1;
+ eq++;
+ }
+#endif
+ *exp_ptr = eq;
+ return a;
+}
+#endif
+
+static int decode_init(AVCodecContext * avctx)
+{
+ MPADecodeContext *s = avctx->priv_data;
+ static int init=0;
+ int i, j, k;
+
+#if defined(USE_HIGHPRECISION) && defined(CONFIG_AUDIO_NONSHORT)
+ avctx->sample_fmt= SAMPLE_FMT_S32;
+#else
+ avctx->sample_fmt= SAMPLE_FMT_S16;
+#endif
+ s->error_resilience= avctx->error_resilience;
+
+ if(avctx->antialias_algo != FF_AA_FLOAT)
+ s->compute_antialias= compute_antialias_integer;
+ else
+ s->compute_antialias= compute_antialias_float;
+
+ if (!init && !avctx->parse_only) {
+ /* 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_t_C(1) << n) * FRAC_ONE) / ((1 << n) - 1);
+ scale_factor_mult[i][0] = MULL(FIXR(1.0 * 2.0), norm);
+ scale_factor_mult[i][1] = MULL(FIXR(0.7937005259 * 2.0), norm);
+ scale_factor_mult[i][2] = MULL(FIXR(0.6299605249 * 2.0), norm);
+ dprintf("%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]);
+ }
+
+ ff_mpa_synth_init(window);
+
+ /* huffman decode tables */
+ for(i=1;i<16;i++) {
+ const HuffTable *h = &mpa_huff_tables[i];
+ int xsize, x, y;
+ unsigned int n;
+ uint8_t tmp_bits [512];
+ uint16_t tmp_codes[512];
+
+ memset(tmp_bits , 0, sizeof(tmp_bits ));
+ memset(tmp_codes, 0, sizeof(tmp_codes));
+
+ xsize = h->xsize;
+ n = xsize * 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 */
+ init_vlc(&huff_vlc[i], 7, 512,
+ tmp_bits, 1, 1, tmp_codes, 2, 2, 1);
+ }
+ for(i=0;i<2;i++) {
+ init_vlc(&huff_quad_vlc[i], i == 0 ? 7 : 4, 16,
+ mpa_quad_bits[i], 1, 1, mpa_quad_codes[i], 1, 1, 1);
+ }
+
+ 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 */
+ table_4_3_exp= av_mallocz_static(TABLE_4_3_SIZE * sizeof(table_4_3_exp[0]));
+ if(!table_4_3_exp)
+ return -1;
+ table_4_3_value= av_mallocz_static(TABLE_4_3_SIZE * sizeof(table_4_3_value[0]));
+ if(!table_4_3_value)
+ return -1;
+
+ int_pow_init();
+ for(i=1;i<TABLE_4_3_SIZE;i++) {
+ double f, fm;
+ int e, m;
+ f = pow((double)(i/4), 4.0 / 3.0) * 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;
+// av_log(NULL, AV_LOG_DEBUG, "%d %d %f\n", i, m, pow((double)i, 4.0 / 3.0));
+ table_4_3_exp[i] = -e;
+ }
+ for(i=0; i<512*16; i++){
+ int exponent= (i>>4);
+ double f= pow(i&15, 4.0 / 3.0) * pow(2, (exponent-400)*0.25 + FRAC_BITS + 5);
+ expval_table[exponent][i&15]= llrint(f);
+ if((i&15)==1)
+ exp_table[exponent]= llrint(f);
+ }
+
+ for(i=0;i<7;i++) {
+ float f;
+ int 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 = pow(2.0, e / 4.0);
+ k = i & 1;
+ is_table_lsf[j][k ^ 1][i] = FIXR(f);
+ is_table_lsf[j][k][i] = FIXR(1.0);
+ dprintf("is_table_lsf %d %d: %x %x\n",
+ i, j, is_table_lsf[j][0][i], 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;
+ 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);
+ csa_table_float[i][0] = cs;
+ csa_table_float[i][1] = ca;
+ csa_table_float[i][2] = ca + cs;
+ csa_table_float[i][3] = ca - cs;
+// printf("%d %d %d %d\n", FIX(cs), FIX(cs-1), FIX(ca), FIX(cs)-FIX(ca));
+// av_log(NULL, AV_LOG_DEBUG,"%f %f %f %f\n", cs, ca, ca+cs, ca-cs);
+ }
+
+ /* 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 / cos(M_PI*(2*i + 19)/72);
+
+ if(j==2)
+ mdct_win[j][i/3] = FIXHR((d / (1<<5)));
+ else
+ mdct_win[j][i ] = FIXHR((d / (1<<5)));
+// av_log(NULL, AV_LOG_DEBUG, "%2d %d %f\n", i,j,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<36;i+=2) {
+ mdct_win[j + 4][i] = mdct_win[j][i];
+ mdct_win[j + 4][i + 1] = -mdct_win[j][i + 1];
+ }
+ }
+
+#if defined(DEBUG)
+ for(j=0;j<8;j++) {
+ av_log(avctx, AV_LOG_DEBUG, "win%d=\n", j);
+ for(i=0;i<36;i++)
+ av_log(avctx, AV_LOG_DEBUG, "%f, ", (double)mdct_win[j][i] / FRAC_ONE);
+ av_log(avctx, AV_LOG_DEBUG, "\n");
+ }
+#endif
+ init = 1;
+ }
+
+#ifdef DEBUG
+ s->frame_count = 0;
+#endif
+ if (avctx->codec_id == CODEC_ID_MP3ADU)
+ s->adu_mode = 1;
+ return 0;
+}
+
+/* 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 = tab[a] + tab[b];\
+ tmp1 = tab[a] - tab[b];\
+ tab[a] = tmp0;\
+ tab[b] = MULH(tmp1<<(s), c);\
+}
+
+#define BF1(a, b, c, d)\
+{\
+ BF(a, b, COS4_0, 1);\
+ BF(c, d,-COS4_0, 1);\
+ tab[c] += tab[d];\
+}
+
+#define BF2(a, b, c, d)\
+{\
+ BF(a, b, COS4_0, 1);\
+ BF(c, d,-COS4_0, 1);\
+ tab[c] += tab[d];\
+ tab[a] += tab[c];\
+ tab[c] += tab[b];\
+ tab[b] += tab[d];\
+}
+
+#define ADD(a, b) tab[a] += tab[b]
+
+/* DCT32 without 1/sqrt(2) coef zero scaling. */
+static void dct32(int32_t *out, int32_t *tab)
+{
+ int tmp0, tmp1;
+
+ /* pass 1 */
+ BF( 0, 31, COS0_0 , 1);
+ BF(15, 16, COS0_15, 5);
+ /* pass 2 */
+ BF( 0, 15, COS1_0 , 1);
+ BF(16, 31,-COS1_0 , 1);
+ /* pass 1 */
+ BF( 7, 24, COS0_7 , 1);
+ BF( 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 */
+ BF( 3, 28, COS0_3 , 1);
+ BF(12, 19, COS0_12, 2);
+ /* pass 2 */
+ BF( 3, 12, COS1_3 , 1);
+ BF(19, 28,-COS1_3 , 1);
+ /* pass 1 */
+ BF( 4, 27, COS0_4 , 1);
+ BF(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 */
+ BF( 1, 30, COS0_1 , 1);
+ BF(14, 17, COS0_14, 3);
+ /* pass 2 */
+ BF( 1, 14, COS1_1 , 1);
+ BF(17, 30,-COS1_1 , 1);
+ /* pass 1 */
+ BF( 6, 25, COS0_6 , 1);
+ BF( 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 */
+ BF( 2, 29, COS0_2 , 1);
+ BF(13, 18, COS0_13, 3);
+ /* pass 2 */
+ BF( 2, 13, COS1_2 , 1);
+ BF(18, 29,-COS1_2 , 1);
+ /* pass 1 */
+ BF( 5, 26, COS0_5 , 1);
+ BF(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] = tab[0];
+ out[16] = tab[1];
+ out[ 8] = tab[2];
+ out[24] = tab[3];
+ out[ 4] = tab[4];
+ out[20] = tab[5];
+ out[12] = tab[6];
+ out[28] = tab[7];
+ out[ 2] = tab[8];
+ out[18] = tab[9];
+ out[10] = tab[10];
+ out[26] = tab[11];
+ out[ 6] = tab[12];
+ out[22] = tab[13];
+ out[14] = tab[14];
+ out[30] = tab[15];
+
+ ADD(24, 28);
+ ADD(28, 26);
+ ADD(26, 30);
+ ADD(30, 25);
+ ADD(25, 29);
+ ADD(29, 27);
+ ADD(27, 31);
+
+ out[ 1] = tab[16] + tab[24];
+ out[17] = tab[17] + tab[25];
+ out[ 9] = tab[18] + tab[26];
+ out[25] = tab[19] + tab[27];
+ out[ 5] = tab[20] + tab[28];
+ out[21] = tab[21] + tab[29];
+ out[13] = tab[22] + tab[30];
+ out[29] = tab[23] + tab[31];
+ out[ 3] = tab[24] + tab[20];
+ out[19] = tab[25] + tab[21];
+ out[11] = tab[26] + tab[22];
+ out[27] = tab[27] + tab[23];
+ out[ 7] = tab[28] + tab[18];
+ out[23] = tab[29] + tab[19];
+ out[15] = tab[30] + tab[17];
+ out[31] = tab[31];
+}
+
+#if FRAC_BITS <= 15
+
+static inline int round_sample(int *sum)
+{
+ int sum1;
+ sum1 = (*sum) >> OUT_SHIFT;
+ *sum &= (1<<OUT_SHIFT)-1;
+ if (sum1 < OUT_MIN)
+ sum1 = OUT_MIN;
+ else if (sum1 > OUT_MAX)
+ sum1 = OUT_MAX;
+ return sum1;
+}
+
+/* signed 16x16 -> 32 multiply add accumulate */
+#define MACS(rt, ra, rb) MAC16(rt, ra, rb)
+
+/* signed 16x16 -> 32 multiply */
+#define MULS(ra, rb) MUL16(ra, rb)
+
+#else
+
+static inline int round_sample(int64_t *sum)
+{
+ int sum1;
+ sum1 = (int)((*sum) >> OUT_SHIFT);
+ *sum &= (1<<OUT_SHIFT)-1;
+ if (sum1 < OUT_MIN)
+ sum1 = OUT_MIN;
+ else if (sum1 > OUT_MAX)
+ sum1 = OUT_MAX;
+ return sum1;
+}
+
+# define MULS(ra, rb) MUL64(ra, rb)
+#endif
+
+#define SUM8(sum, op, w, p) \
+{ \
+ sum op MULS((w)[0 * 64], p[0 * 64]);\
+ sum op MULS((w)[1 * 64], p[1 * 64]);\
+ sum op MULS((w)[2 * 64], p[2 * 64]);\
+ sum op MULS((w)[3 * 64], p[3 * 64]);\
+ sum op MULS((w)[4 * 64], p[4 * 64]);\
+ sum op MULS((w)[5 * 64], p[5 * 64]);\
+ sum op MULS((w)[6 * 64], p[6 * 64]);\
+ sum op MULS((w)[7 * 64], p[7 * 64]);\
+}
+
+#define SUM8P2(sum1, op1, sum2, op2, w1, w2, p) \
+{ \
+ int tmp;\
+ tmp = p[0 * 64];\
+ sum1 op1 MULS((w1)[0 * 64], tmp);\
+ sum2 op2 MULS((w2)[0 * 64], tmp);\
+ tmp = p[1 * 64];\
+ sum1 op1 MULS((w1)[1 * 64], tmp);\
+ sum2 op2 MULS((w2)[1 * 64], tmp);\
+ tmp = p[2 * 64];\
+ sum1 op1 MULS((w1)[2 * 64], tmp);\
+ sum2 op2 MULS((w2)[2 * 64], tmp);\
+ tmp = p[3 * 64];\
+ sum1 op1 MULS((w1)[3 * 64], tmp);\
+ sum2 op2 MULS((w2)[3 * 64], tmp);\
+ tmp = p[4 * 64];\
+ sum1 op1 MULS((w1)[4 * 64], tmp);\
+ sum2 op2 MULS((w2)[4 * 64], tmp);\
+ tmp = p[5 * 64];\
+ sum1 op1 MULS((w1)[5 * 64], tmp);\
+ sum2 op2 MULS((w2)[5 * 64], tmp);\
+ tmp = p[6 * 64];\
+ sum1 op1 MULS((w1)[6 * 64], tmp);\
+ sum2 op2 MULS((w2)[6 * 64], tmp);\
+ tmp = p[7 * 64];\
+ sum1 op1 MULS((w1)[7 * 64], tmp);\
+ sum2 op2 MULS((w2)[7 * 64], tmp);\
+}
+
+void ff_mpa_synth_init(MPA_INT *window)
+{
+ int i;
+
+ /* max = 18760, max sum over all 16 coefs : 44736 */
+ for(i=0;i<257;i++) {
+ int v;
+ v = mpa_enwindow[i];
+#if WFRAC_BITS < 16
+ v = (v + (1 << (16 - WFRAC_BITS - 1))) >> (16 - WFRAC_BITS);
+#endif
+ window[i] = v;
+ if ((i & 63) != 0)
+ v = -v;
+ if (i != 0)
+ window[512 - i] = v;
+ }
+}
+
+/* 32 sub band synthesis filter. Input: 32 sub band samples, Output:
+ 32 samples. */
+/* XXX: optimize by avoiding ring buffer usage */
+void ff_mpa_synth_filter(MPA_INT *synth_buf_ptr, int *synth_buf_offset,
+ MPA_INT *window, int *dither_state,
+ OUT_INT *samples, int incr,
+ int32_t sb_samples[SBLIMIT])
+{
+ int32_t tmp[32];
+ register MPA_INT *synth_buf;
+ register const MPA_INT *w, *w2, *p;
+ int j, offset, v;
+ OUT_INT *samples2;
+#if FRAC_BITS <= 15
+ int sum, sum2;
+#else
+ int64_t sum, sum2;
+#endif
+
+ dct32(tmp, sb_samples);
+
+ offset = *synth_buf_offset;
+ synth_buf = synth_buf_ptr + offset;
+
+ for(j=0;j<32;j++) {
+ v = tmp[j];
+#if FRAC_BITS <= 15
+ /* NOTE: can cause a loss in precision if very high amplitude
+ sound */
+ if (v > 32767)
+ v = 32767;
+ else if (v < -32768)
+ v = -32768;
+#endif
+ synth_buf[j] = v;
+ }
+ /* copy to avoid wrap */
+ memcpy(synth_buf + 512, synth_buf, 32 * sizeof(MPA_INT));
+
+ samples2 = samples + 31 * incr;
+ w = window;
+ w2 = window + 31;
+
+ sum = *dither_state;
+ p = synth_buf + 16;
+ SUM8(sum, +=, w, p);
+ p = synth_buf + 48;
+ SUM8(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, +=, sum2, -=, w, w2, p);
+ p = synth_buf + 48 - j;
+ SUM8P2(sum, -=, sum2, -=, 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(sum, -=, w + 32, p);
+ *samples = round_sample(&sum);
+ *dither_state= sum;
+
+ offset = (offset - 32) & 511;
+ *synth_buf_offset = offset;
+}
+
+#define C3 FIXHR(0.86602540378443864676/2)
+
+/* 0.5 / cos(pi*(2*i+1)/36) */
+static const int 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 int 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),
+};
+
+/* 12 points IMDCT. We compute it "by hand" by factorizing obvious
+ cases. */
+static void imdct12(int *out, int *in)
+{
+ int 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= MULH(2*in2, C3);
+ in3= MULH(4*in3, C3);
+
+ t1 = in0 - in4;
+ t2 = MULH(2*(in1 - in5), icos36h[4]);
+
+ out[ 7]=
+ out[10]= t1 + t2;
+ out[ 1]=
+ out[ 4]= t1 - t2;
+
+ in0 += in4>>1;
+ in4 = in0 + in2;
+ in5 += 2*in1;
+ in1 = MULH(in5 + in3, icos36h[1]);
+ out[ 8]=
+ out[ 9]= in4 + in1;
+ out[ 2]=
+ out[ 3]= in4 - in1;
+
+ in0 -= in2;
+ in5 = MULH(2*(in5 - in3), icos36h[7]);
+ out[ 0]=
+ out[ 5]= in0 - in5;
+ out[ 6]=
+ out[11]= in0 + in5;
+}
+
+/* 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)
+
+
+/* using Lee like decomposition followed by hand coded 9 points DCT */
+static void imdct36(int *out, int *buf, int *in, int *win)
+{
+ int i, j, t0, t1, t2, t3, s0, s1, s2, s3;
+ int 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;
+#if 0
+//more accurate but slower
+ int64_t t0, t1, t2, t3;
+ t2 = in1[2*4] + in1[2*8] - in1[2*2];
+
+ t3 = (in1[2*0] + (int64_t)(in1[2*6]>>1))<<32;
+ t1 = in1[2*0] - in1[2*6];
+ tmp1[ 6] = t1 - (t2>>1);
+ tmp1[16] = t1 + t2;
+
+ t0 = MUL64(2*(in1[2*2] + in1[2*4]), C2);
+ t1 = MUL64( in1[2*4] - in1[2*8] , -2*C8);
+ t2 = MUL64(2*(in1[2*2] + in1[2*8]), -C4);
+
+ tmp1[10] = (t3 - t0 - t2) >> 32;
+ tmp1[ 2] = (t3 + t0 + t1) >> 32;
+ tmp1[14] = (t3 + t2 - t1) >> 32;
+
+ tmp1[ 4] = MULH(2*(in1[2*5] + in1[2*7] - in1[2*1]), -C3);
+ t2 = MUL64(2*(in1[2*1] + in1[2*5]), C1);
+ t3 = MUL64( in1[2*5] - in1[2*7] , -2*C7);
+ t0 = MUL64(2*in1[2*3], C3);
+
+ t1 = MUL64(2*(in1[2*1] + in1[2*7]), -C5);
+
+ tmp1[ 0] = (t2 + t3 + t0) >> 32;
+ tmp1[12] = (t2 + t1 - t0) >> 32;
+ tmp1[ 8] = (t3 - t1 - t0) >> 32;
+#else
+ t2 = in1[2*4] + in1[2*8] - in1[2*2];
+
+ t3 = in1[2*0] + (in1[2*6]>>1);
+ t1 = in1[2*0] - in1[2*6];
+ tmp1[ 6] = t1 - (t2>>1);
+ tmp1[16] = t1 + t2;
+
+ t0 = MULH(2*(in1[2*2] + in1[2*4]), C2);
+ t1 = MULH( in1[2*4] - in1[2*8] , -2*C8);
+ t2 = MULH(2*(in1[2*2] + in1[2*8]), -C4);
+
+ tmp1[10] = t3 - t0 - t2;
+ tmp1[ 2] = t3 + t0 + t1;
+ tmp1[14] = t3 + t2 - t1;
+
+ tmp1[ 4] = MULH(2*(in1[2*5] + in1[2*7] - in1[2*1]), -C3);
+ t2 = MULH(2*(in1[2*1] + in1[2*5]), C1);
+ t3 = MULH( in1[2*5] - in1[2*7] , -2*C7);
+ t0 = MULH(2*in1[2*3], C3);
+
+ t1 = MULH(2*(in1[2*1] + in1[2*7]), -C5);
+
+ tmp1[ 0] = t2 + t3 + t0;
+ tmp1[12] = t2 + t1 - t0;
+ tmp1[ 8] = t3 - t1 - t0;
+#endif
+ }
+
+ 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 = MULH(2*(t3 + t2), icos36h[j]);
+ s3 = MULL(t3 - t2, icos36[8 - j]);
+
+ t0 = s0 + s1;
+ t1 = s0 - s1;
+ out[(9 + j)*SBLIMIT] = MULH(t1, win[9 + j]) + buf[9 + j];
+ out[(8 - j)*SBLIMIT] = MULH(t1, win[8 - j]) + buf[8 - j];
+ buf[9 + j] = MULH(t0, win[18 + 9 + j]);
+ buf[8 - j] = MULH(t0, win[18 + 8 - j]);
+
+ t0 = s2 + s3;
+ t1 = s2 - s3;
+ out[(9 + 8 - j)*SBLIMIT] = MULH(t1, win[9 + 8 - j]) + buf[9 + 8 - j];
+ out[( j)*SBLIMIT] = MULH(t1, win[ j]) + buf[ j];
+ buf[9 + 8 - j] = MULH(t0, win[18 + 9 + 8 - j]);
+ buf[ + j] = MULH(t0, win[18 + j]);
+ i += 4;
+ }
+
+ s0 = tmp[16];
+ s1 = MULH(2*tmp[17], icos36h[4]);
+ t0 = s0 + s1;
+ t1 = s0 - s1;
+ out[(9 + 4)*SBLIMIT] = MULH(t1, win[9 + 4]) + buf[9 + 4];
+ out[(8 - 4)*SBLIMIT] = MULH(t1, win[8 - 4]) + buf[8 - 4];
+ buf[9 + 4] = MULH(t0, win[18 + 9 + 4]);
+ buf[8 - 4] = MULH(t0, win[18 + 8 - 4]);
+}
+
+/* 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 */
+static int decode_header(MPADecodeContext *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 = 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 = 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)
+ dprintf("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)
+ dprintf("ms-");
+ if (s->mode_ext & MODE_EXT_I_STEREO)
+ dprintf("i-");
+ }
+ dprintf("stereo");
+ } else {
+ dprintf("mono");
+ }
+ dprintf("\n");
+#endif
+ return 0;
+}
+
+/* useful helper to get mpeg audio stream infos. Return -1 if error in
+ header, otherwise the coded frame size in bytes */
+int mpa_decode_header(AVCodecContext *avctx, uint32_t head, int *sample_rate)
+{
+ MPADecodeContext s1, *s = &s1;
+
+ if (ff_mpa_check_header(head) != 0)
+ return -1;
+
+ if (decode_header(s, head) != 0) {
+ return -1;
+ }
+
+ switch(s->layer) {
+ case 1:
+ avctx->frame_size = 384;
+ break;
+ case 2:
+ avctx->frame_size = 1152;
+ break;
+ default:
+ case 3:
+ if (s->lsf)
+ avctx->frame_size = 576;
+ else
+ avctx->frame_size = 1152;
+ break;
+ }
+
+ *sample_rate = s->sample_rate;
+ avctx->channels = s->nb_channels;
+ avctx->bit_rate = s->bit_rate;
+ avctx->sub_id = s->layer;
+ return s->frame_size;
+}
+
+/* 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;
+}
+
+/* bitrate is in kb/s */
+int 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;
+}
+
+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 = l2_select_table(s->bit_rate / 1000, s->nb_channels,
+ s->sample_rate, s->lsf);
+ sblimit = sblimit_table[table];
+ alloc_table = alloc_tables[table];
+
+ if (s->mode == MPA_JSTEREO)
+ bound = (s->mode_ext + 1) * 4;
+ else
+ bound = sblimit;
+
+ dprintf("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;
+ }
+
+#ifdef DEBUG
+ {
+ for(ch=0;ch<s->nb_channels;ch++) {
+ for(i=0;i<sblimit;i++)
+ dprintf(" %d", bit_alloc[ch][i]);
+ dprintf("\n");
+ }
+ }
+#endif
+
+ /* 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;
+ }
+ }
+ }
+ }
+
+#ifdef DEBUG
+ for(ch=0;ch<s->nb_channels;ch++) {
+ for(i=0;i<sblimit;i++) {
+ if (bit_alloc[ch][i]) {
+ sf = scale_factors[ch][i];
+ dprintf(" %d %d %d", sf[0], sf[1], sf[2]);
+ } else {
+ dprintf(" -");
+ }
+ }
+ dprintf("\n");
+ }
+#endif
+
+ /* 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 = quant_bits[qindex];
+ if (bits < 0) {
+ /* 3 values at the same time */
+ v = get_bits(&s->gb, -bits);
+ steps = quant_steps[qindex];
+ s->sb_samples[ch][k * 12 + l + 0][i] =
+ l2_unscale_group(steps, v % steps, scale);
+ v = v / steps;
+ s->sb_samples[ch][k * 12 + l + 1][i] =
+ l2_unscale_group(steps, v % steps, scale);
+ v = v / steps;
+ s->sb_samples[ch][k * 12 + l + 2][i] =
+ l2_unscale_group(steps, v, 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 = quant_bits[qindex];
+ if (bits < 0) {
+ /* 3 values at the same time */
+ v = get_bits(&s->gb, -bits);
+ steps = 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;
+}
+
+static inline void lsf_sf_expand(int *slen,
+ int sf, int n1, int n2, int n3)
+{
+ if (n3) {
+ slen[3] = sf % n3;
+ sf /= n3;
+ } else {
+ slen[3] = 0;
+ }
+ if (n2) {
+ slen[2] = sf % n2;
+ sf /= n2;
+ } else {
+ slen[2] = 0;
+ }
+ slen[1] = sf % n1;
+ 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)
+{
+ if (n == 0)
+ return 0;
+ else
+ return get_bits(s, n);
+}
+
+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, v;
+ int pos= get_bits_count(&s->gb);
+
+ if (pos >= end_pos){
+// av_log(NULL, AV_LOG_ERROR, "pos: %d %d %d %d\n", pos, end_pos, end_pos2, s_index);
+ if(s->in_gb.buffer && pos >= s->gb.size_in_bits){
+ s->gb= s->in_gb;
+ s->in_gb.buffer=NULL;
+ assert((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);
+ }
+// av_log(NULL, AV_LOG_ERROR, "new pos: %d %d\n", pos, end_pos);
+ 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];
+
+ dprintf("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){
+ v = expval_table[ exponent ][ x ];
+// v = expval_table[ (exponent&3) ][ x ] >> FFMIN(0 - (exponent>>2), 31);
+ }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){
+ v = 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){
+ v = 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(NULL, AV_LOG_INFO, "overread, skip %d enddists: %d %d\n", last_pos - pos, end_pos-pos, end_pos2-pos);
+ if(s->error_resilience >= FF_ER_COMPLIANT)
+ s_index=0;
+ break;
+ }
+// av_log(NULL, AV_LOG_ERROR, "pos2: %d %d %d %d\n", pos, end_pos, end_pos2, s_index);
+ if(s->in_gb.buffer && pos >= s->gb.size_in_bits){
+ s->gb= s->in_gb;
+ s->in_gb.buffer=NULL;
+ assert((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);
+ }
+// av_log(NULL, AV_LOG_ERROR, "new pos2: %d %d %d\n", pos, end_pos, s_index);
+ if(pos >= end_pos)
+ break;
+ }
+ last_pos= pos;
+
+ code = get_vlc2(&s->gb, vlc->table, vlc->bits, 1);
+ dprintf("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){
+ const static 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];
+ v = exp_table[ exponents[pos] ];
+// v = exp_table[ (exponents[pos]&3) ] >> FFMIN(0 - (exponents[pos]>>2), 31);
+ if(get_bits1(&s->gb))
+ v = -v;
+ g->sb_hybrid[pos] = v;
+ }
+ s_index+=4;
+ }
+ /* skip extension bits */
+ bits_left = end_pos - get_bits_count(&s->gb);
+//av_log(NULL, AV_LOG_ERROR, "left:%d buf:%p\n", bits_left, s->in_gb.buffer);
+ if (bits_left < 0 || bits_left > 16) {
+ av_log(NULL, AV_LOG_ERROR, "bits_left=%d\n", bits_left);
+ s_index=0;
+ }else if(bits_left > 0 && s->error_resilience >= FF_ER_AGGRESSIVE){
+ av_log(NULL, 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);
+
+ 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;
+ int32_t *ptr, *dst, *ptr1;
+ int32_t 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 + 48;
+ }
+ } 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;
+ int32_t v1, v2;
+ int sf_max, tmp0, tmp1, sf, len, non_zero_found;
+ int32_t (*is_tab)[16];
+ int32_t *tab0, *tab1;
+ 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] = MULL(tmp0, v1);
+ tab1[j] = MULL(tmp0, v2);
+ }
+ } 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] = MULL(tmp0 + tmp1, ISQRT2);
+ tab1[j] = MULL(tmp0 - tmp1, ISQRT2);
+ }
+ }
+ }
+ }
+ }
+
+ 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] = MULL(tmp0, v1);
+ tab1[j] = MULL(tmp0, v2);
+ }
+ } 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] = MULL(tmp0 + tmp1, ISQRT2);
+ tab1[j] = MULL(tmp0 - tmp1, ISQRT2);
+ }
+ }
+ }
+ }
+ } 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 */
+ 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;
+ }
+ }
+}
+
+static void compute_antialias_integer(MPADecodeContext *s,
+ GranuleDef *g)
+{
+ int32_t *ptr, *csa;
+ 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--) {
+ int tmp0, tmp1, tmp2;
+ csa = &csa_table[0][0];
+#define INT_AA(j) \
+ tmp0 = ptr[-1-j];\
+ tmp1 = ptr[ j];\
+ tmp2= MULH(tmp0 + tmp1, csa[0+4*j]);\
+ ptr[-1-j] = 4*(tmp2 - MULH(tmp1, csa[2+4*j]));\
+ ptr[ j] = 4*(tmp2 + MULH(tmp0, csa[3+4*j]));
+
+ INT_AA(0)
+ INT_AA(1)
+ INT_AA(2)
+ INT_AA(3)
+ INT_AA(4)
+ INT_AA(5)
+ INT_AA(6)
+ INT_AA(7)
+
+ ptr += 18;
+ }
+}
+
+static void compute_antialias_float(MPADecodeContext *s,
+ GranuleDef *g)
+{
+ int32_t *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--) {
+ float tmp0, tmp1;
+ float *csa = &csa_table_float[0][0];
+#define FLOAT_AA(j)\
+ tmp0= ptr[-1-j];\
+ tmp1= ptr[ j];\
+ ptr[-1-j] = lrintf(tmp0 * csa[0+4*j] - tmp1 * csa[1+4*j]);\
+ ptr[ j] = lrintf(tmp0 * csa[1+4*j] + tmp1 * csa[0+4*j]);
+
+ FLOAT_AA(0)
+ FLOAT_AA(1)
+ FLOAT_AA(2)
+ FLOAT_AA(3)
+ FLOAT_AA(4)
+ FLOAT_AA(5)
+ FLOAT_AA(6)
+ FLOAT_AA(7)
+
+ ptr += 18;
+ }
+}
+
+static void compute_imdct(MPADecodeContext *s,
+ GranuleDef *g,
+ int32_t *sb_samples,
+ int32_t *mdct_buf)
+{
+ int32_t *ptr, *win, *win1, *buf, *out_ptr, *ptr1;
+ int32_t out2[12];
+ int i, j, mdct_long_end, v, sblimit;
+
+ /* find last non zero block */
+ ptr = g->sb_hybrid + 576;
+ ptr1 = g->sb_hybrid + 2 * 18;
+ while (ptr >= ptr1) {
+ ptr -= 6;
+ v = ptr[0] | ptr[1] | ptr[2] | ptr[3] | ptr[4] | ptr[5];
+ if (v != 0)
+ 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;
+ }
+
+ buf = mdct_buf;
+ ptr = g->sb_hybrid;
+ for(j=0;j<mdct_long_end;j++) {
+ /* apply window & overlap with previous buffer */
+ out_ptr = sb_samples + j;
+ /* select window */
+ if (g->switch_point && j < 2)
+ win1 = mdct_win[0];
+ else
+ win1 = mdct_win[g->block_type];
+ /* select frequency inversion */
+ win = win1 + ((4 * 36) & -(j & 1));
+ imdct36(out_ptr, buf, ptr, win);
+ out_ptr += 18*SBLIMIT;
+ ptr += 18;
+ buf += 18;
+ }
+ for(j=mdct_long_end;j<sblimit;j++) {
+ /* select frequency inversion */
+ win = mdct_win[2] + ((4 * 36) & -(j & 1));
+ out_ptr = sb_samples + j;
+
+ for(i=0; i<6; i++){
+ *out_ptr = buf[i];
+ out_ptr += SBLIMIT;
+ }
+ imdct12(out2, ptr + 0);
+ for(i=0;i<6;i++) {
+ *out_ptr = MULH(out2[i], win[i]) + buf[i + 6*1];
+ buf[i + 6*2] = MULH(out2[i + 6], win[i + 6]);
+ out_ptr += SBLIMIT;
+ }
+ imdct12(out2, ptr + 1);
+ for(i=0;i<6;i++) {
+ *out_ptr = MULH(out2[i], win[i]) + buf[i + 6*2];
+ buf[i + 6*0] = MULH(out2[i + 6], win[i + 6]);
+ out_ptr += SBLIMIT;
+ }
+ imdct12(out2, ptr + 2);
+ for(i=0;i<6;i++) {
+ buf[i + 6*0] = MULH(out2[i], win[i]) + buf[i + 6*0];
+ buf[i + 6*1] = MULH(out2[i + 6], win[i + 6]);
+ buf[i + 6*2] = 0;
+ }
+ ptr += 18;
+ buf += 18;
+ }
+ /* zero bands */
+ for(j=sblimit;j<SBLIMIT;j++) {
+ /* overlap */
+ out_ptr = sb_samples + j;
+ for(i=0;i<18;i++) {
+ *out_ptr = buf[i];
+ buf[i] = 0;
+ out_ptr += SBLIMIT;
+ }
+ buf += 18;
+ }
+}
+
+#if defined(DEBUG)
+void sample_dump(int fnum, int32_t *tab, int n)
+{
+ static FILE *files[16], *f;
+ char buf[512];
+ int i;
+ int32_t v;
+
+ f = files[fnum];
+ if (!f) {
+ snprintf(buf, sizeof(buf), "/tmp/out%d.%s.pcm",
+ fnum,
+#ifdef USE_HIGHPRECISION
+ "hp"
+#else
+ "lp"
+#endif
+ );
+ f = fopen(buf, "w");
+ if (!f)
+ return;
+ files[fnum] = f;
+ }
+
+ if (fnum == 0) {
+ static int pos = 0;
+ av_log(NULL, AV_LOG_DEBUG, "pos=%d\n", pos);
+ for(i=0;i<n;i++) {
+ av_log(NULL, AV_LOG_DEBUG, " %0.4f", (double)tab[i] / FRAC_ONE);
+ if ((i % 18) == 17)
+ av_log(NULL, AV_LOG_DEBUG, "\n");
+ }
+ pos += n;
+ }
+ for(i=0;i<n;i++) {
+ /* normalize to 23 frac bits */
+ v = tab[i] << (23 - FRAC_BITS);
+ fwrite(&v, 1, sizeof(int32_t), f);
+ }
+}
+#endif
+
+
+/* main layer3 decoding function */
+static int mp_decode_layer3(MPADecodeContext *s)
+{
+ int nb_granules, main_data_begin, private_bits;
+ int gr, ch, blocksplit_flag, i, j, k, n, bits_pos;
+ GranuleDef granules[2][2], *g;
+ int16_t exponents[576];
+
+ /* read side info */
+ if (s->lsf) {
+ main_data_begin = get_bits(&s->gb, 8);
+ private_bits = get_bits(&s->gb, s->nb_channels);
+ nb_granules = 1;
+ } else {
+ main_data_begin = get_bits(&s->gb, 9);
+ if (s->nb_channels == 2)
+ private_bits = get_bits(&s->gb, 3);
+ else
+ private_bits = get_bits(&s->gb, 5);
+ nb_granules = 2;
+ for(ch=0;ch<s->nb_channels;ch++) {
+ granules[ch][0].scfsi = 0; /* all scale factors are transmitted */
+ granules[ch][1].scfsi = get_bits(&s->gb, 4);
+ }
+ }
+
+ for(gr=0;gr<nb_granules;gr++) {
+ for(ch=0;ch<s->nb_channels;ch++) {
+ dprintf("gr=%d ch=%d: side_info\n", gr, ch);
+ g = &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(NULL, AV_LOG_ERROR, "big_values too big\n");
+ return -1;
+ }
+
+ 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_bits(&s->gb, 1);
+ if (blocksplit_flag) {
+ g->block_type = get_bits(&s->gb, 2);
+ if (g->block_type == 0){
+ av_log(NULL, AV_LOG_ERROR, "invalid block type\n");
+ return -1;
+ }
+ g->switch_point = get_bits(&s->gb, 1);
+ 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);
+ /* compute huffman coded region sizes */
+ if (g->block_type == 2)
+ g->region_size[0] = (36 / 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);
+ } else {
+ int region_address1, region_address2, l;
+ 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);
+ dprintf("region1=%d region2=%d\n",
+ region_address1, region_address2);
+ g->region_size[0] =
+ band_index_long[s->sample_rate_index][region_address1 + 1] >> 1;
+ l = region_address1 + region_address2 + 2;
+ /* should not overflow */
+ if (l > 22)
+ l = 22;
+ g->region_size[1] =
+ band_index_long[s->sample_rate_index][l] >> 1;
+ }
+ /* convert region offsets to region sizes and truncate
+ size to big_values */
+ g->region_size[2] = (576 / 2);
+ j = 0;
+ for(i=0;i<3;i++) {
+ k = FFMIN(g->region_size[i], g->big_values);
+ g->region_size[i] = k - j;
+ j = k;
+ }
+
+ /* compute band indexes */
+ if (g->block_type == 2) {
+ if (g->switch_point) {
+ /* if switched mode, we handle the 36 first samples as
+ long blocks. For 8000Hz, we handle the 48 first
+ exponents as long blocks (XXX: check this!) */
+ if (s->sample_rate_index <= 2)
+ g->long_end = 8;
+ else if (s->sample_rate_index != 8)
+ g->long_end = 6;
+ else
+ g->long_end = 4; /* 8000 Hz */
+
+ g->short_start = 2 + (s->sample_rate_index != 8);
+ } else {
+ g->long_end = 0;
+ g->short_start = 0;
+ }
+ } else {
+ g->short_start = 13;
+ g->long_end = 22;
+ }
+
+ g->preflag = 0;
+ if (!s->lsf)
+ g->preflag = get_bits(&s->gb, 1);
+ g->scalefac_scale = get_bits(&s->gb, 1);
+ g->count1table_select = get_bits(&s->gb, 1);
+ dprintf("block_type=%d switch_point=%d\n",
+ g->block_type, g->switch_point);
+ }
+ }
+
+ if (!s->adu_mode) {
+ const uint8_t *ptr = s->gb.buffer + (get_bits_count(&s->gb)>>3);
+ assert((get_bits_count(&s->gb) & 7) == 0);
+ /* now we get bits from the main_data_begin offset */
+ dprintf("seekback: %d\n", main_data_begin);
+//av_log(NULL, AV_LOG_ERROR, "backstep:%d, lastbuf:%d\n", main_data_begin, s->last_buf_size);
+
+ memcpy(s->last_buf + s->last_buf_size, ptr, EXTRABYTES);
+ s->in_gb= s->gb;
+ init_get_bits(&s->gb, s->last_buf, s->last_buf_size*8);
+ skip_bits_long(&s->gb, 8*(s->last_buf_size - main_data_begin));
+ }
+
+ for(gr=0;gr<nb_granules;gr++) {
+ for(ch=0;ch<s->nb_channels;ch++) {
+ g = &granules[ch][gr];
+ if(get_bits_count(&s->gb)<0){
+ av_log(NULL, AV_LOG_ERROR, "mdb:%d, lastbuf:%d skiping granule %d\n",
+ main_data_begin, s->last_buf_size, gr);
+ skip_bits_long(&s->gb, g->part2_3_length);
+ memset(g->sb_hybrid, 0, sizeof(g->sb_hybrid));
+ if(get_bits_count(&s->gb) >= s->gb.size_in_bits && s->in_gb.buffer){
+ skip_bits_long(&s->in_gb, get_bits_count(&s->gb) - s->gb.size_in_bits);
+ s->gb= s->in_gb;
+ s->in_gb.buffer=NULL;
+ }
+ continue;
+ }
+
+ 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];
+ dprintf("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 = 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;
+ }
+#if defined(DEBUG)
+ {
+ dprintf("scfsi=%x gr=%d ch=%d scale_factors:\n",
+ g->scfsi, gr, ch);
+ for(i=0;i<j;i++)
+ dprintf(" %d", g->scale_factors[i]);
+ dprintf("\n");
+ }
+#endif
+ } 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;
+#if defined(DEBUG)
+ {
+ dprintf("gr=%d ch=%d scale_factors:\n",
+ gr, ch);
+ for(i=0;i<40;i++)
+ dprintf(" %d", g->scale_factors[i]);
+ dprintf("\n");
+ }
+#endif
+ }
+
+ exponents_from_scale_factors(s, g, exponents);
+
+ /* read Huffman coded residue */
+ huffman_decode(s, g, exponents, bits_pos + g->part2_3_length);
+#if defined(DEBUG)
+ sample_dump(0, g->sb_hybrid, 576);
+#endif
+ } /* ch */
+
+ if (s->nb_channels == 2)
+ compute_stereo(s, &granules[0][gr], &granules[1][gr]);
+
+ for(ch=0;ch<s->nb_channels;ch++) {
+ g = &granules[ch][gr];
+
+ reorder_block(s, g);
+#if defined(DEBUG)
+ sample_dump(0, g->sb_hybrid, 576);
+#endif
+ s->compute_antialias(s, g);
+#if defined(DEBUG)
+ sample_dump(1, g->sb_hybrid, 576);
+#endif
+ compute_imdct(s, g, &s->sb_samples[ch][18 * gr][0], s->mdct_buf[ch]);
+#if defined(DEBUG)
+ sample_dump(2, &s->sb_samples[ch][18 * gr][0], 576);
+#endif
+ }
+ } /* 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;
+ 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)
+ get_bits(&s->gb, 16);
+
+ dprintf("frame %d:\n", s->frame_count);
+ switch(s->layer) {
+ case 1:
+ nb_frames = mp_decode_layer1(s);
+ break;
+ case 2:
+ nb_frames = mp_decode_layer2(s);
+ break;
+ case 3:
+ default:
+ nb_frames = mp_decode_layer3(s);
+
+ s->last_buf_size=0;
+ if(s->in_gb.buffer){
+ align_get_bits(&s->gb);
+ i= (s->gb.size_in_bits - get_bits_count(&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(NULL, AV_LOG_ERROR, "invalid old backstep %d\n", i);
+ s->gb= s->in_gb;
+ s->in_gb.buffer= NULL;
+ }
+
+ align_get_bits(&s->gb);
+ assert((get_bits_count(&s->gb) & 7) == 0);
+ i= (s->gb.size_in_bits - get_bits_count(&s->gb))>>3;
+
+ if(i<0 || i > BACKSTEP_SIZE || nb_frames<0){
+ av_log(NULL, AV_LOG_ERROR, "invalid new backstep %d\n", i);
+ i= FFMIN(BACKSTEP_SIZE, buf_size - HEADER_SIZE);
+ }
+ assert(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;
+
+ break;
+ }
+#if defined(DEBUG)
+ for(i=0;i<nb_frames;i++) {
+ for(ch=0;ch<s->nb_channels;ch++) {
+ int j;
+ dprintf("%d-%d:", i, ch);
+ for(j=0;j<SBLIMIT;j++)
+ dprintf(" %0.6f", (double)s->sb_samples[ch][i][j] / FRAC_ONE);
+ dprintf("\n");
+ }
+ }
+#endif
+ /* apply the synthesis filter */
+ for(ch=0;ch<s->nb_channels;ch++) {
+ samples_ptr = samples + ch;
+ for(i=0;i<nb_frames;i++) {
+ ff_mpa_synth_filter(s->synth_buf[ch], &(s->synth_buf_offset[ch]),
+ window, &s->dither_state,
+ samples_ptr, s->nb_channels,
+ s->sb_samples[ch][i]);
+ samples_ptr += 32 * s->nb_channels;
+ }
+ }
+#ifdef DEBUG
+ s->frame_count++;
+#endif
+ return nb_frames * 32 * sizeof(OUT_INT) * s->nb_channels;
+}
+
+static int decode_frame(AVCodecContext * avctx,
+ void *data, int *data_size,
+ uint8_t * buf, int buf_size)
+{
+ MPADecodeContext *s = avctx->priv_data;
+ uint32_t header;
+ int out_size;
+ OUT_INT *out_samples = data;
+
+retry:
+ if(buf_size < HEADER_SIZE)
+ return -1;
+
+ header = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ if(ff_mpa_check_header(header) < 0){
+ buf++;
+// buf_size--;
+ av_log(avctx, AV_LOG_ERROR, "Header missing skipping one byte.\n");
+ goto retry;
+ }
+
+ if (decode_header(s, header) == 1) {
+ /* free format: prepare to compute frame size */
+ s->frame_size = -1;
+ return -1;
+ }
+ /* update codec info */
+ avctx->channels = s->nb_channels;
+ avctx->bit_rate = s->bit_rate;
+ avctx->sub_id = s->layer;
+ switch(s->layer) {
+ case 1:
+ avctx->frame_size = 384;
+ break;
+ case 2:
+ avctx->frame_size = 1152;
+ break;
+ case 3:
+ if (s->lsf)
+ avctx->frame_size = 576;
+ else
+ avctx->frame_size = 1152;
+ break;
+ }
+
+ if(s->frame_size<=0 || s->frame_size > buf_size){
+ av_log(avctx, AV_LOG_ERROR, "incomplete frame\n");
+ return -1;
+ }else if(s->frame_size < buf_size){
+ av_log(avctx, AV_LOG_ERROR, "incorrect frame size\n");
+ }
+
+ out_size = mp_decode_frame(s, out_samples, buf, buf_size);
+ if(out_size>=0){
+ *data_size = out_size;
+ avctx->sample_rate = s->sample_rate;
+ //FIXME maybe move the other codec info stuff from above here too
+ }else
+ av_log(avctx, AV_LOG_DEBUG, "Error while decoding MPEG audio frame.\n"); //FIXME return -1 / but also return the number of bytes consumed
+ s->frame_size = 0;
+ return buf_size;
+}
+
+static void flush(AVCodecContext *avctx){
+ MPADecodeContext *s = avctx->priv_data;
+ s->last_buf_size= 0;
+}
+
+#ifdef CONFIG_MP3ADU_DECODER
+static int decode_frame_adu(AVCodecContext * avctx,
+ void *data, int *data_size,
+ uint8_t * buf, int buf_size)
+{
+ MPADecodeContext *s = avctx->priv_data;
+ uint32_t header;
+ int len, out_size;
+ OUT_INT *out_samples = data;
+
+ len = buf_size;
+
+ // Discard too short frames
+ if (buf_size < HEADER_SIZE) {
+ *data_size = 0;
+ return buf_size;
+ }
+
+
+ if (len > MPA_MAX_CODED_FRAME_SIZE)
+ len = MPA_MAX_CODED_FRAME_SIZE;
+
+ // Get header and restore sync word
+ header = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3] | 0xffe00000;
+
+ if (ff_mpa_check_header(header) < 0) { // Bad header, discard frame
+ *data_size = 0;
+ return buf_size;
+ }
+
+ decode_header(s, header);
+ /* update codec info */
+ avctx->sample_rate = s->sample_rate;
+ avctx->channels = s->nb_channels;
+ avctx->bit_rate = s->bit_rate;
+ avctx->sub_id = s->layer;
+
+ avctx->frame_size=s->frame_size = len;
+
+ if (avctx->parse_only) {
+ out_size = buf_size;
+ } else {
+ out_size = mp_decode_frame(s, out_samples, buf, buf_size);
+ }
+
+ *data_size = out_size;
+ return buf_size;
+}
+#endif /* CONFIG_MP3ADU_DECODER */
+
+#ifdef CONFIG_MP3ON4_DECODER
+/* Next 3 arrays are indexed by channel config number (passed via codecdata) */
+static int mp3Frames[16] = {0,1,1,2,3,3,4,5,2}; /* number of mp3 decoder instances */
+static int mp3Channels[16] = {0,1,2,3,4,5,6,8,4}; /* total output channels */
+/* offsets into output buffer, assume output order is FL FR BL BR C LFE */
+static int chan_offset[9][5] = {
+ {0},
+ {0}, // C
+ {0}, // FLR
+ {2,0}, // C FLR
+ {2,0,3}, // C FLR BS
+ {4,0,2}, // C FLR BLRS
+ {4,0,2,5}, // C FLR BLRS LFE
+ {4,0,2,6,5}, // C FLR BLRS BLR LFE
+ {0,2} // FLR BLRS
+};
+
+
+static int decode_init_mp3on4(AVCodecContext * avctx)
+{
+ MP3On4DecodeContext *s = avctx->priv_data;
+ int i;
+
+ if ((avctx->extradata_size < 2) || (avctx->extradata == NULL)) {
+ av_log(avctx, AV_LOG_ERROR, "Codec extradata missing or too short.\n");
+ return -1;
+ }
+
+ s->chan_cfg = (((unsigned char *)avctx->extradata)[1] >> 3) & 0x0f;
+ s->frames = mp3Frames[s->chan_cfg];
+ if(!s->frames) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid channel config number.\n");
+ return -1;
+ }
+ avctx->channels = mp3Channels[s->chan_cfg];
+
+ /* 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 inited here copying data from the first context
+ */
+ // Allocate zeroed memory for the first decoder context
+ s->mp3decctx[0] = av_mallocz(sizeof(MPADecodeContext));
+ // 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));
+ s->mp3decctx[i]->compute_antialias = s->mp3decctx[0]->compute_antialias;
+ s->mp3decctx[i]->adu_mode = 1;
+ }
+
+ return 0;
+}
+
+
+static int decode_close_mp3on4(AVCodecContext * avctx)
+{
+ MP3On4DecodeContext *s = avctx->priv_data;
+ int i;
+
+ for (i = 0; i < s->frames; i++)
+ if (s->mp3decctx[i])
+ av_free(s->mp3decctx[i]);
+
+ return 0;
+}
+
+
+static int decode_frame_mp3on4(AVCodecContext * avctx,
+ void *data, int *data_size,
+ uint8_t * buf, int buf_size)
+{
+ MP3On4DecodeContext *s = avctx->priv_data;
+ MPADecodeContext *m;
+ int len, out_size = 0;
+ uint32_t header;
+ OUT_INT *out_samples = data;
+ OUT_INT decoded_buf[MPA_FRAME_SIZE * MPA_MAX_CHANNELS];
+ OUT_INT *outptr, *bp;
+ int fsize;
+ unsigned char *start2 = buf, *start;
+ int fr, i, j, n;
+ int off = avctx->channels;
+ int *coff = chan_offset[s->chan_cfg];
+
+ len = buf_size;
+
+ // Discard too short frames
+ if (buf_size < HEADER_SIZE) {
+ *data_size = 0;
+ return buf_size;
+ }
+
+ // If only one decoder interleave is not needed
+ outptr = s->frames == 1 ? out_samples : decoded_buf;
+
+ for (fr = 0; fr < s->frames; fr++) {
+ start = start2;
+ fsize = (start[0] << 4) | (start[1] >> 4);
+ start2 += fsize;
+ if (fsize > len)
+ fsize = len;
+ len -= fsize;
+ if (fsize > MPA_MAX_CODED_FRAME_SIZE)
+ fsize = MPA_MAX_CODED_FRAME_SIZE;
+ m = s->mp3decctx[fr];
+ assert (m != NULL);
+
+ // Get header
+ header = (start[0] << 24) | (start[1] << 16) | (start[2] << 8) | start[3] | 0xfff00000;
+
+ if (ff_mpa_check_header(header) < 0) { // Bad header, discard block
+ *data_size = 0;
+ return buf_size;
+ }
+
+ decode_header(m, header);
+ mp_decode_frame(m, decoded_buf, start, fsize);
+
+ n = MPA_FRAME_SIZE * m->nb_channels;
+ out_size += n * sizeof(OUT_INT);
+ if(s->frames > 1) {
+ /* interleave output data */
+ bp = out_samples + coff[fr];
+ if(m->nb_channels == 1) {
+ for(j = 0; j < n; j++) {
+ *bp = decoded_buf[j];
+ bp += off;
+ }
+ } else {
+ for(j = 0; j < n; j++) {
+ bp[0] = decoded_buf[j++];
+ bp[1] = decoded_buf[j];
+ bp += off;
+ }
+ }
+ }
+ }
+
+ /* update codec info */
+ avctx->sample_rate = s->mp3decctx[0]->sample_rate;
+ avctx->frame_size= buf_size;
+ avctx->bit_rate = 0;
+ for (i = 0; i < s->frames; i++)
+ avctx->bit_rate += s->mp3decctx[i]->bit_rate;
+
+ *data_size = out_size;
+ return buf_size;
+}
+#endif /* CONFIG_MP3ON4_DECODER */
+
+#ifdef CONFIG_MP2_DECODER
+AVCodec mp2_decoder =
+{
+ "mp2",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_MP2,
+ sizeof(MPADecodeContext),
+ decode_init,
+ NULL,
+ NULL,
+ decode_frame,
+ CODEC_CAP_PARSE_ONLY,
+};
+#endif
+#ifdef CONFIG_MP3_DECODER
+AVCodec mp3_decoder =
+{
+ "mp3",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_MP3,
+ sizeof(MPADecodeContext),
+ decode_init,
+ NULL,
+ NULL,
+ decode_frame,
+ CODEC_CAP_PARSE_ONLY,
+ .flush= flush,
+};
+#endif
+#ifdef CONFIG_MP3ADU_DECODER
+AVCodec mp3adu_decoder =
+{
+ "mp3adu",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_MP3ADU,
+ sizeof(MPADecodeContext),
+ decode_init,
+ NULL,
+ NULL,
+ decode_frame_adu,
+ CODEC_CAP_PARSE_ONLY,
+ .flush= flush,
+};
+#endif
+#ifdef CONFIG_MP3ON4_DECODER
+AVCodec mp3on4_decoder =
+{
+ "mp3on4",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_MP3ON4,
+ sizeof(MP3On4DecodeContext),
+ decode_init_mp3on4,
+ NULL,
+ decode_close_mp3on4,
+ decode_frame_mp3on4,
+ .flush= flush,
+};
+#endif
diff --git a/contrib/ffmpeg/libavcodec/mpegaudiodectab.h b/contrib/ffmpeg/libavcodec/mpegaudiodectab.h
new file mode 100644
index 000000000..fdd1096fc
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mpegaudiodectab.h
@@ -0,0 +1,795 @@
+/*
+ * 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 mpegaudiodectab.h
+ * mpeg audio layer decoder tables.
+ */
+
+const uint16_t 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 mpa_freq_tab[3] = { 44100, 48000, 32000 };
+
+/*******************************************************/
+/* half mpeg encoding window (full precision) */
+const int32_t 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,
+};
+
+/*******************************************************/
+/* layer 2 tables */
+
+const int sblimit_table[5] = { 27 , 30 , 8, 12 , 30 };
+
+const int 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 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_0[] = {
+ 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,
+};
+
+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_2[] = {
+ 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,
+};
+
+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 *alloc_tables[5] =
+{ alloc_table_0, alloc_table_1, alloc_table_2, alloc_table_3, alloc_table_4, };
+
+/*******************************************************/
+/* layer 3 tables */
+
+/* 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,
+};
diff --git a/contrib/ffmpeg/libavcodec/mpegaudiotab.h b/contrib/ffmpeg/libavcodec/mpegaudiotab.h
new file mode 100644
index 000000000..8fb37ddff
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mpegaudiotab.h
@@ -0,0 +1,111 @@
+/*
+ * 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 mpegaudiotab.h
+ * mpeg audio layer 2 tables.
+ * Most of them come from the mpeg audio specification.
+ */
+
+#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 };
+
diff --git a/contrib/ffmpeg/libavcodec/mpegvideo.c b/contrib/ffmpeg/libavcodec/mpegvideo.c
new file mode 100644
index 000000000..f0a04a402
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mpegvideo.c
@@ -0,0 +1,6903 @@
+/*
+ * The simplest mpeg encoder (well, it was the simplest!)
+ * Copyright (c) 2000,2001 Fabrice Bellard.
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * 4MV & hq & b-frame encoding stuff by Michael Niedermayer <michaelni@gmx.at>
+ */
+
+/**
+ * @file mpegvideo.c
+ * The simplest mpeg encoder (well, it was the simplest!).
+ */
+
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+#include "faandct.h"
+#include <limits.h>
+
+#ifdef USE_FASTMEMCPY
+#include "libvo/fastmemcpy.h"
+#endif
+
+//#undef NDEBUG
+//#include <assert.h>
+
+#ifdef CONFIG_ENCODERS
+static int encode_picture(MpegEncContext *s, int picture_number);
+#endif //CONFIG_ENCODERS
+static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale);
+static void dct_unquantize_mpeg1_inter_c(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale);
+static void dct_unquantize_mpeg2_intra_c(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale);
+static void dct_unquantize_mpeg2_intra_bitexact(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale);
+static void dct_unquantize_mpeg2_inter_c(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale);
+static void dct_unquantize_h263_intra_c(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale);
+static void dct_unquantize_h263_inter_c(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale);
+static void draw_edges_c(uint8_t *buf, int wrap, int width, int height, int w);
+#ifdef CONFIG_ENCODERS
+static int dct_quantize_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow);
+static int dct_quantize_trellis_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow);
+static int dct_quantize_refine(MpegEncContext *s, DCTELEM *block, int16_t *weight, DCTELEM *orig, int n, int qscale);
+static int sse_mb(MpegEncContext *s);
+static void denoise_dct_c(MpegEncContext *s, DCTELEM *block);
+#endif //CONFIG_ENCODERS
+
+#ifdef HAVE_XVMC
+extern int XVMC_field_start(MpegEncContext*s, AVCodecContext *avctx);
+extern void XVMC_field_end(MpegEncContext *s);
+extern void XVMC_decode_mb(MpegEncContext *s);
+#endif
+
+void (*draw_edges)(uint8_t *buf, int wrap, int width, int height, int w)= draw_edges_c;
+
+
+/* enable all paranoid tests for rounding, overflows, etc... */
+//#define PARANOID
+
+//#define DEBUG
+
+
+/* for jpeg fast DCT */
+#define CONST_BITS 14
+
+static const uint16_t 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
+};
+
+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, 1, 1, 1, 1, 1, 1, 2, 2,
+};
+
+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 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ 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
+};
+
+#ifdef CONFIG_ENCODERS
+static uint8_t (*default_mv_penalty)[MAX_MV*2+1]=NULL;
+static uint8_t default_fcode_tab[MAX_MV*2+1];
+
+enum PixelFormat ff_yuv420p_list[2]= {PIX_FMT_YUV420P, -1};
+
+static void 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
+#ifdef FAAN_POSTSCALE
+ || dsp->fdct == ff_faandct
+#endif
+ ) {
+ for(i=0;i<64;i++) {
+ const int j= dsp->idct_permutation[i];
+ /* 16 <= qscale * quant_matrix[i] <= 7905 */
+ /* 19952 <= aanscales[i] * qscale * quant_matrix[i] <= 249205026 */
+ /* (1<<36)/19952 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= (1<<36)/249205026 */
+ /* 3444240 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= 275 */
+
+ qmat[qscale][i] = (int)((uint64_t_C(1) << QMAT_SHIFT) /
+ (qscale * quant_matrix[j]));
+ }
+ } else if (dsp->fdct == fdct_ifast
+#ifndef FAAN_POSTSCALE
+ || dsp->fdct == ff_faandct
+#endif
+ ) {
+ for(i=0;i<64;i++) {
+ const int j= dsp->idct_permutation[i];
+ /* 16 <= qscale * quant_matrix[i] <= 7905 */
+ /* 19952 <= aanscales[i] * qscale * quant_matrix[i] <= 249205026 */
+ /* (1<<36)/19952 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= (1<<36)/249205026 */
+ /* 3444240 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= 275 */
+
+ qmat[qscale][i] = (int)((uint64_t_C(1) << (QMAT_SHIFT + 14)) /
+ (aanscales[i] * 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
+ So 16 <= qscale * quant_matrix[i] <= 7905
+ so (1<<19) / 16 >= (1<<19) / (qscale * quant_matrix[i]) >= (1<<19) / 7905
+ so 32768 >= (1<<19) / (qscale * quant_matrix[i]) >= 67
+ */
+ qmat[qscale][i] = (int)((uint64_t_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 == fdct_ifast
+#ifndef FAAN_POSTSCALE
+ || dsp->fdct == ff_faandct
+#endif
+ ) {
+ max= (8191LL*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 then %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= clip(s->qscale, s->avctx->qmin, s->avctx->qmax);
+
+ s->lambda2= (s->lambda*s->lambda + FF_LAMBDA_SCALE/2) >> FF_LAMBDA_SHIFT;
+}
+#endif //CONFIG_ENCODERS
+
+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];
+#ifdef ARCH_POWERPC
+ st->inverse[j] = i;
+#endif
+ }
+
+ end=-1;
+ for(i=0; i<64; i++){
+ int j;
+ j = st->permutated[i];
+ if(j>end) end=j;
+ st->raster_end[i]= end;
+ }
+}
+
+#ifdef CONFIG_ENCODERS
+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);
+}
+#endif //CONFIG_ENCODERS
+
+const uint8_t *ff_find_start_code(const uint8_t * restrict p, const uint8_t *end, uint32_t * 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= be2me_32(unaligned32(p));
+
+ return p+4;
+}
+
+/* init common dct for both encoder and decoder */
+int DCT_common_init(MpegEncContext *s)
+{
+ 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;
+
+#ifdef CONFIG_ENCODERS
+ s->dct_quantize= dct_quantize_c;
+ s->denoise_dct= denoise_dct_c;
+#endif //CONFIG_ENCODERS
+
+#ifdef HAVE_MMX
+ MPV_common_init_mmx(s);
+#endif
+#ifdef ARCH_ALPHA
+ MPV_common_init_axp(s);
+#endif
+#ifdef HAVE_MLIB
+ MPV_common_init_mlib(s);
+#endif
+#ifdef HAVE_MMI
+ MPV_common_init_mmi(s);
+#endif
+#ifdef ARCH_ARMV4L
+ MPV_common_init_armv4l(s);
+#endif
+#ifdef ARCH_POWERPC
+ MPV_common_init_ppc(s);
+#endif
+
+#ifdef CONFIG_ENCODERS
+ s->fast_dct_quantize= s->dct_quantize;
+
+ if(s->flags&CODEC_FLAG_TRELLIS_QUANT){
+ s->dct_quantize= dct_quantize_trellis_c; //move before MPV_common_init_*
+ }
+
+#endif //CONFIG_ENCODERS
+
+ /* 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;
+}
+
+static void copy_picture(Picture *dst, Picture *src){
+ *dst = *src;
+ dst->type= FF_BUFFER_TYPE_COPY;
+}
+
+#ifdef CONFIG_ENCODERS
+static void copy_picture_attributes(MpegEncContext *s, AVFrame *dst, AVFrame *src){
+ int i;
+
+ 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;
+
+ if(s->avctx->me_threshold){
+ if(!src->motion_val[0])
+ av_log(s->avctx, AV_LOG_ERROR, "AVFrame.motion_val not set!\n");
+ if(!src->mb_type)
+ av_log(s->avctx, AV_LOG_ERROR, "AVFrame.mb_type not set!\n");
+ if(!src->ref_index[0])
+ av_log(s->avctx, AV_LOG_ERROR, "AVFrame.ref_index not set!\n");
+ if(src->motion_subsample_log2 != dst->motion_subsample_log2)
+ av_log(s->avctx, AV_LOG_ERROR, "AVFrame.motion_subsample_log2 doesn't match! (%d!=%d)\n",
+ src->motion_subsample_log2, dst->motion_subsample_log2);
+
+ memcpy(dst->mb_type, src->mb_type, s->mb_stride * s->mb_height * sizeof(dst->mb_type[0]));
+
+ for(i=0; i<2; i++){
+ int stride= ((16*s->mb_width )>>src->motion_subsample_log2) + 1;
+ int height= ((16*s->mb_height)>>src->motion_subsample_log2);
+
+ if(src->motion_val[i] && src->motion_val[i] != dst->motion_val[i]){
+ memcpy(dst->motion_val[i], src->motion_val[i], 2*stride*height*sizeof(int16_t));
+ }
+ if(src->ref_index[i] && src->ref_index[i] != dst->ref_index[i]){
+ memcpy(dst->ref_index[i], src->ref_index[i], s->b8_stride*2*s->mb_height*sizeof(int8_t));
+ }
+ }
+ }
+}
+#endif
+
+/**
+ * allocates a Picture
+ * The pixels are allocated/set by calling get_buffer() if shared=0
+ */
+static int alloc_picture(MpegEncContext *s, Picture *pic, int shared){
+ const int big_mb_num= s->mb_stride*(s->mb_height+1) + 1; //the +1 is needed so memset(,,stride*height) doesnt sig11
+ const int mb_array_size= s->mb_stride*s->mb_height;
+ const int b8_array_size= s->b8_stride*s->mb_height*2;
+ const int b4_array_size= s->b4_stride*s->mb_height*4;
+ int i;
+
+ if(shared){
+ assert(pic->data[0]);
+ assert(pic->type == 0 || pic->type == FF_BUFFER_TYPE_SHARED);
+ pic->type= FF_BUFFER_TYPE_SHARED;
+ }else{
+ int r;
+
+ assert(!pic->data[0]);
+
+ r= s->avctx->get_buffer(s->avctx, (AVFrame*)pic);
+
+ if(r<0 || !pic->age || !pic->type || !pic->data[0]){
+ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (%d %d %d %p)\n", r, pic->age, pic->type, pic->data[0]);
+ return -1;
+ }
+
+ if(s->linesize && (s->linesize != pic->linesize[0] || s->uvlinesize != pic->linesize[1])){
+ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (stride changed)\n");
+ return -1;
+ }
+
+ if(pic->linesize[1] != pic->linesize[2]){
+ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (uv stride mismatch)\n");
+ return -1;
+ }
+
+ s->linesize = pic->linesize[0];
+ s->uvlinesize= pic->linesize[1];
+ }
+
+ if(pic->qscale_table==NULL){
+ if (s->encoding) {
+ CHECKED_ALLOCZ(pic->mb_var , mb_array_size * sizeof(int16_t))
+ CHECKED_ALLOCZ(pic->mc_mb_var, mb_array_size * sizeof(int16_t))
+ CHECKED_ALLOCZ(pic->mb_mean , mb_array_size * sizeof(int8_t))
+ }
+
+ CHECKED_ALLOCZ(pic->mbskip_table , mb_array_size * sizeof(uint8_t)+2) //the +2 is for the slice end check
+ CHECKED_ALLOCZ(pic->qscale_table , mb_array_size * sizeof(uint8_t))
+ CHECKED_ALLOCZ(pic->mb_type_base , big_mb_num * sizeof(uint32_t))
+ pic->mb_type= pic->mb_type_base + s->mb_stride+1;
+ if(s->out_format == FMT_H264){
+ for(i=0; i<2; i++){
+ CHECKED_ALLOCZ(pic->motion_val_base[i], 2 * (b4_array_size+4) * sizeof(int16_t))
+ pic->motion_val[i]= pic->motion_val_base[i]+4;
+ CHECKED_ALLOCZ(pic->ref_index[i], b8_array_size * sizeof(uint8_t))
+ }
+ pic->motion_subsample_log2= 2;
+ }else if(s->out_format == FMT_H263 || s->encoding || (s->avctx->debug&FF_DEBUG_MV) || (s->avctx->debug_mv)){
+ for(i=0; i<2; i++){
+ CHECKED_ALLOCZ(pic->motion_val_base[i], 2 * (b8_array_size+4) * sizeof(int16_t))
+ pic->motion_val[i]= pic->motion_val_base[i]+4;
+ CHECKED_ALLOCZ(pic->ref_index[i], b8_array_size * sizeof(uint8_t))
+ }
+ pic->motion_subsample_log2= 3;
+ }
+ if(s->avctx->debug&FF_DEBUG_DCT_COEFF) {
+ CHECKED_ALLOCZ(pic->dct_coeff, 64 * mb_array_size * sizeof(DCTELEM)*6)
+ }
+ pic->qstride= s->mb_stride;
+ CHECKED_ALLOCZ(pic->pan_scan , 1 * sizeof(AVPanScan))
+ }
+
+ //it might be nicer if the application would keep track of these but it would require a API change
+ memmove(s->prev_pict_types+1, s->prev_pict_types, PREV_PICT_TYPES_BUFFER_SIZE-1);
+ s->prev_pict_types[0]= s->pict_type;
+ if(pic->age < PREV_PICT_TYPES_BUFFER_SIZE && s->prev_pict_types[pic->age] == B_TYPE)
+ pic->age= INT_MAX; // skipped MBs in b frames are quite rare in mpeg1/2 and its a bit tricky to skip them anyway
+
+ return 0;
+fail: //for the CHECKED_ALLOCZ macro
+ return -1;
+}
+
+/**
+ * deallocates a picture
+ */
+static void free_picture(MpegEncContext *s, Picture *pic){
+ int i;
+
+ if(pic->data[0] && pic->type!=FF_BUFFER_TYPE_SHARED){
+ s->avctx->release_buffer(s->avctx, (AVFrame*)pic);
+ }
+
+ av_freep(&pic->mb_var);
+ av_freep(&pic->mc_mb_var);
+ av_freep(&pic->mb_mean);
+ av_freep(&pic->mbskip_table);
+ av_freep(&pic->qscale_table);
+ av_freep(&pic->mb_type_base);
+ av_freep(&pic->dct_coeff);
+ av_freep(&pic->pan_scan);
+ pic->mb_type= NULL;
+ for(i=0; i<2; i++){
+ av_freep(&pic->motion_val_base[i]);
+ av_freep(&pic->ref_index[i]);
+ }
+
+ if(pic->type == FF_BUFFER_TYPE_SHARED){
+ for(i=0; i<4; i++){
+ pic->base[i]=
+ pic->data[i]= NULL;
+ }
+ pic->type= 0;
+ }
+}
+
+static int init_duplicate_context(MpegEncContext *s, MpegEncContext *base){
+ int i;
+
+ // edge emu needs blocksize + filter length - 1 (=17x17 for halfpel / 21x21 for h264)
+ CHECKED_ALLOCZ(s->allocated_edge_emu_buffer, (s->width+64)*2*21*2); //(width + edge + align)*interlaced*MBsize*tolerance
+ s->edge_emu_buffer= s->allocated_edge_emu_buffer + (s->width+64)*2*21;
+
+ //FIXME should be linesize instead of s->width*2 but that isnt known before get_buffer()
+ CHECKED_ALLOCZ(s->me.scratchpad, (s->width+64)*4*16*2*sizeof(uint8_t))
+ s->rd_scratchpad= s->me.scratchpad;
+ s->b_scratchpad= s->me.scratchpad;
+ s->obmc_scratchpad= s->me.scratchpad + 16;
+ if (s->encoding) {
+ CHECKED_ALLOCZ(s->me.map , ME_MAP_SIZE*sizeof(uint32_t))
+ CHECKED_ALLOCZ(s->me.score_map, ME_MAP_SIZE*sizeof(uint32_t))
+ if(s->avctx->noise_reduction){
+ CHECKED_ALLOCZ(s->dct_error_sum, 2 * 64 * sizeof(int))
+ }
+ }
+ CHECKED_ALLOCZ(s->blocks, 64*12*2 * sizeof(DCTELEM))
+ s->block= s->blocks[0];
+
+ for(i=0;i<12;i++){
+ s->pblocks[i] = (short *)(&s->block[i]);
+ }
+ return 0;
+fail:
+ return -1; //free() through MPV_common_end()
+}
+
+static void free_duplicate_context(MpegEncContext *s){
+ if(s==NULL) return;
+
+ av_freep(&s->allocated_edge_emu_buffer); s->edge_emu_buffer= NULL;
+ av_freep(&s->me.scratchpad);
+ 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);
+ s->block= NULL;
+}
+
+static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src){
+#define COPY(a) bak->a= src->a
+ COPY(allocated_edge_emu_buffer);
+ COPY(edge_emu_buffer);
+ COPY(me.scratchpad);
+ 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]);
+#undef COPY
+}
+
+void ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src){
+ MpegEncContext bak;
+ int i;
+ //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] = (short *)(&dst->block[i]);
+ }
+//STOP_TIMER("update_duplicate_context") //about 10k cycles / 0.01 sec for 1000frames on 1ghz with 2 threads
+}
+
+#ifdef CONFIG_ENCODERS
+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
+}
+#endif
+
+/**
+ * sets the given MpegEncContext to common defaults (same for encoding and decoding).
+ * the changed fields will not depend upon the prior state of the MpegEncContext.
+ */
+static void 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;
+}
+
+/**
+ * sets the given MpegEncContext to defaults for decoding.
+ * the changed fields will not depend upon the prior state of the MpegEncContext.
+ */
+void MPV_decode_defaults(MpegEncContext *s){
+ MPV_common_defaults(s);
+}
+
+/**
+ * sets the given MpegEncContext to defaults for encoding.
+ * the changed fields will not depend upon the prior state of the MpegEncContext.
+ */
+
+#ifdef CONFIG_ENCODERS
+static void MPV_encode_defaults(MpegEncContext *s){
+ static int done=0;
+
+ MPV_common_defaults(s);
+
+ if(!done){
+ int i;
+ done=1;
+
+ default_mv_penalty= av_mallocz( sizeof(uint8_t)*(MAX_FCODE+1)*(2*MAX_MV+1) );
+ memset(default_fcode_tab , 0, sizeof(uint8_t)*(2*MAX_MV+1));
+
+ 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;
+}
+#endif //CONFIG_ENCODERS
+
+/**
+ * init common structure for both encoder and decoder.
+ * this assumes that some variables like width/height are already set
+ */
+int MPV_common_init(MpegEncContext *s)
+{
+ int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y;
+
+ s->mb_height = (s->height + 15) / 16;
+
+ if(s->avctx->thread_count > MAX_THREADS || (s->avctx->thread_count > s->mb_height && s->mb_height)){
+ av_log(s->avctx, AV_LOG_ERROR, "too many threads\n");
+ return -1;
+ }
+
+ if((s->width || s->height) && avcodec_check_dimensions(s->avctx, s->width, s->height))
+ return -1;
+
+ dsputil_init(&s->dsp, s->avctx);
+ DCT_common_init(s);
+
+ s->flags= s->avctx->flags;
+ s->flags2= s->avctx->flags2;
+
+ 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 chroma shifts */
+ avcodec_get_chroma_sub_sample(s->avctx->pix_fmt,&(s->chroma_x_shift),
+ &(s->chroma_y_shift) );
+
+ /* 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;
+
+ /* convert fourcc to upper case */
+ s->codec_tag= toupper( s->avctx->codec_tag &0xFF)
+ + (toupper((s->avctx->codec_tag>>8 )&0xFF)<<8 )
+ + (toupper((s->avctx->codec_tag>>16)&0xFF)<<16)
+ + (toupper((s->avctx->codec_tag>>24)&0xFF)<<24);
+
+ s->stream_codec_tag= toupper( s->avctx->stream_codec_tag &0xFF)
+ + (toupper((s->avctx->stream_codec_tag>>8 )&0xFF)<<8 )
+ + (toupper((s->avctx->stream_codec_tag>>16)&0xFF)<<16)
+ + (toupper((s->avctx->stream_codec_tag>>24)&0xFF)<<24);
+
+ s->avctx->coded_frame= (AVFrame*)&s->current_picture;
+
+ CHECKED_ALLOCZ(s->mb_index2xy, (s->mb_num+1)*sizeof(int)) //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 */
+ CHECKED_ALLOCZ(s->p_mv_table_base , mv_table_size * 2 * sizeof(int16_t))
+ CHECKED_ALLOCZ(s->b_forw_mv_table_base , mv_table_size * 2 * sizeof(int16_t))
+ CHECKED_ALLOCZ(s->b_back_mv_table_base , mv_table_size * 2 * sizeof(int16_t))
+ CHECKED_ALLOCZ(s->b_bidir_forw_mv_table_base , mv_table_size * 2 * sizeof(int16_t))
+ CHECKED_ALLOCZ(s->b_bidir_back_mv_table_base , mv_table_size * 2 * sizeof(int16_t))
+ CHECKED_ALLOCZ(s->b_direct_mv_table_base , mv_table_size * 2 * sizeof(int16_t))
+ 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;
+
+ if(s->msmpeg4_version){
+ CHECKED_ALLOCZ(s->ac_stats, 2*2*(MAX_LEVEL+1)*(MAX_RUN+1)*2*sizeof(int));
+ }
+ CHECKED_ALLOCZ(s->avctx->stats_out, 256);
+
+ /* Allocate MB type table */
+ CHECKED_ALLOCZ(s->mb_type , mb_array_size * sizeof(uint16_t)) //needed for encoding
+
+ CHECKED_ALLOCZ(s->lambda_table, mb_array_size * sizeof(int))
+
+ CHECKED_ALLOCZ(s->q_intra_matrix, 64*32 * sizeof(int))
+ CHECKED_ALLOCZ(s->q_inter_matrix, 64*32 * sizeof(int))
+ CHECKED_ALLOCZ(s->q_intra_matrix16, 64*32*2 * sizeof(uint16_t))
+ CHECKED_ALLOCZ(s->q_inter_matrix16, 64*32*2 * sizeof(uint16_t))
+ CHECKED_ALLOCZ(s->input_picture, MAX_PICTURE_COUNT * sizeof(Picture*))
+ CHECKED_ALLOCZ(s->reordered_input_picture, MAX_PICTURE_COUNT * sizeof(Picture*))
+
+ if(s->avctx->noise_reduction){
+ CHECKED_ALLOCZ(s->dct_offset, 2 * 64 * sizeof(uint16_t))
+ }
+ }
+ CHECKED_ALLOCZ(s->picture, MAX_PICTURE_COUNT * sizeof(Picture))
+
+ CHECKED_ALLOCZ(s->error_status_table, mb_array_size*sizeof(uint8_t))
+
+ if(s->codec_id==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++){
+ CHECKED_ALLOCZ(s->b_field_mv_table_base[i][j][k] , mv_table_size * 2 * sizeof(int16_t))
+ s->b_field_mv_table[i][j][k] = s->b_field_mv_table_base[i][j][k] + s->mb_stride + 1;
+ }
+ CHECKED_ALLOCZ(s->b_field_select_table[i][j] , mb_array_size * 2 * sizeof(uint8_t))
+ CHECKED_ALLOCZ(s->p_field_mv_table_base[i][j] , mv_table_size * 2 * sizeof(int16_t))
+ s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j] + s->mb_stride + 1;
+ }
+ CHECKED_ALLOCZ(s->p_field_select_table[i] , mb_array_size * 2 * sizeof(uint8_t))
+ }
+ }
+ if (s->out_format == FMT_H263) {
+ /* ac values */
+ CHECKED_ALLOCZ(s->ac_val_base, yc_size * sizeof(int16_t) * 16);
+ 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;
+
+ /* cbp values */
+ CHECKED_ALLOCZ(s->coded_block_base, y_size);
+ s->coded_block= s->coded_block_base + s->b8_stride + 1;
+
+ /* cbp, ac_pred, pred_dir */
+ CHECKED_ALLOCZ(s->cbp_table , mb_array_size * sizeof(uint8_t))
+ CHECKED_ALLOCZ(s->pred_dir_table, mb_array_size * sizeof(uint8_t))
+ }
+
+ if (s->h263_pred || s->h263_plus || !s->encoding) {
+ /* dc values */
+ //MN: we need these for error resilience of intra-frames
+ CHECKED_ALLOCZ(s->dc_val_base, yc_size * sizeof(int16_t));
+ 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 */
+ CHECKED_ALLOCZ(s->mbintra_table, mb_array_size);
+ memset(s->mbintra_table, 1, mb_array_size);
+
+ /* init macroblock skip table */
+ CHECKED_ALLOCZ(s->mbskip_table, mb_array_size+2);
+ //Note the +1 is for a quicker mpeg4 slice_end detection
+ CHECKED_ALLOCZ(s->prev_pict_types, PREV_PICT_TYPES_BUFFER_SIZE);
+
+ s->parse_context.state= -1;
+ if((s->avctx->debug&(FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)) || (s->avctx->debug_mv)){
+ s->visualization_buffer[0] = av_malloc((s->mb_width*16 + 2*EDGE_WIDTH) * s->mb_height*16 + 2*EDGE_WIDTH);
+ s->visualization_buffer[1] = av_malloc((s->mb_width*8 + EDGE_WIDTH) * s->mb_height*8 + EDGE_WIDTH);
+ s->visualization_buffer[2] = av_malloc((s->mb_width*8 + EDGE_WIDTH) * s->mb_height*8 + EDGE_WIDTH);
+ }
+
+ s->context_initialized = 1;
+
+ s->thread_context[0]= s;
+ for(i=1; i<s->avctx->thread_count; i++){
+ s->thread_context[i]= av_malloc(sizeof(MpegEncContext));
+ memcpy(s->thread_context[i], s, sizeof(MpegEncContext));
+ }
+
+ for(i=0; i<s->avctx->thread_count; i++){
+ if(init_duplicate_context(s->thread_context[i], s) < 0)
+ goto fail;
+ s->thread_context[i]->start_mb_y= (s->mb_height*(i ) + s->avctx->thread_count/2) / s->avctx->thread_count;
+ s->thread_context[i]->end_mb_y = (s->mb_height*(i+1) + s->avctx->thread_count/2) / s->avctx->thread_count;
+ }
+
+ return 0;
+ fail:
+ MPV_common_end(s);
+ return -1;
+}
+
+/* init common structure for both encoder and decoder */
+void MPV_common_end(MpegEncContext *s)
+{
+ int i, j, k;
+
+ for(i=0; i<s->avctx->thread_count; i++){
+ free_duplicate_context(s->thread_context[i]);
+ }
+ for(i=1; i<s->avctx->thread_count; i++){
+ av_freep(&s->thread_context[i]);
+ }
+
+ av_freep(&s->parse_context.buffer);
+ s->parse_context.buffer_size=0;
+
+ 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->ac_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->prev_pict_types);
+ av_freep(&s->bitstream_buffer);
+ s->allocated_bitstream_buffer_size=0;
+
+ av_freep(&s->avctx->stats_out);
+ av_freep(&s->ac_stats);
+ av_freep(&s->error_status_table);
+ av_freep(&s->mb_index2xy);
+ av_freep(&s->lambda_table);
+ 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(s, &s->picture[i]);
+ }
+ }
+ av_freep(&s->picture);
+ s->context_initialized = 0;
+ s->last_picture_ptr=
+ s->next_picture_ptr=
+ s->current_picture_ptr= NULL;
+ s->linesize= s->uvlinesize= 0;
+
+ for(i=0; i<3; i++)
+ av_freep(&s->visualization_buffer[i]);
+
+ avcodec_default_free_buffers(s->avctx);
+}
+
+#ifdef CONFIG_ENCODERS
+
+/* init video encoder */
+int 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 CODEC_ID_MPEG2VIDEO:
+ if(avctx->pix_fmt != PIX_FMT_YUV420P && avctx->pix_fmt != PIX_FMT_YUV422P){
+ av_log(avctx, AV_LOG_ERROR, "only YUV420 and YUV422 are supported\n");
+ return -1;
+ }
+ break;
+ case CODEC_ID_LJPEG:
+ case CODEC_ID_MJPEG:
+ if(avctx->pix_fmt != PIX_FMT_YUVJ420P && avctx->pix_fmt != PIX_FMT_YUVJ422P &&
+ ((avctx->pix_fmt != PIX_FMT_YUV420P && avctx->pix_fmt != PIX_FMT_YUV422P) || avctx->strict_std_compliance>FF_COMPLIANCE_INOFFICIAL)){
+ av_log(avctx, AV_LOG_ERROR, "colorspace not supported in jpeg\n");
+ return -1;
+ }
+ break;
+ default:
+ if(avctx->pix_fmt != PIX_FMT_YUV420P){
+ av_log(avctx, AV_LOG_ERROR, "only YUV420 is supported\n");
+ return -1;
+ }
+ }
+
+ switch (avctx->pix_fmt) {
+ case PIX_FMT_YUVJ422P:
+ case PIX_FMT_YUV422P:
+ s->chroma_format = CHROMA_422;
+ break;
+ case PIX_FMT_YUVJ420P:
+ case 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_ERROR, "Warning keyframe interval too large! reducing it ...\n");
+ 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->luma_elim_threshold = avctx->luma_elim_threshold;
+ s->chroma_elim_threshold= avctx->chroma_elim_threshold;
+ s->strict_std_compliance= avctx->strict_std_compliance;
+ s->data_partitioning= avctx->flags & CODEC_FLAG_PART;
+ 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->flags&CODEC_FLAG_QP_RD))
+ && !s->fixed_qscale;
+
+ s->obmc= !!(s->flags & CODEC_FLAG_OBMC);
+ s->loop_filter= !!(s->flags & CODEC_FLAG_LOOP_FILTER);
+ s->alternate_scan= !!(s->flags & CODEC_FLAG_ALT_SCAN);
+ s->intra_vlc_format= !!(s->flags2 & CODEC_FLAG2_INTRA_VLC);
+
+ if(avctx->rc_max_rate && !avctx->rc_buffer_size){
+ av_log(avctx, AV_LOG_ERROR, "a vbv buffer size is needed, for encoding with a maximum bitrate\n");
+ 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_INFO, "bitrate below min bitrate\n");
+ return -1;
+ }
+
+ if(avctx->rc_max_rate && avctx->rc_max_rate < avctx->bit_rate){
+ av_log(avctx, AV_LOG_INFO, "bitrate above max bitrate\n");
+ return -1;
+ }
+
+ if( s->avctx->rc_max_rate && s->avctx->rc_min_rate == s->avctx->rc_max_rate
+ && (s->codec_id == CODEC_ID_MPEG1VIDEO || s->codec_id == 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 != CODEC_ID_MPEG4
+ && s->codec_id != CODEC_ID_H263 && s->codec_id != CODEC_ID_H263P && s->codec_id != 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->obmc && s->codec_id != CODEC_ID_H263 && s->codec_id != CODEC_ID_H263P){
+ av_log(avctx, AV_LOG_ERROR, "OBMC is only supported with H263(+)\n");
+ return -1;
+ }
+
+ if(s->quarter_sample && s->codec_id != CODEC_ID_MPEG4){
+ av_log(avctx, AV_LOG_ERROR, "qpel not supported by codec\n");
+ return -1;
+ }
+
+ if(s->data_partitioning && s->codec_id != CODEC_ID_MPEG4){
+ av_log(avctx, AV_LOG_ERROR, "data partitioning not supported by codec\n");
+ return -1;
+ }
+
+ if(s->max_b_frames && s->codec_id != CODEC_ID_MPEG4 && s->codec_id != CODEC_ID_MPEG1VIDEO && s->codec_id != CODEC_ID_MPEG2VIDEO){
+ av_log(avctx, AV_LOG_ERROR, "b frames not supported by codec\n");
+ return -1;
+ }
+
+ if((s->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME|CODEC_FLAG_ALT_SCAN))
+ && s->codec_id != CODEC_ID_MPEG4 && s->codec_id != CODEC_ID_MPEG2VIDEO){
+ av_log(avctx, AV_LOG_ERROR, "interlacing not supported by codec\n");
+ return -1;
+ }
+
+ if(s->mpeg_quant && s->codec_id != CODEC_ID_MPEG4){ //FIXME mpeg2 uses that too
+ av_log(avctx, AV_LOG_ERROR, "mpeg2 style quantization not supported by codec\n");
+ return -1;
+ }
+
+ if((s->flags & CODEC_FLAG_CBP_RD) && !(s->flags & CODEC_FLAG_TRELLIS_QUANT)){
+ av_log(avctx, AV_LOG_ERROR, "CBP RD needs trellis quant\n");
+ return -1;
+ }
+
+ if((s->flags & CODEC_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 arent supported yet\n");
+ return -1;
+ }
+
+ if((s->flags2 & CODEC_FLAG2_INTRA_VLC) && s->codec_id != CODEC_ID_MPEG2VIDEO){
+ av_log(avctx, AV_LOG_ERROR, "intra vlc table not supported by codec\n");
+ return -1;
+ }
+
+ if(s->flags & CODEC_FLAG_LOW_DELAY){
+ if (s->codec_id != CODEC_ID_MPEG2VIDEO && s->codec_id != CODEC_ID_MPEG1VIDEO){
+ av_log(avctx, AV_LOG_ERROR, "low delay forcing is only available for mpeg1/2\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->avctx->thread_count > 1 && s->codec_id != CODEC_ID_MPEG4
+ && s->codec_id != CODEC_ID_MPEG1VIDEO && s->codec_id != CODEC_ID_MPEG2VIDEO
+ && (s->codec_id != CODEC_ID_H263P || !(s->flags & CODEC_FLAG_H263P_SLICE_STRUCT))){
+ av_log(avctx, AV_LOG_ERROR, "multi threaded encoding not supported by codec\n");
+ return -1;
+ }
+
+ if(s->avctx->thread_count > 1)
+ s->rtp_mode= 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->me_threshold >= i){
+ av_log(avctx, AV_LOG_ERROR, "me_threshold too large, max is %d\n", i - 1);
+ return -1;
+ }
+ 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= ff_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->codec_id==CODEC_ID_MJPEG){
+ s->intra_quant_bias= 1<<(QUANT_BIAS_SHIFT-1); //(a + x/2)/x
+ s->inter_quant_bias= 0;
+ }else if(s->mpeg_quant || s->codec_id==CODEC_ID_MPEG1VIDEO || s->codec_id==CODEC_ID_MPEG2VIDEO){
+ s->intra_quant_bias= 3<<(QUANT_BIAS_SHIFT-3); //(a + x*3/8)/x
+ s->inter_quant_bias= 0;
+ }else{
+ s->intra_quant_bias=0;
+ s->inter_quant_bias=-(1<<(QUANT_BIAS_SHIFT-2)); //(a - x/4)/x
+ }
+
+ 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;
+
+ avcodec_get_chroma_sub_sample(avctx->pix_fmt, &chroma_h_shift, &chroma_v_shift);
+
+ if(avctx->codec_id == CODEC_ID_MPEG4 && s->avctx->time_base.den > (1<<16)-1){
+ av_log(avctx, AV_LOG_ERROR, "timebase not supported by mpeg 4 standard\n");
+ return -1;
+ }
+ s->time_increment_bits = av_log2(s->avctx->time_base.den - 1) + 1;
+
+ switch(avctx->codec->id) {
+ case 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 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 CODEC_ID_LJPEG:
+ case CODEC_ID_JPEGLS:
+ case CODEC_ID_MJPEG:
+ s->out_format = FMT_MJPEG;
+ s->intra_only = 1; /* force intra only for jpeg */
+ s->mjpeg_write_tables = avctx->codec->id != CODEC_ID_JPEGLS;
+ s->mjpeg_data_only_frames = 0; /* write all the needed headers */
+ 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 (mjpeg_init(s) < 0)
+ return -1;
+ avctx->delay=0;
+ s->low_delay=1;
+ break;
+#ifdef CONFIG_H261_ENCODER
+ case CODEC_ID_H261:
+ 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;
+#endif
+ case CODEC_ID_H263:
+ if (h263_get_picture_format(s->width, s->height) == 7) {
+ av_log(avctx, AV_LOG_INFO, "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;
+ s->obmc= (avctx->flags & CODEC_FLAG_OBMC) ? 1:0;
+ avctx->delay=0;
+ s->low_delay=1;
+ break;
+ case CODEC_ID_H263P:
+ s->out_format = FMT_H263;
+ s->h263_plus = 1;
+ /* Fx */
+ s->umvplus = (avctx->flags & CODEC_FLAG_H263P_UMV) ? 1:0;
+ s->h263_aic= (avctx->flags & CODEC_FLAG_H263P_AIC) ? 1:0;
+ s->modified_quant= s->h263_aic;
+ s->alt_inter_vlc= (avctx->flags & CODEC_FLAG_H263P_AIV) ? 1:0;
+ s->obmc= (avctx->flags & CODEC_FLAG_OBMC) ? 1:0;
+ s->loop_filter= (avctx->flags & CODEC_FLAG_LOOP_FILTER) ? 1:0;
+ s->unrestricted_mv= s->obmc || s->loop_filter || s->umvplus;
+ s->h263_slice_structured= (s->flags & CODEC_FLAG_H263P_SLICE_STRUCT) ? 1:0;
+
+ /* /Fx */
+ /* These are just to be sure */
+ avctx->delay=0;
+ s->low_delay=1;
+ break;
+ case 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 CODEC_ID_RV10:
+ s->out_format = FMT_H263;
+ avctx->delay=0;
+ s->low_delay=1;
+ break;
+ case 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= s->obmc || s->loop_filter || s->umvplus;
+ break;
+ case 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 CODEC_ID_MSMPEG4V1:
+ s->out_format = FMT_H263;
+ s->h263_msmpeg4 = 1;
+ s->h263_pred = 1;
+ s->unrestricted_mv = 1;
+ s->msmpeg4_version= 1;
+ avctx->delay=0;
+ s->low_delay=1;
+ break;
+ case CODEC_ID_MSMPEG4V2:
+ s->out_format = FMT_H263;
+ s->h263_msmpeg4 = 1;
+ s->h263_pred = 1;
+ s->unrestricted_mv = 1;
+ s->msmpeg4_version= 2;
+ avctx->delay=0;
+ s->low_delay=1;
+ break;
+ case CODEC_ID_MSMPEG4V3:
+ s->out_format = FMT_H263;
+ s->h263_msmpeg4 = 1;
+ 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 CODEC_ID_WMV1:
+ s->out_format = FMT_H263;
+ s->h263_msmpeg4 = 1;
+ 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 CODEC_ID_WMV2:
+ s->out_format = FMT_H263;
+ s->h263_msmpeg4 = 1;
+ 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;
+
+ /* init */
+ if (MPV_common_init(s) < 0)
+ return -1;
+
+ if(s->modified_quant)
+ s->chroma_qscale_table= ff_h263_chroma_qscale_table;
+ s->progressive_frame=
+ s->progressive_sequence= !(avctx->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME|CODEC_FLAG_ALT_SCAN));
+ 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);
+
+#ifdef CONFIG_H261_ENCODER
+ if (s->out_format == FMT_H261)
+ ff_h261_encode_init(s);
+#endif
+ if (s->out_format == FMT_H263)
+ h263_encode_init(s);
+ if(s->msmpeg4_version)
+ ff_msmpeg4_encode_init(s);
+ if (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(s->codec_id==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) {
+ convert_matrix(&s->dsp, s->q_intra_matrix, s->q_intra_matrix16,
+ s->intra_matrix, s->intra_quant_bias, avctx->qmin, 31, 1);
+ 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;
+}
+
+int MPV_encode_end(AVCodecContext *avctx)
+{
+ MpegEncContext *s = avctx->priv_data;
+
+ ff_rate_control_uninit(s);
+
+ MPV_common_end(s);
+ if (s->out_format == FMT_MJPEG)
+ mjpeg_close(s);
+
+ av_freep(&avctx->extradata);
+
+ return 0;
+}
+
+#endif //CONFIG_ENCODERS
+
+void init_rl(RLTable *rl, int use_static)
+{
+ 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(use_static && 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(use_static)
+ rl->max_level[last] = av_mallocz_static(MAX_RUN + 1);
+ else
+ rl->max_level[last] = av_malloc(MAX_RUN + 1);
+ memcpy(rl->max_level[last], max_level, MAX_RUN + 1);
+ if(use_static)
+ rl->max_run[last] = av_mallocz_static(MAX_LEVEL + 1);
+ else
+ rl->max_run[last] = av_malloc(MAX_LEVEL + 1);
+ memcpy(rl->max_run[last], max_run, MAX_LEVEL + 1);
+ if(use_static)
+ rl->index_run[last] = av_mallocz_static(MAX_RUN + 1);
+ else
+ rl->index_run[last] = av_malloc(MAX_RUN + 1);
+ memcpy(rl->index_run[last], index_run, MAX_RUN + 1);
+ }
+}
+
+/* draw the edges of width 'w' of an image of size width, height */
+//FIXME check that this is ok for mpeg4 interlaced
+static void draw_edges_c(uint8_t *buf, int wrap, int width, int height, int w)
+{
+ uint8_t *ptr, *last_line;
+ int i;
+
+ last_line = buf + (height - 1) * wrap;
+ for(i=0;i<w;i++) {
+ /* top and bottom */
+ memcpy(buf - (i + 1) * wrap, buf, width);
+ memcpy(last_line + (i + 1) * wrap, last_line, width);
+ }
+ /* left and right */
+ ptr = buf;
+ for(i=0;i<height;i++) {
+ memset(ptr - w, ptr[0], w);
+ memset(ptr + width, ptr[width-1], w);
+ ptr += wrap;
+ }
+ /* corners */
+ for(i=0;i<w;i++) {
+ memset(buf - (i + 1) * wrap - w, buf[0], w); /* top left */
+ memset(buf - (i + 1) * wrap + width, buf[width-1], w); /* top right */
+ memset(last_line + (i + 1) * wrap - w, last_line[0], w); /* top left */
+ memset(last_line + (i + 1) * wrap + width, last_line[width-1], w); /* top right */
+ }
+}
+
+int ff_find_unused_picture(MpegEncContext *s, int shared){
+ int i;
+
+ if(shared){
+ for(i=0; i<MAX_PICTURE_COUNT; i++){
+ if(s->picture[i].data[0]==NULL && s->picture[i].type==0) return i;
+ }
+ }else{
+ for(i=0; i<MAX_PICTURE_COUNT; i++){
+ if(s->picture[i].data[0]==NULL && s->picture[i].type!=0) return i; //FIXME
+ }
+ for(i=0; i<MAX_PICTURE_COUNT; i++){
+ if(s->picture[i].data[0]==NULL) return i;
+ }
+ }
+
+ assert(0);
+ return -1;
+}
+
+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 MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
+{
+ int i;
+ AVFrame *pic;
+ s->mb_skipped = 0;
+
+ assert(s->last_picture_ptr==NULL || s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3);
+
+ /* mark&release old frames */
+ if (s->pict_type != B_TYPE && s->last_picture_ptr && s->last_picture_ptr != s->next_picture_ptr && s->last_picture_ptr->data[0]) {
+ avctx->release_buffer(avctx, (AVFrame*)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].data[0] && &s->picture[i] != s->next_picture_ptr && s->picture[i].reference){
+ av_log(avctx, AV_LOG_ERROR, "releasing zombie picture\n");
+ avctx->release_buffer(avctx, (AVFrame*)&s->picture[i]);
+ }
+ }
+ }
+ }
+alloc:
+ if(!s->encoding){
+ /* release non reference frames */
+ for(i=0; i<MAX_PICTURE_COUNT; i++){
+ if(s->picture[i].data[0] && !s->picture[i].reference /*&& s->picture[i].type!=FF_BUFFER_TYPE_SHARED*/){
+ s->avctx->release_buffer(s->avctx, (AVFrame*)&s->picture[i]);
+ }
+ }
+
+ if(s->current_picture_ptr && s->current_picture_ptr->data[0]==NULL)
+ pic= (AVFrame*)s->current_picture_ptr; //we allready have a unused image (maybe it was set before reading the header)
+ else{
+ i= ff_find_unused_picture(s, 0);
+ pic= (AVFrame*)&s->picture[i];
+ }
+
+ pic->reference= (s->pict_type != B_TYPE || s->codec_id == CODEC_ID_H264)
+ && !s->dropable ? 3 : 0;
+
+ pic->coded_picture_number= s->coded_picture_number++;
+
+ if( alloc_picture(s, (Picture*)pic, 0) < 0)
+ return -1;
+
+ s->current_picture_ptr= (Picture*)pic;
+ s->current_picture_ptr->top_field_first= s->top_field_first; //FIXME use only the vars from current_pic
+ s->current_picture_ptr->interlaced_frame= !s->progressive_frame && !s->progressive_sequence;
+ }
+
+ s->current_picture_ptr->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->key_frame= s->pict_type == I_TYPE;
+
+ copy_picture(&s->current_picture, s->current_picture_ptr);
+
+ if(s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3){
+ if (s->pict_type != B_TYPE) {
+ s->last_picture_ptr= s->next_picture_ptr;
+ if(!s->dropable)
+ s->next_picture_ptr= s->current_picture_ptr;
+ }
+/* av_log(s->avctx, AV_LOG_DEBUG, "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->data[0] : NULL,
+ s->next_picture_ptr ? s->next_picture_ptr->data[0] : NULL,
+ s->current_picture_ptr ? s->current_picture_ptr->data[0] : NULL,
+ s->pict_type, s->dropable);*/
+
+ if(s->last_picture_ptr) copy_picture(&s->last_picture, s->last_picture_ptr);
+ if(s->next_picture_ptr) copy_picture(&s->next_picture, s->next_picture_ptr);
+
+ if(s->pict_type != I_TYPE && (s->last_picture_ptr==NULL || s->last_picture_ptr->data[0]==NULL)){
+ av_log(avctx, AV_LOG_ERROR, "warning: first frame is no keyframe\n");
+ assert(s->pict_type != B_TYPE); //these should have been dropped if we don't have a reference
+ goto alloc;
+ }
+
+ assert(s->pict_type == I_TYPE || (s->last_picture_ptr && s->last_picture_ptr->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.data[i] += s->current_picture.linesize[i];
+ }
+ s->current_picture.linesize[i] *= 2;
+ s->last_picture.linesize[i] *=2;
+ s->next_picture.linesize[i] *=2;
+ }
+ }
+ }
+
+ s->hurry_up= s->avctx->hurry_up;
+ s->error_resilience= avctx->error_resilience;
+
+ /* 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 isnt called for mpeg4 there yet */
+ if(s->mpeg_quant || s->codec_id == 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);
+ }
+
+#ifdef HAVE_XVMC
+ if(s->avctx->xvmc_acceleration)
+ return XVMC_field_start(s, avctx);
+#endif
+ return 0;
+}
+
+/* generic function for encode/decode called after a frame has been coded/decoded */
+void MPV_frame_end(MpegEncContext *s)
+{
+ int i;
+ /* draw edge for correct motion prediction if outside */
+#ifdef HAVE_XVMC
+//just to make sure that all data is rendered.
+ if(s->avctx->xvmc_acceleration){
+ XVMC_field_end(s);
+ }else
+#endif
+ if(s->unrestricted_mv && s->current_picture.reference && !s->intra_only && !(s->flags&CODEC_FLAG_EMU_EDGE)) {
+ draw_edges(s->current_picture.data[0], s->linesize , s->h_edge_pos , s->v_edge_pos , EDGE_WIDTH );
+ draw_edges(s->current_picture.data[1], s->uvlinesize, s->h_edge_pos>>1, s->v_edge_pos>>1, EDGE_WIDTH/2);
+ draw_edges(s->current_picture.data[2], s->uvlinesize, s->h_edge_pos>>1, s->v_edge_pos>>1, EDGE_WIDTH/2);
+ }
+ emms_c();
+
+ s->last_pict_type = s->pict_type;
+ s->last_lambda_for[s->pict_type]= s->current_picture_ptr->quality;
+ if(s->pict_type!=B_TYPE){
+ 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].data[0] == s->current_picture.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].data[0] && !s->picture[i].reference /*&& s->picture[i].type!=FF_BUFFER_TYPE_SHARED*/){
+ s->avctx->release_buffer(s->avctx, (AVFrame*)&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= (AVFrame*)s->current_picture_ptr;
+}
+
+/**
+ * draws an 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= clip(sx, 0, w-1);
+ sy= clip(sy, 0, h-1);
+ ex= clip(ex, 0, w-1);
+ ey= 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;
+ 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;;
+ buf[y*stride + x+1]+= (color* fr )>>16;;
+ }
+ }
+}
+
+/**
+ * draws 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= clip(sx, -100, w+100);
+ sy= clip(sy, -100, h+100);
+ ex= clip(ex, -100, w+100);
+ ey= 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);
+}
+
+/**
+ * prints debuging info for the given picture.
+ */
+void ff_print_debug_info(MpegEncContext *s, AVFrame *pict){
+
+ if(!pict || !pict->mb_type) return;
+
+ if(s->avctx->debug&(FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE)){
+ int x,y;
+
+ av_log(s->avctx,AV_LOG_DEBUG,"New frame, type: ");
+ switch (pict->pict_type) {
+ case FF_I_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"I\n"); break;
+ case FF_P_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"P\n"); break;
+ case FF_B_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"B\n"); break;
+ case FF_S_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"S\n"); break;
+ case FF_SI_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"SI\n"); break;
+ case FF_SP_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"SP\n"); break;
+ }
+ for(y=0; y<s->mb_height; y++){
+ for(x=0; x<s->mb_width; x++){
+ if(s->avctx->debug&FF_DEBUG_SKIP){
+ int count= s->mbskip_table[x + y*s->mb_stride];
+ if(count>9) count=9;
+ av_log(s->avctx, AV_LOG_DEBUG, "%1d", count);
+ }
+ if(s->avctx->debug&FF_DEBUG_QP){
+ av_log(s->avctx, AV_LOG_DEBUG, "%2d", pict->qscale_table[x + y*s->mb_stride]);
+ }
+ if(s->avctx->debug&FF_DEBUG_MB_TYPE){
+ int mb_type= pict->mb_type[x + y*s->mb_stride];
+ //Type & MV direction
+ if(IS_PCM(mb_type))
+ av_log(s->avctx, AV_LOG_DEBUG, "P");
+ else if(IS_INTRA(mb_type) && IS_ACPRED(mb_type))
+ av_log(s->avctx, AV_LOG_DEBUG, "A");
+ else if(IS_INTRA4x4(mb_type))
+ av_log(s->avctx, AV_LOG_DEBUG, "i");
+ else if(IS_INTRA16x16(mb_type))
+ av_log(s->avctx, AV_LOG_DEBUG, "I");
+ else if(IS_DIRECT(mb_type) && IS_SKIP(mb_type))
+ av_log(s->avctx, AV_LOG_DEBUG, "d");
+ else if(IS_DIRECT(mb_type))
+ av_log(s->avctx, AV_LOG_DEBUG, "D");
+ else if(IS_GMC(mb_type) && IS_SKIP(mb_type))
+ av_log(s->avctx, AV_LOG_DEBUG, "g");
+ else if(IS_GMC(mb_type))
+ av_log(s->avctx, AV_LOG_DEBUG, "G");
+ else if(IS_SKIP(mb_type))
+ av_log(s->avctx, AV_LOG_DEBUG, "S");
+ else if(!USES_LIST(mb_type, 1))
+ av_log(s->avctx, AV_LOG_DEBUG, ">");
+ else if(!USES_LIST(mb_type, 0))
+ av_log(s->avctx, AV_LOG_DEBUG, "<");
+ else{
+ assert(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1));
+ av_log(s->avctx, AV_LOG_DEBUG, "X");
+ }
+
+ //segmentation
+ if(IS_8X8(mb_type))
+ av_log(s->avctx, AV_LOG_DEBUG, "+");
+ else if(IS_16X8(mb_type))
+ av_log(s->avctx, AV_LOG_DEBUG, "-");
+ else if(IS_8X16(mb_type))
+ av_log(s->avctx, AV_LOG_DEBUG, "|");
+ else if(IS_INTRA(mb_type) || IS_16X16(mb_type))
+ av_log(s->avctx, AV_LOG_DEBUG, " ");
+ else
+ av_log(s->avctx, AV_LOG_DEBUG, "?");
+
+
+ if(IS_INTERLACED(mb_type) && s->codec_id == CODEC_ID_H264)
+ av_log(s->avctx, AV_LOG_DEBUG, "=");
+ else
+ av_log(s->avctx, AV_LOG_DEBUG, " ");
+ }
+// av_log(s->avctx, AV_LOG_DEBUG, " ");
+ }
+ av_log(s->avctx, AV_LOG_DEBUG, "\n");
+ }
+ }
+
+ if((s->avctx->debug&(FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)) || (s->avctx->debug_mv)){
+ const int shift= 1 + s->quarter_sample;
+ int mb_y;
+ uint8_t *ptr;
+ int i;
+ int h_chroma_shift, v_chroma_shift;
+ const int width = s->avctx->width;
+ const int height= s->avctx->height;
+ const int mv_sample_log2= 4 - pict->motion_subsample_log2;
+ const int mv_stride= (s->mb_width << mv_sample_log2) + (s->codec_id == CODEC_ID_H264 ? 0 : 1);
+ s->low_delay=0; //needed to see the vectors without trashing the buffers
+
+ avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift);
+ for(i=0; i<3; i++){
+ memcpy(s->visualization_buffer[i], pict->data[i], (i==0) ? pict->linesize[i]*height:pict->linesize[i]*height >> v_chroma_shift);
+ pict->data[i]= s->visualization_buffer[i];
+ }
+ pict->type= FF_BUFFER_TYPE_COPY;
+ ptr= pict->data[0];
+
+ for(mb_y=0; mb_y<s->mb_height; mb_y++){
+ int mb_x;
+ for(mb_x=0; mb_x<s->mb_width; mb_x++){
+ const int mb_index= mb_x + mb_y*s->mb_stride;
+ if((s->avctx->debug_mv) && pict->motion_val){
+ int type;
+ for(type=0; type<3; type++){
+ int direction = 0;
+ switch (type) {
+ case 0: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_P_FOR)) || (pict->pict_type!=FF_P_TYPE))
+ continue;
+ direction = 0;
+ break;
+ case 1: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_B_FOR)) || (pict->pict_type!=FF_B_TYPE))
+ continue;
+ direction = 0;
+ break;
+ case 2: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_B_BACK)) || (pict->pict_type!=FF_B_TYPE))
+ continue;
+ direction = 1;
+ break;
+ }
+ if(!USES_LIST(pict->mb_type[mb_index], direction))
+ continue;
+
+ if(IS_8X8(pict->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= (pict->motion_val[direction][xy][0]>>shift) + sx;
+ int my= (pict->motion_val[direction][xy][1]>>shift) + sy;
+ draw_arrow(ptr, sx, sy, mx, my, width, height, s->linesize, 100);
+ }
+ }else if(IS_16X8(pict->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=(pict->motion_val[direction][xy][0]>>shift);
+ int my=(pict->motion_val[direction][xy][1]>>shift);
+
+ if(IS_INTERLACED(pict->mb_type[mb_index]))
+ my*=2;
+
+ draw_arrow(ptr, sx, sy, mx+sx, my+sy, width, height, s->linesize, 100);
+ }
+ }else if(IS_8X16(pict->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=(pict->motion_val[direction][xy][0]>>shift);
+ int my=(pict->motion_val[direction][xy][1]>>shift);
+
+ if(IS_INTERLACED(pict->mb_type[mb_index]))
+ my*=2;
+
+ draw_arrow(ptr, sx, sy, mx+sx, my+sy, width, height, s->linesize, 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= (pict->motion_val[direction][xy][0]>>shift) + sx;
+ int my= (pict->motion_val[direction][xy][1]>>shift) + sy;
+ draw_arrow(ptr, sx, sy, mx, my, width, height, s->linesize, 100);
+ }
+ }
+ }
+ if((s->avctx->debug&FF_DEBUG_VIS_QP) && pict->motion_val){
+ uint64_t c= (pict->qscale_table[mb_index]*128/31) * 0x0101010101010101ULL;
+ int y;
+ for(y=0; y<8; y++){
+ *(uint64_t*)(pict->data[1] + 8*mb_x + (8*mb_y + y)*pict->linesize[1])= c;
+ *(uint64_t*)(pict->data[2] + 8*mb_x + (8*mb_y + y)*pict->linesize[2])= c;
+ }
+ }
+ if((s->avctx->debug&FF_DEBUG_VIS_MB_TYPE) && pict->motion_val){
+ int mb_type= pict->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{
+ assert(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1));
+ COLOR(300,48)
+ }
+
+ u*= 0x0101010101010101ULL;
+ v*= 0x0101010101010101ULL;
+ for(y=0; y<8; y++){
+ *(uint64_t*)(pict->data[1] + 8*mb_x + (8*mb_y + y)*pict->linesize[1])= u;
+ *(uint64_t*)(pict->data[2] + 8*mb_x + (8*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*)&pict->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) && s->codec_id == CODEC_ID_H264){
+ // hmm
+ }
+ }
+ s->mbskip_table[mb_index]=0;
+ }
+ }
+ }
+}
+
+#ifdef CONFIG_ENCODERS
+
+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, AVFrame *pic_arg){
+ AVFrame *pic=NULL;
+ int64_t pts;
+ int i;
+ const int encoding_delay= s->max_b_frames;
+ int direct=1;
+
+ if(pic_arg){
+ pts= pic_arg->pts;
+ pic_arg->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;
+ }
+ }
+ 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= pic_arg->display_picture_number;
+ }
+ }
+ }
+
+ if(pic_arg){
+ if(encoding_delay && !(s->flags&CODEC_FLAG_INPUT_PRESERVED)) 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_log(AV_LOG_DEBUG, "%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);
+
+ pic= (AVFrame*)&s->picture[i];
+ pic->reference= 3;
+
+ for(i=0; i<4; i++){
+ pic->data[i]= pic_arg->data[i];
+ pic->linesize[i]= pic_arg->linesize[i];
+ }
+ alloc_picture(s, (Picture*)pic, 1);
+ }else{
+ i= ff_find_unused_picture(s, 0);
+
+ pic= (AVFrame*)&s->picture[i];
+ pic->reference= 3;
+
+ alloc_picture(s, (Picture*)pic, 0);
+
+ if( pic->data[0] + INPLACE_OFFSET == pic_arg->data[0]
+ && pic->data[1] + INPLACE_OFFSET == pic_arg->data[1]
+ && pic->data[2] + INPLACE_OFFSET == pic_arg->data[2]){
+ // empty
+ }else{
+ int h_chroma_shift, v_chroma_shift;
+ avcodec_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->data[i];
+
+ if(!s->avctx->rc_buffer_size)
+ dst +=INPLACE_OFFSET;
+
+ if(src_stride==dst_stride)
+ memcpy(dst, src, src_stride*h);
+ else{
+ while(h--){
+ memcpy(dst, src, w);
+ dst += dst_stride;
+ src += src_stride;
+ }
+ }
+ }
+ }
+ }
+ copy_picture_attributes(s, pic, pic_arg);
+ pic->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->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->type == FF_BUFFER_TYPE_SHARED ? 0: 16;
+ int v= s->dsp.frame_skip_cmp[1](s, p->data[plane] + 8*(x + y*stride)+off, ref->data[plane] + 8*(x + y*stride), 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 estimate_best_b_count(MpegEncContext *s){
+ AVCodec *codec= avcodec_find_encoder(s->avctx->codec_id);
+ AVCodecContext *c= avcodec_alloc_context();
+ AVFrame input[FF_MAX_B_FRAMES+2];
+ const int scale= s->avctx->brd_scale;
+ int i, j, out_size, p_lambda, b_lambda, lambda2;
+ int outbuf_size= s->width * s->height; //FIXME
+ uint8_t *outbuf= av_malloc(outbuf_size);
+ int64_t best_rd= INT64_MAX;
+ int best_b_count= -1;
+
+ assert(scale>=0 && scale <=3);
+
+// emms_c();
+ p_lambda= s->last_lambda_for[P_TYPE]; //s->next_picture_ptr->quality;
+ b_lambda= s->last_lambda_for[B_TYPE]; //p_lambda *FFABS(s->avctx->b_quant_factor) + s->avctx->b_quant_offset;
+ if(!b_lambda) b_lambda= p_lambda; //FIXME we should do this somewhere else
+ 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 = PIX_FMT_YUV420P;
+ c->time_base= s->avctx->time_base;
+ c->max_b_frames= s->max_b_frames;
+
+ if (avcodec_open(c, codec) < 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;
+
+ if(pre_input_ptr)
+ pre_input= *pre_input_ptr;
+
+ if(pre_input.type != FF_BUFFER_TYPE_SHARED && i){
+ pre_input.data[0]+=INPLACE_OFFSET;
+ pre_input.data[1]+=INPLACE_OFFSET;
+ pre_input.data[2]+=INPLACE_OFFSET;
+ }
+
+ 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(!i || s->input_picture[i-1]){
+ s->dsp.shrink[scale](input[i].data[0], input[i].linesize[0], pre_input.data[0], pre_input.linesize[0], c->width, c->height);
+ s->dsp.shrink[scale](input[i].data[1], input[i].linesize[1], pre_input.data[1], pre_input.linesize[1], c->width>>1, c->height>>1);
+ s->dsp.shrink[scale](input[i].data[2], input[i].linesize[2], pre_input.data[2], pre_input.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= I_TYPE;
+ input[0].quality= 1 * FF_QP2LAMBDA;
+ out_size = avcodec_encode_video(c, outbuf, outbuf_size, &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 ? P_TYPE : B_TYPE;
+ input[i+1].quality= is_p ? p_lambda : b_lambda;
+ out_size = avcodec_encode_video(c, outbuf, outbuf_size, &input[i+1]);
+ rd += (out_size * lambda2) >> (FF_LAMBDA_SHIFT - 3);
+ }
+
+ /* get the delayed frames */
+ while(out_size){
+ out_size = avcodec_encode_video(c, outbuf, outbuf_size, 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;
+ }
+ }
+
+ av_freep(&outbuf);
+ 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 void select_input_picture(MpegEncContext *s){
+ int i;
+
+ 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]->pict_type= I_TYPE;
+ s->reordered_input_picture[0]->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_log(NULL, AV_LOG_DEBUG, "skip %p %"PRId64"\n", s->input_picture[0]->data[0], s->input_picture[0]->pts);
+
+ if(s->input_picture[0]->type == FF_BUFFER_TYPE_SHARED){
+ for(i=0; i<4; i++)
+ s->input_picture[0]->data[i]= NULL;
+ s->input_picture[0]->type= 0;
+ }else{
+ assert( s->input_picture[0]->type==FF_BUFFER_TYPE_USER
+ || s->input_picture[0]->type==FF_BUFFER_TYPE_INTERNAL);
+
+ s->avctx->release_buffer(s->avctx, (AVFrame*)s->input_picture[0]);
+ }
+
+ 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]->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 = P_TYPE;
+ break;
+ }
+
+ s->input_picture[i]->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 ]->data[0],
+ s->input_picture[i-1]->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();
+//static int b_count=0;
+//b_count+= b_frames;
+//av_log(s->avctx, AV_LOG_DEBUG, "b_frames: %d\n", b_count);
+
+ for(i= b_frames - 1; i>=0; i--){
+ int type= s->input_picture[i]->pict_type;
+ if(type && type != B_TYPE)
+ b_frames= i;
+ }
+ if(s->input_picture[b_frames]->pict_type == B_TYPE && 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->flags2 & CODEC_FLAG2_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]->pict_type= I_TYPE;
+ }
+ }
+
+ if( (s->flags & CODEC_FLAG_CLOSED_GOP)
+ && b_frames
+ && s->input_picture[b_frames]->pict_type== I_TYPE)
+ b_frames--;
+
+ s->reordered_input_picture[0]= s->input_picture[b_frames];
+ if(s->reordered_input_picture[0]->pict_type != I_TYPE)
+ s->reordered_input_picture[0]->pict_type= P_TYPE;
+ s->reordered_input_picture[0]->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]->pict_type= B_TYPE;
+ s->reordered_input_picture[i+1]->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]->pict_type!=B_TYPE ? 3 : 0;
+
+ copy_picture(&s->new_picture, s->reordered_input_picture[0]);
+
+ if(s->reordered_input_picture[0]->type == FF_BUFFER_TYPE_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
+
+ int i= ff_find_unused_picture(s, 0);
+ Picture *pic= &s->picture[i];
+
+ pic->reference = s->reordered_input_picture[0]->reference;
+ alloc_picture(s, pic, 0);
+
+ /* mark us unused / free shared pic */
+ if(s->reordered_input_picture[0]->type == FF_BUFFER_TYPE_INTERNAL)
+ s->avctx->release_buffer(s->avctx, (AVFrame*)s->reordered_input_picture[0]);
+ for(i=0; i<4; i++)
+ s->reordered_input_picture[0]->data[i]= NULL;
+ s->reordered_input_picture[0]->type= 0;
+
+ copy_picture_attributes(s, (AVFrame*)pic, (AVFrame*)s->reordered_input_picture[0]);
+
+ s->current_picture_ptr= pic;
+ }else{
+ // input is not a shared pix -> reuse buffer for current_pix
+
+ assert( s->reordered_input_picture[0]->type==FF_BUFFER_TYPE_USER
+ || s->reordered_input_picture[0]->type==FF_BUFFER_TYPE_INTERNAL);
+
+ s->current_picture_ptr= s->reordered_input_picture[0];
+ for(i=0; i<4; i++){
+ s->new_picture.data[i]+= INPLACE_OFFSET;
+ }
+ }
+ copy_picture(&s->current_picture, s->current_picture_ptr);
+
+ s->picture_number= s->new_picture.display_picture_number;
+//printf("dpn:%d\n", s->picture_number);
+ }else{
+ memset(&s->new_picture, 0, sizeof(Picture));
+ }
+}
+
+int MPV_encode_picture(AVCodecContext *avctx,
+ unsigned char *buf, int buf_size, void *data)
+{
+ MpegEncContext *s = avctx->priv_data;
+ AVFrame *pic_arg = data;
+ int i, stuffing_count;
+
+ for(i=0; i<avctx->thread_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= buf + (size_t)(((int64_t) buf_size)*start_y/h);
+ uint8_t *end = buf + (size_t)(((int64_t) buf_size)* end_y/h);
+
+ init_put_bits(&s->thread_context[i]->pb, start, end - start);
+ }
+
+ s->picture_in_gop_number++;
+
+ if(load_input_picture(s, pic_arg) < 0)
+ return -1;
+
+ select_input_picture(s);
+
+ /* output? */
+ if(s->new_picture.data[0]){
+ s->pict_type= s->new_picture.pict_type;
+//emms_c();
+//printf("qs:%f %f %d\n", s->new_picture.quality, s->current_picture.quality, s->qscale);
+ MPV_frame_start(s, avctx);
+vbv_retry:
+ if (encode_picture(s, s->picture_number) < 0)
+ return -1;
+
+ avctx->real_pict_num = s->picture_number;
+ 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;
+ avctx->p_count = s->mb_num - s->i_count - s->skip_count; //FIXME f/b_count in avctx
+ avctx->skip_count = s->skip_count;
+
+ MPV_frame_end(s);
+
+ if (s->out_format == FMT_MJPEG)
+ mjpeg_picture_trailer(s);
+
+ if(avctx->rc_buffer_size){
+ RateControlContext *rcc= &s->rc_context;
+ int max_size= rcc->buffer_index/3;
+
+ 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()
+ if(s->pict_type==P_TYPE){ //done in encode_picture() so we must undo it
+ if(s->flipflop_rounding || s->codec_id == CODEC_ID_H263P || s->codec_id == CODEC_ID_MPEG4)
+ s->no_rounding ^= 1;
+ }
+ if(s->pict_type!=B_TYPE){
+ s->time_base= s->last_time_base;
+ s->last_non_b_time= s->time - s->pp_time;
+ }
+// av_log(NULL, AV_LOG_ERROR, "R:%d ", s->next_lambda);
+ for(i=0; i<avctx->thread_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->error[i]= s->current_picture.error[i];
+ avctx->error[i] += s->current_picture_ptr->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);
+ 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 CODEC_ID_MPEG1VIDEO:
+ case CODEC_ID_MPEG2VIDEO:
+ while(stuffing_count--){
+ put_bits(&s->pb, 8, 0);
+ }
+ break;
+ case 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;
+
+ assert(s->repeat_first_field==0);
+
+ vbv_delay= lrintf(90000 * s->rc_context.buffer_index / s->avctx->rc_max_rate);
+ assert(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;
+ }
+ s->total_bits += s->frame_bits;
+ avctx->frame_bits = s->frame_bits;
+ }else{
+ assert((pbBufPtr(&s->pb) == s->pb.buf));
+ s->frame_bits=0;
+ }
+ assert((s->frame_bits&7)==0);
+
+ return s->frame_bits/8;
+}
+
+#endif //CONFIG_ENCODERS
+
+static inline 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 = clip(src_x, -16, s->width);
+ if (src_x == s->width)
+ motion_x =0;
+ src_y = 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 >= s->h_edge_pos - 17
+ || (unsigned)src_y >= s->v_edge_pos - 17){
+ ff_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->dsp.put_no_rnd_pixels_tab[0][dxy](dest_y, ptr, linesize, 16);
+ }else{
+ s->dsp.put_pixels_tab [0][dxy](dest_y, ptr, linesize, 16);
+ }
+ }
+
+ if(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 = clip(src_x, -8, s->width>>1);
+ if (src_x == s->width>>1)
+ motion_x =0;
+ src_y = 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 >= (s->h_edge_pos>>1) - 9
+ || (unsigned)src_y >= (s->v_edge_pos>>1) - 9){
+ ff_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){
+ ff_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 inline 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(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);
+}
+
+/**
+ * Copies a rectangular area of samples to a temporary buffer and replicates the boarder 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 ff_emulated_edge_mc(uint8_t *buf, uint8_t *src, int linesize, 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;
+
+ if(src_y>= h){
+ src+= (h-1-src_y)*linesize;
+ src_y=h-1;
+ }else if(src_y<=-block_h){
+ src+= (1-block_h-src_y)*linesize;
+ 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);
+
+ // copy existing part
+ for(y=start_y; y<end_y; y++){
+ for(x=start_x; x<end_x; x++){
+ buf[x + y*linesize]= src[x + y*linesize];
+ }
+ }
+
+ //top
+ for(y=0; y<start_y; y++){
+ for(x=start_x; x<end_x; x++){
+ buf[x + y*linesize]= buf[x + start_y*linesize];
+ }
+ }
+
+ //bottom
+ for(y=end_y; y<block_h; y++){
+ for(x=start_x; x<end_x; x++){
+ buf[x + y*linesize]= buf[x + (end_y-1)*linesize];
+ }
+ }
+
+ for(y=0; y<block_h; y++){
+ //left
+ for(x=0; x<start_x; x++){
+ buf[x + y*linesize]= buf[start_x + y*linesize];
+ }
+
+ //right
+ for(x=end_x; x<block_w; x++){
+ buf[x + y*linesize]= buf[end_x - 1 + y*linesize];
+ }
+ }
+}
+
+static inline int hpel_motion(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, op_pixels_func *pix_op,
+ int motion_x, int motion_y)
+{
+ int dxy;
+ int emu=0;
+
+ dxy = ((motion_y & 1) << 1) | (motion_x & 1);
+ src_x += motion_x >> 1;
+ src_y += motion_y >> 1;
+
+ /* WARNING: do no forget half pels */
+ src_x = clip(src_x, -16, width); //FIXME unneeded for emu?
+ if (src_x == width)
+ dxy &= ~1;
+ src_y = clip(src_y, -16, height);
+ if (src_y == height)
+ dxy &= ~2;
+ src += src_y * stride + src_x;
+
+ if(s->unrestricted_mv && (s->flags&CODEC_FLAG_EMU_EDGE)){
+ if( (unsigned)src_x > h_edge_pos - (motion_x&1) - w
+ || (unsigned)src_y > v_edge_pos - (motion_y&1) - h){
+ ff_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, s->v_edge_pos);
+ src= s->edge_emu_buffer;
+ emu=1;
+ }
+ }
+ if(field_select)
+ src += s->linesize;
+ pix_op[dxy](dest, src, stride, h);
+ return emu;
+}
+
+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 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 > h_edge_pos - (!!sx) - w
+ || (unsigned)src_y >(v_edge_pos >> field_based) - (!!sy) - h){
+ ff_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 <<= 2 - lowres;
+ sy <<= 2 - lowres;
+ if(field_select)
+ src += s->linesize;
+ pix_op[lowres](dest, src, stride, h, sx, sy);
+ return emu;
+}
+
+/* apply one mpeg motion vector to the three components */
+static always_inline void mpeg_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],
+ 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, 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.linesize[0] << field_based;
+ uvlinesize = s->current_picture.linesize[1] << field_based;
+
+ dxy = ((motion_y & 1) << 1) | (motion_x & 1);
+ src_x = s->mb_x* 16 + (motion_x >> 1);
+ src_y =(s->mb_y<<(4-field_based)) + (motion_y >> 1);
+
+ if (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 = (s->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(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 = s->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 = (s->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 > s->h_edge_pos - (motion_x&1) - 16
+ || (unsigned)src_y > v_edge_pos - (motion_y&1) - h){
+ if(s->codec_id == CODEC_ID_MPEG2VIDEO ||
+ s->codec_id == CODEC_ID_MPEG1VIDEO){
+ av_log(s->avctx,AV_LOG_DEBUG,"MPEG motion vector out of boundary\n");
+ return ;
+ }
+ ff_emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize, 17, 17+field_based,
+ src_x, src_y<<field_based, s->h_edge_pos, s->v_edge_pos);
+ ptr_y = s->edge_emu_buffer;
+ if(!(s->flags&CODEC_FLAG_GRAY)){
+ uint8_t *uvbuf= s->edge_emu_buffer+18*s->linesize;
+ ff_emulated_edge_mc(uvbuf , ptr_cb, s->uvlinesize, 9, 9+field_based,
+ uvsrc_x, uvsrc_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1);
+ ff_emulated_edge_mc(uvbuf+16, ptr_cr, s->uvlinesize, 9, 9+field_based,
+ uvsrc_x, uvsrc_y<<field_based, s->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(!(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 defined(CONFIG_H261_ENCODER) || defined(CONFIG_H261_DECODER)
+ if(s->out_format == FMT_H261){
+ ff_h261_loop_filter(s);
+ }
+#endif
+}
+
+/* apply one mpeg motion vector to the three components */
+static 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)
+{
+ 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 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.linesize[0] << field_based;
+ uvlinesize = s->current_picture.linesize[1] << field_based;
+
+ if(s->quarter_sample){ //FIXME obviously not perfect but qpel wont work in lowres anyway
+ 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 =(s->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 = s->mb_y*block_s + (my >> lowres);
+ } else {
+ 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 =(s->mb_y*block_s>>field_based) + (my >> (lowres+1));
+ }
+
+ 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 > h_edge_pos - (!!sx) - 2*block_s
+ || (unsigned)src_y >(v_edge_pos >> field_based) - (!!sy) - h){
+ ff_emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize, 17, 17+field_based,
+ src_x, src_y<<field_based, h_edge_pos, v_edge_pos);
+ ptr_y = s->edge_emu_buffer;
+ if(!(s->flags&CODEC_FLAG_GRAY)){
+ uint8_t *uvbuf= s->edge_emu_buffer+18*s->linesize;
+ ff_emulated_edge_mc(uvbuf , ptr_cb, s->uvlinesize, 9, 9+field_based,
+ uvsrc_x, uvsrc_y<<field_based, h_edge_pos>>1, v_edge_pos>>1);
+ ff_emulated_edge_mc(uvbuf+16, ptr_cr, s->uvlinesize, 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;
+ }
+ }
+
+ 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;
+ }
+
+ sx <<= 2 - lowres;
+ sy <<= 2 - lowres;
+ pix_op[lowres-1](dest_y, ptr_y, linesize, h, sx, sy);
+
+ if(!(s->flags&CODEC_FLAG_GRAY)){
+ uvsx <<= 2 - lowres;
+ uvsy <<= 2 - lowres;
+ pix_op[lowres](dest_cb, ptr_cb, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy);
+ pix_op[lowres](dest_cr, ptr_cr, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy);
+ }
+ //FIXME h261 lowres loop filter
+}
+
+//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];
+
+ assert(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, 0, 0,
+ src_x, src_y,
+ s->width, s->height, s->linesize,
+ s->h_edge_pos, s->v_edge_pos,
+ 8, 8, 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 > s->h_edge_pos - (motion_x&3) - 16
+ || (unsigned)src_y > v_edge_pos - (motion_y&3) - h ){
+ ff_emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize, 17, 17+field_based,
+ src_x, src_y<<field_based, s->h_edge_pos, s->v_edge_pos);
+ ptr_y= s->edge_emu_buffer;
+ if(!(s->flags&CODEC_FLAG_GRAY)){
+ uint8_t *uvbuf= s->edge_emu_buffer + 18*s->linesize;
+ ff_emulated_edge_mc(uvbuf, ptr_cb, s->uvlinesize, 9, 9 + field_based,
+ uvsrc_x, uvsrc_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1);
+ ff_emulated_edge_mc(uvbuf + 16, ptr_cr, s->uvlinesize, 9, 9 + field_based,
+ uvsrc_x, uvsrc_y<<field_based, s->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(!(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);
+ }
+}
+
+inline int ff_h263_round_chroma(int x){
+ if (x >= 0)
+ return (h263_chroma_roundtab[x & 0xf] + ((x >> 3) & ~1));
+ else {
+ x = -x;
+ return -(h263_chroma_roundtab[x & 0xf] + ((x >> 3) & ~1));
+ }
+}
+
+/**
+ * h263 chorma 4mv motion compensation.
+ */
+static inline 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 = clip(src_x, -8, s->width/2);
+ if (src_x == s->width/2)
+ dxy &= ~1;
+ src_y = clip(src_y, -8, s->height/2);
+ if (src_y == s->height/2)
+ 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 > (s->h_edge_pos>>1) - (dxy &1) - 8
+ || (unsigned)src_y > (s->v_edge_pos>>1) - (dxy>>1) - 8){
+ ff_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){
+ ff_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 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 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 > h_edge_pos - (!!sx) - block_s
+ || (unsigned)src_y > v_edge_pos - (!!sy) - block_s){
+ ff_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 <<= 2 - lowres;
+ sy <<= 2 - lowres;
+ pix_op[lowres](dest_cb, ptr, s->uvlinesize, block_s, sx, sy);
+
+ ptr = ref_picture[2] + offset;
+ if(emu){
+ ff_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[lowres](dest_cr, ptr, s->uvlinesize, block_s, sx, sy);
+}
+
+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->dsp.prefetch(pix[0]+off, s->linesize, 4);
+ off= (mx>>1) + ((my>>1) + (s->mb_x&7))*s->uvlinesize + 64;
+ s->dsp.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 pic_op halfpel motion compensation function (average or put normally)
+ * @param pic_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 inline void 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])
+{
+ 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(s->obmc && s->pict_type != B_TYPE){
+ int16_t mv_cache[4][4][2];
+ 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;
+
+ assert(!s->mb_skipped);
+
+ memcpy(mv_cache[1][1], s->current_picture.motion_val[0][mot_xy ], sizeof(int16_t)*4);
+ memcpy(mv_cache[2][1], s->current_picture.motion_val[0][mot_xy+mot_stride], sizeof(int16_t)*4);
+ memcpy(mv_cache[3][1], s->current_picture.motion_val[0][mot_xy+mot_stride], sizeof(int16_t)*4);
+
+ if(mb_y==0 || IS_INTRA(s->current_picture.mb_type[xy-s->mb_stride])){
+ memcpy(mv_cache[0][1], mv_cache[1][1], sizeof(int16_t)*4);
+ }else{
+ memcpy(mv_cache[0][1], s->current_picture.motion_val[0][mot_xy-mot_stride], sizeof(int16_t)*4);
+ }
+
+ if(mb_x==0 || IS_INTRA(s->current_picture.mb_type[xy-1])){
+ *(int32_t*)mv_cache[1][0]= *(int32_t*)mv_cache[1][1];
+ *(int32_t*)mv_cache[2][0]= *(int32_t*)mv_cache[2][1];
+ }else{
+ *(int32_t*)mv_cache[1][0]= *(int32_t*)s->current_picture.motion_val[0][mot_xy-1];
+ *(int32_t*)mv_cache[2][0]= *(int32_t*)s->current_picture.motion_val[0][mot_xy-1+mot_stride];
+ }
+
+ if(mb_x+1>=s->mb_width || IS_INTRA(s->current_picture.mb_type[xy+1])){
+ *(int32_t*)mv_cache[1][3]= *(int32_t*)mv_cache[1][2];
+ *(int32_t*)mv_cache[2][3]= *(int32_t*)mv_cache[2][2];
+ }else{
+ *(int32_t*)mv_cache[1][3]= *(int32_t*)s->current_picture.motion_val[0][mot_xy+2];
+ *(int32_t*)mv_cache[2][3]= *(int32_t*)s->current_picture.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(!(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(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(s->mspel){
+ 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, 0, 0,
+ ref_picture, pix_op,
+ s->mv[dir][0][0], s->mv[dir][0][1], 16);
+ }
+ break;
+ case MV_TYPE_8X8:
+ 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 = clip(src_x, -16, s->width);
+ if (src_x == s->width)
+ dxy &= ~3;
+ src_y = 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 > s->h_edge_pos - (motion_x&3) - 8
+ || (unsigned)src_y > s->v_edge_pos - (motion_y&3) - 8 ){
+ ff_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], 0, 0,
+ mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >>1) * 8,
+ s->width, s->height, s->linesize,
+ s->h_edge_pos, s->v_edge_pos,
+ 8, 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(!(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(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(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], 8);
+ /* bottom field */
+ mpeg_motion(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], 8);
+ }
+ } else {
+ if(s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != B_TYPE && !s->first_field){
+ ref_picture= s->current_picture_ptr->data;
+ }
+
+ mpeg_motion(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], 16);
+ }
+ 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 == B_TYPE || s->first_field){
+ ref2picture= ref_picture;
+ }else{
+ ref2picture= s->current_picture_ptr->data;
+ }
+
+ mpeg_motion(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] + 16*i, 8);
+
+ 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(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], 8);
+ }
+ pix_op = s->dsp.avg_pixels_tab;
+ }
+ }else{
+ for(i=0; i<2; i++){
+ mpeg_motion(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],16);
+
+ // after put we make avg of the same block
+ pix_op=s->dsp.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->data;
+ }
+ }
+ }
+ break;
+ default: assert(0);
+ }
+}
+
+/**
+ * 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 pic_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);
+ 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(!(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);
+ /* 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);
+ } else {
+ if(s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != B_TYPE && !s->first_field){
+ ref_picture= s->current_picture_ptr->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);
+ }
+ 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 == B_TYPE || s->first_field){
+ ref2picture= ref_picture;
+ }else{
+ ref2picture= s->current_picture_ptr->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);
+
+ 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);
+ }
+ pix_op = s->dsp.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);
+
+ // after put we make avg of the same block
+ pix_op = s->dsp.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->data;
+ }
+ }
+ }
+ break;
+ default: assert(0);
+ }
+}
+
+/* put block[] to dest[] */
+static inline void put_dct(MpegEncContext *s,
+ DCTELEM *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,
+ DCTELEM *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,
+ DCTELEM *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);
+ }
+}
+
+/**
+ * cleans 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 always_inline void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64], int lowres_flag)
+{
+ int mb_x, mb_y;
+ const int mb_xy = s->mb_y * s->mb_stride + s->mb_x;
+#ifdef HAVE_XVMC
+ if(s->avctx->xvmc_acceleration){
+ XVMC_decode_mb(s);//xvmc uses pblocks
+ return;
+ }
+#endif
+
+ mb_x = s->mb_x;
+ mb_y = s->mb_y;
+
+ if(s->avctx->debug&FF_DEBUG_DCT_COEFF) {
+ /* save DCT coefficients */
+ int i,j;
+ DCTELEM *dct = &s->current_picture.dct_coeff[mb_xy*64*6];
+ for(i=0; i<6; i++)
+ for(j=0; j<64; j++)
+ *dct++ = block[i][s->dsp.idct_permutation[j]];
+ }
+
+ s->current_picture.qscale_table[mb_xy]= s->qscale;
+
+ /* update DC predictors for P macroblocks */
+ if (!s->mb_intra) {
+ if (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 (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==B_TYPE) && 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.linesize[0]; //not s->linesize as this would be wrong for field pics
+ const int uvlinesize= s->current_picture.linesize[1];
+ const int readable= s->pict_type != B_TYPE || 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];
+ const int age= s->current_picture.age;
+
+ assert(age);
+
+ if (s->mb_skipped) {
+ s->mb_skipped= 0;
+ assert(s->pict_type!=I_TYPE);
+
+ (*mbskip_ptr) ++; /* indicate that this time we skipped it */
+ if(*mbskip_ptr >99) *mbskip_ptr= 99;
+
+ /* if previous was skipped too, then nothing to do ! */
+ if (*mbskip_ptr >= age && s->current_picture.reference){
+ return;
+ }
+ } else if(!s->current_picture.reference){
+ (*mbskip_ptr) ++; /* increase counter so the age can be compared cleanly */
+ if(*mbskip_ptr >99) *mbskip_ptr= 99;
+ } 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(lowres_flag){
+ h264_chroma_mc_func *op_pix = s->dsp.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.data, op_pix);
+ op_pix = s->dsp.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.data, op_pix);
+ }
+ }else{
+ op_qpix= s->me.qpel_put;
+ if ((!s->no_rounding) || s->pict_type==B_TYPE){
+ op_pix = s->dsp.put_pixels_tab;
+ }else{
+ op_pix = s->dsp.put_no_rnd_pixels_tab;
+ }
+ if (s->mv_dir & MV_DIR_FORWARD) {
+ MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.data, op_pix, op_qpix);
+ op_pix = s->dsp.avg_pixels_tab;
+ op_qpix= s->me.qpel_avg;
+ }
+ if (s->mv_dir & MV_DIR_BACKWARD) {
+ MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.data, op_pix, op_qpix);
+ }
+ }
+ }
+
+ /* skip dequant / idct if we are really late ;) */
+ if(s->hurry_up>1) goto skip_idct;
+ if(s->avctx->skip_idct){
+ if( (s->avctx->skip_idct >= AVDISCARD_NONREF && s->pict_type == B_TYPE)
+ ||(s->avctx->skip_idct >= AVDISCARD_NONKEY && s->pict_type != I_TYPE)
+ || s->avctx->skip_idct >= AVDISCARD_ALL)
+ goto skip_idct;
+ }
+
+ /* add dct residue */
+ if(s->encoding || !( s->h263_msmpeg4 || s->codec_id==CODEC_ID_MPEG1VIDEO || s->codec_id==CODEC_ID_MPEG2VIDEO
+ || (s->codec_id==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(!(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(s->codec_id != 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(!(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*8;
+
+ 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+8, dct_linesize);
+ add_dct(s, block[9], 9, dest_cr+8, dct_linesize);
+ add_dct(s, block[10], 10, dest_cb+8+dct_offset, dct_linesize);
+ add_dct(s, block[11], 11, dest_cr+8+dct_offset, dct_linesize);
+ }
+ }
+ }//fi gray
+ }
+ else{
+ ff_wmv2_add_mb(s, block, dest_y, dest_cb, dest_cr);
+ }
+ } else {
+ /* dct only in intra block */
+ if(s->encoding || !(s->codec_id==CODEC_ID_MPEG1VIDEO || s->codec_id==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(!(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(!(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*8;
+
+ 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 + 8, dct_linesize, block[8]);
+ s->dsp.idct_put(dest_cr + 8, dct_linesize, block[9]);
+ s->dsp.idct_put(dest_cb + 8 + dct_offset, dct_linesize, block[10]);
+ s->dsp.idct_put(dest_cr + 8 + dct_offset, dct_linesize, block[11]);
+ }
+ }
+ }//gray
+ }
+ }
+skip_idct:
+ if(!readable){
+ s->dsp.put_pixels_tab[0][0](s->dest[0], dest_y , linesize,16);
+ s->dsp.put_pixels_tab[s->chroma_x_shift][0](s->dest[1], dest_cb, uvlinesize,16 >> s->chroma_y_shift);
+ s->dsp.put_pixels_tab[s->chroma_x_shift][0](s->dest[2], dest_cr, uvlinesize,16 >> s->chroma_y_shift);
+ }
+ }
+}
+
+void MPV_decode_mb(MpegEncContext *s, DCTELEM block[12][64]){
+ if(s->avctx->lowres) MPV_decode_mb_internal(s, block, 1);
+ else MPV_decode_mb_internal(s, block, 0);
+}
+
+#ifdef CONFIG_ENCODERS
+
+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;
+ DCTELEM *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 which we could set to zero are allready 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, DCTELEM *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);
+}
+
+#endif //CONFIG_ENCODERS
+
+/**
+ *
+ * @param h is the normal height, this will be reduced automatically if needed for the last row
+ */
+void ff_draw_horiz_band(MpegEncContext *s, int y, int h){
+ if (s->avctx->draw_horiz_band) {
+ AVFrame *src;
+ int offset[4];
+
+ if(s->picture_structure != PICT_FRAME){
+ h <<= 1;
+ y <<= 1;
+ if(s->first_field && !(s->avctx->slice_flags&SLICE_FLAG_ALLOW_FIELD)) return;
+ }
+
+ h= FFMIN(h, s->avctx->height - y);
+
+ if(s->pict_type==B_TYPE || s->low_delay || (s->avctx->slice_flags&SLICE_FLAG_CODED_ORDER))
+ src= (AVFrame*)s->current_picture_ptr;
+ else if(s->last_picture_ptr)
+ src= (AVFrame*)s->last_picture_ptr;
+ else
+ return;
+
+ if(s->pict_type==B_TYPE && s->picture_structure == PICT_FRAME && s->out_format != FMT_H264){
+ offset[0]=
+ offset[1]=
+ offset[2]=
+ offset[3]= 0;
+ }else{
+ offset[0]= y * s->linesize;;
+ offset[1]=
+ offset[2]= (y >> s->chroma_y_shift) * s->uvlinesize;
+ offset[3]= 0;
+ }
+
+ emms_c();
+
+ s->avctx->draw_horiz_band(s->avctx, src, offset,
+ y, s->picture_structure, h);
+ }
+}
+
+void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename
+ const int linesize= s->current_picture.linesize[0]; //not s->linesize as this would be wrong for field pics
+ const int uvlinesize= s->current_picture.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.data[0] + ((s->mb_x - 1) << mb_size);
+ s->dest[1] = s->current_picture.data[1] + ((s->mb_x - 1) << (mb_size - s->chroma_x_shift));
+ s->dest[2] = s->current_picture.data[2] + ((s->mb_x - 1) << (mb_size - s->chroma_x_shift));
+
+ if(!(s->pict_type==B_TYPE && s->avctx->draw_horiz_band && 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);
+ }
+}
+
+#ifdef CONFIG_ENCODERS
+
+static void get_vissual_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 always_inline void encode_mb_internal(MpegEncContext *s, int motion_x, int motion_y, int mb_block_height, int mb_block_count)
+{
+ int16_t weight[8][64];
+ DCTELEM orig[8][64];
+ const int mb_x= s->mb_x;
+ const int mb_y= s->mb_y;
+ int i;
+ int skip_dct[8];
+ int dct_offset = s->linesize*8; //default for progressive frames
+ uint8_t *ptr_y, *ptr_cb, *ptr_cr;
+ int wrap_y, wrap_c;
+
+ for(i=0; i<mb_block_count; i++) skip_dct[i]=0;
+
+ 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->flags&CODEC_FLAG_QP_RD)){
+ s->dquant= s->qscale - last_qp;
+
+ if(s->out_format==FMT_H263){
+ s->dquant= clip(s->dquant, -2, 2); //FIXME RD
+
+ if(s->codec_id==CODEC_ID_MPEG4){
+ if(!s->mb_intra){
+ if(s->pict_type == B_TYPE){
+ if(s->dquant&1)
+ s->dquant= (s->dquant/2)*2;
+ if(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->flags&CODEC_FLAG_QP_RD)
+ ff_set_qscale(s, s->qscale + s->dquant);
+
+ wrap_y = s->linesize;
+ wrap_c = s->uvlinesize;
+ ptr_y = s->new_picture.data[0] + (mb_y * 16 * wrap_y) + mb_x * 16;
+ ptr_cb = s->new_picture.data[1] + (mb_y * mb_block_height * wrap_c) + mb_x * 8;
+ ptr_cr = s->new_picture.data[2] + (mb_y * mb_block_height * wrap_c) + mb_x * 8;
+
+ if(mb_x*16+16 > s->width || mb_y*16+16 > s->height){
+ uint8_t *ebuf= s->edge_emu_buffer + 32;
+ ff_emulated_edge_mc(ebuf , ptr_y , wrap_y,16,16,mb_x*16,mb_y*16, s->width , s->height);
+ ptr_y= ebuf;
+ ff_emulated_edge_mc(ebuf+18*wrap_y , ptr_cb, wrap_c, 8, mb_block_height, mb_x*8, mb_y*8, s->width>>1, s->height>>1);
+ ptr_cb= ebuf+18*wrap_y;
+ ff_emulated_edge_mc(ebuf+18*wrap_y+8, ptr_cr, wrap_c, 8, mb_block_height, mb_x*8, mb_y*8, s->width>>1, s->height>>1);
+ ptr_cr= ebuf+18*wrap_y+8;
+ }
+
+ 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;
+ wrap_y<<=1;
+ if (s->chroma_format == CHROMA_422)
+ 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){ /* 422 */
+ s->dsp.get_pixels(s->block[6], ptr_cb + (dct_offset>>1), wrap_c);
+ s->dsp.get_pixels(s->block[7], ptr_cr + (dct_offset>>1), 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==B_TYPE){
+ op_pix = s->dsp.put_pixels_tab;
+ op_qpix= s->dsp.put_qpel_pixels_tab;
+ }else{
+ op_pix = s->dsp.put_no_rnd_pixels_tab;
+ op_qpix= s->dsp.put_no_rnd_qpel_pixels_tab;
+ }
+
+ if (s->mv_dir & MV_DIR_FORWARD) {
+ MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.data, op_pix, op_qpix);
+ op_pix = s->dsp.avg_pixels_tab;
+ op_qpix= s->dsp.avg_qpel_pixels_tab;
+ }
+ if (s->mv_dir & MV_DIR_BACKWARD) {
+ MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.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;
+ 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 + (dct_offset>>1), dest_cb + (dct_offset>>1), wrap_c);
+ s->dsp.diff_pixels(s->block[7], ptr_cr + (dct_offset>>1), dest_cr + (dct_offset>>1), 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 +(dct_offset>>1), dest_cb +(dct_offset>>1), wrap_c, 8) < 20*s->qscale) skip_dct[6]= 1;
+ if(s->dsp.sad[1](NULL, ptr_cr +(dct_offset>>1), dest_cr +(dct_offset>>1), wrap_c, 8) < 20*s->qscale) skip_dct[7]= 1;
+ }
+ }
+ }
+
+ if(s->avctx->quantizer_noise_shaping){
+ if(!skip_dct[0]) get_vissual_weight(weight[0], ptr_y , wrap_y);
+ if(!skip_dct[1]) get_vissual_weight(weight[1], ptr_y + 8, wrap_y);
+ if(!skip_dct[2]) get_vissual_weight(weight[2], ptr_y + dct_offset , wrap_y);
+ if(!skip_dct[3]) get_vissual_weight(weight[3], ptr_y + dct_offset + 8, wrap_y);
+ if(!skip_dct[4]) get_vissual_weight(weight[4], ptr_cb , wrap_c);
+ if(!skip_dct[5]) get_vissual_weight(weight[5], ptr_cr , wrap_c);
+ if(!s->chroma_y_shift){ /* 422 */
+ if(!skip_dct[6]) get_vissual_weight(weight[6], ptr_cb + (dct_offset>>1), wrap_c);
+ if(!skip_dct[7]) get_vissual_weight(weight[7], ptr_cr + (dct_offset>>1), wrap_c);
+ }
+ memcpy(orig[0], s->block[0], sizeof(DCTELEM)*64*mb_block_count);
+ }
+
+ /* DCT & quantize */
+ assert(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->avctx->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->flags & CODEC_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;
+ }
+
+ //non c quantize code returns incorrect block_last_index FIXME
+ if(s->alternate_scan && s->dct_quantize != 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 CODEC_ID_MPEG1VIDEO:
+ case CODEC_ID_MPEG2VIDEO:
+ mpeg1_encode_mb(s, s->block, motion_x, motion_y); break;
+ case CODEC_ID_MPEG4:
+ mpeg4_encode_mb(s, s->block, motion_x, motion_y); break;
+ case CODEC_ID_MSMPEG4V2:
+ case CODEC_ID_MSMPEG4V3:
+ case CODEC_ID_WMV1:
+ msmpeg4_encode_mb(s, s->block, motion_x, motion_y); break;
+ case CODEC_ID_WMV2:
+ ff_wmv2_encode_mb(s, s->block, motion_x, motion_y); break;
+#ifdef CONFIG_H261_ENCODER
+ case CODEC_ID_H261:
+ ff_h261_encode_mb(s, s->block, motion_x, motion_y); break;
+#endif
+ case CODEC_ID_H263:
+ case CODEC_ID_H263P:
+ case CODEC_ID_FLV1:
+ case CODEC_ID_RV10:
+ case CODEC_ID_RV20:
+ h263_encode_mb(s, s->block, motion_x, motion_y); break;
+ case CODEC_ID_MJPEG:
+ mjpeg_encode_mb(s, s->block); break;
+ default:
+ assert(0);
+ }
+}
+
+static 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, 6);
+ else encode_mb_internal(s, motion_x, motion_y, 16, 8);
+}
+
+#endif //CONFIG_ENCODERS
+
+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++){
+ if(s->picture[i].data[0] && ( s->picture[i].type == FF_BUFFER_TYPE_INTERNAL
+ || s->picture[i].type == FF_BUFFER_TYPE_USER))
+ avctx->release_buffer(avctx, (AVFrame*)&s->picture[i]);
+ }
+ s->current_picture_ptr = s->last_picture_ptr = s->next_picture_ptr = NULL;
+
+ s->mb_x= s->mb_y= 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;
+}
+
+#ifdef CONFIG_ENCODERS
+void ff_copy_bits(PutBitContext *pb, uint8_t *src, int length)
+{
+ const uint16_t *srcw= (uint16_t*)src;
+ int words= length>>4;
+ int bits= length&15;
+ int i;
+
+ if(length==0) return;
+
+ if(words < 16){
+ for(i=0; i<words; i++) put_bits(pb, 16, be2me_16(srcw[i]));
+ }else if(put_bits_count(pb)&7){
+ for(i=0; i<words; i++) put_bits(pb, 16, be2me_16(srcw[i]));
+ }else{
+ for(i=0; put_bits_count(pb)&31; i++)
+ put_bits(pb, 8, src[i]);
+ flush_put_bits(pb);
+ memcpy(pbBufPtr(pb), src+i, 2*words-i);
+ skip_put_bytes(pb, 2*words-i);
+ }
+
+ put_bits(pb, bits, be2me_16(srcw[words])>>(16-bits));
+}
+
+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 then 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;
+}
+
+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 then 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;
+}
+
+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){
+ 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<h; y++){
+ for(x=0; x<w; x++){
+ acc+= sq[src1[x + y*stride] - src2[x + y*stride]];
+ }
+ }
+
+ assert(acc>=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.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.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.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.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.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.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.data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, s->dest[0], w, h, s->linesize)
+ +sse(s, s->new_picture.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.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= 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= arg;
+
+ 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==B_TYPE)
+ 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= arg;
+ int mb_x, mb_y;
+
+ 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.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(s->codec_id==CODEC_ID_MPEG4){
+ if(s->partitioned_frame){
+ ff_mpeg4_merge_partitions(s);
+ }
+
+ ff_mpeg4_stuffing(&s->pb);
+ }else if(s->out_format == FMT_MJPEG){
+ ff_mjpeg_stuffing(&s->pb);
+ }
+
+ 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 int encode_thread(AVCodecContext *c, void *arg){
+ MpegEncContext *s= arg;
+ int mb_x, mb_y, pdif = 0;
+ 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];
+//printf("%d->%d\n", s->resync_mb_y, s->end_mb_y);
+
+ 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.error[i] = 0;
+ }
+ s->mb_skip_run = 0;
+ memset(s->last_mv, 0, sizeof(s->last_mv));
+
+ s->last_mv_dir = 0;
+
+ switch(s->codec_id){
+ case CODEC_ID_H263:
+ case CODEC_ID_H263P:
+ case CODEC_ID_FLV1:
+ s->gob_index = ff_h263_get_gob_height(s);
+ break;
+ case CODEC_ID_MPEG4:
+ if(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++) {
+// printf("row %d at %X\n", s->mb_y, (int)s);
+ 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 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);
+
+#ifdef CONFIG_H261_ENCODER
+ if(s->codec_id == 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];
+ }
+#endif
+
+ /* 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 CODEC_ID_H263:
+ case CODEC_ID_H263P:
+ if(!s->h263_slice_structured)
+ if(s->mb_x || s->mb_y%s->gob_index) is_gob_start=0;
+ break;
+ case CODEC_ID_MPEG2VIDEO:
+ if(s->mb_x==0 && s->mb_y!=0) is_gob_start=1;
+ case CODEC_ID_MPEG1VIDEO:
+ if(s->mb_skip_run) is_gob_start=0;
+ break;
+ }
+
+ if(is_gob_start){
+ if(s->start_mb_y != mb_y || mb_x!=0){
+ write_slice_end(s);
+
+ if(s->codec_id==CODEC_ID_MPEG4 && s->partitioned_frame){
+ ff_mpeg4_init_partitions(s);
+ }
+ }
+
+ assert((put_bits_count(&s->pb)&7) == 0);
+ current_packet_size= pbBufPtr(&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;
+#ifndef ALT_BITSTREAM_WRITER
+ s->pb.buf_ptr= s->ptr_lastgob;
+#endif
+ assert(pbBufPtr(&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);
+ }
+
+ switch(s->codec_id){
+ case CODEC_ID_MPEG4:
+ ff_mpeg4_encode_video_packet_header(s);
+ ff_mpeg4_clean_buffers(s);
+ break;
+ case CODEC_ID_MPEG1VIDEO:
+ case CODEC_ID_MPEG2VIDEO:
+ ff_mpeg1_encode_slice_header(s);
+ ff_mpeg1_clean_buffers(s);
+ break;
+ case CODEC_ID_H263:
+ case CODEC_ID_H263P:
+ 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
+
+ if(mb_type & (mb_type-1) || (s->flags & CODEC_FLAG_QP_RD)){ // more than 1 MB type possible or CODEC_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_DIRECT){
+ int mx= s->b_direct_mv_table[xy][0];
+ int my= s->b_direct_mv_table[xy][1];
+
+ 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(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->flags & CODEC_FLAG_QP_RD){
+ if(best_s.mv_type==MV_TYPE_16X16 && !(best_s.mv_dir&MV_DIRECT)){
+ const int last_qp= backup_s.qscale;
+ int qpi, qp, dc[6];
+ DCTELEM 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};
+
+ assert(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 == B_TYPE ? 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(s->mb_intra && s->dc_val[0]){
+ 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(DCTELEM)*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(s->mb_intra && s->dc_val[0]){
+ 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(DCTELEM)*16);
+ }
+ }
+ }
+ }
+ qp= best_s.qscale;
+ s->current_picture.qscale_table[xy]= qp;
+ }
+ }
+
+ copy_context_after_encode(s, &best_s, -1);
+
+ pb_bits_count= put_bits_count(&s->pb);
+ flush_put_bits(&s->pb);
+ ff_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);
+ ff_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);
+ ff_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 (s->out_format == FMT_H263 && s->pict_type!=B_TYPE)
+ ff_h263_update_motion_val(s);
+
+ if(next_block==0){ //FIXME 16 vs linesize16
+ s->dsp.put_pixels_tab[0][0](s->dest[0], s->rd_scratchpad , s->linesize ,16);
+ s->dsp.put_pixels_tab[1][0](s->dest[1], s->rd_scratchpad + 16*s->linesize , s->uvlinesize, 8);
+ s->dsp.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)
+ MPV_decode_mb(s, s->block);
+ } else {
+ int motion_x, motion_y;
+ 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];
+ }
+ motion_x = motion_y = 0;
+ 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];
+ }
+ motion_x= motion_y= 0;
+ break;
+ case CANDIDATE_MB_TYPE_DIRECT:
+ 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_BIDIR:
+ s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD;
+ s->mb_intra= 0;
+ motion_x=0;
+ motion_y=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];
+// printf(" %d %d ", motion_x, motion_y);
+ 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];
+ }
+ motion_x=motion_y=0;
+ 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];
+ }
+ motion_x=motion_y=0;
+ 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];
+ }
+ }
+ motion_x=motion_y=0;
+ break;
+ default:
+ motion_x=motion_y=0; //gcc warning fix
+ 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 (s->out_format == FMT_H263 && s->pict_type!=B_TYPE)
+ ff_h263_update_motion_val(s);
+
+ 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.error[0] += sse(
+ s, s->new_picture.data[0] + s->mb_x*16 + s->mb_y*s->linesize*16,
+ s->dest[0], w, h, s->linesize);
+ s->current_picture.error[1] += sse(
+ s, s->new_picture.data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,
+ s->dest[1], w>>1, h>>1, s->uvlinesize);
+ s->current_picture.error[2] += sse(
+ s, s->new_picture .data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,
+ s->dest[2], w>>1, h>>1, s->uvlinesize);
+ }
+ if(s->loop_filter){
+ if(s->out_format == FMT_H263)
+ ff_h263_loop_filter(s);
+ }
+//printf("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 (s->msmpeg4_version && s->msmpeg4_version<4 && s->pict_type == I_TYPE)
+ 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 = pbBufPtr(&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(error_count);
+ MERGE(padding_bug_score);
+ MERGE(current_picture.error[0]);
+ MERGE(current_picture.error[1]);
+ MERGE(current_picture.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);
+ ff_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->quality=
+ s->current_picture.quality = s->next_lambda;
+ if(!dry_run) s->next_lambda= 0;
+ } else if (!s->fixed_qscale) {
+ s->current_picture_ptr->quality=
+ s->current_picture.quality = ff_rate_estimate_qscale(s, dry_run);
+ if (s->current_picture.quality < 0)
+ return -1;
+ }
+
+ if(s->adaptive_quant){
+ switch(s->codec_id){
+ case CODEC_ID_MPEG4:
+ ff_clean_mpeg4_qscales(s);
+ break;
+ case CODEC_ID_H263:
+ case CODEC_ID_H263P:
+ case CODEC_ID_FLV1:
+ ff_clean_h263_qscales(s);
+ break;
+ }
+
+ s->lambda= s->lambda_table[0];
+ //FIXME broken
+ }else
+ s->lambda= s->current_picture.quality;
+//printf("%d %d\n", s->avctx->global_quality, s->current_picture.quality);
+ update_qscale(s);
+ return 0;
+}
+
+static int encode_picture(MpegEncContext *s, int picture_number)
+{
+ int i;
+ int bits;
+
+ 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 == CODEC_ID_MPEG1VIDEO || s->codec_id == CODEC_ID_MPEG2VIDEO || (s->h263_pred && !s->h263_msmpeg4))
+ ff_set_mpeg4_time(s, s->picture_number); //FIXME rename and use has_b_frames or similar
+
+ s->me.scene_change_score=0;
+
+// s->lambda= s->current_picture_ptr->quality; //FIXME qscale / ... stuff for ME ratedistoration
+
+ if(s->pict_type==I_TYPE){
+ if(s->msmpeg4_version >= 3) s->no_rounding=1;
+ else s->no_rounding=0;
+ }else if(s->pict_type!=B_TYPE){
+ if(s->flipflop_rounding || s->codec_id == CODEC_ID_H263P || s->codec_id == 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==B_TYPE)
+ 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);
+ }
+
+ s->mb_intra=0; //for the rate distortion & bit compare functions
+ for(i=1; i<s->avctx->thread_count; i++){
+ ff_update_duplicate_context(s->thread_context[i], s);
+ }
+
+ ff_init_me(s);
+
+ /* Estimate motion for every MB */
+ if(s->pict_type != I_TYPE){
+ 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 != B_TYPE && s->avctx->me_threshold==0){
+ if((s->avctx->pre_me && s->last_non_b_pict_type==I_TYPE) || s->avctx->pre_me==2){
+ s->avctx->execute(s->avctx, pre_estimate_motion_thread, (void**)&(s->thread_context[0]), NULL, s->avctx->thread_count);
+ }
+ }
+
+ s->avctx->execute(s->avctx, estimate_motion_thread, (void**)&(s->thread_context[0]), NULL, s->avctx->thread_count);
+ }else /* if(s->pict_type == I_TYPE) */{
+ /* I-Frame */
+ for(i=0; i<s->mb_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, (void**)&(s->thread_context[0]), NULL, s->avctx->thread_count);
+ }
+ }
+ for(i=1; i<s->avctx->thread_count; i++){
+ merge_context_after_me(s, s->thread_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 == P_TYPE){
+ s->pict_type= I_TYPE;
+ for(i=0; i<s->mb_stride*s->mb_height; i++)
+ s->mb_type[i]= CANDIDATE_MB_TYPE_INTRA;
+//printf("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==P_TYPE || s->pict_type==S_TYPE) {
+ 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= FFMAX(s->f_code, FFMAX(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==B_TYPE){
+ 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==I_TYPE && !(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 */
+ s->intra_matrix[0] = ff_mpeg1_default_intra_matrix[0];
+ for(i=1;i<64;i++){
+ int j= s->dsp.idct_permutation[i];
+
+ s->intra_matrix[j] = clip_uint8((ff_mpeg1_default_intra_matrix[i] * s->qscale) >> 3);
+ }
+ 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;
+ }
+
+ //FIXME var duplication
+ s->current_picture_ptr->key_frame=
+ s->current_picture.key_frame= s->pict_type == I_TYPE; //FIXME pic_ptr
+ s->current_picture_ptr->pict_type=
+ s->current_picture.pict_type= s->pict_type;
+
+ if(s->current_picture.key_frame)
+ s->picture_in_gop_number=0;
+
+ s->last_bits= put_bits_count(&s->pb);
+ switch(s->out_format) {
+ case FMT_MJPEG:
+ mjpeg_picture_header(s);
+ break;
+#ifdef CONFIG_H261_ENCODER
+ case FMT_H261:
+ ff_h261_encode_picture_header(s, picture_number);
+ break;
+#endif
+ case FMT_H263:
+ if (s->codec_id == CODEC_ID_WMV2)
+ ff_wmv2_encode_picture_header(s, picture_number);
+ else if (s->h263_msmpeg4)
+ msmpeg4_encode_picture_header(s, picture_number);
+ else if (s->h263_pred)
+ mpeg4_encode_picture_header(s, picture_number);
+#ifdef CONFIG_RV10_ENCODER
+ else if (s->codec_id == CODEC_ID_RV10)
+ rv10_encode_picture_header(s, picture_number);
+#endif
+#ifdef CONFIG_RV20_ENCODER
+ else if (s->codec_id == CODEC_ID_RV20)
+ rv20_encode_picture_header(s, picture_number);
+#endif
+ else if (s->codec_id == CODEC_ID_FLV1)
+ ff_flv_encode_picture_header(s, picture_number);
+ else
+ h263_encode_picture_header(s, picture_number);
+ break;
+ case FMT_MPEG1:
+ mpeg1_encode_picture_header(s, picture_number);
+ break;
+ case FMT_H264:
+ break;
+ default:
+ assert(0);
+ }
+ bits= put_bits_count(&s->pb);
+ s->header_bits= bits - s->last_bits;
+
+ for(i=1; i<s->avctx->thread_count; i++){
+ update_duplicate_context_after_me(s->thread_context[i], s);
+ }
+ s->avctx->execute(s->avctx, encode_thread, (void**)&(s->thread_context[0]), NULL, s->avctx->thread_count);
+ for(i=1; i<s->avctx->thread_count; i++){
+ merge_context_after_encode(s, s->thread_context[i]);
+ }
+ emms_c();
+ return 0;
+}
+
+static void denoise_dct_c(MpegEncContext *s, DCTELEM *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,
+ DCTELEM *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 = s->q_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<<QMAT_SHIFT) - bias - 1;
+ threshold2= (threshold1<<1);
+
+ for(i=63; i>=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);
+ assert(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(DCTELEM));
+ 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;
+ const int dct_coeff= FFABS(block[ scantable[i] ]);
+ const int zero_distoration= dct_coeff*dct_coeff;
+ int best_score=256*256*256*120;
+ for(level_index=0; level_index < coeff_count[i]; level_index++){
+ int distoration;
+ int level= coeff[level_index][i];
+ const int alevel= FFABS(level);
+ int unquant_coeff;
+
+ assert(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;
+ }
+
+ distoration= (unquant_coeff - dct_coeff) * (unquant_coeff - dct_coeff) - zero_distoration;
+ level+=64;
+ if((level&(~127)) == 0){
+ for(j=survivor_count-1; j>=0; j--){
+ int run= i - survivor[j];
+ int score= distoration + 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= distoration + 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{
+ distoration += esc_length*lambda;
+ for(j=survivor_count-1; j>=0; j--){
+ int run= i - survivor[j];
+ int score= distoration + 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= distoration + 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(DCTELEM));
+
+ 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; i<coeff_count[0]; i++){
+ int level= coeff[i][0];
+ int alevel= FFABS(level);
+ int unquant_coeff, score, distortion;
+
+ if(s->out_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;
+ assert(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<<BASIS_SHIFT);
+ int index= 8*i + j;
+ int perm_index= perm[index];
+ if(i==0) s*= sqrt(0.5);
+ if(j==0) s*= sqrt(0.5);
+ basis[perm_index][8*x + y]= lrintf(s * cos((M_PI/8.0)*i*(x+0.5)) * cos((M_PI/8.0)*j*(y+0.5)));
+ }
+ }
+ }
+ }
+}
+
+static int dct_quantize_refine(MpegEncContext *s, //FIXME breaks denoise?
+ DCTELEM *block, int16_t *weight, DCTELEM *orig,
+ int n, int qscale){
+ int16_t rem[64];
+ DECLARE_ALIGNED_16(DCTELEM, d1[64]);
+ const int *qmat;
+ const uint8_t *scantable= s->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, sum;
+#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;
+ qmat = s->q_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 {
+ dc= 0;
+ start_i = 0;
+ qmat = s->q_inter_matrix[qscale];
+ 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]<<RECON_SHIFT); //FIXME use orig dirrectly instead of copying to rem[]
+ }
+#ifdef REFINE_STATS
+STOP_TIMER("memset rem[]")}
+#endif
+ sum=0;
+ for(i=0; i<64; i++){
+ int one= 36;
+ int qns=4;
+ int w;
+
+ w= FFABS(weight[i]) + qns*one;
+ w= 15 + (48*qns*one + w/2)/w; // 16 .. 63
+
+ weight[i] = w;
+// w=weight[i] = (63*qns + (w/2)) / w;
+
+ assert(w>0);
+ assert(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->avctx->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;
+
+ assert(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(score<best_score){
+ best_score= score;
+ best_coeff= 0;
+ best_change= change;
+ best_unquant_change= new_coeff - old_coeff;
+ }
+ }
+ }
+
+ run=0;
+ rle_index=0;
+ run2= run_tab[rle_index++];
+ prev_level=0;
+ prev_run=0;
+
+ for(i=start_i; i<64; i++){
+ int j= perm_scantable[i];
+ const int level= block[j];
+ int change, old_coeff;
+
+ if(s->avctx->quantizer_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--;
+ assert(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->avctx->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{
+ assert(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;
+ assert(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;
+ assert((score < 100*lambda && score > -100*lambda) || lambda==0);
+
+ score+= s->dsp.try_8x8basis(rem, weight, basis[j], unquant_change);
+ if(score<best_score){
+ best_score= score;
+ best_coeff= i;
+ best_change= change;
+ best_unquant_change= unquant_change;
+ }
+ }
+ if(level){
+ prev_level= level + 64;
+ if(prev_level&(~127))
+ prev_level= 0;
+ prev_run= run;
+ run=0;
+ }else{
+ run++;
+ }
+ }
+#ifdef REFINE_STATS
+STOP_TIMER("iterative step")}
+#endif
+
+ if(best_change){
+ int j= perm_scantable[ best_coeff ];
+
+ block[j] += best_change;
+
+ if(best_coeff > last_non_zero){
+ last_non_zero= best_coeff;
+ assert(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){
+ printf("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;
+}
+
+static int dct_quantize_c(MpegEncContext *s,
+ DCTELEM *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 = s->q_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<<QMAT_SHIFT) - bias - 1;
+ threshold2= (threshold1<<1);
+ for(i=63;i>=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<<QMAT_SHIFT)
+// || bias-level >= (1<<QMAT_SHIFT)){
+ if(((unsigned)(level+threshold1))>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;
+}
+
+#endif //CONFIG_ENCODERS
+
+static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale)
+{
+ int i, level, nCoeffs;
+ const uint16_t *quant_matrix;
+
+ nCoeffs= s->block_last_index[n];
+
+ if (n < 4)
+ block[0] = block[0] * s->y_dc_scale;
+ else
+ block[0] = block[0] * 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,
+ DCTELEM *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,
+ DCTELEM *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];
+
+ if (n < 4)
+ block[0] = block[0] * s->y_dc_scale;
+ else
+ block[0] = block[0] * 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,
+ DCTELEM *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];
+
+ if (n < 4)
+ block[0] = block[0] * s->y_dc_scale;
+ else
+ block[0] = block[0] * 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;
+ sum+=level;
+ }
+ }
+ block[63]^=sum&1;
+}
+
+static void dct_unquantize_mpeg2_inter_c(MpegEncContext *s,
+ DCTELEM *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,
+ DCTELEM *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) {
+ if (n < 4)
+ block[0] = block[0] * s->y_dc_scale;
+ else
+ block[0] = block[0] * 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,
+ DCTELEM *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;
+ }
+ }
+}
+
+#ifdef CONFIG_ENCODERS
+AVCodec h263_encoder = {
+ "h263",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_H263,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+};
+
+AVCodec h263p_encoder = {
+ "h263p",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_H263P,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+};
+
+AVCodec flv_encoder = {
+ "flv",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_FLV1,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+};
+
+AVCodec rv10_encoder = {
+ "rv10",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_RV10,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+};
+
+AVCodec rv20_encoder = {
+ "rv20",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_RV20,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+};
+
+AVCodec mpeg4_encoder = {
+ "mpeg4",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MPEG4,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+ .capabilities= CODEC_CAP_DELAY,
+};
+
+AVCodec msmpeg4v1_encoder = {
+ "msmpeg4v1",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MSMPEG4V1,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+};
+
+AVCodec msmpeg4v2_encoder = {
+ "msmpeg4v2",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MSMPEG4V2,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+};
+
+AVCodec msmpeg4v3_encoder = {
+ "msmpeg4",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MSMPEG4V3,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+};
+
+AVCodec wmv1_encoder = {
+ "wmv1",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_WMV1,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+};
+
+AVCodec mjpeg_encoder = {
+ "mjpeg",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MJPEG,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, -1},
+};
+
+#endif //CONFIG_ENCODERS
diff --git a/contrib/ffmpeg/libavcodec/mpegvideo.h b/contrib/ffmpeg/libavcodec/mpegvideo.h
new file mode 100644
index 000000000..011678a42
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/mpegvideo.h
@@ -0,0 +1,928 @@
+/*
+ * 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.h
+ * mpegvideo header.
+ */
+
+#ifndef AVCODEC_MPEGVIDEO_H
+#define AVCODEC_MPEGVIDEO_H
+
+#include "dsputil.h"
+#include "bitstream.h"
+#include "ratecontrol.h"
+#include "parser.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,
+ FMT_H264,
+};
+
+#define EDGE_WIDTH 16
+
+#define MPEG_BUF_SIZE (16 * 1024)
+
+#define QMAT_SHIFT_MMX 16
+#define QMAT_SHIFT 22
+
+#define MAX_FCODE 7
+#define MAX_MV 2048
+
+#define MAX_THREADS 8
+
+#define MAX_PICTURE_COUNT 32
+
+#define ME_MAP_SIZE 64
+#define ME_MAP_SHIFT 3
+#define ME_MAP_MV_BITS 11
+
+/* run length table */
+#define MAX_RUN 64
+#define MAX_LEVEL 64
+
+#define I_TYPE FF_I_TYPE ///< Intra
+#define P_TYPE FF_P_TYPE ///< Predicted
+#define B_TYPE FF_B_TYPE ///< Bi-dir predicted
+#define S_TYPE FF_S_TYPE ///< S(GMC)-VOP MPEG4
+#define SI_TYPE FF_SI_TYPE ///< Switching Intra
+#define SP_TYPE FF_SP_TYPE ///< Switching Predicted
+
+#define MAX_MB_BYTES (30*16*16*3/8 + 120)
+
+#define INPLACE_OFFSET 16
+
+/**
+ * Scantable.
+ */
+typedef struct ScanTable{
+ const uint8_t *scantable;
+ uint8_t permutated[64];
+ uint8_t raster_end[64];
+#ifdef ARCH_POWERPC
+ /** Used by dct_quantise_alitvec to find last-non-zero */
+ DECLARE_ALIGNED_8(uint8_t, inverse[64]);
+#endif
+} ScanTable;
+
+/**
+ * Picture.
+ */
+typedef struct Picture{
+ FF_COMMON_FRAME
+
+ /**
+ * halfpel luma planes.
+ */
+ uint8_t *interpolated[3];
+ int16_t (*motion_val_base[2])[2];
+ uint32_t *mb_type_base;
+#define MB_TYPE_INTRA MB_TYPE_INTRA4x4 //default mb_type if theres 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 doesnt 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
+ int pic_id; ///< h264 pic_num or long_term_pic_idx
+ int long_ref; ///< 1->long term reference 0->short term reference
+ int ref_poc[2][16]; ///< h264 POCs of the frames used as reference
+ int ref_count[2]; ///< number of entries in ref_poc
+
+ int mb_var_sum; ///< sum of MB variance for current frame
+ int mc_mb_var_sum; ///< motion compensated MB variance for current frame
+ uint16_t *mb_var; ///< Table for MB variances
+ uint16_t *mc_mb_var; ///< Table for motion compensated MB variances
+ uint8_t *mb_mean; ///< Table for MB luminance
+ int32_t *mb_cmp_score; ///< Table for MB cmp scores, for mb decision FIXME remove
+ int b_frame_score; /* */
+} Picture;
+
+struct MpegEncContext;
+
+/**
+ * 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 doesnt 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
+ int map_generation;
+ int pre_penalty_factor;
+ int penalty_factor;
+ 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 {
+ 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
+
+/* the following codec id fields are deprecated in favor of codec_id */
+ int h263_plus; ///< h263 plus headers
+ int h263_msmpeg4; ///< generate MSMPEG4 compatible stream (deprecated, use msmpeg4_version instead)
+ int h263_flv; ///< use flv h263 header
+
+ enum CodecID codec_id; /* see 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 */
+
+ /** bit output */
+ PutBitContext pb;
+
+ /* sequence parameters */
+ int context_initialized;
+ int input_picture_number; ///< used to set pic->display_picture_number, shouldnt be used for/by anything else
+ int coded_picture_number; ///< used to set pic->coded_picture_number, shouldnt be used for/by anything else
+ int picture_number; //FIXME remove, unclear definition
+ int picture_in_gop_number; ///< 0-> first pic in gop, ...
+ int b_frames_since_non_b; ///< used for encoding, relative to not yet reordered input
+ int64_t user_specified_pts;///< last non zero pts from AVFrame which was passed into avcodec_encode_video()
+ 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 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];
+
+ /**
+ * 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
+ uint8_t *visualization_buffer[3]; //< temporary buffer vor MV visualization
+ 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
+ int16_t dc_cache[4*5];
+ int y_dc_scale, c_dc_scale;
+ 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 ac_pred;
+ uint8_t *prev_pict_types; ///< previous picture types in bitstream order, used for mb skip
+#define PREV_PICT_TYPES_BUFFER_SIZE 256
+ 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 *allocated_edge_emu_buffer;
+ uint8_t *edge_emu_buffer; ///< points into the middle of allocated_edge_emu_buffer
+ 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 pict_type; ///< I_TYPE, P_TYPE, B_TYPE, ...
+ int last_pict_type; //FIXME removes
+ int last_non_b_pict_type; ///< used for mpeg4 gmc b-frames & ratecontrol
+ int dropable;
+ int frame_rate_index;
+ int last_lambda_for[5]; ///< last lambda for a specific pict type
+
+ /* motion compensation */
+ int unrestricted_mv; ///< mv can point outside of the coded picture
+ int h263_long_vectors; ///< use horrible h263v1 long vector mode
+ int decode; ///< if 0 then decoding will be skipped (for encoding b frames for example)
+
+ DSPContext dsp; ///< pointers for accelerated dsp functions
+ 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_BACKWARD 1
+#define MV_DIR_FORWARD 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 allways 0 */
+
+ int hurry_up; /**< when set to 1 during decoding, b frames will be skipped
+ when set to 2 idct/dequant will be skipped too */
+
+ /* 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
+
+ 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;
+ uint8_t *chroma_dc_vlc_length;
+#define UNI_AC_ENC_INDEX(run,level) ((run)*128 + (level))
+
+ int coded_score[8];
+
+ /** precomputed matrix (combine qscale and DCT renorm) */
+ int (*q_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_inter_matrix16)[2][64];
+ int block_last_index[12]; ///< last non zero coefficient in block
+ /* scantables */
+ DECLARE_ALIGNED_8(ScanTable, intra_scantable);
+ ScanTable intra_h_scantable;
+ ScanTable intra_v_scantable;
+ ScanTable inter_scantable; ///< if inter == intra then intra should be used to reduce tha cache usage
+
+ /* 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 wanted_bits;
+ int64_t total_bits;
+ int frame_bits; ///< bits used for the current frame
+ 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 error_count;
+ uint8_t *error_status_table; ///< table of the error status of each MB
+#define VP_START 1 ///< current MB is the first after a resync marker
+#define AC_ERROR 2
+#define DC_ERROR 4
+#define MV_ERROR 8
+#define AC_END 16
+#define DC_END 32
+#define MV_END 64
+//FIXME some prefix?
+
+ 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 error_resilience;
+
+ ParseContext parse_context;
+
+ /* H.263 specific */
+ int gob_index;
+ int obmc; ///< overlapped block motion compensation
+
+ /* H.263+ specific */
+ int umvplus; ///< == H263+ && unrestricted_mv
+ int h263_aic; ///< Advanded INTRA Coding (AIC)
+ 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;
+ 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
+
+ /* 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];
+
+ /* 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 mjpeg_write_tables; ///< do we want to have quantisation- and huffmantables in the jpeg file ?
+ int mjpeg_data_only_frames; ///< frames only with SOI, SOS and EOI markers
+
+ /* 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
+
+ /* MPEG2 specific - I wish I had not 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
+
+ /* RTP specific */
+ int rtp_mode;
+
+ uint8_t *ptr_lastgob;
+ int swap_uv;//vcr2 codec is mpeg2 varint with UV swaped
+ short * pblocks[12];
+
+ DCTELEM (*block)[64]; ///< points to one of the following blocks
+ DCTELEM (*blocks)[8][64]; // for HQ mode we need to keep the best block
+ int (*decode_mb)(struct MpegEncContext *s, DCTELEM block[6][64]); // used by some codecs to avoid a switch()
+#define SLICE_OK 0
+#define SLICE_ERROR -1
+#define SLICE_END -2 ///<end marker found
+#define SLICE_NOEND -3 ///<no end marker or error found but mb count exceeded
+
+ void (*dct_unquantize_mpeg1_intra)(struct MpegEncContext *s,
+ DCTELEM *block/*align 16*/, int n, int qscale);
+ void (*dct_unquantize_mpeg1_inter)(struct MpegEncContext *s,
+ DCTELEM *block/*align 16*/, int n, int qscale);
+ void (*dct_unquantize_mpeg2_intra)(struct MpegEncContext *s,
+ DCTELEM *block/*align 16*/, int n, int qscale);
+ void (*dct_unquantize_mpeg2_inter)(struct MpegEncContext *s,
+ DCTELEM *block/*align 16*/, int n, int qscale);
+ void (*dct_unquantize_h263_intra)(struct MpegEncContext *s,
+ DCTELEM *block/*align 16*/, int n, int qscale);
+ void (*dct_unquantize_h263_inter)(struct MpegEncContext *s,
+ DCTELEM *block/*align 16*/, int n, int qscale);
+ void (*dct_unquantize_h261_intra)(struct MpegEncContext *s,
+ DCTELEM *block/*align 16*/, int n, int qscale);
+ void (*dct_unquantize_h261_inter)(struct MpegEncContext *s,
+ DCTELEM *block/*align 16*/, int n, int qscale);
+ void (*dct_unquantize_intra)(struct MpegEncContext *s, // unquantizer to use (mpeg4 can use both)
+ DCTELEM *block/*align 16*/, int n, int qscale);
+ void (*dct_unquantize_inter)(struct MpegEncContext *s, // unquantizer to use (mpeg4 can use both)
+ DCTELEM *block/*align 16*/, int n, int qscale);
+ int (*dct_quantize)(struct MpegEncContext *s, DCTELEM *block/*align 16*/, int n, int qscale, int *overflow);
+ int (*fast_dct_quantize)(struct MpegEncContext *s, DCTELEM *block/*align 16*/, int n, int qscale, int *overflow);
+ void (*denoise_dct)(struct MpegEncContext *s, DCTELEM *block);
+} MpegEncContext;
+
+
+int DCT_common_init(MpegEncContext *s);
+void MPV_decode_defaults(MpegEncContext *s);
+int MPV_common_init(MpegEncContext *s);
+void MPV_common_end(MpegEncContext *s);
+void MPV_decode_mb(MpegEncContext *s, DCTELEM block[12][64]);
+int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx);
+void MPV_frame_end(MpegEncContext *s);
+int MPV_encode_init(AVCodecContext *avctx);
+int MPV_encode_end(AVCodecContext *avctx);
+int MPV_encode_picture(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data);
+#ifdef HAVE_MMX
+void MPV_common_init_mmx(MpegEncContext *s);
+#endif
+#ifdef ARCH_ALPHA
+void MPV_common_init_axp(MpegEncContext *s);
+#endif
+#ifdef HAVE_MLIB
+void MPV_common_init_mlib(MpegEncContext *s);
+#endif
+#ifdef HAVE_MMI
+void MPV_common_init_mmi(MpegEncContext *s);
+#endif
+#ifdef ARCH_ARMV4L
+void MPV_common_init_armv4l(MpegEncContext *s);
+#endif
+#ifdef ARCH_POWERPC
+void MPV_common_init_ppc(MpegEncContext *s);
+#endif
+extern void (*draw_edges)(uint8_t *buf, int wrap, int width, int height, int w);
+void ff_copy_bits(PutBitContext *pb, uint8_t *src, int length);
+void ff_clean_intra_table_entries(MpegEncContext *s);
+void ff_init_scantable(uint8_t *, ScanTable *st, const uint8_t *src_scantable);
+void ff_draw_horiz_band(MpegEncContext *s, int y, int h);
+void ff_emulated_edge_mc(uint8_t *buf, uint8_t *src, int linesize, int block_w, int block_h,
+ int src_x, int src_y, int w, int h);
+void ff_mpeg_flush(AVCodecContext *avctx);
+void ff_print_debug_info(MpegEncContext *s, AVFrame *pict);
+void ff_write_quant_matrix(PutBitContext *pb, uint16_t *matrix);
+int ff_find_unused_picture(MpegEncContext *s, int shared);
+void ff_denoise_dct(MpegEncContext *s, DCTELEM *block);
+void ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src);
+const uint8_t *ff_find_start_code(const uint8_t *p, const uint8_t *end, uint32_t *state);
+
+void ff_er_frame_start(MpegEncContext *s);
+void ff_er_frame_end(MpegEncContext *s);
+void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status);
+
+
+extern enum PixelFormat ff_yuv420p_list[2];
+
+void ff_init_block_index(MpegEncContext *s);
+
+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;
+}
+
+/* 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);
+void ff_init_me(MpegEncContext *s);
+int ff_pre_estimate_p_frame_motion(MpegEncContext * s, int mb_x, int mb_y);
+inline 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);
+inline 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 uint16_t ff_mpeg1_default_intra_matrix[64];
+extern const uint16_t ff_mpeg1_default_non_intra_matrix[64];
+extern const uint8_t ff_mpeg1_dc_scale_table[128];
+
+void mpeg1_encode_picture_header(MpegEncContext *s, int picture_number);
+void mpeg1_encode_mb(MpegEncContext *s,
+ DCTELEM 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);
+
+
+/** 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 deprected FIXME remove
+ RL_VLC_ELEM *rl_vlc[32]; ///< decoding only
+} RLTable;
+
+void init_rl(RLTable *rl, int use_static);
+void init_vlc_rl(RLTable *rl, int use_static);
+
+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;
+}
+
+extern const uint8_t ff_mpeg4_y_dc_scale_table[32];
+extern const uint8_t ff_mpeg4_c_dc_scale_table[32];
+extern const uint8_t ff_aic_dc_scale_table[32];
+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_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,
+ DCTELEM 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);
+
+
+/* h263.c, h263dec.c */
+int ff_h263_decode_init(AVCodecContext *avctx);
+int ff_h263_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size);
+int ff_h263_decode_end(AVCodecContext *avctx);
+void h263_encode_mb(MpegEncContext *s,
+ DCTELEM block[6][64],
+ int motion_x, int motion_y);
+void mpeg4_encode_mb(MpegEncContext *s,
+ DCTELEM block[6][64],
+ int motion_x, int motion_y);
+void h263_encode_picture_header(MpegEncContext *s, int picture_number);
+void ff_flv_encode_picture_header(MpegEncContext *s, int picture_number);
+void h263_encode_gob_header(MpegEncContext * s, int mb_line);
+int16_t *h263_pred_motion(MpegEncContext * s, int block, int dir,
+ int *px, int *py);
+void mpeg4_pred_ac(MpegEncContext * s, DCTELEM *block, int n,
+ int dir);
+void ff_set_mpeg4_time(MpegEncContext * s, int picture_number);
+void mpeg4_encode_picture_header(MpegEncContext *s, int picture_number);
+#ifdef CONFIG_ENCODERS
+void h263_encode_init(MpegEncContext *s);
+#else
+static void h263_encode_init(MpegEncContext *s) {assert(0);}
+#endif
+void h263_decode_init_vlc(MpegEncContext *s);
+int h263_decode_picture_header(MpegEncContext *s);
+int ff_h263_decode_gob_header(MpegEncContext *s);
+int ff_mpeg4_decode_picture_header(MpegEncContext * s, GetBitContext *gb);
+void ff_h263_update_motion_val(MpegEncContext * s);
+void ff_h263_loop_filter(MpegEncContext * s);
+void ff_set_qscale(MpegEncContext * s, int qscale);
+int ff_h263_decode_mba(MpegEncContext *s);
+void ff_h263_encode_mba(MpegEncContext *s);
+
+int intel_h263_decode_picture_header(MpegEncContext *s);
+int flv_h263_decode_picture_header(MpegEncContext *s);
+int ff_h263_decode_mb(MpegEncContext *s,
+ DCTELEM block[6][64]);
+int ff_mpeg4_decode_mb(MpegEncContext *s,
+ DCTELEM block[6][64]);
+int h263_get_picture_format(int width, int height);
+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);
+void ff_clean_h263_qscales(MpegEncContext *s);
+int ff_mpeg4_decode_partitions(MpegEncContext *s);
+int ff_mpeg4_get_video_packet_prefix_length(MpegEncContext *s);
+int ff_h263_resync(MpegEncContext *s);
+int ff_h263_get_gob_height(MpegEncContext *s);
+void ff_mpeg4_init_direct_mv(MpegEncContext *s);
+int ff_mpeg4_set_direct_mv(MpegEncContext *s, int mx, int my);
+int ff_h263_round_chroma(int x);
+void ff_h263_encode_motion(MpegEncContext * s, int val, int f_code);
+
+
+/* rv10.c */
+void rv10_encode_picture_header(MpegEncContext *s, int picture_number);
+int rv_decode_dc(MpegEncContext *s, int n);
+void rv20_encode_picture_header(MpegEncContext *s, int picture_number);
+
+
+/* msmpeg4.c */
+void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number);
+void msmpeg4_encode_ext_header(MpegEncContext * s);
+void msmpeg4_encode_mb(MpegEncContext * s,
+ DCTELEM block[6][64],
+ int motion_x, int motion_y);
+int msmpeg4_decode_picture_header(MpegEncContext * s);
+int msmpeg4_decode_ext_header(MpegEncContext * s, int buf_size);
+int ff_msmpeg4_decode_init(MpegEncContext *s);
+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, DCTELEM 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,
+ DCTELEM block[6][64],
+ int motion_x, int motion_y);
+
+/* mjpeg.c */
+int mjpeg_init(MpegEncContext *s);
+void mjpeg_close(MpegEncContext *s);
+void mjpeg_encode_mb(MpegEncContext *s,
+ DCTELEM block[6][64]);
+void mjpeg_picture_header(MpegEncContext *s);
+void mjpeg_picture_trailer(MpegEncContext *s);
+void ff_mjpeg_stuffing(PutBitContext * pbc);
+
+#endif /* AVCODEC_MPEGVIDEO_H */
+
diff --git a/contrib/ffmpeg/libavcodec/msmpeg4.c b/contrib/ffmpeg/libavcodec/msmpeg4.c
new file mode 100644
index 000000000..a8124172b
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/msmpeg4.c
@@ -0,0 +1,1938 @@
+/*
+ * MSMPEG4 backend for ffmpeg encoder and decoder
+ * Copyright (c) 2001 Fabrice Bellard.
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * msmpeg4v1 & v2 stuff by Michael Niedermayer <michaelni@gmx.at>
+ */
+
+/**
+ * @file msmpeg4.c
+ * MSMPEG4 backend for ffmpeg encoder and decoder.
+ */
+
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.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 CBPY_VLC_BITS 6
+#define INTER_INTRA_VLC_BITS 3
+#define V1_INTRA_CBPC_VLC_BITS 6
+#define V1_INTER_CBPC_VLC_BITS 6
+#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 MB_NON_INTRA_VLC_BITS 9
+#define MB_INTRA_VLC_BITS 9
+
+#define II_BITRATE 128*1024
+#define MBAC_BITRATE 50*1024
+
+#define DEFAULT_INTER_INDEX 3
+
+static uint32_t v2_dc_lum_table[512][2];
+static uint32_t v2_dc_chroma_table[512][2];
+
+static inline void msmpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n);
+static inline int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
+ int n, int coded, const uint8_t *scantable);
+static int msmpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr);
+static int msmpeg4_decode_motion(MpegEncContext * s,
+ int *mx_ptr, int *my_ptr);
+static void init_h263_dc_for_msmpeg4(void);
+static inline void msmpeg4_memsetw(short *tab, int val, int n);
+#ifdef CONFIG_ENCODERS
+static void msmpeg4v2_encode_motion(MpegEncContext * s, int val);
+static int get_size_of_code(MpegEncContext * s, RLTable *rl, int last, int run, int level, int intra);
+#endif //CONFIG_ENCODERS
+static int msmpeg4v12_decode_mb(MpegEncContext *s, DCTELEM block[6][64]);
+static int msmpeg4v34_decode_mb(MpegEncContext *s, DCTELEM block[6][64]);
+static int wmv2_decode_mb(MpegEncContext *s, DCTELEM block[6][64]);
+
+/* vc1 externs */
+extern uint8_t wmv3_dc_scale_table[32];
+
+#ifdef DEBUG
+int intra_count = 0;
+int frame_count = 0;
+#endif
+
+#include "msmpeg4data.h"
+
+#ifdef CONFIG_ENCODERS //strangely gcc includes this even if its not references
+static uint8_t rl_length[NB_RL_TABLES][MAX_LEVEL+1][MAX_RUN+1][2];
+#endif //CONFIG_ENCODERS
+
+static void common_init(MpegEncContext * s)
+{
+ static int inited=0;
+
+ 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= old_ff_y_dc_scale_table;
+ s->c_dc_scale_table= old_ff_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= wmv1_y_dc_scale_table;
+ s->c_dc_scale_table= wmv1_c_dc_scale_table;
+ break;
+#if defined(CONFIG_WMV3_DECODER)||defined(CONFIG_VC1_DECODER)
+ case 6:
+ s->y_dc_scale_table= wmv3_dc_scale_table;
+ s->c_dc_scale_table= wmv3_dc_scale_table;
+ break;
+#endif
+
+ }
+
+
+ if(s->msmpeg4_version>=4){
+ ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable , wmv1_scantable[1]);
+ ff_init_scantable(s->dsp.idct_permutation, &s->intra_h_scantable, wmv1_scantable[2]);
+ ff_init_scantable(s->dsp.idct_permutation, &s->intra_v_scantable, wmv1_scantable[3]);
+ ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable , wmv1_scantable[0]);
+ }
+ //Note the default tables are set in common_init in mpegvideo.c
+
+ if(!inited){
+ inited=1;
+
+ init_h263_dc_for_msmpeg4();
+ }
+}
+
+#ifdef CONFIG_ENCODERS
+
+/* 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;i<tab->n;i++) {
+ x = tab->table_mvx[i];
+ y = tab->table_mvy[i];
+ tab->table_mv_index[(x << 6) | y] = i;
+ }
+}
+
+static void 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));
+ }
+}
+
+void ff_msmpeg4_encode_init(MpegEncContext *s)
+{
+ static int init_done=0;
+ int i;
+
+ 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(&mv_tables[0]);
+ init_mv_table(&mv_tables[1]);
+ for(i=0;i<NB_RL_TABLES;i++)
+ init_rl(&rl_table[i], 1);
+
+ for(i=0; i<NB_RL_TABLES; i++){
+ int level;
+ for(level=0; level<=MAX_LEVEL; level++){
+ int run;
+ for(run=0; run<=MAX_RUN; run++){
+ int last;
+ for(last=0; last<2; last++){
+ rl_length[i][level][run][last]= get_size_of_code(s, &rl_table[ i], last, run, level, 0);
+ }
+ }
+ }
+ }
+ }
+}
+
+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;
+}
+
+static void find_best_tables(MpegEncContext * s)
+{
+ int i;
+ int best =-1, best_size =9999999;
+ int chroma_best=-1, best_chroma_size=9999999;
+
+ for(i=0; i<3; i++){
+ int level;
+ int chroma_size=0;
+ int size=0;
+
+ if(i>0){// ;)
+ 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==I_TYPE){
+ 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(size<best_size){
+ best_size= size;
+ best= i;
+ }
+ if(chroma_size<best_chroma_size){
+ best_chroma_size= chroma_size;
+ chroma_best= i;
+ }
+ }
+
+// printf("type:%d, best:%d, qp:%d, var:%d, mcvar:%d, size:%d //\n",
+// s->pict_type, best, s->qscale, s->mb_var_sum, s->mc_mb_var_sum, best_size);
+
+ if(s->pict_type==P_TYPE) 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==I_TYPE)
+ s->rl_chroma_table_index= 1;
+ else
+ s->rl_chroma_table_index= 2;
+ }
+
+}
+
+/* write MSMPEG4 compatible frame header */
+void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number)
+{
+ find_best_tables(s);
+
+ 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==P_TYPE);
+//printf("%d %d %d %d %d\n", s->pict_type, s->bit_rate, s->inter_intra_pred, s->width, s->height);
+
+ if (s->pict_type == I_TYPE) {
+ s->slice_height= s->mb_height/1;
+ put_bits(&s->pb, 5, 0x16 + s->mb_height/s->slice_height);
+
+ if(s->msmpeg4_version==4){
+ 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){
+ code012(&s->pb, s->rl_chroma_table_index);
+ 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)
+ 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;
+
+#ifdef DEBUG
+ intra_count = 0;
+ av_log(s->avctx, AV_LOG_DEBUG, "*****frame %d:\n", frame_count++);
+#endif
+}
+
+void msmpeg4_encode_ext_header(MpegEncContext * s)
+{
+ put_bits(&s->pb, 5, s->avctx->time_base.den / s->avctx->time_base.num); //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
+ assert(s->flipflop_rounding==0);
+}
+
+#endif //CONFIG_ENCODERS
+
+/* predict coded block */
+static inline int 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;
+}
+
+#ifdef CONFIG_ENCODERS
+
+static void 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 = &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 litterally */
+ put_bits(&s->pb, 6, mx);
+ put_bits(&s->pb, 6, my);
+ }
+}
+
+static inline void 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;
+ }
+ }
+}
+
+void msmpeg4_encode_mb(MpegEncContext * s,
+ DCTELEM block[6][64],
+ int motion_x, int motion_y)
+{
+ int cbp, coded_cbp, i;
+ int pred_x, pred_y;
+ uint8_t *coded_block;
+
+ 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,
+ v2_mb_type[cbp&3][1],
+ v2_mb_type[cbp&3][0]);
+ if((cbp&3) != 3) coded_cbp= cbp ^ 0x3C;
+ else coded_cbp= cbp;
+
+ put_bits(&s->pb,
+ cbpy_tab[coded_cbp>>2][1],
+ cbpy_tab[coded_cbp>>2][0]);
+
+ s->misc_bits += get_bits_diff(s);
+
+ 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,
+ table_mb_non_intra[cbp + 64][1],
+ table_mb_non_intra[cbp + 64][0]);
+
+ s->misc_bits += get_bits_diff(s);
+
+ /* motion vector */
+ h263_pred_motion(s, 0, 0, &pred_x, &pred_y);
+ 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++) {
+ 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 = coded_block_pred(s, i, &coded_block);
+ *coded_block = val;
+ val = val ^ pred;
+ }
+ coded_cbp |= val << (5 - i);
+ }
+#if 0
+ if (coded_cbp)
+ printf("cbp=%x %x\n", cbp, coded_cbp);
+#endif
+
+ if(s->msmpeg4_version<=2){
+ if (s->pict_type == I_TYPE) {
+ put_bits(&s->pb,
+ v2_intra_cbpc[cbp&3][1], 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,
+ v2_mb_type[(cbp&3) + 4][1],
+ v2_mb_type[(cbp&3) + 4][0]);
+ }
+ put_bits(&s->pb, 1, 0); /* no AC prediction yet */
+ put_bits(&s->pb,
+ cbpy_tab[cbp>>2][1],
+ cbpy_tab[cbp>>2][0]);
+ }else{
+ if (s->pict_type == I_TYPE) {
+ 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,
+ table_mb_non_intra[cbp][1],
+ 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, table_inter_intra[s->h263_aic_dir][1], table_inter_intra[s->h263_aic_dir][0]);
+ }
+ }
+ s->misc_bits += get_bits_diff(s);
+
+ for (i = 0; i < 6; i++) {
+ msmpeg4_encode_block(s, block[i], i);
+ }
+ s->i_tex_bits += get_bits_diff(s);
+ s->i_count++;
+ }
+}
+
+#endif //CONFIG_ENCODERS
+
+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 */
+static inline int 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 (defined(ARCH_X86)) && !defined PIC
+ 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 defined (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.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.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;
+}
+
+#define DC_MAX 119
+
+static void msmpeg4_encode_dc(MpegEncContext * s, int level, int n, int *dir_ptr)
+{
+ int sign, code;
+ int pred;
+
+ if(s->msmpeg4_version==1){
+ int32_t *dc_val;
+ pred = msmpeg4v1_pred_dc(s, n, &dc_val);
+
+ /* update predictor */
+ *dc_val= level;
+ }else{
+ int16_t *dc_val;
+ pred = 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,
+ v2_dc_lum_table[level+256][1],
+ v2_dc_lum_table[level+256][0]);
+ }else{
+ put_bits(&s->pb,
+ v2_dc_chroma_table[level+256][1],
+ 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;
+
+ 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 (code == DC_MAX)
+ put_bits(&s->pb, 8, level);
+
+ 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.
+ */
+static inline void msmpeg4_encode_block(MpegEncContext * s, DCTELEM * 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 = &rl_table[s->rl_table_index];
+ } else {
+ rl = &rl_table[3 + s->rl_chroma_table_index];
+ }
+ run_diff = 0;
+ scantable= s->intra_scantable.permutated;
+ } else {
+ i = 0;
+ rl = &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->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]++;
+ }
+#if 0
+else
+ s->ac_stats[s->mb_intra][n>3][40][63][0]++; //esc3 like
+#endif
+ 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, 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;
+ if(s->qscale<8)
+ put_bits(&s->pb, 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_bits(&s->pb, 8, slevel & 0xff);
+ }
+ } 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;
+ }
+ }
+}
+
+/****************************************/
+/* decoding stuff */
+
+static VLC mb_non_intra_vlc[4];
+VLC ff_msmp4_mb_i_vlc;
+VLC ff_msmp4_dc_luma_vlc[2];
+VLC ff_msmp4_dc_chroma_vlc[2];
+static VLC v2_dc_lum_vlc;
+static VLC v2_dc_chroma_vlc;
+static VLC cbpy_vlc;
+static VLC v2_intra_cbpc_vlc;
+static VLC v2_mb_type_vlc;
+static VLC v2_mv_vlc;
+static VLC v1_intra_cbpc_vlc;
+static VLC v1_inter_cbpc_vlc;
+static VLC inter_intra_vlc;
+
+/* this table is practically identical to the one from h263 except that its inverted */
+static void init_h263_dc_for_msmpeg4(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 h263 */
+ uni_code= DCtab_lum[size][0];
+ uni_len = DCtab_lum[size][1];
+ uni_code ^= (1<<uni_len)-1; //M$ doesnt like compatibility
+
+ if (size > 0) {
+ uni_code<<=size; uni_code|=l;
+ uni_len+=size;
+ if (size > 8){
+ uni_code<<=1; uni_code|=1;
+ uni_len++;
+ }
+ }
+ v2_dc_lum_table[level+256][0]= uni_code;
+ v2_dc_lum_table[level+256][1]= uni_len;
+
+ /* chrominance h263 */
+ uni_code= DCtab_chrom[size][0];
+ uni_len = DCtab_chrom[size][1];
+ uni_code ^= (1<<uni_len)-1; //M$ doesnt like compatibility
+
+ if (size > 0) {
+ uni_code<<=size; uni_code|=l;
+ uni_len+=size;
+ if (size > 8){
+ uni_code<<=1; uni_code|=1;
+ uni_len++;
+ }
+ }
+ v2_dc_chroma_table[level+256][0]= uni_code;
+ v2_dc_chroma_table[level+256][1]= uni_len;
+
+ }
+}
+
+/* init all vlc decoding tables */
+int ff_msmpeg4_decode_init(MpegEncContext *s)
+{
+ static int done = 0;
+ int i;
+ MVTable *mv;
+
+ common_init(s);
+
+ if (!done) {
+ done = 1;
+
+ for(i=0;i<NB_RL_TABLES;i++) {
+ init_rl(&rl_table[i], 1);
+ init_vlc_rl(&rl_table[i], 1);
+ }
+ for(i=0;i<2;i++) {
+ mv = &mv_tables[i];
+ init_vlc(&mv->vlc, MV_VLC_BITS, mv->n + 1,
+ mv->table_mv_bits, 1, 1,
+ mv->table_mv_code, 2, 2, 1);
+ }
+
+ init_vlc(&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, 1);
+ init_vlc(&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, 1);
+ init_vlc(&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, 1);
+ init_vlc(&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, 1);
+
+ init_vlc(&v2_dc_lum_vlc, DC_VLC_BITS, 512,
+ &v2_dc_lum_table[0][1], 8, 4,
+ &v2_dc_lum_table[0][0], 8, 4, 1);
+ init_vlc(&v2_dc_chroma_vlc, DC_VLC_BITS, 512,
+ &v2_dc_chroma_table[0][1], 8, 4,
+ &v2_dc_chroma_table[0][0], 8, 4, 1);
+
+ init_vlc(&cbpy_vlc, CBPY_VLC_BITS, 16,
+ &cbpy_tab[0][1], 2, 1,
+ &cbpy_tab[0][0], 2, 1, 1);
+ init_vlc(&v2_intra_cbpc_vlc, V2_INTRA_CBPC_VLC_BITS, 4,
+ &v2_intra_cbpc[0][1], 2, 1,
+ &v2_intra_cbpc[0][0], 2, 1, 1);
+ init_vlc(&v2_mb_type_vlc, V2_MB_TYPE_VLC_BITS, 8,
+ &v2_mb_type[0][1], 2, 1,
+ &v2_mb_type[0][0], 2, 1, 1);
+ init_vlc(&v2_mv_vlc, V2_MV_VLC_BITS, 33,
+ &mvtab[0][1], 2, 1,
+ &mvtab[0][0], 2, 1, 1);
+
+ for(i=0; i<4; i++){
+ init_vlc(&mb_non_intra_vlc[i], MB_NON_INTRA_VLC_BITS, 128,
+ &wmv2_inter_table[i][0][1], 8, 4,
+ &wmv2_inter_table[i][0][0], 8, 4, 1); //FIXME name?
+ }
+
+ init_vlc(&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, 1);
+
+ init_vlc(&v1_intra_cbpc_vlc, V1_INTRA_CBPC_VLC_BITS, 8,
+ intra_MCBPC_bits, 1, 1,
+ intra_MCBPC_code, 1, 1, 1);
+ init_vlc(&v1_inter_cbpc_vlc, V1_INTER_CBPC_VLC_BITS, 25,
+ inter_MCBPC_bits, 1, 1,
+ inter_MCBPC_code, 1, 1, 1);
+
+ init_vlc(&inter_intra_vlc, INTER_INTRA_VLC_BITS, 4,
+ &table_inter_intra[0][1], 2, 1,
+ &table_inter_intra[0][0], 2, 1, 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:
+ s->decode_mb= 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 isnt a keyframe
+
+ return 0;
+}
+
+int msmpeg4_decode_picture_header(MpegEncContext * s)
+{
+ int code;
+
+#if 0
+{
+int i;
+for(i=0; i<s->gb.size_in_bits; i++)
+ av_log(s->avctx, AV_LOG_DEBUG, "%d", get_bits1(&s->gb));
+// get_bits1(&s->gb);
+av_log(s->avctx, AV_LOG_DEBUG, "END\n");
+return -1;
+}
+#endif
+
+ if(s->msmpeg4_version==1){
+ int start_code, num;
+ start_code = (get_bits(&s->gb, 16)<<16) | get_bits(&s->gb, 16);
+ if(start_code!=0x00000100){
+ av_log(s->avctx, AV_LOG_ERROR, "invalid startcode\n");
+ return -1;
+ }
+
+ num= get_bits(&s->gb, 5); // frame number */
+ }
+
+ s->pict_type = get_bits(&s->gb, 2) + 1;
+ if (s->pict_type != I_TYPE &&
+ s->pict_type != P_TYPE){
+ av_log(s->avctx, AV_LOG_ERROR, "invalid picture type\n");
+ return -1;
+ }
+#if 0
+{
+ static int had_i=0;
+ if(s->pict_type == I_TYPE) 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 == I_TYPE) {
+ 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:
+ 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;
+ }
+ }
+//printf("%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;
+
+#ifdef DEBUG
+ av_log(s->avctx, AV_LOG_DEBUG, "*****frame %d:\n", frame_count++);
+#endif
+ return 0;
+}
+
+int 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 && left<length+8)
+ {
+ int fps;
+
+ fps= get_bits(&s->gb, 5);
+ 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;
+
+// printf("fps:%2d bps:%2d roundingType:%1d\n", fps, s->bit_rate/1024, s->flipflop_rounding);
+ }
+ else if(left<length+8)
+ {
+ s->flipflop_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 inline void msmpeg4_memsetw(short *tab, int val, int n)
+{
+ int i;
+ for(i=0;i<n;i++)
+ tab[i] = val;
+}
+
+#ifdef CONFIG_ENCODERS
+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, mvtab[code][1], 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, mvtab[code][1] + 1, (mvtab[code][0] << 1) | sign);
+ if (bit_size > 0) {
+ put_bits(&s->pb, bit_size, bits);
+ }
+ }
+}
+#endif
+
+/* 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);
+// printf("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, DCTELEM block[6][64])
+{
+ int cbp, code, i;
+
+ if (s->pict_type == P_TYPE) {
+ 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;
+ 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, v1_inter_cbpc_vlc.table, V1_INTER_CBPC_VLC_BITS, 3);
+ 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, v1_intra_cbpc_vlc.table, V1_INTRA_CBPC_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, 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;
+
+ 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;
+ } else {
+ if(s->msmpeg4_version==2){
+ s->ac_pred = get_bits1(&s->gb);
+ cbp|= get_vlc2(&s->gb, cbpy_vlc.table, CBPY_VLC_BITS, 1)<<2; //FIXME check errors
+ } else{
+ s->ac_pred = 0;
+ cbp|= get_vlc2(&s->gb, cbpy_vlc.table, CBPY_VLC_BITS, 1)<<2; //FIXME check errors
+ if(s->pict_type==P_TYPE) cbp^=0x3C;
+ }
+ }
+
+ s->dsp.clear_blocks(s->block[0]);
+ for (i = 0; i < 6; i++) {
+ if (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, DCTELEM 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 == P_TYPE) {
+ 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, 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 = coded_block_pred(s, i, &coded_val);
+ val = val ^ pred;
+ *coded_val = val;
+ }
+ cbp |= val << (5 - i);
+ }
+ }
+
+ if (!s->mb_intra) {
+ int mx, my;
+//printf("P at %d %d\n", 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;
+ }
+ h263_pred_motion(s, 0, 0, &mx, &my);
+ if (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 {
+//printf("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, inter_intra_vlc.table, INTER_INTRA_VLC_BITS, 1);
+// printf("%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 (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;
+}
+//#define ERROR_DETAILS
+static inline int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
+ int n, int coded, const uint8_t *scan_table)
+{
+ int level, i, last, run, run_diff;
+ int 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 = &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 = &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 = 0;
+ 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 = &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); LAST_SKIP_CACHE(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;
+ //printf("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){
+ if(SHOW_UBITS(re, &s->gb, 1)) av_log(s->avctx, AV_LOG_ERROR, "cool a new vlc code ,contact the ffmpeg developers and upload the file\n");
+ SKIP_BITS(re, &s->gb, 1);
+ ll=8;
+ }
+ }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);
+//printf("level length:%d, run length: %d\n", ll, s->esc3_run_length);
+ 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;
+ }
+//printf("level: %d, run: %d at %d %d\n", level, run, s->mb_x, s->mb_y);
+#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 */
+#if MIN_CACHE_BITS < 23
+ LAST_SKIP_BITS(re, &s->gb, 2);
+ UPDATE_CACHE(re, &s->gb);
+#else
+ SKIP_BITS(re, &s->gb, 2);
+#endif
+ 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 */
+#if MIN_CACHE_BITS < 22
+ LAST_SKIP_BITS(re, &s->gb, 1);
+ UPDATE_CACHE(re, &s->gb);
+#else
+ SKIP_BITS(re, &s->gb, 1);
+#endif
+ 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= s->gb.size_in_bits - get_bits_count(&s->gb);
+ if(((i+192 == 64 && level/qmul==-1) || s->error_resilience<=1) && left>=0){
+ av_log(s->avctx, AV_LOG_ERROR, "ignoring overflow at %d %d\n", s->mb_x, s->mb_y);
+ 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) {
+ 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;
+}
+
+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 = 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;
+}
+
+static int msmpeg4_decode_motion(MpegEncContext * s,
+ int *mx_ptr, int *my_ptr)
+{
+ MVTable *mv;
+ int code, mx, my;
+
+ mv = &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) {
+//printf("MV ESC %X at %d %d\n", show_bits(&s->gb, 24), s->mb_x, s->mb_y);
+ 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;
+}
+
+/* cleanest way to support it
+ * there is too much shared between versions so that we cant have 1 file per version & 1 common
+ * as allmost everything would be in the common file
+ */
+#include "wmv2.c"
diff --git a/contrib/ffmpeg/libavcodec/msmpeg4data.h b/contrib/ffmpeg/libavcodec/msmpeg4data.h
new file mode 100644
index 000000000..d1ff70371
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/msmpeg4data.h
@@ -0,0 +1,2028 @@
+/*
+ * MSMPEG4 backend for ffmpeg encoder and decoder
+ * copyright (c) 2001 Fabrice Bellard
+ * copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * msmpeg4v1 & v2 stuff by Michael Niedermayer <michaelni@gmx.at>
+ */
+
+/**
+ * @file msmpeg4data.h
+ * MSMPEG4 data tables.
+ */
+
+/* intra picture macro block 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 macro block coded block pattern + mb type */
+static const uint32_t 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 macro blocks */
+
+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 inter_vlc[103][2];
+extern const int8_t inter_level[102];
+extern const int8_t inter_run[102];
+
+extern const uint16_t intra_vlc[103][2];
+extern const int8_t intra_level[102];
+extern const int8_t intra_run[102];
+
+extern const uint8_t DCtab_lum[13][2];
+extern const uint8_t DCtab_chrom[13][2];
+
+extern const uint8_t cbpy_tab[16][2];
+extern const uint8_t mvtab[33][2];
+
+extern const uint8_t intra_MCBPC_code[9];
+extern const uint8_t intra_MCBPC_bits[9];
+
+extern const uint8_t inter_MCBPC_code[28];
+extern const uint8_t inter_MCBPC_bits[28];
+
+#define NB_RL_TABLES 6
+
+static RLTable rl_table[NB_RL_TABLES] = {
+ /* intra luminance tables */
+ {
+ 132,
+ 85,
+ table0_vlc,
+ table0_run,
+ table0_level,
+ },
+ {
+ 185,
+ 119,
+ table2_vlc,
+ table2_run,
+ table2_level,
+ },
+ {
+ 102,
+ 67,
+ intra_vlc,
+ intra_run,
+ intra_level,
+ },
+ /* intra chrominance / non intra tables */
+ {
+ 148,
+ 81,
+ table1_vlc,
+ table1_run,
+ table1_level,
+ },
+ {
+ 168,
+ 99,
+ table4_vlc,
+ table4_run,
+ table4_level,
+ },
+ {
+ 102,
+ 58,
+ inter_vlc,
+ inter_run,
+ 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,
+};
+
+/* 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;
+
+static MVTable 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,
+ }
+};
+
+static const uint8_t v2_mb_type[8][2] = {
+ {1, 1}, {0 , 2}, {3 , 3}, {9 , 5},
+ {5, 4}, {0x21, 7}, {0x20, 7}, {0x11, 6},
+};
+
+static const uint8_t v2_intra_cbpc[4][2] = {
+ {1, 1}, {0, 3}, {1, 3}, {1, 2},
+};
+
+static const uint8_t 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
+};
+static const uint8_t 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
+};
+
+static const uint8_t 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
+};
+static const uint8_t old_ff_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
+};
+
+
+#define WMV1_SCANTABLE_COUNT 4
+
+static const uint8_t wmv1_scantable00[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,
+};
+static const uint8_t wmv1_scantable01[64]= {
+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,
+};
+static const uint8_t wmv1_scantable02[64]= {
+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,
+};
+static const uint8_t wmv1_scantable03[64]= {
+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,
+};
+
+static const uint8_t *wmv1_scantable[WMV1_SCANTABLE_COUNT+1]={
+ wmv1_scantable00,
+ wmv1_scantable01,
+ wmv1_scantable02,
+ wmv1_scantable03,
+};
+
+static const uint8_t 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 */
+};
+
+#define WMV2_INTER_CBP_TABLE_COUNT 4
+
+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},
+};
+
+static const uint32_t (*wmv2_inter_table[WMV2_INTER_CBP_TABLE_COUNT])[2]={
+ table_mb_non_intra2,
+ table_mb_non_intra3,
+ table_mb_non_intra4,
+ table_mb_non_intra,
+};
+
+static const uint8_t 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,
+};
+
+static const uint8_t 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/contrib/ffmpeg/libavcodec/msrle.c b/contrib/ffmpeg/libavcodec/msrle.c
new file mode 100644
index 000000000..fae5616e5
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/msrle.c
@@ -0,0 +1,309 @@
+/*
+ * Micrsoft 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 msrle.c
+ * 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.
+ *
+ * Note that this decoder expects the palette colors from the end of the
+ * BITMAPINFO header passed through palctrl.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.h"
+
+typedef struct MsrleContext {
+ AVCodecContext *avctx;
+ AVFrame frame;
+
+ unsigned char *buf;
+ int size;
+
+} MsrleContext;
+
+#define FETCH_NEXT_STREAM_BYTE() \
+ if (stream_ptr >= s->size) \
+ { \
+ av_log(s->avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (1)\n"); \
+ return; \
+ } \
+ stream_byte = s->buf[stream_ptr++];
+
+static void msrle_decode_pal4(MsrleContext *s)
+{
+ int stream_ptr = 0;
+ unsigned char rle_code;
+ unsigned char extra_byte, odd_pixel;
+ unsigned char stream_byte;
+ int pixel_ptr = 0;
+ int row_dec = s->frame.linesize[0];
+ int row_ptr = (s->avctx->height - 1) * row_dec;
+ int frame_size = row_dec * s->avctx->height;
+ int i;
+
+ /* make the palette available */
+ memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
+ if (s->avctx->palctrl->palette_changed) {
+ s->frame.palette_has_changed = 1;
+ s->avctx->palctrl->palette_changed = 0;
+ }
+
+ while (row_ptr >= 0) {
+ FETCH_NEXT_STREAM_BYTE();
+ rle_code = stream_byte;
+ if (rle_code == 0) {
+ /* fetch the next byte to see how to handle escape code */
+ FETCH_NEXT_STREAM_BYTE();
+ 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;
+ } else if (stream_byte == 2) {
+ /* reposition frame decode coordinates */
+ FETCH_NEXT_STREAM_BYTE();
+ pixel_ptr += stream_byte;
+ FETCH_NEXT_STREAM_BYTE();
+ 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) ||
+ (row_ptr < 0)) {
+ av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
+ return;
+ }
+
+ for (i = 0; i < rle_code; i++) {
+ if (pixel_ptr >= s->avctx->width)
+ break;
+ FETCH_NEXT_STREAM_BYTE();
+ s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
+ pixel_ptr++;
+ if (i + 1 == rle_code && odd_pixel)
+ break;
+ if (pixel_ptr >= s->avctx->width)
+ break;
+ s->frame.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)
+ stream_ptr++;
+ }
+ } else {
+ // decode a run of data
+ if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
+ (row_ptr < 0)) {
+ av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
+ return;
+ }
+ FETCH_NEXT_STREAM_BYTE();
+ for (i = 0; i < rle_code; i++) {
+ if (pixel_ptr >= s->avctx->width)
+ break;
+ if ((i & 1) == 0)
+ s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
+ else
+ s->frame.data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
+ pixel_ptr++;
+ }
+ }
+ }
+
+ /* one last sanity check on the way out */
+ if (stream_ptr < s->size)
+ av_log(s->avctx, AV_LOG_ERROR, " MS RLE: ended frame decode with bytes left over (%d < %d)\n",
+ stream_ptr, s->size);
+}
+
+
+
+static void msrle_decode_pal8(MsrleContext *s)
+{
+ int stream_ptr = 0;
+ unsigned char rle_code;
+ unsigned char extra_byte;
+ unsigned char stream_byte;
+ int pixel_ptr = 0;
+ int row_dec = s->frame.linesize[0];
+ int row_ptr = (s->avctx->height - 1) * row_dec;
+ int frame_size = row_dec * s->avctx->height;
+
+ /* make the palette available */
+ memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
+ if (s->avctx->palctrl->palette_changed) {
+ s->frame.palette_has_changed = 1;
+ s->avctx->palctrl->palette_changed = 0;
+ }
+
+ while (row_ptr >= 0) {
+ FETCH_NEXT_STREAM_BYTE();
+ rle_code = stream_byte;
+ if (rle_code == 0) {
+ /* fetch the next byte to see how to handle escape code */
+ FETCH_NEXT_STREAM_BYTE();
+ 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;
+ } else if (stream_byte == 2) {
+ /* reposition frame decode coordinates */
+ FETCH_NEXT_STREAM_BYTE();
+ pixel_ptr += stream_byte;
+ FETCH_NEXT_STREAM_BYTE();
+ row_ptr -= stream_byte * row_dec;
+ } else {
+ /* copy pixels from encoded stream */
+ if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
+ (row_ptr < 0)) {
+ av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
+ return;
+ }
+
+ rle_code = stream_byte;
+ extra_byte = stream_byte & 0x01;
+ if (stream_ptr + rle_code + extra_byte > s->size) {
+ av_log(s->avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (2)\n");
+ return;
+ }
+
+ while (rle_code--) {
+ FETCH_NEXT_STREAM_BYTE();
+ s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
+ pixel_ptr++;
+ }
+
+ /* if the RLE code is odd, skip a byte in the stream */
+ if (extra_byte)
+ stream_ptr++;
+ }
+ } else {
+ /* decode a run of data */
+ if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
+ (row_ptr < 0)) {
+ av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (2)\n");
+ return;
+ }
+
+ FETCH_NEXT_STREAM_BYTE();
+
+ while(rle_code--) {
+ s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
+ pixel_ptr++;
+ }
+ }
+ }
+
+ /* one last sanity check on the way out */
+ if (stream_ptr < s->size)
+ av_log(s->avctx, AV_LOG_ERROR, " MS RLE: ended frame decode with bytes left over (%d < %d)\n",
+ stream_ptr, s->size);
+}
+
+static int msrle_decode_init(AVCodecContext *avctx)
+{
+ MsrleContext *s = (MsrleContext *)avctx->priv_data;
+
+ s->avctx = avctx;
+
+ avctx->pix_fmt = PIX_FMT_PAL8;
+ avctx->has_b_frames = 0;
+ s->frame.data[0] = NULL;
+
+ return 0;
+}
+
+static int msrle_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ MsrleContext *s = (MsrleContext *)avctx->priv_data;
+
+ s->buf = buf;
+ s->size = buf_size;
+
+ s->frame.reference = 1;
+ s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
+ if (avctx->reget_buffer(avctx, &s->frame)) {
+ av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+ return -1;
+ }
+
+ switch (avctx->bits_per_sample) {
+ case 8:
+ msrle_decode_pal8(s);
+ break;
+ case 4:
+ msrle_decode_pal4(s);
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "Don't know how to decode depth %u.\n",
+ avctx->bits_per_sample);
+ }
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = s->frame;
+
+ /* report that the buffer was completely consumed */
+ return buf_size;
+}
+
+static int msrle_decode_end(AVCodecContext *avctx)
+{
+ MsrleContext *s = (MsrleContext *)avctx->priv_data;
+
+ /* release the last frame */
+ if (s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ return 0;
+}
+
+AVCodec msrle_decoder = {
+ "msrle",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MSRLE,
+ sizeof(MsrleContext),
+ msrle_decode_init,
+ NULL,
+ msrle_decode_end,
+ msrle_decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/msvideo1.c b/contrib/ffmpeg/libavcodec/msvideo1.c
new file mode 100644
index 000000000..5929e1c63
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/msvideo1.c
@@ -0,0 +1,349 @@
+/*
+ * 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 msvideo1.c
+ * 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/
+ *
+ * This decoder outputs either PAL8 or RGB555 data, depending on the
+ * whether a RGB palette was passed through palctrl;
+ * if it's present, then the data is PAL8; RGB555 otherwise.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.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;
+ DSPContext dsp;
+ AVFrame frame;
+
+ unsigned char *buf;
+ int size;
+
+ int mode_8bit; /* if it's not 8-bit, it's 16-bit */
+
+} Msvideo1Context;
+
+static int msvideo1_decode_init(AVCodecContext *avctx)
+{
+ Msvideo1Context *s = (Msvideo1Context *)avctx->priv_data;
+
+ s->avctx = avctx;
+
+ /* figure out the colorspace based on the presence of a palette */
+ if (s->avctx->palctrl) {
+ s->mode_8bit = 1;
+ avctx->pix_fmt = PIX_FMT_PAL8;
+ } else {
+ s->mode_8bit = 0;
+ avctx->pix_fmt = PIX_FMT_RGB555;
+ }
+
+ avctx->has_b_frames = 0;
+ dsputil_init(&s->dsp, avctx);
+
+ s->frame.data[0] = NULL;
+
+ 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 == PIX_FMT_PAL8) {
+ memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
+ if (s->avctx->palctrl->palette_changed) {
+ s->frame.palette_has_changed = 1;
+ s->avctx->palctrl->palette_changed = 0;
+ }
+ }
+}
+
+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] = LE_16(&s->buf[stream_ptr]);
+ stream_ptr += 2;
+ colors[1] = LE_16(&s->buf[stream_ptr]);
+ stream_ptr += 2;
+
+ if (colors[0] & 0x8000) {
+ /* 8-color encoding */
+ CHECK_STREAM_PTR(12);
+ colors[2] = LE_16(&s->buf[stream_ptr]);
+ stream_ptr += 2;
+ colors[3] = LE_16(&s->buf[stream_ptr]);
+ stream_ptr += 2;
+ colors[4] = LE_16(&s->buf[stream_ptr]);
+ stream_ptr += 2;
+ colors[5] = LE_16(&s->buf[stream_ptr]);
+ stream_ptr += 2;
+ colors[6] = LE_16(&s->buf[stream_ptr]);
+ stream_ptr += 2;
+ colors[7] = LE_16(&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 *data_size,
+ uint8_t *buf, int buf_size)
+{
+ Msvideo1Context *s = (Msvideo1Context *)avctx->priv_data;
+
+ s->buf = buf;
+ s->size = buf_size;
+
+ s->frame.reference = 1;
+ s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
+ if (avctx->reget_buffer(avctx, &s->frame)) {
+ av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+ return -1;
+ }
+
+ if (s->mode_8bit)
+ msvideo1_decode_8bit(s);
+ else
+ msvideo1_decode_16bit(s);
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = s->frame;
+
+ /* report that the buffer was completely consumed */
+ return buf_size;
+}
+
+static int msvideo1_decode_end(AVCodecContext *avctx)
+{
+ Msvideo1Context *s = (Msvideo1Context *)avctx->priv_data;
+
+ if (s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ return 0;
+}
+
+AVCodec msvideo1_decoder = {
+ "msvideo1",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MSVIDEO1,
+ sizeof(Msvideo1Context),
+ msvideo1_decode_init,
+ NULL,
+ msvideo1_decode_end,
+ msvideo1_decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/nuv.c b/contrib/ffmpeg/libavcodec/nuv.c
new file mode 100644
index 000000000..592d3de03
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/nuv.c
@@ -0,0 +1,216 @@
+/*
+ * NuppelVideo 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 <stdio.h>
+#include <stdlib.h>
+
+#include "common.h"
+#include "avcodec.h"
+
+#include "bswap.h"
+#include "dsputil.h"
+#include "lzo.h"
+#include "rtjpeg.h"
+
+typedef struct {
+ AVFrame pic;
+ int width, height;
+ unsigned int decomp_size;
+ unsigned char* decomp_buf;
+ uint32_t lq[64], cq[64];
+ RTJpegContext rtj;
+ DSPContext dsp;
+} NuvContext;
+
+/**
+ * \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, uint8_t *src,
+ int width, int height) {
+ AVPicture pic;
+ avpicture_fill(&pic, src, PIX_FMT_YUV420P, width, height);
+ img_copy((AVPicture *)f, &pic, PIX_FMT_YUV420P, width, height);
+}
+
+/**
+ * \brief extract quantization tables from codec data into our context
+ */
+static int get_quant(AVCodecContext *avctx, NuvContext *c,
+ uint8_t *buf, int size) {
+ int i;
+ if (size < 2 * 64 * 4) {
+ av_log(avctx, AV_LOG_ERROR, "insufficient rtjpeg quant data\n");
+ return -1;
+ }
+ for (i = 0; i < 64; i++, buf += 4)
+ c->lq[i] = LE_32(buf);
+ for (i = 0; i < 64; i++, buf += 4)
+ c->cq[i] = LE_32(buf);
+ return 0;
+}
+
+static int decode_frame(AVCodecContext *avctx, void *data, int *data_size,
+ uint8_t *buf, int buf_size) {
+ NuvContext *c = (NuvContext *)avctx->priv_data;
+ AVFrame *picture = data;
+ int orig_size = buf_size;
+ 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 -1;
+ }
+
+ if (c->pic.data[0])
+ avctx->release_buffer(avctx, &c->pic);
+ c->pic.reference = 1;
+ c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_READABLE |
+ FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
+ if (avctx->get_buffer(avctx, &c->pic) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ // 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;
+ rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq, c->cq);
+ return orig_size;
+ }
+
+ if (buf[0] != 'V' || buf_size < 12) {
+ av_log(avctx, AV_LOG_ERROR, "not a nuv video frame\n");
+ return -1;
+ }
+ comptype = buf[1];
+ // skip rest of the frameheader.
+ buf = &buf[12];
+ buf_size -= 12;
+
+ c->pic.pict_type = FF_I_TYPE;
+ c->pic.key_frame = 1;
+ // decompress/copy/whatever data
+ switch (comptype) {
+ 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;
+ }
+ copy_frame(&c->pic, buf, c->width, height);
+ break;
+ }
+ case NUV_RTJPEG: {
+ rtjpeg_decode_frame_yuv420(&c->rtj, &c->pic, buf, buf_size);
+ break;
+ }
+ case NUV_RTJPEG_IN_LZO: {
+ int outlen = c->decomp_size, inlen = buf_size;
+ if (lzo1x_decode(c->decomp_buf, &outlen, buf, &inlen))
+ av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n");
+ rtjpeg_decode_frame_yuv420(&c->rtj, &c->pic, c->decomp_buf, c->decomp_size);
+ break;
+ }
+ case NUV_LZO: {
+ int outlen = c->decomp_size, inlen = buf_size;
+ if (lzo1x_decode(c->decomp_buf, &outlen, buf, &inlen))
+ av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n");
+ copy_frame(&c->pic, c->decomp_buf, c->width, c->height);
+ 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: {
+ c->pic.pict_type = FF_P_TYPE;
+ c->pic.key_frame = 0;
+ /* nothing more to do here */
+ break;
+ }
+ default:
+ av_log(avctx, AV_LOG_ERROR, "unknown compression\n");
+ return -1;
+ }
+
+ *picture = c->pic;
+ *data_size = sizeof(AVFrame);
+ return orig_size;
+}
+
+static int decode_init(AVCodecContext *avctx) {
+ NuvContext *c = (NuvContext *)avctx->priv_data;
+ avctx->width = (avctx->width + 1) & ~1;
+ avctx->height = (avctx->height + 1) & ~1;
+ if (avcodec_check_dimensions(avctx, avctx->height, avctx->width) < 0) {
+ return 1;
+ }
+ avctx->has_b_frames = 0;
+ avctx->pix_fmt = PIX_FMT_YUV420P;
+ c->pic.data[0] = NULL;
+ c->width = avctx->width;
+ c->height = avctx->height;
+ c->decomp_size = c->height * c->width * 3 / 2;
+ c->decomp_buf = av_malloc(c->decomp_size + LZO_OUTPUT_PADDING);
+ if (!c->decomp_buf) {
+ av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
+ return 1;
+ }
+ dsputil_init(&c->dsp, avctx);
+ if (avctx->extradata_size)
+ get_quant(avctx, c, avctx->extradata, avctx->extradata_size);
+ rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq, c->cq);
+ return 0;
+}
+
+static int decode_end(AVCodecContext *avctx) {
+ NuvContext *c = (NuvContext *)avctx->priv_data;
+ av_freep(&c->decomp_buf);
+ if (c->pic.data[0])
+ avctx->release_buffer(avctx, &c->pic);
+ return 0;
+}
+
+AVCodec nuv_decoder = {
+ "nuv",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_NUV,
+ sizeof(NuvContext),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
+
diff --git a/contrib/ffmpeg/libavcodec/oggvorbis.c b/contrib/ffmpeg/libavcodec/oggvorbis.c
new file mode 100644
index 000000000..9e684a0f4
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/oggvorbis.c
@@ -0,0 +1,381 @@
+/*
+ * copyright (c) 2002 Mark Hills <mark@pogo.org.uk>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have 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 oggvorbis.c
+ * Ogg Vorbis codec support via libvorbisenc.
+ * @author Mark Hills <mark@pogo.org.uk>
+ */
+
+#include <vorbis/vorbisenc.h>
+
+#include "avcodec.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+#define OGGVORBIS_FRAME_SIZE 64
+
+#define BUFFER_SIZE (1024*64)
+
+typedef struct OggVorbisContext {
+ vorbis_info vi ;
+ vorbis_dsp_state vd ;
+ vorbis_block vb ;
+ uint8_t buffer[BUFFER_SIZE];
+ int buffer_index;
+
+ /* decoder */
+ vorbis_comment vc ;
+ ogg_packet op;
+} OggVorbisContext ;
+
+
+static int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) {
+ double cfreq;
+
+ if(avccontext->flags & CODEC_FLAG_QSCALE) {
+ /* variable bitrate */
+ if(vorbis_encode_setup_vbr(vi, avccontext->channels,
+ avccontext->sample_rate,
+ avccontext->global_quality / (float)FF_QP2LAMBDA))
+ return -1;
+ } else {
+ /* constant bitrate */
+ if(vorbis_encode_setup_managed(vi, avccontext->channels,
+ avccontext->sample_rate, -1, avccontext->bit_rate, -1))
+ return -1;
+
+#ifdef OGGVORBIS_VBR_BY_ESTIMATE
+ /* variable bitrate by estimate */
+ if(vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE_AVG, NULL))
+ return -1;
+#endif
+ }
+
+ /* cutoff frequency */
+ if(avccontext->cutoff > 0) {
+ cfreq = avccontext->cutoff / 1000.0;
+ if(vorbis_encode_ctl(vi, OV_ECTL_LOWPASS_SET, &cfreq))
+ return -1;
+ }
+
+ return vorbis_encode_setup_init(vi);
+}
+
+static int oggvorbis_encode_init(AVCodecContext *avccontext) {
+ OggVorbisContext *context = avccontext->priv_data ;
+ ogg_packet header, header_comm, header_code;
+ uint8_t *p;
+ unsigned int offset, len;
+
+ vorbis_info_init(&context->vi) ;
+ if(oggvorbis_init_encoder(&context->vi, avccontext) < 0) {
+ av_log(avccontext, AV_LOG_ERROR, "oggvorbis_encode_init: init_encoder failed") ;
+ return -1 ;
+ }
+ vorbis_analysis_init(&context->vd, &context->vi) ;
+ vorbis_block_init(&context->vd, &context->vb) ;
+
+ vorbis_comment_init(&context->vc);
+ vorbis_comment_add_tag(&context->vc, "encoder", LIBAVCODEC_IDENT) ;
+
+ vorbis_analysis_headerout(&context->vd, &context->vc, &header,
+ &header_comm, &header_code);
+
+ len = header.bytes + header_comm.bytes + header_code.bytes;
+ avccontext->extradata_size= 64 + len + len/255;
+ p = avccontext->extradata= av_mallocz(avccontext->extradata_size);
+ 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;
+ avccontext->extradata_size = offset;
+ avccontext->extradata= av_realloc(avccontext->extradata, avccontext->extradata_size);
+
+/* vorbis_block_clear(&context->vb);
+ vorbis_dsp_clear(&context->vd);
+ vorbis_info_clear(&context->vi);*/
+ vorbis_comment_clear(&context->vc);
+
+ avccontext->frame_size = OGGVORBIS_FRAME_SIZE ;
+
+ avccontext->coded_frame= avcodec_alloc_frame();
+ avccontext->coded_frame->key_frame= 1;
+
+ return 0 ;
+}
+
+
+static int oggvorbis_encode_frame(AVCodecContext *avccontext,
+ unsigned char *packets,
+ int buf_size, void *data)
+{
+ OggVorbisContext *context = avccontext->priv_data ;
+ float **buffer ;
+ ogg_packet op ;
+ signed short *audio = data ;
+ int l, samples = data ? OGGVORBIS_FRAME_SIZE : 0;
+
+ buffer = vorbis_analysis_buffer(&context->vd, samples) ;
+
+ if(context->vi.channels == 1) {
+ for(l = 0 ; l < samples ; l++)
+ buffer[0][l]=audio[l]/32768.f;
+ } else {
+ for(l = 0 ; l < samples ; l++){
+ buffer[0][l]=audio[l*2]/32768.f;
+ buffer[1][l]=audio[l*2+1]/32768.f;
+ }
+ }
+
+ vorbis_analysis_wrote(&context->vd, samples) ;
+
+ while(vorbis_analysis_blockout(&context->vd, &context->vb) == 1) {
+ vorbis_analysis(&context->vb, NULL);
+ vorbis_bitrate_addblock(&context->vb) ;
+
+ while(vorbis_bitrate_flushpacket(&context->vd, &op)) {
+ if(op.bytes==1) //id love to say this is a hack, bad sadly its not, appearently the end of stream decission is in libogg
+ continue;
+ memcpy(context->buffer + context->buffer_index, &op, sizeof(ogg_packet));
+ context->buffer_index += sizeof(ogg_packet);
+ memcpy(context->buffer + context->buffer_index, op.packet, op.bytes);
+ context->buffer_index += op.bytes;
+// av_log(avccontext, AV_LOG_DEBUG, "e%d / %d\n", context->buffer_index, op.bytes);
+ }
+ }
+
+ l=0;
+ if(context->buffer_index){
+ ogg_packet *op2= (ogg_packet*)context->buffer;
+ op2->packet = context->buffer + sizeof(ogg_packet);
+
+ l= op2->bytes;
+ avccontext->coded_frame->pts= av_rescale_q(op2->granulepos, (AVRational){1, avccontext->sample_rate}, avccontext->time_base);
+ //FIXME we should reorder the user supplied pts and not assume that they are spaced by 1/sample_rate
+
+ memcpy(packets, op2->packet, l);
+ context->buffer_index -= l + sizeof(ogg_packet);
+ memcpy(context->buffer, context->buffer + l + sizeof(ogg_packet), context->buffer_index);
+// av_log(avccontext, AV_LOG_DEBUG, "E%d\n", l);
+ }
+
+ return l;
+}
+
+
+static int oggvorbis_encode_close(AVCodecContext *avccontext) {
+ OggVorbisContext *context = avccontext->priv_data ;
+/* ogg_packet op ; */
+
+ vorbis_analysis_wrote(&context->vd, 0) ; /* notify vorbisenc this is EOF */
+
+ vorbis_block_clear(&context->vb);
+ vorbis_dsp_clear(&context->vd);
+ vorbis_info_clear(&context->vi);
+
+ av_freep(&avccontext->coded_frame);
+ av_freep(&avccontext->extradata);
+
+ return 0 ;
+}
+
+
+AVCodec oggvorbis_encoder = {
+ "vorbis",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_VORBIS,
+ sizeof(OggVorbisContext),
+ oggvorbis_encode_init,
+ oggvorbis_encode_frame,
+ oggvorbis_encode_close,
+ .capabilities= CODEC_CAP_DELAY,
+} ;
+
+static int oggvorbis_decode_init(AVCodecContext *avccontext) {
+ OggVorbisContext *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] = *p++ << 8;
+ hsizes[i] += *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->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, val ;
+ 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++) {
+
+ val = mono[j] * 32767.f;
+
+ if(val > 32767) val = 32767 ;
+ if(val < -32768) val = -32768 ;
+
+ *ptr = val ;
+ ptr += channels;
+ }
+ }
+
+ return 0 ;
+}
+
+
+static int oggvorbis_decode_frame(AVCodecContext *avccontext,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ OggVorbisContext *context = avccontext->priv_data ;
+ float **pcm ;
+ ogg_packet *op= &context->op;
+ int samples, total_samples, total_bytes;
+
+ if(!buf_size){
+ //FIXME flush
+ return 0;
+ }
+
+ op->packet = buf;
+ op->bytes = buf_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; i<op->bytes; 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*)data + total_bytes, context->vi.channels) ;
+ total_bytes += samples * 2 * context->vi.channels ;
+ total_samples += samples ;
+ vorbis_synthesis_read(&context->vd, samples) ;
+ }
+
+ *data_size = total_bytes ;
+ return buf_size ;
+}
+
+
+static int oggvorbis_decode_close(AVCodecContext *avccontext) {
+ OggVorbisContext *context = avccontext->priv_data ;
+
+ vorbis_info_clear(&context->vi) ;
+ vorbis_comment_clear(&context->vc) ;
+
+ return 0 ;
+}
+
+
+AVCodec oggvorbis_decoder = {
+ "vorbis",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_VORBIS,
+ sizeof(OggVorbisContext),
+ oggvorbis_decode_init,
+ NULL,
+ oggvorbis_decode_close,
+ oggvorbis_decode_frame,
+ .capabilities= CODEC_CAP_DELAY,
+} ;
diff --git a/contrib/ffmpeg/libavcodec/opt.c b/contrib/ffmpeg/libavcodec/opt.c
new file mode 100644
index 000000000..a200d9a82
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/opt.c
@@ -0,0 +1,381 @@
+/*
+ * AVOptions
+ * Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/**
+ * @file opt.c
+ * AVOptions
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#include "avcodec.h"
+#include "opt.h"
+#include "eval.h"
+
+//FIXME order them and do a bin search
+static AVOption *find_opt(void *v, const char *name, const char *unit){
+ AVClass *c= *(AVClass**)v; //FIXME silly way of storing AVClass
+ AVOption *o= c->option;
+
+ for(;o && o->name; o++){
+ if(!strcmp(o->name, name) && (!unit || !strcmp(o->unit, unit)) )
+ return o;
+ }
+ return NULL;
+}
+
+AVOption *av_next_option(void *obj, AVOption *last){
+ if(last && last[1].name) return ++last;
+ else if(last) return NULL;
+ else return (*(AVClass**)obj)->option;
+}
+
+static AVOption *av_set_number(void *obj, const char *name, double num, int den, int64_t intnum){
+ AVOption *o= find_opt(obj, name, NULL);
+ void *dst;
+ if(!o || o->offset<=0)
+ return NULL;
+
+ if(o->max*den < num*intnum || o->min*den > num*intnum) {
+ av_log(NULL, AV_LOG_ERROR, "Value %lf for parameter '%s' out of range.\n", num, name);
+ return NULL;
+ }
+
+ dst= ((uint8_t*)obj) + o->offset;
+
+ switch(o->type){
+ case FF_OPT_TYPE_FLAGS:
+ case FF_OPT_TYPE_INT: *(int *)dst= lrintf(num/den)*intnum; break;
+ case FF_OPT_TYPE_INT64: *(int64_t *)dst= lrintf(num/den)*intnum; break;
+ case FF_OPT_TYPE_FLOAT: *(float *)dst= num*intnum/den; break;
+ case FF_OPT_TYPE_DOUBLE:*(double *)dst= num*intnum/den; break;
+ case FF_OPT_TYPE_RATIONAL:
+ if((int)num == num) *(AVRational*)dst= (AVRational){num*intnum, den};
+ else *(AVRational*)dst= av_d2q(num*intnum/den, 1<<24);
+ default:
+ return NULL;
+ }
+ return o;
+}
+
+static AVOption *set_all_opt(void *v, const char *unit, double d){
+ AVClass *c= *(AVClass**)v; //FIXME silly way of storing AVClass
+ AVOption *o= c->option;
+ AVOption *ret=NULL;
+
+ for(;o && o->name; o++){
+ if(o->type != FF_OPT_TYPE_CONST && o->unit && !strcmp(o->unit, unit)){
+ double tmp= d;
+ if(o->type == FF_OPT_TYPE_FLAGS)
+ tmp= av_get_int(v, o->name, NULL) | (int64_t)d;
+
+ av_set_number(v, o->name, tmp, 1, 1);
+ ret= o;
+ }
+ }
+ return ret;
+}
+
+static double const_values[]={
+ M_PI,
+ M_E,
+ FF_QP2LAMBDA,
+ 0
+};
+
+static const char *const_names[]={
+ "PI",
+ "E",
+ "QP2LAMBDA",
+ 0
+};
+
+AVOption *av_set_string(void *obj, const char *name, const char *val){
+ AVOption *o= find_opt(obj, name, NULL);
+ if(o && o->offset==0 && o->type == FF_OPT_TYPE_CONST && o->unit){
+ return set_all_opt(obj, o->unit, o->default_val);
+ }
+ if(!o || !val || o->offset<=0)
+ return NULL;
+ if(o->type != FF_OPT_TYPE_STRING){
+ for(;;){
+ int i;
+ char buf[256];
+ int cmd=0;
+ double d;
+ char *error = NULL;
+
+ if(*val == '+' || *val == '-')
+ cmd= *(val++);
+
+ for(i=0; i<sizeof(buf)-1 && val[i] && val[i]!='+' && val[i]!='-'; i++)
+ buf[i]= val[i];
+ buf[i]=0;
+ val+= i;
+
+ d = ff_eval2(buf, const_values, const_names, NULL, NULL, NULL, NULL, NULL, &error);
+ if(isnan(d)) {
+ AVOption *o_named= find_opt(obj, buf, o->unit);
+ if(o_named && o_named->type == FF_OPT_TYPE_CONST)
+ d= o_named->default_val;
+ else if(!strcmp(buf, "default")) d= o->default_val;
+ else if(!strcmp(buf, "max" )) d= o->max;
+ else if(!strcmp(buf, "min" )) d= o->min;
+ else {
+ if (!error)
+ av_log(NULL, AV_LOG_ERROR, "Unable to parse option value \"%s\": %s\n", val, error);
+ return NULL;
+ }
+ }
+ if(o->type == FF_OPT_TYPE_FLAGS){
+ if (cmd=='+') d= av_get_int(obj, name, NULL) | (int64_t)d;
+ else if(cmd=='-') d= av_get_int(obj, name, NULL) &~(int64_t)d;
+ }else if(cmd=='-')
+ d= -d;
+
+ av_set_number(obj, name, d, 1, 1);
+ if(!*val)
+ return o;
+ }
+ return NULL;
+ }
+
+ memcpy(((uint8_t*)obj) + o->offset, val, sizeof(val));
+ return o;
+}
+
+AVOption *av_set_double(void *obj, const char *name, double n){
+ return av_set_number(obj, name, n, 1, 1);
+}
+
+AVOption *av_set_q(void *obj, const char *name, AVRational n){
+ return av_set_number(obj, name, n.num, n.den, 1);
+}
+
+AVOption *av_set_int(void *obj, const char *name, int64_t n){
+ return av_set_number(obj, name, 1, 1, n);
+}
+
+/**
+ *
+ * @param buf a buffer which is used for returning non string values as strings, can be NULL
+ * @param buf_len allocated length in bytes of buf
+ */
+const char *av_get_string(void *obj, const char *name, AVOption **o_out, char *buf, int buf_len){
+ AVOption *o= find_opt(obj, name, NULL);
+ void *dst;
+ if(!o || o->offset<=0)
+ return NULL;
+ if(o->type != FF_OPT_TYPE_STRING && (!buf || !buf_len))
+ return NULL;
+
+ dst= ((uint8_t*)obj) + o->offset;
+ if(o_out) *o_out= o;
+
+ if(o->type == FF_OPT_TYPE_STRING)
+ return dst;
+
+ switch(o->type){
+ case FF_OPT_TYPE_FLAGS: snprintf(buf, buf_len, "0x%08X",*(int *)dst);break;
+ case FF_OPT_TYPE_INT: snprintf(buf, buf_len, "%d" , *(int *)dst);break;
+ case FF_OPT_TYPE_INT64: snprintf(buf, buf_len, "%"PRId64, *(int64_t*)dst);break;
+ case FF_OPT_TYPE_FLOAT: snprintf(buf, buf_len, "%f" , *(float *)dst);break;
+ case FF_OPT_TYPE_DOUBLE: snprintf(buf, buf_len, "%f" , *(double *)dst);break;
+ case FF_OPT_TYPE_RATIONAL: snprintf(buf, buf_len, "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
+ default: return NULL;
+ }
+ return buf;
+}
+
+static int av_get_number(void *obj, const char *name, AVOption **o_out, double *num, int *den, int64_t *intnum){
+ AVOption *o= find_opt(obj, name, NULL);
+ void *dst;
+ if(!o || o->offset<=0)
+ goto error;
+
+ dst= ((uint8_t*)obj) + o->offset;
+
+ if(o_out) *o_out= o;
+
+ switch(o->type){
+ case FF_OPT_TYPE_FLAGS:
+ case FF_OPT_TYPE_INT: *intnum= *(int *)dst;return 0;
+ case FF_OPT_TYPE_INT64: *intnum= *(int64_t*)dst;return 0;
+ case FF_OPT_TYPE_FLOAT: *num= *(float *)dst;return 0;
+ case FF_OPT_TYPE_DOUBLE: *num= *(double *)dst;return 0;
+ case FF_OPT_TYPE_RATIONAL: *intnum= ((AVRational*)dst)->num;
+ *den = ((AVRational*)dst)->den;
+ return 0;
+ }
+error:
+ *den=*intnum=0;
+ return -1;
+}
+
+double av_get_double(void *obj, const char *name, AVOption **o_out){
+ int64_t intnum=1;
+ double num=1;
+ int den=1;
+
+ av_get_number(obj, name, o_out, &num, &den, &intnum);
+ return num*intnum/den;
+}
+
+AVRational av_get_q(void *obj, const char *name, AVOption **o_out){
+ int64_t intnum=1;
+ double num=1;
+ int den=1;
+
+ av_get_number(obj, name, o_out, &num, &den, &intnum);
+ if(num == 1.0 && (int)intnum == intnum)
+ return (AVRational){intnum, den};
+ else
+ return av_d2q(num*intnum/den, 1<<24);
+}
+
+int64_t av_get_int(void *obj, const char *name, AVOption **o_out){
+ int64_t intnum=1;
+ double num=1;
+ int den=1;
+
+ av_get_number(obj, name, o_out, &num, &den, &intnum);
+ return num*intnum/den;
+}
+
+static void opt_list(void *obj, void *av_log_obj, char *unit)
+{
+ AVOption *opt=NULL;
+
+ while((opt= av_next_option(obj, opt))){
+ if(!(opt->flags & (AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM)))
+ continue;
+
+ /* Don't print CONST's on level one.
+ * Don't print anything but CONST's on level two.
+ * Only print items from the requested unit.
+ */
+ if (!unit && opt->type==FF_OPT_TYPE_CONST)
+ continue;
+ else if (unit && opt->type!=FF_OPT_TYPE_CONST)
+ continue;
+ else if (unit && opt->type==FF_OPT_TYPE_CONST && strcmp(unit, opt->unit))
+ continue;
+ else if (unit && opt->type == FF_OPT_TYPE_CONST)
+ av_log(av_log_obj, AV_LOG_INFO, " %-15s ", opt->name);
+ else
+ av_log(av_log_obj, AV_LOG_INFO, "-%-17s ", opt->name);
+
+ switch( opt->type )
+ {
+ case FF_OPT_TYPE_FLAGS:
+ av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<flags>" );
+ break;
+ case FF_OPT_TYPE_INT:
+ av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<int>" );
+ break;
+ case FF_OPT_TYPE_INT64:
+ av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<int64>" );
+ break;
+ case FF_OPT_TYPE_DOUBLE:
+ av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<double>" );
+ break;
+ case FF_OPT_TYPE_FLOAT:
+ av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<float>" );
+ break;
+ case FF_OPT_TYPE_STRING:
+ av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<string>" );
+ break;
+ case FF_OPT_TYPE_RATIONAL:
+ av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<rational>" );
+ break;
+ case FF_OPT_TYPE_CONST:
+ default:
+ av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "" );
+ break;
+ }
+ av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.');
+ av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.');
+ av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM ) ? 'V' : '.');
+ av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM ) ? 'A' : '.');
+ av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.');
+
+ if(opt->help)
+ av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help);
+ av_log(av_log_obj, AV_LOG_INFO, "\n");
+ if (opt->unit && opt->type != FF_OPT_TYPE_CONST) {
+ opt_list(obj, av_log_obj, opt->unit);
+ }
+ }
+}
+
+int av_opt_show(void *obj, void *av_log_obj){
+ if(!obj)
+ return -1;
+
+ av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass**)obj)->class_name);
+
+ opt_list(obj, av_log_obj, NULL);
+
+ return 0;
+}
+
+/** Set the values of the AVCodecContext or AVFormatContext structure.
+ * They are set to the defaults specified in the according AVOption options
+ * array default_val field.
+ *
+ * @param s AVCodecContext or AVFormatContext for which the defaults will be set
+ */
+void av_opt_set_defaults(void *s)
+{
+ AVOption *opt = NULL;
+ while ((opt = av_next_option(s, opt)) != NULL) {
+ switch(opt->type) {
+ case FF_OPT_TYPE_CONST:
+ /* Nothing to be done here */
+ break;
+ case FF_OPT_TYPE_FLAGS:
+ case FF_OPT_TYPE_INT: {
+ int val;
+ val = opt->default_val;
+ av_set_int(s, opt->name, val);
+ }
+ break;
+ case FF_OPT_TYPE_FLOAT: {
+ double val;
+ val = opt->default_val;
+ av_set_double(s, opt->name, val);
+ }
+ break;
+ case FF_OPT_TYPE_RATIONAL: {
+ AVRational val;
+ val = av_d2q(opt->default_val, INT_MAX);
+ av_set_q(s, opt->name, val);
+ }
+ break;
+ case FF_OPT_TYPE_STRING:
+ /* Cannot set default for string as default_val is of type * double */
+ break;
+ default:
+ av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n", opt->type, opt->name);
+ }
+ }
+}
+
diff --git a/contrib/ffmpeg/libavcodec/opt.h b/contrib/ffmpeg/libavcodec/opt.h
new file mode 100644
index 000000000..b8a17031b
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/opt.h
@@ -0,0 +1,83 @@
+/*
+ * AVOptions
+ * copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 AVOPT_H
+#define AVOPT_H
+
+/**
+ * @file opt.h
+ * AVOptions
+ */
+
+enum AVOptionType{
+ FF_OPT_TYPE_FLAGS,
+ FF_OPT_TYPE_INT,
+ FF_OPT_TYPE_INT64,
+ FF_OPT_TYPE_DOUBLE,
+ FF_OPT_TYPE_FLOAT,
+ FF_OPT_TYPE_STRING,
+ FF_OPT_TYPE_RATIONAL,
+ FF_OPT_TYPE_CONST=128,
+};
+
+/**
+ * AVOption.
+ */
+typedef struct AVOption {
+ const char *name;
+
+ /**
+ * short English text help.
+ * @fixme what about other languages
+ */
+ const char *help;
+ int offset; ///< offset to context structure where the parsed value should be stored
+ enum AVOptionType type;
+
+ double default_val;
+ double min;
+ double max;
+
+ int flags;
+#define AV_OPT_FLAG_ENCODING_PARAM 1 ///< a generic parameter which can be set by the user for muxing or encoding
+#define AV_OPT_FLAG_DECODING_PARAM 2 ///< a generic parameter which can be set by the user for demuxing or decoding
+#define AV_OPT_FLAG_METADATA 4 ///< some data extracted or inserted into the file like title, comment, ...
+#define AV_OPT_FLAG_AUDIO_PARAM 8
+#define AV_OPT_FLAG_VIDEO_PARAM 16
+#define AV_OPT_FLAG_SUBTITLE_PARAM 32
+//FIXME think about enc-audio, ... style flags
+ const char *unit;
+} AVOption;
+
+
+AVOption *av_set_string(void *obj, const char *name, const char *val);
+AVOption *av_set_double(void *obj, const char *name, double n);
+AVOption *av_set_q(void *obj, const char *name, AVRational n);
+AVOption *av_set_int(void *obj, const char *name, int64_t n);
+double av_get_double(void *obj, const char *name, AVOption **o_out);
+AVRational av_get_q(void *obj, const char *name, AVOption **o_out);
+int64_t av_get_int(void *obj, const char *name, AVOption **o_out);
+const char *av_get_string(void *obj, const char *name, AVOption **o_out, char *buf, int buf_len);
+AVOption *av_next_option(void *obj, AVOption *last);
+int av_opt_show(void *obj, void *av_log_obj);
+void av_opt_set_defaults(void *s);
+
+#endif
diff --git a/contrib/ffmpeg/libavcodec/os2thread.c b/contrib/ffmpeg/libavcodec/os2thread.c
new file mode 100644
index 000000000..c52b7ae02
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/os2thread.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have 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
+ *
+ */
+//#define DEBUG
+
+// Ported by Vlad Stelmahovsky
+
+#include "avcodec.h"
+#include "common.h"
+
+#define INCL_DOS
+#define INCL_DOSERRORS
+#define INCL_DOSDEVIOCTL
+#include <os2.h>
+
+typedef struct ThreadContext{
+ AVCodecContext *avctx;
+ int thread;
+ HEV work_sem;
+ HEV done_sem;
+ int (*func)(AVCodecContext *c, void *arg);
+ void *arg;
+ int ret;
+}ThreadContext;
+
+
+void thread_func(void *v){
+ ThreadContext *c= v;
+
+ for(;;){
+ //printf("thread_func %X enter wait\n", (int)v); fflush(stdout);
+ DosWaitEventSem(c->work_sem, SEM_INDEFINITE_WAIT);
+// WaitForSingleObject(c->work_sem, INFINITE);
+//printf("thread_func %X after wait (func=%X)\n", (int)v, (int)c->func); fflush(stdout);
+ if(c->func)
+ c->ret= c->func(c->avctx, c->arg);
+ else
+ return;
+ //printf("thread_func %X signal complete\n", (int)v); fflush(stdout);
+ DosPostEventSem(c->done_sem);
+// ReleaseSemaphore(c->done_sem, 1, 0);
+ }
+
+ return;
+}
+
+/**
+ * free what has been allocated by avcodec_thread_init().
+ * must be called after decoding has finished, especially dont call while avcodec_thread_execute() is running
+ */
+void avcodec_thread_free(AVCodecContext *s){
+ ThreadContext *c= s->thread_opaque;
+ int i;
+
+ for(i=0; i<s->thread_count; i++){
+
+ c[i].func= NULL;
+ DosPostEventSem(c[i].work_sem);
+ // ReleaseSemaphore(c[i].work_sem, 1, 0);
+ DosWaitThread((PTID)&c[i].thread,DCWW_WAIT);
+// WaitForSingleObject(c[i].thread, INFINITE);
+ if(c[i].work_sem) DosCloseEventSem(c[i].work_sem);//CloseHandle(c[i].work_sem);
+ if(c[i].done_sem) DosCloseEventSem(c[i].done_sem);//CloseHandle(c[i].done_sem);
+ }
+
+ av_freep(&s->thread_opaque);
+}
+
+int avcodec_thread_execute(AVCodecContext *s, int (*func)(AVCodecContext *c2, void *arg2),void **arg, int *ret, int count){
+ ThreadContext *c= s->thread_opaque;
+ int i;
+
+ assert(s == c->avctx);
+ assert(count <= s->thread_count);
+
+ /* note, we can be certain that this is not called with the same AVCodecContext by different threads at the same time */
+
+ for(i=0; i<count; i++){
+
+ c[i].arg= arg[i];
+ c[i].func= func;
+ c[i].ret= 12345;
+
+ DosPostEventSem(c[i].work_sem);
+// ReleaseSemaphore(c[i].work_sem, 1, 0);
+ }
+ for(i=0; i<count; i++){
+ DosWaitEventSem(c[i].done_sem,SEM_INDEFINITE_WAIT);
+// WaitForSingleObject(c[i].done_sem, INFINITE);
+
+ c[i].func= NULL;
+ if(ret) ret[i]= c[i].ret;
+ }
+ return 0;
+}
+
+int avcodec_thread_init(AVCodecContext *s, int thread_count){
+ int i;
+ ThreadContext *c;
+ uint32_t threadid;
+
+ s->thread_count= thread_count;
+
+ assert(!s->thread_opaque);
+ c= av_mallocz(sizeof(ThreadContext)*thread_count);
+ s->thread_opaque= c;
+
+ for(i=0; i<thread_count; i++){
+//printf("init semaphors %d\n", i); fflush(stdout);
+ c[i].avctx= s;
+
+ if (DosCreateEventSem(NULL,&c[i].work_sem,DC_SEM_SHARED,0))
+ goto fail;
+ if (DosCreateEventSem(NULL,&c[i].done_sem,DC_SEM_SHARED,0))
+ goto fail;
+
+//printf("create thread %d\n", i); fflush(stdout);
+// c[i].thread = (HANDLE)_beginthreadex(NULL, 0, thread_func, &c[i], 0, &threadid );
+ c[i].thread = _beginthread(thread_func, NULL, 0x10000, &c[i]);
+ if( c[i].thread <= 0 ) goto fail;
+ }
+//printf("init done\n"); fflush(stdout);
+
+ s->execute= avcodec_thread_execute;
+
+ return 0;
+fail:
+ avcodec_thread_free(s);
+ return -1;
+}
diff --git a/contrib/ffmpeg/libavcodec/parser.c b/contrib/ffmpeg/libavcodec/parser.c
new file mode 100644
index 000000000..72a3e55a3
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/parser.c
@@ -0,0 +1,860 @@
+/*
+ * 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 "avcodec.h"
+#include "mpegvideo.h"
+#include "mpegaudio.h"
+#include "parser.h"
+
+AVCodecParser *av_first_parser = NULL;
+
+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;
+ AVCodecParser *parser;
+ int ret;
+
+ if(codec_id == 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)
+ return NULL;
+ s->parser = parser;
+ s->priv_data = av_mallocz(parser->priv_data_size);
+ if (!s->priv_data) {
+ av_free(s);
+ return NULL;
+ }
+ if (parser->parser_init) {
+ ret = parser->parser_init(s);
+ if (ret != 0) {
+ av_free(s->priv_data);
+ av_free(s);
+ return NULL;
+ }
+ }
+ s->fetch_timestamp=1;
+ return s;
+}
+
+/**
+ *
+ * @param buf input
+ * @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 poutbuf will contain a pointer to the first byte of the output frame
+ * @param poutbuf_size will contain the length of the output frame
+ * @return the number of bytes of the input bitstream used
+ *
+ * Example:
+ * @code
+ * while(in_len){
+ * len = av_parser_parse(myparser, AVCodecContext, &data, &size,
+ * in_data, in_len,
+ * pts, dts);
+ * in_data += len;
+ * in_len -= len;
+ *
+ * decode_frame(data, size);
+ * }
+ * @endcode
+ */
+int av_parser_parse(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size,
+ int64_t pts, int64_t dts)
+{
+ int index, i, k;
+ uint8_t dummy_buf[FF_INPUT_BUFFER_PADDING_SIZE];
+
+ 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 {
+ /* add a new packet descriptor */
+ k = (s->cur_frame_start_index + 1) & (AV_PARSER_PTS_NB - 1);
+ s->cur_frame_start_index = k;
+ s->cur_frame_offset[k] = s->cur_offset;
+ s->cur_frame_pts[k] = pts;
+ s->cur_frame_dts[k] = dts;
+
+ /* fill first PTS/DTS */
+ if (s->fetch_timestamp){
+ s->fetch_timestamp=0;
+ s->last_pts = pts;
+ s->last_dts = dts;
+ s->cur_frame_pts[k] =
+ s->cur_frame_dts[k] = AV_NOPTS_VALUE;
+ }
+ }
+
+ /* WARNING: the returned index can be negative */
+ index = s->parser->parser_parse(s, avctx, poutbuf, poutbuf_size, buf, buf_size);
+//av_log(NULL, AV_LOG_DEBUG, "parser: in:%"PRId64", %"PRId64", out:%"PRId64", %"PRId64", in:%d out:%d id:%d\n", pts, dts, s->last_pts, s->last_dts, buf_size, *poutbuf_size, avctx->codec_id);
+ /* update the file pointer */
+ if (*poutbuf_size) {
+ /* fill the data for the current frame */
+ s->frame_offset = s->last_frame_offset;
+ s->pts = s->last_pts;
+ s->dts = s->last_dts;
+
+ /* offset of the next frame */
+ s->last_frame_offset = s->cur_offset + index;
+ /* find the packet in which the new frame starts. It
+ is tricky because of MPEG video start codes
+ which can begin in one packet and finish in
+ another packet. In the worst case, an MPEG
+ video start code could be in 4 different
+ packets. */
+ k = s->cur_frame_start_index;
+ for(i = 0; i < AV_PARSER_PTS_NB; i++) {
+ if (s->last_frame_offset >= s->cur_frame_offset[k])
+ break;
+ k = (k - 1) & (AV_PARSER_PTS_NB - 1);
+ }
+
+ s->last_pts = s->cur_frame_pts[k];
+ s->last_dts = s->cur_frame_dts[k];
+
+ /* some parsers tell us the packet size even before seeing the first byte of the next packet,
+ so the next pts/dts is in the next chunk */
+ if(index == buf_size){
+ s->fetch_timestamp=1;
+ }
+ }
+ if (index < 0)
+ index = 0;
+ s->cur_offset += index;
+ return index;
+}
+
+/**
+ *
+ * @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){
+
+ 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 != I_TYPE && (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->parser->parser_close)
+ s->parser->parser_close(s);
+ av_free(s->priv_data);
+ av_free(s);
+}
+
+/*****************************************************/
+
+/**
+ * combines the (truncated) bitstream to a complete frame
+ * @returns -1 if no complete frame could be created
+ */
+int ff_combine_frame(ParseContext *pc, int next, uint8_t **buf, int *buf_size)
+{
+#if 0
+ if(pc->overread){
+ printf("overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index);
+ printf("%X %X %X %X\n", (*buf)[0], (*buf)[1],(*buf)[2],(*buf)[3]);
+ }
+#endif
+
+ /* copy overreaded 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){
+ pc->buffer= av_fast_realloc(pc->buffer, &pc->buffer_size, (*buf_size) + pc->index + FF_INPUT_BUFFER_PADDING_SIZE);
+
+ 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){
+ pc->buffer= av_fast_realloc(pc->buffer, &pc->buffer_size, next + pc->index + 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->overread++;
+ }
+
+#if 0
+ if(pc->overread){
+ printf("overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index);
+ printf("%X %X %X %X\n", (*buf)[0], (*buf)[1],(*buf)[2],(*buf)[3]);
+ }
+#endif
+
+ return 0;
+}
+
+void ff_parse_close(AVCodecParserContext *s)
+{
+ ParseContext *pc = s->priv_data;
+
+ av_free(pc->buffer);
+}
+
+void ff_parse1_close(AVCodecParserContext *s)
+{
+ ParseContext1 *pc1 = s->priv_data;
+
+ av_free(pc1->pc.buffer);
+ av_free(pc1->enc);
+}
+
+/*************************/
+
+#ifdef CONFIG_MPEG4VIDEO_PARSER
+/* used by parser */
+/* XXX: make it use less memory */
+static int av_mpeg4_decode_header(AVCodecParserContext *s1,
+ AVCodecContext *avctx,
+ const uint8_t *buf, int buf_size)
+{
+ ParseContext1 *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) {
+ avcodec_set_dimensions(avctx, s->width, s->height);
+ }
+ s1->pict_type= s->pict_type;
+ pc->first_picture = 0;
+ return ret;
+}
+
+static int mpeg4video_parse_init(AVCodecParserContext *s)
+{
+ ParseContext1 *pc = s->priv_data;
+
+ pc->enc = av_mallocz(sizeof(MpegEncContext));
+ if (!pc->enc)
+ return -1;
+ pc->first_picture = 1;
+ return 0;
+}
+
+static int mpeg4video_parse(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ 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, (uint8_t **)&buf, &buf_size) < 0) {
+ *poutbuf = NULL;
+ *poutbuf_size = 0;
+ return buf_size;
+ }
+ }
+ av_mpeg4_decode_header(s, avctx, buf, buf_size);
+
+ *poutbuf = (uint8_t *)buf;
+ *poutbuf_size = buf_size;
+ return next;
+}
+#endif
+
+int ff_mpeg4video_split(AVCodecContext *avctx,
+ const uint8_t *buf, int buf_size)
+{
+ int i;
+ uint32_t state= -1;
+
+ for(i=0; i<buf_size; i++){
+ state= (state<<8) | buf[i];
+ if(state == 0x1B3 || state == 0x1B6)
+ return i-3;
+ }
+ return 0;
+}
+
+/*************************/
+
+#ifdef CONFIG_MPEGAUDIO_PARSER
+typedef struct MpegAudioParseContext {
+ uint8_t inbuf[MPA_MAX_CODED_FRAME_SIZE]; /* input buffer */
+ uint8_t *inbuf_ptr;
+ int frame_size;
+ int free_format_frame_size;
+ int free_format_next_header;
+ uint32_t header;
+ int header_count;
+} MpegAudioParseContext;
+
+#define MPA_HEADER_SIZE 4
+
+/* header + layer + bitrate + freq + lsf/mpeg25 */
+#undef SAME_HEADER_MASK /* mpegaudio.h defines different version */
+#define SAME_HEADER_MASK \
+ (0xffe00000 | (3 << 17) | (3 << 10) | (3 << 19))
+
+static int mpegaudio_parse_init(AVCodecParserContext *s1)
+{
+ MpegAudioParseContext *s = s1->priv_data;
+ s->inbuf_ptr = s->inbuf;
+ return 0;
+}
+
+static int mpegaudio_parse(AVCodecParserContext *s1,
+ AVCodecContext *avctx,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size)
+{
+ MpegAudioParseContext *s = s1->priv_data;
+ int len, ret, sr;
+ uint32_t header;
+ const uint8_t *buf_ptr;
+
+ *poutbuf = NULL;
+ *poutbuf_size = 0;
+ buf_ptr = buf;
+ while (buf_size > 0) {
+ len = s->inbuf_ptr - s->inbuf;
+ if (s->frame_size == 0) {
+ /* special case for next header for first frame in free
+ format case (XXX: find a simpler method) */
+ if (s->free_format_next_header != 0) {
+ s->inbuf[0] = s->free_format_next_header >> 24;
+ s->inbuf[1] = s->free_format_next_header >> 16;
+ s->inbuf[2] = s->free_format_next_header >> 8;
+ s->inbuf[3] = s->free_format_next_header;
+ s->inbuf_ptr = s->inbuf + 4;
+ s->free_format_next_header = 0;
+ goto got_header;
+ }
+ /* no header seen : find one. We need at least MPA_HEADER_SIZE
+ bytes to parse it */
+ len = FFMIN(MPA_HEADER_SIZE - len, buf_size);
+ if (len > 0) {
+ memcpy(s->inbuf_ptr, buf_ptr, len);
+ buf_ptr += len;
+ buf_size -= len;
+ s->inbuf_ptr += len;
+ }
+ if ((s->inbuf_ptr - s->inbuf) >= MPA_HEADER_SIZE) {
+ got_header:
+ header = (s->inbuf[0] << 24) | (s->inbuf[1] << 16) |
+ (s->inbuf[2] << 8) | s->inbuf[3];
+
+ ret = mpa_decode_header(avctx, header, &sr);
+ if (ret < 0) {
+ s->header_count= -2;
+ /* no sync found : move by one byte (inefficient, but simple!) */
+ memmove(s->inbuf, s->inbuf + 1, s->inbuf_ptr - s->inbuf - 1);
+ s->inbuf_ptr--;
+ dprintf("skip %x\n", header);
+ /* reset free format frame size to give a chance
+ to get a new bitrate */
+ s->free_format_frame_size = 0;
+ } else {
+ if((header&SAME_HEADER_MASK) != (s->header&SAME_HEADER_MASK) && s->header)
+ s->header_count= -3;
+ s->header= header;
+ s->header_count++;
+ s->frame_size = ret;
+
+#if 0
+ /* free format: prepare to compute frame size */
+ if (decode_header(s, header) == 1) {
+ s->frame_size = -1;
+ }
+#endif
+ }
+ if(s->header_count > 1)
+ avctx->sample_rate= sr;
+ }
+ } else
+#if 0
+ if (s->frame_size == -1) {
+ /* free format : find next sync to compute frame size */
+ len = MPA_MAX_CODED_FRAME_SIZE - len;
+ if (len > buf_size)
+ len = buf_size;
+ if (len == 0) {
+ /* frame too long: resync */
+ s->frame_size = 0;
+ memmove(s->inbuf, s->inbuf + 1, s->inbuf_ptr - s->inbuf - 1);
+ s->inbuf_ptr--;
+ } else {
+ uint8_t *p, *pend;
+ uint32_t header1;
+ int padding;
+
+ memcpy(s->inbuf_ptr, buf_ptr, len);
+ /* check for header */
+ p = s->inbuf_ptr - 3;
+ pend = s->inbuf_ptr + len - 4;
+ while (p <= pend) {
+ header = (p[0] << 24) | (p[1] << 16) |
+ (p[2] << 8) | p[3];
+ header1 = (s->inbuf[0] << 24) | (s->inbuf[1] << 16) |
+ (s->inbuf[2] << 8) | s->inbuf[3];
+ /* check with high probability that we have a
+ valid header */
+ if ((header & SAME_HEADER_MASK) ==
+ (header1 & SAME_HEADER_MASK)) {
+ /* header found: update pointers */
+ len = (p + 4) - s->inbuf_ptr;
+ buf_ptr += len;
+ buf_size -= len;
+ s->inbuf_ptr = p;
+ /* compute frame size */
+ s->free_format_next_header = header;
+ s->free_format_frame_size = s->inbuf_ptr - s->inbuf;
+ padding = (header1 >> 9) & 1;
+ if (s->layer == 1)
+ s->free_format_frame_size -= padding * 4;
+ else
+ s->free_format_frame_size -= padding;
+ dprintf("free frame size=%d padding=%d\n",
+ s->free_format_frame_size, padding);
+ decode_header(s, header1);
+ goto next_data;
+ }
+ p++;
+ }
+ /* not found: simply increase pointers */
+ buf_ptr += len;
+ s->inbuf_ptr += len;
+ buf_size -= len;
+ }
+ } else
+#endif
+ if (len < s->frame_size) {
+ if (s->frame_size > MPA_MAX_CODED_FRAME_SIZE)
+ s->frame_size = MPA_MAX_CODED_FRAME_SIZE;
+ len = FFMIN(s->frame_size - len, buf_size);
+ memcpy(s->inbuf_ptr, buf_ptr, len);
+ buf_ptr += len;
+ s->inbuf_ptr += len;
+ buf_size -= len;
+ }
+
+ if(s->frame_size > 0 && buf_ptr - buf == s->inbuf_ptr - s->inbuf
+ && buf_size + buf_ptr - buf >= s->frame_size){
+ if(s->header_count > 0){
+ *poutbuf = buf;
+ *poutbuf_size = s->frame_size;
+ }
+ buf_ptr = buf + s->frame_size;
+ s->inbuf_ptr = s->inbuf;
+ s->frame_size = 0;
+ break;
+ }
+
+ // next_data:
+ if (s->frame_size > 0 &&
+ (s->inbuf_ptr - s->inbuf) >= s->frame_size) {
+ if(s->header_count > 0){
+ *poutbuf = s->inbuf;
+ *poutbuf_size = s->inbuf_ptr - s->inbuf;
+ }
+ s->inbuf_ptr = s->inbuf;
+ s->frame_size = 0;
+ break;
+ }
+ }
+ return buf_ptr - buf;
+}
+#endif /* CONFIG_MPEGAUDIO_PARSER */
+
+#if defined(CONFIG_AC3_PARSER) || defined(CONFIG_AAC_PARSER)
+/* also used for ADTS AAC */
+typedef struct AC3ParseContext {
+ uint8_t *inbuf_ptr;
+ int frame_size;
+ int header_size;
+ int (*sync)(const uint8_t *buf, int *channels, int *sample_rate,
+ int *bit_rate, int *samples);
+ uint8_t inbuf[8192]; /* input buffer */
+} AC3ParseContext;
+
+#define AC3_HEADER_SIZE 7
+#define AAC_HEADER_SIZE 7
+
+#ifdef CONFIG_AC3_PARSER
+static const int ac3_sample_rates[4] = {
+ 48000, 44100, 32000, 0
+};
+
+static const int ac3_frame_sizes[64][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 },
+};
+
+static const int ac3_bitrates[64] = {
+ 32, 32, 40, 40, 48, 48, 56, 56, 64, 64, 80, 80, 96, 96, 112, 112,
+ 128, 128, 160, 160, 192, 192, 224, 224, 256, 256, 320, 320, 384,
+ 384, 448, 448, 512, 512, 576, 576, 640, 640,
+};
+
+static const int ac3_channels[8] = {
+ 2, 1, 2, 3, 3, 4, 4, 5
+};
+#endif /* CONFIG_AC3_PARSER */
+
+#ifdef CONFIG_AAC_PARSER
+static const int aac_sample_rates[16] = {
+ 96000, 88200, 64000, 48000, 44100, 32000,
+ 24000, 22050, 16000, 12000, 11025, 8000, 7350
+};
+
+static const int aac_channels[8] = {
+ 0, 1, 2, 3, 4, 5, 6, 8
+};
+#endif
+
+#ifdef CONFIG_AC3_PARSER
+static int ac3_sync(const uint8_t *buf, int *channels, int *sample_rate,
+ int *bit_rate, int *samples)
+{
+ unsigned int fscod, frmsizecod, acmod, bsid, lfeon;
+ GetBitContext bits;
+
+ init_get_bits(&bits, buf, AC3_HEADER_SIZE * 8);
+
+ if(get_bits(&bits, 16) != 0x0b77)
+ return 0;
+
+ skip_bits(&bits, 16); /* crc */
+ fscod = get_bits(&bits, 2);
+ frmsizecod = get_bits(&bits, 6);
+
+ if(!ac3_sample_rates[fscod])
+ return 0;
+
+ bsid = get_bits(&bits, 5);
+ if(bsid > 8)
+ return 0;
+ skip_bits(&bits, 3); /* bsmod */
+ acmod = get_bits(&bits, 3);
+ if(acmod & 1 && acmod != 1)
+ skip_bits(&bits, 2); /* cmixlev */
+ if(acmod & 4)
+ skip_bits(&bits, 2); /* surmixlev */
+ if(acmod & 2)
+ skip_bits(&bits, 2); /* dsurmod */
+ lfeon = get_bits1(&bits);
+
+ *sample_rate = ac3_sample_rates[fscod];
+ *bit_rate = ac3_bitrates[frmsizecod] * 1000;
+ *channels = ac3_channels[acmod] + lfeon;
+ *samples = 6 * 256;
+
+ return ac3_frame_sizes[frmsizecod][fscod] * 2;
+}
+#endif /* CONFIG_AC3_PARSER */
+
+#ifdef CONFIG_AAC_PARSER
+static int aac_sync(const uint8_t *buf, int *channels, int *sample_rate,
+ int *bit_rate, int *samples)
+{
+ GetBitContext bits;
+ int size, rdb, ch, sr;
+
+ init_get_bits(&bits, buf, AAC_HEADER_SIZE * 8);
+
+ if(get_bits(&bits, 12) != 0xfff)
+ return 0;
+
+ skip_bits1(&bits); /* id */
+ skip_bits(&bits, 2); /* layer */
+ skip_bits1(&bits); /* protection_absent */
+ skip_bits(&bits, 2); /* profile_objecttype */
+ sr = get_bits(&bits, 4); /* sample_frequency_index */
+ if(!aac_sample_rates[sr])
+ return 0;
+ skip_bits1(&bits); /* private_bit */
+ ch = get_bits(&bits, 3); /* channel_configuration */
+ if(!aac_channels[ch])
+ return 0;
+ skip_bits1(&bits); /* original/copy */
+ skip_bits1(&bits); /* home */
+
+ /* adts_variable_header */
+ skip_bits1(&bits); /* copyright_identification_bit */
+ skip_bits1(&bits); /* copyright_identification_start */
+ size = get_bits(&bits, 13); /* aac_frame_length */
+ skip_bits(&bits, 11); /* adts_buffer_fullness */
+ rdb = get_bits(&bits, 2); /* number_of_raw_data_blocks_in_frame */
+
+ *channels = aac_channels[ch];
+ *sample_rate = aac_sample_rates[sr];
+ *samples = (rdb + 1) * 1024;
+ *bit_rate = size * 8 * *sample_rate / *samples;
+
+ return size;
+}
+#endif /* CONFIG_AAC_PARSER */
+
+#ifdef CONFIG_AC3_PARSER
+static int ac3_parse_init(AVCodecParserContext *s1)
+{
+ AC3ParseContext *s = s1->priv_data;
+ s->inbuf_ptr = s->inbuf;
+ s->header_size = AC3_HEADER_SIZE;
+ s->sync = ac3_sync;
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_AAC_PARSER
+static int aac_parse_init(AVCodecParserContext *s1)
+{
+ AC3ParseContext *s = s1->priv_data;
+ s->inbuf_ptr = s->inbuf;
+ s->header_size = AAC_HEADER_SIZE;
+ s->sync = aac_sync;
+ return 0;
+}
+#endif
+
+/* also used for ADTS AAC */
+static int ac3_parse(AVCodecParserContext *s1,
+ AVCodecContext *avctx,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size)
+{
+ AC3ParseContext *s = s1->priv_data;
+ const uint8_t *buf_ptr;
+ int len, sample_rate, bit_rate, channels, samples;
+
+ *poutbuf = NULL;
+ *poutbuf_size = 0;
+
+ buf_ptr = buf;
+ while (buf_size > 0) {
+ len = s->inbuf_ptr - s->inbuf;
+ if (s->frame_size == 0) {
+ /* no header seen : find one. We need at least s->header_size
+ bytes to parse it */
+ len = FFMIN(s->header_size - len, buf_size);
+
+ memcpy(s->inbuf_ptr, buf_ptr, len);
+ buf_ptr += len;
+ s->inbuf_ptr += len;
+ buf_size -= len;
+ if ((s->inbuf_ptr - s->inbuf) == s->header_size) {
+ len = s->sync(s->inbuf, &channels, &sample_rate, &bit_rate,
+ &samples);
+ if (len == 0) {
+ /* no sync found : move by one byte (inefficient, but simple!) */
+ memmove(s->inbuf, s->inbuf + 1, s->header_size - 1);
+ s->inbuf_ptr--;
+ } else {
+ s->frame_size = len;
+ /* update codec info */
+ avctx->sample_rate = sample_rate;
+ /* set channels,except if the user explicitly requests 1 or 2 channels, XXX/FIXME this is a bit ugly */
+ if(avctx->codec_id == CODEC_ID_AC3){
+ if(avctx->channels!=1 && avctx->channels!=2){
+ avctx->channels = channels;
+ }
+ } else {
+ avctx->channels = channels;
+ }
+ avctx->bit_rate = bit_rate;
+ avctx->frame_size = samples;
+ }
+ }
+ } else {
+ len = FFMIN(s->frame_size - len, buf_size);
+
+ memcpy(s->inbuf_ptr, buf_ptr, len);
+ buf_ptr += len;
+ s->inbuf_ptr += len;
+ buf_size -= len;
+
+ if(s->inbuf_ptr - s->inbuf == s->frame_size){
+ *poutbuf = s->inbuf;
+ *poutbuf_size = s->frame_size;
+ s->inbuf_ptr = s->inbuf;
+ s->frame_size = 0;
+ break;
+ }
+ }
+ }
+ return buf_ptr - buf;
+}
+#endif /* CONFIG_AC3_PARSER || CONFIG_AAC_PARSER */
+
+#ifdef CONFIG_MPEG4VIDEO_PARSER
+AVCodecParser mpeg4video_parser = {
+ { CODEC_ID_MPEG4 },
+ sizeof(ParseContext1),
+ mpeg4video_parse_init,
+ mpeg4video_parse,
+ ff_parse1_close,
+ ff_mpeg4video_split,
+};
+#endif
+#ifdef CONFIG_MPEGAUDIO_PARSER
+AVCodecParser mpegaudio_parser = {
+ { CODEC_ID_MP2, CODEC_ID_MP3 },
+ sizeof(MpegAudioParseContext),
+ mpegaudio_parse_init,
+ mpegaudio_parse,
+ NULL,
+};
+#endif
+#ifdef CONFIG_AC3_PARSER
+AVCodecParser ac3_parser = {
+ { CODEC_ID_AC3 },
+ sizeof(AC3ParseContext),
+ ac3_parse_init,
+ ac3_parse,
+ NULL,
+};
+#endif
+#ifdef CONFIG_AAC_PARSER
+AVCodecParser aac_parser = {
+ { CODEC_ID_AAC },
+ sizeof(AC3ParseContext),
+ aac_parse_init,
+ ac3_parse,
+ NULL,
+};
+#endif
diff --git a/contrib/ffmpeg/libavcodec/parser.h b/contrib/ffmpeg/libavcodec/parser.h
new file mode 100644
index 000000000..3496b341f
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/parser.h
@@ -0,0 +1,63 @@
+/*
+ * AVCodecParser prototypes and definitions
+ * 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 FFMPEG_PARSER_H
+#define FFMPEG_PARSER_H
+
+typedef struct ParseContext{
+ uint8_t *buffer;
+ int index;
+ int last_index;
+ unsigned int buffer_size;
+ uint32_t state; ///< contains the last few bytes in MSB order
+ int frame_start_found;
+ int overread; ///< the number of bytes which where irreversibly read from the next frame
+ int overread_index; ///< the index into ParseContext.buffer of the overreaded bytes
+} ParseContext;
+
+struct MpegEncContext;
+
+typedef struct ParseContext1{
+ ParseContext pc;
+/* XXX/FIXME PC1 vs. PC */
+ /* MPEG2 specific */
+ AVRational frame_rate;
+ int progressive_sequence;
+ int width, height;
+
+ /* XXX: suppress that, needed by MPEG4 */
+ struct MpegEncContext *enc;
+ int first_picture;
+} ParseContext1;
+
+#define END_NOT_FOUND (-100)
+
+int ff_combine_frame(ParseContext *pc, int next, uint8_t **buf, int *buf_size);
+int ff_mpeg4video_split(AVCodecContext *avctx, const uint8_t *buf,
+ int buf_size);
+void ff_parse_close(AVCodecParserContext *s);
+void ff_parse1_close(AVCodecParserContext *s);
+
+/* h263dec.c */
+int ff_mpeg4_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size);
+
+#endif /* !FFMPEG_PARSER_H */
diff --git a/contrib/ffmpeg/libavcodec/pcm.c b/contrib/ffmpeg/libavcodec/pcm.c
new file mode 100644
index 000000000..26c38b329
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/pcm.c
@@ -0,0 +1,548 @@
+/*
+ * 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.c
+ * PCM codecs
+ */
+
+#include "avcodec.h"
+#include "bitstream.h" // for ff_reverse
+
+/* 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 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 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));
+}
+
+/* 16384 entries per table */
+static uint8_t *linear_to_alaw = NULL;
+static int linear_to_alaw_ref = 0;
+
+static uint8_t *linear_to_ulaw = NULL;
+static int linear_to_ulaw_ref = 0;
+
+static 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<v;j++) {
+ linear_to_xlaw[8192 + j] = (i ^ mask);
+ if (j > 0)
+ linear_to_xlaw[8192 - j] = (i ^ (mask ^ 0x80));
+ }
+ }
+ linear_to_xlaw[0] = linear_to_xlaw[1];
+}
+
+static int pcm_encode_init(AVCodecContext *avctx)
+{
+ avctx->frame_size = 1;
+ switch(avctx->codec->id) {
+ case CODEC_ID_PCM_ALAW:
+ if (linear_to_alaw_ref == 0) {
+ linear_to_alaw = av_malloc(16384);
+ if (!linear_to_alaw)
+ return -1;
+ build_xlaw_table(linear_to_alaw, alaw2linear, 0xd5);
+ }
+ linear_to_alaw_ref++;
+ break;
+ case CODEC_ID_PCM_MULAW:
+ if (linear_to_ulaw_ref == 0) {
+ linear_to_ulaw = av_malloc(16384);
+ if (!linear_to_ulaw)
+ return -1;
+ build_xlaw_table(linear_to_ulaw, ulaw2linear, 0xff);
+ }
+ linear_to_ulaw_ref++;
+ break;
+ default:
+ break;
+ }
+
+ switch(avctx->codec->id) {
+ case CODEC_ID_PCM_S32LE:
+ case CODEC_ID_PCM_S32BE:
+ case CODEC_ID_PCM_U32LE:
+ case CODEC_ID_PCM_U32BE:
+ avctx->block_align = 4 * avctx->channels;
+ break;
+ case CODEC_ID_PCM_S24LE:
+ case CODEC_ID_PCM_S24BE:
+ case CODEC_ID_PCM_U24LE:
+ case CODEC_ID_PCM_U24BE:
+ case CODEC_ID_PCM_S24DAUD:
+ avctx->block_align = 3 * avctx->channels;
+ break;
+ case CODEC_ID_PCM_S16LE:
+ case CODEC_ID_PCM_S16BE:
+ case CODEC_ID_PCM_U16LE:
+ case CODEC_ID_PCM_U16BE:
+ avctx->block_align = 2 * avctx->channels;
+ break;
+ case CODEC_ID_PCM_S8:
+ case CODEC_ID_PCM_U8:
+ case CODEC_ID_PCM_MULAW:
+ case CODEC_ID_PCM_ALAW:
+ avctx->block_align = avctx->channels;
+ break;
+ default:
+ break;
+ }
+
+ avctx->coded_frame= avcodec_alloc_frame();
+ avctx->coded_frame->key_frame= 1;
+
+ return 0;
+}
+
+static int pcm_encode_close(AVCodecContext *avctx)
+{
+ av_freep(&avctx->coded_frame);
+
+ switch(avctx->codec->id) {
+ case CODEC_ID_PCM_ALAW:
+ if (--linear_to_alaw_ref == 0)
+ av_free(linear_to_alaw);
+ break;
+ case CODEC_ID_PCM_MULAW:
+ if (--linear_to_ulaw_ref == 0)
+ av_free(linear_to_ulaw);
+ break;
+ default:
+ /* nothing to free */
+ break;
+ }
+ return 0;
+}
+
+/**
+ * \brief convert samples from 16 bit
+ * \param bps byte per sample for the destination format, must be >= 2
+ * \param le 0 for big-, 1 for little-endian
+ * \param us 0 for signed, 1 for unsigned output
+ * \param samples input samples
+ * \param dst output samples
+ * \param n number of samples in samples buffer.
+ */
+static inline void encode_from16(int bps, int le, int us,
+ short **samples, uint8_t **dst, int n) {
+ if (bps > 2)
+ memset(*dst, 0, n * bps);
+ if (le) *dst += bps - 2;
+ for(;n>0;n--) {
+ register int v = *(*samples)++;
+ if (us) v += 0x8000;
+ (*dst)[le] = v >> 8;
+ (*dst)[1 - le] = v;
+ *dst += bps;
+ }
+ if (le) *dst -= bps - 2;
+}
+
+static int pcm_encode_frame(AVCodecContext *avctx,
+ unsigned char *frame, int buf_size, void *data)
+{
+ int n, sample_size, v;
+ short *samples;
+ unsigned char *dst;
+
+ switch(avctx->codec->id) {
+ case CODEC_ID_PCM_S32LE:
+ case CODEC_ID_PCM_S32BE:
+ case CODEC_ID_PCM_U32LE:
+ case CODEC_ID_PCM_U32BE:
+ sample_size = 4;
+ break;
+ case CODEC_ID_PCM_S24LE:
+ case CODEC_ID_PCM_S24BE:
+ case CODEC_ID_PCM_U24LE:
+ case CODEC_ID_PCM_U24BE:
+ case CODEC_ID_PCM_S24DAUD:
+ sample_size = 3;
+ break;
+ case CODEC_ID_PCM_S16LE:
+ case CODEC_ID_PCM_S16BE:
+ case CODEC_ID_PCM_U16LE:
+ case CODEC_ID_PCM_U16BE:
+ sample_size = 2;
+ break;
+ default:
+ sample_size = 1;
+ break;
+ }
+ n = buf_size / sample_size;
+ samples = data;
+ dst = frame;
+
+ switch(avctx->codec->id) {
+ case CODEC_ID_PCM_S32LE:
+ encode_from16(4, 1, 0, &samples, &dst, n);
+ break;
+ case CODEC_ID_PCM_S32BE:
+ encode_from16(4, 0, 0, &samples, &dst, n);
+ break;
+ case CODEC_ID_PCM_U32LE:
+ encode_from16(4, 1, 1, &samples, &dst, n);
+ break;
+ case CODEC_ID_PCM_U32BE:
+ encode_from16(4, 0, 1, &samples, &dst, n);
+ break;
+ case CODEC_ID_PCM_S24LE:
+ encode_from16(3, 1, 0, &samples, &dst, n);
+ break;
+ case CODEC_ID_PCM_S24BE:
+ encode_from16(3, 0, 0, &samples, &dst, n);
+ break;
+ case CODEC_ID_PCM_U24LE:
+ encode_from16(3, 1, 1, &samples, &dst, n);
+ break;
+ case CODEC_ID_PCM_U24BE:
+ encode_from16(3, 0, 1, &samples, &dst, n);
+ break;
+ case CODEC_ID_PCM_S24DAUD:
+ for(;n>0;n--) {
+ uint32_t tmp = ff_reverse[*samples >> 8] +
+ (ff_reverse[*samples & 0xff] << 8);
+ tmp <<= 4; // sync flags would go here
+ dst[2] = tmp & 0xff;
+ tmp >>= 8;
+ dst[1] = tmp & 0xff;
+ dst[0] = tmp >> 8;
+ samples++;
+ dst += 3;
+ }
+ break;
+ case CODEC_ID_PCM_S16LE:
+ for(;n>0;n--) {
+ v = *samples++;
+ dst[0] = v & 0xff;
+ dst[1] = v >> 8;
+ dst += 2;
+ }
+ break;
+ case CODEC_ID_PCM_S16BE:
+ for(;n>0;n--) {
+ v = *samples++;
+ dst[0] = v >> 8;
+ dst[1] = v;
+ dst += 2;
+ }
+ break;
+ case CODEC_ID_PCM_U16LE:
+ for(;n>0;n--) {
+ v = *samples++;
+ v += 0x8000;
+ dst[0] = v & 0xff;
+ dst[1] = v >> 8;
+ dst += 2;
+ }
+ break;
+ case CODEC_ID_PCM_U16BE:
+ for(;n>0;n--) {
+ v = *samples++;
+ v += 0x8000;
+ dst[0] = v >> 8;
+ dst[1] = v;
+ dst += 2;
+ }
+ break;
+ case CODEC_ID_PCM_S8:
+ for(;n>0;n--) {
+ v = *samples++;
+ dst[0] = v >> 8;
+ dst++;
+ }
+ break;
+ case CODEC_ID_PCM_U8:
+ for(;n>0;n--) {
+ v = *samples++;
+ dst[0] = (v >> 8) + 128;
+ dst++;
+ }
+ break;
+ case CODEC_ID_PCM_ALAW:
+ for(;n>0;n--) {
+ v = *samples++;
+ dst[0] = linear_to_alaw[(v + 32768) >> 2];
+ dst++;
+ }
+ break;
+ case CODEC_ID_PCM_MULAW:
+ for(;n>0;n--) {
+ v = *samples++;
+ dst[0] = linear_to_ulaw[(v + 32768) >> 2];
+ dst++;
+ }
+ break;
+ default:
+ return -1;
+ }
+ //avctx->frame_size = (dst - frame) / (sample_size * avctx->channels);
+
+ return dst - frame;
+}
+
+typedef struct PCMDecode {
+ short table[256];
+} PCMDecode;
+
+static int pcm_decode_init(AVCodecContext * avctx)
+{
+ PCMDecode *s = avctx->priv_data;
+ int i;
+
+ switch(avctx->codec->id) {
+ case CODEC_ID_PCM_ALAW:
+ for(i=0;i<256;i++)
+ s->table[i] = alaw2linear(i);
+ break;
+ case CODEC_ID_PCM_MULAW:
+ for(i=0;i<256;i++)
+ s->table[i] = ulaw2linear(i);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+/**
+ * \brief convert samples to 16 bit
+ * \param bps byte per sample for the source format, must be >= 2
+ * \param le 0 for big-, 1 for little-endian
+ * \param us 0 for signed, 1 for unsigned input
+ * \param src input samples
+ * \param samples output samples
+ * \param src_len number of bytes in src
+ */
+static inline void decode_to16(int bps, int le, int us,
+ uint8_t **src, short **samples, int src_len)
+{
+ register int n = src_len / bps;
+ if (le) *src += bps - 2;
+ for(;n>0;n--) {
+ *(*samples)++ = ((*src)[le] << 8 | (*src)[1 - le]) - (us?0x8000:0);
+ *src += bps;
+ }
+ if (le) *src -= bps - 2;
+}
+
+static int pcm_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ PCMDecode *s = avctx->priv_data;
+ int n;
+ short *samples;
+ uint8_t *src;
+
+ samples = data;
+ src = buf;
+
+ if(buf_size > AVCODEC_MAX_AUDIO_FRAME_SIZE/2)
+ buf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE/2;
+
+ switch(avctx->codec->id) {
+ case CODEC_ID_PCM_S32LE:
+ decode_to16(4, 1, 0, &src, &samples, buf_size);
+ break;
+ case CODEC_ID_PCM_S32BE:
+ decode_to16(4, 0, 0, &src, &samples, buf_size);
+ break;
+ case CODEC_ID_PCM_U32LE:
+ decode_to16(4, 1, 1, &src, &samples, buf_size);
+ break;
+ case CODEC_ID_PCM_U32BE:
+ decode_to16(4, 0, 1, &src, &samples, buf_size);
+ break;
+ case CODEC_ID_PCM_S24LE:
+ decode_to16(3, 1, 0, &src, &samples, buf_size);
+ break;
+ case CODEC_ID_PCM_S24BE:
+ decode_to16(3, 0, 0, &src, &samples, buf_size);
+ break;
+ case CODEC_ID_PCM_U24LE:
+ decode_to16(3, 1, 1, &src, &samples, buf_size);
+ break;
+ case CODEC_ID_PCM_U24BE:
+ decode_to16(3, 0, 1, &src, &samples, buf_size);
+ break;
+ case CODEC_ID_PCM_S24DAUD:
+ n = buf_size / 3;
+ for(;n>0;n--) {
+ uint32_t v = src[0] << 16 | src[1] << 8 | src[2];
+ v >>= 4; // sync flags are here
+ *samples++ = ff_reverse[(v >> 8) & 0xff] +
+ (ff_reverse[v & 0xff] << 8);
+ src += 3;
+ }
+ break;
+ case CODEC_ID_PCM_S16LE:
+ n = buf_size >> 1;
+ for(;n>0;n--) {
+ *samples++ = src[0] | (src[1] << 8);
+ src += 2;
+ }
+ break;
+ case CODEC_ID_PCM_S16BE:
+ n = buf_size >> 1;
+ for(;n>0;n--) {
+ *samples++ = (src[0] << 8) | src[1];
+ src += 2;
+ }
+ break;
+ case CODEC_ID_PCM_U16LE:
+ n = buf_size >> 1;
+ for(;n>0;n--) {
+ *samples++ = (src[0] | (src[1] << 8)) - 0x8000;
+ src += 2;
+ }
+ break;
+ case CODEC_ID_PCM_U16BE:
+ n = buf_size >> 1;
+ for(;n>0;n--) {
+ *samples++ = ((src[0] << 8) | src[1]) - 0x8000;
+ src += 2;
+ }
+ break;
+ case CODEC_ID_PCM_S8:
+ n = buf_size;
+ for(;n>0;n--) {
+ *samples++ = src[0] << 8;
+ src++;
+ }
+ break;
+ case CODEC_ID_PCM_U8:
+ n = buf_size;
+ for(;n>0;n--) {
+ *samples++ = ((int)src[0] - 128) << 8;
+ src++;
+ }
+ break;
+ case CODEC_ID_PCM_ALAW:
+ case CODEC_ID_PCM_MULAW:
+ n = buf_size;
+ for(;n>0;n--) {
+ *samples++ = s->table[src[0]];
+ src++;
+ }
+ break;
+ default:
+ return -1;
+ }
+ *data_size = (uint8_t *)samples - (uint8_t *)data;
+ return src - buf;
+}
+
+#define PCM_CODEC(id, name) \
+AVCodec name ## _encoder = { \
+ #name, \
+ CODEC_TYPE_AUDIO, \
+ id, \
+ 0, \
+ pcm_encode_init, \
+ pcm_encode_frame, \
+ pcm_encode_close, \
+ NULL, \
+}; \
+AVCodec name ## _decoder = { \
+ #name, \
+ CODEC_TYPE_AUDIO, \
+ id, \
+ sizeof(PCMDecode), \
+ pcm_decode_init, \
+ NULL, \
+ NULL, \
+ pcm_decode_frame, \
+}
+
+PCM_CODEC(CODEC_ID_PCM_S32LE, pcm_s32le);
+PCM_CODEC(CODEC_ID_PCM_S32BE, pcm_s32be);
+PCM_CODEC(CODEC_ID_PCM_U32LE, pcm_u32le);
+PCM_CODEC(CODEC_ID_PCM_U32BE, pcm_u32be);
+PCM_CODEC(CODEC_ID_PCM_S24LE, pcm_s24le);
+PCM_CODEC(CODEC_ID_PCM_S24BE, pcm_s24be);
+PCM_CODEC(CODEC_ID_PCM_U24LE, pcm_u24le);
+PCM_CODEC(CODEC_ID_PCM_U24BE, pcm_u24be);
+PCM_CODEC(CODEC_ID_PCM_S24DAUD, pcm_s24daud);
+PCM_CODEC(CODEC_ID_PCM_S16LE, pcm_s16le);
+PCM_CODEC(CODEC_ID_PCM_S16BE, pcm_s16be);
+PCM_CODEC(CODEC_ID_PCM_U16LE, pcm_u16le);
+PCM_CODEC(CODEC_ID_PCM_U16BE, pcm_u16be);
+PCM_CODEC(CODEC_ID_PCM_S8, pcm_s8);
+PCM_CODEC(CODEC_ID_PCM_U8, pcm_u8);
+PCM_CODEC(CODEC_ID_PCM_ALAW, pcm_alaw);
+PCM_CODEC(CODEC_ID_PCM_MULAW, pcm_mulaw);
+
+#undef PCM_CODEC
diff --git a/contrib/ffmpeg/libavcodec/png.c b/contrib/ffmpeg/libavcodec/png.c
new file mode 100644
index 000000000..a257492b7
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/png.c
@@ -0,0 +1,968 @@
+/*
+ * 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"
+
+/* TODO:
+ * - add 2, 4 and 16 bit depth support
+ * - use filters when generating a png (better compression)
+ */
+
+#ifdef CONFIG_ZLIB
+#include <zlib.h>
+
+//#define DEBUG
+
+#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_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_IHDR 0x0001
+#define PNG_IDAT 0x0002
+#define PNG_ALLIMAGE 0x0004
+#define PNG_PLTE 0x0008
+
+#define NB_PASSES 7
+
+#define IOBUF_SIZE 4096
+
+typedef struct PNGContext {
+ uint8_t *bytestream;
+ uint8_t *bytestream_start;
+ uint8_t *bytestream_end;
+ AVFrame picture;
+
+ 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;
+ uint8_t buf[IOBUF_SIZE];
+} PNGContext;
+
+static unsigned int get32(uint8_t **b){
+ (*b) += 4;
+ return ((*b)[-4]<<24) + ((*b)[-3]<<16) + ((*b)[-2]<<8) + (*b)[-1];
+}
+
+#ifdef CONFIG_ENCODERS
+static void put32(uint8_t **b, unsigned int v){
+ *(*b)++= v>>24;
+ *(*b)++= v>>16;
+ *(*b)++= v>>8;
+ *(*b)++= v;
+}
+#endif
+
+static const uint8_t pngsig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
+
+/* Mask to determine which y pixels are valid in a pass */
+static const uint8_t png_pass_ymask[NB_PASSES] = {
+ 0x80, 0x80, 0x08, 0x88, 0x22, 0xaa, 0x55,
+};
+
+/* 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, 0xcc, 0x33, 0xff, 0x55,
+};
+
+/* minimum x value */
+static const uint8_t png_pass_xmin[NB_PASSES] = {
+ 0, 4, 0, 2, 0, 1, 0
+};
+
+/* x shift to get row width */
+static const uint8_t png_pass_xshift[NB_PASSES] = {
+ 3, 3, 2, 2, 1, 1, 0
+};
+
+/* Mask to determine which pixels are valid in a pass */
+static const uint8_t png_pass_mask[NB_PASSES] = {
+ 0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff
+};
+
+/* 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
+};
+#if 0
+static int png_probe(AVProbeData *pd)
+{
+ if (pd->buf_size >= 8 &&
+ memcmp(pd->buf, pngsig, 8) == 0)
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+#endif
+static void *png_zalloc(void *opaque, unsigned int items, unsigned int size)
+{
+ if(items >= UINT_MAX / size)
+ return NULL;
+ return av_malloc(items * size);
+}
+
+static void png_zfree(void *opaque, void *ptr)
+{
+ av_free(ptr);
+}
+
+static int 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 */
+static int png_pass_row_size(int pass, int bits_per_pixel, int width)
+{
+ int shift, xmin, pass_width;
+
+ xmin = png_pass_xmin[pass];
+ if (width <= xmin)
+ return 0;
+ shift = png_pass_xshift[pass];
+ pass_width = (width - xmin + (1 << shift) - 1) >> shift;
+ return (pass_width * bits_per_pixel + 7) >> 3;
+}
+
+/* NOTE: we try to construct a good looking image at each pass. width
+ is the original image width. We also do pixel format convertion 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:
+ /* we must intialize the line to zero before writing to it */
+ if (pass == 0)
+ memset(dst, 0, (width + 7) >> 3);
+ 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] |= b << (7 - j);
+ }
+ if ((mask << j) & 0x80)
+ src_x++;
+ }
+ break;
+ default:
+ bpp = bits_per_pixel >> 3;
+ d = dst;
+ s = src;
+ if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
+ for(x = 0; x < width; x++) {
+ j = x & 7;
+ if ((dsp_mask << j) & 0x80) {
+ *(uint32_t *)d = (s[3] << 24) | (s[0] << 16) | (s[1] << 8) | s[2];
+ }
+ d += bpp;
+ if ((mask << j) & 0x80)
+ s += bpp;
+ }
+ } else {
+ 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;
+ }
+}
+
+#ifdef CONFIG_ENCODERS
+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 = png_pass_mask[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;
+ }
+}
+#endif
+
+/* XXX: optimize */
+/* NOTE: 'dst' can be equal to 'last' */
+static void png_filter_row(uint8_t *dst, int filter_type,
+ uint8_t *src, uint8_t *last, int size, int bpp)
+{
+ int i, p;
+
+ 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];
+ }
+ for(i = bpp; i < size; i++) {
+ p = dst[i - bpp];
+ dst[i] = p + src[i];
+ }
+ break;
+ case PNG_FILTER_VALUE_UP:
+ for(i = 0; i < size; i++) {
+ p = last[i];
+ dst[i] = p + src[i];
+ }
+ break;
+ case PNG_FILTER_VALUE_AVG:
+ for(i = 0; i < bpp; i++) {
+ p = (last[i] >> 1);
+ dst[i] = p + src[i];
+ }
+ for(i = bpp; i < size; i++) {
+ p = ((dst[i - bpp] + last[i]) >> 1);
+ dst[i] = p + src[i];
+ }
+ break;
+ case PNG_FILTER_VALUE_PAETH:
+ for(i = 0; i < bpp; i++) {
+ p = last[i];
+ dst[i] = p + src[i];
+ }
+ for(i = bpp; i < size; i++) {
+ int a, b, c, pa, pb, pc;
+
+ a = dst[i - bpp];
+ b = last[i];
+ c = last[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];
+ }
+ break;
+ }
+}
+
+#ifdef CONFIG_ENCODERS
+static void convert_from_rgba32(uint8_t *dst, const uint8_t *src, int width)
+{
+ uint8_t *d;
+ int j;
+ unsigned int v;
+
+ d = dst;
+ for(j = 0; j < width; j++) {
+ v = ((const uint32_t *)src)[j];
+ d[0] = v >> 16;
+ d[1] = v >> 8;
+ d[2] = v;
+ d[3] = v >> 24;
+ d += 4;
+ }
+}
+#endif
+
+#ifdef CONFIG_DECODERS
+static void convert_to_rgba32(uint8_t *dst, const uint8_t *src, int width)
+{
+ int j;
+ unsigned int r, g, b, a;
+
+ for(j = 0;j < width; j++) {
+ r = src[0];
+ g = src[1];
+ b = src[2];
+ a = src[3];
+ *(uint32_t *)dst = (a << 24) | (r << 16) | (g << 8) | b;
+ dst += 4;
+ src += 4;
+ }
+}
+
+/* process exactly one decompressed row */
+static void png_handle_row(PNGContext *s)
+{
+ uint8_t *ptr, *last_row;
+ int got_line;
+
+ if (!s->interlace_type) {
+ ptr = s->image_buf + s->image_linesize * s->y;
+ /* need to swap bytes correctly for RGB_ALPHA */
+ if (s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
+ png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
+ s->last_row, s->row_size, s->bpp);
+ memcpy(s->last_row, s->tmp_row, s->row_size);
+ convert_to_rgba32(ptr, s->tmp_row, s->width);
+ } else {
+ /* in normal case, we avoid one copy */
+ if (s->y == 0)
+ last_row = s->last_row;
+ else
+ last_row = ptr - s->image_linesize;
+
+ png_filter_row(ptr, s->crow_buf[0], s->crow_buf + 1,
+ last_row, s->row_size, s->bpp);
+ }
+ s->y++;
+ if (s->y == s->height) {
+ s->state |= PNG_ALLIMAGE;
+ }
+ } else {
+ got_line = 0;
+ for(;;) {
+ ptr = s->image_buf + s->image_linesize * s->y;
+ if ((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->tmp_row, s->crow_buf[0], s->crow_buf + 1,
+ s->last_row, s->pass_row_size, s->bpp);
+ memcpy(s->last_row, s->tmp_row, s->pass_row_size);
+ got_line = 1;
+ }
+ if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) {
+ /* NOTE: rgba32 is handled directly in png_put_interlaced_row */
+ 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) {
+ for(;;) {
+ if (s->pass == NB_PASSES - 1) {
+ s->state |= PNG_ALLIMAGE;
+ goto the_end;
+ } else {
+ s->pass++;
+ s->y = 0;
+ s->pass_row_size = 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(PNGContext *s, int length)
+{
+ int ret;
+ s->zstream.avail_in = length;
+ s->zstream.next_in = s->bytestream;
+ s->bytestream += length;
+
+ if(s->bytestream > s->bytestream_end)
+ return -1;
+
+ /* 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) {
+ 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_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ PNGContext * const s = avctx->priv_data;
+ AVFrame *picture = data;
+ AVFrame * const p= (AVFrame*)&s->picture;
+ uint32_t tag, length;
+ int ret, crc;
+
+ s->bytestream_start=
+ s->bytestream= buf;
+ s->bytestream_end= buf + buf_size;
+
+ /* check signature */
+ if (memcmp(s->bytestream, pngsig, 8) != 0)
+ return -1;
+ s->bytestream+= 8;
+ s->y=
+ s->state=0;
+// memset(s, 0, sizeof(PNGContext));
+ /* init the zlib */
+ s->zstream.zalloc = png_zalloc;
+ s->zstream.zfree = png_zfree;
+ s->zstream.opaque = NULL;
+ ret = inflateInit(&s->zstream);
+ if (ret != Z_OK)
+ return -1;
+ for(;;) {
+ int tag32;
+ if (s->bytestream >= s->bytestream_end)
+ goto fail;
+ length = get32(&s->bytestream);
+ if (length > 0x7fffffff)
+ goto fail;
+ tag32 = get32(&s->bytestream);
+ tag = bswap_32(tag32);
+#ifdef DEBUG
+ 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);
+#endif
+ switch(tag) {
+ case MKTAG('I', 'H', 'D', 'R'):
+ if (length != 13)
+ goto fail;
+ s->width = get32(&s->bytestream);
+ s->height = get32(&s->bytestream);
+ if(avcodec_check_dimensions(avctx, s->width, s->height)){
+ s->width= s->height= 0;
+ goto fail;
+ }
+ s->bit_depth = *s->bytestream++;
+ s->color_type = *s->bytestream++;
+ s->compression_type = *s->bytestream++;
+ s->filter_type = *s->bytestream++;
+ s->interlace_type = *s->bytestream++;
+ crc = get32(&s->bytestream);
+ s->state |= PNG_IHDR;
+#ifdef DEBUG
+ 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);
+#endif
+ break;
+ case MKTAG('I', 'D', 'A', 'T'):
+ if (!(s->state & PNG_IHDR))
+ goto fail;
+ if (!(s->state & PNG_IDAT)) {
+ /* init image info */
+ avctx->width = s->width;
+ avctx->height = s->height;
+
+ s->channels = 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 == 8 &&
+ s->color_type == PNG_COLOR_TYPE_RGB) {
+ avctx->pix_fmt = PIX_FMT_RGB24;
+ } else if (s->bit_depth == 8 &&
+ s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
+ avctx->pix_fmt = PIX_FMT_RGBA32;
+ } else if (s->bit_depth == 8 &&
+ s->color_type == PNG_COLOR_TYPE_GRAY) {
+ avctx->pix_fmt = PIX_FMT_GRAY8;
+ } else if (s->bit_depth == 16 &&
+ s->color_type == PNG_COLOR_TYPE_GRAY) {
+ avctx->pix_fmt = PIX_FMT_GRAY16BE;
+ } else if (s->bit_depth == 1 &&
+ s->color_type == PNG_COLOR_TYPE_GRAY) {
+ avctx->pix_fmt = PIX_FMT_MONOBLACK;
+ } else if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
+ avctx->pix_fmt = PIX_FMT_PAL8;
+ } else {
+ goto fail;
+ }
+ if(p->data[0])
+ avctx->release_buffer(avctx, p);
+
+ p->reference= 0;
+ if(avctx->get_buffer(avctx, p) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ goto fail;
+ }
+ p->pict_type= FF_I_TYPE;
+ 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 = png_pass_row_size(s->pass,
+ s->bits_per_pixel,
+ s->width);
+ s->crow_size = s->pass_row_size + 1;
+ }
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_DEBUG, "row_size=%d crow_size =%d\n",
+ s->row_size, s->crow_size);
+#endif
+ s->image_buf = p->data[0];
+ s->image_linesize = p->linesize[0];
+ /* copy the palette if needed */
+ if (s->color_type == PNG_COLOR_TYPE_PALETTE)
+ 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 */
+ s->crow_buf = av_malloc(s->row_size + 1);
+ if (!s->crow_buf)
+ goto fail;
+ 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;
+ /* skip crc */
+ crc = get32(&s->bytestream);
+ 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 = *s->bytestream++;
+ g = *s->bytestream++;
+ b = *s->bytestream++;
+ s->palette[i] = (0xff << 24) | (r << 16) | (g << 8) | b;
+ }
+ for(;i<256;i++) {
+ s->palette[i] = (0xff << 24);
+ }
+ s->state |= PNG_PLTE;
+ crc = get32(&s->bytestream);
+ }
+ 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 = *s->bytestream++;
+ s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
+ }
+ crc = get32(&s->bytestream);
+ }
+ break;
+ case MKTAG('I', 'E', 'N', 'D'):
+ if (!(s->state & PNG_ALLIMAGE))
+ goto fail;
+ crc = get32(&s->bytestream);
+ goto exit_loop;
+ default:
+ /* skip tag */
+ skip_tag:
+ s->bytestream += length + 4;
+ break;
+ }
+ }
+ exit_loop:
+ *picture= *(AVFrame*)&s->picture;
+ *data_size = sizeof(AVPicture);
+
+ ret = s->bytestream - s->bytestream_start;
+ the_end:
+ inflateEnd(&s->zstream);
+ av_freep(&s->crow_buf);
+ av_freep(&s->last_row);
+ av_freep(&s->tmp_row);
+ return ret;
+ fail:
+ ret = -1;
+ goto the_end;
+}
+#endif
+
+#ifdef CONFIG_ENCODERS
+static void png_write_chunk(uint8_t **f, uint32_t tag,
+ const uint8_t *buf, int length)
+{
+ uint32_t crc;
+ uint8_t tagbuf[4];
+
+ put32(f, length);
+ crc = crc32(0, Z_NULL, 0);
+ tagbuf[0] = tag;
+ tagbuf[1] = tag >> 8;
+ tagbuf[2] = tag >> 16;
+ tagbuf[3] = tag >> 24;
+ crc = crc32(crc, tagbuf, 4);
+ put32(f, bswap_32(tag));
+ if (length > 0) {
+ crc = crc32(crc, buf, length);
+ memcpy(*f, buf, length);
+ *f += length;
+ }
+ put32(f, crc);
+}
+
+/* XXX: use avcodec generic function ? */
+static void to_be32(uint8_t *p, uint32_t v)
+{
+ p[0] = v >> 24;
+ p[1] = v >> 16;
+ p[2] = v >> 8;
+ p[3] = v;
+}
+
+/* XXX: do filtering */
+static int png_write_row(PNGContext *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;
+}
+#endif /* CONFIG_ENCODERS */
+
+static int common_init(AVCodecContext *avctx){
+ PNGContext *s = avctx->priv_data;
+
+ avcodec_get_frame_defaults((AVFrame*)&s->picture);
+ avctx->coded_frame= (AVFrame*)&s->picture;
+// s->avctx= avctx;
+
+ return 0;
+}
+
+#ifdef CONFIG_ENCODERS
+static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
+ PNGContext *s = avctx->priv_data;
+ AVFrame *pict = data;
+ AVFrame * const p= (AVFrame*)&s->picture;
+ int bit_depth, color_type, y, len, row_size, ret, is_progressive;
+ int bits_per_pixel, pass_row_size;
+ uint8_t *ptr;
+ uint8_t *crow_buf = NULL;
+ uint8_t *tmp_buf = NULL;
+
+ *p = *pict;
+ p->pict_type= FF_I_TYPE;
+ p->key_frame= 1;
+
+ s->bytestream_start=
+ s->bytestream= buf;
+ s->bytestream_end= buf+buf_size;
+
+ is_progressive = !!(avctx->flags & CODEC_FLAG_INTERLACED_DCT);
+ switch(avctx->pix_fmt) {
+ case PIX_FMT_RGBA32:
+ bit_depth = 8;
+ color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ break;
+ case PIX_FMT_RGB24:
+ bit_depth = 8;
+ color_type = PNG_COLOR_TYPE_RGB;
+ break;
+ case PIX_FMT_GRAY8:
+ bit_depth = 8;
+ color_type = PNG_COLOR_TYPE_GRAY;
+ break;
+ case PIX_FMT_MONOBLACK:
+ bit_depth = 1;
+ color_type = PNG_COLOR_TYPE_GRAY;
+ break;
+ case PIX_FMT_PAL8:
+ bit_depth = 8;
+ color_type = PNG_COLOR_TYPE_PALETTE;
+ break;
+ default:
+ return -1;
+ }
+ bits_per_pixel = png_get_nb_channels(color_type) * bit_depth;
+ row_size = (avctx->width * bits_per_pixel + 7) >> 3;
+
+ s->zstream.zalloc = png_zalloc;
+ s->zstream.zfree = png_zfree;
+ s->zstream.opaque = NULL;
+ ret = deflateInit2(&s->zstream, Z_DEFAULT_COMPRESSION,
+ Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY);
+ if (ret != Z_OK)
+ return -1;
+ crow_buf = av_malloc(row_size + 1);
+ if (!crow_buf)
+ goto fail;
+ if (is_progressive) {
+ tmp_buf = av_malloc(row_size + 1);
+ if (!tmp_buf)
+ goto fail;
+ }
+
+ /* write png header */
+ memcpy(s->bytestream, pngsig, 8);
+ s->bytestream += 8;
+
+ to_be32(s->buf, avctx->width);
+ to_be32(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);
+
+ /* 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 && alpha != 0xff)
+ has_alpha = 1;
+ *alpha_ptr++ = alpha;
+ ptr[0] = v >> 16;
+ ptr[1] = v >> 8;
+ ptr[2] = v;
+ ptr += 3;
+ }
+ 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) {
+ uint8_t *ptr1;
+ int pass;
+
+ for(pass = 0; pass < NB_PASSES; pass++) {
+ /* NOTE: a pass is completely omited if no pixels would be
+ output */
+ pass_row_size = png_pass_row_size(pass, bits_per_pixel, avctx->width);
+ if (pass_row_size > 0) {
+ for(y = 0; y < avctx->height; y++) {
+ if ((png_pass_ymask[pass] << (y & 7)) & 0x80) {
+ ptr = p->data[0] + y * p->linesize[0];
+ if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
+ convert_from_rgba32(tmp_buf, ptr, avctx->width);
+ ptr1 = tmp_buf;
+ } else {
+ ptr1 = ptr;
+ }
+ png_get_interlaced_row(crow_buf + 1, pass_row_size,
+ bits_per_pixel, pass,
+ ptr1, avctx->width);
+ crow_buf[0] = PNG_FILTER_VALUE_NONE;
+ png_write_row(s, crow_buf, pass_row_size + 1);
+ }
+ }
+ }
+ }
+ } else {
+ for(y = 0; y < avctx->height; y++) {
+ ptr = p->data[0] + y * p->linesize[0];
+ if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ convert_from_rgba32(crow_buf + 1, ptr, avctx->width);
+ else
+ memcpy(crow_buf + 1, ptr, row_size);
+ crow_buf[0] = PNG_FILTER_VALUE_NONE;
+ png_write_row(s, crow_buf, row_size + 1);
+ }
+ }
+ /* 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);
+
+ ret = s->bytestream - s->bytestream_start;
+ the_end:
+ av_free(crow_buf);
+ av_free(tmp_buf);
+ deflateEnd(&s->zstream);
+ return ret;
+ fail:
+ ret = -1;
+ goto the_end;
+}
+#endif
+
+#ifdef CONFIG_PNG_DECODER
+AVCodec png_decoder = {
+ "png",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_PNG,
+ sizeof(PNGContext),
+ common_init,
+ NULL,
+ NULL, //decode_end,
+ decode_frame,
+ 0 /*CODEC_CAP_DR1*/ /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
+ NULL
+};
+#endif
+
+#ifdef CONFIG_PNG_ENCODER
+AVCodec png_encoder = {
+ "png",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_PNG,
+ sizeof(PNGContext),
+ common_init,
+ encode_frame,
+ NULL, //encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGBA32, PIX_FMT_PAL8, PIX_FMT_GRAY8, PIX_FMT_MONOBLACK, -1},
+};
+#endif // CONFIG_PNG_ENCODER
+#endif
diff --git a/contrib/ffmpeg/libavcodec/pnm.c b/contrib/ffmpeg/libavcodec/pnm.c
new file mode 100644
index 000000000..610bb28be
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/pnm.c
@@ -0,0 +1,606 @@
+/*
+ * 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 "parser.h" //for ParseContext
+
+typedef struct PNMContext {
+ uint8_t *bytestream;
+ uint8_t *bytestream_start;
+ uint8_t *bytestream_end;
+ AVFrame picture;
+} PNMContext;
+
+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 */
+ for(;;) {
+ c = *sc->bytestream++;
+ if (c == '#') {
+ do {
+ c = *sc->bytestream++;
+ } while (c != '\n' && sc->bytestream < sc->bytestream_end);
+ } 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';
+}
+
+static int common_init(AVCodecContext *avctx){
+ PNMContext *s = avctx->priv_data;
+
+ avcodec_get_frame_defaults((AVFrame*)&s->picture);
+ avctx->coded_frame= (AVFrame*)&s->picture;
+
+ return 0;
+}
+
+static int 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));
+ if (!strcmp(buf1, "P4")) {
+ avctx->pix_fmt = PIX_FMT_MONOWHITE;
+ } else if (!strcmp(buf1, "P5")) {
+ if (avctx->codec_id == CODEC_ID_PGMYUV)
+ avctx->pix_fmt = PIX_FMT_YUV420P;
+ else
+ avctx->pix_fmt = PIX_FMT_GRAY8;
+ } else if (!strcmp(buf1, "P6")) {
+ avctx->pix_fmt = PIX_FMT_RGB24;
+ } else if (!strcmp(buf1, "P7")) {
+ 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, "TUPLETYPE")) {
+ pnm_get(s, tuple_type, sizeof(tuple_type));
+ } else if (!strcmp(buf1, "ENDHDR")) {
+ break;
+ } else {
+ return -1;
+ }
+ }
+ /* check that all tags are present */
+ if (w <= 0 || h <= 0 || maxval <= 0 || depth <= 0 || tuple_type[0] == '\0' || avcodec_check_dimensions(avctx, w, h))
+ return -1;
+
+ avctx->width = w;
+ avctx->height = h;
+ if (depth == 1) {
+ if (maxval == 1)
+ avctx->pix_fmt = PIX_FMT_MONOWHITE;
+ else
+ avctx->pix_fmt = PIX_FMT_GRAY8;
+ } else if (depth == 3) {
+ avctx->pix_fmt = PIX_FMT_RGB24;
+ } else if (depth == 4) {
+ avctx->pix_fmt = PIX_FMT_RGBA32;
+ } else {
+ return -1;
+ }
+ return 0;
+ } else {
+ return -1;
+ }
+ pnm_get(s, buf1, sizeof(buf1));
+ avctx->width = atoi(buf1);
+ if (avctx->width <= 0)
+ return -1;
+ pnm_get(s, buf1, sizeof(buf1));
+ avctx->height = atoi(buf1);
+ if(avcodec_check_dimensions(avctx, avctx->width, avctx->height))
+ return -1;
+ if (avctx->pix_fmt != PIX_FMT_MONOWHITE) {
+ pnm_get(s, buf1, sizeof(buf1));
+ if(atoi(buf1) == 65535 && avctx->pix_fmt == PIX_FMT_GRAY8)
+ avctx->pix_fmt = PIX_FMT_GRAY16BE;
+ }
+ /* more check if YUV420 */
+ if (avctx->pix_fmt == PIX_FMT_YUV420P) {
+ if ((avctx->width & 1) != 0)
+ return -1;
+ h = (avctx->height * 2);
+ if ((h % 3) != 0)
+ return -1;
+ h /= 3;
+ avctx->height = h;
+ }
+ return 0;
+}
+
+static int pnm_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ PNMContext * const s = avctx->priv_data;
+ AVFrame *picture = data;
+ AVFrame * const p= (AVFrame*)&s->picture;
+ int i, n, linesize, h;
+ unsigned char *ptr;
+
+ s->bytestream_start=
+ s->bytestream= buf;
+ s->bytestream_end= buf + buf_size;
+
+ if(pnm_decode_header(avctx, s) < 0)
+ return -1;
+
+ if(p->data[0])
+ avctx->release_buffer(avctx, p);
+
+ p->reference= 0;
+ if(avctx->get_buffer(avctx, p) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+ p->pict_type= FF_I_TYPE;
+ p->key_frame= 1;
+
+ switch(avctx->pix_fmt) {
+ default:
+ return -1;
+ case PIX_FMT_RGB24:
+ n = avctx->width * 3;
+ goto do_read;
+ case PIX_FMT_GRAY8:
+ n = avctx->width;
+ goto do_read;
+ case PIX_FMT_GRAY16BE:
+ n = avctx->width * 2;
+ goto do_read;
+ case PIX_FMT_MONOWHITE:
+ case PIX_FMT_MONOBLACK:
+ n = (avctx->width + 7) >> 3;
+ do_read:
+ ptr = p->data[0];
+ linesize = p->linesize[0];
+ if(s->bytestream + n*avctx->height > s->bytestream_end)
+ return -1;
+ for(i = 0; i < avctx->height; i++) {
+ memcpy(ptr, s->bytestream, n);
+ s->bytestream += n;
+ ptr += linesize;
+ }
+ break;
+ case PIX_FMT_YUV420P:
+ {
+ unsigned char *ptr1, *ptr2;
+
+ n = avctx->width;
+ ptr = p->data[0];
+ linesize = p->linesize[0];
+ if(s->bytestream + n*avctx->height*3/2 > s->bytestream_end)
+ return -1;
+ 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 PIX_FMT_RGBA32:
+ ptr = p->data[0];
+ linesize = p->linesize[0];
+ if(s->bytestream + avctx->width*avctx->height*4 > s->bytestream_end)
+ return -1;
+ for(i = 0; i < avctx->height; i++) {
+ int j, r, g, b, a;
+
+ for(j = 0;j < avctx->width; j++) {
+ r = *s->bytestream++;
+ g = *s->bytestream++;
+ b = *s->bytestream++;
+ a = *s->bytestream++;
+ ((uint32_t *)ptr)[j] = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ ptr += linesize;
+ }
+ break;
+ }
+ *picture= *(AVFrame*)&s->picture;
+ *data_size = sizeof(AVPicture);
+
+ return s->bytestream - s->bytestream_start;
+}
+
+static int pnm_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
+ PNMContext *s = avctx->priv_data;
+ AVFrame *pict = data;
+ AVFrame * const p= (AVFrame*)&s->picture;
+ int i, h, h1, c, n, linesize;
+ uint8_t *ptr, *ptr1, *ptr2;
+
+ if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){
+ av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n");
+ return -1;
+ }
+
+ *p = *pict;
+ p->pict_type= FF_I_TYPE;
+ p->key_frame= 1;
+
+ s->bytestream_start=
+ s->bytestream= outbuf;
+ s->bytestream_end= outbuf+buf_size;
+
+ h = avctx->height;
+ h1 = h;
+ switch(avctx->pix_fmt) {
+ case PIX_FMT_MONOWHITE:
+ c = '4';
+ n = (avctx->width + 7) >> 3;
+ break;
+ case PIX_FMT_GRAY8:
+ c = '5';
+ n = avctx->width;
+ break;
+ case PIX_FMT_GRAY16BE:
+ c = '5';
+ n = avctx->width * 2;
+ break;
+ case PIX_FMT_RGB24:
+ c = '6';
+ n = avctx->width * 3;
+ break;
+ case PIX_FMT_YUV420P:
+ c = '5';
+ n = avctx->width;
+ 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 != PIX_FMT_MONOWHITE) {
+ snprintf(s->bytestream, s->bytestream_end - s->bytestream,
+ "%d\n", (avctx->pix_fmt != PIX_FMT_GRAY16BE) ? 255 : 65535);
+ 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 == PIX_FMT_YUV420P) {
+ 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];
+ }
+ }
+ return s->bytestream - s->bytestream_start;
+}
+
+static int pam_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
+ PNMContext *s = avctx->priv_data;
+ AVFrame *pict = data;
+ AVFrame * const p= (AVFrame*)&s->picture;
+ int i, h, w, n, linesize, depth, maxval;
+ const char *tuple_type;
+ uint8_t *ptr;
+
+ if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){
+ av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n");
+ return -1;
+ }
+
+ *p = *pict;
+ p->pict_type= FF_I_TYPE;
+ p->key_frame= 1;
+
+ s->bytestream_start=
+ s->bytestream= outbuf;
+ s->bytestream_end= outbuf+buf_size;
+
+ h = avctx->height;
+ w = avctx->width;
+ switch(avctx->pix_fmt) {
+ case PIX_FMT_MONOWHITE:
+ n = (w + 7) >> 3;
+ depth = 1;
+ maxval = 1;
+ tuple_type = "BLACKANDWHITE";
+ break;
+ case PIX_FMT_GRAY8:
+ n = w;
+ depth = 1;
+ maxval = 255;
+ tuple_type = "GRAYSCALE";
+ break;
+ case PIX_FMT_RGB24:
+ n = w * 3;
+ depth = 3;
+ maxval = 255;
+ tuple_type = "RGB";
+ break;
+ case PIX_FMT_RGBA32:
+ n = w * 4;
+ depth = 4;
+ maxval = 255;
+ tuple_type = "RGB_ALPHA";
+ break;
+ default:
+ return -1;
+ }
+ snprintf(s->bytestream, s->bytestream_end - s->bytestream,
+ "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLETYPE %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 == PIX_FMT_RGBA32) {
+ int j;
+ unsigned int v;
+
+ for(i=0;i<h;i++) {
+ for(j=0;j<w;j++) {
+ v = ((uint32_t *)ptr)[j];
+ *s->bytestream++ = v >> 16;
+ *s->bytestream++ = v >> 8;
+ *s->bytestream++ = v;
+ *s->bytestream++ = v >> 24;
+ }
+ ptr += linesize;
+ }
+ } else {
+ for(i=0;i<h;i++) {
+ memcpy(s->bytestream, ptr, n);
+ s->bytestream += n;
+ ptr += linesize;
+ }
+ }
+ return s->bytestream - s->bytestream_start;
+}
+
+#if 0
+static int pnm_probe(AVProbeData *pd)
+{
+ const char *p = pd->buf;
+ if (pd->buf_size >= 8 &&
+ p[0] == 'P' &&
+ p[1] >= '4' && p[1] <= '6' &&
+ pnm_space(p[2]) )
+ return AVPROBE_SCORE_MAX - 1; /* to permit pgmyuv probe */
+ else
+ return 0;
+}
+
+static int pgmyuv_probe(AVProbeData *pd)
+{
+ if (match_ext(pd->filename, "pgmyuv"))
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+static int pam_probe(AVProbeData *pd)
+{
+ const char *p = pd->buf;
+ if (pd->buf_size >= 8 &&
+ p[0] == 'P' &&
+ p[1] == '7' &&
+ p[2] == '\n')
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_PNM_PARSER
+static int pnm_parse(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ 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(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, (uint8_t **)&buf, &buf_size)<0){
+ *poutbuf = NULL;
+ *poutbuf_size = 0;
+ return buf_size;
+ }
+ *poutbuf = (uint8_t *)buf;
+ *poutbuf_size = buf_size;
+ return next;
+}
+
+AVCodecParser pnm_parser = {
+ { CODEC_ID_PGM, CODEC_ID_PGMYUV, CODEC_ID_PPM, CODEC_ID_PBM, CODEC_ID_PAM},
+ sizeof(ParseContext),
+ NULL,
+ pnm_parse,
+ ff_parse_close,
+};
+#endif /* CONFIG_PNM_PARSER */
+
+#ifdef CONFIG_PGM_ENCODER
+AVCodec pgm_encoder = {
+ "pgm",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_PGM,
+ sizeof(PNMContext),
+ common_init,
+ pnm_encode_frame,
+ NULL, //encode_end,
+ pnm_decode_frame,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_GRAY8, PIX_FMT_GRAY16BE, -1},
+};
+#endif // CONFIG_PGM_ENCODER
+
+#ifdef CONFIG_PGMYUV_ENCODER
+AVCodec pgmyuv_encoder = {
+ "pgmyuv",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_PGMYUV,
+ sizeof(PNMContext),
+ common_init,
+ pnm_encode_frame,
+ NULL, //encode_end,
+ pnm_decode_frame,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+};
+#endif // CONFIG_PGMYUV_ENCODER
+
+#ifdef CONFIG_PPM_ENCODER
+AVCodec ppm_encoder = {
+ "ppm",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_PPM,
+ sizeof(PNMContext),
+ common_init,
+ pnm_encode_frame,
+ NULL, //encode_end,
+ pnm_decode_frame,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, -1},
+};
+#endif // CONFIG_PPM_ENCODER
+
+#ifdef CONFIG_PBM_ENCODER
+AVCodec pbm_encoder = {
+ "pbm",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_PBM,
+ sizeof(PNMContext),
+ common_init,
+ pnm_encode_frame,
+ NULL, //encode_end,
+ pnm_decode_frame,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_MONOWHITE, -1},
+};
+#endif // CONFIG_PBM_ENCODER
+
+#ifdef CONFIG_PAM_ENCODER
+AVCodec pam_encoder = {
+ "pam",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_PAM,
+ sizeof(PNMContext),
+ common_init,
+ pam_encode_frame,
+ NULL, //encode_end,
+ pnm_decode_frame,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGBA32, PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, -1},
+};
+#endif // CONFIG_PAM_ENCODER
diff --git a/contrib/ffmpeg/libavcodec/ppc/dsputil_altivec.c b/contrib/ffmpeg/libavcodec/ppc/dsputil_altivec.c
new file mode 100644
index 000000000..6f48893a4
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/dsputil_altivec.c
@@ -0,0 +1,1591 @@
+/*
+ * Copyright (c) 2002 Brian Foley
+ * Copyright (c) 2002 Dieter Shirley
+ * Copyright (c) 2003-2004 Romain Dolbeau <romain@dolbeau.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
+ */
+
+#include "../dsputil.h"
+
+#include "gcc_fixes.h"
+
+#include "dsputil_altivec.h"
+
+#ifdef CONFIG_DARWIN
+#include <sys/sysctl.h>
+#else /* CONFIG_DARWIN */
+#ifdef __AMIGAOS4__
+#include <exec/exec.h>
+#include <interfaces/exec.h>
+#include <proto/exec.h>
+#else /* __AMIGAOS4__ */
+#include <signal.h>
+#include <setjmp.h>
+
+static sigjmp_buf jmpbuf;
+static volatile sig_atomic_t canjump = 0;
+
+static void sigill_handler (int sig)
+{
+ if (!canjump) {
+ signal (sig, SIG_DFL);
+ raise (sig);
+ }
+
+ canjump = 0;
+ siglongjmp (jmpbuf, 1);
+}
+#endif /* CONFIG_DARWIN */
+#endif /* __AMIGAOS4__ */
+
+int sad16_x2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+{
+ int i;
+ int s __attribute__((aligned(16)));
+ const_vector unsigned char zero = (const_vector unsigned char)vec_splat_u8(0);
+ vector unsigned char *tv;
+ 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]
+ */
+ tv = (vector unsigned char *) pix1;
+ pix1v = vec_perm(tv[0], tv[1], vec_lvsl(0, pix1));
+
+ tv = (vector unsigned char *) &pix2[0];
+ pix2v = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix2[0]));
+
+ tv = (vector unsigned char *) &pix2[1];
+ pix2iv = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix2[1]));
+
+ /* 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;
+}
+
+int sad16_y2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+{
+ int i;
+ int s __attribute__((aligned(16)));
+ const_vector unsigned char zero = (const_vector unsigned char)vec_splat_u8(0);
+ vector unsigned char *tv;
+ 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
+ */
+ tv = (vector unsigned char *) &pix2[0];
+ pix2v = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix2[0]));
+
+ 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]
+ */
+ tv = (vector unsigned char *) pix1;
+ pix1v = vec_perm(tv[0], tv[1], vec_lvsl(0, pix1));
+
+ tv = (vector unsigned char *) &pix3[0];
+ pix3v = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix3[0]));
+
+ /* 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;
+}
+
+int sad16_xy2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+{
+ int i;
+ int s __attribute__((aligned(16)));
+ 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 *tv, avgv, t5;
+ 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
+ */
+ tv = (vector unsigned char *) &pix2[0];
+ pix2v = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix2[0]));
+
+ tv = (vector unsigned char *) &pix2[1];
+ pix2iv = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix2[1]));
+
+ 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]
+ */
+ tv = (vector unsigned char *) pix1;
+ pix1v = vec_perm(tv[0], tv[1], vec_lvsl(0, pix1));
+
+ tv = (vector unsigned char *) &pix3[0];
+ pix3v = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix3[0]));
+
+ tv = (vector unsigned char *) &pix3[1];
+ pix3iv = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix3[1]));
+
+ /*
+ 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;
+}
+
+int sad16_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+{
+ int i;
+ int s __attribute__((aligned(16)));
+ const_vector unsigned int zero = (const_vector unsigned int)vec_splat_u32(0);
+ vector unsigned char perm1, perm2, *pix1v, *pix2v;
+ 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 */
+ perm1 = vec_lvsl(0, pix1);
+ pix1v = (vector unsigned char *) pix1;
+ perm2 = vec_lvsl(0, pix2);
+ pix2v = (vector unsigned char *) pix2;
+ t1 = vec_perm(pix1v[0], pix1v[1], perm1);
+ t2 = vec_perm(pix2v[0], pix2v[1], perm2);
+
+ /* 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;
+}
+
+int sad8_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+{
+ int i;
+ int s __attribute__((aligned(16)));
+ const_vector unsigned int zero = (const_vector unsigned int)vec_splat_u32(0);
+ vector unsigned char perm1, perm2, permclear, *pix1v, *pix2v;
+ vector unsigned char t1, t2, t3,t4, t5;
+ vector unsigned int sad;
+ vector signed int sumdiffs;
+
+ sad = (vector unsigned int)vec_splat_u32(0);
+
+ permclear = (vector unsigned char)AVV(255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,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. */
+ perm1 = vec_lvsl(0, pix1);
+ pix1v = (vector unsigned char *) pix1;
+ perm2 = vec_lvsl(0, pix2);
+ pix2v = (vector unsigned char *) pix2;
+ t1 = vec_and(vec_perm(pix1v[0], pix1v[1], perm1), permclear);
+ t2 = vec_and(vec_perm(pix2v[0], pix2v[1], 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;
+}
+
+int pix_norm1_altivec(uint8_t *pix, int line_size)
+{
+ int i;
+ int s __attribute__((aligned(16)));
+ const_vector unsigned int zero = (const_vector unsigned int)vec_splat_u32(0);
+ vector unsigned char *tv;
+ 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 */
+ tv = (vector unsigned char *) pix;
+ pixv = vec_perm(tv[0], tv[1], vec_lvsl(0, pix));
+
+ /* 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.
+ */
+int sse8_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+{
+ int i;
+ int s __attribute__((aligned(16)));
+ const_vector unsigned int zero = (const_vector unsigned int)vec_splat_u32(0);
+ vector unsigned char perm1, perm2, permclear, *pix1v, *pix2v;
+ vector unsigned char t1, t2, t3,t4, t5;
+ vector unsigned int sum;
+ vector signed int sumsqr;
+
+ sum = (vector unsigned int)vec_splat_u32(0);
+
+ permclear = (vector unsigned char)AVV(255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,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. */
+ perm1 = vec_lvsl(0, pix1);
+ pix1v = (vector unsigned char *) pix1;
+ perm2 = vec_lvsl(0, pix2);
+ pix2v = (vector unsigned char *) pix2;
+ t1 = vec_and(vec_perm(pix1v[0], pix1v[1], perm1), permclear);
+ t2 = vec_and(vec_perm(pix2v[0], pix2v[1], 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.
+ */
+int sse16_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+{
+ int i;
+ int s __attribute__((aligned(16)));
+ const_vector unsigned int zero = (const_vector unsigned int)vec_splat_u32(0);
+ vector unsigned char perm1, perm2, *pix1v, *pix2v;
+ 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 */
+ perm1 = vec_lvsl(0, pix1);
+ pix1v = (vector unsigned char *) pix1;
+ perm2 = vec_lvsl(0, pix2);
+ pix2v = (vector unsigned char *) pix2;
+ t1 = vec_perm(pix1v[0], pix1v[1], perm1);
+ t2 = vec_perm(pix2v[0], pix2v[1], perm2);
+
+ /*
+ 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;
+}
+
+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, *pixv;
+ vector unsigned char t1;
+ vector unsigned int sad;
+ vector signed int sumdiffs;
+
+ int i;
+ int s __attribute__((aligned(16)));
+
+ sad = (vector unsigned int)vec_splat_u32(0);
+
+ for (i = 0; i < 16; i++) {
+ /* Read the potentially unaligned 16 pixels into t1 */
+ perm = vec_lvsl(0, pix);
+ pixv = (vector unsigned char *) pix;
+ t1 = vec_perm(pixv[0], pixv[1], 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;
+}
+
+void get_pixels_altivec(DCTELEM *restrict block, const uint8_t *pixels, int line_size)
+{
+ int i;
+ vector unsigned char perm, bytes, *pixv;
+ 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.
+ perm = vec_lvsl(0, pixels);
+ pixv = (vector unsigned char *) pixels;
+ bytes = vec_perm(pixv[0], pixv[1], 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;
+ }
+}
+
+void diff_pixels_altivec(DCTELEM *restrict block, const uint8_t *s1,
+ const uint8_t *s2, int stride)
+{
+ int i;
+ vector unsigned char perm, bytes, *pixv;
+ 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.
+ perm = vec_lvsl(0, s1);
+ pixv = (vector unsigned char *) s1;
+ bytes = vec_perm(pixv[0], pixv[1], perm);
+
+ // convert the bytes into shorts
+ shorts1 = (vector signed short)vec_mergeh(zero, bytes);
+
+ // Do the same for the second block of pixels
+ perm = vec_lvsl(0, s2);
+ pixv = (vector unsigned char *) s2;
+ bytes = vec_perm(pixv[0], pixv[1], perm);
+
+ // 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.
+ perm = vec_lvsl(0, s1);
+ pixv = (vector unsigned char *) s1;
+ bytes = vec_perm(pixv[0], pixv[1], perm);
+
+ // convert the bytes into shorts
+ shorts1 = (vector signed short)vec_mergeh(zero, bytes);
+
+ // Do the same for the second block of pixels
+ perm = vec_lvsl(0, s2);
+ pixv = (vector unsigned char *) s2;
+ bytes = vec_perm(pixv[0], pixv[1], perm);
+
+ // 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;
+ }
+}
+
+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];
+ }
+}
+
+/* next one assumes that ((line_size % 16) == 0) */
+void put_pixels16_altivec(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+POWERPC_PERF_DECLARE(altivec_put_pixels16_num, 1);
+ 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 int line_size_2 = line_size << 1;
+ register int line_size_3 = line_size + line_size_2;
+ register int line_size_4 = line_size << 2;
+
+POWERPC_PERF_START_COUNT(altivec_put_pixels16_num, 1);
+// 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
+#if 0
+ for(i=0; i<h; i++) {
+ pixelsv1 = vec_ld(0, (unsigned char*)pixels);
+ pixelsv2 = vec_ld(16, (unsigned char*)pixels);
+ vec_st(vec_perm(pixelsv1, pixelsv2, perm),
+ 0, (unsigned char*)block);
+ pixels+=line_size;
+ block +=line_size;
+ }
+#else
+ for(i=0; i<h; i+=4) {
+ pixelsv1 = vec_ld(0, (unsigned char*)pixels);
+ pixelsv2 = vec_ld(15, (unsigned char*)pixels);
+ pixelsv1B = vec_ld(line_size, (unsigned char*)pixels);
+ pixelsv2B = vec_ld(15 + line_size, (unsigned char*)pixels);
+ pixelsv1C = vec_ld(line_size_2, (unsigned char*)pixels);
+ pixelsv2C = vec_ld(15 + line_size_2, (unsigned char*)pixels);
+ pixelsv1D = vec_ld(line_size_3, (unsigned char*)pixels);
+ pixelsv2D = vec_ld(15 + line_size_3, (unsigned char*)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;
+ }
+#endif
+POWERPC_PERF_STOP_COUNT(altivec_put_pixels16_num, 1);
+}
+
+/* next one assumes that ((line_size % 16) == 0) */
+#define op_avg(a,b) a = ( ((a)|(b)) - ((((a)^(b))&0xFEFEFEFEUL)>>1) )
+void avg_pixels16_altivec(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+POWERPC_PERF_DECLARE(altivec_avg_pixels16_num, 1);
+ register vector unsigned char pixelsv1, pixelsv2, pixelsv, blockv;
+ register vector unsigned char perm = vec_lvsl(0, pixels);
+ int i;
+
+POWERPC_PERF_START_COUNT(altivec_avg_pixels16_num, 1);
+
+ for(i=0; i<h; i++) {
+ pixelsv1 = vec_ld(0, (unsigned char*)pixels);
+ pixelsv2 = vec_ld(16, (unsigned char*)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;
+ }
+
+POWERPC_PERF_STOP_COUNT(altivec_avg_pixels16_num, 1);
+}
+
+/* next one assumes that ((line_size % 8) == 0) */
+void avg_pixels8_altivec(uint8_t * block, const uint8_t * pixels, int line_size, int h)
+{
+POWERPC_PERF_DECLARE(altivec_avg_pixels8_num, 1);
+ register vector unsigned char pixelsv1, pixelsv2, pixelsv, blockv;
+ int i;
+
+POWERPC_PERF_START_COUNT(altivec_avg_pixels8_num, 1);
+
+ 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, (unsigned char*)pixels);
+ pixelsv2 = vec_ld(16, (unsigned char*)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;
+ }
+
+POWERPC_PERF_STOP_COUNT(altivec_avg_pixels8_num, 1);
+}
+
+/* next one assumes that ((line_size % 8) == 0) */
+void put_pixels8_xy2_altivec(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+POWERPC_PERF_DECLARE(altivec_put_pixels8_xy2_num, 1);
+ 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);
+
+POWERPC_PERF_START_COUNT(altivec_put_pixels8_xy2_num, 1);
+ 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;
+ }
+
+POWERPC_PERF_STOP_COUNT(altivec_put_pixels8_xy2_num, 1);
+}
+
+/* next one assumes that ((line_size % 8) == 0) */
+void put_no_rnd_pixels8_xy2_altivec(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+POWERPC_PERF_DECLARE(altivec_put_no_rnd_pixels8_xy2_num, 1);
+ 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);
+
+POWERPC_PERF_START_COUNT(altivec_put_no_rnd_pixels8_xy2_num, 1);
+ 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;
+ }
+
+POWERPC_PERF_STOP_COUNT(altivec_put_no_rnd_pixels8_xy2_num, 1);
+}
+
+/* next one assumes that ((line_size % 16) == 0) */
+void put_pixels16_xy2_altivec(uint8_t * block, const uint8_t * pixels, int line_size, int h)
+{
+POWERPC_PERF_DECLARE(altivec_put_pixels16_xy2_num, 1);
+ register int i;
+ register vector unsigned char
+ pixelsv1, pixelsv2, pixelsv3, pixelsv4;
+ register vector unsigned char
+ blockv, temp1, temp2;
+ register vector unsigned short
+ pixelssum1, pixelssum2, temp3,
+ pixelssum3, pixelssum4, temp4;
+ 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);
+
+POWERPC_PERF_START_COUNT(altivec_put_pixels16_xy2_num, 1);
+
+ 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;
+ }
+
+POWERPC_PERF_STOP_COUNT(altivec_put_pixels16_xy2_num, 1);
+}
+
+/* next one assumes that ((line_size % 16) == 0) */
+void put_no_rnd_pixels16_xy2_altivec(uint8_t * block, const uint8_t * pixels, int line_size, int h)
+{
+POWERPC_PERF_DECLARE(altivec_put_no_rnd_pixels16_xy2_num, 1);
+ register int i;
+ register vector unsigned char
+ pixelsv1, pixelsv2, pixelsv3, pixelsv4;
+ register vector unsigned char
+ blockv, temp1, temp2;
+ register vector unsigned short
+ pixelssum1, pixelssum2, temp3,
+ pixelssum3, pixelssum4, temp4;
+ 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);
+
+POWERPC_PERF_START_COUNT(altivec_put_no_rnd_pixels16_xy2_num, 1);
+
+ 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;
+ }
+
+POWERPC_PERF_STOP_COUNT(altivec_put_no_rnd_pixels16_xy2_num, 1);
+}
+
+int hadamard8_diff8x8_altivec(/*MpegEncContext*/ void *s, uint8_t *dst, uint8_t *src, int stride, int h){
+POWERPC_PERF_DECLARE(altivec_hadamard8_diff8x8_num, 1);
+ 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;
+POWERPC_PERF_START_COUNT(altivec_hadamard8_diff8x8_num, 1);
+ {
+ register const_vector signed short vprod1 =(const_vector signed short)
+ AVV( 1,-1, 1,-1, 1,-1, 1,-1);
+ register const_vector signed short vprod2 =(const_vector signed short)
+ AVV( 1, 1,-1,-1, 1, 1,-1,-1);
+ register const_vector signed short vprod3 =(const_vector signed short)
+ AVV( 1, 1, 1, 1,-1,-1,-1,-1);
+ register const_vector unsigned char perm1 = (const_vector unsigned char)
+ AVV(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)
+ AVV(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)
+ AVV(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); \
+ if ((((stride * i) + (unsigned long)src) & 0x0000000F) > 8) \
+ src2 = vec_ld((stride * i) + 16, src); \
+ srcO = vec_perm(src1, src2, vec_lvsl(stride * i, src)); \
+ dst1 = vec_ld(stride * i, dst); \
+ if ((((stride * i) + (unsigned long)dst) & 0x0000000F) > 8) \
+ dst2 = vec_ld((stride * i) + 16, 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); \
+ /* substractions 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);
+ }
+POWERPC_PERF_STOP_COUNT(altivec_hadamard8_diff8x8_num, 1);
+ 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 (arount 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 REG_v(v0),
+ temp1 REG_v(v1),
+ temp2 REG_v(v2),
+ temp3 REG_v(v3),
+ temp4 REG_v(v4),
+ temp5 REG_v(v5),
+ temp6 REG_v(v6),
+ temp7 REG_v(v7);
+ register vector signed short
+ temp0S REG_v(v8),
+ temp1S REG_v(v9),
+ temp2S REG_v(v10),
+ temp3S REG_v(v11),
+ temp4S REG_v(v12),
+ temp5S REG_v(v13),
+ temp6S REG_v(v14),
+ temp7S REG_v(v15);
+ register const_vector unsigned char vzero REG_v(v31)=
+ (const_vector unsigned char)vec_splat_u8(0);
+ {
+ register const_vector signed short vprod1 REG_v(v16)=
+ (const_vector signed short)AVV( 1,-1, 1,-1, 1,-1, 1,-1);
+ register const_vector signed short vprod2 REG_v(v17)=
+ (const_vector signed short)AVV( 1, 1,-1,-1, 1, 1,-1,-1);
+ register const_vector signed short vprod3 REG_v(v18)=
+ (const_vector signed short)AVV( 1, 1, 1, 1,-1,-1,-1,-1);
+ register const_vector unsigned char perm1 REG_v(v19)=
+ (const_vector unsigned char)
+ AVV(0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05,
+ 0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D);
+ register const_vector unsigned char perm2 REG_v(v20)=
+ (const_vector unsigned char)
+ AVV(0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x08, 0x09, 0x0A, 0x0B);
+ register const_vector unsigned char perm3 REG_v(v21)=
+ (const_vector unsigned char)
+ AVV(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 REG_v(v22), \
+ src2 REG_v(v23), \
+ dst1 REG_v(v24), \
+ dst2 REG_v(v25), \
+ srcO REG_v(v22), \
+ dstO REG_v(v23); \
+ \
+ register vector signed short srcV REG_v(v24), \
+ dstV REG_v(v25), \
+ srcW REG_v(v26), \
+ dstW REG_v(v27), \
+ but0 REG_v(v28), \
+ but0S REG_v(v29), \
+ op1 REG_v(v30), \
+ but1 REG_v(v22), \
+ op1S REG_v(v23), \
+ but1S REG_v(v24), \
+ op2 REG_v(v25), \
+ but2 REG_v(v26), \
+ op2S REG_v(v27), \
+ but2S REG_v(v28), \
+ op3 REG_v(v29), \
+ op3S REG_v(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); \
+ /* substractions 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;
+}
+
+int hadamard8_diff16_altivec(/*MpegEncContext*/ void *s, uint8_t *dst, uint8_t *src, int stride, int h){
+POWERPC_PERF_DECLARE(altivec_hadamard8_diff16_num, 1);
+ int score;
+POWERPC_PERF_START_COUNT(altivec_hadamard8_diff16_num, 1);
+ 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);
+ }
+POWERPC_PERF_STOP_COUNT(altivec_hadamard8_diff16_num, 1);
+ return score;
+}
+
+int has_altivec(void)
+{
+#ifdef __AMIGAOS4__
+ ULONG result = 0;
+ extern struct ExecIFace *IExec;
+
+ IExec->GetCPUInfoTags(GCIT_VectorUnit, &result, TAG_DONE);
+ if (result == VECTORTYPE_ALTIVEC) return 1;
+ return 0;
+#else /* __AMIGAOS4__ */
+
+#ifdef CONFIG_DARWIN
+ int sels[2] = {CTL_HW, HW_VECTORUNIT};
+ int has_vu = 0;
+ size_t len = sizeof(has_vu);
+ int err;
+
+ err = sysctl(sels, 2, &has_vu, &len, NULL, 0);
+
+ if (err == 0) return (has_vu != 0);
+#else /* CONFIG_DARWIN */
+/* no Darwin, do it the brute-force way */
+/* this is borrowed from the libmpeg2 library */
+ {
+ signal (SIGILL, sigill_handler);
+ if (sigsetjmp (jmpbuf, 1)) {
+ signal (SIGILL, SIG_DFL);
+ } else {
+ canjump = 1;
+
+ asm volatile ("mtspr 256, %0\n\t"
+ "vand %%v0, %%v0, %%v0"
+ :
+ : "r" (-1));
+
+ signal (SIGILL, SIG_DFL);
+ return 1;
+ }
+ }
+#endif /* CONFIG_DARWIN */
+ return 0;
+#endif /* __AMIGAOS4__ */
+}
+
+static void vorbis_inverse_coupling_altivec(float *mag, float *ang,
+ int 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);
+ }
+}
+
+/* next one assumes that ((line_size % 8) == 0) */
+void avg_pixels8_xy2_altivec(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+POWERPC_PERF_DECLARE(altivec_avg_pixels8_xy2_num, 1);
+ 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);
+
+POWERPC_PERF_START_COUNT(altivec_avg_pixels8_xy2_num, 1);
+ 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;
+ }
+
+POWERPC_PERF_STOP_COUNT(altivec_avg_pixels8_xy2_num, 1);
+}
+
+void dsputil_init_altivec(DSPContext* c, AVCodecContext *avctx)
+{
+ 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->get_pixels = get_pixels_altivec;
+ c->add_bytes= add_bytes_altivec;
+ c->put_pixels_tab[0][0] = put_pixels16_altivec;
+ /* the two functions do the same thing, so use the same code */
+ c->put_no_rnd_pixels_tab[0][0] = put_pixels16_altivec;
+ c->avg_pixels_tab[0][0] = 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;
+
+ c->hadamard8_diff[0] = hadamard8_diff16_altivec;
+ c->hadamard8_diff[1] = hadamard8_diff8x8_altivec;
+#ifdef CONFIG_VORBIS_DECODER
+ c->vorbis_inverse_coupling = vorbis_inverse_coupling_altivec;
+#endif
+}
diff --git a/contrib/ffmpeg/libavcodec/ppc/dsputil_altivec.h b/contrib/ffmpeg/libavcodec/ppc/dsputil_altivec.h
new file mode 100644
index 000000000..560d778bb
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/dsputil_altivec.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2002 Brian Foley
+ * Copyright (c) 2002 Dieter Shirley
+ * Copyright (c) 2003-2004 Romain Dolbeau <romain@dolbeau.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
+ */
+
+#ifndef _DSPUTIL_ALTIVEC_
+#define _DSPUTIL_ALTIVEC_
+
+#include "dsputil_ppc.h"
+
+#ifdef HAVE_ALTIVEC
+
+extern int has_altivec(void);
+
+void put_pixels16_altivec(uint8_t *block, const uint8_t *pixels, int line_size, int h);
+
+void avg_pixels16_altivec(uint8_t *block, const uint8_t *pixels, int line_size, int h);
+
+// used to build registers permutation vectors (vcprm)
+// the 's' are for words in the _s_econd vector
+#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
+
+#ifdef CONFIG_DARWIN
+#define vcprm(a,b,c,d) (const vector unsigned char)(WORD_ ## a, WORD_ ## b, WORD_ ## c, WORD_ ## d)
+#else
+#define vcprm(a,b,c,d) (const vector unsigned char){WORD_ ## a, WORD_ ## b, WORD_ ## c, WORD_ ## d}
+#endif
+
+// vcprmle is used to keep the same index as in the SSE version.
+// it's the same as vcprm, with the index inversed
+// ('le' is Little Endian)
+#define vcprmle(a,b,c,d) vcprm(d,c,b,a)
+
+// used to build inverse/identity vectors (vcii)
+// n is _n_egative, p is _p_ositive
+#define FLOAT_n -1.
+#define FLOAT_p 1.
+
+
+#ifdef CONFIG_DARWIN
+#define vcii(a,b,c,d) (const vector float)(FLOAT_ ## a, FLOAT_ ## b, FLOAT_ ## c, FLOAT_ ## d)
+#else
+#define vcii(a,b,c,d) (const vector float){FLOAT_ ## a, FLOAT_ ## b, FLOAT_ ## c, FLOAT_ ## d}
+#endif
+
+// Transpose 8x8 matrix of 16-bit elements (in-place)
+#define TRANSPOSE8(a,b,c,d,e,f,g,h) \
+do { \
+ vector signed short A1, B1, C1, D1, E1, F1, G1, H1; \
+ vector signed short A2, B2, C2, D2, E2, F2, G2, H2; \
+ \
+ A1 = vec_mergeh (a, e); \
+ B1 = vec_mergel (a, e); \
+ C1 = vec_mergeh (b, f); \
+ D1 = vec_mergel (b, f); \
+ E1 = vec_mergeh (c, g); \
+ F1 = vec_mergel (c, g); \
+ G1 = vec_mergeh (d, h); \
+ H1 = vec_mergel (d, h); \
+ \
+ A2 = vec_mergeh (A1, E1); \
+ B2 = vec_mergel (A1, E1); \
+ C2 = vec_mergeh (B1, F1); \
+ D2 = vec_mergel (B1, F1); \
+ E2 = vec_mergeh (C1, G1); \
+ F2 = vec_mergel (C1, G1); \
+ G2 = vec_mergeh (D1, H1); \
+ H2 = vec_mergel (D1, H1); \
+ \
+ a = vec_mergeh (A2, E2); \
+ b = vec_mergel (A2, E2); \
+ c = vec_mergeh (B2, F2); \
+ d = vec_mergel (B2, F2); \
+ e = vec_mergeh (C2, G2); \
+ f = vec_mergel (C2, G2); \
+ g = vec_mergeh (D2, H2); \
+ h = vec_mergel (D2, H2); \
+} while (0)
+
+#endif /* HAVE_ALTIVEC */
+
+#endif /* _DSPUTIL_ALTIVEC_ */
diff --git a/contrib/ffmpeg/libavcodec/ppc/dsputil_ppc.c b/contrib/ffmpeg/libavcodec/ppc/dsputil_ppc.c
new file mode 100644
index 000000000..9169eaef0
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/dsputil_ppc.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2002 Brian Foley
+ * Copyright (c) 2002 Dieter Shirley
+ * Copyright (c) 2003-2004 Romain Dolbeau <romain@dolbeau.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
+ */
+
+#include "../dsputil.h"
+
+#include "dsputil_ppc.h"
+
+#ifdef HAVE_ALTIVEC
+#include "dsputil_altivec.h"
+
+extern void fdct_altivec(int16_t *block);
+extern void gmc1_altivec(uint8_t *dst, uint8_t *src, int stride, int h,
+ int x16, int y16, int rounder);
+extern void idct_put_altivec(uint8_t *dest, int line_size, int16_t *block);
+extern void idct_add_altivec(uint8_t *dest, int line_size, int16_t *block);
+
+void dsputil_h264_init_ppc(DSPContext* c, AVCodecContext *avctx);
+
+void dsputil_init_altivec(DSPContext* c, AVCodecContext *avctx);
+void vc1dsp_init_altivec(DSPContext* c, AVCodecContext *avctx);
+void snow_init_altivec(DSPContext* c, AVCodecContext *avctx);
+void float_init_altivec(DSPContext* c, AVCodecContext *avctx);
+
+#endif
+
+int mm_flags = 0;
+
+int mm_support(void)
+{
+ int result = 0;
+#ifdef HAVE_ALTIVEC
+ if (has_altivec()) {
+ result |= MM_ALTIVEC;
+ }
+#endif /* result */
+ return result;
+}
+
+#ifdef POWERPC_PERFORMANCE_REPORT
+unsigned long long perfdata[POWERPC_NUM_PMC_ENABLED][powerpc_perf_total][powerpc_data_total];
+/* list below must match enum in dsputil_ppc.h */
+static unsigned char* perfname[] = {
+ "ff_fft_calc_altivec",
+ "gmc1_altivec",
+ "dct_unquantize_h263_altivec",
+ "fdct_altivec",
+ "idct_add_altivec",
+ "idct_put_altivec",
+ "put_pixels16_altivec",
+ "avg_pixels16_altivec",
+ "avg_pixels8_altivec",
+ "put_pixels8_xy2_altivec",
+ "put_no_rnd_pixels8_xy2_altivec",
+ "put_pixels16_xy2_altivec",
+ "put_no_rnd_pixels16_xy2_altivec",
+ "hadamard8_diff8x8_altivec",
+ "hadamard8_diff16_altivec",
+ "avg_pixels8_xy2_altivec",
+ "clear_blocks_dcbz32_ppc",
+ "clear_blocks_dcbz128_ppc",
+ "put_h264_chroma_mc8_altivec",
+ "avg_h264_chroma_mc8_altivec",
+ "put_h264_qpel16_h_lowpass_altivec",
+ "avg_h264_qpel16_h_lowpass_altivec",
+ "put_h264_qpel16_v_lowpass_altivec",
+ "avg_h264_qpel16_v_lowpass_altivec",
+ "put_h264_qpel16_hv_lowpass_altivec",
+ "avg_h264_qpel16_hv_lowpass_altivec",
+ ""
+};
+#include <stdio.h>
+#endif
+
+#ifdef POWERPC_PERFORMANCE_REPORT
+void powerpc_display_perf_report(void)
+{
+ int i, j;
+ av_log(NULL, AV_LOG_INFO, "PowerPC performance report\n Values are from the PMC registers, and represent whatever the registers are set to record.\n");
+ for(i = 0 ; i < powerpc_perf_total ; i++)
+ {
+ for (j = 0; j < POWERPC_NUM_PMC_ENABLED ; j++)
+ {
+ if (perfdata[j][i][powerpc_data_num] != (unsigned long long)0)
+ av_log(NULL, AV_LOG_INFO,
+ " Function \"%s\" (pmc%d):\n\tmin: %"PRIu64"\n\tmax: %"PRIu64"\n\tavg: %1.2lf (%"PRIu64")\n",
+ perfname[i],
+ j+1,
+ perfdata[j][i][powerpc_data_min],
+ perfdata[j][i][powerpc_data_max],
+ (double)perfdata[j][i][powerpc_data_sum] /
+ (double)perfdata[j][i][powerpc_data_num],
+ perfdata[j][i][powerpc_data_num]);
+ }
+ }
+}
+#endif /* POWERPC_PERFORMANCE_REPORT */
+
+/* ***** 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 <http://developer.apple.com/technotes/tn/tn2087.html>
+ and <http://developer.apple.com/technotes/tn/tn2086.html>
+*/
+void clear_blocks_dcbz32_ppc(DCTELEM *blocks)
+{
+POWERPC_PERF_DECLARE(powerpc_clear_blocks_dcbz32, 1);
+ register int misal = ((unsigned long)blocks & 0x00000010);
+ register int i = 0;
+POWERPC_PERF_START_COUNT(powerpc_clear_blocks_dcbz32, 1);
+#if 1
+ 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(DCTELEM)*6*64-31 ; i += 32) {
+#ifndef __MWERKS__
+ asm volatile("dcbz %0,%1" : : "b" (blocks), "r" (i) : "memory");
+#else
+ __dcbz( blocks, i );
+#endif
+ }
+ if (misal) {
+ ((unsigned long*)blocks)[188] = 0L;
+ ((unsigned long*)blocks)[189] = 0L;
+ ((unsigned long*)blocks)[190] = 0L;
+ ((unsigned long*)blocks)[191] = 0L;
+ i += 16;
+ }
+#else
+ memset(blocks, 0, sizeof(DCTELEM)*6*64);
+#endif
+POWERPC_PERF_STOP_COUNT(powerpc_clear_blocks_dcbz32, 1);
+}
+
+/* same as above, when dcbzl clear a whole 128B cache line
+ i.e. the PPC970 aka G5 */
+#ifdef HAVE_DCBZL
+void clear_blocks_dcbz128_ppc(DCTELEM *blocks)
+{
+POWERPC_PERF_DECLARE(powerpc_clear_blocks_dcbz128, 1);
+ register int misal = ((unsigned long)blocks & 0x0000007f);
+ register int i = 0;
+POWERPC_PERF_START_COUNT(powerpc_clear_blocks_dcbz128, 1);
+#if 1
+ 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(DCTELEM)*6*64);
+ }
+ else
+ for ( ; i < sizeof(DCTELEM)*6*64 ; i += 128) {
+ asm volatile("dcbzl %0,%1" : : "b" (blocks), "r" (i) : "memory");
+ }
+#else
+ memset(blocks, 0, sizeof(DCTELEM)*6*64);
+#endif
+POWERPC_PERF_STOP_COUNT(powerpc_clear_blocks_dcbz128, 1);
+}
+#else
+void clear_blocks_dcbz128_ppc(DCTELEM *blocks)
+{
+ memset(blocks, 0, sizeof(DCTELEM)*6*64);
+}
+#endif
+
+#ifdef 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 ... */
+long check_dcbzl_effect(void)
+{
+ register char *fakedata = (char*)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
+long check_dcbzl_effect(void)
+{
+ return 0;
+}
+#endif
+
+static void prefetch_ppc(void *mem, int stride, int h)
+{
+ register const uint8_t *p = mem;
+ do {
+ asm volatile ("dcbt 0,%0" : : "r" (p));
+ p+= stride;
+ } while(--h);
+}
+
+void dsputil_init_ppc(DSPContext* c, AVCodecContext *avctx)
+{
+ // Common optimizations whether Altivec is available or not
+ c->prefetch = prefetch_ppc;
+ 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;
+ }
+
+#ifdef HAVE_ALTIVEC
+ if(ENABLE_H264_DECODER) dsputil_h264_init_ppc(c, avctx);
+
+ if (has_altivec()) {
+ mm_flags |= MM_ALTIVEC;
+
+ dsputil_init_altivec(c, avctx);
+ if(ENABLE_SNOW_DECODER) snow_init_altivec(c, avctx);
+ if(ENABLE_VC1_DECODER || ENABLE_WMV3_DECODER)
+ vc1dsp_init_altivec(c, avctx);
+ float_init_altivec(c, avctx);
+ c->gmc1 = gmc1_altivec;
+
+#ifdef CONFIG_ENCODERS
+ if (avctx->dct_algo == FF_DCT_AUTO ||
+ avctx->dct_algo == FF_DCT_ALTIVEC)
+ {
+ c->fdct = fdct_altivec;
+ }
+#endif //CONFIG_ENCODERS
+
+ if (avctx->lowres==0)
+ {
+ if ((avctx->idct_algo == FF_IDCT_AUTO) ||
+ (avctx->idct_algo == FF_IDCT_ALTIVEC))
+ {
+ c->idct_put = idct_put_altivec;
+ c->idct_add = idct_add_altivec;
+ c->idct_permutation_type = FF_TRANSPOSE_IDCT_PERM;
+ }
+ }
+
+#ifdef POWERPC_PERFORMANCE_REPORT
+ {
+ int i, j;
+ for (i = 0 ; i < powerpc_perf_total ; i++)
+ {
+ for (j = 0; j < POWERPC_NUM_PMC_ENABLED ; j++)
+ {
+ perfdata[j][i][powerpc_data_min] = 0xFFFFFFFFFFFFFFFFULL;
+ perfdata[j][i][powerpc_data_max] = 0x0000000000000000ULL;
+ perfdata[j][i][powerpc_data_sum] = 0x0000000000000000ULL;
+ perfdata[j][i][powerpc_data_num] = 0x0000000000000000ULL;
+ }
+ }
+ }
+#endif /* POWERPC_PERFORMANCE_REPORT */
+ }
+#endif /* HAVE_ALTIVEC */
+}
diff --git a/contrib/ffmpeg/libavcodec/ppc/dsputil_ppc.h b/contrib/ffmpeg/libavcodec/ppc/dsputil_ppc.h
new file mode 100644
index 000000000..ab2b05780
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/dsputil_ppc.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2003-2004 Romain Dolbeau <romain@dolbeau.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
+ */
+
+#ifndef _DSPUTIL_PPC_
+#define _DSPUTIL_PPC_
+
+#ifdef POWERPC_PERFORMANCE_REPORT
+void powerpc_display_perf_report(void);
+/* the 604* have 2, the G3* have 4, the G4s have 6,
+ and the G5 are completely different (they MUST use
+ POWERPC_MODE_64BITS, and let's hope all future 64 bis PPC
+ will use the same PMCs... */
+#define POWERPC_NUM_PMC_ENABLED 6
+/* if you add to the enum below, also add to the perfname array
+ in dsputil_ppc.c */
+enum powerpc_perf_index {
+ altivec_fft_num = 0,
+ altivec_gmc1_num,
+ altivec_dct_unquantize_h263_num,
+ altivec_fdct,
+ altivec_idct_add_num,
+ altivec_idct_put_num,
+ altivec_put_pixels16_num,
+ altivec_avg_pixels16_num,
+ altivec_avg_pixels8_num,
+ altivec_put_pixels8_xy2_num,
+ altivec_put_no_rnd_pixels8_xy2_num,
+ altivec_put_pixels16_xy2_num,
+ altivec_put_no_rnd_pixels16_xy2_num,
+ altivec_hadamard8_diff8x8_num,
+ altivec_hadamard8_diff16_num,
+ altivec_avg_pixels8_xy2_num,
+ powerpc_clear_blocks_dcbz32,
+ powerpc_clear_blocks_dcbz128,
+ altivec_put_h264_chroma_mc8_num,
+ altivec_avg_h264_chroma_mc8_num,
+ altivec_put_h264_qpel16_h_lowpass_num,
+ altivec_avg_h264_qpel16_h_lowpass_num,
+ altivec_put_h264_qpel16_v_lowpass_num,
+ altivec_avg_h264_qpel16_v_lowpass_num,
+ altivec_put_h264_qpel16_hv_lowpass_num,
+ altivec_avg_h264_qpel16_hv_lowpass_num,
+ powerpc_perf_total
+};
+enum powerpc_data_index {
+ powerpc_data_min = 0,
+ powerpc_data_max,
+ powerpc_data_sum,
+ powerpc_data_num,
+ powerpc_data_total
+};
+extern unsigned long long perfdata[POWERPC_NUM_PMC_ENABLED][powerpc_perf_total][powerpc_data_total];
+
+#ifndef POWERPC_MODE_64BITS
+#define POWERP_PMC_DATATYPE unsigned long
+#define POWERPC_GET_PMC1(a) asm volatile("mfspr %0, 937" : "=r" (a))
+#define POWERPC_GET_PMC2(a) asm volatile("mfspr %0, 938" : "=r" (a))
+#if (POWERPC_NUM_PMC_ENABLED > 2)
+#define POWERPC_GET_PMC3(a) asm volatile("mfspr %0, 941" : "=r" (a))
+#define POWERPC_GET_PMC4(a) asm volatile("mfspr %0, 942" : "=r" (a))
+#else
+#define POWERPC_GET_PMC3(a) do {} while (0)
+#define POWERPC_GET_PMC4(a) do {} while (0)
+#endif
+#if (POWERPC_NUM_PMC_ENABLED > 4)
+#define POWERPC_GET_PMC5(a) asm volatile("mfspr %0, 929" : "=r" (a))
+#define POWERPC_GET_PMC6(a) asm volatile("mfspr %0, 930" : "=r" (a))
+#else
+#define POWERPC_GET_PMC5(a) do {} while (0)
+#define POWERPC_GET_PMC6(a) do {} while (0)
+#endif
+#else /* POWERPC_MODE_64BITS */
+#define POWERP_PMC_DATATYPE unsigned long long
+#define POWERPC_GET_PMC1(a) asm volatile("mfspr %0, 771" : "=r" (a))
+#define POWERPC_GET_PMC2(a) asm volatile("mfspr %0, 772" : "=r" (a))
+#if (POWERPC_NUM_PMC_ENABLED > 2)
+#define POWERPC_GET_PMC3(a) asm volatile("mfspr %0, 773" : "=r" (a))
+#define POWERPC_GET_PMC4(a) asm volatile("mfspr %0, 774" : "=r" (a))
+#else
+#define POWERPC_GET_PMC3(a) do {} while (0)
+#define POWERPC_GET_PMC4(a) do {} while (0)
+#endif
+#if (POWERPC_NUM_PMC_ENABLED > 4)
+#define POWERPC_GET_PMC5(a) asm volatile("mfspr %0, 775" : "=r" (a))
+#define POWERPC_GET_PMC6(a) asm volatile("mfspr %0, 776" : "=r" (a))
+#else
+#define POWERPC_GET_PMC5(a) do {} while (0)
+#define POWERPC_GET_PMC6(a) do {} while (0)
+#endif
+#endif /* POWERPC_MODE_64BITS */
+#define POWERPC_PERF_DECLARE(a, cond) \
+ POWERP_PMC_DATATYPE \
+ pmc_start[POWERPC_NUM_PMC_ENABLED], \
+ pmc_stop[POWERPC_NUM_PMC_ENABLED], \
+ pmc_loop_index;
+#define POWERPC_PERF_START_COUNT(a, cond) do { \
+ POWERPC_GET_PMC6(pmc_start[5]); \
+ POWERPC_GET_PMC5(pmc_start[4]); \
+ POWERPC_GET_PMC4(pmc_start[3]); \
+ POWERPC_GET_PMC3(pmc_start[2]); \
+ POWERPC_GET_PMC2(pmc_start[1]); \
+ POWERPC_GET_PMC1(pmc_start[0]); \
+ } while (0)
+#define POWERPC_PERF_STOP_COUNT(a, cond) do { \
+ POWERPC_GET_PMC1(pmc_stop[0]); \
+ POWERPC_GET_PMC2(pmc_stop[1]); \
+ POWERPC_GET_PMC3(pmc_stop[2]); \
+ POWERPC_GET_PMC4(pmc_stop[3]); \
+ POWERPC_GET_PMC5(pmc_stop[4]); \
+ POWERPC_GET_PMC6(pmc_stop[5]); \
+ if (cond) \
+ { \
+ for(pmc_loop_index = 0; \
+ pmc_loop_index < POWERPC_NUM_PMC_ENABLED; \
+ pmc_loop_index++) \
+ { \
+ if (pmc_stop[pmc_loop_index] >= pmc_start[pmc_loop_index]) \
+ { \
+ POWERP_PMC_DATATYPE diff = \
+ pmc_stop[pmc_loop_index] - pmc_start[pmc_loop_index]; \
+ if (diff < perfdata[pmc_loop_index][a][powerpc_data_min]) \
+ perfdata[pmc_loop_index][a][powerpc_data_min] = diff; \
+ if (diff > perfdata[pmc_loop_index][a][powerpc_data_max]) \
+ perfdata[pmc_loop_index][a][powerpc_data_max] = diff; \
+ perfdata[pmc_loop_index][a][powerpc_data_sum] += diff; \
+ perfdata[pmc_loop_index][a][powerpc_data_num] ++; \
+ } \
+ } \
+ } \
+} while (0)
+#else /* POWERPC_PERFORMANCE_REPORT */
+// those are needed to avoid empty statements.
+#define POWERPC_PERF_DECLARE(a, cond) int altivec_placeholder __attribute__ ((unused))
+#define POWERPC_PERF_START_COUNT(a, cond) do {} while (0)
+#define POWERPC_PERF_STOP_COUNT(a, cond) do {} while (0)
+#endif /* POWERPC_PERFORMANCE_REPORT */
+
+#endif /* _DSPUTIL_PPC_ */
diff --git a/contrib/ffmpeg/libavcodec/ppc/fdct_altivec.c b/contrib/ffmpeg/libavcodec/ppc/fdct_altivec.c
new file mode 100644
index 000000000..2418c32bb
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/fdct_altivec.c
@@ -0,0 +1,493 @@
+/* ffmpeg/libavcodec/ppc/fdct_altivec.c, this file is part of the
+ * AltiVec optimized library for the FFMPEG Multimedia System
+ * Copyright (C) 2003 James Klicman <james@klicman.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
+ */
+
+
+#include "common.h"
+#include "../dsputil.h"
+#include "dsputil_altivec.h"
+#include "gcc_fixes.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] = {
+ (vector float)AVV( W0, W1, W2, W3 ),
+ (vector float)AVV( W4, W5, W6, W7 ),
+ (vector float)AVV( 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 fdct_altivec(int16_t *block)
+{
+POWERPC_PERF_DECLARE(altivec_fdct, 1);
+ 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;
+
+ POWERPC_PERF_START_COUNT(altivec_fdct, 1);
+
+
+ /* 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.
+ */
+#if 1
+ /* 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);
+ /* }}} */
+#else
+ /* convert to float {{{ */
+#define CTF(n) \
+ vs32(b##n##1) = vec_unpackl(vs16(b##n##0)); \
+ vs32(b##n##0) = 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); \
+
+ CTF(0);
+ CTF(1);
+ CTF(2);
+ CTF(3);
+ CTF(4);
+ CTF(5);
+ CTF(6);
+ CTF(7);
+
+#undef CTF
+ /* }}} */
+
+ FDCTROW(b00, b10, b20, b30, b40, b50, b60, b70);
+ FDCTROW(b01, b11, b21, b31, b41, b51, b61, b71);
+#endif
+
+
+ /* 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
+ /* }}} */
+
+POWERPC_PERF_STOP_COUNT(altivec_fdct, 1);
+}
+
+/* vim:set foldmethod=marker foldlevel=0: */
diff --git a/contrib/ffmpeg/libavcodec/ppc/fft_altivec.c b/contrib/ffmpeg/libavcodec/ppc/fft_altivec.c
new file mode 100644
index 000000000..384a774ff
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/fft_altivec.c
@@ -0,0 +1,166 @@
+/*
+ * FFT/IFFT transforms
+ * AltiVec-enabled
+ * Copyright (c) 2003 Romain Dolbeau <romain@dolbeau.org>
+ * Based on code 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 "../dsputil.h"
+
+#include "gcc_fixes.h"
+
+#include "dsputil_altivec.h"
+
+/*
+ those three macros are from libavcodec/fft.c
+ and are required for the reference C code
+*/
+/* butter fly op */
+#define BF(pre, pim, qre, qim, pre1, pim1, qre1, qim1) \
+{\
+ FFTSample ax, ay, bx, by;\
+ bx=pre1;\
+ by=pim1;\
+ ax=qre1;\
+ ay=qim1;\
+ pre = (bx + ax);\
+ pim = (by + ay);\
+ qre = (bx - ax);\
+ qim = (by - ay);\
+}
+#define MUL16(a,b) ((a) * (b))
+#define CMUL(pre, pim, are, aim, bre, bim) \
+{\
+ pre = (MUL16(are, bre) - MUL16(aim, bim));\
+ pim = (MUL16(are, bim) + MUL16(bre, aim));\
+}
+
+
+/**
+ * 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
+ * The code is exactly the same as the SSE version, except
+ * that successive MUL + ADD/SUB have been merged into
+ * fused multiply-add ('vec_madd' in altivec)
+ */
+void ff_fft_calc_altivec(FFTContext *s, FFTComplex *z)
+{
+POWERPC_PERF_DECLARE(altivec_fft_num, s->nbits >= 6);
+ register const vector float vczero = (const vector float)vec_splat_u32(0.);
+
+ int ln = s->nbits;
+ int j, np, np2;
+ int nblocks, nloops;
+ register FFTComplex *p, *q;
+ FFTComplex *cptr, *cptr1;
+ int k;
+
+POWERPC_PERF_START_COUNT(altivec_fft_num, s->nbits >= 6);
+
+ np = 1 << ln;
+
+ {
+ vector float *r, a, b, a1, c1, c2;
+
+ r = (vector float *)&z[0];
+
+ c1 = vcii(p,p,n,n);
+
+ if (s->inverse)
+ {
+ c2 = vcii(p,p,n,p);
+ }
+ else
+ {
+ c2 = vcii(p,p,p,n);
+ }
+
+ j = (np >> 2);
+ do {
+ a = vec_ld(0, r);
+ a1 = vec_ld(sizeof(vector float), r);
+
+ b = vec_perm(a,a,vcprmle(1,0,3,2));
+ a = vec_madd(a,c1,b);
+ /* do the pass 0 butterfly */
+
+ b = vec_perm(a1,a1,vcprmle(1,0,3,2));
+ b = vec_madd(a1,c1,b);
+ /* do the pass 0 butterfly */
+
+ /* multiply third by -i */
+ b = vec_perm(b,b,vcprmle(2,3,1,0));
+
+ /* do the pass 1 butterfly */
+ vec_st(vec_madd(b,c2,a), 0, r);
+ vec_st(vec_nmsub(b,c2,a), sizeof(vector float), r);
+
+ r += 2;
+ } while (--j != 0);
+ }
+ /* pass 2 .. ln-1 */
+
+ nblocks = np >> 3;
+ nloops = 1 << 2;
+ np2 = np >> 1;
+
+ cptr1 = s->exptab1;
+ do {
+ p = z;
+ q = z + nloops;
+ j = nblocks;
+ do {
+ cptr = cptr1;
+ k = nloops >> 1;
+ do {
+ vector float a,b,c,t1;
+
+ a = vec_ld(0, (float*)p);
+ b = vec_ld(0, (float*)q);
+
+ /* complex mul */
+ c = vec_ld(0, (float*)cptr);
+ /* cre*re cim*re */
+ t1 = vec_madd(c, vec_perm(b,b,vcprmle(2,2,0,0)),vczero);
+ c = vec_ld(sizeof(vector float), (float*)cptr);
+ /* -cim*im cre*im */
+ b = vec_madd(c, vec_perm(b,b,vcprmle(3,3,1,1)),t1);
+
+ /* butterfly */
+ vec_st(vec_add(a,b), 0, (float*)p);
+ vec_st(vec_sub(a,b), 0, (float*)q);
+
+ p += 2;
+ q += 2;
+ cptr += 4;
+ } while (--k);
+
+ p += nloops;
+ q += nloops;
+ } while (--j);
+ cptr1 += nloops * 2;
+ nblocks = nblocks >> 1;
+ nloops = nloops << 1;
+ } while (nblocks != 0);
+
+POWERPC_PERF_STOP_COUNT(altivec_fft_num, s->nbits >= 6);
+}
diff --git a/contrib/ffmpeg/libavcodec/ppc/float_altivec.c b/contrib/ffmpeg/libavcodec/ppc/float_altivec.c
new file mode 100644
index 000000000..c6e43dec2
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/float_altivec.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2006 Luca Barbato <lu_zero@gentoo.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
+ */
+
+#include "../dsputil.h"
+
+#include "gcc_fixes.h"
+
+#include "dsputil_altivec.h"
+
+static void vector_fmul_altivec(float *dst, const float *src, int len)
+{
+ int i;
+ vector float d0, d1, s, zero = (vector float)vec_splat_u32(0);
+ for(i=0; i<len-7; i+=8) {
+ d0 = vec_ld(0, dst+i);
+ s = vec_ld(0, src+i);
+ d1 = vec_ld(16, dst+i);
+ d0 = vec_madd(d0, s, zero);
+ d1 = vec_madd(d1, vec_ld(16,src+i), zero);
+ vec_st(d0, 0, dst+i);
+ vec_st(d1, 16, dst+i);
+ }
+}
+
+static void vector_fmul_reverse_altivec(float *dst, const float *src0,
+ const float *src1, int len)
+{
+ int i;
+ vector float d, s0, s1, h0, l0,
+ s2, s3, zero = (vector float)vec_splat_u32(0);
+ src1 += len-4;
+ for(i=0; i<len-7; i+=8) {
+ s1 = vec_ld(0, src1-i); // [a,b,c,d]
+ s0 = vec_ld(0, src0+i);
+ l0 = vec_mergel(s1, s1); // [c,c,d,d]
+ s3 = vec_ld(-16, src1-i);
+ h0 = vec_mergeh(s1, s1); // [a,a,b,b]
+ s2 = vec_ld(16, src0+i);
+ s1 = vec_mergeh(vec_mergel(l0,h0), // [d,b,d,b]
+ vec_mergeh(l0,h0)); // [c,a,c,a]
+ // [d,c,b,a]
+ l0 = vec_mergel(s3, s3);
+ d = vec_madd(s0, s1, zero);
+ h0 = vec_mergeh(s3, s3);
+ vec_st(d, 0, dst+i);
+ s3 = vec_mergeh(vec_mergel(l0,h0),
+ vec_mergeh(l0,h0));
+ d = vec_madd(s2, s3, zero);
+ vec_st(d, 16, dst+i);
+ }
+}
+
+static void vector_fmul_add_add_altivec(float *dst, const float *src0,
+ const float *src1, const float *src2,
+ int src3, int len, int step)
+{
+ int i;
+ vector float d, s0, s1, s2, t0, t1, edges;
+ vector unsigned char align = vec_lvsr(0,dst),
+ mask = vec_lvsl(0, dst);
+
+ t0 = vec_ld(0, dst);
+#if 0 //FIXME: there is still something wrong
+ if (step == 2) {
+ int y;
+ vector float d0, d1, s3, t2;
+ vector unsigned int sel =
+ vec_mergeh(vec_splat_u32(-1), vec_splat_u32(0));
+ t1 = vec_ld(16, dst);
+ for (i=0,y=0; i<len-3; i+=4,y+=8) {
+
+ s0 = vec_ld(0,src0+i);
+ s1 = vec_ld(0,src1+i);
+ s2 = vec_ld(0,src2+i);
+
+// t0 = vec_ld(0, dst+y); //[x x x|a]
+// t1 = vec_ld(16, dst+y); //[b c d|e]
+ t2 = vec_ld(31, dst+y); //[f g h|x]
+
+ d = vec_madd(s0,s1,s2); // [A B C D]
+
+ // [A A B B]
+
+ // [C C D D]
+
+ d0 = vec_perm(t0, t1, mask); // [a b c d]
+
+ d0 = vec_sel(vec_mergeh(d, d), d0, sel); // [A b B d]
+
+ edges = vec_perm(t1, t0, mask);
+
+ t0 = vec_perm(edges, d0, align); // [x x x|A]
+
+ t1 = vec_perm(d0, edges, align); // [b B d|e]
+
+ vec_stl(t0, 0, dst+y);
+
+ d1 = vec_perm(t1, t2, mask); // [e f g h]
+
+ d1 = vec_sel(vec_mergel(d, d), d1, sel); // [C f D h]
+
+ edges = vec_perm(t2, t1, mask);
+
+ t1 = vec_perm(edges, d1, align); // [b B d|C]
+
+ t2 = vec_perm(d1, edges, align); // [f D h|x]
+
+ vec_stl(t1, 16, dst+y);
+
+ t0 = t1;
+
+ vec_stl(t2, 31, dst+y);
+
+ t1 = t2;
+ }
+ } else
+ #endif
+ if (step == 1 && src3 == 0)
+ for (i=0; i<len-3; i+=4) {
+ t1 = vec_ld(15, dst+i);
+ s0 = vec_ld(0, src0+i);
+ s1 = vec_ld(0, src1+i);
+ s2 = vec_ld(0, src2+i);
+ edges = vec_perm(t1 ,t0, mask);
+ d = vec_madd(s0,s1,s2);
+ t1 = vec_perm(d, edges, align);
+ t0 = vec_perm(edges, d, align);
+ vec_st(t1, 15, dst+i);
+ vec_st(t0, 0, dst+i);
+ t0 = t1;
+ }
+ else
+ ff_vector_fmul_add_add_c(dst, src0, src1, src2, src3, len, step);
+}
+
+void float_to_int16_altivec(int16_t *dst, const float *src, int len)
+{
+ int i;
+ vector float s0, s1;
+ vector signed int t0, t1;
+ vector signed short d0, d1, d;
+ vector unsigned char align;
+ if(((long)dst)&15) //FIXME
+ for(i=0; i<len-7; i+=8) {
+ s0 = vec_ld(0, src+i);
+ s1 = vec_ld(16, src+i);
+ t0 = vec_cts(s0, 0);
+ d0 = vec_ld(0, dst+i);
+ t1 = vec_cts(s1, 0);
+ d1 = vec_ld(15, dst+i);
+ d = vec_packs(t0,t1);
+ 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) {
+ s0 = vec_ld(0, src+i);
+ s1 = vec_ld(16, src+i);
+ t0 = vec_cts(s0, 0);
+ t1 = vec_cts(s1, 0);
+ d = vec_packs(t0,t1);
+ vec_st(d, 0, dst+i);
+ }
+}
+
+void float_init_altivec(DSPContext* c, AVCodecContext *avctx)
+{
+ c->vector_fmul = vector_fmul_altivec;
+ c->vector_fmul_reverse = vector_fmul_reverse_altivec;
+ c->vector_fmul_add_add = vector_fmul_add_add_altivec;
+ if(!(avctx->flags & CODEC_FLAG_BITEXACT))
+ c->float_to_int16 = float_to_int16_altivec;
+}
diff --git a/contrib/ffmpeg/libavcodec/ppc/gcc_fixes.h b/contrib/ffmpeg/libavcodec/ppc/gcc_fixes.h
new file mode 100644
index 000000000..5a4a55188
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/gcc_fixes.h
@@ -0,0 +1,119 @@
+/*
+ * gcc fixes for altivec.
+ * Used to workaround broken gcc (FSF gcc-3 pre gcc-3.3)
+ * and to stay somewhat compatible with Darwin.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 _GCC_FIXES_
+#define _GCC_FIXES_
+
+#ifdef HAVE_ALTIVEC_H
+#include <altivec.h>
+#endif
+
+#ifdef CONFIG_DARWIN
+# ifndef __MWERKS__
+# define AVV(x...) (x)
+# else
+# define AVV
+# endif
+#define REG_v(a) asm ( #a )
+#else
+
+#define AVV(x...) {x}
+
+#if (__GNUC__ < 4)
+# define REG_v(a)
+#else
+# define REG_v(a) asm ( #a )
+#endif
+
+#if (__GNUC__ * 100 + __GNUC_MINOR__ < 303)
+
+/* This code was provided to me by Bartosch Pixa
+ * as a separate header file (broken_mergel.h).
+ * thanks to lu_zero for the workaround.
+ *
+ * See this mail for more information:
+ * http://gcc.gnu.org/ml/gcc/2003-04/msg00967.html
+ */
+
+static inline vector signed char ff_vmrglb (vector signed char const A,
+ vector signed char const B)
+{
+ static const vector unsigned char lowbyte = {
+ 0x08, 0x18, 0x09, 0x19, 0x0a, 0x1a, 0x0b, 0x1b,
+ 0x0c, 0x1c, 0x0d, 0x1d, 0x0e, 0x1e, 0x0f, 0x1f
+ };
+ return vec_perm (A, B, lowbyte);
+}
+
+static inline vector signed short ff_vmrglh (vector signed short const A,
+ vector signed short const B)
+{
+ static const vector unsigned char lowhalf = {
+ 0x08, 0x09, 0x18, 0x19, 0x0a, 0x0b, 0x1a, 0x1b,
+ 0x0c, 0x0d, 0x1c, 0x1d, 0x0e, 0x0f, 0x1e, 0x1f
+ };
+ return vec_perm (A, B, lowhalf);
+}
+
+static inline vector signed int ff_vmrglw (vector signed int const A,
+ vector signed int const B)
+{
+ static const vector unsigned char lowword = {
+ 0x08, 0x09, 0x0a, 0x0b, 0x18, 0x19, 0x1a, 0x1b,
+ 0x0c, 0x0d, 0x0e, 0x0f, 0x1c, 0x1d, 0x1e, 0x1f
+ };
+ return vec_perm (A, B, lowword);
+}
+/*#define ff_vmrglb ff_vmrglb
+#define ff_vmrglh ff_vmrglh
+#define ff_vmrglw ff_vmrglw
+*/
+#undef vec_mergel
+
+#define vec_mergel(a1, a2) \
+__ch (__bin_args_eq (vector signed char, (a1), vector signed char, (a2)), \
+ ((vector signed char) ff_vmrglb ((vector signed char) (a1), (vector signed char) (a2))), \
+__ch (__bin_args_eq (vector unsigned char, (a1), vector unsigned char, (a2)), \
+ ((vector unsigned char) ff_vmrglb ((vector signed char) (a1), (vector signed char) (a2))), \
+__ch (__bin_args_eq (vector signed short, (a1), vector signed short, (a2)), \
+ ((vector signed short) ff_vmrglh ((vector signed short) (a1), (vector signed short) (a2))), \
+__ch (__bin_args_eq (vector unsigned short, (a1), vector unsigned short, (a2)), \
+ ((vector unsigned short) ff_vmrglh ((vector signed short) (a1), (vector signed short) (a2))), \
+__ch (__bin_args_eq (vector float, (a1), vector float, (a2)), \
+ ((vector float) ff_vmrglw ((vector signed int) (a1), (vector signed int) (a2))), \
+__ch (__bin_args_eq (vector signed int, (a1), vector signed int, (a2)), \
+ ((vector signed int) ff_vmrglw ((vector signed int) (a1), (vector signed int) (a2))), \
+__ch (__bin_args_eq (vector unsigned int, (a1), vector unsigned int, (a2)), \
+ ((vector unsigned int) ff_vmrglw ((vector signed int) (a1), (vector signed int) (a2))), \
+ __altivec_link_error_invalid_argument ())))))))
+
+#endif
+
+#endif /* CONFIG_DARWIN */
+
+#ifndef __MWERKS__
+#define const_vector const vector
+#else
+#define const_vector vector
+#endif
+
+#endif /* _GCC_FIXES_ */
diff --git a/contrib/ffmpeg/libavcodec/ppc/gmc_altivec.c b/contrib/ffmpeg/libavcodec/ppc/gmc_altivec.c
new file mode 100644
index 000000000..42c936bb3
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/gmc_altivec.c
@@ -0,0 +1,146 @@
+/*
+ * GMC (Global Motion Compensation)
+ * AltiVec-enabled
+ * Copyright (c) 2003 Romain Dolbeau <romain@dolbeau.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
+ */
+
+#include "../dsputil.h"
+
+#include "gcc_fixes.h"
+
+#include "dsputil_altivec.h"
+
+/*
+ altivec-enhanced gmc1. ATM this code assume stride is a multiple of 8,
+ to preserve proper dst alignement.
+*/
+#define GMC1_PERF_COND (h==8)
+void gmc1_altivec(uint8_t *dst /* align 8 */, uint8_t *src /* align1 */, int stride, int h, int x16, int y16, int rounder)
+{
+POWERPC_PERF_DECLARE(altivec_gmc1_num, GMC1_PERF_COND);
+ const unsigned short __attribute__ ((aligned(16))) rounder_a[8] =
+ {rounder, rounder, rounder, rounder,
+ rounder, rounder, rounder, rounder};
+ const unsigned short __attribute__ ((aligned(16))) 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;
+
+
+POWERPC_PERF_START_COUNT(altivec_gmc1_num, GMC1_PERF_COND);
+
+ tempA = vec_ld(0, (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_ld(0, (unsigned short*)rounder_a);
+
+ // 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<h; i++)
+ {
+ dst_odd = (unsigned long)dst & 0x0000000F;
+ src_really_odd = (((unsigned long)src) + stride) & 0x0000000F;
+
+ dstv = vec_ld(0, dst);
+
+ // we we'll be able to pick-up our 9 char elements
+ // at src + stride from those 32 bytes
+ // then reuse the resulting 2 vectors srvcC and srcvD
+ // as the next srcvA and srcvB
+ src_0 = vec_ld(stride + 0, src);
+ src_1 = vec_ld(stride + 16, src);
+ srcvC = vec_perm(src_0, src_1, vec_lvsl(stride + 0, src));
+
+ if (src_really_odd != 0x0000000F)
+ { // if src & 0xF == 0xF, then (src+1) is properly aligned on the second vector.
+ srcvD = vec_perm(src_0, src_1, vec_lvsl(stride + 1, src));
+ }
+ else
+ {
+ srcvD = src_1;
+ }
+
+ srcvC = vec_mergeh(vczero, srcvC);
+ srcvD = vec_mergeh(vczero, srcvD);
+
+
+ // OK, now we (finally) do the math :-)
+ // those four instructions replaces 32 int muls & 32 int adds.
+ // isn't AltiVec nice ?
+ tempA = vec_mladd((vector unsigned short)srcvA, Av, rounderV);
+ tempB = vec_mladd((vector unsigned short)srcvB, Bv, tempA);
+ tempC = vec_mladd((vector unsigned short)srcvC, Cv, tempB);
+ tempD = vec_mladd((vector unsigned short)srcvD, Dv, tempC);
+
+ srcvA = srcvC;
+ srcvB = srcvD;
+
+ tempD = vec_sr(tempD, vcsr8);
+
+ dstv2 = vec_pack(tempD, (vector unsigned short)vczero);
+
+ if (dst_odd)
+ {
+ dstv2 = vec_perm(dstv, dstv2, vcprm(0,1,s0,s1));
+ }
+ else
+ {
+ dstv2 = vec_perm(dstv, dstv2, vcprm(s0,s1,2,3));
+ }
+
+ vec_st(dstv2, 0, dst);
+
+ dst += stride;
+ src += stride;
+ }
+
+POWERPC_PERF_STOP_COUNT(altivec_gmc1_num, GMC1_PERF_COND);
+}
diff --git a/contrib/ffmpeg/libavcodec/ppc/h264_altivec.c b/contrib/ffmpeg/libavcodec/ppc/h264_altivec.c
new file mode 100644
index 000000000..4aa366f97
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/h264_altivec.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 2004 Romain Dolbeau <romain@dolbeau.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
+ */
+
+#include "../dsputil.h"
+
+#include "gcc_fixes.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
+#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_template_altivec.c"
+#undef OP_U8_ALTIVEC
+#undef PREFIX_h264_chroma_mc8_altivec
+#undef PREFIX_h264_chroma_mc8_num
+#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_chroma_mc8_altivec avg_h264_chroma_mc8_altivec
+#define PREFIX_h264_chroma_mc8_num altivec_avg_h264_chroma_mc8_num
+#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_template_altivec.c"
+#undef OP_U8_ALTIVEC
+#undef PREFIX_h264_chroma_mc8_altivec
+#undef PREFIX_h264_chroma_mc8_num
+#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, int stride){\
+ OPNAME ## pixels ## SIZE ## _ ## CODETYPE(dst, src, stride, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc10_ ## CODETYPE(uint8_t *dst, uint8_t *src, int 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, int 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, int 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, int 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, int 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, int 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, int 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, int 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, int 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, int 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, int 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, int 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, int 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, int 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, int 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);\
+}\
+
+/* this code assume that stride % 16 == 0 */
+void put_no_rnd_h264_chroma_mc8_altivec(uint8_t * dst, uint8_t * src, int stride, int h, int x, int y) {
+ signed int ABCD[4] __attribute__((aligned(16))) =
+ {((8 - x) * (8 - y)),
+ ((x) * (8 - y)),
+ ((8 - x) * (y)),
+ ((x) * (y))};
+ register int i;
+ vector unsigned char fperm;
+ const vector signed int vABCD = vec_ld(0, ABCD);
+ const vector signed short vA = vec_splat((vector signed short)vABCD, 1);
+ const vector signed short vB = vec_splat((vector signed short)vABCD, 3);
+ const vector signed short vC = vec_splat((vector signed short)vABCD, 5);
+ const vector signed short vD = vec_splat((vector signed short)vABCD, 7);
+ const vector signed int vzero = vec_splat_s32(0);
+ const vector signed short v28ss = vec_sub(vec_sl(vec_splat_s16(1),vec_splat_u16(5)),vec_splat_s16(4));
+ const vector unsigned short 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;
+
+ vector unsigned char vsrcAuc, vsrcBuc, vsrcperm0, vsrcperm1;
+ vector unsigned char vsrc0uc, vsrc1uc;
+ vector signed short vsrc0ssH, vsrc1ssH;
+ vector unsigned char vsrcCuc, vsrc2uc, vsrc3uc;
+ vector signed short vsrc2ssH, vsrc3ssH, psum;
+ vector unsigned char vdst, ppsum, vfdst, fsum;
+
+ if (((unsigned long)dst) % 16 == 0) {
+ fperm = (vector unsigned char)AVV(0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17,
+ 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F);
+ } else {
+ fperm = (vector unsigned char)AVV(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 = (vector signed short)vec_mergeh((vector unsigned char)vzero,
+ (vector unsigned char)vsrc0uc);
+ vsrc1ssH = (vector signed short)vec_mergeh((vector unsigned char)vzero,
+ (vector unsigned char)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);
+
+ vsrc2ssH = (vector signed short)vec_mergeh((vector unsigned char)vzero,
+ (vector unsigned char)vsrc2uc);
+ vsrc3ssH = (vector signed short)vec_mergeh((vector unsigned char)vzero,
+ (vector unsigned char)vsrc3uc);
+
+ psum = vec_mladd(vA, vsrc0ssH, vec_splat_s16(0));
+ psum = vec_mladd(vB, vsrc1ssH, psum);
+ psum = vec_mladd(vC, vsrc2ssH, psum);
+ psum = vec_mladd(vD, vsrc3ssH, psum);
+ psum = vec_add(v28ss, psum);
+ psum = vec_sra(psum, v6us);
+
+ vdst = vec_ld(0, dst);
+ ppsum = (vector unsigned char)vec_packsu(psum, psum);
+ fsum = vec_perm(vdst, ppsum, fperm);
+
+ vec_st(fsum, 0, dst);
+
+ vsrc0ssH = vsrc2ssH;
+ vsrc1ssH = vsrc3ssH;
+
+ dst += stride;
+ src += stride;
+ }
+ } else {
+ vector unsigned char 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);
+
+ vsrc2ssH = (vector signed short)vec_mergeh((vector unsigned char)vzero,
+ (vector unsigned char)vsrc2uc);
+ vsrc3ssH = (vector signed short)vec_mergeh((vector unsigned char)vzero,
+ (vector unsigned char)vsrc3uc);
+
+ psum = vec_mladd(vA, vsrc0ssH, vec_splat_s16(0));
+ psum = vec_mladd(vB, vsrc1ssH, psum);
+ psum = vec_mladd(vC, vsrc2ssH, psum);
+ psum = vec_mladd(vD, vsrc3ssH, psum);
+ psum = vec_add(v28ss, psum);
+ psum = vec_sr(psum, v6us);
+
+ vdst = vec_ld(0, dst);
+ ppsum = (vector unsigned char)vec_pack(psum, psum);
+ fsum = vec_perm(vdst, ppsum, fperm);
+
+ vec_st(fsum, 0, dst);
+
+ vsrc0ssH = vsrc2ssH;
+ vsrc1ssH = vsrc3ssH;
+
+ dst += stride;
+ src += stride;
+ }
+ }
+}
+
+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;
+ vector unsigned char 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;
+ vector unsigned char 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)
+
+void dsputil_h264_init_ppc(DSPContext* c, AVCodecContext *avctx) {
+
+#ifdef HAVE_ALTIVEC
+ if (has_altivec()) {
+ c->put_h264_chroma_pixels_tab[0] = put_h264_chroma_mc8_altivec;
+ c->put_no_rnd_h264_chroma_pixels_tab[0] = put_no_rnd_h264_chroma_mc8_altivec;
+ c->avg_h264_chroma_pixels_tab[0] = avg_h264_chroma_mc8_altivec;
+
+#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
+
+ } else
+#endif /* HAVE_ALTIVEC */
+ {
+ // Non-AltiVec PPC optimisations
+
+ // ... pending ...
+ }
+}
diff --git a/contrib/ffmpeg/libavcodec/ppc/h264_template_altivec.c b/contrib/ffmpeg/libavcodec/ppc/h264_template_altivec.c
new file mode 100644
index 000000000..e8ad67f2f
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/h264_template_altivec.c
@@ -0,0 +1,719 @@
+/*
+ * Copyright (c) 2004 Romain Dolbeau <romain@dolbeau.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
+ */
+
+/* this code assume that stride % 16 == 0 */
+void PREFIX_h264_chroma_mc8_altivec(uint8_t * dst, uint8_t * src, int stride, int h, int x, int y) {
+ POWERPC_PERF_DECLARE(PREFIX_h264_chroma_mc8_num, 1);
+ signed int ABCD[4] __attribute__((aligned(16))) =
+ {((8 - x) * (8 - y)),
+ ((x) * (8 - y)),
+ ((8 - x) * (y)),
+ ((x) * (y))};
+ register int i;
+ vector unsigned char fperm;
+ const vector signed int vABCD = vec_ld(0, ABCD);
+ const vector signed short vA = vec_splat((vector signed short)vABCD, 1);
+ const vector signed short vB = vec_splat((vector signed short)vABCD, 3);
+ const vector signed short vC = vec_splat((vector signed short)vABCD, 5);
+ const vector signed short vD = vec_splat((vector signed short)vABCD, 7);
+ const vector signed int vzero = vec_splat_s32(0);
+ const vector signed short v32ss = vec_sl(vec_splat_s16(1),vec_splat_u16(5));
+ const vector unsigned short 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;
+
+ vector unsigned char vsrcAuc, vsrcBuc, vsrcperm0, vsrcperm1;
+ vector unsigned char vsrc0uc, vsrc1uc;
+ vector signed short vsrc0ssH, vsrc1ssH;
+ vector unsigned char vsrcCuc, vsrc2uc, vsrc3uc;
+ vector signed short vsrc2ssH, vsrc3ssH, psum;
+ vector unsigned char vdst, ppsum, vfdst, fsum;
+
+ POWERPC_PERF_START_COUNT(PREFIX_h264_chroma_mc8_num, 1);
+
+ if (((unsigned long)dst) % 16 == 0) {
+ fperm = (vector unsigned char)AVV(0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17,
+ 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F);
+ } else {
+ fperm = (vector unsigned char)AVV(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 = (vector signed short)vec_mergeh((vector unsigned char)vzero,
+ (vector unsigned char)vsrc0uc);
+ vsrc1ssH = (vector signed short)vec_mergeh((vector unsigned char)vzero,
+ (vector unsigned char)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);
+
+ vsrc2ssH = (vector signed short)vec_mergeh((vector unsigned char)vzero,
+ (vector unsigned char)vsrc2uc);
+ vsrc3ssH = (vector signed short)vec_mergeh((vector unsigned char)vzero,
+ (vector unsigned char)vsrc3uc);
+
+ psum = vec_mladd(vA, vsrc0ssH, vec_splat_s16(0));
+ psum = vec_mladd(vB, vsrc1ssH, psum);
+ psum = vec_mladd(vC, vsrc2ssH, psum);
+ psum = vec_mladd(vD, vsrc3ssH, psum);
+ psum = vec_add(v32ss, psum);
+ psum = vec_sra(psum, v6us);
+
+ vdst = vec_ld(0, dst);
+ ppsum = (vector unsigned char)vec_packsu(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;
+ }
+ } else {
+ vector unsigned char 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);
+
+ vsrc2ssH = (vector signed short)vec_mergeh((vector unsigned char)vzero,
+ (vector unsigned char)vsrc2uc);
+ vsrc3ssH = (vector signed short)vec_mergeh((vector unsigned char)vzero,
+ (vector unsigned char)vsrc3uc);
+
+ psum = vec_mladd(vA, vsrc0ssH, vec_splat_s16(0));
+ psum = vec_mladd(vB, vsrc1ssH, psum);
+ psum = vec_mladd(vC, vsrc2ssH, psum);
+ psum = vec_mladd(vD, vsrc3ssH, psum);
+ psum = vec_add(v32ss, psum);
+ psum = vec_sr(psum, v6us);
+
+ vdst = vec_ld(0, dst);
+ ppsum = (vector unsigned char)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;
+ }
+ }
+ POWERPC_PERF_STOP_COUNT(PREFIX_h264_chroma_mc8_num, 1);
+}
+
+/* this code assume stride % 16 == 0 */
+static void PREFIX_h264_qpel16_h_lowpass_altivec(uint8_t * dst, uint8_t * src, int dstStride, int srcStride) {
+ POWERPC_PERF_DECLARE(PREFIX_h264_qpel16_h_lowpass_num, 1);
+ register int i;
+
+ const vector signed int vzero = vec_splat_s32(0);
+ const vector unsigned char permM2 = vec_lvsl(-2, src);
+ const vector unsigned char permM1 = vec_lvsl(-1, src);
+ const vector unsigned char permP0 = vec_lvsl(+0, src);
+ const vector unsigned char permP1 = vec_lvsl(+1, src);
+ const vector unsigned char permP2 = vec_lvsl(+2, src);
+ const vector unsigned char permP3 = vec_lvsl(+3, src);
+ const vector signed short v5ss = vec_splat_s16(5);
+ const vector unsigned short v5us = vec_splat_u16(5);
+ const vector signed short v20ss = vec_sl(vec_splat_s16(5),vec_splat_u16(2));
+ const vector signed short v16ss = vec_sl(vec_splat_s16(1),vec_splat_u16(4));
+ const vector unsigned char dstperm = vec_lvsr(0, dst);
+ const vector unsigned char neg1 =
+ (const vector unsigned char) vec_splat_s8(-1);
+
+ const vector unsigned char dstmask =
+ vec_perm((const vector unsigned char)vzero,
+ neg1, dstperm);
+
+ vector unsigned char srcM2, srcM1, srcP0, srcP1, srcP2, srcP3;
+
+ register int align = ((((unsigned long)src) - 2) % 16);
+
+ vector signed short 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;
+
+ vector unsigned char sum, dst1, dst2, vdst, fsum,
+ rsum, fdst1, fdst2;
+
+ POWERPC_PERF_START_COUNT(PREFIX_h264_qpel16_h_lowpass_num, 1);
+
+ for (i = 0 ; i < 16 ; i ++) {
+ vector unsigned char srcR1 = vec_ld(-2, src);
+ vector unsigned char 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: {
+ vector unsigned char 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: {
+ vector unsigned char 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: {
+ vector unsigned char 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: {
+ vector unsigned char 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 = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcP0);
+ srcP0B = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, srcP0);
+ srcP1A = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcP1);
+ srcP1B = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, srcP1);
+
+ srcP2A = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcP2);
+ srcP2B = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, srcP2);
+ srcP3A = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcP3);
+ srcP3B = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, srcP3);
+
+ srcM1A = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcM1);
+ srcM1B = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, srcM1);
+ srcM2A = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcM2);
+ srcM2B = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, 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, (vector signed short)vzero);
+ pp2B = vec_mladd(sum2B, v5ss, (vector signed short)vzero);
+
+ 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);
+
+ dst1 = vec_ld(0, dst);
+ dst2 = vec_ld(16, dst);
+ vdst = vec_perm(dst1, dst2, vec_lvsl(0, dst));
+
+ OP_U8_ALTIVEC(fsum, sum, vdst);
+
+ rsum = vec_perm(fsum, fsum, dstperm);
+ fdst1 = vec_sel(dst1, rsum, dstmask);
+ fdst2 = vec_sel(rsum, dst2, dstmask);
+
+ vec_st(fdst1, 0, dst);
+ vec_st(fdst2, 16, dst);
+
+ src += srcStride;
+ dst += dstStride;
+ }
+POWERPC_PERF_STOP_COUNT(PREFIX_h264_qpel16_h_lowpass_num, 1);
+}
+
+/* this code assume stride % 16 == 0 */
+static void PREFIX_h264_qpel16_v_lowpass_altivec(uint8_t * dst, uint8_t * src, int dstStride, int srcStride) {
+ POWERPC_PERF_DECLARE(PREFIX_h264_qpel16_v_lowpass_num, 1);
+
+ register int i;
+
+ const vector signed int vzero = vec_splat_s32(0);
+ const vector unsigned char perm = vec_lvsl(0, src);
+ const vector signed short v20ss = vec_sl(vec_splat_s16(5),vec_splat_u16(2));
+ const vector unsigned short v5us = vec_splat_u16(5);
+ const vector signed short v5ss = vec_splat_s16(5);
+ const vector signed short v16ss = vec_sl(vec_splat_s16(1),vec_splat_u16(4));
+ const vector unsigned char dstperm = vec_lvsr(0, dst);
+ const vector unsigned char neg1 = (const vector unsigned char)vec_splat_s8(-1);
+ const vector unsigned char dstmask = vec_perm((const vector unsigned char)vzero, neg1, dstperm);
+
+ uint8_t *srcbis = src - (srcStride * 2);
+
+ const vector unsigned char srcM2a = vec_ld(0, srcbis);
+ const vector unsigned char srcM2b = vec_ld(16, srcbis);
+ const vector unsigned char srcM2 = vec_perm(srcM2a, srcM2b, perm);
+// srcbis += srcStride;
+ const vector unsigned char srcM1a = vec_ld(0, srcbis += srcStride);
+ const vector unsigned char srcM1b = vec_ld(16, srcbis);
+ const vector unsigned char srcM1 = vec_perm(srcM1a, srcM1b, perm);
+// srcbis += srcStride;
+ const vector unsigned char srcP0a = vec_ld(0, srcbis += srcStride);
+ const vector unsigned char srcP0b = vec_ld(16, srcbis);
+ const vector unsigned char srcP0 = vec_perm(srcP0a, srcP0b, perm);
+// srcbis += srcStride;
+ const vector unsigned char srcP1a = vec_ld(0, srcbis += srcStride);
+ const vector unsigned char srcP1b = vec_ld(16, srcbis);
+ const vector unsigned char srcP1 = vec_perm(srcP1a, srcP1b, perm);
+// srcbis += srcStride;
+ const vector unsigned char srcP2a = vec_ld(0, srcbis += srcStride);
+ const vector unsigned char srcP2b = vec_ld(16, srcbis);
+ const vector unsigned char srcP2 = vec_perm(srcP2a, srcP2b, perm);
+// srcbis += srcStride;
+
+ vector signed short srcM2ssA = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcM2);
+ vector signed short srcM2ssB = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, srcM2);
+ vector signed short srcM1ssA = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcM1);
+ vector signed short srcM1ssB = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, srcM1);
+ vector signed short srcP0ssA = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcP0);
+ vector signed short srcP0ssB = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, srcP0);
+ vector signed short srcP1ssA = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcP1);
+ vector signed short srcP1ssB = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, srcP1);
+ vector signed short srcP2ssA = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcP2);
+ vector signed short srcP2ssB = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, srcP2);
+
+ vector signed short pp1A, pp1B, pp2A, pp2B, pp3A, pp3B,
+ psumA, psumB, sumA, sumB,
+ srcP3ssA, srcP3ssB,
+ sum1A, sum1B, sum2A, sum2B, sum3A, sum3B;
+
+ vector unsigned char sum, dst1, dst2, vdst, fsum, rsum, fdst1, fdst2,
+ srcP3a, srcP3b, srcP3;
+
+ POWERPC_PERF_START_COUNT(PREFIX_h264_qpel16_v_lowpass_num, 1);
+
+ for (i = 0 ; i < 16 ; i++) {
+ srcP3a = vec_ld(0, srcbis += srcStride);
+ srcP3b = vec_ld(16, srcbis);
+ srcP3 = vec_perm(srcP3a, srcP3b, perm);
+ srcP3ssA = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcP3);
+ srcP3ssB = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, 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, (vector signed short)vzero);
+ pp2B = vec_mladd(sum2B, v5ss, (vector signed short)vzero);
+
+ 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);
+
+ dst1 = vec_ld(0, dst);
+ dst2 = vec_ld(16, dst);
+ vdst = vec_perm(dst1, dst2, vec_lvsl(0, dst));
+
+ OP_U8_ALTIVEC(fsum, sum, vdst);
+
+ rsum = vec_perm(fsum, fsum, dstperm);
+ fdst1 = vec_sel(dst1, rsum, dstmask);
+ fdst2 = vec_sel(rsum, dst2, dstmask);
+
+ vec_st(fdst1, 0, dst);
+ vec_st(fdst2, 16, dst);
+
+ dst += dstStride;
+ }
+ POWERPC_PERF_STOP_COUNT(PREFIX_h264_qpel16_v_lowpass_num, 1);
+}
+
+/* this code assume stride % 16 == 0 *and* tmp is properly aligned */
+static void PREFIX_h264_qpel16_hv_lowpass_altivec(uint8_t * dst, int16_t * tmp, uint8_t * src, int dstStride, int tmpStride, int srcStride) {
+ POWERPC_PERF_DECLARE(PREFIX_h264_qpel16_hv_lowpass_num, 1);
+ register int i;
+ const vector signed int vzero = vec_splat_s32(0);
+ const vector unsigned char permM2 = vec_lvsl(-2, src);
+ const vector unsigned char permM1 = vec_lvsl(-1, src);
+ const vector unsigned char permP0 = vec_lvsl(+0, src);
+ const vector unsigned char permP1 = vec_lvsl(+1, src);
+ const vector unsigned char permP2 = vec_lvsl(+2, src);
+ const vector unsigned char permP3 = vec_lvsl(+3, src);
+ const vector signed short v20ss = vec_sl(vec_splat_s16(5),vec_splat_u16(2));
+ const vector unsigned int v10ui = vec_splat_u32(10);
+ const vector signed short v5ss = vec_splat_s16(5);
+ const vector signed short v1ss = vec_splat_s16(1);
+ const vector signed int v512si = vec_sl(vec_splat_s32(1),vec_splat_u32(9));
+ const vector unsigned int v16ui = vec_sl(vec_splat_u32(1),vec_splat_u32(4));
+
+ register int align = ((((unsigned long)src) - 2) % 16);
+
+ const vector unsigned char neg1 = (const vector unsigned char)
+ vec_splat_s8(-1);
+
+ vector signed short 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 vector unsigned char dstperm = vec_lvsr(0, dst);
+
+ const vector unsigned char dstmask = vec_perm((const vector unsigned char)vzero, neg1, dstperm);
+
+ const vector unsigned char mperm = (const vector unsigned char)
+ AVV(0x00, 0x08, 0x01, 0x09, 0x02, 0x0A, 0x03, 0x0B,
+ 0x04, 0x0C, 0x05, 0x0D, 0x06, 0x0E, 0x07, 0x0F);
+ int16_t *tmpbis = tmp;
+
+ vector signed short tmpM1ssA, tmpM1ssB, tmpM2ssA, tmpM2ssB,
+ tmpP0ssA, tmpP0ssB, tmpP1ssA, tmpP1ssB,
+ tmpP2ssA, tmpP2ssB;
+
+ vector signed int 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;
+ vector unsigned char fsum, sumv, sum, dst1, dst2, vdst,
+ rsum, fdst1, fdst2;
+ vector signed short ssume, ssumo;
+
+ POWERPC_PERF_START_COUNT(PREFIX_h264_qpel16_hv_lowpass_num, 1);
+ src -= (2 * srcStride);
+ for (i = 0 ; i < 21 ; i ++) {
+ vector unsigned char srcM2, srcM1, srcP0, srcP1, srcP2, srcP3;
+ vector unsigned char srcR1 = vec_ld(-2, src);
+ vector unsigned char 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: {
+ vector unsigned char 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: {
+ vector unsigned char 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: {
+ vector unsigned char 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: {
+ vector unsigned char 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 = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcP0);
+ srcP0B = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, srcP0);
+ srcP1A = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcP1);
+ srcP1B = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, srcP1);
+
+ srcP2A = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcP2);
+ srcP2B = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, srcP2);
+ srcP3A = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcP3);
+ srcP3B = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, srcP3);
+
+ srcM1A = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcM1);
+ srcM1B = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, srcM1);
+ srcM2A = (vector signed short)
+ vec_mergeh((vector unsigned char)vzero, srcM2);
+ srcM2B = (vector signed short)
+ vec_mergel((vector unsigned char)vzero, 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, (vector signed short)vzero);
+ pp2B = vec_mladd(sum2B, v5ss, (vector signed short)vzero);
+
+ 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 vector signed short tmpP3ssA = vec_ld(0, tmpbis);
+ const vector signed short tmpP3ssB = vec_ld(16, tmpbis);
+
+ const vector signed short sum1A = vec_adds(tmpP0ssA, tmpP1ssA);
+ const vector signed short sum1B = vec_adds(tmpP0ssB, tmpP1ssB);
+ const vector signed short sum2A = vec_adds(tmpM1ssA, tmpP2ssA);
+ const vector signed short sum2B = vec_adds(tmpM1ssB, tmpP2ssB);
+ const vector signed short sum3A = vec_adds(tmpM2ssA, tmpP3ssA);
+ const vector signed short 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((vector signed int)sum3A, v16ui);
+ pp3Ao = vec_mulo(sum3A, v1ss);
+ pp3Be = vec_sra((vector signed int)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);
+
+ dst1 = vec_ld(0, dst);
+ dst2 = vec_ld(16, dst);
+ vdst = vec_perm(dst1, dst2, vec_lvsl(0, dst));
+
+ OP_U8_ALTIVEC(fsum, sum, vdst);
+
+ rsum = vec_perm(fsum, fsum, dstperm);
+ fdst1 = vec_sel(dst1, rsum, dstmask);
+ fdst2 = vec_sel(rsum, dst2, dstmask);
+
+ vec_st(fdst1, 0, dst);
+ vec_st(fdst2, 16, dst);
+
+ dst += dstStride;
+ }
+ POWERPC_PERF_STOP_COUNT(PREFIX_h264_qpel16_hv_lowpass_num, 1);
+}
diff --git a/contrib/ffmpeg/libavcodec/ppc/idct_altivec.c b/contrib/ffmpeg/libavcodec/ppc/idct_altivec.c
new file mode 100644
index 000000000..cee46fc25
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/idct_altivec.c
@@ -0,0 +1,237 @@
+/*
+ * 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
+ * re-ordered 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 <stdlib.h> /* malloc(), free() */
+#include <string.h>
+#include "../dsputil.h"
+
+#include "gcc_fixes.h"
+
+#include "dsputil_altivec.h"
+
+#define vector_s16_t vector signed short
+#define const_vector_s16_t const_vector signed short
+#define vector_u16_t vector unsigned short
+#define vector_s8_t vector signed char
+#define vector_u8_t vector unsigned char
+#define vector_s32_t vector signed int
+#define vector_u32_t vector unsigned int
+
+#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 \
+ vector_s16_t vx0, vx1, vx2, vx3, vx4, vx5, vx6, vx7; \
+ vector_s16_t vy0, vy1, vy2, vy3, vy4, vy5, vy6, vy7; \
+ vector_s16_t a0, a1, a2, ma2, c4, mc4, zero, bias; \
+ vector_s16_t t0, t1, t2, t3, t4, t5, t6, t7, t8; \
+ vector_u16_t 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 = (vector_s16_t)vec_splat ((vector_s32_t)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_vector_s16_t constants[5] = {
+ (vector_s16_t) AVV(23170, 13573, 6518, 21895, -23170, -21895, 32, 31),
+ (vector_s16_t) AVV(16384, 22725, 21407, 19266, 16384, 19266, 21407, 22725),
+ (vector_s16_t) AVV(22725, 31521, 29692, 26722, 22725, 26722, 29692, 31521),
+ (vector_s16_t) AVV(21407, 29692, 27969, 25172, 21407, 25172, 27969, 29692),
+ (vector_s16_t) AVV(19266, 26722, 25172, 22654, 19266, 22654, 25172, 26722)
+};
+
+void idct_put_altivec(uint8_t* dest, int stride, vector_s16_t* block)
+{
+POWERPC_PERF_DECLARE(altivec_idct_put_num, 1);
+ vector_u8_t tmp;
+
+#ifdef POWERPC_PERFORMANCE_REPORT
+POWERPC_PERF_START_COUNT(altivec_idct_put_num, 1);
+#endif
+ IDCT
+
+#define COPY(dest,src) \
+ tmp = vec_packsu (src, src); \
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest); \
+ vec_ste ((vector_u32_t)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)
+
+POWERPC_PERF_STOP_COUNT(altivec_idct_put_num, 1);
+}
+
+void idct_add_altivec(uint8_t* dest, int stride, vector_s16_t* block)
+{
+POWERPC_PERF_DECLARE(altivec_idct_add_num, 1);
+ vector_u8_t tmp;
+ vector_s16_t tmp2, tmp3;
+ vector_u8_t perm0;
+ vector_u8_t perm1;
+ vector_u8_t p0, p1, p;
+
+#ifdef POWERPC_PERFORMANCE_REPORT
+POWERPC_PERF_START_COUNT(altivec_idct_add_num, 1);
+#endif
+
+ 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 = (vector_s16_t)vec_perm (tmp, (vector_u8_t)zero, perm); \
+ tmp3 = vec_adds (tmp2, src); \
+ tmp = vec_packsu (tmp3, tmp3); \
+ vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest); \
+ vec_ste ((vector_u32_t)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)
+
+POWERPC_PERF_STOP_COUNT(altivec_idct_add_num, 1);
+}
+
diff --git a/contrib/ffmpeg/libavcodec/ppc/mathops.h b/contrib/ffmpeg/libavcodec/ppc/mathops.h
new file mode 100644
index 000000000..6af23f246
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/mathops.h
@@ -0,0 +1,33 @@
+/*
+ * simple math operations
+ * Copyright (c) 2001, 2002 Fabrice Bellard.
+ * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> 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
+ */
+
+#if defined(ARCH_POWERPC_405)
+/* 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
diff --git a/contrib/ffmpeg/libavcodec/ppc/mpegvideo_altivec.c b/contrib/ffmpeg/libavcodec/ppc/mpegvideo_altivec.c
new file mode 100644
index 000000000..3822cb20e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/mpegvideo_altivec.c
@@ -0,0 +1,603 @@
+/*
+ * Copyright (c) 2002 Dieter Shirley
+ *
+ * dct_unquantize_h263_altivec:
+ * Copyright (c) 2003 Romain Dolbeau <romain@dolbeau.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
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "../dsputil.h"
+#include "../mpegvideo.h"
+
+#include "gcc_fixes.h"
+
+#include "dsputil_altivec.h"
+
+// Swaps two variables (used for altivec registers)
+#define SWAP(a,b) \
+do { \
+ __typeof__(a) swap_temp=a; \
+ a=b; \
+ b=swap_temp; \
+} while (0)
+
+// transposes a matrix consisting of four vectors with four elements each
+#define TRANSPOSE4(a,b,c,d) \
+do { \
+ __typeof__(a) _trans_ach = vec_mergeh(a, c); \
+ __typeof__(a) _trans_acl = vec_mergel(a, c); \
+ __typeof__(a) _trans_bdh = vec_mergeh(b, d); \
+ __typeof__(a) _trans_bdl = vec_mergel(b, d); \
+ \
+ a = vec_mergeh(_trans_ach, _trans_bdh); \
+ b = vec_mergel(_trans_ach, _trans_bdh); \
+ c = vec_mergeh(_trans_acl, _trans_bdl); \
+ d = vec_mergel(_trans_acl, _trans_bdl); \
+} while (0)
+
+
+// Loads a four-byte value (int or float) from the target address
+// into every element in the target vector. Only works if the
+// target address is four-byte aligned (which should be always).
+#define LOAD4(vec, address) \
+{ \
+ __typeof__(vec)* _load_addr = (__typeof__(vec)*)(address); \
+ vector unsigned char _perm_vec = vec_lvsl(0,(address)); \
+ vec = vec_ld(0, _load_addr); \
+ vec = vec_perm(vec, vec, _perm_vec); \
+ vec = vec_splat(vec, 0); \
+}
+
+
+#ifdef CONFIG_DARWIN
+#define FOUROF(a) (a)
+#else
+// slower, for dumb non-apple GCC
+#define FOUROF(a) {a,a,a,a}
+#endif
+int dct_quantize_altivec(MpegEncContext* s,
+ DCTELEM* data, int n,
+ int qscale, int* overflow)
+{
+ int lastNonZero;
+ vector float row0, row1, row2, row3, row4, row5, row6, row7;
+ vector float alt0, alt1, alt2, alt3, alt4, alt5, alt6, alt7;
+ const_vector float zero = (const_vector float)FOUROF(0.);
+ // used after quantise step
+ int oldBaseValue = 0;
+
+ // Load the data into the row/alt vectors
+ {
+ vector signed short data0, data1, data2, data3, data4, data5, data6, data7;
+
+ data0 = vec_ld(0, data);
+ data1 = vec_ld(16, data);
+ data2 = vec_ld(32, data);
+ data3 = vec_ld(48, data);
+ data4 = vec_ld(64, data);
+ data5 = vec_ld(80, data);
+ data6 = vec_ld(96, data);
+ data7 = vec_ld(112, data);
+
+ // Transpose the data before we start
+ TRANSPOSE8(data0, data1, data2, data3, data4, data5, data6, data7);
+
+ // load the data into floating point vectors. We load
+ // the high half of each row into the main row vectors
+ // and the low half into the alt vectors.
+ row0 = vec_ctf(vec_unpackh(data0), 0);
+ alt0 = vec_ctf(vec_unpackl(data0), 0);
+ row1 = vec_ctf(vec_unpackh(data1), 0);
+ alt1 = vec_ctf(vec_unpackl(data1), 0);
+ row2 = vec_ctf(vec_unpackh(data2), 0);
+ alt2 = vec_ctf(vec_unpackl(data2), 0);
+ row3 = vec_ctf(vec_unpackh(data3), 0);
+ alt3 = vec_ctf(vec_unpackl(data3), 0);
+ row4 = vec_ctf(vec_unpackh(data4), 0);
+ alt4 = vec_ctf(vec_unpackl(data4), 0);
+ row5 = vec_ctf(vec_unpackh(data5), 0);
+ alt5 = vec_ctf(vec_unpackl(data5), 0);
+ row6 = vec_ctf(vec_unpackh(data6), 0);
+ alt6 = vec_ctf(vec_unpackl(data6), 0);
+ row7 = vec_ctf(vec_unpackh(data7), 0);
+ alt7 = vec_ctf(vec_unpackl(data7), 0);
+ }
+
+ // The following block could exist as a separate an altivec dct
+ // function. However, if we put it inline, the DCT data can remain
+ // in the vector local variables, as floats, which we'll use during the
+ // quantize step...
+ {
+ const vector float vec_0_298631336 = (vector float)FOUROF(0.298631336f);
+ const vector float vec_0_390180644 = (vector float)FOUROF(-0.390180644f);
+ const vector float vec_0_541196100 = (vector float)FOUROF(0.541196100f);
+ const vector float vec_0_765366865 = (vector float)FOUROF(0.765366865f);
+ const vector float vec_0_899976223 = (vector float)FOUROF(-0.899976223f);
+ const vector float vec_1_175875602 = (vector float)FOUROF(1.175875602f);
+ const vector float vec_1_501321110 = (vector float)FOUROF(1.501321110f);
+ const vector float vec_1_847759065 = (vector float)FOUROF(-1.847759065f);
+ const vector float vec_1_961570560 = (vector float)FOUROF(-1.961570560f);
+ const vector float vec_2_053119869 = (vector float)FOUROF(2.053119869f);
+ const vector float vec_2_562915447 = (vector float)FOUROF(-2.562915447f);
+ const vector float vec_3_072711026 = (vector float)FOUROF(3.072711026f);
+
+
+ int whichPass, whichHalf;
+
+ for(whichPass = 1; whichPass<=2; whichPass++)
+ {
+ for(whichHalf = 1; whichHalf<=2; whichHalf++)
+ {
+ vector float tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ vector float tmp10, tmp11, tmp12, tmp13;
+ vector float z1, z2, z3, z4, z5;
+
+ tmp0 = vec_add(row0, row7); // tmp0 = dataptr[0] + dataptr[7];
+ tmp7 = vec_sub(row0, row7); // tmp7 = dataptr[0] - dataptr[7];
+ tmp3 = vec_add(row3, row4); // tmp3 = dataptr[3] + dataptr[4];
+ tmp4 = vec_sub(row3, row4); // tmp4 = dataptr[3] - dataptr[4];
+ tmp1 = vec_add(row1, row6); // tmp1 = dataptr[1] + dataptr[6];
+ tmp6 = vec_sub(row1, row6); // tmp6 = dataptr[1] - dataptr[6];
+ tmp2 = vec_add(row2, row5); // tmp2 = dataptr[2] + dataptr[5];
+ tmp5 = vec_sub(row2, row5); // tmp5 = dataptr[2] - dataptr[5];
+
+ tmp10 = vec_add(tmp0, tmp3); // tmp10 = tmp0 + tmp3;
+ tmp13 = vec_sub(tmp0, tmp3); // tmp13 = tmp0 - tmp3;
+ tmp11 = vec_add(tmp1, tmp2); // tmp11 = tmp1 + tmp2;
+ tmp12 = vec_sub(tmp1, tmp2); // tmp12 = tmp1 - tmp2;
+
+
+ // dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS);
+ row0 = vec_add(tmp10, tmp11);
+
+ // dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS);
+ row4 = vec_sub(tmp10, tmp11);
+
+
+ // z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+ z1 = vec_madd(vec_add(tmp12, tmp13), vec_0_541196100, (vector float)zero);
+
+ // dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
+ // CONST_BITS-PASS1_BITS);
+ row2 = vec_madd(tmp13, vec_0_765366865, z1);
+
+ // dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065),
+ // CONST_BITS-PASS1_BITS);
+ row6 = vec_madd(tmp12, vec_1_847759065, z1);
+
+ z1 = vec_add(tmp4, tmp7); // z1 = tmp4 + tmp7;
+ z2 = vec_add(tmp5, tmp6); // z2 = tmp5 + tmp6;
+ z3 = vec_add(tmp4, tmp6); // z3 = tmp4 + tmp6;
+ z4 = vec_add(tmp5, tmp7); // z4 = tmp5 + tmp7;
+
+ // z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
+ z5 = vec_madd(vec_add(z3, z4), vec_1_175875602, (vector float)zero);
+
+ // z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z3 = vec_madd(z3, vec_1_961570560, z5);
+
+ // z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+ z4 = vec_madd(z4, vec_0_390180644, z5);
+
+ // The following adds are rolled into the multiplies above
+ // z3 = vec_add(z3, z5); // z3 += z5;
+ // z4 = vec_add(z4, z5); // z4 += z5;
+
+ // z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ // Wow! It's actually more effecient to roll this multiply
+ // into the adds below, even thought the multiply gets done twice!
+ // z2 = vec_madd(z2, vec_2_562915447, (vector float)zero);
+
+ // z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+ // Same with this one...
+ // z1 = vec_madd(z1, vec_0_899976223, (vector float)zero);
+
+ // tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+ // dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS);
+ row7 = vec_madd(tmp4, vec_0_298631336, vec_madd(z1, vec_0_899976223, z3));
+
+ // tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+ // dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS);
+ row5 = vec_madd(tmp5, vec_2_053119869, vec_madd(z2, vec_2_562915447, z4));
+
+ // tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+ // dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS);
+ row3 = vec_madd(tmp6, vec_3_072711026, vec_madd(z2, vec_2_562915447, z3));
+
+ // tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+ // dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS);
+ row1 = vec_madd(z1, vec_0_899976223, vec_madd(tmp7, vec_1_501321110, z4));
+
+ // Swap the row values with the alts. If this is the first half,
+ // this sets up the low values to be acted on in the second half.
+ // If this is the second half, it puts the high values back in
+ // the row values where they are expected to be when we're done.
+ SWAP(row0, alt0);
+ SWAP(row1, alt1);
+ SWAP(row2, alt2);
+ SWAP(row3, alt3);
+ SWAP(row4, alt4);
+ SWAP(row5, alt5);
+ SWAP(row6, alt6);
+ SWAP(row7, alt7);
+ }
+
+ if (whichPass == 1)
+ {
+ // transpose the data for the second pass
+
+ // First, block transpose the upper right with lower left.
+ SWAP(row4, alt0);
+ SWAP(row5, alt1);
+ SWAP(row6, alt2);
+ SWAP(row7, alt3);
+
+ // Now, transpose each block of four
+ TRANSPOSE4(row0, row1, row2, row3);
+ TRANSPOSE4(row4, row5, row6, row7);
+ TRANSPOSE4(alt0, alt1, alt2, alt3);
+ TRANSPOSE4(alt4, alt5, alt6, alt7);
+ }
+ }
+ }
+
+ // perform the quantise step, using the floating point data
+ // still in the row/alt registers
+ {
+ const int* biasAddr;
+ const vector signed int* qmat;
+ vector float bias, negBias;
+
+ if (s->mb_intra)
+ {
+ vector signed int baseVector;
+
+ // We must cache element 0 in the intra case
+ // (it needs special handling).
+ baseVector = vec_cts(vec_splat(row0, 0), 0);
+ vec_ste(baseVector, 0, &oldBaseValue);
+
+ qmat = (vector signed int*)s->q_intra_matrix[qscale];
+ biasAddr = &(s->intra_quant_bias);
+ }
+ else
+ {
+ qmat = (vector signed int*)s->q_inter_matrix[qscale];
+ biasAddr = &(s->inter_quant_bias);
+ }
+
+ // Load the bias vector (We add 0.5 to the bias so that we're
+ // rounding when we convert to int, instead of flooring.)
+ {
+ vector signed int biasInt;
+ const vector float negOneFloat = (vector float)FOUROF(-1.0f);
+ LOAD4(biasInt, biasAddr);
+ bias = vec_ctf(biasInt, QUANT_BIAS_SHIFT);
+ negBias = vec_madd(bias, negOneFloat, zero);
+ }
+
+ {
+ vector float q0, q1, q2, q3, q4, q5, q6, q7;
+
+ q0 = vec_ctf(qmat[0], QMAT_SHIFT);
+ q1 = vec_ctf(qmat[2], QMAT_SHIFT);
+ q2 = vec_ctf(qmat[4], QMAT_SHIFT);
+ q3 = vec_ctf(qmat[6], QMAT_SHIFT);
+ q4 = vec_ctf(qmat[8], QMAT_SHIFT);
+ q5 = vec_ctf(qmat[10], QMAT_SHIFT);
+ q6 = vec_ctf(qmat[12], QMAT_SHIFT);
+ q7 = vec_ctf(qmat[14], QMAT_SHIFT);
+
+ row0 = vec_sel(vec_madd(row0, q0, negBias), vec_madd(row0, q0, bias),
+ vec_cmpgt(row0, zero));
+ row1 = vec_sel(vec_madd(row1, q1, negBias), vec_madd(row1, q1, bias),
+ vec_cmpgt(row1, zero));
+ row2 = vec_sel(vec_madd(row2, q2, negBias), vec_madd(row2, q2, bias),
+ vec_cmpgt(row2, zero));
+ row3 = vec_sel(vec_madd(row3, q3, negBias), vec_madd(row3, q3, bias),
+ vec_cmpgt(row3, zero));
+ row4 = vec_sel(vec_madd(row4, q4, negBias), vec_madd(row4, q4, bias),
+ vec_cmpgt(row4, zero));
+ row5 = vec_sel(vec_madd(row5, q5, negBias), vec_madd(row5, q5, bias),
+ vec_cmpgt(row5, zero));
+ row6 = vec_sel(vec_madd(row6, q6, negBias), vec_madd(row6, q6, bias),
+ vec_cmpgt(row6, zero));
+ row7 = vec_sel(vec_madd(row7, q7, negBias), vec_madd(row7, q7, bias),
+ vec_cmpgt(row7, zero));
+
+ q0 = vec_ctf(qmat[1], QMAT_SHIFT);
+ q1 = vec_ctf(qmat[3], QMAT_SHIFT);
+ q2 = vec_ctf(qmat[5], QMAT_SHIFT);
+ q3 = vec_ctf(qmat[7], QMAT_SHIFT);
+ q4 = vec_ctf(qmat[9], QMAT_SHIFT);
+ q5 = vec_ctf(qmat[11], QMAT_SHIFT);
+ q6 = vec_ctf(qmat[13], QMAT_SHIFT);
+ q7 = vec_ctf(qmat[15], QMAT_SHIFT);
+
+ alt0 = vec_sel(vec_madd(alt0, q0, negBias), vec_madd(alt0, q0, bias),
+ vec_cmpgt(alt0, zero));
+ alt1 = vec_sel(vec_madd(alt1, q1, negBias), vec_madd(alt1, q1, bias),
+ vec_cmpgt(alt1, zero));
+ alt2 = vec_sel(vec_madd(alt2, q2, negBias), vec_madd(alt2, q2, bias),
+ vec_cmpgt(alt2, zero));
+ alt3 = vec_sel(vec_madd(alt3, q3, negBias), vec_madd(alt3, q3, bias),
+ vec_cmpgt(alt3, zero));
+ alt4 = vec_sel(vec_madd(alt4, q4, negBias), vec_madd(alt4, q4, bias),
+ vec_cmpgt(alt4, zero));
+ alt5 = vec_sel(vec_madd(alt5, q5, negBias), vec_madd(alt5, q5, bias),
+ vec_cmpgt(alt5, zero));
+ alt6 = vec_sel(vec_madd(alt6, q6, negBias), vec_madd(alt6, q6, bias),
+ vec_cmpgt(alt6, zero));
+ alt7 = vec_sel(vec_madd(alt7, q7, negBias), vec_madd(alt7, q7, bias),
+ vec_cmpgt(alt7, zero));
+ }
+
+
+ }
+
+ // Store the data back into the original block
+ {
+ vector signed short data0, data1, data2, data3, data4, data5, data6, data7;
+
+ data0 = vec_pack(vec_cts(row0, 0), vec_cts(alt0, 0));
+ data1 = vec_pack(vec_cts(row1, 0), vec_cts(alt1, 0));
+ data2 = vec_pack(vec_cts(row2, 0), vec_cts(alt2, 0));
+ data3 = vec_pack(vec_cts(row3, 0), vec_cts(alt3, 0));
+ data4 = vec_pack(vec_cts(row4, 0), vec_cts(alt4, 0));
+ data5 = vec_pack(vec_cts(row5, 0), vec_cts(alt5, 0));
+ data6 = vec_pack(vec_cts(row6, 0), vec_cts(alt6, 0));
+ data7 = vec_pack(vec_cts(row7, 0), vec_cts(alt7, 0));
+
+ {
+ // Clamp for overflow
+ vector signed int max_q_int, min_q_int;
+ vector signed short max_q, min_q;
+
+ LOAD4(max_q_int, &(s->max_qcoeff));
+ LOAD4(min_q_int, &(s->min_qcoeff));
+
+ max_q = vec_pack(max_q_int, max_q_int);
+ min_q = vec_pack(min_q_int, min_q_int);
+
+ data0 = vec_max(vec_min(data0, max_q), min_q);
+ data1 = vec_max(vec_min(data1, max_q), min_q);
+ data2 = vec_max(vec_min(data2, max_q), min_q);
+ data4 = vec_max(vec_min(data4, max_q), min_q);
+ data5 = vec_max(vec_min(data5, max_q), min_q);
+ data6 = vec_max(vec_min(data6, max_q), min_q);
+ data7 = vec_max(vec_min(data7, max_q), min_q);
+ }
+
+ {
+ vector bool char zero_01, zero_23, zero_45, zero_67;
+ vector signed char scanIndices_01, scanIndices_23, scanIndices_45, scanIndices_67;
+ vector signed char negOne = vec_splat_s8(-1);
+ vector signed char* scanPtr =
+ (vector signed char*)(s->intra_scantable.inverse);
+ signed char lastNonZeroChar;
+
+ // Determine the largest non-zero index.
+ zero_01 = vec_pack(vec_cmpeq(data0, (vector signed short)zero),
+ vec_cmpeq(data1, (vector signed short)zero));
+ zero_23 = vec_pack(vec_cmpeq(data2, (vector signed short)zero),
+ vec_cmpeq(data3, (vector signed short)zero));
+ zero_45 = vec_pack(vec_cmpeq(data4, (vector signed short)zero),
+ vec_cmpeq(data5, (vector signed short)zero));
+ zero_67 = vec_pack(vec_cmpeq(data6, (vector signed short)zero),
+ vec_cmpeq(data7, (vector signed short)zero));
+
+ // 64 biggest values
+ scanIndices_01 = vec_sel(scanPtr[0], negOne, zero_01);
+ scanIndices_23 = vec_sel(scanPtr[1], negOne, zero_23);
+ scanIndices_45 = vec_sel(scanPtr[2], negOne, zero_45);
+ scanIndices_67 = vec_sel(scanPtr[3], negOne, zero_67);
+
+ // 32 largest values
+ scanIndices_01 = vec_max(scanIndices_01, scanIndices_23);
+ scanIndices_45 = vec_max(scanIndices_45, scanIndices_67);
+
+ // 16 largest values
+ scanIndices_01 = vec_max(scanIndices_01, scanIndices_45);
+
+ // 8 largest values
+ scanIndices_01 = vec_max(vec_mergeh(scanIndices_01, negOne),
+ vec_mergel(scanIndices_01, negOne));
+
+ // 4 largest values
+ scanIndices_01 = vec_max(vec_mergeh(scanIndices_01, negOne),
+ vec_mergel(scanIndices_01, negOne));
+
+ // 2 largest values
+ scanIndices_01 = vec_max(vec_mergeh(scanIndices_01, negOne),
+ vec_mergel(scanIndices_01, negOne));
+
+ // largest value
+ scanIndices_01 = vec_max(vec_mergeh(scanIndices_01, negOne),
+ vec_mergel(scanIndices_01, negOne));
+
+ scanIndices_01 = vec_splat(scanIndices_01, 0);
+
+
+ vec_ste(scanIndices_01, 0, &lastNonZeroChar);
+
+ lastNonZero = lastNonZeroChar;
+
+ // While the data is still in vectors we check for the transpose IDCT permute
+ // and handle it using the vector unit if we can. This is the permute used
+ // by the altivec idct, so it is common when using the altivec dct.
+
+ if ((lastNonZero > 0) && (s->dsp.idct_permutation_type == FF_TRANSPOSE_IDCT_PERM))
+ {
+ TRANSPOSE8(data0, data1, data2, data3, data4, data5, data6, data7);
+ }
+
+ vec_st(data0, 0, data);
+ vec_st(data1, 16, data);
+ vec_st(data2, 32, data);
+ vec_st(data3, 48, data);
+ vec_st(data4, 64, data);
+ vec_st(data5, 80, data);
+ vec_st(data6, 96, data);
+ vec_st(data7, 112, data);
+ }
+ }
+
+ // special handling of block[0]
+ if (s->mb_intra)
+ {
+ if (!s->h263_aic)
+ {
+ if (n < 4)
+ oldBaseValue /= s->y_dc_scale;
+ else
+ oldBaseValue /= s->c_dc_scale;
+ }
+
+ // Divide by 8, rounding the result
+ data[0] = (oldBaseValue + 4) >> 3;
+ }
+
+ // We handled the tranpose permutation above and we don't
+ // need to permute the "no" permutation case.
+ if ((lastNonZero > 0) &&
+ (s->dsp.idct_permutation_type != FF_TRANSPOSE_IDCT_PERM) &&
+ (s->dsp.idct_permutation_type != FF_NO_IDCT_PERM))
+ {
+ ff_block_permute(data, s->dsp.idct_permutation,
+ s->intra_scantable.scantable, lastNonZero);
+ }
+
+ return lastNonZero;
+}
+#undef FOUROF
+
+/*
+ AltiVec version of dct_unquantize_h263
+ this code assumes `block' is 16 bytes-aligned
+*/
+void dct_unquantize_h263_altivec(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale)
+{
+POWERPC_PERF_DECLARE(altivec_dct_unquantize_h263_num, 1);
+ int i, level, qmul, qadd;
+ int nCoeffs;
+
+ assert(s->block_last_index[n]>=0);
+
+POWERPC_PERF_START_COUNT(altivec_dct_unquantize_h263_num, 1);
+
+ 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 allways 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);
+ short __attribute__ ((aligned(16))) qmul8[] =
+ {
+ qmul, qmul, qmul, qmul,
+ qmul, qmul, qmul, qmul
+ };
+ short __attribute__ ((aligned(16))) qadd8[] =
+ {
+ qadd, qadd, qadd, qadd,
+ qadd, qadd, qadd, qadd
+ };
+ short __attribute__ ((aligned(16))) nqadd8[] =
+ {
+ -qadd, -qadd, -qadd, -qadd,
+ -qadd, -qadd, -qadd, -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_ld(0, qmul8);
+ qaddv = vec_ld(0, qadd8);
+ nqaddv = vec_ld(0, nqadd8);
+
+#if 0 // block *is* 16 bytes-aligned, it seems.
+ // first make sure block[j] is 16 bytes-aligned
+ for(j = 0; (j <= nCoeffs) && ((((unsigned long)block) + (j << 1)) & 0x0000000F) ; j++) {
+ level = block[j];
+ if (level) {
+ if (level < 0) {
+ level = level * qmul - qadd;
+ } else {
+ level = level * qmul + qadd;
+ }
+ block[j] = level;
+ }
+ }
+#endif
+
+ // 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;
+ }
+ }
+POWERPC_PERF_STOP_COUNT(altivec_dct_unquantize_h263_num, nCoeffs == 63);
+}
diff --git a/contrib/ffmpeg/libavcodec/ppc/mpegvideo_ppc.c b/contrib/ffmpeg/libavcodec/ppc/mpegvideo_ppc.c
new file mode 100644
index 000000000..c5e822f77
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/mpegvideo_ppc.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2002 Dieter Shirley
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * 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 "../mpegvideo.h"
+#include <time.h>
+
+#ifdef HAVE_ALTIVEC
+#include "dsputil_altivec.h"
+#endif
+
+extern int dct_quantize_altivec(MpegEncContext *s,
+ DCTELEM *block, int n,
+ int qscale, int *overflow);
+extern void dct_unquantize_h263_altivec(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale);
+
+extern void idct_put_altivec(uint8_t *dest, int line_size, int16_t *block);
+extern void idct_add_altivec(uint8_t *dest, int line_size, int16_t *block);
+
+
+void MPV_common_init_ppc(MpegEncContext *s)
+{
+#ifdef HAVE_ALTIVEC
+ if (has_altivec())
+ {
+ if (s->avctx->lowres==0)
+ {
+ if ((s->avctx->idct_algo == FF_IDCT_AUTO) ||
+ (s->avctx->idct_algo == FF_IDCT_ALTIVEC))
+ {
+ s->dsp.idct_put = idct_put_altivec;
+ s->dsp.idct_add = idct_add_altivec;
+ s->dsp.idct_permutation_type = FF_TRANSPOSE_IDCT_PERM;
+ }
+ }
+
+ // Test to make sure that the dct required alignments are met.
+ if ((((long)(s->q_intra_matrix) & 0x0f) != 0) ||
+ (((long)(s->q_inter_matrix) & 0x0f) != 0))
+ {
+ av_log(s->avctx, AV_LOG_INFO, "Internal Error: q-matrix blocks must be 16-byte aligned "
+ "to use Altivec DCT. Reverting to non-altivec version.\n");
+ return;
+ }
+
+ if (((long)(s->intra_scantable.inverse) & 0x0f) != 0)
+ {
+ av_log(s->avctx, AV_LOG_INFO, "Internal Error: scan table blocks must be 16-byte aligned "
+ "to use Altivec DCT. Reverting to non-altivec version.\n");
+ return;
+ }
+
+
+ if ((s->avctx->dct_algo == FF_DCT_AUTO) ||
+ (s->avctx->dct_algo == FF_DCT_ALTIVEC))
+ {
+#if 0 /* seems to cause trouble under some circumstances */
+ s->dct_quantize = dct_quantize_altivec;
+#endif
+ s->dct_unquantize_h263_intra = dct_unquantize_h263_altivec;
+ s->dct_unquantize_h263_inter = dct_unquantize_h263_altivec;
+ }
+ } else
+#endif
+ {
+ /* Non-AltiVec PPC optimisations here */
+ }
+}
+
diff --git a/contrib/ffmpeg/libavcodec/ppc/snow_altivec.c b/contrib/ffmpeg/libavcodec/ppc/snow_altivec.c
new file mode 100644
index 000000000..b15672ffe
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/snow_altivec.c
@@ -0,0 +1,788 @@
+/*
+ * Altivec optimized snow DSP utils
+ * Copyright (c) 2006 Luca Barbato <lu_zero@gentoo.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
+ *
+ *
+ */
+
+#include "../dsputil.h"
+
+#include "gcc_fixes.h"
+#include "dsputil_altivec.h"
+#include "../snow.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+
+
+//FIXME remove this replication
+#define slice_buffer_get_line(slice_buf, line_num) ((slice_buf)->line[line_num] ? (slice_buf)->line[line_num] : slice_buffer_load_line((slice_buf), (line_num)))
+
+static DWTELEM * slice_buffer_load_line(slice_buffer * buf, int line)
+{
+ int offset;
+ DWTELEM * buffer;
+
+// av_log(NULL, AV_LOG_DEBUG, "Cache hit: %d\n", line);
+
+ assert(buf->data_stack_top >= 0);
+// assert(!buf->line[line]);
+ if (buf->line[line])
+ return buf->line[line];
+
+ offset = buf->line_width * line;
+ buffer = buf->data_stack[buf->data_stack_top];
+ buf->data_stack_top--;
+ buf->line[line] = buffer;
+
+// av_log(NULL, AV_LOG_DEBUG, "slice_buffer_load_line: line: %d remaining: %d\n", line, buf->data_stack_top + 1);
+
+ return buffer;
+}
+
+
+//altivec code
+
+void ff_snow_horizontal_compose97i_altivec(DWTELEM *b, int width)
+{
+ const int w2= (width+1)>>1;
+ DECLARE_ALIGNED_16(DWTELEM, temp[(width>>1)]);
+ const int w_l= (width>>1);
+ const int w_r= w2 - 1;
+ int i;
+ vector signed int t1, t2, x, y, tmp1, tmp2;
+ vector signed int *vbuf, *vtmp;
+ vector unsigned char align;
+
+
+
+ { // Lift 0
+ DWTELEM * const ref = b + w2 - 1;
+ DWTELEM b_0 = b[0];
+ vbuf = (vector signed int *)b;
+
+ tmp1 = vec_ld (0, ref);
+ align = vec_lvsl (0, ref);
+ tmp2 = vec_ld (15, ref);
+ t1= vec_perm(tmp1, tmp2, align);
+
+ i = 0;
+
+ for (i=0; i<w_l-15; i+=16) {
+#if 0
+ b[i+0] = b[i+0] - ((3 * (ref[i+0] + ref[i+1]) + 4) >> 3);
+ b[i+1] = b[i+1] - ((3 * (ref[i+1] + ref[i+2]) + 4) >> 3);
+ b[i+2] = b[i+2] - ((3 * (ref[i+2] + ref[i+3]) + 4) >> 3);
+ b[i+3] = b[i+3] - ((3 * (ref[i+3] + ref[i+4]) + 4) >> 3);
+#else
+
+ tmp1 = vec_ld (0, ref+4+i);
+ tmp2 = vec_ld (15, ref+4+i);
+
+ t2 = vec_perm(tmp1, tmp2, align);
+
+ y = vec_add(t1,vec_sld(t1,t2,4));
+ y = vec_add(vec_add(y,y),y);
+
+ tmp1 = vec_ld (0, ref+8+i);
+
+ y = vec_add(y, vec_splat_s32(4));
+ y = vec_sra(y, vec_splat_u32(3));
+
+ tmp2 = vec_ld (15, ref+8+i);
+
+ *vbuf = vec_sub(*vbuf, y);
+
+ t1=t2;
+
+ vbuf++;
+
+ t2 = vec_perm(tmp1, tmp2, align);
+
+ y = vec_add(t1,vec_sld(t1,t2,4));
+ y = vec_add(vec_add(y,y),y);
+
+ tmp1 = vec_ld (0, ref+12+i);
+
+ y = vec_add(y, vec_splat_s32(4));
+ y = vec_sra(y, vec_splat_u32(3));
+
+ tmp2 = vec_ld (15, ref+12+i);
+
+ *vbuf = vec_sub(*vbuf, y);
+
+ t1=t2;
+
+ vbuf++;
+
+ t2 = vec_perm(tmp1, tmp2, align);
+
+ y = vec_add(t1,vec_sld(t1,t2,4));
+ y = vec_add(vec_add(y,y),y);
+
+ tmp1 = vec_ld (0, ref+16+i);
+
+ y = vec_add(y, vec_splat_s32(4));
+ y = vec_sra(y, vec_splat_u32(3));
+
+ tmp2 = vec_ld (15, ref+16+i);
+
+ *vbuf = vec_sub(*vbuf, y);
+
+ t1=t2;
+
+ t2 = vec_perm(tmp1, tmp2, align);
+
+ y = vec_add(t1,vec_sld(t1,t2,4));
+ y = vec_add(vec_add(y,y),y);
+
+ vbuf++;
+
+ y = vec_add(y, vec_splat_s32(4));
+ y = vec_sra(y, vec_splat_u32(3));
+ *vbuf = vec_sub(*vbuf, y);
+
+ t1=t2;
+
+ vbuf++;
+
+#endif
+ }
+
+ snow_horizontal_compose_lift_lead_out(i, b, b, ref, width, w_l, 0, W_DM, W_DO, W_DS);
+ b[0] = b_0 - ((W_DM * 2 * ref[1]+W_DO)>>W_DS);
+ }
+
+ { // Lift 1
+ DWTELEM * const dst = b+w2;
+
+ i = 0;
+ for(; (((long)&dst[i]) & 0xF) && i<w_r; i++){
+ dst[i] = dst[i] - (b[i] + b[i + 1]);
+ }
+
+ align = vec_lvsl(0, b+i);
+ tmp1 = vec_ld(0, b+i);
+ vbuf = (vector signed int*) (dst + i);
+ tmp2 = vec_ld(15, b+i);
+
+ t1 = vec_perm(tmp1, tmp2, align);
+
+ for (; i<w_r-3; i+=4) {
+
+#if 0
+ dst[i] = dst[i] - (b[i] + b[i + 1]);
+ dst[i+1] = dst[i+1] - (b[i+1] + b[i + 2]);
+ dst[i+2] = dst[i+2] - (b[i+2] + b[i + 3]);
+ dst[i+3] = dst[i+3] - (b[i+3] + b[i + 4]);
+#else
+
+ tmp1 = vec_ld(0, b+4+i);
+ tmp2 = vec_ld(15, b+4+i);
+
+ t2 = vec_perm(tmp1, tmp2, align);
+
+ y = vec_add(t1, vec_sld(t1,t2,4));
+ *vbuf = vec_sub (*vbuf, y);
+
+ vbuf++;
+
+ t1 = t2;
+
+#endif
+
+ }
+
+ snow_horizontal_compose_lift_lead_out(i, dst, dst, b, width, w_r, 1, W_CM, W_CO, W_CS);
+ }
+
+ { // Lift 2
+ DWTELEM * const ref = b+w2 - 1;
+ DWTELEM b_0 = b[0];
+ vbuf= (vector signed int *) b;
+
+ tmp1 = vec_ld (0, ref);
+ align = vec_lvsl (0, ref);
+ tmp2 = vec_ld (15, ref);
+ t1= vec_perm(tmp1, tmp2, align);
+
+ i = 0;
+ for (; i<w_l-15; i+=16) {
+#if 0
+ b[i] = b[i] - (((8 -(ref[i] + ref[i+1])) - (b[i] <<2)) >> 4);
+ b[i+1] = b[i+1] - (((8 -(ref[i+1] + ref[i+2])) - (b[i+1]<<2)) >> 4);
+ b[i+2] = b[i+2] - (((8 -(ref[i+2] + ref[i+3])) - (b[i+2]<<2)) >> 4);
+ b[i+3] = b[i+3] - (((8 -(ref[i+3] + ref[i+4])) - (b[i+3]<<2)) >> 4);
+#else
+ tmp1 = vec_ld (0, ref+4+i);
+ tmp2 = vec_ld (15, ref+4+i);
+
+ t2 = vec_perm(tmp1, tmp2, align);
+
+ y = vec_add(t1,vec_sld(t1,t2,4));
+ y = vec_sub(vec_splat_s32(8),y);
+
+ tmp1 = vec_ld (0, ref+8+i);
+
+ x = vec_sl(*vbuf,vec_splat_u32(2));
+ y = vec_sra(vec_sub(y,x),vec_splat_u32(4));
+
+ tmp2 = vec_ld (15, ref+8+i);
+
+ *vbuf = vec_sub( *vbuf, y);
+
+ t1 = t2;
+
+ vbuf++;
+
+ t2 = vec_perm(tmp1, tmp2, align);
+
+ y = vec_add(t1,vec_sld(t1,t2,4));
+ y = vec_sub(vec_splat_s32(8),y);
+
+ tmp1 = vec_ld (0, ref+12+i);
+
+ x = vec_sl(*vbuf,vec_splat_u32(2));
+ y = vec_sra(vec_sub(y,x),vec_splat_u32(4));
+
+ tmp2 = vec_ld (15, ref+12+i);
+
+ *vbuf = vec_sub( *vbuf, y);
+
+ t1 = t2;
+
+ vbuf++;
+
+ t2 = vec_perm(tmp1, tmp2, align);
+
+ y = vec_add(t1,vec_sld(t1,t2,4));
+ y = vec_sub(vec_splat_s32(8),y);
+
+ tmp1 = vec_ld (0, ref+16+i);
+
+ x = vec_sl(*vbuf,vec_splat_u32(2));
+ y = vec_sra(vec_sub(y,x),vec_splat_u32(4));
+
+ tmp2 = vec_ld (15, ref+16+i);
+
+ *vbuf = vec_sub( *vbuf, y);
+
+ t1 = t2;
+
+ vbuf++;
+
+ t2 = vec_perm(tmp1, tmp2, align);
+
+ y = vec_add(t1,vec_sld(t1,t2,4));
+ y = vec_sub(vec_splat_s32(8),y);
+
+ t1 = t2;
+
+ x = vec_sl(*vbuf,vec_splat_u32(2));
+ y = vec_sra(vec_sub(y,x),vec_splat_u32(4));
+ *vbuf = vec_sub( *vbuf, y);
+
+ vbuf++;
+
+#endif
+ }
+
+ snow_horizontal_compose_liftS_lead_out(i, b, b, ref, width, w_l);
+ b[0] = b_0 - (((-2 * ref[1] + W_BO) - 4 * b_0) >> W_BS);
+ }
+
+ { // Lift 3
+ DWTELEM * const src = b+w2;
+
+ vbuf = (vector signed int *)b;
+ vtmp = (vector signed int *)temp;
+
+ i = 0;
+ align = vec_lvsl(0, src);
+
+ for (; i<w_r-3; i+=4) {
+#if 0
+ temp[i] = src[i] - ((-3*(b[i] + b[i+1]))>>1);
+ temp[i+1] = src[i+1] - ((-3*(b[i+1] + b[i+2]))>>1);
+ temp[i+2] = src[i+2] - ((-3*(b[i+2] + b[i+3]))>>1);
+ temp[i+3] = src[i+3] - ((-3*(b[i+3] + b[i+4]))>>1);
+#else
+ tmp1 = vec_ld(0,src+i);
+ t1 = vec_add(vbuf[0],vec_sld(vbuf[0],vbuf[1],4));
+ tmp2 = vec_ld(15,src+i);
+ t1 = vec_sub(vec_splat_s32(0),t1); //bad!
+ t1 = vec_add(t1,vec_add(t1,t1));
+ t2 = vec_perm(tmp1 ,tmp2 ,align);
+ t1 = vec_sra(t1,vec_splat_u32(1));
+ vbuf++;
+ *vtmp = vec_sub(t2,t1);
+ vtmp++;
+
+#endif
+
+ }
+
+ snow_horizontal_compose_lift_lead_out(i, temp, src, b, width, w_r, 1, -3, 0, 1);
+ }
+
+ {
+ //Interleave
+ int a;
+ vector signed int *t = (vector signed int *)temp,
+ *v = (vector signed int *)b;
+
+ snow_interleave_line_header(&i, width, b, temp);
+
+ for (; (i & 0xE) != 0xE; i-=2){
+ b[i+1] = temp[i>>1];
+ b[i] = b[i>>1];
+ }
+ for (i-=14; i>=0; i-=16){
+ a=i/4;
+
+ v[a+3]=vec_mergel(v[(a>>1)+1],t[(a>>1)+1]);
+ v[a+2]=vec_mergeh(v[(a>>1)+1],t[(a>>1)+1]);
+ v[a+1]=vec_mergel(v[a>>1],t[a>>1]);
+ v[a]=vec_mergeh(v[a>>1],t[a>>1]);
+
+ }
+
+ }
+}
+
+void ff_snow_vertical_compose97i_altivec(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, DWTELEM *b3, DWTELEM *b4, DWTELEM *b5, int width)
+{
+ int i, w4 = width/4;
+ vector signed int *v0, *v1,*v2,*v3,*v4,*v5;
+ vector signed int t1, t2;
+
+ v0=(vector signed int *)b0;
+ v1=(vector signed int *)b1;
+ v2=(vector signed int *)b2;
+ v3=(vector signed int *)b3;
+ v4=(vector signed int *)b4;
+ v5=(vector signed int *)b5;
+
+ for (i=0; i< w4;i++)
+ {
+
+ #if 0
+ b4[i] -= (3*(b3[i] + b5[i])+4)>>3;
+ b3[i] -= ((b2[i] + b4[i]));
+ b2[i] += ((b1[i] + b3[i])+4*b2[i]+8)>>4;
+ b1[i] += (3*(b0[i] + b2[i]))>>1;
+ #else
+ t1 = vec_add(v3[i], v5[i]);
+ t2 = vec_add(t1, vec_add(t1,t1));
+ t1 = vec_add(t2, vec_splat_s32(4));
+ v4[i] = vec_sub(v4[i], vec_sra(t1,vec_splat_u32(3)));
+
+ v3[i] = vec_sub(v3[i], vec_add(v2[i], v4[i]));
+
+ t1 = vec_add(vec_splat_s32(8), vec_add(v1[i], v3[i]));
+ t2 = vec_sl(v2[i], vec_splat_u32(2));
+ v2[i] = vec_add(v2[i], vec_sra(vec_add(t1,t2),vec_splat_u32(4)));
+ t1 = vec_add(v0[i], v2[i]);
+ t2 = vec_add(t1, vec_add(t1,t1));
+ v1[i] = vec_add(v1[i], vec_sra(t2,vec_splat_u32(1)));
+
+ #endif
+ }
+
+ for(i*=4; 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;
+ }
+}
+
+#define LOAD_BLOCKS \
+ tmp1 = vec_ld(0, &block[3][y*src_stride]);\
+ align = vec_lvsl(0, &block[3][y*src_stride]);\
+ tmp2 = vec_ld(15, &block[3][y*src_stride]);\
+\
+ b3 = vec_perm(tmp1,tmp2,align);\
+\
+ tmp1 = vec_ld(0, &block[2][y*src_stride]);\
+ align = vec_lvsl(0, &block[2][y*src_stride]);\
+ tmp2 = vec_ld(15, &block[2][y*src_stride]);\
+\
+ b2 = vec_perm(tmp1,tmp2,align);\
+\
+ tmp1 = vec_ld(0, &block[1][y*src_stride]);\
+ align = vec_lvsl(0, &block[1][y*src_stride]);\
+ tmp2 = vec_ld(15, &block[1][y*src_stride]);\
+\
+ b1 = vec_perm(tmp1,tmp2,align);\
+\
+ tmp1 = vec_ld(0, &block[0][y*src_stride]);\
+ align = vec_lvsl(0, &block[0][y*src_stride]);\
+ tmp2 = vec_ld(15, &block[0][y*src_stride]);\
+\
+ b0 = vec_perm(tmp1,tmp2,align);
+
+#define LOAD_OBMCS \
+ tmp1 = vec_ld(0, obmc1);\
+ align = vec_lvsl(0, obmc1);\
+ tmp2 = vec_ld(15, obmc1);\
+\
+ ob1 = vec_perm(tmp1,tmp2,align);\
+\
+ tmp1 = vec_ld(0, obmc2);\
+ align = vec_lvsl(0, obmc2);\
+ tmp2 = vec_ld(15, obmc2);\
+\
+ ob2 = vec_perm(tmp1,tmp2,align);\
+\
+ tmp1 = vec_ld(0, obmc3);\
+ align = vec_lvsl(0, obmc3);\
+ tmp2 = vec_ld(15, obmc3);\
+\
+ ob3 = vec_perm(tmp1,tmp2,align);\
+\
+ tmp1 = vec_ld(0, obmc4);\
+ align = vec_lvsl(0, obmc4);\
+ tmp2 = vec_ld(15, obmc4);\
+\
+ ob4 = vec_perm(tmp1,tmp2,align);
+
+/* interleave logic
+ * h1 <- [ a,b,a,b, a,b,a,b, a,b,a,b, a,b,a,b ]
+ * h2 <- [ c,d,c,d, c,d,c,d, c,d,c,d, c,d,c,d ]
+ * h <- [ a,b,c,d, a,b,c,d, a,b,c,d, a,b,c,d ]
+ */
+
+#define STEPS_0_1\
+ h1 = (vector unsigned short)\
+ vec_mergeh(ob1, ob2);\
+\
+ h2 = (vector unsigned short)\
+ vec_mergeh(ob3, ob4);\
+\
+ ih = (vector unsigned char)\
+ vec_mergeh(h1,h2);\
+\
+ l1 = (vector unsigned short) vec_mergeh(b3, b2);\
+\
+ ih1 = (vector unsigned char) vec_mergel(h1, h2);\
+\
+ l2 = (vector unsigned short) vec_mergeh(b1, b0);\
+\
+ il = (vector unsigned char) vec_mergeh(l1, l2);\
+\
+ v[0] = (vector signed int) vec_msum(ih, il, vec_splat_u32(0));\
+\
+ il1 = (vector unsigned char) vec_mergel(l1, l2);\
+\
+ v[1] = (vector signed int) vec_msum(ih1, il1, vec_splat_u32(0));
+
+#define FINAL_STEP_SCALAR\
+ for(x=0; x<b_w; x++)\
+ if(add){\
+ vbuf[x] += dst[x + src_x];\
+ vbuf[x] = (vbuf[x] + (1<<(FRAC_BITS-1))) >> FRAC_BITS;\
+ if(vbuf[x]&(~255)) vbuf[x]= ~(vbuf[x]>>31);\
+ dst8[x + y*src_stride] = vbuf[x];\
+ }else{\
+ dst[x + src_x] -= vbuf[x];\
+ }
+
+static void inner_add_yblock_bw_8_obmc_16_altivec(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;
+ DWTELEM * dst;
+ vector unsigned short h1, h2, l1, l2;
+ vector unsigned char ih, il, ih1, il1, tmp1, tmp2, align;
+ vector unsigned char b0,b1,b2,b3;
+ vector unsigned char ob1,ob2,ob3,ob4;
+
+ DECLARE_ALIGNED_16(int, vbuf[16]);
+ vector signed int *v = (vector signed int *)vbuf, *d;
+
+ for(y=0; y<b_h; y++){
+ //FIXME ugly missue of obmc_stride
+
+ uint8_t *obmc1= obmc + y*obmc_stride;
+ uint8_t *obmc2= obmc1+ (obmc_stride>>1);
+ uint8_t *obmc3= obmc1+ obmc_stride*(obmc_stride>>1);
+ uint8_t *obmc4= obmc3+ (obmc_stride>>1);
+
+ dst = slice_buffer_get_line(sb, src_y + y);
+ d = (vector signed int *)(dst + src_x);
+
+//FIXME i could avoid some loads!
+
+ // load blocks
+ LOAD_BLOCKS
+
+ // load obmcs
+ LOAD_OBMCS
+
+ // steps 0 1
+ STEPS_0_1
+
+ FINAL_STEP_SCALAR
+
+ }
+
+}
+
+#define STEPS_2_3\
+ h1 = (vector unsigned short) vec_mergel(ob1, ob2);\
+\
+ h2 = (vector unsigned short) vec_mergel(ob3, ob4);\
+\
+ ih = (vector unsigned char) vec_mergeh(h1,h2);\
+\
+ l1 = (vector unsigned short) vec_mergel(b3, b2);\
+\
+ l2 = (vector unsigned short) vec_mergel(b1, b0);\
+\
+ ih1 = (vector unsigned char) vec_mergel(h1,h2);\
+\
+ il = (vector unsigned char) vec_mergeh(l1,l2);\
+\
+ v[2] = (vector signed int) vec_msum(ih, il, vec_splat_u32(0));\
+\
+ il1 = (vector unsigned char) vec_mergel(l1,l2);\
+\
+ v[3] = (vector signed int) vec_msum(ih1, il1, vec_splat_u32(0));
+
+
+static void inner_add_yblock_bw_16_obmc_32_altivec(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;
+ DWTELEM * dst;
+ vector unsigned short h1, h2, l1, l2;
+ vector unsigned char ih, il, ih1, il1, tmp1, tmp2, align;
+ vector unsigned char b0,b1,b2,b3;
+ vector unsigned char ob1,ob2,ob3,ob4;
+ DECLARE_ALIGNED_16(int, vbuf[b_w]);
+ vector signed int *v = (vector signed int *)vbuf, *d;
+
+ for(y=0; y<b_h; y++){
+ //FIXME ugly missue of obmc_stride
+
+ uint8_t *obmc1= obmc + y*obmc_stride;
+ uint8_t *obmc2= obmc1+ (obmc_stride>>1);
+ uint8_t *obmc3= obmc1+ obmc_stride*(obmc_stride>>1);
+ uint8_t *obmc4= obmc3+ (obmc_stride>>1);
+
+ dst = slice_buffer_get_line(sb, src_y + y);
+ d = (vector signed int *)(dst + src_x);
+
+ // load blocks
+ LOAD_BLOCKS
+
+ // load obmcs
+ LOAD_OBMCS
+
+ // steps 0 1 2 3
+ STEPS_0_1
+
+ STEPS_2_3
+
+ FINAL_STEP_SCALAR
+
+ }
+}
+
+#define FINAL_STEP_VEC \
+\
+ if(add)\
+ {\
+ for(x=0; x<b_w/4; x++)\
+ {\
+ v[x] = vec_add(v[x], d[x]);\
+ v[x] = vec_sra(vec_add(v[x],\
+ vec_sl( vec_splat_s32(1),\
+ vec_splat_u32(7))),\
+ vec_splat_u32(8));\
+\
+ mask = (vector bool int) vec_sl((vector signed int)\
+ vec_cmpeq(v[x],v[x]),vec_splat_u32(8));\
+ mask = (vector bool int) vec_and(v[x],vec_nor(mask,mask));\
+\
+ mask = (vector bool int)\
+ vec_cmpeq((vector signed int)mask,\
+ (vector signed int)vec_splat_u32(0));\
+\
+ vs = vec_sra(v[x],vec_splat_u32(8));\
+ vs = vec_sra(v[x],vec_splat_u32(8));\
+ vs = vec_sra(v[x],vec_splat_u32(15));\
+\
+ vs = vec_nor(vs,vs);\
+\
+ v[x]= vec_sel(v[x],vs,mask);\
+ }\
+\
+ for(x=0; x<b_w; x++)\
+ dst8[x + y*src_stride] = vbuf[x];\
+\
+ }\
+ else\
+ for(x=0; x<b_w/4; x++)\
+ d[x] = vec_sub(d[x], v[x]);
+
+static void inner_add_yblock_a_bw_8_obmc_16_altivec(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;
+ DWTELEM * dst;
+ vector bool int mask;
+ vector signed int vs;
+ vector unsigned short h1, h2, l1, l2;
+ vector unsigned char ih, il, ih1, il1, tmp1, tmp2, align;
+ vector unsigned char b0,b1,b2,b3;
+ vector unsigned char ob1,ob2,ob3,ob4;
+
+ DECLARE_ALIGNED_16(int, vbuf[16]);
+ vector signed int *v = (vector signed int *)vbuf, *d;
+
+ for(y=0; y<b_h; y++){
+ //FIXME ugly missue of obmc_stride
+
+ uint8_t *obmc1= obmc + y*obmc_stride;
+ uint8_t *obmc2= obmc1+ (obmc_stride>>1);
+ uint8_t *obmc3= obmc1+ obmc_stride*(obmc_stride>>1);
+ uint8_t *obmc4= obmc3+ (obmc_stride>>1);
+
+ dst = slice_buffer_get_line(sb, src_y + y);
+ d = (vector signed int *)(dst + src_x);
+
+//FIXME i could avoid some loads!
+
+ // load blocks
+ LOAD_BLOCKS
+
+ // load obmcs
+ LOAD_OBMCS
+
+ // steps 0 1
+ STEPS_0_1
+
+ FINAL_STEP_VEC
+
+ }
+
+}
+
+static void inner_add_yblock_a_bw_16_obmc_32_altivec(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;
+ DWTELEM * dst;
+ vector bool int mask;
+ vector signed int vs;
+ vector unsigned short h1, h2, l1, l2;
+ vector unsigned char ih, il, ih1, il1, tmp1, tmp2, align;
+ vector unsigned char b0,b1,b2,b3;
+ vector unsigned char ob1,ob2,ob3,ob4;
+ DECLARE_ALIGNED_16(int, vbuf[b_w]);
+ vector signed int *v = (vector signed int *)vbuf, *d;
+
+ for(y=0; y<b_h; y++){
+ //FIXME ugly missue of obmc_stride
+
+ uint8_t *obmc1= obmc + y*obmc_stride;
+ uint8_t *obmc2= obmc1+ (obmc_stride>>1);
+ uint8_t *obmc3= obmc1+ obmc_stride*(obmc_stride>>1);
+ uint8_t *obmc4= obmc3+ (obmc_stride>>1);
+
+ dst = slice_buffer_get_line(sb, src_y + y);
+ d = (vector signed int *)(dst + src_x);
+
+ // load blocks
+ LOAD_BLOCKS
+
+ // load obmcs
+ LOAD_OBMCS
+
+ // steps 0 1 2 3
+ STEPS_0_1
+
+ STEPS_2_3
+
+ FINAL_STEP_VEC
+
+ }
+}
+
+
+void ff_snow_inner_add_yblock_altivec(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 (src_x&15) {
+ if (b_w == 16)
+ inner_add_yblock_bw_16_obmc_32_altivec(obmc, obmc_stride, block,
+ b_w, b_h, src_x, src_y,
+ src_stride, sb, add, dst8);
+ else if (b_w == 8)
+ inner_add_yblock_bw_8_obmc_16_altivec(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);
+ } else {
+ if (b_w == 16)
+ inner_add_yblock_a_bw_16_obmc_32_altivec(obmc, obmc_stride, block,
+ b_w, b_h, src_x, src_y,
+ src_stride, sb, add, dst8);
+ else if (b_w == 8)
+ inner_add_yblock_a_bw_8_obmc_16_altivec(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);
+ }
+}
+
+
+void snow_init_altivec(DSPContext* c, AVCodecContext *avctx)
+{
+ c->horizontal_compose97i = ff_snow_horizontal_compose97i_altivec;
+ c->vertical_compose97i = ff_snow_vertical_compose97i_altivec;
+ c->inner_add_yblock = ff_snow_inner_add_yblock_altivec;
+}
diff --git a/contrib/ffmpeg/libavcodec/ppc/types_altivec.h b/contrib/ffmpeg/libavcodec/ppc/types_altivec.h
new file mode 100644
index 000000000..f29026e04
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/types_altivec.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2006 Guillaume Poirier <gpoirier@mplayerhq.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
+ */
+
+/***********************************************************************
+ * Vector types
+ **********************************************************************/
+#define vec_u8_t vector unsigned char
+#define vec_s8_t vector signed char
+#define vec_u16_t vector unsigned short
+#define vec_s16_t vector signed short
+#define vec_u32_t vector unsigned int
+#define vec_s32_t vector signed int
+
+/***********************************************************************
+ * Null vector
+ **********************************************************************/
+#define LOAD_ZERO const vec_u8_t zerov = vec_splat_u8( 0 )
+
+#define zero_u8v (vec_u8_t) zerov
+#define zero_s8v (vec_s8_t) zerov
+#define zero_u16v (vec_u16_t) zerov
+#define zero_s16v (vec_s16_t) zerov
+#define zero_u32v (vec_u32_t) zerov
+#define zero_s32v (vec_s32_t) zerov
diff --git a/contrib/ffmpeg/libavcodec/ppc/vc1dsp_altivec.c b/contrib/ffmpeg/libavcodec/ppc/vc1dsp_altivec.c
new file mode 100644
index 000000000..114c9d41f
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ppc/vc1dsp_altivec.c
@@ -0,0 +1,338 @@
+/*
+ * 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 "../dsputil.h"
+
+#include "gcc_fixes.h"
+
+#include "dsputil_altivec.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(DCTELEM 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_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 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);
+
+ 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_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(DCTELEM block[64], int n)
+{
+ 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);
+
+ 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);
+
+ if(!n){ // upper half of block
+ 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);
+
+ vec_st(src0, 0, block);
+ vec_st(src1, 16, block);
+ vec_st(src2, 32, block);
+ vec_st(src3, 48, block);
+ } else { //lower half of block
+ s0 = vec_unpackh(src4);
+ s1 = vec_unpackh(src5);
+ s2 = vec_unpackh(src6);
+ s3 = vec_unpackh(src7);
+ s8 = vec_unpackl(src4);
+ s9 = vec_unpackl(src5);
+ sA = vec_unpackl(src6);
+ sB = vec_unpackl(src7);
+ 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);
+ src4 = vec_pack(s0, s8);
+ src5 = vec_pack(s1, s9);
+ src6 = vec_pack(s2, sA);
+ src7 = vec_pack(s3, sB);
+
+ vec_st(src4, 64, block);
+ vec_st(src5, 80, block);
+ vec_st(src6, 96, block);
+ vec_st(src7,112, block);
+ }
+}
+
+
+void vc1dsp_init_altivec(DSPContext* dsp, AVCodecContext *avctx) {
+ dsp->vc1_inv_trans_8x8 = vc1_inv_trans_8x8_altivec;
+ dsp->vc1_inv_trans_8x4 = vc1_inv_trans_8x4_altivec;
+}
diff --git a/contrib/ffmpeg/libavcodec/ps2/dsputil_mmi.c b/contrib/ffmpeg/libavcodec/ps2/dsputil_mmi.c
new file mode 100644
index 000000000..0d72ae88c
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ps2/dsputil_mmi.c
@@ -0,0 +1,163 @@
+/*
+ * MMI optimized DSP utils
+ * 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
+ *
+ * MMI optimization by Leon van Stuivenberg
+ * clear_blocks_mmi() by BroadQ
+ */
+
+#include "../dsputil.h"
+#include "mmi.h"
+
+void ff_mmi_idct_put(uint8_t *dest, int line_size, DCTELEM *block);
+void ff_mmi_idct_add(uint8_t *dest, int line_size, DCTELEM *block);
+void ff_mmi_idct(DCTELEM *block);
+
+static void clear_blocks_mmi(DCTELEM * blocks)
+{
+ asm volatile(
+ ".set noreorder \n"
+ "addiu $9, %0, 768 \n"
+ "nop \n"
+ "1: \n"
+ "sq $0, 0(%0) \n"
+ "move $8, %0 \n"
+ "addi %0, %0, 64 \n"
+ "sq $0, 16($8) \n"
+ "slt $10, %0, $9 \n"
+ "sq $0, 32($8) \n"
+ "bnez $10, 1b \n"
+ "sq $0, 48($8) \n"
+ ".set reorder \n"
+ : "+r" (blocks) :: "$8", "$9", "memory" );
+}
+
+
+static void get_pixels_mmi(DCTELEM *block, const uint8_t *pixels, int line_size)
+{
+ asm volatile(
+ ".set push \n\t"
+ ".set mips3 \n\t"
+ "ld $8, 0(%0) \n\t"
+ "add %0, %0, %2 \n\t"
+ "ld $9, 0(%0) \n\t"
+ "add %0, %0, %2 \n\t"
+ "ld $10, 0(%0) \n\t"
+ "pextlb $8, $0, $8 \n\t"
+ "sq $8, 0(%1) \n\t"
+ "add %0, %0, %2 \n\t"
+ "ld $8, 0(%0) \n\t"
+ "pextlb $9, $0, $9 \n\t"
+ "sq $9, 16(%1) \n\t"
+ "add %0, %0, %2 \n\t"
+ "ld $9, 0(%0) \n\t"
+ "pextlb $10, $0, $10 \n\t"
+ "sq $10, 32(%1) \n\t"
+ "add %0, %0, %2 \n\t"
+ "ld $10, 0(%0) \n\t"
+ "pextlb $8, $0, $8 \n\t"
+ "sq $8, 48(%1) \n\t"
+ "add %0, %0, %2 \n\t"
+ "ld $8, 0(%0) \n\t"
+ "pextlb $9, $0, $9 \n\t"
+ "sq $9, 64(%1) \n\t"
+ "add %0, %0, %2 \n\t"
+ "ld $9, 0(%0) \n\t"
+ "pextlb $10, $0, $10 \n\t"
+ "sq $10, 80(%1) \n\t"
+ "pextlb $8, $0, $8 \n\t"
+ "sq $8, 96(%1) \n\t"
+ "pextlb $9, $0, $9 \n\t"
+ "sq $9, 112(%1) \n\t"
+ ".set pop \n\t"
+ : "+r" (pixels) : "r" (block), "r" (line_size) : "$8", "$9", "$10", "memory" );
+}
+
+
+static void put_pixels8_mmi(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ asm volatile(
+ ".set push \n\t"
+ ".set mips3 \n\t"
+ "1: \n\t"
+ "ldr $8, 0(%1) \n\t"
+ "addiu %2, %2, -1 \n\t"
+ "ldl $8, 7(%1) \n\t"
+ "add %1, %1, %3 \n\t"
+ "sd $8, 0(%0) \n\t"
+ "add %0, %0, %3 \n\t"
+ "bgtz %2, 1b \n\t"
+ ".set pop \n\t"
+ : "+r" (block), "+r" (pixels), "+r" (h) : "r" (line_size)
+ : "$8", "memory" );
+}
+
+
+static void put_pixels16_mmi(uint8_t *block, const uint8_t *pixels, int line_size, int h)
+{
+ asm volatile (
+ ".set push \n\t"
+ ".set mips3 \n\t"
+ "1: \n\t"
+ "ldr $8, 0(%1) \n\t"
+ "add $11, %1, %3 \n\t"
+ "ldl $8, 7(%1) \n\t"
+ "add $10, %0, %3 \n\t"
+ "ldr $9, 8(%1) \n\t"
+ "ldl $9, 15(%1) \n\t"
+ "ldr $12, 0($11) \n\t"
+ "add %1, $11, %3 \n\t"
+ "ldl $12, 7($11) \n\t"
+ "pcpyld $8, $9, $8 \n\t"
+ "sq $8, 0(%0) \n\t"
+ "ldr $13, 8($11) \n\t"
+ "addiu %2, %2, -2 \n\t"
+ "ldl $13, 15($11) \n\t"
+ "add %0, $10, %3 \n\t"
+ "pcpyld $12, $13, $12 \n\t"
+ "sq $12, 0($10) \n\t"
+ "bgtz %2, 1b \n\t"
+ ".set pop \n\t"
+ : "+r" (block), "+r" (pixels), "+r" (h) : "r" (line_size)
+ : "$8", "$9", "$10", "$11", "$12", "$13", "memory" );
+}
+
+
+void dsputil_init_mmi(DSPContext* c, AVCodecContext *avctx)
+{
+ const int idct_algo= avctx->idct_algo;
+
+ c->clear_blocks = clear_blocks_mmi;
+
+ c->put_pixels_tab[1][0] = put_pixels8_mmi;
+ c->put_no_rnd_pixels_tab[1][0] = put_pixels8_mmi;
+
+ c->put_pixels_tab[0][0] = put_pixels16_mmi;
+ c->put_no_rnd_pixels_tab[0][0] = put_pixels16_mmi;
+
+ c->get_pixels = get_pixels_mmi;
+
+ if(idct_algo==FF_IDCT_AUTO || idct_algo==FF_IDCT_PS2){
+ c->idct_put= ff_mmi_idct_put;
+ c->idct_add= ff_mmi_idct_add;
+ c->idct = ff_mmi_idct;
+ c->idct_permutation_type= FF_LIBMPEG2_IDCT_PERM;
+ }
+}
+
diff --git a/contrib/ffmpeg/libavcodec/ps2/idct_mmi.c b/contrib/ffmpeg/libavcodec/ps2/idct_mmi.c
new file mode 100644
index 000000000..dfe9b3726
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ps2/idct_mmi.c
@@ -0,0 +1,363 @@
+/*
+ * Originally provided by Intel at Application Note AP-922.
+ *
+ * Column code adapted from Peter Gubanov.
+ * Copyright (c) 2000-2001 Peter Gubanov <peter@elecard.net.ru>
+ * http://www.elecard.com/peter/idct.shtml
+ * rounding trick copyright (c) 2000 Michel Lespinasse <walken@zoy.org>
+ *
+ * MMI port and (c) 2002 by Leon van Stuivenberg
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+*/
+
+#include "../common.h"
+#include "../dsputil.h"
+#include "mmi.h"
+
+#define BITS_INV_ACC 5 // 4 or 5 for IEEE
+#define SHIFT_INV_ROW (16 - BITS_INV_ACC)
+#define SHIFT_INV_COL (1 + BITS_INV_ACC)
+
+#define TG1 6518
+#define TG2 13573
+#define TG3 21895
+#define CS4 23170
+
+#define ROUNDER_0 0
+#define ROUNDER_1 16
+
+#define TAB_i_04 (32+0)
+#define TAB_i_17 (32+64)
+#define TAB_i_26 (32+128)
+#define TAB_i_35 (32+192)
+
+#define TG_1_16 (32+256+0)
+#define TG_2_16 (32+256+16)
+#define TG_3_16 (32+256+32)
+#define COS_4_16 (32+256+48)
+
+#define CLIPMAX (32+256+64+0)
+
+static short consttable[] align16 = {
+/* rounder 0*/ // assume SHIFT_INV_ROW == 11
+ 0x3ff, 1, 0x3ff, 1, 0x3ff, 1, 0x3ff, 1,
+/* rounder 1*/
+ 0x3ff, 0, 0x3ff, 0, 0x3ff, 0, 0x3ff, 0,
+/* row 0/4*/
+ 16384, 21407, -16384, -21407, 22725, 19266, -22725, -12873,
+ 8867, 16384, 8867, 16384, 4520, 12873, -4520, 19266,
+ 16384, -8867, 16384, -8867, 12873, -22725, 19266, -22725,
+ 21407, -16384, -21407, 16384, 19266, 4520, -12873, 4520,
+/* row 1/7*/
+ 22725, 29692, -22725, -29692, 31521, 26722, -31521, -17855,
+ 12299, 22725, 12299, 22725, 6270, 17855, -6270, 26722,
+ 22725, -12299, 22725, -12299, 17855, -31521, 26722, -31521,
+ 29692, -22725, -29692, 22725, 26722, 6270, -17855, 6270,
+/* row 2/6*/
+ 21407, 27969, -21407, -27969, 29692, 25172, -29692, -16819,
+ 11585, 21407, 11585, 21407, 5906, 16819, -5906, 25172,
+ 21407, -11585, 21407, -11585, 16819, -29692, 25172, -29692,
+ 27969, -21407, -27969, 21407, 25172, 5906, -16819, 5906,
+/*row 3/5*/
+ 19266, 25172, -19266, -25172, 26722, 22654, -26722, -15137,
+ 10426, 19266, 10426, 19266, 5315, 15137, -5315, 22654,
+ 19266, -10426, 19266, -10426, 15137, -26722, 22654, -26722,
+ 25172, -19266, -25172, 19266, 22654, 5315, -15137, 5315,
+/*column constants*/
+ TG1, TG1, TG1, TG1, TG1, TG1, TG1, TG1,
+ TG2, TG2, TG2, TG2, TG2, TG2, TG2, TG2,
+ TG3, TG3, TG3, TG3, TG3, TG3, TG3, TG3,
+ CS4, CS4, CS4, CS4, CS4, CS4, CS4, CS4,
+/* clamp */
+ 255, 255, 255, 255, 255, 255, 255, 255
+};
+
+
+#define DCT_8_INV_ROW1(blk, rowoff, taboff, rnd, outreg) { \
+ lq(blk, rowoff, $16); /* r16 = x7 x5 x3 x1 x6 x4 x2 x0 */ \
+ /*slot*/ \
+ lq($24, 0+taboff, $17); /* r17 = w */ \
+ /*delay slot $16*/ \
+ lq($24, 16+taboff, $18);/* r18 = w */ \
+ prevh($16, $2); /* r2 = x1 x3 x5 x7 x0 x2 x4 x6 */ \
+ lq($24, 32+taboff, $19);/* r19 = w */ \
+ phmadh($17, $16, $17); /* r17 = b1"b0'a1"a0' */ \
+ lq($24, 48+taboff, $20);/* r20 = w */ \
+ phmadh($18, $2, $18); /* r18 = b1'b0"a1'a0" */ \
+ phmadh($19, $16, $19); /* r19 = b3"b2'a3"a2' */ \
+ phmadh($20, $2, $20); /* r20 = b3'b2"a3'a2" */ \
+ paddw($17, $18, $17); /* r17 = (b1)(b0)(a1)(a0) */ \
+ paddw($19, $20, $19); /* r19 = (b3)(b2)(a3)(a2) */ \
+ pcpyld($19, $17, $18); /* r18 = (a3)(a2)(a1)(a0) */ \
+ pcpyud($17, $19, $20); /* r20 = (b3)(b2)(b1)(b0) */ \
+ paddw($18, rnd, $18); /* r18 = (a3)(a2)(a1)(a0) */\
+ paddw($18, $20, $17); /* r17 = ()()()(a0+b0) */ \
+ psubw($18, $20, $20); /* r20 = ()()()(a0-b0) */ \
+ psraw($17, SHIFT_INV_ROW, $17); /* r17 = (y3 y2 y1 y0) */ \
+ psraw($20, SHIFT_INV_ROW, $20); /* r20 = (y4 y5 y6 y7) */ \
+ ppach($20, $17, outreg);/* out = y4 y5 y6 y7 y3 y2 y1 y0 Note order */ \
+\
+ prevh(outreg, $2); \
+ pcpyud($2, $2, $2); \
+ pcpyld($2, outreg, outreg); \
+}
+
+
+#define DCT_8_INV_COL8() \
+\
+ lq($24, TG_3_16, $2); /* r2 = tn3 */ \
+\
+ pmulth($11, $2, $17); /* r17 = x3 * tn3 (6420) */ \
+ psraw($17, 15, $17); \
+ pmfhl_uw($3); /* r3 = 7531 */ \
+ psraw($3, 15, $3); \
+ pinteh($3, $17, $17); /* r17 = x3 * tn3 */ \
+ psubh($17, $13, $17); /* r17 = tm35 */ \
+\
+ pmulth($13, $2, $18); /* r18 = x5 * tn3 (6420) */ \
+ psraw($18, 15, $18); \
+ pmfhl_uw($3); /* r3 = 7531 */ \
+ psraw($3, 15, $3); \
+ pinteh($3, $18, $18); /* r18 = x5 * tn3 */ \
+ paddh($18, $11, $18); /* r18 = tp35 */ \
+\
+ lq($24, TG_1_16, $2); /* r2 = tn1 */ \
+\
+ pmulth($15, $2, $19); /* r19 = x7 * tn1 (6420) */ \
+ psraw($19, 15, $19); \
+ pmfhl_uw($3); /* r3 = 7531 */ \
+ psraw($3, 15, $3); \
+ pinteh($3, $19, $19); /* r19 = x7 * tn1 */ \
+ paddh($19, $9, $19); /* r19 = tp17 */ \
+\
+ pmulth($9, $2, $20); /* r20 = x1 * tn1 (6420) */ \
+ psraw($20, 15, $20); \
+ pmfhl_uw($3); /* r3 = 7531 */ \
+ psraw($3, 15, $3); \
+ pinteh($3, $20, $20); /* r20 = x1 * tn1 */ \
+ psubh($20, $15, $20); /* r20 = tm17 */ \
+\
+ psubh($19, $18, $3); /* r3 = t1 */ \
+ paddh($20, $17, $16); /* r16 = t2 */ \
+ psubh($20, $17, $23); /* r23 = b3 */ \
+ paddh($19, $18, $20); /* r20 = b0 */ \
+\
+ lq($24, COS_4_16, $2); /* r2 = cs4 */ \
+\
+ paddh($3, $16, $21); /* r21 = t1+t2 */ \
+ psubh($3, $16, $22); /* r22 = t1-t2 */ \
+\
+ pmulth($21, $2, $21); /* r21 = cs4 * (t1+t2) 6420 */ \
+ psraw($21, 15, $21); \
+ pmfhl_uw($3); /* r3 = 7531 */ \
+ psraw($3, 15, $3); \
+ pinteh($3, $21, $21); /* r21 = b1 */ \
+\
+ pmulth($22, $2, $22); /* r22 = cs4 * (t1-t2) 6420 */ \
+ psraw($22, 15, $22); \
+ pmfhl_uw($3); /* r3 = 7531 */ \
+ psraw($3, 15, $3); \
+ pinteh($3, $22, $22); /* r22 = b2 */ \
+\
+ lq($24, TG_2_16, $2); /* r2 = tn2 */ \
+\
+ pmulth($10, $2, $17); /* r17 = x2 * tn2 (6420) */ \
+ psraw($17, 15, $17); \
+ pmfhl_uw($3); /* r3 = 7531 */ \
+ psraw($3, 15, $3); \
+ pinteh($3, $17, $17); /* r17 = x3 * tn3 */ \
+ psubh($17, $14, $17); /* r17 = tm26 */ \
+\
+ pmulth($14, $2, $18); /* r18 = x6 * tn2 (6420) */ \
+ psraw($18, 15, $18); \
+ pmfhl_uw($3); /* r3 = 7531 */ \
+ psraw($3, 15, $3); \
+ pinteh($3, $18, $18); /* r18 = x6 * tn2 */ \
+ paddh($18, $10, $18); /* r18 = tp26 */ \
+\
+ paddh($8, $12, $2); /* r2 = tp04 */ \
+ psubh($8, $12, $3); /* r3 = tm04 */ \
+\
+ paddh($2, $18, $16); /* r16 = a0 */ \
+ psubh($2, $18, $19); /* r19 = a3 */ \
+ psubh($3, $17, $18); /* r18 = a2 */ \
+ paddh($3, $17, $17); /* r17 = a1 */
+
+
+#define DCT_8_INV_COL8_STORE(blk) \
+\
+ paddh($16, $20, $2); /* y0 a0+b0 */ \
+ psubh($16, $20, $16); /* y7 a0-b0 */ \
+ psrah($2, SHIFT_INV_COL, $2); \
+ psrah($16, SHIFT_INV_COL, $16); \
+ sq($2, 0, blk); \
+ sq($16, 112, blk); \
+\
+ paddh($17, $21, $3); /* y1 a1+b1 */ \
+ psubh($17, $21, $17); /* y6 a1-b1 */ \
+ psrah($3, SHIFT_INV_COL, $3); \
+ psrah($17, SHIFT_INV_COL, $17); \
+ sq($3, 16, blk); \
+ sq($17, 96, blk); \
+\
+ paddh($18, $22, $2); /* y2 a2+b2 */ \
+ psubh($18, $22, $18); /* y5 a2-b2 */ \
+ psrah($2, SHIFT_INV_COL, $2); \
+ psrah($18, SHIFT_INV_COL, $18); \
+ sq($2, 32, blk); \
+ sq($18, 80, blk); \
+\
+ paddh($19, $23, $3); /* y3 a3+b3 */ \
+ psubh($19, $23, $19); /* y4 a3-b3 */ \
+ psrah($3, SHIFT_INV_COL, $3); \
+ psrah($19, SHIFT_INV_COL, $19); \
+ sq($3, 48, blk); \
+ sq($19, 64, blk);
+
+
+
+#define DCT_8_INV_COL8_PMS() \
+ paddh($16, $20, $2); /* y0 a0+b0 */ \
+ psubh($16, $20, $20); /* y7 a0-b0 */ \
+ psrah($2, SHIFT_INV_COL, $16); \
+ psrah($20, SHIFT_INV_COL, $20); \
+\
+ paddh($17, $21, $3); /* y1 a1+b1 */ \
+ psubh($17, $21, $21); /* y6 a1-b1 */ \
+ psrah($3, SHIFT_INV_COL, $17); \
+ psrah($21, SHIFT_INV_COL, $21); \
+\
+ paddh($18, $22, $2); /* y2 a2+b2 */ \
+ psubh($18, $22, $22); /* y5 a2-b2 */ \
+ psrah($2, SHIFT_INV_COL, $18); \
+ psrah($22, SHIFT_INV_COL, $22); \
+\
+ paddh($19, $23, $3); /* y3 a3+b3 */ \
+ psubh($19, $23, $23); /* y4 a3-b3 */ \
+ psrah($3, SHIFT_INV_COL, $19); \
+ psrah($23, SHIFT_INV_COL, $23);
+
+#define PUT(rs) \
+ pminh(rs, $11, $2); \
+ pmaxh($2, $0, $2); \
+ ppacb($0, $2, $2); \
+ sd3(2, 0, 4); \
+ __asm__ __volatile__ ("add $4, $5, $4");
+
+#define DCT_8_INV_COL8_PUT() \
+ PUT($16); \
+ PUT($17); \
+ PUT($18); \
+ PUT($19); \
+ PUT($23); \
+ PUT($22); \
+ PUT($21); \
+ PUT($20);
+
+#define ADD(rs) \
+ ld3(4, 0, 2); \
+ pextlb($0, $2, $2); \
+ paddh($2, rs, $2); \
+ pminh($2, $11, $2); \
+ pmaxh($2, $0, $2); \
+ ppacb($0, $2, $2); \
+ sd3(2, 0, 4); \
+ __asm__ __volatile__ ("add $4, $5, $4");
+
+/*fixme: schedule*/
+#define DCT_8_INV_COL8_ADD() \
+ ADD($16); \
+ ADD($17); \
+ ADD($18); \
+ ADD($19); \
+ ADD($23); \
+ ADD($22); \
+ ADD($21); \
+ ADD($20);
+
+
+void ff_mmi_idct(int16_t * block)
+{
+ /* $4 = block */
+ __asm__ __volatile__("la $24, %0"::"m"(consttable[0]));
+ lq($24, ROUNDER_0, $8);
+ lq($24, ROUNDER_1, $7);
+ DCT_8_INV_ROW1($4, 0, TAB_i_04, $8, $8);
+ DCT_8_INV_ROW1($4, 16, TAB_i_17, $7, $9);
+ DCT_8_INV_ROW1($4, 32, TAB_i_26, $7, $10);
+ DCT_8_INV_ROW1($4, 48, TAB_i_35, $7, $11);
+ DCT_8_INV_ROW1($4, 64, TAB_i_04, $7, $12);
+ DCT_8_INV_ROW1($4, 80, TAB_i_35, $7, $13);
+ DCT_8_INV_ROW1($4, 96, TAB_i_26, $7, $14);
+ DCT_8_INV_ROW1($4, 112, TAB_i_17, $7, $15);
+ DCT_8_INV_COL8();
+ DCT_8_INV_COL8_STORE($4);
+
+ //let savedtemp regs be saved
+ __asm__ __volatile__(" ":::"$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23");
+}
+
+
+void ff_mmi_idct_put(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ /* $4 = dest, $5 = line_size, $6 = block */
+ __asm__ __volatile__("la $24, %0"::"m"(consttable[0]));
+ lq($24, ROUNDER_0, $8);
+ lq($24, ROUNDER_1, $7);
+ DCT_8_INV_ROW1($6, 0, TAB_i_04, $8, $8);
+ DCT_8_INV_ROW1($6, 16, TAB_i_17, $7, $9);
+ DCT_8_INV_ROW1($6, 32, TAB_i_26, $7, $10);
+ DCT_8_INV_ROW1($6, 48, TAB_i_35, $7, $11);
+ DCT_8_INV_ROW1($6, 64, TAB_i_04, $7, $12);
+ DCT_8_INV_ROW1($6, 80, TAB_i_35, $7, $13);
+ DCT_8_INV_ROW1($6, 96, TAB_i_26, $7, $14);
+ DCT_8_INV_ROW1($6, 112, TAB_i_17, $7, $15);
+ DCT_8_INV_COL8();
+ lq($24, CLIPMAX, $11);
+ DCT_8_INV_COL8_PMS();
+ DCT_8_INV_COL8_PUT();
+
+ //let savedtemp regs be saved
+ __asm__ __volatile__(" ":::"$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23");
+}
+
+
+void ff_mmi_idct_add(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ /* $4 = dest, $5 = line_size, $6 = block */
+ __asm__ __volatile__("la $24, %0"::"m"(consttable[0]));
+ lq($24, ROUNDER_0, $8);
+ lq($24, ROUNDER_1, $7);
+ DCT_8_INV_ROW1($6, 0, TAB_i_04, $8, $8);
+ DCT_8_INV_ROW1($6, 16, TAB_i_17, $7, $9);
+ DCT_8_INV_ROW1($6, 32, TAB_i_26, $7, $10);
+ DCT_8_INV_ROW1($6, 48, TAB_i_35, $7, $11);
+ DCT_8_INV_ROW1($6, 64, TAB_i_04, $7, $12);
+ DCT_8_INV_ROW1($6, 80, TAB_i_35, $7, $13);
+ DCT_8_INV_ROW1($6, 96, TAB_i_26, $7, $14);
+ DCT_8_INV_ROW1($6, 112, TAB_i_17, $7, $15);
+ DCT_8_INV_COL8();
+ lq($24, CLIPMAX, $11);
+ DCT_8_INV_COL8_PMS();
+ DCT_8_INV_COL8_ADD();
+
+ //let savedtemp regs be saved
+ __asm__ __volatile__(" ":::"$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23");
+}
+
diff --git a/contrib/ffmpeg/libavcodec/ps2/mmi.h b/contrib/ffmpeg/libavcodec/ps2/mmi.h
new file mode 100644
index 000000000..e2e49a86c
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ps2/mmi.h
@@ -0,0 +1,172 @@
+/*
+ * copyright (c) 2002 Leon van Stuivenberg
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 __mmi_H
+#define __mmi_H
+
+#define align16 __attribute__ ((aligned (16)))
+
+/*
+#define r0 $zero
+#define r1 $at //assembler!
+#define r2 $v0 //return
+#define r3 $v1 //return
+#define r4 $a0 //arg
+#define r5 $a1 //arg
+#define r6 $a2 //arg
+#define r7 $a3 //arg
+#define r8 $t0 //temp
+#define r9 $t1 //temp
+#define r10 $t2 //temp
+#define r11 $t3 //temp
+#define r12 $t4 //temp
+#define r13 $t5 //temp
+#define r14 $t6 //temp
+#define r15 $t7 //temp
+#define r16 $s0 //saved temp
+#define r17 $s1 //saved temp
+#define r18 $s2 //saved temp
+#define r19 $s3 //saved temp
+#define r20 $s4 //saved temp
+#define r21 $s5 //saved temp
+#define r22 $s6 //saved temp
+#define r23 $s7 //saved temp
+#define r24 $t8 //temp
+#define r25 $t9 //temp
+#define r26 $k0 //kernel
+#define r27 $k1 //kernel
+#define r28 $gp //global ptr
+#define r29 $sp //stack ptr
+#define r30 $fp //frame ptr
+#define r31 $ra //return addr
+*/
+
+
+#define lq(base, off, reg) \
+ __asm__ __volatile__ ("lq " #reg ", %0("#base ")" : : "i" (off) )
+
+#define lq2(mem, reg) \
+ __asm__ __volatile__ ("lq " #reg ", %0" : : "r" (mem))
+
+#define sq(reg, off, base) \
+ __asm__ __volatile__ ("sq " #reg ", %0("#base ")" : : "i" (off) )
+
+/*
+#define ld(base, off, reg) \
+ __asm__ __volatile__ ("ld " #reg ", " #off "("#base ")")
+*/
+
+#define ld3(base, off, reg) \
+ __asm__ __volatile__ (".word %0" : : "i" ( 0xdc000000 | (base<<21) | (reg<<16) | (off)))
+
+#define ldr3(base, off, reg) \
+ __asm__ __volatile__ (".word %0" : : "i" ( 0x6c000000 | (base<<21) | (reg<<16) | (off)))
+
+#define ldl3(base, off, reg) \
+ __asm__ __volatile__ (".word %0" : : "i" ( 0x68000000 | (base<<21) | (reg<<16) | (off)))
+
+/*
+#define sd(reg, off, base) \
+ __asm__ __volatile__ ("sd " #reg ", " #off "("#base ")")
+*/
+//seems assembler has bug encoding mnemonic 'sd', so DIY
+#define sd3(reg, off, base) \
+ __asm__ __volatile__ (".word %0" : : "i" ( 0xfc000000 | (base<<21) | (reg<<16) | (off)))
+
+#define sw(reg, off, base) \
+ __asm__ __volatile__ ("sw " #reg ", " #off "("#base ")")
+
+#define sq2(reg, mem) \
+ __asm__ __volatile__ ("sq " #reg ", %0" : : "m" (*(mem)))
+
+#define pinth(rs, rt, rd) \
+ __asm__ __volatile__ ("pinth " #rd ", " #rs ", " #rt )
+
+#define phmadh(rs, rt, rd) \
+ __asm__ __volatile__ ("phmadh " #rd ", " #rs ", " #rt )
+
+#define pcpyud(rs, rt, rd) \
+ __asm__ __volatile__ ("pcpyud " #rd ", " #rs ", " #rt )
+
+#define pcpyld(rs, rt, rd) \
+ __asm__ __volatile__ ("pcpyld " #rd ", " #rs ", " #rt )
+
+#define pcpyh(rt, rd) \
+ __asm__ __volatile__ ("pcpyh " #rd ", " #rt )
+
+#define paddw(rs, rt, rd) \
+ __asm__ __volatile__ ("paddw " #rd ", " #rs ", " #rt )
+
+#define pextlw(rs, rt, rd) \
+ __asm__ __volatile__ ("pextlw " #rd ", " #rs ", " #rt )
+
+#define pextuw(rs, rt, rd) \
+ __asm__ __volatile__ ("pextuw " #rd ", " #rs ", " #rt )
+
+#define pextlh(rs, rt, rd) \
+ __asm__ __volatile__ ("pextlh " #rd ", " #rs ", " #rt )
+
+#define pextuh(rs, rt, rd) \
+ __asm__ __volatile__ ("pextuh " #rd ", " #rs ", " #rt )
+
+#define psubw(rs, rt, rd) \
+ __asm__ __volatile__ ("psubw " #rd ", " #rs ", " #rt )
+
+#define psraw(rt, sa, rd) \
+ __asm__ __volatile__ ("psraw " #rd ", " #rt ", %0" : : "i"(sa) )
+
+#define ppach(rs, rt, rd) \
+ __asm__ __volatile__ ("ppach " #rd ", " #rs ", " #rt )
+
+#define ppacb(rs, rt, rd) \
+ __asm__ __volatile__ ("ppacb " #rd ", " #rs ", " #rt )
+
+#define prevh(rt, rd) \
+ __asm__ __volatile__ ("prevh " #rd ", " #rt )
+
+#define pmulth(rs, rt, rd) \
+ __asm__ __volatile__ ("pmulth " #rd ", " #rs ", " #rt )
+
+#define pmaxh(rs, rt, rd) \
+ __asm__ __volatile__ ("pmaxh " #rd ", " #rs ", " #rt )
+
+#define pminh(rs, rt, rd) \
+ __asm__ __volatile__ ("pminh " #rd ", " #rs ", " #rt )
+
+#define pinteh(rs, rt, rd) \
+ __asm__ __volatile__ ("pinteh " #rd ", " #rs ", " #rt )
+
+#define paddh(rs, rt, rd) \
+ __asm__ __volatile__ ("paddh " #rd ", " #rs ", " #rt )
+
+#define psubh(rs, rt, rd) \
+ __asm__ __volatile__ ("psubh " #rd ", " #rs ", " #rt )
+
+#define psrah(rt, sa, rd) \
+ __asm__ __volatile__ ("psrah " #rd ", " #rt ", %0" : : "i"(sa) )
+
+#define pmfhl_uw(rd) \
+ __asm__ __volatile__ ("pmfhl.uw " #rd)
+
+#define pextlb(rs, rt, rd) \
+ __asm__ __volatile__ ("pextlb " #rd ", " #rs ", " #rt )
+
+#endif
+
diff --git a/contrib/ffmpeg/libavcodec/ps2/mpegvideo_mmi.c b/contrib/ffmpeg/libavcodec/ps2/mpegvideo_mmi.c
new file mode 100644
index 000000000..1e5f08aae
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ps2/mpegvideo_mmi.c
@@ -0,0 +1,89 @@
+/*
+ * 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
+ *
+ * MMI optimization by Leon van Stuivenberg
+ */
+
+#include "../dsputil.h"
+#include "../mpegvideo.h"
+#include "../avcodec.h"
+
+static void dct_unquantize_h263_mmi(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale)
+{
+ int level=0, 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)
+ level = block[0] * s->y_dc_scale;
+ else
+ level = block[0] * s->c_dc_scale;
+ }else {
+ qadd = 0;
+ level = block[0];
+ }
+ nCoeffs= 63; //does not allways use zigzag table
+ } else {
+ nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ];
+ }
+
+ asm volatile(
+ "add $14, $0, %3 \n\t"
+ "pcpyld $8, %0, %0 \n\t"
+ "pcpyh $8, $8 \n\t" //r8 = qmul
+ "pcpyld $9, %1, %1 \n\t"
+ "pcpyh $9, $9 \n\t" //r9 = qadd
+ ".p2align 2 \n\t"
+ "1: \n\t"
+ "lq $10, 0($14) \n\t" //r10 = level
+ "addi $14, $14, 16 \n\t" //block+=8
+ "addi %2, %2, -8 \n\t"
+ "pcgth $11, $0, $10 \n\t" //r11 = level < 0 ? -1 : 0
+ "pcgth $12, $10, $0 \n\t" //r12 = level > 0 ? -1 : 0
+ "por $12, $11, $12 \n\t"
+ "pmulth $10, $10, $8 \n\t"
+ "paddh $13, $9, $11 \n\t"
+ "pxor $13, $13, $11 \n\t" //r13 = level < 0 ? -qadd : qadd
+ "pmfhl.uw $11 \n\t"
+ "pinteh $10, $11, $10 \n\t" //r10 = level * qmul
+ "paddh $10, $10, $13 \n\t"
+ "pand $10, $10, $12 \n\t"
+ "sq $10, -16($14) \n\t"
+ "bgez %2, 1b \n\t"
+ :: "r"(qmul), "r" (qadd), "r" (nCoeffs), "r" (block) : "$8", "$9", "$10", "$11", "$12", "$13", "$14", "memory" );
+
+ if(s->mb_intra)
+ block[0]= level;
+}
+
+
+void MPV_common_init_mmi(MpegEncContext *s)
+{
+ s->dct_unquantize_h263_intra =
+ s->dct_unquantize_h263_inter = dct_unquantize_h263_mmi;
+}
+
+
diff --git a/contrib/ffmpeg/libavcodec/pthread.c b/contrib/ffmpeg/libavcodec/pthread.c
new file mode 100644
index 000000000..4737211cb
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/pthread.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2004 Roman Shaposhnik.
+ *
+ * Many thanks to Steven M. Schultz for providing clever ideas and
+ * to Michael Niedermayer <michaelni@gmx.at> 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
+ *
+ */
+#include <pthread.h>
+
+#include "avcodec.h"
+#include "common.h"
+
+typedef int (action_t)(AVCodecContext *c, void *arg);
+
+typedef struct ThreadContext {
+ pthread_t *workers;
+ action_t *func;
+ void **args;
+ int *rets;
+ int rets_count;
+ int job_count;
+
+ pthread_cond_t last_job_cond;
+ pthread_cond_t current_job_cond;
+ pthread_mutex_t current_job_lock;
+ int current_job;
+ int done;
+} ThreadContext;
+
+static void* worker(void *v)
+{
+ AVCodecContext *avctx = v;
+ ThreadContext *c = avctx->thread_opaque;
+ int our_job = c->job_count;
+ 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);
+
+ pthread_cond_wait(&c->current_job_cond, &c->current_job_lock);
+ 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(avctx, c->args[our_job]);
+
+ pthread_mutex_lock(&c->current_job_lock);
+ our_job = c->current_job++;
+ }
+}
+
+static always_inline void avcodec_thread_park_workers(ThreadContext *c, int thread_count)
+{
+ pthread_cond_wait(&c->last_job_cond, &c->current_job_lock);
+ pthread_mutex_unlock(&c->current_job_lock);
+}
+
+void avcodec_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; i<avctx->thread_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_free(c);
+}
+
+int avcodec_thread_execute(AVCodecContext *avctx, action_t* func, void **arg, int *ret, int job_count)
+{
+ ThreadContext *c= avctx->thread_opaque;
+ int dummy_ret;
+
+ 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->args = arg;
+ c->func = func;
+ if (ret) {
+ c->rets = ret;
+ c->rets_count = job_count;
+ } else {
+ c->rets = &dummy_ret;
+ c->rets_count = 1;
+ }
+ pthread_cond_broadcast(&c->current_job_cond);
+
+ avcodec_thread_park_workers(c, avctx->thread_count);
+
+ return 0;
+}
+
+int avcodec_thread_init(AVCodecContext *avctx, int thread_count)
+{
+ int i;
+ ThreadContext *c;
+
+ 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;
+ avctx->thread_count = thread_count;
+ c->current_job = 0;
+ c->job_count = 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; i<thread_count; i++) {
+ if(pthread_create(&c->workers[i], NULL, worker, avctx)) {
+ avctx->thread_count = i;
+ pthread_mutex_unlock(&c->current_job_lock);
+ avcodec_thread_free(avctx);
+ return -1;
+ }
+ }
+
+ avcodec_thread_park_workers(c, thread_count);
+
+ avctx->execute = avcodec_thread_execute;
+ return 0;
+}
diff --git a/contrib/ffmpeg/libavcodec/qdm2.c b/contrib/ffmpeg/libavcodec/qdm2.c
new file mode 100644
index 000000000..b9462f3cb
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/qdm2.c
@@ -0,0 +1,2042 @@
+/*
+ * 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.c
+ * 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 <math.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#define ALT_BITSTREAM_READER_LE
+#include "avcodec.h"
+#include "bitstream.h"
+#include "dsputil.h"
+
+#ifdef CONFIG_MPEGAUDIO_HP
+#define USE_HIGHPRECISION
+#endif
+
+#include "mpegaudio.h"
+
+#include "qdm2data.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+
+#define SOFTCLIP_THRESHOLD 27600
+#define HARDCLIP_THRESHOLD 35716
+
+
+#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 BITS_LEFT(length,gb) ((length) - get_bits_count ((gb)))
+
+#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);
+
+
+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 level;
+ float *samples_im;
+ float *samples_re;
+ 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 {
+ float re;
+ float im;
+} QDM2Complex;
+
+typedef struct {
+ QDM2Complex complex[256 + 1] __attribute__((aligned(16)));
+ float samples_im[MPA_MAX_CHANNELS][256];
+ float samples_re[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 fft_frame_size; ///< size of fft frame, in components (1 comples = re + im)
+ 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];
+ FFTContext fft_ctx;
+ FFTComplex exptab[128];
+ QDM2FFT fft;
+
+ /// I/O data
+ uint8_t *compressed_data;
+ int compressed_size;
+ float output_buffer[1024];
+
+ /// Synthesis filter
+ MPA_INT synth_buf[MPA_MAX_CHANNELS][512*2] __attribute__((aligned(16)));
+ int synth_buf_offset[MPA_MAX_CHANNELS];
+ int32_t sb_samples[MPA_MAX_CHANNELS][128][SBLIMIT] __attribute__((aligned(16)));
+
+ /// 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 uint8_t empty_buffer[FF_INPUT_BUFFER_PADDING_SIZE];
+
+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 uint16_t softclip_table[HARDCLIP_THRESHOLD - SOFTCLIP_THRESHOLD + 1];
+static float noise_table[4096];
+static uint8_t random_dequant_index[256][5];
+static uint8_t random_dequant_type24[128][3];
+static float noise_samples[128];
+
+static MPA_INT mpa_window[512] __attribute__((aligned(16)));
+
+
+static 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 void rnd_table_init(void) {
+ int i,j;
+ uint32_t ldw,hdw;
+ uint64_t tmp64_1;
+ 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] = (uint8_t)((ldw / random_seed) & 0xFF);
+ ldw = (uint32_t)ldw % (uint32_t)random_seed;
+ tmp64_1 = (random_seed * 0x55555556);
+ hdw = (uint32_t)(tmp64_1 >> 32);
+ random_seed = (uint64_t)(hdw + (ldw >> 31));
+ }
+ }
+ for (i = 0; i < 128 ;i++) {
+ random_seed = 25;
+ ldw = i;
+ for (j = 0; j < 3 ;j++) {
+ random_dequant_type24[i][j] = (uint8_t)((ldw / random_seed) & 0xFF);
+ ldw = (uint32_t)ldw % (uint32_t)random_seed;
+ tmp64_1 = (random_seed * 0x66666667);
+ hdw = (uint32_t)(tmp64_1 >> 33);
+ random_seed = hdw + (ldw >> 31);
+ }
+ }
+}
+
+
+static void init_noise_samples(void) {
+ int i;
+ int 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);
+ }
+}
+
+
+static void qdm2_init_vlc(void)
+{
+ init_vlc (&vlc_tab_level, 8, 24,
+ vlc_tab_level_huffbits, 1, 1,
+ vlc_tab_level_huffcodes, 2, 2, INIT_VLC_USE_STATIC | INIT_VLC_LE);
+
+ init_vlc (&vlc_tab_diff, 8, 37,
+ vlc_tab_diff_huffbits, 1, 1,
+ vlc_tab_diff_huffcodes, 2, 2, INIT_VLC_USE_STATIC | INIT_VLC_LE);
+
+ init_vlc (&vlc_tab_run, 5, 6,
+ vlc_tab_run_huffbits, 1, 1,
+ vlc_tab_run_huffcodes, 1, 1, INIT_VLC_USE_STATIC | INIT_VLC_LE);
+
+ 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_STATIC | INIT_VLC_LE);
+
+ init_vlc (&fft_level_exp_vlc, 8, 20,
+ fft_level_exp_huffbits, 1, 1,
+ fft_level_exp_huffcodes, 2, 2, INIT_VLC_USE_STATIC | INIT_VLC_LE);
+
+ init_vlc (&fft_stereo_exp_vlc, 6, 7,
+ fft_stereo_exp_huffbits, 1, 1,
+ fft_stereo_exp_huffcodes, 1, 1, INIT_VLC_USE_STATIC | INIT_VLC_LE);
+
+ init_vlc (&fft_stereo_phase_vlc, 6, 9,
+ fft_stereo_phase_huffbits, 1, 1,
+ fft_stereo_phase_huffcodes, 1, 1, INIT_VLC_USE_STATIC | INIT_VLC_LE);
+
+ 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_STATIC | INIT_VLC_LE);
+
+ 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_STATIC | INIT_VLC_LE);
+
+ 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_STATIC | INIT_VLC_LE);
+
+ init_vlc (&vlc_tab_type30, 6, 9,
+ vlc_tab_type30_huffbits, 1, 1,
+ vlc_tab_type30_huffcodes, 1, 1, INIT_VLC_USE_STATIC | INIT_VLC_LE);
+
+ init_vlc (&vlc_tab_type34, 5, 10,
+ vlc_tab_type34_huffbits, 1, 1,
+ vlc_tab_type34_huffcodes, 1, 1, INIT_VLC_USE_STATIC | INIT_VLC_LE);
+
+ 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_STATIC | INIT_VLC_LE);
+
+ 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_STATIC | INIT_VLC_LE);
+
+ 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_STATIC | INIT_VLC_LE);
+
+ 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_STATIC | INIT_VLC_LE);
+
+ 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_STATIC | INIT_VLC_LE);
+}
+
+
+/* for floating point to fixed point conversion */
+static float f2i_scale = (float) (1 << (FRAC_BITS - 15));
+
+
+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 = 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 (uint8_t *data, int length, int value) {
+ int i;
+
+ for (i=0; i < length; i++)
+ value -= data[i];
+
+ return (uint16_t)(value & 0xffff);
+}
+
+
+/**
+ * Fills 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;
+}
+
+
+/**
+ * Replaces 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] = (int32_t)(f2i_scale * SB_DITHERING_NOISE(sb,q->noise_idx) * q->tone_level[ch][sb][j] + .5);
+ q->sb_samples[ch][j * 2 + 1][sb] = (int32_t)(f2i_scale * SB_DITHERING_NOISE(sb,q->noise_idx) * q->tone_level[ch][sb][j] + .5);
+ }
+}
+
+
+/**
+ * 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;
+ 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;
+
+ // This should never happen
+ if (q->nb_channels <= 0)
+ return;
+
+ 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;
+
+ // This should never happen
+ if (nb_channels <= 0)
+ return;
+
+ if (!superblocktype_2_3) {
+ /* This case is untested, no samples available */
+ SAMPLES_NEEDED
+ for (ch = 0; ch < nb_channels; ch++)
+ for (sb = 0; sb < 30; sb++) {
+ for (j = 1; j < 64; j++) {
+ 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];
+ if (acc)
+ tmp = c * 256 / (acc & 0xffff);
+ multres = 0x66666667 * (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 void 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;
+ }
+
+ 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 = (BITS_LEFT(length,gb) >= 1) ? get_bits1 (gb) : 0;
+
+ if (joined_stereo) {
+ if (BITS_LEFT(length,gb) >= 16)
+ for (j = 0; j < 16; j++)
+ sign_bits[j] = get_bits1 (gb);
+
+ 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 = (BITS_LEFT(length,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 (BITS_LEFT(length,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);
+ 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 (BITS_LEFT(length,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 (BITS_LEFT(length,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);
+ 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 (BITS_LEFT(length,gb) >= 7) {
+ n = get_bits(gb, 7);
+ 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 (BITS_LEFT(length,gb) >= 4)
+ samples[0] = type30_dequant[qdm2_get_vlc(gb, &vlc_tab_type30, 0, 1)];
+ else
+ samples[0] = SB_DITHERING_NOISE(sb,q->noise_idx);
+
+ run = 1;
+ break;
+
+ case 34:
+ if (BITS_LEFT(length,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 {
+ samples[0] = type34_delta[qdm2_get_vlc(gb, &vlc_tab_type34, 0, 1)] / 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];
+ 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] = (int32_t)(f2i_scale * q->tone_level[chs][sb][((j + k)/2)] * tmp[k][chs] + .5);
+ } else {
+ for (k = 0; k < run; k++)
+ if ((j + k) < 128)
+ q->sb_samples[ch][j + k][sb] = (int32_t)(f2i_scale * q->tone_level[ch][sb][(j + k)/2] * samples[k] + .5);
+ }
+
+ j += run;
+ } // j loop
+ } // channel loop
+ } // subband loop
+}
+
+
+/**
+ * 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 q context
+ * @param quantized_coeffs pointer to quantized_coeffs[ch][0]
+ * @param gb bitreader context
+ * @param length packet length in bits
+ */
+static void init_quantized_coeffs_elem0 (int8_t *quantized_coeffs, GetBitContext *gb, int length)
+{
+ int i, k, run, level, diff;
+
+ if (BITS_LEFT(length,gb) < 16)
+ return;
+ level = qdm2_get_vlc(gb, &vlc_tab_level, 0, 2);
+
+ quantized_coeffs[0] = level;
+
+ for (i = 0; i < 7; ) {
+ if (BITS_LEFT(length,gb) < 16)
+ break;
+ run = qdm2_get_vlc(gb, &vlc_tab_run, 0, 1) + 1;
+
+ if (BITS_LEFT(length,gb) < 16)
+ break;
+ 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;
+ }
+}
+
+
+/**
+ * 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
+ * @param length packet length in bits
+ */
+static void init_tone_level_dequantization (QDM2Context *q, GetBitContext *gb, int length)
+{
+ int sb, j, k, n, ch;
+
+ for (ch = 0; ch < q->nb_channels; ch++) {
+ init_quantized_coeffs_elem0(q->quantized_coeffs[ch][0], gb, length);
+
+ if (BITS_LEFT(length,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 (BITS_LEFT(length,gb) < 1)
+ break;
+ if (get_bits1(gb)) {
+ for (k=0; k < 8; k++) {
+ if (BITS_LEFT(length,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 (BITS_LEFT(length,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 (BITS_LEFT(length,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 void 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);
+
+ 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;
+}
+
+
+/**
+ * Process subpacket 10 if not null, else
+ *
+ * @param q context
+ * @param node pointer to node with packet
+ * @param length packet length in bits
+ */
+static void process_subpacket_10 (QDM2Context *q, QDM2SubPNode *node, int length)
+{
+ GetBitContext gb;
+
+ init_get_bits(&gb, ((node == NULL) ? empty_buffer : node->packet->data), ((node == NULL) ? 0 : node->packet->size*8));
+
+ if (length != 0) {
+ init_tone_level_dequantization(q, &gb, length);
+ 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
+ * @param length packet length in bit
+ */
+static void process_subpacket_11 (QDM2Context *q, QDM2SubPNode *node, int length)
+{
+ GetBitContext gb;
+
+ init_get_bits(&gb, ((node == NULL) ? empty_buffer : node->packet->data), ((node == NULL) ? 0 : node->packet->size*8));
+ 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
+ * @param length packet length in bits
+ */
+static void process_subpacket_12 (QDM2Context *q, QDM2SubPNode *node, int length)
+{
+ GetBitContext gb;
+
+ init_get_bits(&gb, ((node == NULL) ? empty_buffer : node->packet->data), ((node == NULL) ? 0 : node->packet->size*8));
+ 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], nodes[1]->packet->size << 3);
+ else
+ process_subpacket_10(q, NULL, 0);
+
+ 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], (nodes[2]->packet->size << 3));
+ else
+ process_subpacket_11(q, NULL, 0);
+
+ 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], (nodes[3]->packet->size << 3));
+ else
+ process_subpacket_12(q, NULL, 0);
+}
+
+
+/*
+ * 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) + 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;
+
+ 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, 0);
+ process_subpacket_11(q, NULL, 0);
+ process_subpacket_12(q, NULL, 0);
+ }
+/* **************************************************************** */
+}
+
+
+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 (1) {
+ if (q->superblocktype_2_3) {
+ while ((n = qdm2_get_vlc(gb, &vlc_tab_fft_tone_offset[local_int_8], 1, 2)) < 2) {
+ 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 (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 indices 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;
+
+ /* find subpacket with largest type less than max */
+ for (j = 0, min = 0, packet = NULL; 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 (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 indices 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->samples_im[0] += c.im;
+ tone->samples_re[0] += c.re;
+ tone->samples_im[1] -= c.im;
+ tone->samples_re[1] -= 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->samples_re[fft_cutoff_index_table[tone->cutoff][i]] += c.re * f[i];
+ tone->samples_im[fft_cutoff_index_table[tone->cutoff][i]] += c.im *((tone->cutoff <= i) ? -f[i] : f[i]);
+ }
+ for (i = 0; i < 4; i++) {
+ tone->samples_re[i] += c.re * f[i+2];
+ tone->samples_im[i] += 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.samples_im[ch], 0, q->fft_size * sizeof(float));
+ memset(q->fft.samples_re[ch], 0, q->fft_size * sizeof(float));
+ }
+
+
+ /* 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.samples_re[ch][q->fft_coefs[i].offset + 0] += c.re;
+ q->fft.samples_im[ch][q->fft_coefs[i].offset + 0] += c.im;
+ q->fft.samples_re[ch][q->fft_coefs[i].offset + 1] -= c.re;
+ q->fft.samples_im[ch][q->fft_coefs[i].offset + 1] -= 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.samples_im = &q->fft.samples_im[ch][offset];
+ tone.samples_re = &q->fft.samples_re[ch][offset];
+ tone.table = (float*)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 int n = 1 << (q->fft_order - 1);
+ const int n2 = n >> 1;
+ const float gain = (q->channels == 1 && q->nb_channels == 2) ? 0.25f : 0.50f;
+ float c, s, f0, f1, f2, f3;
+ int i, j;
+
+ /* prerotation (or something like that) */
+ for (i=1; i < n2; i++) {
+ j = (n - i);
+ c = q->exptab[i].re;
+ s = -q->exptab[i].im;
+ f0 = (q->fft.samples_re[channel][i] - q->fft.samples_re[channel][j]) * gain;
+ f1 = (q->fft.samples_im[channel][i] + q->fft.samples_im[channel][j]) * gain;
+ f2 = (q->fft.samples_re[channel][i] + q->fft.samples_re[channel][j]) * gain;
+ f3 = (q->fft.samples_im[channel][i] - q->fft.samples_im[channel][j]) * gain;
+ q->fft.complex[i].re = s * f0 - c * f1 + f2;
+ q->fft.complex[i].im = c * f0 + s * f1 + f3;
+ q->fft.complex[j].re = -s * f0 + c * f1 + f2;
+ q->fft.complex[j].im = c * f0 + s * f1 - f3;
+ }
+
+ q->fft.complex[ 0].re = q->fft.samples_re[channel][ 0] * gain * 2.0;
+ q->fft.complex[ 0].im = q->fft.samples_re[channel][ 0] * gain * 2.0;
+ q->fft.complex[n2].re = q->fft.samples_re[channel][n2] * gain * 2.0;
+ q->fft.complex[n2].im = -q->fft.samples_im[channel][n2] * gain * 2.0;
+
+ ff_fft_permute(&q->fft_ctx, (FFTComplex *) q->fft.complex);
+ ff_fft_calc (&q->fft_ctx, (FFTComplex *) q->fft.complex);
+ /* add samples to output buffer */
+ for (i = 0; i < ((q->fft_frame_size + 15) & ~15); i++)
+ q->output_buffer[q->channels * i + channel] += ((float *) q->fft.complex)[i];
+}
+
+
+/**
+ * @param q context
+ * @param index subpacket number
+ */
+static void qdm2_synthesis_filter (QDM2Context *q, int index)
+{
+ OUT_INT samples[MPA_MAX_CHANNELS * MPA_FRAME_SIZE];
+ 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++) {
+ OUT_INT *samples_ptr = samples + ch;
+
+ for (i = 0; i < 8; i++) {
+ ff_mpa_synth_filter(q->synth_buf[ch], &(q->synth_buf_offset[ch]),
+ mpa_window, &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] += (float)(samples[q->nb_channels * sub_sampling * i + ch] >> (sizeof(OUT_INT)*8-16));
+}
+
+
+/**
+ * Init static data (does not depend on specific file)
+ *
+ * @param q context
+ */
+static void qdm2_init(QDM2Context *q) {
+ static int inited = 0;
+
+ if (inited != 0)
+ return;
+ inited = 1;
+
+ qdm2_init_vlc();
+ ff_mpa_synth_init(mpa_window);
+ softclip_table_init();
+ rnd_table_init();
+ init_noise_samples();
+
+ av_log(NULL, AV_LOG_DEBUG, "init done\n");
+}
+
+
+#if 0
+static void dump_context(QDM2Context *q)
+{
+ int i;
+#define PRINT(a,b) av_log(NULL,AV_LOG_DEBUG," %s = %d\n", a, b);
+ PRINT("compressed_data",q->compressed_data);
+ PRINT("compressed_size",q->compressed_size);
+ PRINT("frame_size",q->frame_size);
+ PRINT("checksum_size",q->checksum_size);
+ PRINT("channels",q->channels);
+ PRINT("nb_channels",q->nb_channels);
+ PRINT("fft_frame_size",q->fft_frame_size);
+ PRINT("fft_size",q->fft_size);
+ PRINT("sub_sampling",q->sub_sampling);
+ PRINT("fft_order",q->fft_order);
+ PRINT("group_order",q->group_order);
+ PRINT("group_size",q->group_size);
+ PRINT("sub_packet",q->sub_packet);
+ PRINT("frequency_range",q->frequency_range);
+ PRINT("has_errors",q->has_errors);
+ PRINT("fft_tone_end",q->fft_tone_end);
+ PRINT("fft_tone_start",q->fft_tone_start);
+ PRINT("fft_coefs_index",q->fft_coefs_index);
+ PRINT("coeff_per_sb_select",q->coeff_per_sb_select);
+ PRINT("cm_table_select",q->cm_table_select);
+ PRINT("noise_idx",q->noise_idx);
+
+ for (i = q->fft_tone_start; i < q->fft_tone_end; i++)
+ {
+ FFTTone *t = &q->fft_tones[i];
+
+ av_log(NULL,AV_LOG_DEBUG,"Tone (%d) dump:\n", i);
+ av_log(NULL,AV_LOG_DEBUG," level = %f\n", t->level);
+// PRINT(" level", t->level);
+ PRINT(" phase", t->phase);
+ PRINT(" phase_shift", t->phase_shift);
+ PRINT(" duration", t->duration);
+ PRINT(" samples_im", t->samples_im);
+ PRINT(" samples_re", t->samples_re);
+ PRINT(" table", t->table);
+ }
+
+}
+#endif
+
+
+/**
+ * Init parameters from codec extradata
+ */
+static int qdm2_decode_init(AVCodecContext *avctx)
+{
+ QDM2Context *s = avctx->priv_data;
+ uint8_t *extradata;
+ int extradata_size;
+ int tmp_val, tmp, size;
+ int i;
+ float alpha;
+
+ /* 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 = BE_32(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 (BE_32(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 = BE_32(extradata);
+ extradata += 4;
+
+ avctx->sample_rate = BE_32(extradata);
+ extradata += 4;
+
+ avctx->bit_rate = BE_32(extradata);
+ extradata += 4;
+
+ s->group_size = BE_32(extradata);
+ extradata += 4;
+
+ s->fft_size = BE_32(extradata);
+ extradata += 4;
+
+ s->checksum_size = BE_32(extradata);
+ extradata += 4;
+
+ s->fft_order = av_log2(s->fft_size) + 1;
+ s->fft_frame_size = 2 * s->fft_size; // complex has two floats
+
+ // 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
+
+ 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 it's > 9 it can overflow s->exptab[]
+ 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_fft_init(&s->fft_ctx, s->fft_order - 1, 1);
+
+ for (i = 1; i < (1 << (s->fft_order - 2)); i++) {
+ alpha = 2 * M_PI * (float)i / (float)(1 << (s->fft_order - 1));
+ s->exptab[i].re = cos(alpha);
+ s->exptab[i].im = sin(alpha);
+ }
+
+ qdm2_init(s);
+
+// dump_context(s);
+ return 0;
+}
+
+
+static int qdm2_decode_close(AVCodecContext *avctx)
+{
+ QDM2Context *s = avctx->priv_data;
+
+ ff_fft_end(&s->fft_ctx);
+
+ return 0;
+}
+
+
+static void qdm2_decode (QDM2Context *q, uint8_t *in, int16_t *out)
+{
+ int ch, i;
+ const int frame_size = (q->frame_size * q->channels);
+
+ /* select input buffer */
+ q->compressed_data = in;
+ q->compressed_size = q->checksum_size;
+
+// dump_context(q);
+
+ /* 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;
+ }
+ }
+
+ /* 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;
+ }
+}
+
+
+static int qdm2_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ QDM2Context *s = avctx->priv_data;
+
+ if(!buf)
+ return 0;
+ if(buf_size < s->checksum_size)
+ return -1;
+
+ *data_size = s->channels * s->frame_size * sizeof(int16_t);
+
+ av_log(avctx, AV_LOG_DEBUG, "decode(%d): %p[%d] -> %p[%d]\n",
+ buf_size, buf, s->checksum_size, data, *data_size);
+
+ qdm2_decode(s, buf, data);
+
+ // reading only when next superblock found
+ if (s->sub_packet == 0) {
+ return s->checksum_size;
+ }
+
+ return 0;
+}
+
+AVCodec qdm2_decoder =
+{
+ .name = "qdm2",
+ .type = CODEC_TYPE_AUDIO,
+ .id = CODEC_ID_QDM2,
+ .priv_data_size = sizeof(QDM2Context),
+ .init = qdm2_decode_init,
+ .close = qdm2_decode_close,
+ .decode = qdm2_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/qdm2data.h b/contrib/ffmpeg/libavcodec/qdm2data.h
new file mode 100644
index 000000000..6d7d07463
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/qdm2data.h
@@ -0,0 +1,530 @@
+/*
+ * 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 qdm2data.h
+ * Various QDM2 tables.
+ */
+
+#ifndef QDM2DATA_H
+#define QDM2DATA_H
+
+/** 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 uint8_t last_coeff[3] = {
+ 4, 7, 10
+};
+
+static 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 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 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 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 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 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 /* QDM2DATA_H */
diff --git a/contrib/ffmpeg/libavcodec/qdrw.c b/contrib/ffmpeg/libavcodec/qdrw.c
new file mode 100644
index 000000000..8ebb43c4a
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/qdrw.c
@@ -0,0 +1,160 @@
+/*
+ * 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 qdrw.c
+ * Apple QuickDraw codec.
+ */
+
+#include "avcodec.h"
+#include "mpegvideo.h"
+
+typedef struct QdrawContext{
+ AVCodecContext *avctx;
+ AVFrame pic;
+ uint8_t palette[256*3];
+} QdrawContext;
+
+static int decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ QdrawContext * const a = avctx->priv_data;
+ AVFrame * const p= (AVFrame*)&a->pic;
+ uint8_t* outdata;
+ int colors;
+ int i;
+
+ if(p->data[0])
+ avctx->release_buffer(avctx, p);
+
+ p->reference= 0;
+ if(avctx->get_buffer(avctx, p) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+ p->pict_type= I_TYPE;
+ p->key_frame= 1;
+
+ outdata = a->pic.data[0];
+
+ buf += 0x68; /* jump to palette */
+ colors = BE_32(buf);
+ buf += 4;
+
+ if(colors < 0 || colors > 256) {
+ av_log(avctx, AV_LOG_ERROR, "Error color count - %i(0x%X)\n", colors, colors);
+ return -1;
+ }
+
+ for (i = 0; i <= colors; i++) {
+ unsigned int idx;
+ idx = BE_16(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;
+ }
+ a->palette[idx * 3 + 0] = *buf++;
+ buf++;
+ a->palette[idx * 3 + 1] = *buf++;
+ buf++;
+ a->palette[idx * 3 + 2] = *buf++;
+ buf++;
+ }
+
+ buf += 18; /* skip unneeded data */
+ for (i = 0; i < avctx->height; i++) {
+ int size, left, code, pix;
+ uint8_t *next;
+ uint8_t *out;
+ int tsize = 0;
+
+ /* decode line */
+ out = outdata;
+ size = BE_16(buf); /* size of packed line */
+ buf += 2;
+ left = size;
+ next = buf + size;
+ while (left > 0) {
+ code = *buf++;
+ if (code & 0x80 ) { /* run */
+ int i;
+ pix = *buf++;
+ if ((out + (257 - code) * 3) > (outdata + a->pic.linesize[0]))
+ break;
+ for (i = 0; i < 257 - code; i++) {
+ *out++ = a->palette[pix * 3 + 0];
+ *out++ = a->palette[pix * 3 + 1];
+ *out++ = a->palette[pix * 3 + 2];
+ }
+ tsize += 257 - code;
+ left -= 2;
+ } else { /* copy */
+ int i, pix;
+ if ((out + code * 3) > (outdata + a->pic.linesize[0]))
+ break;
+ for (i = 0; i <= code; i++) {
+ pix = *buf++;
+ *out++ = a->palette[pix * 3 + 0];
+ *out++ = a->palette[pix * 3 + 1];
+ *out++ = a->palette[pix * 3 + 2];
+ }
+ left -= 2 + code;
+ tsize += code + 1;
+ }
+ }
+ buf = next;
+ outdata += a->pic.linesize[0];
+ }
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = a->pic;
+
+ return buf_size;
+}
+
+static int decode_init(AVCodecContext *avctx){
+// QdrawContext * const a = avctx->priv_data;
+
+ if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
+ return 1;
+ }
+
+ avctx->pix_fmt= PIX_FMT_RGB24;
+
+ return 0;
+}
+
+AVCodec qdraw_decoder = {
+ "qdraw",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_QDRAW,
+ sizeof(QdrawContext),
+ decode_init,
+ NULL,
+ NULL,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/qpeg.c b/contrib/ffmpeg/libavcodec/qpeg.c
new file mode 100644
index 000000000..3c597e8df
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/qpeg.c
@@ -0,0 +1,324 @@
+/*
+ * 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.c
+ * QPEG codec.
+ */
+
+#include "avcodec.h"
+#include "mpegvideo.h"
+
+typedef struct QpegContext{
+ AVCodecContext *avctx;
+ AVFrame pic;
+ uint8_t *refdata;
+} QpegContext;
+
+static void qpeg_decode_intra(uint8_t *src, uint8_t *dst, int size,
+ 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((size > 0) && (rows_to_go > 0)) {
+ code = *src++;
+ size--;
+ run = copy = 0;
+ if(code == 0xFC) /* end-of-picture code */
+ break;
+ if(code >= 0xF8) { /* very long run */
+ c0 = *src++;
+ c1 = *src++;
+ size -= 2;
+ run = ((code & 0x7) << 16) + (c0 << 8) + c1 + 2;
+ } else if (code >= 0xF0) { /* long run */
+ c0 = *src++;
+ size--;
+ run = ((code & 0xF) << 8) + c0 + 2;
+ } else if (code >= 0xE0) { /* short run */
+ run = (code & 0x1F) + 2;
+ } else if (code >= 0xC0) { /* very long copy */
+ c0 = *src++;
+ c1 = *src++;
+ size -= 2;
+ copy = ((code & 0x3F) << 16) + (c0 << 8) + c1 + 1;
+ } else if (code >= 0x80) { /* long copy */
+ c0 = *src++;
+ size--;
+ copy = ((code & 0x7F) << 8) + c0 + 1;
+ } else { /* short copy */
+ copy = code + 1;
+ }
+
+ /* perform actual run or copy */
+ if(run) {
+ int p;
+
+ p = *src++;
+ size--;
+ 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 {
+ size -= copy;
+ for(i = 0; i < copy; i++) {
+ dst[filled++] = *src++;
+ if (filled >= width) {
+ filled = 0;
+ dst -= stride;
+ rows_to_go--;
+ if(rows_to_go <= 0)
+ break;
+ }
+ }
+ }
+ }
+}
+
+static int qpeg_table_h[16] =
+ { 0x00, 0x20, 0x20, 0x20, 0x18, 0x10, 0x10, 0x20, 0x10, 0x08, 0x18, 0x08, 0x08, 0x18, 0x10, 0x04};
+static 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(uint8_t *src, uint8_t *dst, int size,
+ int stride, int width, int height,
+ int delta, uint8_t *ctable, uint8_t *refdata)
+{
+ int i, j;
+ int code;
+ int filled = 0;
+ int orig_height;
+ uint8_t *blkdata;
+
+ /* copy prev frame */
+ for(i = 0; i < height; i++)
+ memcpy(refdata + (i * width), dst + (i * stride), width);
+
+ orig_height = height;
+ blkdata = src - 0x86;
+ height--;
+ dst = dst + height * stride;
+
+ while((size > 0) && (height >= 0)) {
+ code = *src++;
+ size--;
+
+ if(delta) {
+ /* motion compensation */
+ while((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 = *src++;
+ size--;
+
+ 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) * width;
+ for(j = 0; j < me_h; j++) {
+ for(i = 0; i < me_w; i++)
+ dst[filled + i - (j * stride)] = me_plane[i - (j * width)];
+ }
+ }
+ }
+ code = *src++;
+ size--;
+ }
+ }
+
+ if(code == 0xE0) /* end-of-picture code */
+ break;
+ if(code > 0xE0) { /* run code: 0xE1..0xFF */
+ int p;
+
+ code &= 0x1F;
+ p = *src++;
+ size--;
+ for(i = 0; i <= code; i++) {
+ dst[filled++] = p;
+ if(filled >= width) {
+ filled = 0;
+ dst -= stride;
+ height--;
+ }
+ }
+ } else if(code >= 0xC0) { /* copy code: 0xC0..0xDF */
+ code &= 0x1F;
+
+ for(i = 0; i <= code; i++) {
+ dst[filled++] = *src++;
+ if(filled >= width) {
+ filled = 0;
+ dst -= stride;
+ height--;
+ }
+ }
+ size -= code + 1;
+ } 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 = (*src++) + 64;
+ else if(code == 1)
+ skip = (*src++) + 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 *data_size,
+ uint8_t *buf, int buf_size)
+{
+ QpegContext * const a = avctx->priv_data;
+ AVFrame * const p= (AVFrame*)&a->pic;
+ uint8_t* outdata;
+ int delta;
+
+ if(p->data[0])
+ avctx->release_buffer(avctx, p);
+
+ p->reference= 0;
+ if(avctx->get_buffer(avctx, p) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+ outdata = a->pic.data[0];
+ if(buf[0x85] == 0x10) {
+ qpeg_decode_intra(buf+0x86, outdata, buf_size - 0x86, a->pic.linesize[0], avctx->width, avctx->height);
+ } else {
+ delta = buf[0x85];
+ qpeg_decode_inter(buf+0x86, outdata, buf_size - 0x86, a->pic.linesize[0], avctx->width, avctx->height, delta, buf + 4, a->refdata);
+ }
+
+ /* make the palette available on the way out */
+ memcpy(a->pic.data[1], a->avctx->palctrl->palette, AVPALETTE_SIZE);
+ if (a->avctx->palctrl->palette_changed) {
+ a->pic.palette_has_changed = 1;
+ a->avctx->palctrl->palette_changed = 0;
+ }
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = a->pic;
+
+ return buf_size;
+}
+
+static int decode_init(AVCodecContext *avctx){
+ QpegContext * const a = avctx->priv_data;
+
+ a->avctx = avctx;
+ avctx->pix_fmt= PIX_FMT_PAL8;
+ avctx->has_b_frames = 0;
+ a->pic.data[0] = NULL;
+ a->refdata = av_malloc(avctx->width * avctx->height);
+
+ return 0;
+}
+
+static int decode_end(AVCodecContext *avctx){
+ QpegContext * const a = avctx->priv_data;
+ AVFrame * const p= (AVFrame*)&a->pic;
+
+ if(p->data[0])
+ avctx->release_buffer(avctx, p);
+
+ av_free(a->refdata);
+ return 0;
+}
+
+AVCodec qpeg_decoder = {
+ "qpeg",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_QPEG,
+ sizeof(QpegContext),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/qtrle.c b/contrib/ffmpeg/libavcodec/qtrle.c
new file mode 100644
index 000000000..d4b314d03
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/qtrle.c
@@ -0,0 +1,630 @@
+/*
+ * 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 qtrle.c
+ * 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 RGBA32.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.h"
+
+typedef struct QtrleContext {
+
+ AVCodecContext *avctx;
+ DSPContext dsp;
+ AVFrame frame;
+
+ unsigned char *buf;
+ int size;
+
+} QtrleContext;
+
+#define CHECK_STREAM_PTR(n) \
+ if ((stream_ptr + n) > s->size) { \
+ av_log (s->avctx, AV_LOG_INFO, "Problem: stream_ptr out of bounds (%d >= %d)\n", \
+ stream_ptr + n, s->size); \
+ return; \
+ }
+
+#define CHECK_PIXEL_PTR(n) \
+ if ((pixel_ptr + n > pixel_limit) || (pixel_ptr + n < 0)) { \
+ av_log (s->avctx, AV_LOG_INFO, "Problem: pixel_ptr = %d, pixel_limit = %d\n", \
+ pixel_ptr + n, pixel_limit); \
+ return; \
+ } \
+
+static void qtrle_decode_1bpp(QtrleContext *s)
+{
+}
+
+static void qtrle_decode_2bpp(QtrleContext *s)
+{
+}
+
+static void qtrle_decode_4bpp(QtrleContext *s)
+{
+ int stream_ptr;
+ int header;
+ int start_line;
+ int lines_to_change;
+ int rle_code;
+ int row_ptr, pixel_ptr;
+ int row_inc = s->frame.linesize[0];
+ unsigned char pi1, pi2, pi3, pi4, pi5, pi6, pi7, pi8; /* 8 palette indices */
+ unsigned char *rgb = s->frame.data[0];
+ int pixel_limit = s->frame.linesize[0] * s->avctx->height;
+
+ /* check if this frame is even supposed to change */
+ if (s->size < 8)
+ return;
+
+ /* start after the chunk size */
+ stream_ptr = 4;
+
+ /* fetch the header */
+ CHECK_STREAM_PTR(2);
+ header = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 2;
+
+ /* if a header is present, fetch additional decoding parameters */
+ if (header & 0x0008) {
+ CHECK_STREAM_PTR(8);
+ start_line = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 4;
+ lines_to_change = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 4;
+ } else {
+ start_line = 0;
+ lines_to_change = s->avctx->height;
+ }
+
+ row_ptr = row_inc * start_line;
+ while (lines_to_change--) {
+ CHECK_STREAM_PTR(2);
+ pixel_ptr = row_ptr + (8 * (s->buf[stream_ptr++] - 1));
+
+ while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
+ if (rle_code == 0) {
+ /* there's another skip code in the stream */
+ CHECK_STREAM_PTR(1);
+ pixel_ptr += (8 * (s->buf[stream_ptr++] - 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
+ * indices, and output them rle_code times */
+ CHECK_STREAM_PTR(4);
+ pi1 = ((s->buf[stream_ptr]) >> 4) & 0x0f;
+ pi2 = (s->buf[stream_ptr++]) & 0x0f;
+ pi3 = ((s->buf[stream_ptr]) >> 4) & 0x0f;
+ pi4 = (s->buf[stream_ptr++]) & 0x0f;
+ pi5 = ((s->buf[stream_ptr]) >> 4) & 0x0f;
+ pi6 = (s->buf[stream_ptr++]) & 0x0f;
+ pi7 = ((s->buf[stream_ptr]) >> 4) & 0x0f;
+ pi8 = (s->buf[stream_ptr++]) & 0x0f;
+
+ CHECK_PIXEL_PTR(rle_code * 8);
+
+ while (rle_code--) {
+ rgb[pixel_ptr++] = pi1;
+ rgb[pixel_ptr++] = pi2;
+ rgb[pixel_ptr++] = pi3;
+ rgb[pixel_ptr++] = pi4;
+ rgb[pixel_ptr++] = pi5;
+ rgb[pixel_ptr++] = pi6;
+ rgb[pixel_ptr++] = pi7;
+ rgb[pixel_ptr++] = pi8;
+ }
+ } else {
+ /* copy the same pixel directly to output 4 times */
+ rle_code *= 4;
+ CHECK_STREAM_PTR(rle_code);
+ CHECK_PIXEL_PTR(rle_code*2);
+
+ while (rle_code--) {
+ rgb[pixel_ptr++] = ((s->buf[stream_ptr]) >> 4) & 0x0f;
+ rgb[pixel_ptr++] = (s->buf[stream_ptr++]) & 0x0f;
+ }
+ }
+ }
+ row_ptr += row_inc;
+ }
+}
+
+static void qtrle_decode_8bpp(QtrleContext *s)
+{
+ int stream_ptr;
+ int header;
+ int start_line;
+ int lines_to_change;
+ int rle_code;
+ int row_ptr, pixel_ptr;
+ int row_inc = s->frame.linesize[0];
+ unsigned char pi1, pi2, pi3, pi4; /* 4 palette indices */
+ unsigned char *rgb = s->frame.data[0];
+ int pixel_limit = s->frame.linesize[0] * s->avctx->height;
+
+ /* check if this frame is even supposed to change */
+ if (s->size < 8)
+ return;
+
+ /* start after the chunk size */
+ stream_ptr = 4;
+
+ /* fetch the header */
+ CHECK_STREAM_PTR(2);
+ header = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 2;
+
+ /* if a header is present, fetch additional decoding parameters */
+ if (header & 0x0008) {
+ CHECK_STREAM_PTR(8);
+ start_line = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 4;
+ lines_to_change = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 4;
+ } else {
+ start_line = 0;
+ lines_to_change = s->avctx->height;
+ }
+
+ row_ptr = row_inc * start_line;
+ while (lines_to_change--) {
+ CHECK_STREAM_PTR(2);
+ pixel_ptr = row_ptr + (4 * (s->buf[stream_ptr++] - 1));
+
+ while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
+ if (rle_code == 0) {
+ /* there's another skip code in the stream */
+ CHECK_STREAM_PTR(1);
+ pixel_ptr += (4 * (s->buf[stream_ptr++] - 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
+ * indices, and output them rle_code times */
+ CHECK_STREAM_PTR(4);
+ pi1 = s->buf[stream_ptr++];
+ pi2 = s->buf[stream_ptr++];
+ pi3 = s->buf[stream_ptr++];
+ pi4 = s->buf[stream_ptr++];
+
+ 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_STREAM_PTR(rle_code);
+ CHECK_PIXEL_PTR(rle_code);
+
+ while (rle_code--) {
+ rgb[pixel_ptr++] = s->buf[stream_ptr++];
+ }
+ }
+ }
+ row_ptr += row_inc;
+ }
+}
+
+static void qtrle_decode_16bpp(QtrleContext *s)
+{
+ int stream_ptr;
+ int header;
+ int start_line;
+ int lines_to_change;
+ int rle_code;
+ int row_ptr, 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;
+
+ /* check if this frame is even supposed to change */
+ if (s->size < 8)
+ return;
+
+ /* start after the chunk size */
+ stream_ptr = 4;
+
+ /* fetch the header */
+ CHECK_STREAM_PTR(2);
+ header = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 2;
+
+ /* if a header is present, fetch additional decoding parameters */
+ if (header & 0x0008) {
+ CHECK_STREAM_PTR(8);
+ start_line = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 4;
+ lines_to_change = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 4;
+ } else {
+ start_line = 0;
+ lines_to_change = s->avctx->height;
+ }
+
+ row_ptr = row_inc * start_line;
+ while (lines_to_change--) {
+ CHECK_STREAM_PTR(2);
+ pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 2;
+
+ while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
+ if (rle_code == 0) {
+ /* there's another skip code in the stream */
+ CHECK_STREAM_PTR(1);
+ pixel_ptr += (s->buf[stream_ptr++] - 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;
+ CHECK_STREAM_PTR(2);
+ rgb16 = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 2;
+
+ CHECK_PIXEL_PTR(rle_code * 2);
+
+ while (rle_code--) {
+ *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
+ pixel_ptr += 2;
+ }
+ } else {
+ CHECK_STREAM_PTR(rle_code * 2);
+ CHECK_PIXEL_PTR(rle_code * 2);
+
+ /* copy pixels directly to output */
+ while (rle_code--) {
+ rgb16 = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 2;
+ *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
+ pixel_ptr += 2;
+ }
+ }
+ }
+ row_ptr += row_inc;
+ }
+}
+
+static void qtrle_decode_24bpp(QtrleContext *s)
+{
+ int stream_ptr;
+ int header;
+ int start_line;
+ int lines_to_change;
+ int rle_code;
+ int row_ptr, 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;
+
+ /* check if this frame is even supposed to change */
+ if (s->size < 8)
+ return;
+
+ /* start after the chunk size */
+ stream_ptr = 4;
+
+ /* fetch the header */
+ CHECK_STREAM_PTR(2);
+ header = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 2;
+
+ /* if a header is present, fetch additional decoding parameters */
+ if (header & 0x0008) {
+ CHECK_STREAM_PTR(8);
+ start_line = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 4;
+ lines_to_change = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 4;
+ } else {
+ start_line = 0;
+ lines_to_change = s->avctx->height;
+ }
+
+ row_ptr = row_inc * start_line;
+ while (lines_to_change--) {
+ CHECK_STREAM_PTR(2);
+ pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 3;
+
+ while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
+ if (rle_code == 0) {
+ /* there's another skip code in the stream */
+ CHECK_STREAM_PTR(1);
+ pixel_ptr += (s->buf[stream_ptr++] - 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;
+ CHECK_STREAM_PTR(3);
+ r = s->buf[stream_ptr++];
+ g = s->buf[stream_ptr++];
+ b = s->buf[stream_ptr++];
+
+ CHECK_PIXEL_PTR(rle_code * 3);
+
+ while (rle_code--) {
+ rgb[pixel_ptr++] = r;
+ rgb[pixel_ptr++] = g;
+ rgb[pixel_ptr++] = b;
+ }
+ } else {
+ CHECK_STREAM_PTR(rle_code * 3);
+ CHECK_PIXEL_PTR(rle_code * 3);
+
+ /* copy pixels directly to output */
+ while (rle_code--) {
+ rgb[pixel_ptr++] = s->buf[stream_ptr++];
+ rgb[pixel_ptr++] = s->buf[stream_ptr++];
+ rgb[pixel_ptr++] = s->buf[stream_ptr++];
+ }
+ }
+ }
+ row_ptr += row_inc;
+ }
+}
+
+static void qtrle_decode_32bpp(QtrleContext *s)
+{
+ int stream_ptr;
+ int header;
+ int start_line;
+ int lines_to_change;
+ int rle_code;
+ int row_ptr, pixel_ptr;
+ int row_inc = s->frame.linesize[0];
+ unsigned char a, r, g, b;
+ unsigned int argb;
+ unsigned char *rgb = s->frame.data[0];
+ int pixel_limit = s->frame.linesize[0] * s->avctx->height;
+
+ /* check if this frame is even supposed to change */
+ if (s->size < 8)
+ return;
+
+ /* start after the chunk size */
+ stream_ptr = 4;
+
+ /* fetch the header */
+ CHECK_STREAM_PTR(2);
+ header = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 2;
+
+ /* if a header is present, fetch additional decoding parameters */
+ if (header & 0x0008) {
+ CHECK_STREAM_PTR(8);
+ start_line = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 4;
+ lines_to_change = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 4;
+ } else {
+ start_line = 0;
+ lines_to_change = s->avctx->height;
+ }
+
+ row_ptr = row_inc * start_line;
+ while (lines_to_change--) {
+ CHECK_STREAM_PTR(2);
+ pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 4;
+
+ while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
+ if (rle_code == 0) {
+ /* there's another skip code in the stream */
+ CHECK_STREAM_PTR(1);
+ pixel_ptr += (s->buf[stream_ptr++] - 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;
+ CHECK_STREAM_PTR(4);
+ a = s->buf[stream_ptr++];
+ r = s->buf[stream_ptr++];
+ g = s->buf[stream_ptr++];
+ b = s->buf[stream_ptr++];
+ argb = (a << 24) | (r << 16) | (g << 8) | (b << 0);
+
+ CHECK_PIXEL_PTR(rle_code * 4);
+
+ while (rle_code--) {
+ *(unsigned int *)(&rgb[pixel_ptr]) = argb;
+ pixel_ptr += 4;
+ }
+ } else {
+ CHECK_STREAM_PTR(rle_code * 4);
+ CHECK_PIXEL_PTR(rle_code * 4);
+
+ /* copy pixels directly to output */
+ while (rle_code--) {
+ a = s->buf[stream_ptr++];
+ r = s->buf[stream_ptr++];
+ g = s->buf[stream_ptr++];
+ b = s->buf[stream_ptr++];
+ argb = (a << 24) | (r << 16) | (g << 8) | (b << 0);
+ *(unsigned int *)(&rgb[pixel_ptr]) = argb;
+ pixel_ptr += 4;
+ }
+ }
+ }
+ row_ptr += row_inc;
+ }
+}
+
+static int qtrle_decode_init(AVCodecContext *avctx)
+{
+ QtrleContext *s = (QtrleContext *)avctx->priv_data;
+
+ s->avctx = avctx;
+ switch (avctx->bits_per_sample) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 33:
+ case 34:
+ case 36:
+ case 40:
+ avctx->pix_fmt = PIX_FMT_PAL8;
+ break;
+
+ case 16:
+ avctx->pix_fmt = PIX_FMT_RGB555;
+ break;
+
+ case 24:
+ avctx->pix_fmt = PIX_FMT_RGB24;
+ break;
+
+ case 32:
+ avctx->pix_fmt = PIX_FMT_RGBA32;
+ break;
+
+ default:
+ av_log (avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
+ avctx->bits_per_sample);
+ break;
+ }
+ avctx->has_b_frames = 0;
+ dsputil_init(&s->dsp, avctx);
+
+ s->frame.data[0] = NULL;
+
+ return 0;
+}
+
+static int qtrle_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ QtrleContext *s = (QtrleContext *)avctx->priv_data;
+
+ s->buf = buf;
+ s->size = buf_size;
+
+ s->frame.reference = 1;
+ s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
+ FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
+ if (avctx->reget_buffer(avctx, &s->frame)) {
+ av_log (s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+ return -1;
+ }
+
+ switch (avctx->bits_per_sample) {
+ case 1:
+ case 33:
+ qtrle_decode_1bpp(s);
+ break;
+
+ case 2:
+ case 34:
+ qtrle_decode_2bpp(s);
+ break;
+
+ case 4:
+ case 36:
+ qtrle_decode_4bpp(s);
+ /* make the palette available on the way out */
+ memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
+ if (s->avctx->palctrl->palette_changed) {
+ s->frame.palette_has_changed = 1;
+ s->avctx->palctrl->palette_changed = 0;
+ }
+ break;
+
+ case 8:
+ case 40:
+ qtrle_decode_8bpp(s);
+ /* make the palette available on the way out */
+ memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
+ if (s->avctx->palctrl->palette_changed) {
+ s->frame.palette_has_changed = 1;
+ s->avctx->palctrl->palette_changed = 0;
+ }
+ break;
+
+ case 16:
+ qtrle_decode_16bpp(s);
+ break;
+
+ case 24:
+ qtrle_decode_24bpp(s);
+ break;
+
+ case 32:
+ qtrle_decode_32bpp(s);
+ break;
+
+ default:
+ av_log (s->avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
+ avctx->bits_per_sample);
+ break;
+ }
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = s->frame;
+
+ /* always report that the buffer was completely consumed */
+ return buf_size;
+}
+
+static int qtrle_decode_end(AVCodecContext *avctx)
+{
+ QtrleContext *s = (QtrleContext *)avctx->priv_data;
+
+ if (s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ return 0;
+}
+
+AVCodec qtrle_decoder = {
+ "qtrle",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_QTRLE,
+ sizeof(QtrleContext),
+ qtrle_decode_init,
+ NULL,
+ qtrle_decode_end,
+ qtrle_decode_frame,
+ CODEC_CAP_DR1,
+};
+
diff --git a/contrib/ffmpeg/libavcodec/ra144.c b/contrib/ffmpeg/libavcodec/ra144.c
new file mode 100644
index 000000000..c4f4b813b
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ra144.c
@@ -0,0 +1,519 @@
+/*
+ * 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 "avcodec.h"
+#include "ra144.h"
+
+#define DATABLOCK1 20 /* size of 14.4 input block in bytes */
+#define DATACHUNK1 1440 /* size of 14.4 input chunk in bytes */
+#define AUDIOBLOCK 160 /* size of output block in 16-bit words (320 bytes) */
+#define AUDIOBUFFER 12288 /* size of output buffer in 16-bit words (24576 bytes) */
+/* consts */
+#define NBLOCKS 4 /* number of segments within a block */
+#define BLOCKSIZE 40 /* (quarter) block size in 16-bit words (80 bytes) */
+#define HALFBLOCK 20 /* BLOCKSIZE/2 */
+#define BUFFERSIZE 146 /* for do_output */
+
+
+/* internal globals */
+typedef struct {
+ unsigned int resetflag, val, oldval;
+ unsigned int unpacked[28]; /* buffer for unpacked input */
+ unsigned int *iptr; /* pointer to current input (from unpacked) */
+ unsigned int gval;
+ unsigned short *gsp;
+ unsigned int gbuf1[8];
+ unsigned short gbuf2[120];
+ signed short output_buffer[40];
+ unsigned int *decptr; /* decoder ptr */
+ signed short *decsp;
+
+ /* the swapped buffers */
+ unsigned int swapb1a[10];
+ unsigned int swapb2a[10];
+ unsigned int swapb1b[10];
+ unsigned int swapb2b[10];
+ unsigned int *swapbuf1;
+ unsigned int *swapbuf2;
+ unsigned int *swapbuf1alt;
+ unsigned int *swapbuf2alt;
+
+ unsigned int buffer[5];
+ unsigned short int buffer_2[148];
+ unsigned short int buffer_a[40];
+ unsigned short int buffer_b[40];
+ unsigned short int buffer_c[40];
+ unsigned short int buffer_d[40];
+
+ unsigned short int work[50];
+ unsigned short *sptr;
+
+ int buffer1[10];
+ int buffer2[10];
+
+ signed short wavtable1[2304];
+ unsigned short wavtable2[2304];
+} Real144_internal;
+
+static int ra144_decode_init(AVCodecContext * avctx)
+{
+ Real144_internal *glob=avctx->priv_data;
+
+ memset(glob,0,sizeof(Real144_internal));
+ glob->resetflag=1;
+ glob->swapbuf1=glob->swapb1a;
+ glob->swapbuf2=glob->swapb2a;
+ glob->swapbuf1alt=glob->swapb1b;
+ glob->swapbuf2alt=glob->swapb2b;
+
+ memcpy(glob->wavtable1,wavtable1,sizeof(wavtable1));
+ memcpy(glob->wavtable2,wavtable2,sizeof(wavtable2));
+
+ return 0;
+}
+
+static void final(Real144_internal *glob, short *i1, short *i2, void *out, int *statbuf, int len);
+static void add_wav(Real144_internal *glob, int n, int f, int m1, int m2, int m3, short *s1, short *s2, short *s3, short *dest);
+static int irms(short *data, int factor);
+static void rotate_block(short *source, short *target, int offset);
+/* lookup square roots in table */
+static int t_sqrt(unsigned int x)
+{
+ int s=0;
+ while (x>0xfff) { s++; x=x>>2; }
+ return (sqrt_table[x]<<s)<<2;
+}
+
+/* do 'voice' */
+static void do_voice(int *a1, int *a2)
+{
+ int buffer[10];
+ int *b1,*b2;
+ int x,y;
+ int *ptr,*tmp;
+
+ b1=buffer;
+ b2=a2;
+
+ for (x=0;x<10;x++) {
+ b1[x]=(*a1)<<4;
+
+ if(x>0) {
+ ptr=b2+x;
+ for (y=0;y<=x-1;y++)
+ b1[y]=(((*a1)*(*(--ptr)))>>12)+b2[y];
+ }
+ tmp=b1;
+ b1=b2;
+ b2=tmp;
+ a1++;
+ }
+ ptr=a2+10;
+ while (ptr>a2) (*a2++)>>=4;
+}
+
+
+/* do quarter-block output */
+static void do_output_subblock(Real144_internal *glob, unsigned int x)
+{
+ int a,b,c,d,e,f,g;
+
+ if (x==1) memset(glob->buffer,0,20);
+ if ((*glob->iptr)==0) a=0;
+ else a=(*glob->iptr)+HALFBLOCK-1;
+ glob->iptr++;
+ b=*(glob->iptr++);
+ c=*(glob->iptr++);
+ d=*(glob->iptr++);
+ if (a) rotate_block(glob->buffer_2,glob->buffer_a,a);
+ memcpy(glob->buffer_b,etable1+b*BLOCKSIZE,BLOCKSIZE*2);
+ e=((ftable1[b]>>4)*glob->gval)>>8;
+ memcpy(glob->buffer_c,etable2+c*BLOCKSIZE,BLOCKSIZE*2);
+ f=((ftable2[c]>>4)*glob->gval)>>8;
+ if (a) g=irms(glob->buffer_a,glob->gval)>>12;
+ else g=0;
+ add_wav(glob,d,a,g,e,f,glob->buffer_a,glob->buffer_b,glob->buffer_c,glob->buffer_d);
+ memmove(glob->buffer_2,glob->buffer_2+BLOCKSIZE,(BUFFERSIZE-BLOCKSIZE)*2);
+ memcpy(glob->buffer_2+BUFFERSIZE-BLOCKSIZE,glob->buffer_d,BLOCKSIZE*2);
+ final(glob,glob->gsp,glob->buffer_d,glob->output_buffer,glob->buffer,BLOCKSIZE);
+}
+
+/* rotate block */
+static void rotate_block(short *source, short *target, int offset)
+{
+ short *end;
+ short *ptr1;
+ short *ptr2;
+ short *ptr3;
+ ptr2=source+BUFFERSIZE;
+ ptr3=ptr1=ptr2-offset;
+ end=target+BLOCKSIZE;
+ while (target<end) {
+ *(target++)=*(ptr3++);
+ if (ptr3==ptr2) ptr3=ptr1;
+ }
+}
+
+/* inverse root mean square */
+static int irms(short *data, int factor)
+{
+ short *p1,*p2;
+ unsigned int sum;
+ p2=(p1=data)+BLOCKSIZE;
+ for (sum=0;p2>p1;p1++) sum+=(*p1)*(*p1);
+ if (sum==0) return 0; /* OOPS - division by zero */
+ return (0x20000000/(t_sqrt(sum)>>8))*factor;
+}
+
+/* multiply/add wavetable */
+static void add_wav(Real144_internal *glob, int n, int f, int m1, int m2, int m3, short *s1, short *s2, short *s3, short *dest)
+{
+ int a,b,c;
+ short *ptr,*ptr2;
+
+ ptr=glob->wavtable1+n*9;
+ ptr2=glob->wavtable2+n*9;
+ if (f!=0) {
+ a=((*ptr)*m1)>>((*ptr2)+1);
+ } else {
+ a=0;
+ }
+ ptr++;ptr2++;
+ b=((*ptr)*m2)>>((*ptr2)+1);
+ ptr++;ptr2++;
+ c=((*ptr)*m3)>>((*ptr2)+1);
+ ptr2=(ptr=dest)+BLOCKSIZE;
+ if (f!=0)
+ while (ptr<ptr2)
+ *(ptr++)=((*(s1++))*a+(*(s2++))*b+(*(s3++))*c)>>12;
+ else
+ while (ptr<ptr2)
+ *(ptr++)=((*(s2++))*b+(*(s3++))*c)>>12;
+}
+
+
+static void final(Real144_internal *glob, short *i1, short *i2, void *out, int *statbuf, int len)
+{
+ int x,sum;
+ int buffer[10];
+ short *ptr;
+ short *ptr2;
+
+ memcpy(glob->work,statbuf,20);
+ memcpy(glob->work+10,i2,len*2);
+
+ buffer[9]=i1[0];
+ buffer[8]=i1[1];
+ buffer[7]=i1[2];
+ buffer[6]=i1[3];
+ buffer[5]=i1[4];
+ buffer[4]=i1[5];
+ buffer[3]=i1[6];
+ buffer[2]=i1[7];
+ buffer[1]=i1[8];
+ buffer[0]=i1[9];
+
+ ptr2=(ptr=glob->work)+len;
+ while (ptr<ptr2) {
+ for(sum=0,x=0;x<=9;x++)
+ sum+=buffer[x]*(ptr[x]);
+ sum=sum>>12;
+ x=ptr[10]-sum;
+ if (x<-32768 || x>32767)
+ {
+ memset(out,0,len*2);
+ memset(statbuf,0,20);
+ return;
+ }
+ ptr[10]=x;
+ ptr++;
+ }
+ memcpy(out,ptr+10-len,len*2);
+ memcpy(statbuf,ptr,20);
+}
+
+/* Decode 20-byte input */
+static void unpack_input(unsigned char *input, unsigned int *output)
+{
+ unsigned int outbuffer[28];
+ unsigned short inbuffer[10];
+ unsigned int x;
+ unsigned int *ptr;
+
+ /* fix endianness */
+ for (x=0;x<20;x+=2)
+ inbuffer[x/2]=(input[x]<<8)+input[x+1];
+
+ /* unpack */
+ ptr=outbuffer;
+ *(ptr++)=27;
+ *(ptr++)=(inbuffer[0]>>10)&0x3f;
+ *(ptr++)=(inbuffer[0]>>5)&0x1f;
+ *(ptr++)=inbuffer[0]&0x1f;
+ *(ptr++)=(inbuffer[1]>>12)&0xf;
+ *(ptr++)=(inbuffer[1]>>8)&0xf;
+ *(ptr++)=(inbuffer[1]>>5)&7;
+ *(ptr++)=(inbuffer[1]>>2)&7;
+ *(ptr++)=((inbuffer[1]<<1)&6)|((inbuffer[2]>>15)&1);
+ *(ptr++)=(inbuffer[2]>>12)&7;
+ *(ptr++)=(inbuffer[2]>>10)&3;
+ *(ptr++)=(inbuffer[2]>>5)&0x1f;
+ *(ptr++)=((inbuffer[2]<<2)&0x7c)|((inbuffer[3]>>14)&3);
+ *(ptr++)=(inbuffer[3]>>6)&0xff;
+ *(ptr++)=((inbuffer[3]<<1)&0x7e)|((inbuffer[4]>>15)&1);
+ *(ptr++)=(inbuffer[4]>>8)&0x7f;
+ *(ptr++)=(inbuffer[4]>>1)&0x7f;
+ *(ptr++)=((inbuffer[4]<<7)&0x80)|((inbuffer[5]>>9)&0x7f);
+ *(ptr++)=(inbuffer[5]>>2)&0x7f;
+ *(ptr++)=((inbuffer[5]<<5)&0x60)|((inbuffer[6]>>11)&0x1f);
+ *(ptr++)=(inbuffer[6]>>4)&0x7f;
+ *(ptr++)=((inbuffer[6]<<4)&0xf0)|((inbuffer[7]>>12)&0xf);
+ *(ptr++)=(inbuffer[7]>>5)&0x7f;
+ *(ptr++)=((inbuffer[7]<<2)&0x7c)|((inbuffer[8]>>14)&3);
+ *(ptr++)=(inbuffer[8]>>7)&0x7f;
+ *(ptr++)=((inbuffer[8]<<1)&0xfe)|((inbuffer[9]>>15)&1);
+ *(ptr++)=(inbuffer[9]>>8)&0x7f;
+ *(ptr++)=(inbuffer[9]>>1)&0x7f;
+
+ *(output++)=outbuffer[11];
+ for (x=1;x<11;*(output++)=outbuffer[x++]);
+ ptr=outbuffer+12;
+ for (x=0;x<16;x+=4)
+ {
+ *(output++)=ptr[x];
+ *(output++)=ptr[x+2];
+ *(output++)=ptr[x+3];
+ *(output++)=ptr[x+1];
+ }
+}
+
+static unsigned int rms(int *data, int f)
+{
+ int *c;
+ int x;
+ unsigned int res;
+ int b;
+
+ c=data;
+ b=0;
+ res=0x10000;
+ for (x=0;x<10;x++)
+ {
+ res=(((0x1000000-(*c)*(*c))>>12)*res)>>12;
+ if (res==0) return 0;
+ if (res<=0x3fff)
+ {
+ while (res<=0x3fff)
+ {
+ b++;
+ res<<=2;
+ }
+ } else {
+ if (res>0x10000)
+ return 0; /* We're screwed, might as well go out with a bang. :P */
+ }
+ c++;
+ }
+ if (res>0) res=t_sqrt(res);
+
+ res>>=(b+10);
+ res=(res*f)>>10;
+ return res;
+}
+
+static void dec1(Real144_internal *glob, int *data, int *inp, int n, int f)
+{
+ short *ptr,*end;
+
+ *(glob->decptr++)=rms(data,f);
+ glob->decptr++;
+ end=(ptr=glob->decsp)+(n*10);
+ while (ptr<end) *(ptr++)=*(inp++);
+}
+
+static int eq(Real144_internal *glob, short *in, int *target)
+{
+ int retval;
+ int a;
+ int b;
+ int c;
+ unsigned int u;
+ short *sptr;
+ int *ptr1,*ptr2,*ptr3;
+ int *bp1,*bp2,*temp;
+
+ retval=0;
+ bp1=glob->buffer1;
+ bp2=glob->buffer2;
+ ptr2=(ptr3=glob->buffer2)+9;
+ sptr=in;
+ while (ptr2>=ptr3)
+ *(ptr3++)=*(sptr++);
+
+ target+=9;
+ a=bp2[9];
+ *target=a;
+ if (a+0x1000>0x1fff)
+ return 0; /* We're screwed, might as well go out with a bang. :P */
+ c=8;u=a;
+ while (c>=0)
+ {
+ if (u==0x1000) u++;
+ if (u==0xfffff000) u--;
+ b=0x1000-((u*u)>>12);
+ if (b==0) b++;
+ ptr2=bp1;
+ ptr1=(ptr3=bp2)+c;
+ for (u=0;u<=c;u++)
+ *(ptr2++)=((*(ptr3++)-(((*target)*(*(ptr1--)))>>12))*(0x1000000/b))>>12;
+ *(--target)=u=bp1[(c--)];
+ if ((u+0x1000)>0x1fff) retval=1;
+ temp=bp2;
+ bp2=bp1;
+ bp1=temp;
+ }
+ return retval;
+}
+
+static void dec2(Real144_internal *glob, int *data, int *inp, int n, int f, int *inp2, int l)
+{
+ unsigned int *ptr1,*ptr2;
+ int work[10];
+ int a,b;
+ int x;
+ int result;
+
+ if(l+1<NBLOCKS/2) a=NBLOCKS-(l+1);
+ else a=l+1;
+ b=NBLOCKS-a;
+ if (l==0)
+ {
+ glob->decsp=glob->sptr=glob->gbuf2;
+ glob->decptr=glob->gbuf1;
+ }
+ ptr1=inp;
+ ptr2=inp2;
+ for (x=0;x<10*n;x++)
+ *(glob->sptr++)=(a*(*ptr1++)+b*(*ptr2++))>>2;
+ result=eq(glob,glob->decsp,work);
+ if (result==1)
+ {
+ dec1(glob,data,inp,n,f);
+ } else {
+ *(glob->decptr++)=rms(work,f);
+ glob->decptr++;
+ }
+ glob->decsp+=n*10;
+}
+
+/* Uncompress one block (20 bytes -> 160*2 bytes) */
+static int ra144_decode_frame(AVCodecContext * avctx,
+ void *vdata, int *data_size,
+ uint8_t * buf, int buf_size)
+{
+ unsigned int a,b,c;
+ long s;
+ signed short *shptr;
+ unsigned int *lptr,*temp;
+ const short **dptr;
+ int16_t *datao;
+ int16_t *data = vdata;
+ Real144_internal *glob=avctx->priv_data;
+
+ if(buf_size==0)
+ return 0;
+
+ datao = data;
+ unpack_input(buf,glob->unpacked);
+
+ glob->iptr=glob->unpacked;
+ glob->val=decodetable[0][(*(glob->iptr++))<<1];
+
+ dptr=decodetable+1;
+ lptr=glob->swapbuf1;
+ while (lptr<glob->swapbuf1+10)
+ *(lptr++)=(*(dptr++))[(*(glob->iptr++))<<1];
+
+ do_voice(glob->swapbuf1,glob->swapbuf2);
+
+ a=t_sqrt(glob->val*glob->oldval)>>12;
+
+ for (c=0;c<NBLOCKS;c++) {
+ if (c==(NBLOCKS-1)) {
+ dec1(glob,glob->swapbuf1,glob->swapbuf2,3,glob->val);
+ } else {
+ if (c*2==(NBLOCKS-2)) {
+ if (glob->oldval<glob->val) {
+ dec2(glob,glob->swapbuf1,glob->swapbuf2,3,a,glob->swapbuf2alt,c);
+ } else {
+ dec2(glob,glob->swapbuf1alt,glob->swapbuf2alt,3,a,glob->swapbuf2,c);
+ }
+ } else {
+ if (c*2<(NBLOCKS-2)) {
+ dec2(glob,glob->swapbuf1alt,glob->swapbuf2alt,3,glob->oldval,glob->swapbuf2,c);
+ } else {
+ dec2(glob,glob->swapbuf1,glob->swapbuf2,3,glob->val,glob->swapbuf2alt,c);
+ }
+ }
+ }
+ }
+
+ /* do output */
+ for (b=0,c=0;c<4;c++) {
+ glob->gval=glob->gbuf1[c*2];
+ glob->gsp=glob->gbuf2+b;
+ do_output_subblock(glob,glob->resetflag);
+ glob->resetflag=0;
+
+ shptr=glob->output_buffer;
+ while (shptr<glob->output_buffer+BLOCKSIZE) {
+ s=*(shptr++)<<2;
+ *data=s;
+ if (s>32767) *data=32767;
+ if (s<-32767) *data=-32768;
+ data++;
+ }
+ b+=30;
+ }
+
+ glob->oldval=glob->val;
+ temp=glob->swapbuf1alt;
+ glob->swapbuf1alt=glob->swapbuf1;
+ glob->swapbuf1=temp;
+ temp=glob->swapbuf2alt;
+ glob->swapbuf2alt=glob->swapbuf2;
+ glob->swapbuf2=temp;
+ *data_size=(data-datao)*sizeof(*data);
+ return 20;
+}
+
+
+AVCodec ra_144_decoder =
+{
+ "real_144",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_RA_144,
+ sizeof(Real144_internal),
+ ra144_decode_init,
+ NULL,
+ NULL,
+ ra144_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/ra144.h b/contrib/ffmpeg/libavcodec/ra144.h
new file mode 100644
index 000000000..6d477b2f8
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ra144.h
@@ -0,0 +1,2428 @@
+/*
+ * 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 RA144TABLES_H
+#define RA144TABLES_H
+
+/* 14.4 data tables */
+static const unsigned short sqrt_table[4096]={
+0x0000,0x0400,0x05a8,0x06ed,0x0800,0x08f1,0x09cc,0x0a95,
+0x0b50,0x0c00,0x0ca6,0x0d44,0x0ddb,0x0e6c,0x0ef7,0x0f7d,
+0x1000,0x107e,0x10f8,0x116f,0x11e3,0x1254,0x12c2,0x132e,
+0x1398,0x1400,0x1465,0x14c8,0x152a,0x158a,0x15e8,0x1645,
+0x16a0,0x16fa,0x1752,0x17aa,0x1800,0x1854,0x18a8,0x18fa,
+0x194c,0x199c,0x19ec,0x1a3a,0x1a88,0x1ad5,0x1b21,0x1b6c,
+0x1bb6,0x1c00,0x1c48,0x1c90,0x1cd8,0x1d1e,0x1d64,0x1daa,
+0x1dee,0x1e33,0x1e76,0x1eb9,0x1efb,0x1f3d,0x1f7e,0x1fbf,
+0x2000,0x203f,0x207f,0x20bd,0x20fc,0x2139,0x2177,0x21b4,
+0x21f0,0x222d,0x2268,0x22a4,0x22df,0x2319,0x2353,0x238d,
+0x23c6,0x2400,0x2438,0x2471,0x24a9,0x24e0,0x2518,0x254f,
+0x2585,0x25bc,0x25f2,0x2628,0x265d,0x2693,0x26c8,0x26fc,
+0x2731,0x2765,0x2799,0x27cc,0x2800,0x2833,0x2865,0x2898,
+0x28ca,0x28fc,0x292e,0x2960,0x2991,0x29c2,0x29f3,0x2a24,
+0x2a54,0x2a85,0x2ab5,0x2ae5,0x2b14,0x2b44,0x2b73,0x2ba2,
+0x2bd1,0x2c00,0x2c2e,0x2c5c,0x2c8a,0x2cb8,0x2ce6,0x2d13,
+0x2d41,0x2d6e,0x2d9b,0x2dc8,0x2df4,0x2e21,0x2e4d,0x2e79,
+0x2ea5,0x2ed1,0x2efd,0x2f28,0x2f54,0x2f7f,0x2faa,0x2fd5,
+0x3000,0x302a,0x3055,0x307f,0x30a9,0x30d3,0x30fd,0x3127,
+0x3150,0x317a,0x31a3,0x31cc,0x31f5,0x321e,0x3247,0x3270,
+0x3298,0x32c1,0x32e9,0x3311,0x3339,0x3361,0x3389,0x33b0,
+0x33d8,0x3400,0x3427,0x344e,0x3475,0x349c,0x34c3,0x34ea,
+0x3510,0x3537,0x355d,0x3584,0x35aa,0x35d0,0x35f6,0x361c,
+0x3642,0x3667,0x368d,0x36b2,0x36d8,0x36fd,0x3722,0x3747,
+0x376c,0x3791,0x37b6,0x37db,0x3800,0x3824,0x3848,0x386d,
+0x3891,0x38b5,0x38d9,0x38fd,0x3921,0x3945,0x3969,0x398c,
+0x39b0,0x39d3,0x39f7,0x3a1a,0x3a3d,0x3a60,0x3a83,0x3aa6,
+0x3ac9,0x3aec,0x3b0f,0x3b31,0x3b54,0x3b76,0x3b99,0x3bbb,
+0x3bdd,0x3c00,0x3c22,0x3c44,0x3c66,0x3c87,0x3ca9,0x3ccb,
+0x3ced,0x3d0e,0x3d30,0x3d51,0x3d72,0x3d94,0x3db5,0x3dd6,
+0x3df7,0x3e18,0x3e39,0x3e5a,0x3e7b,0x3e9c,0x3ebc,0x3edd,
+0x3efd,0x3f1e,0x3f3e,0x3f5f,0x3f7f,0x3f9f,0x3fbf,0x3fdf,
+0x4000,0x401f,0x403f,0x405f,0x407f,0x409f,0x40be,0x40de,
+0x40fe,0x411d,0x413c,0x415c,0x417b,0x419a,0x41ba,0x41d9,
+0x41f8,0x4217,0x4236,0x4255,0x4273,0x4292,0x42b1,0x42d0,
+0x42ee,0x430d,0x432b,0x434a,0x4368,0x4387,0x43a5,0x43c3,
+0x43e1,0x4400,0x441e,0x443c,0x445a,0x4478,0x4495,0x44b3,
+0x44d1,0x44ef,0x450c,0x452a,0x4548,0x4565,0x4583,0x45a0,
+0x45be,0x45db,0x45f8,0x4615,0x4633,0x4650,0x466d,0x468a,
+0x46a7,0x46c4,0x46e1,0x46fe,0x471b,0x4737,0x4754,0x4771,
+0x478d,0x47aa,0x47c7,0x47e3,0x4800,0x481c,0x4838,0x4855,
+0x4871,0x488d,0x48a9,0x48c6,0x48e2,0x48fe,0x491a,0x4936,
+0x4952,0x496e,0x498a,0x49a5,0x49c1,0x49dd,0x49f9,0x4a14,
+0x4a30,0x4a4b,0x4a67,0x4a83,0x4a9e,0x4ab9,0x4ad5,0x4af0,
+0x4b0b,0x4b27,0x4b42,0x4b5d,0x4b78,0x4b93,0x4bae,0x4bca,
+0x4be5,0x4c00,0x4c1a,0x4c35,0x4c50,0x4c6b,0x4c86,0x4ca1,
+0x4cbb,0x4cd6,0x4cf1,0x4d0b,0x4d26,0x4d40,0x4d5b,0x4d75,
+0x4d90,0x4daa,0x4dc4,0x4ddf,0x4df9,0x4e13,0x4e2d,0x4e48,
+0x4e62,0x4e7c,0x4e96,0x4eb0,0x4eca,0x4ee4,0x4efe,0x4f18,
+0x4f32,0x4f4c,0x4f65,0x4f7f,0x4f99,0x4fb3,0x4fcc,0x4fe6,
+0x5000,0x5019,0x5033,0x504c,0x5066,0x507f,0x5099,0x50b2,
+0x50cb,0x50e5,0x50fe,0x5117,0x5130,0x514a,0x5163,0x517c,
+0x5195,0x51ae,0x51c7,0x51e0,0x51f9,0x5212,0x522b,0x5244,
+0x525d,0x5276,0x528f,0x52a7,0x52c0,0x52d9,0x52f2,0x530a,
+0x5323,0x533c,0x5354,0x536d,0x5385,0x539e,0x53b6,0x53cf,
+0x53e7,0x5400,0x5418,0x5430,0x5449,0x5461,0x5479,0x5491,
+0x54a9,0x54c2,0x54da,0x54f2,0x550a,0x5522,0x553a,0x5552,
+0x556a,0x5582,0x559a,0x55b2,0x55ca,0x55e2,0x55fa,0x5611,
+0x5629,0x5641,0x5659,0x5670,0x5688,0x56a0,0x56b7,0x56cf,
+0x56e6,0x56fe,0x5716,0x572d,0x5745,0x575c,0x5773,0x578b,
+0x57a2,0x57ba,0x57d1,0x57e8,0x5800,0x5817,0x582e,0x5845,
+0x585c,0x5874,0x588b,0x58a2,0x58b9,0x58d0,0x58e7,0x58fe,
+0x5915,0x592c,0x5943,0x595a,0x5971,0x5988,0x599f,0x59b5,
+0x59cc,0x59e3,0x59fa,0x5a11,0x5a27,0x5a3e,0x5a55,0x5a6b,
+0x5a82,0x5a99,0x5aaf,0x5ac6,0x5adc,0x5af3,0x5b09,0x5b20,
+0x5b36,0x5b4d,0x5b63,0x5b7a,0x5b90,0x5ba6,0x5bbd,0x5bd3,
+0x5be9,0x5c00,0x5c16,0x5c2c,0x5c42,0x5c58,0x5c6f,0x5c85,
+0x5c9b,0x5cb1,0x5cc7,0x5cdd,0x5cf3,0x5d09,0x5d1f,0x5d35,
+0x5d4b,0x5d61,0x5d77,0x5d8d,0x5da3,0x5db9,0x5dce,0x5de4,
+0x5dfa,0x5e10,0x5e26,0x5e3b,0x5e51,0x5e67,0x5e7c,0x5e92,
+0x5ea8,0x5ebd,0x5ed3,0x5ee9,0x5efe,0x5f14,0x5f29,0x5f3f,
+0x5f54,0x5f6a,0x5f7f,0x5f95,0x5faa,0x5fbf,0x5fd5,0x5fea,
+0x6000,0x6015,0x602a,0x603f,0x6055,0x606a,0x607f,0x6094,
+0x60aa,0x60bf,0x60d4,0x60e9,0x60fe,0x6113,0x6128,0x613d,
+0x6152,0x6168,0x617d,0x6192,0x61a7,0x61bb,0x61d0,0x61e5,
+0x61fa,0x620f,0x6224,0x6239,0x624e,0x6263,0x6277,0x628c,
+0x62a1,0x62b6,0x62ca,0x62df,0x62f4,0x6309,0x631d,0x6332,
+0x6347,0x635b,0x6370,0x6384,0x6399,0x63ad,0x63c2,0x63d7,
+0x63eb,0x6400,0x6414,0x6428,0x643d,0x6451,0x6466,0x647a,
+0x648e,0x64a3,0x64b7,0x64cb,0x64e0,0x64f4,0x6508,0x651d,
+0x6531,0x6545,0x6559,0x656e,0x6582,0x6596,0x65aa,0x65be,
+0x65d2,0x65e6,0x65fa,0x660f,0x6623,0x6637,0x664b,0x665f,
+0x6673,0x6687,0x669b,0x66af,0x66c3,0x66d6,0x66ea,0x66fe,
+0x6712,0x6726,0x673a,0x674e,0x6761,0x6775,0x6789,0x679d,
+0x67b1,0x67c4,0x67d8,0x67ec,0x6800,0x6813,0x6827,0x683b,
+0x684e,0x6862,0x6875,0x6889,0x689d,0x68b0,0x68c4,0x68d7,
+0x68eb,0x68fe,0x6912,0x6925,0x6939,0x694c,0x6960,0x6973,
+0x6986,0x699a,0x69ad,0x69c1,0x69d4,0x69e7,0x69fb,0x6a0e,
+0x6a21,0x6a35,0x6a48,0x6a5b,0x6a6e,0x6a82,0x6a95,0x6aa8,
+0x6abb,0x6ace,0x6ae2,0x6af5,0x6b08,0x6b1b,0x6b2e,0x6b41,
+0x6b54,0x6b67,0x6b7a,0x6b8d,0x6ba1,0x6bb4,0x6bc7,0x6bda,
+0x6bed,0x6c00,0x6c12,0x6c25,0x6c38,0x6c4b,0x6c5e,0x6c71,
+0x6c84,0x6c97,0x6caa,0x6cbc,0x6ccf,0x6ce2,0x6cf5,0x6d08,
+0x6d1a,0x6d2d,0x6d40,0x6d53,0x6d65,0x6d78,0x6d8b,0x6d9e,
+0x6db0,0x6dc3,0x6dd6,0x6de8,0x6dfb,0x6e0d,0x6e20,0x6e33,
+0x6e45,0x6e58,0x6e6a,0x6e7d,0x6e8f,0x6ea2,0x6eb4,0x6ec7,
+0x6ed9,0x6eec,0x6efe,0x6f11,0x6f23,0x6f36,0x6f48,0x6f5a,
+0x6f6d,0x6f7f,0x6f92,0x6fa4,0x6fb6,0x6fc9,0x6fdb,0x6fed,
+0x7000,0x7012,0x7024,0x7036,0x7049,0x705b,0x706d,0x707f,
+0x7091,0x70a4,0x70b6,0x70c8,0x70da,0x70ec,0x70fe,0x7110,
+0x7123,0x7135,0x7147,0x7159,0x716b,0x717d,0x718f,0x71a1,
+0x71b3,0x71c5,0x71d7,0x71e9,0x71fb,0x720d,0x721f,0x7231,
+0x7243,0x7255,0x7267,0x7279,0x728a,0x729c,0x72ae,0x72c0,
+0x72d2,0x72e4,0x72f5,0x7307,0x7319,0x732b,0x733d,0x734e,
+0x7360,0x7372,0x7384,0x7395,0x73a7,0x73b9,0x73ca,0x73dc,
+0x73ee,0x7400,0x7411,0x7423,0x7434,0x7446,0x7458,0x7469,
+0x747b,0x748c,0x749e,0x74b0,0x74c1,0x74d3,0x74e4,0x74f6,
+0x7507,0x7519,0x752a,0x753c,0x754d,0x755f,0x7570,0x7581,
+0x7593,0x75a4,0x75b6,0x75c7,0x75d8,0x75ea,0x75fb,0x760d,
+0x761e,0x762f,0x7641,0x7652,0x7663,0x7674,0x7686,0x7697,
+0x76a8,0x76ba,0x76cb,0x76dc,0x76ed,0x76fe,0x7710,0x7721,
+0x7732,0x7743,0x7754,0x7766,0x7777,0x7788,0x7799,0x77aa,
+0x77bb,0x77cc,0x77dd,0x77ee,0x7800,0x7811,0x7822,0x7833,
+0x7844,0x7855,0x7866,0x7877,0x7888,0x7899,0x78aa,0x78bb,
+0x78cc,0x78dd,0x78ee,0x78fe,0x790f,0x7920,0x7931,0x7942,
+0x7953,0x7964,0x7975,0x7986,0x7996,0x79a7,0x79b8,0x79c9,
+0x79da,0x79eb,0x79fb,0x7a0c,0x7a1d,0x7a2e,0x7a3e,0x7a4f,
+0x7a60,0x7a71,0x7a81,0x7a92,0x7aa3,0x7ab3,0x7ac4,0x7ad5,
+0x7ae5,0x7af6,0x7b07,0x7b17,0x7b28,0x7b39,0x7b49,0x7b5a,
+0x7b6b,0x7b7b,0x7b8c,0x7b9c,0x7bad,0x7bbd,0x7bce,0x7bde,
+0x7bef,0x7c00,0x7c10,0x7c21,0x7c31,0x7c41,0x7c52,0x7c62,
+0x7c73,0x7c83,0x7c94,0x7ca4,0x7cb5,0x7cc5,0x7cd5,0x7ce6,
+0x7cf6,0x7d07,0x7d17,0x7d27,0x7d38,0x7d48,0x7d58,0x7d69,
+0x7d79,0x7d89,0x7d9a,0x7daa,0x7dba,0x7dcb,0x7ddb,0x7deb,
+0x7dfb,0x7e0c,0x7e1c,0x7e2c,0x7e3c,0x7e4d,0x7e5d,0x7e6d,
+0x7e7d,0x7e8d,0x7e9e,0x7eae,0x7ebe,0x7ece,0x7ede,0x7eee,
+0x7efe,0x7f0f,0x7f1f,0x7f2f,0x7f3f,0x7f4f,0x7f5f,0x7f6f,
+0x7f7f,0x7f8f,0x7f9f,0x7faf,0x7fbf,0x7fcf,0x7fdf,0x7fef,
+0x8000,0x800f,0x801f,0x802f,0x803f,0x804f,0x805f,0x806f,
+0x807f,0x808f,0x809f,0x80af,0x80bf,0x80cf,0x80df,0x80ef,
+0x80ff,0x810e,0x811e,0x812e,0x813e,0x814e,0x815e,0x816d,
+0x817d,0x818d,0x819d,0x81ad,0x81bc,0x81cc,0x81dc,0x81ec,
+0x81fc,0x820b,0x821b,0x822b,0x823b,0x824a,0x825a,0x826a,
+0x8279,0x8289,0x8299,0x82a8,0x82b8,0x82c8,0x82d7,0x82e7,
+0x82f7,0x8306,0x8316,0x8326,0x8335,0x8345,0x8354,0x8364,
+0x8374,0x8383,0x8393,0x83a2,0x83b2,0x83c1,0x83d1,0x83e0,
+0x83f0,0x8400,0x840f,0x841f,0x842e,0x843e,0x844d,0x845c,
+0x846c,0x847b,0x848b,0x849a,0x84aa,0x84b9,0x84c9,0x84d8,
+0x84e7,0x84f7,0x8506,0x8516,0x8525,0x8534,0x8544,0x8553,
+0x8562,0x8572,0x8581,0x8591,0x85a0,0x85af,0x85be,0x85ce,
+0x85dd,0x85ec,0x85fc,0x860b,0x861a,0x862a,0x8639,0x8648,
+0x8657,0x8667,0x8676,0x8685,0x8694,0x86a3,0x86b3,0x86c2,
+0x86d1,0x86e0,0x86ef,0x86ff,0x870e,0x871d,0x872c,0x873b,
+0x874a,0x8759,0x8769,0x8778,0x8787,0x8796,0x87a5,0x87b4,
+0x87c3,0x87d2,0x87e1,0x87f0,0x8800,0x880f,0x881e,0x882d,
+0x883c,0x884b,0x885a,0x8869,0x8878,0x8887,0x8896,0x88a5,
+0x88b4,0x88c3,0x88d2,0x88e1,0x88f0,0x88ff,0x890e,0x891c,
+0x892b,0x893a,0x8949,0x8958,0x8967,0x8976,0x8985,0x8994,
+0x89a3,0x89b2,0x89c0,0x89cf,0x89de,0x89ed,0x89fc,0x8a0b,
+0x8a19,0x8a28,0x8a37,0x8a46,0x8a55,0x8a64,0x8a72,0x8a81,
+0x8a90,0x8a9f,0x8aad,0x8abc,0x8acb,0x8ada,0x8ae8,0x8af7,
+0x8b06,0x8b15,0x8b23,0x8b32,0x8b41,0x8b50,0x8b5e,0x8b6d,
+0x8b7c,0x8b8a,0x8b99,0x8ba8,0x8bb6,0x8bc5,0x8bd4,0x8be2,
+0x8bf1,0x8c00,0x8c0e,0x8c1d,0x8c2b,0x8c3a,0x8c49,0x8c57,
+0x8c66,0x8c74,0x8c83,0x8c91,0x8ca0,0x8caf,0x8cbd,0x8ccc,
+0x8cda,0x8ce9,0x8cf7,0x8d06,0x8d14,0x8d23,0x8d31,0x8d40,
+0x8d4e,0x8d5d,0x8d6b,0x8d7a,0x8d88,0x8d97,0x8da5,0x8db4,
+0x8dc2,0x8dd1,0x8ddf,0x8ded,0x8dfc,0x8e0a,0x8e19,0x8e27,
+0x8e36,0x8e44,0x8e52,0x8e61,0x8e6f,0x8e7d,0x8e8c,0x8e9a,
+0x8ea9,0x8eb7,0x8ec5,0x8ed4,0x8ee2,0x8ef0,0x8eff,0x8f0d,
+0x8f1b,0x8f2a,0x8f38,0x8f46,0x8f54,0x8f63,0x8f71,0x8f7f,
+0x8f8e,0x8f9c,0x8faa,0x8fb8,0x8fc7,0x8fd5,0x8fe3,0x8ff1,
+0x9000,0x900e,0x901c,0x902a,0x9038,0x9047,0x9055,0x9063,
+0x9071,0x907f,0x908d,0x909c,0x90aa,0x90b8,0x90c6,0x90d4,
+0x90e2,0x90f0,0x90ff,0x910d,0x911b,0x9129,0x9137,0x9145,
+0x9153,0x9161,0x916f,0x917e,0x918c,0x919a,0x91a8,0x91b6,
+0x91c4,0x91d2,0x91e0,0x91ee,0x91fc,0x920a,0x9218,0x9226,
+0x9234,0x9242,0x9250,0x925e,0x926c,0x927a,0x9288,0x9296,
+0x92a4,0x92b2,0x92c0,0x92ce,0x92dc,0x92ea,0x92f8,0x9306,
+0x9314,0x9321,0x932f,0x933d,0x934b,0x9359,0x9367,0x9375,
+0x9383,0x9391,0x939f,0x93ac,0x93ba,0x93c8,0x93d6,0x93e4,
+0x93f2,0x9400,0x940d,0x941b,0x9429,0x9437,0x9445,0x9452,
+0x9460,0x946e,0x947c,0x948a,0x9497,0x94a5,0x94b3,0x94c1,
+0x94cf,0x94dc,0x94ea,0x94f8,0x9506,0x9513,0x9521,0x952f,
+0x953c,0x954a,0x9558,0x9566,0x9573,0x9581,0x958f,0x959c,
+0x95aa,0x95b8,0x95c5,0x95d3,0x95e1,0x95ee,0x95fc,0x960a,
+0x9617,0x9625,0x9633,0x9640,0x964e,0x965c,0x9669,0x9677,
+0x9684,0x9692,0x96a0,0x96ad,0x96bb,0x96c8,0x96d6,0x96e4,
+0x96f1,0x96ff,0x970c,0x971a,0x9727,0x9735,0x9742,0x9750,
+0x975d,0x976b,0x9779,0x9786,0x9794,0x97a1,0x97af,0x97bc,
+0x97ca,0x97d7,0x97e5,0x97f2,0x9800,0x980d,0x981a,0x9828,
+0x9835,0x9843,0x9850,0x985e,0x986b,0x9879,0x9886,0x9893,
+0x98a1,0x98ae,0x98bc,0x98c9,0x98d6,0x98e4,0x98f1,0x98ff,
+0x990c,0x9919,0x9927,0x9934,0x9942,0x994f,0x995c,0x996a,
+0x9977,0x9984,0x9992,0x999f,0x99ac,0x99ba,0x99c7,0x99d4,
+0x99e2,0x99ef,0x99fc,0x9a09,0x9a17,0x9a24,0x9a31,0x9a3f,
+0x9a4c,0x9a59,0x9a66,0x9a74,0x9a81,0x9a8e,0x9a9b,0x9aa9,
+0x9ab6,0x9ac3,0x9ad0,0x9ade,0x9aeb,0x9af8,0x9b05,0x9b12,
+0x9b20,0x9b2d,0x9b3a,0x9b47,0x9b54,0x9b62,0x9b6f,0x9b7c,
+0x9b89,0x9b96,0x9ba3,0x9bb1,0x9bbe,0x9bcb,0x9bd8,0x9be5,
+0x9bf2,0x9c00,0x9c0d,0x9c1a,0x9c27,0x9c34,0x9c41,0x9c4e,
+0x9c5b,0x9c68,0x9c75,0x9c83,0x9c90,0x9c9d,0x9caa,0x9cb7,
+0x9cc4,0x9cd1,0x9cde,0x9ceb,0x9cf8,0x9d05,0x9d12,0x9d1f,
+0x9d2c,0x9d39,0x9d46,0x9d53,0x9d60,0x9d6d,0x9d7a,0x9d87,
+0x9d94,0x9da1,0x9dae,0x9dbb,0x9dc8,0x9dd5,0x9de2,0x9def,
+0x9dfc,0x9e09,0x9e16,0x9e23,0x9e30,0x9e3d,0x9e4a,0x9e57,
+0x9e64,0x9e71,0x9e7e,0x9e8b,0x9e98,0x9ea4,0x9eb1,0x9ebe,
+0x9ecb,0x9ed8,0x9ee5,0x9ef2,0x9eff,0x9f0c,0x9f18,0x9f25,
+0x9f32,0x9f3f,0x9f4c,0x9f59,0x9f66,0x9f72,0x9f7f,0x9f8c,
+0x9f99,0x9fa6,0x9fb3,0x9fbf,0x9fcc,0x9fd9,0x9fe6,0x9ff3,
+0xa000,0xa00c,0xa019,0xa026,0xa033,0xa03f,0xa04c,0xa059,
+0xa066,0xa073,0xa07f,0xa08c,0xa099,0xa0a6,0xa0b2,0xa0bf,
+0xa0cc,0xa0d9,0xa0e5,0xa0f2,0xa0ff,0xa10b,0xa118,0xa125,
+0xa132,0xa13e,0xa14b,0xa158,0xa164,0xa171,0xa17e,0xa18a,
+0xa197,0xa1a4,0xa1b0,0xa1bd,0xa1ca,0xa1d6,0xa1e3,0xa1f0,
+0xa1fc,0xa209,0xa216,0xa222,0xa22f,0xa23c,0xa248,0xa255,
+0xa261,0xa26e,0xa27b,0xa287,0xa294,0xa2a0,0xa2ad,0xa2ba,
+0xa2c6,0xa2d3,0xa2df,0xa2ec,0xa2f8,0xa305,0xa312,0xa31e,
+0xa32b,0xa337,0xa344,0xa350,0xa35d,0xa369,0xa376,0xa382,
+0xa38f,0xa39b,0xa3a8,0xa3b5,0xa3c1,0xa3ce,0xa3da,0xa3e7,
+0xa3f3,0xa400,0xa40c,0xa418,0xa425,0xa431,0xa43e,0xa44a,
+0xa457,0xa463,0xa470,0xa47c,0xa489,0xa495,0xa4a2,0xa4ae,
+0xa4ba,0xa4c7,0xa4d3,0xa4e0,0xa4ec,0xa4f9,0xa505,0xa511,
+0xa51e,0xa52a,0xa537,0xa543,0xa54f,0xa55c,0xa568,0xa574,
+0xa581,0xa58d,0xa59a,0xa5a6,0xa5b2,0xa5bf,0xa5cb,0xa5d7,
+0xa5e4,0xa5f0,0xa5fc,0xa609,0xa615,0xa621,0xa62e,0xa63a,
+0xa646,0xa653,0xa65f,0xa66b,0xa678,0xa684,0xa690,0xa69d,
+0xa6a9,0xa6b5,0xa6c1,0xa6ce,0xa6da,0xa6e6,0xa6f2,0xa6ff,
+0xa70b,0xa717,0xa724,0xa730,0xa73c,0xa748,0xa754,0xa761,
+0xa76d,0xa779,0xa785,0xa792,0xa79e,0xa7aa,0xa7b6,0xa7c3,
+0xa7cf,0xa7db,0xa7e7,0xa7f3,0xa800,0xa80c,0xa818,0xa824,
+0xa830,0xa83c,0xa849,0xa855,0xa861,0xa86d,0xa879,0xa885,
+0xa892,0xa89e,0xa8aa,0xa8b6,0xa8c2,0xa8ce,0xa8da,0xa8e6,
+0xa8f3,0xa8ff,0xa90b,0xa917,0xa923,0xa92f,0xa93b,0xa947,
+0xa953,0xa960,0xa96c,0xa978,0xa984,0xa990,0xa99c,0xa9a8,
+0xa9b4,0xa9c0,0xa9cc,0xa9d8,0xa9e4,0xa9f0,0xa9fc,0xaa09,
+0xaa15,0xaa21,0xaa2d,0xaa39,0xaa45,0xaa51,0xaa5d,0xaa69,
+0xaa75,0xaa81,0xaa8d,0xaa99,0xaaa5,0xaab1,0xaabd,0xaac9,
+0xaad5,0xaae1,0xaaed,0xaaf9,0xab05,0xab11,0xab1d,0xab29,
+0xab35,0xab41,0xab4d,0xab58,0xab64,0xab70,0xab7c,0xab88,
+0xab94,0xaba0,0xabac,0xabb8,0xabc4,0xabd0,0xabdc,0xabe8,
+0xabf4,0xac00,0xac0b,0xac17,0xac23,0xac2f,0xac3b,0xac47,
+0xac53,0xac5f,0xac6b,0xac76,0xac82,0xac8e,0xac9a,0xaca6,
+0xacb2,0xacbe,0xacc9,0xacd5,0xace1,0xaced,0xacf9,0xad05,
+0xad11,0xad1c,0xad28,0xad34,0xad40,0xad4c,0xad57,0xad63,
+0xad6f,0xad7b,0xad87,0xad92,0xad9e,0xadaa,0xadb6,0xadc2,
+0xadcd,0xadd9,0xade5,0xadf1,0xadfd,0xae08,0xae14,0xae20,
+0xae2c,0xae37,0xae43,0xae4f,0xae5b,0xae66,0xae72,0xae7e,
+0xae8a,0xae95,0xaea1,0xaead,0xaeb8,0xaec4,0xaed0,0xaedc,
+0xaee7,0xaef3,0xaeff,0xaf0a,0xaf16,0xaf22,0xaf2e,0xaf39,
+0xaf45,0xaf51,0xaf5c,0xaf68,0xaf74,0xaf7f,0xaf8b,0xaf97,
+0xafa2,0xafae,0xafba,0xafc5,0xafd1,0xafdd,0xafe8,0xaff4,
+0xb000,0xb00b,0xb017,0xb022,0xb02e,0xb03a,0xb045,0xb051,
+0xb05c,0xb068,0xb074,0xb07f,0xb08b,0xb097,0xb0a2,0xb0ae,
+0xb0b9,0xb0c5,0xb0d0,0xb0dc,0xb0e8,0xb0f3,0xb0ff,0xb10a,
+0xb116,0xb121,0xb12d,0xb139,0xb144,0xb150,0xb15b,0xb167,
+0xb172,0xb17e,0xb189,0xb195,0xb1a0,0xb1ac,0xb1b8,0xb1c3,
+0xb1cf,0xb1da,0xb1e6,0xb1f1,0xb1fd,0xb208,0xb214,0xb21f,
+0xb22b,0xb236,0xb242,0xb24d,0xb259,0xb264,0xb270,0xb27b,
+0xb286,0xb292,0xb29d,0xb2a9,0xb2b4,0xb2c0,0xb2cb,0xb2d7,
+0xb2e2,0xb2ee,0xb2f9,0xb305,0xb310,0xb31b,0xb327,0xb332,
+0xb33e,0xb349,0xb355,0xb360,0xb36b,0xb377,0xb382,0xb38e,
+0xb399,0xb3a4,0xb3b0,0xb3bb,0xb3c7,0xb3d2,0xb3dd,0xb3e9,
+0xb3f4,0xb400,0xb40b,0xb416,0xb422,0xb42d,0xb438,0xb444,
+0xb44f,0xb45a,0xb466,0xb471,0xb47c,0xb488,0xb493,0xb49f,
+0xb4aa,0xb4b5,0xb4c1,0xb4cc,0xb4d7,0xb4e2,0xb4ee,0xb4f9,
+0xb504,0xb510,0xb51b,0xb526,0xb532,0xb53d,0xb548,0xb554,
+0xb55f,0xb56a,0xb575,0xb581,0xb58c,0xb597,0xb5a3,0xb5ae,
+0xb5b9,0xb5c4,0xb5d0,0xb5db,0xb5e6,0xb5f1,0xb5fd,0xb608,
+0xb613,0xb61e,0xb62a,0xb635,0xb640,0xb64b,0xb657,0xb662,
+0xb66d,0xb678,0xb684,0xb68f,0xb69a,0xb6a5,0xb6b0,0xb6bc,
+0xb6c7,0xb6d2,0xb6dd,0xb6e8,0xb6f4,0xb6ff,0xb70a,0xb715,
+0xb720,0xb72c,0xb737,0xb742,0xb74d,0xb758,0xb763,0xb76f,
+0xb77a,0xb785,0xb790,0xb79b,0xb7a6,0xb7b2,0xb7bd,0xb7c8,
+0xb7d3,0xb7de,0xb7e9,0xb7f4,0xb800,0xb80b,0xb816,0xb821,
+0xb82c,0xb837,0xb842,0xb84d,0xb858,0xb864,0xb86f,0xb87a,
+0xb885,0xb890,0xb89b,0xb8a6,0xb8b1,0xb8bc,0xb8c7,0xb8d3,
+0xb8de,0xb8e9,0xb8f4,0xb8ff,0xb90a,0xb915,0xb920,0xb92b,
+0xb936,0xb941,0xb94c,0xb957,0xb962,0xb96d,0xb978,0xb983,
+0xb98f,0xb99a,0xb9a5,0xb9b0,0xb9bb,0xb9c6,0xb9d1,0xb9dc,
+0xb9e7,0xb9f2,0xb9fd,0xba08,0xba13,0xba1e,0xba29,0xba34,
+0xba3f,0xba4a,0xba55,0xba60,0xba6b,0xba76,0xba81,0xba8c,
+0xba97,0xbaa2,0xbaad,0xbab8,0xbac3,0xbace,0xbad8,0xbae3,
+0xbaee,0xbaf9,0xbb04,0xbb0f,0xbb1a,0xbb25,0xbb30,0xbb3b,
+0xbb46,0xbb51,0xbb5c,0xbb67,0xbb72,0xbb7d,0xbb88,0xbb92,
+0xbb9d,0xbba8,0xbbb3,0xbbbe,0xbbc9,0xbbd4,0xbbdf,0xbbea,
+0xbbf5,0xbc00,0xbc0a,0xbc15,0xbc20,0xbc2b,0xbc36,0xbc41,
+0xbc4c,0xbc57,0xbc61,0xbc6c,0xbc77,0xbc82,0xbc8d,0xbc98,
+0xbca3,0xbcad,0xbcb8,0xbcc3,0xbcce,0xbcd9,0xbce4,0xbcef,
+0xbcf9,0xbd04,0xbd0f,0xbd1a,0xbd25,0xbd30,0xbd3a,0xbd45,
+0xbd50,0xbd5b,0xbd66,0xbd70,0xbd7b,0xbd86,0xbd91,0xbd9c,
+0xbda6,0xbdb1,0xbdbc,0xbdc7,0xbdd2,0xbddc,0xbde7,0xbdf2,
+0xbdfd,0xbe08,0xbe12,0xbe1d,0xbe28,0xbe33,0xbe3d,0xbe48,
+0xbe53,0xbe5e,0xbe68,0xbe73,0xbe7e,0xbe89,0xbe93,0xbe9e,
+0xbea9,0xbeb4,0xbebe,0xbec9,0xbed4,0xbedf,0xbee9,0xbef4,
+0xbeff,0xbf0a,0xbf14,0xbf1f,0xbf2a,0xbf34,0xbf3f,0xbf4a,
+0xbf55,0xbf5f,0xbf6a,0xbf75,0xbf7f,0xbf8a,0xbf95,0xbf9f,
+0xbfaa,0xbfb5,0xbfbf,0xbfca,0xbfd5,0xbfdf,0xbfea,0xbff5,
+0xc000,0xc00a,0xc015,0xc01f,0xc02a,0xc035,0xc03f,0xc04a,
+0xc055,0xc05f,0xc06a,0xc075,0xc07f,0xc08a,0xc095,0xc09f,
+0xc0aa,0xc0b5,0xc0bf,0xc0ca,0xc0d4,0xc0df,0xc0ea,0xc0f4,
+0xc0ff,0xc109,0xc114,0xc11f,0xc129,0xc134,0xc13e,0xc149,
+0xc154,0xc15e,0xc169,0xc173,0xc17e,0xc189,0xc193,0xc19e,
+0xc1a8,0xc1b3,0xc1bd,0xc1c8,0xc1d3,0xc1dd,0xc1e8,0xc1f2,
+0xc1fd,0xc207,0xc212,0xc21d,0xc227,0xc232,0xc23c,0xc247,
+0xc251,0xc25c,0xc266,0xc271,0xc27b,0xc286,0xc290,0xc29b,
+0xc2a5,0xc2b0,0xc2bb,0xc2c5,0xc2d0,0xc2da,0xc2e5,0xc2ef,
+0xc2fa,0xc304,0xc30f,0xc319,0xc324,0xc32e,0xc339,0xc343,
+0xc34e,0xc358,0xc363,0xc36d,0xc377,0xc382,0xc38c,0xc397,
+0xc3a1,0xc3ac,0xc3b6,0xc3c1,0xc3cb,0xc3d6,0xc3e0,0xc3eb,
+0xc3f5,0xc400,0xc40a,0xc414,0xc41f,0xc429,0xc434,0xc43e,
+0xc449,0xc453,0xc45d,0xc468,0xc472,0xc47d,0xc487,0xc492,
+0xc49c,0xc4a6,0xc4b1,0xc4bb,0xc4c6,0xc4d0,0xc4da,0xc4e5,
+0xc4ef,0xc4fa,0xc504,0xc50e,0xc519,0xc523,0xc52e,0xc538,
+0xc542,0xc54d,0xc557,0xc562,0xc56c,0xc576,0xc581,0xc58b,
+0xc595,0xc5a0,0xc5aa,0xc5b4,0xc5bf,0xc5c9,0xc5d4,0xc5de,
+0xc5e8,0xc5f3,0xc5fd,0xc607,0xc612,0xc61c,0xc626,0xc631,
+0xc63b,0xc645,0xc650,0xc65a,0xc664,0xc66f,0xc679,0xc683,
+0xc68e,0xc698,0xc6a2,0xc6ac,0xc6b7,0xc6c1,0xc6cb,0xc6d6,
+0xc6e0,0xc6ea,0xc6f5,0xc6ff,0xc709,0xc713,0xc71e,0xc728,
+0xc732,0xc73d,0xc747,0xc751,0xc75b,0xc766,0xc770,0xc77a,
+0xc784,0xc78f,0xc799,0xc7a3,0xc7ae,0xc7b8,0xc7c2,0xc7cc,
+0xc7d7,0xc7e1,0xc7eb,0xc7f5,0xc800,0xc80a,0xc814,0xc81e,
+0xc828,0xc833,0xc83d,0xc847,0xc851,0xc85c,0xc866,0xc870,
+0xc87a,0xc884,0xc88f,0xc899,0xc8a3,0xc8ad,0xc8b7,0xc8c2,
+0xc8cc,0xc8d6,0xc8e0,0xc8ea,0xc8f5,0xc8ff,0xc909,0xc913,
+0xc91d,0xc928,0xc932,0xc93c,0xc946,0xc950,0xc95a,0xc965,
+0xc96f,0xc979,0xc983,0xc98d,0xc997,0xc9a2,0xc9ac,0xc9b6,
+0xc9c0,0xc9ca,0xc9d4,0xc9df,0xc9e9,0xc9f3,0xc9fd,0xca07,
+0xca11,0xca1b,0xca26,0xca30,0xca3a,0xca44,0xca4e,0xca58,
+0xca62,0xca6c,0xca76,0xca81,0xca8b,0xca95,0xca9f,0xcaa9,
+0xcab3,0xcabd,0xcac7,0xcad1,0xcadc,0xcae6,0xcaf0,0xcafa,
+0xcb04,0xcb0e,0xcb18,0xcb22,0xcb2c,0xcb36,0xcb40,0xcb4a,
+0xcb55,0xcb5f,0xcb69,0xcb73,0xcb7d,0xcb87,0xcb91,0xcb9b,
+0xcba5,0xcbaf,0xcbb9,0xcbc3,0xcbcd,0xcbd7,0xcbe1,0xcbeb,
+0xcbf5,0xcc00,0xcc0a,0xcc14,0xcc1e,0xcc28,0xcc32,0xcc3c,
+0xcc46,0xcc50,0xcc5a,0xcc64,0xcc6e,0xcc78,0xcc82,0xcc8c,
+0xcc96,0xcca0,0xccaa,0xccb4,0xccbe,0xccc8,0xccd2,0xccdc,
+0xcce6,0xccf0,0xccfa,0xcd04,0xcd0e,0xcd18,0xcd22,0xcd2c,
+0xcd36,0xcd40,0xcd4a,0xcd54,0xcd5e,0xcd68,0xcd72,0xcd7c,
+0xcd86,0xcd90,0xcd99,0xcda3,0xcdad,0xcdb7,0xcdc1,0xcdcb,
+0xcdd5,0xcddf,0xcde9,0xcdf3,0xcdfd,0xce07,0xce11,0xce1b,
+0xce25,0xce2f,0xce39,0xce43,0xce4c,0xce56,0xce60,0xce6a,
+0xce74,0xce7e,0xce88,0xce92,0xce9c,0xcea6,0xceb0,0xceba,
+0xcec3,0xcecd,0xced7,0xcee1,0xceeb,0xcef5,0xceff,0xcf09,
+0xcf13,0xcf1d,0xcf26,0xcf30,0xcf3a,0xcf44,0xcf4e,0xcf58,
+0xcf62,0xcf6c,0xcf75,0xcf7f,0xcf89,0xcf93,0xcf9d,0xcfa7,
+0xcfb1,0xcfbb,0xcfc4,0xcfce,0xcfd8,0xcfe2,0xcfec,0xcff6,
+0xd000,0xd009,0xd013,0xd01d,0xd027,0xd031,0xd03b,0xd044,
+0xd04e,0xd058,0xd062,0xd06c,0xd076,0xd07f,0xd089,0xd093,
+0xd09d,0xd0a7,0xd0b0,0xd0ba,0xd0c4,0xd0ce,0xd0d8,0xd0e1,
+0xd0eb,0xd0f5,0xd0ff,0xd109,0xd112,0xd11c,0xd126,0xd130,
+0xd13a,0xd143,0xd14d,0xd157,0xd161,0xd16b,0xd174,0xd17e,
+0xd188,0xd192,0xd19b,0xd1a5,0xd1af,0xd1b9,0xd1c3,0xd1cc,
+0xd1d6,0xd1e0,0xd1ea,0xd1f3,0xd1fd,0xd207,0xd211,0xd21a,
+0xd224,0xd22e,0xd238,0xd241,0xd24b,0xd255,0xd25f,0xd268,
+0xd272,0xd27c,0xd285,0xd28f,0xd299,0xd2a3,0xd2ac,0xd2b6,
+0xd2c0,0xd2c9,0xd2d3,0xd2dd,0xd2e7,0xd2f0,0xd2fa,0xd304,
+0xd30d,0xd317,0xd321,0xd32b,0xd334,0xd33e,0xd348,0xd351,
+0xd35b,0xd365,0xd36e,0xd378,0xd382,0xd38b,0xd395,0xd39f,
+0xd3a8,0xd3b2,0xd3bc,0xd3c6,0xd3cf,0xd3d9,0xd3e3,0xd3ec,
+0xd3f6,0xd400,0xd409,0xd413,0xd41c,0xd426,0xd430,0xd439,
+0xd443,0xd44d,0xd456,0xd460,0xd46a,0xd473,0xd47d,0xd487,
+0xd490,0xd49a,0xd4a3,0xd4ad,0xd4b7,0xd4c0,0xd4ca,0xd4d4,
+0xd4dd,0xd4e7,0xd4f0,0xd4fa,0xd504,0xd50d,0xd517,0xd521,
+0xd52a,0xd534,0xd53d,0xd547,0xd551,0xd55a,0xd564,0xd56d,
+0xd577,0xd581,0xd58a,0xd594,0xd59d,0xd5a7,0xd5b0,0xd5ba,
+0xd5c4,0xd5cd,0xd5d7,0xd5e0,0xd5ea,0xd5f4,0xd5fd,0xd607,
+0xd610,0xd61a,0xd623,0xd62d,0xd637,0xd640,0xd64a,0xd653,
+0xd65d,0xd666,0xd670,0xd679,0xd683,0xd68c,0xd696,0xd6a0,
+0xd6a9,0xd6b3,0xd6bc,0xd6c6,0xd6cf,0xd6d9,0xd6e2,0xd6ec,
+0xd6f5,0xd6ff,0xd708,0xd712,0xd71b,0xd725,0xd72f,0xd738,
+0xd742,0xd74b,0xd755,0xd75e,0xd768,0xd771,0xd77b,0xd784,
+0xd78e,0xd797,0xd7a1,0xd7aa,0xd7b4,0xd7bd,0xd7c7,0xd7d0,
+0xd7da,0xd7e3,0xd7ed,0xd7f6,0xd800,0xd809,0xd812,0xd81c,
+0xd825,0xd82f,0xd838,0xd842,0xd84b,0xd855,0xd85e,0xd868,
+0xd871,0xd87b,0xd884,0xd88e,0xd897,0xd8a0,0xd8aa,0xd8b3,
+0xd8bd,0xd8c6,0xd8d0,0xd8d9,0xd8e3,0xd8ec,0xd8f5,0xd8ff,
+0xd908,0xd912,0xd91b,0xd925,0xd92e,0xd938,0xd941,0xd94a,
+0xd954,0xd95d,0xd967,0xd970,0xd979,0xd983,0xd98c,0xd996,
+0xd99f,0xd9a9,0xd9b2,0xd9bb,0xd9c5,0xd9ce,0xd9d8,0xd9e1,
+0xd9ea,0xd9f4,0xd9fd,0xda07,0xda10,0xda19,0xda23,0xda2c,
+0xda35,0xda3f,0xda48,0xda52,0xda5b,0xda64,0xda6e,0xda77,
+0xda81,0xda8a,0xda93,0xda9d,0xdaa6,0xdaaf,0xdab9,0xdac2,
+0xdacb,0xdad5,0xdade,0xdae8,0xdaf1,0xdafa,0xdb04,0xdb0d,
+0xdb16,0xdb20,0xdb29,0xdb32,0xdb3c,0xdb45,0xdb4e,0xdb58,
+0xdb61,0xdb6a,0xdb74,0xdb7d,0xdb86,0xdb90,0xdb99,0xdba2,
+0xdbac,0xdbb5,0xdbbe,0xdbc8,0xdbd1,0xdbda,0xdbe4,0xdbed,
+0xdbf6,0xdc00,0xdc09,0xdc12,0xdc1b,0xdc25,0xdc2e,0xdc37,
+0xdc41,0xdc4a,0xdc53,0xdc5d,0xdc66,0xdc6f,0xdc78,0xdc82,
+0xdc8b,0xdc94,0xdc9e,0xdca7,0xdcb0,0xdcb9,0xdcc3,0xdccc,
+0xdcd5,0xdcde,0xdce8,0xdcf1,0xdcfa,0xdd04,0xdd0d,0xdd16,
+0xdd1f,0xdd29,0xdd32,0xdd3b,0xdd44,0xdd4e,0xdd57,0xdd60,
+0xdd69,0xdd73,0xdd7c,0xdd85,0xdd8e,0xdd98,0xdda1,0xddaa,
+0xddb3,0xddbd,0xddc6,0xddcf,0xddd8,0xdde2,0xddeb,0xddf4,
+0xddfd,0xde06,0xde10,0xde19,0xde22,0xde2b,0xde35,0xde3e,
+0xde47,0xde50,0xde59,0xde63,0xde6c,0xde75,0xde7e,0xde87,
+0xde91,0xde9a,0xdea3,0xdeac,0xdeb5,0xdebf,0xdec8,0xded1,
+0xdeda,0xdee3,0xdeed,0xdef6,0xdeff,0xdf08,0xdf11,0xdf1a,
+0xdf24,0xdf2d,0xdf36,0xdf3f,0xdf48,0xdf52,0xdf5b,0xdf64,
+0xdf6d,0xdf76,0xdf7f,0xdf89,0xdf92,0xdf9b,0xdfa4,0xdfad,
+0xdfb6,0xdfbf,0xdfc9,0xdfd2,0xdfdb,0xdfe4,0xdfed,0xdff6,
+0xe000,0xe009,0xe012,0xe01b,0xe024,0xe02d,0xe036,0xe03f,
+0xe049,0xe052,0xe05b,0xe064,0xe06d,0xe076,0xe07f,0xe088,
+0xe092,0xe09b,0xe0a4,0xe0ad,0xe0b6,0xe0bf,0xe0c8,0xe0d1,
+0xe0db,0xe0e4,0xe0ed,0xe0f6,0xe0ff,0xe108,0xe111,0xe11a,
+0xe123,0xe12c,0xe136,0xe13f,0xe148,0xe151,0xe15a,0xe163,
+0xe16c,0xe175,0xe17e,0xe187,0xe190,0xe199,0xe1a3,0xe1ac,
+0xe1b5,0xe1be,0xe1c7,0xe1d0,0xe1d9,0xe1e2,0xe1eb,0xe1f4,
+0xe1fd,0xe206,0xe20f,0xe218,0xe221,0xe22b,0xe234,0xe23d,
+0xe246,0xe24f,0xe258,0xe261,0xe26a,0xe273,0xe27c,0xe285,
+0xe28e,0xe297,0xe2a0,0xe2a9,0xe2b2,0xe2bb,0xe2c4,0xe2cd,
+0xe2d6,0xe2df,0xe2e8,0xe2f1,0xe2fa,0xe303,0xe30c,0xe315,
+0xe31f,0xe328,0xe331,0xe33a,0xe343,0xe34c,0xe355,0xe35e,
+0xe367,0xe370,0xe379,0xe382,0xe38b,0xe394,0xe39d,0xe3a6,
+0xe3af,0xe3b8,0xe3c1,0xe3ca,0xe3d3,0xe3dc,0xe3e5,0xe3ee,
+0xe3f7,0xe400,0xe408,0xe411,0xe41a,0xe423,0xe42c,0xe435,
+0xe43e,0xe447,0xe450,0xe459,0xe462,0xe46b,0xe474,0xe47d,
+0xe486,0xe48f,0xe498,0xe4a1,0xe4aa,0xe4b3,0xe4bc,0xe4c5,
+0xe4ce,0xe4d7,0xe4e0,0xe4e9,0xe4f2,0xe4fa,0xe503,0xe50c,
+0xe515,0xe51e,0xe527,0xe530,0xe539,0xe542,0xe54b,0xe554,
+0xe55d,0xe566,0xe56f,0xe578,0xe580,0xe589,0xe592,0xe59b,
+0xe5a4,0xe5ad,0xe5b6,0xe5bf,0xe5c8,0xe5d1,0xe5da,0xe5e3,
+0xe5eb,0xe5f4,0xe5fd,0xe606,0xe60f,0xe618,0xe621,0xe62a,
+0xe633,0xe63c,0xe644,0xe64d,0xe656,0xe65f,0xe668,0xe671,
+0xe67a,0xe683,0xe68c,0xe694,0xe69d,0xe6a6,0xe6af,0xe6b8,
+0xe6c1,0xe6ca,0xe6d3,0xe6db,0xe6e4,0xe6ed,0xe6f6,0xe6ff,
+0xe708,0xe711,0xe71a,0xe722,0xe72b,0xe734,0xe73d,0xe746,
+0xe74f,0xe758,0xe760,0xe769,0xe772,0xe77b,0xe784,0xe78d,
+0xe795,0xe79e,0xe7a7,0xe7b0,0xe7b9,0xe7c2,0xe7cb,0xe7d3,
+0xe7dc,0xe7e5,0xe7ee,0xe7f7,0xe800,0xe808,0xe811,0xe81a,
+0xe823,0xe82c,0xe834,0xe83d,0xe846,0xe84f,0xe858,0xe861,
+0xe869,0xe872,0xe87b,0xe884,0xe88d,0xe895,0xe89e,0xe8a7,
+0xe8b0,0xe8b9,0xe8c1,0xe8ca,0xe8d3,0xe8dc,0xe8e5,0xe8ed,
+0xe8f6,0xe8ff,0xe908,0xe911,0xe919,0xe922,0xe92b,0xe934,
+0xe93c,0xe945,0xe94e,0xe957,0xe960,0xe968,0xe971,0xe97a,
+0xe983,0xe98b,0xe994,0xe99d,0xe9a6,0xe9ae,0xe9b7,0xe9c0,
+0xe9c9,0xe9d2,0xe9da,0xe9e3,0xe9ec,0xe9f5,0xe9fd,0xea06,
+0xea0f,0xea18,0xea20,0xea29,0xea32,0xea3b,0xea43,0xea4c,
+0xea55,0xea5e,0xea66,0xea6f,0xea78,0xea80,0xea89,0xea92,
+0xea9b,0xeaa3,0xeaac,0xeab5,0xeabe,0xeac6,0xeacf,0xead8,
+0xeae0,0xeae9,0xeaf2,0xeafb,0xeb03,0xeb0c,0xeb15,0xeb1d,
+0xeb26,0xeb2f,0xeb38,0xeb40,0xeb49,0xeb52,0xeb5a,0xeb63,
+0xeb6c,0xeb74,0xeb7d,0xeb86,0xeb8f,0xeb97,0xeba0,0xeba9,
+0xebb1,0xebba,0xebc3,0xebcb,0xebd4,0xebdd,0xebe5,0xebee,
+0xebf7,0xec00,0xec08,0xec11,0xec1a,0xec22,0xec2b,0xec34,
+0xec3c,0xec45,0xec4e,0xec56,0xec5f,0xec68,0xec70,0xec79,
+0xec82,0xec8a,0xec93,0xec9c,0xeca4,0xecad,0xecb5,0xecbe,
+0xecc7,0xeccf,0xecd8,0xece1,0xece9,0xecf2,0xecfb,0xed03,
+0xed0c,0xed15,0xed1d,0xed26,0xed2e,0xed37,0xed40,0xed48,
+0xed51,0xed5a,0xed62,0xed6b,0xed74,0xed7c,0xed85,0xed8d,
+0xed96,0xed9f,0xeda7,0xedb0,0xedb8,0xedc1,0xedca,0xedd2,
+0xeddb,0xede4,0xedec,0xedf5,0xedfd,0xee06,0xee0f,0xee17,
+0xee20,0xee28,0xee31,0xee3a,0xee42,0xee4b,0xee53,0xee5c,
+0xee65,0xee6d,0xee76,0xee7e,0xee87,0xee8f,0xee98,0xeea1,
+0xeea9,0xeeb2,0xeeba,0xeec3,0xeecc,0xeed4,0xeedd,0xeee5,
+0xeeee,0xeef6,0xeeff,0xef08,0xef10,0xef19,0xef21,0xef2a,
+0xef32,0xef3b,0xef43,0xef4c,0xef55,0xef5d,0xef66,0xef6e,
+0xef77,0xef7f,0xef88,0xef90,0xef99,0xefa2,0xefaa,0xefb3,
+0xefbb,0xefc4,0xefcc,0xefd5,0xefdd,0xefe6,0xefee,0xeff7,
+0xf000,0xf008,0xf011,0xf019,0xf022,0xf02a,0xf033,0xf03b,
+0xf044,0xf04c,0xf055,0xf05d,0xf066,0xf06e,0xf077,0xf07f,
+0xf088,0xf090,0xf099,0xf0a1,0xf0aa,0xf0b2,0xf0bb,0xf0c3,
+0xf0cc,0xf0d4,0xf0dd,0xf0e5,0xf0ee,0xf0f6,0xf0ff,0xf107,
+0xf110,0xf118,0xf121,0xf129,0xf132,0xf13a,0xf143,0xf14b,
+0xf154,0xf15c,0xf165,0xf16d,0xf176,0xf17e,0xf187,0xf18f,
+0xf198,0xf1a0,0xf1a9,0xf1b1,0xf1ba,0xf1c2,0xf1cb,0xf1d3,
+0xf1dc,0xf1e4,0xf1ec,0xf1f5,0xf1fd,0xf206,0xf20e,0xf217,
+0xf21f,0xf228,0xf230,0xf239,0xf241,0xf24a,0xf252,0xf25a,
+0xf263,0xf26b,0xf274,0xf27c,0xf285,0xf28d,0xf296,0xf29e,
+0xf2a6,0xf2af,0xf2b7,0xf2c0,0xf2c8,0xf2d1,0xf2d9,0xf2e1,
+0xf2ea,0xf2f2,0xf2fb,0xf303,0xf30c,0xf314,0xf31c,0xf325,
+0xf32d,0xf336,0xf33e,0xf347,0xf34f,0xf357,0xf360,0xf368,
+0xf371,0xf379,0xf381,0xf38a,0xf392,0xf39b,0xf3a3,0xf3ac,
+0xf3b4,0xf3bc,0xf3c5,0xf3cd,0xf3d6,0xf3de,0xf3e6,0xf3ef,
+0xf3f7,0xf400,0xf408,0xf410,0xf419,0xf421,0xf429,0xf432,
+0xf43a,0xf443,0xf44b,0xf453,0xf45c,0xf464,0xf46d,0xf475,
+0xf47d,0xf486,0xf48e,0xf496,0xf49f,0xf4a7,0xf4b0,0xf4b8,
+0xf4c0,0xf4c9,0xf4d1,0xf4d9,0xf4e2,0xf4ea,0xf4f2,0xf4fb,
+0xf503,0xf50c,0xf514,0xf51c,0xf525,0xf52d,0xf535,0xf53e,
+0xf546,0xf54e,0xf557,0xf55f,0xf567,0xf570,0xf578,0xf580,
+0xf589,0xf591,0xf599,0xf5a2,0xf5aa,0xf5b2,0xf5bb,0xf5c3,
+0xf5cb,0xf5d4,0xf5dc,0xf5e4,0xf5ed,0xf5f5,0xf5fd,0xf606,
+0xf60e,0xf616,0xf61f,0xf627,0xf62f,0xf638,0xf640,0xf648,
+0xf651,0xf659,0xf661,0xf66a,0xf672,0xf67a,0xf682,0xf68b,
+0xf693,0xf69b,0xf6a4,0xf6ac,0xf6b4,0xf6bd,0xf6c5,0xf6cd,
+0xf6d6,0xf6de,0xf6e6,0xf6ee,0xf6f7,0xf6ff,0xf707,0xf710,
+0xf718,0xf720,0xf728,0xf731,0xf739,0xf741,0xf74a,0xf752,
+0xf75a,0xf762,0xf76b,0xf773,0xf77b,0xf784,0xf78c,0xf794,
+0xf79c,0xf7a5,0xf7ad,0xf7b5,0xf7bd,0xf7c6,0xf7ce,0xf7d6,
+0xf7de,0xf7e7,0xf7ef,0xf7f7,0xf800,0xf808,0xf810,0xf818,
+0xf821,0xf829,0xf831,0xf839,0xf842,0xf84a,0xf852,0xf85a,
+0xf863,0xf86b,0xf873,0xf87b,0xf883,0xf88c,0xf894,0xf89c,
+0xf8a4,0xf8ad,0xf8b5,0xf8bd,0xf8c5,0xf8ce,0xf8d6,0xf8de,
+0xf8e6,0xf8ef,0xf8f7,0xf8ff,0xf907,0xf90f,0xf918,0xf920,
+0xf928,0xf930,0xf939,0xf941,0xf949,0xf951,0xf959,0xf962,
+0xf96a,0xf972,0xf97a,0xf982,0xf98b,0xf993,0xf99b,0xf9a3,
+0xf9ab,0xf9b4,0xf9bc,0xf9c4,0xf9cc,0xf9d4,0xf9dd,0xf9e5,
+0xf9ed,0xf9f5,0xf9fd,0xfa06,0xfa0e,0xfa16,0xfa1e,0xfa26,
+0xfa2f,0xfa37,0xfa3f,0xfa47,0xfa4f,0xfa58,0xfa60,0xfa68,
+0xfa70,0xfa78,0xfa80,0xfa89,0xfa91,0xfa99,0xfaa1,0xfaa9,
+0xfab1,0xfaba,0xfac2,0xfaca,0xfad2,0xfada,0xfae2,0xfaeb,
+0xfaf3,0xfafb,0xfb03,0xfb0b,0xfb13,0xfb1c,0xfb24,0xfb2c,
+0xfb34,0xfb3c,0xfb44,0xfb4c,0xfb55,0xfb5d,0xfb65,0xfb6d,
+0xfb75,0xfb7d,0xfb85,0xfb8e,0xfb96,0xfb9e,0xfba6,0xfbae,
+0xfbb6,0xfbbe,0xfbc7,0xfbcf,0xfbd7,0xfbdf,0xfbe7,0xfbef,
+0xfbf7,0xfc00,0xfc08,0xfc10,0xfc18,0xfc20,0xfc28,0xfc30,
+0xfc38,0xfc40,0xfc49,0xfc51,0xfc59,0xfc61,0xfc69,0xfc71,
+0xfc79,0xfc81,0xfc8a,0xfc92,0xfc9a,0xfca2,0xfcaa,0xfcb2,
+0xfcba,0xfcc2,0xfcca,0xfcd2,0xfcdb,0xfce3,0xfceb,0xfcf3,
+0xfcfb,0xfd03,0xfd0b,0xfd13,0xfd1b,0xfd23,0xfd2c,0xfd34,
+0xfd3c,0xfd44,0xfd4c,0xfd54,0xfd5c,0xfd64,0xfd6c,0xfd74,
+0xfd7c,0xfd84,0xfd8d,0xfd95,0xfd9d,0xfda5,0xfdad,0xfdb5,
+0xfdbd,0xfdc5,0xfdcd,0xfdd5,0xfddd,0xfde5,0xfded,0xfdf5,
+0xfdfd,0xfe06,0xfe0e,0xfe16,0xfe1e,0xfe26,0xfe2e,0xfe36,
+0xfe3e,0xfe46,0xfe4e,0xfe56,0xfe5e,0xfe66,0xfe6e,0xfe76,
+0xfe7e,0xfe86,0xfe8e,0xfe97,0xfe9f,0xfea7,0xfeaf,0xfeb7,
+0xfebf,0xfec7,0xfecf,0xfed7,0xfedf,0xfee7,0xfeef,0xfef7,
+0xfeff,0xff07,0xff0f,0xff17,0xff1f,0xff27,0xff2f,0xff37,
+0xff3f,0xff47,0xff4f,0xff57,0xff5f,0xff67,0xff6f,0xff77,
+0xff7f,0xff87,0xff8f,0xff97,0xff9f,0xffa7,0xffaf,0xffb7,
+0xffbf,0xffc7,0xffcf,0xffd7,0xffdf,0xffe7,0xffef,0xfff7};
+
+static const signed short wavtable1[2304]={
+0x021d,0x03bc,0x0300,0xfc0d,0xfcd5,0xfd33,0xfdc5,0xfc83,
+0xfdc0,0x036d,0x0245,0x0238,0xfc1b,0xfc31,0xfd7a,0xfd10,
+0xfd6b,0xfd88,0x02a3,0x0313,0x027b,0xfdf9,0xfcba,0xfc2f,
+0xfc86,0xfda3,0xfceb,0x0270,0x02dc,0x029c,0xfc83,0xfcd1,
+0xfc44,0xfd06,0xfdf5,0xfc97,0x026f,0x0347,0x02b9,0xfc02,
+0xfcaf,0xfdc5,0xfd09,0xfd50,0xfc4b,0x0280,0x02b5,0x03df,
+0xfc9d,0xfd95,0xfd61,0xfce0,0xfc54,0xfc41,0x039d,0x02af,
+0x0260,0xfd93,0xfddb,0xfccf,0xfcbb,0xfc64,0xfd2e,0x0228,
+0x031d,0x023c,0xfca3,0xfd97,0xfc84,0xfdac,0xfd93,0xfd80,
+0x0217,0x0340,0x031f,0xfc99,0xfcbc,0xfd77,0xfdd0,0xfd5c,
+0xfd90,0x02fa,0x025d,0x0241,0xfc7a,0xfca5,0xfd56,0xfdc8,
+0xfd34,0xfd76,0x0340,0x0231,0x03eb,0xfc6f,0xfcd1,0xfdda,
+0xfd5c,0xfd98,0xfc2a,0x024e,0x02af,0x024c,0xfce7,0xfd59,
+0xfcea,0xfd57,0xfc65,0xfd5b,0x0286,0x0385,0x02dc,0xfdc7,
+0xfc64,0xfd7b,0xfcd0,0xfce6,0xfdf4,0x033c,0x02b1,0x0380,
+0xfdd3,0xfd2b,0xfda5,0xfd62,0xfc61,0xfcf0,0x036b,0x0270,
+0x0350,0xfdeb,0xfd2b,0xfdfc,0xfd14,0xfd08,0xfd42,0x023b,
+0x03ae,0x03fe,0xfdf2,0xfdc6,0xfc53,0xfd82,0xfc9c,0xfc04,
+0x0338,0x02e0,0x0283,0xfdaf,0xfdfb,0xfc63,0xfd69,0xfdee,
+0xfcd8,0x0205,0x02fd,0x0200,0xfcfa,0xfdfa,0xfd01,0xfdf5,
+0xfdc4,0xfdff,0x0232,0x038c,0x02f9,0xfc1b,0xfcbc,0xfd5d,
+0xfd97,0xfcdb,0xfdca,0x02b6,0x0391,0x02a3,0xfd95,0xfc6c,
+0xfda5,0xfc53,0xfcd1,0xfc85,0x02c0,0x020c,0x02a0,0xfd2e,
+0xfc63,0xfd4f,0xfc37,0xfde6,0xfc8d,0x02d1,0x02f5,0x022e,
+0xfdea,0xfcee,0xfcc6,0xfc06,0xfdcf,0xfda0,0x0374,0x0227,
+0x0279,0xfc49,0xfdde,0xfd57,0xfd05,0xfdb0,0xfcf0,0x022e,
+0x03ef,0x034e,0xfddb,0xfc65,0xfcc0,0xfda0,0xfc21,0xfd45,
+0x03a4,0x02ea,0x0309,0xfd59,0xfd3d,0xfdca,0xfcaf,0xfde0,
+0xfdb3,0x0236,0x0336,0x039e,0xfc72,0xfdff,0xfd18,0xfd8d,
+0xfd6d,0xfcb9,0x0265,0x0303,0x0263,0xfc64,0xfd25,0xfc67,
+0xfd23,0xfdbb,0xfd27,0x02e1,0x029f,0x03f0,0xfc39,0xfd2a,
+0xfd6b,0xfded,0xfc90,0xfc1f,0x028b,0x0252,0x0243,0xfd0b,
+0xfd1f,0xfd5f,0xfcc2,0xfd4d,0xfd71,0x0321,0x027c,0x0234,
+0xfc1c,0xfc8d,0xfd42,0xfd8e,0xfce8,0xfd92,0x0354,0x038e,
+0x02cf,0xfd0b,0xfda9,0xfd81,0xfd3b,0xfcd7,0xfc0c,0x03e6,
+0x0266,0x023f,0xfda9,0xfdcf,0xfd4d,0xfc32,0xfd1f,0xfd79,
+0x0299,0x03a7,0x0274,0xfda1,0xfcd0,0xfdc2,0xfca1,0xfcaa,
+0xfcfd,0x0277,0x0254,0x033d,0xfd21,0xfc01,0xfc3a,0xfcf6,
+0xfd4a,0xfd60,0x0284,0x039e,0x020e,0xfdb9,0xfd69,0xfc47,
+0xfcd5,0xfcba,0xfde2,0x036f,0x03dc,0x0265,0xfcb0,0xfdf2,
+0xfdb0,0xfd0d,0xfc47,0xfd22,0x03ad,0x02b4,0x02b5,0xfd83,
+0xfd82,0xfc55,0xfc9e,0xfc57,0xfc54,0x0235,0x02a0,0x0240,
+0xfd1a,0xfd83,0xfd0b,0xfd8f,0xfc8e,0xfd77,0x0223,0x0274,
+0x02e4,0xfd61,0xfce9,0xfc73,0xfdb7,0xfcfd,0xfde9,0x027f,
+0x0214,0x0219,0xfd67,0xfd61,0xfdd1,0xfce2,0xfdd6,0xfdcc,
+0x03bb,0x025c,0x0256,0xfdcc,0xfdd2,0xfd3e,0xfc85,0xfd36,
+0xfd45,0x0232,0x0244,0x0384,0xfd83,0xfc23,0xfc03,0xfd97,
+0xfd6e,0xfce9,0x025b,0x0383,0x026d,0xfdee,0xfd23,0xfddf,
+0xfd38,0xfceb,0xfd0d,0x02ea,0x0215,0x0270,0xfcf8,0xfc73,
+0xfd76,0xfde1,0xfdd5,0xfd07,0x02d9,0x0202,0x02df,0xfd23,
+0xfdf5,0xfd1d,0xfdf9,0xfdfb,0xfdf0,0x0355,0x0227,0x02b4,
+0xfc69,0xfdbf,0xfd17,0xfd39,0xfdaf,0xfc58,0x03b5,0x03fa,
+0x03ec,0xfc50,0xfc5d,0xfc19,0xfc90,0xfc0b,0xfc27,0x0220,
+0x03dc,0x02df,0xfdf3,0xfcf3,0xfd3a,0xfdbe,0xfc46,0xfdf0,
+0x0315,0x030e,0x0335,0xfda5,0xfd87,0xfd8c,0xfda0,0xfdaa,
+0xfd6d,0x0381,0x0204,0x02f2,0xfc76,0xfd6b,0xfd07,0xfcee,
+0xfdf7,0xfdd4,0x0205,0x02be,0x033c,0xfd3a,0xfcbb,0xfdc8,
+0xfdf5,0xfc3d,0xfd62,0x024a,0x0332,0x02fb,0xfc57,0xfc96,
+0xfd9f,0xfd60,0xfd72,0xfdc8,0x038b,0x028c,0x0250,0xfdbe,
+0xfdf3,0xfd0e,0xfcdc,0xfcc2,0xfd52,0x0210,0x028c,0x0282,
+0xfd5f,0xfd69,0xfcce,0xfdde,0xfcc2,0xfcda,0x0213,0x02c4,
+0x030c,0xfd20,0xfcd5,0xfde4,0xfdd8,0xfc2b,0xfdad,0x029a,
+0x0271,0x02d7,0xfcd3,0xfc4e,0xfc88,0xfc9d,0xfd05,0xfdfc,
+0x03b3,0x02d7,0x022a,0xfd5f,0xfe00,0xfced,0xfc95,0xfdfb,
+0xfda9,0x0225,0x0291,0x03d5,0xfd3f,0xfdf2,0xfd8a,0xfdb3,
+0xfcb5,0xfc53,0x025d,0x0398,0x0354,0xfde0,0xfc10,0xfd02,
+0xfd34,0xfcc5,0xfd3b,0x0270,0x026b,0x03d7,0xfd0d,0xfda9,
+0xfdad,0xfd07,0xfd12,0xfc50,0x025d,0x038d,0x0223,0xfde7,
+0xfd7a,0xfc35,0xfd35,0xfcd9,0xfdb8,0x02b2,0x03a7,0x0204,
+0xfd89,0xfd47,0xfc50,0xfc5c,0xfca9,0xfdf7,0x02bc,0x0264,
+0x0355,0xfcba,0xfdb8,0xfc03,0xfc41,0xfd24,0xfd39,0x02ff,
+0x0340,0x023e,0xfd91,0xfca3,0xfc5b,0xfdc1,0xfd5c,0xfd7d,
+0x020b,0x0382,0x039b,0xfc69,0xfc4f,0xfcd6,0xfde8,0xfceb,
+0xfcbf,0x02d2,0x03be,0x02b3,0xfd5c,0xfc30,0xfd79,0xfc04,
+0xfc80,0xfc59,0x0265,0x0303,0x03a0,0xfc64,0xfdd4,0xfd44,
+0xfd22,0xfdbb,0xfcb6,0x02f6,0x02f5,0x0248,0xfdcf,0xfc9e,
+0xfc9f,0xfdce,0xfdd0,0xfd65,0x0200,0x0237,0x0241,0xfdc9,
+0xfdbf,0xfd81,0xfe00,0xfd8c,0xfd76,0x0267,0x027e,0x02ba,
+0xfd02,0xfcb9,0xfc99,0xfd1d,0xfce5,0xfc46,0x023e,0x0282,
+0x024d,0xfd30,0xfd6c,0xfd1d,0xfd7c,0xfcda,0xfd5b,0x03e1,
+0x02aa,0x036e,0xfd6a,0xfcac,0xfdb7,0xfc3d,0xfc72,0xfd0f,
+0x021b,0x037a,0x0391,0xfc55,0xfc3d,0xfce5,0xfdc7,0xfcf9,
+0xfcd1,0x02b6,0x03a0,0x0220,0xfd8b,0xfd1e,0xfc25,0xfc53,
+0xfcb6,0xfdbe,0x0325,0x0258,0x02a8,0xfc50,0xfde9,0xfce2,
+0xfd87,0xfd40,0xfc77,0x021c,0x03b7,0x030e,0xfc14,0xfcc7,
+0xfd29,0xfdc6,0xfc8c,0xfdab,0x0330,0x03b6,0x024e,0xfd0b,
+0xfc53,0xfddc,0xfd76,0xfc8f,0xfd57,0x03bb,0x034f,0x032b,
+0xfcea,0xfd0b,0xfd61,0xfc85,0xfd44,0xfd7d,0x0223,0x0373,
+0x022c,0xfc4f,0xfdad,0xfc40,0xfdb6,0xfd06,0xfda3,0x028c,
+0x0378,0x025c,0xfdcb,0xfcfe,0xfdf4,0xfcc1,0xfcfe,0xfd37,
+0x035f,0x0249,0x0357,0xfc26,0xfd2f,0xfc2e,0xfd29,0xfd64,
+0xfd35,0x03ff,0x03e5,0x0204,0xfc1b,0xfdfc,0xfc12,0xfc01,
+0xfc34,0xfdf8,0x03a4,0x0266,0x0280,0xfdd0,0xfdb9,0xfcff,
+0xfcae,0xfd1e,0xfce0,0x0273,0x0234,0x023d,0xfd4d,0xfd42,
+0xfd89,0xfcff,0xfd93,0xfd7f,0x036c,0x0384,0x02d4,0xfcfe,
+0xfd94,0xfd83,0xfd12,0xfce8,0xfe00,0x0203,0x0359,0x0380,
+0xfca1,0xfc7a,0xfd12,0xfdf9,0xfd32,0xfcf0,0x0287,0x03b9,
+0x036f,0xfda6,0xfdd5,0xfcce,0xfccf,0xfc88,0xfd0d,0x0326,
+0x0356,0x0359,0xfd60,0xfd5d,0xfd35,0xfd86,0xfd38,0xfd32,
+0x0221,0x0247,0x0277,0xfd93,0xfd60,0xfd31,0xfdbb,0xfd68,
+0xfcf6,0x0291,0x0259,0x02ef,0xfcfc,0xfc3d,0xfc8e,0xfcb5,
+0xfd3d,0xfdda,0x02e4,0x0389,0x031b,0xfd72,0xfdc1,0xfd40,
+0xfde9,0xfcdf,0xfd96,0x0349,0x03f8,0x0238,0xfcbd,0xfc5a,
+0xfdcc,0xfd4d,0xfc0f,0xfd89,0x02eb,0x024d,0x03d7,0xfca3,
+0xfd32,0xfdca,0xfddf,0xfd59,0xfc4f,0x036e,0x0265,0x020e,
+0xfdf2,0xfc7a,0xfd8a,0xfd0f,0xfd20,0xfde4,0x0360,0x02d3,
+0x030b,0xfd9e,0xfd6f,0xfdda,0xfd27,0xfc02,0xfdb0,0x0216,
+0x02a2,0x0306,0xfd41,0xfcd8,0xfc05,0xfdd3,0xfc89,0xfdb6,
+0x03b6,0x0289,0x03ab,0xfda6,0xfc99,0xfdad,0xfc8f,0xfcc8,
+0xfca3,0x024e,0x02bf,0x0383,0xfcd5,0xfdfa,0xfd96,0xfd58,
+0xfc3a,0xfcea,0x026a,0x020f,0x0243,0xfd83,0xfd44,0xfdab,
+0xfd16,0xfde1,0xfd6f,0x02d5,0x0287,0x03cc,0xfc6b,0xfd4f,
+0xfd99,0xfdff,0xfcce,0xfc64,0x0281,0x0287,0x02c3,0xfcd6,
+0xfc8b,0xfc83,0xfcdd,0xfccf,0xfc30,0x02da,0x0297,0x0284,
+0xfc4e,0xfc68,0xfcbd,0xfdf7,0xfca4,0xfcd4,0x0327,0x023c,
+0x0242,0xfc7a,0xfc70,0xfd7a,0xfd83,0xfd81,0xfd73,0x036f,
+0x0263,0x0335,0xfdf4,0xfd3f,0xfc2d,0xfd0d,0xfd27,0xfd6e,
+0x029b,0x02d9,0x0349,0xfc49,0xfddb,0xfda9,0xfc99,0xfdf9,
+0xfd4c,0x030e,0x0249,0x02ef,0xfc81,0xfdc2,0xfca5,0xfdaa,
+0xfd62,0xfdd9,0x0322,0x02dd,0x03d0,0xfdc2,0xfd03,0xfd45,
+0xfd8c,0xfdf3,0xfc5d,0x0352,0x0367,0x02c4,0xfd2c,0xfdb4,
+0xfda6,0xfd3e,0xfd1a,0xfc2d,0x0366,0x02e7,0x02c0,0xfd88,
+0xfdaa,0xfc01,0xfd1d,0xfde4,0xfc36,0x03ad,0x0383,0x0249,
+0xfcc5,0xfde6,0xfdfe,0xfc9e,0xfcea,0xfd63,0x03af,0x0278,
+0x036b,0xfdba,0xfcda,0xfde3,0xfc9b,0xfcf3,0xfd13,0x03ff,
+0x02dc,0x027e,0xfd25,0xfd83,0xfc70,0xfc02,0xfdf5,0xfce5,
+0x030a,0x02f1,0x028f,0xfdc3,0xfc1b,0xfc3b,0xfdb0,0xfdd6,
+0xfcb9,0x034b,0x03b1,0x03b1,0xfcf5,0xfcf5,0xfc97,0xfd4a,
+0xfc97,0xfc97,0x03ae,0x03c9,0x023c,0xfc84,0xfdf1,0xfde2,
+0xfc9d,0xfc6a,0xfd80,0x03f0,0x022f,0x0356,0xfdd9,0xfcb7,
+0xfc5a,0xfc1f,0xfd9c,0xfd38,0x0364,0x02d9,0x0313,0xfd96,
+0xfd64,0xfdd0,0xfd1f,0xfdf9,0xfda3,0x03ca,0x02ae,0x0223,
+0xfd76,0xfdfa,0xfd23,0xfc69,0xfc69,0xfdb7,0x0217,0x027b,
+0x02a2,0xfd68,0xfd3f,0xfcbc,0xfdd0,0xfcec,0xfc89,0x0230,
+0x027c,0x033c,0xfd48,0xfc75,0xfdfe,0xfd9b,0xfcea,0xfd62,
+0x03e2,0x0250,0x0341,0xfdc1,0xfcd7,0xfc3c,0xfc3a,0xfd52,
+0xfd5b,0x0224,0x026d,0x02b6,0xfd67,0xfd19,0xfcb5,0xfdb5,
+0xfd0d,0xfc52,0x0226,0x0321,0x03bb,0xfca3,0xfdff,0xfd14,
+0xfdb1,0xfd8d,0xfc84,0x0246,0x020a,0x0286,0xfdae,0xfd21,
+0xfd6d,0xfd69,0xfdeb,0xfcd1,0x025e,0x0271,0x0332,0xfd1d,
+0xfc37,0xfc19,0xfd33,0xfd05,0xfd71,0x026f,0x024f,0x036a,
+0xfd30,0xfded,0xfc0e,0xfd0a,0xfd55,0xfd16,0x029d,0x0217,
+0x03e9,0xfd44,0xfd72,0xfdf5,0xfc94,0xfdd1,0xfc2d,0x02bd,
+0x03aa,0x0250,0xfd7e,0xfcd6,0xfde2,0xfc40,0xfca4,0xfd54,
+0x039d,0x0334,0x02e2,0xfd1b,0xfd65,0xfdb0,0xfcbd,0xfd6f,
+0xfdeb,0x02df,0x0316,0x0220,0xfdc9,0xfcf3,0xfcb8,0xfdf1,
+0xfd9e,0xfdbe,0x023f,0x0314,0x02a2,0xfc8a,0xfd0a,0xfdf9,
+0xfd79,0xfda1,0xfc88,0x028f,0x030f,0x0210,0xfc15,0xfd5b,
+0xfcd7,0xfcb8,0xfda9,0xfddf,0x020f,0x0201,0x02a5,0xfdef,
+0xfd45,0xfd59,0xfde0,0xfdfe,0xfc7f,0x030e,0x0354,0x03ac,
+0xfd75,0xfd32,0xfcf1,0xfdab,0xfd3b,0xfca1,0x0242,0x038e,
+0x0201,0xfdfe,0xfdbb,0xfc6e,0xfd72,0xfcd7,0xfdfd,0x02b4,
+0x0372,0x02de,0xfdac,0xfc1f,0xfd88,0xfc57,0xfd09,0xfdf2,
+0x024a,0x02ab,0x02cb,0xfcf2,0xfcce,0xfc46,0xfd62,0xfc71,
+0xfc19,0x02e3,0x0261,0x02cd,0xfc90,0xfdfa,0xfcaa,0xfdea,
+0xfd2b,0xfc12,0x030a,0x0305,0x02b9,0xfdb4,0xfdee,0xfdf1,
+0xfdb0,0xfdb8,0xfc49,0x039a,0x0311,0x032d,0xfd3d,0xfd24,
+0xfd90,0xfcc2,0xfda6,0xfd7a,0x02fe,0x028b,0x03d8,0xfc32,
+0xfd20,0xfd8e,0xfdc3,0xfcc5,0xfc4e,0x03d2,0x0254,0x0203,
+0xfdc7,0xfc28,0xfda8,0xfc5a,0xfd4a,0xfdfa,0x0217,0x02f5,
+0x021c,0xfce8,0xfdcb,0xfce1,0xfdd0,0xfdd1,0xfdc5,0x0296,
+0x02af,0x024d,0xfc86,0xfd06,0xfce9,0xfca7,0xfc64,0xfd5a,
+0x022a,0x0218,0x03d3,0xfdbc,0xfdee,0xfe00,0xfda7,0xfdcf,
+0xfc58,0x02d3,0x03d6,0x02b2,0xfd4a,0xfc30,0xfd6a,0xfc02,
+0xfc51,0xfc5c,0x03a8,0x03bc,0x020f,0xfc95,0xfc3b,0xfc26,
+0xfca8,0xfc82,0xfde1,0x024e,0x03ea,0x0223,0xfdbf,0xfd89,
+0xfde8,0xfd58,0xfc2c,0xfdb6,0x0205,0x028d,0x0339,0xfd6c,
+0xfcbf,0xfdf2,0xfdf6,0xfcbe,0xfd68,0x0340,0x0250,0x03ce,
+0xfc3c,0xfce8,0xfdcc,0xfd5b,0xfd52,0xfc60,0x0200,0x03bd,
+0x0387,0xfc43,0xfc79,0xfcb4,0xfe00,0xfc82,0xfce4,0x0277,
+0x0221,0x038a,0xfd60,0xfdd2,0xfc3b,0xfcf7,0xfdbb,0xfcde,
+0x0202,0x02d0,0x0289,0xfd2d,0xfd74,0xfc6f,0xfdfc,0xfc0c,
+0xfcc8,0x0254,0x02a7,0x02b6,0xfcea,0xfcd9,0xfc68,0xfd4b,
+0xfc7c,0xfc54,0x0269,0x02e4,0x03d3,0xfc84,0xfdb2,0xfd3c,
+0xfd19,0xfde9,0xfc58,0x02c7,0x02ad,0x036d,0xfc48,0xfd9f,
+0xfdb5,0xfc25,0xfc6b,0xfd10,0x028f,0x0343,0x0350,0xfdea,
+0xfde2,0xfd4d,0xfcba,0xfd57,0xfd42,0x02f2,0x0347,0x02ba,
+0xfd96,0xfdfd,0xfdc3,0xfdd4,0xfd50,0xfc46,0x0367,0x0203,
+0x0301,0xfc93,0xfd71,0xfcfa,0xfd1a,0xfdfa,0xfdbe,0x03bb,
+0x0354,0x023d,0xfce5,0xfde9,0xfc45,0xfc84,0xfd3b,0xfd7d,
+0x0280,0x035b,0x024b,0xfde7,0xfd21,0xfc26,0xfcdf,0xfd2f,
+0xfd5e,0x0318,0x035f,0x022a,0xfd65,0xfca6,0xfc59,0xfd9c,
+0xfd29,0xfda7,0x034b,0x02c4,0x02aa,0xfdb9,0xfdce,0xfc50,
+0xfd4a,0xfc2d,0xfc72,0x03cb,0x0300,0x0228,0xfd28,0xfdf4,
+0xfcc3,0xfc67,0xfdc0,0xfdac,0x037b,0x0218,0x02b2,0xfc59,
+0xfda7,0xfd2c,0xfcf8,0xfdcd,0xfc5d,0x03f8,0x0230,0x0297,
+0xfdd4,0xfd6d,0xfd29,0xfc0f,0xfd9a,0xfca4,0x021f,0x0366,
+0x02a2,0xfc64,0xfd34,0xfdc3,0xfdbf,0xfd1d,0xfc87,0x0259,
+0x03e7,0x0249,0xfdb6,0xfd52,0xfdc5,0xfd3f,0xfc31,0xfd64,
+0x03b1,0x03c6,0x0379,0xfc84,0xfccb,0xfcb8,0xfc98,0xfc70,
+0xfcfb,0x0211,0x0390,0x0309,0xfc51,0xfcdc,0xfd4c,0xfddd,
+0xfcd4,0xfdb2,0x023e,0x03fc,0x02ca,0xfdc4,0xfcdf,0xfd39,
+0xfd7d,0xfc08,0xfc1b,0x0261,0x039a,0x03a4,0xfddb,0xfdd5,
+0xfcb8,0xfd2b,0xfcc1,0xfcb0,0x0256,0x030a,0x03a1,0xfc73,
+0xfde1,0xfd3d,0xfd46,0xfdb0,0xfcb4,0x028b,0x0304,0x02e8,
+0xfc2a,0xfc4d,0xfdcf,0xfcc5,0xfdba,0xfde3,0x02b3,0x03bd,
+0x02d2,0xfd7a,0xfc30,0xfd5d,0xfc5a,0xfc82,0xfc04,0x02d9,
+0x02fe,0x03d8,0xfdde,0xfd43,0xfd20,0xfdf8,0xfdc3,0xfc4f,
+0x0223,0x0207,0x0278,0xfdd5,0xfd5d,0xfd80,0xfdb7,0xfdf2,
+0xfcf4,0x0247,0x0214,0x039a,0xfda1,0xfdf3,0xfc40,0xfd68,
+0xfdd6,0xfcc1,0x0279,0x03e3,0x025b,0xfd99,0xfd17,0xfdb6,
+0xfcf1,0xfc38,0xfd3a,0x02a5,0x023b,0x036a,0xfd0b,0xfdbe,
+0xfc2f,0xfc80,0xfd82,0xfd15,0x025a,0x0221,0x029a,0xfd7f,
+0xfcf1,0xfd3b,0xfd3c,0xfdbc,0xfc9e,0x0273,0x021e,0x036b,
+0xfd67,0xfde8,0xfc60,0xfcff,0xfdc1,0xfd14,0x02a0,0x03d7,
+0x0256,0xfd7b,0xfcee,0xfdc1,0xfc8e,0xfc50,0xfd44,0x02b4,
+0x03d3,0x02da,0xfd6a,0xfc24,0xfd46,0xfc57,0xfc57,0xfdf7,
+0x029c,0x027a,0x0368,0xfcc5,0xfdc7,0xfde4,0xfc99,0xfcef,
+0xfd1a,0x02c7,0x02c2,0x02a2,0xfc2a,0xfc57,0xfc5d,0xfc24,
+0xfc31,0xfc87,0x02e3,0x03d1,0x0253,0xfd3e,0xfca4,0xfdc8,
+0xfdea,0xfc5c,0xfd4d,0x02f7,0x0389,0x02fb,0xfd61,0xfdca,
+0xfd5d,0xfdcd,0xfce1,0xfdc7,0x02f4,0x0246,0x02fb,0xfca4,
+0xfdcd,0xfc9c,0xfdd2,0xfd69,0xfdc8,0x02ec,0x03f5,0x038c,
+0xfd1b,0xfd68,0xfc7e,0xfddd,0xfc16,0xfcdb,0x0324,0x03a9,
+0x03b6,0xfd20,0xfd16,0xfc9b,0xfd89,0xfca6,0xfc8e,0x0311,
+0x021f,0x03e6,0xfcbf,0xfd02,0xfdef,0xfda6,0xfdc0,0xfc33,
+0x03e7,0x02ac,0x03ae,0xfd64,0xfc68,0xfd8a,0xfc31,0xfc6d,
+0xfc9c,0x0272,0x0279,0x03e4,0xfcfa,0xfd9f,0xfd98,0xfd03,
+0xfcf1,0xfc36,0x0272,0x0237,0x0343,0xfd4b,0xfc03,0xfc63,
+0xfd03,0xfd8c,0xfd57,0x02e3,0x023b,0x03cd,0xfcc7,0xfd42,
+0xfde1,0xfdeb,0xfd83,0xfc63,0x028f,0x0301,0x02c3,0xfc28,
+0xfc76,0xfded,0xfcb9,0xfdbf,0xfc2e,0x02be,0x03b8,0x023b,
+0xfd73,0xfcef,0xfdec,0xfc3c,0xfc8a,0xfd82,0x02d7,0x02c8,
+0x0202,0xfc0c,0xfd26,0xfd35,0xfdfc,0xfc22,0xfdfc,0x02e8,
+0x02ae,0x02e5,0xfc1a,0xfde5,0xfc1e,0xfde3,0xfc67,0xfde8,
+0x02db,0x0228,0x02ca,0xfceb,0xfc03,0xfcfc,0xfdf6,0xfdac,
+0xfc1a,0x0338,0x03df,0x02d6,0xfce2,0xfdb7,0xfd41,0xfd68,
+0xfc41,0xfdfd,0x031b,0x0267,0x0220,0xfc45,0xfcb4,0xfd73,
+0xfd97,0xfd1e,0xfdbe,0x0366,0x023f,0x0338,0xfc2e,0xfd44,
+0xfc62,0xfd1d,0xfd7a,0xfd68,0x0323,0x0340,0x039b,0xfd73,
+0xfd2c,0xfd12,0xfd8a,0xfd5b,0xfcc0,0x0333,0x0347,0x0213,
+0xfd61,0xfcaf,0xfc99,0xfd71,0xfd50,0xfdda,0x0377,0x0312,
+0x0354,0xfd57,0xfd1e,0xfd72,0xfcff,0xfda5,0xfd3b,0x03a5,
+0x02fc,0x023a,0xfd48,0xfdf9,0xfcad,0xfcae,0xfdc6,0xfd86,
+0x02cc,0x038a,0x028e,0xfd86,0xfc6c,0xfdbd,0xfc15,0xfcde,
+0xfcbb,0x0310,0x0324,0x0233,0xfd98,0xfca0,0xfc8b,0xfda7,
+0xfd89,0xfd94,0x0306,0x0217,0x036c,0xfcd7,0xfd6a,0xfc6d,
+0xfdb7,0xfdd1,0xfd13,0x0327,0x0256,0x0289,0xfc51,0xfc01,
+0xfd0a,0xfd84,0xfd45,0xfcca,0x0331,0x02f7,0x02ce,0xfda2,
+0xfdc3,0xfdeb,0xfd74,0xfdcd,0xfc10,0x033f,0x03e1,0x034e,
+0xfcda,0xfd51,0xfccb,0xfd5d,0xfc3d,0xfd45,0x035a,0x0237,
+0x025d,0xfc49,0xfc09,0xfd62,0xfd30,0xfd8c,0xfd34,0x036c,
+0x03f4,0x028b,0xfc9e,0xfdd3,0xfd7d,0xfd12,0xfc17,0xfcc5,
+0x0354,0x0224,0x0225,0xfc6f,0xfc6e,0xfdb4,0xfd3a,0xfdb5,
+0xfdb3,0x037f,0x03f0,0x0367,0xfc8f,0xfd07,0xfca6,0xfcf2,
+0xfc1f,0xfd1b,0x037c,0x03e8,0x024f,0xfc98,0xfdfd,0xfdbe,
+0xfcf7,0xfc2f,0xfd55,0x03a7,0x0204,0x0344,0xfc50,0xfd04,
+0xfcb4,0xfca9,0xfdf7,0xfd56,0x03a3,0x0264,0x0308,0xfdd3,
+0xfd3e,0xfc5f,0xfcb1,0xfd23,0xfdb3,0x03c8,0x0266,0x0330,
+0xfdbb,0xfcfd,0xfc2c,0xfc6d,0xfd1e,0xfd75,0x020c,0x0309,
+0x02cf,0xfce4,0xfd1f,0xfdde,0xfde7,0xfdb2,0xfc0c,0x0225,
+0x02b6,0x0312,0xfd18,0xfcb5,0xfdeb,0xfdb3,0xfc53,0xfda5,
+0x0372,0x02f2,0x0216,0xfd77,0xfc68,0xfced,0xfd09,0xfdd5,
+0xfdd3,0x0255,0x0345,0x02fe,0xfc2f,0xfc81,0xfd8d,0xfd47,
+0xfd54,0xfdc2,0x027b,0x03ba,0x02c0,0xfdb0,0xfc97,0xfd70,
+0xfcec,0xfc86,0xfc37,0x0323,0x0226,0x031e,0xfca1,0xfd8e,
+0xfca6,0xfd8a,0xfdb1,0xfd92,0x02bb,0x028e,0x031e,0xfc82,
+0xfddf,0xfc03,0xfc46,0xfcbb,0xfd92,0x039c,0x02ff,0x02e2,
+0xfd4b,0xfd66,0xfdd7,0xfcbe,0xfdc1,0xfded,0x03ca,0x02a3,
+0x0260,0xfd81,0xfdc0,0xfcdf,0xfc69,0xfc86,0xfd2e,0x0278,
+0x02c2,0x02ac,0xfc97,0xfcb4,0xfc50,0xfcf4,0xfc30,0xfc6e,
+0x035a,0x02ff,0x0233,0xfd7d,0xfc4f,0xfcb4,0xfd31,0xfdc2,
+0xfd94,0x020f,0x02fd,0x02be,0xfcec,0xfd2c,0xfdf3,0xfde1,
+0xfdc4,0xfc3c,0x022f,0x039c,0x03eb,0xfc0f,0xfddd,0xfc77,
+0xfd9e,0xfcbf,0xfc29,0x026a,0x020c,0x0263,0xfd87,0xfd1e,
+0xfd8f,0xfd15,0xfde8,0xfd27,0x03e7,0x03ae,0x03c3,0xfc68,
+0xfc54,0xfc8a,0xfc30,0xfc9d,0xfc77,0x0223,0x0359,0x03a7,
+0xfc6c,0xfc19,0xfcf1,0xfdb8,0xfd32,0xfcaa,0x02de,0x039e,
+0x0239,0xfd67,0xfcce,0xfdfd,0xfdf1,0xfcba,0xfd86,0x03c7,
+0x02ea,0x0227,0xfd3f,0xfdf8,0xfcdc,0xfc6f,0xfde0,0xfdaf,
+0x0342,0x0279,0x0371,0xfdfd,0xfd32,0xfddf,0xfd59,0xfcf1,
+0xfd0a,0x03ad,0x02bd,0x02d7,0xfd7b,0xfd64,0xfc1b,0xfc9f,
+0xfc3f,0xfdfc,0x03b1,0x0234,0x027c,0xfdf7,0xfdb5,0xfd43,
+0xfc97,0xfd91,0xfcea,0x0200,0x0233,0x0319,0xfdcd,0xfce6,
+0xfc97,0xfe00,0xfd95,0xfd99,0x03d8,0x022c,0x023a,0xfdea,
+0xfddc,0xfd94,0xfc4f,0xfda4,0xfd84,0x03d8,0x021c,0x02e4,
+0xfdf9,0xfd38,0xfcf2,0xfc4e,0xfdc6,0xfde8,0x020f,0x02fc,
+0x036a,0xfced,0xfc7b,0xfd74,0xfde1,0xfdc6,0xfd15,0x0212,
+0x0298,0x03f6,0xfd50,0xfdf3,0xfd6e,0xfddb,0xfca2,0xfc13,
+0x0222,0x0203,0x0209,0xfdda,0xfdd4,0xfdf3,0xfdb8,0xfdf9,
+0xfded,0x022a,0x03a6,0x02a0,0xfc0d,0xfd28,0xfd9b,0xfda8,
+0xfcac,0xfc8e,0x0256,0x03b1,0x022c,0xfdd8,0xfd76,0xfdff,
+0xfd44,0xfc98,0xfda5,0x0273,0x0213,0x02dd,0xfd75,0xfc7d,
+0xfd08,0xfcff,0xfdd9,0xfdf3,0x0240,0x03fc,0x03f6,0xfdc2,
+0xfdc5,0xfc0d,0xfd76,0xfc08,0xfc13,0x026f,0x039c,0x0252,
+0xfdcd,0xfd2c,0xfde7,0xfd09,0xfcbd,0xfd4d,0x02a6,0x038d,
+0x025b,0xfda6,0xfce0,0xfde8,0xfc7d,0xfcd9,0xfd38,0x032e,
+0x02e8,0x021f,0xfdb0,0xfc9f,0xfcea,0xfd78,0xfde3,0xfdbf};
+
+static const unsigned short wavtable2[2304]={
+0x0e,0x0e,0x0e,0x14,0x14,0x13,0x15,0x14,0x14,0x0e,0x0e,0x0e,
+0x14,0x14,0x14,0x14,0x15,0x15,0x0e,0x0d,0x0e,0x12,0x14,0x13,
+0x15,0x12,0x15,0x0d,0x0d,0x0e,0x12,0x13,0x13,0x13,0x12,0x15,
+0x0d,0x0e,0x0d,0x13,0x12,0x12,0x13,0x14,0x13,0x0d,0x0e,0x0f,
+0x13,0x13,0x14,0x13,0x15,0x16,0x0d,0x0d,0x0d,0x11,0x11,0x12,
+0x12,0x13,0x13,0x0c,0x0e,0x0d,0x12,0x11,0x13,0x11,0x14,0x13,
+0x0d,0x0d,0x0d,0x12,0x12,0x11,0x13,0x12,0x12,0x0d,0x0d,0x0c,
+0x12,0x11,0x11,0x12,0x13,0x11,0x0d,0x0c,0x0d,0x11,0x11,0x10,
+0x12,0x11,0x12,0x0c,0x0d,0x0c,0x11,0x10,0x11,0x11,0x13,0x11,
+0x0c,0x0d,0x0d,0x10,0x11,0x11,0x11,0x12,0x12,0x0c,0x0d,0x0d,
+0x10,0x10,0x11,0x10,0x13,0x12,0x0c,0x0c,0x0d,0x0f,0x10,0x10,
+0x10,0x11,0x12,0x0b,0x0d,0x0d,0x0f,0x0f,0x11,0x0f,0x12,0x12,
+0x0d,0x0c,0x0d,0x10,0x11,0x11,0x12,0x10,0x13,0x0c,0x0c,0x0c,
+0x10,0x10,0x10,0x11,0x10,0x11,0x0d,0x0c,0x0c,0x11,0x11,0x0f,
+0x13,0x10,0x10,0x0d,0x0c,0x0b,0x10,0x10,0x0e,0x13,0x10,0x0f,
+0x0c,0x0c,0x0c,0x10,0x10,0x10,0x11,0x11,0x11,0x0c,0x0d,0x0b,
+0x10,0x0f,0x10,0x11,0x12,0x0f,0x0c,0x0c,0x0b,0x10,0x0e,0x0f,
+0x10,0x11,0x0f,0x0b,0x0d,0x0c,0x0f,0x0f,0x10,0x0f,0x12,0x10,
+0x0c,0x0c,0x0c,0x0f,0x0f,0x0f,0x10,0x10,0x10,0x0b,0x0c,0x0c,
+0x0f,0x0e,0x0f,0x0f,0x10,0x10,0x0b,0x0c,0x0c,0x0f,0x0f,0x10,
+0x0f,0x10,0x11,0x0b,0x0c,0x0d,0x0f,0x0f,0x10,0x0e,0x11,0x12,
+0x0b,0x0c,0x0b,0x0f,0x0e,0x0f,0x0f,0x11,0x0f,0x0b,0x0c,0x0b,
+0x0f,0x0e,0x0f,0x0e,0x11,0x0f,0x0b,0x0d,0x0c,0x0f,0x0e,0x10,
+0x0e,0x12,0x11,0x0b,0x0c,0x0c,0x0e,0x0e,0x10,0x0e,0x11,0x11,
+0x0c,0x0c,0x0c,0x0f,0x10,0x0f,0x11,0x10,0x11,0x0c,0x0b,0x0c,
+0x0f,0x10,0x0f,0x11,0x0f,0x10,0x0c,0x0c,0x0b,0x0f,0x0f,0x0f,
+0x11,0x10,0x0f,0x0c,0x0c,0x0b,0x0f,0x0e,0x0e,0x10,0x10,0x0f,
+0x0d,0x0b,0x0b,0x0f,0x0f,0x0e,0x12,0x0f,0x0f,0x0c,0x0b,0x0a,
+0x0f,0x0e,0x0d,0x11,0x0f,0x0d,0x0b,0x0b,0x0b,0x0e,0x0e,0x0e,
+0x0f,0x0f,0x0e,0x0b,0x0b,0x0a,0x0e,0x0d,0x0d,0x0f,0x0f,0x0d,
+0x0c,0x0b,0x0c,0x0e,0x0f,0x0f,0x10,0x0f,0x11,0x0b,0x0b,0x0c,
+0x0e,0x0f,0x0f,0x0f,0x0f,0x10,0x0b,0x0c,0x0b,0x0e,0x0e,0x0e,
+0x0f,0x10,0x0f,0x0b,0x0b,0x0b,0x0e,0x0e,0x0e,0x0e,0x0f,0x0f,
+0x0b,0x0b,0x0c,0x0e,0x0e,0x0f,0x0e,0x0f,0x10,0x0b,0x0b,0x0c,
+0x0e,0x0e,0x0f,0x0e,0x0f,0x11,0x0b,0x0c,0x0c,0x0e,0x0e,0x0f,
+0x0e,0x10,0x10,0x0a,0x0c,0x0c,0x0d,0x0e,0x0f,0x0d,0x10,0x10,
+0x0b,0x0c,0x0b,0x0e,0x0d,0x0e,0x0e,0x10,0x0e,0x0b,0x0b,0x0b,
+0x0e,0x0d,0x0e,0x0e,0x0f,0x0e,0x0a,0x0c,0x0b,0x0e,0x0d,0x0e,
+0x0d,0x11,0x0e,0x0a,0x0c,0x0b,0x0e,0x0d,0x0e,0x0d,0x10,0x0e,
+0x0b,0x0b,0x0b,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x0a,0x0b,0x0b,
+0x0d,0x0d,0x0e,0x0d,0x0f,0x0f,0x0a,0x0b,0x0c,0x0d,0x0e,0x0e,
+0x0d,0x0f,0x10,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x0d,0x0f,0x10,
+0x0b,0x0c,0x0b,0x0e,0x0d,0x0f,0x0e,0x10,0x0f,0x0a,0x0c,0x0c,
+0x0e,0x0d,0x0f,0x0d,0x11,0x10,0x0a,0x0d,0x0c,0x0e,0x0e,0x10,
+0x0d,0x12,0x10,0x0a,0x0c,0x0d,0x0e,0x0e,0x10,0x0d,0x11,0x12,
+0x0a,0x0c,0x0b,0x0d,0x0d,0x0f,0x0d,0x10,0x0f,0x0a,0x0c,0x0b,
+0x0d,0x0d,0x0f,0x0d,0x10,0x0f,0x0a,0x0c,0x0c,0x0e,0x0d,0x10,
+0x0d,0x11,0x10,0x0a,0x0c,0x0c,0x0d,0x0e,0x10,0x0c,0x10,0x11,
+0x0c,0x0b,0x0c,0x0f,0x10,0x0e,0x11,0x0e,0x10,0x0c,0x0b,0x0b,
+0x0e,0x0f,0x0d,0x11,0x0e,0x0f,0x0b,0x0b,0x0c,0x0e,0x0e,0x0e,
+0x0f,0x0e,0x10,0x0b,0x0b,0x0b,0x0d,0x0e,0x0e,0x0e,0x0e,0x0f,
+0x0b,0x0a,0x0b,0x0d,0x0e,0x0d,0x0f,0x0d,0x0f,0x0b,0x0a,0x0b,
+0x0d,0x0e,0x0d,0x0f,0x0d,0x0f,0x0c,0x0a,0x0a,0x0e,0x0e,0x0c,
+0x11,0x0d,0x0d,0x0c,0x0a,0x0a,0x0d,0x0d,0x0b,0x10,0x0d,0x0c,
+0x0b,0x0b,0x0b,0x0e,0x0e,0x0d,0x0f,0x0e,0x0e,0x0b,0x0b,0x0a,
+0x0d,0x0d,0x0d,0x0f,0x0e,0x0d,0x0b,0x0b,0x0a,0x0e,0x0c,0x0d,
+0x0e,0x0f,0x0d,0x0a,0x0c,0x0a,0x0e,0x0c,0x0d,0x0d,0x10,0x0c,
+0x0b,0x0b,0x0b,0x0d,0x0e,0x0d,0x0e,0x0e,0x0f,0x0b,0x0b,0x0b,
+0x0d,0x0d,0x0d,0x0e,0x0e,0x0e,0x0a,0x0b,0x0b,0x0d,0x0d,0x0e,
+0x0d,0x0e,0x0f,0x0a,0x0b,0x0b,0x0c,0x0d,0x0d,0x0d,0x0e,0x0f,
+0x0b,0x0a,0x0b,0x0d,0x0d,0x0d,0x0e,0x0d,0x0e,0x0b,0x0b,0x0a,
+0x0d,0x0c,0x0d,0x0e,0x0e,0x0d,0x0b,0x0a,0x0a,0x0c,0x0c,0x0c,
+0x0e,0x0d,0x0d,0x0a,0x0a,0x0a,0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,
+0x0b,0x0b,0x0a,0x0d,0x0c,0x0c,0x0e,0x0e,0x0c,0x0a,0x0b,0x0a,
+0x0d,0x0c,0x0c,0x0d,0x0e,0x0c,0x0a,0x0b,0x0a,0x0c,0x0b,0x0c,
+0x0d,0x0e,0x0c,0x0a,0x0b,0x0a,0x0c,0x0b,0x0c,0x0c,0x0e,0x0c,
+0x0a,0x0a,0x0b,0x0c,0x0d,0x0d,0x0d,0x0d,0x0f,0x0a,0x0a,0x0b,
+0x0c,0x0d,0x0d,0x0d,0x0d,0x0e,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,
+0x0c,0x0e,0x0e,0x0a,0x0b,0x0b,0x0c,0x0d,0x0d,0x0c,0x0e,0x0f,
+0x0a,0x0a,0x0b,0x0c,0x0c,0x0c,0x0c,0x0d,0x0e,0x0a,0x0a,0x0a,
+0x0b,0x0c,0x0c,0x0c,0x0d,0x0d,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,
+0x0c,0x0d,0x0e,0x09,0x0a,0x0b,0x0b,0x0c,0x0d,0x0b,0x0d,0x0e,
+0x0b,0x0b,0x0b,0x0d,0x0d,0x0d,0x0e,0x0f,0x0e,0x0a,0x0b,0x0b,
+0x0d,0x0c,0x0d,0x0d,0x0f,0x0e,0x0a,0x0b,0x0a,0x0d,0x0c,0x0d,
+0x0d,0x0f,0x0d,0x0a,0x0b,0x0b,0x0d,0x0c,0x0d,0x0c,0x0f,0x0e,
+0x0a,0x0b,0x0b,0x0d,0x0d,0x0e,0x0d,0x0f,0x0f,0x0a,0x0b,0x0b,
+0x0d,0x0d,0x0e,0x0c,0x0f,0x0f,0x0a,0x0b,0x0b,0x0d,0x0d,0x0e,
+0x0c,0x0f,0x0f,0x0a,0x0b,0x0c,0x0c,0x0d,0x0f,0x0c,0x0f,0x10,
+0x0a,0x0c,0x0b,0x0e,0x0c,0x0e,0x0d,0x10,0x0e,0x0a,0x0c,0x0b,
+0x0e,0x0c,0x0f,0x0c,0x11,0x0e,0x0a,0x0c,0x0c,0x0d,0x0d,0x0f,
+0x0c,0x10,0x10,0x0a,0x0d,0x0c,0x0e,0x0d,0x10,0x0c,0x12,0x11,
+0x0a,0x0c,0x0b,0x0d,0x0c,0x0f,0x0c,0x10,0x0f,0x0a,0x0c,0x0b,
+0x0d,0x0c,0x0e,0x0c,0x10,0x0f,0x0a,0x0c,0x0c,0x0d,0x0d,0x0f,
+0x0c,0x11,0x10,0x0a,0x0c,0x0c,0x0d,0x0d,0x10,0x0c,0x10,0x11,
+0x0a,0x0c,0x0a,0x0d,0x0c,0x0e,0x0c,0x10,0x0d,0x0a,0x0c,0x0b,
+0x0d,0x0c,0x0e,0x0c,0x10,0x0e,0x0a,0x0c,0x0a,0x0d,0x0b,0x0d,
+0x0c,0x10,0x0d,0x0a,0x0b,0x0b,0x0c,0x0c,0x0e,0x0c,0x0f,0x0e,
+0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0c,0x0e,0x0e,0x0a,0x0b,0x0b,
+0x0c,0x0c,0x0e,0x0c,0x0f,0x0f,0x09,0x0b,0x0b,0x0c,0x0c,0x0e,
+0x0b,0x0f,0x0f,0x09,0x0b,0x0c,0x0c,0x0d,0x0e,0x0b,0x0f,0x10,
+0x0a,0x0c,0x0b,0x0d,0x0c,0x0f,0x0c,0x11,0x0e,0x09,0x0c,0x0b,
+0x0d,0x0c,0x0f,0x0b,0x11,0x0f,0x09,0x0c,0x0c,0x0d,0x0c,0x0f,
+0x0b,0x10,0x10,0x09,0x0c,0x0c,0x0d,0x0d,0x10,0x0b,0x11,0x11,
+0x09,0x0c,0x0b,0x0d,0x0c,0x0f,0x0b,0x11,0x0e,0x09,0x0c,0x0c,
+0x0d,0x0c,0x10,0x0b,0x11,0x10,0x09,0x0c,0x0c,0x0d,0x0c,0x0f,
+0x0b,0x11,0x10,0x09,0x0d,0x0c,0x0d,0x0d,0x10,0x0b,0x12,0x11,
+0x0c,0x0a,0x0b,0x0d,0x0e,0x0c,0x10,0x0c,0x0e,0x0b,0x0a,0x0a,
+0x0c,0x0d,0x0c,0x0e,0x0c,0x0d,0x0a,0x0a,0x0b,0x0c,0x0d,0x0c,
+0x0d,0x0c,0x0f,0x0a,0x0a,0x0a,0x0c,0x0c,0x0c,0x0d,0x0c,0x0d,
+0x0b,0x09,0x0a,0x0c,0x0d,0x0b,0x0f,0x0b,0x0d,0x0b,0x0a,0x0a,
+0x0c,0x0c,0x0b,0x0e,0x0c,0x0c,0x0a,0x0a,0x09,0x0b,0x0b,0x0b,
+0x0d,0x0c,0x0b,0x0a,0x0a,0x09,0x0b,0x0b,0x0a,0x0d,0x0c,0x0a,
+0x0a,0x0a,0x0a,0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x0a,0x0a,0x0a,
+0x0c,0x0b,0x0c,0x0c,0x0d,0x0d,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,
+0x0c,0x0c,0x0d,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,
+0x0a,0x0a,0x0a,0x0c,0x0b,0x0b,0x0c,0x0d,0x0c,0x0a,0x0a,0x09,
+0x0b,0x0b,0x0b,0x0c,0x0d,0x0b,0x09,0x0a,0x09,0x0b,0x0a,0x0b,
+0x0b,0x0c,0x0b,0x09,0x0a,0x09,0x0b,0x0a,0x0b,0x0b,0x0d,0x0b,
+0x0a,0x09,0x0b,0x0b,0x0c,0x0b,0x0d,0x0b,0x0e,0x0a,0x0a,0x0a,
+0x0b,0x0c,0x0b,0x0d,0x0c,0x0d,0x0a,0x0a,0x0a,0x0b,0x0c,0x0c,
+0x0c,0x0c,0x0d,0x09,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0d,
+0x0a,0x09,0x0a,0x0b,0x0c,0x0a,0x0d,0x0b,0x0c,0x0a,0x09,0x0a,
+0x0b,0x0b,0x0a,0x0c,0x0b,0x0c,0x09,0x0a,0x0a,0x0b,0x0b,0x0b,
+0x0b,0x0c,0x0c,0x09,0x09,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,
+0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0b,0x0d,0x0d,0x09,0x0a,0x0a,
+0x0b,0x0b,0x0c,0x0b,0x0d,0x0d,0x09,0x0a,0x0b,0x0b,0x0b,0x0c,
+0x0b,0x0c,0x0e,0x09,0x0a,0x0b,0x0b,0x0b,0x0c,0x0b,0x0d,0x0e,
+0x09,0x0a,0x0a,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x09,0x0a,0x0a,
+0x0a,0x0a,0x0b,0x0a,0x0c,0x0d,0x09,0x09,0x0a,0x0a,0x0a,0x0b,
+0x0a,0x0b,0x0c,0x09,0x0a,0x0a,0x0a,0x0a,0x0c,0x0a,0x0c,0x0d,
+0x0a,0x0b,0x0a,0x0c,0x0c,0x0d,0x0d,0x0e,0x0d,0x0a,0x0b,0x0a,
+0x0c,0x0c,0x0d,0x0c,0x0e,0x0d,0x0a,0x0b,0x0a,0x0c,0x0b,0x0d,
+0x0c,0x0f,0x0d,0x0a,0x0b,0x0a,0x0c,0x0b,0x0d,0x0c,0x0e,0x0d,
+0x0a,0x0a,0x0a,0x0c,0x0b,0x0c,0x0c,0x0d,0x0d,0x0a,0x0a,0x0a,
+0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x09,0x0b,0x0a,0x0c,0x0b,0x0c,
+0x0b,0x0e,0x0d,0x09,0x0b,0x0a,0x0b,0x0b,0x0c,0x0b,0x0e,0x0d,
+0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0c,0x0e,0x0e,0x09,0x0b,0x0b,
+0x0c,0x0c,0x0d,0x0b,0x0e,0x0e,0x09,0x0b,0x0b,0x0b,0x0c,0x0d,
+0x0b,0x0e,0x0f,0x09,0x0b,0x0c,0x0b,0x0c,0x0e,0x0b,0x0e,0x10,
+0x09,0x0b,0x0b,0x0c,0x0b,0x0d,0x0b,0x0e,0x0e,0x09,0x0b,0x0b,
+0x0c,0x0c,0x0d,0x0b,0x0e,0x0e,0x09,0x0b,0x0b,0x0b,0x0c,0x0d,
+0x0b,0x0e,0x0f,0x09,0x0b,0x0c,0x0b,0x0c,0x0e,0x0a,0x0e,0x10,
+0x09,0x0b,0x0a,0x0c,0x0b,0x0d,0x0b,0x0f,0x0d,0x09,0x0b,0x0b,
+0x0c,0x0b,0x0e,0x0b,0x0f,0x0e,0x09,0x0c,0x0a,0x0c,0x0b,0x0d,
+0x0b,0x10,0x0d,0x09,0x0b,0x0b,0x0c,0x0b,0x0e,0x0b,0x0f,0x0e,
+0x09,0x0b,0x0b,0x0c,0x0c,0x0e,0x0b,0x0f,0x0f,0x09,0x0b,0x0c,
+0x0c,0x0c,0x0f,0x0b,0x0f,0x10,0x09,0x0c,0x0b,0x0c,0x0c,0x0e,
+0x0b,0x10,0x0f,0x09,0x0c,0x0c,0x0c,0x0d,0x0f,0x0b,0x10,0x10,
+0x09,0x0c,0x0b,0x0d,0x0b,0x0e,0x0b,0x11,0x0e,0x09,0x0c,0x0b,
+0x0d,0x0c,0x0f,0x0b,0x11,0x0f,0x09,0x0c,0x0b,0x0c,0x0c,0x0e,
+0x0a,0x10,0x0f,0x09,0x0c,0x0c,0x0c,0x0c,0x0f,0x0a,0x10,0x10,
+0x09,0x0c,0x0b,0x0d,0x0b,0x0f,0x0a,0x11,0x0e,0x09,0x0d,0x0c,
+0x0d,0x0c,0x10,0x0a,0x12,0x10,0x09,0x0d,0x0c,0x0d,0x0c,0x10,
+0x0a,0x12,0x10,0x09,0x0c,0x0d,0x0d,0x0d,0x10,0x0a,0x11,0x12,
+0x0a,0x0b,0x0a,0x0c,0x0b,0x0c,0x0c,0x0f,0x0c,0x09,0x0b,0x0a,
+0x0c,0x0a,0x0c,0x0b,0x0f,0x0c,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,
+0x0b,0x0d,0x0c,0x09,0x0a,0x0a,0x0b,0x0a,0x0b,0x0a,0x0d,0x0c,
+0x09,0x0b,0x0a,0x0c,0x0b,0x0c,0x0b,0x0e,0x0d,0x09,0x0b,0x0a,
+0x0b,0x0b,0x0c,0x0b,0x0e,0x0d,0x09,0x0b,0x0a,0x0c,0x0b,0x0d,
+0x0a,0x0f,0x0d,0x09,0x0b,0x0b,0x0c,0x0b,0x0e,0x0a,0x0f,0x0e,
+0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0a,0x0d,0x0d,0x09,0x0b,0x0a,
+0x0b,0x0a,0x0c,0x0a,0x0e,0x0c,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,
+0x0a,0x0d,0x0d,0x09,0x0a,0x0b,0x0b,0x0b,0x0d,0x0a,0x0d,0x0e,
+0x09,0x0b,0x0b,0x0b,0x0b,0x0d,0x0a,0x0e,0x0e,0x09,0x0b,0x0b,
+0x0b,0x0c,0x0e,0x0a,0x0e,0x0f,0x09,0x0b,0x0b,0x0b,0x0b,0x0d,
+0x0a,0x0e,0x0e,0x09,0x0b,0x0b,0x0b,0x0b,0x0e,0x0a,0x0e,0x0f,
+0x09,0x0c,0x0a,0x0c,0x0b,0x0d,0x0b,0x10,0x0d,0x09,0x0c,0x0a,
+0x0c,0x0b,0x0e,0x0a,0x10,0x0d,0x09,0x0b,0x0b,0x0c,0x0b,0x0e,
+0x0a,0x0f,0x0e,0x09,0x0b,0x0b,0x0c,0x0c,0x0e,0x0a,0x0f,0x0f,
+0x09,0x0c,0x0b,0x0c,0x0b,0x0e,0x0a,0x10,0x0f,0x09,0x0c,0x0c,
+0x0c,0x0c,0x0f,0x0a,0x10,0x10,0x09,0x0c,0x0b,0x0d,0x0c,0x0f,
+0x0a,0x11,0x0f,0x09,0x0d,0x0c,0x0d,0x0c,0x10,0x0a,0x12,0x11,
+0x09,0x0b,0x0a,0x0c,0x0b,0x0d,0x0a,0x0f,0x0d,0x09,0x0c,0x0b,
+0x0c,0x0b,0x0e,0x0a,0x10,0x0e,0x09,0x0c,0x0b,0x0c,0x0b,0x0e,
+0x0a,0x10,0x0f,0x09,0x0b,0x0c,0x0c,0x0c,0x0f,0x0a,0x0f,0x10,
+0x09,0x0c,0x0b,0x0c,0x0b,0x0f,0x0a,0x11,0x0e,0x09,0x0c,0x0c,
+0x0c,0x0c,0x10,0x0a,0x11,0x10,0x08,0x0c,0x0b,0x0c,0x0b,0x0e,
+0x09,0x10,0x0f,0x08,0x0c,0x0c,0x0c,0x0c,0x0f,0x09,0x11,0x10,
+0x0a,0x09,0x09,0x0a,0x0b,0x0a,0x0c,0x0a,0x0b,0x09,0x09,0x09,
+0x0a,0x0a,0x09,0x0b,0x0a,0x0a,0x09,0x0a,0x09,0x0a,0x0a,0x0a,
+0x0b,0x0c,0x0b,0x09,0x09,0x09,0x0a,0x09,0x0a,0x0a,0x0b,0x0a,
+0x09,0x09,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x09,0x09,0x0a,
+0x09,0x0a,0x0a,0x0a,0x0a,0x0c,0x09,0x09,0x09,0x09,0x09,0x0a,
+0x0a,0x0b,0x0b,0x08,0x09,0x09,0x09,0x09,0x0a,0x09,0x0b,0x0b,
+0x09,0x0a,0x09,0x0a,0x0a,0x0b,0x0a,0x0c,0x0b,0x08,0x0a,0x09,
+0x0a,0x09,0x0a,0x09,0x0c,0x0b,0x08,0x0a,0x0a,0x0a,0x09,0x0b,
+0x09,0x0c,0x0c,0x08,0x09,0x0a,0x09,0x0a,0x0b,0x09,0x0b,0x0d,
+0x09,0x09,0x09,0x09,0x09,0x09,0x0a,0x0a,0x0a,0x07,0x08,0x08,
+0x07,0x07,0x07,0x07,0x08,0x08,0x08,0x0a,0x09,0x09,0x09,0x0a,
+0x08,0x0c,0x0b,0x08,0x09,0x09,0x08,0x08,0x0a,0x08,0x0a,0x0b,
+0x09,0x0b,0x0a,0x0b,0x0a,0x0c,0x0a,0x0f,0x0c,0x09,0x0b,0x0a,
+0x0b,0x0a,0x0d,0x0a,0x0f,0x0c,0x09,0x0a,0x0a,0x0a,0x0a,0x0c,
+0x0a,0x0d,0x0d,0x08,0x0a,0x0b,0x0a,0x0b,0x0d,0x09,0x0d,0x0e,
+0x09,0x0b,0x0a,0x0b,0x0a,0x0d,0x0a,0x0f,0x0d,0x09,0x0b,0x0b,
+0x0b,0x0b,0x0e,0x0a,0x0f,0x0e,0x08,0x0b,0x0b,0x0b,0x0b,0x0d,
+0x09,0x0e,0x0e,0x08,0x0b,0x0c,0x0b,0x0b,0x0e,0x09,0x0f,0x10,
+0x08,0x0a,0x09,0x0a,0x09,0x0b,0x09,0x0d,0x0b,0x08,0x0b,0x0a,
+0x0b,0x0a,0x0c,0x09,0x0e,0x0d,0x08,0x0b,0x0a,0x0a,0x0a,0x0c,
+0x09,0x0e,0x0d,0x08,0x0a,0x0b,0x0a,0x0b,0x0d,0x09,0x0d,0x0e,
+0x08,0x0c,0x0b,0x0b,0x0a,0x0e,0x09,0x10,0x0e,0x08,0x0c,0x0b,
+0x0b,0x0b,0x0e,0x09,0x10,0x0f,0x08,0x0b,0x0a,0x0a,0x0a,0x0c,
+0x09,0x0e,0x0d,0x08,0x0b,0x0a,0x0a,0x0a,0x0d,0x08,0x0e,0x0d};
+
+static const signed short etable1[5120]={
+0x0026,0xfffc,0x000f,0xfffc,0x000e,0xfff3,0x000c,0xfff5,
+0xfffe,0xfffa,0xfffa,0xfff5,0xffd3,0xfff0,0xfff5,0xfff3,
+0xfff9,0x0006,0xfff4,0x0004,0xffec,0x0003,0xfff0,0x000c,
+0xffff,0x000c,0x002e,0x0018,0x0000,0x0021,0xfffd,0x0009,
+0xfff4,0xfff4,0xfff8,0xfff9,0x0011,0xfffa,0x0000,0xfffe,
+0x003c,0xfff0,0x0003,0xffea,0x000a,0xffe0,0x0000,0xffe4,
+0xffef,0xffee,0xfffd,0xffe7,0xffdb,0xffe9,0xfff6,0x0003,
+0x0002,0x0003,0x0000,0x0003,0xfff2,0x0000,0xfff2,0xffff,
+0x0000,0x0002,0x0020,0x0009,0xffff,0x0019,0x0007,0x000d,
+0xfffb,0x000d,0x0008,0x0001,0x0002,0x0008,0xfff6,0x0006,
+0x001b,0xfff4,0x001c,0xfffe,0x0006,0xfff9,0x000f,0x0009,
+0xfff5,0x0001,0xfff3,0xfff5,0xffd8,0x0004,0xffe3,0xfff2,
+0xffed,0xfffb,0xffe9,0xfff8,0xffe2,0xfff3,0xffef,0x0000,
+0xfff2,0x000c,0x0022,0x0014,0xfffe,0x0019,0x0002,0xfff0,
+0xfffc,0xfff4,0x000f,0x0010,0x001d,0x0007,0x0018,0x000a,
+0x0031,0xffe8,0x0010,0xffec,0x0002,0xffe6,0x0002,0xfff9,
+0xffe7,0xfff6,0xfff5,0xffe7,0xffe0,0xfffd,0xffe5,0x0002,
+0xfff8,0xfff8,0xfff5,0xfff7,0xffe8,0xffef,0xfff0,0xfff2,
+0xfff3,0x0002,0x0014,0x0005,0xfffc,0x0011,0x000e,0xfff4,
+0x0003,0x000d,0x0021,0x0019,0x000e,0x0017,0x000f,0x0013,
+0x002e,0xfffa,0x0015,0x0008,0xfffe,0xfff0,0xfffb,0xfff8,
+0xfff5,0x0004,0x0008,0x000f,0xffe8,0x0004,0xfffe,0xffe6,
+0xfffd,0xfff0,0xfff0,0xfff2,0xfff7,0xfffe,0xffff,0x0004,
+0x0013,0x0007,0x0024,0x0011,0x0009,0x000d,0x0000,0x001f,
+0xfffb,0xfff4,0x0007,0xfff8,0x000b,0xfff1,0xfff3,0xfffc,
+0x0044,0xffee,0x0009,0xfff7,0xfffa,0xffdd,0xffee,0xffe7,
+0xffe6,0xfff9,0x000a,0x0001,0xfff0,0xfffd,0xffff,0xfff7,
+0x0006,0xffed,0xfffc,0xfff1,0xfffc,0xfffa,0x0000,0xfff8,
+0x0014,0xfffe,0x0017,0x0002,0x0007,0x0005,0x000c,0x0023,
+0x0001,0x000d,0x0018,0x0000,0xfffd,0x0000,0xffea,0x0004,
+0x0023,0xfff2,0x0022,0x000a,0xfff6,0xfff6,0xffff,0x000c,
+0xffec,0x000c,0x0000,0x000f,0xffee,0x0018,0xffec,0xffe5,
+0xfff2,0xffe4,0xffe5,0xffe5,0xffec,0xffed,0xfffe,0xfff8,
+0x0005,0x0007,0x0019,0x000d,0x0005,0x0005,0x0006,0x0005,
+0x0002,0xfff4,0x001f,0x000f,0x0017,0xffff,0x000c,0x0008,
+0x0039,0xffe6,0x0016,0xfff9,0xfff2,0xffe4,0xfff2,0xfffd,
+0xffdd,0x0000,0x0003,0x0001,0xfff5,0x0010,0xffee,0xfff6,
+0xfffc,0xffe1,0xfff1,0xffe4,0xfff2,0xffe9,0xffff,0xffeb,
+0x0007,0xfffe,0x000b,0xffff,0x0003,0xffff,0x0012,0x0009,
+0x000a,0x000d,0x0031,0x0018,0x0008,0x000e,0x0002,0x0010,
+0x0019,0x000f,0x0016,0x000b,0x0012,0x0004,0x000f,0xffea,
+0x0008,0xfffe,0xffef,0xfff7,0xffd0,0xffec,0xffe2,0xffef,
+0xfff0,0x000b,0xffff,0x0010,0x0002,0x000a,0xfffb,0x001a,
+0xfffe,0xfffc,0x0016,0x0000,0x0002,0x000a,0xfffa,0x000d,
+0xfff2,0x000a,0xffe9,0x0000,0x000a,0xfffe,0x0001,0x0000,
+0x002f,0x0003,0x000b,0xfffa,0x000f,0xfff3,0x0002,0xffda,
+0xfffa,0xfff3,0xfff1,0xffea,0xffd8,0xffe4,0xffe4,0x0000,
+0xfffb,0x0008,0x000a,0x000f,0x0007,0x0007,0xfffc,0x000d,
+0xffff,0xfff2,0x0009,0xfff2,0x0000,0x0002,0x0004,0x0012,
+0xfff9,0x0024,0xfffa,0x0008,0xfffd,0x000d,0xfff9,0x0008,
+0x000e,0x0007,0x0024,0x000d,0x000a,0x000a,0x0012,0x0000,
+0x0000,0x0005,0xffe7,0xfff8,0xffd5,0x0000,0xffd0,0xffee,
+0xffe5,0x0000,0xfff4,0x0003,0xfff9,0xfffa,0xfff9,0x000d,
+0xfff1,0xfffb,0x000b,0xfffd,0x0000,0x0002,0x0000,0xfff4,
+0xfffa,0x000a,0x0000,0x0017,0x0016,0x000b,0x001a,0x000c,
+0x0024,0xfffb,0x0018,0xfffc,0x0007,0xfff9,0x0006,0xffef,
+0xfff2,0xfffb,0xffea,0xffea,0xffdd,0xfff8,0xffd2,0xffff,
+0xffef,0xfffd,0x0000,0x0002,0xfffe,0xfff6,0xfffb,0x0000,
+0xfff2,0xfff1,0xfffe,0xffee,0xfffe,0xfffc,0x000b,0xfff9,
+0x0001,0x0024,0x0012,0x0020,0x0007,0x001b,0x0011,0x0014,
+0x0021,0x000d,0x001d,0x0018,0x0001,0x0001,0xfffe,0xffee,
+0x0000,0x0009,0xfffd,0x0011,0xffe5,0x0000,0xffeb,0xffe2,
+0xfff4,0xfff5,0xfffb,0xfffe,0x000c,0x0004,0x0009,0x0013,
+0x0012,0xfff7,0x000d,0xfffa,0x000b,0xfff8,0xfffe,0x0023,
+0xfff8,0x000a,0xfff9,0xffff,0x0004,0xfff5,0xfff6,0xfffe,
+0x0037,0x0001,0x0011,0x0006,0xffff,0xfff0,0xfff1,0xffdd,
+0xfff1,0xfffe,0x0000,0x0004,0xffed,0xfff8,0xffec,0xfff3,
+0xffff,0xfff2,0x0007,0xfffd,0x0012,0x0000,0x000a,0x0005,
+0x0013,0xffed,0x0000,0xffeb,0x0008,0xfff0,0x0009,0x0027,
+0x0000,0x0024,0x000a,0x0007,0xfff7,0x0004,0xffec,0x0005,
+0x0016,0x0005,0x002a,0x001a,0xfffa,0x0008,0x0001,0x0002,
+0xfff7,0x0011,0xfff6,0x0012,0xffeb,0x0013,0xffd9,0xffe1,
+0xffe9,0xffe9,0xfff0,0xfff1,0x0002,0xfff4,0x0007,0x0006,
+0x0005,0xfff7,0x0001,0xfff6,0x0007,0xfff0,0x0004,0x0009,
+0x0000,0x000a,0x0011,0x0016,0x0010,0x0002,0x000e,0x0009,
+0x002c,0xfffa,0x001e,0x0008,0xfff7,0xfff6,0xfff5,0xfff2,
+0xffe9,0x0005,0xfff8,0x0004,0xfff2,0x000c,0xffdb,0xfff2,
+0xfff4,0xffe6,0xfffc,0xfff0,0x0008,0xfff0,0x0009,0xfff9,
+0x0006,0xffed,0xfff4,0xffe7,0x0005,0xffe8,0x000f,0x000d,
+0x0008,0x0024,0x0022,0x001f,0x0001,0x0012,0x0004,0x0012,
+0xfffd,0xfffb,0xfff7,0xfff9,0x000f,0xffff,0x0005,0x000d,
+0x0002,0x000c,0x0005,0x0002,0xffeb,0xffe9,0xfffe,0xfff0,
+0x0000,0x0005,0xfffa,0x000d,0xffe9,0x0003,0xffe0,0x000a,
+0xfff1,0x0008,0x002c,0x001c,0x0009,0x0025,0xfffe,0x000d,
+0xfff7,0xfff1,0xfff4,0xffe5,0xfff9,0xfff4,0x0000,0xfff5,
+0x0012,0xffef,0xffeb,0xffe7,0x000b,0xffed,0xfffa,0xfffd,
+0xfff5,0x0000,0x0007,0xfff5,0xfff3,0xffe1,0xffff,0x0000,
+0x0009,0x0001,0x0005,0x000c,0xffee,0x0000,0xffe1,0xfffe,
+0xfff3,0xffff,0x001e,0x000e,0x0007,0x001d,0x0009,0x0012,
+0xffff,0x000a,0x0004,0xffee,0xffea,0x0003,0xfff6,0xfffe,
+0xfff3,0xfff3,0x0003,0xfffb,0x0007,0x0004,0x0009,0x0022,
+0xfffb,0x0014,0xfffe,0x0003,0xfff0,0xfffd,0xffec,0xffef,
+0xfff5,0xfff9,0xffef,0x0000,0xffde,0xfff3,0xffdf,0xfffe,
+0xffe4,0x0008,0x0020,0x0018,0x0005,0x001d,0x0003,0xfff4,
+0x0000,0xfff1,0x000b,0xfffd,0x0003,0x0002,0x0018,0x0001,
+0x0008,0xffe7,0xfff8,0xffe9,0x0003,0xfff3,0xfffd,0x0011,
+0xffec,0x0008,0x0000,0xfff6,0xfff8,0xfff5,0xffee,0x0000,
+0xffff,0xfff6,0xfffb,0x0000,0xffe4,0xffef,0xffe0,0xfff1,
+0xffe6,0xffff,0x0013,0x0009,0x0003,0x0015,0x000f,0xfff9,
+0x0006,0x0009,0x001d,0x0005,0xfff6,0x0011,0x000f,0x0009,
+0x0004,0xfffa,0xfffd,0x0005,0xffff,0xfffc,0xfff5,0x0010,
+0xfffa,0x0017,0x0013,0x001d,0x0000,0xfffd,0x0006,0xffe2,
+0x0003,0xffef,0xfff6,0xfffb,0xfff3,0xfffe,0xffef,0x0003,
+0x0005,0x0003,0x0023,0x0015,0x0011,0x0011,0x0002,0x0023,
+0xfffe,0xfff1,0x0003,0xffe4,0xfff3,0xffeb,0xfff3,0xfff3,
+0x001a,0xffed,0xfff1,0xfff4,0xfffb,0xffea,0xffe8,0x0000,
+0xffeb,0x000c,0x0015,0x000f,0x0008,0xfff5,0x0007,0xfff4,
+0x000e,0xffec,0x0002,0xfffa,0xfff9,0xfffa,0xfff0,0xfff7,
+0x0006,0xfffb,0x0015,0x0007,0x000f,0x000a,0x000d,0x0027,
+0x0005,0x000a,0x0014,0xffed,0xffe4,0xfffb,0xffea,0xfffb,
+0xfffb,0xfff1,0x0009,0x0007,0xfff7,0x0002,0xfff8,0x0025,
+0xfff2,0x001f,0x000b,0x001d,0x0005,0x0010,0xfff5,0xffe2,
+0xfff9,0xffe3,0xffeb,0xffee,0xffe9,0xffed,0xffee,0xfff7,
+0xfff9,0x0003,0x0017,0x0011,0x000e,0x0009,0x0008,0x0009,
+0x0006,0xfff1,0x001b,0xfffc,0xfffe,0xfffa,0x000c,0xffff,
+0x0010,0xffe5,0xfffe,0xfff6,0xfff3,0xfff0,0xffec,0x0014,
+0xffe3,0x0014,0x000e,0x0010,0x000d,0x0008,0xfff7,0xfff3,
+0x0002,0xffdf,0xfff7,0xffed,0xffef,0xffe9,0xffef,0xffea,
+0xfffa,0xfffa,0x0009,0x0002,0x000c,0x0002,0x0014,0x000d,
+0x000d,0x000a,0x002d,0x0004,0xfff0,0x0008,0x0002,0x0007,
+0xfff0,0x000e,0xfffe,0x0008,0x0014,0x0011,0x0009,0x0002,
+0x000e,0x0010,0xfffa,0x0005,0xffe8,0xffe4,0xffeb,0xffec,
+0xfff8,0x0009,0x0004,0x0019,0xffff,0x000b,0xffea,0x0018,
+0xfff1,0xfff8,0x0015,0x0005,0x000b,0x000e,0xfffb,0x0012,
+0xfff5,0x0007,0xffe5,0xffec,0xfff2,0xfff9,0x0001,0xfff7,
+0x0006,0x0002,0xfff2,0xfff7,0x0010,0xffff,0xfffd,0xfff2,
+0x0000,0x0005,0xfffd,0xfff8,0xfff0,0xffdc,0xffed,0xfffd,
+0x0001,0x0006,0x0011,0x0018,0x0004,0x0007,0xffeb,0x000b,
+0xfff2,0xffee,0x0007,0xfff7,0x0009,0x0007,0x0006,0x0016,
+0xfffd,0x0021,0xfff6,0xfff5,0xffe4,0x0007,0xfff9,0x0000,
+0xffe6,0x0006,0x000b,0x000a,0x000c,0x0017,0x000c,0x0017,
+0x0005,0x0018,0xfff3,0x0005,0xffed,0xfff8,0xffda,0xffeb,
+0xffec,0xfffe,0xfffa,0x000c,0xfff5,0xfffb,0xffe9,0x000b,
+0xffe3,0xfff7,0x0009,0x0000,0x0007,0x0006,0x0001,0xfff9,
+0xfffe,0x0007,0xfffd,0x0003,0xfffe,0x0006,0x001b,0x0003,
+0xfffc,0xfffa,0x0000,0xfff9,0x0008,0x0004,0x0000,0x0006,
+0xfff7,0x000d,0xfff5,0xfff9,0xfff5,0xfff1,0xffdb,0xfffc,
+0xfff7,0xfffb,0x0005,0x000b,0xfffb,0xfff7,0xffea,0xffff,
+0xffe5,0xffee,0xfffc,0xfff2,0x0005,0x0000,0x000c,0xfffd,
+0x0004,0x0020,0x000e,0x000c,0xffef,0x0016,0x0011,0x000b,
+0xfff8,0x000c,0x0003,0x0015,0x0003,0x000e,0xfff8,0x0005,
+0x0004,0x001c,0x0007,0x0020,0xfffe,0xfff8,0xfff4,0xffde,
+0xfffc,0xfff4,0x0001,0x0006,0x0009,0x0004,0xfff9,0x0011,
+0x0004,0xfff3,0x000b,0xffff,0x0013,0xfffc,0x0000,0x0027,
+0xfffc,0x0007,0xfff5,0xffeb,0xffec,0xfff0,0xfff6,0xfff5,
+0x000d,0x0000,0xfff8,0x0003,0x0000,0xfffc,0xffeb,0xfff5,
+0xfff7,0x0010,0x000a,0x0012,0x0005,0xfff0,0xfff6,0xfff0,
+0x0005,0xfff1,0x000d,0x0005,0x000f,0x0001,0xfffa,0x0004,
+0x0006,0xffe9,0xfffe,0xfff0,0x0011,0xfff4,0x000a,0x002c,
+0x0003,0x0021,0x0006,0xfff4,0xffde,0xffff,0xffec,0xfffd,
+0xffee,0x0004,0x0011,0x0017,0xfffc,0x0014,0xfffc,0x001a,
+0xfffd,0x0024,0x0000,0x0020,0x0002,0x000c,0xffe3,0xffde,
+0xfff0,0xffe8,0xfff6,0xfffa,0x0000,0xfff4,0xfff8,0x0004,
+0xfff8,0xfff3,0x0000,0xfffa,0x0010,0xfff4,0x0005,0x000d,
+0x0003,0x0007,0x000d,0x0003,0xfff8,0xfffe,0x000e,0x0000,
+0x0003,0xfff9,0x0005,0x0005,0xfff8,0x0002,0xffef,0x0009,
+0xffee,0x0018,0x0002,0x0013,0x000a,0x0004,0xffe4,0xffef,
+0xfffb,0xffe4,0x0002,0xfff9,0x0004,0xfff1,0xfff9,0xfff8,
+0xfffa,0xffe9,0xfff3,0xffeb,0x000e,0xffec,0x0011,0x0012,
+0x000b,0x0021,0x001e,0x000b,0xffe9,0x000d,0x0005,0x0009,
+0x003c,0x000a,0x0007,0xffff,0x0009,0xfff8,0x0006,0xfff3,
+0x0002,0xfff1,0xffff,0xfff6,0xfff3,0xfff5,0x000f,0x0000,
+0x0006,0x0009,0xffff,0x0000,0xfff3,0x0001,0xfff5,0xfffd,
+0xfff3,0x0015,0x000d,0x001a,0xfff9,0x001f,0xfff6,0xfff9,
+0xfff0,0xffdf,0xffe1,0xfff6,0x0016,0xfff8,0x0001,0xfffe,
+0x0052,0xffff,0xfffc,0xffed,0x0006,0xffe5,0xfffa,0xffe3,
+0xfff4,0xffe6,0x0001,0xffe8,0xfffb,0xffee,0x0011,0x0011,
+0x0011,0x0006,0x000a,0x0000,0xfff9,0xfffe,0xfff7,0xfff0,
+0xfff4,0x000b,0x0000,0x000b,0xfff7,0x0017,0x0000,0xfffd,
+0xfff8,0xfff8,0xfff3,0xffff,0x0008,0x0007,0xfff9,0x0006,
+0x0031,0x0002,0x0015,0x0000,0x0001,0xfffe,0x0009,0x0008,
+0xfffa,0xfffa,0xfff8,0xfff6,0xfff8,0x0009,0xfffe,0x0000,
+0xfffc,0xfffe,0xfff3,0xfff4,0xffe9,0xfff1,0xfff4,0xfff0,
+0xffe6,0x0015,0x0002,0x0015,0xfff5,0x0017,0xfffc,0xffdf,
+0xfff9,0xffdf,0xfffa,0x000d,0x0022,0x0005,0x001b,0x000a,
+0x0047,0xfff6,0x0009,0xffef,0xffff,0xffec,0xfffd,0xfff8,
+0xffeb,0xffee,0xfffa,0xffe8,0x0000,0x0001,0x0000,0x0010,
+0x0006,0xfffb,0x0000,0xfff3,0xffef,0xffed,0xfff5,0xffe3,
+0xffe7,0x000b,0xfff5,0x0006,0xfff3,0x000f,0x0007,0xffe3,
+0x0000,0xfff8,0x000b,0x0016,0x0014,0x0015,0x0011,0x0012,
+0x0043,0x0008,0x000e,0x000b,0xfff9,0xfff5,0xfff5,0xfff7,
+0xfff9,0xfffd,0x000d,0x0010,0x0008,0x0009,0x0018,0xfff4,
+0x000a,0xfff3,0xfffb,0xffef,0xfffe,0xfffc,0x0003,0xfff6,
+0x0006,0x0011,0x0004,0x0013,0x0000,0x000b,0xfffa,0x000d,
+0xfff7,0xffdf,0xfff2,0xfff6,0x0010,0xffef,0xfff6,0xfffc,
+0x005a,0xfffd,0x0002,0xfffa,0xfff6,0xffe3,0xffe8,0xffe6,
+0xffeb,0xfff1,0x000f,0x0002,0x0010,0x0001,0x0019,0x0004,
+0x0015,0xfff0,0x0006,0xffee,0x0003,0xfff8,0x0005,0xffe8,
+0x0008,0x0007,0xfff7,0x0004,0xffff,0x0003,0x0005,0x0012,
+0xffff,0xfff9,0x0002,0xffff,0x0002,0xffff,0xffed,0x0003,
+0x0039,0x0000,0x001b,0x000d,0xfff2,0xfffb,0xfff9,0x000b,
+0xfff1,0x0004,0x0005,0x0010,0x000d,0x001d,0x0006,0xfff3,
+0x0000,0xffe7,0xfff0,0xffe1,0xfff4,0xffea,0x0002,0xffe9,
+0xfffa,0x0010,0xfff9,0x000e,0xfffe,0x0003,0x0000,0xfff4,
+0x0000,0xffdf,0x0009,0x000d,0x001c,0xfffd,0x000e,0x0007,
+0x004f,0xfff5,0x000f,0xfffc,0xffee,0xffe9,0xffec,0xfffb,
+0xffe2,0xfff9,0x0007,0x0002,0x0015,0x0015,0x0008,0x0003,
+0x000a,0xffe4,0xfffc,0xffe1,0xfffa,0xffe7,0x0003,0xffdb,
+0xfffc,0x0007,0xffec,0x0000,0xfffc,0xfffc,0x000b,0xfff9,
+0x0006,0xfff8,0x001b,0x0016,0x000e,0x000c,0x0005,0x0010,
+0x002f,0x001e,0x000f,0x000e,0x000e,0x0009,0x0009,0xffe9,
+0x000d,0xfff6,0xfff4,0xfff9,0xfff0,0xfff1,0xfffd,0xfffd,
+0xffff,0x000e,0x0009,0x000c,0x0009,0x0008,0x0000,0x000a,
+0xfff2,0x0004,0xfff7,0x0002,0xfffb,0x0008,0xfff3,0xfffd,
+0xffee,0xfff6,0xffd3,0xfffd,0x0010,0xfffc,0x0004,0x0000,
+0x0045,0x0011,0x0003,0xfffd,0x000a,0xfff8,0xfffd,0xffd8,
+0xffff,0xffeb,0xfff6,0xffeb,0xfff8,0xffe9,0xffff,0x000d,
+0x0008,0x000b,0x0015,0x000b,0x000f,0x0004,0x0000,0xfffe,
+0xfff3,0xfffb,0xffe9,0xfff4,0xfff9,0x0000,0xffff,0x0000,
+0xfff6,0x000e,0xffe4,0x0005,0x0001,0x000b,0xfffb,0x0007,
+0x0024,0x0015,0x001c,0x0010,0x0006,0x0010,0x000c,0xfffe,
+0x0004,0xfffe,0xffec,0xfff9,0xfff5,0x0004,0xffec,0xfffc,
+0xfff4,0x0002,0xffff,0x0000,0x0000,0xfff8,0xfffe,0xfffe,
+0xffe5,0x0004,0xffeb,0xfffe,0xfff7,0x0000,0xfffa,0xffe3,
+0xfff7,0xfff6,0xffeb,0x0015,0x001c,0x000a,0x001d,0x000b,
+0x003a,0x0009,0x0010,0xffff,0x0002,0xfffe,0x0000,0xffed,
+0xfff6,0xfff3,0xffef,0xffeb,0xfffd,0xfffd,0xffed,0x000c,
+0xfffe,0x0000,0x000a,0xffff,0x0005,0xfff4,0x0000,0xfff1,
+0xffe6,0xfffb,0xffde,0xfff0,0xfff5,0xfff9,0x0004,0xffe7,
+0xfffe,0x000e,0xfffd,0x001d,0x000d,0x0019,0x0014,0x0014,
+0x0037,0x001c,0x0015,0x001b,0xfffe,0x0007,0xfff8,0xffec,
+0x0004,0x0001,0x0001,0x0012,0x0005,0x0004,0x0005,0xfff0,
+0x0002,0xfff8,0x0005,0xfffb,0x0013,0x0002,0x000e,0x0003,
+0x0006,0x0000,0xffee,0xfffc,0x0002,0xfff5,0xfff8,0x0012,
+0xfff5,0xfff6,0xffe3,0xfffd,0x000a,0xfff3,0xfff8,0xfffd,
+0x004d,0x0010,0x0009,0x0009,0xfffa,0xfff5,0xffeb,0xffdb,
+0xfff6,0xfff6,0x0004,0x0005,0x000d,0xfffd,0x0007,0x0000,
+0x000d,0xfff5,0x0011,0xfffa,0x0019,0xffff,0x000f,0xfff7,
+0x0007,0xfff7,0xffe0,0xffed,0x0000,0xffee,0x0002,0x0016,
+0xfffd,0x000f,0xfff4,0x0005,0xfffc,0x0002,0xffef,0x0005,
+0x002c,0x0014,0x0022,0x001d,0xfff6,0x000d,0xfffc,0x0000,
+0xfffc,0x0009,0xfffb,0x0013,0x000a,0x0018,0xfff5,0xffef,
+0xfff8,0xffec,0xfffb,0xffed,0x0009,0xfff2,0x000c,0xfff7,
+0xfffa,0x0000,0xffe2,0xfff7,0x0000,0xffed,0xfffe,0xfff9,
+0xfffe,0xfff6,0xfffb,0x0014,0x0015,0x0001,0x0011,0x0009,
+0x0042,0x0008,0x0017,0x000b,0xfff2,0xfffb,0xffef,0xfff0,
+0xffed,0xfffe,0xfffd,0x0005,0x0012,0x0011,0xfff6,0x0000,
+0x0001,0xffe9,0x0006,0xffec,0x000f,0xffee,0x000e,0xffea,
+0xfffb,0xfff6,0xffd4,0xffe9,0xfffe,0xffe6,0x0009,0xfffd,
+0x0004,0x000e,0x000c,0x001d,0x0007,0x0010,0x0007,0x0012,
+0x0012,0x0009,0xffef,0xfffc,0x000b,0x0003,0x0000,0x000b,
+0x0007,0x0004,0x000a,0x0003,0x000a,0xffee,0x0018,0xfffd,
+0x000e,0x0007,0x0004,0x000a,0xfff0,0x0001,0xffe5,0xfffc,
+0xffe5,0x0011,0x000c,0x001e,0x0000,0x0023,0xfff7,0xfffd,
+0xfff4,0xffdc,0xffdd,0xffe2,0xfffe,0xfff3,0x0002,0xfff5,
+0x0028,0xfffe,0xffe3,0xffea,0x0007,0xfff2,0xfff4,0xfffb,
+0xfff9,0xfff9,0x000c,0xfff7,0x0012,0xffe6,0x001a,0x000e,
+0x0018,0x0004,0x0010,0x0009,0xfff6,0xfffe,0xffe6,0xffee,
+0xffe6,0x0007,0xffff,0x000f,0xffff,0x001b,0x0002,0x0000,
+0xfffc,0xfff5,0xffef,0xffeb,0xfff0,0x0001,0xfff9,0xfffd,
+0x0008,0x0001,0xfffd,0xfffe,0x0003,0x000a,0x0003,0x0020,
+0xffff,0x000c,0x0002,0x0004,0x000f,0x0001,0x0007,0xfffd,
+0x0002,0xfffc,0xfffa,0xfffd,0xffe6,0xfff1,0xffe3,0xffef,
+0xffd8,0x0011,0x0000,0x001a,0xfffe,0x001b,0xfffe,0xffe3,
+0xfffc,0xffdc,0xfff6,0xfffa,0x0009,0x0000,0x001b,0x0000,
+0x001e,0xfff5,0xfff1,0xffec,0x0000,0xfff8,0xfff7,0x000f,
+0xfff1,0x0000,0x0005,0xfff7,0x0017,0xfffa,0x0008,0x000d,
+0x000d,0xfff9,0x0005,0xfffd,0xffec,0xffed,0xffe5,0xffe1,
+0xffd9,0x0007,0xfff3,0x000b,0xfffc,0x0013,0x0008,0xffe7,
+0x0003,0xfff5,0x0007,0x0002,0xfffc,0x0010,0x0012,0x0009,
+0x001a,0x0007,0xfff5,0x0008,0xfffb,0x0001,0xffef,0x000e,
+0xffff,0x000f,0x0018,0x001e,0x0020,0x0001,0x0021,0xfff0,
+0x0012,0xfff2,0x0000,0xfff8,0xfffa,0xfffc,0xfff4,0xfff4,
+0xfffa,0x000d,0x0002,0x0017,0x0008,0x000f,0xfffc,0x0011,
+0xfffb,0xffdc,0xffee,0xffe2,0xfff8,0xffea,0xfff6,0xfff2,
+0x0030,0xfffc,0xffe9,0xfff7,0xfff7,0xffef,0xffe2,0xfffe,
+0xfff0,0x0003,0x001a,0x0010,0x0028,0xfffa,0x0023,0x0001,
+0x001c,0xffef,0x000c,0xfff7,0x0000,0xfff8,0xfff5,0xffe7,
+0xfffb,0x0003,0xfff6,0x0008,0x0006,0x0007,0x0006,0x0016,
+0x0001,0xfff5,0xffff,0xffeb,0xffea,0xfff9,0xffed,0xfffb,
+0x000f,0x0000,0x0002,0x000a,0xfff3,0x0007,0xfff2,0x0023,
+0xfff6,0x0017,0x0010,0x001f,0x0025,0x0015,0x0010,0xffef,
+0x0006,0xffe6,0xfff6,0xffeb,0xfff0,0xffeb,0xfff3,0xffe7,
+0xffed,0x000d,0xfff8,0x0013,0x0005,0x0007,0x0001,0xfff8,
+0x0002,0xffdc,0x0005,0xfffa,0x0003,0xfff8,0x000f,0xffff,
+0x0025,0xfff4,0xfff7,0xfff9,0xffef,0xfff5,0xffe6,0x0012,
+0xffe7,0x000c,0x0013,0x0011,0x002d,0x000e,0x0011,0x0000,
+0x0011,0xffe2,0x0001,0xffea,0xfff6,0xffe7,0xfff4,0xffda,
+0xffee,0x0003,0xffea,0x0004,0x0003,0x0000,0x000d,0xfffd,
+0x000a,0xfff5,0x0017,0x0002,0xfff6,0x0007,0x0005,0x0007,
+0x0005,0x001d,0xfff7,0x000b,0x000f,0x0016,0x0003,0x0000,
+0x0012,0x0008,0xffff,0x0006,0x0007,0xffe9,0x0006,0xfffa,
+0x0005,0x000c,0x000f,0x0015,0x0005,0x0008,0xffef,0x0009,
+0xffe4,0x0000,0xfff5,0x0006,0x0002,0x000c,0xfff5,0x0000,
+0xfff2,0xfff3,0xffcf,0xffea,0xfff8,0xfff7,0x0004,0xfff7,
+0x001b,0x0010,0xffeb,0xfffa,0x000c,0x0003,0xfff7,0xfff0,
+0x0003,0xfffe,0x0001,0xfff9,0x000f,0xffe1,0x0007,0x000a,
+0x0010,0x0009,0x001b,0x0015,0x000b,0x0005,0xfff0,0xfffd,
+0xffe6,0xfff7,0xffe8,0xfff9,0x0000,0x0004,0x0000,0x0004,
+0xfffa,0x000b,0xffe0,0xfff2,0xffe9,0x0006,0xfffb,0xffff,
+0xfffc,0x0014,0x0003,0x000d,0x0008,0x001c,0x0006,0x0015,
+0x000a,0x0010,0xfff8,0x0007,0x000c,0xfffd,0xfff5,0xfff9,
+0xfffb,0x0000,0x0004,0x0008,0xfffc,0xfff8,0xffee,0xfffd,
+0xffd7,0x0000,0xffea,0x0002,0x0000,0x0004,0xfffb,0xffe7,
+0xfffa,0xfff2,0xffe7,0x0001,0x0002,0x0004,0x001d,0x0002,
+0x0011,0x0008,0xfff8,0xfffc,0x0004,0x000a,0xfffa,0x0005,
+0xfffc,0x0005,0xfffa,0xfffa,0x0014,0xfff6,0xfff7,0x0009,
+0x0004,0xfffe,0x0010,0x0007,0x0001,0xfff4,0xffef,0xfff0,
+0xffd9,0xfff7,0xffdc,0xfff4,0xfffe,0xfffd,0x0006,0xffeb,
+0x0001,0x000b,0xfff9,0x000a,0xfff5,0x0014,0x0014,0x000b,
+0x000d,0x001b,0xfffd,0x0018,0xffff,0x0013,0xfff2,0x0003,
+0x0009,0x0014,0x000c,0x0021,0x001d,0xfffd,0x000f,0xffec,
+0x0009,0xfff7,0x000b,0x0003,0x0010,0x0002,0xfffe,0x0002,
+0xfff9,0xfffd,0xffec,0x0000,0x000a,0xfff9,0xfff9,0x0016,
+0xfff9,0xfff3,0xffdf,0xffe9,0xfff2,0xffee,0xfff9,0xfff4,
+0x0023,0x000f,0xfff1,0x0006,0xfffc,0x0001,0xffe5,0xfff4,
+0xfffb,0x0008,0x000f,0x0013,0x0025,0xfff5,0x0010,0xfffe,
+0x0014,0xfff4,0x0017,0x0002,0x0016,0xffff,0xffff,0xfff5,
+0xfffb,0xfff3,0xffde,0xfff2,0x0008,0xfff2,0x0004,0x001a,
+0x0000,0x000b,0xfff0,0xfff2,0xffe3,0xfffe,0xffef,0xfffd,
+0x0003,0x0013,0x0009,0x001a,0xfff8,0x001a,0xfff6,0x0018,
+0x0000,0x001c,0x0005,0x0021,0x0022,0x0011,0xfffe,0xffec,
+0xffff,0xffea,0x0000,0xfff6,0x0006,0xfff2,0xfffd,0xfff6,
+0xffec,0xfffc,0xffe0,0xfffc,0x0007,0xfff1,0x0000,0xfffd,
+0x0000,0xfff3,0xfff7,0x0000,0xfffd,0xfffc,0x0011,0x0000,
+0x0019,0x0007,0xfffe,0x0008,0xfff4,0x0007,0xffe9,0x0008,
+0xfff3,0x0010,0x0007,0x0014,0x002a,0x0009,0x0000,0xfffd,
+0x0009,0xffe7,0x000c,0xfff6,0x000c,0xffee,0xfffe,0xffe8,
+0xffed,0xfff3,0xffd2,0xffed,0x0005,0xffea,0x000a,0x0000,
+0x0008,0x000b,0x0008,0x0009,0xffef,0x000b,0x0007,0x0008,
+0xffe7,0xfff9,0x0002,0xfff8,0x000c,0xfff9,0x0017,0xfff8,
+0x000d,0xfff0,0xfff9,0xffec,0xffd6,0xfff7,0x0000,0x0003,
+0xfff7,0x0019,0xfff4,0x000a,0xfff4,0x0012,0x0002,0x0018,
+0x0013,0x000d,0x002e,0x0013,0xfffb,0x0016,0xfff6,0x0000,
+0xfff8,0xfff5,0xfff8,0xfff7,0x0011,0xfff5,0xfff9,0xfff8,
+0xfffd,0xffed,0xfff7,0xffe6,0x0008,0xffe6,0x000a,0xffe8,
+0x0000,0xffe4,0xfffb,0xffdf,0xffde,0xffef,0x0002,0x0014,
+0x0001,0x0016,0x0000,0x000a,0xfffa,0x000e,0x0003,0x000a,
+0x0014,0x0004,0x0020,0x0004,0xfff9,0x000f,0x0000,0x0003,
+0x0000,0x000d,0x0009,0x0000,0x0003,0x0004,0xffef,0x0000,
+0xffdd,0xfff1,0x000f,0xfffa,0x0004,0xffff,0x001b,0x000c,
+0x0005,0xfff8,0xfff1,0xffed,0xffdb,0x000b,0xfff0,0x0002,
+0xffec,0x000c,0xffe9,0xfffe,0xffea,0x0001,0x0001,0x000b,
+0x0005,0x000d,0x0022,0x000e,0xfff8,0x000e,0xfffc,0xffe6,
+0x0000,0xfff5,0x0010,0x000e,0x001d,0x0002,0x0011,0x0003,
+0xfff3,0xffe5,0x0003,0xffe8,0x0001,0xffed,0x000e,0xfffd,
+0xfff7,0xffec,0xfff4,0xffdf,0xffe3,0x0003,0xfff1,0x0014,
+0xfff7,0x0009,0xfff5,0xfffd,0xfff0,0xfffe,0x0002,0xfffe,
+0x0007,0x0003,0x0014,0x0000,0xfff6,0x0007,0x0007,0xffea,
+0x0007,0x000d,0x0021,0x0017,0x000e,0x0012,0x0007,0x000c,
+0xffef,0xfff8,0x0008,0x0004,0xfffc,0xfff6,0x0006,0xfffb,
+0x0004,0xfffb,0x0006,0x0006,0xffec,0x000a,0x0009,0xfff7,
+0xfffc,0x0002,0xfff0,0xfff9,0xffff,0x000c,0x0011,0x0010,
+0x0027,0x0009,0x0024,0x000c,0x0002,0x0003,0xfffa,0x0015,
+0xffff,0xfff5,0x0007,0xfff6,0x000b,0xffec,0xffec,0xfff5,
+0x0004,0xffec,0xfffd,0xfff3,0xfff8,0xffe4,0xfffa,0xffeb,
+0xfff6,0xfff0,0x0008,0xfff9,0xfff4,0x0003,0x000b,0x0007,
+0x0005,0x0000,0xfffc,0xfff8,0x0004,0x0008,0x0012,0x0003,
+0x0029,0x0000,0x0016,0xfffe,0x0000,0xfffc,0x0005,0x0019,
+0x0006,0x000e,0x0019,0xffff,0xfffe,0xfffc,0xffe3,0xfffe,
+0xffe5,0xfff0,0x0015,0x0006,0xfff4,0xfffd,0x0009,0x0010,
+0xfffd,0x0002,0xffff,0x0007,0xfff1,0x001f,0xfff9,0xfff6,
+0xfff0,0xfff7,0xffe5,0xffeb,0xfff5,0xfffb,0x0010,0x0003,
+0x001a,0x0009,0x0018,0x0007,0x0000,0xfffc,0x0000,0xfffc,
+0x0006,0xfff5,0x0020,0x000e,0x0017,0xfffa,0x0005,0x0001,
+0xfffb,0xffe3,0x0009,0xfff5,0xfff1,0xffea,0xfffd,0x0000,
+0xffee,0xfff8,0x0001,0xfffa,0xfff9,0x0017,0xfffa,0x0006,
+0xfffb,0xfff4,0xfff1,0xffeb,0xfffb,0xfff8,0x0011,0xfff7,
+0x001c,0x0000,0x000b,0xfffa,0xfffe,0xfff4,0x000b,0x0000,
+0x000e,0x000d,0x0031,0x0016,0x0008,0x0009,0xfffc,0x0009,
+0xffdb,0x000c,0x0009,0x0007,0x0011,0x000b,0x001a,0xffee,
+0x0019,0xfff4,0xffed,0xffef,0xffd3,0xfff2,0xffef,0x0000,
+0xffef,0x001e,0xffff,0x0016,0x000a,0x0019,0x000c,0x0026,
+0x0012,0xfffd,0x0016,0xfffc,0xfffd,0x0000,0xfff3,0x0003,
+0xfff6,0x000b,0xffe9,0xfffe,0x000a,0xfff9,0xfffb,0xfff9,
+0xfff1,0x0000,0xfffe,0xfff6,0x000d,0xfff9,0x000e,0xffdd,
+0x000a,0xffe9,0xfff0,0xffe1,0xffdb,0xffeb,0xfff0,0x0011,
+0xfffa,0x001a,0x000a,0x0015,0x0010,0x0015,0x000d,0x0019,
+0x0013,0xfff3,0x0008,0xffed,0xfffb,0xfff9,0xffff,0x0008,
+0xfffe,0x0024,0xfffb,0x0006,0xfffd,0x0008,0xfff1,0x0001,
+0xffd0,0x0004,0x0017,0x0009,0x0009,0x0011,0x001e,0x0002,
+0x0010,0xfffd,0xffe6,0xfff0,0xffd8,0x0006,0xffdd,0xffff,
+0xffe4,0x0011,0xfff4,0x0009,0x0000,0x0008,0x000b,0x0019,
+0x0005,0xfffd,0x000a,0xfff8,0xfffa,0xfff9,0xfffa,0xffea,
+0xffff,0x000b,0x0001,0x0015,0x0016,0x0007,0x0013,0x0005,
+0xffe6,0xfff9,0x000b,0xfff8,0x0005,0xffff,0x0011,0xfff2,
+0x0001,0xfff1,0xffe8,0xffe2,0xffe0,0xffff,0xffdf,0x0010,
+0xffee,0x000e,0x0000,0x0008,0x0006,0x0004,0x000c,0x000c,
+0x0006,0xfff3,0xfffe,0xffe9,0xfff8,0xfff1,0x0004,0xffef,
+0x0005,0x0024,0x0012,0x001e,0x0008,0x0016,0x000a,0x000e,
+0xffe2,0x000b,0x000f,0x0014,0x0000,0x0008,0x0009,0xfff1,
+0x000f,0x0000,0xfffb,0x0009,0xffe9,0x0006,0xfff8,0xfff3,
+0xfff3,0x0007,0xfffb,0x0003,0x0014,0x0013,0x001b,0x001f,
+0x0027,0xfff9,0x000d,0xfff5,0x0004,0xffed,0xfff8,0x0019,
+0xfffd,0x000b,0xfff9,0xfffe,0x0004,0xfff0,0xffee,0xfff7,
+0xfff8,0xffff,0x0003,0x0002,0xfffd,0xfff6,0xfffd,0xffe0,
+0x0001,0xfff4,0xfffe,0xfffc,0xfff1,0xffff,0xfff9,0x0003,
+0xfffe,0x0004,0x0006,0x0003,0x001a,0x000f,0x001d,0x0011,
+0x0028,0xffef,0x0000,0xffe6,0x0002,0xffe5,0x0002,0x001d,
+0x0004,0x0024,0x000a,0x0006,0xfff7,0x0000,0xffe5,0x0000,
+0xffd8,0x0002,0x001d,0x0016,0xfff9,0x000e,0x000c,0x0005,
+0x0007,0x0007,0xfff4,0x0009,0xffee,0x001a,0xffe6,0xfff2,
+0xffe8,0xfffc,0xfff0,0xfff7,0x000a,0x0002,0x001a,0x0012,
+0x001a,0xfff9,0x0001,0xfff1,0x0001,0xffe5,0xfffe,0x0000,
+0x0004,0x000b,0x0011,0x0015,0x0010,0xffff,0x0007,0x0003,
+0xffee,0xfff7,0x0011,0x0004,0xfff5,0xfffd,0x0000,0xfff5,
+0xfff9,0xfffc,0xfff6,0xfffd,0xfff6,0x0012,0xffe8,0x0003,
+0xfff2,0xfff9,0xfffc,0xfff6,0x0010,0xffff,0x001b,0x0004,
+0x001b,0xffef,0xfff4,0xffe2,0x0000,0xffdd,0x0009,0x0003,
+0x000c,0x0024,0x0023,0x001e,0x0002,0x000d,0xfffe,0x000b,
+0xffbe,0xfff8,0xffe9,0xfff5,0x000e,0x0005,0x0011,0x0010,
+0x0013,0x0002,0x0003,0xfffb,0xffee,0xffef,0x000a,0x0000,
+0xffff,0x0017,0xfffa,0x0014,0xfff1,0x0012,0xfff2,0x0016,
+0x0005,0x000a,0x002c,0x0017,0x0002,0x001a,0xfff7,0x0003,
+0xfffc,0xfff2,0xfff4,0xffe3,0xfff9,0xfff0,0xfff9,0xffee,
+0xffd4,0xffec,0xffde,0xffe3,0x000a,0xfff3,0x0004,0x0000,
+0x0004,0xfff7,0x0005,0xffed,0xfff6,0xffe8,0x000b,0x0011,
+0x0008,0x0014,0x0005,0x0013,0xfff7,0x000e,0xfff4,0x0009,
+0x0006,0x0000,0x001e,0x0009,0x0000,0x0013,0x0002,0x0007,
+0x0002,0x000a,0x0005,0xffec,0xffeb,0xffff,0xffef,0xfff7,
+0xffb3,0xfff0,0xfff7,0xfff7,0x0006,0x000b,0x0015,0x0025,
+0x000a,0x000a,0xfffc,0xfffb,0xfff3,0x0003,0xfff9,0x0000,
+0xfff3,0x000b,0xffef,0x0006,0xffe7,0x0001,0xfff1,0x0009,
+0xfff9,0x0009,0x0020,0x0013,0x0000,0x0012,0xfffe,0xffea,
+0x0003,0xfff1,0x000c,0xfffb,0x0004,0xfffe,0x0011,0xfffb,
+0xffc9,0xffe4,0xffeb,0xffe5,0x0002,0xfff9,0x0008,0x0014,
+0xfffc,0xffff,0xffff,0xffee,0xfffb,0xfffc,0xfffb,0x0010,
+0xfffe,0x0008,0xfffb,0x0005,0xffed,0xfffe,0xfff2,0xfffd,
+0xfffa,0x0000,0x0012,0x0004,0xfffe,0x000b,0x0008,0xffee,
+0x000b,0x000a,0x001d,0x0003,0xfff6,0x000d,0x0008,0x0003,
+0xffc6,0xfff7,0xfff0,0x0001,0xfffe,0x0002,0x0000,0x0013,
+0x000a,0x000d,0x0011,0x0015,0x0003,0x0003,0x0013,0xfff4,
+0x0002,0x0000,0xfff6,0x0001,0xfffb,0x000c,0x0000,0x000f,
+0x001a,0x0005,0x0022,0x0010,0x000b,0x0007,0xfffc,0x0019,
+0x0002,0xfff2,0x0003,0xffe3,0xfff3,0xffe7,0xffec,0xffec,
+0xffdc,0xffeb,0xffe4,0xfff0,0xfffa,0xfff0,0xfff4,0x0002,
+0xfffc,0x0002,0x0014,0x0007,0x000b,0xfffc,0x0014,0x0004,
+0x000c,0xfffe,0x0001,0x0000,0x0000,0x0008,0x0002,0x0002,
+0x001b,0xfffc,0x0015,0x0002,0x0009,0x0000,0x0006,0x001d,
+0x0009,0x000a,0x0015,0xffeb,0xffe4,0xfff6,0xffe3,0xfff5,
+0xffbb,0xffef,0xfffd,0x0003,0xfff6,0x0008,0x0003,0x0028,
+0x0001,0x0015,0x000a,0x0015,0x0008,0x0017,0x0001,0xfff3,
+0xfff8,0xfff5,0xffeb,0xfff5,0xfff1,0xfffc,0x0000,0x0002,
+0x000d,0x0005,0x0017,0x000c,0x0007,0x0000,0x0001,0x0000,
+0x000a,0xfff2,0x001c,0xfffb,0xffff,0xfff5,0x0005,0xfff9,
+0xffd1,0xffe2,0xfff1,0xfff2,0xfff2,0xfff7,0xfff7,0x0017,
+0xfff3,0x000a,0x000c,0x0007,0x0010,0x000f,0x0003,0x0003,
+0x0001,0xfff2,0xfff7,0xfff4,0xfff7,0xfff8,0x0000,0xfff6,
+0x000e,0xfffc,0x0009,0xfffe,0x0005,0xfff8,0x000d,0x0003,
+0x0012,0x000a,0x002d,0x0003,0xfff0,0x0004,0xfffc,0x0000,
+0xffb1,0x000b,0xfff1,0x0004,0x0012,0x0017,0x0014,0x0005,
+0x001e,0x0007,0xfff9,0xfffe,0xffeb,0xffeb,0xfff8,0xfffd,
+0xfff6,0x001c,0x0004,0x001f,0x0006,0x0019,0xfffd,0x0025,
+0x0004,0xfff9,0x0014,0x0000,0x0004,0x0004,0xfff5,0x0007,
+0xfffa,0x0008,0xffe5,0xffea,0xfff2,0xfff4,0xfffb,0xfff0,
+0xffc7,0x0000,0xffe5,0xfff3,0x000e,0x0005,0x0007,0xfff5,
+0x000f,0xfffc,0xfffb,0xfff0,0xfff3,0xffe3,0xfffa,0x000d,
+0x0000,0x0019,0x0010,0x001f,0x000c,0x0016,0xfffe,0x0017,
+0x0006,0xfff0,0x0007,0xfff2,0x0002,0xfffd,0x0000,0x000c,
+0x0000,0x0021,0xfff7,0xfff3,0xffe4,0x0003,0xfff2,0xfff9,
+0xffa6,0x0003,0xfffe,0x0006,0x000a,0x001d,0x0018,0x001a,
+0x0015,0x000f,0xfff1,0xfffe,0xfff0,0xffff,0xffe7,0xfffc,
+0xffeb,0x0010,0xfffa,0x0012,0xfffd,0x0008,0xfffb,0x0018,
+0xfff8,0xfff9,0x0009,0xfffc,0x0001,0xfffd,0xfffb,0xffee,
+0x0001,0x0007,0xfffe,0x0001,0xfffe,0x0001,0x0013,0xfffd,
+0xffbd,0xfff8,0xfff2,0xfff5,0x0007,0x000b,0x000b,0x0009,
+0x0007,0x0003,0xfff3,0xfff0,0xfff8,0xfff7,0xffe8,0x000c,
+0xfff6,0x000d,0x0005,0x0011,0x0002,0x0004,0xfffd,0x000a,
+0xfffa,0xffef,0xfffc,0xffed,0x0000,0xfff5,0x0006,0xfff3,
+0x0009,0x0021,0x000e,0x000a,0xfff0,0x0011,0x000a,0x0004,
+0xffb9,0x000a,0xfff7,0x0011,0x0001,0x0014,0x0003,0x0008,
+0x0015,0x0012,0x0006,0x0018,0x0000,0xffff,0x0000,0xfff0,
+0xfffa,0x0005,0x0000,0x000d,0x0011,0x0013,0x000b,0x001d,
+0x0019,0xfff5,0x000b,0xfffa,0x000d,0xfff1,0xfff9,0x001d,
+0x0000,0x0008,0xfff5,0xffea,0xffec,0xffeb,0xffef,0xffee,
+0xffcf,0xfffe,0xffeb,0x0000,0xffff,0x0002,0xfff7,0xfff8,
+0x0006,0x0006,0x0008,0x000a,0x0008,0xfff7,0x0002,0x0000,
+0x0004,0x0002,0x000d,0x000c,0x0017,0x000f,0x000c,0x0010,
+0x001a,0xffeb,0xfffe,0xffeb,0x000b,0xffe9,0x0004,0x0021,
+0x0007,0x0021,0x0006,0xfff3,0xffde,0xfffb,0xffe5,0xfff6,
+0xffae,0x0001,0x0004,0x0013,0xfffa,0x001b,0x0006,0x001d,
+0x000c,0x001a,0xffff,0x0018,0x0005,0x0012,0xffef,0xffef,
+0xffef,0xfffa,0xfff6,0x0000,0x0007,0x0002,0x0009,0x0010,
+0x000c,0xfff5,0x0000,0xfff5,0x0009,0xffe9,0x0000,0x0003,
+0x0008,0x0008,0x000d,0x0001,0xfff8,0xfff9,0x0007,0xfffa,
+0xffc4,0xfff6,0xfff9,0x0001,0xfff7,0x0008,0xfffa,0x000d,
+0xfffe,0x000f,0x0001,0x000a,0x000d,0x000b,0xfff1,0x0000,
+0xfffa,0xfff7,0x0001,0x0000,0x000d,0xffff,0x000b,0x0003,
+0x000d,0xffeb,0xfff3,0xffe6,0x0007,0xffe1,0x000a,0x0007,
+0x0010,0x0021,0x001f,0x000a,0xffea,0x0008,0xffff,0x0002,
+0xfffd,0x0007,0xfffb,0xfffb,0x0008,0xfffe,0x0011,0xfff7,
+0x0012,0xffe8,0xfffe,0xffed,0xfff6,0xfffc,0x001c,0x0011,
+0x0005,0x001c,0xfffe,0x0007,0xfffc,0x000f,0x0007,0x0008,
+0x0006,0x0017,0x000d,0x0015,0xfff2,0x0014,0xffef,0xffee,
+0xfff5,0xffdf,0xffe2,0xfff5,0x0017,0xfff3,0xfffb,0xfff7,
+0x0012,0xfffc,0xffef,0xffe9,0x0004,0xffec,0x0004,0xffe6,
+0x0003,0xffdc,0x0000,0xffe0,0xfffe,0xfff4,0x001d,0x0022,
+0x0010,0x0018,0x000a,0x0006,0x0000,0x000c,0x0008,0xfffc,
+0x0008,0x000d,0x0000,0x0006,0xfff0,0x000c,0xfffb,0xfff3,
+0xfffd,0xfff9,0xfff3,0xfffd,0x0008,0x0002,0xfff2,0x0000,
+0xfff3,0x0000,0x0008,0xfffd,0x0000,0x0004,0x0015,0x000b,
+0x0009,0xfff0,0xfff6,0xffee,0xfffb,0x0010,0x000a,0x0010,
+0xfffb,0x000f,0xfff3,0xfffb,0xfff1,0xffff,0x0006,0xfffc,
+0xfffa,0x0017,0x0002,0x0010,0xffef,0x000c,0xfff6,0xffd4,
+0xfffd,0xffdf,0xfffa,0x000c,0x0022,0x0001,0x0014,0x0003,
+0x0008,0xfff4,0xfffd,0xffeb,0xfffd,0xfff2,0x0008,0xfffb,
+0xfffc,0xffe4,0xfff9,0xffe0,0x0002,0x0008,0x000c,0x0022,
+0x0004,0x000c,0xffff,0xfffa,0xfff7,0xfffc,0x0007,0xffef,
+0xfffc,0x000d,0xfff5,0x0001,0xffed,0x0004,0x0000,0xffd9,
+0x0004,0xfff9,0x000b,0x0015,0x0014,0x0010,0x000a,0x000b,
+0x0004,0x0006,0x0000,0x0007,0xfff8,0xfffc,0x0000,0xfffa,
+0x0009,0xfff3,0x000b,0x0007,0x000b,0x000f,0x0025,0x0004,
+0x0009,0x0005,0xfffb,0xfff5,0x0005,0x0009,0x0016,0x0001,
+0x001b,0x0012,0x0004,0x000e,0xfffb,0x0000,0xfff4,0x0003,
+0xfffc,0xffe0,0xfff2,0xfff4,0x0011,0xffea,0xffef,0xfff5,
+0x001a,0xfffa,0xfff5,0xfff6,0xfff4,0xffe9,0xfff4,0xffe9,
+0xfffb,0xffe8,0x000d,0xfffb,0x0013,0x0008,0x0026,0x0015,
+0x0014,0x0002,0x0006,0xfff4,0x000b,0x0005,0x0017,0xfff5,
+0x001d,0x0009,0xfff7,0x0000,0xfff9,0xfffa,0xffff,0x0007,
+0x0002,0xfff9,0x0003,0xfffd,0x0002,0xfffa,0xffe5,0xfffd,
+0xfffa,0xfffe,0x000e,0x0009,0xfff0,0x0001,0x0003,0x000e,
+0x0000,0xfffb,0x0003,0x0008,0x0010,0x0024,0x0013,0x0003,
+0xffff,0xfffa,0xffef,0xffe8,0xfffc,0xfff9,0x0015,0xfff5,
+0x000e,0x0012,0xfff9,0x0009,0xfff7,0xfff9,0xfffa,0xffea,
+0x0003,0xffdf,0x000a,0x000b,0x001c,0xfff9,0x0007,0x0000,
+0x0010,0xfff2,0x0002,0xfff8,0xffec,0xffef,0xfff7,0xfffe,
+0xfff2,0xfff0,0x0006,0xfffb,0x0018,0x001c,0x0015,0x0014,
+0x0008,0xfff7,0xfffc,0xffe7,0x0001,0xfff5,0x0016,0xffe8,
+0x000f,0x0008,0xffeb,0xfffb,0xfff5,0xfff2,0x0005,0xffee,
+0x000b,0xfff9,0x001b,0x0014,0x000e,0x0007,0xffff,0x0009,
+0xfff0,0x001b,0x0002,0x000a,0x000d,0x0010,0x0014,0xffec,
+0x001d,0xffec,0xfff2,0xfff0,0xfff3,0xfff8,0x0009,0x000d,
+0xfffe,0x0021,0x0009,0x0013,0x0011,0x0017,0x0011,0x0016,
+0x0006,0x0006,0xfff7,0xfffe,0xfff4,0xfffe,0xffec,0xfff3,
+0xfff3,0xfff6,0xffd3,0xfffc,0x0010,0xfff8,0xfffe,0xfff9,
+0x0005,0x000f,0xfff7,0xfff9,0x0009,0xfffe,0x0008,0xffdb,
+0x000e,0xffe1,0xfff5,0xffe3,0xfffb,0xfff0,0x000b,0x001e,
+0x0007,0x001d,0x0015,0x0012,0x0017,0x0013,0x0012,0x0009,
+0x0007,0xfffd,0xffe9,0xffef,0xfff2,0xfff7,0xfff8,0xfff7,
+0xfffa,0x000f,0xffe5,0x0004,0x0002,0x0006,0xfff4,0x0001,
+0xffe6,0x0013,0x000f,0x000c,0x0005,0x0016,0x0018,0x0000,
+0x0015,0xfff4,0xffeb,0xfff1,0xfff8,0x000b,0xfff9,0x000c,
+0xfff2,0x0014,0xfffe,0x0006,0x0007,0x0006,0x0010,0x0009,
+0xfffa,0x0005,0xffeb,0xfff9,0xfff1,0xfff6,0xfff3,0xffd9,
+0xfffb,0xfff6,0xffec,0x0013,0x001c,0x0005,0x0016,0x0005,
+0xfffc,0x0006,0x0003,0xfffb,0x0001,0x0004,0x000b,0xfff0,
+0x0006,0xffe9,0xffed,0xffe3,0x0000,0x0003,0xfffa,0x001e,
+0xfffd,0x0011,0x000a,0x0005,0x000d,0x0002,0x0011,0xfffd,
+0xfffb,0xfffd,0xffdd,0xffeb,0xffef,0xffef,0xfffe,0xffdd,
+0x0002,0x000f,0xfffd,0x001c,0x000d,0x0015,0x000d,0x000d,
+0xfff8,0x0019,0x0008,0x0017,0xfffd,0x000d,0x0003,0xffef,
+0x0014,0xfff8,0x0000,0x000a,0x0008,0x000b,0x0012,0x0000,
+0x0001,0x000a,0x0005,0x0000,0x001c,0x0011,0x0020,0x000f,
+0x001a,0x0001,0xffed,0xfff7,0xfffd,0xffeb,0xfff1,0x0007,
+0xfffa,0xfff7,0xffe3,0xfffb,0x000a,0xffef,0xfff1,0xfff7,
+0x000d,0x000d,0xfffd,0x0005,0xfff9,0xfffc,0xfff7,0xffde,
+0x0005,0xffec,0x0002,0xfffd,0x0010,0x0003,0x0014,0x0011,
+0x000b,0x0007,0x0011,0x0000,0x0022,0x000d,0x0021,0x0002,
+0x001c,0xfff8,0xffe0,0xffe8,0xfffb,0xffe3,0xfffd,0x000c,
+0x0000,0x000f,0xfff5,0x0003,0xfffd,0xfffe,0xffe8,0xffff,
+0xffee,0x0011,0x0015,0x0019,0xfff5,0x0013,0x0006,0x0003,
+0x000b,0x0000,0xfff9,0x000b,0x000d,0x001f,0x0001,0x0000,
+0xfff7,0xffff,0xfffb,0xfff4,0x0012,0x0000,0x001f,0x0002,
+0x000d,0x0001,0xffe2,0xfff2,0xfff9,0xffe3,0xfff7,0xffee,
+0x0001,0xfff6,0xfffc,0x0012,0x0016,0xfffd,0x000a,0x0002,
+0x0003,0x0005,0x0009,0x0007,0xfff1,0x0001,0xfffb,0xfff3,
+0xfffe,0xfff4,0xfffb,0xfffe,0x0015,0x0017,0x0002,0x0010,
+0x0000,0xfffb,0x0006,0xfff3,0x0017,0xfffd,0x0020,0xfff6,
+0x000f,0xfff8,0xffd4,0xffe4,0xfff7,0xffdb,0x0002,0xfff3,
+0x0009,0x000f,0x000c,0x001b,0x0007,0x000c,0x0000,0x000b,
+0xffd4,0x0006,0xffe2,0xfff8,0x0009,0x000a,0x000b,0x000e,
+0x0017,0xfffb,0x0008,0xfffc,0x000e,0xfff4,0x0025,0x000e,
+0x000c,0x001a,0x0004,0x0010,0xfff8,0x0010,0xfff7,0x0007,
+0xfffa,0x0013,0x000c,0x0019,0xfffb,0x0018,0xfff1,0xfff3,
+0xfff8,0xffdc,0xffde,0xffe1,0xffff,0xffee,0xfffc,0xffee,
+0xffea,0xfffb,0xffd6,0xffe6,0x0006,0xfff8,0xffff,0xfffe,
+0x0009,0xffef,0x000a,0xffee,0x0015,0xffed,0x0027,0x001f,
+0x0017,0x0017,0x0010,0x000f,0xfffe,0x000c,0xfff9,0xfffa,
+0xfffb,0x0009,0xffff,0x000a,0xfff9,0x0010,0xfffc,0xfff7,
+0x0000,0xfff6,0xffef,0xffea,0xfff0,0xfffe,0xfff2,0xfff7,
+0xffc9,0xffff,0xffef,0xfffa,0x0001,0x0010,0x000f,0x0023,
+0x000f,0x0002,0x0000,0xfffc,0x0013,0x0008,0x0014,0x000d,
+0x0001,0x000e,0xfff9,0x0003,0xffee,0x0000,0xfff6,0xfffb,
+0xffed,0x0013,0x0000,0x0015,0xfff8,0x0010,0xfff7,0xffd9,
+0x0000,0xffdc,0xfff6,0xfff9,0x0009,0xfffc,0x0014,0xfffb,
+0xffdf,0xfff3,0xffe3,0xffe8,0xffff,0xffff,0x0002,0x0012,
+0x0000,0xfff7,0x0003,0xffef,0x001b,0x0000,0x0015,0x001e,
+0x000c,0x000b,0x0005,0x0002,0xfff4,0xfffc,0xfff7,0xffed,
+0xffee,0x0009,0xfff3,0x0006,0xfff5,0x0008,0x0002,0xffdd,
+0x0008,0xfff6,0x0007,0x0001,0xfffc,0x000b,0x000a,0x0002,
+0xffdc,0x0005,0xffe8,0x0004,0xfff9,0x0007,0xfffa,0x0011,
+0x000e,0x0005,0x0016,0x0016,0x0023,0x0008,0x002e,0x0001,
+0x0011,0x0003,0x0000,0xfffe,0x0002,0x000a,0x0005,0x0000,
+0x000e,0x000f,0x0002,0x0012,0x0002,0x0004,0xfff5,0x0007,
+0xffff,0xffdc,0xffee,0xffe0,0xfff9,0xffe5,0xffef,0xffec,
+0xfff2,0xfff9,0xffdc,0xfff3,0xfff6,0xfff6,0xffee,0x0000,
+0x0000,0xfffb,0x0019,0x0008,0x002b,0x0000,0x0030,0x0012,
+0x001b,0x0000,0x000c,0xfffd,0x0007,0x0006,0x0007,0xfff3,
+0x000f,0x0005,0xfff5,0x0003,0x0000,0xfffe,0x0000,0x000c,
+0x0006,0xfff6,0x0000,0xffe9,0xffea,0xfff5,0xffe6,0xfff4,
+0xffd1,0xfffd,0xfff5,0x0006,0xfff1,0x000d,0xfffe,0x0026,
+0x0006,0x000d,0x000f,0x0016,0x0028,0x001c,0x001c,0x0000,
+0x0005,0xfff8,0xfff6,0xfff1,0xfff9,0xfff9,0x0004,0xfff3,
+0x0001,0x000e,0xfff7,0x000e,0x0000,0xfffe,0xfffc,0xffee,
+0x0007,0xffdc,0x0006,0xfff8,0x0003,0xfff3,0x0007,0xfff8,
+0xffe7,0xfff1,0xffea,0xfff5,0xffee,0xfffc,0xfff1,0x0016,
+0xfff8,0x0002,0x0011,0x0009,0x0030,0x0014,0x001e,0x0011,
+0x0010,0xfff5,0x0001,0xfff0,0xfffe,0xfff6,0x0005,0xffe6,
+0x0002,0x0004,0xffea,0x0000,0xfffe,0xfff6,0x0006,0xfff3,
+0x000e,0xfff6,0x0017,0x0000,0xfff6,0x0002,0xffff,0x0000,
+0xffc7,0x001a,0xffea,0x0007,0x000e,0x001c,0x000e,0x0003,
+0x0023,0x0000,0xfffd,0xffff,0x000b,0xfff0,0x0012,0x000a,
+0x0004,0x001f,0x000f,0x001c,0x000e,0x0017,0x0001,0x0015,
+0xfff9,0x0002,0xfff5,0x0001,0xfffd,0x0001,0xffee,0xfff7,
+0xfff6,0xfff3,0xffcf,0xffe8,0xfff8,0xfff2,0xfffe,0xfff0,
+0xffdd,0x000e,0xffde,0xfff6,0x000a,0x000a,0x0001,0xfff4,
+0x0014,0xfff4,0x0000,0xfff1,0x0012,0xffe8,0x0014,0x001b,
+0x000e,0x001c,0x001b,0x001b,0x0014,0x0013,0x0002,0x0008,
+0xfffb,0xfff9,0xffe7,0xfff3,0xfffb,0xfffb,0xfffa,0xfffb,
+0xfffe,0x000c,0xffe1,0xfff1,0xffe9,0x0001,0xfff4,0xfff8,
+0xffbc,0x0012,0xfff7,0x0009,0x0006,0x0023,0x0012,0x0019,
+0x001a,0x0007,0xfff6,0xffff,0x0010,0x0003,0x0001,0x0009,
+0xfffa,0x0013,0x0004,0x000f,0x0004,0x0006,0x0000,0x0008,
+0xffec,0x0002,0xffe9,0xfffe,0xfff9,0xfffb,0xfff4,0xffdd,
+0xffff,0xfff3,0xffe8,0x0000,0x0003,0x0000,0x0016,0xfffc,
+0xffd2,0x0006,0xffeb,0xfff8,0x0002,0x0010,0x0005,0x0008,
+0x000b,0xfffc,0xfff8,0xfff1,0x0018,0xfffc,0x0002,0x001a,
+0x0003,0x0010,0x0010,0x000e,0x0009,0x0002,0x0001,0xfffc,
+0xffed,0xfff9,0xffdc,0xffef,0xfff7,0xfff3,0x0000,0xffe1,
+0x0005,0x000c,0xfff9,0x0008,0xfff5,0x000f,0x000d,0x0004,
+0xffcf,0x0018,0xfff0,0x0014,0xfffe,0x001a,0xfffe,0x0007,
+0x0019,0x000a,0x000b,0x0019,0x0020,0x0003,0x001b,0xfffe,
+0x0008,0x0008,0x000b,0x0009,0x0018,0x0011,0x0010,0x000e,
+0x000d,0xfffe,0xffec,0xfffb,0x0004,0xffef,0xfff2,0x000c,
+0xfffd,0xfff3,0xffdf,0xffe7,0xfff2,0xffe9,0xfff1,0xffed,
+0xffe5,0x000c,0xffe4,0x0002,0xfffa,0x0007,0xfff1,0xfff7,
+0x000b,0xffff,0x000d,0x000b,0x0028,0xfffc,0x001d,0x000e,
+0x0013,0x0005,0x0017,0x0008,0x001e,0x000d,0x0011,0x0000,
+0x000e,0xfff4,0xffde,0xffec,0x0002,0xffe7,0xfffe,0x0010,
+0x0004,0x000c,0xfff1,0xfff0,0xffe3,0xfff9,0xffe8,0xfff6,
+0xffc4,0x0010,0xfffd,0x0016,0xfff6,0x0020,0x0000,0x001c,
+0x0011,0x0012,0x0003,0x0019,0x0025,0x0017,0x000a,0xfffd,
+0xfffe,0xfffd,0x0000,0xfffd,0x000e,0x0000,0x000e,0x0001,
+0x0000,0xfffe,0xffe0,0xfff7,0x0001,0xffe7,0xfff9,0xfff3,
+0x0005,0xfff3,0xfff8,0xffff,0xfffe,0xfff8,0x000a,0xfffa,
+0xffda,0x0004,0xfff1,0x0004,0xfff2,0x000d,0xfff4,0x000b,
+0x0002,0x0006,0x0006,0x000b,0x002d,0x0010,0x000b,0x000d,
+0x0007,0xfffa,0x000c,0xfffc,0x0014,0xfffd,0x0010,0xfff4,
+0x0001,0xfff4,0xffd2,0xffe8,0x0000,0xffdf,0x0003,0xfff7,
+0x000c,0x000c,0x0008,0x0007,0xffef,0x0006,0x0000,0x0002};
+
+static const signed short etable2[5120]={
+0x0049,0xffe0,0xffc4,0xfff1,0xffe6,0x003b,0x0002,0xffdf,
+0x001e,0xfff6,0xfffd,0xffef,0x0008,0x001e,0xffff,0xffe6,
+0xfffc,0xffea,0x000a,0x0010,0xffdc,0xfffb,0xfff5,0x0038,
+0x0025,0x0006,0xfff6,0xfffb,0xfff3,0xfffd,0x0006,0xfffb,
+0x000b,0x0004,0xffed,0xfffb,0xfff0,0x0029,0x0018,0x000d,
+0x0004,0xfff5,0xffdb,0x0017,0xfffb,0x002e,0xfffe,0xffe3,
+0xfffb,0xffd9,0xffeb,0xfff7,0x0000,0x0031,0x000c,0xfff7,
+0xfff0,0xffe6,0x0016,0x000f,0xffd3,0xffec,0xfffb,0x0028,
+0x0016,0x0011,0xffe6,0x001f,0xfff2,0x0002,0xfff2,0x000a,
+0x001e,0x0014,0xffe5,0xfff7,0xffd9,0x0027,0x0012,0x0005,
+0x0022,0xffe7,0xffd0,0xffe4,0xfff5,0x0022,0xfffe,0xffd7,
+0x0009,0xfff9,0xffef,0x0015,0x0014,0x0018,0xffef,0xffdf,
+0x0000,0xffe8,0x000a,0x002a,0x0003,0xfffb,0x000a,0x002a,
+0x000b,0x0008,0xfffd,0x0003,0x0010,0x0009,0x0016,0xfffe,
+0x0000,0xffdf,0xfff6,0x0012,0x0007,0x003a,0x000a,0x001c,
+0xffde,0xfffc,0xffe7,0x000a,0x0009,0x0015,0xfff9,0xffdc,
+0xffe6,0xffdc,0xffdd,0x001c,0x000c,0x002a,0xfffd,0xfff0,
+0xfff4,0xffe4,0x0015,0x002a,0xfffb,0xffeb,0x0010,0x001a,
+0xfffc,0x0013,0xffed,0x0027,0x000f,0x000f,0x0001,0x000d,
+0x0013,0xffef,0xffef,0x000e,0xfff1,0x0037,0x0004,0x0013,
+0x001c,0xffec,0xffcd,0xfff2,0xfffa,0x0007,0x0000,0xffe6,
+0x001b,0xfffc,0x0012,0xffd8,0xfffa,0x0010,0xffff,0xfff1,
+0x0000,0xffc9,0xfffb,0xfff0,0xffed,0x000e,0xfffd,0x0031,
+0x000e,0x0001,0xffea,0xffe2,0xfff4,0x0000,0x0018,0x000f,
+0x0009,0xffef,0xffd3,0xffe3,0x0004,0x001c,0x0033,0x0023,
+0xffd8,0x0000,0xffe4,0x0018,0x000e,0xfffb,0xfffc,0xffeb,
+0xfff9,0xffdf,0x0000,0xffe0,0xfff1,0x0023,0x000c,0x0001,
+0xfff5,0xffc6,0x0005,0xfff0,0xffe4,0x0000,0x0001,0x0021,
+0x0000,0x000b,0xffd9,0x0005,0xfff2,0x0006,0x0003,0x001f,
+0x001c,0xffff,0xffcb,0xffdf,0xffed,0x0019,0x002e,0x001a,
+0xfff5,0xfff2,0xffd9,0xffe5,0x0009,0xffef,0xfffc,0xffdf,
+0x0006,0x0000,0x0004,0xffff,0x0005,0x000a,0xffef,0xffea,
+0x0005,0xffc7,0xfffb,0x0009,0x0014,0x000d,0x0012,0x0023,
+0xfff5,0x0003,0xfff0,0xffea,0x0011,0x000d,0x0028,0x0013,
+0xffff,0xffc9,0xffdd,0xfffb,0x001b,0x002c,0x0025,0x0031,
+0xffb0,0x0006,0xfff0,0x000b,0x001e,0xffe2,0xfff7,0xffe4,
+0xffe4,0xffe3,0xfff3,0x0006,0xfffe,0x001c,0xfffd,0xfffb,
+0xfff9,0xffc4,0x0005,0x0009,0x000b,0xffff,0x0018,0x0013,
+0xffe5,0x000d,0xffe0,0x000d,0x000f,0x0013,0x0013,0x0023,
+0x0011,0xffd9,0xffd5,0xfff7,0x0004,0x002a,0x0020,0x0029,
+0x004e,0xffeb,0xffd5,0x0004,0xffda,0x0011,0x0011,0xfffb,
+0x0037,0x0018,0xfff1,0xffdc,0x000e,0x0004,0x0018,0xffe8,
+0x000c,0x0005,0x0011,0x001f,0xffca,0xfffb,0xfffe,0x001b,
+0x002b,0xfff4,0x0002,0x0009,0xfff7,0xfff1,0x0016,0xfffd,
+0x001c,0x0015,0xffec,0x0003,0x0014,0x001c,0x0009,0xfffb,
+0x0009,0xffff,0xffec,0x002b,0xffef,0x0003,0x000c,0x0000,
+0x0014,0xfffc,0xffdf,0xffe3,0x0006,0x0016,0x0026,0xfff9,
+0x0000,0x0001,0x001d,0x001e,0xffc1,0xffeb,0x0003,0x000b,
+0x001b,0xffff,0xfff2,0x002d,0xfff6,0xfff7,0x0001,0x000c,
+0x002f,0x0025,0xffe4,0x0000,0xfffe,0x001a,0x0004,0xfff3,
+0x0027,0xfff2,0xffe2,0xfff8,0xffea,0xfff8,0x000c,0xfff4,
+0x0022,0x001b,0xffe3,0x0002,0x001a,0xfffe,0x0008,0xffe1,
+0x0010,0x0003,0x0011,0x0039,0xfff2,0xfffa,0x0013,0x000d,
+0x0010,0xfff6,0x0008,0x0011,0x0014,0xfffe,0x0026,0x0000,
+0x0011,0xfff0,0xfff5,0x001b,0x002c,0x002d,0xfffc,0x0008,
+0xffe3,0x0005,0xfff9,0x001e,0xffff,0xffeb,0x0007,0xfff9,
+0x0000,0x0000,0xffd1,0x0009,0x0012,0x000f,0x0016,0xfff2,
+0x0004,0x0000,0x001c,0x0039,0xffe9,0xffeb,0x0019,0xfffe,
+0x0001,0x0000,0xfff9,0x0035,0x0013,0x0003,0x0011,0x000f,
+0x0024,0x0000,0xffed,0x0018,0x0015,0x002b,0xfff7,0x0000,
+0x0021,0xfff6,0xffde,0x0005,0xffef,0xffdd,0x000f,0x0001,
+0x0035,0x001e,0x0006,0xffc5,0x0000,0xfff6,0x0018,0xfff3,
+0x0011,0xffe5,0x0001,0xffff,0xffdb,0x000d,0x0004,0x0014,
+0x0014,0xffee,0xfff6,0xfff0,0xfff8,0xfff5,0x0027,0x0012,
+0x001a,0x0000,0xffd2,0xffec,0x0029,0x000f,0x0025,0x000f,
+0xffdd,0x000a,0xfff5,0x002c,0x0003,0xffd0,0x000a,0x0006,
+0x0011,0x0002,0xfff5,0xffcd,0xfff8,0x0008,0x0026,0x0003,
+0x0004,0xffe1,0x000c,0xfffe,0xffd2,0xffff,0x000a,0x0004,
+0x0005,0xfff9,0xffe6,0x0013,0xfff6,0xfffb,0x0012,0x0022,
+0x002d,0x000f,0xffca,0xffe8,0x0012,0x000d,0x001f,0x0007,
+0xfffb,0xfffd,0xffeb,0xfff9,0xfffe,0xffc4,0x000a,0xfffb,
+0x0020,0x0022,0xfff9,0xffec,0x000b,0xfff0,0x0008,0xffec,
+0x0015,0xffe3,0x0001,0x0018,0x0002,0x000d,0x001b,0x0006,
+0xfffb,0xfff1,0xfffd,0xfff8,0x0015,0x0001,0x0037,0x0015,
+0x000f,0xffda,0xffdb,0x0003,0x0041,0x0020,0x0017,0x001e,
+0xffb6,0x0011,0x0000,0x001f,0x0012,0xffb7,0x0005,0x0000,
+0xfffd,0x0005,0xffe7,0xfff4,0x0003,0x0001,0x0016,0xfffd,
+0x0009,0xffdf,0x000c,0x0018,0xfffa,0xfffe,0x0021,0xfff7,
+0xffeb,0xfffb,0xffec,0x001b,0x0013,0x0007,0x0022,0x0025,
+0x0022,0xffea,0xffd4,0x0000,0x0029,0x001d,0x0011,0x0015,
+0x004c,0xffdd,0xffe1,0xffe4,0xffcf,0x002b,0xffd8,0x0000,
+0x001d,0xfff2,0x0008,0x0005,0x000a,0x0012,0xffe6,0xffd2,
+0x0000,0x0007,0x0006,0x0003,0xffe7,0xfff9,0xfffe,0x0028,
+0x001c,0x000e,0x0012,0xfffd,0xffe5,0xffe4,0xfff8,0xffd3,
+0xfff3,0x0022,0xfff3,0xffe5,0xfff1,0x001f,0x000c,0x0003,
+0x0007,0xfff1,0xfff7,0x0009,0xffe4,0x001d,0xffd3,0x0005,
+0xfffa,0xffd5,0xfff7,0x000c,0x0002,0x0024,0xfff4,0xffe2,
+0xfff5,0x0003,0x0011,0x0003,0xffde,0xffea,0x0003,0x0018,
+0x000c,0x0018,0x0002,0x0020,0xffe4,0xffea,0xffe3,0xffe3,
+0x0005,0x0032,0xffeb,0xffe1,0xffda,0x001d,0x0007,0xfffb,
+0x0024,0xffe3,0xffed,0xffd7,0xffde,0x0012,0xffd3,0xfffa,
+0x0008,0xfff6,0xfffb,0x002b,0x0017,0x000b,0xffd6,0xffcb,
+0x0005,0x0005,0x0006,0x001e,0x000e,0xfff8,0x0014,0x001a,
+0x0001,0x0010,0x0019,0x0004,0x0003,0xfff1,0x0007,0xffd7,
+0xffe9,0xfffd,0xfffc,0xfffd,0x0008,0x0030,0xffff,0x0011,
+0xffe0,0xfff8,0x0003,0xfffe,0xfff3,0x0004,0xffce,0xffff,
+0xffe5,0xffd9,0xffe9,0x0033,0x000f,0x001e,0xffe5,0xffdb,
+0xfff9,0x0001,0x0011,0x001d,0x0005,0xffe9,0x0019,0x000a,
+0xfff2,0x001a,0x0008,0x0029,0x0001,0xfff7,0xfff3,0xffe6,
+0xfffb,0x000c,0xfff4,0xfff9,0xfff2,0x002d,0xfffa,0x0009,
+0x001f,0xffe8,0xffe9,0xffe5,0xffe3,0xfff7,0xffd5,0x0008,
+0x001a,0xfff9,0x001e,0xffef,0xfffc,0x0003,0xffe6,0xffdd,
+0x0005,0xffe8,0xfff6,0xffe4,0xfff7,0x000c,0x0005,0x0021,
+0x0005,0x0008,0x0005,0xffe3,0xffe6,0xffe8,0x0009,0xffe9,
+0xfff2,0x000c,0xffd9,0xffcc,0x0005,0x0012,0x0027,0x0018,
+0xffdb,0xfffd,0x0000,0x000a,0xfff9,0xffea,0xffd0,0x000c,
+0xfff8,0xffdc,0x000c,0xfff7,0xfff4,0x0016,0xfff4,0xffed,
+0xfffa,0xffe4,0x0000,0xffe3,0xffee,0xfffd,0x000b,0x0011,
+0xfff6,0x0012,0xfff6,0x0007,0xffe5,0xffee,0xfff5,0xfff9,
+0x0003,0x001c,0xffd1,0xffc9,0xffee,0x000f,0x0022,0x0010,
+0xfff8,0xffef,0xfff6,0xffd8,0xfff3,0xffde,0xffd1,0x0000,
+0x0005,0xfffc,0x0010,0x0015,0x0008,0xfffe,0xffd6,0xffd5,
+0x000a,0xffe6,0xfff6,0xfffe,0x001f,0x000b,0x001b,0x0013,
+0xffeb,0x000a,0x000c,0xffec,0x0003,0xfff5,0x0019,0xffec,
+0xffe7,0xffe7,0xffe3,0xffe4,0x001c,0x0022,0x0019,0x0026,
+0xffb3,0x0002,0x000b,0xffff,0x0007,0xffd1,0xffcc,0x0005,
+0xffe3,0xffdf,0xffff,0x001c,0x0000,0x000f,0xffe4,0xffe6,
+0xfffe,0xffe2,0x0000,0xfffe,0x0016,0xfffc,0x0021,0x0003,
+0xffdc,0x0015,0xfffd,0x000f,0x0002,0xfffb,0x0004,0xfffc,
+0xfffa,0xfff7,0xffdb,0xffe1,0x0005,0x0020,0x0014,0x001e,
+0x0051,0xffe7,0xfff2,0xfff8,0xffc3,0x0000,0xffe7,0x001c,
+0x0036,0x0014,0xfffd,0xfff2,0x0011,0xfff8,0x0000,0xffd4,
+0x0010,0x0023,0x000d,0x0012,0xffd5,0xfff9,0x0006,0x000b,
+0x0021,0xfffc,0x001e,0x000b,0xffea,0xffd8,0x0006,0xffd5,
+0x0003,0x0032,0xfff2,0xffee,0x0016,0x0012,0xffff,0xfff0,
+0x000c,0xfffc,0x0008,0x001d,0xffd9,0xfff4,0xffe2,0x0021,
+0x0013,0xfff8,0xffeb,0xfffa,0x0008,0x0009,0x000d,0xffe4,
+0x0004,0x001f,0x0018,0x0012,0xffcc,0xffe9,0x000c,0xfffc,
+0x0012,0x0005,0x000e,0x002f,0xffe8,0xffde,0xfff2,0xffe5,
+0x0016,0x0042,0xffea,0xffea,0xffff,0x0010,0xfffa,0xffe8,
+0x0029,0xffee,0xfffe,0xffeb,0xffd3,0xffe8,0xffe2,0x0015,
+0x0021,0x0018,0xffef,0x0018,0x001d,0xfff1,0xfff0,0xffcd,
+0x0015,0x0021,0x000d,0x002d,0xfffd,0xfff8,0x001c,0xfffe,
+0x0007,0xfffe,0x0025,0x0013,0x0007,0xffe5,0x0016,0xffd9,
+0xfff9,0x000c,0xfffb,0x0005,0x002d,0x0023,0xfff1,0xffff,
+0xffe5,0x0001,0x0014,0x0011,0xffe8,0xffda,0xffdd,0x001a,
+0xffff,0xfffc,0xffdd,0x0020,0x0015,0x0003,0xfffe,0xffdd,
+0x0008,0x001d,0x0018,0x002c,0xfff4,0xffe8,0x0022,0xffee,
+0xfff8,0x0007,0x0015,0x0037,0x0005,0xffeb,0x0002,0xffe9,
+0x000b,0x001c,0xfff3,0x0001,0x0016,0x0021,0xffeb,0xfff6,
+0x0024,0xfff3,0xfffb,0xfff9,0xffd8,0xffcd,0xffe4,0x0024,
+0x0034,0x001b,0x0012,0xffdc,0x0002,0xffea,0x0000,0xffdf,
+0x0015,0x0002,0xfffd,0xfff3,0xffe6,0x000b,0x000e,0x0004,
+0x000a,0xfff6,0x0012,0xfff2,0xffea,0xffdc,0x0018,0xffeb,
+0x0001,0x001c,0xffd8,0xffd6,0x002a,0x0005,0x0019,0x0005,
+0xffe0,0x0006,0x0011,0x001f,0xffed,0xffbf,0xffdf,0x0029,
+0x0010,0xffff,0x0000,0xffe3,0xfffa,0xfffc,0x000d,0xffef,
+0x0009,0xffff,0x0008,0xfff2,0xffdd,0xfffd,0x0013,0xfff5,
+0xfffc,0x0000,0x0001,0x0015,0xffe9,0xffe2,0x0003,0xfffb,
+0x0014,0x002c,0xffd0,0xffd2,0x0013,0x0003,0x0014,0xfffd,
+0xfffd,0xfff9,0x0006,0xffec,0xffe7,0xffb3,0xffe0,0x001d,
+0x001f,0x001e,0x0004,0x0002,0x000e,0xffe3,0xfff0,0xffd8,
+0x001a,0x0000,0xfffd,0x000c,0x000d,0x000a,0x0024,0xfff7,
+0xfff1,0xfff8,0x0018,0xfffa,0x0007,0xffea,0x0028,0xffef,
+0xfff8,0xfff7,0xffe1,0xffee,0x0042,0x0016,0x000b,0x0013,
+0xffb8,0x000d,0x001d,0x0012,0xfffc,0xffa6,0xffdb,0x0022,
+0xfffc,0x0001,0xfff3,0x0009,0x0006,0xfff5,0xfffe,0xffe8,
+0x000d,0xfffd,0x0007,0x000b,0x0004,0xfffc,0x002a,0xffe7,
+0xffe1,0x0001,0x0008,0x001d,0x0006,0xffef,0x0013,0xfffe,
+0x000a,0x0006,0xffda,0xffea,0x002a,0x0013,0x0006,0x000b,
+0x0074,0xffec,0xffbc,0xffe2,0xffe4,0x0053,0x001c,0xffee,
+0x0020,0xffea,0xfff3,0xffeb,0x0005,0x001c,0x0005,0xfff9,
+0xffe8,0xfff8,0xffea,0x0011,0xffe9,0x001e,0xffe7,0x002d,
+0x000f,0xfff7,0xfff5,0xffee,0x0016,0xfff6,0x0004,0xfffe,
+0x0013,0xfff4,0x0017,0x0003,0xffd5,0x0002,0x000c,0xfffc,
+0x002f,0x0000,0xffd3,0x0007,0xfff9,0x0045,0x0017,0xfff3,
+0xfffe,0xffcd,0xffe0,0xfff2,0xfffd,0x002f,0x0013,0x0008,
+0xffdb,0xfff5,0xfff6,0x0010,0xffe0,0x000f,0xffed,0x001d,
+0x0000,0x0001,0xffe4,0x0012,0x0014,0xfffc,0xfff0,0x000d,
+0x0026,0x0003,0x000f,0x0000,0xffbe,0x0000,0x0007,0xfff3,
+0x004d,0xfff3,0xffc8,0xffd5,0xfff3,0x0039,0x0017,0xffe6,
+0x000b,0xffed,0xffe5,0x0010,0x0011,0x0016,0xfff6,0xfff1,
+0xffed,0xfff6,0xffea,0x002b,0x0010,0x001e,0xfffe,0x001f,
+0xfff5,0xfffa,0xfffb,0xfff7,0x0034,0x0002,0x0014,0x0000,
+0x0008,0xffce,0x0021,0x001b,0xffed,0x0013,0xffff,0x0009,
+0x0008,0x0006,0xffdf,0xfffc,0x0007,0x002c,0x0012,0xffeb,
+0xffe9,0xffd0,0xffd2,0x0018,0x0009,0x0028,0x0003,0x0001,
+0xffe0,0xfff3,0xfff5,0x002b,0x0007,0x000e,0x0003,0x000f,
+0xffe6,0x0003,0xffeb,0x001a,0x0032,0x0008,0x0000,0x0010,
+0x001b,0xffde,0x0019,0x0017,0xffd5,0x0011,0xfffa,0x0001,
+0x0047,0xfff7,0xffc5,0xffe3,0xfff8,0x001e,0x001a,0xfff5,
+0x001e,0xfff0,0x0008,0xffd4,0xfff7,0x000e,0x0005,0x0002,
+0xffed,0xffd8,0xffda,0xfff1,0xfff9,0x0032,0xffef,0x0026,
+0xfff9,0xfff2,0xffe8,0xffd5,0x0016,0xfffa,0x0016,0x0013,
+0x0011,0xffde,0xfffe,0xffec,0xffe9,0xfff6,0x0027,0x0010,
+0x0002,0x000b,0xffdc,0x0009,0x000d,0x0011,0x0015,0xfffa,
+0xfffb,0xffd3,0xfff6,0xffdc,0xffee,0x0021,0x0013,0x0013,
+0xffe1,0xffd4,0xffe5,0xfff1,0xfff0,0x0022,0xfff5,0x0016,
+0xffea,0xfffc,0xffd8,0xfff9,0x0015,0x0000,0x0001,0x0023,
+0x0024,0xffee,0xfff6,0xffe8,0xffd2,0xfff4,0x0022,0x0008,
+0x0020,0xfffe,0xffd1,0xffd6,0x0007,0x0005,0x0015,0xffee,
+0x0009,0xfff4,0xfffb,0xfffb,0x0002,0x0008,0xfff6,0xfffc,
+0xfff2,0xffd6,0xffda,0x000a,0x0021,0x0031,0x0005,0x0018,
+0xffdf,0xfff4,0xffef,0xffdd,0x0034,0x0006,0x0026,0x0016,
+0x0007,0xffb8,0x0007,0x0003,0x0000,0x0006,0x0019,0x001e,
+0xffdc,0x0012,0xffe8,0xfffd,0x001c,0xfff9,0x0010,0xfff3,
+0xffe6,0xffd7,0xffe8,0x0001,0xfffb,0x001a,0x0003,0x000c,
+0xffe5,0xffd2,0xffe5,0x000a,0x0018,0x0022,0x000a,0x0008,
+0xffcf,0xfffe,0xffde,0x0000,0x0033,0x000c,0x0011,0x0026,
+0x0019,0xffc8,0x0000,0x0000,0xffea,0x0003,0x0014,0x0016,
+0x0079,0xfff7,0xffce,0xfff6,0xffd8,0x0028,0x002b,0x0009,
+0x003a,0x000c,0xffe7,0xffd7,0x000b,0x0002,0x001f,0xfffb,
+0xfff8,0x0013,0xfff1,0x0020,0xffd7,0x001e,0xfff0,0x0010,
+0x0014,0xffe4,0x0000,0xfffd,0x001a,0xffea,0x0013,0x0000,
+0x0024,0x0004,0x0016,0x000c,0xfffa,0xfff7,0xffff,0xffe8,
+0x0034,0x000a,0xffe5,0x001b,0xffee,0x001a,0x0026,0x000e,
+0x0017,0xfff0,0xffd4,0xffdf,0x0003,0x0014,0x002d,0x000a,
+0xffec,0x000f,0xfffd,0x001f,0xffce,0x000e,0xfff6,0x0000,
+0x0005,0xffef,0xfff1,0x0020,0x0018,0xfff0,0xffff,0x000f,
+0x0037,0x0014,0x000e,0x0008,0xffe3,0xfff4,0xfff9,0xffe0,
+0x0052,0xfffd,0xffda,0xffe9,0xffe8,0x000f,0x0026,0x0002,
+0x0025,0x000f,0xffd9,0xfffe,0x0017,0xfffc,0x000f,0xfff4,
+0xfffd,0x0011,0xfff1,0x003a,0xffff,0x001d,0x0006,0x0002,
+0xfffb,0xffe6,0x0007,0x0004,0x0038,0xfff7,0x0023,0x0003,
+0x0019,0xffdf,0x0020,0x0024,0x0011,0x0007,0xfff1,0xfff7,
+0x000d,0x0011,0xfff1,0x000f,0xfffd,0x0001,0x0021,0x0007,
+0x0001,0xfff4,0xffc6,0x0005,0x000f,0x000d,0x001d,0x0003,
+0xfff0,0x000d,0xfffc,0x0039,0xfff6,0x000d,0x000b,0xfff3,
+0xffeb,0xfff1,0xfff7,0x0028,0x0037,0xfffd,0x000e,0x0013,
+0x002c,0xffef,0x0018,0x0020,0xfffb,0x0004,0xffeb,0xffee,
+0x004c,0x0001,0xffd7,0xfff7,0xffed,0xfff4,0x0029,0x0011,
+0x0037,0x0012,0xfffd,0xffc1,0xfffd,0xfff4,0x001e,0x0005,
+0xfffd,0xfff4,0xffe1,0x0000,0xffe8,0x0031,0xfff8,0x0009,
+0xffff,0xffdf,0xfff4,0xffe3,0x001b,0xffee,0x0025,0x0015,
+0x0022,0xffef,0xfffd,0xfff5,0x000e,0xffe9,0x0019,0xfffe,
+0x0007,0x0016,0xffee,0x001d,0x0001,0xffe7,0x0024,0x0015,
+0x0014,0xfff7,0xffea,0xffc8,0xfff5,0x0006,0x002d,0x0015,
+0xfff1,0xfff0,0xffec,0xffff,0xffdf,0x0022,0xfffe,0xfffa,
+0xffef,0xffe9,0xffe4,0x0006,0x0019,0xfff4,0x0010,0x0025,
+0x0035,0xffff,0xfff5,0xfff1,0xfff8,0xffe7,0x0014,0xfff5,
+0x0025,0x0008,0xffe3,0xffea,0xfffc,0xffdb,0x0024,0x0009,
+0x0022,0x0016,0xffef,0xffe8,0x0008,0xffee,0x000f,0xfffe,
+0x0001,0xfff2,0xffe1,0x0019,0x000f,0x0030,0x000d,0xfffc,
+0xffe4,0xffe1,0xfffb,0xffeb,0x0039,0xfffc,0x0035,0x0018,
+0x0017,0xffc9,0x0006,0x000c,0x0025,0xfffa,0x000b,0x000b,
+0xffe1,0x001c,0xfffa,0x0010,0x0010,0xffce,0x001f,0x000e,
+0x0000,0xfffa,0xffdc,0xffef,0x0000,0x0000,0x001d,0x000e,
+0xfff5,0xffee,0xffec,0x0019,0x0006,0x0021,0x0013,0xffec,
+0xffd5,0xffeb,0xffeb,0x000e,0x0037,0x0000,0x0020,0x0028,
+0x002a,0xffd9,0xffff,0x0008,0x000e,0xfff8,0x0006,0x0003,
+0x0077,0xffe8,0xffd9,0xffd4,0xffcd,0x0042,0xfff2,0x000f,
+0x001f,0xffe6,0xffff,0x0000,0x0007,0x0010,0xffed,0xffe4,
+0xffed,0x0016,0xffe6,0x0004,0xfff3,0x001c,0xfff0,0x001d,
+0x0005,0xffff,0x0010,0xfff0,0x0008,0xffdd,0xfff6,0xffd6,
+0xfffc,0x0011,0x001d,0xffed,0xffd6,0xfff9,0x0000,0xfff1,
+0x0032,0xfffd,0xfff0,0xfffb,0xffe2,0x0035,0xffed,0x0014,
+0xfffd,0xffc9,0xffed,0x0008,0x0000,0x0022,0xfffb,0xfff5,
+0xffe0,0x0012,0xfff1,0x0004,0xffea,0x000d,0xfff6,0x000d,
+0xfff7,0x0008,0x0000,0x0013,0x0007,0xffe3,0xffe1,0xffe6,
+0x000d,0x0021,0x0015,0xffea,0xffbf,0xfff7,0xfffc,0xffe9,
+0x004f,0xffef,0xffe5,0xffc8,0xffdc,0x0029,0xffed,0x0008,
+0x000a,0xffea,0xfff1,0x0027,0x0014,0x0009,0xffdd,0xffdd,
+0xfff1,0x0014,0xffe6,0x001f,0x001a,0x001b,0x0006,0x000f,
+0xffec,0x0000,0x0017,0xfff8,0x0026,0xffea,0x0005,0xffda,
+0xfff1,0xffec,0x0027,0x0004,0xffee,0x0009,0xfff3,0xffff,
+0x000a,0x0003,0xfffc,0xffee,0xfff1,0x001b,0xffe8,0x000d,
+0xffe8,0xffcd,0xffde,0x002f,0x000c,0x001c,0xffeb,0xffed,
+0xffe5,0x0010,0xfff1,0x001e,0x0011,0x000c,0x000c,0x0000,
+0xffdc,0x000a,0x0007,0x001b,0x0025,0xfff0,0xfff1,0xffea,
+0x0003,0xfffc,0x001f,0x0001,0xffd6,0x0007,0xffee,0xfff7,
+0x004a,0xfff4,0xffe2,0xffd6,0xffe2,0x000e,0xfff0,0x0017,
+0x001d,0xffed,0x0014,0xffeb,0xfff9,0x0001,0xffed,0xffef,
+0xfff2,0xfff6,0xffd5,0xffe5,0x0003,0x0030,0xfff8,0x0016,
+0xfff0,0xfff9,0x0004,0xffd6,0x0009,0xffe1,0x0006,0xffec,
+0xfffa,0xfffc,0x0003,0xffd5,0xffea,0xffec,0x001c,0x0005,
+0x0005,0x0007,0xfff9,0xfffc,0xfff7,0x0000,0xffeb,0x001c,
+0xfffa,0xffd0,0x0002,0xfff2,0xfff1,0x0014,0xfffb,0x0000,
+0xffe5,0xfff2,0xffe0,0xffe4,0xfffb,0x0020,0xfffe,0x0006,
+0xffe0,0x0003,0xfff4,0xfffb,0x0008,0xffe7,0xfff2,0xfffc,
+0x000c,0x000b,0xfffc,0xffd1,0xffd3,0xffea,0x0016,0xfffe,
+0x0022,0xfffa,0xffee,0xffc9,0xfff1,0xfff5,0xffeb,0x0010,
+0x0008,0xfff0,0x0006,0x0010,0x0005,0xfffc,0xffdd,0xffe8,
+0xfff6,0xfff4,0xffd5,0xffff,0x002b,0x002f,0x000e,0x0008,
+0xffd5,0xfffb,0x000a,0xffde,0x0027,0xffee,0x0016,0xfff0,
+0xffef,0xffd6,0x000d,0xffed,0x0001,0xfffd,0x000e,0x0014,
+0xffde,0x000e,0x0004,0xffef,0x0005,0xffe8,0xffe6,0x0014,
+0xffe5,0xffd3,0xfff4,0x0018,0xfffe,0x000d,0xffeb,0xfff8,
+0xffea,0xfff0,0xffe0,0xfffe,0x0022,0x001f,0x0014,0xfff9,
+0xffc6,0x0005,0xfffb,0x0002,0x0026,0xfff4,0x0002,0xffff,
+0x0001,0xffe6,0x0005,0xffe9,0xffeb,0xfffa,0x0008,0x000b,
+0x007c,0xfff3,0xffeb,0xffe9,0xffc2,0x0017,0x0000,0x002b,
+0x0039,0x0008,0xfff3,0xffee,0x000e,0xfff6,0x0006,0xffe6,
+0xfffd,0x0031,0xffed,0x0013,0xffe1,0x001b,0xfff9,0x0000,
+0x000b,0xffec,0x001d,0xffff,0x000c,0xffd1,0x0004,0xffd9,
+0x000b,0x0022,0x001c,0xfff7,0xfffb,0xffed,0xfff3,0xffde,
+0x0037,0x0006,0x0001,0x000e,0xffd7,0x000a,0xfffc,0x0030,
+0x0016,0xffec,0xffe1,0xfff6,0x0005,0x0007,0x0014,0xfff7,
+0xfff0,0x002d,0xfff8,0x0013,0xffd8,0x000c,0xffff,0xfff1,
+0xfffc,0xfff6,0x000c,0x0022,0x000b,0xffd7,0xfff0,0xffe8,
+0x001e,0x0031,0x0014,0xfff3,0xffe4,0xffea,0xffee,0xffd5,
+0x0054,0xfffa,0xfff7,0xffdc,0xffd1,0xffff,0xfffc,0x0024,
+0x0024,0x000c,0xffe5,0x0014,0x001a,0xffef,0xfff7,0xffdf,
+0x0001,0x002f,0xffed,0x002e,0x0009,0x001b,0x000f,0xfff3,
+0xfff1,0xffee,0x0023,0x0006,0x002a,0xffdf,0x0014,0xffdc,
+0x0001,0xfffc,0x0026,0x000e,0x0012,0xfffe,0xffe5,0xffec,
+0x000f,0x000d,0x000d,0x0001,0xffe6,0xfff2,0xfff7,0x0029,
+0x0001,0xfff0,0xffd2,0x001b,0x0012,0x0001,0x0004,0xfff0,
+0xfff5,0x002b,0xfff8,0x002d,0x0000,0x000b,0x0015,0xffe3,
+0xffe2,0xfff8,0x0013,0x002a,0x0029,0xffe4,0x0000,0xffec,
+0x0014,0x000b,0x001e,0x000a,0xfffc,0xfffb,0xffe0,0xffe4,
+0x004f,0xfffe,0xfff4,0xffea,0xffd6,0xffe4,0xffff,0x0033,
+0x0036,0x000f,0x0008,0xffd7,0x0000,0xffe8,0x0006,0xfff1,
+0x0001,0x0011,0xffdc,0xfff4,0xfff2,0x002f,0x0000,0xfffa,
+0xfff5,0xffe6,0x0010,0xffe5,0x000d,0xffd5,0x0016,0xffee,
+0x000a,0x000c,0x0002,0xffde,0x000f,0xffdf,0x000d,0xfff3,
+0x000a,0x0012,0x000a,0x000f,0xffeb,0xffd7,0xfffa,0x0038,
+0x0013,0xfff3,0xfff7,0xffdf,0xfff7,0xfffa,0x0014,0x0001,
+0xfff5,0x000d,0xffe8,0xfff3,0xffe9,0x0020,0x0006,0xffea,
+0xffe6,0xfff1,0x0000,0x0008,0x000c,0xffdb,0x0001,0xfffe,
+0x001c,0x001b,0xfffb,0xffdb,0xfff9,0xffdd,0x0008,0xffeb,
+0x0027,0x0004,0x0000,0xffdd,0xffe5,0xffcb,0xfffa,0x002c,
+0x0021,0x0012,0xfffb,0xfffe,0x000b,0xffe1,0xfff7,0xffea,
+0x0006,0x000f,0xffdc,0x000d,0x0019,0x002e,0x0017,0xffec,
+0xffdb,0xffe8,0x0017,0xffed,0x002b,0xffe3,0x0026,0xfff2,
+0x0000,0xffe6,0x000c,0xfff6,0x0026,0xfff0,0x0000,0x0000,
+0xffe3,0x0019,0x0016,0x0002,0xfffa,0xffbd,0xfff5,0x0031,
+0xffff,0xfff6,0xffe8,0x0005,0x0003,0xfff3,0x0004,0xfffb,
+0xfffa,0x000b,0xffe7,0x000c,0x0010,0x001f,0x001c,0xffdc,
+0xffcb,0xfff3,0x0006,0x0010,0x002a,0xffe8,0x0011,0x0001,
+0x0012,0xfff6,0x0004,0xfff3,0x000f,0xffee,0xfffb,0xfff9,
+0x001d,0xffe7,0xffea,0xfffe,0x0006,0x0043,0x000b,0xffcf,
+0x0001,0x000a,0x0018,0xfffb,0xfffd,0x000d,0xfffc,0x0005,
+0x0006,0xfff5,0x0019,0xfff4,0xfff0,0xffe1,0xffe4,0x0024,
+0x0035,0x000d,0xfffa,0xfff0,0xffd6,0x0018,0xffef,0xffff,
+0xffee,0x000a,0xfffc,0x000d,0xfff1,0x0012,0x0005,0x0007,
+0xffd9,0xfffc,0x0000,0x0023,0x001b,0x0035,0x0006,0xffd4,
+0xffdf,0xffee,0x0005,0x0002,0xfff5,0x001f,0x0009,0x0016,
+0xfffa,0xfff1,0x0024,0xfff3,0xffe7,0xffd2,0xffe9,0x0014,
+0x0025,0x0018,0xffe9,0x0013,0xffd5,0x001d,0xffda,0x000e,
+0x0000,0x001a,0xfff4,0x000a,0xffda,0x0010,0x0000,0x0000,
+0xfff6,0xffee,0xfff6,0xfff1,0x0015,0x0029,0x0006,0xffc8,
+0xffed,0x000d,0x0009,0x0021,0x0009,0x0006,0xffec,0xffff,
+0x000b,0xfff3,0x0018,0x000d,0x0017,0xffe0,0xfffa,0x0016,
+0x001a,0x000f,0x0000,0xfff8,0xfff4,0x0025,0xffff,0x0002,
+0xffe4,0xffe5,0x0005,0x0025,0x0007,0x0023,0xfff8,0x0015,
+0xffb1,0x0002,0x000c,0x0016,0x002a,0x001c,0x0001,0xffcd,
+0xffca,0xfff1,0xfff8,0x0029,0x0000,0x0018,0xfffa,0x000f,
+0xffff,0xffef,0x0024,0x000c,0x000e,0xffd1,0x0000,0x0006,
+0x000b,0x001a,0xfff0,0x001b,0xfff3,0x002b,0xffea,0x0012,
+0xfff6,0xfff4,0xfffe,0x0022,0xfff1,0x0021,0xfff3,0x000d,
+0xfff1,0xfff3,0xfff3,0xffff,0x001a,0x000e,0x0009,0xffd7,
+0xffff,0x0010,0x002e,0xffe5,0xffee,0xffff,0xfffc,0x0010,
+0x000b,0xffd5,0x0008,0xffd3,0x0000,0xfff5,0xffeb,0x001d,
+0x001e,0x0008,0xffed,0xffd6,0xffd7,0x001c,0x0000,0x0014,
+0xffec,0xfff5,0xffe2,0xfff6,0x0004,0x0005,0x0020,0x001c,
+0xffac,0x0006,0x0009,0x0024,0x002f,0x0001,0x0004,0xffdc,
+0xffdc,0xfff4,0x001b,0xffec,0xffe6,0x0011,0x0009,0x0021,
+0xffff,0xffd1,0x0013,0xffd2,0xfff7,0xffe5,0xfff1,0x000d,
+0x000f,0x0012,0xffdd,0xfffa,0xffd6,0x0021,0xffec,0x0024,
+0xffff,0x0004,0xffda,0xfff2,0xffee,0x0002,0x001b,0x0014,
+0xffc9,0xfffa,0xffff,0xfff2,0x0029,0xfff6,0x0004,0xffd0,
+0xffea,0x0014,0x001f,0x000a,0xfffb,0xfff9,0xffec,0x0009,
+0x0010,0xffd3,0x0008,0xffed,0x0028,0xfff4,0x0001,0x000f,
+0x0004,0x000a,0xfff4,0xffde,0xfff5,0x0029,0x0010,0x0018,
+0xffe2,0xffcf,0xffec,0x000d,0x001c,0x0016,0x0012,0x002b,
+0xff84,0x000d,0x0015,0x0017,0x003e,0xffe9,0x0000,0xffd5,
+0xffc7,0xfff8,0x000d,0x0012,0xfff2,0x000a,0xfffa,0x001a,
+0x0003,0xffcf,0x0013,0xffed,0x001f,0xffe5,0x0007,0x0000,
+0xfff5,0x0014,0xffe3,0x0001,0xfff4,0x002f,0xfffc,0x0027,
+0xfff5,0xffde,0xffe4,0x0009,0x0005,0x0013,0x000d,0x0022,
+0x0022,0xfff2,0xfffc,0x0011,0xfffb,0x0018,0x001a,0xffec,
+0x001b,0x002d,0x000c,0xffe8,0x0002,0xfff3,0x0015,0x0008,
+0x0016,0x0010,0x0020,0x0002,0xffde,0xffe1,0xffec,0x0007,
+0x003a,0xfffb,0x0005,0xfffe,0xffda,0x000c,0xfffe,0x0001,
+0xffff,0x001a,0xfffb,0x0017,0x0015,0x0006,0xfff8,0xfff5,
+0xffde,0x0006,0x0012,0x0037,0x000f,0x000b,0x0015,0xfff0,
+0xfff8,0x0010,0xfffa,0xfff0,0xfffb,0x0004,0x0023,0x0018,
+0x000a,0x000c,0x002b,0x0001,0xffd5,0xffd1,0xfff2,0xfff8,
+0x002b,0x0005,0xfff6,0x0022,0xffd9,0x0012,0xffea,0x0010,
+0x0011,0x002a,0xfff3,0x0013,0xffff,0x0003,0xfff2,0xffec,
+0xfffb,0xfff9,0x0007,0x0004,0x0009,0x0000,0x0015,0xffe4,
+0x0006,0x0030,0xfffe,0x000e,0x000f,0xffec,0x0005,0x0000,
+0x001b,0x000e,0x0020,0x001c,0x0005,0xffe0,0x0002,0xfffa,
+0x0020,0xfffd,0x000c,0x0005,0xfff8,0x0019,0x000e,0x0004,
+0xfff4,0xfff5,0x0004,0x002f,0x002d,0x0016,0xffea,0x0002,
+0xffb6,0x000c,0x001e,0x002a,0x001e,0xfff2,0x0010,0xffe9,
+0xffe3,0x0013,0xffec,0x0015,0x0007,0xffff,0x0013,0x0011,
+0x000e,0x000a,0x002b,0x001b,0xfffd,0xffd0,0x0008,0xffea,
+0x0010,0x0007,0xfffc,0x002a,0xfff7,0x001f,0xfffa,0x0014,
+0x0006,0x0004,0xfffd,0x002b,0x0016,0x0014,0xffe4,0xfffb,
+0xfff6,0xfffd,0x0004,0x0012,0x000f,0xffe5,0x0018,0xfff3,
+0x0018,0x0033,0x0022,0xffd1,0xfff4,0xffe4,0x0015,0x0013,
+0x001b,0xfff0,0x000f,0xffe2,0xffef,0xfff4,0xfff4,0x0000,
+0x0024,0xfff6,0xfff9,0xffe5,0xffdb,0x0010,0x000f,0x0016,
+0xfffd,0x0004,0xffe1,0xffff,0x002a,0xfff9,0x0012,0x0009,
+0xffb1,0x0011,0x001b,0x0038,0x0024,0xffd7,0x0013,0xfff8,
+0xfff6,0x0016,0x000f,0xffd9,0xffec,0xfff7,0x0023,0x0023,
+0x000f,0xffec,0x001a,0xffe1,0xffe6,0xffe5,0xfffa,0xfff1,
+0x0014,0x0000,0xffe9,0x0008,0xffda,0x0016,0xfffb,0x0026,
+0x000f,0x0014,0xffd9,0xfffc,0x0012,0xfff7,0x000d,0x0001,
+0xffce,0x0003,0x0010,0x0005,0x001e,0xffcb,0x0013,0xffec,
+0x0003,0x0037,0x0013,0xfff8,0x0000,0xffde,0x0005,0x000b,
+0x0020,0xffee,0x000f,0xfffc,0x0016,0xfff3,0x000a,0xfff3,
+0x0009,0xfff8,0x0000,0xffed,0xfff9,0x001d,0x001f,0x001a,
+0xfff3,0xffdf,0xffeb,0x0016,0x0041,0x0009,0x0004,0x0017,
+0xff89,0x0018,0x0027,0x002c,0x0033,0xffbe,0x000e,0xfff1,
+0xffe1,0x001a,0x0001,0x0000,0xfff9,0xfff0,0x0013,0x001c,
+0x0013,0xffea,0x001a,0xfffc,0x000d,0xffe4,0x0010,0xffe3,
+0xfffb,0x0001,0xfff0,0x0010,0xfff8,0x0023,0x000a,0x002a,
+0x0004,0xffef,0xffe3,0x0013,0x002a,0x0007,0x0000,0x000f,
+0x001f,0xffe4,0x0006,0xfff0,0xfff0,0x0032,0xffe1,0xfff2,
+0x0000,0x0006,0x0024,0x0011,0x0000,0x0000,0xffe3,0xfff2,
+0x000b,0x0012,0x0014,0xffe7,0xfffa,0xffdf,0xffed,0x0014,
+0x002b,0x0015,0x0015,0xfff2,0xffc9,0x0000,0xffe0,0xffd8,
+0xffd6,0x0027,0x0001,0xfff8,0xfff2,0x0008,0xfffa,0xfffd,
+0xffdb,0xfff8,0x001d,0x0016,0x0004,0x0025,0xffdc,0xfff7,
+0xffde,0xffea,0x0011,0x0018,0xfff8,0x0012,0xfff1,0x0002,
+0xffff,0x000e,0x001f,0xffe7,0xfff1,0xffd0,0xfff3,0x0004,
+0x001c,0x001f,0x0005,0x0015,0xffc7,0x0004,0xffcb,0xffe8,
+0xffe9,0x0037,0xfffa,0xfff4,0xffdb,0x0006,0xfff5,0xfff5,
+0xfff9,0xffea,0x0012,0xffe3,0xffff,0x0019,0xffdc,0xffeb,
+0xffec,0x0009,0x0016,0x0038,0x000b,0xfffa,0xffd3,0xffeb,
+0x000f,0x0010,0x0014,0x0001,0x0021,0xffde,0x0002,0x0006,
+0x0011,0x0017,0x001c,0xfffa,0xffe7,0x000c,0xfff0,0xffdb,
+0xffcb,0x0001,0x000b,0x000f,0x0008,0x0019,0xffec,0x000b,
+0xffb4,0xffff,0x0029,0x0009,0x0013,0x000c,0xffd7,0xffef,
+0xffc9,0xffee,0x0003,0x003f,0x0003,0x000c,0xffe2,0xfffb,
+0x0003,0x000c,0x001f,0x0000,0x0018,0xffcf,0x0008,0xfff7,
+0x0001,0x0021,0x000c,0x001d,0xffe5,0x0012,0xffdb,0xffeb,
+0xffde,0x0011,0x0003,0x000b,0xfff2,0x0017,0xffe7,0x0002,
+0xfff3,0xffef,0x000f,0xfff1,0x0003,0xffff,0xffdf,0xfff9,
+0xffff,0x000c,0x003a,0xfffb,0xfff1,0xfff3,0xffe3,0xfffd,
+0x0010,0xfff3,0x0004,0xffc7,0x000a,0xfff3,0xfff5,0x000d,
+0x0015,0x000f,0x0009,0xffd8,0xffc9,0x0003,0xfff2,0xffed,
+0xffd4,0x0011,0xffe8,0xffe0,0x0005,0xfffc,0x0015,0x0012,
+0xffae,0x0003,0x0026,0x0017,0x0018,0xfff1,0xffda,0xfffe,
+0xffdb,0xfff1,0x0027,0x0002,0xffe9,0x0004,0xfff1,0x000c,
+0x0003,0xffef,0x000f,0xffc6,0x0001,0xffe3,0xfffa,0xfffe,
+0x0005,0x001a,0xfff9,0xfffc,0xffc8,0x0009,0xffdd,0xfffd,
+0xffe7,0x0021,0xffe0,0xffdc,0xffef,0xfff9,0x000f,0x0009,
+0xffcc,0xfff6,0x001b,0xffe5,0x0012,0xffe6,0xffda,0xfff2,
+0xffe9,0x0010,0x002c,0x0021,0xfffd,0xffec,0xffd3,0xfff6,
+0x0014,0xfff1,0x0003,0xffe1,0x0032,0xfff2,0x000a,0x0000,
+0xfffb,0x0011,0x000f,0xffe0,0xffe8,0x0010,0x0001,0xfff1,
+0xffc9,0xffec,0xfff2,0xfff8,0x001d,0x000c,0x0007,0x0020,
+0xff87,0x0009,0x0032,0x000a,0x0028,0xffd8,0xffd5,0xfff7,
+0xffc6,0xfff4,0x0019,0x0029,0xfff5,0xfffe,0xffe1,0x0005,
+0x0008,0xffed,0x000f,0xffe0,0x0029,0xffe2,0x0010,0xfff0,
+0xffec,0x001c,0x0000,0x0003,0xffe6,0x0016,0xffed,0x0000,
+0xffdc,0xfffc,0xffea,0xfff4,0x0006,0x0009,0x0001,0x0018,
+0x0024,0xffee,0x0018,0x0003,0xffe4,0x0007,0xfff0,0x000d,
+0x001a,0x0029,0x0018,0xffff,0x0005,0xffe6,0xfffd,0xfff4,
+0x001b,0x002e,0x001b,0xfff6,0xffe8,0xffde,0xfff6,0xfff8,
+0x0031,0x0002,0x0022,0x0000,0xffcd,0xfff4,0xffef,0xffda,
+0xffe7,0x0038,0x0000,0x0000,0x0016,0xfffd,0xffec,0xffea,
+0xffe0,0x0002,0x002f,0x002a,0xfff9,0xfffb,0xffeb,0x0012,
+0xfff7,0x000c,0x0005,0x0005,0xfffe,0xfff8,0x000a,0x0004,
+0x000e,0x002a,0x0026,0xfff6,0xffdf,0xffcf,0xfffb,0xffe8,
+0x0021,0x000c,0x0011,0x0023,0xffcc,0xfffa,0xffda,0xffea,
+0xfff9,0x0048,0xfff9,0xfffd,0x0000,0xfffa,0xffe7,0xffe2,
+0xfffe,0xfff5,0x0024,0xfff7,0xfff3,0xffef,0xffeb,0x0006,
+0x0005,0x002d,0x000a,0x0024,0x0012,0xffdf,0xffed,0xffed,
+0x001f,0x002c,0x001b,0x000f,0x0010,0xffde,0x000b,0xffea,
+0x0016,0x0004,0x0028,0x0007,0xffeb,0x0000,0xffff,0xffdd,
+0xffdc,0x0012,0x000a,0x0018,0x002e,0x000c,0xffde,0xfff8,
+0xffb9,0x0009,0x003b,0x001d,0x0008,0xffe2,0xffe6,0x000b,
+0xffe2,0x0010,0xfff8,0x002c,0x0009,0xfff2,0xfffb,0xfffe,
+0x0013,0x0028,0x0026,0x000f,0x0007,0xffce,0x0011,0xffda,
+0x0007,0x000e,0x0018,0x002b,0xffea,0x0006,0xffea,0xffed,
+0xffef,0x0022,0x0002,0x0014,0x0017,0x000a,0xffd9,0xfff0,
+0xfff8,0xfffa,0x0021,0x0004,0xfff9,0xffd4,0xffee,0x0015,
+0x0017,0x0030,0x002e,0xffe8,0xfff7,0xffd8,0xfffd,0xffff,
+0x0020,0x000d,0x000b,0xffd5,0xfff9,0xfff2,0xfffd,0xfff1,
+0x001a,0xfffd,0x0015,0xffe6,0xffce,0xfff8,0x0000,0xfff0,
+0xffe5,0x0022,0xffe7,0xffe9,0x002b,0xffef,0x0006,0xffff,
+0xffb3,0x000d,0x0038,0x002b,0x000d,0xffc7,0xffe9,0x001a,
+0xfff5,0x0013,0x001b,0xfff0,0xffef,0xffea,0x000a,0x000f,
+0x0013,0x000a,0x0016,0xffd5,0xfff0,0xffe2,0x0002,0xffe1,
+0x000b,0x0006,0x0005,0x0009,0xffcc,0xfffe,0xffec,0x0000,
+0xfff8,0x0032,0xffdf,0xffe5,0x0013,0xffed,0x0001,0xfff7,
+0xffd1,0x0000,0x002d,0xfff9,0x0007,0xffbb,0xffe9,0x000d,
+0x0002,0x0033,0x0020,0x000e,0x0003,0xffd1,0xffed,0xfff8,
+0x0025,0x000b,0x000a,0xfff0,0x0020,0xfff1,0x0013,0xffe3,
+0x0000,0xffff,0x001c,0xffee,0xffec,0x0004,0x0010,0xfff3,
+0xffda,0xfffd,0xfff1,0x0000,0x0042,0x0000,0xfff9,0x000d,
+0xff8c,0x0014,0x0044,0x001e,0x001c,0xffad,0xffe4,0x0012,
+0xffe0,0x0016,0x000d,0x0015,0xfffb,0xffe4,0xfffb,0x0007,
+0x0018,0x0008,0x0016,0xffef,0x0017,0xffe2,0x0019,0xffd3,
+0xfff1,0x0009,0x000b,0x0012,0xffea,0x000a,0xfffc,0x0002,
+0xffed,0x000c,0xffe9,0xfffd,0x002b,0xfffe,0xfff4,0x0004,
+0x0048,0xfff3,0xffe3,0xffee,0x0004,0x005a,0x0025,0xffde,
+0x0004,0xffff,0x000d,0xfff7,0xfffa,0x000b,0x0002,0x0018,
+0xfff3,0x0003,0xfff9,0xfff5,0xfffc,0x0004,0xffd6,0x0019,
+0x001f,0xffff,0xfff8,0xffe3,0xfffa,0x0011,0xffed,0x0002,
+0xfff6,0xfffa,0x0026,0x0016,0xffd6,0xffed,0xfffa,0xfff5,
+0x0003,0x0007,0xfffa,0x0014,0x0019,0x004d,0x0020,0xffe3,
+0xffe1,0xffe2,0xfffc,0xfffe,0xfff2,0x001d,0x0010,0x0028,
+0xffe6,0x0000,0x0003,0xfff4,0xfff3,0xfff6,0xffdc,0x0009,
+0x000f,0x0008,0xffe8,0x0006,0xfff9,0x0016,0xffd8,0x0011,
+0x0008,0x0009,0x001f,0x0012,0xffbe,0xffea,0xfff5,0xffed,
+0x0020,0xfffa,0xffef,0xffe1,0x0013,0x0041,0x0021,0xffd7,
+0xfff0,0x0001,0x0000,0x001d,0x0006,0x0004,0xfff3,0x0011,
+0xfff7,0x0001,0xfff8,0x000e,0x0023,0x0003,0xffed,0x000b,
+0x0004,0x0000,0xffff,0xffeb,0x0017,0x001e,0xfffd,0x0005,
+0xffec,0xffd4,0x0030,0x002e,0xffed,0xfffd,0xffec,0x0003,
+0xffdc,0x000d,0x0005,0x0007,0x0028,0x0033,0x001c,0xffdc,
+0xffcc,0xffe5,0xffee,0x0024,0xfffe,0x0016,0x0000,0x0021,
+0xffeb,0xfffe,0x0003,0x000d,0x001a,0xfff5,0xfff2,0xfffc,
+0xfff6,0x000a,0xffee,0x000e,0x0016,0x0024,0xffe8,0x0015,
+0xffff,0xffe4,0x0028,0x002a,0xffd6,0xfffb,0xffe7,0xfffb,
+0x001b,0xffff,0xffec,0xffef,0x0018,0x0026,0x0023,0xffe6,
+0x0001,0x0004,0x0023,0xffe0,0xffeb,0xfffd,0x0002,0x0023,
+0xfff8,0xffe3,0xffe8,0xffd4,0x000c,0x0018,0xffde,0x0012,
+0x0008,0xfff9,0xffeb,0xffc9,0xfffb,0x0015,0xfffe,0x0017,
+0xfff5,0xffe4,0x000d,0xffff,0xffea,0xffdf,0x0015,0x000a,
+0xffd7,0x0012,0x0002,0x0015,0x002d,0x0018,0x001e,0xffeb,
+0xffdf,0xffe8,0x0011,0xffe8,0xffe3,0x000f,0x0010,0x0033,
+0xffeb,0xffdf,0xfff3,0xffd3,0x0003,0x0008,0xffe4,0x0002,
+0xfff9,0x0002,0xffdb,0xffed,0xfff9,0x001b,0xffea,0x0027,
+0x0007,0xfff4,0x0005,0xfffb,0xffd3,0xffdd,0x000f,0x0001,
+0xfff4,0x0004,0xfff8,0xffe3,0x0027,0x000c,0x001e,0xffdf,
+0xffed,0x0008,0x0015,0x0006,0xfff8,0xfff7,0xfff3,0x001c,
+0xfffc,0xffe1,0xffe8,0xffee,0x0034,0x0017,0xfff4,0x0004,
+0xffee,0xfffb,0xfff2,0xffd1,0x0018,0x0022,0x000e,0x001b,
+0xffea,0xffbe,0x0016,0x0016,0x0001,0xfff0,0x0006,0x0018,
+0xffaf,0x0019,0x000e,0x0008,0x003d,0x0000,0x0019,0xffe4,
+0xffca,0xffec,0x0003,0x000e,0xffef,0x0008,0x0000,0x002c,
+0xfff0,0xffdd,0xfff3,0xffee,0x002b,0x0007,0xfffa,0xfff5,
+0xffdf,0x0004,0xffe2,0xfff5,0x0016,0x0028,0xfffa,0x002b,
+0xfffd,0xffce,0x000e,0x0012,0xffea,0xffee,0x0001,0x0010,
+0x004d,0xfffe,0xfff5,0x0001,0xfff9,0x002f,0x0034,0xfffb,
+0x001d,0x0021,0x0001,0xffe4,0x0000,0xfff1,0x001c,0x001a,
+0x0002,0x001e,0x0000,0x0002,0xffea,0x0004,0xffdf,0xfffd,
+0x0024,0xffeb,0x0003,0xfff1,0xfffe,0x0005,0xfffc,0x0004,
+0x0006,0x0009,0x0025,0x001f,0xfffb,0xffe0,0xffec,0xffe2,
+0x0008,0x0011,0x000a,0x0028,0x000d,0x0022,0x002f,0x0000,
+0xfffb,0x0004,0xfff0,0xffeb,0xfff8,0x0002,0x002a,0x002b,
+0xfff6,0x001a,0x000a,0x0002,0xffe1,0xfff5,0xffe5,0xffed,
+0x0015,0xfff6,0xfff4,0x0014,0xfffd,0x000b,0xffe7,0x0014,
+0x0019,0x0019,0x001d,0x001c,0xffe4,0xffde,0xffe7,0xffda,
+0x0025,0x0003,0x0000,0xfff6,0x0007,0x0016,0x0030,0xfff4,
+0x0008,0x0024,0xfff4,0x0009,0x000c,0xffea,0x000c,0x0013,
+0x0006,0x001c,0x0000,0x001d,0x0012,0x0003,0xfff5,0xffef,
+0x000a,0xffee,0x000a,0xfff9,0x001b,0x0012,0x000b,0x0007,
+0xfffd,0xffe4,0x002f,0x0037,0x0012,0xfff1,0xffde,0xfff0,
+0xffe1,0x0018,0x0017,0x001b,0x001d,0x0009,0x002b,0xfff8,
+0xffe6,0x0007,0xffe2,0x0011,0x0004,0xfffd,0x001a,0x0023,
+0xfffb,0x0018,0x000a,0x001c,0x0009,0xfff4,0xfffb,0xffdf,
+0xfffb,0xfff8,0xfffb,0x001d,0x001a,0x0018,0xfff7,0x0017,
+0x000e,0xfff4,0x0027,0x0034,0xfffb,0xffee,0xffd9,0xffe8,
+0x0020,0x0008,0xfffd,0x0002,0x000d,0xfffc,0x0032,0x0001,
+0x001b,0x0027,0x0017,0xffcd,0xfff1,0xffe2,0x001b,0x0025,
+0x0007,0xffff,0xffef,0xffe3,0xfffb,0x0017,0xffe7,0xfff6,
+0x000e,0xffe6,0xfff8,0xffd7,0xffff,0x0009,0x000d,0x001a,
+0x0005,0xfff4,0x000c,0x0007,0x000e,0xffd3,0x0006,0xfff7,
+0xffdc,0x001d,0x0013,0x0029,0x0022,0xffee,0x002d,0x0006,
+0xfff8,0x000a,0x0005,0xffd5,0xffe9,0xfff5,0x002a,0x0035,
+0xfffb,0xfffb,0xfffa,0xffe2,0xfff2,0x0008,0xffec,0xffe6,
+0xffff,0xfff0,0xffe7,0xfffc,0xfffd,0x000f,0xfff9,0x0029,
+0x0017,0x0003,0x0004,0x0003,0xfff8,0xffd0,0x0001,0xffef,
+0xfff9,0x000f,0x0009,0xfff7,0x001c,0xffe3,0x002d,0xfffb,
+0x0006,0x002b,0x0009,0xfff4,0xfffe,0xffdc,0x000c,0x001e,
+0x000b,0xfffd,0xffef,0xfffd,0x0022,0x0016,0xfffd,0xffe8,
+0xfff4,0xffe8,0xfffe,0xffe0,0x001c,0x0016,0x001d,0x001d,
+0xfffb,0xffce,0x0015,0x001f,0x0026,0xffe3,0xfff9,0x0005,
+0xffb4,0x0023,0x001f,0x001c,0x0031,0xffd5,0x0028,0x0000,
+0xffe3,0x000e,0xfff8,0xfffb,0xfff6,0xffee,0x001a,0x002e,
+0x0000,0xfff9,0xfffa,0xfffd,0x0019,0x0007,0x0002,0xffd8,
+0xffe4,0xfff2,0xffee,0x0003,0x001b,0x001c,0x0008,0x002d,
+0x000d,0xffde,0x000d,0x001b,0x000f,0xffe1,0xfff4,0xfffd,
+0x004a,0xffef,0x0000,0xffe1,0xffee,0x0049,0xfffb,0x0000,
+0x0003,0xfffb,0x0019,0x000c,0xfffd,0xffff,0xffea,0x0003,
+0xfff7,0x0021,0xfff4,0xffe8,0x0006,0x0002,0xffdf,0x0009,
+0x0015,0x0005,0x0014,0xffe5,0xffed,0xfff9,0xffde,0xffdb,
+0xffde,0x0016,0x002c,0x0000,0xffd7,0xffe3,0xffef,0xffeb,
+0x0005,0x0003,0x0015,0x0007,0x0002,0x003c,0xfff6,0x0005,
+0xffe0,0xffde,0x0007,0x0014,0xfff5,0x0010,0xfff8,0x0014,
+0xffeb,0x001d,0xffff,0xffe8,0xfffe,0xfff3,0xffe5,0xfffa,
+0x0005,0x000f,0x0003,0x0008,0xffeb,0xffff,0xffc9,0xffeb,
+0xfff1,0x0026,0x0025,0xfffd,0xffbf,0xffe0,0xffe9,0xffe2,
+0x0023,0xfff6,0x000b,0xffd4,0xfffd,0x0030,0xfff6,0xfffa,
+0xffef,0xfffe,0x000b,0x0033,0x0008,0xfff8,0xffda,0xfffd,
+0xfffc,0x001f,0xfff4,0x0002,0x002e,0x0001,0xfff6,0xfffc,
+0xfffb,0x0007,0x001a,0xffed,0x000a,0x0005,0xffee,0xffde,
+0xffd3,0xfff1,0x0036,0x0018,0xffee,0xfff3,0xffe1,0xfff9,
+0xffdf,0x000a,0x0022,0xfffb,0x0011,0x0023,0xfff1,0xffff,
+0xffcb,0xffe2,0xfffa,0x003b,0x0000,0x000a,0xffe8,0x000d,
+0xffef,0x001b,0xffff,0x0001,0x0025,0xfff3,0xfffc,0xffec,
+0xffec,0x0012,0x000a,0x0010,0x0008,0x000b,0xffd9,0xffee,
+0xffe6,0x0000,0x002e,0x0014,0xffd7,0xfff1,0xffdb,0xfff1,
+0x001d,0xfffb,0x0007,0xffe2,0x0001,0x0015,0xfff9,0x0007,
+0x0000,0x0000,0x002f,0xfff7,0xffee,0xfff1,0xffea,0x000e,
+0xfffc,0x0000,0xffe4,0xffc7,0x0017,0x0015,0xffe7,0x0002,
+0xffff,0x0000,0x0007,0xffcb,0xffed,0xfffd,0xffef,0xfff1,
+0xffdc,0x0000,0x0013,0xffe8,0xffeb,0xffd5,0x0009,0x0000,
+0xffd9,0x000e,0x001e,0x0008,0x0016,0x0008,0xfff4,0x000c,
+0xffde,0xffe5,0x001d,0xfffe,0xffe6,0x0002,0xfff8,0x001f,
+0xfff0,0xfffd,0xffef,0xffc7,0x000e,0x0006,0xffed,0xfff3,
+0xfff0,0x000a,0xfff8,0xffef,0xffec,0x0002,0xffda,0x0000,
+0xffef,0x0010,0x000b,0xffe5,0xffd4,0xffd3,0x0004,0xfff8,
+0xfff7,0x0001,0x0014,0xffd5,0x0011,0xfffd,0xfff4,0x0000,
+0xffec,0x0004,0x0021,0x001d,0xfffa,0xffea,0xffda,0x0007,
+0x0000,0xffff,0xffe3,0xffe2,0x003f,0x0015,0xfffd,0xfff5,
+0xffe5,0x0001,0x000e,0xffd3,0x000a,0x0009,0xffff,0xfff4,
+0xffd1,0xffdb,0x001c,0x0000,0x0002,0xffe6,0xfffc,0x000d,
+0xffb2,0x0015,0x002b,0xfffc,0x0026,0xffef,0xffef,0x0005,
+0xffc9,0xffe8,0x000f,0x0024,0xfff2,0xfffc,0xffe8,0x0018,
+0xfff4,0xfffb,0xffef,0xffe1,0x0036,0x0005,0x0002,0xffe5,
+0xffd5,0x000c,0xfffe,0xfff7,0x0009,0x000f,0xffea,0x0003,
+0xffe4,0xffeb,0x0014,0xfffd,0xffec,0xffe4,0xfff7,0x0005,
+0x0050,0xfffa,0x0010,0xfff5,0xffe2,0x001e,0x0009,0x001c,
+0x001c,0x001d,0x000d,0xfffa,0x0002,0xffe4,0x0003,0x0005,
+0x0007,0x003c,0xfffb,0xfff7,0xfff5,0x0001,0xffe8,0xffed,
+0x001b,0xfff3,0x0020,0xfff3,0xfff1,0xffed,0xffed,0xffdd,
+0xffef,0x0027,0x002b,0x0009,0xfffc,0xffd6,0xffe0,0xffd7,
+0x000b,0x000e,0x0027,0x001b,0xfff7,0x0011,0x0004,0x0021,
+0xfffa,0x0000,0xfffc,0x0001,0xfffb,0xfff6,0x0011,0x0016,
+0xfffb,0x0039,0x0005,0xfff7,0xffec,0xfff3,0xffee,0xffdd,
+0x000b,0xfffd,0x0010,0x0016,0xffef,0xfff3,0xffd8,0xffed,
+0x0001,0x0037,0x0023,0x0005,0xffe5,0xffd4,0xffdb,0xffcf,
+0x0028,0x0000,0x001c,0xffe8,0xfff2,0x0005,0x0004,0x0015,
+0x0007,0x0021,0x0000,0x0020,0x000f,0xffdd,0xfff4,0xffff,
+0x000b,0x003a,0xfffb,0x0010,0x001c,0x0000,0xffff,0xffdf,
+0x0000,0xfff5,0x0027,0xfffb,0x000e,0xfffa,0xfffd,0xffe1,
+0xffe4,0x0001,0x0035,0x0021,0x0013,0xffe7,0xffd2,0xffe6,
+0xffe4,0x0014,0x0033,0x000e,0x0006,0xfff9,0x0000,0x001a,
+0xffe5,0x0004,0xffee,0x0028,0x0006,0xfff0,0x0001,0x000f,
+0x0000,0x0037,0x0005,0x0010,0x0013,0xfff2,0x0003,0xffcf,
+0xfff2,0xffff,0x0016,0x001e,0x000c,0x0000,0xffe8,0xfff1,
+0xfff7,0x0011,0x002d,0x001d,0xfffc,0xffe4,0xffcd,0xffdd,
+0x0022,0x0004,0x0019,0xfff6,0xfff7,0xffeb,0x0007,0x0024,
+0x001a,0x0024,0x0023,0xffe4,0xfff4,0xffd6,0x0003,0x0010,
+0x000c,0x001c,0xffeb,0xffd6,0x0005,0x0015,0xfff0,0xffe6,
+0x0004,0xffed,0x0013,0xffd9,0xfff1,0xfff1,0xffff,0xfff3,
+0xffed,0x0011,0x0011,0xfff2,0x000f,0xffc9,0xfffc,0xffed,
+0xffde,0x0019,0x0030,0x001c,0x000b,0xffde,0x0002,0x0029,
+0xfff7,0x0007,0x0011,0xffeb,0xffec,0xffe8,0x0011,0x0021,
+0x0000,0x0018,0xfff6,0xffd6,0xfffd,0x0005,0xfff6,0xffd6,
+0xfff5,0xfff8,0x0003,0xfffd,0xfff0,0xfff7,0xffea,0x0002,
+0x0000,0x0021,0x000a,0xffee,0xfff9,0xffc6,0xfff6,0xffe4,
+0xfffc,0x000b,0x0025,0xffe9,0x0005,0xffd2,0x0002,0x001d,
+0x0005,0x0027,0x0015,0x0009,0x0000,0xffcf,0xfff4,0x0009,
+0x0010,0x001a,0xffea,0xfff1,0x002d,0x0014,0x0005,0xffd8,
+0xffea,0xffef,0x001a,0xffe1,0x000e,0xfffe,0x000e,0xfff6,
+0xffe2,0xffec,0x001b,0x0009,0x0027,0xffd9,0xffee,0xfffb,
+0xffb7,0x0020,0x003c,0x000f,0x001a,0xffc5,0xfffe,0x0021,
+0xffe2,0x000a,0x0003,0x0011,0xfff8,0xffe2,0x0001,0x001a,
+0x0004,0x0016,0xfff6,0xfff0,0x0024,0x0005,0x000b,0xffc8,
+0xffdb,0xfffa,0x000a,0x0005,0x000d,0x0003,0xfffa,0x0005,
+0xfff5,0xfffc,0x0013,0x0005,0x0010,0xffd7,0xffe8,0xfff3};
+
+static const unsigned long ftable1[128]={
+0x4cc9f,0x482af,0x47bd8,0x44700,0x5238b,0x47377,0x4898a,0x411fd,
+0x4f8b7,0x4a7d5,0x4bd1b,0x47feb,0x5554b,0x49414,0x4c9d4,0x4403c,
+0x4fa57,0x550c5,0x4ea1c,0x54c6e,0x51f27,0x4ff8f,0x4cab5,0x4bbb6,
+0x53e58,0x5a5e8,0x5551f,0x5d6ff,0x56499,0x540f7,0x528e8,0x51740,
+0x4cdba,0x459db,0x4a644,0x4445b,0x4e123,0x423bc,0x480ed,0x3ed60,
+0x5292b,0x49d33,0x51d8c,0x49f1d,0x53cc4,0x45a9d,0x4e88c,0x43073,
+0x4d3a1,0x4e583,0x4f702,0x5182e,0x4b81f,0x47291,0x49dc4,0x46541,
+0x5434b,0x55bc1,0x5a27e,0x5d510,0x51ba0,0x4c587,0x51f83,0x4d45f,
+0x4d45f,0x51f83,0x4c587,0x51ba0,0x5d510,0x5a27e,0x55bc1,0x5434b,
+0x46541,0x49dc4,0x47291,0x4b81f,0x5182e,0x4f702,0x4e583,0x4d3a1,
+0x43073,0x4e88c,0x45a9d,0x53cc4,0x49f1d,0x51d8c,0x49d33,0x5292b,
+0x3ed60,0x480ed,0x423bc,0x4e123,0x4445b,0x4a644,0x459db,0x4cdba,
+0x51740,0x528e8,0x540f7,0x56499,0x5d6ff,0x5551f,0x5a5e8,0x53e58,
+0x4bbb6,0x4cab5,0x4ff8f,0x51f27,0x54c6e,0x4ea1c,0x550c5,0x4fa57,
+0x4403c,0x4c9d4,0x49414,0x5554b,0x47feb,0x4bd1b,0x4a7d5,0x4f8b7,
+0x411fd,0x4898a,0x47377,0x5238b,0x44700,0x47bd8,0x482af,0x4cc9f};
+
+static const unsigned long ftable2[128]={
+0x2f8e9,0x3444d,0x3637b,0x3608d,0x3372e,0x33ab9,0x33946,0x2f157,
+0x307a1,0x36a4d,0x380c9,0x39279,0x332c0,0x34673,0x33a8a,0x2fec4,
+0x2ecea,0x36011,0x34bb0,0x37829,0x36353,0x39c4a,0x35f32,0x33352,
+0x2cb99,0x33db5,0x3221f,0x3595c,0x31b84,0x35804,0x31d79,0x3075f,
+0x27f6f,0x2f99d,0x2d6c9,0x3369b,0x2df25,0x34928,0x3018c,0x32129,
+0x28cb2,0x31e5c,0x2eebd,0x36c4e,0x2e2a3,0x3601f,0x30a58,0x33aa8,
+0x28cee,0x336a2,0x2e69d,0x37dcd,0x323b6,0x3fa08,0x34b2d,0x3acd3,
+0x27abc,0x3214b,0x2cff6,0x3695f,0x2f09d,0x3ae92,0x315ba,0x37761,
+0x37761,0x315ba,0x3ae92,0x2f09d,0x3695f,0x2cff6,0x3214b,0x27abc,
+0x3acd3,0x34b2d,0x3fa08,0x323b6,0x37dcd,0x2e69d,0x336a2,0x28cee,
+0x33aa8,0x30a58,0x3601f,0x2e2a3,0x36c4e,0x2eebd,0x31e5c,0x28cb2,
+0x32129,0x3018c,0x34928,0x2df25,0x3369b,0x2d6c9,0x2f99d,0x27f6f,
+0x3075f,0x31d79,0x35804,0x31b84,0x3595c,0x3221f,0x33db5,0x2cb99,
+0x33352,0x35f32,0x39c4a,0x36353,0x37829,0x34bb0,0x36011,0x2ecea,
+0x2fec4,0x33a8a,0x34673,0x332c0,0x39279,0x380c9,0x36a4d,0x307a1,
+0x2f157,0x33946,0x33ab9,0x3372e,0x3608d,0x3637b,0x3444d,0x2f8e9};
+
+static const short decodetable1[63]={
+0x0000,0x0006,0x0010,0x0012,0x0014,0x0017,0x0019,0x001d,
+0x0020,0x0024,0x0029,0x002e,0x0033,0x0039,0x0041,0x0049,
+0x0051,0x005b,0x0067,0x0073,0x0081,0x0091,0x00a3,0x00b7,
+0x00cd,0x00e6,0x0103,0x0122,0x0146,0x016d,0x019a,0x01cc,
+0x0204,0x0243,0x028a,0x02da,0x0333,0x0397,0x0407,0x0485,
+0x0512,0x05b0,0x0662,0x0729,0x0809,0x0904,0x0a1e,0x0b5a,
+0x0cbd,0x0e4b,0x1009,0x11fe,0x1430,0x16a7,0x196b,0x1c85,
+0x2000,0x23e7,0x2849,0x2d33,0x32b7,0x38e7,0x3fd9};
+
+static const short decodetable2[127]={
+0xf037,0xf043,0xf04e,0xf058,0xf062,0xf06c,0xf077,0xf082,
+0xf08e,0xf09a,0xf0a6,0xf0b2,0xf0be,0xf0cc,0xf0d9,0xf0e6,
+0xf0f4,0xf101,0xf10f,0xf11e,0xf12d,0xf13d,0xf14c,0xf15c,
+0xf16d,0xf17d,0xf18d,0xf19d,0xf1ae,0xf1bf,0xf1d1,0xf1e3,
+0xf1f6,0xf20a,0xf21d,0xf232,0xf247,0xf25d,0xf274,0xf28c,
+0xf2a4,0xf2bc,0xf2d4,0xf2ee,0xf307,0xf321,0xf33c,0xf358,
+0xf374,0xf391,0xf3af,0xf3ce,0xf3ee,0xf410,0xf433,0xf459,
+0xf480,0xf4a9,0xf4d1,0xf4ff,0xf52c,0xf55c,0xf58c,0xf5c4,
+0xf5fb,0xf637,0xf673,0xf6ad,0xf6e8,0xf727,0xf766,0xf7a7,
+0xf7e8,0xf82a,0xf86b,0xf8ae,0xf8f0,0xf93a,0xf984,0xf9d0,
+0xfa1c,0xfa6c,0xfabc,0xfb0d,0xfb5f,0xfbbe,0xfc1e,0xfc80,
+0xfce2,0xfd45,0xfda8,0xfe19,0xfe8a,0xff0e,0xff92,0x0015,
+0x0098,0x012c,0x01bf,0x0248,0x02d0,0x0353,0x03d6,0x0451,
+0x04cd,0x053e,0x05b0,0x0621,0x0692,0x0707,0x077c,0x07e7,
+0x0852,0x08c2,0x0931,0x09aa,0x0a23,0x0aa4,0x0b25,0x0baa,
+0x0c2e,0x0ca8,0x0d23,0x0d93,0x0e04,0x0e75,0x0ee6};
+
+static const short decodetable3[63]={
+0xf3ed,0xf54d,0xf6ae,0xf7af,0xf8b1,0xf990,0xfa6f,0xfb39,
+0xfc03,0xfcbd,0xfd77,0xfe1d,0xfec4,0xff58,0xffec,0x007b,
+0x010b,0x0196,0x0220,0x02a5,0x032a,0x03a9,0x0429,0x04a1,
+0x0519,0x058c,0x05fe,0x066d,0x06dc,0x0747,0x07b2,0x0817,
+0x087b,0x08d9,0x0937,0x0990,0x09e8,0x0a3a,0x0a8c,0x0ad9,
+0x0b26,0x0b6d,0x0bb4,0x0bf8,0x0c3d,0x0c7e,0x0cbf,0x0cfc,
+0x0d3a,0x0d72,0x0dab,0x0ddf,0x0e13,0x0e44,0x0e75,0x0ea1,
+0x0ecd,0x0ef5,0x0f1e,0x0f44,0x0f6b,0x0f8f,0x0fb4};
+
+static const short decodetable4[63]={
+0xf23b,0xf2ae,0xf321,0xf38c,0xf3f7,0xf457,0xf4b6,0xf517,
+0xf578,0xf5d5,0xf631,0xf68d,0xf6e8,0xf742,0xf79b,0xf7f0,
+0xf845,0xf896,0xf8e7,0xf937,0xf986,0xf9d6,0xfa26,0xfa74,
+0xfac3,0xfb0f,0xfb5c,0xfbaa,0xfbf8,0xfc46,0xfc94,0xfce2,
+0xfd2f,0xfd7f,0xfdcf,0xfe22,0xfe76,0xfec9,0xff1c,0xff73,
+0xffca,0x0020,0x0077,0x00d0,0x0128,0x0186,0x01e4,0x0248,
+0x02ab,0x0315,0x037f,0x03f1,0x0463,0x04e0,0x055d,0x05e8,
+0x0673,0x0710,0x07ad,0x0872,0x0938,0x0a2f,0x0b26};
+
+static const short decodetable5[31]={
+0xf8cb,0xfa55,0xfbdf,0xfcea,0xfdf6,0xfed4,0xffb3,0x006f,
+0x012d,0x01da,0x0287,0x032b,0x03cf,0x046a,0x0505,0x059a,
+0x062e,0x06bf,0x0751,0x07e2,0x0873,0x0904,0x0994,0x0a22,
+0x0aaf,0x0b3c,0x0bc9,0x0c56,0x0ce3,0x0d6a,0x0df1};
+
+static const short decodetable6[31]={
+0xf57d,0xf679,0xf775,0xf83d,0xf904,0xf9b5,0xfa65,0xfb04,
+0xfba2,0xfc2f,0xfcbb,0xfd40,0xfdc5,0xfe44,0xfec4,0xff44,
+0xffc5,0x0047,0x00c9,0x0150,0x01d6,0x0266,0x02f7,0x0396,
+0x0435,0x04f3,0x05b1,0x0692,0x0774,0x0899,0x09bf};
+
+static const short decodetable7[15]={
+0xfaa4,0xfc65,0xfe26,0xff56,0x0085,0x017f,0x0278,0x0362,
+0x044c,0x0537,0x0623,0x071f,0x081b,0x0946,0x0a70};
+
+static const short decodetable8[15]={
+0xf6ab,0xf7d8,0xf905,0xfa1b,0xfb31,0xfc32,0xfd33,0xfe22,
+0xff11,0xfffe,0x00ea,0x01f6,0x0302,0x0462,0x05c2};
+
+static const short decodetable9[15]={
+0xf9df,0xfb3f,0xfca0,0xfdbc,0xfed8,0xffd1,0x00c8,0x01b3,
+0x029e,0x038f,0x047f,0x0596,0x06ad,0x07ff,0x0951};
+
+static const short decodetable10[15]={
+0xf768,0xf890,0xf9b8,0xfac9,0xfbda,0xfcd0,0xfdc7,0xfea8,
+0xff88,0x006c,0x0152,0x0258,0x035f,0x04da,0x0655};
+
+static const short decodetable11[7]={
+0xfd97,0xff2b,0x00be,0x01f0,0x0322,0x0476,0x05cb};
+
+static const short *decodetable[11]={
+decodetable1,decodetable2,decodetable3,decodetable4,decodetable5,
+decodetable6,decodetable7,decodetable8,decodetable9,decodetable10,
+decodetable11};
+
+#endif /* RA144TABLES_H */
diff --git a/contrib/ffmpeg/libavcodec/ra288.c b/contrib/ffmpeg/libavcodec/ra288.c
new file mode 100644
index 000000000..9ba5209ab
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ra288.c
@@ -0,0 +1,258 @@
+/*
+ * 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 "avcodec.h"
+#include "ra288.h"
+
+typedef struct {
+ float history[8];
+ float output[40];
+ float pr1[36];
+ float pr2[10];
+ int phase, phasep;
+
+ float st1a[111],st1b[37],st1[37];
+ float st2a[38],st2b[11],st2[11];
+ float sb[41];
+ float lhist[10];
+} Real288_internal;
+
+static int ra288_decode_init(AVCodecContext * avctx)
+{
+ Real288_internal *glob=avctx->priv_data;
+ memset(glob,0,sizeof(Real288_internal));
+ return 0;
+}
+
+static void prodsum(float *tgt, float *src, int len, int n);
+static void co(int n, int i, int j, float *in, float *out, float *st1, float *st2, const float *table);
+static int pred(float *in, float *tgt, int n);
+static void colmult(float *tgt, float *m1, const float *m2, int n);
+
+
+/* initial decode */
+static void unpack(unsigned short *tgt, unsigned char *src, unsigned int len)
+{
+ int x,y,z;
+ int n,temp;
+ int buffer[len];
+
+ for (x=0;x<len;tgt[x++]=0)
+ buffer[x]=9+(x&1);
+
+ for (x=y=z=0;x<len/*was 38*/;x++) {
+ n=buffer[y]-z;
+ temp=src[x];
+ if (n<8) temp&=255>>(8-n);
+ tgt[y]+=temp<<z;
+ if (n<=8) {
+ tgt[++y]+=src[x]>>n;
+ z=8-n;
+ } else z+=8;
+ }
+}
+
+static void update(Real288_internal *glob)
+{
+ int x,y;
+ float buffer1[40],temp1[37];
+ float buffer2[8],temp2[11];
+
+ for (x=0,y=glob->phasep+5;x<40;buffer1[x++]=glob->output[(y++)%40]);
+ co(36,40,35,buffer1,temp1,glob->st1a,glob->st1b,table1);
+ if (pred(temp1,glob->st1,36))
+ colmult(glob->pr1,glob->st1,table1a,36);
+
+ for (x=0,y=glob->phase+1;x<8;buffer2[x++]=glob->history[(y++)%8]);
+ co(10,8,20,buffer2,temp2,glob->st2a,glob->st2b,table2);
+ if (pred(temp2,glob->st2,10))
+ colmult(glob->pr2,glob->st2,table2a,10);
+}
+
+/* Decode and produce output */
+static void decode(Real288_internal *glob, unsigned int input)
+{
+ unsigned int x,y;
+ float f;
+ double sum,sumsum;
+ float *p1,*p2;
+ float buffer[5];
+ const float *table;
+
+ for (x=36;x--;glob->sb[x+5]=glob->sb[x]);
+ for (x=5;x--;) {
+ p1=glob->sb+x;p2=glob->pr1;
+ for (sum=0,y=36;y--;sum-=(*(++p1))*(*(p2++)));
+ glob->sb[x]=sum;
+ }
+
+ f=amptable[input&7];
+ table=codetable+(input>>3)*5;
+
+ /* convert log and do rms */
+ for (sum=32,x=10;x--;sum-=glob->pr2[x]*glob->lhist[x]);
+ if (sum<0) sum=0; else if (sum>60) sum=60;
+
+ sumsum=exp(sum*0.1151292546497)*f; /* pow(10.0,sum/20)*f */
+ for (sum=0,x=5;x--;) { buffer[x]=table[x]*sumsum; sum+=buffer[x]*buffer[x]; }
+ if ((sum/=5)<1) sum=1;
+
+ /* shift and store */
+ for (x=10;--x;glob->lhist[x]=glob->lhist[x-1]);
+ *glob->lhist=glob->history[glob->phase]=10*log10(sum)-32;
+
+ for (x=1;x<5;x++) for (y=x;y--;buffer[x]-=glob->pr1[x-y-1]*buffer[y]);
+
+ /* output */
+ for (x=0;x<5;x++) {
+ f=glob->sb[4-x]+buffer[x];
+ if (f>4095) f=4095; else if (f<-4095) f=-4095;
+ glob->output[glob->phasep+x]=glob->sb[4-x]=f;
+ }
+}
+
+/* column multiply */
+static void colmult(float *tgt, float *m1, const float *m2, int n)
+{
+ while (n--)
+ *(tgt++)=(*(m1++))*(*(m2++));
+}
+
+static int pred(float *in, float *tgt, int n)
+{
+ int x,y;
+ float *p1,*p2;
+ double f0,f1,f2;
+ float temp;
+
+ if (in[n]==0) return 0;
+ if ((f0=*in)<=0) return 0;
+
+ for (x=1;;x++) {
+ if (n<x) return 1;
+
+ p1=in+x;
+ p2=tgt;
+ f1=*(p1--);
+ for (y=x;--y;f1+=(*(p1--))*(*(p2++)));
+
+ p1=tgt+x-1;
+ p2=tgt;
+ *(p1--)=f2=-f1/f0;
+ for (y=x>>1;y--;) {
+ temp=*p2+*p1*f2;
+ *(p1--)+=*p2*f2;
+ *(p2++)=temp;
+ }
+ if ((f0+=f1*f2)<0) return 0;
+ }
+}
+
+static void co(int n, int i, int j, float *in, float *out, float *st1, float *st2, const float *table)
+{
+ int a,b,c;
+ unsigned int x;
+ float *fp;
+ float buffer1[37];
+ float buffer2[37];
+ float work[111];
+
+ /* rotate and multiply */
+ c=(b=(a=n+i)+j)-i;
+ fp=st1+i;
+ for (x=0;x<b;x++) {
+ if (x==c) fp=in;
+ work[x]=*(table++)*(*(st1++)=*(fp++));
+ }
+
+ prodsum(buffer1,work+n,i,n);
+ prodsum(buffer2,work+a,j,n);
+
+ for (x=0;x<=n;x++) {
+ *st2=*st2*(0.5625)+buffer1[x];
+ out[x]=*(st2++)+buffer2[x];
+ }
+ *out*=1.00390625; /* to prevent clipping */
+}
+
+/* product sum (lsf) */
+static void prodsum(float *tgt, float *src, int len, int n)
+{
+ unsigned int x;
+ float *p1,*p2;
+ double sum;
+
+ while (n>=0)
+ {
+ p1=(p2=src)-n;
+ for (sum=0,x=len;x--;sum+=(*p1++)*(*p2++));
+ tgt[n--]=sum;
+ }
+}
+
+static void * decode_block(AVCodecContext * avctx, unsigned char *in, signed short int *out,unsigned len)
+{
+ int x,y;
+ Real288_internal *glob=avctx->priv_data;
+ unsigned short int buffer[len];
+
+ unpack(buffer,in,len);
+ for (x=0;x<32;x++)
+ {
+ glob->phasep=(glob->phase=x&7)*5;
+ decode(glob,buffer[x]);
+ for (y=0;y<5;*(out++)=8*glob->output[glob->phasep+(y++)]);
+ if (glob->phase==3) update(glob);
+ }
+ return out;
+}
+
+/* Decode a block (celp) */
+static int ra288_decode_frame(AVCodecContext * avctx,
+ void *data, int *data_size,
+ uint8_t * buf, int buf_size)
+{
+ void *datao;
+
+ if (buf_size < avctx->block_align)
+ {
+ av_log(avctx, AV_LOG_ERROR, "ffra288: Error! Input buffer is too small [%d<%d]\n",buf_size,avctx->block_align);
+ return 0;
+ }
+
+ datao = data;
+ data = decode_block(avctx, buf, (signed short *)data, avctx->block_align);
+
+ *data_size = (char *)data - (char *)datao;
+ return avctx->block_align;
+}
+
+AVCodec ra_288_decoder =
+{
+ "real_288",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_RA_288,
+ sizeof(Real288_internal),
+ ra288_decode_init,
+ NULL,
+ NULL,
+ ra288_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/ra288.h b/contrib/ffmpeg/libavcodec/ra288.h
new file mode 100644
index 000000000..8cc290397
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ra288.h
@@ -0,0 +1,205 @@
+/*
+ * 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 RA288TABLES_H
+#define RA288TABLES_H
+
+static const float amptable[8]={ 0.515625, 0.90234375, 1.57910156, 2.76342773,
+ -0.515625,-0.90234375,-1.57910156,-2.76342773 };
+
+static const float codetable[640]={
+ 0.326171875, -1.4404296875, -0.6123046875, -0.8740234375, -1.24658203125,
+ -2.45703125, -2.23486328125, -0.51025390625, 1.419921875, 1.6201171875,
+ -1.37646484375, -1.30712890625, -0.462890625, -1.37939453125, -2.1728515625,
+ -3.26123046875, -0.166015625, 0.7236328125, -0.623046875, 0.6162109375,
+ -0.2744140625, -3.29931640625, 0.62548828125, 0.08740234375, -0.6220703125,
+ -1.2265625, -3.4814453125, -2.40478515625, 3.37548828125, 1.17724609375,
+ -1.2099609375, -0.076171875, 2.28662109375, -1.89111328125, 0,
+ -4.0078125, 1.044921875, -0.2333984375, -1.35986328125, 0.26025390625,
+ 0.92236328125, 1.34716796875, 0.67431640625, -3.39599609375, -2.88720703125,
+ 2.4814453125, -1.201171875, -2.8212890625, 0.87744140625, 0.27734375,
+ -1.078125, -1.61572265625, -2.20849609375, -3.044921875, -3.66455078125,
+ -1.32763671875, 2.1279296875, -1.458984375, -0.56103515625, 1.30078125,
+ 0.61474609375, 0.48583984375, 1.32373046875, -1.203125, -5.0732421875,
+ 0.8408203125, -3.69580078125, -1.3388671875, 1.06005859375, -1.13720703125,
+ 0.50390625, 0.36474609375, -0.4189453125, -3.8798828125, -6.27099609375,
+ 1.5166015625, 2.37109375, -2.04736328125, -1.24072265625, 0.50537109375,
+ 0.9091796875, -0.46875, -3.236328125, 0.2001953125, 2.8720703125,
+ -1.21728515625, -1.283203125, -1.953125, -0.029296875, 3.5166015625,
+ -1.3046875, 0.7060546875, 0.75, -1.87060546875, 0.60205078125,
+ -2.5888671875, 3.375, 0.77587890625, -2.04443359375, 1.78955078125,
+ -1.6875, -3.9892578125, -3.76416015625, 0.67578125, 2.2939453125,
+ -2.29443359375, -3.03173828125, -5.45703125, 3.95703125, 8.2177734375,
+ 0.4541015625, 3.419921875, 0.61962890625, -4.38330078125, 1.25341796875,
+ 2.27001953125, 5.763671875, 1.68017578125, -2.76220703125, 0.58544921875,
+ 1.2412109375, -0.08935546875, -4.32568359375, -3.89453125, 1.5771484375,
+ -1.40234375, -0.98193359375, -4.74267578125, -4.09423828125, 6.33935546875,
+ 1.5068359375, 1.044921875, -1.796875, -4.70849609375, -1.4140625,
+ -3.71533203125, 3.18115234375, -1.11474609375, -1.2314453125, 3.091796875,
+ -1.62744140625, -2.744140625, -4.4580078125, -5.43505859375, 2.70654296875,
+ -0.19873046875, -3.28173828125, -8.5283203125, -1.41064453125, 5.6484375,
+ 1.802734375, 3.318359375, -0.1279296875, -5.2958984375, -0.90625,
+ 3.55224609375, 6.544921875, -1.45947265625, -5.17333984375, 2.41015625,
+ 0.119140625, -1.08349609375, 1.296875, 1.84375, -2.642578125,
+ -1.97412109375, -2.8974609375, 1.04052734375, 0.42138671875, -1.3994140625,
+ -1.6123046875, 0.85107421875, -0.9794921875, -0.0625, -1.001953125,
+ -3.10595703125, 1.6318359375, -0.77294921875, -0.01025390625, 0.5576171875,
+ -1.87353515625, -0.89404296875, 3.12353515625, 1.24267578125, -1.390625,
+ -4.556640625, -3.1875, 2.59228515625, 0.9697265625, -1.09619140625,
+ -2.1923828125, 0.365234375, 0.94482421875, -1.47802734375, -0.24072265625,
+ -4.51904296875, 2.6201171875, 1.55908203125, -2.19384765625, 0.87109375,
+ 2.3359375, -0.1806640625, 0.9111328125, 0.51611328125, -0.92236328125,
+ 3.5849609375, -1.3134765625, -1.25830078125, 0.330078125, -0.29833984375,
+ -0.2451171875, 1.09130859375, -0.9033203125, -0.86767578125, -1.00048828125,
+ 0.49365234375, 1.89453125, -1.20361328125, 1.07861328125, -0.07421875,
+ 1.265625, 1.38134765625, 2.728515625, 1.38623046875, -3.5673828125,
+ -1.48876953125, -2.4013671875, 2.90771484375, 4.49267578125, -2.17138671875,
+ 0.34033203125, 1.908203125, 2.8310546875, -2.17333984375, -2.267578125,
+ -1.03564453125, 2.658203125, -1.2548828125, 0.15673828125, -0.5869140625,
+ 1.3896484375, -1.0185546875, 1.724609375, 0.2763671875, -0.345703125,
+ -2.08935546875, 0.4638671875, 2.431640625, 1.83056640625, 0.220703125,
+ -1.212890625, 1.7099609375, 0.83935546875, -0.0830078125, 0.1162109375,
+ -1.67724609375, 0.12841796875, 1.0322265625, -0.97900390625, 1.15283203125,
+ -3.5830078125, -0.58984375, 4.56396484375, -0.59375, -1.95947265625,
+ -6.5908203125, -0.21435546875, 3.919921875, -2.06640625, 0.17626953125,
+ -1.82080078125, 2.65283203125, 0.978515625, -2.30810546875, -0.61474609375,
+ -1.9462890625, 3.78076171875, 4.11572265625, -1.80224609375, -0.48193359375,
+ 2.5380859375, -0.20654296875, 0.5615234375, -0.62548828125, 0.3984375,
+ 3.61767578125, 2.00634765625, -1.92822265625, 1.3134765625, 0.0146484384313,
+ 0.6083984375, 1.49169921875, -0.01708984375, -0.6689453125, -0.1201171875,
+ -0.72705078125, 2.75146484375, -0.3310546875, -1.28271484375, 1.5478515625,
+ 2.3583984375, -2.23876953125, 0.98046875, -0.5185546875, 0.39013671875,
+ -0.06298828125, 0.35009765625, 2.2431640625, 7.29345703125, 5.2275390625,
+ 0.20361328125, 1.34716796875, 0.9033203125, -2.46923828125, -0.56298828125,
+ -1.89794921875, 3.59423828125, -2.81640625, 2.09228515625, 0.3251953125,
+ 0.70458984375, -0.4580078125, 0.009765625, -1.03466796875, -0.82861328125,
+ -1.8125, -1.6611328125, -1.080078125, 0.0537109375, 1.04296875,
+ -1.44140625, 0.005859375, -0.765625, -1.708984375, -0.90576171875,
+ -0.64208984375, -0.84521484375, 0.56640625, -0.2724609375, 0.83447265625,
+ 0.04296875, -2.23095703125, 0.0947265625, -0.2216796875, -1.44384765625,
+ -1.38623046875, -0.8134765625, -0.13330078125, 1.017578125, -0.07568359375,
+ -0.09228515625, -1.16015625, 0.81201171875, -0.5078125, -1.19580078125,
+ -1.3876953125, -0.66845703125, 0.310546875, -0.12109375, -1.30712890625,
+ 0.74072265625, 0.03857421875, -1.47119140625, -1.79150390625, -0.47509765625,
+ 0.93408203125, -1.21728515625, -2.59375, -0.36572265625, 0.62060546875,
+ -1.41748046875, -1.623046875, -1.833984375, -1.8017578125, -0.89306640625,
+ -1.42236328125, -0.75537109375, -1.34765625, -0.6865234375, 0.548828125,
+ 0.900390625, -0.8955078125, 0.22265625, 0.3447265625, -2.0859375,
+ 0.22802734375, -2.078125, -0.93212890625, 0.74267578125, 0.5537109375,
+ -0.06201171875, -0.4853515625, -0.31103515625, -0.72802734375, -3.1708984375,
+ 0.42626953125, -0.99853515625, -1.869140625, -1.36328125, -0.2822265625,
+ 1.12841796875, -0.88720703125, 1.28515625, -1.490234375, 0.9609375,
+ 0.31298828125, 0.5830078125, 0.92431640625, 2.00537109375, 3.0966796875,
+ -0.02197265625, 0.5849609375, 1.0546875, -0.70751953125, 1.07568359375,
+ -0.978515625, 0.83642578125, 1.7177734375, 1.294921875, 2.07568359375,
+ 1.43359375, -1.9375, 0.625, 0.06396484375, -0.720703125,
+ 1.38037109375, 0.00390625, -0.94140625, 1.2978515625, 1.71533203125,
+ 1.56201171875, -0.3984375, 1.31201171875, -0.85009765625, -0.68701171875,
+ 1.439453125, 1.96728515625, 0.1923828125, -0.12353515625, 0.6337890625,
+ 2.0927734375, 0.02490234375, -2.20068359375, -0.015625, -0.32177734375,
+ 1.90576171875, 2.7568359375, -2.728515625, -1.265625, 2.78662109375,
+ -0.2958984375, 0.6025390625, -0.78466796875, -2.53271484375, 0.32421875,
+ -0.25634765625, 1.767578125, -1.0703125, -1.23388671875, 0.83349609375,
+ 2.09814453125, -1.58740234375, -1.11474609375, 0.396484375, -1.10546875,
+ 2.81494140625, 0.2578125, -1.60498046875, 0.66015625, 0.81640625,
+ 1.33544921875, 0.60595703125, -0.53857421875, -1.59814453125, -1.66357421875,
+ 1.96923828125, 0.8046875, -1.44775390625, -0.5732421875, 0.705078125,
+ 0.0361328125, 0.4482421875, 0.97607421875, 0.44677734375, -0.5009765625,
+ -1.21875, -0.78369140625, 0.9931640625, 1.4404296875, 0.11181640625,
+ -1.05859375, 0.99462890625, 0.00732421921566,-0.6171875, -0.1015625,
+ -1.734375, 0.7470703125, 0.28369140625, 0.72802734375, 0.4697265625,
+ -1.27587890625, -1.1416015625, 1.76806640625, -0.7265625, -1.06689453125,
+ -0.85302734375, 0.03955078125, 2.7041015625, 0.69921875, -1.10205078125,
+ -0.49755859375, 0.42333984375, 0.1044921875, -1.115234375, -0.7373046875,
+ -0.822265625, 1.375, -0.11181640625, 1.24560546875, -0.67822265625,
+ 1.32177734375, 0.24609375, 0.23388671875, 1.35888671875, -0.49267578125,
+ 1.22900390625, -0.72607421875, -0.779296875, 0.30322265625, 0.94189453125,
+ -0.072265625, 1.0771484375, -2.09375, 0.630859375, -0.68408203125,
+ -0.25732421875, 0.60693359375, -1.33349609375, 0.93212890625, 0.625,
+ 1.04931640625, -0.73291015625, 1.80078125, 0.2978515625, -2.24169921875,
+ 1.6142578125, -1.64501953125, 0.91552734375, 1.775390625, -0.59423828125,
+ 1.2568359375, 1.22705078125, 0.70751953125, -1.5009765625, -2.43115234375,
+ 0.3974609375, 0.8916015625, -1.21923828125, 2.0673828125, -1.99072265625,
+ 0.8125, -0.107421875, 1.6689453125, 0.4892578125, 0.54443359375,
+ 0.38134765625, 0.8095703125, 1.91357421875, 2.9931640625, 1.533203125,
+ 0.560546875, 1.98486328125, 0.740234375, 0.39794921875, 0.09716796875,
+ 0.58154296875, 1.21533203125, 1.25048828125, 1.18212890625, 1.19287109375,
+ 0.3759765625, -2.88818359375, 2.69287109375, -0.1796875, -1.56201171875,
+ 0.5810546875, 0.51123046875, 1.8271484375, 3.38232421875, -1.02001953125,
+ 0.142578125, 1.51318359375, 2.103515625, -0.3701171875, -1.19873046875,
+ 0.25537109375, 1.91455078125, 1.974609375, 0.6767578125, 0.04150390625,
+ 2.13232421875, 0.4912109375, -0.611328125, -0.7158203125, -0.67529296875,
+ 1.880859375, 0.77099609375, -0.03759765625, 1.0078125, 0.423828125,
+ 2.49462890625, 1.42529296875, -0.0986328125, 0.17529296875, -0.24853515625,
+ 1.7822265625, 1.5654296875, 1.12451171875, 0.82666015625, 0.6328125,
+ 1.41845703125, -1.90771484375, 0.11181640625, -0.583984375, -1.138671875,
+ 2.91845703125, -1.75048828125, 0.39306640625, 1.86767578125, -1.5322265625,
+ 1.8291015625, -0.2958984375, 0.02587890625, -0.13134765625, -1.61181640625,
+ 0.2958984375, 0.9853515625, -0.642578125, 1.984375, 0.1943359375
+};
+
+static const float table1[111]={
+ 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
+};
+
+static const float table2[38]={
+ 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
+};
+
+static const float table1a[36]={
+ 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
+};
+
+static const float table2a[10]={
+ 0.90625, 0.821289063, 0.74432373, 0.674499512, 0.61126709,
+ 0.553955078, 0.50201416, 0.454956055, 0.41229248, 0.373657227
+};
+
+#endif /* RA288TABLES_H */
diff --git a/contrib/ffmpeg/libavcodec/rangecoder.c b/contrib/ffmpeg/libavcodec/rangecoder.c
new file mode 100644
index 000000000..1f35d0852
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/rangecoder.c
@@ -0,0 +1,181 @@
+/*
+ * Range coder
+ * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/**
+ * @file rangecoder.c
+ * 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 <string.h>
+
+#include "avcodec.h"
+#include "common.h"
+#include "rangecoder.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 =(*c->bytestream++)<<8;
+ c->low+= *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));
+
+#if 0
+ for(i=1; i<256; i++){
+ if(c->one_state[i])
+ continue;
+
+ p= (i*one + 128) >> 8;
+ last_p8= i;
+ for(;;){
+ p+= ((one-p)*factor + one/2) >> 32;
+ p8= (256*p + one/2) >> 32; //FIXME try without the one
+ if(p8 <= last_p8) p8= last_p8+1;
+ if(p8 > max_p) p8= max_p;
+ if(p8 < last_p8)
+ break;
+ c->one_state[last_p8]= p8;
+ if(p8 == last_p8)
+ break;
+ last_p8= p8;
+ }
+ }
+#endif
+#if 1
+ 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;
+ }
+#endif
+ 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];
+#if 0
+ for(i=0; i<256; i++)
+ av_log(NULL, AV_LOG_DEBUG, "%3d %3d\n", i, c->one_state[i]);
+#endif
+}
+
+/**
+ *
+ * @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);
+
+ assert(c->low == 0);
+ assert(c->range >= 0x100);
+
+ return c->bytestream - c->bytestream_start;
+}
+
+#if 0 //selftest
+#define SIZE 10240
+int main(){
+ RangeCoder c;
+ uint8_t b[9*SIZE];
+ uint8_t r[9*SIZE];
+ int i;
+ uint8_t state[10]= {0};
+
+ 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]= random()%7;
+ }
+
+
+ for(i=0; i<SIZE; i++){
+START_TIMER
+ put_rac(&c, state, r[i]&1);
+STOP_TIMER("put_rac")
+ }
+
+ ff_put_rac_terminate(&c);
+
+ ff_init_range_decoder(&c, b, SIZE);
+
+ memset(state, 128, sizeof(state));
+
+ for(i=0; i<SIZE; i++){
+START_TIMER
+ if( (r[i]&1) != get_rac(&c, state) )
+ av_log(NULL, AV_LOG_DEBUG, "rac failure at %d\n", i);
+STOP_TIMER("get_rac")
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/contrib/ffmpeg/libavcodec/rangecoder.h b/contrib/ffmpeg/libavcodec/rangecoder.h
new file mode 100644
index 000000000..68bd3b60e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/rangecoder.h
@@ -0,0 +1,127 @@
+/*
+ * Range coder
+ * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/**
+ * @file rangecoder.h
+ * Range coder.
+ */
+
+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 void put_rac(RangeCoder *c, uint8_t * const state, int bit){
+ int range1= (c->range * (*state)) >> 8;
+
+ assert(*state);
+ assert(range1 < c->range);
+ assert(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 attribute_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
+}
+
diff --git a/contrib/ffmpeg/libavcodec/ratecontrol.c b/contrib/ffmpeg/libavcodec/ratecontrol.c
new file mode 100644
index 000000000..d96c837e6
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ratecontrol.c
@@ -0,0 +1,944 @@
+/*
+ * Rate control for video encoders
+ *
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file ratecontrol.c
+ * Rate control for video encoders.
+ */
+
+#include "avcodec.h"
+#include "dsputil.h"
+#include "ratecontrol.h"
+#include "mpegvideo.h"
+#include "eval.h"
+
+#undef NDEBUG // allways check asserts, the speed effect is far too small to disable them
+#include <assert.h>
+
+#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->display_picture_number, s->current_picture_ptr->coded_picture_number, s->pict_type,
+ s->current_picture.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 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;
+ char *error = NULL;
+ static const char *const_names[]={
+ "PI",
+ "E",
+ "iTex",
+ "pTex",
+ "tex",
+ "mv",
+ "fCode",
+ "iCount",
+ "mcVar",
+ "var",
+ "isI",
+ "isP",
+ "isB",
+ "avgQP",
+ "qComp",
+/* "lastIQP",
+ "lastPQP",
+ "lastBQP",
+ "nextNonBQP",*/
+ "avgIITex",
+ "avgPITex",
+ "avgPPTex",
+ "avgBPTex",
+ "avgTex",
+ NULL
+ };
+ static double (*func1[])(void *, double)={
+ (void *)bits2qp,
+ (void *)qp2bits,
+ NULL
+ };
+ static const char *func1_names[]={
+ "bits2qp",
+ "qp2bits",
+ NULL
+ };
+ emms_c();
+
+ rcc->rc_eq_eval = ff_parse(s->avctx->rc_eq, const_names, func1, func1_names, NULL, NULL, &error);
+ if (!rcc->rc_eq_eval) {
+ av_log(s->avctx, AV_LOG_ERROR, "Error parsing rc_eq \"%s\": %s\n", s->avctx->rc_eq, error? error : "");
+ return -1;
+ }
+
+ 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 cuz of 1/0 and such
+ rcc->last_qscale_for[i]=FF_QP2LAMBDA * 5;
+ }
+ rcc->buffer_index= s->avctx->rc_initial_buffer_occupancy;
+
+ 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 = (RateControlEntry*)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=P_TYPE;
+ 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 unbelieavle slow on looong strings //FIXME copy / dont 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) {
+#ifdef CONFIG_XVID
+ 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;
+
+ /* 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;
+ double q;
+
+ if (i%((s->gop_size+3)/4)==0) rce.pict_type= I_TYPE;
+ else if(i%(s->max_b_frames+1)) rce.pict_type= B_TYPE;
+ else rce.pict_type= P_TYPE;
+
+ 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== I_TYPE){
+ 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] ++;
+
+ bits= rce.i_tex_bits + rce.p_tex_bits;
+
+ q= get_qscale(s, &rce, rcc->pass1_wanted_bits/rcc->pass1_rc_eq_output_sum, i);
+ rcc->pass1_wanted_bits+= s->bit_rate/(1/av_q2d(s->avctx->time_base)); //FIXME missbehaves a little for variable fps
+ }
+ }
+
+ }
+
+ return 0;
+}
+
+void ff_rate_control_uninit(MpegEncContext *s)
+{
+ RateControlContext *rcc= &s->rc_context;
+ emms_c();
+
+ ff_eval_free(rcc->rc_eq_eval);
+ av_freep(&rcc->entry);
+
+#ifdef CONFIG_XVID
+ 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= 1/av_q2d(s->avctx->time_base);
+ 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;
+
+//printf("%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 += 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 == 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;
+}
+
+/**
+ * modifies 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;
+ double q, bits;
+ const int pict_type= rce->new_pict_type;
+ const double mb_num= s->mb_num;
+ 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 == B_TYPE ? (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 == I_TYPE,
+ rce->pict_type == P_TYPE,
+ rce->pict_type == B_TYPE,
+ rcc->qscale_sum[pict_type] / (double)rcc->frame_count[pict_type],
+ a->qcompress,
+/* rcc->last_qscale_for[I_TYPE],
+ rcc->last_qscale_for[P_TYPE],
+ rcc->last_qscale_for[B_TYPE],
+ rcc->next_non_b_qscale,*/
+ rcc->i_cplx_sum[I_TYPE] / (double)rcc->frame_count[I_TYPE],
+ rcc->i_cplx_sum[P_TYPE] / (double)rcc->frame_count[P_TYPE],
+ rcc->p_cplx_sum[P_TYPE] / (double)rcc->frame_count[P_TYPE],
+ rcc->p_cplx_sum[B_TYPE] / (double)rcc->frame_count[B_TYPE],
+ (rcc->i_cplx_sum[pict_type] + rcc->p_cplx_sum[pict_type]) / (double)rcc->frame_count[pict_type],
+ 0
+ };
+
+ bits= ff_parse_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==I_TYPE && s->avctx->i_quant_factor<0.0)
+ q= -q*s->avctx->i_quant_factor + s->avctx->i_quant_offset;
+ else if(pict_type==B_TYPE && s->avctx->b_quant_factor<0.0)
+ q= -q*s->avctx->b_quant_factor + s->avctx->b_quant_offset;
+
+ 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[P_TYPE];
+ const double last_non_b_q= rcc->last_qscale_for[rcc->last_non_b_pict_type];
+
+ if (pict_type==I_TYPE && (a->i_quant_factor>0.0 || rcc->last_non_b_pict_type==P_TYPE))
+ q= last_p_q *FFABS(a->i_quant_factor) + a->i_quant_offset;
+ else if(pict_type==B_TYPE && a->b_quant_factor>0.0)
+ q= last_non_b_q* a->b_quant_factor + a->b_quant_offset;
+
+ /* last qscale / qdiff stuff */
+ if(rcc->last_non_b_pict_type==pict_type || pict_type!=I_TYPE){
+ 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 cant do that after blurring
+
+ if(pict_type!=B_TYPE)
+ rcc->last_non_b_pict_type= pict_type;
+
+ return q;
+}
+
+/**
+ * gets 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);
+
+ if(pict_type==B_TYPE){
+ 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);
+ }else if(pict_type==I_TYPE){
+ 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);
+ }
+
+ qmin= clip(qmin, 1, FF_LAMBDA_MAX);
+ qmax= 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;
+ int qmin, qmax;
+ double bits;
+ const int pict_type= rce->new_pict_type;
+ const double buffer_size= s->avctx->rc_buffer_size;
+ const double fps= 1/av_q2d(s->avctx->time_base);
+ const double min_rate= s->avctx->rc_min_rate / fps;
+ const double max_rate= s->avctx->rc_max_rate / fps;
+
+ get_qminmax(&qmin, &qmax, s, pict_type);
+
+ /* modulation */
+ if(s->avctx->rc_qmod_freq && frame_num%s->avctx->rc_qmod_freq==0 && pict_type==P_TYPE)
+ q*= s->avctx->rc_qmod_amp;
+
+ bits= qp2bits(rce, q);
+//printf("q:%f\n", q);
+ /* 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)*3, 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/3, 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;
+ }
+ }
+ }
+//printf("q:%f max:%f min:%f size:%f index:%d bits:%f agr:%f\n", q,max_rate, min_rate, buffer_size, rcc->buffer_index, bits, 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 double predict_qp(Predictor *p, double size, double var)
+{
+//printf("coeff:%f, count:%f, var:%f, size:%f//\n", p->coeff, p->count, var, size);
+ return p->coeff*var / (size*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->mb_num];
+ float bits_tab[s->mb_num];
+ 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 0
+ if(spat_cplx < q/3) spat_cplx= q/3; //FIXME finetune
+ if(temp_cplx < q/3) temp_cplx= q/3; //FIXME finetune
+#endif
+ 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 cliping */
+ 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;
+//if(i%s->mb_width==0) printf("\n");
+//printf("%2d%3d ", intq, ff_sqrt(s->mc_mb_var[i]));
+ s->lambda_table[mb_xy]= intq;
+ }
+}
+
+void ff_get_2pass_fcode(MpegEncContext *s){
+ RateControlContext *rcc= &s->rc_context;
+ int picture_number= s->picture_number;
+ RateControlEntry *rce;
+
+ rce= &rcc->entry[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();
+
+#ifdef CONFIG_XVID
+ 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= 1/av_q2d(s->avctx->time_base);
+//printf("input_pic_num:%d pic_num:%d frame_rate:%d\n", s->input_picture_number, s->picture_number, s->frame_rate);
+ /* update predictors */
+ if(picture_number>2 && !dry_run){
+ const int last_var= s->last_pict_type == I_TYPE ? rcc->last_mb_var_sum : rcc->last_mc_mb_var_sum;
+ update_predictor(&rcc->pred[s->last_pict_type], rcc->last_qscale, sqrt(last_var), s->frame_bits);
+ }
+
+ if(s->flags&CODEC_FLAG_PASS2){
+ assert(picture_number>=0);
+ assert(picture_number<rcc->num_entries);
+ rce= &rcc->entry[picture_number];
+ wanted_bits= rce->expected_bits;
+ }else{
+ rce= &local_rce;
+ wanted_bits= (uint64_t)(s->bit_rate*(double)picture_number/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 == I_TYPE ? pic->mb_var_sum : pic->mc_mb_var_sum;
+
+ short_term_q = 0; /* avoid warning */
+ if(s->flags&CODEC_FLAG_PASS2){
+ if(pict_type!=I_TYPE)
+ assert(pict_type == rce->new_pict_type);
+
+ q= rce->new_qscale / br_compensation;
+//printf("%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== I_TYPE){
+ 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);
+//printf("%f ", q);
+ q= get_diff_limited_q(s, rce, q);
+//printf("%f ", q);
+ assert(q>0.0);
+
+ if(pict_type==P_TYPE || s->intra_only){ //FIXME type dependant blur like in 2-pass
+ rcc->short_term_qsum*=a->qblur;
+ rcc->short_term_qcount*=a->qblur;
+
+ rcc->short_term_qsum+= q;
+ rcc->short_term_qcount++;
+//printf("%f ", q);
+ q= short_term_q= rcc->short_term_qsum/rcc->short_term_qcount;
+//printf("%f ", q);
+ }
+ 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_pict_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;
+ }
+#if 0
+{
+ static int mvsum=0, texsum=0;
+ mvsum += s->mv_bits;
+ texsum += s->i_tex_bits + s->p_tex_bits;
+ printf("%d %d//\n\n", mvsum, texsum);
+}
+#endif
+ 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= 1/av_q2d(s->avctx->time_base);
+ double complexity[5]={0,0,0,0,0}; // aproximate bits at quant=1
+ uint64_t const_bits[5]={0,0,0,0,0}; // quantizer idependant 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;
+ //int last_i_frame=-10000000;
+ const int filter_size= (int)(a->qblur*4) | 1;
+ double expected_bits;
+ double *qscale, *blured_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[I_TYPE] + const_bits[P_TYPE] + const_bits[B_TYPE];
+
+ 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);
+ blured_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++){
+ qscale[i]= get_qscale(s, &rcc->entry[i], rate_factor, i);
+ }
+ assert(filter_size%2==1);
+
+ /* fixed I/B QP relative to P mode */
+ 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;
+ }
+ blured_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, blured_qscale[i], i);
+ bits= qp2bits(rce, rce->new_qscale) + rce->mv_bits + rce->misc_bits;
+//printf("%d %f\n", rce->new_bits, blured_qscale[i]);
+ bits += 8*ff_vbv_update(s, bits);
+
+ rce->expected_bits= expected_bits;
+ expected_bits += bits;
+ }
+
+ /*
+ av_log(s->avctx, AV_LOG_INFO,
+ "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(blured_qscale);
+
+ /* check bitrate calculations and print info */
+ qscale_sum = 0.0;
+ for(i=0; i<rcc->num_entries; i++){
+ /* av_log(s->avctx, AV_LOG_DEBUG, "[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 += 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/contrib/ffmpeg/libavcodec/ratecontrol.h b/contrib/ffmpeg/libavcodec/ratecontrol.h
new file mode 100644
index 000000000..c428923a5
--- /dev/null
+++ b/contrib/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.h
+ * ratecontrol header.
+ */
+
+#include "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{
+ FILE *stats_file;
+ 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
+ AVEvalExpr * 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/contrib/ffmpeg/libavcodec/raw.c b/contrib/ffmpeg/libavcodec/raw.c
new file mode 100644
index 000000000..f4fddf73c
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/raw.c
@@ -0,0 +1,210 @@
+/*
+ * 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.c
+ * Raw Video Codec
+ */
+
+#include "avcodec.h"
+
+typedef struct RawVideoContext {
+ unsigned char * buffer; /* block of memory for holding one frame */
+ int length; /* number of bytes in buffer */
+ AVFrame pic; ///< AVCodecContext.coded_frame
+} RawVideoContext;
+
+typedef struct PixelFormatTag {
+ int pix_fmt;
+ unsigned int fourcc;
+} PixelFormatTag;
+
+static const PixelFormatTag pixelFormatTags[] = {
+ { PIX_FMT_YUV420P, MKTAG('I', '4', '2', '0') }, /* Planar formats */
+ { PIX_FMT_YUV420P, MKTAG('I', 'Y', 'U', 'V') },
+ { PIX_FMT_YUV420P, MKTAG('Y', 'V', '1', '2') },
+ { PIX_FMT_YUV410P, MKTAG('Y', 'U', 'V', '9') },
+ { PIX_FMT_YUV411P, MKTAG('Y', '4', '1', 'B') },
+ { PIX_FMT_YUV422P, MKTAG('Y', '4', '2', 'B') },
+ { PIX_FMT_GRAY8, MKTAG('Y', '8', '0', '0') },
+ { PIX_FMT_GRAY8, MKTAG(' ', ' ', 'Y', '8') },
+
+
+ { PIX_FMT_YUV422, MKTAG('Y', 'U', 'Y', '2') }, /* Packed formats */
+ { PIX_FMT_YUV422, MKTAG('Y', '4', '2', '2') },
+ { PIX_FMT_UYVY422, MKTAG('U', 'Y', 'V', 'Y') },
+ { PIX_FMT_GRAY8, MKTAG('G', 'R', 'E', 'Y') },
+ { PIX_FMT_RGB555, MKTAG('R', 'G', 'B', 15) },
+ { PIX_FMT_BGR555, MKTAG('B', 'G', 'R', 15) },
+ { PIX_FMT_RGB565, MKTAG('R', 'G', 'B', 16) },
+ { PIX_FMT_BGR565, MKTAG('B', 'G', 'R', 16) },
+
+ /* quicktime */
+ { PIX_FMT_UYVY422, MKTAG('2', 'v', 'u', 'y') },
+
+ { -1, 0 },
+};
+
+static int findPixelFormat(unsigned int fourcc)
+{
+ const PixelFormatTag * tags = pixelFormatTags;
+ while (tags->pix_fmt >= 0) {
+ if (tags->fourcc == fourcc)
+ return tags->pix_fmt;
+ tags++;
+ }
+ return PIX_FMT_YUV420P;
+}
+
+unsigned int avcodec_pix_fmt_to_codec_tag(enum PixelFormat fmt)
+{
+ const PixelFormatTag * tags = pixelFormatTags;
+ while (tags->pix_fmt >= 0) {
+ if (tags->pix_fmt == fmt)
+ return tags->fourcc;
+ tags++;
+ }
+ return 0;
+}
+
+/* RAW Decoder Implementation */
+
+static int raw_init_decoder(AVCodecContext *avctx)
+{
+ RawVideoContext *context = avctx->priv_data;
+
+ if (avctx->codec_tag)
+ avctx->pix_fmt = findPixelFormat(avctx->codec_tag);
+ else if (avctx->bits_per_sample){
+ switch(avctx->bits_per_sample){
+ case 8: avctx->pix_fmt= PIX_FMT_PAL8 ; break;
+ case 15: avctx->pix_fmt= PIX_FMT_RGB555; break;
+ case 16: avctx->pix_fmt= PIX_FMT_RGB555; break;
+ case 24: avctx->pix_fmt= PIX_FMT_BGR24 ; break;
+ case 32: avctx->pix_fmt= PIX_FMT_RGBA32; break;
+ }
+ }
+
+ context->length = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height);
+ context->buffer = av_malloc(context->length);
+ context->pic.pict_type = FF_I_TYPE;
+ context->pic.key_frame = 1;
+
+ avctx->coded_frame= &context->pic;
+
+ if (!context->buffer)
+ return -1;
+
+ return 0;
+}
+
+static void flip(AVCodecContext *avctx, AVPicture * picture){
+ if(!avctx->codec_tag && avctx->bits_per_sample && picture->linesize[2]==0){
+ picture->data[0] += picture->linesize[0] * (avctx->height-1);
+ picture->linesize[0] *= -1;
+ }
+}
+
+static int raw_decode(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ RawVideoContext *context = avctx->priv_data;
+
+ AVFrame * frame = (AVFrame *) data;
+ AVPicture * picture = (AVPicture *) data;
+
+ frame->interlaced_frame = avctx->coded_frame->interlaced_frame;
+ frame->top_field_first = avctx->coded_frame->top_field_first;
+
+ if(buf_size < context->length - (avctx->pix_fmt==PIX_FMT_PAL8 ? 256*4 : 0))
+ return -1;
+
+ avpicture_fill(picture, buf, avctx->pix_fmt, avctx->width, avctx->height);
+ if(avctx->pix_fmt==PIX_FMT_PAL8 && buf_size < context->length){
+ frame->data[1]= context->buffer;
+ }
+ if (avctx->palctrl && avctx->palctrl->palette_changed) {
+ memcpy(frame->data[1], avctx->palctrl->palette, AVPALETTE_SIZE);
+ avctx->palctrl->palette_changed = 0;
+ }
+
+ flip(avctx, picture);
+
+ if (avctx->codec_tag == MKTAG('Y', 'V', '1', '2'))
+ {
+ // swap fields
+ unsigned char *tmp = picture->data[1];
+ picture->data[1] = picture->data[2];
+ picture->data[2] = tmp;
+ }
+
+ *data_size = sizeof(AVPicture);
+ return buf_size;
+}
+
+static int raw_close_decoder(AVCodecContext *avctx)
+{
+ RawVideoContext *context = avctx->priv_data;
+
+ av_freep(&context->buffer);
+ return 0;
+}
+
+/* RAW Encoder Implementation */
+#ifdef CONFIG_RAWVIDEO_ENCODER
+static int raw_init_encoder(AVCodecContext *avctx)
+{
+ avctx->coded_frame = (AVFrame *)avctx->priv_data;
+ avctx->coded_frame->pict_type = FF_I_TYPE;
+ avctx->coded_frame->key_frame = 1;
+ if(!avctx->codec_tag)
+ avctx->codec_tag = avcodec_pix_fmt_to_codec_tag(avctx->pix_fmt);
+ return 0;
+}
+
+static int raw_encode(AVCodecContext *avctx,
+ unsigned char *frame, int buf_size, void *data)
+{
+ return avpicture_layout((AVPicture *)data, avctx->pix_fmt, avctx->width,
+ avctx->height, frame, buf_size);
+}
+
+AVCodec rawvideo_encoder = {
+ "rawvideo",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_RAWVIDEO,
+ sizeof(AVFrame),
+ raw_init_encoder,
+ raw_encode,
+};
+#endif // CONFIG_RAWVIDEO_ENCODER
+
+AVCodec rawvideo_decoder = {
+ "rawvideo",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_RAWVIDEO,
+ sizeof(RawVideoContext),
+ raw_init_decoder,
+ NULL,
+ raw_close_decoder,
+ raw_decode,
+};
diff --git a/contrib/ffmpeg/libavcodec/resample.c b/contrib/ffmpeg/libavcodec/resample.c
new file mode 100644
index 000000000..043e812c8
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/resample.c
@@ -0,0 +1,249 @@
+/*
+ * Sample rate convertion 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 resample.c
+ * Sample rate convertion for both audio and video.
+ */
+
+#include "avcodec.h"
+
+struct AVResampleContext;
+
+struct ReSampleContext {
+ struct AVResampleContext *resample_context;
+ short *temp[2];
+ int temp_len;
+ float ratio;
+ /* channel convert */
+ int input_channels, output_channels, filter_channels;
+};
+
+/* 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--;
+ }
+}
+
+/* XXX: should use more abstract 'N' channels system */
+static void stereo_split(short *output1, short *output2, short *input, int n)
+{
+ int i;
+
+ for(i=0;i<n;i++) {
+ *output1++ = *input++;
+ *output2++ = *input++;
+ }
+}
+
+static void stereo_mux(short *output, short *input1, short *input2, int n)
+{
+ int i;
+
+ for(i=0;i<n;i++) {
+ *output++ = *input1++;
+ *output++ = *input2++;
+ }
+}
+
+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 */
+ }
+}
+
+ReSampleContext *audio_resample_init(int output_channels, int input_channels,
+ int output_rate, int input_rate)
+{
+ ReSampleContext *s;
+
+ if ( input_channels > 2)
+ {
+ av_log(NULL, AV_LOG_ERROR, "Resampling with input channels greater than 2 unsupported.");
+ return NULL;
+ }
+
+ s = av_mallocz(sizeof(ReSampleContext));
+ if (!s)
+ {
+ av_log(NULL, AV_LOG_ERROR, "Can't allocate memory for resample context.");
+ return NULL;
+ }
+
+ s->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;
+
+/*
+ * ac3 output is the only case where filter_channels could be greater than 2.
+ * input channels can't be greater than 2, so resample the 2 channels and then
+ * expand to 6 channels after the resampling.
+ */
+ if(s->filter_channels>2)
+ s->filter_channels = 2;
+
+ s->resample_context= av_resample_init(output_rate, input_rate, 16, 10, 0, 1.0);
+
+ 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[2];
+ short *bufout[2];
+ short *buftmp2[2], *buftmp3[2];
+ 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;
+ }
+
+ /* XXX: move those malloc to resample init code */
+ for(i=0; i<s->filter_channels; i++){
+ bufin[i]= (short*) 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;
+ }
+
+ /* make some zoom to avoid round pb */
+ lenout= (int)(nb_samples * s->ratio) + 16;
+ bufout[0]= (short*) av_malloc( lenout * sizeof(short) );
+ bufout[1]= (short*) 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->output_channels >= 2) {
+ buftmp3[0] = bufout[0];
+ buftmp3[1] = bufout[1];
+ stereo_split(buftmp2[0], buftmp2[1], input, 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 == 2) {
+ stereo_mux(output, buftmp3[0], buftmp3[1], nb_samples1);
+ } else if (s->output_channels == 6) {
+ ac3_5p1_mux(output, buftmp3[0], buftmp3[1], nb_samples1);
+ }
+
+ for(i=0; i<s->filter_channels; i++)
+ av_free(bufin[i]);
+
+ av_free(bufout[0]);
+ av_free(bufout[1]);
+ return nb_samples1;
+}
+
+void audio_resample_close(ReSampleContext *s)
+{
+ av_resample_close(s->resample_context);
+ av_freep(&s->temp[0]);
+ av_freep(&s->temp[1]);
+ av_free(s);
+}
diff --git a/contrib/ffmpeg/libavcodec/resample2.c b/contrib/ffmpeg/libavcodec/resample2.c
new file mode 100644
index 000000000..3ae0ba855
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/resample2.c
@@ -0,0 +1,274 @@
+/*
+ * audio resampling
+ * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/**
+ * @file resample2.c
+ * audio resampling
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#include "avcodec.h"
+#include "common.h"
+#include "dsputil.h"
+
+#if 1
+#define FILTER_SHIFT 15
+
+#define FELEM int16_t
+#define FELEM2 int32_t
+#define FELEM_MAX INT16_MAX
+#define FELEM_MIN INT16_MIN
+#else
+#define FILTER_SHIFT 22
+
+#define FELEM int32_t
+#define FELEM2 int64_t
+#define FELEM_MAX INT32_MAX
+#define FELEM_MIN INT32_MIN
+#endif
+
+
+typedef struct AVResampleContext{
+ 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 t=1;
+ int i;
+
+ for(i=1; i<50; i++){
+ t *= i;
+ v += pow(x*x/4, i)/(t*t);
+ }
+ return v;
+}
+
+/**
+ * builds 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->kaiser windowed sinc beta=16
+ */
+void av_build_filter(FELEM *filter, double factor, int tap_count, int phase_count, int scale, int type){
+ int ph, i, v;
+ double x, y, w, tab[tap_count];
+ const int center= (tap_count-1)/2;
+
+ /* if upsampling, only need to interpolate, no filter */
+ if (factor > 1.0)
+ factor = 1.0;
+
+ for(ph=0;ph<phase_count;ph++) {
+ double norm = 0;
+ double e= 0;
+ for(i=0;i<tap_count;i++) {
+ x = M_PI * ((double)(i - center) - (double)ph / phase_count) * factor;
+ if (x == 0) y = 1.0;
+ else y = sin(x) / x;
+ switch(type){
+ case 0:{
+ const float d= -0.5; //first order derivative = -0.5
+ x = fabs(((double)(i - center) - (double)ph / phase_count) * factor);
+ if(x<1.0) y= 1 - 3*x*x + 2*x*x*x + d*( -x*x + x*x*x);
+ else y= d*(-4 + 8*x - 5*x*x + x*x*x);
+ break;}
+ case 1:
+ w = 2.0*x / (factor*tap_count) + M_PI;
+ y *= 0.3635819 - 0.4891775 * cos(w) + 0.1365995 * cos(2*w) - 0.0106411 * cos(3*w);
+ break;
+ case 2:
+ w = 2.0*x / (factor*tap_count*M_PI);
+ y *= bessel(16*sqrt(FFMAX(1-w*w, 0)));
+ break;
+ }
+
+ tab[i] = y;
+ norm += y;
+ }
+
+ /* normalize so that an uniform color remains the same */
+ for(i=0;i<tap_count;i++) {
+ v = clip(lrintf(tab[i] * scale / norm + e), FELEM_MIN, FELEM_MAX);
+ filter[ph * tap_count + i] = v;
+ e += tab[i] * scale / norm - v;
+ }
+ }
+}
+
+/**
+ * initalizes a audio resampler.
+ * note, if either rate is not a integer then simply scale both rates up so they are
+ */
+AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_size, int phase_shift, int linear, double cutoff){
+ AVResampleContext *c= av_mallocz(sizeof(AVResampleContext));
+ double factor= FFMIN(out_rate * cutoff / in_rate, 1.0);
+ int phase_count= 1<<phase_shift;
+
+ c->phase_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));
+ av_build_filter(c->filter_bank, factor, c->filter_length, phase_count, 1<<FILTER_SHIFT, 1);
+ memcpy(&c->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];
+
+ c->src_incr= out_rate;
+ c->ideal_dst_incr= c->dst_incr= in_rate * phase_count;
+ c->index= -phase_count*((c->filter_length-1)/2);
+
+ return c;
+}
+
+void av_resample_close(AVResampleContext *c){
+ av_freep(&c->filter_bank);
+ av_freep(&c);
+}
+
+/**
+ * Compensates samplerate/timestamp drift. The compensation is done by changing
+ * the resampler parameters, so no audible clicks or similar distortions ocur
+ * @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
+ */
+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;
+}
+
+/**
+ * resamples.
+ * @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 wont 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 occured
+ */
+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;
+ }
+ frac += dst_index * dst_incr_frac;
+ index += dst_index * dst_incr;
+ index += frac / c->src_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; i<c->filter_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){
+ int64_t v=0;
+ int sub_phase= (frac<<8) / c->src_incr;
+ for(i=0; i<c->filter_length; i++){
+ int64_t coeff= filter[i]*(256 - sub_phase) + filter[i + c->filter_length]*sub_phase;
+ v += src[sample_index + i] * coeff;
+ }
+ val= v>>8;
+ }else{
+ for(i=0; i<c->filter_length; i++){
+ val += src[sample_index + i] * (FELEM2)filter[i];
+ }
+ }
+
+ val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT;
+ dst[dst_index] = (unsigned)(val + 32768) > 65535 ? (val>>31) ^ 32767 : val;
+
+ 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;
+ assert(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;
+ }
+#if 0
+ if(update_ctx && !c->compensation_distance){
+#undef rand
+ av_resample_compensate(c, rand() % (8000*2) - 8000, 8000*2);
+av_log(NULL, AV_LOG_DEBUG, "%d %d %d\n", c->dst_incr, c->ideal_dst_incr, c->compensation_distance);
+ }
+#endif
+
+ return dst_index;
+}
diff --git a/contrib/ffmpeg/libavcodec/roqvideo.c b/contrib/ffmpeg/libavcodec/roqvideo.c
new file mode 100644
index 000000000..4595b047c
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/roqvideo.c
@@ -0,0 +1,474 @@
+/*
+ * 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 roqvideo.c
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.h"
+
+typedef struct {
+ unsigned char y0, y1, y2, y3, u, v;
+} roq_cell;
+
+typedef struct {
+ int idx[4];
+} roq_qcell;
+
+static int uiclip[1024], *uiclp; /* clipping table */
+#define avg2(a,b) uiclp[(((int)(a)+(int)(b)+1)>>1)]
+#define avg4(a,b,c,d) uiclp[(((int)(a)+(int)(b)+(int)(c)+(int)(d)+2)>>2)]
+
+typedef struct RoqContext {
+
+ AVCodecContext *avctx;
+ DSPContext dsp;
+ AVFrame last_frame;
+ AVFrame current_frame;
+ int first_frame;
+ int y_stride;
+ int c_stride;
+
+ roq_cell cells[256];
+ roq_qcell qcells[256];
+
+ unsigned char *buf;
+ int size;
+
+} 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
+
+#define get_byte(in_buffer) *(in_buffer++)
+#define get_word(in_buffer) ((unsigned short)(in_buffer += 2, \
+ (in_buffer[-1] << 8 | in_buffer[-2])))
+#define get_long(in_buffer) ((unsigned long)(in_buffer += 4, \
+ (in_buffer[-1] << 24 | in_buffer[-2] << 16 | in_buffer[-3] << 8 | in_buffer[-4])))
+
+
+static void apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell)
+{
+ unsigned char *yptr;
+
+ yptr = ri->current_frame.data[0] + (y * ri->y_stride) + x;
+ *yptr++ = cell->y0;
+ *yptr++ = cell->y1;
+ yptr += (ri->y_stride - 2);
+ *yptr++ = cell->y2;
+ *yptr++ = cell->y3;
+ ri->current_frame.data[1][(y/2) * (ri->c_stride) + x/2] = cell->u;
+ ri->current_frame.data[2][(y/2) * (ri->c_stride) + x/2] = cell->v;
+}
+
+static void apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell)
+{
+ unsigned long row_inc, c_row_inc;
+ register unsigned char y0, y1, u, v;
+ unsigned char *yptr, *uptr, *vptr;
+
+ yptr = ri->current_frame.data[0] + (y * ri->y_stride) + x;
+ uptr = ri->current_frame.data[1] + (y/2) * (ri->c_stride) + x/2;
+ vptr = ri->current_frame.data[2] + (y/2) * (ri->c_stride) + x/2;
+
+ row_inc = ri->y_stride - 4;
+ c_row_inc = (ri->c_stride) - 2;
+ *yptr++ = y0 = cell->y0; *uptr++ = u = cell->u; *vptr++ = v = cell->v;
+ *yptr++ = y0;
+ *yptr++ = y1 = cell->y1; *uptr++ = u; *vptr++ = v;
+ *yptr++ = y1;
+
+ yptr += row_inc;
+
+ *yptr++ = y0;
+ *yptr++ = y0;
+ *yptr++ = y1;
+ *yptr++ = y1;
+
+ yptr += row_inc; uptr += c_row_inc; vptr += c_row_inc;
+
+ *yptr++ = y0 = cell->y2; *uptr++ = u; *vptr++ = v;
+ *yptr++ = y0;
+ *yptr++ = y1 = cell->y3; *uptr++ = u; *vptr++ = v;
+ *yptr++ = y1;
+
+ yptr += row_inc;
+
+ *yptr++ = y0;
+ *yptr++ = y0;
+ *yptr++ = y1;
+ *yptr++ = y1;
+}
+
+static void apply_motion_4x4(RoqContext *ri, int x, int y, unsigned char mv,
+ signed char mean_x, signed char mean_y)
+{
+ int i, hw, mx, my;
+ unsigned char *pa, *pb;
+
+ mx = x + 8 - (mv >> 4) - mean_x;
+ my = y + 8 - (mv & 0xf) - mean_y;
+
+ /* check MV against frame boundaries */
+ if ((mx < 0) || (mx > ri->avctx->width - 4) ||
+ (my < 0) || (my > ri->avctx->height - 4)) {
+ av_log(ri->avctx, AV_LOG_ERROR, "motion vector out of bounds: MV = (%d, %d), boundaries = (0, 0, %d, %d)\n",
+ mx, my, ri->avctx->width, ri->avctx->height);
+ return;
+ }
+
+ pa = ri->current_frame.data[0] + (y * ri->y_stride) + x;
+ pb = ri->last_frame.data[0] + (my * ri->y_stride) + mx;
+ for(i = 0; i < 4; i++) {
+ pa[0] = pb[0];
+ pa[1] = pb[1];
+ pa[2] = pb[2];
+ pa[3] = pb[3];
+ pa += ri->y_stride;
+ pb += ri->y_stride;
+ }
+
+ hw = ri->y_stride/2;
+ pa = ri->current_frame.data[1] + (y * ri->y_stride)/4 + x/2;
+ pb = ri->last_frame.data[1] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
+
+ for(i = 0; i < 2; i++) {
+ switch(((my & 0x01) << 1) | (mx & 0x01)) {
+
+ case 0:
+ pa[0] = pb[0];
+ pa[1] = pb[1];
+ pa[hw] = pb[hw];
+ pa[hw+1] = pb[hw+1];
+ break;
+
+ case 1:
+ pa[0] = avg2(pb[0], pb[1]);
+ pa[1] = avg2(pb[1], pb[2]);
+ pa[hw] = avg2(pb[hw], pb[hw+1]);
+ pa[hw+1] = avg2(pb[hw+1], pb[hw+2]);
+ break;
+
+ case 2:
+ pa[0] = avg2(pb[0], pb[hw]);
+ pa[1] = avg2(pb[1], pb[hw+1]);
+ pa[hw] = avg2(pb[hw], pb[hw*2]);
+ pa[hw+1] = avg2(pb[hw+1], pb[(hw*2)+1]);
+ break;
+
+ case 3:
+ pa[0] = avg4(pb[0], pb[1], pb[hw], pb[hw+1]);
+ pa[1] = avg4(pb[1], pb[2], pb[hw+1], pb[hw+2]);
+ pa[hw] = avg4(pb[hw], pb[hw+1], pb[hw*2], pb[(hw*2)+1]);
+ pa[hw+1] = avg4(pb[hw+1], pb[hw+2], pb[(hw*2)+1], pb[(hw*2)+1]);
+ break;
+ }
+
+ pa = ri->current_frame.data[2] + (y * ri->y_stride)/4 + x/2;
+ pb = ri->last_frame.data[2] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
+ }
+}
+
+static void apply_motion_8x8(RoqContext *ri, int x, int y,
+ unsigned char mv, signed char mean_x, signed char mean_y)
+{
+ int mx, my, i, j, hw;
+ unsigned char *pa, *pb;
+
+ mx = x + 8 - (mv >> 4) - mean_x;
+ my = y + 8 - (mv & 0xf) - mean_y;
+
+ /* check MV against frame boundaries */
+ if ((mx < 0) || (mx > ri->avctx->width - 8) ||
+ (my < 0) || (my > ri->avctx->height - 8)) {
+ av_log(ri->avctx, AV_LOG_ERROR, "motion vector out of bounds: MV = (%d, %d), boundaries = (0, 0, %d, %d)\n",
+ mx, my, ri->avctx->width, ri->avctx->height);
+ return;
+ }
+
+ pa = ri->current_frame.data[0] + (y * ri->y_stride) + x;
+ pb = ri->last_frame.data[0] + (my * ri->y_stride) + mx;
+ for(i = 0; i < 8; i++) {
+ pa[0] = pb[0];
+ pa[1] = pb[1];
+ pa[2] = pb[2];
+ pa[3] = pb[3];
+ pa[4] = pb[4];
+ pa[5] = pb[5];
+ pa[6] = pb[6];
+ pa[7] = pb[7];
+ pa += ri->y_stride;
+ pb += ri->y_stride;
+ }
+
+ hw = ri->c_stride;
+ pa = ri->current_frame.data[1] + (y * ri->y_stride)/4 + x/2;
+ pb = ri->last_frame.data[1] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
+ for(j = 0; j < 2; j++) {
+ for(i = 0; i < 4; i++) {
+ switch(((my & 0x01) << 1) | (mx & 0x01)) {
+
+ case 0:
+ pa[0] = pb[0];
+ pa[1] = pb[1];
+ pa[2] = pb[2];
+ pa[3] = pb[3];
+ break;
+
+ case 1:
+ pa[0] = avg2(pb[0], pb[1]);
+ pa[1] = avg2(pb[1], pb[2]);
+ pa[2] = avg2(pb[2], pb[3]);
+ pa[3] = avg2(pb[3], pb[4]);
+ break;
+
+ case 2:
+ pa[0] = avg2(pb[0], pb[hw]);
+ pa[1] = avg2(pb[1], pb[hw+1]);
+ pa[2] = avg2(pb[2], pb[hw+2]);
+ pa[3] = avg2(pb[3], pb[hw+3]);
+ break;
+
+ case 3:
+ pa[0] = avg4(pb[0], pb[1], pb[hw], pb[hw+1]);
+ pa[1] = avg4(pb[1], pb[2], pb[hw+1], pb[hw+2]);
+ pa[2] = avg4(pb[2], pb[3], pb[hw+2], pb[hw+3]);
+ pa[3] = avg4(pb[3], pb[4], pb[hw+3], pb[hw+4]);
+ break;
+ }
+ pa += ri->c_stride;
+ pb += ri->c_stride;
+ }
+
+ pa = ri->current_frame.data[2] + (y * ri->y_stride)/4 + x/2;
+ pb = ri->last_frame.data[2] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
+ }
+}
+
+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, bpos, xpos, ypos, xp, yp, x, y;
+ int frame_stats[2][4] = {{0},{0}};
+ roq_qcell *qcell;
+ unsigned char *buf = ri->buf;
+ unsigned char *buf_end = ri->buf + ri->size;
+
+ while (buf < buf_end) {
+ chunk_id = get_word(buf);
+ chunk_size = get_long(buf);
+ chunk_arg = get_word(buf);
+
+ 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->cells[i].y0 = get_byte(buf);
+ ri->cells[i].y1 = get_byte(buf);
+ ri->cells[i].y2 = get_byte(buf);
+ ri->cells[i].y3 = get_byte(buf);
+ ri->cells[i].u = get_byte(buf);
+ ri->cells[i].v = get_byte(buf);
+ }
+ for(i = 0; i < nv2; i++)
+ for(j = 0; j < 4; j++)
+ ri->qcells[i].idx[j] = get_byte(buf);
+ }
+ }
+
+ bpos = xpos = ypos = 0;
+ while(bpos < chunk_size) {
+ for (yp = ypos; yp < ypos + 16; yp += 8)
+ for (xp = xpos; xp < xpos + 16; xp += 8) {
+ if (vqflg_pos < 0) {
+ vqflg = buf[bpos++]; vqflg |= (buf[bpos++] << 8);
+ vqflg_pos = 7;
+ }
+ vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
+ frame_stats[0][vqid]++;
+ vqflg_pos--;
+
+ switch(vqid) {
+ case RoQ_ID_MOT:
+ apply_motion_8x8(ri, xp, yp, 0, 8, 8);
+ break;
+ case RoQ_ID_FCC:
+ apply_motion_8x8(ri, xp, yp, buf[bpos++], chunk_arg >> 8,
+ chunk_arg & 0xff);
+ break;
+ case RoQ_ID_SLD:
+ qcell = ri->qcells + buf[bpos++];
+ apply_vector_4x4(ri, xp, yp, ri->cells + qcell->idx[0]);
+ apply_vector_4x4(ri, xp+4, yp, ri->cells + qcell->idx[1]);
+ apply_vector_4x4(ri, xp, yp+4, ri->cells + qcell->idx[2]);
+ apply_vector_4x4(ri, xp+4, yp+4, ri->cells + 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 (vqflg_pos < 0) {
+ vqflg = buf[bpos++];
+ vqflg |= (buf[bpos++] << 8);
+ vqflg_pos = 7;
+ }
+ vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
+ frame_stats[1][vqid]++;
+ vqflg_pos--;
+ switch(vqid) {
+ case RoQ_ID_MOT:
+ apply_motion_4x4(ri, x, y, 0, 8, 8);
+ break;
+ case RoQ_ID_FCC:
+ apply_motion_4x4(ri, x, y, buf[bpos++],
+ chunk_arg >> 8, chunk_arg & 0xff);
+ break;
+ case RoQ_ID_SLD:
+ qcell = ri->qcells + buf[bpos++];
+ apply_vector_2x2(ri, x, y, ri->cells + qcell->idx[0]);
+ apply_vector_2x2(ri, x+2, y, ri->cells + qcell->idx[1]);
+ apply_vector_2x2(ri, x, y+2, ri->cells + qcell->idx[2]);
+ apply_vector_2x2(ri, x+2, y+2, ri->cells + qcell->idx[3]);
+ break;
+ case RoQ_ID_CCC:
+ apply_vector_2x2(ri, x, y, ri->cells + buf[bpos]);
+ apply_vector_2x2(ri, x+2, y, ri->cells + buf[bpos+1]);
+ apply_vector_2x2(ri, x, y+2, ri->cells + buf[bpos+2]);
+ apply_vector_2x2(ri, x+2, y+2, ri->cells + buf[bpos+3]);
+ bpos += 4;
+ break;
+ }
+ }
+ break;
+ default:
+ av_log(ri->avctx, AV_LOG_ERROR, "Unknown vq code: %d\n", vqid);
+ }
+ }
+
+ xpos += 16;
+ if (xpos >= ri->avctx->width) {
+ xpos -= ri->avctx->width;
+ ypos += 16;
+ }
+ if(ypos >= ri->avctx->height)
+ break;
+ }
+}
+
+
+static int roq_decode_init(AVCodecContext *avctx)
+{
+ RoqContext *s = avctx->priv_data;
+ int i;
+
+ s->avctx = avctx;
+ s->first_frame = 1;
+ avctx->pix_fmt = PIX_FMT_YUV420P;
+ avctx->has_b_frames = 0;
+ dsputil_init(&s->dsp, avctx);
+
+ uiclp = uiclip+512;
+ for(i = -512; i < 512; i++)
+ uiclp[i] = (i < 0 ? 0 : (i > 255 ? 255 : i));
+
+ return 0;
+}
+
+static int roq_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ RoqContext *s = avctx->priv_data;
+
+ if (avctx->get_buffer(avctx, &s->current_frame)) {
+ av_log(avctx, AV_LOG_ERROR, " RoQ: get_buffer() failed\n");
+ return -1;
+ }
+ s->y_stride = s->current_frame.linesize[0];
+ s->c_stride = s->current_frame.linesize[1];
+
+ s->buf = buf;
+ s->size = buf_size;
+ roqvideo_decode_frame(s);
+
+ /* release the last frame if it is allocated */
+ if (s->first_frame)
+ s->first_frame = 0;
+ else
+ avctx->release_buffer(avctx, &s->last_frame);
+
+ /* shuffle frames */
+ s->last_frame = s->current_frame;
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = s->current_frame;
+
+ return buf_size;
+}
+
+static int roq_decode_end(AVCodecContext *avctx)
+{
+ RoqContext *s = avctx->priv_data;
+
+ /* release the last frame */
+ if (s->last_frame.data[0])
+ avctx->release_buffer(avctx, &s->last_frame);
+
+ return 0;
+}
+
+AVCodec roq_decoder = {
+ "roqvideo",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_ROQ,
+ sizeof(RoqContext),
+ roq_decode_init,
+ NULL,
+ roq_decode_end,
+ roq_decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/rpza.c b/contrib/ffmpeg/libavcodec/rpza.c
new file mode 100644
index 000000000..9a996da37
--- /dev/null
+++ b/contrib/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 rpza.c
+ * QT RPZA Video Decoder by Roberto Togni <rtogni@bresciaonline.it>
+ * 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 ffmpeg documentation states that RGB555 pixels
+ * shall be stored in native CPU endianness.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.h"
+
+typedef struct RpzaContext {
+
+ AVCodecContext *avctx;
+ DSPContext dsp;
+ AVFrame frame;
+
+ 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 = BE_32(&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 = BE_16 (&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 = BE_16 (&s->buf[stream_ptr]);
+ stream_ptr += 2;
+ case 0x20:
+ colorB = BE_16 (&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);
+
+ 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:
+ 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 = BE_16 (&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 int rpza_decode_init(AVCodecContext *avctx)
+{
+ RpzaContext *s = (RpzaContext *)avctx->priv_data;
+
+ s->avctx = avctx;
+ avctx->pix_fmt = PIX_FMT_RGB555;
+ avctx->has_b_frames = 0;
+ dsputil_init(&s->dsp, avctx);
+
+ s->frame.data[0] = NULL;
+
+ return 0;
+}
+
+static int rpza_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ RpzaContext *s = (RpzaContext *)avctx->priv_data;
+
+ s->buf = buf;
+ s->size = buf_size;
+
+ s->frame.reference = 1;
+ s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
+ if (avctx->reget_buffer(avctx, &s->frame)) {
+ av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+ return -1;
+ }
+
+ rpza_decode_stream(s);
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = s->frame;
+
+ /* always report that the buffer was completely consumed */
+ return buf_size;
+}
+
+static int rpza_decode_end(AVCodecContext *avctx)
+{
+ RpzaContext *s = (RpzaContext *)avctx->priv_data;
+
+ if (s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ return 0;
+}
+
+AVCodec rpza_decoder = {
+ "rpza",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_RPZA,
+ sizeof(RpzaContext),
+ rpza_decode_init,
+ NULL,
+ rpza_decode_end,
+ rpza_decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/rtjpeg.c b/contrib/ffmpeg/libavcodec/rtjpeg.c
new file mode 100644
index 000000000..dbc6cfd88
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/rtjpeg.c
@@ -0,0 +1,165 @@
+/*
+ * 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 "common.h"
+#include "bitstream.h"
+#include "dsputil.h"
+#include "rtjpeg.h"
+
+#define PUT_COEFF(c) \
+ i = scan[coeff--]; \
+ block[i] = (c) * quant[i];
+
+//! aligns the bitstream to the give 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
+ *
+ * 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, DCTELEM *block, uint8_t *scan,
+ 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);
+ // 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(DCTELEM));
+
+ // 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);
+ while (coeff) {
+ ac = get_sbits(gb, 4);
+ if (ac == -8)
+ break; // continue with more bits
+ PUT_COEFF(ac);
+ }
+
+ // 8 bits per coefficient
+ ALIGN(8);
+ 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 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 rtjpeg_decode_frame_yuv420(RTJpegContext *c, AVFrame *f,
+ uint8_t *buf, int buf_size) {
+ DECLARE_ALIGNED_16(DCTELEM, block[64]);
+ 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++) {
+ if (get_block(&gb, block, c->scan, c->lquant))
+ c->dsp->idct_put(y1, f->linesize[0], block);
+ y1 += 8;
+ if (get_block(&gb, block, c->scan, c->lquant))
+ c->dsp->idct_put(y1, f->linesize[0], block);
+ y1 += 8;
+ if (get_block(&gb, block, c->scan, c->lquant))
+ c->dsp->idct_put(y2, f->linesize[0], block);
+ y2 += 8;
+ if (get_block(&gb, block, c->scan, c->lquant))
+ c->dsp->idct_put(y2, f->linesize[0], block);
+ y2 += 8;
+ if (get_block(&gb, block, c->scan, c->cquant))
+ c->dsp->idct_put(u, f->linesize[1], block);
+ u += 8;
+ if (get_block(&gb, block, c->scan, c->cquant))
+ c->dsp->idct_put(v, f->linesize[2], block);
+ 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 rtjpeg_decode_init(RTJpegContext *c, DSPContext *dsp,
+ int width, int height,
+ uint32_t *lquant, 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/contrib/ffmpeg/libavcodec/rtjpeg.h b/contrib/ffmpeg/libavcodec/rtjpeg.h
new file mode 100644
index 000000000..daecc8a75
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/rtjpeg.h
@@ -0,0 +1,39 @@
+/*
+ * 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 RTJPEG_H
+#define RTJPEG_H
+
+typedef struct {
+ int w, h;
+ DSPContext *dsp;
+ uint8_t scan[64];
+ uint32_t lquant[64];
+ uint32_t cquant[64];
+} RTJpegContext;
+
+void rtjpeg_decode_init(RTJpegContext *c, DSPContext *dsp,
+ int width, int height,
+ uint32_t *lquant, uint32_t *cquant);
+
+int rtjpeg_decode_frame_yuv420(RTJpegContext *c, AVFrame *f,
+ uint8_t *buf, int buf_size);
+#endif
diff --git a/contrib/ffmpeg/libavcodec/rv10.c b/contrib/ffmpeg/libavcodec/rv10.c
new file mode 100644
index 000000000..4b50609c1
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/rv10.c
@@ -0,0 +1,803 @@
+/*
+ * RV10 codec
+ * 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.c
+ * RV10 codec.
+ */
+
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+//#define DEBUG
+
+#define DC_VLC_BITS 14 //FIXME find a better solution
+
+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 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_bits(&s->gb, 1) == 0)
+ code = (int8_t)(get_bits(&s->gb, 8) + 1);
+ else
+ code = (int8_t)(get_bits(&s->gb, 8));
+ } else if (code == 0x7f) {
+ get_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) {
+ get_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;
+}
+
+#ifdef CONFIG_ENCODERS
+
+/* write RV 1.0 compatible frame header */
+void rv10_encode_picture_header(MpegEncContext *s, int picture_number)
+{
+ int full_frame= 0;
+
+ align_put_bits(&s->pb);
+
+ put_bits(&s->pb, 1, 1); /* marker */
+
+ put_bits(&s->pb, 1, (s->pict_type == P_TYPE));
+
+ put_bits(&s->pb, 1, 0); /* not PB frame */
+
+ put_bits(&s->pb, 5, s->qscale);
+
+ if (s->pict_type == I_TYPE) {
+ /* specific MPEG like DC coding not used */
+ }
+ /* if multiple packets per frame are sent, the position at which
+ to display the macro blocks 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 */
+}
+
+void 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_bits(&s->pb, 8, picture_number&0xFF); //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);
+
+ assert(s->f_code == 1);
+ assert(s->unrestricted_mv == 1);
+// assert(s->h263_aic== (s->pict_type == I_TYPE));
+ assert(s->alt_inter_vlc == 0);
+ assert(s->umvplus == 0);
+ assert(s->modified_quant==1);
+ assert(s->loop_filter==1);
+
+ s->h263_aic= s->pict_type == I_TYPE;
+ 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 0 /* unused, remove? */
+static int get_num(GetBitContext *gb)
+{
+ int n, n1;
+
+ n = get_bits(gb, 16);
+ if (n >= 0x4000) {
+ return n - 0x4000;
+ } else {
+ n1 = get_bits(gb, 16);
+ return (n << 16) | n1;
+ }
+}
+#endif
+
+#endif //CONFIG_ENCODERS
+
+/* read RV 1.0 compatible frame header */
+static int rv10_decode_picture_header(MpegEncContext *s)
+{
+ int mb_count, pb_frame, marker, unk, mb_xy;
+
+//printf("ff:%d\n", full_frame);
+ marker = get_bits(&s->gb, 1);
+
+ if (get_bits(&s->gb, 1))
+ s->pict_type = P_TYPE;
+ else
+ s->pict_type = I_TYPE;
+//printf("h:%X ver:%d\n",h,s->rv10_version);
+ if(!marker) av_log(s->avctx, AV_LOG_ERROR, "marker missing\n");
+ pb_frame = get_bits(&s->gb, 1);
+
+#ifdef DEBUG
+ av_log(s->avctx, AV_LOG_DEBUG, "pict_type=%d pb_frame=%d\n", s->pict_type, pb_frame);
+#endif
+
+ 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 == I_TYPE) {
+ 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);
+#ifdef DEBUG
+ av_log(s->avctx, AV_LOG_DEBUG, "DC:%d %d %d\n",
+ s->last_dc[0],
+ s->last_dc[1],
+ s->last_dc[2]);
+#endif
+ }
+ }
+ /* if multiple packets per frame are sent, the position at which
+ to display the macro blocks 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;
+ }
+ unk= get_bits(&s->gb, 3); /* ignored */
+//printf("%d\n", unk);
+ s->f_code = 1;
+ s->unrestricted_mv = 1;
+
+ return mb_count;
+}
+
+static int rv20_decode_picture_header(MpegEncContext *s)
+{
+ int seq, mb_pos, i;
+
+#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; i<s->avctx->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
+
+ if(s->avctx->sub_id == 0x30202002 || s->avctx->sub_id == 0x30203002){
+ if (get_bits(&s->gb, 3)){
+ av_log(s->avctx, AV_LOG_ERROR, "unknown triplet set\n");
+ return -1;
+ }
+ }
+
+ i= get_bits(&s->gb, 2);
+ switch(i){
+ case 0: s->pict_type= I_TYPE; break;
+ case 1: s->pict_type= I_TYPE; break; //hmm ...
+ case 2: s->pict_type= P_TYPE; break;
+ case 3: s->pict_type= B_TYPE; break;
+ default:
+ av_log(s->avctx, AV_LOG_ERROR, "unknown frame type\n");
+ return -1;
+ }
+
+ if(s->last_picture_ptr==NULL && s->pict_type==B_TYPE){
+ av_log(s->avctx, AV_LOG_ERROR, "early B pix\n");
+ return -1;
+ }
+
+ if (get_bits(&s->gb, 1)){
+ av_log(s->avctx, AV_LOG_ERROR, "unknown 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(s->avctx->sub_id == 0x30203002){
+ if (get_bits(&s->gb, 1)){
+ av_log(s->avctx, AV_LOG_ERROR, "unknown bit2 set\n");
+ return -1;
+ }
+ }
+
+ if(s->avctx->has_b_frames){
+ int f, new_w, new_h;
+ int v= s->avctx->extradata_size >= 4 ? 7&((uint8_t*)s->avctx->extradata)[1] : 0;
+
+ if (get_bits(&s->gb, 1)){
+ av_log(s->avctx, AV_LOG_ERROR, "unknown bit3 set\n");
+// return -1;
+ }
+ seq= get_bits(&s->gb, 13)<<2;
+
+ f= get_bits(&s->gb, av_log2(v)+1);
+
+ 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->width; //FIXME wrong we of course must save the original in the context
+ new_h= s->height;
+ }
+ if(new_w != s->width || new_h != s->height){
+ av_log(s->avctx, AV_LOG_DEBUG, "attempting to change resolution to %dx%d\n", new_w, new_h);
+ MPV_common_end(s);
+ s->width = s->avctx->width = new_w;
+ s->height = s->avctx->height= new_h;
+ if (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, v);
+ }
+ }else{
+ seq= get_bits(&s->gb, 8)*128;
+ }
+
+// if(s->avctx->sub_id <= 0x20201002){ //0x20201002 definitely needs this
+ mb_pos= ff_h263_decode_mba(s);
+/* }else{
+ mb_pos= get_bits(&s->gb, av_log2(s->mb_num-1)+1);
+ s->mb_x= mb_pos % s->mb_width;
+ s->mb_y= mb_pos / s->mb_width;
+ }*/
+//av_log(s->avctx, AV_LOG_DEBUG, "%d\n", seq);
+ 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!=B_TYPE){
+ 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->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");
+ return FRAME_SKIPPED;
+ }
+ ff_mpeg4_init_direct_mv(s);
+ }
+ }
+// printf("%d %d %d %d %d\n", seq, (int)s->time, (int)s->last_non_b_time, s->pp_time, s->pb_time);
+/*for(i=0; i<32; i++){
+ av_log(s->avctx, AV_LOG_DEBUG, "%d", get_bits1(&s->gb));
+}
+av_log(s->avctx, AV_LOG_DEBUG, "\n");*/
+ s->no_rounding= get_bits1(&s->gb);
+
+ s->f_code = 1;
+ s->unrestricted_mv = 1;
+ s->h263_aic= s->pict_type == I_TYPE;
+// s->alt_inter_vlc=1;
+// s->obmc=1;
+// s->umvplus=1;
+ s->modified_quant=1;
+ 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);
+ }
+
+ assert(s->pict_type != B_TYPE || !s->low_delay);
+
+ return s->mb_width*s->mb_height - mb_pos;
+}
+
+static int rv10_decode_init(AVCodecContext *avctx)
+{
+ MpegEncContext *s = avctx->priv_data;
+ static int done=0;
+
+ 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;
+
+ s->h263_long_vectors= ((uint8_t*)avctx->extradata)[3] & 1;
+ avctx->sub_id= BE_32((uint8_t*)avctx->extradata + 4);
+
+ switch(avctx->sub_id){
+ case 0x10000000:
+ s->rv10_version= 0;
+ s->low_delay=1;
+ break;
+ case 0x10002000:
+ s->rv10_version= 3;
+ s->low_delay=1;
+ s->obmc=1;
+ break;
+ case 0x10003000:
+ s->rv10_version= 3;
+ s->low_delay=1;
+ break;
+ case 0x10003001:
+ s->rv10_version= 3;
+ s->low_delay=1;
+ break;
+ case 0x20001000: /* real rv20 decoder fail on this id */
+ /*case 0x20100001:
+ case 0x20101001:
+ case 0x20103001:*/
+ case 0x20100000 ... 0x2019ffff:
+ s->low_delay=1;
+ break;
+ /*case 0x20200002:
+ case 0x20201002:
+ case 0x20203002:*/
+ case 0x20200002 ... 0x202fffff:
+ case 0x30202002:
+ case 0x30203002:
+ s->low_delay=0;
+ s->avctx->has_b_frames=1;
+ break;
+ default:
+ av_log(s->avctx, AV_LOG_ERROR, "unknown header %X\n", avctx->sub_id);
+ }
+
+ if(avctx->debug & FF_DEBUG_PICT_INFO){
+ av_log(avctx, AV_LOG_DEBUG, "ver:%X ver0:%X\n", avctx->sub_id, avctx->extradata_size >= 4 ? ((uint32_t*)avctx->extradata)[0] : -1);
+ }
+
+ avctx->pix_fmt = PIX_FMT_YUV420P;
+
+ if (MPV_common_init(s) < 0)
+ return -1;
+
+ h263_decode_init_vlc(s);
+
+ /* init rv vlc */
+ if (!done) {
+ init_vlc(&rv_dc_lum, DC_VLC_BITS, 256,
+ rv_lum_bits, 1, 1,
+ rv_lum_code, 2, 2, 1);
+ init_vlc(&rv_dc_chrom, DC_VLC_BITS, 256,
+ rv_chrom_bits, 1, 1,
+ rv_chrom_code, 2, 2, 1);
+ done = 1;
+ }
+
+ return 0;
+}
+
+static int rv10_decode_end(AVCodecContext *avctx)
+{
+ MpegEncContext *s = avctx->priv_data;
+
+ MPV_common_end(s);
+ return 0;
+}
+
+static int rv10_decode_packet(AVCodecContext *avctx,
+ uint8_t *buf, int buf_size)
+{
+ MpegEncContext *s = avctx->priv_data;
+ int mb_count, mb_pos, left, start_mb_x;
+
+ init_get_bits(&s->gb, buf, buf_size*8);
+ if(s->codec_id ==CODEC_ID_RV10)
+ mb_count = rv10_decode_picture_header(s);
+ else
+ mb_count = rv20_decode_picture_header(s);
+ if (mb_count < 0) {
+ 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->pict_type == P_TYPE) return 0;
+
+ 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);
+ MPV_frame_end(s);
+ s->mb_x= s->mb_y = s->resync_mb_x = s->resync_mb_y= 0;
+ }
+ if(MPV_frame_start(s, avctx) < 0)
+ return -1;
+ ff_er_frame_start(s);
+ }
+
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_DEBUG, "qscale=%d\n", s->qscale);
+#endif
+
+ /* default quantization values */
+ if(s->codec_id== 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;
+//printf("%d %X %X\n", s->pict_type, s->current_picture.motion_val[0], s->current_picture.motion_val[1]);
+ 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);
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_DEBUG, "**mb x=%d y=%d\n", s->mb_x, s->mb_y);
+#endif
+
+ s->mv_dir = MV_DIR_FORWARD;
+ s->mv_type = MV_TYPE_16X16;
+ ret=ff_h263_decode_mb(s, s->block);
+
+ if (ret == SLICE_ERROR || s->gb.size_in_bits < 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 != B_TYPE)
+ ff_h263_update_motion_val(s);
+ 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, start_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, AC_END|DC_END|MV_END);
+
+ return buf_size;
+}
+
+static int rv10_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ MpegEncContext *s = avctx->priv_data;
+ int i;
+ AVFrame *pict = data;
+
+#ifdef DEBUG
+ av_log(avctx, AV_LOG_DEBUG, "*****frame %d size=%d\n", avctx->frame_number, buf_size);
+#endif
+
+ /* no supplementary picture */
+ if (buf_size == 0) {
+ return 0;
+ }
+
+ if(avctx->slice_count){
+ for(i=0; i<avctx->slice_count; i++){
+ int offset= avctx->slice_offset[i];
+ int size;
+
+ if(i+1 == avctx->slice_count)
+ size= buf_size - offset;
+ else
+ size= avctx->slice_offset[i+1] - offset;
+
+ rv10_decode_packet(avctx, buf+offset, size);
+ }
+ }else{
+ rv10_decode_packet(avctx, buf, buf_size);
+ }
+
+ if(s->current_picture_ptr != NULL && s->mb_y>=s->mb_height){
+ ff_er_frame_end(s);
+ MPV_frame_end(s);
+
+ if (s->pict_type == B_TYPE || s->low_delay) {
+ *pict= *(AVFrame*)s->current_picture_ptr;
+ } else if (s->last_picture_ptr != NULL) {
+ *pict= *(AVFrame*)s->last_picture_ptr;
+ }
+
+ if(s->last_picture_ptr || s->low_delay){
+ *data_size = sizeof(AVFrame);
+ ff_print_debug_info(s, pict);
+ }
+ s->current_picture_ptr= NULL; //so we can detect if frame_end wasnt called (find some nicer solution...)
+ }
+
+ return buf_size;
+}
+
+AVCodec rv10_decoder = {
+ "rv10",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_RV10,
+ sizeof(MpegEncContext),
+ rv10_decode_init,
+ NULL,
+ rv10_decode_end,
+ rv10_decode_frame,
+ CODEC_CAP_DR1
+};
+
+AVCodec rv20_decoder = {
+ "rv20",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_RV20,
+ sizeof(MpegEncContext),
+ rv10_decode_init,
+ NULL,
+ rv10_decode_end,
+ rv10_decode_frame,
+ CODEC_CAP_DR1 | CODEC_CAP_DELAY,
+ .flush= ff_mpeg_flush,
+};
+
diff --git a/contrib/ffmpeg/libavcodec/sh4/dsputil_align.c b/contrib/ffmpeg/libavcodec/sh4/dsputil_align.c
new file mode 100644
index 000000000..7e7e3304b
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/sh4/dsputil_align.c
@@ -0,0 +1,430 @@
+/*
+ * aligned/packed access motion
+ *
+ * Copyright (c) 2001-2003 BERO <bero@geocities.co.jp>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * 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"
+
+
+#define LP(p) *(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(LP(ref),LP(ref+4),ofs)); \
+ ref+=stride; \
+ dest+=stride; \
+ } while(--height)
+
+#define OP_C40() \
+ do { \
+ OP(LP(dest),LP(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 = LP(ref+0); \
+ t1 = LP(ref+4); \
+ OP(LP(dest+0), MERGE1(t0,t1,ofs)); \
+ t0 = LP(ref+8); \
+ OP(LP(dest+4), MERGE1(t1,t0,ofs)); \
+if (sz==16) { \
+ t1 = LP(ref+12); \
+ OP(LP(dest+8), MERGE1(t0,t1,ofs)); \
+ t0 = LP(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), LP(ref+0)); \
+ OP(LP(dest+4), LP(ref+4)); \
+if (sz==16) { \
+ OP(LP(dest+8), LP(ref+8)); \
+ OP(LP(dest+12), LP(ref+12)); \
+} \
+ ref+=stride; \
+ dest+= stride; \
+ } while(--height); \
+}
+
+#define OP_X(ofs,sz,avg2) \
+{ \
+ ref-=ofs; \
+ do { \
+ uint32_t t0,t1; \
+ t0 = LP(ref+0); \
+ t1 = LP(ref+4); \
+ OP(LP(dest+0), avg2(MERGE1(t0,t1,ofs),MERGE2(t0,t1,ofs))); \
+ t0 = LP(ref+8); \
+ OP(LP(dest+4), avg2(MERGE1(t1,t0,ofs),MERGE2(t1,t0,ofs))); \
+if (sz==16) { \
+ t1 = LP(ref+12); \
+ OP(LP(dest+8), avg2(MERGE1(t0,t1,ofs),MERGE2(t0,t1,ofs))); \
+ t0 = LP(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 = LP(ref+0); \
+ t1 = LP(ref+4); \
+if (sz==16) { \
+ t2 = LP(ref+8); \
+ t3 = LP(ref+12); \
+} \
+ do { \
+ ref += stride; \
+\
+ t = LP(ref+0); \
+ OP(LP(dest+0), avg2(t0,t)); t0 = t; \
+ t = LP(ref+4); \
+ OP(LP(dest+4), avg2(t1,t)); t1 = t; \
+if (sz==16) { \
+ t = LP(ref+8); \
+ OP(LP(dest+8), avg2(t2,t)); t2 = t; \
+ t = LP(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 = LP(ref+0); \
+ w1 = LP(ref+4); \
+ t0 = MERGE1(w0,w1,ofs); \
+ w0 = LP(ref+8); \
+ t1 = MERGE1(w1,w0,ofs); \
+if (sz==16) { \
+ w1 = LP(ref+12); \
+ t2 = MERGE1(w0,w1,ofs); \
+ w0 = LP(ref+16); \
+ t3 = MERGE1(w1,w0,ofs); \
+} \
+ do { \
+ ref += stride; \
+\
+ w0 = LP(ref+0); \
+ w1 = LP(ref+4); \
+ t = MERGE1(w0,w1,ofs); \
+ OP(LP(dest+0), avg2(t0,t)); t0 = t; \
+ w0 = LP(ref+8); \
+ t = MERGE1(w1,w0,ofs); \
+ OP(LP(dest+4), avg2(t1,t)); t1 = t; \
+if (sz==16) { \
+ w1 = LP(ref+12); \
+ t = MERGE1(w0,w1,ofs); \
+ OP(LP(dest+8), avg2(t2,t)); t2 = t; \
+ w0 = LP(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 = LP(ref+0); \
+ w1 = LP(ref+4); \
+ UNPACK(a0,a1,MERGE1(w0,w1,ofs),MERGE2(w0,w1,ofs)); \
+ w0 = LP(ref+8); \
+ UNPACK(a2,a3,MERGE1(w1,w0,ofs),MERGE2(w1,w0,ofs)); \
+if (sz==16) { \
+ w1 = LP(ref+12); \
+ UNPACK(a4,a5,MERGE1(w0,w1,ofs),MERGE2(w0,w1,ofs)); \
+ w0 = LP(ref+16); \
+ UNPACK(a6,a7,MERGE1(w1,w0,ofs),MERGE2(w1,w0,ofs)); \
+} \
+ do { \
+ ref+=stride; \
+ w0 = LP(ref+0); \
+ w1 = LP(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 = LP(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 = LP(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 = LP(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 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(put, rnd,o,8,OP_C,avg2)
+DEFFUNC(put, rnd,x,8,OP_X,avg2)
+DEFFUNC(put,no_rnd,x,8,OP_X,avg2)
+DEFFUNC(put, rnd,y,8,OP_Y,avg2)
+DEFFUNC(put,no_rnd,y,8,OP_Y,avg2)
+DEFFUNC(put, rnd,xy,8,OP_XY,PACK)
+DEFFUNC(put,no_rnd,xy,8,OP_XY,PACK)
+DEFFUNC(put, rnd,o,16,OP_C,avg2)
+DEFFUNC(put, rnd,x,16,OP_X,avg2)
+DEFFUNC(put,no_rnd,x,16,OP_X,avg2)
+DEFFUNC(put, rnd,y,16,OP_Y,avg2)
+DEFFUNC(put,no_rnd,y,16,OP_Y,avg2)
+DEFFUNC(put, rnd,xy,16,OP_XY,PACK)
+DEFFUNC(put,no_rnd,xy,16,OP_XY,PACK)
+
+#undef OP
+#define OP avg
+
+DEFFUNC(avg, rnd,o,8,OP_C,avg2)
+DEFFUNC(avg, rnd,x,8,OP_X,avg2)
+DEFFUNC(avg,no_rnd,x,8,OP_X,avg2)
+DEFFUNC(avg, rnd,y,8,OP_Y,avg2)
+DEFFUNC(avg,no_rnd,y,8,OP_Y,avg2)
+DEFFUNC(avg, rnd,xy,8,OP_XY,PACK)
+DEFFUNC(avg,no_rnd,xy,8,OP_XY,PACK)
+DEFFUNC(avg, rnd,o,16,OP_C,avg2)
+DEFFUNC(avg, rnd,x,16,OP_X,avg2)
+DEFFUNC(avg,no_rnd,x,16,OP_X,avg2)
+DEFFUNC(avg, rnd,y,16,OP_Y,avg2)
+DEFFUNC(avg,no_rnd,y,16,OP_Y,avg2)
+DEFFUNC(avg, rnd,xy,16,OP_XY,PACK)
+DEFFUNC(avg,no_rnd,xy,16,OP_XY,PACK)
+
+#undef OP
+
+#define put_no_rnd_pixels8_o put_rnd_pixels8_o
+#define put_no_rnd_pixels16_o put_rnd_pixels16_o
+#define avg_no_rnd_pixels8_o avg_rnd_pixels8_o
+#define avg_no_rnd_pixels16_o avg_rnd_pixels16_o
+
+#define put_pixels8_c put_rnd_pixels8_o
+#define put_pixels16_c put_rnd_pixels16_o
+#define avg_pixels8_c avg_rnd_pixels8_o
+#define avg_pixels16_c avg_rnd_pixels16_o
+#define put_no_rnd_pixels8_c put_rnd_pixels8_o
+#define put_no_rnd_pixels16_c put_rnd_pixels16_o
+#define avg_no_rnd_pixels8_c avg_rnd_pixels8_o
+#define avg_no_rnd_pixels16_c avg_rnd_pixels16_o
+
+#define QPEL
+
+#ifdef QPEL
+
+#include "qpel.c"
+
+#endif
+
+void dsputil_init_align(DSPContext* c, AVCodecContext *avctx)
+{
+ c->put_pixels_tab[0][0] = 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] = 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] = 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] = 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] = 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] = 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][0] = avg_no_rnd_pixels16_o;
+ c->avg_no_rnd_pixels_tab[0][1] = avg_no_rnd_pixels16_x;
+ c->avg_no_rnd_pixels_tab[0][2] = avg_no_rnd_pixels16_y;
+ c->avg_no_rnd_pixels_tab[0][3] = avg_no_rnd_pixels16_xy;
+ c->avg_no_rnd_pixels_tab[1][0] = avg_no_rnd_pixels8_o;
+ c->avg_no_rnd_pixels_tab[1][1] = avg_no_rnd_pixels8_x;
+ c->avg_no_rnd_pixels_tab[1][2] = avg_no_rnd_pixels8_y;
+ c->avg_no_rnd_pixels_tab[1][3] = avg_no_rnd_pixels8_xy;
+
+#ifdef QPEL
+
+#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); */
+
+ dspfunc(put_h264_qpel, 0, 16);
+ dspfunc(put_h264_qpel, 1, 8);
+ dspfunc(put_h264_qpel, 2, 4);
+ dspfunc(avg_h264_qpel, 0, 16);
+ dspfunc(avg_h264_qpel, 1, 8);
+ dspfunc(avg_h264_qpel, 2, 4);
+
+#undef dspfunc
+ c->put_h264_chroma_pixels_tab[0]= put_h264_chroma_mc8_c;
+ c->put_h264_chroma_pixels_tab[1]= put_h264_chroma_mc4_c;
+ c->put_h264_chroma_pixels_tab[2]= put_h264_chroma_mc2_c;
+ c->avg_h264_chroma_pixels_tab[0]= avg_h264_chroma_mc8_c;
+ c->avg_h264_chroma_pixels_tab[1]= avg_h264_chroma_mc4_c;
+ c->avg_h264_chroma_pixels_tab[2]= avg_h264_chroma_mc2_c;
+
+ c->put_mspel_pixels_tab[0]= put_mspel8_mc00_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;
+
+ c->gmc1 = gmc1_c;
+ c->gmc = gmc_c;
+
+#endif
+}
diff --git a/contrib/ffmpeg/libavcodec/sh4/dsputil_sh4.c b/contrib/ffmpeg/libavcodec/sh4/dsputil_sh4.c
new file mode 100644
index 000000000..b38eb2551
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/sh4/dsputil_sh4.c
@@ -0,0 +1,120 @@
+/*
+ * sh4 dsputil
+ *
+ * Copyright (c) 2003 BERO <bero@geocities.co.jp>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * 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"
+
+static void memzero_align8(void *dst,size_t size)
+{
+#if defined(__SH4__) || defined(__SH4_SINGLE__) || defined(__SH4_SINGLE_ONLY__)
+ (char*)dst+=size;
+ size/=8*4;
+ asm(
+#if defined(__SH4__)
+ " fschg\n" //single float mode
+#endif
+ " 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"
+#if defined(__SH4_SINGLE__) || defined(__SH4_SINGLE_ONLY__)
+ " fschg" //back to single
+#endif
+ : : "r"(dst),"r"(size): "memory" );
+#else
+ double *d = dst;
+ size/=8*4;
+ do {
+ d[0] = 0.0;
+ d[1] = 0.0;
+ d[2] = 0.0;
+ d[3] = 0.0;
+ d+=4;
+ } while(--size);
+#endif
+}
+
+static void clear_blocks_sh4(DCTELEM *blocks)
+{
+// if (((int)blocks&7)==0)
+ memzero_align8(blocks,sizeof(DCTELEM)*6*64);
+}
+
+extern void idct_sh4(DCTELEM *block);
+static void idct_put(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ idct_sh4(block);
+ int i;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+ 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, DCTELEM *block)
+{
+ idct_sh4(block);
+ int i;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+ 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;
+ }
+}
+
+extern void dsputil_init_align(DSPContext* c, AVCodecContext *avctx);
+
+void dsputil_init_sh4(DSPContext* c, AVCodecContext *avctx)
+{
+ const int idct_algo= avctx->idct_algo;
+ dsputil_init_align(c,avctx);
+
+ c->clear_blocks = clear_blocks_sh4;
+ if(idct_algo==FF_IDCT_AUTO || idct_algo==FF_IDCT_SH4){
+ c->idct_put = idct_put;
+ c->idct_add = idct_add;
+ c->idct = idct_sh4;
+ c->idct_permutation_type= FF_NO_IDCT_PERM; //FF_SIMPLE_IDCT_PERM; //FF_LIBMPEG2_IDCT_PERM;
+ }
+}
diff --git a/contrib/ffmpeg/libavcodec/sh4/idct_sh4.c b/contrib/ffmpeg/libavcodec/sh4/idct_sh4.c
new file mode 100644
index 000000000..3b8428c3c
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/sh4/idct_sh4.c
@@ -0,0 +1,366 @@
+/*
+ * idct for sh4
+ *
+ * Copyright (c) 2001-2003 BERO <bero@geocities.co.jp>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * 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"
+#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
+
+#if defined(__SH4_SINGLE__) || defined(__SH4_SINGLE_ONLY__)
+
+#define load_matrix(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"(table)\
+ : "0" \
+ )
+
+#define ftrv() \
+ __asm__ volatile("ftrv xmtrx,fv0" \
+ : "=f"(fr0),"=f"(fr1),"=f"(fr2),"=f"(fr3) \
+ : "0"(fr0), "1"(fr1), "2"(fr2), "3"(fr3) );
+
+#define DEFREG \
+ register float fr0 __asm__("fr0"); \
+ register float fr1 __asm__("fr1"); \
+ register float fr2 __asm__("fr2"); \
+ register float fr3 __asm__("fr3")
+
+#else
+
+/* generic C code for check */
+
+static void ftrv_(const float xf[],float fv[])
+{
+ float f0,f1,f2,f3;
+ f0 = fv[0];
+ f1 = fv[1];
+ f2 = fv[2];
+ f3 = fv[3];
+ fv[0] = xf[0]*f0 + xf[4]*f1 + xf[ 8]*f2 + xf[12]*f3;
+ fv[1] = xf[1]*f0 + xf[5]*f1 + xf[ 9]*f2 + xf[13]*f3;
+ fv[2] = xf[2]*f0 + xf[6]*f1 + xf[10]*f2 + xf[14]*f3;
+ fv[3] = xf[3]*f0 + xf[7]*f1 + xf[11]*f2 + xf[15]*f3;
+}
+
+static void load_matrix_(float xf[],const float table[])
+{
+ int i;
+ for(i=0;i<16;i++) xf[i]=table[i];
+}
+
+#define ftrv() ftrv_(xf,fv)
+#define load_matrix(table) load_matrix_(xf,table)
+
+#define DEFREG \
+ float fv[4],xf[16]
+
+#define fr0 fv[0]
+#define fr1 fv[1]
+#define fr2 fv[2]
+#define fr3 fv[3]
+
+#endif
+
+#if 1
+#define DESCALE(x,n) (x)*(1.0f/(1<<(n)))
+#else
+#define DESCALE(x,n) (((int)(x)+(1<<(n-1)))>>(n))
+#endif
+
+/* this code work worse on gcc cvs. 3.2.3 work fine */
+
+
+#if 1
+//optimized
+
+void idct_sh4(DCTELEM *block)
+{
+ DEFREG;
+
+ int i;
+ float tblock[8*8],*fblock;
+ int ofs1,ofs2,ofs3;
+
+#if defined(__SH4__)
+#error "FIXME!! change to single float"
+#endif
+
+ /* 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;
+
+// ofs1 = sizeof(float)*1;
+// ofs2 = sizeof(float)*2;
+// ofs3 = sizeof(float)*3;
+
+ 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);
+
+#if defined(__SH4__)
+#error "FIXME!! change to double"
+#endif
+}
+#else
+void idct_sh4(DCTELEM *block)
+{
+ DEFREG;
+
+ int i;
+ float tblock[8*8],*fblock;
+
+ /* row */
+
+ /* even part */
+ load_matrix(even_table);
+
+ fblock = tblock;
+ i = 8;
+ do {
+ fr0 = block[0];
+ fr1 = block[2];
+ fr2 = block[4];
+ fr3 = block[6];
+ block+=8;
+ ftrv();
+ fblock[0] = fr0;
+ fblock[2] = fr1;
+ fblock[4] = fr2;
+ fblock[6] = fr3;
+ fblock+=8;
+ } while(--i);
+ block-=8*8;
+ fblock-=8*8;
+
+ 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[0];
+ t1 = fblock[2];
+ t2 = fblock[4];
+ t3 = fblock[6];
+ fblock[0] = t0 + fr0;
+ fblock[7] = t0 - fr0;
+ fblock[1] = t1 + fr1;
+ fblock[6] = t1 - fr1;
+ fblock[2] = t2 + fr2;
+ fblock[5] = t2 - fr2;
+ fblock[3] = t3 + fr3;
+ fblock[4] = t3 - fr3;
+ fblock+=8;
+ } while(--i);
+ block-=8*8;
+ fblock-=8*8;
+
+ /* col */
+
+ /* even part */
+ load_matrix(even_table);
+
+ i = 8;
+
+ do {
+ fr0 = fblock[8*0];
+ fr1 = fblock[8*2];
+ fr2 = fblock[8*4];
+ fr3 = fblock[8*6];
+ ftrv();
+ fblock[8*0] = fr0;
+ fblock[8*2] = fr1;
+ fblock[8*4] = fr2;
+ fblock[8*6] = fr3;
+ fblock++;
+ } while(--i);
+ fblock-=8;
+
+ load_matrix(odd_table);
+
+ i=8;
+ do {
+ float t0,t1,t2,t3;
+ fr0 = fblock[8*1];
+ fr1 = fblock[8*3];
+ fr2 = fblock[8*5];
+ fr3 = fblock[8*7];
+ ftrv();
+ t0 = fblock[8*0];
+ t1 = fblock[8*2];
+ t2 = fblock[8*4];
+ t3 = fblock[8*6];
+ fblock++;
+ 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);
+}
+#endif
diff --git a/contrib/ffmpeg/libavcodec/sh4/qpel.c b/contrib/ffmpeg/libavcodec/sh4/qpel.c
new file mode 100644
index 000000000..7a73ac50d
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/sh4/qpel.c
@@ -0,0 +1,1600 @@
+/*
+ * 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 <bero@geocities.co.jp>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 LD(adr) *(uint32_t*)(adr)
+
+#define PIXOP2(OPNAME, OP) \
+/*static inline void 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) \
+{\
+ do {\
+ OP(LP(dst ),no_rnd_avg32(LD32(src1 ),LD32(src2 )) ); \
+ OP(LP(dst+4),no_rnd_avg32(LD32(src1+4),LD32(src2+4)) ); \
+ src1+=src_stride1; \
+ src2+=src_stride2; \
+ dst+=dst_stride; \
+ } while(--h); \
+}\
+\
+static inline void OPNAME ## _pixels8_l2(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(LD32(src1 ),LD32(src2 )) ); \
+ OP(LP(dst+4),rnd_avg32(LD32(src1+4),LD32(src2+4)) ); \
+ src1+=src_stride1; \
+ src2+=src_stride2; \
+ dst+=dst_stride; \
+ } while(--h); \
+}\
+\
+static inline void OPNAME ## _pixels4_l2(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(LD32(src1 ),LD32(src2 )) ); \
+ src1+=src_stride1; \
+ src2+=src_stride2; \
+ dst+=dst_stride; \
+ } while(--h); \
+}\
+\
+static inline void OPNAME ## _no_rnd_pixels16_l2(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(LD32(src1 ),LD32(src2 )) ); \
+ OP(LP(dst+4),no_rnd_avg32(LD32(src1+4),LD32(src2+4)) ); \
+ OP(LP(dst+8),no_rnd_avg32(LD32(src1+8),LD32(src2+8)) ); \
+ OP(LP(dst+12),no_rnd_avg32(LD32(src1+12),LD32(src2+12)) ); \
+ src1+=src_stride1; \
+ src2+=src_stride2; \
+ dst+=dst_stride; \
+ } while(--h); \
+}\
+\
+static inline void OPNAME ## _pixels16_l2(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(LD32(src1 ),LD32(src2 )) ); \
+ OP(LP(dst+4),rnd_avg32(LD32(src1+4),LD32(src2+4)) ); \
+ OP(LP(dst+8),rnd_avg32(LD32(src1+8),LD32(src2+8)) ); \
+ OP(LP(dst+12),rnd_avg32(LD32(src1+12),LD32(src2+12)) ); \
+ src1+=src_stride1; \
+ src2+=src_stride2; \
+ dst+=dst_stride; \
+ } while(--h); \
+}*/\
+\
+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(LP(src1 ),LP(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(LD32(src1 ),LP(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(LD32(src1 ),LP(src2 )) ); \
+ OP(LP(dst+4),no_rnd_avg32(LD32(src1+4),LP(src2+4)) ); \
+ OP(LP(dst+8),no_rnd_avg32(LD32(src1+8),LP(src2+8)) ); \
+ OP(LP(dst+12),no_rnd_avg32(LD32(src1+12),LP(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(LD32(src1 ),LP(src2 )) ); \
+ OP(LP(dst+4),rnd_avg32(LD32(src1+4),LP(src2+4)) ); \
+ OP(LP(dst+8),rnd_avg32(LD32(src1+8),LP(src2+8)) ); \
+ OP(LP(dst+12),rnd_avg32(LD32(src1+12),LP(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(LD32(src1 ),LP(src2 )) ); \
+ OP(LP(dst+4),no_rnd_avg32(LD32(src1+4),LP(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(LD32(src1 ),LP(src2 )) ); \
+ OP(LP(dst+4),rnd_avg32(LD32(src1+4),LP(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(LP(src1 ),LP(src2 )) ); \
+ OP(LP(dst+4),no_rnd_avg32(LP(src1+4),LP(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(LP(src1 ),LP(src2 )) ); \
+ OP(LP(dst+4),rnd_avg32(LP(src1+4),LP(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(LP(src1 ),LP(src2 )) ); \
+ OP(LP(dst+4),no_rnd_avg32(LP(src1+4),LP(src2+4)) ); \
+ OP(LP(dst+8),no_rnd_avg32(LP(src1+8),LP(src2+8)) ); \
+ OP(LP(dst+12),no_rnd_avg32(LP(src1+12),LP(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(LP(src1 ),LP(src2 )) ); \
+ OP(LP(dst+4),rnd_avg32(LP(src1+4),LP(src2+4)) ); \
+ OP(LP(dst+8),rnd_avg32(LP(src1+8),LP(src2+8)) ); \
+ OP(LP(dst+12),rnd_avg32(LP(src1+12),LP(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,LP(src1),LP(src2)); \
+ UNPACK(a2,a3,LP(src3),LP(src4)); \
+ OP(LP(dst),rnd_PACK(a0,a1,a2,a3)); \
+ UNPACK(a0,a1,LP(src1+4),LP(src2+4)); \
+ UNPACK(a2,a3,LP(src3+4),LP(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,LP(src1),LP(src2)); \
+ UNPACK(a2,a3,LP(src3),LP(src4)); \
+ OP(LP(dst),no_rnd_PACK(a0,a1,a2,a3)); \
+ UNPACK(a0,a1,LP(src1+4),LP(src2+4)); \
+ UNPACK(a2,a3,LP(src3+4),LP(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,LD32(src1),LP(src2)); \
+ UNPACK(a2,a3,LP(src3),LP(src4)); \
+ OP(LP(dst),rnd_PACK(a0,a1,a2,a3)); \
+ UNPACK(a0,a1,LD32(src1+4),LP(src2+4)); \
+ UNPACK(a2,a3,LP(src3+4),LP(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,LD32(src1),LP(src2)); \
+ UNPACK(a2,a3,LP(src3),LP(src4)); \
+ OP(LP(dst),no_rnd_PACK(a0,a1,a2,a3)); \
+ UNPACK(a0,a1,LD32(src1+4),LP(src2+4)); \
+ UNPACK(a2,a3,LP(src3+4),LP(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,LP(src1),LP(src2)); \
+ UNPACK(a2,a3,LP(src3),LP(src4)); \
+ OP(LP(dst),rnd_PACK(a0,a1,a2,a3)); \
+ UNPACK(a0,a1,LP(src1+4),LP(src2+4)); \
+ UNPACK(a2,a3,LP(src3+4),LP(src4+4)); \
+ OP(LP(dst+8),rnd_PACK(a0,a1,a2,a3)); \
+ UNPACK(a0,a1,LP(src1+8),LP(src2+8)); \
+ UNPACK(a2,a3,LP(src3+8),LP(src4+8)); \
+ OP(LP(dst+8),rnd_PACK(a0,a1,a2,a3)); \
+ UNPACK(a0,a1,LP(src1+12),LP(src2+12)); \
+ UNPACK(a2,a3,LP(src3+12),LP(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,LP(src1),LP(src2)); \
+ UNPACK(a2,a3,LP(src3),LP(src4)); \
+ OP(LP(dst),no_rnd_PACK(a0,a1,a2,a3)); \
+ UNPACK(a0,a1,LP(src1+4),LP(src2+4)); \
+ UNPACK(a2,a3,LP(src3+4),LP(src4+4)); \
+ OP(LP(dst+4),no_rnd_PACK(a0,a1,a2,a3)); \
+ UNPACK(a0,a1,LP(src1+8),LP(src2+8)); \
+ UNPACK(a2,a3,LP(src3+8),LP(src4+8)); \
+ OP(LP(dst+8),no_rnd_PACK(a0,a1,a2,a3)); \
+ UNPACK(a0,a1,LP(src1+12),LP(src2+12)); \
+ UNPACK(a2,a3,LP(src3+12),LP(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,LD32(src1),LP(src2)); \
+ UNPACK(a2,a3,LP(src3),LP(src4)); \
+ OP(LP(dst),rnd_PACK(a0,a1,a2,a3)); \
+ UNPACK(a0,a1,LD32(src1+4),LP(src2+4)); \
+ UNPACK(a2,a3,LP(src3+4),LP(src4+4)); \
+ OP(LP(dst+8),rnd_PACK(a0,a1,a2,a3)); \
+ UNPACK(a0,a1,LD32(src1+8),LP(src2+8)); \
+ UNPACK(a2,a3,LP(src3+8),LP(src4+8)); \
+ OP(LP(dst+8),rnd_PACK(a0,a1,a2,a3)); \
+ UNPACK(a0,a1,LD32(src1+12),LP(src2+12)); \
+ UNPACK(a2,a3,LP(src3+12),LP(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,LD32(src1),LP(src2)); \
+ UNPACK(a2,a3,LP(src3),LP(src4)); \
+ OP(LP(dst),no_rnd_PACK(a0,a1,a2,a3)); \
+ UNPACK(a0,a1,LD32(src1+4),LP(src2+4)); \
+ UNPACK(a2,a3,LP(src3+4),LP(src4+4)); \
+ OP(LP(dst+4),no_rnd_PACK(a0,a1,a2,a3)); \
+ UNPACK(a0,a1,LD32(src1+8),LP(src2+8)); \
+ UNPACK(a2,a3,LP(src3+8),LP(src4+8)); \
+ OP(LP(dst+8),no_rnd_PACK(a0,a1,a2,a3)); \
+ UNPACK(a0,a1,LD32(src1+12),LP(src2+12)); \
+ UNPACK(a2,a3,LP(src3+12),LP(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);
+}
+
+static void 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<<shift;
+
+ width--;
+ height--;
+
+ for(y=0; y<h; y++){
+ int x;
+
+ vx= ox;
+ vy= oy;
+ for(x=0; x<8; x++){ //XXX FIXME optimize
+ int src_x, src_y, frac_x, frac_y, index;
+
+ src_x= vx>>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 + 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= 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= clip(src_x, 0, width) + clip(src_y, 0, height)*stride;
+ dst[y*stride + x]= src[index ];
+ }
+ }
+
+ vx+= dxx;
+ vy+= dyx;
+ }
+ ox += dxy;
+ oy += dyy;
+ }
+}
+#define H264_CHROMA_MC(OPNAME, OP)\
+static void OPNAME ## h264_chroma_mc2_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);\
+ \
+ 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_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);\
+ \
+ 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_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);\
+ \
+ 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
+
+#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_c (uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## pixels8_c(dst, src, stride, 8);\
+}\
+\
+static void OPNAME ## qpel8_mc10_c(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_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## mpeg4_qpel8_h_lowpass(dst, src, stride, stride, 8);\
+}\
+\
+static void OPNAME ## qpel8_mc30_c(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_c(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_c(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_c(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 ff_ ## OPNAME ## qpel8_mc11_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[16*9];\
+ uint8_t halfH[72];\
+ uint8_t halfV[64];\
+ uint8_t halfHV[64];\
+ copy_block9(full, src, 16, stride, 9);\
+ put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full, 8, 16);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l4_aligned(dst, full, halfH, halfV, halfHV, stride, 16, 8, 8, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc11_c(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 ff_ ## OPNAME ## qpel8_mc31_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[16*9];\
+ uint8_t halfH[72];\
+ uint8_t halfV[64];\
+ uint8_t halfHV[64];\
+ copy_block9(full, src, 16, stride, 9);\
+ put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full+1, 8, 16);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l4_aligned0(dst, full+1, halfH, halfV, halfHV, stride, 16, 8, 8, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc31_c(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 ff_ ## OPNAME ## qpel8_mc13_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[16*9];\
+ uint8_t halfH[72];\
+ uint8_t halfV[64];\
+ uint8_t halfHV[64];\
+ copy_block9(full, src, 16, stride, 9);\
+ put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full, 8, 16);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l4_aligned(dst, full+16, halfH+8, halfV, halfHV, stride, 16, 8, 8, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc13_c(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 ff_ ## OPNAME ## qpel8_mc33_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[16*9];\
+ uint8_t halfH[72];\
+ uint8_t halfV[64];\
+ uint8_t halfHV[64];\
+ copy_block9(full, src, 16, stride, 9);\
+ put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full , 8, 16, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full+1, 8, 16);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l4_aligned0(dst, full+17, halfH+8, halfV, halfHV, stride, 16, 8, 8, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc33_c(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_c(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_c(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 ff_ ## OPNAME ## qpel8_mc12_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[16*9];\
+ uint8_t halfH[72];\
+ uint8_t halfV[64];\
+ uint8_t halfHV[64];\
+ copy_block9(full, src, 16, stride, 9);\
+ put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full, 8, 16);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l2_aligned(dst, halfV, halfHV, stride, 8, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc12_c(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 ff_ ## OPNAME ## qpel8_mc32_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[16*9];\
+ uint8_t halfH[72];\
+ uint8_t halfV[64];\
+ uint8_t halfHV[64];\
+ copy_block9(full, src, 16, stride, 9);\
+ put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfV, full+1, 8, 16);\
+ put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\
+ OPNAME ## pixels8_l2_aligned(dst, halfV, halfHV, stride, 8, 8, 8);\
+}\
+static void OPNAME ## qpel8_mc32_c(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_c(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_c (uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## pixels16_c(dst, src, stride, 16);\
+}\
+\
+static void OPNAME ## qpel16_mc10_c(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_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## mpeg4_qpel16_h_lowpass(dst, src, stride, stride, 16);\
+}\
+\
+static void OPNAME ## qpel16_mc30_c(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_c(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_c(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_c(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 ff_ ## OPNAME ## qpel16_mc11_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[24*17];\
+ uint8_t halfH[272];\
+ uint8_t halfV[256];\
+ uint8_t halfHV[256];\
+ copy_block17(full, src, 24, stride, 17);\
+ put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full, 16, 24);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l4_aligned(dst, full, halfH, halfV, halfHV, stride, 24, 16, 16, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc11_c(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 ff_ ## OPNAME ## qpel16_mc31_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[24*17];\
+ uint8_t halfH[272];\
+ uint8_t halfV[256];\
+ uint8_t halfHV[256];\
+ copy_block17(full, src, 24, stride, 17);\
+ put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full+1, 16, 24);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l4_aligned0(dst, full+1, halfH, halfV, halfHV, stride, 24, 16, 16, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc31_c(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 ff_ ## OPNAME ## qpel16_mc13_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[24*17];\
+ uint8_t halfH[272];\
+ uint8_t halfV[256];\
+ uint8_t halfHV[256];\
+ copy_block17(full, src, 24, stride, 17);\
+ put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full, 16, 24);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l4_aligned(dst, full+24, halfH+16, halfV, halfHV, stride, 24, 16, 16, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc13_c(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 ff_ ## OPNAME ## qpel16_mc33_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[24*17];\
+ uint8_t halfH[272];\
+ uint8_t halfV[256];\
+ uint8_t halfHV[256];\
+ copy_block17(full, src, 24, stride, 17);\
+ put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full , 16, 24, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full+1, 16, 24);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l4_aligned0(dst, full+25, halfH+16, halfV, halfHV, stride, 24, 16, 16, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc33_c(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_c(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_c(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 ff_ ## OPNAME ## qpel16_mc12_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[24*17];\
+ uint8_t halfH[272];\
+ uint8_t halfV[256];\
+ uint8_t halfHV[256];\
+ copy_block17(full, src, 24, stride, 17);\
+ put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full, 16, 24);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l2_aligned(dst, halfV, halfHV, stride, 16, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc12_c(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 ff_ ## OPNAME ## qpel16_mc32_old_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[24*17];\
+ uint8_t halfH[272];\
+ uint8_t halfV[256];\
+ uint8_t halfHV[256];\
+ copy_block17(full, src, 24, stride, 17);\
+ put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfV, full+1, 16, 24);\
+ put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\
+ OPNAME ## pixels16_l2_aligned(dst, halfV, halfHV, stride, 16, 16, 16);\
+}\
+static void OPNAME ## qpel16_mc32_c(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_c(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
+
+#if 1
+#define H264_LOWPASS(OPNAME, OP, OP2) \
+static inline void OPNAME ## h264_qpel_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride,int w,int h){\
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\
+ do {\
+ int srcB,srcA,src0,src1,src2,src3,src4,src5,src6;\
+ uint8_t *s = src-2;\
+ srcB = *s++;\
+ srcA = *s++;\
+ src0 = *s++;\
+ src1 = *s++;\
+ src2 = *s++;\
+ src3 = *s++;\
+ OP(dst[0], (src0+src1)*20 - (srcA+src2)*5 + (srcB+src3));\
+ src4 = *s++;\
+ OP(dst[1], (src1+src2)*20 - (src0+src3)*5 + (srcA+src4));\
+ src5 = *s++;\
+ OP(dst[2], (src2+src3)*20 - (src1+src4)*5 + (src0+src5));\
+ src6 = *s++;\
+ OP(dst[3], (src3+src4)*20 - (src2+src5)*5 + (src1+src6));\
+ if (w>4) { /* it optimized */ \
+ int src7,src8,src9,src10; \
+ src7 = *s++;\
+ OP(dst[4], (src4+src5)*20 - (src3+src6)*5 + (src2+src7));\
+ src8 = *s++;\
+ OP(dst[5], (src5+src6)*20 - (src4+src7)*5 + (src3+src8));\
+ src9 = *s++;\
+ OP(dst[6], (src6+src7)*20 - (src5+src8)*5 + (src4+src9));\
+ src10 = *s++;\
+ OP(dst[7], (src7+src8)*20 - (src6+src9)*5 + (src5+src10));\
+ if (w>8) { \
+ int src11,src12,src13,src14,src15,src16,src17,src18; \
+ src11 = *s++;\
+ OP(dst[8] , (src8 +src9 )*20 - (src7 +src10)*5 + (src6 +src11));\
+ src12 = *s++;\
+ OP(dst[9] , (src9 +src10)*20 - (src8 +src11)*5 + (src7 +src12));\
+ src13 = *s++;\
+ OP(dst[10], (src10+src11)*20 - (src9 +src12)*5 + (src8 +src13));\
+ src14 = *s++;\
+ OP(dst[11], (src11+src12)*20 - (src10+src13)*5 + (src9 +src14));\
+ src15 = *s++;\
+ OP(dst[12], (src12+src13)*20 - (src11+src14)*5 + (src10+src15));\
+ src16 = *s++;\
+ OP(dst[13], (src13+src14)*20 - (src12+src15)*5 + (src11+src16));\
+ src17 = *s++;\
+ OP(dst[14], (src14+src15)*20 - (src13+src16)*5 + (src12+src17));\
+ src18 = *s++;\
+ OP(dst[15], (src15+src16)*20 - (src14+src17)*5 + (src13+src18));\
+ } \
+ } \
+ dst+=dstStride;\
+ src+=srcStride;\
+ }while(--h);\
+}\
+\
+static inline void OPNAME ## h264_qpel_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride,int w,int h){\
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\
+ do{\
+ int srcB,srcA,src0,src1,src2,src3,src4,src5,src6;\
+ uint8_t *s = src-2*srcStride,*d=dst;\
+ srcB = *s; s+=srcStride;\
+ srcA = *s; s+=srcStride;\
+ src0 = *s; s+=srcStride;\
+ src1 = *s; s+=srcStride;\
+ src2 = *s; s+=srcStride;\
+ src3 = *s; s+=srcStride;\
+ OP(*d, (src0+src1)*20 - (srcA+src2)*5 + (srcB+src3));d+=dstStride;\
+ src4 = *s; s+=srcStride;\
+ OP(*d, (src1+src2)*20 - (src0+src3)*5 + (srcA+src4));d+=dstStride;\
+ src5 = *s; s+=srcStride;\
+ OP(*d, (src2+src3)*20 - (src1+src4)*5 + (src0+src5));d+=dstStride;\
+ src6 = *s; s+=srcStride;\
+ OP(*d, (src3+src4)*20 - (src2+src5)*5 + (src1+src6));d+=dstStride;\
+ if (h>4) { \
+ int src7,src8,src9,src10; \
+ src7 = *s; s+=srcStride;\
+ OP(*d, (src4+src5)*20 - (src3+src6)*5 + (src2+src7));d+=dstStride;\
+ src8 = *s; s+=srcStride;\
+ OP(*d, (src5+src6)*20 - (src4+src7)*5 + (src3+src8));d+=dstStride;\
+ src9 = *s; s+=srcStride;\
+ OP(*d, (src6+src7)*20 - (src5+src8)*5 + (src4+src9));d+=dstStride;\
+ src10 = *s; s+=srcStride;\
+ OP(*d, (src7+src8)*20 - (src6+src9)*5 + (src5+src10));d+=dstStride;\
+ if (h>8) { \
+ int src11,src12,src13,src14,src15,src16,src17,src18; \
+ src11 = *s; s+=srcStride;\
+ OP(*d , (src8 +src9 )*20 - (src7 +src10)*5 + (src6 +src11));d+=dstStride;\
+ src12 = *s; s+=srcStride;\
+ OP(*d , (src9 +src10)*20 - (src8 +src11)*5 + (src7 +src12));d+=dstStride;\
+ src13 = *s; s+=srcStride;\
+ OP(*d, (src10+src11)*20 - (src9 +src12)*5 + (src8 +src13));d+=dstStride;\
+ src14 = *s; s+=srcStride;\
+ OP(*d, (src11+src12)*20 - (src10+src13)*5 + (src9 +src14));d+=dstStride;\
+ src15 = *s; s+=srcStride;\
+ OP(*d, (src12+src13)*20 - (src11+src14)*5 + (src10+src15));d+=dstStride;\
+ src16 = *s; s+=srcStride;\
+ OP(*d, (src13+src14)*20 - (src12+src15)*5 + (src11+src16));d+=dstStride;\
+ src17 = *s; s+=srcStride;\
+ OP(*d, (src14+src15)*20 - (src13+src16)*5 + (src12+src17));d+=dstStride;\
+ src18 = *s; s+=srcStride;\
+ OP(*d, (src15+src16)*20 - (src14+src17)*5 + (src13+src18));d+=dstStride;\
+ } \
+ } \
+ dst++;\
+ src++;\
+ }while(--w);\
+}\
+\
+static inline void OPNAME ## h264_qpel_hv_lowpass(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride,int w,int h){\
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\
+ int i;\
+ src -= 2*srcStride;\
+ i= h+5; \
+ do {\
+ int srcB,srcA,src0,src1,src2,src3,src4,src5,src6;\
+ uint8_t *s = src-2;\
+ srcB = *s++;\
+ srcA = *s++;\
+ src0 = *s++;\
+ src1 = *s++;\
+ src2 = *s++;\
+ src3 = *s++;\
+ tmp[0] = ((src0+src1)*20 - (srcA+src2)*5 + (srcB+src3));\
+ src4 = *s++;\
+ tmp[1] = ((src1+src2)*20 - (src0+src3)*5 + (srcA+src4));\
+ src5 = *s++;\
+ tmp[2] = ((src2+src3)*20 - (src1+src4)*5 + (src0+src5));\
+ src6 = *s++;\
+ tmp[3] = ((src3+src4)*20 - (src2+src5)*5 + (src1+src6));\
+ if (w>4) { /* it optimized */ \
+ int src7,src8,src9,src10; \
+ src7 = *s++;\
+ tmp[4] = ((src4+src5)*20 - (src3+src6)*5 + (src2+src7));\
+ src8 = *s++;\
+ tmp[5] = ((src5+src6)*20 - (src4+src7)*5 + (src3+src8));\
+ src9 = *s++;\
+ tmp[6] = ((src6+src7)*20 - (src5+src8)*5 + (src4+src9));\
+ src10 = *s++;\
+ tmp[7] = ((src7+src8)*20 - (src6+src9)*5 + (src5+src10));\
+ if (w>8) { \
+ int src11,src12,src13,src14,src15,src16,src17,src18; \
+ src11 = *s++;\
+ tmp[8] = ((src8 +src9 )*20 - (src7 +src10)*5 + (src6 +src11));\
+ src12 = *s++;\
+ tmp[9] = ((src9 +src10)*20 - (src8 +src11)*5 + (src7 +src12));\
+ src13 = *s++;\
+ tmp[10] = ((src10+src11)*20 - (src9 +src12)*5 + (src8 +src13));\
+ src14 = *s++;\
+ tmp[11] = ((src11+src12)*20 - (src10+src13)*5 + (src9 +src14));\
+ src15 = *s++;\
+ tmp[12] = ((src12+src13)*20 - (src11+src14)*5 + (src10+src15));\
+ src16 = *s++;\
+ tmp[13] = ((src13+src14)*20 - (src12+src15)*5 + (src11+src16));\
+ src17 = *s++;\
+ tmp[14] = ((src14+src15)*20 - (src13+src16)*5 + (src12+src17));\
+ src18 = *s++;\
+ tmp[15] = ((src15+src16)*20 - (src14+src17)*5 + (src13+src18));\
+ } \
+ } \
+ tmp+=tmpStride;\
+ src+=srcStride;\
+ }while(--i);\
+ tmp -= tmpStride*(h+5-2);\
+ i = w; \
+ do {\
+ int tmpB,tmpA,tmp0,tmp1,tmp2,tmp3,tmp4,tmp5,tmp6;\
+ int16_t *s = tmp-2*tmpStride; \
+ uint8_t *d=dst;\
+ tmpB = *s; s+=tmpStride;\
+ tmpA = *s; s+=tmpStride;\
+ tmp0 = *s; s+=tmpStride;\
+ tmp1 = *s; s+=tmpStride;\
+ tmp2 = *s; s+=tmpStride;\
+ tmp3 = *s; s+=tmpStride;\
+ OP2(*d, (tmp0+tmp1)*20 - (tmpA+tmp2)*5 + (tmpB+tmp3));d+=dstStride;\
+ tmp4 = *s; s+=tmpStride;\
+ OP2(*d, (tmp1+tmp2)*20 - (tmp0+tmp3)*5 + (tmpA+tmp4));d+=dstStride;\
+ tmp5 = *s; s+=tmpStride;\
+ OP2(*d, (tmp2+tmp3)*20 - (tmp1+tmp4)*5 + (tmp0+tmp5));d+=dstStride;\
+ tmp6 = *s; s+=tmpStride;\
+ OP2(*d, (tmp3+tmp4)*20 - (tmp2+tmp5)*5 + (tmp1+tmp6));d+=dstStride;\
+ if (h>4) { \
+ int tmp7,tmp8,tmp9,tmp10; \
+ tmp7 = *s; s+=tmpStride;\
+ OP2(*d, (tmp4+tmp5)*20 - (tmp3+tmp6)*5 + (tmp2+tmp7));d+=dstStride;\
+ tmp8 = *s; s+=tmpStride;\
+ OP2(*d, (tmp5+tmp6)*20 - (tmp4+tmp7)*5 + (tmp3+tmp8));d+=dstStride;\
+ tmp9 = *s; s+=tmpStride;\
+ OP2(*d, (tmp6+tmp7)*20 - (tmp5+tmp8)*5 + (tmp4+tmp9));d+=dstStride;\
+ tmp10 = *s; s+=tmpStride;\
+ OP2(*d, (tmp7+tmp8)*20 - (tmp6+tmp9)*5 + (tmp5+tmp10));d+=dstStride;\
+ if (h>8) { \
+ int tmp11,tmp12,tmp13,tmp14,tmp15,tmp16,tmp17,tmp18; \
+ tmp11 = *s; s+=tmpStride;\
+ OP2(*d , (tmp8 +tmp9 )*20 - (tmp7 +tmp10)*5 + (tmp6 +tmp11));d+=dstStride;\
+ tmp12 = *s; s+=tmpStride;\
+ OP2(*d , (tmp9 +tmp10)*20 - (tmp8 +tmp11)*5 + (tmp7 +tmp12));d+=dstStride;\
+ tmp13 = *s; s+=tmpStride;\
+ OP2(*d, (tmp10+tmp11)*20 - (tmp9 +tmp12)*5 + (tmp8 +tmp13));d+=dstStride;\
+ tmp14 = *s; s+=tmpStride;\
+ OP2(*d, (tmp11+tmp12)*20 - (tmp10+tmp13)*5 + (tmp9 +tmp14));d+=dstStride;\
+ tmp15 = *s; s+=tmpStride;\
+ OP2(*d, (tmp12+tmp13)*20 - (tmp11+tmp14)*5 + (tmp10+tmp15));d+=dstStride;\
+ tmp16 = *s; s+=tmpStride;\
+ OP2(*d, (tmp13+tmp14)*20 - (tmp12+tmp15)*5 + (tmp11+tmp16));d+=dstStride;\
+ tmp17 = *s; s+=tmpStride;\
+ OP2(*d, (tmp14+tmp15)*20 - (tmp13+tmp16)*5 + (tmp12+tmp17));d+=dstStride;\
+ tmp18 = *s; s+=tmpStride;\
+ OP2(*d, (tmp15+tmp16)*20 - (tmp14+tmp17)*5 + (tmp13+tmp18));d+=dstStride;\
+ } \
+ } \
+ dst++;\
+ tmp++;\
+ }while(--i);\
+}\
+\
+static void OPNAME ## h264_qpel4_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ OPNAME ## h264_qpel_h_lowpass(dst,src,dstStride,srcStride,4,4); \
+}\
+static void OPNAME ## h264_qpel8_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ OPNAME ## h264_qpel_h_lowpass(dst,src,dstStride,srcStride,8,8); \
+}\
+static void OPNAME ## h264_qpel16_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ OPNAME ## h264_qpel_h_lowpass(dst,src,dstStride,srcStride,16,16); \
+}\
+\
+static void OPNAME ## h264_qpel4_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ OPNAME ## h264_qpel_v_lowpass(dst,src,dstStride,srcStride,4,4); \
+}\
+static void OPNAME ## h264_qpel8_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ OPNAME ## h264_qpel_v_lowpass(dst,src,dstStride,srcStride,8,8); \
+}\
+static void OPNAME ## h264_qpel16_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
+ OPNAME ## h264_qpel_v_lowpass(dst,src,dstStride,srcStride,16,16); \
+}\
+static void OPNAME ## h264_qpel4_hv_lowpass(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride){\
+ OPNAME ## h264_qpel_hv_lowpass(dst,tmp,src,dstStride,tmpStride,srcStride,4,4); \
+}\
+static void OPNAME ## h264_qpel8_hv_lowpass(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride){\
+ OPNAME ## h264_qpel_hv_lowpass(dst,tmp,src,dstStride,tmpStride,srcStride,8,8); \
+}\
+static void OPNAME ## h264_qpel16_hv_lowpass(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride){\
+ OPNAME ## h264_qpel_hv_lowpass(dst,tmp,src,dstStride,tmpStride,srcStride,16,16); \
+}\
+
+#define H264_MC(OPNAME, SIZE) \
+static void OPNAME ## h264_qpel ## SIZE ## _mc00_c (uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## pixels ## SIZE ## _c(dst, src, stride, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc10_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t half[SIZE*SIZE];\
+ put_h264_qpel ## SIZE ## _h_lowpass(half, src, SIZE, stride);\
+ OPNAME ## pixels ## SIZE ## _l2_aligned2(dst, src, half, stride, stride, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc20_c(uint8_t *dst, uint8_t *src, int stride){\
+ OPNAME ## h264_qpel ## SIZE ## _h_lowpass(dst, src, stride, stride);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc30_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t half[SIZE*SIZE];\
+ put_h264_qpel ## SIZE ## _h_lowpass(half, src, SIZE, stride);\
+ OPNAME ## pixels ## SIZE ## _l2_aligned2(dst, src+1, half, stride, stride, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc01_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ uint8_t half[SIZE*SIZE];\
+ copy_block ## SIZE (full, src - stride*2, SIZE, stride, SIZE + 5);\
+ put_h264_qpel ## SIZE ## _v_lowpass(half, full_mid, SIZE, SIZE);\
+ OPNAME ## pixels ## SIZE ## _l2_aligned(dst, full_mid, half, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc02_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ copy_block ## SIZE (full, src - stride*2, SIZE, stride, SIZE + 5);\
+ OPNAME ## h264_qpel ## SIZE ## _v_lowpass(dst, full_mid, stride, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc03_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ uint8_t half[SIZE*SIZE];\
+ copy_block ## SIZE (full, src - stride*2, SIZE, stride, SIZE + 5);\
+ put_h264_qpel ## SIZE ## _v_lowpass(half, full_mid, SIZE, SIZE);\
+ OPNAME ## pixels ## SIZE ## _l2_aligned(dst, full_mid+SIZE, half, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc11_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ uint8_t halfH[SIZE*SIZE];\
+ uint8_t halfV[SIZE*SIZE];\
+ put_h264_qpel ## SIZE ## _h_lowpass(halfH, src, SIZE, stride);\
+ copy_block ## SIZE (full, src - stride*2, SIZE, stride, SIZE + 5);\
+ put_h264_qpel ## SIZE ## _v_lowpass(halfV, full_mid, SIZE, SIZE);\
+ OPNAME ## pixels ## SIZE ## _l2_aligned(dst, halfH, halfV, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc31_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ uint8_t halfH[SIZE*SIZE];\
+ uint8_t halfV[SIZE*SIZE];\
+ put_h264_qpel ## SIZE ## _h_lowpass(halfH, src, SIZE, stride);\
+ copy_block ## SIZE (full, src - stride*2 + 1, SIZE, stride, SIZE + 5);\
+ put_h264_qpel ## SIZE ## _v_lowpass(halfV, full_mid, SIZE, SIZE);\
+ OPNAME ## pixels ## SIZE ## _l2_aligned(dst, halfH, halfV, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc13_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ uint8_t halfH[SIZE*SIZE];\
+ uint8_t halfV[SIZE*SIZE];\
+ put_h264_qpel ## SIZE ## _h_lowpass(halfH, src + stride, SIZE, stride);\
+ copy_block ## SIZE (full, src - stride*2, SIZE, stride, SIZE + 5);\
+ put_h264_qpel ## SIZE ## _v_lowpass(halfV, full_mid, SIZE, SIZE);\
+ OPNAME ## pixels ## SIZE ## _l2_aligned(dst, halfH, halfV, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc33_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ uint8_t halfH[SIZE*SIZE];\
+ uint8_t halfV[SIZE*SIZE];\
+ put_h264_qpel ## SIZE ## _h_lowpass(halfH, src + stride, SIZE, stride);\
+ copy_block ## SIZE (full, src - stride*2 + 1, SIZE, stride, SIZE + 5);\
+ put_h264_qpel ## SIZE ## _v_lowpass(halfV, full_mid, SIZE, SIZE);\
+ OPNAME ## pixels ## SIZE ## _l2_aligned(dst, halfH, halfV, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc22_c(uint8_t *dst, uint8_t *src, int stride){\
+ int16_t tmp[SIZE*(SIZE+5)];\
+ OPNAME ## h264_qpel ## SIZE ## _hv_lowpass(dst, tmp, src, stride, SIZE, stride);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc21_c(uint8_t *dst, uint8_t *src, int stride){\
+ int16_t tmp[SIZE*(SIZE+5)];\
+ uint8_t halfH[SIZE*SIZE];\
+ uint8_t halfHV[SIZE*SIZE];\
+ put_h264_qpel ## SIZE ## _h_lowpass(halfH, src, SIZE, stride);\
+ put_h264_qpel ## SIZE ## _hv_lowpass(halfHV, tmp, src, SIZE, SIZE, stride);\
+ OPNAME ## pixels ## SIZE ## _l2_aligned(dst, halfH, halfHV, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc23_c(uint8_t *dst, uint8_t *src, int stride){\
+ int16_t tmp[SIZE*(SIZE+5)];\
+ uint8_t halfH[SIZE*SIZE];\
+ uint8_t halfHV[SIZE*SIZE];\
+ put_h264_qpel ## SIZE ## _h_lowpass(halfH, src + stride, SIZE, stride);\
+ put_h264_qpel ## SIZE ## _hv_lowpass(halfHV, tmp, src, SIZE, SIZE, stride);\
+ OPNAME ## pixels ## SIZE ## _l2_aligned(dst, halfH, halfHV, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc12_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ int16_t tmp[SIZE*(SIZE+5)];\
+ uint8_t halfV[SIZE*SIZE];\
+ uint8_t halfHV[SIZE*SIZE];\
+ copy_block ## SIZE (full, src - stride*2, SIZE, stride, SIZE + 5);\
+ put_h264_qpel ## SIZE ## _v_lowpass(halfV, full_mid, SIZE, SIZE);\
+ put_h264_qpel ## SIZE ## _hv_lowpass(halfHV, tmp, src, SIZE, SIZE, stride);\
+ OPNAME ## pixels ## SIZE ## _l2_aligned(dst, halfV, halfHV, stride, SIZE, SIZE, SIZE);\
+}\
+\
+static void OPNAME ## h264_qpel ## SIZE ## _mc32_c(uint8_t *dst, uint8_t *src, int stride){\
+ uint8_t full[SIZE*(SIZE+5)];\
+ uint8_t * const full_mid= full + SIZE*2;\
+ int16_t tmp[SIZE*(SIZE+5)];\
+ uint8_t halfV[SIZE*SIZE];\
+ uint8_t halfHV[SIZE*SIZE];\
+ copy_block ## SIZE (full, src - stride*2 + 1, SIZE, stride, SIZE + 5);\
+ put_h264_qpel ## SIZE ## _v_lowpass(halfV, full_mid, SIZE, SIZE);\
+ put_h264_qpel ## SIZE ## _hv_lowpass(halfHV, tmp, src, SIZE, SIZE, stride);\
+ OPNAME ## pixels ## SIZE ## _l2_aligned(dst, halfV, halfHV, stride, SIZE, SIZE, SIZE);\
+}\
+
+#define op_avg(a, b) a = (((a)+cm[((b) + 16)>>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 = cm[((b) + 16)>>5]
+#define op2_avg(a, b) a = (((a)+cm[((b) + 512)>>10]+1)>>1)
+#define op2_put(a, b) a = cm[((b) + 512)>>10]
+
+H264_LOWPASS(put_ , op_put, op2_put)
+H264_LOWPASS(avg_ , op_avg, op2_avg)
+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
+#endif
+
+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_c (uint8_t *dst, uint8_t *src, int stride){
+ put_pixels8_c(dst, src, stride, 8);
+}
+
+static void put_mspel8_mc10_c(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_c(uint8_t *dst, uint8_t *src, int stride){
+ wmv2_mspel8_h_lowpass(dst, src, stride, stride, 8);
+}
+
+static void put_mspel8_mc30_c(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_c(uint8_t *dst, uint8_t *src, int stride){
+ wmv2_mspel8_v_lowpass(dst, src, stride, stride, 8);
+}
+
+static void put_mspel8_mc12_c(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_c(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_c(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/contrib/ffmpeg/libavcodec/shorten.c b/contrib/ffmpeg/libavcodec/shorten.c
new file mode 100644
index 000000000..358ecf23f
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/shorten.c
@@ -0,0 +1,533 @@
+/*
+ * 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.c
+ * Shorten decoder
+ * @author Jeff Muizelaar
+ *
+ */
+
+#define DEBUG
+#include <limits.h>
+#include "avcodec.h"
+#include "bitstream.h"
+#include "golomb.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_S16HL 3
+#define TYPE_S16LH 5
+
+#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
+
+#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;
+ int channels;
+
+ int32_t *decoded[MAX_CHANNELS];
+ int32_t *offset[MAX_CHANNELS];
+ 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;
+} ShortenContext;
+
+static 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;
+ 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 -1;
+ }
+ 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 -1;
+ }
+
+ s->offset[chan] = av_realloc(s->offset[chan], sizeof(int32_t)*FFMAX(1, s->nmean));
+
+ s->decoded[chan] = av_realloc(s->decoded[chan], sizeof(int32_t)*(s->blocksize + s->nwrap));
+ for (i=0; i<s->nwrap; i++)
+ s->decoded[chan][i] = 0;
+ s->decoded[chan] += s->nwrap;
+ }
+ 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[s->nwrap + i] <<= s->bitshift;
+}
+
+
+static void 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_S16HL:
+ case TYPE_S16LH:
+ mean = 0;
+ break;
+ default:
+ av_log(s->avctx, AV_LOG_ERROR, "unknown audio type");
+ abort();
+ }
+
+ for (chan = 0; chan < s->channels; chan++)
+ for (i = 0; i < nblock; i++)
+ s->offset[chan][i] = mean;
+}
+
+static int inline get_le32(GetBitContext *gb)
+{
+ return bswap_32(get_bits_long(gb, 32));
+}
+
+static short inline get_le16(GetBitContext *gb)
+{
+ return bswap_16(get_bits_long(gb, 16));
+}
+
+static int decode_wave_header(AVCodecContext *avctx, uint8_t *header, int header_size)
+{
+ GetBitContext hb;
+ int len;
+ int chunk_size;
+ short wave_format;
+
+ init_get_bits(&hb, header, header_size*8);
+ if (get_le32(&hb) != MKTAG('R','I','F','F')) {
+ av_log(avctx, AV_LOG_ERROR, "missing RIFF tag\n");
+ return -1;
+ }
+
+ chunk_size = get_le32(&hb);
+
+ if (get_le32(&hb) != MKTAG('W','A','V','E')) {
+ av_log(avctx, AV_LOG_ERROR, "missing WAVE tag\n");
+ return -1;
+ }
+
+ while (get_le32(&hb) != MKTAG('f','m','t',' ')) {
+ len = get_le32(&hb);
+ skip_bits(&hb, 8*len);
+ }
+ len = get_le32(&hb);
+
+ if (len < 16) {
+ av_log(avctx, AV_LOG_ERROR, "fmt chunk was too short\n");
+ return -1;
+ }
+
+ wave_format = get_le16(&hb);
+
+ switch (wave_format) {
+ case WAVE_FORMAT_PCM:
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "unsupported wave format\n");
+ return -1;
+ }
+
+ avctx->channels = get_le16(&hb);
+ avctx->sample_rate = get_le32(&hb);
+ avctx->bit_rate = get_le32(&hb) * 8;
+ avctx->block_align = get_le16(&hb);
+ avctx->bits_per_sample = get_le16(&hb);
+
+ if (avctx->bits_per_sample != 16) {
+ av_log(avctx, AV_LOG_ERROR, "unsupported number of bits per sample\n");
+ return -1;
+ }
+
+ len -= 16;
+ if (len > 0)
+ av_log(avctx, AV_LOG_INFO, "%d header bytes unparsed\n", len);
+
+ return 0;
+}
+
+static int16_t * interleave_buffer(int16_t *samples, int nchan, int blocksize, int32_t **buffer) {
+ int i, chan;
+ for (i=0; i<blocksize; i++)
+ for (chan=0; chan < nchan; chan++)
+ *samples++ = FFMIN(buffer[chan][i], 32768);
+ return samples;
+}
+
+static void decode_subframe_lpc(ShortenContext *s, int channel, int residual_size, int pred_order)
+{
+ int sum, i, j;
+ int coeffs[pred_order];
+
+ for (i=0; i<pred_order; i++)
+ coeffs[i] = get_sr_golomb_shorten(&s->gb, LPCQUANT);
+
+ for (i=0; i < s->blocksize; i++) {
+ sum = s->lpcqoffset;
+ 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 >> LPCQUANT);
+ }
+}
+
+
+static int shorten_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ ShortenContext *s = avctx->priv_data;
+ int i, input_buf_size = 0;
+ int16_t *samples = data;
+ if(s->max_framesize == 0){
+ s->max_framesize= 1024; // should hopefully be enough for the first header
+ s->bitstream= av_fast_realloc(s->bitstream, &s->allocated_bitstream_size, s->max_framesize);
+ }
+
+ 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){
+ // printf("memmove\n");
+ memmove(s->bitstream, &s->bitstream[s->bitstream_index], s->bitstream_size);
+ s->bitstream_index=0;
+ }
+ 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;
+
+ if(buf_size < s->max_framesize){
+ //dprintf("wanna more data ... %d\n", buf_size);
+ return input_buf_size;
+ }
+ }
+ init_get_bits(&s->gb, buf, buf_size*8);
+ get_bits(&s->gb, s->bitindex);
+ if (!s->blocksize)
+ {
+ int maxnlpc = 0;
+ /* shorten signature */
+ if (get_bits_long(&s->gb, 32) != bswap_32(ff_get_fourcc("ajkg"))) {
+ av_log(s->avctx, AV_LOG_ERROR, "missing shorten magic 'ajkg'\n");
+ return -1;
+ }
+
+ s->lpcqoffset = 0;
+ s->blocksize = DEFAULT_BLOCK_SIZE;
+ s->channels = 1;
+ 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 > MAX_CHANNELS) {
+ av_log(s->avctx, AV_LOG_ERROR, "too many channels: %d\n", s->channels);
+ return -1;
+ }
+
+ /* get blocksize if version > 0 */
+ if (s->version > 0) {
+ int skip_bytes;
+ s->blocksize = get_uint(s, av_log2(DEFAULT_BLOCK_SIZE));
+ 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 (allocate_buffers(s))
+ return -1;
+
+ init_offset(s);
+
+ 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 begining of stream\n");
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ for (i=0; i<s->header_size; i++)
+ s->header[i] = (char)get_ur_golomb_shorten(&s->gb, VERBATIM_BYTE_SIZE);
+
+ if (decode_wave_header(avctx, s->header, s->header_size) < 0)
+ return -1;
+
+ s->cur_chan = 0;
+ s->bitshift = 0;
+ }
+ else
+ {
+ int cmd;
+ int len;
+ cmd = get_ur_golomb_shorten(&s->gb, FNSIZE);
+ switch (cmd) {
+ case FN_ZERO:
+ case FN_DIFF0:
+ case FN_DIFF1:
+ case FN_DIFF2:
+ case FN_DIFF3:
+ case FN_QLPC:
+ {
+ int residual_size = 0;
+ int channel = s->cur_chan;
+ int32_t coffset;
+ if (cmd != FN_ZERO) {
+ residual_size = get_ur_golomb_shorten(&s->gb, ENERGYSIZE);
+ /* this is a hack as version 0 differed in defintion of get_sr_golomb_shorten */
+ if (s->version == 0)
+ residual_size--;
+ }
+
+ 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 >>= FFMIN(1, s->bitshift);
+ }
+ switch (cmd) {
+ case FN_ZERO:
+ for (i=0; i<s->blocksize; i++)
+ s->decoded[channel][i] = 0;
+ break;
+ case FN_DIFF0:
+ for (i=0; i<s->blocksize; i++)
+ s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + coffset;
+ break;
+ case FN_DIFF1:
+ for (i=0; i<s->blocksize; i++)
+ s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + s->decoded[channel][i - 1];
+ break;
+ case FN_DIFF2:
+ for (i=0; i<s->blocksize; i++)
+ s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + 2*s->decoded[channel][i-1]
+ - s->decoded[channel][i-2];
+ break;
+ case FN_DIFF3:
+ for (i=0; i<s->blocksize; i++)
+ s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + 3*s->decoded[channel][i-1]
+ - 3*s->decoded[channel][i-2]
+ + s->decoded[channel][i-3];
+ break;
+ case FN_QLPC:
+ {
+ int pred_order = get_ur_golomb_shorten(&s->gb, LPCQSIZE);
+ for (i=0; i<pred_order; i++)
+ s->decoded[channel][i - pred_order] -= coffset;
+ decode_subframe_lpc(s, channel, residual_size, pred_order);
+ if (coffset != 0)
+ for (i=0; i < s->blocksize; i++)
+ s->decoded[channel][i] += coffset;
+ }
+ }
+ 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;
+ }
+ for (i=-s->nwrap; i<0; i++)
+ s->decoded[channel][i] = s->decoded[channel][i + s->blocksize];
+
+ fix_bitshift(s, s->decoded[channel]);
+
+ s->cur_chan++;
+ if (s->cur_chan == s->channels) {
+ samples = interleave_buffer(samples, s->channels, s->blocksize, s->decoded);
+ s->cur_chan = 0;
+ goto frame_done;
+ }
+ break;
+ }
+ break;
+ 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:
+ s->blocksize = get_uint(s, av_log2(s->blocksize));
+ break;
+ case FN_QUIT:
+ return buf_size;
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "unknown shorten function %d\n", cmd);
+ return -1;
+ break;
+ }
+ }
+frame_done:
+ *data_size = (int8_t *)samples - (int8_t *)data;
+
+ // s->last_blocksize = s->blocksize;
+ 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 -1;
+ }
+ if (s->bitstream_size) {
+ s->bitstream_index += i;
+ s->bitstream_size -= i;
+ return input_buf_size;
+ } else
+ return i;
+}
+
+static int shorten_decode_close(AVCodecContext *avctx)
+{
+ ShortenContext *s = avctx->priv_data;
+ int i;
+
+ for (i = 0; i < s->channels; i++) {
+ s->decoded[i] -= s->nwrap;
+ av_freep(&s->decoded[i]);
+ av_freep(&s->offset[i]);
+ }
+ av_freep(&s->bitstream);
+ return 0;
+}
+
+static void shorten_flush(AVCodecContext *avctx){
+ ShortenContext *s = avctx->priv_data;
+
+ s->bitstream_size=
+ s->bitstream_index= 0;
+}
+
+AVCodec shorten_decoder = {
+ "shorten",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_SHORTEN,
+ sizeof(ShortenContext),
+ shorten_decode_init,
+ NULL,
+ shorten_decode_close,
+ shorten_decode_frame,
+ .flush= shorten_flush,
+};
diff --git a/contrib/ffmpeg/libavcodec/simple_idct.c b/contrib/ffmpeg/libavcodec/simple_idct.c
new file mode 100644
index 000000000..2c026f08f
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/simple_idct.c
@@ -0,0 +1,587 @@
+/*
+ * Simple IDCT
+ *
+ * Copyright (c) 2001 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * 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.c
+ * simpleidct in C.
+ */
+
+/*
+ based upon some outcommented c code from mpeg2dec (idct_mmx.c
+ written by Aaron Holtzman <aholtzma@ess.engr.uvic.ca>)
+ */
+#include "avcodec.h"
+#include "dsputil.h"
+#include "simple_idct.h"
+
+#if 0
+#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) */
+#define ROW_SHIFT 8
+#define COL_SHIFT 17
+#else
+#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 // 6
+#endif
+
+#if defined(ARCH_POWERPC_405)
+
+/* 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(rt, ra, rb) \
+ asm ("mullhw %0, %1, %2" : "=r" (rt) : "r" (ra), "r" (rb));
+
+#else
+
+/* signed 16x16 -> 32 multiply add accumulate */
+#define MAC16(rt, ra, rb) rt += (ra) * (rb)
+
+/* signed 16x16 -> 32 multiply */
+#define MUL16(rt, ra, rb) rt = (ra) * (rb)
+
+#endif
+
+static inline void idctRowCondDC (DCTELEM * row)
+{
+ int a0, a1, a2, a3, b0, b1, b2, b3;
+#ifdef FAST_64BIT
+ uint64_t temp;
+#else
+ uint32_t temp;
+#endif
+
+#ifdef FAST_64BIT
+#ifdef WORDS_BIGENDIAN
+#define ROW0_MASK 0xffff000000000000LL
+#else
+#define ROW0_MASK 0xffffLL
+#endif
+ if(sizeof(DCTELEM)==2){
+ if ( ((((uint64_t *)row)[0] & ~ROW0_MASK) |
+ ((uint64_t *)row)[1]) == 0) {
+ temp = (row[0] << 3) & 0xffff;
+ temp += temp << 16;
+ temp += temp << 32;
+ ((uint64_t *)row)[0] = temp;
+ ((uint64_t *)row)[1] = temp;
+ return;
+ }
+ }else{
+ if (!(row[1]|row[2]|row[3]|row[4]|row[5]|row[6]|row[7])) {
+ row[0]=row[1]=row[2]=row[3]=row[4]=row[5]=row[6]=row[7]= row[0] << 3;
+ return;
+ }
+ }
+#else
+ if(sizeof(DCTELEM)==2){
+ if (!(((uint32_t*)row)[1] |
+ ((uint32_t*)row)[2] |
+ ((uint32_t*)row)[3] |
+ row[1])) {
+ temp = (row[0] << 3) & 0xffff;
+ temp += temp << 16;
+ ((uint32_t*)row)[0]=((uint32_t*)row)[1] =
+ ((uint32_t*)row)[2]=((uint32_t*)row)[3] = temp;
+ return;
+ }
+ }else{
+ if (!(row[1]|row[2]|row[3]|row[4]|row[5]|row[6]|row[7])) {
+ row[0]=row[1]=row[2]=row[3]=row[4]=row[5]=row[6]=row[7]= row[0] << 3;
+ return;
+ }
+ }
+#endif
+
+ a0 = (W4 * row[0]) + (1 << (ROW_SHIFT - 1));
+ a1 = a0;
+ a2 = a0;
+ a3 = a0;
+
+ /* no need to optimize : gcc does it */
+ a0 += W2 * row[2];
+ a1 += W6 * row[2];
+ a2 -= W6 * row[2];
+ a3 -= W2 * row[2];
+
+ MUL16(b0, W1, row[1]);
+ MAC16(b0, W3, row[3]);
+ MUL16(b1, W3, row[1]);
+ MAC16(b1, -W7, row[3]);
+ MUL16(b2, W5, row[1]);
+ MAC16(b2, -W1, row[3]);
+ MUL16(b3, W7, row[1]);
+ MAC16(b3, -W5, row[3]);
+
+#ifdef FAST_64BIT
+ temp = ((uint64_t*)row)[1];
+#else
+ temp = ((uint32_t*)row)[2] | ((uint32_t*)row)[3];
+#endif
+ if (temp != 0) {
+ 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];
+
+ MAC16(b0, W5, row[5]);
+ MAC16(b0, W7, row[7]);
+
+ MAC16(b1, -W1, row[5]);
+ MAC16(b1, -W5, row[7]);
+
+ MAC16(b2, W7, row[5]);
+ MAC16(b2, W3, row[7]);
+
+ MAC16(b3, W3, row[5]);
+ MAC16(b3, -W1, row[7]);
+ }
+
+ row[0] = (a0 + b0) >> ROW_SHIFT;
+ row[7] = (a0 - b0) >> ROW_SHIFT;
+ row[1] = (a1 + b1) >> ROW_SHIFT;
+ row[6] = (a1 - b1) >> ROW_SHIFT;
+ row[2] = (a2 + b2) >> ROW_SHIFT;
+ row[5] = (a2 - b2) >> ROW_SHIFT;
+ row[3] = (a3 + b3) >> ROW_SHIFT;
+ row[4] = (a3 - b3) >> ROW_SHIFT;
+}
+
+static inline void idctSparseColPut (uint8_t *dest, int line_size,
+ DCTELEM * col)
+{
+ int a0, a1, a2, a3, b0, b1, b2, b3;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ /* XXX: I did that only to give same values as previous code */
+ 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];
+
+ MUL16(b0, W1, col[8*1]);
+ MUL16(b1, W3, col[8*1]);
+ MUL16(b2, W5, col[8*1]);
+ MUL16(b3, W7, col[8*1]);
+
+ MAC16(b0, + W3, col[8*3]);
+ MAC16(b1, - W7, col[8*3]);
+ MAC16(b2, - W1, col[8*3]);
+ MAC16(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]) {
+ MAC16(b0, + W5, col[8*5]);
+ MAC16(b1, - W1, col[8*5]);
+ MAC16(b2, + W7, col[8*5]);
+ MAC16(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]) {
+ MAC16(b0, + W7, col[8*7]);
+ MAC16(b1, - W5, col[8*7]);
+ MAC16(b2, + W3, col[8*7]);
+ MAC16(b3, - W1, col[8*7]);
+ }
+
+ dest[0] = cm[(a0 + b0) >> COL_SHIFT];
+ dest += line_size;
+ dest[0] = cm[(a1 + b1) >> COL_SHIFT];
+ dest += line_size;
+ dest[0] = cm[(a2 + b2) >> COL_SHIFT];
+ dest += line_size;
+ dest[0] = cm[(a3 + b3) >> COL_SHIFT];
+ dest += line_size;
+ dest[0] = cm[(a3 - b3) >> COL_SHIFT];
+ dest += line_size;
+ dest[0] = cm[(a2 - b2) >> COL_SHIFT];
+ dest += line_size;
+ dest[0] = cm[(a1 - b1) >> COL_SHIFT];
+ dest += line_size;
+ dest[0] = cm[(a0 - b0) >> COL_SHIFT];
+}
+
+static inline void idctSparseColAdd (uint8_t *dest, int line_size,
+ DCTELEM * col)
+{
+ int a0, a1, a2, a3, b0, b1, b2, b3;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ /* XXX: I did that only to give same values as previous code */
+ 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];
+
+ MUL16(b0, W1, col[8*1]);
+ MUL16(b1, W3, col[8*1]);
+ MUL16(b2, W5, col[8*1]);
+ MUL16(b3, W7, col[8*1]);
+
+ MAC16(b0, + W3, col[8*3]);
+ MAC16(b1, - W7, col[8*3]);
+ MAC16(b2, - W1, col[8*3]);
+ MAC16(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]) {
+ MAC16(b0, + W5, col[8*5]);
+ MAC16(b1, - W1, col[8*5]);
+ MAC16(b2, + W7, col[8*5]);
+ MAC16(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]) {
+ MAC16(b0, + W7, col[8*7]);
+ MAC16(b1, - W5, col[8*7]);
+ MAC16(b2, + W3, col[8*7]);
+ MAC16(b3, - W1, col[8*7]);
+ }
+
+ dest[0] = cm[dest[0] + ((a0 + b0) >> COL_SHIFT)];
+ dest += line_size;
+ dest[0] = cm[dest[0] + ((a1 + b1) >> COL_SHIFT)];
+ dest += line_size;
+ dest[0] = cm[dest[0] + ((a2 + b2) >> COL_SHIFT)];
+ dest += line_size;
+ dest[0] = cm[dest[0] + ((a3 + b3) >> COL_SHIFT)];
+ dest += line_size;
+ dest[0] = cm[dest[0] + ((a3 - b3) >> COL_SHIFT)];
+ dest += line_size;
+ dest[0] = cm[dest[0] + ((a2 - b2) >> COL_SHIFT)];
+ dest += line_size;
+ dest[0] = cm[dest[0] + ((a1 - b1) >> COL_SHIFT)];
+ dest += line_size;
+ dest[0] = cm[dest[0] + ((a0 - b0) >> COL_SHIFT)];
+}
+
+static inline void idctSparseCol (DCTELEM * col)
+{
+ int a0, a1, a2, a3, b0, b1, b2, b3;
+
+ /* XXX: I did that only to give same values as previous code */
+ 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];
+
+ MUL16(b0, W1, col[8*1]);
+ MUL16(b1, W3, col[8*1]);
+ MUL16(b2, W5, col[8*1]);
+ MUL16(b3, W7, col[8*1]);
+
+ MAC16(b0, + W3, col[8*3]);
+ MAC16(b1, - W7, col[8*3]);
+ MAC16(b2, - W1, col[8*3]);
+ MAC16(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]) {
+ MAC16(b0, + W5, col[8*5]);
+ MAC16(b1, - W1, col[8*5]);
+ MAC16(b2, + W7, col[8*5]);
+ MAC16(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]) {
+ MAC16(b0, + W7, col[8*7]);
+ MAC16(b1, - W5, col[8*7]);
+ MAC16(b2, + W3, col[8*7]);
+ MAC16(b3, - W1, col[8*7]);
+ }
+
+ 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 simple_idct_put(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ int i;
+ for(i=0; i<8; i++)
+ idctRowCondDC(block + i*8);
+
+ for(i=0; i<8; i++)
+ idctSparseColPut(dest + i, line_size, block + i);
+}
+
+void simple_idct_add(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ int i;
+ for(i=0; i<8; i++)
+ idctRowCondDC(block + i*8);
+
+ for(i=0; i<8; i++)
+ idctSparseColAdd(dest + i, line_size, block + i);
+}
+
+void simple_idct(DCTELEM *block)
+{
+ int i;
+ for(i=0; i<8; i++)
+ idctRowCondDC(block + i*8);
+
+ for(i=0; i<8; i++)
+ idctSparseCol(block + i);
+}
+
+/* 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(uint8_t *dest, int line_size, const DCTELEM *col)
+{
+ int c0, c1, c2, c3, a0, a1, a2, a3;
+ const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ 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] = cm[(c0 + c1) >> C_SHIFT];
+ dest += line_size;
+ dest[0] = cm[(c2 + c3) >> C_SHIFT];
+ dest += line_size;
+ dest[0] = cm[(c2 - c3) >> C_SHIFT];
+ dest += line_size;
+ dest[0] = cm[(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 simple_idct248_put(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ int i;
+ DCTELEM *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(block + i*8);
+ }
+
+ /* IDCT4 and store */
+ for(i=0;i<8;i++) {
+ idct4col(dest + i, 2 * line_size, block + i);
+ idct4col(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 DCTELEM *col)
+{
+ int c0, c1, c2, c3, a0, a1, a2, a3;
+ const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ 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] = cm[dest[0] + ((c0 + c1) >> C_SHIFT)];
+ dest += line_size;
+ dest[0] = cm[dest[0] + ((c2 + c3) >> C_SHIFT)];
+ dest += line_size;
+ dest[0] = cm[dest[0] + ((c2 - c3) >> C_SHIFT)];
+ dest += line_size;
+ dest[0] = cm[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(DCTELEM *row)
+{
+ int c0, c1, c2, c3, a0, a1, a2, a3;
+ //const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ 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 simple_idct84_add(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ int i;
+
+ /* IDCT8 on each line */
+ for(i=0; i<4; i++) {
+ idctRowCondDC(block + i*8);
+ }
+
+ /* IDCT4 and store */
+ for(i=0;i<8;i++) {
+ idct4col_add(dest + i, line_size, block + i);
+ }
+}
+
+void simple_idct48_add(uint8_t *dest, int line_size, DCTELEM *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(dest + i, line_size, block + i);
+ }
+}
+
diff --git a/contrib/ffmpeg/libavcodec/simple_idct.h b/contrib/ffmpeg/libavcodec/simple_idct.h
new file mode 100644
index 000000000..c4b453329
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/simple_idct.h
@@ -0,0 +1,38 @@
+/*
+ * Simple IDCT
+ *
+ * Copyright (c) 2001 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * 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.h
+ * simple idct header.
+ */
+
+void simple_idct_put(uint8_t *dest, int line_size, DCTELEM *block);
+void simple_idct_add(uint8_t *dest, int line_size, DCTELEM *block);
+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 simple_idct(DCTELEM *block);
+
+void simple_idct248_put(uint8_t *dest, int line_size, DCTELEM *block);
+
+void simple_idct84_add(uint8_t *dest, int line_size, DCTELEM *block);
+void simple_idct48_add(uint8_t *dest, int line_size, DCTELEM *block);
diff --git a/contrib/ffmpeg/libavcodec/smacker.c b/contrib/ffmpeg/libavcodec/smacker.c
new file mode 100644
index 000000000..2f2185848
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/smacker.c
@@ -0,0 +1,723 @@
+/*
+ * 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.c
+ * Smacker decoder
+ */
+
+/*
+ * Based on http://wiki.multimedia.cx/index.php?title=Smacker
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "common.h"
+#include "avcodec.h"
+
+#define ALT_BITSTREAM_READER_LE
+#include "bitstream.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(!get_bits1(gb)){ //Leaf
+ if(hc->current >= 256){
+ av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n");
+ return -1;
+ }
+ 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(!get_bits1(gb)){ //Leaf
+ int val, i1, i2, b1, b2;
+ if(hc->current >= hc->length){
+ av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n");
+ return -1;
+ }
+ b1 = get_bits_count(gb);
+ i1 = get_vlc2(gb, ctx->v1->table, SMKTREE_BITS, 3);
+ b1 = get_bits_count(gb) - b1;
+ b2 = get_bits_count(gb);
+ i2 = get_vlc2(gb, ctx->v2->table, SMKTREE_BITS, 3);
+ b2 = get_bits_count(gb) - b2;
+ 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, t;
+
+ t = hc->current++;
+ r = smacker_decode_bigtree(gb, hc, ctx);
+ if(r < 0)
+ return r;
+ hc->values[t] = SMK_NODE | r;
+ r++;
+ r += smacker_decode_bigtree(gb, hc, ctx);
+ return r;
+ }
+}
+
+/**
+ * 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];
+ int escapes[3];
+ DBCtx ctx;
+
+ 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 -1;
+ }
+
+ 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));
+
+ memset(&vlc[0], 0, sizeof(VLC));
+ memset(&vlc[1], 0, sizeof(VLC));
+
+ if(get_bits1(gb)) {
+ smacker_decode_tree(gb, &tmp1, 0, 0);
+ get_bits1(gb);
+ 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 -1;
+ }
+ } else {
+ av_log(smk->avctx, AV_LOG_ERROR, "Skipping low bytes tree\n");
+ }
+ if(get_bits1(gb)){
+ smacker_decode_tree(gb, &tmp2, 0, 0);
+ get_bits1(gb);
+ 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 -1;
+ }
+ } else {
+ av_log(smk->avctx, AV_LOG_ERROR, "Skipping high bytes tree\n");
+ }
+
+ escapes[0] = get_bits(gb, 8);
+ escapes[0] |= get_bits(gb, 8) << 8;
+ escapes[1] = get_bits(gb, 8);
+ escapes[1] |= get_bits(gb, 8) << 8;
+ escapes[2] = get_bits(gb, 8);
+ escapes[2] |= get_bits(gb, 8) << 8;
+
+ 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));
+
+ smacker_decode_bigtree(gb, &huff, &ctx);
+ get_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++;
+
+ *recodes = huff.values;
+
+ if(vlc[0].table)
+ free_vlc(&vlc[0]);
+ if(vlc[1].table)
+ 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 0;
+}
+
+static int decode_header_trees(SmackVContext *smk) {
+ GetBitContext gb;
+ int mmap_size, mclr_size, full_size, type_size;
+
+ mmap_size = LE_32(smk->avctx->extradata);
+ mclr_size = LE_32(smk->avctx->extradata + 4);
+ full_size = LE_32(smk->avctx->extradata + 8);
+ type_size = LE_32(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 {
+ smacker_decode_header_tree(smk, &gb, &smk->mmap_tbl, smk->mmap_last, mmap_size);
+ }
+ if(!get_bits(&gb, 1)) {
+ 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 {
+ smacker_decode_header_tree(smk, &gb, &smk->mclr_tbl, smk->mclr_last, mclr_size);
+ }
+ if(!get_bits(&gb, 1)) {
+ 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 {
+ smacker_decode_header_tree(smk, &gb, &smk->full_tbl, smk->full_last, full_size);
+ }
+ if(!get_bits(&gb, 1)) {
+ 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 {
+ smacker_decode_header_tree(smk, &gb, &smk->type_tbl, smk->type_last, type_size);
+ }
+
+ return 0;
+}
+
+static 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 always_inline int smk_get_code(GetBitContext *gb, int *recode, int *last) {
+ register int *table = recode;
+ int v, b;
+
+ b = get_bits_count(gb);
+ while(*table & SMK_NODE) {
+ if(get_bits1(gb))
+ table += (*table) & (~SMK_NODE);
+ table++;
+ }
+ v = *table;
+ b = get_bits_count(gb) - b;
+
+ 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 *data_size, uint8_t *buf, int buf_size)
+{
+ SmackVContext * const smk = (SmackVContext *)avctx->priv_data;
+ uint8_t *out;
+ uint32_t *pal;
+ GetBitContext gb;
+ int blocks, blk, bw, bh;
+ int i;
+ int stride;
+
+ if(buf_size == 769)
+ return 0;
+ if(smk->pic.data[0])
+ avctx->release_buffer(avctx, &smk->pic);
+
+ smk->pic.reference = 1;
+ smk->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
+ if(avctx->reget_buffer(avctx, &smk->pic) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ /* make the palette available on the way out */
+ out = buf + 1;
+ pal = (uint32_t*)smk->pic.data[1];
+ smk->pic.palette_has_changed = buf[0] & 1;
+ smk->pic.key_frame = !!(buf[0] & 2);
+ if(smk->pic.key_frame)
+ smk->pic.pict_type = FF_I_TYPE;
+ else
+ smk->pic.pict_type = FF_P_TYPE;
+
+ for(i = 0; i < 256; i++) {
+ int r, g, b;
+ r = *out++;
+ g = *out++;
+ b = *out++;
+ *pal++ = (r << 16) | (g << 8) | b;
+ }
+
+ 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, buf + 769, (buf_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);
+ out[2] = pix & 0xFF;
+ out[3] = pix >> 8;
+ pix = smk_get_code(&gb, smk->full_tbl, smk->full_last);
+ out[0] = pix & 0xFF;
+ out[1] = pix >> 8;
+ 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;
+ pix1 = smk_get_code(&gb, smk->full_tbl, smk->full_last);
+ pix2 = smk_get_code(&gb, smk->full_tbl, smk->full_last);
+ out[0] = pix1 & 0xFF; out[1] = pix1 >> 8;
+ out[2] = pix2 & 0xFF; out[3] = pix2 >> 8;
+ out += stride;
+ out[0] = pix1 & 0xFF; out[1] = pix1 >> 8;
+ out[2] = pix2 & 0xFF; out[3] = pix2 >> 8;
+ 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;
+ }
+
+ }
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = smk->pic;
+
+ /* always report that the buffer was completely consumed */
+ return buf_size;
+}
+
+
+
+/*
+ *
+ * Init smacker decoder
+ *
+ */
+static int decode_init(AVCodecContext *avctx)
+{
+ SmackVContext * const c = (SmackVContext *)avctx->priv_data;
+
+ c->avctx = avctx;
+ avctx->has_b_frames = 0;
+
+ c->pic.data[0] = NULL;
+
+ if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
+ return 1;
+ }
+
+ avctx->pix_fmt = PIX_FMT_PAL8;
+
+
+ /* decode huffman trees from extradata */
+ if(avctx->extradata_size < 16){
+ av_log(avctx, AV_LOG_ERROR, "Extradata missing!\n");
+ return -1;
+ }
+
+ decode_header_trees(c);
+
+
+ return 0;
+}
+
+
+
+/*
+ *
+ * Uninit smacker decoder
+ *
+ */
+static int decode_end(AVCodecContext *avctx)
+{
+ SmackVContext * const smk = (SmackVContext *)avctx->priv_data;
+
+ av_freep(&smk->mmap_tbl);
+ av_freep(&smk->mclr_tbl);
+ av_freep(&smk->full_tbl);
+ av_freep(&smk->type_tbl);
+
+ if (smk->pic.data[0])
+ avctx->release_buffer(avctx, &smk->pic);
+
+ return 0;
+}
+
+
+static int smka_decode_init(AVCodecContext *avctx)
+{
+ return 0;
+}
+
+/**
+ * Decode Smacker audio data
+ */
+static int smka_decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size)
+{
+ GetBitContext gb;
+ HuffContext h[4];
+ VLC vlc[4];
+ int16_t *samples = data;
+ int val;
+ int i, res;
+ int unp_size;
+ int bits, stereo;
+ int pred[2] = {0, 0};
+
+ unp_size = LE_32(buf);
+
+ init_get_bits(&gb, buf + 4, (buf_size - 4) * 8);
+
+ if(!get_bits1(&gb)){
+ av_log(avctx, AV_LOG_INFO, "Sound: no data\n");
+ *data_size = 0;
+ return 1;
+ }
+ stereo = get_bits1(&gb);
+ bits = get_bits1(&gb);
+
+ memset(vlc, 0, sizeof(VLC) * 4);
+ memset(h, 0, sizeof(HuffContext) * 4);
+ // 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));
+ get_bits1(&gb);
+ smacker_decode_tree(&gb, &h[i], 0, 0);
+ get_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 -1;
+ }
+ }
+ }
+ if(bits) { //decode 16-bit data
+ pred[0] = get_bits(&gb, 8);
+ pred[0] |= get_bits(&gb, 8);
+ *samples++ = pred[0];
+ if(stereo) {
+ pred[1] = get_bits(&gb, 8);
+ pred[1] |= get_bits(&gb, 8);
+ *samples++ = pred[1];
+ }
+ for(i = 0; i < unp_size / 2; i++) {
+ if(i & stereo) {
+ if(vlc[2].table)
+ res = get_vlc2(&gb, vlc[2].table, SMKTREE_BITS, 3);
+ else
+ res = 0;
+ val = h[2].values[res];
+ if(vlc[3].table)
+ res = get_vlc2(&gb, vlc[3].table, SMKTREE_BITS, 3);
+ else
+ res = 0;
+ val |= h[3].values[res] << 8;
+ pred[1] += (int16_t)val;
+ *samples++ = pred[1];
+ } else {
+ if(vlc[0].table)
+ res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3);
+ else
+ res = 0;
+ val = h[0].values[res];
+ if(vlc[1].table)
+ res = get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3);
+ else
+ res = 0;
+ val |= h[1].values[res] << 8;
+ pred[0] += val;
+ *samples++ = pred[0];
+ }
+ }
+ } else { //8-bit data
+ pred[0] = get_bits(&gb, 8);
+ *samples++ = (pred[0] - 0x80) << 8;
+ if(stereo) {
+ pred[1] = get_bits(&gb, 8);
+ *samples++ = (pred[1] - 0x80) << 8;
+ }
+ for(i = 0; i < unp_size; i++) {
+ if(i & stereo){
+ if(vlc[1].table)
+ res = get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3);
+ else
+ res = 0;
+ pred[1] += (int8_t)h[1].values[res];
+ *samples++ = (pred[1] - 0x80) << 8;
+ } else {
+ if(vlc[0].table)
+ res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3);
+ else
+ res = 0;
+ pred[0] += (int8_t)h[0].values[res];
+ *samples++ = (pred[0] - 0x80) << 8;
+ }
+ }
+ unp_size *= 2;
+ }
+
+ for(i = 0; i < 4; i++) {
+ if(vlc[i].table)
+ free_vlc(&vlc[i]);
+ if(h[i].bits)
+ av_free(h[i].bits);
+ if(h[i].lengths)
+ av_free(h[i].lengths);
+ if(h[i].values)
+ av_free(h[i].values);
+ }
+
+ *data_size = unp_size;
+ return buf_size;
+}
+
+AVCodec smacker_decoder = {
+ "smackvid",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_SMACKVIDEO,
+ sizeof(SmackVContext),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame
+};
+
+AVCodec smackaud_decoder = {
+ "smackaud",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_SMACKAUDIO,
+ 0,
+ smka_decode_init,
+ NULL,
+ NULL,
+ smka_decode_frame
+};
+
diff --git a/contrib/ffmpeg/libavcodec/smc.c b/contrib/ffmpeg/libavcodec/smc.c
new file mode 100644
index 000000000..77fae328b
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/smc.c
@@ -0,0 +1,493 @@
+/*
+ * 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 smc.c
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.h"
+
+#define CPAIR 2
+#define CQUAD 4
+#define COCTET 8
+
+#define COLORS_PER_TABLE 256
+
+typedef struct SmcContext {
+
+ AVCodecContext *avctx;
+ DSPContext dsp;
+ AVFrame frame;
+
+ unsigned char *buf;
+ int size;
+
+ /* 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];
+
+} SmcContext;
+
+#define GET_BLOCK_COUNT() \
+ (opcode & 0x10) ? (1 + s->buf[stream_ptr++]) : 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 stream_ptr = 0;
+ int chunk_size;
+ 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->avctx->palctrl->palette, AVPALETTE_SIZE);
+ if (s->avctx->palctrl->palette_changed) {
+ s->frame.palette_has_changed = 1;
+ s->avctx->palctrl->palette_changed = 0;
+ }
+
+ chunk_size = BE_32(&s->buf[stream_ptr]) & 0x00FFFFFF;
+ stream_ptr += 4;
+ if (chunk_size != s->size)
+ av_log(s->avctx, AV_LOG_INFO, "warning: MOV chunk size != encoded chunk size (%d != %d); using MOV chunk size\n",
+ chunk_size, s->size);
+
+ chunk_size = s->size;
+ total_blocks = ((s->avctx->width + 3) / 4) * ((s->avctx->height + 3) / 4);
+
+ /* traverse through the blocks */
+ while (total_blocks) {
+ /* sanity checks */
+ /* make sure stream ptr hasn't gone out of bounds */
+ if (stream_ptr > chunk_size) {
+ av_log(s->avctx, AV_LOG_INFO, "SMC decoder just went out of bounds (stream ptr = %d, chunk size = %d)\n",
+ stream_ptr, chunk_size);
+ return;
+ }
+ /* 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 = s->buf[stream_ptr++];
+ 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);
+ break;
+ }
+
+ /* 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);
+ break;
+ }
+
+ /* 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 = s->buf[stream_ptr++];
+
+ 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 = s->buf[stream_ptr++];
+ 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 * s->buf[stream_ptr++];
+
+ while (n_blocks--) {
+ color_flags = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 2;
+ 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 = s->buf[stream_ptr++];
+ 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 * s->buf[stream_ptr++];
+
+ while (n_blocks--) {
+ color_flags = BE_32(&s->buf[stream_ptr]);
+ stream_ptr += 4;
+ /* 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 = s->buf[stream_ptr++];
+ 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 * s->buf[stream_ptr++];
+
+ 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 */
+ color_flags_a = color_flags_b = 0;
+ color_flags_a =
+ (s->buf[stream_ptr + 0] << 16) |
+ ((s->buf[stream_ptr + 1] & 0xF0) << 8) |
+ ((s->buf[stream_ptr + 2] & 0xF0) << 4) |
+ ((s->buf[stream_ptr + 2] & 0x0F) << 4) |
+ ((s->buf[stream_ptr + 3] & 0xF0) >> 4);
+ color_flags_b =
+ (s->buf[stream_ptr + 4] << 16) |
+ ((s->buf[stream_ptr + 5] & 0xF0) << 8) |
+ ((s->buf[stream_ptr + 1] & 0x0F) << 8) |
+ ((s->buf[stream_ptr + 3] & 0x0F) << 4) |
+ (s->buf[stream_ptr + 5] & 0x0F);
+ stream_ptr += 6;
+
+ 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++] = s->buf[stream_ptr++];
+ }
+ block_ptr += row_inc;
+ }
+ ADVANCE_BLOCK();
+ }
+ break;
+
+ case 0xF0:
+ av_log(s->avctx, AV_LOG_INFO, "0xF0 opcode seen in SMC chunk (contact the developers)\n");
+ break;
+ }
+ }
+}
+
+static int smc_decode_init(AVCodecContext *avctx)
+{
+ SmcContext *s = (SmcContext *)avctx->priv_data;
+
+ s->avctx = avctx;
+ avctx->pix_fmt = PIX_FMT_PAL8;
+ avctx->has_b_frames = 0;
+ dsputil_init(&s->dsp, avctx);
+
+ s->frame.data[0] = NULL;
+
+ return 0;
+}
+
+static int smc_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ SmcContext *s = (SmcContext *)avctx->priv_data;
+
+ s->buf = buf;
+ s->size = buf_size;
+
+ s->frame.reference = 1;
+ s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
+ FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
+ if (avctx->reget_buffer(avctx, &s->frame)) {
+ av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+ return -1;
+ }
+
+ smc_decode_stream(s);
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = s->frame;
+
+ /* always report that the buffer was completely consumed */
+ return buf_size;
+}
+
+static int smc_decode_end(AVCodecContext *avctx)
+{
+ SmcContext *s = (SmcContext *)avctx->priv_data;
+
+ if (s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ return 0;
+}
+
+AVCodec smc_decoder = {
+ "smc",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_SMC,
+ sizeof(SmcContext),
+ smc_decode_init,
+ NULL,
+ smc_decode_end,
+ smc_decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/snow.c b/contrib/ffmpeg/libavcodec/snow.c
new file mode 100644
index 000000000..6bc9a8f1a
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/snow.c
@@ -0,0 +1,4686 @@
+/*
+ * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * 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 "common.h"
+#include "dsputil.h"
+#include "snow.h"
+
+#include "rangecoder.h"
+
+#include "mpegvideo.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+static const int8_t quant3[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, 0,
+};
+static const int8_t quant3b[256]={
+ 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,-1,
+};
+static const int8_t 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,
+};
+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 quant7[256]={
+ 0, 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, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,
+-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,
+-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,
+-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,
+-3,-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,-1,-1,
+};
+static const int8_t quant9[256]={
+ 0, 1, 1, 2, 2, 2, 2, 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,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,
+-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,
+-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,
+-4,-4,-4,-4,-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,-2,-2,-2,-2,-1,-1,
+};
+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 int8_t quant13[256]={
+ 0, 1, 2, 2, 3, 3, 3, 3, 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, 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, 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,-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,-5,
+-5,-5,-5,-5,-5,-5,-5,-5,-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,-3,-3,-3,-3,-2,-2,-1,
+};
+
+#if 0 //64*cubic
+static const uint8_t obmc32[1024]={
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 1, 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 7, 8, 8, 8, 8, 7, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1, 1, 0, 0,
+ 0, 0, 1, 2, 2, 3, 4, 6, 7, 8, 9,10,11,12,12,12,12,12,12,11,10, 9, 8, 7, 6, 4, 3, 2, 2, 1, 0, 0,
+ 0, 1, 1, 2, 3, 5, 6, 8,10,11,13,14,15,16,17,18,18,17,16,15,14,13,11,10, 8, 6, 5, 3, 2, 1, 1, 0,
+ 0, 1, 1, 3, 4, 6, 8,10,13,15,17,19,20,22,22,23,23,22,22,20,19,17,15,13,10, 8, 6, 4, 3, 1, 1, 0,
+ 0, 1, 2, 4, 6, 8,10,13,16,19,21,23,25,27,28,29,29,28,27,25,23,21,19,16,13,10, 8, 6, 4, 2, 1, 0,
+ 0, 1, 2, 4, 7,10,13,16,19,22,25,28,31,33,34,35,35,34,33,31,28,25,22,19,16,13,10, 7, 4, 2, 1, 0,
+ 0, 1, 3, 5, 8,11,15,19,22,26,30,33,36,38,40,41,41,40,38,36,33,30,26,22,19,15,11, 8, 5, 3, 1, 0,
+ 0, 1, 3, 6, 9,12,17,21,25,30,34,38,41,44,45,46,46,45,44,41,38,34,30,25,21,17,12, 9, 6, 3, 1, 0,
+ 0, 1, 3, 6,10,14,19,23,28,33,38,42,45,48,51,52,52,51,48,45,42,38,33,28,23,19,14,10, 6, 3, 1, 0,
+ 0, 1, 4, 7,11,15,20,25,31,36,41,45,49,52,55,56,56,55,52,49,45,41,36,31,25,20,15,11, 7, 4, 1, 0,
+ 0, 2, 4, 7,12,16,22,27,33,38,44,48,52,56,58,60,60,58,56,52,48,44,38,33,27,22,16,12, 7, 4, 2, 0,
+ 0, 1, 4, 8,12,17,22,28,34,40,45,51,55,58,61,62,62,61,58,55,51,45,40,34,28,22,17,12, 8, 4, 1, 0,
+ 0, 2, 4, 8,12,18,23,29,35,41,46,52,56,60,62,64,64,62,60,56,52,46,41,35,29,23,18,12, 8, 4, 2, 0,
+ 0, 2, 4, 8,12,18,23,29,35,41,46,52,56,60,62,64,64,62,60,56,52,46,41,35,29,23,18,12, 8, 4, 2, 0,
+ 0, 1, 4, 8,12,17,22,28,34,40,45,51,55,58,61,62,62,61,58,55,51,45,40,34,28,22,17,12, 8, 4, 1, 0,
+ 0, 2, 4, 7,12,16,22,27,33,38,44,48,52,56,58,60,60,58,56,52,48,44,38,33,27,22,16,12, 7, 4, 2, 0,
+ 0, 1, 4, 7,11,15,20,25,31,36,41,45,49,52,55,56,56,55,52,49,45,41,36,31,25,20,15,11, 7, 4, 1, 0,
+ 0, 1, 3, 6,10,14,19,23,28,33,38,42,45,48,51,52,52,51,48,45,42,38,33,28,23,19,14,10, 6, 3, 1, 0,
+ 0, 1, 3, 6, 9,12,17,21,25,30,34,38,41,44,45,46,46,45,44,41,38,34,30,25,21,17,12, 9, 6, 3, 1, 0,
+ 0, 1, 3, 5, 8,11,15,19,22,26,30,33,36,38,40,41,41,40,38,36,33,30,26,22,19,15,11, 8, 5, 3, 1, 0,
+ 0, 1, 2, 4, 7,10,13,16,19,22,25,28,31,33,34,35,35,34,33,31,28,25,22,19,16,13,10, 7, 4, 2, 1, 0,
+ 0, 1, 2, 4, 6, 8,10,13,16,19,21,23,25,27,28,29,29,28,27,25,23,21,19,16,13,10, 8, 6, 4, 2, 1, 0,
+ 0, 1, 1, 3, 4, 6, 8,10,13,15,17,19,20,22,22,23,23,22,22,20,19,17,15,13,10, 8, 6, 4, 3, 1, 1, 0,
+ 0, 1, 1, 2, 3, 5, 6, 8,10,11,13,14,15,16,17,18,18,17,16,15,14,13,11,10, 8, 6, 5, 3, 2, 1, 1, 0,
+ 0, 0, 1, 2, 2, 3, 4, 6, 7, 8, 9,10,11,12,12,12,12,12,12,11,10, 9, 8, 7, 6, 4, 3, 2, 2, 1, 0, 0,
+ 0, 0, 1, 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 7, 8, 8, 8, 8, 7, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1, 1, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 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,
+//error:0.000022
+};
+static const uint8_t obmc16[256]={
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 2, 4, 5, 5, 6, 6, 5, 5, 4, 2, 1, 1, 0,
+ 0, 1, 4, 6, 9,11,13,15,15,13,11, 9, 6, 4, 1, 0,
+ 0, 2, 6,11,15,20,24,26,26,24,20,15,11, 6, 2, 0,
+ 0, 4, 9,15,23,29,34,38,38,34,29,23,15, 9, 4, 0,
+ 0, 5,11,20,29,38,45,49,49,45,38,29,20,11, 5, 0,
+ 1, 5,13,24,34,45,53,57,57,53,45,34,24,13, 5, 1,
+ 1, 6,15,26,38,49,57,62,62,57,49,38,26,15, 6, 1,
+ 1, 6,15,26,38,49,57,62,62,57,49,38,26,15, 6, 1,
+ 1, 5,13,24,34,45,53,57,57,53,45,34,24,13, 5, 1,
+ 0, 5,11,20,29,38,45,49,49,45,38,29,20,11, 5, 0,
+ 0, 4, 9,15,23,29,34,38,38,34,29,23,15, 9, 4, 0,
+ 0, 2, 6,11,15,20,24,26,26,24,20,15,11, 6, 2, 0,
+ 0, 1, 4, 6, 9,11,13,15,15,13,11, 9, 6, 4, 1, 0,
+ 0, 1, 1, 2, 4, 5, 5, 6, 6, 5, 5, 4, 2, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+//error:0.000033
+};
+#elif 1 // 64*linear
+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
+};
+#else //64*cos
+static const uint8_t obmc32[1024]={
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0,
+ 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 9,10,11,11,12,12,12,12,11,11,10, 9, 7, 6, 5, 4, 3, 2, 1, 1, 0, 0,
+ 0, 0, 1, 2, 3, 5, 6, 8, 9,11,12,14,15,16,17,17,17,17,16,15,14,12,11, 9, 8, 6, 5, 3, 2, 1, 0, 0,
+ 0, 1, 1, 2, 4, 6, 8,10,12,15,17,19,20,21,22,23,23,22,21,20,19,17,15,12,10, 8, 6, 4, 2, 1, 1, 0,
+ 0, 1, 2, 3, 5, 8,10,13,16,19,21,24,26,27,28,29,29,28,27,26,24,21,19,16,13,10, 8, 5, 3, 2, 1, 0,
+ 0, 1, 2, 4, 6, 9,12,16,19,23,26,29,31,33,34,35,35,34,33,31,29,26,23,19,16,12, 9, 6, 4, 2, 1, 0,
+ 0, 1, 3, 5, 7,11,15,19,23,26,30,34,37,39,40,41,41,40,39,37,34,30,26,23,19,15,11, 7, 5, 3, 1, 0,
+ 0, 1, 3, 5, 9,12,17,21,26,30,35,38,42,44,46,47,47,46,44,42,38,35,30,26,21,17,12, 9, 5, 3, 1, 0,
+ 0, 1, 3, 6, 9,14,19,24,29,34,38,43,46,49,51,52,52,51,49,46,43,38,34,29,24,19,14, 9, 6, 3, 1, 0,
+ 0, 1, 3, 6,11,15,20,26,31,37,42,46,50,53,56,57,57,56,53,50,46,42,37,31,26,20,15,11, 6, 3, 1, 0,
+ 0, 1, 3, 7,11,16,21,27,33,39,44,49,53,57,59,60,60,59,57,53,49,44,39,33,27,21,16,11, 7, 3, 1, 0,
+ 0, 1, 4, 7,12,17,22,28,34,40,46,51,56,59,61,63,63,61,59,56,51,46,40,34,28,22,17,12, 7, 4, 1, 0,
+ 0, 1, 4, 7,12,17,23,29,35,41,47,52,57,60,63,64,64,63,60,57,52,47,41,35,29,23,17,12, 7, 4, 1, 0,
+ 0, 1, 4, 7,12,17,23,29,35,41,47,52,57,60,63,64,64,63,60,57,52,47,41,35,29,23,17,12, 7, 4, 1, 0,
+ 0, 1, 4, 7,12,17,22,28,34,40,46,51,56,59,61,63,63,61,59,56,51,46,40,34,28,22,17,12, 7, 4, 1, 0,
+ 0, 1, 3, 7,11,16,21,27,33,39,44,49,53,57,59,60,60,59,57,53,49,44,39,33,27,21,16,11, 7, 3, 1, 0,
+ 0, 1, 3, 6,11,15,20,26,31,37,42,46,50,53,56,57,57,56,53,50,46,42,37,31,26,20,15,11, 6, 3, 1, 0,
+ 0, 1, 3, 6, 9,14,19,24,29,34,38,43,46,49,51,52,52,51,49,46,43,38,34,29,24,19,14, 9, 6, 3, 1, 0,
+ 0, 1, 3, 5, 9,12,17,21,26,30,35,38,42,44,46,47,47,46,44,42,38,35,30,26,21,17,12, 9, 5, 3, 1, 0,
+ 0, 1, 3, 5, 7,11,15,19,23,26,30,34,37,39,40,41,41,40,39,37,34,30,26,23,19,15,11, 7, 5, 3, 1, 0,
+ 0, 1, 2, 4, 6, 9,12,16,19,23,26,29,31,33,34,35,35,34,33,31,29,26,23,19,16,12, 9, 6, 4, 2, 1, 0,
+ 0, 1, 2, 3, 5, 8,10,13,16,19,21,24,26,27,28,29,29,28,27,26,24,21,19,16,13,10, 8, 5, 3, 2, 1, 0,
+ 0, 1, 1, 2, 4, 6, 8,10,12,15,17,19,20,21,22,23,23,22,21,20,19,17,15,12,10, 8, 6, 4, 2, 1, 1, 0,
+ 0, 0, 1, 2, 3, 5, 6, 8, 9,11,12,14,15,16,17,17,17,17,16,15,14,12,11, 9, 8, 6, 5, 3, 2, 1, 0, 0,
+ 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 9,10,11,11,12,12,12,12,11,11,10, 9, 7, 6, 5, 4, 3, 2, 1, 1, 0, 0,
+ 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 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,
+//error:0.000022
+};
+static const uint8_t obmc16[256]={
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 2, 3, 4, 5, 5, 5, 5, 4, 3, 2, 1, 0, 0,
+ 0, 1, 3, 6, 8,11,13,14,14,13,11, 8, 6, 3, 1, 0,
+ 0, 2, 6,10,15,20,24,26,26,24,20,15,10, 6, 2, 0,
+ 0, 3, 8,16,23,30,35,38,38,35,30,23,16, 8, 3, 0,
+ 1, 4,11,20,30,39,46,49,49,46,39,30,20,11, 4, 1,
+ 1, 5,13,24,35,46,54,58,58,54,46,35,24,13, 5, 1,
+ 0, 5,14,26,38,49,58,63,63,58,49,38,26,14, 5, 0,
+ 0, 5,14,26,38,49,58,63,63,58,49,38,26,14, 5, 0,
+ 1, 5,13,24,35,46,54,58,58,54,46,35,24,13, 5, 1,
+ 1, 4,11,20,30,39,46,49,49,46,39,30,20,11, 4, 1,
+ 0, 3, 8,16,23,30,35,38,38,35,30,23,16, 8, 3, 0,
+ 0, 2, 6,10,15,20,24,26,26,24,20,15,10, 6, 2, 0,
+ 0, 1, 3, 6, 8,11,13,14,14,13,11, 8, 6, 3, 1, 0,
+ 0, 0, 1, 2, 3, 4, 5, 5, 5, 5, 4, 3, 2, 1, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+//error:0.000022
+};
+#endif
+
+//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
+};
+
+static const uint8_t *obmc_tab[4]={
+ obmc32, obmc16, obmc8, obmc4
+};
+
+static int scale_mv_ref[MAX_REF_FRAMES][MAX_REF_FRAMES];
+
+typedef struct BlockNode{
+ int16_t mx;
+ int16_t my;
+ uint8_t ref;
+ uint8_t color[3];
+ uint8_t type;
+//#define TYPE_SPLIT 1
+#define BLOCK_INTRA 1
+#define BLOCK_OPT 2
+//#define TYPE_NOCOLOR 4
+ uint8_t level; //FIXME merge into type?
+}BlockNode;
+
+static const BlockNode null_block= { //FIXME add border maybe
+ .color= {128,128,128},
+ .mx= 0,
+ .my= 0,
+ .ref= 0,
+ .type= 0,
+ .level= 0,
+};
+
+#define LOG2_MB_SIZE 4
+#define MB_SIZE (1<<LOG2_MB_SIZE)
+
+typedef struct x_and_coeff{
+ int16_t x;
+ uint16_t coeff;
+} x_and_coeff;
+
+typedef struct SubBand{
+ int level;
+ int stride;
+ int width;
+ int height;
+ int qlog; ///< log(qscale)/log[2^(1/6)]
+ DWTELEM *buf;
+ int buf_x_offset;
+ int buf_y_offset;
+ int stride_line; ///< Stride measured in lines, not pixels.
+ x_and_coeff * x_coeff;
+ struct SubBand *parent;
+ uint8_t state[/*7*2*/ 7 + 512][32];
+}SubBand;
+
+typedef struct Plane{
+ int width;
+ int height;
+ SubBand band[MAX_DECOMPOSITIONS][4];
+}Plane;
+
+typedef struct SnowContext{
+// MpegEncContext m; // needed for motion estimation, should not be used for anything else, the idea is to make the motion estimation eventually independant of MpegEncContext, so this will be removed then (FIXME/XXX)
+
+ AVCodecContext *avctx;
+ RangeCoder c;
+ DSPContext dsp;
+ AVFrame new_picture;
+ AVFrame input_picture; ///< new_picture with the internal linesizes
+ AVFrame current_picture;
+ AVFrame last_picture[MAX_REF_FRAMES];
+ AVFrame mconly_picture;
+// uint8_t q_context[16];
+ uint8_t header_state[32];
+ uint8_t block_state[128 + 32*128];
+ int keyframe;
+ int always_reset;
+ int version;
+ int spatial_decomposition_type;
+ int temporal_decomposition_type;
+ int spatial_decomposition_count;
+ int temporal_decomposition_count;
+ int max_ref_frames;
+ int ref_frames;
+ int16_t (*ref_mvs[MAX_REF_FRAMES])[2];
+ uint32_t *ref_scores[MAX_REF_FRAMES];
+ DWTELEM *spatial_dwt_buffer;
+ int colorspace_type;
+ int chroma_h_shift;
+ int chroma_v_shift;
+ int spatial_scalability;
+ int qlog;
+ int lambda;
+ int lambda2;
+ int pass1_rc;
+ int mv_scale;
+ int qbias;
+#define QBIAS_SHIFT 3
+ int b_width;
+ int b_height;
+ int block_max_depth;
+ Plane plane[MAX_PLANES];
+ BlockNode *block;
+#define ME_CACHE_SIZE 1024
+ int me_cache[ME_CACHE_SIZE];
+ int me_cache_generation;
+ slice_buffer sb;
+
+ MpegEncContext m; // needed for motion estimation, should not be used for anything else, the idea is to make the motion estimation eventually independant of MpegEncContext, so this will be removed then (FIXME/XXX)
+}SnowContext;
+
+typedef struct {
+ DWTELEM *b0;
+ DWTELEM *b1;
+ DWTELEM *b2;
+ DWTELEM *b3;
+ int y;
+} dwt_compose_t;
+
+#define slice_buffer_get_line(slice_buf, line_num) ((slice_buf)->line[line_num] ? (slice_buf)->line[line_num] : slice_buffer_load_line((slice_buf), (line_num)))
+//#define slice_buffer_get_line(slice_buf, line_num) (slice_buffer_load_line((slice_buf), (line_num)))
+
+static void iterative_me(SnowContext *s);
+
+static void slice_buffer_init(slice_buffer * buf, int line_count, int max_allocated_lines, int line_width, DWTELEM * 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 = (DWTELEM * *) av_mallocz (sizeof(DWTELEM *) * line_count);
+ buf->data_stack = (DWTELEM * *) av_malloc (sizeof(DWTELEM *) * max_allocated_lines);
+
+ for (i = 0; i < max_allocated_lines; i++)
+ {
+ buf->data_stack[i] = (DWTELEM *) av_malloc (sizeof(DWTELEM) * line_width);
+ }
+
+ buf->data_stack_top = max_allocated_lines - 1;
+}
+
+static DWTELEM * slice_buffer_load_line(slice_buffer * buf, int line)
+{
+ int offset;
+ DWTELEM * buffer;
+
+// av_log(NULL, AV_LOG_DEBUG, "Cache hit: %d\n", line);
+
+ assert(buf->data_stack_top >= 0);
+// assert(!buf->line[line]);
+ if (buf->line[line])
+ return buf->line[line];
+
+ offset = buf->line_width * line;
+ buffer = buf->data_stack[buf->data_stack_top];
+ buf->data_stack_top--;
+ buf->line[line] = buffer;
+
+// av_log(NULL, AV_LOG_DEBUG, "slice_buffer_load_line: line: %d remaining: %d\n", line, buf->data_stack_top + 1);
+
+ return buffer;
+}
+
+static void slice_buffer_release(slice_buffer * buf, int line)
+{
+ int offset;
+ DWTELEM * buffer;
+
+ assert(line >= 0 && line < buf->line_count);
+ assert(buf->line[line]);
+
+ offset = buf->line_width * line;
+ buffer = buf->line[line];
+ buf->data_stack_top++;
+ buf->data_stack[buf->data_stack_top] = buffer;
+ buf->line[line] = NULL;
+
+// av_log(NULL, AV_LOG_DEBUG, "slice_buffer_release: line: %d remaining: %d\n", line, buf->data_stack_top + 1);
+}
+
+static void slice_buffer_flush(slice_buffer * buf)
+{
+ int i;
+ for (i = 0; i < buf->line_count; i++)
+ {
+ if (buf->line[i])
+ {
+// av_log(NULL, AV_LOG_DEBUG, "slice_buffer_flush: line: %d \n", i);
+ slice_buffer_release(buf, i);
+ }
+ }
+}
+
+static void slice_buffer_destroy(slice_buffer * buf)
+{
+ int i;
+ slice_buffer_flush(buf);
+
+ for (i = buf->data_count - 1; i >= 0; i--)
+ {
+ assert(buf->data_stack[i]);
+ av_freep(&buf->data_stack[i]);
+ }
+ assert(buf->data_stack);
+ av_freep(&buf->data_stack);
+ assert(buf->line);
+ av_freep(&buf->line);
+}
+
+#ifdef __sgi
+// Avoid a name clash on SGI IRIX
+#undef qexp
+#endif
+#define QEXPSHIFT (7-FRAC_BITS+8) //FIXME try to change this to 0
+static uint8_t qexp[QROOT];
+
+static inline int mirror(int v, int m){
+ while((unsigned)v > (unsigned)m){
+ v=-v;
+ if(v<0) v+= 2*m;
+ }
+ return v;
+}
+
+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);
+#if 1
+ const int el= FFMIN(e, 10);
+ put_rac(c, state+0, 0);
+
+ for(i=0; i<el; i++){
+ put_rac(c, state+1+i, 1); //1..10
+ }
+ for(; i<e; i++){
+ put_rac(c, state+1+9, 1); //1..10
+ }
+ put_rac(c, state+1+FFMIN(i,9), 0);
+
+ for(i=e-1; 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, 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+FFMIN(i,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 + FFMIN(e,10), v < 0); //11..21
+ }
+#endif
+ }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
+ }
+
+ if(is_signed && get_rac(c, state+11 + FFMIN(e,10))) //11..21
+ return -a;
+ else
+ return a;
+ }
+}
+
+static inline void put_symbol2(RangeCoder *c, uint8_t *state, int v, int log2){
+ int i;
+ int r= log2>=0 ? 1<<log2 : 1;
+
+ assert(v>=0);
+ assert(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<<log2 : 1;
+ int v=0;
+
+ assert(log2>=-4);
+
+ while(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)<<i;
+ }
+
+ return v;
+}
+
+static 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);
+ }
+}
+
+#ifndef lift5
+static always_inline void lift5(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;
+
+ if(mirror_left){
+ int r= 3*2*ref[0];
+ r += r>>4;
+ r += r>>8;
+ dst[0] = LIFT(src[0], ((r+add)>>shift), inverse);
+ dst += dst_step;
+ src += src_step;
+ }
+
+ for(i=0; i<w; i++){
+ int r= 3*(ref[i*ref_step] + ref[(i+1)*ref_step]);
+ r += r>>4;
+ r += r>>8;
+ dst[i*dst_step] = LIFT(src[i*src_step], ((r+add)>>shift), inverse);
+ }
+
+ if(mirror_right){
+ int r= 3*2*ref[w*ref_step];
+ r += r>>4;
+ r += r>>8;
+ dst[w*dst_step] = LIFT(src[w*src_step], ((r+add)>>shift), inverse);
+ }
+}
+#endif
+
+#ifndef liftS
+static 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;
+
+ assert(shift == 4);
+#define LIFTS(src, ref, inv) ((inv) ? (src) - (((ref) - 4*(src))>>shift): (16*4*(src) + 4*(ref) + 8 + (5<<27))/(5*16) - (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);
+ }
+}
+#endif
+
+
+static void inplace_lift(DWTELEM *dst, int width, int *coeffs, int n, int shift, int start, int inverse){
+ int x, i;
+
+ for(x=start; x<width; x+=2){
+ int64_t sum=0;
+
+ for(i=0; i<n; i++){
+ int x2= x + 2*i - n + 1;
+ if (x2< 0) x2= -x2;
+ else if(x2>=width) x2= 2*width-x2-2;
+ sum += coeffs[i]*(int64_t)dst[x2];
+ }
+ if(inverse) dst[x] -= (sum + (1<<shift)/2)>>shift;
+ else dst[x] += (sum + (1<<shift)/2)>>shift;
+ }
+}
+
+static void inplace_liftV(DWTELEM *dst, int width, int height, int stride, int *coeffs, int n, int shift, int start, int inverse){
+ int x, y, i;
+ for(y=start; y<height; y+=2){
+ for(x=0; x<width; x++){
+ int64_t sum=0;
+
+ for(i=0; i<n; i++){
+ int y2= y + 2*i - n + 1;
+ if (y2< 0) y2= -y2;
+ else if(y2>=height) y2= 2*height-y2-2;
+ sum += coeffs[i]*(int64_t)dst[x + y2*stride];
+ }
+ if(inverse) dst[x + y*stride] -= (sum + (1<<shift)/2)>>shift;
+ else dst[x + y*stride] += (sum + (1<<shift)/2)>>shift;
+ }
+ }
+}
+
+#define SCALEX 1
+#define LX0 0
+#define LX1 1
+
+#if 0 // more accurate 9/7
+#define N1 2
+#define SHIFT1 14
+#define COEFFS1 (int[]){-25987,-25987}
+#define N2 2
+#define SHIFT2 19
+#define COEFFS2 (int[]){-27777,-27777}
+#define N3 2
+#define SHIFT3 15
+#define COEFFS3 (int[]){28931,28931}
+#define N4 2
+#define SHIFT4 15
+#define COEFFS4 (int[]){14533,14533}
+#elif 1 // 13/7 CRF
+#define N1 4
+#define SHIFT1 4
+#define COEFFS1 (int[]){1,-9,-9,1}
+#define N2 4
+#define SHIFT2 4
+#define COEFFS2 (int[]){-1,5,5,-1}
+#define N3 0
+#define SHIFT3 1
+#define COEFFS3 NULL
+#define N4 0
+#define SHIFT4 1
+#define COEFFS4 NULL
+#elif 1 // 3/5
+#define LX0 1
+#define LX1 0
+#define SCALEX 0.5
+#define N1 2
+#define SHIFT1 1
+#define COEFFS1 (int[]){1,1}
+#define N2 2
+#define SHIFT2 2
+#define COEFFS2 (int[]){-1,-1}
+#define N3 0
+#define SHIFT3 0
+#define COEFFS3 NULL
+#define N4 0
+#define SHIFT4 0
+#define COEFFS4 NULL
+#elif 1 // 11/5
+#define N1 0
+#define SHIFT1 1
+#define COEFFS1 NULL
+#define N2 2
+#define SHIFT2 2
+#define COEFFS2 (int[]){-1,-1}
+#define N3 2
+#define SHIFT3 0
+#define COEFFS3 (int[]){-1,-1}
+#define N4 4
+#define SHIFT4 7
+#define COEFFS4 (int[]){-5,29,29,-5}
+#define SCALEX 4
+#elif 1 // 9/7 CDF
+#define N1 2
+#define SHIFT1 7
+#define COEFFS1 (int[]){-203,-203}
+#define N2 2
+#define SHIFT2 12
+#define COEFFS2 (int[]){-217,-217}
+#define N3 2
+#define SHIFT3 7
+#define COEFFS3 (int[]){113,113}
+#define N4 2
+#define SHIFT4 9
+#define COEFFS4 (int[]){227,227}
+#define SCALEX 1
+#elif 1 // 7/5 CDF
+#define N1 0
+#define SHIFT1 1
+#define COEFFS1 NULL
+#define N2 2
+#define SHIFT2 2
+#define COEFFS2 (int[]){-1,-1}
+#define N3 2
+#define SHIFT3 0
+#define COEFFS3 (int[]){-1,-1}
+#define N4 2
+#define SHIFT4 4
+#define COEFFS4 (int[]){3,3}
+#elif 1 // 9/7 MN
+#define N1 4
+#define SHIFT1 4
+#define COEFFS1 (int[]){1,-9,-9,1}
+#define N2 2
+#define SHIFT2 2
+#define COEFFS2 (int[]){1,1}
+#define N3 0
+#define SHIFT3 1
+#define COEFFS3 NULL
+#define N4 0
+#define SHIFT4 1
+#define COEFFS4 NULL
+#else // 13/7 CRF
+#define N1 4
+#define SHIFT1 4
+#define COEFFS1 (int[]){1,-9,-9,1}
+#define N2 4
+#define SHIFT2 4
+#define COEFFS2 (int[]){-1,5,5,-1}
+#define N3 0
+#define SHIFT3 1
+#define COEFFS3 NULL
+#define N4 0
+#define SHIFT4 1
+#define COEFFS4 NULL
+#endif
+static void horizontal_decomposeX(DWTELEM *b, int width){
+ DWTELEM temp[width];
+ const int width2= width>>1;
+ const int w2= (width+1)>>1;
+ int x;
+
+ inplace_lift(b, width, COEFFS1, N1, SHIFT1, LX1, 0);
+ inplace_lift(b, width, COEFFS2, N2, SHIFT2, LX0, 0);
+ inplace_lift(b, width, COEFFS3, N3, SHIFT3, LX1, 0);
+ inplace_lift(b, width, COEFFS4, N4, SHIFT4, LX0, 0);
+
+ 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 ];
+ memcpy(b, temp, width*sizeof(int));
+}
+
+static void horizontal_composeX(DWTELEM *b, int width){
+ DWTELEM temp[width];
+ const int width2= width>>1;
+ int x;
+ const int w2= (width+1)>>1;
+
+ memcpy(temp, b, width*sizeof(int));
+ for(x=0; x<width2; x++){
+ b[2*x ]= temp[x ];
+ b[2*x + 1]= temp[x+w2];
+ }
+ if(width&1)
+ b[2*x ]= temp[x ];
+
+ inplace_lift(b, width, COEFFS4, N4, SHIFT4, LX0, 1);
+ inplace_lift(b, width, COEFFS3, N3, SHIFT3, LX1, 1);
+ inplace_lift(b, width, COEFFS2, N2, SHIFT2, LX0, 1);
+ inplace_lift(b, width, COEFFS1, N1, SHIFT1, LX1, 1);
+}
+
+static void spatial_decomposeX(DWTELEM *buffer, int width, int height, int stride){
+ int x, y;
+
+ for(y=0; y<height; y++){
+ for(x=0; x<width; x++){
+ buffer[y*stride + x] *= SCALEX;
+ }
+ }
+
+ for(y=0; y<height; y++){
+ horizontal_decomposeX(buffer + y*stride, width);
+ }
+
+ inplace_liftV(buffer, width, height, stride, COEFFS1, N1, SHIFT1, LX1, 0);
+ inplace_liftV(buffer, width, height, stride, COEFFS2, N2, SHIFT2, LX0, 0);
+ inplace_liftV(buffer, width, height, stride, COEFFS3, N3, SHIFT3, LX1, 0);
+ inplace_liftV(buffer, width, height, stride, COEFFS4, N4, SHIFT4, LX0, 0);
+}
+
+static void spatial_composeX(DWTELEM *buffer, int width, int height, int stride){
+ int x, y;
+
+ inplace_liftV(buffer, width, height, stride, COEFFS4, N4, SHIFT4, LX0, 1);
+ inplace_liftV(buffer, width, height, stride, COEFFS3, N3, SHIFT3, LX1, 1);
+ inplace_liftV(buffer, width, height, stride, COEFFS2, N2, SHIFT2, LX0, 1);
+ inplace_liftV(buffer, width, height, stride, COEFFS1, N1, SHIFT1, LX1, 1);
+
+ for(y=0; y<height; y++){
+ horizontal_composeX(buffer + y*stride, width);
+ }
+
+ for(y=0; y<height; y++){
+ for(x=0; x<width; x++){
+ buffer[y*stride + x] /= SCALEX;
+ }
+ }
+}
+
+static void horizontal_decompose53i(DWTELEM *b, int width){
+ DWTELEM temp[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 ];
+#if 0
+ {
+ int A1,A2,A3,A4;
+ A2= temp[1 ];
+ A4= temp[0 ];
+ A1= temp[0+width2];
+ A1 -= (A2 + A4)>>1;
+ A4 += (A1 + 1)>>1;
+ b[0+width2] = A1;
+ b[0 ] = A4;
+ for(x=1; x+1<width2; x+=2){
+ A3= temp[x+width2];
+ A4= temp[x+1 ];
+ A3 -= (A2 + A4)>>1;
+ A2 += (A1 + A3 + 2)>>2;
+ b[x+width2] = A3;
+ b[x ] = A2;
+
+ A1= temp[x+1+width2];
+ A2= temp[x+2 ];
+ A1 -= (A2 + A4)>>1;
+ A4 += (A1 + A3 + 2)>>2;
+ b[x+1+width2] = A1;
+ b[x+1 ] = A4;
+ }
+ A3= temp[width-1];
+ A3 -= A2;
+ A2 += (A1 + A3 + 2)>>2;
+ b[width -1] = A3;
+ b[width2-1] = A2;
+ }
+#else
+ 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);
+#endif
+}
+
+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, 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;
+
+{START_TIMER
+ if(y+1<(unsigned)height) horizontal_decompose53i(b2, width);
+ if(y+2<(unsigned)height) horizontal_decompose53i(b3, width);
+STOP_TIMER("horizontal_decompose53i")}
+
+{START_TIMER
+ if(y+1<(unsigned)height) vertical_decompose53iH0(b1, b2, b3, width);
+ if(y+0<(unsigned)height) vertical_decompose53iL0(b0, b1, b2, width);
+STOP_TIMER("vertical_decompose53i*")}
+
+ b0=b2;
+ b1=b3;
+ }
+}
+
+static void horizontal_decompose97i(DWTELEM *b, int width){
+ DWTELEM temp[width];
+ const int w2= (width+1)>>1;
+
+ lift (temp+w2, b +1, b , 1, 2, 2, width, -W_AM, W_AO, W_AS, 1, 0);
+ liftS(temp , b , temp+w2, 1, 2, 1, width, -W_BM, W_BO, W_BS, 0, 0);
+ lift5(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++){
+#ifdef lift5
+ b1[i] += (W_CM*(b0[i] + b2[i])+W_CO)>>W_CS;
+#else
+ int r= 3*(b0[i] + b2[i]);
+ r+= r>>4;
+ r+= r>>8;
+ b1[i] += (r+W_CO)>>W_CS;
+#endif
+ }
+}
+
+static void vertical_decompose97iL0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, int width){
+ int i;
+
+ for(i=0; i<width; i++){
+#ifdef liftS
+ b1[i] -= (W_BM*(b0[i] + b2[i])+W_BO)>>W_BS;
+#else
+ b1[i] = (16*4*b1[i] - 4*(b0[i] + b2[i]) + 8*5 + (5<<27)) / (5*16) - (1<<23);
+#endif
+ }
+}
+
+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, 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;
+
+{START_TIMER
+ if(y+3<(unsigned)height) horizontal_decompose97i(b4, width);
+ if(y+4<(unsigned)height) horizontal_decompose97i(b5, width);
+if(width>400){
+STOP_TIMER("horizontal_decompose97i")
+}}
+
+{START_TIMER
+ 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);
+
+if(width>400){
+STOP_TIMER("vertical_decompose97i")
+}}
+
+ b0=b2;
+ b1=b3;
+ b2=b4;
+ b3=b5;
+ }
+}
+
+void ff_spatial_dwt(DWTELEM *buffer, 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, width>>level, height>>level, stride<<level); break;
+ case DWT_53: spatial_decompose53i(buffer, width>>level, height>>level, stride<<level); break;
+ case DWT_X: spatial_decomposeX (buffer, width>>level, height>>level, stride<<level); break;
+ }
+ }
+}
+
+static void horizontal_compose53i(DWTELEM *b, int width){
+ DWTELEM temp[width];
+ const int width2= width>>1;
+ const int w2= (width+1)>>1;
+ int x;
+
+#if 0
+ int A1,A2,A3,A4;
+ A2= temp[1 ];
+ A4= temp[0 ];
+ A1= temp[0+width2];
+ A1 -= (A2 + A4)>>1;
+ A4 += (A1 + 1)>>1;
+ b[0+width2] = A1;
+ b[0 ] = A4;
+ for(x=1; x+1<width2; x+=2){
+ A3= temp[x+width2];
+ A4= temp[x+1 ];
+ A3 -= (A2 + A4)>>1;
+ A2 += (A1 + A3 + 2)>>2;
+ b[x+width2] = A3;
+ b[x ] = A2;
+
+ A1= temp[x+1+width2];
+ A2= temp[x+2 ];
+ A1 -= (A2 + A4)>>1;
+ A4 += (A1 + A3 + 2)>>2;
+ b[x+1+width2] = A1;
+ b[x+1 ] = A4;
+ }
+ A3= temp[width-1];
+ A3 -= A2;
+ A2 += (A1 + A3 + 2)>>2;
+ b[width -1] = A3;
+ b[width2-1] = A2;
+#else
+ lift(temp , b , b+w2, 1, 1, 1, width, 1, 2, 2, 0, 1);
+ lift(temp+w2, b+w2, temp, 1, 1, 1, width, -1, 0, 1, 1, 1);
+#endif
+ for(x=0; x<width2; x++){
+ b[2*x ]= temp[x ];
+ b[2*x + 1]= temp[x+w2];
+ }
+ if(width&1)
+ b[2*x ]= temp[x ];
+}
+
+static void vertical_compose53iH0(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_compose53iL0(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_compose53i_buffered_init(dwt_compose_t *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(dwt_compose_t *cs, DWTELEM *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(dwt_compose_t *cs, slice_buffer * sb, int width, int height, int stride_line){
+ int y= cs->y;
+
+ DWTELEM *b0= cs->b0;
+ DWTELEM *b1= cs->b1;
+ DWTELEM *b2= slice_buffer_get_line(sb, mirror(y+1, height-1) * stride_line);
+ DWTELEM *b3= slice_buffer_get_line(sb, mirror(y+2, height-1) * stride_line);
+
+{START_TIMER
+ if(y+1<(unsigned)height) vertical_compose53iL0(b1, b2, b3, width);
+ if(y+0<(unsigned)height) vertical_compose53iH0(b0, b1, b2, width);
+STOP_TIMER("vertical_compose53i*")}
+
+{START_TIMER
+ if(y-1<(unsigned)height) horizontal_compose53i(b0, width);
+ if(y+0<(unsigned)height) horizontal_compose53i(b1, width);
+STOP_TIMER("horizontal_compose53i")}
+
+ cs->b0 = b2;
+ cs->b1 = b3;
+ cs->y += 2;
+}
+
+static void spatial_compose53i_dy(dwt_compose_t *cs, DWTELEM *buffer, int width, int height, int stride){
+ int y= cs->y;
+ DWTELEM *b0= cs->b0;
+ DWTELEM *b1= cs->b1;
+ DWTELEM *b2= buffer + mirror(y+1, height-1)*stride;
+ DWTELEM *b3= buffer + mirror(y+2, height-1)*stride;
+
+{START_TIMER
+ if(y+1<(unsigned)height) vertical_compose53iL0(b1, b2, b3, width);
+ if(y+0<(unsigned)height) vertical_compose53iH0(b0, b1, b2, width);
+STOP_TIMER("vertical_compose53i*")}
+
+{START_TIMER
+ if(y-1<(unsigned)height) horizontal_compose53i(b0, width);
+ if(y+0<(unsigned)height) horizontal_compose53i(b1, width);
+STOP_TIMER("horizontal_compose53i")}
+
+ cs->b0 = b2;
+ cs->b1 = b3;
+ cs->y += 2;
+}
+
+static void spatial_compose53i(DWTELEM *buffer, int width, int height, int stride){
+ dwt_compose_t cs;
+ spatial_compose53i_init(&cs, buffer, height, stride);
+ while(cs.y <= height)
+ spatial_compose53i_dy(&cs, buffer, width, height, stride);
+}
+
+
+void ff_snow_horizontal_compose97i(DWTELEM *b, int width){
+ DWTELEM temp[width];
+ const int w2= (width+1)>>1;
+
+ lift (temp , b , b +w2, 1, 1, 1, width, W_DM, W_DO, W_DS, 0, 1);
+ lift5(temp+w2, b +w2, temp , 1, 1, 1, width, W_CM, W_CO, W_CS, 1, 1);
+ liftS(b , temp , temp+w2, 2, 1, 1, width, -W_BM, W_BO, W_BS, 0, 1);
+ lift (b+1 , temp+w2, b , 2, 1, 2, width, -W_AM, W_AO, W_AS, 1, 1);
+}
+
+static void vertical_compose97iH0(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_compose97iH1(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, int width){
+ int i;
+
+ for(i=0; i<width; i++){
+#ifdef lift5
+ b1[i] -= (W_CM*(b0[i] + b2[i])+W_CO)>>W_CS;
+#else
+ int r= 3*(b0[i] + b2[i]);
+ r+= r>>4;
+ r+= r>>8;
+ b1[i] -= (r+W_CO)>>W_CS;
+#endif
+ }
+}
+
+static void vertical_compose97iL0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, int width){
+ int i;
+
+ for(i=0; i<width; i++){
+#ifdef liftS
+ b1[i] += (W_BM*(b0[i] + b2[i])+W_BO)>>W_BS;
+#else
+ b1[i] += (W_BM*(b0[i] + b2[i])+4*b1[i]+W_BO)>>W_BS;
+#endif
+ }
+}
+
+static void vertical_compose97iL1(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;
+ }
+}
+
+void ff_snow_vertical_compose97i(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, DWTELEM *b3, DWTELEM *b4, DWTELEM *b5, int width){
+ int i;
+
+ for(i=0; i<width; i++){
+#ifndef lift5
+ int r;
+#endif
+ b4[i] -= (W_DM*(b3[i] + b5[i])+W_DO)>>W_DS;
+#ifdef lift5
+ b3[i] -= (W_CM*(b2[i] + b4[i])+W_CO)>>W_CS;
+#else
+ r= 3*(b2[i] + b4[i]);
+ r+= r>>4;
+ r+= r>>8;
+ b3[i] -= (r+W_CO)>>W_CS;
+#endif
+#ifdef liftS
+ b2[i] += (W_BM*(b1[i] + b3[i])+W_BO)>>W_BS;
+#else
+ b2[i] += (W_BM*(b1[i] + b3[i])+4*b2[i]+W_BO)>>W_BS;
+#endif
+ b1[i] += (W_AM*(b0[i] + b2[i])+W_AO)>>W_AS;
+ }
+}
+
+static void spatial_compose97i_buffered_init(dwt_compose_t *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(dwt_compose_t *cs, DWTELEM *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(DSPContext *dsp, dwt_compose_t *cs, slice_buffer * sb, int width, int height, int stride_line){
+ int y = cs->y;
+
+ DWTELEM *b0= cs->b0;
+ DWTELEM *b1= cs->b1;
+ DWTELEM *b2= cs->b2;
+ DWTELEM *b3= cs->b3;
+ DWTELEM *b4= slice_buffer_get_line(sb, mirror(y + 3, height - 1) * stride_line);
+ DWTELEM *b5= slice_buffer_get_line(sb, mirror(y + 4, height - 1) * stride_line);
+
+{START_TIMER
+ 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(width>400){
+STOP_TIMER("vertical_compose97i")}}
+
+{START_TIMER
+ if(y-1<(unsigned)height) dsp->horizontal_compose97i(b0, width);
+ if(y+0<(unsigned)height) dsp->horizontal_compose97i(b1, width);
+if(width>400 && y+0<(unsigned)height){
+STOP_TIMER("horizontal_compose97i")}}
+
+ cs->b0=b2;
+ cs->b1=b3;
+ cs->b2=b4;
+ cs->b3=b5;
+ cs->y += 2;
+}
+
+static void spatial_compose97i_dy(dwt_compose_t *cs, DWTELEM *buffer, int width, int height, int stride){
+ int y = cs->y;
+ DWTELEM *b0= cs->b0;
+ DWTELEM *b1= cs->b1;
+ DWTELEM *b2= cs->b2;
+ DWTELEM *b3= cs->b3;
+ DWTELEM *b4= buffer + mirror(y+3, height-1)*stride;
+ DWTELEM *b5= buffer + mirror(y+4, height-1)*stride;
+
+{START_TIMER
+ 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(width>400){
+STOP_TIMER("vertical_compose97i")}}
+
+{START_TIMER
+ if(y-1<(unsigned)height) ff_snow_horizontal_compose97i(b0, width);
+ if(y+0<(unsigned)height) ff_snow_horizontal_compose97i(b1, width);
+if(width>400 && b0 <= b2){
+STOP_TIMER("horizontal_compose97i")}}
+
+ cs->b0=b2;
+ cs->b1=b3;
+ cs->b2=b4;
+ cs->b3=b5;
+ cs->y += 2;
+}
+
+static void spatial_compose97i(DWTELEM *buffer, int width, int height, int stride){
+ dwt_compose_t cs;
+ spatial_compose97i_init(&cs, buffer, height, stride);
+ while(cs.y <= height)
+ spatial_compose97i_dy(&cs, buffer, width, height, stride);
+}
+
+static void ff_spatial_idwt_buffered_init(dwt_compose_t *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;
+ /* not slicified yet */
+ case DWT_X: /*spatial_composeX(buffer, width>>level, height>>level, stride<<level); break;*/
+ av_log(NULL, AV_LOG_ERROR, "spatial_composeX neither buffered nor slicified yet.\n"); break;
+ }
+ }
+}
+
+static void ff_spatial_idwt_init(dwt_compose_t *cs, DWTELEM *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;
+ /* not slicified yet */
+ case DWT_X: spatial_composeX(buffer, width>>level, height>>level, stride<<level); break;
+ }
+ }
+}
+
+static void ff_spatial_idwt_slice(dwt_compose_t *cs, DWTELEM *buffer, 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, width>>level, height>>level, stride<<level);
+ break;
+ case DWT_53: spatial_compose53i_dy(cs+level, buffer, width>>level, height>>level, stride<<level);
+ break;
+ case DWT_X: break;
+ }
+ }
+ }
+}
+
+static void ff_spatial_idwt_buffered_slice(DSPContext *dsp, dwt_compose_t *cs, slice_buffer * slice_buf, 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, width>>level, height>>level, stride_line<<level);
+ break;
+ case DWT_53: spatial_compose53i_dy_buffered(cs+level, slice_buf, width>>level, height>>level, stride_line<<level);
+ break;
+ case DWT_X: break;
+ }
+ }
+ }
+}
+
+static void ff_spatial_idwt(DWTELEM *buffer, int width, int height, int stride, int type, int decomposition_count){
+ if(type==2){
+ int level;
+ for(level=decomposition_count-1; level>=0; level--)
+ spatial_composeX (buffer, width>>level, height>>level, stride<<level);
+ }else{
+ dwt_compose_t 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, width, height, stride, type, decomposition_count, y);
+ }
+}
+
+static int encode_subband_c0run(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *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[w*h];
+ int run_index=0;
+ int max_index;
+
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ int v, p=0;
+ int /*ll=0, */l=0, lt=0, t=0, rt=0;
+ v= src[x + y*stride];
+
+ if(y){
+ t= src[x + (y-1)*stride];
+ if(x){
+ lt= src[x - 1 + (y-1)*stride];
+ }
+ if(x + 1 < w){
+ rt= src[x + 1 + (y-1)*stride];
+ }
+ }
+ if(x){
+ l= src[x - 1 + y*stride];
+ /*if(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(px<b->parent->width && py<b->parent->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; y<h; y++){
+ if(s->c.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<w; x++){
+ int v, p=0;
+ int /*ll=0, */l=0, lt=0, t=0, rt=0;
+ v= src[x + y*stride];
+
+ if(y){
+ t= src[x + (y-1)*stride];
+ if(x){
+ lt= src[x - 1 + (y-1)*stride];
+ }
+ if(x + 1 < w){
+ rt= src[x + 1 + (y-1)*stride];
+ }
+ }
+ if(x){
+ l= src[x - 1 + y*stride];
+ /*if(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(px<b->parent->width && py<b->parent->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 + quant3bA[l2&0xFF] + 3*quant3bA[t2&0xFF]], v<0);
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static int encode_subband(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *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 inline void unpack_coeffs(SnowContext *s, SubBand *b, SubBand * parent, int orientation){
+ const int w= b->width;
+ const int h= b->height;
+ int x,y;
+
+ if(1){
+ 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; y<h; y++){
+ int v=0;
+ int lt=0, t=0, rt=0;
+
+ if(y && prev_xc->x == 0){
+ rt= prev_xc->coeff;
+ }
+ for(x=0; x<w; x++){
+ int p=0;
+ const int l= v;
+
+ lt= t; t= rt;
+
+ if(y){
+ if(prev_xc->x <= 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 + quant3bA[l&0xFF] + 3*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;
+
+ 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);
+ 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
+ }
+}
+
+static inline void decode_subband_slice_buffered(SnowContext *s, SubBand *b, slice_buffer * sb, int start_y, int h, int save_state[1]){
+ const int w= b->width;
+ int y;
+ const int qlog= clip(s->qlog + b->qlog, 0, QROOT*16);
+ int qmul= qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT);
+ int qadd= (s->qbias*qmul)>>QBIAS_SHIFT;
+ int new_index = 0;
+
+ START_TIMER
+
+ if(b->buf == s->spatial_dwt_buffer || s->qlog == LOSSLESS_QLOG){
+ qadd= 0;
+ qmul= 1<<QEXPSHIFT;
+ }
+
+ /* If we are on the second or later slice, restore our index. */
+ if (start_y != 0)
+ new_index = save_state[0];
+
+
+ for(y=start_y; y<h; y++){
+ int x = 0;
+ int v;
+ DWTELEM * line = slice_buffer_get_line(sb, y * b->stride_line + b->buf_y_offset) + b->buf_x_offset;
+ memset(line, 0, b->width*sizeof(DWTELEM));
+ 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;
+ }
+ }
+ if(w > 200 && start_y != 0/*level+1 == s->spatial_decomposition_count*/){
+ STOP_TIMER("decode_subband")
+ }
+
+ /* Save our variables for the next slice. */
+ save_state[0] = new_index;
+
+ return;
+}
+
+static void reset_contexts(SnowContext *s){
+ int plane_index, level, orientation;
+
+ for(plane_index=0; plane_index<3; plane_index++){
+ for(level=0; level<s->spatial_decomposition_count; level++){
+ for(orientation=level ? 1:0; orientation<4; orientation++){
+ memset(s->plane[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));
+}
+
+static int 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;
+
+ s->block= av_mallocz(w * h * sizeof(BlockNode) << (s->block_max_depth*2));
+ return 0;
+}
+
+static inline void copy_rac_state(RangeCoder *d, RangeCoder *s){
+ uint8_t *bytestream= d->bytestream;
+ uint8_t *bytestream_start= d->bytestream_start;
+ *d= *s;
+ d->bytestream= bytestream;
+ d->bytestream_start= bytestream_start;
+}
+
+//near copy & paste from dsputil, FIXME
+static int pix_sum(uint8_t * pix, int line_size, int w)
+{
+ int s, i, j;
+
+ s = 0;
+ for (i = 0; i < w; 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 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<<rem_depth;
+ BlockNode block;
+ int i,j;
+
+ block.color[0]= l;
+ block.color[1]= cb;
+ block.color[2]= cr;
+ block.mx= mx;
+ block.my= my;
+ block.ref= ref;
+ block.type= type;
+ block.level= level;
+
+ for(j=0; j<block_w; j++){
+ for(i=0; i<block_w; i++){
+ s->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){
+ 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];
+ c->ref[0][i]= ref [i] + offset[i];
+ }
+ assert(!ref_index);
+}
+
+static inline void pred_mv(SnowContext *s, int *mx, int *my, int ref,
+ BlockNode *left, BlockNode *top, 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 = 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);
+ }
+}
+
+//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;
+ 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)<<rem_depth;
+ int try= (y+1)<<rem_depth;
+ BlockNode *left = x ? &s->block[index-1] : &null_block;
+ BlockNode *top = y ? &s->block[index-w] : &null_block;
+ BlockNode *right = trx<w ? &s->block[index+1] : &null_block;
+ BlockNode *bottom= try<h ? &s->block[index+w] : &null_block;
+ BlockNode *tl = y && x ? &s->block[index-w-1] : left;
+ BlockNode *tr = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
+ int pl = left->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 + y*uvstride)*block_w/2,
+ s->input_picture.data[2] + (x + y*uvstride)*block_w/2};
+ 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;
+ s->m.me.skip= 0;
+
+ assert(s->m.me. stride == stride);
+ assert(s->m.me.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+2;
+ c->ymin = - y*block_w - 16+2;
+ c->xmax = - (x+1)*block_w + (w<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-2;
+ c->ymax = - (y+1)*block_w + (h<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-2;
+
+ if(P_LEFT[0] > (c->xmax<<shift)) P_LEFT[0] = (c->xmax<<shift);
+ if(P_LEFT[1] > (c->ymax<<shift)) P_LEFT[1] = (c->ymax<<shift);
+ if(P_TOP[0] > (c->xmax<<shift)) P_TOP[0] = (c->xmax<<shift);
+ 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[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift); //due to pmx no clip
+ 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]);
+
+ if (!y) {
+ c->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; ref<s->ref_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= s->m.me.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 cant be compared currently and mb_penalty vs. lambda2
+
+ // subpel search
+ 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*(p_len*8
+ + (pc.outstanding_count - s->c.outstanding_count)*8
+ + (-av_log2(pc.range) + av_log2(s->c.range))
+ ))>>FF_LAMBDA_SHIFT;
+
+ block_s= block_w*block_w;
+ sum = pix_sum(current_data[0], stride, 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>>2;
+ sum = pix_sum(current_data[1], uvstride, block_w>>1);
+ cb= (sum + block_s/2)/block_s;
+// iscore += pix_norm1(&current_mb[1][0], uvstride, block_w>>1) - 2*cb*sum + cb*cb*block_s;
+ sum = pix_sum(current_data[2], uvstride, block_w>>1);
+ cr= (sum + block_s/2)/block_s;
+// iscore += pix_norm1(&current_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*(i_len*8
+ + (ic.outstanding_count - s->c.outstanding_count)*8
+ + (-av_log2(ic.range) + av_log2(s->c.range))
+ ))>>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 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));
+ }
+}
+
+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)<<rem_depth;
+ BlockNode *b= &s->block[index];
+ BlockNode *left = x ? &s->block[index-1] : &null_block;
+ BlockNode *top = y ? &s->block[index-w] : &null_block;
+ BlockNode *tl = y && x ? &s->block[index-w-1] : left;
+ BlockNode *tr = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
+ int pl = left->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 void 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)<<rem_depth;
+ BlockNode *left = x ? &s->block[index-1] : &null_block;
+ BlockNode *top = y ? &s->block[index-w] : &null_block;
+ BlockNode *tl = y && x ? &s->block[index-w-1] : left;
+ BlockNode *tr = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
+ int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
+
+ 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;
+ }
+
+ if(level==s->block_max_depth || get_rac(&s->c, &s->block_state[4 + s_context])){
+ int type;
+ int l = left->color[0];
+ int cb= left->color[1];
+ int cr= left->color[2];
+ int mx= mid_pred(left->mx, top->mx, tr->mx);
+ int my= mid_pred(left->my, top->my, tr->my);
+ 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);
+ 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{
+ decode_q_branch(s, level+1, 2*x+0, 2*y+0);
+ decode_q_branch(s, level+1, 2*x+1, 2*y+0);
+ decode_q_branch(s, level+1, 2*x+0, 2*y+1);
+ decode_q_branch(s, level+1, 2*x+1, 2*y+1);
+ }
+}
+
+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; y<h; y++){
+ if(s->c.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; x<w; x++){
+ if(s->avctx->me_method == ME_ITER || !search)
+ encode_q_branch2(s, 0, x, y);
+ else
+ encode_q_branch (s, 0, x, y);
+ }
+ }
+}
+
+static void decode_blocks(SnowContext *s){
+ int x, y;
+ int w= s->b_width;
+ int h= s->b_height;
+
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ decode_q_branch(s, 0, x, y);
+ }
+ }
+}
+
+static void mc_block(uint8_t *dst, uint8_t *src, uint8_t *tmp, int stride, int b_w, int b_h, int dx, int dy){
+ int x, y;
+START_TIMER
+ for(y=0; y < b_h+5; y++){
+ for(x=0; x < b_w; x++){
+ int a0= src[x ];
+ int a1= src[x + 1];
+ int a2= src[x + 2];
+ int a3= src[x + 3];
+ int a4= src[x + 4];
+ int a5= src[x + 5];
+// int am= 9*(a1+a2) - (a0+a3);
+ int am= 20*(a2+a3) - 5*(a1+a4) + (a0+a5);
+// int am= 18*(a2+a3) - 2*(a1+a4);
+// int aL= (-7*a0 + 105*a1 + 35*a2 - 5*a3)>>3;
+// int aR= (-7*a3 + 105*a2 + 35*a1 - 5*a0)>>3;
+
+// if(b_w==16) am= 8*(a1+a2);
+
+ if(dx<8) am = (32*a2*( 8-dx) + am* dx + 128)>>8;
+ else am = ( am*(16-dx) + 32*a3*(dx-8) + 128)>>8;
+
+ /* FIXME Try increasing tmp buffer to 16 bits and not clipping here. Should give marginally better results. - Robert*/
+ if(am&(~255)) am= ~(am>>31);
+
+ tmp[x] = am;
+
+/* if (dx< 4) tmp[x + y*stride]= (16*a1*( 4-dx) + aL* dx + 32)>>6;
+ else if(dx< 8) tmp[x + y*stride]= ( aL*( 8-dx) + am*(dx- 4) + 32)>>6;
+ else if(dx<12) tmp[x + y*stride]= ( am*(12-dx) + aR*(dx- 8) + 32)>>6;
+ else tmp[x + y*stride]= ( aR*(16-dx) + 16*a2*(dx-12) + 32)>>6;*/
+ }
+ tmp += stride;
+ src += stride;
+ }
+ tmp -= (b_h+5)*stride;
+
+ for(y=0; y < b_h; y++){
+ for(x=0; x < b_w; x++){
+ int a0= tmp[x + 0*stride];
+ int a1= tmp[x + 1*stride];
+ int a2= tmp[x + 2*stride];
+ int a3= tmp[x + 3*stride];
+ int a4= tmp[x + 4*stride];
+ int a5= tmp[x + 5*stride];
+ int am= 20*(a2+a3) - 5*(a1+a4) + (a0+a5);
+// int am= 18*(a2+a3) - 2*(a1+a4);
+/* int aL= (-7*a0 + 105*a1 + 35*a2 - 5*a3)>>3;
+ int aR= (-7*a3 + 105*a2 + 35*a1 - 5*a0)>>3;*/
+
+// if(b_w==16) am= 8*(a1+a2);
+
+ if(dy<8) am = (32*a2*( 8-dy) + am* dy + 128)>>8;
+ else am = ( am*(16-dy) + 32*a3*(dy-8) + 128)>>8;
+
+ if(am&(~255)) am= ~(am>>31);
+
+ dst[x] = am;
+/* if (dy< 4) tmp[x + y*stride]= (16*a1*( 4-dy) + aL* dy + 32)>>6;
+ else if(dy< 8) tmp[x + y*stride]= ( aL*( 8-dy) + am*(dy- 4) + 32)>>6;
+ else if(dy<12) tmp[x + y*stride]= ( am*(12-dy) + aR*(dy- 8) + 32)>>6;
+ else tmp[x + y*stride]= ( aR*(16-dy) + 16*a2*(dy-12) + 32)>>6;*/
+ }
+ dst += stride;
+ tmp += stride;
+ }
+STOP_TIMER("mc_block")
+}
+
+#define mca(dx,dy,b_w)\
+static void mc_block_hpel ## dx ## dy ## b_w(uint8_t *dst, uint8_t *src, int stride, int h){\
+ uint8_t tmp[stride*(b_w+5)];\
+ assert(h==b_w);\
+ mc_block(dst, src-2-2*stride, tmp, 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)
+
+static void 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 int color = block->color[plane_index];
+ const int 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 ? s->mv_scale : 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) - 2;
+ sy += (my>>4) - 2;
+ src += sx + sy*stride;
+ if( (unsigned)sx >= w - b_w - 4
+ || (unsigned)sy >= h - b_h - 4){
+ ff_emulated_edge_mc(tmp + MB_SIZE, src, stride, b_w+5, b_h+5, sx, sy, w, h);
+ src= tmp + MB_SIZE;
+ }
+// assert(b_w == b_h || 2*b_w == b_h || b_w == 2*b_h);
+// assert(!(b_w&(b_w-1)));
+ assert(b_w>1 && b_h>1);
+ assert(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)))
+ mc_block(dst, src, tmp, stride, b_w, b_h, dx, dy);
+ else if(b_w==32){
+ int y;
+ for(y=0; y<b_h; y+=16){
+ s->dsp.put_h264_qpel_pixels_tab[0][dy+(dx>>2)](dst + y*stride, src + 2 + (y+2)*stride,stride);
+ s->dsp.put_h264_qpel_pixels_tab[0][dy+(dx>>2)](dst + 16 + y*stride, src + 18 + (y+2)*stride,stride);
+ }
+ }else if(b_w==b_h)
+ s->dsp.put_h264_qpel_pixels_tab[tab_index ][dy+(dx>>2)](dst,src + 2 + 2*stride,stride);
+ else if(b_w==2*b_h){
+ s->dsp.put_h264_qpel_pixels_tab[tab_index+1][dy+(dx>>2)](dst ,src + 2 + 2*stride,stride);
+ s->dsp.put_h264_qpel_pixels_tab[tab_index+1][dy+(dx>>2)](dst+b_h,src + 2 + b_h + 2*stride,stride);
+ }else{
+ assert(2*b_w==b_h);
+ s->dsp.put_h264_qpel_pixels_tab[tab_index ][dy+(dx>>2)](dst ,src + 2 + 2*stride ,stride);
+ s->dsp.put_h264_qpel_pixels_tab[tab_index ][dy+(dx>>2)](dst+b_w*stride,src + 2 + 2*stride+b_w*stride,stride);
+ }
+ }
+}
+
+void ff_snow_inner_add_yblock(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;
+ DWTELEM * dst;
+ for(y=0; y<b_h; y++){
+ //FIXME ugly missue of obmc_stride
+ uint8_t *obmc1= obmc + y*obmc_stride;
+ uint8_t *obmc2= obmc1+ (obmc_stride>>1);
+ uint8_t *obmc3= obmc1+ obmc_stride*(obmc_stride>>1);
+ uint8_t *obmc4= obmc3+ (obmc_stride>>1);
+ dst = slice_buffer_get_line(sb, src_y + y);
+ for(x=0; x<b_w; x++){
+ int v= obmc1[x] * block[3][x + y*src_stride]
+ +obmc2[x] * block[2][x + y*src_stride]
+ +obmc3[x] * block[1][x + y*src_stride]
+ +obmc4[x] * block[0][x + y*src_stride];
+
+ v <<= 8 - LOG2_OBMC_MAX;
+ if(FRAC_BITS != 8){
+ v += 1<<(7 - FRAC_BITS);
+ v >>= 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;
+ }
+ }
+ }
+}
+
+//FIXME name clenup (b_w, block_w, b_width stuff)
+static always_inline void add_yblock(SnowContext *s, int sliced, slice_buffer *sb, DWTELEM *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[src_stride*7*MB_SIZE]; //FIXME align
+ 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 upto *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;
+
+assert(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;
+ 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;
+ 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;
+ 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;
+ pred_block(s, block[3], tmp, src_stride, src_x, src_y, b_w, b_h, rb, plane_index, w, h);
+ }
+#if 0
+ for(y=0; y<b_h; y++){
+ for(x=0; x<b_w; x++){
+ int v= obmc [x + y*obmc_stride] * block[3][x + y*src_stride] * (256/OBMC_MAX);
+ if(add) dst[x + y*dst_stride] += v;
+ else dst[x + y*dst_stride] -= v;
+ }
+ }
+ for(y=0; y<b_h; y++){
+ uint8_t *obmc2= obmc + (obmc_stride>>1);
+ for(x=0; x<b_w; x++){
+ int v= obmc2[x + y*obmc_stride] * block[2][x + y*src_stride] * (256/OBMC_MAX);
+ if(add) dst[x + y*dst_stride] += v;
+ else dst[x + y*dst_stride] -= v;
+ }
+ }
+ for(y=0; y<b_h; y++){
+ uint8_t *obmc3= obmc + obmc_stride*(obmc_stride>>1);
+ for(x=0; x<b_w; x++){
+ int v= obmc3[x + y*obmc_stride] * block[1][x + y*src_stride] * (256/OBMC_MAX);
+ if(add) dst[x + y*dst_stride] += v;
+ else dst[x + y*dst_stride] -= v;
+ }
+ }
+ for(y=0; y<b_h; y++){
+ uint8_t *obmc3= obmc + obmc_stride*(obmc_stride>>1);
+ uint8_t *obmc4= obmc3+ (obmc_stride>>1);
+ for(x=0; x<b_w; x++){
+ int v= obmc4[x + y*obmc_stride] * block[0][x + y*src_stride] * (256/OBMC_MAX);
+ if(add) dst[x + y*dst_stride] += v;
+ else dst[x + y*dst_stride] -= v;
+ }
+ }
+#else
+ if(sliced){
+ START_TIMER
+
+ s->dsp.inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8);
+ STOP_TIMER("inner_add_yblock")
+ }else
+ for(y=0; y<b_h; y++){
+ //FIXME ugly missue of obmc_stride
+ uint8_t *obmc1= obmc + y*obmc_stride;
+ uint8_t *obmc2= obmc1+ (obmc_stride>>1);
+ uint8_t *obmc3= obmc1+ obmc_stride*(obmc_stride>>1);
+ uint8_t *obmc4= obmc3+ (obmc_stride>>1);
+ for(x=0; x<b_w; x++){
+ int v= obmc1[x] * block[3][x + y*src_stride]
+ +obmc2[x] * block[2][x + y*src_stride]
+ +obmc3[x] * block[1][x + y*src_stride]
+ +obmc4[x] * block[0][x + y*src_stride];
+
+ v <<= 8 - LOG2_OBMC_MAX;
+ if(FRAC_BITS != 8){
+ v += 1<<(7 - FRAC_BITS);
+ v >>= 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;
+ }
+ }
+ }
+#endif
+}
+
+static always_inline void predict_slice_buffered(SnowContext *s, slice_buffer * sb, DWTELEM * 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/2 : block_size;
+ const uint8_t *obmc = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth];
+ int obmc_stride= plane_index ? block_size : 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;
+ START_TIMER
+
+ if(s->keyframe || (s->avctx->debug&512)){
+ if(mb_y==mb_h)
+ return;
+
+ if(add){
+ for(y=block_w*mb_y; y<FFMIN(h,block_w*(mb_y+1)); y++)
+ {
+// DWTELEM * line = slice_buffer_get_line(sb, y);
+ DWTELEM * line = sb->line[y];
+ for(x=0; x<w; x++)
+ {
+// int v= buf[x + y*w] + (128<<FRAC_BITS) + (1<<(FRAC_BITS-1));
+ int v= line[x] + (128<<FRAC_BITS) + (1<<(FRAC_BITS-1));
+ v >>= FRAC_BITS;
+ if(v&(~255)) v= ~(v>>31);
+ dst8[x + y*ref_stride]= v;
+ }
+ }
+ }else{
+ for(y=block_w*mb_y; y<FFMIN(h,block_w*(mb_y+1)); y++)
+ {
+// DWTELEM * line = slice_buffer_get_line(sb, y);
+ DWTELEM * line = sb->line[y];
+ for(x=0; x<w; x++)
+ {
+ line[x] -= 128 << FRAC_BITS;
+// buf[x + y*w]-= 128<<FRAC_BITS;
+ }
+ }
+ }
+
+ return;
+ }
+
+ for(mb_x=0; mb_x<=mb_w; mb_x++){
+ START_TIMER
+
+ add_yblock(s, 1, sb, old_buffer, dst8, obmc,
+ block_w*mb_x - block_w/2,
+ block_w*mb_y - block_w/2,
+ block_w, block_w,
+ w, h,
+ w, ref_stride, obmc_stride,
+ mb_x - 1, mb_y - 1,
+ add, 0, plane_index);
+
+ STOP_TIMER("add_yblock")
+ }
+
+ STOP_TIMER("predict_slice")
+}
+
+static always_inline void predict_slice(SnowContext *s, DWTELEM *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/2 : block_size;
+ const uint8_t *obmc = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth];
+ const int obmc_stride= plane_index ? block_size : 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;
+ START_TIMER
+
+ if(s->keyframe || (s->avctx->debug&512)){
+ if(mb_y==mb_h)
+ return;
+
+ if(add){
+ for(y=block_w*mb_y; y<FFMIN(h,block_w*(mb_y+1)); y++){
+ for(x=0; x<w; x++){
+ int v= buf[x + y*w] + (128<<FRAC_BITS) + (1<<(FRAC_BITS-1));
+ v >>= FRAC_BITS;
+ if(v&(~255)) v= ~(v>>31);
+ dst8[x + y*ref_stride]= v;
+ }
+ }
+ }else{
+ for(y=block_w*mb_y; y<FFMIN(h,block_w*(mb_y+1)); y++){
+ for(x=0; x<w; x++){
+ buf[x + y*w]-= 128<<FRAC_BITS;
+ }
+ }
+ }
+
+ return;
+ }
+
+ for(mb_x=0; mb_x<=mb_w; mb_x++){
+ START_TIMER
+
+ add_yblock(s, 0, NULL, buf, dst8, obmc,
+ block_w*mb_x - block_w/2,
+ block_w*mb_y - block_w/2,
+ block_w, block_w,
+ w, h,
+ w, ref_stride, obmc_stride,
+ mb_x - 1, mb_y - 1,
+ add, 1, plane_index);
+
+ STOP_TIMER("add_yblock")
+ }
+
+ STOP_TIMER("predict_slice")
+}
+
+static always_inline void predict_plane(SnowContext *s, DWTELEM *buf, int plane_index, int add){
+ const int mb_h= s->b_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 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/2 : block_size;
+ const uint8_t *obmc = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth];
+ const int obmc_stride= plane_index ? block_size : 2*block_size;
+ const int ref_stride= s->current_picture.linesize[plane_index];
+ uint8_t *src= s-> input_picture.data[plane_index];
+ DWTELEM *dst= (DWTELEM*)s->m.obmc_scratchpad + plane_index*block_size*block_size*4;
+ 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;
+
+ b->type|= BLOCK_INTRA;
+ b->color[plane_index]= 0;
+ memset(dst, 0, obmc_stride*obmc_stride*sizeof(DWTELEM));
+
+ 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_w*mb_y2 + block_w/2;
+
+ add_yblock(s, 0, NULL, dst + ((i&1)+(i>>1)*obmc_stride)*block_w, NULL, obmc,
+ x, y, block_w, block_w, w, h, obmc_stride, ref_stride, obmc_stride, mb_x2, mb_y2, 0, 0, plane_index);
+
+ for(y2= FFMAX(y, 0); y2<FFMIN(h, y+block_w); y2++){
+ for(x2= FFMAX(x, 0); x2<FFMIN(w, x+block_w); x2++){
+ int index= x2-(block_w*mb_x - block_w/2) + (y2-(block_w*mb_y - block_w/2))*obmc_stride;
+ int obmc_v= obmc[index];
+ int d;
+ if(y<0) obmc_v += obmc[index + block_w*obmc_stride];
+ if(x<0) obmc_v += obmc[index + block_w];
+ if(y+block_w>h) obmc_v += obmc[index - block_w*obmc_stride];
+ if(x+block_w>w) obmc_v += obmc[index - block_w];
+ //FIXME precalc 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 precalclate this
+ }
+ }
+ }
+ *b= backup;
+
+ return clip(((ab<<LOG2_OBMC_MAX) + aa/2)/aa, 0, 255); //FIXME we shouldnt need cliping
+}
+
+static inline int get_block_bits(SnowContext *s, int x, int y, int w){
+ const int b_stride = s->b_width << s->block_max_depth;
+ const int b_height = s->b_height<< s->block_max_depth;
+ int index= x + y*b_stride;
+ BlockNode *b = &s->block[index];
+ BlockNode *left = x ? &s->block[index-1] : &null_block;
+ BlockNode *top = y ? &s->block[index-b_stride] : &null_block;
+ BlockNode *tl = y && x ? &s->block[index-b_stride-1] : left;
+ BlockNode *tr = y && x+w<b_stride ? &s->block[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 arent 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, const uint8_t *obmc_edged){
+ Plane *p= &s->plane[plane_index];
+ const int block_size = MB_SIZE >> s->block_max_depth;
+ const int block_w = plane_index ? block_size/2 : block_size;
+ const int obmc_stride= plane_index ? block_size : 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];
+ DWTELEM *pred= (DWTELEM*)s->m.obmc_scratchpad + plane_index*block_size*block_size*4;
+ uint8_t cur[ref_stride*2*MB_SIZE]; //FIXME alignment
+ uint8_t tmp[ref_stride*(2*MB_SIZE+5)];
+ 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_w*mb_y - block_w/2;
+ int x0= FFMAX(0,-sx);
+ int y0= FFMAX(0,-sy);
+ int x1= FFMIN(block_w*2, w-sx);
+ int y1= FFMIN(block_w*2, h-sy);
+ int i,x,y;
+
+ pred_block(s, cur, tmp, ref_stride, sx, sy, block_w*2, block_w*2, &s->block[mb_x + mb_y*b_stride], plane_index, w, h);
+
+ for(y=y0; y<y1; y++){
+ const uint8_t *obmc1= obmc_edged + y*obmc_stride;
+ const DWTELEM *pred1 = pred + y*obmc_stride;
+ uint8_t *cur1 = cur + y*ref_stride;
+ uint8_t *dst1 = dst + sx + (sy+y)*ref_stride;
+ for(x=x0; x<x1; x++){
+ int v = (cur1[x] * obmc1[x]) << (FRAC_BITS - LOG2_OBMC_MAX);
+ 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_w;
+ else
+ y0 = block_w;
+ for(y=y0; y<y1; y++)
+ memcpy(dst + sx+x0 + (sy+y)*ref_stride, cur + x0 + y*ref_stride, x1-x0);
+ }
+
+ if(block_w==16){
+ /* FIXME rearrange dsputil to fit 32x32 cmp functions */
+ /* FIXME check alignment of the cmp wavelet vs the encoding wavelet */
+ /* FIXME cmps overlap but don't cover the wavelet's whole support,
+ * so improving the score of one block is not strictly guaranteed to
+ * improve the score of the whole frame, so iterative motion est
+ * doesn't always converge. */
+ if(s->avctx->me_cmp == FF_CMP_W97)
+ distortion = 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 = 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/2 : block_size;
+ const uint8_t *obmc = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth];
+ const int obmc_stride= plane_index ? block_size : 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];
+ static const DWTELEM 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);
+
+ 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_w*mb_y2 + block_w/2;
+
+ add_yblock(s, 0, NULL, zero_dst, dst, obmc,
+ x, y, block_w, block_w, 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<y+block_w; y2++)
+ memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, block_w);
+ if(x<0){
+ for(y2= y; y2<y+block_w; y2++)
+ memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, -x);
+ }
+ if(x+block_w > w){
+ for(y2= y; y2<y+block_w; y2++)
+ memcpy(dst + w + y2*ref_stride, src + w + y2*ref_stride, x+block_w - w);
+ }
+
+ assert(block_w== 8 || block_w==16);
+ distortion += s->dsp.me_cmp[block_w==8](&s->m, src + x + y*ref_stride, dst + x + y*ref_stride, ref_stride, block_w);
+ }
+
+ 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 always_inline int check_block(SnowContext *s, int mb_x, int mb_y, int p[3], int intra, const uint8_t *obmc_edged, 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;
+ int rd, index, value;
+
+ assert(mb_x>=0 && mb_y>=0);
+ assert(mb_x<b_stride);
+
+ if(intra){
+ block->color[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 afterward, fixes compilation prob with gcc 2.95 */
+static always_inline int check_block_inter(SnowContext *s, int mb_x, int mb_y, int p0, int p1, const uint8_t *obmc_edged, int *best_rd){
+ int p[2] = {p0, p1};
+ return check_block(s, mb_x, mb_y, p, 0, obmc_edged, best_rd);
+}
+
+static 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]= {block[0], block[1], block[b_stride], block[b_stride+1]};
+ int rd, index, value;
+
+ assert(mb_x>=0 && mb_y>=0);
+ assert(mb_x<b_stride);
+ assert(((mb_x|mb_y)&1) == 0);
+
+ index= (p0 + 31*p1) & (ME_CACHE_SIZE-1);
+ value= s->me_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_y<s->b_height; mb_y++)
+ for(mb_x= 0; mb_x<s->b_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_y<b_height; mb_y++){
+ for(mb_x= 0; mb_x<b_width; mb_x++){
+ int dia_change, i, j, ref;
+ int best_rd= INT_MAX, ref_rd;
+ BlockNode backup, ref_b;
+ const int index= mb_x + mb_y * b_stride;
+ BlockNode *block= &s->block[index];
+ BlockNode *tb = mb_y ? &s->block[index-b_stride ] : NULL;
+ BlockNode *lb = mb_x ? &s->block[index -1] : NULL;
+ BlockNode *rb = mb_x+1<b_width ? &s->block[index +1] : NULL;
+ BlockNode *bb = mb_y+1<b_height ? &s->block[index+b_stride ] : NULL;
+ BlockNode *tlb= mb_x && mb_y ? &s->block[index-b_stride-1] : NULL;
+ BlockNode *trb= mb_x+1<b_width && mb_y ? &s->block[index-b_stride+1] : NULL;
+ BlockNode *blb= mb_x && mb_y+1<b_height ? &s->block[index+b_stride-1] : NULL;
+ BlockNode *brb= mb_x+1<b_width && mb_y+1<b_height ? &s->block[index+b_stride+1] : NULL;
+ const int b_w= (MB_SIZE >> s->block_max_depth);
+ uint8_t obmc_edged[b_w*2][b_w*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 precalc
+ {
+ int x, y;
+ memcpy(obmc_edged, obmc_tab[s->block_max_depth], b_w*b_w*4);
+ if(mb_x==0)
+ for(y=0; y<b_w*2; y++)
+ memset(obmc_edged[y], obmc_edged[y][0] + obmc_edged[y][b_w-1], b_w);
+ if(mb_x==b_stride-1)
+ for(y=0; y<b_w*2; y++)
+ memset(obmc_edged[y]+b_w, obmc_edged[y][b_w] + obmc_edged[y][b_w*2-1], b_w);
+ if(mb_y==0){
+ for(x=0; x<b_w*2; x++)
+ obmc_edged[0][x] += obmc_edged[b_w-1][x];
+ for(y=1; y<b_w; y++)
+ memcpy(obmc_edged[y], obmc_edged[0], b_w*2);
+ }
+ if(mb_y==b_height-1){
+ for(x=0; x<b_w*2; x++)
+ obmc_edged[b_w*2-1][x] += obmc_edged[b_w][x];
+ for(y=b_w; y<b_w*2-1; y++)
+ memcpy(obmc_edged[y], obmc_edged[b_w*2-1], b_w*2);
+ }
+ }
+
+ //skip stuff outside the picture
+ if(mb_x==0 || mb_y==0 || mb_x==b_width-1 || mb_y==b_height-1)
+ {
+ uint8_t *src= s-> 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 sx= block_w*mb_x - block_w/2;
+ const int sy= block_w*mb_y - block_w/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<sy+block_w*2; y++)
+ memcpy(dst + sx + y*stride, src + sx + y*stride, block_w*2);
+ if(sx<0){
+ for(y=sy; y<sy+block_w*2; y++)
+ memcpy(dst + sx + y*stride, src + sx + y*stride, -sx);
+ }
+ if(sx+block_w*2 > w){
+ for(y=sy; y<sy+block_w*2; y++)
+ memcpy(dst + w + y*stride, src + w + y*stride, sx+block_w*2 - w);
+ }
+ }
+
+ // intra(black) = neighbors' contribution to the current block
+ for(i=0; i<3; i++)
+ color[i]= get_dc(s, mb_x, mb_y, i);
+
+ // get previous score (cant be cached due to OBMC)
+ if(pass > 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 interpol / round to nearest integer
+ do{
+ dia_change=0;
+ for(i=0; i<FFMAX(s->avctx->dia_size, 1); i++){
+ for(j=0; j<i; j++){
+ 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);
+ 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;
+#if 1
+ check_block(s, mb_x, mb_y, color, 1, *obmc_edged, &best_rd);
+ //FIXME RD style color selection
+#endif
+ 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(NULL, 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_y<b_height; mb_y+=2){
+ for(mb_x= 0; mb_x<b_width; mb_x+=2){
+ int i;
+ int best_rd, init_rd;
+ const int index= mb_x + mb_y * b_stride;
+ BlockNode *b[4];
+
+ b[0]= &s->block[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(NULL, AV_LOG_ERROR, "pass:4mv changed:%d\n", change*4);
+ }
+}
+
+static void quantize(SnowContext *s, SubBand *b, DWTELEM *src, int stride, int bias){
+ const int level= b->level;
+ const int w= b->width;
+ const int h= b->height;
+ const int qlog= clip(s->qlog + b->qlog, 0, QROOT*16);
+ const int qmul= qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT);
+ int x,y, thres1, thres2;
+// START_TIMER
+
+ if(s->qlog == LOSSLESS_QLOG) return;
+
+ bias= bias ? 0 : (3*qmul)>>3;
+ thres1= ((qmul - bias)>>QEXPSHIFT) - 1;
+ thres2= 2*thres1;
+
+ if(!bias){
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ int i= src[x + y*stride];
+
+ if((unsigned)(i+thres1) > thres2){
+ if(i>=0){
+ i<<= QEXPSHIFT;
+ i/= qmul; //FIXME optimize
+ src[x + y*stride]= i;
+ }else{
+ i= -i;
+ i<<= QEXPSHIFT;
+ i/= qmul; //FIXME optimize
+ src[x + y*stride]= -i;
+ }
+ }else
+ src[x + y*stride]= 0;
+ }
+ }
+ }else{
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ int i= src[x + y*stride];
+
+ if((unsigned)(i+thres1) > thres2){
+ if(i>=0){
+ i<<= QEXPSHIFT;
+ i= (i + bias) / qmul; //FIXME optimize
+ src[x + y*stride]= i;
+ }else{
+ i= -i;
+ i<<= QEXPSHIFT;
+ i= (i + bias) / qmul; //FIXME optimize
+ src[x + y*stride]= -i;
+ }
+ }else
+ src[x + y*stride]= 0;
+ }
+ }
+ }
+ if(level+1 == s->spatial_decomposition_count){
+// STOP_TIMER("quantize")
+ }
+}
+
+static void dequantize_slice_buffered(SnowContext *s, slice_buffer * sb, SubBand *b, DWTELEM *src, int stride, int start_y, int end_y){
+ const int w= b->width;
+ const int qlog= clip(s->qlog + b->qlog, 0, QROOT*16);
+ const int qmul= qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT);
+ const int qadd= (s->qbias*qmul)>>QBIAS_SHIFT;
+ int x,y;
+ START_TIMER
+
+ if(s->qlog == LOSSLESS_QLOG) return;
+
+ for(y=start_y; y<end_y; y++){
+// DWTELEM * line = slice_buffer_get_line_from_address(sb, src + (y * stride));
+ DWTELEM * line = slice_buffer_get_line(sb, (y * b->stride_line) + b->buf_y_offset) + b->buf_x_offset;
+ for(x=0; x<w; x++){
+ int i= line[x];
+ if(i<0){
+ line[x]= -((-i*qmul + qadd)>>(QEXPSHIFT)); //FIXME try different bias
+ }else if(i>0){
+ line[x]= (( i*qmul + qadd)>>(QEXPSHIFT));
+ }
+ }
+ }
+ if(w > 200 /*level+1 == s->spatial_decomposition_count*/){
+ STOP_TIMER("dquant")
+ }
+}
+
+static void dequantize(SnowContext *s, SubBand *b, DWTELEM *src, int stride){
+ const int w= b->width;
+ const int h= b->height;
+ const int qlog= clip(s->qlog + b->qlog, 0, QROOT*16);
+ const int qmul= qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT);
+ const int qadd= (s->qbias*qmul)>>QBIAS_SHIFT;
+ int x,y;
+ START_TIMER
+
+ if(s->qlog == LOSSLESS_QLOG) return;
+
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ int i= src[x + y*stride];
+ if(i<0){
+ src[x + y*stride]= -((-i*qmul + qadd)>>(QEXPSHIFT)); //FIXME try different bias
+ }else if(i>0){
+ src[x + y*stride]= (( i*qmul + qadd)>>(QEXPSHIFT));
+ }
+ }
+ }
+ if(w > 200 /*level+1 == s->spatial_decomposition_count*/){
+ STOP_TIMER("dquant")
+ }
+}
+
+static void decorrelate(SnowContext *s, SubBand *b, DWTELEM *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+1<w) src[i] -= mid_pred(src[i - 1], src[i - stride], src[i - stride + 1]);
+ else src[i] -= src[i - 1];
+ }else{
+ if(y) src[i] -= mid_pred(src[i - 1], src[i - stride], src[i - 1] + src[i - stride] - src[i - 1 - stride]);
+ else src[i] -= src[i - 1];
+ }
+ }else{
+ if(y) src[i] -= src[i - stride];
+ }
+ }
+ }
+}
+
+static void correlate_slice_buffered(SnowContext *s, slice_buffer * sb, SubBand *b, DWTELEM *src, int stride, int inverse, int use_median, int start_y, int end_y){
+ const int w= b->width;
+ int x,y;
+
+// START_TIMER
+
+ DWTELEM * line;
+ DWTELEM * 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; y<end_y; y++){
+ prev = line;
+// line = slice_buffer_get_line_from_address(sb, src + (y * stride));
+ line = slice_buffer_get_line(sb, (y * b->stride_line) + b->buf_y_offset) + b->buf_x_offset;
+ for(x=0; x<w; x++){
+ if(x){
+ if(use_median){
+ if(y && x+1<w) line[x] += mid_pred(line[x - 1], prev[x], prev[x + 1]);
+ else line[x] += line[x - 1];
+ }else{
+ if(y) line[x] += mid_pred(line[x - 1], prev[x], line[x - 1] + prev[x] - prev[x - 1]);
+ else line[x] += line[x - 1];
+ }
+ }else{
+ if(y) line[x] += prev[x];
+ }
+ }
+ }
+
+// STOP_TIMER("correlate")
+}
+
+static void correlate(SnowContext *s, SubBand *b, DWTELEM *src, int stride, int inverse, int use_median){
+ const int w= b->width;
+ const int h= b->height;
+ int x,y;
+
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ int i= x + y*stride;
+
+ if(x){
+ if(use_median){
+ if(y && x+1<w) src[i] += mid_pred(src[i - 1], src[i - stride], src[i - stride + 1]);
+ else src[i] += src[i - 1];
+ }else{
+ if(y) src[i] += mid_pred(src[i - 1], src[i - stride], src[i - 1] + src[i - stride] - src[i - 1 - stride]);
+ else src[i] += src[i - 1];
+ }
+ }else{
+ if(y) src[i] += src[i - stride];
+ }
+ }
+ }
+}
+
+static void encode_header(SnowContext *s){
+ int plane_index, level, orientation;
+ uint8_t kstate[32];
+
+ memset(kstate, MID_STATE, sizeof(kstate));
+
+ put_rac(&s->c, kstate, s->keyframe);
+ if(s->keyframe || s->always_reset)
+ reset_contexts(s);
+ 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);
+
+ for(plane_index=0; plane_index<2; plane_index++){
+ for(level=0; level<s->spatial_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);
+ }
+ }
+ }
+ }
+ put_symbol(&s->c, s->header_state, s->spatial_decomposition_type, 0);
+ put_symbol(&s->c, s->header_state, s->qlog, 1);
+ put_symbol(&s->c, s->header_state, s->mv_scale, 0);
+ put_symbol(&s->c, s->header_state, s->qbias, 1);
+ put_symbol(&s->c, s->header_state, s->block_max_depth, 0);
+}
+
+static int decode_header(SnowContext *s){
+ int plane_index, level, orientation;
+ uint8_t kstate[32];
+
+ memset(kstate, MID_STATE, sizeof(kstate));
+
+ s->keyframe= get_rac(&s->c, kstate);
+ if(s->keyframe || s->always_reset)
+ reset_contexts(s);
+ if(s->keyframe){
+ s->version= get_symbol(&s->c, s->header_state, 0);
+ if(s->version>0){
+ av_log(s->avctx, AV_LOG_ERROR, "version %d not supported", s->version);
+ return -1;
+ }
+ 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);
+ s->spatial_decomposition_count= get_symbol(&s->c, s->header_state, 0);
+ 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);
+ s->spatial_scalability= get_rac(&s->c, s->header_state);
+// s->rate_scalability= get_rac(&s->c, s->header_state);
+ s->max_ref_frames= get_symbol(&s->c, s->header_state, 0)+1;
+
+ for(plane_index=0; plane_index<3; plane_index++){
+ for(level=0; level<s->spatial_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;
+ }
+ }
+ }
+ }
+
+ s->spatial_decomposition_type= get_symbol(&s->c, s->header_state, 0);
+ if(s->spatial_decomposition_type > 2){
+ av_log(s->avctx, AV_LOG_ERROR, "spatial_decomposition_type %d not supported", s->spatial_decomposition_type);
+ return -1;
+ }
+
+ s->qlog= get_symbol(&s->c, s->header_state, 1);
+ s->mv_scale= get_symbol(&s->c, s->header_state, 0);
+ s->qbias= get_symbol(&s->c, s->header_state, 1);
+ s->block_max_depth= get_symbol(&s->c, s->header_state, 0);
+ 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", s->block_max_depth);
+ s->block_max_depth= 0;
+ return -1;
+ }
+
+ return 0;
+}
+
+static void init_qexp(void){
+ int i;
+ double v=128;
+
+ for(i=0; i<QROOT; i++){
+ qexp[i]= lrintf(v);
+ v *= pow(2, 1.0 / QROOT);
+ }
+}
+
+static int common_init(AVCodecContext *avctx){
+ SnowContext *s = avctx->priv_data;
+ int width, height;
+ int level, orientation, plane_index, dec;
+ int i, j;
+
+ s->avctx= avctx;
+
+ dsputil_init(&s->dsp, avctx);
+
+#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->dsp.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->dsp.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->dsp.put_pixels_tab [0][dy/4+dx/8]=\
+ s->dsp.put_no_rnd_pixels_tab[0][dy/4+dx/8]=\
+ mc_block_hpel ## dx ## dy ## 16;\
+ s->dsp.put_pixels_tab [1][dy/4+dx/8]=\
+ s->dsp.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)
+
+ if(!qexp[0])
+ init_qexp();
+
+ dec= s->spatial_decomposition_count= 5;
+ s->spatial_decomposition_type= avctx->prediction_method; //FIXME add decorrelator type r transform_type
+
+ s->chroma_h_shift= 1; //FIXME XXX
+ s->chroma_v_shift= 1;
+
+// dec += FFMAX(s->chroma_h_shift, s->chroma_v_shift);
+
+ width= s->avctx->width;
+ height= s->avctx->height;
+
+ s->spatial_dwt_buffer= av_mallocz(width*height*sizeof(DWTELEM));
+
+ s->mv_scale= (s->avctx->flags & CODEC_FLAG_QPEL) ? 2 : 4;
+ s->block_max_depth= (s->avctx->flags & CODEC_FLAG_4MV) ? 1 : 0;
+
+ 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;
+//av_log(NULL, AV_LOG_DEBUG, "%d %d\n", w, 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;
+ }
+
+ if(level)
+ b->parent= &s->plane[plane_index].band[level-1][orientation];
+ b->x_coeff=av_mallocz(((b->width+1) * b->height+1)*sizeof(x_and_coeff));
+ }
+ w= (w+1)>>1;
+ h= (h+1)>>1;
+ }
+ }
+
+ for(i=0; i<MAX_REF_FRAMES; i++)
+ for(j=0; j<MAX_REF_FRAMES; j++)
+ scale_mv_ref[i][j] = 256*(i+1)/(j+1);
+
+ reset_contexts(s);
+/*
+ width= s->width= avctx->width;
+ height= s->height= avctx->height;
+
+ assert(width && height);
+*/
+ s->avctx->get_buffer(s->avctx, &s->mconly_picture);
+
+ return 0;
+}
+
+static int qscale2qlog(int qscale){
+ return rint(QROOT*log(qscale / (float)FF_QP2LAMBDA)/log(2))
+ + 61*QROOT/8; //<64 >60
+}
+
+static int ratecontrol_1pass(SnowContext *s, AVFrame *pict)
+{
+ /* estimate the frame's complexity as a sum of weighted dwt coefs.
+ * 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; level<s->spatial_decomposition_count; level++){
+ for(orientation=level ? 1 : 0; orientation<4; orientation++){
+ SubBand *b= &s->plane[0].band[level][orientation];
+ DWTELEM *buf= b->buf;
+ const int w= b->width;
+ const int h= b->height;
+ const int stride= b->stride;
+ const int qlog= clip(2*QROOT + b->qlog, 0, QROOT*16);
+ const int qmul= qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT);
+ const int qdiv= (1<<16)/qmul;
+ int x, y;
+ if(orientation==0)
+ decorrelate(s, b, buf, stride, 1, 0);
+ for(y=0; y<h; y++)
+ for(x=0; x<w; x++)
+ coef_sum+= abs(buf[x+y*stride]) * qdiv >> 16;
+ if(orientation==0)
+ correlate(s, b, buf, stride, 1, 0);
+ }
+ }
+
+ /* 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 == I_TYPE){
+ 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_vissual_weight(SnowContext *s, Plane *p){
+ int width = p->width;
+ int height= p->height;
+ int level, orientation, x, y;
+
+ for(level=0; level<s->spatial_decomposition_count; level++){
+ for(orientation=level ? 1 : 0; orientation<4; orientation++){
+ SubBand *b= &p->band[level][orientation];
+ DWTELEM *buf= b->buf;
+ int64_t error=0;
+
+ memset(s->spatial_dwt_buffer, 0, sizeof(int)*width*height);
+ buf[b->width/2 + b->height/2*b->stride]= 256*256;
+ ff_spatial_idwt(s->spatial_dwt_buffer, width, height, width, s->spatial_decomposition_type, s->spatial_decomposition_count);
+ for(y=0; y<height; y++){
+ for(x=0; x<width; x++){
+ int64_t d= s->spatial_dwt_buffer[x + y*width];
+ error += d*d;
+ }
+ }
+
+ b->qlog= (int)(log(352256.0/sqrt(error)) / log(pow(2.0, 1.0/QROOT))+0.5);
+// av_log(NULL, AV_LOG_DEBUG, "%d %d %d\n", level, orientation, b->qlog/*, sqrt(error)*/);
+ }
+ }
+}
+
+static int encode_init(AVCodecContext *avctx)
+{
+ SnowContext *s = avctx->priv_data;
+ int plane_index;
+
+ 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;
+ }
+
+ common_init(avctx);
+ 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.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));
+ 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));
+
+ for(plane_index=0; plane_index<3; plane_index++){
+ calculate_vissual_weight(s, &s->plane[plane_index]);
+ }
+
+
+ avctx->coded_frame= &s->current_picture;
+ switch(avctx->pix_fmt){
+// case PIX_FMT_YUV444P:
+// case PIX_FMT_YUV422P:
+ case PIX_FMT_YUV420P:
+ case PIX_FMT_GRAY8:
+// case PIX_FMT_YUV411P:
+// case PIX_FMT_YUV410P:
+ s->colorspace_type= 0;
+ break;
+/* case PIX_FMT_RGBA32:
+ s->colorspace= 1;
+ break;*/
+ default:
+ av_log(avctx, AV_LOG_ERROR, "format not supported\n");
+ return -1;
+ }
+// avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_h_shift, &s->chroma_v_shift);
+ s->chroma_h_shift= 1;
+ s->chroma_v_shift= 1;
+
+ 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);
+
+ s->avctx->get_buffer(s->avctx, &s->input_picture);
+
+ 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; i<s->max_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;
+}
+
+static int frame_start(SnowContext *s){
+ AVFrame tmp;
+ int w= s->avctx->width; //FIXME round up to x16 ?
+ int h= s->avctx->height;
+
+ if(s->current_picture.data[0]){
+ draw_edges(s->current_picture.data[0], s->current_picture.linesize[0], w , h , EDGE_WIDTH );
+ draw_edges(s->current_picture.data[1], s->current_picture.linesize[1], w>>1, h>>1, EDGE_WIDTH/2);
+ draw_edges(s->current_picture.data[2], s->current_picture.linesize[2], w>>1, h>>1, EDGE_WIDTH/2);
+ }
+
+ tmp= s->last_picture[s->max_ref_frames-1];
+ memmove(s->last_picture+1, s->last_picture, (s->max_ref_frames-1)*sizeof(AVFrame));
+ s->last_picture[0]= s->current_picture;
+ s->current_picture= tmp;
+
+ if(s->keyframe){
+ s->ref_frames= 0;
+ }else{
+ int i;
+ for(i=0; i<s->max_ref_frames && s->last_picture[i].data[0]; i++)
+ if(i && s->last_picture[i-1].key_frame)
+ break;
+ s->ref_frames= i;
+ }
+
+ s->current_picture.reference= 1;
+ if(s->avctx->get_buffer(s->avctx, &s->current_picture) < 0){
+ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ s->current_picture.key_frame= s->keyframe;
+
+ return 0;
+}
+
+static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
+ SnowContext *s = avctx->priv_data;
+ RangeCoder * const c= &s->c;
+ AVFrame *pict = data;
+ const int width= s->avctx->width;
+ const int height= s->avctx->height;
+ int level, orientation, plane_index, i, y;
+ uint8_t rc_header_bak[sizeof(s->header_state)];
+ uint8_t rc_block_bak[sizeof(s->block_state)];
+
+ ff_init_range_encoder(c, buf, buf_size);
+ ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
+
+ for(i=0; i<3; i++){
+ int shift= !!i;
+ for(y=0; y<(height>>shift); y++)
+ memcpy(&s->input_picture.data[i][y * s->input_picture.linesize[i]],
+ &pict->data[i][y * pict->linesize[i]],
+ width>>shift);
+ }
+ s->new_picture = *pict;
+
+ s->m.picture_number= avctx->frame_number;
+ if(avctx->flags&CODEC_FLAG_PASS2){
+ s->m.pict_type =
+ pict->pict_type= s->m.rc_context.entry[avctx->frame_number].new_pict_type;
+ s->keyframe= pict->pict_type==FF_I_TYPE;
+ if(!(avctx->flags&CODEC_FLAG_QSCALE)) {
+ pict->quality= ff_rate_estimate_qscale(&s->m, 0);
+ if (pict->quality < 0)
+ return -1;
+ }
+ }else{
+ s->keyframe= avctx->gop_size==0 || avctx->frame_number % avctx->gop_size == 0;
+ s->m.pict_type=
+ pict->pict_type= s->keyframe ? FF_I_TYPE : FF_P_TYPE;
+ }
+
+ if(s->pass1_rc && avctx->frame_number == 0)
+ pict->quality= 2*FF_QP2LAMBDA;
+ if(pict->quality){
+ s->qlog= qscale2qlog(pict->quality);
+ s->lambda = pict->quality * 3/2;
+ }
+ if(s->qlog < 0 || (!pict->quality && (avctx->flags & CODEC_FLAG_QSCALE))){
+ s->qlog= LOSSLESS_QLOG;
+ s->lambda = 0;
+ }//else keep previous frame's qlog until after motion est
+
+ frame_start(s);
+
+ s->m.current_picture_ptr= &s->m.current_picture;
+ if(pict->pict_type == P_TYPE){
+ 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.data[0]= s->current_picture.data[0];
+ s->m. last_picture.data[0]= s->last_picture[0].data[0];
+ s->m. new_picture.data[0]= s-> input_picture.data[0];
+ s->m. last_picture_ptr= &s->m. last_picture;
+ s->m.linesize=
+ s->m. last_picture.linesize[0]=
+ s->m. new_picture.linesize[0]=
+ s->m.current_picture.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= pict->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
+ ff_init_me(&s->m);
+ 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:
+
+ s->m.pict_type = pict->pict_type;
+ s->qbias= pict->pict_type == P_TYPE ? 2 : 0;
+
+ 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(!(avctx->flags2 & CODEC_FLAG2_MEMC_ONLY)){
+ //FIXME optimize
+ if(pict->data[plane_index]) //FIXME gray hack
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ s->spatial_dwt_buffer[y*w + x]= pict->data[plane_index][y*pict->linesize[plane_index] + x]<<FRAC_BITS;
+ }
+ }
+ predict_plane(s, s->spatial_dwt_buffer, plane_index, 0);
+
+ if( plane_index==0
+ && pict->pict_type == P_TYPE
+ && !(avctx->flags&CODEC_FLAG_PASS2)
+ && s->m.me.scene_change_score > s->avctx->scenechange_threshold){
+ ff_init_range_encoder(c, buf, buf_size);
+ ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
+ pict->pict_type= FF_I_TYPE;
+ s->keyframe=1;
+ s->current_picture.key_frame=1;
+ reset_contexts(s);
+ goto redo_frame;
+ }
+
+ if(s->qlog == LOSSLESS_QLOG){
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ s->spatial_dwt_buffer[y*w + x]= (s->spatial_dwt_buffer[y*w + x] + (1<<(FRAC_BITS-1))-1)>>FRAC_BITS;
+ }
+ }
+ }
+
+ ff_spatial_dwt(s->spatial_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, pict);
+ if (delta_qlog <= INT_MIN)
+ return -1;
+ if(delta_qlog){
+ //reordering qlog in the bitstream would eliminate this reset
+ ff_init_range_encoder(c, buf, buf_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; level<s->spatial_decomposition_count; level++){
+ for(orientation=level ? 1 : 0; orientation<4; orientation++){
+ SubBand *b= &p->band[level][orientation];
+
+ quantize(s, b, b->buf, b->stride, s->qbias);
+ if(orientation==0)
+ decorrelate(s, b, b->buf, b->stride, pict->pict_type == P_TYPE, 0);
+ encode_subband(s, b, b->buf, b->parent ? b->parent->buf : NULL, b->stride, orientation);
+ assert(b->parent==NULL || b->parent->stride == b->stride*2);
+ if(orientation==0)
+ correlate(s, b, b->buf, b->stride, 1, 0);
+ }
+ }
+// av_log(NULL, AV_LOG_DEBUG, "plane:%d bits:%d\n", plane_index, put_bits_count(&s->c.pb) - bits);
+
+ for(level=0; level<s->spatial_decomposition_count; level++){
+ for(orientation=level ? 1 : 0; orientation<4; orientation++){
+ SubBand *b= &p->band[level][orientation];
+
+ dequantize(s, b, b->buf, b->stride);
+ }
+ }
+
+ ff_spatial_idwt(s->spatial_dwt_buffer, w, h, w, s->spatial_decomposition_type, s->spatial_decomposition_count);
+ if(s->qlog == LOSSLESS_QLOG){
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ s->spatial_dwt_buffer[y*w + x]<<=FRAC_BITS;
+ }
+ }
+ }
+{START_TIMER
+ predict_plane(s, s->spatial_dwt_buffer, plane_index, 1);
+STOP_TIMER("pred-conv")}
+ }else{
+ //ME/MC only
+ if(pict->pict_type == I_TYPE){
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ s->current_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_dwt_buffer, 0, sizeof(DWTELEM)*w*h);
+ predict_plane(s, s->spatial_dwt_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; y<h; y++){
+ for(x=0; x<w; x++){
+ int d= s->current_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;
+ }
+ }
+
+ if(s->last_picture[s->max_ref_frames-1].data[0])
+ avctx->release_buffer(avctx, &s->last_picture[s->max_ref_frames-1]);
+
+ 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.display_picture_number =
+ s->m.current_picture.coded_picture_number = avctx->frame_number;
+ s->m.current_picture.quality = pict->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();
+
+ return ff_rac_terminate(c);
+}
+
+static void common_end(SnowContext *s){
+ int plane_index, level, orientation, i;
+
+ av_freep(&s->spatial_dwt_buffer);
+
+ 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);
+
+ for(i=0; i<MAX_REF_FRAMES; i++){
+ av_freep(&s->ref_mvs[i]);
+ av_freep(&s->ref_scores[i]);
+ if(s->last_picture[i].data[0])
+ s->avctx->release_buffer(s->avctx, &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);
+ }
+ }
+ }
+}
+
+static int encode_end(AVCodecContext *avctx)
+{
+ SnowContext *s = avctx->priv_data;
+
+ common_end(s);
+ av_free(avctx->stats_out);
+
+ return 0;
+}
+
+static int decode_init(AVCodecContext *avctx)
+{
+ SnowContext *s = avctx->priv_data;
+ int block_size;
+
+ avctx->pix_fmt= PIX_FMT_YUV420P;
+
+ common_init(avctx);
+
+ block_size = MB_SIZE >> s->block_max_depth;
+ slice_buffer_init(&s->sb, s->plane[0].height, (block_size) + (s->spatial_decomposition_count * (s->spatial_decomposition_count + 3)) + 1, s->plane[0].width, s->spatial_dwt_buffer);
+
+ return 0;
+}
+
+static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size){
+ SnowContext *s = avctx->priv_data;
+ RangeCoder * const c= &s->c;
+ int bytes_read;
+ AVFrame *picture = data;
+ int level, orientation, plane_index;
+
+ ff_init_range_decoder(c, buf, buf_size);
+ ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
+
+ s->current_picture.pict_type= FF_I_TYPE; //FIXME I vs. P
+ decode_header(s);
+ if(!s->block) alloc_blocks(s);
+
+ frame_start(s);
+ //keyframe flag dupliaction mess FIXME
+ if(avctx->debug&FF_DEBUG_PICT_INFO)
+ av_log(avctx, AV_LOG_ERROR, "keyframe:%d qlog:%d\n", s->keyframe, s->qlog);
+
+ decode_blocks(s);
+
+ 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_dwt_buffer, plane_index, 1);
+
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ int v= s->current_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;
+ }
+ }
+}
+
+{ START_TIMER
+ for(level=0; level<s->spatial_decomposition_count; level++){
+ for(orientation=level ? 1 : 0; orientation<4; orientation++){
+ SubBand *b= &p->band[level][orientation];
+ unpack_coeffs(s, b, b->parent, orientation);
+ }
+ }
+ STOP_TIMER("unpack coeffs");
+}
+
+{START_TIMER
+ const int mb_h= s->b_height << s->block_max_depth;
+ const int block_size = MB_SIZE >> s->block_max_depth;
+ const int block_w = plane_index ? block_size/2 : block_size;
+ int mb_y;
+ dwt_compose_t 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_w*mb_y;
+ int slice_h = block_w*(mb_y+1);
+ if (!(s->keyframe || s->avctx->debug&512)){
+ slice_starty = FFMAX(0, slice_starty - (block_w >> 1));
+ slice_h -= (block_w >> 1);
+ }
+
+ {
+ START_TIMER
+ for(level=0; level<s->spatial_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_w * our_mb_start) >> (s->spatial_decomposition_count - level)) + s->spatial_decomposition_count - level + extra: 0);
+ end_y = (((block_w * 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_w >> (1+s->spatial_decomposition_count - level)));
+ end_y = FFMAX(0, end_y - (block_w >> (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->buf, correlate_band->stride, 1, 0, correlate_start_y, correlate_end_y);
+ dequantize_slice_buffered(s, &s->sb, correlate_band, correlate_band->buf, correlate_band->stride, start_y, end_y);
+ }
+ else
+ decode_subband_slice_buffered(s, b, &s->sb, start_y, end_y, decode_state[level][orientation]);
+ }
+ }
+ }
+ STOP_TIMER("decode_subband_slice");
+ }
+
+{ START_TIMER
+ for(; yd<slice_h; yd+=4){
+ ff_spatial_idwt_buffered_slice(&s->dsp, cs, &s->sb, w, h, 1, s->spatial_decomposition_type, s->spatial_decomposition_count, yd);
+ }
+ STOP_TIMER("idwt slice");}
+
+
+ if(s->qlog == LOSSLESS_QLOG){
+ for(; yq<slice_h && yq<h; yq++){
+ DWTELEM * line = slice_buffer_get_line(&s->sb, yq);
+ for(x=0; x<w; x++){
+ line[x] <<= FRAC_BITS;
+ }
+ }
+ }
+
+ predict_slice_buffered(s, &s->sb, s->spatial_dwt_buffer, plane_index, 1, mb_y);
+
+ y = FFMIN(p->height, slice_starty);
+ end_y = FFMIN(p->height, slice_h);
+ while(y < end_y)
+ slice_buffer_release(&s->sb, y++);
+ }
+
+ slice_buffer_flush(&s->sb);
+
+STOP_TIMER("idwt + predict_slices")}
+ }
+
+ emms_c();
+
+ if(s->last_picture[s->max_ref_frames-1].data[0])
+ avctx->release_buffer(avctx, &s->last_picture[s->max_ref_frames-1]);
+
+if(!(s->avctx->debug&2048))
+ *picture= s->current_picture;
+else
+ *picture= s->mconly_picture;
+
+ *data_size = sizeof(AVFrame);
+
+ 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 int decode_end(AVCodecContext *avctx)
+{
+ SnowContext *s = avctx->priv_data;
+
+ slice_buffer_destroy(&s->sb);
+
+ common_end(s);
+
+ return 0;
+}
+
+AVCodec snow_decoder = {
+ "snow",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_SNOW,
+ sizeof(SnowContext),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame,
+ 0 /*CODEC_CAP_DR1*/ /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
+ NULL
+};
+
+#ifdef CONFIG_ENCODERS
+AVCodec snow_encoder = {
+ "snow",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_SNOW,
+ sizeof(SnowContext),
+ encode_init,
+ encode_frame,
+ encode_end,
+};
+#endif
+
+
+#if 0
+#undef malloc
+#undef free
+#undef printf
+
+int main(){
+ int width=256;
+ int height=256;
+ int buffer[2][width*height];
+ SnowContext s;
+ int i;
+ s.spatial_decomposition_count=6;
+ s.spatial_decomposition_type=1;
+
+ printf("testing 5/3 DWT\n");
+ for(i=0; i<width*height; i++)
+ buffer[0][i]= buffer[1][i]= random()%54321 - 12345;
+
+ ff_spatial_dwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
+ ff_spatial_idwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
+
+ for(i=0; i<width*height; i++)
+ if(buffer[0][i]!= buffer[1][i]) printf("fsck: %d %d %d\n",i, buffer[0][i], buffer[1][i]);
+
+ printf("testing 9/7 DWT\n");
+ s.spatial_decomposition_type=0;
+ for(i=0; i<width*height; i++)
+ buffer[0][i]= buffer[1][i]= random()%54321 - 12345;
+
+ ff_spatial_dwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
+ ff_spatial_idwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
+
+ for(i=0; i<width*height; i++)
+ if(FFABS(buffer[0][i] - buffer[1][i])>20) printf("fsck: %d %d %d\n",i, buffer[0][i], buffer[1][i]);
+
+#if 0
+ printf("testing AC coder\n");
+ memset(s.header_state, 0, sizeof(s.header_state));
+ ff_init_range_encoder(&s.c, buffer[0], 256*256);
+ ff_init_cabac_states(&s.c, ff_h264_lps_range, ff_h264_mps_state, ff_h264_lps_state, 64);
+
+ for(i=-256; i<256; i++){
+START_TIMER
+ put_symbol(&s.c, s.header_state, i*i*i/3*FFABS(i), 1);
+STOP_TIMER("put_symbol")
+ }
+ ff_rac_terminate(&s.c);
+
+ memset(s.header_state, 0, sizeof(s.header_state));
+ ff_init_range_decoder(&s.c, buffer[0], 256*256);
+ ff_init_cabac_states(&s.c, ff_h264_lps_range, ff_h264_mps_state, ff_h264_lps_state, 64);
+
+ for(i=-256; i<256; i++){
+ int j;
+START_TIMER
+ j= get_symbol(&s.c, s.header_state, 1);
+STOP_TIMER("get_symbol")
+ if(j!=i*i*i/3*FFABS(i)) printf("fsck: %d != %d\n", i, j);
+ }
+#endif
+{
+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++){
+ for(orientation=level ? 1 : 0; orientation<4; orientation++){
+ int w= width >> (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(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
+ for(y=0; y<height; y++){
+ for(x=0; x<width; x++){
+ int64_t d= buffer[0][x + y*width];
+ error += d*d;
+ if(FFABS(width/2-x)<9 && FFABS(height/2-y)<9 && level==2) printf("%8"PRId64" ", d);
+ }
+ if(FFABS(height/2-y)<9 && level==2) printf("\n");
+ }
+ error= (int)(sqrt(error)+0.5);
+ errors[level][orientation]= error;
+ if(g) g=ff_gcd(g, error);
+ else g= error;
+ }
+ }
+ printf("static int const visual_weight[][4]={\n");
+ for(level=0; level<s.spatial_decomposition_count; level++){
+ printf(" {");
+ for(orientation=0; orientation<4; orientation++){
+ printf("%8"PRId64",", errors[level][orientation]/g);
+ }
+ printf("},\n");
+ }
+ printf("};\n");
+ {
+ int level=2;
+ int orientation=3;
+ int w= width >> (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);
+#if 1
+ for(y=0; y<height; y++){
+ for(x=0; x<width; x++){
+ int tab[4]={0,2,3,1};
+ buffer[0][x+width*y]= 256*256*tab[(x&1) + 2*(y&1)];
+ }
+ }
+ ff_spatial_dwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
+#else
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ buf[x + y*stride ]=169;
+ buf[x + y*stride-w]=64;
+ }
+ }
+ ff_spatial_idwt(buffer[0], width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
+#endif
+ for(y=0; y<height; y++){
+ for(x=0; x<width; x++){
+ int64_t d= buffer[0][x + y*width];
+ error += d*d;
+ if(FFABS(width/2-x)<9 && FFABS(height/2-y)<9) printf("%8"PRId64" ", d);
+ }
+ if(FFABS(height/2-y)<9) printf("\n");
+ }
+ }
+
+}
+ return 0;
+}
+#endif
+
diff --git a/contrib/ffmpeg/libavcodec/snow.h b/contrib/ffmpeg/libavcodec/snow.h
new file mode 100644
index 000000000..f7cee131a
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/snow.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
+ * Copyright (C) 2006 Robert Edele <yartrebo@earthlink.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
+ */
+
+#ifndef _SNOW_H
+#define _SNOW_H
+
+#include "dsputil.h"
+
+#define MID_STATE 128
+
+#define MAX_DECOMPOSITIONS 8
+#define MAX_PLANES 4
+#define QSHIFT 5
+#define QROOT (1<<QSHIFT)
+#define LOSSLESS_QLOG -128
+#define FRAC_BITS 8
+#define MAX_REF_FRAMES 8
+
+#define LOG2_OBMC_MAX 8
+#define OBMC_MAX (1<<(LOG2_OBMC_MAX))
+
+#define DWT_97 0
+#define DWT_53 1
+#define DWT_X 2
+
+/** Used to minimize the amount of memory used in order to optimize cache performance. **/
+struct slice_buffer_s {
+ DWTELEM * * line; ///< For use by idwt and predict_slices.
+ DWTELEM * * data_stack; ///< Used for internal purposes.
+ int data_stack_top;
+ int line_count;
+ int line_width;
+ int data_count;
+ DWTELEM * base_buffer; ///< Buffer that this structure is caching.
+};
+
+#define liftS lift
+#define lift5 lift
+#if 1
+#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
+#elif 0
+#define W_AM 55
+#define W_AO 16
+#define W_AS 5
+
+#define W_BM 3
+#define W_BO 32
+#define W_BS 6
+
+#define W_CM 127
+#define W_CO 64
+#define W_CS 7
+
+#define W_DM 7
+#define W_DO 8
+#define W_DS 4
+#elif 0
+#define W_AM 97
+#define W_AO 32
+#define W_AS 6
+
+#define W_BM 63
+#define W_BO 512
+#define W_BS 10
+
+#define W_CM 13
+#define W_CO 8
+#define W_CS 4
+
+#define W_DM 15
+#define W_DO 16
+#define W_DS 5
+
+#else
+
+#define W_AM 203
+#define W_AO 64
+#define W_AS 7
+
+#define W_BM 217
+#define W_BO 2048
+#define W_BS 12
+
+#define W_CM 113
+#define W_CO 64
+#define W_CS 7
+
+#define W_DM 227
+#define W_DO 128
+#define W_DS 9
+#endif
+
+extern void ff_snow_vertical_compose97i(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, DWTELEM *b3, DWTELEM *b4, DWTELEM *b5, int width);
+extern void ff_snow_horizontal_compose97i(DWTELEM *b, int width);
+extern void ff_snow_inner_add_yblock(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);
+
+#ifdef CONFIG_SNOW_ENCODER
+int w53_32_c(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h);
+int w97_32_c(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h);
+#else
+static int w53_32_c(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {assert (0);}
+static int w97_32_c(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {assert (0);}
+#endif
+
+/* C bits used by mmx/sse2/altivec */
+
+static always_inline void snow_interleave_line_header(int * i, int width, DWTELEM * low, DWTELEM * high){
+ (*i) = (width) - 2;
+
+ if (width & 1){
+ low[(*i)+1] = low[((*i)+1)>>1];
+ (*i)--;
+ }
+}
+
+static always_inline void snow_interleave_line_footer(int * i, DWTELEM * low, DWTELEM * high){
+ for (; (*i)>=0; (*i)-=2){
+ low[(*i)+1] = high[(*i)>>1];
+ low[*i] = low[(*i)>>1];
+ }
+}
+
+static always_inline void snow_horizontal_compose_lift_lead_out(int i, DWTELEM * dst, DWTELEM * src, DWTELEM * ref, int width, int w, int lift_high, int mul, int add, int shift){
+ for(; i<w; i++){
+ dst[i] = src[i] - ((mul * (ref[i] + ref[i + 1]) + add) >> shift);
+ }
+
+ if((width^lift_high)&1){
+ dst[w] = src[w] - ((mul * 2 * ref[w] + add) >> shift);
+ }
+}
+
+static always_inline void snow_horizontal_compose_liftS_lead_out(int i, DWTELEM * dst, DWTELEM * src, DWTELEM * ref, int width, int w){
+ for(; i<w; i++){
+ dst[i] = src[i] - (((-(ref[i] + ref[(i+1)])+W_BO) - 4 * src[i]) >> W_BS);
+ }
+
+ if(width&1){
+ dst[w] = src[w] - (((-2 * ref[w] + W_BO) - 4 * src[w]) >> W_BS);
+ }
+}
+
+#endif
diff --git a/contrib/ffmpeg/libavcodec/sonic.c b/contrib/ffmpeg/libavcodec/sonic.c
new file mode 100644
index 000000000..2f798cc03
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/sonic.c
@@ -0,0 +1,981 @@
+/*
+ * Simple free lossless/lossy audio codec
+ * 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
+ */
+#include "avcodec.h"
+#include "bitstream.h"
+#include "golomb.h"
+
+/**
+ * @file sonic.c
+ * Simple free lossless/lossy audio codec
+ * Based on Paul Francis Harrison's Bonk (http://www.logarithmic.net/pfh/bonk)
+ * Written and designed by Alex Beregszaszi
+ *
+ * TODO:
+ * - CABAC put/get_symbol
+ * - independent quantizer for channels
+ * - >2 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 {
+ 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;
+}
+
+#ifdef CONFIG_ENCODERS
+// 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);
+}
+#endif /* CONFIG_ENCODERS */
+
+static int samplerate_table[] =
+ { 44100, 22050, 11025, 96000, 48000, 32000, 24000, 16000, 8000 };
+
+#ifdef CONFIG_ENCODERS
+
+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 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 == 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 = av_mallocz(4* s->num_taps*s->channels);
+ if (!s->tail)
+ return -1;
+ s->tail_size = s->num_taps*s->channels;
+
+ 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 -ENOMEM;
+ avctx->coded_frame->key_frame = 1;
+ avctx->frame_size = s->block_align*s->downsampling;
+
+ return 0;
+}
+
+static 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,
+ uint8_t *buf, int buf_size, void *data)
+{
+ SonicContext *s = avctx->priv_data;
+ PutBitContext pb;
+ int i, j, ch, quant = 0, x = 0;
+ short *samples = data;
+
+ init_put_bits(&pb, buf, buf_size*8);
+
+ // 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 > 65535)
+ quant = 65535;
+
+ 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);
+ return (put_bits_count(&pb)+7)/8;
+}
+#endif //CONFIG_ENCODERS
+
+#ifdef CONFIG_DECODERS
+static 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;
+
+ 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);
+ 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);
+
+ return 0;
+}
+
+static 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 *data_size,
+ uint8_t *buf, int buf_size)
+{
+ SonicContext *s = avctx->priv_data;
+ GetBitContext gb;
+ int i, quant, ch, j;
+ short *samples = data;
+
+ if (buf_size == 0) return 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++)
+ {
+ if (s->int_samples[i] > 32767)
+ samples[i] = 32767;
+ else if (s->int_samples[i] < -32768)
+ samples[i] = -32768;
+ else
+ samples[i] = s->int_samples[i];
+ }
+
+ align_get_bits(&gb);
+
+ *data_size = s->frame_size * 2;
+
+ return (get_bits_count(&gb)+7)/8;
+}
+#endif
+
+#ifdef CONFIG_ENCODERS
+AVCodec sonic_encoder = {
+ "sonic",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_SONIC,
+ sizeof(SonicContext),
+ sonic_encode_init,
+ sonic_encode_frame,
+ sonic_encode_close,
+ NULL,
+};
+
+AVCodec sonic_ls_encoder = {
+ "sonicls",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_SONIC_LS,
+ sizeof(SonicContext),
+ sonic_encode_init,
+ sonic_encode_frame,
+ sonic_encode_close,
+ NULL,
+};
+#endif
+
+#ifdef CONFIG_DECODERS
+AVCodec sonic_decoder = {
+ "sonic",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_SONIC,
+ sizeof(SonicContext),
+ sonic_decode_init,
+ NULL,
+ sonic_decode_close,
+ sonic_decode_frame,
+};
+#endif
diff --git a/contrib/ffmpeg/libavcodec/sp5x.h b/contrib/ffmpeg/libavcodec/sp5x.h
new file mode 100644
index 000000000..0d0d3551f
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/sp5x.h
@@ -0,0 +1,332 @@
+/*
+ * 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 SP5X_H
+#define SP5X_H
+
+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 }
+};
+
+#if 0
+/* 4NF-M, not ZigZag */
+static const uint8_t sp5x_quant_table_orig[18][64] =
+{
+ /* index 0, Q50 */
+ { 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 },
+ { 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 },
+
+ /* index 1, Q70 */
+ { 10, 7, 6, 10, 14, 24, 31, 37, 7, 7, 8, 11, 16, 35, 36, 33,
+ 8, 8, 10, 14, 24, 34, 41, 34, 8, 10, 13, 17, 31, 52, 48, 37,
+ 11, 13, 22, 34, 41, 65, 62, 46, 14, 21, 33, 38, 49, 62, 68, 55,
+ 29, 38, 47, 52, 62, 73, 72, 61, 43, 55, 57, 59, 67, 60, 62, 59 },
+ { 10, 11, 14, 28, 59, 59, 59, 59, 11, 13, 16, 40, 59, 59, 59, 59,
+ 14, 16, 34, 59, 59, 59, 59, 59, 28, 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 },
+
+ /* index 2, Q80 */
+ { 6, 4, 4, 6, 10, 16, 20, 24, 5, 5, 6, 8, 10, 23, 24, 22,
+ 6, 5, 6, 10, 16, 23, 28, 22, 6, 7, 9, 12, 20, 35, 32, 25,
+ 7, 9, 15, 22, 27, 44, 41, 31, 10, 14, 22, 26, 32, 42, 45, 37,
+ 20, 26, 31, 35, 41, 48, 48, 40, 29, 37, 38, 39, 45, 40, 41, 40 },
+ { 7, 7, 10, 19, 40, 40, 40, 40, 7, 8, 10, 26, 40, 40, 40, 40,
+ 10, 10, 22, 40, 40, 40, 40, 40, 19, 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 },
+
+ /* index 3, Q85 */
+ { 5, 3, 3, 5, 7, 12, 15, 18, 4, 4, 4, 6, 8, 17, 18, 17,
+ 4, 4, 5, 7, 12, 17, 21, 17, 4, 5, 7, 9, 15, 26, 24, 19,
+ 5, 7, 11, 17, 20, 33, 31, 23, 7, 11, 17, 19, 24, 31, 34, 28,
+ 15, 19, 23, 26, 31, 36, 36, 30, 22, 28, 29, 29, 34, 30, 31, 30 },
+ { 5, 5, 7, 14, 30, 30, 30, 30, 5, 6, 8, 20, 30, 30, 30, 30,
+ 7, 8, 17, 30, 30, 30, 30, 30, 14, 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 },
+
+ /* index 4, Q90 */
+ { 3, 2, 2, 3, 5, 8, 10, 12, 2, 2, 3, 4, 5, 12, 12, 11,
+ 3, 3, 3, 5, 8, 11, 14, 11, 3, 3, 4, 6, 10, 17, 16, 12,
+ 4, 4, 7, 11, 14, 22, 21, 15, 5, 7, 11, 13, 16, 21, 23, 18,
+ 10, 13, 16, 17, 21, 24, 24, 20, 14, 18, 19, 20, 22, 20, 21, 20 },
+ { 3, 4, 5, 9, 20, 20, 20, 20, 4, 4, 5, 13, 20, 20, 20, 20,
+ 5, 5, 11, 20, 20, 20, 20, 20, 9, 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 },
+
+ /* index 5, Q60 */
+ { 13, 9, 8, 13, 19, 32, 41, 49, 10, 10, 11, 15, 21, 46, 48, 44,
+ 11, 10, 13, 19, 32, 46, 55, 45, 11, 14, 18, 23, 41, 70, 64, 50,
+ 14, 18, 30, 45, 54, 87, 82, 62, 19, 28, 44, 51, 65, 83, 90, 74,
+ 39, 51, 62, 70, 82, 97, 96, 81, 58, 74, 76, 78, 90, 80, 82, 79 },
+ { 14, 14, 19, 38, 79, 79, 79, 79, 14, 17, 21, 53, 79, 79, 79, 79,
+ 19, 21, 45, 79, 79, 79, 79, 79, 38, 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 },
+
+ /* index 6, Q25 */
+ { 32, 22, 20, 32, 48, 80,102,122, 24, 24, 28, 38, 52,116,120,110,
+ 28, 26, 32, 48, 80,114,138,112, 28, 34, 44, 58,102,174,160,124,
+ 36, 44, 74,112,136,218,206,154, 48, 70,110,128,162,208,226,184,
+ 98,128,156,174,206,242,240,202,144,184,190,196,224,200,206,198 },
+ { 34, 36, 48, 94,198,198,198,198, 36, 42, 52,132,198,198,198,198,
+ 48, 52,112,198,198,198,198,198, 94,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 },
+
+ /* index 7, Q95 */
+ { 2, 1, 1, 2, 2, 4, 5, 6, 1, 1, 1, 2, 3, 6, 6, 6,
+ 1, 1, 2, 2, 4, 6, 7, 6, 1, 2, 2, 3, 5, 9, 8, 6,
+ 2, 2, 4, 6, 7, 11, 10, 8, 2, 4, 6, 6, 8, 10, 11, 9,
+ 5, 6, 8, 9, 10, 12, 12, 10, 7, 9, 10, 10, 11, 10, 10, 10 },
+ { 2, 2, 2, 5, 10, 10, 10, 10, 2, 2, 3, 7, 10, 10, 10, 10,
+ 2, 3, 6, 10, 10, 10, 10, 10, 5, 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 },
+
+ /* index 8, Q93 */
+ { 2, 2, 1, 2, 3, 6, 7, 9, 2, 2, 2, 3, 4, 8, 8, 8,
+ 2, 2, 2, 3, 6, 8, 10, 8, 2, 2, 3, 4, 7, 12, 11, 9,
+ 3, 3, 5, 8, 10, 15, 14, 11, 3, 5, 8, 9, 11, 15, 16, 13,
+ 7, 9, 11, 12, 14, 17, 17, 14, 10, 13, 13, 14, 16, 14, 14, 14 },
+ { 2, 3, 3, 7, 14, 14, 14, 14, 3, 3, 4, 9, 14, 14, 14, 14,
+ 3, 4, 8, 14, 14, 14, 14, 14, 7, 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 }
+};
+#endif
+
+#endif /* SP5X_H */
diff --git a/contrib/ffmpeg/libavcodec/sparc/dsputil_vis.c b/contrib/ffmpeg/libavcodec/sparc/dsputil_vis.c
new file mode 100644
index 000000000..5e59ce776
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/sparc/dsputil_vis.c
@@ -0,0 +1,4090 @@
+/*
+ * dsputil_vis.c
+ * Copyright (C) 2003 David S. Miller <davem@redhat.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
+ */
+
+/* The *no_round* functions have been added by James A. Morrison, 2003,2004.
+ The vis code from libmpeg2 was adapted for ffmpeg by James A. Morrison.
+ */
+
+#include "config.h"
+
+#ifdef ARCH_SPARC
+
+#include <inttypes.h>
+#include <signal.h>
+#include <setjmp.h>
+
+#include "../dsputil.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 ATTR_ALIGN(alignd) __attribute__ ((aligned(alignd)))
+
+#define DUP4(x) {x, x, x, x}
+#define DUP8(x) {x, x, x, x, x, x, x, x}
+static const int16_t constants1[] ATTR_ALIGN(8) = DUP4 (1);
+static const int16_t constants2[] ATTR_ALIGN(8) = DUP4 (2);
+static const int16_t constants3[] ATTR_ALIGN(8) = DUP4 (3);
+static const int16_t constants6[] ATTR_ALIGN(8) = DUP4 (6);
+static const int8_t constants_fe[] ATTR_ALIGN(8) = DUP8 (0xfe);
+static const int8_t constants_7f[] ATTR_ALIGN(8) = DUP8 (0x7f);
+static const int8_t constants128[] ATTR_ALIGN(8) = DUP8 (128);
+static const int16_t constants256_512[] ATTR_ALIGN(8) =
+ {256, 512, 256, 512};
+static const int16_t constants256_1024[] ATTR_ALIGN(8) =
+ {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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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_avg_no_round_o_8_vis (uint8_t * dest, const uint8_t * _ref,
+ const int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+
+ 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_and(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_padd16(TMP6, TMP4, TMP4);
+ vis_st64(TMP4, dest[0]);
+ dest += stride;
+ vis_mul8x16(CONST_128, TMP0, TMP0);
+
+ vis_and(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_padd16(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_and(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_padd16(TMP6, TMP4, TMP4);
+ vis_st64(TMP4, dest[0]);
+ dest += stride;
+ vis_mul8x16(CONST_128, TMP0, TMP0);
+
+ vis_and(DST_0, REF_0, TMP6);
+
+ vis_and(TMP0, MASK_7f, TMP0);
+
+ vis_padd16(TMP6, TMP0, TMP4);
+ vis_st64(TMP4, dest[0]);
+}
+
+static void MC_put_no_round_x_16_vis (uint8_t * dest, const uint8_t * _ref,
+ const int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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_no_round_x_8_vis (uint8_t * dest, const uint8_t * _ref,
+ const int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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_no_round_y_16_vis (uint8_t * dest, const uint8_t * _ref,
+ const int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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_no_round_y_8_vis (uint8_t * dest, const uint8_t * _ref,
+ const int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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_no_round_xy_16_vis (uint8_t * dest, const uint8_t * _ref,
+ const int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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 int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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_no_round_xy_8_vis (uint8_t * dest, const uint8_t * _ref,
+ const int stride, int height)
+{
+ uint8_t *ref = (uint8_t *) _ref;
+ 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 no rounding code */
+
+static sigjmp_buf jmpbuf;
+static volatile sig_atomic_t canjump = 0;
+
+static void sigill_handler (int sig)
+{
+ if (!canjump) {
+ signal (sig, SIG_DFL);
+ raise (sig);
+ }
+
+ canjump = 0;
+ siglongjmp (jmpbuf, 1);
+}
+
+#define ACCEL_SPARC_VIS 1
+#define ACCEL_SPARC_VIS2 2
+
+static int vis_level ()
+{
+ int accel = 0;
+
+ signal (SIGILL, sigill_handler);
+ if (sigsetjmp (jmpbuf, 1)) {
+ signal (SIGILL, SIG_DFL);
+ return accel;
+ }
+
+ canjump = 1;
+
+ /* pdist %f0, %f0, %f0 */
+ __asm__ __volatile__(".word\t0x81b007c0");
+
+ canjump = 0;
+ accel |= ACCEL_SPARC_VIS;
+
+ if (sigsetjmp (jmpbuf, 1)) {
+ signal (SIGILL, SIG_DFL);
+ return accel;
+ }
+
+ canjump = 1;
+
+ /* edge8n %g0, %g0, %g0 */
+ __asm__ __volatile__(".word\t0x81b00020");
+
+ canjump = 0;
+ accel |= ACCEL_SPARC_VIS2;
+
+ signal (SIGILL, SIG_DFL);
+
+ return accel;
+}
+
+/* libavcodec initialization code */
+void dsputil_init_vis(DSPContext* c, AVCodecContext *avctx)
+{
+ /* VIS specific optimisations */
+ 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][0] = MC_avg_no_round_o_16_vis;
+ c->avg_no_rnd_pixels_tab[0][1] = MC_avg_no_round_x_16_vis;
+ c->avg_no_rnd_pixels_tab[0][2] = MC_avg_no_round_y_16_vis;
+ c->avg_no_rnd_pixels_tab[0][3] = MC_avg_no_round_xy_16_vis;
+
+ c->avg_no_rnd_pixels_tab[1][0] = MC_avg_no_round_o_8_vis;
+ c->avg_no_rnd_pixels_tab[1][1] = MC_avg_no_round_x_8_vis;
+ c->avg_no_rnd_pixels_tab[1][2] = MC_avg_no_round_y_8_vis;
+ c->avg_no_rnd_pixels_tab[1][3] = MC_avg_no_round_xy_8_vis;
+ }
+}
+
+#endif /* !(ARCH_SPARC) */
diff --git a/contrib/ffmpeg/libavcodec/sparc/vis.h b/contrib/ffmpeg/libavcodec/sparc/vis.h
new file mode 100644
index 000000000..d4a8ce092
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/sparc/vis.h
@@ -0,0 +1,327 @@
+/*
+ * vis.h
+ * Copyright (C) 2003 David S. Miller <davem@redhat.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
+ */
+
+/* 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.
+ */
+
+#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 void *vis_alignaddr(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(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)
diff --git a/contrib/ffmpeg/libavcodec/svq1.c b/contrib/ffmpeg/libavcodec/svq1.c
new file mode 100644
index 000000000..5e8616269
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/svq1.c
@@ -0,0 +1,1431 @@
+/*
+ *
+ * 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
+ *
+ * (SVQ1 Decoder)
+ * Ported to mplayer by Arpi <arpi@thot.banki.hu>
+ * Ported to libavcodec by Nick Kurshev <nickols_k@mail.ru>
+ *
+ * SVQ1 Encoder (c) 2004 Mike Melanson <melanson@pcisys.net>
+ */
+
+/**
+ * @file svq1.c
+ * Sorenson Vector Quantizer #1 (SVQ1) video codec.
+ * For more information of the SVQ1 algorithm, visit:
+ * http://www.pcisys.net/~melanson/codecs/
+ */
+
+
+//#define DEBUG_SVQ1
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+#include "bswap.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+extern const uint8_t 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;
+
+#define SVQ1_BLOCK_SKIP 0
+#define SVQ1_BLOCK_INTER 1
+#define SVQ1_BLOCK_INTER_4V 2
+#define SVQ1_BLOCK_INTRA 3
+
+typedef struct SVQ1Context {
+ MpegEncContext m; // needed for motion estimation, should not be used for anything else, the idea is to make the motion estimation eventually independant of MpegEncContext, so this will be removed then (FIXME/XXX)
+ AVCodecContext *avctx;
+ DSPContext dsp;
+ AVFrame picture;
+ AVFrame current_picture;
+ AVFrame last_picture;
+ PutBitContext pb;
+ GetBitContext gb;
+
+ PutBitContext reorder_pb[6]; //why ooh why this sick breadth first order, everything is slower and more complex
+
+ 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;
+} SVQ1Context;
+
+/* motion vector (prediction) */
+typedef struct svq1_pmv_s {
+ int x;
+ int y;
+} svq1_pmv_t;
+
+#include "svq1_cb.h"
+#include "svq1_vlc.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
+};
+
+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_bits (bitbuf, 1) == 0)\
+ break;\
+ /* add child nodes */\
+ list[n++] = list[i];\
+ list[n++] = list[i] + (((level & 1) ? pitch : 1) << ((level / 2) + 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_DO_CODEBOOK_INTRA()\
+ 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);\
+ }
+
+#define SVQ1_DO_CODEBOOK_NONINTRA()\
+ for (y=0; y < height; y++) {\
+ for (x=0; x < (width / 4); x++, codebook++) {\
+ n3 = dst[x];\
+ /* add mean value to vector */\
+ n1 = ((n3 & 0xFF00FF00) >> 8) + n4;\
+ n2 = (n3 & 0x00FF00FF) + n4;\
+ SVQ1_ADD_CODEBOOK()\
+ /* store result */\
+ dst[x] = (n1 << 8) | n2;\
+ }\
+ dst += (pitch / 4);\
+ }
+
+#define SVQ1_CALC_CODEBOOK_ENTRIES(cbook)\
+ codebook = (const uint32_t *) cbook[level];\
+ 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 + (mean >> 31)) << 16) | (mean & 0xFFFF);
+
+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)) {
+#ifdef DEBUG_SVQ1
+ av_log(s->avctx, AV_LOG_INFO, "Error (svq1_decode_block_intra): invalid vector: stages=%i level=%i\n",stages,level);
+#endif
+ return -1; /* 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(svq1_intra_codebooks);
+ SVQ1_DO_CODEBOOK_INTRA()
+ }
+ }
+
+ 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)) {
+#ifdef DEBUG_SVQ1
+ av_log(s->avctx, AV_LOG_INFO, "Error (svq1_decode_block_non_intra): invalid vector: stages=%i level=%i\n",stages,level);
+#endif
+ return -1; /* invalid vector */
+ }
+
+ mean = get_vlc2(bitbuf, svq1_inter_mean.table, 9, 3) - 256;
+
+ SVQ1_CALC_CODEBOOK_ENTRIES(svq1_inter_codebooks);
+ SVQ1_DO_CODEBOOK_NONINTRA()
+ }
+ return 0;
+}
+
+static int svq1_decode_motion_vector (GetBitContext *bitbuf, svq1_pmv_t *mv, svq1_pmv_t **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 -1;
+ else if(diff){
+ if(get_bits1(bitbuf)) diff= -diff;
+ }
+
+ /* add median of motion vector predictors and clip result */
+ if (i == 1)
+ mv->y = ((diff + mid_pred(pmv[0]->y, pmv[1]->y, pmv[2]->y)) << 26) >> 26;
+ else
+ mv->x = ((diff + mid_pred(pmv[0]->x, pmv[1]->x, pmv[2]->x)) << 26) >> 26;
+ }
+
+ 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 (MpegEncContext *s, GetBitContext *bitbuf,
+ uint8_t *current, uint8_t *previous, int pitch,
+ svq1_pmv_t *motion, int x, int y) {
+ uint8_t *src;
+ uint8_t *dst;
+ svq1_pmv_t mv;
+ svq1_pmv_t *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 != 0)
+ 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;
+
+#if 0
+ int w= (s->width+15)&~15;
+ int h= (s->height+15)&~15;
+ if(x + (mv.x >> 1)<0 || y + (mv.y >> 1)<0 || x + (mv.x >> 1) + 16 > w || y + (mv.y >> 1) + 16> h)
+ av_log(s->avctx, AV_LOG_INFO, "%d %d %d %d\n", x, y, x + (mv.x >> 1), y + (mv.y >> 1));
+#endif
+
+ src = &previous[(x + (mv.x >> 1)) + (y + (mv.y >> 1))*pitch];
+ dst = current;
+
+ s->dsp.put_pixels_tab[0][((mv.y & 1) << 1) | (mv.x & 1)](dst,src,pitch,16);
+
+ return 0;
+}
+
+static int svq1_motion_inter_4v_block (MpegEncContext *s, GetBitContext *bitbuf,
+ uint8_t *current, uint8_t *previous, int pitch,
+ svq1_pmv_t *motion,int x, int y) {
+ uint8_t *src;
+ uint8_t *dst;
+ svq1_pmv_t mv;
+ svq1_pmv_t *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 != 0)
+ 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 != 0)
+ 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 != 0)
+ 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 != 0)
+ 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;
+
+ ///XXX /FIXME cliping or padding?
+ if(y + (mvy >> 1)<0)
+ mvy= 0;
+ if(x + (mvx >> 1)<0)
+ mvx= 0;
+
+#if 0
+ int w= (s->width+15)&~15;
+ int h= (s->height+15)&~15;
+ if(x + (mvx >> 1)<0 || y + (mvy >> 1)<0 || x + (mvx >> 1) + 8 > w || y + (mvy >> 1) + 8> h)
+ av_log(s->avctx, AV_LOG_INFO, "%d %d %d %d\n", x, y, x + (mvx >> 1), y + (mvy >> 1));
+#endif
+ src = &previous[(x + (mvx >> 1)) + (y + (mvy >> 1))*pitch];
+ dst = current;
+
+ s->dsp.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 (MpegEncContext *s, GetBitContext *bitbuf,
+ uint8_t *current, uint8_t *previous, int pitch,
+ svq1_pmv_t *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 (s, bitbuf, current, previous, pitch, motion, x, y);
+
+ if (result != 0)
+ {
+#ifdef DEBUG_SVQ1
+ av_log(s->avctx, AV_LOG_INFO, "Error in svq1_motion_inter_block %i\n",result);
+#endif
+ break;
+ }
+ result = svq1_decode_block_non_intra (bitbuf, current, pitch);
+ break;
+
+ case SVQ1_BLOCK_INTER_4V:
+ result = svq1_motion_inter_4v_block (s, bitbuf, current, previous, pitch, motion, x, y);
+
+ if (result != 0)
+ {
+#ifdef DEBUG_SVQ1
+ av_log(s->avctx, AV_LOG_INFO, "Error in svq1_motion_inter_4v_block %i\n",result);
+#endif
+ 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;
+}
+
+/* standard video sizes */
+static struct { int width; int height; } svq1_frame_size_table[8] = {
+ { 160, 120 }, { 128, 96 }, { 176, 144 }, { 352, 288 },
+ { 704, 576 }, { 240, 180 }, { 320, 240 }, { -1, -1 }
+};
+
+static uint16_t svq1_packet_checksum (uint8_t *data, int length, int value) {
+ int i;
+
+ for (i=0; i < length; i++) {
+ value = checksum_table[data[i] ^ (value >> 8)] ^ ((value & 0xFF) << 8);
+ }
+
+ return value;
+}
+
+#if 0 /* unused, remove? */
+static uint16_t svq1_component_checksum (uint16_t *pixels, int pitch,
+ int width, int height, int value) {
+ int x, y;
+
+ for (y=0; y < height; y++) {
+ for (x=0; x < width; x++) {
+ value = checksum_table[pixels[x] ^ (value >> 8)] ^ ((value & 0xFF) << 8);
+ }
+
+ pixels += pitch;
+ }
+
+ return value;
+}
+#endif
+
+#ifdef CONFIG_DECODERS
+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 (GetBitContext *bitbuf,MpegEncContext *s) {
+ int frame_size_code;
+ int temporal_reference;
+
+ temporal_reference = get_bits (bitbuf, 8);
+
+ /* frame type */
+ s->pict_type= get_bits (bitbuf, 2)+1;
+ if(s->pict_type==4)
+ return -1;
+
+ if (s->pict_type == I_TYPE) {
+
+ /* unknown fields */
+ if (s->f_code == 0x50 || s->f_code == 0x60) {
+ int csum = get_bits (bitbuf, 16);
+
+ csum = svq1_packet_checksum ((uint8_t *)bitbuf->buffer, bitbuf->size_in_bits>>3, csum);
+
+// av_log(s->avctx, AV_LOG_INFO, "%s checksum (%02x) for packet data\n",
+// (csum == 0) ? "correct" : "incorrect", csum);
+ }
+
+ if ((s->f_code ^ 0x10) >= 0x50) {
+ uint8_t msg[256];
+
+ svq1_parse_string (bitbuf, msg);
+
+ av_log(s->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) */
+ s->width = get_bits (bitbuf, 12);
+ s->height = get_bits (bitbuf, 12);
+
+ if (!s->width || !s->height)
+ return -1;
+ } else {
+ /* get width, height from table */
+ s->width = svq1_frame_size_table[frame_size_code].width;
+ s->height = svq1_frame_size_table[frame_size_code].height;
+ }
+ }
+
+ /* unknown fields */
+ if (get_bits (bitbuf, 1) == 1) {
+ 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 -1;
+ }
+
+ if (get_bits (bitbuf, 1) == 1) {
+ skip_bits1 (bitbuf);
+ skip_bits (bitbuf, 4);
+ skip_bits1 (bitbuf);
+ skip_bits (bitbuf, 2);
+
+ while (get_bits (bitbuf, 1) == 1) {
+ skip_bits (bitbuf, 8);
+ }
+ }
+
+ return 0;
+}
+
+static int svq1_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ MpegEncContext *s=avctx->priv_data;
+ uint8_t *current, *previous;
+ int result, i, x, y, width, height;
+ AVFrame *pict = data;
+
+ /* initialize bit buffer */
+ init_get_bits(&s->gb,buf,buf_size*8);
+
+ /* decode frame header */
+ s->f_code = get_bits (&s->gb, 22);
+
+ if ((s->f_code & ~0x70) || !(s->f_code & 0x60))
+ return -1;
+
+ /* swap some header bytes (why?) */
+ if (s->f_code != 0x20) {
+ uint32_t *src = (uint32_t *) (buf + 4);
+
+ for (i=0; i < 4; i++) {
+ src[i] = ((src[i] << 16) | (src[i] >> 16)) ^ src[7 - i];
+ }
+ }
+
+ result = svq1_decode_frame_header (&s->gb, s);
+
+ if (result != 0)
+ {
+#ifdef DEBUG_SVQ1
+ av_log(s->avctx, AV_LOG_INFO, "Error in svq1_decode_frame_header %i\n",result);
+#endif
+ return result;
+ }
+
+ //FIXME this avoids some confusion for "B frames" without 2 references
+ //this should be removed after libavcodec can handle more flexible picture types & ordering
+ if(s->pict_type==B_TYPE && s->last_picture_ptr==NULL) return buf_size;
+
+ if(avctx->hurry_up && s->pict_type==B_TYPE) return buf_size;
+ if( (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type==B_TYPE)
+ ||(avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type!=I_TYPE)
+ || avctx->skip_frame >= AVDISCARD_ALL)
+ return buf_size;
+
+ if(MPV_frame_start(s, avctx) < 0)
+ return -1;
+
+ /* decode y, u and v components */
+ for (i=0; i < 3; i++) {
+ int linesize;
+ if (i == 0) {
+ width = (s->width+15)&~15;
+ height = (s->height+15)&~15;
+ linesize= s->linesize;
+ } else {
+ if(s->flags&CODEC_FLAG_GRAY) break;
+ width = (s->width/4+15)&~15;
+ height = (s->height/4+15)&~15;
+ linesize= s->uvlinesize;
+ }
+
+ current = s->current_picture.data[i];
+
+ if(s->pict_type==B_TYPE){
+ previous = s->next_picture.data[i];
+ }else{
+ previous = s->last_picture.data[i];
+ }
+
+ if (s->pict_type == I_TYPE) {
+ /* keyframe */
+ for (y=0; y < height; y+=16) {
+ for (x=0; x < width; x+=16) {
+ result = svq1_decode_block_intra (&s->gb, &current[x], linesize);
+ if (result != 0)
+ {
+//#ifdef DEBUG_SVQ1
+ av_log(s->avctx, AV_LOG_INFO, "Error in svq1_decode_block %i (keyframe)\n",result);
+//#endif
+ return result;
+ }
+ }
+ current += 16*linesize;
+ }
+ } else {
+ svq1_pmv_t pmv[width/8+3];
+ /* delta frame */
+ memset (pmv, 0, ((width / 8) + 3) * sizeof(svq1_pmv_t));
+
+ for (y=0; y < height; y+=16) {
+ for (x=0; x < width; x+=16) {
+ result = svq1_decode_delta_block (s, &s->gb, &current[x], previous,
+ linesize, pmv, x, y);
+ if (result != 0)
+ {
+#ifdef DEBUG_SVQ1
+ av_log(s->avctx, AV_LOG_INFO, "Error in svq1_decode_delta_block %i\n",result);
+#endif
+ return result;
+ }
+ }
+
+ pmv[0].x =
+ pmv[0].y = 0;
+
+ current += 16*linesize;
+ }
+ }
+ }
+
+ *pict = *(AVFrame*)&s->current_picture;
+
+
+ MPV_frame_end(s);
+
+ *data_size=sizeof(AVFrame);
+ return buf_size;
+}
+
+static int svq1_decode_init(AVCodecContext *avctx)
+{
+ MpegEncContext *s = avctx->priv_data;
+ int i;
+
+ MPV_decode_defaults(s);
+
+ s->avctx = avctx;
+ s->width = (avctx->width+3)&~3;
+ s->height = (avctx->height+3)&~3;
+ s->codec_id= avctx->codec->id;
+ avctx->pix_fmt = PIX_FMT_YUV410P;
+ avctx->has_b_frames= 1; // not true, but DP frames and these behave like unidirectional b frames
+ s->flags= avctx->flags;
+ if (MPV_common_init(s) < 0) return -1;
+
+ init_vlc(&svq1_block_type, 2, 4,
+ &svq1_block_type_vlc[0][1], 2, 1,
+ &svq1_block_type_vlc[0][0], 2, 1, 1);
+
+ init_vlc(&svq1_motion_component, 7, 33,
+ &mvtab[0][1], 2, 1,
+ &mvtab[0][0], 2, 1, 1);
+
+ for (i = 0; i < 6; i++) {
+ init_vlc(&svq1_intra_multistage[i], 3, 8,
+ &svq1_intra_multistage_vlc[i][0][1], 2, 1,
+ &svq1_intra_multistage_vlc[i][0][0], 2, 1, 1);
+ init_vlc(&svq1_inter_multistage[i], 3, 8,
+ &svq1_inter_multistage_vlc[i][0][1], 2, 1,
+ &svq1_inter_multistage_vlc[i][0][0], 2, 1, 1);
+ }
+
+ init_vlc(&svq1_intra_mean, 8, 256,
+ &svq1_intra_mean_vlc[0][1], 4, 2,
+ &svq1_intra_mean_vlc[0][0], 4, 2, 1);
+
+ init_vlc(&svq1_inter_mean, 9, 512,
+ &svq1_inter_mean_vlc[0][1], 4, 2,
+ &svq1_inter_mean_vlc[0][0], 4, 2, 1);
+
+ return 0;
+}
+
+static int svq1_decode_end(AVCodecContext *avctx)
+{
+ MpegEncContext *s = avctx->priv_data;
+
+ MPV_common_end(s);
+ return 0;
+}
+#endif /* CONFIG_DECODERS */
+
+#ifdef CONFIG_ENCODERS
+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 == I_TYPE) {
+
+ /* 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 */
+
+ for (i = 0; i < 7; i++)
+ {
+ if ((svq1_frame_size_table[i].width == s->frame_width) &&
+ (svq1_frame_size_table[i].height == s->frame_height))
+ {
+ put_bits(&s->pb, 3, i);
+ break;
+ }
+ }
+
+ if (i == 7)
+ {
+ put_bits(&s->pb, 3, 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
+
+#if defined(HAVE_ALTIVEC)
+#undef vector
+#endif
+
+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 doenst need to be done multiple times
+ if(intra){
+ codebook_sum= svq1_intra_codebook_sum[level];
+ codebook= svq1_intra_codebooks[level];
+ mean_vlc= svq1_intra_mean_vlc;
+ multistage_vlc= 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= svq1_inter_codebooks[level];
+ mean_vlc= svq1_inter_mean_vlc + 256;
+ multistage_vlc= 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 -= ((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=0;
+ int diff, mean, score;
+
+ vector = codebook + stage*size*16 + i*size;
+
+ for(j=0; j<size; j++){
+ int v= vector[j];
+ sqr += (v - block[stage][j])*(v - block[stage][j]);
+ }
+ diff= block_sum[stage] - sum;
+ mean= (diff + (size>>1)) >> (level+3);
+ assert(mean >-300 && mean<300);
+ if(intra) mean= clip(mean, 0, 255);
+ else mean= clip(mean, -256, 255);
+ score= sqr - ((diff*(int64_t)diff)>>(level+3)); //FIXME 64bit slooow
+ if(score < best_vector_score){
+ best_vector_score= score;
+ best_vector[stage]= i;
+ best_vector_sum= sum;
+ best_vector_mean= mean;
+ }
+ }
+ assert(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){
+ assert((best_mean >= 0 && best_mean<256) || !intra);
+ assert(best_mean >= -256 && best_mean<256);
+ assert(best_count >=0 && best_count<7);
+ assert(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++){
+ assert(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];
+ 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 == P_TYPE){
+ 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.data[0]= ref_plane;
+ s->m.linesize=
+ s->m.last_picture.linesize[0]=
+ s->m.new_picture.linesize[0]=
+ s->m.current_picture.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++) {
+ uint8_t src[stride*16];
+
+ s->m.new_picture.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++) {
+ uint8_t src[stride*16];
+
+ 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[16*stride];
+
+ 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 == I_TYPE || (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 == P_TYPE){
+ const uint8_t *vlc= 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 == P_TYPE){
+ const uint8_t *vlc= svq1_block_type_vlc[SVQ1_BLOCK_INTER];
+ int mx, my, pred_x, pred_y, dxy;
+ int16_t *motion_ptr;
+
+ motion_ptr= 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];
+ assert(mx>=-32 && mx<=31);
+ assert(my>=-32 && my<=31);
+ assert(pred_x>=-32 && pred_x<=31);
+ assert(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->dsp.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= 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->dsp.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--){
+ ff_copy_bits(&s->pb, reorder_buffer[best][i], count[best][i]);
+ }
+ if(best==0){
+ s->dsp.put_pixels_tab[0][0](decoded, temp, stride, 16);
+ }
+ }
+ s->m.first_slice_line=0;
+ }
+ return 0;
+}
+
+static int svq1_encode_init(AVCodecContext *avctx)
+{
+ SVQ1Context * const s = avctx->priv_data;
+
+ dsputil_init(&s->dsp, avctx);
+ avctx->coded_frame= (AVFrame*)&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.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));
+ h263_encode_init(&s->m); //mv_penalty
+
+ return 0;
+}
+
+static int svq1_encode_frame(AVCodecContext *avctx, unsigned char *buf,
+ int buf_size, void *data)
+{
+ SVQ1Context * const s = avctx->priv_data;
+ AVFrame *pict = data;
+ AVFrame * const p= (AVFrame*)&s->picture;
+ AVFrame temp;
+ int i;
+
+ if(avctx->pix_fmt != PIX_FMT_YUV410P){
+ av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n");
+ return -1;
+ }
+
+ if(!s->current_picture.data[0]){
+ avctx->get_buffer(avctx, &s->current_picture);
+ avctx->get_buffer(avctx, &s->last_picture);
+ }
+
+ temp= s->current_picture;
+ s->current_picture= s->last_picture;
+ s->last_picture= temp;
+
+ init_put_bits(&s->pb, buf, buf_size);
+
+ *p = *pict;
+ p->pict_type = avctx->gop_size && avctx->frame_number % avctx->gop_size ? P_TYPE : I_TYPE;
+ p->key_frame = p->pict_type == I_TYPE;
+
+ 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;
+ }
+
+// align_put_bits(&s->pb);
+ while(put_bits_count(&s->pb) & 31)
+ put_bits(&s->pb, 1, 0);
+
+ flush_put_bits(&s->pb);
+
+ return (put_bits_count(&s->pb) / 8);
+}
+
+static 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);
+
+ for(i=0; i<3; i++){
+ av_freep(&s->motion_val8[i]);
+ av_freep(&s->motion_val16[i]);
+ }
+
+ return 0;
+}
+
+#endif //CONFIG_ENCODERS
+
+#ifdef CONFIG_DECODERS
+AVCodec svq1_decoder = {
+ "svq1",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_SVQ1,
+ sizeof(MpegEncContext),
+ svq1_decode_init,
+ NULL,
+ svq1_decode_end,
+ svq1_decode_frame,
+ CODEC_CAP_DR1,
+ .flush= ff_mpeg_flush,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV410P, -1},
+};
+#endif
+
+#ifdef CONFIG_ENCODERS
+
+AVCodec svq1_encoder = {
+ "svq1",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_SVQ1,
+ sizeof(SVQ1Context),
+ svq1_encode_init,
+ svq1_encode_frame,
+ svq1_encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV410P, -1},
+};
+
+#endif //CONFIG_ENCODERS
diff --git a/contrib/ffmpeg/libavcodec/svq1_cb.h b/contrib/ffmpeg/libavcodec/svq1_cb.h
new file mode 100644
index 000000000..a0748bd44
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/svq1_cb.h
@@ -0,0 +1,1580 @@
+/*
+ *
+ * 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
+ *
+ * Ported to mplayer by Arpi <arpi@thot.banki.hu>
+ * Ported to libavcodec by Nick Kurshev <nickols_k@mail.ru>
+ *
+ */
+
+/**
+ * @file svq1_cb.h
+ * svq1 code books.
+ */
+
+/* 6x16-entry codebook for inter-coded 4x2 vectors */
+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 */
+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 */
+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 */
+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 */
+static const int8_t* const svq1_inter_codebooks[6] = {
+ svq1_inter_codebook_4x2, svq1_inter_codebook_4x4,
+ svq1_inter_codebook_8x4, svq1_inter_codebook_8x8,
+ NULL, NULL,
+};
+
+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,
+ }
+};
+
+/* 6x16-entry codebook for intra-coded 4x2 vectors */
+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 */
+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 */
+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 */
+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 */
+static const int8_t* const svq1_intra_codebooks[6] = {
+ svq1_intra_codebook_4x2, svq1_intra_codebook_4x4,
+ svq1_intra_codebook_8x4, svq1_intra_codebook_8x8,
+ NULL, NULL,
+};
+
+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,
+ }
+};
diff --git a/contrib/ffmpeg/libavcodec/svq1_vlc.h b/contrib/ffmpeg/libavcodec/svq1_vlc.h
new file mode 100644
index 000000000..56463700f
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/svq1_vlc.h
@@ -0,0 +1,281 @@
+/*
+ * 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 SVQ1_VLC_H
+#define SVQ1_VLC_H
+
+/* values in this table range from 0..3; adjust retrieved value by +0 */
+static const uint8_t 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 */
+static const uint8_t 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 */
+static const uint8_t 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 */
+static const uint16_t svq1_intra_mean_vlc[256][2] = {
+ /* { code, length } */
+ { 0x37, 6 }, { 0x56, 7 }, { 0x1, 17 }, { 0x1, 20 },
+ { 0x2, 20 }, { 0x3, 20 }, { 0x0, 20 }, { 0x4, 20 },
+ { 0x5, 20 }, { 0x3, 19 }, { 0x15, 11 }, { 0x42, 9 },
+ { 0x14, 11 }, { 0x3, 14 }, { 0x2, 14 }, { 0x1, 15 },
+ { 0x1, 16 }, { 0x1, 12 }, { 0x2B, 10 }, { 0x18, 11 },
+ { 0xC, 11 }, { 0x41, 9 }, { 0x78, 8 }, { 0x6C, 8 },
+ { 0x55, 7 }, { 0xF, 4 }, { 0xE, 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 }, { 0xD, 10 }, { 0xE, 10 },
+ { 0xF, 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 }, { 0x9, 11 }, { 0x8, 11 }, { 0x7, 11 },
+ { 0x27, 10 }, { 0x5, 11 }, { 0xB, 11 }, { 0x6, 11 },
+ { 0x4, 11 }, { 0x3, 11 }, { 0x2, 11 }, { 0x1, 11 },
+ { 0xA, 11 }, { 0x16, 11 }, { 0x19, 11 }, { 0x17, 11 },
+ { 0xD, 11 }, { 0xE, 11 }, { 0xF, 11 }, { 0x10, 11 },
+ { 0x11, 11 }, { 0x12, 11 }, { 0x13, 11 }, { 0x1, 14 }
+};
+
+/* values in this table range from -256..255; adjust retrieved value by -256 */
+static const uint16_t 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 }, { 0xF, 11 },
+ { 0x10, 11 }, { 0x12, 11 }, { 0x13, 11 }, { 0x1B, 11 },
+ { 0x1A, 11 }, { 0xE, 10 }, { 0x13, 10 }, { 0xF, 10 },
+ { 0x10, 10 }, { 0x11, 10 }, { 0x12, 10 }, { 0xD, 9 },
+ { 0x14, 9 }, { 0x15, 9 }, { 0xC, 9 }, { 0x13, 9 },
+ { 0xF, 8 }, { 0xE, 8 }, { 0x10, 8 }, { 0x11, 8 },
+ { 0xC, 7 }, { 0x9, 7 }, { 0xA, 7 }, { 0x8, 6 },
+ { 0x9, 6 }, { 0x9, 5 }, { 0x8, 5 }, { 0x5, 4 },
+ { 0x1, 1 }, { 0x3, 3 }, { 0x7, 5 }, { 0x6, 5 },
+ { 0xB, 6 }, { 0xA, 6 }, { 0xE, 7 }, { 0xF, 7 },
+ { 0xB, 7 }, { 0xD, 7 }, { 0xB, 8 }, { 0xD, 8 },
+ { 0xC, 8 }, { 0xF, 9 }, { 0x10, 9 }, { 0x11, 9 },
+ { 0xE, 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 },
+ { 0xF, 22 }, { 0xE, 22 }, { 0xD, 22 }, { 0xC, 22 },
+ { 0xB, 22 }, { 0xA, 22 }, { 0x9, 22 }, { 0x8, 22 },
+ { 0x7, 22 }, { 0x6, 22 }, { 0x5, 22 }, { 0x4, 22 },
+ { 0x3, 22 }, { 0x2, 22 }, { 0x1, 22 }, { 0x0, 22 }
+};
+
+#endif
diff --git a/contrib/ffmpeg/libavcodec/svq3.c b/contrib/ffmpeg/libavcodec/svq3.c
new file mode 100644
index 000000000..edf3b6714
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/svq3.c
@@ -0,0 +1,1014 @@
+/*
+ * 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:
+ * ftp://ftp.mplayerhq.hu/MPlayer/samples/V-codecs/SVQ3/Vertical400kbit.sorenson3.mov
+ *
+ */
+
+/**
+ * @file svq3.c
+ * svq3 decoder.
+ */
+
+#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
+};
+
+
+static void svq3_luma_dc_dequant_idct_c(DCTELEM *block, int qp){
+ const int qmul= svq3_dequant_coeff[qp];
+#define stride 16
+ int i;
+ int temp[16];
+ static const int x_offset[4]={0, 1*stride, 4* stride, 5*stride};
+ static const int y_offset[4]={0, 2*stride, 8* stride, 10*stride};
+
+ for(i=0; i<4; i++){
+ const int offset= y_offset[i];
+ const int z0= 13*(block[offset+stride*0] + block[offset+stride*4]);
+ const int z1= 13*(block[offset+stride*0] - block[offset+stride*4]);
+ const int z2= 7* block[offset+stride*1] - 17*block[offset+stride*5];
+ const int z3= 17* block[offset+stride*1] + 7*block[offset+stride*5];
+
+ 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];
+
+ block[stride*0 +offset]= ((z0 + z3)*qmul + 0x80000)>>20;
+ block[stride*2 +offset]= ((z1 + z2)*qmul + 0x80000)>>20;
+ block[stride*8 +offset]= ((z1 - z2)*qmul + 0x80000)>>20;
+ block[stride*10+offset]= ((z0 - z3)*qmul + 0x80000)>>20;
+ }
+}
+#undef stride
+
+static void svq3_add_idct_c (uint8_t *dst, DCTELEM *block, int stride, int qp, int dc){
+ const int qmul= svq3_dequant_coeff[qp];
+ int i;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ 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]= cm[ dst[i + stride*0] + (((z0 + z3)*qmul + rr) >> 20) ];
+ dst[i + stride*1]= cm[ dst[i + stride*1] + (((z1 + z2)*qmul + rr) >> 20) ];
+ dst[i + stride*2]= cm[ dst[i + stride*2] + (((z1 - z2)*qmul + rr) >> 20) ];
+ dst[i + stride*3]= cm[ dst[i + stride*3] + (((z0 - z3)*qmul + rr) >> 20) ];
+ }
+}
+
+static void pred4x4_down_left_svq3_c(uint8_t *src, uint8_t *topright, int stride){
+ LOAD_TOP_EDGE
+ LOAD_LEFT_EDGE
+ const __attribute__((unused)) int unu0= t0;
+ const __attribute__((unused)) int unu1= l0;
+
+ 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 pred16x16_plane_svq3_c(uint8_t *src, int stride){
+ pred16x16_plane_compat_c(src, stride, 1);
+}
+
+static inline int svq3_decode_block (GetBitContext *gb, DCTELEM *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, vlc, limit;
+ 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 (vlc == INVALID_VLC)
+ return -1;
+
+ sign = (vlc & 0x1) - 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 < 16) {
+ 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 (MpegEncContext *s,
+ int x, int y, int width, int height,
+ int mx, int my, int dxy,
+ int thirdpel, int dir, int avg) {
+
+ const Picture *pic = (dir == 0) ? &s->last_picture : &s->next_picture;
+ 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)) {
+
+ if ((s->flags & CODEC_FLAG_EMU_EDGE)) {
+ emu = 1;
+ }
+
+ mx = clip (mx, -16, (s->h_edge_pos - width + 15));
+ my = clip (my, -16, (s->v_edge_pos - height + 15));
+ }
+
+ /* form component predictions */
+ dest = s->current_picture.data[0] + x + y*s->linesize;
+ src = pic->data[0] + mx + my*s->linesize;
+
+ if (emu) {
+ ff_emulated_edge_mc (s->edge_emu_buffer, src, s->linesize, (width + 1), (height + 1),
+ mx, my, s->h_edge_pos, s->v_edge_pos);
+ src = s->edge_emu_buffer;
+ }
+ if(thirdpel)
+ (avg ? s->dsp.avg_tpel_pixels_tab : s->dsp.put_tpel_pixels_tab)[dxy](dest, src, s->linesize, width, height);
+ else
+ (avg ? s->dsp.avg_pixels_tab : s->dsp.put_pixels_tab)[blocksize][dxy](dest, src, s->linesize, height);
+
+ if (!(s->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 = s->current_picture.data[i] + (x >> 1) + (y >> 1)*s->uvlinesize;
+ src = pic->data[i] + mx + my*s->uvlinesize;
+
+ if (emu) {
+ ff_emulated_edge_mc (s->edge_emu_buffer, src, s->uvlinesize, (width + 1), (height + 1),
+ mx, my, (s->h_edge_pos >> 1), (s->v_edge_pos >> 1));
+ src = s->edge_emu_buffer;
+ }
+ if(thirdpel)
+ (avg ? s->dsp.avg_tpel_pixels_tab : s->dsp.put_tpel_pixels_tab)[dxy](dest, src, s->uvlinesize, width, height);
+ else
+ (avg ? s->dsp.avg_pixels_tab : s->dsp.put_pixels_tab)[blocksize][dxy](dest, src, s->uvlinesize, height);
+ }
+ }
+}
+
+static inline int svq3_mc_dir (H264Context *h, int size, int mode, int dir, int avg) {
+
+ int i, j, k, mx, my, dx, dy, x, y;
+ MpegEncContext *const s = (MpegEncContext *) 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*s->mb_x+(j>>2)) + (4*s->mb_y+(i>>2))*h->b_stride;
+ int dxy;
+ x = 16*s->mb_x + j;
+ y = 16*s->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_picture.motion_val[0][b_xy][0]<<1;
+ my = s->next_picture.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 = clip (mx, extra_width - 6*x, h_edge_pos - 6*x);
+ my = 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 (&s->gb);
+ dx = svq3_get_se_golomb (&s->gb);
+
+ if (dx == INVALID_VLC || dy == INVALID_VLC) {
+ av_log(h->s.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) {
+ *(int32_t *) h->mv_cache[dir][scan8[k] + 1*8] = mv;
+
+ if (part_width == 8 && j < 8) {
+ *(int32_t *) h->mv_cache[dir][scan8[k] + 1 + 1*8] = mv;
+ }
+ }
+ if (part_width == 8 && j < 8) {
+ *(int32_t *) h->mv_cache[dir][scan8[k] + 1] = mv;
+ }
+ if (part_width == 4 || part_height == 4) {
+ *(int32_t *) h->mv_cache[dir][scan8[k]] = mv;
+ }
+ }
+
+ /* write back motion vectors */
+ fill_rectangle(s->current_picture.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 (H264Context *h, unsigned int mb_type) {
+ int i, j, k, m, dir, mode;
+ int cbp = 0;
+ uint32_t vlc;
+ int8_t *top, *left;
+ MpegEncContext *const s = (MpegEncContext *) h;
+ const int mb_xy = s->mb_x + s->mb_y*s->mb_stride;
+ const int b_xy = 4*s->mb_x + 4*s->mb_y*h->b_stride;
+
+ h->top_samples_available = (s->mb_y == 0) ? 0x33FF : 0xFFFF;
+ h->left_samples_available = (s->mb_x == 0) ? 0x5F5F : 0xFFFF;
+ h->topright_samples_available = 0xFFFF;
+
+ if (mb_type == 0) { /* SKIP */
+ if (s->pict_type == P_TYPE || s->next_picture.mb_type[mb_xy] == -1) {
+ svq3_mc_dir_part (s, 16*s->mb_x, 16*s->mb_y, 16, 16, 0, 0, 0, 0, 0, 0);
+
+ if (s->pict_type == B_TYPE) {
+ svq3_mc_dir_part (s, 16*s->mb_x, 16*s->mb_y, 16, 16, 0, 0, 0, 0, 1, 1);
+ }
+
+ mb_type = MB_TYPE_SKIP;
+ } else {
+ mb_type= FFMIN(s->next_picture.mb_type[mb_xy], 6);
+ if(svq3_mc_dir (h, mb_type, PREDICT_MODE, 0, 0) < 0)
+ return -1;
+ if(svq3_mc_dir (h, mb_type, PREDICT_MODE, 1, 1) < 0)
+ return -1;
+
+ mb_type = MB_TYPE_16x16;
+ }
+ } else if (mb_type < 8) { /* INTER */
+ if (h->thirdpel_flag && h->halfpel_flag == !get_bits (&s->gb, 1)) {
+ mode = THIRDPEL_MODE;
+ } else if (h->halfpel_flag && h->thirdpel_flag == !get_bits (&s->gb, 1)) {
+ mode = HALFPEL_MODE;
+ } else {
+ mode = FULLPEL_MODE;
+ }
+
+ /* fill caches */
+ /* note ref_cache should contain here:
+ ????????
+ ???11111
+ N??11111
+ N??11111
+ N??11111
+ N
+ */
+
+ for (m=0; m < 2; m++) {
+ if (s->mb_x > 0 && h->intra4x4_pred_mode[mb_xy - 1][0] != -1) {
+ for (i=0; i < 4; i++) {
+ *(uint32_t *) h->mv_cache[m][scan8[0] - 1 + i*8] = *(uint32_t *) s->current_picture.motion_val[m][b_xy - 1 + i*h->b_stride];
+ }
+ } else {
+ for (i=0; i < 4; i++) {
+ *(uint32_t *) h->mv_cache[m][scan8[0] - 1 + i*8] = 0;
+ }
+ }
+ if (s->mb_y > 0) {
+ memcpy (h->mv_cache[m][scan8[0] - 1*8], s->current_picture.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[mb_xy - s->mb_stride][4] == -1) ? PART_NOT_AVAILABLE : 1, 4);
+
+ if (s->mb_x < (s->mb_width - 1)) {
+ *(uint32_t *) h->mv_cache[m][scan8[0] + 4 - 1*8] = *(uint32_t *) s->current_picture.motion_val[m][b_xy - h->b_stride + 4];
+ h->ref_cache[m][scan8[0] + 4 - 1*8] =
+ (h->intra4x4_pred_mode[mb_xy - s->mb_stride + 1][0] == -1 ||
+ h->intra4x4_pred_mode[mb_xy - s->mb_stride][4] == -1) ? PART_NOT_AVAILABLE : 1;
+ }else
+ h->ref_cache[m][scan8[0] + 4 - 1*8] = PART_NOT_AVAILABLE;
+ if (s->mb_x > 0) {
+ *(uint32_t *) h->mv_cache[m][scan8[0] - 1 - 1*8] = *(uint32_t *) s->current_picture.motion_val[m][b_xy - h->b_stride - 1];
+ h->ref_cache[m][scan8[0] - 1 - 1*8] = (h->intra4x4_pred_mode[mb_xy - s->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 (s->pict_type != B_TYPE)
+ break;
+ }
+
+ /* decode motion vector(s) and form prediction(s) */
+ if (s->pict_type == P_TYPE) {
+ if(svq3_mc_dir (h, (mb_type - 1), mode, 0, 0) < 0)
+ return -1;
+ } else { /* B_TYPE */
+ if (mb_type != 2) {
+ if(svq3_mc_dir (h, 0, mode, 0, 0) < 0)
+ return -1;
+ } else {
+ for (i=0; i < 4; i++) {
+ memset (s->current_picture.motion_val[0][b_xy + i*h->b_stride], 0, 4*2*sizeof(int16_t));
+ }
+ }
+ if (mb_type != 1) {
+ if(svq3_mc_dir (h, 0, mode, 1, (mb_type == 3)) < 0)
+ return -1;
+ } else {
+ for (i=0; i < 4; i++) {
+ memset (s->current_picture.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 (s->mb_x > 0) {
+ for (i=0; i < 4; i++) {
+ h->intra4x4_pred_mode_cache[scan8[0] - 1 + i*8] = h->intra4x4_pred_mode[mb_xy - 1][i];
+ }
+ if (h->intra4x4_pred_mode_cache[scan8[0] - 1] == -1) {
+ h->left_samples_available = 0x5F5F;
+ }
+ }
+ if (s->mb_y > 0) {
+ h->intra4x4_pred_mode_cache[4+8*0] = h->intra4x4_pred_mode[mb_xy - s->mb_stride][4];
+ h->intra4x4_pred_mode_cache[5+8*0] = h->intra4x4_pred_mode[mb_xy - s->mb_stride][5];
+ h->intra4x4_pred_mode_cache[6+8*0] = h->intra4x4_pred_mode[mb_xy - s->mb_stride][6];
+ h->intra4x4_pred_mode_cache[7+8*0] = h->intra4x4_pred_mode[mb_xy - s->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 (&s->gb);
+
+ if (vlc >= 25){
+ av_log(h->s.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->s.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) {
+ check_intra4x4_pred_mode (h);
+
+ h->top_samples_available = (s->mb_y == 0) ? 0x33FF : 0xFFFF;
+ h->left_samples_available = (s->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 = check_intra_pred_mode (h, dir)) == -1){
+ av_log(h->s.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) && s->pict_type != I_TYPE) {
+ for (i=0; i < 4; i++) {
+ memset (s->current_picture.motion_val[0][b_xy + i*h->b_stride], 0, 4*2*sizeof(int16_t));
+ }
+ if (s->pict_type == B_TYPE) {
+ for (i=0; i < 4; i++) {
+ memset (s->current_picture.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[mb_xy], DC_PRED, 8);
+ }
+ if (!IS_SKIP(mb_type) || s->pict_type == B_TYPE) {
+ memset (h->non_zero_count_cache + 8, 0, 4*9*sizeof(uint8_t));
+ s->dsp.clear_blocks(h->mb);
+ }
+
+ if (!IS_INTRA16x16(mb_type) && (!IS_SKIP(mb_type) || s->pict_type == B_TYPE)) {
+ if ((vlc = svq3_get_ue_golomb (&s->gb)) >= 48){
+ av_log(h->s.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) || (s->pict_type != I_TYPE && s->adaptive_quant && cbp)) {
+ s->qscale += svq3_get_se_golomb (&s->gb);
+
+ if (s->qscale > 31){
+ av_log(h->s.avctx, AV_LOG_ERROR, "qscale:%d\n", s->qscale);
+ return -1;
+ }
+ }
+ if (IS_INTRA16x16(mb_type)) {
+ if (svq3_decode_block (&s->gb, h->mb, 0, 0)){
+ av_log(h->s.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 = ((s->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 ? ((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 (&s->gb, &h->mb[16*k], index, type)){
+ av_log(h->s.avctx, AV_LOG_ERROR, "error while decoding block\n");
+ return -1;
+ }
+ }
+ }
+ }
+
+ if ((cbp & 0x30)) {
+ for (i=0; i < 2; ++i) {
+ if (svq3_decode_block (&s->gb, &h->mb[16*(16 + 4*i)], 0, 3)){
+ av_log(h->s.avctx, AV_LOG_ERROR, "error while decoding chroma dc block\n");
+ return -1;
+ }
+ }
+
+ if ((cbp & 0x20)) {
+ for (i=0; i < 8; i++) {
+ h->non_zero_count_cache[ scan8[16+i] ] = 1;
+
+ if (svq3_decode_block (&s->gb, &h->mb[16*(16 + i)], 1, 1)){
+ av_log(h->s.avctx, AV_LOG_ERROR, "error while decoding chroma ac block\n");
+ return -1;
+ }
+ }
+ }
+ }
+ }
+
+ s->current_picture.mb_type[mb_xy] = mb_type;
+
+ if (IS_INTRA(mb_type)) {
+ h->chroma_pred_mode = check_intra_pred_mode (h, DC_PRED8x8);
+ }
+
+ return 0;
+}
+
+static int svq3_decode_slice_header (H264Context *h) {
+ MpegEncContext *const s = (MpegEncContext *) h;
+ const int mb_xy = s->mb_x + s->mb_y*s->mb_stride;
+ int i, header;
+
+ header = get_bits (&s->gb, 8);
+
+ if (((header & 0x9F) != 1 && (header & 0x9F) != 2) || (header & 0x60) == 0) {
+ /* TODO: what? */
+ av_log(h->s.avctx, AV_LOG_ERROR, "unsupported slice header (%02X)\n", header);
+ return -1;
+ } else {
+ int length = (header >> 5) & 3;
+
+ h->next_slice_index = get_bits_count(&s->gb) + 8*show_bits (&s->gb, 8*length) + 8*length;
+
+ if (h->next_slice_index > s->gb.size_in_bits){
+ av_log(h->s.avctx, AV_LOG_ERROR, "slice after bitstream end\n");
+ return -1;
+ }
+
+ s->gb.size_in_bits = h->next_slice_index - 8*(length - 1);
+ skip_bits(&s->gb, 8);
+
+ if (length > 0) {
+ memcpy ((uint8_t *) &s->gb.buffer[get_bits_count(&s->gb) >> 3],
+ &s->gb.buffer[s->gb.size_in_bits >> 3], (length - 1));
+ }
+ }
+
+ if ((i = svq3_get_ue_golomb (&s->gb)) == INVALID_VLC || i >= 3){
+ av_log(h->s.avctx, AV_LOG_ERROR, "illegal slice type %d \n", i);
+ return -1;
+ }
+
+ h->slice_type = golomb_to_pict_type[i];
+
+ if ((header & 0x9F) == 2) {
+ i = (s->mb_num < 64) ? 6 : (1 + av_log2 (s->mb_num - 1));
+ s->mb_skip_run = get_bits (&s->gb, i) - (s->mb_x + (s->mb_y * s->mb_width));
+ } else {
+ get_bits1 (&s->gb);
+ s->mb_skip_run = 0;
+ }
+
+ h->slice_num = get_bits (&s->gb, 8);
+ s->qscale = get_bits (&s->gb, 5);
+ s->adaptive_quant = get_bits1 (&s->gb);
+
+ /* unknown fields */
+ get_bits1 (&s->gb);
+
+ if (h->unknown_svq3_flag) {
+ get_bits1 (&s->gb);
+ }
+
+ get_bits1 (&s->gb);
+ get_bits (&s->gb, 2);
+
+ while (get_bits1 (&s->gb)) {
+ get_bits (&s->gb, 8);
+ }
+
+ /* reset intra predictors and invalidate motion vector references */
+ if (s->mb_x > 0) {
+ memset (h->intra4x4_pred_mode[mb_xy - 1], -1, 4*sizeof(int8_t));
+ memset (h->intra4x4_pred_mode[mb_xy - s->mb_x], -1, 8*sizeof(int8_t)*s->mb_x);
+ }
+ if (s->mb_y > 0) {
+ memset (h->intra4x4_pred_mode[mb_xy - s->mb_stride], -1, 8*sizeof(int8_t)*(s->mb_width - s->mb_x));
+
+ if (s->mb_x > 0) {
+ h->intra4x4_pred_mode[mb_xy - s->mb_stride - 1][3] = -1;
+ }
+ }
+
+ return 0;
+}
+
+static int svq3_decode_frame (AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size) {
+ MpegEncContext *const s = avctx->priv_data;
+ H264Context *const h = avctx->priv_data;
+ int m, mb_type;
+ unsigned char *extradata;
+ unsigned int size;
+
+ s->flags = avctx->flags;
+ s->flags2 = avctx->flags2;
+ s->unrestricted_mv = 1;
+
+ if (!s->context_initialized) {
+ s->width = avctx->width;
+ s->height = avctx->height;
+ h->pred4x4[DIAG_DOWN_LEFT_PRED] = pred4x4_down_left_svq3_c;
+ h->pred16x16[PLANE_PRED8x8] = pred16x16_plane_svq3_c;
+ h->halfpel_flag = 1;
+ h->thirdpel_flag = 1;
+ h->unknown_svq3_flag = 0;
+ h->chroma_qp = 4;
+
+ if (MPV_common_init (s) < 0)
+ return -1;
+
+ h->b_stride = 4*s->mb_width;
+
+ alloc_tables (h);
+
+ /* prowl for the "SEQH" marker in the extradata */
+ extradata = (unsigned char *)avctx->extradata;
+ for (m = 0; m < avctx->extradata_size; m++) {
+ if (!memcmp (extradata, "SEQH", 4))
+ break;
+ extradata++;
+ }
+
+ /* if a match was found, parse the extra data */
+ if (!memcmp (extradata, "SEQH", 4)) {
+
+ GetBitContext gb;
+
+ size = BE_32(&extradata[4]);
+ init_get_bits (&gb, extradata + 8, size*8);
+
+ /* 'frame size code' and optional 'width, height' */
+ if (get_bits (&gb, 3) == 7) {
+ get_bits (&gb, 12);
+ get_bits (&gb, 12);
+ }
+
+ h->halfpel_flag = get_bits1 (&gb);
+ h->thirdpel_flag = get_bits1 (&gb);
+
+ /* unknown fields */
+ get_bits1 (&gb);
+ get_bits1 (&gb);
+ get_bits1 (&gb);
+ get_bits1 (&gb);
+
+ s->low_delay = get_bits1 (&gb);
+
+ /* unknown field */
+ get_bits1 (&gb);
+
+ while (get_bits1 (&gb)) {
+ get_bits (&gb, 8);
+ }
+
+ h->unknown_svq3_flag = get_bits1 (&gb);
+ avctx->has_b_frames = !s->low_delay;
+ }
+ }
+
+ /* special case for last picture */
+ if (buf_size == 0) {
+ if (s->next_picture_ptr && !s->low_delay) {
+ *(AVFrame *) data = *(AVFrame *) &s->next_picture;
+ *data_size = sizeof(AVFrame);
+ }
+ return 0;
+ }
+
+ init_get_bits (&s->gb, buf, 8*buf_size);
+
+ s->mb_x = s->mb_y = 0;
+
+ if (svq3_decode_slice_header (h))
+ return -1;
+
+ s->pict_type = h->slice_type;
+ s->picture_number = h->slice_num;
+
+ if(avctx->debug&FF_DEBUG_PICT_INFO){
+ av_log(h->s.avctx, AV_LOG_DEBUG, "%c hpel:%d, tpel:%d aqp:%d qp:%d\n",
+ av_get_pict_type_char(s->pict_type), h->halfpel_flag, h->thirdpel_flag,
+ s->adaptive_quant, s->qscale
+ );
+ }
+
+ /* for hurry_up==5 */
+ s->current_picture.pict_type = s->pict_type;
+ s->current_picture.key_frame = (s->pict_type == I_TYPE);
+
+ /* skip b frames if we dont have reference frames */
+ if (s->last_picture_ptr == NULL && s->pict_type == B_TYPE) return 0;
+ /* skip b frames if we are in a hurry */
+ if (avctx->hurry_up && s->pict_type == B_TYPE) return 0;
+ /* skip everything if we are in a hurry >= 5 */
+ if (avctx->hurry_up >= 5) return 0;
+ if( (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type==B_TYPE)
+ ||(avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type!=I_TYPE)
+ || avctx->skip_frame >= AVDISCARD_ALL)
+ return 0;
+
+ if (s->next_p_frame_damaged) {
+ if (s->pict_type == B_TYPE)
+ return 0;
+ else
+ s->next_p_frame_damaged = 0;
+ }
+
+ frame_start (h);
+
+ if (s->pict_type == B_TYPE) {
+ 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->s.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;
+ h->ref_cache[m][scan8[0] + 8*i + j]= PART_NOT_AVAILABLE;
+ }
+ }
+
+ for (s->mb_y=0; s->mb_y < s->mb_height; s->mb_y++) {
+ for (s->mb_x=0; s->mb_x < s->mb_width; s->mb_x++) {
+
+ if ( (get_bits_count(&s->gb) + 7) >= s->gb.size_in_bits &&
+ ((get_bits_count(&s->gb) & 7) == 0 || show_bits (&s->gb, (-get_bits_count(&s->gb) & 7)) == 0)) {
+
+ skip_bits(&s->gb, h->next_slice_index - get_bits_count(&s->gb));
+ s->gb.size_in_bits = 8*buf_size;
+
+ if (svq3_decode_slice_header (h))
+ return -1;
+
+ /* TODO: support s->mb_skip_run */
+ }
+
+ mb_type = svq3_get_ue_golomb (&s->gb);
+
+ if (s->pict_type == I_TYPE) {
+ mb_type += 8;
+ } else if (s->pict_type == B_TYPE && mb_type >= 4) {
+ mb_type += 4;
+ }
+ if (mb_type > 33 || svq3_decode_mb (h, mb_type)) {
+ av_log(h->s.avctx, AV_LOG_ERROR, "error while decoding MB %d %d\n", s->mb_x, s->mb_y);
+ return -1;
+ }
+
+ if (mb_type != 0) {
+ hl_decode_mb (h);
+ }
+
+ if (s->pict_type != B_TYPE && !s->low_delay) {
+ s->current_picture.mb_type[s->mb_x + s->mb_y*s->mb_stride] =
+ (s->pict_type == P_TYPE && mb_type < 8) ? (mb_type - 1) : -1;
+ }
+ }
+
+ ff_draw_horiz_band(s, 16*s->mb_y, 16);
+ }
+
+ MPV_frame_end(s);
+
+ if (s->pict_type == B_TYPE || s->low_delay) {
+ *(AVFrame *) data = *(AVFrame *) &s->current_picture;
+ } else {
+ *(AVFrame *) data = *(AVFrame *) &s->last_picture;
+ }
+
+ avctx->frame_number = s->picture_number - 1;
+
+ /* dont output the last pic after seeking */
+ if (s->last_picture_ptr || s->low_delay) {
+ *data_size = sizeof(AVFrame);
+ }
+
+ return buf_size;
+}
+
+
+AVCodec svq3_decoder = {
+ "svq3",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_SVQ3,
+ sizeof(H264Context),
+ decode_init,
+ NULL,
+ decode_end,
+ svq3_decode_frame,
+ CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_DELAY,
+};
diff --git a/contrib/ffmpeg/libavcodec/targa.c b/contrib/ffmpeg/libavcodec/targa.c
new file mode 100644
index 000000000..4eb18f87e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/targa.c
@@ -0,0 +1,254 @@
+/*
+ * 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 "avcodec.h"
+
+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
+};
+
+typedef struct TargaContext {
+ AVFrame picture;
+
+ int width, height;
+ int bpp;
+ int color_type;
+ int compression_type;
+} TargaContext;
+
+static void targa_decode_rle(AVCodecContext *avctx, TargaContext *s, uint8_t *src, uint8_t *dst, int w, int h, int stride, int bpp)
+{
+ int i, x, y;
+ int depth = (bpp + 1) >> 3;
+ int type, count;
+ int diff;
+
+ diff = stride - w * depth;
+ x = y = 0;
+ while(y < h){
+ type = *src++;
+ count = (type & 0x7F) + 1;
+ type &= 0x80;
+ if((x + count > w) && (x + count + 1 > (h - y) * w)){
+ av_log(avctx, AV_LOG_ERROR, "Packet went out of bounds: position (%i,%i) size %i\n", x, y, count);
+ return;
+ }
+ for(i = 0; i < count; i++){
+ switch(depth){
+ case 1:
+ *dst = *src;
+ break;
+ case 2:
+ *((uint16_t*)dst) = LE_16(src);
+ break;
+ case 3:
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ break;
+ case 4:
+ *((uint32_t*)dst) = LE_32(src);
+ break;
+ }
+ dst += depth;
+ if(!type)
+ src += depth;
+
+ x++;
+ if(x == w){
+ x = 0;
+ y++;
+ dst += diff;
+ }
+ }
+ if(type)
+ src += depth;
+ }
+}
+
+static int decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ TargaContext * const s = avctx->priv_data;
+ AVFrame *picture = data;
+ AVFrame * const p= (AVFrame*)&s->picture;
+ uint8_t *dst;
+ int stride;
+ int idlen, pal, compr, x, y, w, h, bpp, flags;
+ int first_clr, colors, csize;
+
+ /* parse image header */
+ idlen = *buf++;
+ pal = *buf++;
+ compr = *buf++;
+ first_clr = LE_16(buf); buf += 2;
+ colors = LE_16(buf); buf += 2;
+ csize = *buf++;
+ x = LE_16(buf); buf += 2;
+ y = LE_16(buf); buf += 2;
+ w = LE_16(buf); buf += 2;
+ h = LE_16(buf); buf += 2;
+ bpp = *buf++;
+ flags = *buf++;
+ //skip identifier if any
+ buf += idlen;
+ s->bpp = bpp;
+ s->width = w;
+ s->height = h;
+ switch(s->bpp){
+ case 8:
+ avctx->pix_fmt = ((compr & (~TGA_RLE)) == TGA_BW) ? PIX_FMT_GRAY8 : PIX_FMT_PAL8;
+ break;
+ case 15:
+ avctx->pix_fmt = PIX_FMT_RGB555;
+ break;
+ case 16:
+ avctx->pix_fmt = PIX_FMT_RGB555;
+ break;
+ case 24:
+ avctx->pix_fmt = PIX_FMT_BGR24;
+ break;
+ case 32:
+ avctx->pix_fmt = PIX_FMT_RGBA32;
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "Bit depth %i is not supported\n", s->bpp);
+ return -1;
+ }
+
+ if(s->picture.data[0])
+ avctx->release_buffer(avctx, &s->picture);
+
+ if(avcodec_check_dimensions(avctx, w, h))
+ return -1;
+ if(w != avctx->width || h != avctx->height)
+ avcodec_set_dimensions(avctx, w, h);
+ if(avctx->get_buffer(avctx, p) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+ if(flags & 0x20){
+ 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];
+ }
+
+ if(avctx->pix_fmt == PIX_FMT_PAL8 && avctx->palctrl){
+ memcpy(p->data[1], avctx->palctrl->palette, AVPALETTE_SIZE);
+ if(avctx->palctrl->palette_changed){
+ p->palette_has_changed = 1;
+ avctx->palctrl->palette_changed = 0;
+ }
+ }
+ if(colors){
+ if((colors + first_clr) > 256){
+ av_log(avctx, AV_LOG_ERROR, "Incorrect palette: %i colors with offset %i\n", colors, first_clr);
+ return -1;
+ }
+ if(csize != 24){
+ av_log(avctx, AV_LOG_ERROR, "Palette entry size %i bits is not supported\n", csize);
+ return -1;
+ }
+ if(avctx->pix_fmt != PIX_FMT_PAL8)//should not occur but skip palette anyway
+ buf += colors * ((csize + 1) >> 3);
+ else{
+ int r, g, b, t;
+ int32_t *pal = ((int32_t*)p->data[1]) + first_clr;
+ for(t = 0; t < colors; t++){
+ r = *buf++;
+ g = *buf++;
+ b = *buf++;
+ *pal++ = (b << 16) | (g << 8) | r;
+ }
+ p->palette_has_changed = 1;
+ avctx->palctrl->palette_changed = 0;
+ }
+ }
+ if((compr & (~TGA_RLE)) == TGA_NODATA)
+ memset(p->data[0], 0, p->linesize[0] * s->height);
+ else{
+ if(compr & TGA_RLE)
+ targa_decode_rle(avctx, s, buf, dst, avctx->width, avctx->height, stride, bpp);
+ else{
+ for(y = 0; y < s->height; y++){
+#ifdef WORDS_BIGENDIAN
+ if((s->bpp + 1) >> 3 == 2){
+ uint16_t *dst16 = (uint16_t*)dst;
+ for(x = 0; x < s->width; x++)
+ dst16[x] = LE_16(buf + x * 2);
+ }else if((s->bpp + 1) >> 3 == 4){
+ uint32_t *dst32 = (uint32_t*)dst;
+ for(x = 0; x < s->width; x++)
+ dst32[x] = LE_32(buf + x * 4);
+ }else
+#endif
+ memcpy(dst, buf, s->width * ((s->bpp + 1) >> 3));
+
+ dst += stride;
+ buf += s->width * ((s->bpp + 1) >> 3);
+ }
+ }
+ }
+
+ *picture= *(AVFrame*)&s->picture;
+ *data_size = sizeof(AVPicture);
+
+ return buf_size;
+}
+
+static int targa_init(AVCodecContext *avctx){
+ TargaContext *s = avctx->priv_data;
+
+ avcodec_get_frame_defaults((AVFrame*)&s->picture);
+ avctx->coded_frame= (AVFrame*)&s->picture;
+ s->picture.data[0] = NULL;
+
+ return 0;
+}
+
+static int targa_end(AVCodecContext *avctx){
+ TargaContext *s = avctx->priv_data;
+
+ if(s->picture.data[0])
+ avctx->release_buffer(avctx, &s->picture);
+
+ return 0;
+}
+
+AVCodec targa_decoder = {
+ "targa",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_TARGA,
+ sizeof(TargaContext),
+ targa_init,
+ NULL,
+ targa_end,
+ decode_frame,
+ 0,
+ NULL
+};
diff --git a/contrib/ffmpeg/libavcodec/tiertexseqv.c b/contrib/ffmpeg/libavcodec/tiertexseqv.c
new file mode 100644
index 000000000..ca3baf09e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/tiertexseqv.c
@@ -0,0 +1,232 @@
+/*
+ * 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 tiertexseqv.c
+ * Tiertex Limited SEQ video decoder
+ */
+
+#include "avcodec.h"
+#include "common.h"
+#define ALT_BITSTREAM_READER_LE
+#include "bitstream.h"
+
+
+typedef struct SeqVideoContext {
+ AVCodecContext *avctx;
+ AVFrame frame;
+ unsigned int palette[256];
+ unsigned char block[8 * 8];
+} SeqVideoContext;
+
+
+static unsigned char *seq_unpack_rle_block(unsigned char *src, unsigned char *dst, int dst_size)
+{
+ int i, len, sz;
+ GetBitContext gb;
+ int code_table[64];
+
+ /* get the rle codes (at most 64 bytes) */
+ init_get_bits(&gb, src, 64 * 8);
+ for (i = 0, sz = 0; i < 64 && sz < dst_size; i++) {
+ 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;
+ memset(dst, *src++, FFMIN(len, dst_size));
+ } else {
+ memcpy(dst, src, FFMIN(len, dst_size));
+ src += len;
+ }
+ dst += len;
+ dst_size -= len;
+ }
+ return src;
+}
+
+static unsigned char *seq_decode_op1(SeqVideoContext *seq, unsigned char *src, unsigned char *dst)
+{
+ unsigned char *color_table;
+ int b, i, len, bits;
+ GetBitContext gb;
+
+ len = *src++;
+ if (len & 0x80) {
+ switch (len & 3) {
+ case 1:
+ src = seq_unpack_rle_block(src, seq->block, sizeof(seq->block));
+ for (b = 0; b < 8; b++) {
+ memcpy(dst, &seq->block[b * 8], 8);
+ dst += seq->frame.linesize[0];
+ }
+ break;
+ case 2:
+ src = seq_unpack_rle_block(src, seq->block, sizeof(seq->block));
+ for (i = 0; i < 8; i++) {
+ for (b = 0; b < 8; b++)
+ dst[b * seq->frame.linesize[0]] = seq->block[i * 8 + b];
+ ++dst;
+ }
+ break;
+ }
+ } else {
+ color_table = src;
+ src += len;
+ bits = ff_log2_tab[len - 1] + 1;
+ 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 unsigned char *seq_decode_op2(SeqVideoContext *seq, unsigned char *src, unsigned char *dst)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ memcpy(dst, src, 8);
+ src += 8;
+ dst += seq->frame.linesize[0];
+ }
+
+ return src;
+}
+
+static unsigned char *seq_decode_op3(SeqVideoContext *seq, unsigned char *src, unsigned char *dst)
+{
+ int pos, offset;
+
+ do {
+ pos = *src++;
+ offset = ((pos >> 3) & 7) * seq->frame.linesize[0] + (pos & 7);
+ dst[offset] = *src++;
+ } while (!(pos & 0x80));
+
+ return src;
+}
+
+static void seqvideo_decode(SeqVideoContext *seq, unsigned char *data, int data_size)
+{
+ GetBitContext gb;
+ int flags, i, j, x, y, op;
+ unsigned char c[3];
+ unsigned char *dst;
+
+ flags = *data++;
+
+ if (flags & 1) {
+ for (i = 0; i < 256; i++) {
+ for (j = 0; j < 3; j++, data++)
+ c[j] = (*data << 2) | (*data >> 4);
+ seq->palette[i] = (c[0] << 16) | (c[1] << 8) | c[2];
+ }
+ memcpy(seq->frame.data[1], seq->palette, sizeof(seq->palette));
+ seq->frame.palette_has_changed = 1;
+ }
+
+ if (flags & 2) {
+ 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, dst);
+ break;
+ case 2:
+ data = seq_decode_op2(seq, data, dst);
+ break;
+ case 3:
+ data = seq_decode_op3(seq, data, dst);
+ break;
+ }
+ }
+ }
+}
+
+static int seqvideo_decode_init(AVCodecContext *avctx)
+{
+ SeqVideoContext *seq = (SeqVideoContext *)avctx->priv_data;
+
+ seq->avctx = avctx;
+ avctx->pix_fmt = PIX_FMT_PAL8;
+ avctx->has_b_frames = 0;
+
+ seq->frame.data[0] = NULL;
+
+ return 0;
+}
+
+static int seqvideo_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+
+ SeqVideoContext *seq = (SeqVideoContext *)avctx->priv_data;
+
+ seq->frame.reference = 1;
+ seq->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
+ if (avctx->reget_buffer(avctx, &seq->frame)) {
+ av_log(seq->avctx, AV_LOG_ERROR, "tiertexseqvideo: reget_buffer() failed\n");
+ return -1;
+ }
+
+ seqvideo_decode(seq, buf, buf_size);
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame *)data = seq->frame;
+
+ return buf_size;
+}
+
+static int seqvideo_decode_end(AVCodecContext *avctx)
+{
+ SeqVideoContext *seq = (SeqVideoContext *)avctx->priv_data;
+
+ if (seq->frame.data[0])
+ avctx->release_buffer(avctx, &seq->frame);
+
+ return 0;
+}
+
+AVCodec tiertexseqvideo_decoder = {
+ "tiertexseqvideo",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_TIERTEXSEQVIDEO,
+ sizeof(SeqVideoContext),
+ seqvideo_decode_init,
+ NULL,
+ seqvideo_decode_end,
+ seqvideo_decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/tiff.c b/contrib/ffmpeg/libavcodec/tiff.c
new file mode 100644
index 000000000..5925af1ae
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/tiff.c
@@ -0,0 +1,531 @@
+/*
+ * TIFF 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 "avcodec.h"
+#ifdef CONFIG_ZLIB
+#include <zlib.h>
+#endif
+#include "lzw.h"
+
+/* abridged list of TIFF tags */
+enum TiffTags{
+ TIFF_WIDTH = 0x100,
+ TIFF_HEIGHT,
+ TIFF_BPP,
+ TIFF_COMPR,
+ TIFF_INVERT = 0x106,
+ TIFF_STRIP_OFFS = 0x111,
+ TIFF_ROWSPERSTRIP = 0x116,
+ TIFF_STRIP_SIZE,
+ TIFF_PLANAR = 0x11C,
+ TIFF_XPOS = 0x11E,
+ TIFF_YPOS = 0x11F,
+ TIFF_PREDICTOR = 0x13D,
+ TIFF_PAL = 0x140
+};
+
+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_LONGLONG
+};
+
+/** sizes of various TIFF field types */
+static const int type_sizes[6] = {
+ 0, 1, 100, 2, 4, 8
+};
+
+typedef struct TiffContext {
+ AVCodecContext *avctx;
+ AVFrame picture;
+
+ int width, height;
+ unsigned int bpp;
+ int le;
+ int compr;
+ int invert;
+
+ int strips, rps;
+ int sot;
+ uint8_t* stripdata;
+ uint8_t* stripsizes;
+ int stripsize, stripoff;
+ LZWState *lzw;
+} TiffContext;
+
+static int tget_short(uint8_t **p, int le){
+ int v = le ? LE_16(*p) : BE_16(*p);
+ *p += 2;
+ return v;
+}
+
+static int tget_long(uint8_t **p, int le){
+ int v = le ? LE_32(*p) : BE_32(*p);
+ *p += 4;
+ return v;
+}
+
+static int tget(uint8_t **p, int type, int le){
+ switch(type){
+ case TIFF_BYTE : return *(*p)++;
+ case TIFF_SHORT: return tget_short(p, le);
+ case TIFF_LONG : return tget_long (p, le);
+ default : return -1;
+ }
+}
+
+static int tiff_unpack_strip(TiffContext *s, uint8_t* dst, int stride, uint8_t *src, int size, int lines){
+ int c, line, pixels, code;
+ uint8_t *ssrc = src;
+ int width = s->width * (s->bpp / 8);
+#ifdef CONFIG_ZLIB
+ uint8_t *zbuf; unsigned long outlen;
+
+ if(s->compr == TIFF_DEFLATE || s->compr == TIFF_ADOBE_DEFLATE){
+ outlen = width * lines;
+ zbuf = av_malloc(outlen);
+ if(uncompress(zbuf, &outlen, src, size) != Z_OK){
+ av_log(s->avctx, AV_LOG_ERROR, "Uncompressing failed (%lu of %lu)\n", outlen, (unsigned long)width * lines);
+ av_free(zbuf);
+ return -1;
+ }
+ src = zbuf;
+ for(line = 0; line < lines; line++){
+ memcpy(dst, src, width);
+ dst += stride;
+ src += width;
+ }
+ av_free(zbuf);
+ return 0;
+ }
+#endif
+ if(s->compr == TIFF_LZW){
+ if(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 -1;
+ }
+ }
+ for(line = 0; line < lines; line++){
+ if(src - ssrc > size){
+ av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n");
+ return -1;
+ }
+ switch(s->compr){
+ case TIFF_RAW:
+ memcpy(dst, src, s->width * (s->bpp / 8));
+ src += s->width * (s->bpp / 8);
+ break;
+ case TIFF_PACKBITS:
+ for(pixels = 0; pixels < width;){
+ 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 -1;
+ }
+ memcpy(dst + pixels, src, code);
+ 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 -1;
+ }
+ c = *src++;
+ memset(dst + pixels, c, code);
+ 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 -1;
+ }
+ break;
+ }
+ dst += stride;
+ }
+ return 0;
+}
+
+
+static int tiff_decode_tag(TiffContext *s, uint8_t *start, uint8_t *buf, uint8_t *end_buf, AVFrame *pic)
+{
+ int tag, type, count, off, value = 0;
+ uint8_t *src, *dst;
+ int i, j, ssize, soff, stride;
+ int *pal, *rp, *gp, *bp;
+
+ tag = tget_short(&buf, s->le);
+ type = tget_short(&buf, s->le);
+ count = tget_long(&buf, s->le);
+ off = tget_long(&buf, s->le);
+
+ if(count == 1){
+ switch(type){
+ case TIFF_BYTE:
+ case TIFF_SHORT:
+ buf -= 4;
+ value = tget(&buf, type, s->le);
+ buf = NULL;
+ break;
+ case TIFF_LONG:
+ value = off;
+ buf = NULL;
+ break;
+ default:
+ value = -1;
+ buf = start + off;
+ }
+ }else if(type_sizes[type] * count <= 4){
+ buf -= 4;
+ }else{
+ buf = start + off;
+ }
+
+ if(buf && (buf < start || buf > end_buf)){
+ av_log(s->avctx, AV_LOG_ERROR, "Tag referencing position outside the image\n");
+ return -1;
+ }
+
+ switch(tag){
+ case TIFF_WIDTH:
+ s->width = value;
+ break;
+ case TIFF_HEIGHT:
+ s->height = value;
+ break;
+ case TIFF_BPP:
+ 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;
+ for(i = 0; i < count; i++) s->bpp += tget(&buf, type, s->le);
+ break;
+ default:
+ s->bpp = -1;
+ }
+ }
+ switch(s->bpp){
+ case 8:
+ s->avctx->pix_fmt = PIX_FMT_PAL8;
+ break;
+ case 24:
+ s->avctx->pix_fmt = PIX_FMT_RGB24;
+ break;
+ case 16:
+ if(count == 1){
+ s->avctx->pix_fmt = PIX_FMT_GRAY16BE;
+ }else{
+ av_log(s->avctx, AV_LOG_ERROR, "This format is not supported (bpp=%i)\n", s->bpp);
+ return -1;
+ }
+ break;
+ default:
+ av_log(s->avctx, AV_LOG_ERROR, "This format is not supported (bpp=%i)\n", s->bpp);
+ return -1;
+ }
+ if(s->width != s->avctx->width || s->height != s->avctx->height){
+ if(avcodec_check_dimensions(s->avctx, s->width, s->height))
+ return -1;
+ avcodec_set_dimensions(s->avctx, s->width, s->height);
+ }
+ if(s->picture.data[0])
+ s->avctx->release_buffer(s->avctx, &s->picture);
+ if(s->avctx->get_buffer(s->avctx, &s->picture) < 0){
+ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+ if(s->bpp == 8){
+ /* make default grayscale pal */
+ pal = s->picture.data[1];
+ for(i = 0; i < 256; i++)
+ pal[i] = i * 0x010101;
+ }
+ break;
+ case TIFF_COMPR:
+ s->compr = value;
+ switch(s->compr){
+ case TIFF_RAW:
+ case TIFF_PACKBITS:
+ case TIFF_LZW:
+ break;
+ case TIFF_DEFLATE:
+ case TIFF_ADOBE_DEFLATE:
+#ifdef CONFIG_ZLIB
+ break;
+#else
+ av_log(s->avctx, AV_LOG_ERROR, "Deflate: ZLib not compiled in\n");
+ return -1;
+#endif
+ case TIFF_G3:
+ av_log(s->avctx, AV_LOG_ERROR, "CCITT G3 compression is not supported\n");
+ return -1;
+ case TIFF_G4:
+ av_log(s->avctx, AV_LOG_ERROR, "CCITT G4 compression is not supported\n");
+ return -1;
+ case TIFF_CCITT_RLE:
+ av_log(s->avctx, AV_LOG_ERROR, "CCITT RLE compression is not supported\n");
+ return -1;
+ case TIFF_JPEG:
+ case TIFF_NEWJPEG:
+ av_log(s->avctx, AV_LOG_ERROR, "JPEG compression is not supported\n");
+ return -1;
+ default:
+ av_log(s->avctx, AV_LOG_ERROR, "Unknown compression method %i\n", s->compr);
+ return -1;
+ }
+ break;
+ case TIFF_ROWSPERSTRIP:
+ if(value < 1){
+ av_log(s->avctx, AV_LOG_ERROR, "Incorrect value of rows per strip\n");
+ return -1;
+ }
+ s->rps = value;
+ break;
+ case TIFF_STRIP_OFFS:
+ if(count == 1){
+ s->stripdata = NULL;
+ s->stripoff = value;
+ }else
+ s->stripdata = start + off;
+ s->strips = count;
+ s->sot = type;
+ if(s->stripdata > end_buf){
+ av_log(s->avctx, AV_LOG_ERROR, "Tag referencing position outside the image\n");
+ return -1;
+ }
+ break;
+ case TIFF_STRIP_SIZE:
+ if(count == 1){
+ s->stripsizes = NULL;
+ s->stripsize = value;
+ s->strips = 1;
+ }else{
+ s->stripsizes = start + off;
+ }
+ s->strips = count;
+ if(s->stripsizes > end_buf){
+ av_log(s->avctx, AV_LOG_ERROR, "Tag referencing position outside the image\n");
+ return -1;
+ }
+ if(!pic->data[0]){
+ av_log(s->avctx, AV_LOG_ERROR, "Picture initialization missing\n");
+ return -1;
+ }
+ /* now we have the data and may start decoding */
+ stride = pic->linesize[0];
+ dst = pic->data[0];
+ for(i = 0; i < s->height; i += s->rps){
+ if(s->stripsizes)
+ ssize = tget(&s->stripsizes, type, s->le);
+ else
+ ssize = s->stripsize;
+
+ if(s->stripdata){
+ soff = tget(&s->stripdata, s->sot, s->le);
+ }else
+ soff = s->stripoff;
+ src = start + soff;
+ if(tiff_unpack_strip(s, dst, stride, src, ssize, FFMIN(s->rps, s->height - i)) < 0)
+ break;
+ dst += s->rps * stride;
+ }
+ break;
+ case TIFF_PREDICTOR:
+ if(!pic->data[0]){
+ av_log(s->avctx, AV_LOG_ERROR, "Picture initialization missing\n");
+ return -1;
+ }
+ if(value == 2){
+ src = pic->data[0];
+ stride = pic->linesize[0];
+ soff = s->bpp >> 3;
+ ssize = s->width * soff;
+ for(i = 0; i < s->height; i++) {
+ for(j = soff; j < ssize; j++)
+ src[j] += src[j - soff];
+ src += stride;
+ }
+ }
+ 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 -1;
+ }
+ break;
+ case TIFF_PAL:
+ if(s->avctx->pix_fmt != PIX_FMT_PAL8){
+ av_log(s->avctx, AV_LOG_ERROR, "Palette met but this is not palettized format\n");
+ return -1;
+ }
+ pal = s->picture.data[1];
+ off = type_sizes[type];
+ rp = buf;
+ gp = buf + count / 3 * off;
+ bp = buf + count / 3 * off * 2;
+ off = (type_sizes[type] - 1) << 3;
+ for(i = 0; i < count / 3; i++){
+ j = (tget(&rp, type, s->le) >> off) << 16;
+ j |= (tget(&gp, type, s->le) >> off) << 8;
+ j |= tget(&bp, type, s->le) >> off;
+ pal[i] = j;
+ }
+ break;
+ case TIFF_PLANAR:
+ if(value == 2){
+ av_log(s->avctx, AV_LOG_ERROR, "Planar format is not supported\n");
+ return -1;
+ }
+ break;
+ }
+ return 0;
+}
+
+static int decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ TiffContext * const s = avctx->priv_data;
+ AVFrame *picture = data;
+ AVFrame * const p= (AVFrame*)&s->picture;
+ uint8_t *orig_buf = buf, *end_buf = buf + buf_size;
+ int id, le, off;
+ int i, entries;
+
+ //parse image header
+ id = LE_16(buf); buf += 2;
+ if(id == 0x4949) le = 1;
+ else if(id == 0x4D4D) le = 0;
+ else{
+ av_log(avctx, AV_LOG_ERROR, "TIFF header not found\n");
+ return -1;
+ }
+ s->le = le;
+ s->invert = 0;
+ // 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(&buf, le) != 42){
+ av_log(avctx, AV_LOG_ERROR, "The answer to life, universe and everything is not correct!\n");
+ return -1;
+ }
+ /* parse image file directory */
+ off = tget_long(&buf, le);
+ if(orig_buf + off + 14 >= end_buf){
+ av_log(avctx, AV_LOG_ERROR, "IFD offset is greater than image size\n");
+ return -1;
+ }
+ buf = orig_buf + off;
+ entries = tget_short(&buf, le);
+ for(i = 0; i < entries; i++){
+ if(tiff_decode_tag(s, orig_buf, buf, end_buf, p) < 0)
+ return -1;
+ buf += 12;
+ }
+
+ if(s->invert){
+ uint8_t *src;
+ int j;
+
+ src = s->picture.data[0];
+ for(j = 0; j < s->height; j++){
+ for(i = 0; i < s->picture.linesize[0]; i++)
+ src[i] = 255 - src[i];
+ src += s->picture.linesize[0];
+ }
+ }
+ *picture= *(AVFrame*)&s->picture;
+ *data_size = sizeof(AVPicture);
+
+ return buf_size;
+}
+
+static int tiff_init(AVCodecContext *avctx){
+ TiffContext *s = avctx->priv_data;
+
+ s->width = 0;
+ s->height = 0;
+ s->avctx = avctx;
+ avcodec_get_frame_defaults((AVFrame*)&s->picture);
+ avctx->coded_frame= (AVFrame*)&s->picture;
+ s->picture.data[0] = NULL;
+ ff_lzw_decode_open(&s->lzw);
+
+ return 0;
+}
+
+static int tiff_end(AVCodecContext *avctx)
+{
+ TiffContext * const s = avctx->priv_data;
+
+ ff_lzw_decode_close(&s->lzw);
+ if(s->picture.data[0])
+ avctx->release_buffer(avctx, &s->picture);
+ return 0;
+}
+
+AVCodec tiff_decoder = {
+ "tiff",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_TIFF,
+ sizeof(TiffContext),
+ tiff_init,
+ NULL,
+ tiff_end,
+ decode_frame,
+ 0,
+ NULL
+};
diff --git a/contrib/ffmpeg/libavcodec/truemotion1.c b/contrib/ffmpeg/libavcodec/truemotion1.c
new file mode 100644
index 000000000..11d9320c0
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/truemotion1.c
@@ -0,0 +1,923 @@
+/*
+ * 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 truemotion1.c
+ * Duck TrueMotion v1 Video Decoder by
+ * Alex Beregszaszi (alex@fsn.hu) 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.h"
+
+#include "truemotion1data.h"
+
+typedef struct TrueMotion1Context {
+ AVCodecContext *avctx;
+ AVFrame frame;
+ AVFrame prev_frame;
+
+ uint8_t *buf;
+ int size;
+
+ uint8_t *mb_change_bits;
+ int mb_change_bits_row_size;
+ 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;
+
+} 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 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;
+ }
+}
+
+#ifdef WORDS_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);
+}
+
+#ifdef WORDS_BIGENDIAN
+static int make_cdt15_entry(int p2, int p1, int16_t *cdt)
+#else
+static int make_cdt15_entry(int p1, int p2, int16_t *cdt)
+#endif
+{
+ int r, b, lo;
+
+ b = cdt[p2];
+ r = cdt[p1] << 10;
+ lo = b + r;
+ return ((lo + (lo << 16)) << 1);
+}
+
+#ifdef WORDS_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);
+}
+
+#ifdef WORDS_BIGENDIAN
+static int make_cdt16_entry(int p2, int p1, int16_t *cdt)
+#else
+static int make_cdt16_entry(int p1, int p2, int16_t *cdt)
+#endif
+{
+ int r, b, lo;
+
+ b = cdt[p2];
+ r = cdt[p1] << 11;
+ lo = b + r;
+ return ((lo + (lo << 16)) << 1);
+}
+
+#ifdef WORDS_BIGENDIAN
+static int make_ydt24_entry(int p2, int p1, int16_t *ydt)
+#else
+static int make_ydt24_entry(int p1, int p2, int16_t *ydt)
+#endif
+{
+ int lo, hi;
+
+ lo = ydt[p1];
+ hi = ydt[p2];
+ return ((lo + (hi << 8) + (hi << 16)) << 1);
+}
+
+#ifdef WORDS_BIGENDIAN
+static int make_cdt24_entry(int p2, int p1, int16_t *cdt)
+#else
+static int make_cdt24_entry(int p1, int p2, int16_t *cdt)
+#endif
+{
+ 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;
+ struct frame_header header;
+ uint8_t header_buffer[128]; /* logical maximum size of the header */
+ const uint8_t *sel_vector_table;
+
+ /* 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) + 7) >> 3;
+
+ header.header_size = ((s->buf[0] >> 5) | (s->buf[0] << 3)) & 0x7f;
+ if (s->buf[0] < 0x10)
+ {
+ av_log(s->avctx, AV_LOG_ERROR, "invalid header size (%d)\n", s->buf[0]);
+ return -1;
+ }
+
+ /* unscramble the header bytes with a XOR operation */
+ memset(header_buffer, 0, 128);
+ 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 = LE_16(&header_buffer[3]);
+ header.xsize = LE_16(&header_buffer[5]);
+ header.checksum = LE_16(&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 -1;
+ } 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) {
+ av_log(s->avctx, AV_LOG_INFO, "SPRITE frame found, please report the sample to the developers\n");
+ s->w = header.width;
+ s->h = header.height;
+ s->x = header.xoffset;
+ s->y = header.yoffset;
+ } 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;
+ av_log(s->avctx, AV_LOG_INFO, "INTERPOLATION selected, please report the sample to the developers\n");
+ }
+ }
+ }
+
+ if (header.compression > 17) {
+ av_log(s->avctx, AV_LOG_ERROR, "invalid compression type (%d)\n", header.compression);
+ return -1;
+ }
+
+ 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 < 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 -1;
+ }
+ }
+
+ // FIXME: where to place this ?!?!
+ if (compression_types[header.compression].algorithm == ALGO_RGB24H)
+ s->avctx->pix_fmt = PIX_FMT_RGBA32;
+ else
+ s->avctx->pix_fmt = PIX_FMT_RGB555; // RGB565 is supported aswell
+
+ 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 == 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 int truemotion1_decode_init(AVCodecContext *avctx)
+{
+ TrueMotion1Context *s = (TrueMotion1Context *)avctx->priv_data;
+
+ s->avctx = avctx;
+
+ // FIXME: it may change ?
+// if (avctx->bits_per_sample == 24)
+// avctx->pix_fmt = PIX_FMT_RGB24;
+// else
+// avctx->pix_fmt = PIX_FMT_RGB555;
+
+ avctx->has_b_frames = 0;
+ s->frame.data[0] = s->prev_frame.data[0] = NULL;
+
+ /* there is a vertical predictor for each pixel in a line; each vertical
+ * predictor is 0 to start with */
+ s->vert_pred =
+ (unsigned int *)av_malloc(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() \
+ 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() \
+ 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() \
+ 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() \
+ 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++; \
+ prev_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 int *prev_pixel_pair;
+ unsigned char *current_line = s->frame.data[0];
+ unsigned char *prev_line = s->prev_frame.data[0];
+ int keyframe = s->flags & FLAG_KEYFRAME;
+
+ /* these variables are for managing the stream of macroblock change bits */
+ 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;
+ prev_pixel_pair = (unsigned int *)prev_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 */
+ *current_pixel_pair = *prev_pixel_pair++;
+ *vert_pred++ = *current_pixel_pair++;
+ *current_pixel_pair = *prev_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];
+ prev_line += s->prev_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 int *prev_pixel_pair;
+ unsigned char *current_line = s->frame.data[0];
+ unsigned char *prev_line = s->prev_frame.data[0];
+ int keyframe = s->flags & FLAG_KEYFRAME;
+
+ /* these variables are for managing the stream of macroblock change bits */
+ 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;
+ prev_pixel_pair = (unsigned int *)prev_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 */
+ *current_pixel_pair = *prev_pixel_pair++;
+ *vert_pred++ = *current_pixel_pair++;
+ *current_pixel_pair = *prev_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];
+ prev_line += s->prev_frame.linesize[0];
+ }
+}
+
+
+static int truemotion1_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ TrueMotion1Context *s = (TrueMotion1Context *)avctx->priv_data;
+
+ s->buf = buf;
+ s->size = buf_size;
+
+ if (truemotion1_decode_header(s) == -1)
+ return -1;
+
+ s->frame.reference = 1;
+ if (avctx->get_buffer(avctx, &s->frame) < 0) {
+ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ /* check for a do-nothing frame and copy the previous frame */
+ if (compression_types[s->compression].algorithm == ALGO_NOP)
+ {
+ memcpy(s->frame.data[0], s->prev_frame.data[0],
+ s->frame.linesize[0] * s->avctx->height);
+ } else if (compression_types[s->compression].algorithm == ALGO_RGB24H) {
+ truemotion1_decode_24bit(s);
+ } else {
+ truemotion1_decode_16bit(s);
+ }
+
+ if (s->prev_frame.data[0])
+ avctx->release_buffer(avctx, &s->prev_frame);
+
+ /* shuffle frames */
+ s->prev_frame = s->frame;
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = s->frame;
+
+ /* report that the buffer was completely consumed */
+ return buf_size;
+}
+
+static int truemotion1_decode_end(AVCodecContext *avctx)
+{
+ TrueMotion1Context *s = (TrueMotion1Context *)avctx->priv_data;
+
+ /* release the last frame */
+ if (s->prev_frame.data[0])
+ avctx->release_buffer(avctx, &s->prev_frame);
+
+ av_free(s->vert_pred);
+
+ return 0;
+}
+
+AVCodec truemotion1_decoder = {
+ "truemotion1",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_TRUEMOTION1,
+ sizeof(TrueMotion1Context),
+ truemotion1_decode_init,
+ NULL,
+ truemotion1_decode_end,
+ truemotion1_decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/truemotion1data.h b/contrib/ffmpeg/libavcodec/truemotion1data.h
new file mode 100644
index 000000000..63d307c65
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/truemotion1data.h
@@ -0,0 +1,829 @@
+/*
+ * 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 ffmpeg under the
+ * GNU LGPL using the common understanding that data tables necessary for
+ * decoding algorithms are not necessarily licensable.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 TRUEMOTION1DATA_H
+#define TRUEMOTION1DATA_H
+
+/* 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 };
+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 };
+/* NOTE: This table breaks the [+,-] pattern that the rest of the
+ * tables maintain. Is this intentional? */
+static const int16_t fat_cdt3[8] = { 0, 40, 80, -76, 160, -154, 236, -236 };
+
+/* all the delta tables to choose from, at all 4 delta levels */
+static const int16_t *ydts[] = { ydt1, ydt2, ydt3, ydt4, NULL };
+static const int16_t *fat_ydts[] = { fat_ydt3, fat_ydt3, fat_ydt3, fat_ydt4, NULL };
+static const int16_t *cdts[] = { cdt1, cdt1, cdt2, cdt3, NULL };
+static const int16_t *fat_cdts[] = { fat_cdt2, fat_cdt2, fat_cdt2, fat_cdt3, 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 *tables[] = { pc_tbl2, pc_tbl3, pc_tbl4 };
+#endif
diff --git a/contrib/ffmpeg/libavcodec/truemotion2.c b/contrib/ffmpeg/libavcodec/truemotion2.c
new file mode 100644
index 000000000..1b67bd22a
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/truemotion2.c
@@ -0,0 +1,893 @@
+/*
+ * 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 truemotion2.c
+ * Duck TrueMotion2 decoder.
+ */
+
+#include "avcodec.h"
+#include "common.h"
+#include "bitstream.h"
+#include "dsputil.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;
+
+ /* 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, *U1, *V1, *Y2, *U2, *V2;
+ 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)
+{
+ if(length > huff->max_bits) {
+ av_log(ctx->avctx, AV_LOG_ERROR, "Tree exceeded its given depth (%i)\n", huff->max_bits);
+ return -1;
+ }
+
+ 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 -1;
+ }
+ 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(tm2_read_tree(ctx, prefix << 1, length + 1, huff) == -1)
+ return -1;
+ if(tm2_read_tree(ctx, (prefix << 1) | 1, length + 1, huff) == -1)
+ return -1;
+ }
+ 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 > 32)) {
+ 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 -1;
+ }
+ 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 -1;
+ }
+ /* 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));
+
+ if(tm2_read_tree(ctx, 0, 0, &huff) == -1)
+ res = -1;
+
+ 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 = -1;
+ }
+
+ /* convert codes to vlc_table */
+ if(res != -1) {
+ 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");
+ res = -1;
+ } else
+ res = 0;
+ if(res != -1) {
+ 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)
+{
+ if(code->recode)
+ av_free(code->recode);
+ if(code->vlc.table)
+ 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);
+ return code->recode[val];
+}
+
+static inline int tm2_read_header(TM2Context *ctx, uint8_t *buf)
+{
+ uint32_t magic;
+ uint8_t *obuf;
+ int length;
+
+ obuf = buf;
+
+ magic = LE_32(buf);
+ buf += 4;
+
+ if(magic == 0x00000100) { /* old header */
+/* av_log (ctx->avctx, AV_LOG_ERROR, "TM2 old header: not implemented (yet)\n"); */
+ return 40;
+ } else if(magic == 0x00000101) { /* new header */
+ int w, h, size, flags, xr, yr;
+
+ length = LE_32(buf);
+ buf += 4;
+
+ init_get_bits(&ctx->gb, buf, 32 * 8);
+ size = get_bits_long(&ctx->gb, 31);
+ h = get_bits(&ctx->gb, 15);
+ w = get_bits(&ctx->gb, 15);
+ flags = get_bits_long(&ctx->gb, 31);
+ yr = get_bits(&ctx->gb, 9);
+ xr = get_bits(&ctx->gb, 9);
+
+ return 40;
+ } else {
+ av_log (ctx->avctx, AV_LOG_ERROR, "Not a TM2 header: 0x%08X\n", magic);
+ return -1;
+ }
+
+ return (buf - obuf);
+}
+
+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 -1;
+ }
+
+ 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, uint8_t *buf, int stream_id) {
+ int i;
+ int cur = 0;
+ int skip = 0;
+ int len, toks;
+ TM2Codes codes;
+
+ /* get stream length in dwords */
+ len = BE_32(buf); buf += 4; cur += 4;
+ skip = len * 4 + 4;
+
+ if(len == 0)
+ return 4;
+
+ toks = BE_32(buf); buf += 4; cur += 4;
+ if(toks & 1) {
+ len = BE_32(buf); buf += 4; cur += 4;
+ if(len == TM2_ESCAPE) {
+ len = BE_32(buf); buf += 4; cur += 4;
+ }
+ if(len > 0) {
+ init_get_bits(&ctx->gb, buf, (skip - cur) * 8);
+ if(tm2_read_deltas(ctx, stream_id) == -1)
+ return -1;
+ buf += ((get_bits_count(&ctx->gb) + 31) >> 5) << 2;
+ cur += ((get_bits_count(&ctx->gb) + 31) >> 5) << 2;
+ }
+ }
+ /* skip unused fields */
+ if(BE_32(buf) == TM2_ESCAPE) {
+ buf += 4; cur += 4; /* some unknown length - could be escaped too */
+ }
+ buf += 4; cur += 4;
+ buf += 4; cur += 4; /* unused by decoder */
+
+ init_get_bits(&ctx->gb, buf, (skip - cur) * 8);
+ if(tm2_build_huff_table(ctx, &codes) == -1)
+ return -1;
+ buf += ((get_bits_count(&ctx->gb) + 31) >> 5) << 2;
+ cur += ((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 -1;
+ }
+ ctx->tokens[stream_id] = av_realloc(ctx->tokens[stream_id], toks * sizeof(int));
+ ctx->tok_lens[stream_id] = toks;
+ len = BE_32(buf); buf += 4; cur += 4;
+ if(len > 0) {
+ init_get_bits(&ctx->gb, buf, (skip - cur) * 8);
+ for(i = 0; i < toks; i++)
+ ctx->tokens[stream_id][i] = tm2_get_token(&ctx->gb, &codes);
+ } else {
+ for(i = 0; i < toks; i++)
+ ctx->tokens[stream_id][i] = codes.recode[0];
+ }
+ 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)
+ 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->avctx->width;\
+ Vstride = (ctx->avctx->width + 1) >> 1;\
+ Ustride = (ctx->avctx->width + 1) >> 1;\
+ 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] - 128) - last[1];\
+ CD[1] = (int)CHR[stride + 1] - (int)CHR[1];\
+ last[0] = (int)CHR[stride + 0] - 128;\
+ last[1] = (int)CHR[stride + 1] - 128;}
+
+/* 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] = 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] + 128;
+ }
+ 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);
+
+ 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 bw, bh;
+ int type;
+ int keyframe = 1;
+ uint8_t *Y, *U, *V;
+ int *src;
+
+ bw = ctx->avctx->width >> 2;
+ bh = ctx->avctx->height >> 2;
+
+ for(i = 0; i < TM2_NUM_STREAMS; i++)
+ ctx->tok_ptrs[i] = 0;
+
+ if (ctx->tok_lens[TM2_TYPE]<bw*bh){
+ av_log(ctx->avctx,AV_LOG_ERROR,"Got %i tokens for %i blocks\n",ctx->tok_lens[TM2_TYPE],bw*bh);
+ return -1;
+ }
+
+ 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 = p->data[0];
+ src = (ctx->cur?ctx->Y2:ctx->Y1);
+ for(j = 0; j < ctx->avctx->height; j++){
+ for(i = 0; i < ctx->avctx->width; i++){
+ Y[i] = clip_uint8(*src++);
+ }
+ Y += p->linesize[0];
+ }
+ U = p->data[2];
+ src = (ctx->cur?ctx->U2:ctx->U1);
+ for(j = 0; j < (ctx->avctx->height + 1) >> 1; j++){
+ for(i = 0; i < (ctx->avctx->width + 1) >> 1; i++){
+ U[i] = clip_uint8(*src++);
+ }
+ U += p->linesize[2];
+ }
+ V = p->data[1];
+ src = (ctx->cur?ctx->V2:ctx->V1);
+ for(j = 0; j < (ctx->avctx->height + 1) >> 1; j++){
+ for(i = 0; i < (ctx->avctx->width + 1) >> 1; i++){
+ V[i] = clip_uint8(*src++);
+ }
+ V += p->linesize[1];
+ }
+
+ return keyframe;
+}
+
+static int decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ TM2Context * const l = avctx->priv_data;
+ AVFrame * const p= (AVFrame*)&l->pic;
+ int skip, t;
+
+ p->reference = 1;
+ p->buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
+ if(avctx->reget_buffer(avctx, p) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ l->dsp.bswap_buf((uint32_t*)buf, (uint32_t*)buf, buf_size >> 2);
+ skip = tm2_read_header(l, buf);
+
+ if(skip == -1)
+ return -1;
+
+ t = tm2_read_stream(l, buf + skip, TM2_C_HI);
+ if(t == -1)
+ return -1;
+ skip += t;
+ t = tm2_read_stream(l, buf + skip, TM2_C_LO);
+ if(t == -1)
+ return -1;
+ skip += t;
+ t = tm2_read_stream(l, buf + skip, TM2_L_HI);
+ if(t == -1)
+ return -1;
+ skip += t;
+ t = tm2_read_stream(l, buf + skip, TM2_L_LO);
+ if(t == -1)
+ return -1;
+ skip += t;
+ t = tm2_read_stream(l, buf + skip, TM2_UPD);
+ if(t == -1)
+ return -1;
+ skip += t;
+ t = tm2_read_stream(l, buf + skip, TM2_MOT);
+ if(t == -1)
+ return -1;
+ skip += t;
+ t = tm2_read_stream(l, buf + skip, TM2_TYPE);
+ if(t == -1)
+ return -1;
+ p->key_frame = tm2_decode_blocks(l, p);
+ if(p->key_frame)
+ p->pict_type = FF_I_TYPE;
+ else
+ p->pict_type = FF_P_TYPE;
+
+ l->cur = !l->cur;
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = l->pic;
+
+ return buf_size;
+}
+
+static int decode_init(AVCodecContext *avctx){
+ TM2Context * const l = avctx->priv_data;
+ int i;
+
+ if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
+ return -1;
+ }
+ if((avctx->width & 3) || (avctx->height & 3)){
+ av_log(avctx, AV_LOG_ERROR, "Width and height must be multiple of 4\n");
+ return -1;
+ }
+
+ l->avctx = avctx;
+ l->pic.data[0]=NULL;
+ avctx->has_b_frames = 0;
+ avctx->pix_fmt = PIX_FMT_YUV420P;
+
+ dsputil_init(&l->dsp, avctx);
+
+ l->last = av_malloc(4 * sizeof(int) * (avctx->width >> 2));
+ l->clast = av_malloc(4 * sizeof(int) * (avctx->width >> 2));
+
+ for(i = 0; i < TM2_NUM_STREAMS; i++) {
+ l->tokens[i] = NULL;
+ l->tok_lens[i] = 0;
+ }
+
+ l->Y1 = av_malloc(sizeof(int) * avctx->width * avctx->height);
+ l->U1 = av_malloc(sizeof(int) * ((avctx->width + 1) >> 1) * ((avctx->height + 1) >> 1));
+ l->V1 = av_malloc(sizeof(int) * ((avctx->width + 1) >> 1) * ((avctx->height + 1) >> 1));
+ l->Y2 = av_malloc(sizeof(int) * avctx->width * avctx->height);
+ l->U2 = av_malloc(sizeof(int) * ((avctx->width + 1) >> 1) * ((avctx->height + 1) >> 1));
+ l->V2 = av_malloc(sizeof(int) * ((avctx->width + 1) >> 1) * ((avctx->height + 1) >> 1));
+ l->cur = 0;
+
+ return 0;
+}
+
+static int decode_end(AVCodecContext *avctx){
+ TM2Context * const l = avctx->priv_data;
+ int i;
+
+ if(l->last)
+ av_free(l->last);
+ if(l->clast)
+ av_free(l->clast);
+ for(i = 0; i < TM2_NUM_STREAMS; i++)
+ if(l->tokens[i])
+ av_free(l->tokens[i]);
+ if(l->Y1){
+ av_free(l->Y1);
+ av_free(l->U1);
+ av_free(l->V1);
+ av_free(l->Y2);
+ av_free(l->U2);
+ av_free(l->V2);
+ }
+ return 0;
+}
+
+AVCodec truemotion2_decoder = {
+ "truemotion2",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_TRUEMOTION2,
+ sizeof(TM2Context),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/truespeech.c b/contrib/ffmpeg/libavcodec/truespeech.c
new file mode 100644
index 000000000..077e9b037
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/truespeech.c
@@ -0,0 +1,381 @@
+/*
+ * 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 "avcodec.h"
+
+#include "truespeech_data.h"
+/**
+ * @file truespeech.c
+ * TrueSpeech decoder.
+ */
+
+/**
+ * TrueSpeech decoder context
+ */
+typedef struct {
+ /* input data */
+ 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 int truespeech_decode_init(AVCodecContext * avctx)
+{
+// TSContext *c = avctx->priv_data;
+
+ return 0;
+}
+
+static void truespeech_read_frame(TSContext *dec, uint8_t *input)
+{
+ uint32_t t;
+
+ /* first dword */
+ t = LE_32(input);
+ input += 4;
+
+ dec->flag = t & 1;
+
+ dec->vector[0] = ts_codebook[0][(t >> 1) & 0x1F];
+ dec->vector[1] = ts_codebook[1][(t >> 6) & 0x1F];
+ dec->vector[2] = ts_codebook[2][(t >> 11) & 0xF];
+ dec->vector[3] = ts_codebook[3][(t >> 15) & 0xF];
+ dec->vector[4] = ts_codebook[4][(t >> 19) & 0xF];
+ dec->vector[5] = ts_codebook[5][(t >> 23) & 0x7];
+ dec->vector[6] = ts_codebook[6][(t >> 26) & 0x7];
+ dec->vector[7] = ts_codebook[7][(t >> 29) & 0x7];
+
+ /* second dword */
+ t = LE_32(input);
+ input += 4;
+
+ dec->offset2[0] = (t >> 0) & 0x7F;
+ dec->offset2[1] = (t >> 7) & 0x7F;
+ dec->offset2[2] = (t >> 14) & 0x7F;
+ dec->offset2[3] = (t >> 21) & 0x7F;
+
+ dec->offset1[0] = ((t >> 28) & 0xF) << 4;
+
+ /* third dword */
+ t = LE_32(input);
+ input += 4;
+
+ dec->pulseval[0] = (t >> 0) & 0x3FFF;
+ dec->pulseval[1] = (t >> 14) & 0x3FFF;
+
+ dec->offset1[1] = (t >> 28) & 0x0F;
+
+ /* fourth dword */
+ t = LE_32(input);
+ input += 4;
+
+ dec->pulseval[2] = (t >> 0) & 0x3FFF;
+ dec->pulseval[3] = (t >> 14) & 0x3FFF;
+
+ dec->offset1[1] |= ((t >> 28) & 0x0F) << 4;
+
+ /* fifth dword */
+ t = LE_32(input);
+ input += 4;
+
+ dec->pulsepos[0] = (t >> 4) & 0x7FFFFFF;
+
+ dec->pulseoff[0] = (t >> 0) & 0xF;
+
+ dec->offset1[0] |= (t >> 31) & 1;
+
+ /* sixth dword */
+ t = LE_32(input);
+ input += 4;
+
+ dec->pulsepos[1] = (t >> 4) & 0x7FFFFFF;
+
+ dec->pulseoff[1] = (t >> 0) & 0xF;
+
+ dec->offset1[0] |= ((t >> 31) & 1) << 1;
+
+ /* seventh dword */
+ t = LE_32(input);
+ input += 4;
+
+ dec->pulsepos[2] = (t >> 4) & 0x7FFFFFF;
+
+ dec->pulseoff[2] = (t >> 0) & 0xF;
+
+ dec->offset1[0] |= ((t >> 31) & 1) << 2;
+
+ /* eighth dword */
+ t = LE_32(input);
+ input += 4;
+
+ dec->pulsepos[3] = (t >> 4) & 0x7FFFFFF;
+
+ dec->pulseoff[3] = (t >> 0) & 0xF;
+
+ dec->offset1[0] |= ((t >> 31) & 1) << 3;
+
+}
+
+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 * 2);
+ 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_230[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 * 2);
+ return;
+ }
+ for(i = 0; i < 146; i++)
+ tmp[i] = dec->filtbuf[i];
+ off = (t / 25) + dec->offset1[quart >> 1] + 18;
+ ptr0 = tmp + 145 - off;
+ ptr1 = tmp + 146;
+ filter = (const int16_t*)ts_240 + (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 * 2);
+ for(i = 0; i < 7; i++) {
+ t = dec->pulseval[quart] & 3;
+ dec->pulseval[quart] >>= 2;
+ tmp[6 - i] = ts_562[dec->pulseoff[quart] * 4 + t];
+ }
+
+ coef = dec->pulsepos[quart] >> 15;
+ ptr1 = (const int16_t*)ts_140 + 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 = (const int16_t*)ts_140;
+ 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;
+
+ for(i = 0; i < 86; i++)
+ dec->filtbuf[i] = dec->filtbuf[i + 60];
+ 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] = 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_5E2[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_5F2[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] = clip((sum + 0x800) >> 12, -0x7FFE, 0x7FFE);
+
+ sum = ((ptr0[1] * (dec->filtval - (dec->filtval >> 2))) >> 4) + sum;
+ sum = sum - (sum >> 3);
+ out[i] = 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 *data_size,
+ uint8_t *buf, int buf_size)
+{
+ TSContext *c = avctx->priv_data;
+
+ int i;
+ short *samples = data;
+ int consumed = 0;
+ int16_t out_buf[240];
+
+ if (!buf_size)
+ return 0;
+
+ while (consumed < buf_size) {
+ truespeech_read_frame(c, buf + consumed);
+ consumed += 32;
+
+ truespeech_correlate_filter(c);
+ truespeech_filters_merge(c);
+
+ memset(out_buf, 0, 240 * 2);
+ for(i = 0; i < 4; i++) {
+ truespeech_apply_twopoint_filter(c, i);
+ truespeech_place_pulses(c, out_buf + i * 60, i);
+ truespeech_update_filters(c, out_buf + i * 60, i);
+ truespeech_synth(c, out_buf + i * 60, i);
+ }
+
+ truespeech_save_prevvec(c);
+
+ /* finally output decoded frame */
+ for(i = 0; i < 240; i++)
+ *samples++ = out_buf[i];
+
+ }
+
+ *data_size = consumed * 15;
+
+ return buf_size;
+}
+
+AVCodec truespeech_decoder = {
+ "truespeech",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_TRUESPEECH,
+ sizeof(TSContext),
+ truespeech_decode_init,
+ NULL,
+ NULL,
+ truespeech_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/truespeech_data.h b/contrib/ffmpeg/libavcodec/truespeech_data.h
new file mode 100644
index 000000000..cd8822fde
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/truespeech_data.h
@@ -0,0 +1,157 @@
+/*
+ * 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 __TRUESPEECH_DATA__
+#define __TRUESPEECH_DATA__
+
+/* 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 *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_140[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_230[8] =
+ { 0x7F3B, 0x7E78, 0x7DB6, 0x7CF5, 0x7C35, 0x7B76, 0x7AB8, 0x79FC };
+
+/* two-point filters table */
+static const int16_t ts_240[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_562[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_5E2[8] =
+ { 0x4666, 0x26B8, 0x154C, 0x0BB6, 0x0671, 0x038B, 0x01F3, 0x0112 };
+static const int16_t ts_5F2[8] =
+ { 0x6000, 0x4800, 0x3600, 0x2880, 0x1E60, 0x16C8, 0x1116, 0x0CD1 };
+
+#endif
diff --git a/contrib/ffmpeg/libavcodec/tscc.c b/contrib/ffmpeg/libavcodec/tscc.c
new file mode 100644
index 000000000..a24540f37
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/tscc.c
@@ -0,0 +1,348 @@
+/*
+ * 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 tscc.c
+ * 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 <stdio.h>
+#include <stdlib.h>
+
+#include "common.h"
+#include "avcodec.h"
+
+#ifdef CONFIG_ZLIB
+#include <zlib.h>
+#endif
+
+
+/*
+ * Decoder context
+ */
+typedef struct TsccContext {
+
+ AVCodecContext *avctx;
+ AVFrame pic;
+
+ // Bits per pixel
+ int bpp;
+ // Decompressed data size
+ unsigned int decomp_size;
+ // Decompression buffer
+ unsigned char* decomp_buf;
+ int height;
+#ifdef CONFIG_ZLIB
+ z_stream zstream;
+#endif
+} CamtasiaContext;
+
+/*
+ *
+ * Decode RLE - almost identical to Windows BMP RLE8
+ * and enhanced to bigger color depths
+ *
+ */
+
+static int decode_rle(CamtasiaContext *c, unsigned int srcsize)
+{
+ unsigned char *src = c->decomp_buf;
+ unsigned char *output, *output_end;
+ int p1, p2, line=c->height, pos=0, i;
+ uint16_t pix16;
+ uint32_t pix32;
+
+ output = c->pic.data[0] + (c->height - 1) * c->pic.linesize[0];
+ output_end = c->pic.data[0] + (c->height) * c->pic.linesize[0];
+ while(src < c->decomp_buf + srcsize) {
+ p1 = *src++;
+ if(p1 == 0) { //Escape code
+ p2 = *src++;
+ if(p2 == 0) { //End-of-line
+ output = c->pic.data[0] + (--line) * c->pic.linesize[0];
+ if (line < 0)
+ return -1;
+ pos = 0;
+ continue;
+ } else if(p2 == 1) { //End-of-picture
+ return 0;
+ } else if(p2 == 2) { //Skip
+ p1 = *src++;
+ p2 = *src++;
+ line -= p2;
+ if (line < 0)
+ return -1;
+ pos += p1;
+ output = c->pic.data[0] + line * c->pic.linesize[0] + pos * (c->bpp / 8);
+ continue;
+ }
+ // Copy data
+ if (output + p2 * (c->bpp / 8) > output_end) {
+ src += p2 * (c->bpp / 8);
+ continue;
+ }
+ if ((c->bpp == 8) || (c->bpp == 24)) {
+ for(i = 0; i < p2 * (c->bpp / 8); i++) {
+ *output++ = *src++;
+ }
+ // RLE8 copy is actually padded - and runs are not!
+ if(c->bpp == 8 && (p2 & 1)) {
+ src++;
+ }
+ } else if (c->bpp == 16) {
+ for(i = 0; i < p2; i++) {
+ pix16 = LE_16(src);
+ src += 2;
+ *(uint16_t*)output = pix16;
+ output += 2;
+ }
+ } else if (c->bpp == 32) {
+ for(i = 0; i < p2; i++) {
+ pix32 = LE_32(src);
+ src += 4;
+ *(uint32_t*)output = pix32;
+ output += 4;
+ }
+ }
+ pos += p2;
+ } else { //Run of pixels
+ int pix[4]; //original pixel
+ switch(c->bpp){
+ case 8: pix[0] = *src++;
+ break;
+ case 16: pix16 = LE_16(src);
+ src += 2;
+ *(uint16_t*)pix = pix16;
+ break;
+ case 24: pix[0] = *src++;
+ pix[1] = *src++;
+ pix[2] = *src++;
+ break;
+ case 32: pix32 = LE_32(src);
+ src += 4;
+ *(uint32_t*)pix = pix32;
+ break;
+ }
+ if (output + p1 * (c->bpp / 8) > output_end)
+ continue;
+ for(i = 0; i < p1; i++) {
+ switch(c->bpp){
+ case 8: *output++ = pix[0];
+ break;
+ case 16: *(uint16_t*)output = pix16;
+ output += 2;
+ break;
+ case 24: *output++ = pix[0];
+ *output++ = pix[1];
+ *output++ = pix[2];
+ break;
+ case 32: *(uint32_t*)output = pix32;
+ output += 4;
+ break;
+ }
+ }
+ pos += p1;
+ }
+ }
+
+ av_log(c->avctx, AV_LOG_ERROR, "Camtasia warning: no End-of-picture code\n");
+ return 1;
+}
+
+/*
+ *
+ * Decode a frame
+ *
+ */
+static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size)
+{
+ CamtasiaContext * const c = (CamtasiaContext *)avctx->priv_data;
+ unsigned char *encoded = (unsigned char *)buf;
+ unsigned char *outptr;
+#ifdef CONFIG_ZLIB
+ int zret; // Zlib return code
+#endif
+ int len = buf_size;
+
+ if(c->pic.data[0])
+ avctx->release_buffer(avctx, &c->pic);
+
+ c->pic.reference = 1;
+ c->pic.buffer_hints = FF_BUFFER_HINTS_VALID;
+ if(avctx->get_buffer(avctx, &c->pic) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ outptr = c->pic.data[0]; // Output image pointer
+
+#ifdef CONFIG_ZLIB
+ zret = inflateReset(&(c->zstream));
+ if (zret != Z_OK) {
+ av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret);
+ return -1;
+ }
+ c->zstream.next_in = 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 -1;
+ }
+
+
+ if(zret != Z_DATA_ERROR)
+ decode_rle(c, c->zstream.avail_out);
+
+ /* make the palette available on the way out */
+ if (c->avctx->pix_fmt == PIX_FMT_PAL8) {
+ memcpy(c->pic.data[1], c->avctx->palctrl->palette, AVPALETTE_SIZE);
+ if (c->avctx->palctrl->palette_changed) {
+ c->pic.palette_has_changed = 1;
+ c->avctx->palctrl->palette_changed = 0;
+ }
+ }
+
+#else
+ av_log(avctx, AV_LOG_ERROR, "BUG! Zlib support not compiled in frame decoder.\n");
+ return -1;
+#endif
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = c->pic;
+
+ /* always report that the buffer was completely consumed */
+ return buf_size;
+}
+
+
+
+/*
+ *
+ * Init tscc decoder
+ *
+ */
+static int decode_init(AVCodecContext *avctx)
+{
+ CamtasiaContext * const c = (CamtasiaContext *)avctx->priv_data;
+ int zret; // Zlib return code
+
+ c->avctx = avctx;
+ avctx->has_b_frames = 0;
+
+ c->pic.data[0] = NULL;
+ c->height = avctx->height;
+
+ if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
+ return 1;
+ }
+
+#ifdef CONFIG_ZLIB
+ // Needed if zlib unused or init aborted before inflateInit
+ memset(&(c->zstream), 0, sizeof(z_stream));
+#else
+ av_log(avctx, AV_LOG_ERROR, "Zlib support not compiled.\n");
+ return 1;
+#endif
+ switch(avctx->bits_per_sample){
+ case 8: avctx->pix_fmt = PIX_FMT_PAL8; break;
+ case 16: avctx->pix_fmt = PIX_FMT_RGB555; break;
+ case 24:
+ avctx->pix_fmt = PIX_FMT_BGR24;
+ break;
+ case 32: avctx->pix_fmt = PIX_FMT_RGBA32; break;
+ default: av_log(avctx, AV_LOG_ERROR, "Camtasia error: unknown depth %i bpp\n", avctx->bits_per_sample);
+ return -1;
+ }
+ c->bpp = avctx->bits_per_sample;
+ c->decomp_size = (avctx->width * c->bpp + (avctx->width + 254) / 255 + 2) * avctx->height + 2;//RLE in the 'best' case
+
+ /* 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 1;
+ }
+ }
+
+#ifdef CONFIG_ZLIB
+ 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 1;
+ }
+#endif
+
+ return 0;
+}
+
+
+
+/*
+ *
+ * Uninit tscc decoder
+ *
+ */
+static int decode_end(AVCodecContext *avctx)
+{
+ CamtasiaContext * const c = (CamtasiaContext *)avctx->priv_data;
+
+ av_freep(&c->decomp_buf);
+
+ if (c->pic.data[0])
+ avctx->release_buffer(avctx, &c->pic);
+#ifdef CONFIG_ZLIB
+ inflateEnd(&(c->zstream));
+#endif
+
+ return 0;
+}
+
+AVCodec tscc_decoder = {
+ "camtasia",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_TSCC,
+ sizeof(CamtasiaContext),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
+
diff --git a/contrib/ffmpeg/libavcodec/tta.c b/contrib/ffmpeg/libavcodec/tta.c
new file mode 100644
index 000000000..82713fb0f
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/tta.c
@@ -0,0 +1,446 @@
+/*
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file tta.c
+ * TTA (The Lossless True Audio) decoder
+ * (www.true-audio.com or tta.corecodec.org)
+ * @author Alex Beregszaszi
+ *
+ */
+
+#define ALT_BITSTREAM_READER_LE
+//#define DEBUG
+#include <limits.h>
+#include "avcodec.h"
+#include "bitstream.h"
+
+#define FORMAT_INT 1
+#define FORMAT_FLOAT 3
+
+typedef struct TTAContext {
+ AVCodecContext *avctx;
+ GetBitContext gb;
+
+ int flags, channels, bps, is_float, data_length;
+ int frame_length, last_frame_length, total_frames;
+
+ int32_t *decode_buffer;
+} TTAContext;
+
+#if 0
+static inline int shift_1(int i)
+{
+ if (i < 32)
+ return 1 << i;
+ else
+ return 0x80000000; // 16 << 31
+}
+
+static inline int shift_16(int i)
+{
+ if (i < 28)
+ return 16 << i;
+ else
+ return 0x80000000; // 16 << 27
+}
+#else
+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 *shift_16 = shift_1 + 4;
+#endif
+
+#define MAX_ORDER 16
+typedef struct TTAFilter {
+ int32_t shift, round, error, mode;
+ int32_t qm[MAX_ORDER];
+ int32_t dx[MAX_ORDER];
+ int32_t dl[MAX_ORDER];
+} TTAFilter;
+
+static int32_t ttafilter_configs[4][2] = {
+ {10, 1},
+ {9, 1},
+ {10, 1},
+ {12, 0}
+};
+
+static void ttafilter_init(TTAFilter *c, int32_t shift, int32_t mode) {
+ memset(c, 0, sizeof(TTAFilter));
+ c->shift = shift;
+ c->round = shift_1[shift-1];
+// c->round = 1 << (shift - 1);
+ c->mode = mode;
+}
+
+// FIXME: copy paste from original
+static inline void memshl(register int32_t *a, register int32_t *b) {
+ *a++ = *b++;
+ *a++ = *b++;
+ *a++ = *b++;
+ *a++ = *b++;
+ *a++ = *b++;
+ *a++ = *b++;
+ *a++ = *b++;
+ *a = *b;
+}
+
+// FIXME: copy paste from original
+// mode=1 encoder, mode=0 decoder
+static inline void ttafilter_process(TTAFilter *c, int32_t *in, int32_t mode) {
+ register int32_t *dl = c->dl, *qm = c->qm, *dx = c->dx, sum = c->round;
+
+ if (!c->error) {
+ sum += *dl++ * *qm, qm++;
+ sum += *dl++ * *qm, qm++;
+ sum += *dl++ * *qm, qm++;
+ sum += *dl++ * *qm, qm++;
+ sum += *dl++ * *qm, qm++;
+ sum += *dl++ * *qm, qm++;
+ sum += *dl++ * *qm, qm++;
+ sum += *dl++ * *qm, qm++;
+ dx += 8;
+ } else if(c->error < 0) {
+ sum += *dl++ * (*qm -= *dx++), qm++;
+ sum += *dl++ * (*qm -= *dx++), qm++;
+ sum += *dl++ * (*qm -= *dx++), qm++;
+ sum += *dl++ * (*qm -= *dx++), qm++;
+ sum += *dl++ * (*qm -= *dx++), qm++;
+ sum += *dl++ * (*qm -= *dx++), qm++;
+ sum += *dl++ * (*qm -= *dx++), qm++;
+ sum += *dl++ * (*qm -= *dx++), qm++;
+ } else {
+ sum += *dl++ * (*qm += *dx++), qm++;
+ sum += *dl++ * (*qm += *dx++), qm++;
+ sum += *dl++ * (*qm += *dx++), qm++;
+ sum += *dl++ * (*qm += *dx++), qm++;
+ sum += *dl++ * (*qm += *dx++), qm++;
+ sum += *dl++ * (*qm += *dx++), qm++;
+ sum += *dl++ * (*qm += *dx++), qm++;
+ sum += *dl++ * (*qm += *dx++), qm++;
+ }
+
+ *(dx-0) = ((*(dl-1) >> 30) | 1) << 2;
+ *(dx-1) = ((*(dl-2) >> 30) | 1) << 1;
+ *(dx-2) = ((*(dl-3) >> 30) | 1) << 1;
+ *(dx-3) = ((*(dl-4) >> 30) | 1);
+
+ // compress
+ if (mode) {
+ *dl = *in;
+ *in -= (sum >> c->shift);
+ c->error = *in;
+ } else {
+ c->error = *in;
+ *in += (sum >> c->shift);
+ *dl = *in;
+ }
+
+ if (c->mode) {
+ *(dl-1) = *dl - *(dl-1);
+ *(dl-2) = *(dl-1) - *(dl-2);
+ *(dl-3) = *(dl-2) - *(dl-3);
+ }
+
+ memshl(c->dl, c->dl + 1);
+ memshl(c->dx, c->dx + 1);
+}
+
+typedef struct TTARice {
+ uint32_t k0, k1, sum0, sum1;
+} TTARice;
+
+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_bits1(gb))
+ ret++;
+ return ret;
+}
+
+static int tta_decode_init(AVCodecContext * avctx)
+{
+ TTAContext *s = avctx->priv_data;
+ int i;
+
+ s->avctx = avctx;
+
+ // 30bytes includes a seektable with one frame
+ if (avctx->extradata_size < 30)
+ return -1;
+
+ init_get_bits(&s->gb, avctx->extradata, avctx->extradata_size);
+ if (show_bits_long(&s->gb, 32) == ff_get_fourcc("TTA1"))
+ {
+ /* signature */
+ skip_bits(&s->gb, 32);
+// if (get_bits_long(&s->gb, 32) != bswap_32(ff_get_fourcc("TTA1"))) {
+// av_log(s->avctx, AV_LOG_ERROR, "Missing magic\n");
+// return -1;
+// }
+
+ s->flags = get_bits(&s->gb, 16);
+ if (s->flags != 1 && s->flags != 3)
+ {
+ av_log(s->avctx, AV_LOG_ERROR, "Invalid flags\n");
+ return -1;
+ }
+ s->is_float = (s->flags == FORMAT_FLOAT);
+ avctx->channels = s->channels = get_bits(&s->gb, 16);
+ avctx->bits_per_sample = get_bits(&s->gb, 16);
+ s->bps = (avctx->bits_per_sample + 7) / 8;
+ avctx->sample_rate = get_bits_long(&s->gb, 32);
+ if(avctx->sample_rate > 1000000){ //prevent FRAME_TIME * avctx->sample_rate from overflowing and sanity check
+ av_log(avctx, AV_LOG_ERROR, "sample_rate too large\n");
+ return -1;
+ }
+ s->data_length = get_bits_long(&s->gb, 32);
+ skip_bits(&s->gb, 32); // CRC32 of header
+
+ if (s->is_float)
+ {
+ avctx->sample_fmt = SAMPLE_FMT_FLT;
+ av_log(s->avctx, AV_LOG_ERROR, "Unsupported sample format. Please contact the developers.\n");
+ return -1;
+ }
+ else switch(s->bps) {
+// case 1: avctx->sample_fmt = SAMPLE_FMT_U8; break;
+ case 2: avctx->sample_fmt = SAMPLE_FMT_S16; break;
+// case 3: avctx->sample_fmt = SAMPLE_FMT_S24; break;
+ case 4: avctx->sample_fmt = SAMPLE_FMT_S32; break;
+ default:
+ av_log(s->avctx, AV_LOG_ERROR, "Invalid/unsupported sample format. Please contact the developers.\n");
+ return -1;
+ }
+
+ // FIXME: horribly broken, but directly from reference source
+#define FRAME_TIME 1.04489795918367346939
+ s->frame_length = (int)(FRAME_TIME * avctx->sample_rate);
+
+ s->last_frame_length = s->data_length % s->frame_length;
+ s->total_frames = s->data_length / s->frame_length +
+ (s->last_frame_length ? 1 : 0);
+
+ av_log(s->avctx, AV_LOG_DEBUG, "flags: %x chans: %d bps: %d rate: %d block: %d\n",
+ s->flags, avctx->channels, avctx->bits_per_sample, avctx->sample_rate,
+ avctx->block_align);
+ av_log(s->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, s->total_frames);
+
+ // FIXME: seek table
+ for (i = 0; i < s->total_frames; i++)
+ skip_bits(&s->gb, 32);
+ skip_bits(&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 -1;
+ }
+
+ s->decode_buffer = av_mallocz(sizeof(int32_t)*s->frame_length*s->channels);
+ } else {
+ av_log(avctx, AV_LOG_ERROR, "Wrong extradata present\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int tta_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ TTAContext *s = avctx->priv_data;
+ int i;
+
+ init_get_bits(&s->gb, buf, buf_size*8);
+ {
+ int32_t predictors[s->channels];
+ TTAFilter filters[s->channels];
+ TTARice rices[s->channels];
+ int cur_chan = 0, framelen = s->frame_length;
+ int32_t *p;
+
+ // FIXME: seeking
+ s->total_frames--;
+ if (!s->total_frames && s->last_frame_length)
+ framelen = s->last_frame_length;
+
+ // init per channel states
+ for (i = 0; i < s->channels; i++) {
+ predictors[i] = 0;
+ ttafilter_init(&(filters[i]), ttafilter_configs[s->bps-1][0], ttafilter_configs[s->bps-1][1]);
+ rice_init(&(rices[i]), 10, 10);
+ }
+
+ for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++) {
+ int32_t *predictor = &(predictors[cur_chan]);
+ TTAFilter *filter = &(filters[cur_chan]);
+ TTARice *rice = &(rices[cur_chan]);
+ 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 (k)
+ 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
+#define UNFOLD(x) (((x)&1) ? (++(x)>>1) : (-(x)>>1))
+ *p = UNFOLD(value);
+
+ // run hybrid filter
+ ttafilter_process(filter, p, 0);
+
+ // 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;
+
+#if 0
+ // extract 32bit float from last two int samples
+ if (s->is_float && ((p - data) & 1)) {
+ uint32_t neg = *p & 0x80000000;
+ uint32_t hi = *(p - 1);
+ uint32_t lo = abs(*p) - 1;
+
+ hi += (hi || lo) ? 0x3f80 : 0;
+ // SWAP16: swap all the 16 bits
+ *(p - 1) = (hi << 16) | SWAP16(lo) | neg;
+ }
+#endif
+
+ /*if ((get_bits_count(&s->gb)+7)/8 > buf_size)
+ {
+ av_log(NULL, AV_LOG_INFO, "overread!!\n");
+ break;
+ }*/
+
+ // flip channels
+ if (cur_chan < (s->channels-1))
+ cur_chan++;
+ else {
+ // decorrelate in case of stereo integer
+ if (!s->is_float && (s->channels > 1)) {
+ int32_t *r = p - 1;
+ for (*p += *r / 2; r > p - s->channels; r--)
+ *r = *(r + 1) - *r;
+ }
+ cur_chan = 0;
+ }
+ }
+
+ skip_bits(&s->gb, 32); // frame crc
+
+ // convert to output buffer
+ switch(s->bps) {
+ case 2: {
+ uint16_t *samples = data;
+ for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++) {
+// *samples++ = (unsigned char)*p;
+// *samples++ = (unsigned char)(*p >> 8);
+ *samples++ = *p;
+ }
+ *data_size = (uint8_t *)samples - (uint8_t *)data;
+ break;
+ }
+ default:
+ av_log(s->avctx, AV_LOG_ERROR, "Error, only 16bit samples supported!\n");
+ }
+ }
+
+// return get_bits_count(&s->gb)+7)/8;
+ return buf_size;
+}
+
+static int tta_decode_close(AVCodecContext *avctx) {
+ TTAContext *s = avctx->priv_data;
+
+ if (s->decode_buffer)
+ av_free(s->decode_buffer);
+
+ return 0;
+}
+
+AVCodec tta_decoder = {
+ "tta",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_TTA,
+ sizeof(TTAContext),
+ tta_decode_init,
+ NULL,
+ tta_decode_close,
+ tta_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/ulti.c b/contrib/ffmpeg/libavcodec/ulti.c
new file mode 100644
index 000000000..b4028f439
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ulti.c
@@ -0,0 +1,428 @@
+/*
+ * 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 ulti.c
+ * IBM Ultimotion Video Decoder.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+
+#include "ulti_cb.h"
+
+typedef struct UltimotionDecodeContext {
+ AVCodecContext *avctx;
+ int width, height, blocks;
+ AVFrame frame;
+ const uint8_t *ulti_codebook;
+} UltimotionDecodeContext;
+
+static 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 = PIX_FMT_YUV410P;
+ avctx->has_b_frames = 0;
+ avctx->coded_frame = (AVFrame*) &s->frame;
+ s->ulti_codebook = ulti_codebook;
+
+ return 0;
+}
+
+static int block_coords[8] = // 4x4 block coords in 8x8 superblock
+ { 0, 0, 0, 4, 4, 4, 4, 0};
+
+static int angle_by_index[4] = { 0, 2, 6, 12};
+
+/* Lookup tables for luma and chroma - used by ulti_convert_yuv() */
+static 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 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 *data_size,
+ uint8_t *buf, int buf_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;
+ int skip;
+ int tmp;
+
+ if(s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ s->frame.reference = 1;
+ s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
+ if(avctx->get_buffer(avctx, &s->frame) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ while(!done) {
+ int idx;
+ if(blocks >= s->blocks || y >= s->height)
+ break;//all blocks decoded
+
+ idx = *buf++;
+ if((idx & 0xF8) == 0x70) {
+ switch(idx) {
+ case 0x70: //change modifier
+ modifier = *buf++;
+ 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 = *buf++;
+ 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 = *buf++;
+ }
+ 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 = *buf++;
+ tx = x + block_coords[i * 2];
+ ty = y + block_coords[(i * 2) + 1];
+ switch(code) {
+ case 1:
+ tmp = *buf++;
+
+ 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 = (*buf++) << 16;
+ tmp += (*buf++) << 8;
+ tmp += *buf++;
+
+ 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 = (*buf++) << 8;
+ tmp += (*buf++);
+
+ 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];
+
+ tmp = (*buf++) << 16;
+ tmp += (*buf++) << 8;
+ tmp += *buf++;
+ Luma[0] = (tmp >> 18) & 0x3F;
+ Luma[1] = (tmp >> 12) & 0x3F;
+ Luma[2] = (tmp >> 6) & 0x3F;
+ Luma[3] = tmp & 0x3F;
+
+ tmp = (*buf++) << 16;
+ tmp += (*buf++) << 8;
+ tmp += *buf++;
+ Luma[4] = (tmp >> 18) & 0x3F;
+ Luma[5] = (tmp >> 12) & 0x3F;
+ Luma[6] = (tmp >> 6) & 0x3F;
+ Luma[7] = tmp & 0x3F;
+
+ tmp = (*buf++) << 16;
+ tmp += (*buf++) << 8;
+ tmp += *buf++;
+ Luma[8] = (tmp >> 18) & 0x3F;
+ Luma[9] = (tmp >> 12) & 0x3F;
+ Luma[10] = (tmp >> 6) & 0x3F;
+ Luma[11] = tmp & 0x3F;
+
+ tmp = (*buf++) << 16;
+ tmp += (*buf++) << 8;
+ tmp += *buf++;
+ 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 {
+ tmp = *buf++;
+ if(tmp & 0x80) {
+ angle = (tmp >> 4) & 0x7;
+ tmp = (tmp << 8) + *buf++;
+ Y[0] = (tmp >> 6) & 0x3F;
+ Y[1] = tmp & 0x3F;
+ Y[2] = (*buf++) & 0x3F;
+ Y[3] = (*buf++) & 0x3F;
+ ulti_grad(&s->frame, tx, ty, Y, chroma, angle); //draw block
+ } else { // some patterns
+ int f0, f1;
+ f0 = *buf++;
+ f1 = tmp;
+ Y[0] = (*buf++) & 0x3F;
+ Y[1] = (*buf++) & 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;
+ }
+ }
+ }
+
+ *data_size=sizeof(AVFrame);
+ *(AVFrame*)data= s->frame;
+
+ return buf_size;
+}
+
+static int ulti_decode_end(AVCodecContext *avctx)
+{
+/* UltimotionDecodeContext *s = avctx->priv_data;*/
+
+ return 0;
+}
+
+AVCodec ulti_decoder = {
+ "ultimotion",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_ULTI,
+ sizeof(UltimotionDecodeContext),
+ ulti_decode_init,
+ NULL,
+ ulti_decode_end,
+ ulti_decode_frame,
+ CODEC_CAP_DR1,
+ NULL
+};
+
diff --git a/contrib/ffmpeg/libavcodec/ulti_cb.h b/contrib/ffmpeg/libavcodec/ulti_cb.h
new file mode 100644
index 000000000..2d8c9082c
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ulti_cb.h
@@ -0,0 +1,4119 @@
+/*
+ * 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
+ */
+
+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
+};
diff --git a/contrib/ffmpeg/libavcodec/utils.c b/contrib/ffmpeg/libavcodec/utils.c
new file mode 100644
index 000000000..2c7a76c11
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/utils.c
@@ -0,0 +1,1331 @@
+/*
+ * utils for libavcodec
+ * Copyright (c) 2001 Fabrice Bellard.
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * 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.c
+ * utils.
+ */
+
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+#include "integer.h"
+#include "opt.h"
+#include "crc.h"
+#include <stdarg.h>
+#include <limits.h>
+#include <float.h>
+#ifdef __MINGW32__
+#include <fcntl.h>
+#endif
+
+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,
+};
+
+static int volatile entangled_thread_counter=0;
+
+/**
+ * realloc which does nothing if the block is large enough
+ */
+void *av_fast_realloc(void *ptr, unsigned int *size, unsigned int min_size)
+{
+ if(min_size < *size)
+ return ptr;
+
+ *size= FFMAX(17*min_size/16 + 32, min_size);
+
+ return av_realloc(ptr, *size);
+}
+
+static unsigned int last_static = 0;
+static unsigned int allocated_static = 0;
+static void** array_static = NULL;
+
+/**
+ * allocation of static arrays - do not use for normal allocation.
+ */
+void *av_mallocz_static(unsigned int size)
+{
+ void *ptr = av_mallocz(size);
+
+ if(ptr){
+ array_static =av_fast_realloc(array_static, &allocated_static, sizeof(void*)*(last_static+1));
+ if(!array_static)
+ return NULL;
+ array_static[last_static++] = ptr;
+ }
+
+ return ptr;
+}
+
+/**
+ * same as above, but does realloc
+ */
+
+void *av_realloc_static(void *ptr, unsigned int size)
+{
+ int i;
+ if(!ptr)
+ return av_mallocz_static(size);
+ /* Look for the old ptr */
+ for(i = 0; i < last_static; i++) {
+ if(array_static[i] == ptr) {
+ array_static[i] = av_realloc(array_static[i], size);
+ return array_static[i];
+ }
+ }
+ return NULL;
+
+}
+
+/**
+ * free all static arrays and reset pointers to 0.
+ */
+void av_free_static(void)
+{
+ while(last_static){
+ av_freep(&array_static[--last_static]);
+ }
+ av_freep(&array_static);
+}
+
+/**
+ * Call av_free_static automatically before it's too late
+ */
+
+static void do_free(void) __attribute__ ((destructor));
+
+static void do_free(void)
+{
+ av_free_static();
+}
+
+
+/* encoder management */
+AVCodec *first_avcodec = NULL;
+
+void register_avcodec(AVCodec *format)
+{
+ AVCodec **p;
+ p = &first_avcodec;
+ while (*p != NULL) p = &(*p)->next;
+ *p = format;
+ format->next = NULL;
+}
+
+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);
+}
+
+typedef struct InternalBuffer{
+ int last_pic_num;
+ uint8_t *base[4];
+ uint8_t *data[4];
+ int linesize[4];
+}InternalBuffer;
+
+#define INTERNAL_BUFFER_SIZE 32
+
+#define ALIGN(x, a) (((x)+(a)-1)&~((a)-1))
+
+void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){
+ int w_align= 1;
+ int h_align= 1;
+
+ switch(s->pix_fmt){
+ case PIX_FMT_YUV420P:
+ case PIX_FMT_YUV422:
+ case PIX_FMT_UYVY422:
+ case PIX_FMT_YUV422P:
+ case PIX_FMT_YUV444P:
+ case PIX_FMT_GRAY8:
+ case PIX_FMT_GRAY16BE:
+ case PIX_FMT_GRAY16LE:
+ case PIX_FMT_YUVJ420P:
+ case PIX_FMT_YUVJ422P:
+ case PIX_FMT_YUVJ444P:
+ w_align= 16; //FIXME check for non mpeg style codecs and use less alignment
+ h_align= 16;
+ break;
+ case PIX_FMT_YUV411P:
+ case PIX_FMT_UYVY411:
+ w_align=32;
+ h_align=8;
+ break;
+ case PIX_FMT_YUV410P:
+ if(s->codec_id == CODEC_ID_SVQ1){
+ w_align=64;
+ h_align=64;
+ }
+ case PIX_FMT_RGB555:
+ if(s->codec_id == CODEC_ID_RPZA){
+ w_align=4;
+ h_align=4;
+ }
+ case PIX_FMT_PAL8:
+ if(s->codec_id == CODEC_ID_SMC){
+ w_align=4;
+ h_align=4;
+ }
+ break;
+ case PIX_FMT_BGR24:
+ if((s->codec_id == CODEC_ID_MSZH) || (s->codec_id == CODEC_ID_ZLIB)){
+ w_align=4;
+ h_align=4;
+ }
+ break;
+ default:
+ w_align= 1;
+ h_align= 1;
+ break;
+ }
+
+ *width = ALIGN(*width , w_align);
+ *height= ALIGN(*height, h_align);
+}
+
+int avcodec_check_dimensions(void *av_log_ctx, unsigned int w, unsigned int h){
+ if((int)w>0 && (int)h>0 && (w+128)*(uint64_t)(h+128) < INT_MAX/4)
+ return 0;
+
+ av_log(av_log_ctx, AV_LOG_ERROR, "picture size invalid (%ux%u)\n", w, h);
+ return -1;
+}
+
+int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){
+ int i;
+ int w= s->width;
+ int h= s->height;
+ InternalBuffer *buf;
+ int *picture_number;
+
+ assert(pic->data[0]==NULL);
+ assert(INTERNAL_BUFFER_SIZE > s->internal_buffer_count);
+
+ if(avcodec_check_dimensions(s,w,h))
+ return -1;
+
+ if(s->internal_buffer==NULL){
+ s->internal_buffer= av_mallocz(INTERNAL_BUFFER_SIZE*sizeof(InternalBuffer));
+ }
+#if 0
+ s->internal_buffer= av_fast_realloc(
+ s->internal_buffer,
+ &s->internal_buffer_size,
+ sizeof(InternalBuffer)*FFMAX(99, s->internal_buffer_count+1)/*FIXME*/
+ );
+#endif
+
+ buf= &((InternalBuffer*)s->internal_buffer)[s->internal_buffer_count];
+ picture_number= &(((InternalBuffer*)s->internal_buffer)[INTERNAL_BUFFER_SIZE-1]).last_pic_num; //FIXME ugly hack
+ (*picture_number)++;
+
+ if(buf->base[0]){
+ pic->age= *picture_number - buf->last_pic_num;
+ buf->last_pic_num= *picture_number;
+ }else{
+ int h_chroma_shift, v_chroma_shift;
+ int pixel_size, size[3];
+ AVPicture picture;
+
+ avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift);
+
+ avcodec_align_dimensions(s, &w, &h);
+
+ if(!(s->flags&CODEC_FLAG_EMU_EDGE)){
+ w+= EDGE_WIDTH*2;
+ h+= EDGE_WIDTH*2;
+ }
+ avpicture_fill(&picture, NULL, s->pix_fmt, w, h);
+ pixel_size= picture.linesize[0]*8 / w;
+//av_log(NULL, AV_LOG_ERROR, "%d %d %d %d\n", (int)picture.data[1], w, h, s->pix_fmt);
+ assert(pixel_size>=1);
+ //FIXME next ensures that linesize= 2^x uvlinesize, thats needed because some MC code assumes it
+ if(pixel_size == 3*8)
+ w= ALIGN(w, STRIDE_ALIGN<<h_chroma_shift);
+ else
+ w= ALIGN(pixel_size*w, STRIDE_ALIGN<<(h_chroma_shift+3)) / pixel_size;
+ size[1] = avpicture_fill(&picture, NULL, s->pix_fmt, w, h);
+ size[0] = picture.linesize[0] * h;
+ size[1] -= size[0];
+ if(picture.data[2])
+ size[1]= size[2]= size[1]/2;
+ else
+ size[2]= 0;
+
+ buf->last_pic_num= -256*256*256*64;
+ memset(buf->base, 0, sizeof(buf->base));
+ memset(buf->data, 0, sizeof(buf->data));
+
+ for(i=0; i<3 && size[i]; i++){
+ const int h_shift= i==0 ? 0 : h_chroma_shift;
+ const int v_shift= i==0 ? 0 : v_chroma_shift;
+
+ buf->linesize[i]= picture.linesize[i];
+
+ buf->base[i]= av_malloc(size[i]+16); //FIXME 16
+ if(buf->base[i]==NULL) return -1;
+ memset(buf->base[i], 128, size[i]);
+
+ // no edge if EDEG EMU or not planar YUV, we check for PAL8 redundantly to protect against a exploitable bug regression ...
+ if((s->flags&CODEC_FLAG_EMU_EDGE) || (s->pix_fmt == PIX_FMT_PAL8) || !size[2])
+ buf->data[i] = buf->base[i];
+ else
+ buf->data[i] = buf->base[i] + ALIGN((buf->linesize[i]*EDGE_WIDTH>>v_shift) + (EDGE_WIDTH>>h_shift), STRIDE_ALIGN);
+ }
+ pic->age= 256*256*256*64;
+ }
+ pic->type= FF_BUFFER_TYPE_INTERNAL;
+
+ for(i=0; i<4; i++){
+ pic->base[i]= buf->base[i];
+ pic->data[i]= buf->data[i];
+ pic->linesize[i]= buf->linesize[i];
+ }
+ s->internal_buffer_count++;
+
+ return 0;
+}
+
+void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic){
+ int i;
+ InternalBuffer *buf, *last, temp;
+
+ assert(pic->type==FF_BUFFER_TYPE_INTERNAL);
+ assert(s->internal_buffer_count);
+
+ buf = NULL; /* avoids warning */
+ for(i=0; i<s->internal_buffer_count; i++){ //just 3-5 checks so is not worth to optimize
+ buf= &((InternalBuffer*)s->internal_buffer)[i];
+ if(buf->data[0] == pic->data[0])
+ break;
+ }
+ assert(i < s->internal_buffer_count);
+ s->internal_buffer_count--;
+ last = &((InternalBuffer*)s->internal_buffer)[s->internal_buffer_count];
+
+ temp= *buf;
+ *buf= *last;
+ *last= temp;
+
+ for(i=0; i<3; i++){
+ pic->data[i]=NULL;
+// pic->base[i]=NULL;
+ }
+//printf("R%X\n", pic->opaque);
+}
+
+int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic){
+ AVFrame temp_pic;
+ int i;
+
+ /* If no picture return a new buffer */
+ if(pic->data[0] == NULL) {
+ /* We will copy from buffer, so must be readable */
+ pic->buffer_hints |= FF_BUFFER_HINTS_READABLE;
+ return s->get_buffer(s, pic);
+ }
+
+ /* If internal buffer type return the same buffer */
+ if(pic->type == FF_BUFFER_TYPE_INTERNAL)
+ return 0;
+
+ /*
+ * Not internal type and reget_buffer not overridden, emulate cr buffer
+ */
+ temp_pic = *pic;
+ for(i = 0; i < 4; i++)
+ pic->data[i] = pic->base[i] = NULL;
+ pic->opaque = NULL;
+ /* Allocate new frame */
+ if (s->get_buffer(s, pic))
+ return -1;
+ /* Copy image data from old buffer to new buffer */
+ img_copy((AVPicture*)pic, (AVPicture*)&temp_pic, s->pix_fmt, s->width,
+ s->height);
+ s->release_buffer(s, &temp_pic); // Release old frame
+ return 0;
+}
+
+int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void **arg, int *ret, int count){
+ int i;
+
+ for(i=0; i<count; i++){
+ int r= func(c, arg[i]);
+ if(ret) ret[i]= r;
+ }
+ return 0;
+}
+
+enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum PixelFormat * fmt){
+ return fmt[0];
+}
+
+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";
+}
+
+#define OFFSET(x) offsetof(AVCodecContext,x)
+#define DEFAULT 0 //should be NAN but it doesnt work as its 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 video bitrate (in bits/s)", OFFSET(bit_rate), FF_OPT_TYPE_INT, AV_CODEC_DEFAULT_BITRATE, INT_MIN, INT_MAX, V|A|E},
+{"bt", "set video bitrate tolerance (in bits/s)", OFFSET(bit_rate_tolerance), FF_OPT_TYPE_INT, AV_CODEC_DEFAULT_BITRATE*20, INT_MIN, INT_MAX, V|E},
+{"flags", NULL, OFFSET(flags), FF_OPT_TYPE_FLAGS, DEFAULT, INT_MIN, INT_MAX, V|A|E|D, "flags"},
+{"mv4", "use four motion vector by macroblock (mpeg4)", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_4MV, INT_MIN, INT_MAX, V|E, "flags"},
+{"obmc", "use overlapped block motion compensation (h263+)", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_OBMC, INT_MIN, INT_MAX, V|E, "flags"},
+{"qpel", "use 1/4 pel motion compensation", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_QPEL, INT_MIN, INT_MAX, V|E, "flags"},
+{"loop", "use loop filter", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_LOOP_FILTER, INT_MIN, INT_MAX, V|E, "flags"},
+{"qscale", "use fixed qscale", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_QSCALE, INT_MIN, INT_MAX, 0, "flags"},
+{"gmc", "use gmc", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_GMC, INT_MIN, INT_MAX, V|E, "flags"},
+{"mv0", "always try a mb with mv=<0,0>", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_MV0, INT_MIN, INT_MAX, V|E, "flags"},
+{"part", "use data partitioning", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_PART, INT_MIN, INT_MAX, V|E, "flags"},
+{"input_preserved", NULL, 0, FF_OPT_TYPE_CONST, CODEC_FLAG_INPUT_PRESERVED, INT_MIN, INT_MAX, 0, "flags"},
+{"pass1", "use internal 2pass ratecontrol in first pass mode", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_PASS1, INT_MIN, INT_MAX, 0, "flags"},
+{"pass2", "use internal 2pass ratecontrol in second pass mode", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_PASS2, INT_MIN, INT_MAX, 0, "flags"},
+{"extern_huff", "use external huffman table (for mjpeg)", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_EXTERN_HUFF, INT_MIN, INT_MAX, 0, "flags"},
+{"gray", "only decode/encode grayscale", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_GRAY, INT_MIN, INT_MAX, V|E|D, "flags"},
+{"emu_edge", "don't draw edges", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_EMU_EDGE, INT_MIN, INT_MAX, 0, "flags"},
+{"psnr", "error[?] variables will be set during encoding", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_PSNR, INT_MIN, INT_MAX, V|E, "flags"},
+{"truncated", NULL, 0, FF_OPT_TYPE_CONST, CODEC_FLAG_TRUNCATED, INT_MIN, INT_MAX, 0, "flags"},
+{"naq", "normalize adaptive quantization", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_NORMALIZE_AQP, INT_MIN, INT_MAX, V|E, "flags"},
+{"ildct", "use interlaced dct", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_INTERLACED_DCT, INT_MIN, INT_MAX, V|E, "flags"},
+{"low_delay", "force low delay", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_LOW_DELAY, INT_MIN, INT_MAX, V|D|E, "flags"},
+{"alt", "enable alternate scantable (mpeg2/mpeg4)", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_ALT_SCAN, INT_MIN, INT_MAX, V|E, "flags"},
+{"trell", "use trellis quantization", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_TRELLIS_QUANT, INT_MIN, INT_MAX, V|E, "flags"},
+{"global_header", "place global headers in extradata instead of every keyframe", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_GLOBAL_HEADER, INT_MIN, INT_MAX, 0, "flags"},
+{"bitexact", "use only bitexact stuff (except (i)dct)", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_BITEXACT, INT_MIN, INT_MAX, A|V|S|D|E, "flags"},
+{"aic", "h263 advanced intra coding / mpeg4 ac prediction", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_AC_PRED, INT_MIN, INT_MAX, V|E, "flags"},
+{"umv", "use unlimited motion vectors", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_H263P_UMV, INT_MIN, INT_MAX, V|E, "flags"},
+{"cbp", "use rate distortion optimization for cbp", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_CBP_RD, INT_MIN, INT_MAX, V|E, "flags"},
+{"qprd", "use rate distortion optimization for qp selection", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_QP_RD, INT_MIN, INT_MAX, V|E, "flags"},
+{"aiv", "h263 alternative inter vlc", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_H263P_AIV, INT_MIN, INT_MAX, V|E, "flags"},
+{"slice", NULL, 0, FF_OPT_TYPE_CONST, CODEC_FLAG_H263P_SLICE_STRUCT, INT_MIN, INT_MAX, V|E, "flags"},
+{"ilme", "interlaced motion estimation", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_INTERLACED_ME, INT_MIN, INT_MAX, V|E, "flags"},
+{"scan_offset", "will reserve space for svcd scan offset user data", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_SVCD_SCAN_OFFSET, INT_MIN, INT_MAX, V|E, "flags"},
+{"cgop", "closed gop", 0, FF_OPT_TYPE_CONST, CODEC_FLAG_CLOSED_GOP, INT_MIN, INT_MAX, V|E, "flags"},
+{"fast", "allow non spec compliant speedup tricks", 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_FAST, INT_MIN, INT_MAX, V|E, "flags2"},
+{"sgop", "strictly enforce gop size", 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_STRICT_GOP, INT_MIN, INT_MAX, V|E, "flags2"},
+{"noout", "skip bitstream encoding", 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_NO_OUTPUT, INT_MIN, INT_MAX, V|E, "flags2"},
+{"local_header", "place global headers at every keyframe instead of in extradata", 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_LOCAL_HEADER, INT_MIN, INT_MAX, V|E, "flags2"},
+{"sub_id", NULL, OFFSET(sub_id), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"me_method", "set motion estimation method", OFFSET(me_method), FF_OPT_TYPE_INT, ME_EPZS, INT_MIN, INT_MAX, V|E, "me_method"},
+{"extradata_size", NULL, OFFSET(extradata_size), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"time_base", NULL, OFFSET(time_base), FF_OPT_TYPE_RATIONAL, DEFAULT, INT_MIN, INT_MAX},
+{"g", "set the group of picture size", OFFSET(gop_size), FF_OPT_TYPE_INT, 12, INT_MIN, INT_MAX, V|E},
+{"rate_emu", NULL, OFFSET(rate_emu), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"ar", "set audio sampling rate (in Hz)", OFFSET(sample_rate), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"ac", "set number of audio channels", OFFSET(channels), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"cutoff", "set cutoff bandwidth", OFFSET(cutoff), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, A|E},
+{"frame_size", NULL, OFFSET(frame_size), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, A|E},
+{"frame_number", NULL, OFFSET(frame_number), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"real_pict_num", NULL, OFFSET(real_pict_num), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"delay", NULL, OFFSET(delay), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"qcomp", "video quantizer scale compression (VBR)", OFFSET(qcompress), FF_OPT_TYPE_FLOAT, 0.5, FLT_MIN, FLT_MAX, V|E},
+{"qblur", "video quantizer scale blur (VBR)", OFFSET(qblur), FF_OPT_TYPE_FLOAT, 0.5, FLT_MIN, FLT_MAX, V|E},
+{"qmin", "min video quantizer scale (VBR)", OFFSET(qmin), FF_OPT_TYPE_INT, 2, 1, 51, V|E},
+{"qmax", "max video quantizer scale (VBR)", OFFSET(qmax), FF_OPT_TYPE_INT, 31, 1, 51, V|E},
+{"qdiff", "max difference between the quantizer scale (VBR)", OFFSET(max_qdiff), FF_OPT_TYPE_INT, 3, INT_MIN, INT_MAX, V|E},
+{"bf", "use 'frames' B frames", OFFSET(max_b_frames), FF_OPT_TYPE_INT, DEFAULT, 0, FF_MAX_B_FRAMES, V|E},
+{"b_qfactor", "qp factor between p and b frames", OFFSET(b_quant_factor), FF_OPT_TYPE_FLOAT, 1.25, FLT_MIN, FLT_MAX, V|E},
+{"rc_strategy", NULL, OFFSET(rc_strategy), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"b_strategy", NULL, OFFSET(b_frame_strategy), FF_OPT_TYPE_INT, 0, INT_MIN, INT_MAX, V|E},
+{"hurry_up", NULL, OFFSET(hurry_up), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|D},
+{"rtp_mode", NULL, OFFSET(rtp_mode), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"rtp_payload_size", NULL, OFFSET(rtp_payload_size), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"mv_bits", NULL, OFFSET(mv_bits), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"header_bits", NULL, OFFSET(header_bits), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"i_tex_bits", NULL, OFFSET(i_tex_bits), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"p_tex_bits", NULL, OFFSET(p_tex_bits), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"i_count", NULL, OFFSET(i_count), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"p_count", NULL, OFFSET(p_count), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"skip_count", NULL, OFFSET(skip_count), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"misc_bits", NULL, OFFSET(misc_bits), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"frame_bits", NULL, OFFSET(frame_bits), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"codec_tag", NULL, OFFSET(codec_tag), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"bug", "workaround not auto detected encoder bugs", OFFSET(workaround_bugs), FF_OPT_TYPE_FLAGS, FF_BUG_AUTODETECT, INT_MIN, INT_MAX, V|D, "bug"},
+{"autodetect", NULL, 0, FF_OPT_TYPE_CONST, FF_BUG_AUTODETECT, INT_MIN, INT_MAX, V|D, "bug"},
+{"old_msmpeg4", NULL, 0, FF_OPT_TYPE_CONST, FF_BUG_OLD_MSMPEG4, INT_MIN, INT_MAX, V|D, "bug"},
+{"xvid_ilace", NULL, 0, FF_OPT_TYPE_CONST, FF_BUG_XVID_ILACE, INT_MIN, INT_MAX, V|D, "bug"},
+{"ump4", NULL, 0, FF_OPT_TYPE_CONST, FF_BUG_UMP4, INT_MIN, INT_MAX, V|D, "bug"},
+{"no_padding", NULL, 0, FF_OPT_TYPE_CONST, FF_BUG_NO_PADDING, INT_MIN, INT_MAX, V|D, "bug"},
+{"amv", NULL, 0, FF_OPT_TYPE_CONST, FF_BUG_AMV, INT_MIN, INT_MAX, V|D, "bug"},
+{"ac_vlc", NULL, 0, FF_OPT_TYPE_CONST, FF_BUG_AC_VLC, INT_MIN, INT_MAX, V|D, "bug"},
+{"qpel_chroma", NULL, 0, FF_OPT_TYPE_CONST, FF_BUG_QPEL_CHROMA, INT_MIN, INT_MAX, V|D, "bug"},
+{"std_qpel", NULL, 0, FF_OPT_TYPE_CONST, FF_BUG_STD_QPEL, INT_MIN, INT_MAX, V|D, "bug"},
+{"qpel_chroma2", NULL, 0, FF_OPT_TYPE_CONST, FF_BUG_QPEL_CHROMA2, INT_MIN, INT_MAX, V|D, "bug"},
+{"direct_blocksize", NULL, 0, FF_OPT_TYPE_CONST, FF_BUG_DIRECT_BLOCKSIZE, INT_MIN, INT_MAX, V|D, "bug"},
+{"edge", NULL, 0, FF_OPT_TYPE_CONST, FF_BUG_EDGE, INT_MIN, INT_MAX, V|D, "bug"},
+{"hpel_chroma", NULL, 0, FF_OPT_TYPE_CONST, FF_BUG_HPEL_CHROMA, INT_MIN, INT_MAX, V|D, "bug"},
+{"dc_clip", NULL, 0, FF_OPT_TYPE_CONST, FF_BUG_DC_CLIP, INT_MIN, INT_MAX, V|D, "bug"},
+{"ms", NULL, 0, FF_OPT_TYPE_CONST, FF_BUG_MS, INT_MIN, INT_MAX, V|D, "bug"},
+{"lelim", "single coefficient elimination threshold for luminance (negative values also consider dc coefficient)", OFFSET(luma_elim_threshold), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"celim", "single coefficient elimination threshold for chrominance (negative values also consider dc coefficient)", OFFSET(chroma_elim_threshold), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"strict", "how strictly to follow the standards", OFFSET(strict_std_compliance), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E, "strict"},
+{"very", NULL, 0, FF_OPT_TYPE_CONST, FF_COMPLIANCE_VERY_STRICT, INT_MIN, INT_MAX, V|E, "strict"},
+{"strict", NULL, 0, FF_OPT_TYPE_CONST, FF_COMPLIANCE_STRICT, INT_MIN, INT_MAX, V|E, "strict"},
+{"normal", NULL, 0, FF_OPT_TYPE_CONST, FF_COMPLIANCE_NORMAL, INT_MIN, INT_MAX, V|E, "strict"},
+{"inofficial", NULL, 0, FF_OPT_TYPE_CONST, FF_COMPLIANCE_INOFFICIAL, INT_MIN, INT_MAX, V|E, "strict"},
+{"experimental", NULL, 0, FF_OPT_TYPE_CONST, FF_COMPLIANCE_EXPERIMENTAL, INT_MIN, INT_MAX, V|E, "strict"},
+{"b_qoffset", "qp offset between p and b frames", OFFSET(b_quant_offset), FF_OPT_TYPE_FLOAT, 1.25, FLT_MIN, FLT_MAX, V|E},
+{"er", NULL, OFFSET(error_resilience), FF_OPT_TYPE_INT, FF_ER_CAREFUL, INT_MIN, INT_MAX, V|D, "er"},
+{"careful", NULL, 0, FF_OPT_TYPE_CONST, FF_ER_CAREFUL, INT_MIN, INT_MAX, V|D, "er"},
+{"compliant", NULL, 0, FF_OPT_TYPE_CONST, FF_ER_COMPLIANT, INT_MIN, INT_MAX, V|D, "er"},
+{"aggressive", NULL, 0, FF_OPT_TYPE_CONST, FF_ER_AGGRESSIVE, INT_MIN, INT_MAX, V|D, "er"},
+{"very_aggressive", NULL, 0, FF_OPT_TYPE_CONST, FF_ER_VERY_AGGRESSIVE, INT_MIN, INT_MAX, V|D, "er"},
+{"has_b_frames", NULL, OFFSET(has_b_frames), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"block_align", NULL, OFFSET(block_align), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"parse_only", NULL, OFFSET(parse_only), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"mpeg_quant", NULL, OFFSET(mpeg_quant), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"stats_out", NULL, OFFSET(stats_out), FF_OPT_TYPE_STRING, DEFAULT, CHAR_MIN, CHAR_MAX},
+{"stats_in", NULL, OFFSET(stats_in), FF_OPT_TYPE_STRING, DEFAULT, CHAR_MIN, CHAR_MAX},
+{"qsquish", "how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable function)", OFFSET(rc_qsquish), FF_OPT_TYPE_FLOAT, DEFAULT, 0, 99, V|E},
+{"rc_qmod_amp", NULL, OFFSET(rc_qmod_amp), FF_OPT_TYPE_FLOAT, DEFAULT, -FLT_MAX, FLT_MAX, V|E},
+{"rc_qmod_freq", NULL, OFFSET(rc_qmod_freq), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"rc_override_count", NULL, OFFSET(rc_override_count), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"rc_eq", "set rate control equation", OFFSET(rc_eq), FF_OPT_TYPE_STRING, DEFAULT, CHAR_MIN, CHAR_MAX, V|E},
+{"maxrate", "set max video bitrate tolerance (in bits/s)", OFFSET(rc_max_rate), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"minrate", "set min video bitrate tolerance (in bits/s)", OFFSET(rc_min_rate), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"bufsize", "set ratecontrol buffer size (in bits)", OFFSET(rc_buffer_size), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"rc_buf_aggressivity", NULL, OFFSET(rc_buffer_aggressivity), FF_OPT_TYPE_FLOAT, 1.0, FLT_MIN, FLT_MAX, V|E},
+{"i_qfactor", "qp factor between p and i frames", OFFSET(i_quant_factor), FF_OPT_TYPE_FLOAT, -0.8, -FLT_MAX, FLT_MAX, V|E},
+{"i_qoffset", "qp offset between p and i frames", OFFSET(i_quant_offset), FF_OPT_TYPE_FLOAT, 0.0, -FLT_MAX, FLT_MAX, V|E},
+{"rc_init_cplx", "initial complexity for 1-pass encoding", OFFSET(rc_initial_cplx), FF_OPT_TYPE_FLOAT, DEFAULT, -FLT_MAX, FLT_MAX, V|E},
+{"dct", NULL, OFFSET(dct_algo), FF_OPT_TYPE_INT, DEFAULT, 0, INT_MAX, V|E, "dct"},
+{"auto", NULL, 0, FF_OPT_TYPE_CONST, FF_DCT_AUTO, INT_MIN, INT_MAX, V|E, "dct"},
+{"fastint", NULL, 0, FF_OPT_TYPE_CONST, FF_DCT_FASTINT, INT_MIN, INT_MAX, V|E, "dct"},
+{"int", NULL, 0, FF_OPT_TYPE_CONST, FF_DCT_INT, INT_MIN, INT_MAX, V|E, "dct"},
+{"mmx", NULL, 0, FF_OPT_TYPE_CONST, FF_DCT_MMX, INT_MIN, INT_MAX, V|E, "dct"},
+{"mlib", NULL, 0, FF_OPT_TYPE_CONST, FF_DCT_MLIB, INT_MIN, INT_MAX, V|E, "dct"},
+{"altivec", NULL, 0, FF_OPT_TYPE_CONST, FF_DCT_ALTIVEC, INT_MIN, INT_MAX, V|E, "dct"},
+{"faan", NULL, 0, FF_OPT_TYPE_CONST, FF_DCT_FAAN, INT_MIN, INT_MAX, V|E, "dct"},
+{"lumi_mask", "lumimasking", OFFSET(lumi_masking), FF_OPT_TYPE_FLOAT, 0, -FLT_MAX, FLT_MAX, V|E},
+{"tcplx_mask", "temporal complexity masking", OFFSET(temporal_cplx_masking), FF_OPT_TYPE_FLOAT, 0, -FLT_MAX, FLT_MAX, V|E},
+{"scplx_mask", "spatial complexity masking", OFFSET(spatial_cplx_masking), FF_OPT_TYPE_FLOAT, 0, -FLT_MAX, FLT_MAX, V|E},
+{"p_mask", "inter masking", OFFSET(p_masking), FF_OPT_TYPE_FLOAT, 0, -FLT_MAX, FLT_MAX, V|E},
+{"dark_mask", "darkness masking", OFFSET(dark_masking), FF_OPT_TYPE_FLOAT, 0, -FLT_MAX, FLT_MAX, V|E},
+{"unused", NULL, OFFSET(unused), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"idct", NULL, OFFSET(idct_algo), FF_OPT_TYPE_INT, DEFAULT, 0, INT_MAX, V|E|D, "idct"},
+{"auto", NULL, 0, FF_OPT_TYPE_CONST, FF_IDCT_AUTO, INT_MIN, INT_MAX, V|E|D, "idct"},
+{"int", NULL, 0, FF_OPT_TYPE_CONST, FF_IDCT_INT, INT_MIN, INT_MAX, V|E|D, "idct"},
+{"simple", NULL, 0, FF_OPT_TYPE_CONST, FF_IDCT_SIMPLE, INT_MIN, INT_MAX, V|E|D, "idct"},
+{"simplemmx", NULL, 0, FF_OPT_TYPE_CONST, FF_IDCT_SIMPLEMMX, INT_MIN, INT_MAX, V|E|D, "idct"},
+{"libmpeg2mmx", NULL, 0, FF_OPT_TYPE_CONST, FF_IDCT_LIBMPEG2MMX, INT_MIN, INT_MAX, V|E|D, "idct"},
+{"ps2", NULL, 0, FF_OPT_TYPE_CONST, FF_IDCT_PS2, INT_MIN, INT_MAX, V|E|D, "idct"},
+{"mlib", NULL, 0, FF_OPT_TYPE_CONST, FF_IDCT_MLIB, INT_MIN, INT_MAX, V|E|D, "idct"},
+{"arm", NULL, 0, FF_OPT_TYPE_CONST, FF_IDCT_ARM, INT_MIN, INT_MAX, V|E|D, "idct"},
+{"altivec", NULL, 0, FF_OPT_TYPE_CONST, FF_IDCT_ALTIVEC, INT_MIN, INT_MAX, V|E|D, "idct"},
+{"sh4", NULL, 0, FF_OPT_TYPE_CONST, FF_IDCT_SH4, INT_MIN, INT_MAX, V|E|D, "idct"},
+{"simplearm", NULL, 0, FF_OPT_TYPE_CONST, FF_IDCT_SIMPLEARM, INT_MIN, INT_MAX, V|E|D, "idct"},
+{"simplearmv5te", NULL, 0, FF_OPT_TYPE_CONST, FF_IDCT_SIMPLEARMV5TE, INT_MIN, INT_MAX, V|E|D, "idct"},
+{"h264", NULL, 0, FF_OPT_TYPE_CONST, FF_IDCT_H264, INT_MIN, INT_MAX, V|E|D, "idct"},
+{"vp3", NULL, 0, FF_OPT_TYPE_CONST, FF_IDCT_VP3, INT_MIN, INT_MAX, V|E|D, "idct"},
+{"ipp", NULL, 0, FF_OPT_TYPE_CONST, FF_IDCT_IPP, INT_MIN, INT_MAX, V|E|D, "idct"},
+{"xvidmmx", NULL, 0, FF_OPT_TYPE_CONST, FF_IDCT_XVIDMMX, INT_MIN, INT_MAX, V|E|D, "idct"},
+{"slice_count", NULL, OFFSET(slice_count), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"ec", NULL, OFFSET(error_concealment), FF_OPT_TYPE_FLAGS, 3, INT_MIN, INT_MAX, V|D, "ec"},
+{"guess_mvs", NULL, 0, FF_OPT_TYPE_CONST, FF_EC_GUESS_MVS, INT_MIN, INT_MAX, V|D, "ec"},
+{"deblock", NULL, 0, FF_OPT_TYPE_CONST, FF_EC_DEBLOCK, INT_MIN, INT_MAX, V|D, "ec"},
+{"bits_per_sample", NULL, OFFSET(bits_per_sample), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"pred", "prediction method", OFFSET(prediction_method), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E, "pred"},
+{"left", NULL, 0, FF_OPT_TYPE_CONST, FF_PRED_LEFT, INT_MIN, INT_MAX, V|E, "pred"},
+{"plane", NULL, 0, FF_OPT_TYPE_CONST, FF_PRED_PLANE, INT_MIN, INT_MAX, V|E, "pred"},
+{"median", NULL, 0, FF_OPT_TYPE_CONST, FF_PRED_MEDIAN, INT_MIN, INT_MAX, V|E, "pred"},
+{"aspect", NULL, OFFSET(sample_aspect_ratio), FF_OPT_TYPE_RATIONAL, DEFAULT, 0, 10, V|E},
+{"debug", "print specific debug info", OFFSET(debug), FF_OPT_TYPE_FLAGS, DEFAULT, 0, INT_MAX, V|A|S|E|D, "debug"},
+{"pict", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_PICT_INFO, INT_MIN, INT_MAX, V|D, "debug"},
+{"rc", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_RC, INT_MIN, INT_MAX, V|E, "debug"},
+{"bitstream", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_BITSTREAM, INT_MIN, INT_MAX, V|D, "debug"},
+{"mb_type", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_MB_TYPE, INT_MIN, INT_MAX, V|D, "debug"},
+{"qp", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_QP, INT_MIN, INT_MAX, V|D, "debug"},
+{"mv", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_MV, INT_MIN, INT_MAX, V|D, "debug"},
+{"dct_coeff", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_DCT_COEFF, INT_MIN, INT_MAX, V|D, "debug"},
+{"skip", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_SKIP, INT_MIN, INT_MAX, V|D, "debug"},
+{"startcode", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_STARTCODE, INT_MIN, INT_MAX, V|D, "debug"},
+{"pts", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_PTS, INT_MIN, INT_MAX, V|D, "debug"},
+{"er", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_ER, INT_MIN, INT_MAX, V|D, "debug"},
+{"mmco", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_MMCO, INT_MIN, INT_MAX, V|D, "debug"},
+{"bugs", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_BUGS, INT_MIN, INT_MAX, V|D, "debug"},
+{"vis_qp", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_VIS_QP, INT_MIN, INT_MAX, V|D, "debug"},
+{"vis_mb_type", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_VIS_MB_TYPE, INT_MIN, INT_MAX, V|D, "debug"},
+{"vismv", "visualize motion vectors", OFFSET(debug_mv), FF_OPT_TYPE_INT, DEFAULT, 0, INT_MAX, V|D, "debug_mv"},
+{"pf", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_VIS_MV_P_FOR, INT_MIN, INT_MAX, V|D, "debug_mv"},
+{"bf", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_VIS_MV_B_FOR, INT_MIN, INT_MAX, V|D, "debug_mv"},
+{"bb", NULL, 0, FF_OPT_TYPE_CONST, FF_DEBUG_VIS_MV_B_BACK, INT_MIN, INT_MAX, V|D, "debug_mv"},
+{"mb_qmin", NULL, OFFSET(mb_qmin), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"mb_qmax", NULL, OFFSET(mb_qmax), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"cmp", "full pel me compare function", OFFSET(me_cmp), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"subcmp", "sub pel me compare function", OFFSET(me_sub_cmp), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"mbcmp", "macroblock compare function", OFFSET(mb_cmp), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"ildctcmp", "interlaced dct compare function", OFFSET(ildct_cmp), FF_OPT_TYPE_INT, FF_CMP_VSAD, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"dia_size", NULL, OFFSET(dia_size), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"last_pred", NULL, OFFSET(last_predictor_count), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"preme", "pre motion estimation", OFFSET(pre_me), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"precmp", "pre motion estimation compare function", OFFSET(me_pre_cmp), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"sad", NULL, 0, FF_OPT_TYPE_CONST, FF_CMP_SAD, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"sse", NULL, 0, FF_OPT_TYPE_CONST, FF_CMP_SSE, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"satd", NULL, 0, FF_OPT_TYPE_CONST, FF_CMP_SATD, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"dct", NULL, 0, FF_OPT_TYPE_CONST, FF_CMP_DCT, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"psnr", NULL, 0, FF_OPT_TYPE_CONST, FF_CMP_PSNR, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"bit", NULL, 0, FF_OPT_TYPE_CONST, FF_CMP_BIT, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"rd", NULL, 0, FF_OPT_TYPE_CONST, FF_CMP_RD, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"zero", NULL, 0, FF_OPT_TYPE_CONST, FF_CMP_ZERO, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"vsad", NULL, 0, FF_OPT_TYPE_CONST, FF_CMP_VSAD, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"vsse", NULL, 0, FF_OPT_TYPE_CONST, FF_CMP_VSSE, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"nsse", NULL, 0, FF_OPT_TYPE_CONST, FF_CMP_NSSE, INT_MIN, INT_MAX, V|E, "cmp_func"},
+#ifdef CONFIG_SNOW_ENCODER
+{"w53", NULL, 0, FF_OPT_TYPE_CONST, FF_CMP_W53, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"w97", NULL, 0, FF_OPT_TYPE_CONST, FF_CMP_W97, INT_MIN, INT_MAX, V|E, "cmp_func"},
+#endif
+{"dctmax", NULL, 0, FF_OPT_TYPE_CONST, FF_CMP_DCTMAX, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"chroma", NULL, 0, FF_OPT_TYPE_CONST, FF_CMP_CHROMA, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"pre_dia_size", NULL, OFFSET(pre_dia_size), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"subq", "sub pel motion estimation quality", OFFSET(me_subpel_quality), FF_OPT_TYPE_INT, 8, INT_MIN, INT_MAX, V|E},
+{"dtg_active_format", NULL, OFFSET(dtg_active_format), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"me_range", "limit motion vectors range (1023 for DivX player)", OFFSET(me_range), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"ibias", "intra quant bias", OFFSET(intra_quant_bias), FF_OPT_TYPE_INT, FF_DEFAULT_QUANT_BIAS, INT_MIN, INT_MAX, V|E},
+{"pbias", "inter quant bias", OFFSET(inter_quant_bias), FF_OPT_TYPE_INT, FF_DEFAULT_QUANT_BIAS, INT_MIN, INT_MAX, V|E},
+{"color_table_id", NULL, OFFSET(color_table_id), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"internal_buffer_count", NULL, OFFSET(internal_buffer_count), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"global_quality", NULL, OFFSET(global_quality), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"coder", NULL, OFFSET(coder_type), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E, "coder"},
+{"vlc", "variable length coder / huffman coder", 0, FF_OPT_TYPE_CONST, FF_CODER_TYPE_VLC, INT_MIN, INT_MAX, V|E, "coder"},
+{"ac", "arithmetic coder", 0, FF_OPT_TYPE_CONST, FF_CODER_TYPE_AC, INT_MIN, INT_MAX, V|E, "coder"},
+{"context", "context model", OFFSET(context_model), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"slice_flags", NULL, OFFSET(slice_flags), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"xvmc_acceleration", NULL, OFFSET(xvmc_acceleration), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"mbd", NULL, OFFSET(mb_decision), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E, "mbd"},
+{"simple", NULL, 0, FF_OPT_TYPE_CONST, FF_MB_DECISION_SIMPLE, INT_MIN, INT_MAX, V|E, "mbd"},
+{"bits", NULL, 0, FF_OPT_TYPE_CONST, FF_MB_DECISION_BITS, INT_MIN, INT_MAX, V|E, "mbd"},
+{"rd", NULL, 0, FF_OPT_TYPE_CONST, FF_MB_DECISION_RD, INT_MIN, INT_MAX, V|E, "mbd"},
+{"stream_codec_tag", NULL, OFFSET(stream_codec_tag), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"sc_threshold", "scene change threshold", OFFSET(scenechange_threshold), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"lmin", "min lagrange factor (VBR)", OFFSET(lmin), FF_OPT_TYPE_INT, 2*FF_QP2LAMBDA, 0, INT_MAX, V|E},
+{"lmax", "max lagrange factor (VBR)", OFFSET(lmax), FF_OPT_TYPE_INT, 31*FF_QP2LAMBDA, 0, INT_MAX, V|E},
+{"nr", "noise reduction", OFFSET(noise_reduction), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"rc_init_occupancy", NULL, OFFSET(rc_initial_buffer_occupancy), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"inter_threshold", NULL, OFFSET(inter_threshold), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"flags2", NULL, OFFSET(flags2), FF_OPT_TYPE_FLAGS, CODEC_FLAG2_FASTPSKIP, INT_MIN, INT_MAX, V|A|E|D, "flags2"},
+{"error", NULL, OFFSET(error_rate), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"antialias", NULL, OFFSET(antialias_algo), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|D, "aa"},
+{"auto", NULL, 0, FF_OPT_TYPE_CONST, FF_AA_AUTO, INT_MIN, INT_MAX, V|D, "aa"},
+{"fastint", NULL, 0, FF_OPT_TYPE_CONST, FF_AA_FASTINT, INT_MIN, INT_MAX, V|D, "aa"},
+{"int", NULL, 0, FF_OPT_TYPE_CONST, FF_AA_INT, INT_MIN, INT_MAX, V|D, "aa"},
+{"float", NULL, 0, FF_OPT_TYPE_CONST, FF_AA_FLOAT, INT_MIN, INT_MAX, V|D, "aa"},
+{"qns", "quantizer noise shaping", OFFSET(quantizer_noise_shaping), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"threads", NULL, OFFSET(thread_count), FF_OPT_TYPE_INT, 1, INT_MIN, INT_MAX, V|E|D},
+{"me_threshold", "motion estimaton threshold", OFFSET(me_threshold), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX},
+{"mb_threshold", "macroblock threshold", OFFSET(mb_threshold), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"dc", "intra_dc_precision", OFFSET(intra_dc_precision), FF_OPT_TYPE_INT, 0, INT_MIN, INT_MAX, V|E},
+{"nssew", "nsse weight", OFFSET(nsse_weight), FF_OPT_TYPE_INT, 8, INT_MIN, INT_MAX, V|E},
+{"skip_top", NULL, OFFSET(skip_top), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|D},
+{"skip_bottom", NULL, OFFSET(skip_bottom), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|D},
+{"profile", NULL, OFFSET(profile), FF_OPT_TYPE_INT, FF_PROFILE_UNKNOWN, INT_MIN, INT_MAX, V|A|E, "profile"},
+{"unknown", NULL, 0, FF_OPT_TYPE_CONST, FF_PROFILE_UNKNOWN, INT_MIN, INT_MAX, V|A|E, "profile"},
+{"level", NULL, OFFSET(level), FF_OPT_TYPE_INT, FF_LEVEL_UNKNOWN, INT_MIN, INT_MAX, V|A|E, "level"},
+{"unknown", NULL, 0, FF_OPT_TYPE_CONST, FF_LEVEL_UNKNOWN, INT_MIN, INT_MAX, V|A|E, "level"},
+{"lowres", NULL, OFFSET(lowres), FF_OPT_TYPE_INT, 0, 0, INT_MAX, V|D},
+{"skip_threshold", "frame skip threshold", OFFSET(frame_skip_threshold), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"skip_factor", "frame skip factor", OFFSET(frame_skip_factor), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"skip_exp", "frame skip exponent", OFFSET(frame_skip_exp), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"skipcmp", "frame skip compare function", OFFSET(frame_skip_cmp), FF_OPT_TYPE_INT, FF_CMP_DCTMAX, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"border_mask", NULL, OFFSET(border_masking), FF_OPT_TYPE_FLOAT, DEFAULT, -FLT_MAX, FLT_MAX, V|E},
+{"mblmin", "min macroblock lagrange factor (VBR)", OFFSET(mb_lmin), FF_OPT_TYPE_INT, FF_QP2LAMBDA * 2, 1, FF_LAMBDA_MAX, V|E},
+{"mblmax", "max macroblock lagrange factor (VBR)", OFFSET(mb_lmax), FF_OPT_TYPE_INT, FF_QP2LAMBDA * 31, 1, FF_LAMBDA_MAX, V|E},
+{"mepc", "motion estimation bitrate penalty compensation (1.0 = 256)", OFFSET(me_penalty_compensation), FF_OPT_TYPE_INT, 256, INT_MIN, INT_MAX, V|E},
+{"bidir_refine", NULL, OFFSET(bidir_refine), FF_OPT_TYPE_INT, DEFAULT, 0, 4, V|E},
+{"brd_scale", NULL, OFFSET(brd_scale), FF_OPT_TYPE_INT, DEFAULT, 0, 10, V|E},
+{"crf", NULL, OFFSET(crf), FF_OPT_TYPE_FLOAT, DEFAULT, 0, 51, V|E},
+{"cqp", NULL, OFFSET(cqp), FF_OPT_TYPE_INT, -1, INT_MIN, INT_MAX, V|E},
+{"keyint_min", NULL, OFFSET(keyint_min), FF_OPT_TYPE_INT, 25, INT_MIN, INT_MAX, V|E},
+{"refs", NULL, OFFSET(refs), FF_OPT_TYPE_INT, 1, INT_MIN, INT_MAX, V|E},
+{"chromaoffset", NULL, OFFSET(chromaoffset), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"bframebias", NULL, OFFSET(bframebias), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"trellis", NULL, OFFSET(trellis), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|A|E},
+{"directpred", NULL, OFFSET(directpred), FF_OPT_TYPE_INT, 2, INT_MIN, INT_MAX, V|E},
+{"bpyramid", NULL, 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_BPYRAMID, INT_MIN, INT_MAX, V|E, "flags2"},
+{"wpred", NULL, 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_WPRED, INT_MIN, INT_MAX, V|E, "flags2"},
+{"mixed_refs", NULL, 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_MIXED_REFS, INT_MIN, INT_MAX, V|E, "flags2"},
+{"8x8dct", NULL, 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_8X8DCT, INT_MIN, INT_MAX, V|E, "flags2"},
+{"fastpskip", NULL, 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_FASTPSKIP, INT_MIN, INT_MAX, V|E, "flags2"},
+{"aud", NULL, 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_AUD, INT_MIN, INT_MAX, V|E, "flags2"},
+{"brdo", NULL, 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_BRDO, INT_MIN, INT_MAX, V|E, "flags2"},
+{"complexityblur", NULL, OFFSET(complexityblur), FF_OPT_TYPE_FLOAT, 20.0, FLT_MIN, FLT_MAX, V|E},
+{"deblockalpha", NULL, OFFSET(deblockalpha), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"deblockbeta", NULL, OFFSET(deblockbeta), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"partitions", NULL, OFFSET(partitions), FF_OPT_TYPE_FLAGS, DEFAULT, INT_MIN, INT_MAX, V|E, "partitions"},
+{"parti4x4", NULL, 0, FF_OPT_TYPE_CONST, X264_PART_I4X4, INT_MIN, INT_MAX, V|E, "partitions"},
+{"parti8x8", NULL, 0, FF_OPT_TYPE_CONST, X264_PART_I8X8, INT_MIN, INT_MAX, V|E, "partitions"},
+{"partp4x4", NULL, 0, FF_OPT_TYPE_CONST, X264_PART_P4X4, INT_MIN, INT_MAX, V|E, "partitions"},
+{"partp8x8", NULL, 0, FF_OPT_TYPE_CONST, X264_PART_P8X8, INT_MIN, INT_MAX, V|E, "partitions"},
+{"partb8x8", NULL, 0, FF_OPT_TYPE_CONST, X264_PART_B8X8, INT_MIN, INT_MAX, V|E, "partitions"},
+{"sc_factor", NULL, OFFSET(scenechange_factor), FF_OPT_TYPE_INT, 6, 0, INT_MAX, V|E},
+{"mv0_threshold", NULL, OFFSET(mv0_threshold), FF_OPT_TYPE_INT, 256, 0, INT_MAX, V|E},
+{"ivlc", "intra vlc table", 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_INTRA_VLC, INT_MIN, INT_MAX, V|E, "flags2"},
+{"b_sensitivity", NULL, OFFSET(b_sensitivity), FF_OPT_TYPE_INT, 40, 1, INT_MAX, V|E},
+{"compression_level", NULL, OFFSET(compression_level), FF_OPT_TYPE_INT, FF_COMPRESSION_DEFAULT, INT_MIN, INT_MAX, V|A|E},
+{"use_lpc", NULL, OFFSET(use_lpc), FF_OPT_TYPE_INT, -1, INT_MIN, INT_MAX, A|E},
+{"lpc_coeff_precision", NULL, OFFSET(lpc_coeff_precision), FF_OPT_TYPE_INT, DEFAULT, 0, INT_MAX, A|E},
+{"min_prediction_order", NULL, OFFSET(min_prediction_order), FF_OPT_TYPE_INT, -1, INT_MIN, INT_MAX, A|E},
+{"max_prediction_order", NULL, OFFSET(max_prediction_order), FF_OPT_TYPE_INT, -1, INT_MIN, INT_MAX, A|E},
+{"prediction_order_method", NULL, OFFSET(prediction_order_method), FF_OPT_TYPE_INT, -1, INT_MIN, INT_MAX, A|E},
+{"min_partition_order", NULL, OFFSET(min_partition_order), FF_OPT_TYPE_INT, -1, INT_MIN, INT_MAX, A|E},
+{"max_partition_order", NULL, OFFSET(max_partition_order), FF_OPT_TYPE_INT, -1, INT_MIN, INT_MAX, A|E},
+{"timecode_frame_start", NULL, OFFSET(timecode_frame_start), FF_OPT_TYPE_INT, 0, 0, INT_MAX, V|E},
+{"drop_frame_timecode", NULL, 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_DROP_FRAME_TIMECODE, INT_MIN, INT_MAX, V|E, "flags2"},
+{NULL},
+};
+
+#undef A
+#undef V
+#undef S
+#undef E
+#undef D
+#undef DEFAULT
+
+static AVClass av_codec_context_class = { "AVCodecContext", context_to_name, options };
+
+void avcodec_get_context_defaults(AVCodecContext *s){
+ memset(s, 0, sizeof(AVCodecContext));
+
+ s->av_class= &av_codec_context_class;
+
+ av_opt_set_defaults(s);
+
+ s->rc_eq= "tex^qComp";
+ s->time_base= (AVRational){0,1};
+ s->get_buffer= avcodec_default_get_buffer;
+ s->release_buffer= avcodec_default_release_buffer;
+ s->get_format= avcodec_default_get_format;
+ s->execute= avcodec_default_execute;
+ s->sample_aspect_ratio= (AVRational){0,1};
+ s->pix_fmt= PIX_FMT_NONE;
+ s->sample_fmt= SAMPLE_FMT_S16; // FIXME: set to NONE
+
+ s->palctrl = NULL;
+ s->reget_buffer= avcodec_default_reget_buffer;
+}
+
+/**
+ * allocates a AVCodecContext and set it to defaults.
+ * this can be deallocated by simply calling free()
+ */
+AVCodecContext *avcodec_alloc_context(void){
+ AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext));
+
+ if(avctx==NULL) return NULL;
+
+ avcodec_get_context_defaults(avctx);
+
+ return avctx;
+}
+
+void avcodec_get_frame_defaults(AVFrame *pic){
+ memset(pic, 0, sizeof(AVFrame));
+
+ pic->pts= AV_NOPTS_VALUE;
+ pic->key_frame= 1;
+}
+
+/**
+ * allocates a AVPFrame and set it to defaults.
+ * this can be deallocated by simply calling free()
+ */
+AVFrame *avcodec_alloc_frame(void){
+ AVFrame *pic= av_malloc(sizeof(AVFrame));
+
+ if(pic==NULL) return NULL;
+
+ avcodec_get_frame_defaults(pic);
+
+ return pic;
+}
+
+int avcodec_open(AVCodecContext *avctx, AVCodec *codec)
+{
+ int ret= -1;
+
+ entangled_thread_counter++;
+ if(entangled_thread_counter != 1){
+ av_log(avctx, AV_LOG_ERROR, "insufficient thread locking around avcodec_open/close()\n");
+ goto end;
+ }
+
+ if(avctx->codec)
+ goto end;
+
+ if (codec->priv_data_size > 0) {
+ avctx->priv_data = av_mallocz(codec->priv_data_size);
+ if (!avctx->priv_data)
+ goto end;
+ } else {
+ avctx->priv_data = NULL;
+ }
+
+ 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) && avcodec_check_dimensions(avctx,avctx->coded_width,avctx->coded_height)){
+ av_freep(&avctx->priv_data);
+ goto end;
+ }
+
+ avctx->codec = codec;
+ avctx->codec_id = codec->id;
+ avctx->frame_number = 0;
+ ret = avctx->codec->init(avctx);
+ if (ret < 0) {
+ av_freep(&avctx->priv_data);
+ avctx->codec= NULL;
+ goto end;
+ }
+ ret=0;
+end:
+ entangled_thread_counter--;
+ return ret;
+}
+
+int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size,
+ const short *samples)
+{
+ if(buf_size < FF_MIN_BUFFER_SIZE && 0){
+ av_log(avctx, AV_LOG_ERROR, "buffer smaller then minimum size\n");
+ return -1;
+ }
+ if((avctx->codec->capabilities & CODEC_CAP_DELAY) || samples){
+ int ret = avctx->codec->encode(avctx, buf, buf_size, (void *)samples);
+ avctx->frame_number++;
+ return ret;
+ }else
+ return 0;
+}
+
+int avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size,
+ const AVFrame *pict)
+{
+ if(buf_size < FF_MIN_BUFFER_SIZE){
+ av_log(avctx, AV_LOG_ERROR, "buffer smaller then minimum size\n");
+ return -1;
+ }
+ if(avcodec_check_dimensions(avctx,avctx->width,avctx->height))
+ return -1;
+ if((avctx->codec->capabilities & CODEC_CAP_DELAY) || pict){
+ int ret = avctx->codec->encode(avctx, buf, buf_size, (void *)pict);
+ avctx->frame_number++;
+ emms_c(); //needed to avoid an emms_c() call before every return;
+
+ return ret;
+ }else
+ return 0;
+}
+
+int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size,
+ const AVSubtitle *sub)
+{
+ int ret;
+ ret = avctx->codec->encode(avctx, buf, buf_size, (void *)sub);
+ avctx->frame_number++;
+ return ret;
+}
+
+/**
+ * decode a frame.
+ * @param buf bitstream buffer, must be FF_INPUT_BUFFER_PADDING_SIZE larger then the actual read bytes
+ * because some optimized bitstream readers read 32 or 64 bit at once and could read over the end
+ * @param buf_size the size of the buffer in bytes
+ * @param got_picture_ptr zero if no frame could be decompressed, Otherwise, it is non zero
+ * @return -1 if error, otherwise return the number of
+ * bytes used.
+ */
+int avcodec_decode_video(AVCodecContext *avctx, AVFrame *picture,
+ int *got_picture_ptr,
+ uint8_t *buf, int buf_size)
+{
+ int ret;
+
+ *got_picture_ptr= 0;
+ if((avctx->coded_width||avctx->coded_height) && avcodec_check_dimensions(avctx,avctx->coded_width,avctx->coded_height))
+ return -1;
+ if((avctx->codec->capabilities & CODEC_CAP_DELAY) || buf_size){
+ ret = avctx->codec->decode(avctx, picture, got_picture_ptr,
+ buf, buf_size);
+
+ emms_c(); //needed to avoid an emms_c() call before every return;
+
+ if (*got_picture_ptr)
+ avctx->frame_number++;
+ }else
+ ret= 0;
+
+ return ret;
+}
+
+/* decode an audio frame. return -1 if error, otherwise return the
+ *number of bytes used. If no frame could be decompressed,
+ *frame_size_ptr is zero. Otherwise, it is the decompressed frame
+ *size in BYTES. */
+int avcodec_decode_audio(AVCodecContext *avctx, int16_t *samples,
+ int *frame_size_ptr,
+ uint8_t *buf, int buf_size)
+{
+ int ret;
+
+ *frame_size_ptr= 0;
+ if((avctx->codec->capabilities & CODEC_CAP_DELAY) || buf_size){
+ ret = avctx->codec->decode(avctx, samples, frame_size_ptr,
+ buf, buf_size);
+ avctx->frame_number++;
+ }else
+ ret= 0;
+ return ret;
+}
+
+/* decode a subtitle message. return -1 if 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. */
+int avcodec_decode_subtitle(AVCodecContext *avctx, AVSubtitle *sub,
+ int *got_sub_ptr,
+ const uint8_t *buf, int buf_size)
+{
+ int ret;
+
+ *got_sub_ptr = 0;
+ ret = avctx->codec->decode(avctx, sub, got_sub_ptr,
+ (uint8_t *)buf, buf_size);
+ if (*got_sub_ptr)
+ avctx->frame_number++;
+ return ret;
+}
+
+int avcodec_close(AVCodecContext *avctx)
+{
+ entangled_thread_counter++;
+ if(entangled_thread_counter != 1){
+ av_log(avctx, AV_LOG_ERROR, "insufficient thread locking around avcodec_open/close()\n");
+ entangled_thread_counter--;
+ return -1;
+ }
+
+ if (avctx->codec->close)
+ avctx->codec->close(avctx);
+ avcodec_default_free_buffers(avctx);
+ av_freep(&avctx->priv_data);
+ avctx->codec = NULL;
+ entangled_thread_counter--;
+ return 0;
+}
+
+AVCodec *avcodec_find_encoder(enum CodecID id)
+{
+ AVCodec *p;
+ p = first_avcodec;
+ while (p) {
+ if (p->encode != NULL && p->id == id)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
+AVCodec *avcodec_find_encoder_by_name(const char *name)
+{
+ AVCodec *p;
+ p = first_avcodec;
+ while (p) {
+ if (p->encode != NULL && strcmp(name,p->name) == 0)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
+AVCodec *avcodec_find_decoder(enum CodecID id)
+{
+ AVCodec *p;
+ p = first_avcodec;
+ while (p) {
+ if (p->decode != NULL && p->id == id)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
+AVCodec *avcodec_find_decoder_by_name(const char *name)
+{
+ AVCodec *p;
+ p = first_avcodec;
+ while (p) {
+ if (p->decode != NULL && strcmp(name,p->name) == 0)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
+void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
+{
+ const char *codec_name;
+ AVCodec *p;
+ char buf1[32];
+ char channels_str[100];
+ int bitrate;
+
+ if (encode)
+ p = avcodec_find_encoder(enc->codec_id);
+ else
+ p = avcodec_find_decoder(enc->codec_id);
+
+ if (p) {
+ codec_name = p->name;
+ if (!encode && enc->codec_id == CODEC_ID_MP3) {
+ if (enc->sub_id == 2)
+ codec_name = "mp2";
+ else if (enc->sub_id == 1)
+ codec_name = "mp1";
+ }
+ } else if (enc->codec_id == CODEC_ID_MPEG2TS) {
+ /* fake mpeg2 transport stream codec (currently not
+ registered) */
+ codec_name = "mpeg2ts";
+ } else if (enc->codec_name[0] != '\0') {
+ codec_name = enc->codec_name;
+ } else {
+ /* output avi tags */
+ if( isprint(enc->codec_tag&0xFF) && isprint((enc->codec_tag>>8)&0xFF)
+ && isprint((enc->codec_tag>>16)&0xFF) && isprint((enc->codec_tag>>24)&0xFF)){
+ snprintf(buf1, sizeof(buf1), "%c%c%c%c / 0x%04X",
+ enc->codec_tag & 0xff,
+ (enc->codec_tag >> 8) & 0xff,
+ (enc->codec_tag >> 16) & 0xff,
+ (enc->codec_tag >> 24) & 0xff,
+ enc->codec_tag);
+ } else {
+ snprintf(buf1, sizeof(buf1), "0x%04x", enc->codec_tag);
+ }
+ codec_name = buf1;
+ }
+
+ switch(enc->codec_type) {
+ case CODEC_TYPE_VIDEO:
+ snprintf(buf, buf_size,
+ "Video: %s%s",
+ codec_name, enc->mb_decision ? " (hq)" : "");
+ if (enc->pix_fmt != PIX_FMT_NONE) {
+ snprintf(buf + strlen(buf), buf_size - strlen(buf),
+ ", %s",
+ avcodec_get_pix_fmt_name(enc->pix_fmt));
+ }
+ if (enc->width) {
+ snprintf(buf + strlen(buf), buf_size - strlen(buf),
+ ", %dx%d",
+ enc->width, enc->height);
+ if(av_log_get_level() >= AV_LOG_DEBUG){
+ int g= ff_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);
+ }
+ bitrate = enc->bit_rate;
+ break;
+ case CODEC_TYPE_AUDIO:
+ snprintf(buf, buf_size,
+ "Audio: %s",
+ codec_name);
+ switch (enc->channels) {
+ case 1:
+ strcpy(channels_str, "mono");
+ break;
+ case 2:
+ strcpy(channels_str, "stereo");
+ break;
+ case 6:
+ strcpy(channels_str, "5:1");
+ break;
+ default:
+ snprintf(channels_str, sizeof(channels_str), "%d channels", enc->channels);
+ break;
+ }
+ if (enc->sample_rate) {
+ snprintf(buf + strlen(buf), buf_size - strlen(buf),
+ ", %d Hz, %s",
+ enc->sample_rate,
+ channels_str);
+ }
+
+ /* for PCM codecs, compute bitrate directly */
+ switch(enc->codec_id) {
+ case CODEC_ID_PCM_S32LE:
+ case CODEC_ID_PCM_S32BE:
+ case CODEC_ID_PCM_U32LE:
+ case CODEC_ID_PCM_U32BE:
+ bitrate = enc->sample_rate * enc->channels * 32;
+ break;
+ case CODEC_ID_PCM_S24LE:
+ case CODEC_ID_PCM_S24BE:
+ case CODEC_ID_PCM_U24LE:
+ case CODEC_ID_PCM_U24BE:
+ case CODEC_ID_PCM_S24DAUD:
+ bitrate = enc->sample_rate * enc->channels * 24;
+ break;
+ case CODEC_ID_PCM_S16LE:
+ case CODEC_ID_PCM_S16BE:
+ case CODEC_ID_PCM_U16LE:
+ case CODEC_ID_PCM_U16BE:
+ bitrate = enc->sample_rate * enc->channels * 16;
+ break;
+ case CODEC_ID_PCM_S8:
+ case CODEC_ID_PCM_U8:
+ case CODEC_ID_PCM_ALAW:
+ case CODEC_ID_PCM_MULAW:
+ bitrate = enc->sample_rate * enc->channels * 8;
+ break;
+ default:
+ bitrate = enc->bit_rate;
+ break;
+ }
+ break;
+ case CODEC_TYPE_DATA:
+ snprintf(buf, buf_size, "Data: %s", codec_name);
+ bitrate = enc->bit_rate;
+ break;
+ case CODEC_TYPE_SUBTITLE:
+ snprintf(buf, buf_size, "Subtitle: %s", codec_name);
+ bitrate = enc->bit_rate;
+ break;
+ default:
+ snprintf(buf, buf_size, "Invalid Codec type %d", enc->codec_type);
+ 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");
+ }
+ if (bitrate != 0) {
+ snprintf(buf + strlen(buf), buf_size - strlen(buf),
+ ", %d kb/s", bitrate / 1000);
+ }
+}
+
+unsigned avcodec_version( void )
+{
+ return LIBAVCODEC_VERSION_INT;
+}
+
+unsigned avcodec_build( void )
+{
+ return LIBAVCODEC_BUILD;
+}
+
+static void init_crcs(void){
+ av_crc04C11DB7= av_mallocz_static(sizeof(AVCRC) * 257);
+ av_crc8005 = av_mallocz_static(sizeof(AVCRC) * 257);
+ av_crc07 = av_mallocz_static(sizeof(AVCRC) * 257);
+ av_crc_init(av_crc04C11DB7, 0, 32, 0x04c11db7, sizeof(AVCRC)*257);
+ av_crc_init(av_crc8005 , 0, 16, 0x8005 , sizeof(AVCRC)*257);
+ av_crc_init(av_crc07 , 0, 8, 0x07 , sizeof(AVCRC)*257);
+}
+
+/* must be called before any other functions */
+void avcodec_init(void)
+{
+ static int inited = 0;
+
+ if (inited != 0)
+ return;
+ inited = 1;
+
+ dsputil_static_init();
+ init_crcs();
+}
+
+/**
+ * Flush buffers, should be called when seeking or when swicthing to a different stream.
+ */
+void avcodec_flush_buffers(AVCodecContext *avctx)
+{
+ if(avctx->codec->flush)
+ avctx->codec->flush(avctx);
+}
+
+void avcodec_default_free_buffers(AVCodecContext *s){
+ int i, j;
+
+ if(s->internal_buffer==NULL) return;
+
+ for(i=0; i<INTERNAL_BUFFER_SIZE; i++){
+ InternalBuffer *buf= &((InternalBuffer*)s->internal_buffer)[i];
+ for(j=0; j<4; j++){
+ av_freep(&buf->base[j]);
+ buf->data[j]= NULL;
+ }
+ }
+ av_freep(&s->internal_buffer);
+
+ s->internal_buffer_count=0;
+}
+
+char av_get_pict_type_char(int pict_type){
+ switch(pict_type){
+ case I_TYPE: return 'I';
+ case P_TYPE: return 'P';
+ case B_TYPE: return 'B';
+ case S_TYPE: return 'S';
+ case SI_TYPE:return 'i';
+ case SP_TYPE:return 'p';
+ default: return '?';
+ }
+}
+
+int av_get_bits_per_sample(enum CodecID codec_id){
+ switch(codec_id){
+ case CODEC_ID_ADPCM_SBPRO_2:
+ return 2;
+ case CODEC_ID_ADPCM_SBPRO_3:
+ return 3;
+ case CODEC_ID_ADPCM_SBPRO_4:
+ case CODEC_ID_ADPCM_CT:
+ return 4;
+ case CODEC_ID_PCM_ALAW:
+ case CODEC_ID_PCM_MULAW:
+ case CODEC_ID_PCM_S8:
+ case CODEC_ID_PCM_U8:
+ return 8;
+ case CODEC_ID_PCM_S16BE:
+ case CODEC_ID_PCM_S16LE:
+ case CODEC_ID_PCM_U16BE:
+ case CODEC_ID_PCM_U16LE:
+ return 16;
+ case CODEC_ID_PCM_S24DAUD:
+ case CODEC_ID_PCM_S24BE:
+ case CODEC_ID_PCM_S24LE:
+ case CODEC_ID_PCM_U24BE:
+ case CODEC_ID_PCM_U24LE:
+ return 24;
+ case CODEC_ID_PCM_S32BE:
+ case CODEC_ID_PCM_S32LE:
+ case CODEC_ID_PCM_U32BE:
+ case CODEC_ID_PCM_U32LE:
+ return 32;
+ default:
+ return 0;
+ }
+}
+
+#if !defined(HAVE_THREADS)
+int avcodec_thread_init(AVCodecContext *s, int thread_count){
+ 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;
+}
+
+/* Wrapper to work around the lack of mkstemp() on mingw/cygin.
+ * Also, tries to create file in /tmp first, if possible.
+ * *prefix can be a character constant; *filename will be allocated internally.
+ * Returns file descriptor of opened file (or -1 on error)
+ * and opened file name in **filename. */
+int av_tempfile(char *prefix, char **filename) {
+ int fd=-1;
+#ifdef __MINGW32__
+ *filename = tempnam(".", prefix);
+#else
+ size_t len = strlen(prefix) + 12; /* room for "/tmp/" and "XXXXXX\0" */
+ *filename = av_malloc(len);
+#endif
+ /* -----common section-----*/
+ if (*filename == NULL) {
+ av_log(NULL, AV_LOG_ERROR, "ff_tempfile: Cannot allocate file name\n");
+ return -1;
+ }
+#ifdef __MINGW32__
+ fd = open(*filename, _O_RDWR | _O_BINARY | _O_CREAT, 0444);
+#else
+ snprintf(*filename, len, "/tmp/%sXXXXXX", prefix);
+ fd = mkstemp(*filename);
+ if (fd < 0) {
+ snprintf(*filename, len, "./%sXXXXXX", prefix);
+ fd = mkstemp(*filename);
+ }
+#endif
+ /* -----common section-----*/
+ if (fd < 0) {
+ av_log(NULL, AV_LOG_ERROR, "ff_tempfile: Cannot open temporary file %s\n", *filename);
+ return -1;
+ }
+ return fd; /* success */
+}
diff --git a/contrib/ffmpeg/libavcodec/vc1.c b/contrib/ffmpeg/libavcodec/vc1.c
new file mode 100644
index 000000000..cd3c0c2d6
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vc1.c
@@ -0,0 +1,4370 @@
+/*
+ * VC-1 and WMV3 decoder
+ * Copyright (c) 2006 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 vc1.c
+ * VC-1 and WMV3 decoder
+ *
+ */
+#include "common.h"
+#include "dsputil.h"
+#include "avcodec.h"
+#include "mpegvideo.h"
+#include "vc1data.h"
+#include "vc1acdata.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+extern const uint32_t ff_table0_dc_lum[120][2], ff_table1_dc_lum[120][2];
+extern const uint32_t ff_table0_dc_chroma[120][2], ff_table1_dc_chroma[120][2];
+extern VLC ff_msmp4_dc_luma_vlc[2], ff_msmp4_dc_chroma_vlc[2];
+#define MB_INTRA_VLC_BITS 9
+extern VLC ff_msmp4_mb_i_vlc;
+extern const uint16_t ff_msmp4_mb_i_table[64][2];
+#define DC_VLC_BITS 9
+#define AC_VLC_BITS 9
+static const uint16_t table_mb_intra[64][2];
+
+
+/** 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
+};
+//@}
+
+/** @name MV types for B frames */
+//@{
+enum BMVTypes {
+ BMV_TYPE_BACKWARD,
+ BMV_TYPE_FORWARD,
+ BMV_TYPE_INTERPOLATED
+};
+//@}
+
+/** @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
+};
+//@}
+
+/** Table for conversion between TTBLK and TTMB */
+static const int 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 }
+};
+
+static const int ttfrm_to_tt[4] = { TT_8X8, TT_8X4, TT_4X8, TT_4X4 };
+
+/** MV P mode - the 5th element is only used for mode 1 */
+static const uint8_t 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 }
+};
+static const uint8_t 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 }
+};
+
+/** One more frame type */
+#define BI_TYPE 7
+
+static const int fps_nr[5] = { 24, 25, 30, 50, 60 },
+ fps_dr[2] = { 1000, 1001 };
+static const uint8_t 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
+static VLC vc1_bfraction_vlc;
+#define VC1_IMODE_VLC_BITS 4
+static VLC vc1_imode_vlc;
+#define VC1_NORM2_VLC_BITS 3
+static VLC vc1_norm2_vlc;
+#define VC1_NORM6_VLC_BITS 9
+static VLC vc1_norm6_vlc;
+/* Could be optimized, one table only needs 8 bits */
+#define VC1_TTMB_VLC_BITS 9 //12
+static VLC vc1_ttmb_vlc[3];
+#define VC1_MV_DIFF_VLC_BITS 9 //15
+static VLC vc1_mv_diff_vlc[4];
+#define VC1_CBPCY_P_VLC_BITS 9 //14
+static VLC vc1_cbpcy_p_vlc[4];
+#define VC1_4MV_BLOCK_PATTERN_VLC_BITS 6
+static VLC vc1_4mv_block_pattern_vlc[4];
+#define VC1_TTBLK_VLC_BITS 5
+static VLC vc1_ttblk_vlc[3];
+#define VC1_SUBBLKPAT_VLC_BITS 6
+static VLC vc1_subblkpat_vlc[3];
+
+static VLC vc1_ac_coeff_table[8];
+//@}
+
+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
+};
+//@}
+
+
+/** The VC1 Context
+ * @fixme Change size wherever another size is more efficient
+ * Many members are only used for Advanced Profile
+ */
+typedef struct VC1Context{
+ MpegEncContext s;
+
+ int bits;
+
+ /** Simple/Main Profile sequence header */
+ //@{
+ int res_sm; ///< reserved, 2b
+ 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 extended_dmv; ///< Additional extended dmv range at P/B frame-level
+ int color_prim; ///< 8bits, chroma coordinates of the color primaries
+ int transfer_char; ///< 8bits, Opto-electronic transfer characteristics
+ int matrix_coef; ///< 8bits, Color primaries->YCbCr transform matrix
+ 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 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
+ /** 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
+ uint8_t ttblk4x4; ///< Value of ttblk which indicates a 4x4 transform
+ 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;
+ uint8_t pquantizer; ///< Uniform (over sequence) quantizer in use
+ VLC *cbpcy_vlc; ///< CBPCY VLC table
+ int tt_index; ///< Index for Transform Type tables
+ uint8_t* mv_type_mb_plane; ///< bitplane for mv_type == (4MV)
+ uint8_t* direct_mb_plane; ///< bitplane for "direct" MBs
+ int mv_type_is_raw; ///< mv type mb plane is not coded
+ int dmb_is_raw; ///< direct 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 */
+ //@{
+ uint8_t fcm; ///< 0->Progressive, 2->Frame-Interlace, 3->Field-Interlace
+ 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;
+ //@}
+
+ int p_frame_skipped;
+ int bi_type;
+} VC1Context;
+
+/**
+ * Get unary code of limited length
+ * @fixme FIXME Slow and ugly
+ * @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 int get_prefix(GetBitContext *gb, int stop, int len)
+{
+#if 1
+ int i;
+
+ for(i = 0; i < len && get_bits1(gb) != stop; i++);
+ return i;
+/* int i = 0, tmp = !stop;
+
+ while (i != len && tmp != stop)
+ {
+ tmp = get_bits(gb, 1);
+ i++;
+ }
+ if (i == len && tmp != stop) return len+1;
+ return i;*/
+#else
+ unsigned int buf;
+ int log;
+
+ OPEN_READER(re, gb);
+ UPDATE_CACHE(re, gb);
+ buf=GET_CACHE(re, gb); //Still not sure
+ if (stop) buf = ~buf;
+
+ log= av_log2(-buf); //FIXME: -?
+ if (log < limit){
+ LAST_SKIP_BITS(re, gb, log+1);
+ CLOSE_READER(re, gb);
+ return log;
+ }
+
+ LAST_SKIP_BITS(re, gb, limit);
+ CLOSE_READER(re, gb);
+ return limit;
+#endif
+}
+
+static inline int decode210(GetBitContext *gb){
+ int n;
+ n = get_bits1(gb);
+ if (n == 1)
+ return 0;
+ else
+ return 2 - get_bits1(gb);
+}
+
+/**
+ * Init VC-1 specific tables and VC1Context members
+ * @param v The VC1Context to initialize
+ * @return Status
+ */
+static int vc1_init_common(VC1Context *v)
+{
+ static int done = 0;
+ int i = 0;
+
+ v->hrd_rate = v->hrd_buffer = NULL;
+
+ /* VLC tables */
+ if(!done)
+ {
+ done = 1;
+ init_vlc(&vc1_bfraction_vlc, VC1_BFRACTION_VLC_BITS, 23,
+ vc1_bfraction_bits, 1, 1,
+ vc1_bfraction_codes, 1, 1, 1);
+ init_vlc(&vc1_norm2_vlc, VC1_NORM2_VLC_BITS, 4,
+ vc1_norm2_bits, 1, 1,
+ vc1_norm2_codes, 1, 1, 1);
+ init_vlc(&vc1_norm6_vlc, VC1_NORM6_VLC_BITS, 64,
+ vc1_norm6_bits, 1, 1,
+ vc1_norm6_codes, 2, 2, 1);
+ init_vlc(&vc1_imode_vlc, VC1_IMODE_VLC_BITS, 7,
+ vc1_imode_bits, 1, 1,
+ vc1_imode_codes, 1, 1, 1);
+ for (i=0; i<3; i++)
+ {
+ init_vlc(&vc1_ttmb_vlc[i], VC1_TTMB_VLC_BITS, 16,
+ vc1_ttmb_bits[i], 1, 1,
+ vc1_ttmb_codes[i], 2, 2, 1);
+ init_vlc(&vc1_ttblk_vlc[i], VC1_TTBLK_VLC_BITS, 8,
+ vc1_ttblk_bits[i], 1, 1,
+ vc1_ttblk_codes[i], 1, 1, 1);
+ init_vlc(&vc1_subblkpat_vlc[i], VC1_SUBBLKPAT_VLC_BITS, 15,
+ vc1_subblkpat_bits[i], 1, 1,
+ vc1_subblkpat_codes[i], 1, 1, 1);
+ }
+ for(i=0; i<4; i++)
+ {
+ init_vlc(&vc1_4mv_block_pattern_vlc[i], VC1_4MV_BLOCK_PATTERN_VLC_BITS, 16,
+ vc1_4mv_block_pattern_bits[i], 1, 1,
+ vc1_4mv_block_pattern_codes[i], 1, 1, 1);
+ init_vlc(&vc1_cbpcy_p_vlc[i], VC1_CBPCY_P_VLC_BITS, 64,
+ vc1_cbpcy_p_bits[i], 1, 1,
+ vc1_cbpcy_p_codes[i], 2, 2, 1);
+ init_vlc(&vc1_mv_diff_vlc[i], VC1_MV_DIFF_VLC_BITS, 73,
+ vc1_mv_diff_bits[i], 1, 1,
+ vc1_mv_diff_codes[i], 2, 2, 1);
+ }
+ for(i=0; i<8; i++)
+ init_vlc(&vc1_ac_coeff_table[i], AC_VLC_BITS, vc1_ac_sizes[i],
+ &vc1_ac_tables[i][0][1], 8, 4,
+ &vc1_ac_tables[i][0][0], 8, 4, 1);
+ init_vlc(&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, 1);
+ }
+
+ /* Other defaults */
+ v->pq = -1;
+ v->mvrange = 0; /* 7.1.1.18, p80 */
+
+ return 0;
+}
+
+/***********************************************************************/
+/**
+ * @defgroup bitplane VC9 Bitplane decoding
+ * @see 8.7, p56
+ * @{
+ */
+
+/** @addtogroup bitplane
+ * 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_bits(gb, 1)) //rowskip
+ memset(plane, 0, width);
+ else
+ for (x=0; x<width; x++)
+ plane[x] = get_bits(gb, 1);
+ 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
+ * @fixme 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_bits(gb, 1)) //colskip
+ for (y=0; y<height; y++)
+ plane[y*stride] = 0;
+ else
+ for (y=0; y<height; y++)
+ plane[y*stride] = get_bits(gb, 1);
+ plane ++;
+ }
+}
+
+/** Decode a bitplane's bits
+ * @param bp Bitplane where to store the decode bits
+ * @param v VC-1 context for bit reading and logging
+ * @return Status
+ * @fixme 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;
+ stride = v->s.mb_stride;
+ invert = get_bits(gb, 1);
+ imode = get_vlc2(gb, 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_bits(gb, 1);
+ offset = 1;
+ }
+ else offset = 0;
+ // decode bitplane as one long line
+ for (y = offset; y < height * width; y += 2) {
+ code = get_vlc2(gb, 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, 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, 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_bits(gb, 1);
+ 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_bits(gb, 1);
+ 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;
+}
+
+/** Put block onto picture
+ */
+static void vc1_put_block(VC1Context *v, DCTELEM block[6][64])
+{
+ uint8_t *Y;
+ int ys, us, vs;
+ DSPContext *dsp = &v->s.dsp;
+
+ if(v->rangeredfrm) {
+ int i, j, k;
+ for(k = 0; k < 6; k++)
+ for(j = 0; j < 8; j++)
+ for(i = 0; i < 8; i++)
+ block[k][i + j*8] = ((block[k][i + j*8] - 128) << 1) + 128;
+
+ }
+ ys = v->s.current_picture.linesize[0];
+ us = v->s.current_picture.linesize[1];
+ vs = v->s.current_picture.linesize[2];
+ Y = v->s.dest[0];
+
+ dsp->put_pixels_clamped(block[0], Y, ys);
+ dsp->put_pixels_clamped(block[1], Y + 8, ys);
+ Y += ys * 8;
+ dsp->put_pixels_clamped(block[2], Y, ys);
+ dsp->put_pixels_clamped(block[3], Y + 8, ys);
+
+ if(!(v->s.flags & CODEC_FLAG_GRAY)) {
+ dsp->put_pixels_clamped(block[4], v->s.dest[1], us);
+ dsp->put_pixels_clamped(block[5], v->s.dest[2], vs);
+ }
+}
+
+/** 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;
+ DSPContext *dsp = &v->s.dsp;
+ uint8_t *srcY, *srcU, *srcV;
+ int dxy, uvdxy, mx, my, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y;
+
+ if(!v->s.last_picture.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 == P_TYPE) {
+ s->current_picture.motion_val[1][s->block_index[0]][0] = mx;
+ s->current_picture.motion_val[1][s->block_index[0]][1] = my;
+ }
+ uvmx = (mx + ((mx & 3) == 3)) >> 1;
+ uvmy = (my + ((my & 3) == 3)) >> 1;
+ if(!dir) {
+ srcY = s->last_picture.data[0];
+ srcU = s->last_picture.data[1];
+ srcV = s->last_picture.data[2];
+ } else {
+ srcY = s->next_picture.data[0];
+ srcU = s->next_picture.data[1];
+ srcV = s->next_picture.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);
+
+ src_x = clip( src_x, -16, s->mb_width * 16);
+ src_y = clip( src_y, -16, s->mb_height * 16);
+ uvsrc_x = clip(uvsrc_x, -8, s->mb_width * 8);
+ uvsrc_y = clip(uvsrc_y, -8, s->mb_height * 8);
+
+ srcY += src_y * s->linesize + src_x;
+ srcU += uvsrc_y * s->uvlinesize + uvsrc_x;
+ srcV += uvsrc_y * s->uvlinesize + uvsrc_x;
+
+ /* 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)
+ || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx&3) - 16 - s->mspel*3
+ || (unsigned)(src_y - s->mspel) > s->v_edge_pos - (my&3) - 16 - s->mspel*3){
+ uint8_t *uvbuf= s->edge_emu_buffer + 19 * s->linesize;
+
+ srcY -= s->mspel * (1 + s->linesize);
+ ff_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, s->v_edge_pos);
+ srcY = s->edge_emu_buffer;
+ ff_emulated_edge_mc(uvbuf , srcU, s->uvlinesize, 8+1, 8+1,
+ uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, s->v_edge_pos >> 1);
+ ff_emulated_edge_mc(uvbuf + 16, srcV, s->uvlinesize, 8+1, 8+1,
+ uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, s->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);
+ }
+
+ if(v->fastuvmc) {
+ uvmx = uvmx + ((uvmx<0)?-(uvmx&1):(uvmx&1));
+ uvmy = uvmy + ((uvmy<0)?-(uvmy&1):(uvmy&1));
+ }
+
+ if(s->mspel) {
+ dxy = ((my & 3) << 2) | (mx & 3);
+ dsp->put_vc1_mspel_pixels_tab[dxy](s->dest[0] , srcY , s->linesize, v->rnd);
+ dsp->put_vc1_mspel_pixels_tab[dxy](s->dest[0] + 8, srcY + 8, s->linesize, v->rnd);
+ srcY += s->linesize * 8;
+ dsp->put_vc1_mspel_pixels_tab[dxy](s->dest[0] + 8 * s->linesize , srcY , s->linesize, v->rnd);
+ dsp->put_vc1_mspel_pixels_tab[dxy](s->dest[0] + 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)
+ dsp->put_pixels_tab[0][dxy](s->dest[0], srcY, s->linesize, 16);
+ else
+ dsp->put_no_rnd_pixels_tab[0][dxy](s->dest[0], srcY, s->linesize, 16);
+ }
+
+ if(s->flags & CODEC_FLAG_GRAY) return;
+ /* Chroma MC always uses qpel bilinear */
+ uvdxy = ((uvmy & 3) << 2) | (uvmx & 3);
+ uvmx = (uvmx&3)<<1;
+ uvmy = (uvmy&3)<<1;
+ if(!v->rnd){
+ dsp->put_h264_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy);
+ dsp->put_h264_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy);
+ }else{
+ dsp->put_no_rnd_h264_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy);
+ dsp->put_no_rnd_h264_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy);
+ }
+}
+
+/** Do motion compensation for 4-MV macroblock - luminance block
+ */
+static void vc1_mc_4mv_luma(VC1Context *v, int n)
+{
+ MpegEncContext *s = &v->s;
+ DSPContext *dsp = &v->s.dsp;
+ uint8_t *srcY;
+ int dxy, mx, my, src_x, src_y;
+ int off;
+
+ if(!v->s.last_picture.data[0])return;
+ mx = s->mv[0][n][0];
+ my = s->mv[0][n][1];
+ srcY = s->last_picture.data[0];
+
+ off = s->linesize * 4 * (n&2) + (n&1) * 8;
+
+ src_x = s->mb_x * 16 + (n&1) * 8 + (mx >> 2);
+ src_y = s->mb_y * 16 + (n&2) * 4 + (my >> 2);
+
+ src_x = clip( src_x, -16, s->mb_width * 16);
+ src_y = clip( src_y, -16, s->mb_height * 16);
+
+ srcY += src_y * s->linesize + src_x;
+
+ if(v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP)
+ || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx&3) - 8 - s->mspel*2
+ || (unsigned)(src_y - s->mspel) > s->v_edge_pos - (my&3) - 8 - s->mspel*2){
+ srcY -= s->mspel * (1 + s->linesize);
+ ff_emulated_edge_mc(s->edge_emu_buffer, srcY, s->linesize, 9+s->mspel*2, 9+s->mspel*2,
+ src_x - s->mspel, src_y - s->mspel, s->h_edge_pos, s->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;
+ }
+ }
+ /* 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;
+ }
+ }
+ srcY += s->mspel * (1 + s->linesize);
+ }
+
+ if(s->mspel) {
+ dxy = ((my & 3) << 2) | (mx & 3);
+ dsp->put_vc1_mspel_pixels_tab[dxy](s->dest[0] + off, srcY, s->linesize, v->rnd);
+ } else { // hpel mc - always used for luma
+ dxy = (my & 2) | ((mx & 2) >> 1);
+ if(!v->rnd)
+ dsp->put_pixels_tab[1][dxy](s->dest[0] + off, srcY, s->linesize, 8);
+ else
+ dsp->put_no_rnd_pixels_tab[1][dxy](s->dest[0] + off, srcY, s->linesize, 8);
+ }
+}
+
+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 - both chroma blocks
+ */
+static void vc1_mc_4mv_chroma(VC1Context *v)
+{
+ MpegEncContext *s = &v->s;
+ DSPContext *dsp = &v->s.dsp;
+ uint8_t *srcU, *srcV;
+ int uvdxy, uvmx, uvmy, uvsrc_x, uvsrc_y;
+ int i, idx, tx = 0, ty = 0;
+ int mvx[4], mvy[4], intra[4];
+ static const int count[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
+
+ if(!v->s.last_picture.data[0])return;
+ if(s->flags & CODEC_FLAG_GRAY) return;
+
+ for(i = 0; i < 4; i++) {
+ mvx[i] = s->mv[0][i][0];
+ mvy[i] = s->mv[0][i][1];
+ intra[i] = v->mb_type[0][s->block_index[i]];
+ }
+
+ /* calculate chroma MV vector from four luma MVs */
+ idx = (intra[3] << 3) | (intra[2] << 2) | (intra[1] << 1) | intra[0];
+ if(!idx) { // all blocks are inter
+ tx = median4(mvx[0], mvx[1], mvx[2], mvx[3]);
+ ty = median4(mvy[0], mvy[1], mvy[2], mvy[3]);
+ } else if(count[idx] == 1) { // 3 inter blocks
+ switch(idx) {
+ case 0x1:
+ tx = mid_pred(mvx[1], mvx[2], mvx[3]);
+ ty = mid_pred(mvy[1], mvy[2], mvy[3]);
+ break;
+ case 0x2:
+ tx = mid_pred(mvx[0], mvx[2], mvx[3]);
+ ty = mid_pred(mvy[0], mvy[2], mvy[3]);
+ break;
+ case 0x4:
+ tx = mid_pred(mvx[0], mvx[1], mvx[3]);
+ ty = mid_pred(mvy[0], mvy[1], mvy[3]);
+ break;
+ case 0x8:
+ tx = mid_pred(mvx[0], mvx[1], mvx[2]);
+ ty = mid_pred(mvy[0], mvy[1], mvy[2]);
+ break;
+ }
+ } else if(count[idx] == 2) {
+ int t1 = 0, t2 = 0;
+ for(i=0; i<3;i++) if(!intra[i]) {t1 = i; break;}
+ for(i= t1+1; i<4; i++)if(!intra[i]) {t2 = i; break;}
+ tx = (mvx[t1] + mvx[t2]) / 2;
+ ty = (mvy[t1] + mvy[t2]) / 2;
+ } else
+ return; //no need to do MC for inter blocks
+
+ s->current_picture.motion_val[1][s->block_index[0]][0] = tx;
+ s->current_picture.motion_val[1][s->block_index[0]][1] = ty;
+ uvmx = (tx + ((tx&3) == 3)) >> 1;
+ uvmy = (ty + ((ty&3) == 3)) >> 1;
+
+ uvsrc_x = s->mb_x * 8 + (uvmx >> 2);
+ uvsrc_y = s->mb_y * 8 + (uvmy >> 2);
+
+ uvsrc_x = clip(uvsrc_x, -8, s->mb_width * 8);
+ uvsrc_y = clip(uvsrc_y, -8, s->mb_height * 8);
+ srcU = s->last_picture.data[1] + uvsrc_y * s->uvlinesize + uvsrc_x;
+ srcV = s->last_picture.data[2] + uvsrc_y * s->uvlinesize + uvsrc_x;
+ if(v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP)
+ || (unsigned)uvsrc_x > (s->h_edge_pos >> 1) - 9
+ || (unsigned)uvsrc_y > (s->v_edge_pos >> 1) - 9){
+ ff_emulated_edge_mc(s->edge_emu_buffer , srcU, s->uvlinesize, 8+1, 8+1,
+ uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, s->v_edge_pos >> 1);
+ ff_emulated_edge_mc(s->edge_emu_buffer + 16, srcV, s->uvlinesize, 8+1, 8+1,
+ uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, s->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;
+ }
+ }
+ }
+
+ if(v->fastuvmc) {
+ uvmx = uvmx + ((uvmx<0)?-(uvmx&1):(uvmx&1));
+ uvmy = uvmy + ((uvmy<0)?-(uvmy&1):(uvmy&1));
+ }
+
+ /* Chroma MC always uses qpel bilinear */
+ uvdxy = ((uvmy & 3) << 2) | (uvmx & 3);
+ uvmx = (uvmx&3)<<1;
+ uvmy = (uvmy&3)<<1;
+ if(!v->rnd){
+ dsp->put_h264_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy);
+ dsp->put_h264_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy);
+ }else{
+ dsp->put_no_rnd_h264_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy);
+ dsp->put_no_rnd_h264_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy);
+ }
+}
+
+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
+ */
+static int decode_sequence_header(AVCodecContext *avctx, GetBitContext *gb)
+{
+ VC1Context *v = avctx->priv_data;
+
+ av_log(avctx, AV_LOG_DEBUG, "Header: %0X\n", show_bits(gb, 32));
+ v->profile = get_bits(gb, 2);
+ if (v->profile == 2)
+ {
+ av_log(avctx, AV_LOG_ERROR, "Profile value 2 is forbidden (and WMV3 Complex Profile is unsupported)\n");
+ return -1;
+ }
+
+ if (v->profile == PROFILE_ADVANCED)
+ {
+ return decode_sequence_header_adv(v, gb);
+ }
+ else
+ {
+ v->res_sm = get_bits(gb, 2); //reserved
+ if (v->res_sm)
+ {
+ av_log(avctx, AV_LOG_ERROR,
+ "Reserved RES_SM=%i is forbidden\n", v->res_sm);
+ 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_bits(gb, 1); //common
+ if(v->s.loop_filter == 1 && v->profile == PROFILE_SIMPLE)
+ {
+ av_log(avctx, AV_LOG_ERROR,
+ "LOOPFILTER shell not be enabled in simple profile\n");
+ }
+
+ v->res_x8 = get_bits(gb, 1); //reserved
+ if (v->res_x8)
+ {
+ av_log(avctx, AV_LOG_ERROR,
+ "1 for reserved RES_X8 is forbidden\n");
+ //return -1;
+ }
+ v->multires = get_bits(gb, 1);
+ v->res_fasttx = get_bits(gb, 1);
+ if (!v->res_fasttx)
+ {
+ av_log(avctx, AV_LOG_ERROR,
+ "0 for reserved RES_FASTTX is forbidden\n");
+ //return -1;
+ }
+
+ v->fastuvmc = get_bits(gb, 1); //common
+ if (!v->profile && !v->fastuvmc)
+ {
+ av_log(avctx, AV_LOG_ERROR,
+ "FASTUVMC unavailable in Simple Profile\n");
+ return -1;
+ }
+ v->extended_mv = get_bits(gb, 1); //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_bits(gb, 1); //common
+
+ v->res_transtab = get_bits(gb, 1);
+ if (v->res_transtab)
+ {
+ av_log(avctx, AV_LOG_ERROR,
+ "1 for reserved RES_TRANSTAB is forbidden\n");
+ return -1;
+ }
+
+ v->overlap = get_bits(gb, 1); //common
+
+ v->s.resync_marker = get_bits(gb, 1);
+ v->rangered = get_bits(gb, 1);
+ 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_bits(gb, 1); //common
+ v->res_rtm_flag = get_bits(gb, 1); //reserved
+ if (!v->res_rtm_flag)
+ {
+// av_log(avctx, AV_LOG_ERROR,
+// "0 for reserved RES_RTM_FLAG is forbidden\n");
+ av_log(avctx, AV_LOG_ERROR,
+ "Old WMV3 version detected, only I-frames will be decoded\n");
+ //return -1;
+ }
+ 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_bits(gb, 1); //common
+
+ v->s.avctx->coded_width = (get_bits(gb, 12) + 1) << 1;
+ v->s.avctx->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);
+ get_bits1(gb); // reserved
+ 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;
+ }
+ if(get_bits1(gb)) { //Display Info - decoding is not affected by it
+ int w, h, ar = 0;
+ av_log(v->s.avctx, AV_LOG_INFO, "Display extended info:\n");
+ w = get_bits(gb, 14);
+ h = get_bits(gb, 14);
+ av_log(v->s.avctx, AV_LOG_INFO, "Display dimensions: %ix%i\n", w, h);
+ //TODO: store aspect ratio in AVCodecContext
+ if(get_bits1(gb))
+ ar = get_bits(gb, 4);
+ if(ar == 15) {
+ w = get_bits(gb, 8);
+ h = get_bits(gb, 8);
+ }
+
+ if(get_bits1(gb)){ //framerate stuff
+ if(get_bits1(gb)) {
+ get_bits(gb, 16);
+ } else {
+ get_bits(gb, 8);
+ get_bits(gb, 4);
+ }
+ }
+
+ if(get_bits1(gb)){
+ v->color_prim = get_bits(gb, 8);
+ v->transfer_char = get_bits(gb, 8);
+ v->matrix_coef = get_bits(gb, 8);
+ }
+ }
+
+ v->hrd_param_flag = get_bits1(gb);
+ if(v->hrd_param_flag) {
+ int i;
+ v->hrd_num_leaky_buckets = get_bits(gb, 5);
+ get_bits(gb, 4); //bitrate exponent
+ get_bits(gb, 4); //buffer size exponent
+ for(i = 0; i < v->hrd_num_leaky_buckets; i++) {
+ get_bits(gb, 16); //hrd_rate[n]
+ get_bits(gb, 16); //hrd_buffer[n]
+ }
+ }
+ return 0;
+}
+
+static int decode_entry_point(AVCodecContext *avctx, GetBitContext *gb)
+{
+ VC1Context *v = avctx->priv_data;
+ int i;
+
+ av_log(avctx, AV_LOG_DEBUG, "Entry point: %08X\n", show_bits_long(gb, 32));
+ get_bits1(gb); // broken link
+ avctx->max_b_frames = 1 - get_bits1(gb); // 'closed entry' also signalize possible B-frames
+ v->panscanflag = get_bits1(gb);
+ get_bits1(gb); // refdist flag
+ v->s.loop_filter = get_bits1(gb);
+ 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++) {
+ get_bits(gb, 8); //hrd_full[n]
+ }
+ }
+
+ if(get_bits1(gb)){
+ avctx->coded_width = (get_bits(gb, 12)+1)<<1;
+ avctx->coded_height = (get_bits(gb, 12)+1)<<1;
+ }
+ if(v->extended_mv)
+ v->extended_dmv = get_bits1(gb);
+ if(get_bits1(gb)) {
+ av_log(avctx, AV_LOG_ERROR, "Luma scaling is not supported, expect wrong picture\n");
+ skip_bits(gb, 3); // Y range, ignored for now
+ }
+ if(get_bits1(gb)) {
+ av_log(avctx, AV_LOG_ERROR, "Chroma scaling is not supported, expect wrong picture\n");
+ skip_bits(gb, 3); // UV range, ignored for now
+ }
+
+ return 0;
+}
+
+static int vc1_parse_frame_header(VC1Context *v, GetBitContext* gb)
+{
+ int pqindex, lowquant, status;
+
+ if(v->finterpflag) v->interpfrm = get_bits(gb, 1);
+ skip_bits(gb, 2); //framecnt unused
+ v->rangeredfrm = 0;
+ if (v->rangered) v->rangeredfrm = get_bits(gb, 1);
+ v->s.pict_type = get_bits(gb, 1);
+ if (v->s.avctx->max_b_frames) {
+ if (!v->s.pict_type) {
+ if (get_bits(gb, 1)) v->s.pict_type = I_TYPE;
+ else v->s.pict_type = B_TYPE;
+ } else v->s.pict_type = P_TYPE;
+ } else v->s.pict_type = v->s.pict_type ? P_TYPE : I_TYPE;
+
+ v->bi_type = 0;
+ if(v->s.pict_type == B_TYPE) {
+ v->bfraction = get_vlc2(gb, vc1_bfraction_vlc.table, VC1_BFRACTION_VLC_BITS, 1);
+ v->bfraction = vc1_bfraction_lut[v->bfraction];
+ if(v->bfraction == 0) {
+ v->s.pict_type = BI_TYPE;
+ }
+ }
+ if(v->s.pict_type == I_TYPE || v->s.pict_type == BI_TYPE)
+ get_bits(gb, 7); // skip buffer fullness
+
+ /* calculate RND */
+ if(v->s.pict_type == I_TYPE || v->s.pict_type == BI_TYPE)
+ v->rnd = 1;
+ if(v->s.pict_type == P_TYPE)
+ v->rnd ^= 1;
+
+ /* Quantizer stuff */
+ pqindex = get_bits(gb, 5);
+ if (v->quantizer_mode == QUANT_FRAME_IMPLICIT)
+ v->pq = pquant_table[0][pqindex];
+ else
+ v->pq = 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_bits(gb, 1);
+ else v->halfpq = 0;
+ if (v->quantizer_mode == QUANT_FRAME_EXPLICIT)
+ v->pquantizer = get_bits(gb, 1);
+ v->dquantfrm = 0;
+ if (v->extended_mv == 1) v->mvrange = get_prefix(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->profile == PROFILE_ADVANCED)
+ {
+ if (v->postprocflag) v->postproc = get_bits(gb, 1);
+ }
+ else
+ if (v->multires && v->s.pict_type != B_TYPE) v->respic = get_bits(gb, 2);
+
+//av_log(v->s.avctx, AV_LOG_INFO, "%c Frame: QP=[%i]%i (+%i/2) %i\n",
+// (v->s.pict_type == P_TYPE) ? 'P' : ((v->s.pict_type == I_TYPE) ? 'I' : 'B'), pqindex, v->pq, v->halfpq, v->rangeredfrm);
+
+ if(v->s.pict_type == I_TYPE || v->s.pict_type == P_TYPE) v->use_ic = 0;
+
+ switch(v->s.pict_type) {
+ case P_TYPE:
+ 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 = mv_pmode_table[lowquant][get_prefix(gb, 1, 4)];
+ if (v->mv_mode == MV_PMODE_INTENSITY_COMP)
+ {
+ int scale, shift, i;
+ v->mv_mode2 = mv_pmode_table2[lowquant][get_prefix(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] = clip_uint8((scale * i + shift + 32) >> 6);
+ v->lutuv[i] = clip_uint8((scale * (i - 128) + 128*64 + 32) >> 6);
+ }
+ }
+ 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 vc1_ tables
+ v->cbpcy_vlc = &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_bits(gb, 1);
+ if (v->ttmbf)
+ {
+ v->ttfrm = ttfrm_to_tt[get_bits(gb, 2)];
+ }
+ } else {
+ v->ttmbf = 1;
+ v->ttfrm = TT_8X8;
+ }
+ break;
+ case B_TYPE:
+ 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 = get_bits1(gb) ? MV_PMODE_1MV : MV_PMODE_1MV_HPEL_BILIN;
+ 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 = &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_bits(gb, 1);
+ if (v->ttmbf)
+ {
+ v->ttfrm = ttfrm_to_tt[get_bits(gb, 2)];
+ }
+ } else {
+ v->ttmbf = 1;
+ v->ttfrm = TT_8X8;
+ }
+ break;
+ }
+
+ /* AC Syntax */
+ v->c_ac_table_index = decode012(gb);
+ if (v->s.pict_type == I_TYPE || v->s.pict_type == BI_TYPE)
+ {
+ v->y_ac_table_index = decode012(gb);
+ }
+ /* DC Syntax */
+ v->s.dc_table_index = get_bits(gb, 1);
+
+ if(v->s.pict_type == BI_TYPE) {
+ v->s.pict_type = B_TYPE;
+ v->bi_type = 1;
+ }
+ return 0;
+}
+
+static int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb)
+{
+ int fcm;
+ int pqindex, lowquant;
+ int status;
+
+ v->p_frame_skipped = 0;
+
+ if(v->interlace)
+ fcm = decode012(gb);
+ switch(get_prefix(gb, 0, 4)) {
+ case 0:
+ v->s.pict_type = P_TYPE;
+ break;
+ case 1:
+ v->s.pict_type = B_TYPE;
+ break;
+ case 2:
+ v->s.pict_type = I_TYPE;
+ break;
+ case 3:
+ v->s.pict_type = BI_TYPE;
+ break;
+ case 4:
+ v->s.pict_type = P_TYPE; // skipped pic
+ v->p_frame_skipped = 1;
+ return 0;
+ }
+ if(v->tfcntrflag)
+ get_bits(gb, 8);
+ if(v->broadcast) {
+ if(!v->interlace || v->panscanflag) {
+ get_bits(gb, 2);
+ } else {
+ get_bits1(gb);
+ get_bits1(gb);
+ }
+ }
+ if(v->panscanflag) {
+ //...
+ }
+ v->rnd = get_bits1(gb);
+ if(v->interlace)
+ v->uvsamp = get_bits1(gb);
+ if(v->finterpflag) v->interpfrm = get_bits(gb, 1);
+ if(v->s.pict_type == B_TYPE) {
+ v->bfraction = get_vlc2(gb, vc1_bfraction_vlc.table, VC1_BFRACTION_VLC_BITS, 1);
+ v->bfraction = vc1_bfraction_lut[v->bfraction];
+ if(v->bfraction == 0) {
+ v->s.pict_type = BI_TYPE; /* XXX: should not happen here */
+ }
+ }
+ pqindex = get_bits(gb, 5);
+ v->pqindex = pqindex;
+ if (v->quantizer_mode == QUANT_FRAME_IMPLICIT)
+ v->pq = pquant_table[0][pqindex];
+ else
+ v->pq = 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_bits(gb, 1);
+ else v->halfpq = 0;
+ if (v->quantizer_mode == QUANT_FRAME_EXPLICIT)
+ v->pquantizer = get_bits(gb, 1);
+
+ switch(v->s.pict_type) {
+ case I_TYPE:
+ case BI_TYPE:
+ 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 P_TYPE:
+ if(v->postprocflag)
+ v->postproc = get_bits1(gb);
+ if (v->extended_mv) v->mvrange = get_prefix(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;
+
+ lowquant = (v->pq > 12) ? 0 : 1;
+ v->mv_mode = mv_pmode_table[lowquant][get_prefix(gb, 1, 4)];
+ if (v->mv_mode == MV_PMODE_INTENSITY_COMP)
+ {
+ int scale, shift, i;
+ v->mv_mode2 = mv_pmode_table2[lowquant][get_prefix(gb, 1, 3)];
+ v->lumscale = get_bits(gb, 6);
+ v->lumshift = get_bits(gb, 6);
+ /* 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] = clip_uint8((scale * i + shift + 32) >> 6);
+ v->lutuv[i] = clip_uint8((scale * (i - 128) + 128*64 + 32) >> 6);
+ }
+ }
+ 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 vc1_ tables
+ v->cbpcy_vlc = &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_bits(gb, 1);
+ if (v->ttmbf)
+ {
+ v->ttfrm = ttfrm_to_tt[get_bits(gb, 2)];
+ }
+ } else {
+ v->ttmbf = 1;
+ v->ttfrm = TT_8X8;
+ }
+ break;
+ case B_TYPE:
+ if(v->postprocflag)
+ v->postproc = get_bits1(gb);
+ if (v->extended_mv) v->mvrange = get_prefix(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;
+
+ lowquant = (v->pq > 12) ? 0 : 1;
+ v->mv_mode = get_bits1(gb) ? MV_PMODE_1MV : MV_PMODE_1MV_HPEL_BILIN;
+ 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 = &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_bits(gb, 1);
+ if (v->ttmbf)
+ {
+ v->ttfrm = ttfrm_to_tt[get_bits(gb, 2)];
+ }
+ } else {
+ v->ttmbf = 1;
+ v->ttfrm = TT_8X8;
+ }
+ break;
+ }
+
+ /* AC Syntax */
+ v->c_ac_table_index = decode012(gb);
+ if (v->s.pict_type == I_TYPE || v->s.pict_type == BI_TYPE)
+ {
+ v->y_ac_table_index = decode012(gb);
+ }
+ /* DC Syntax */
+ v->s.dc_table_index = get_bits(gb, 1);
+ if (v->s.pict_type == I_TYPE && 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 == BI_TYPE) {
+ v->s.pict_type = B_TYPE;
+ v->bi_type = 1;
+ }
+ return 0;
+}
+
+/***********************************************************************/
+/**
+ * @defgroup block 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_bits(gb, 1)) ? 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; \
+ }
+
+/**
+ * @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, 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; \
+ }
+
+/** Predict and set motion vector
+ */
+static inline void vc1_pred_mv(MpegEncContext *s, int n, int dmv_x, int dmv_y, int mv1, int r_x, int r_y, uint8_t* is_intra)
+{
+ int xy, wrap, off = 0;
+ int16_t *A, *B, *C;
+ int px, py;
+ int sum;
+
+ /* 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][0] = 0;
+ s->mv[0][n][1] = s->current_picture.motion_val[0][xy][1] = 0;
+ if(mv1) { /* 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;
+ }
+ return;
+ }
+
+ C = s->current_picture.motion_val[0][xy - 1];
+ A = s->current_picture.motion_val[0][xy - wrap];
+ if(mv1)
+ 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[0][xy - wrap + off];
+
+ if(!s->first_slice_line || (n==2 || n==3)) { // 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 || (n==1 || n==3)) { // 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;
+ 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;
+ }
+ /* Calculate hybrid prediction as specified in 8.3.5.3.5 */
+ if((!s->first_slice_line || (n==2 || n==3)) && (s->mb_x || (n==1 || n==3))) {
+ 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 - 1])
+ 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][n][0] = s->current_picture.motion_val[0][xy][0] = ((px + dmv_x + r_x) & ((r_x << 1) - 1)) - r_x;
+ s->mv[0][n][1] = s->current_picture.motion_val[0][xy][1] = ((py + dmv_y + r_y) & ((r_y << 1) - 1)) - r_y;
+ if(mv1) { /* duplicate motion data for 1-MV block */
+ s->current_picture.motion_val[0][xy + 1][0] = s->current_picture.motion_val[0][xy][0];
+ s->current_picture.motion_val[0][xy + 1][1] = s->current_picture.motion_val[0][xy][1];
+ s->current_picture.motion_val[0][xy + wrap][0] = s->current_picture.motion_val[0][xy][0];
+ s->current_picture.motion_val[0][xy + wrap][1] = s->current_picture.motion_val[0][xy][1];
+ s->current_picture.motion_val[0][xy + wrap + 1][0] = s->current_picture.motion_val[0][xy][0];
+ s->current_picture.motion_val[0][xy + wrap + 1][1] = s->current_picture.motion_val[0][xy][1];
+ }
+}
+
+/** Motion compensation for direct or interpolated blocks in B-frames
+ */
+static void vc1_interp_mc(VC1Context *v)
+{
+ MpegEncContext *s = &v->s;
+ DSPContext *dsp = &v->s.dsp;
+ uint8_t *srcY, *srcU, *srcV;
+ int dxy, uvdxy, mx, my, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y;
+
+ if(!v->s.next_picture.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;
+ srcY = s->next_picture.data[0];
+ srcU = s->next_picture.data[1];
+ srcV = s->next_picture.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);
+
+ src_x = clip( src_x, -16, s->mb_width * 16);
+ src_y = clip( src_y, -16, s->mb_height * 16);
+ uvsrc_x = clip(uvsrc_x, -8, s->mb_width * 8);
+ uvsrc_y = clip(uvsrc_y, -8, s->mb_height * 8);
+
+ srcY += src_y * s->linesize + src_x;
+ srcU += uvsrc_y * s->uvlinesize + uvsrc_x;
+ srcV += uvsrc_y * s->uvlinesize + uvsrc_x;
+
+ /* 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
+ || (unsigned)src_x > s->h_edge_pos - (mx&3) - 16
+ || (unsigned)src_y > s->v_edge_pos - (my&3) - 16){
+ uint8_t *uvbuf= s->edge_emu_buffer + 19 * s->linesize;
+
+ srcY -= s->mspel * (1 + s->linesize);
+ ff_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, s->v_edge_pos);
+ srcY = s->edge_emu_buffer;
+ ff_emulated_edge_mc(uvbuf , srcU, s->uvlinesize, 8+1, 8+1,
+ uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, s->v_edge_pos >> 1);
+ ff_emulated_edge_mc(uvbuf + 16, srcV, s->uvlinesize, 8+1, 8+1,
+ uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, s->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);
+ }
+
+ if(v->fastuvmc) {
+ uvmx = uvmx + ((uvmx<0)?-(uvmx&1):(uvmx&1));
+ uvmy = uvmy + ((uvmy<0)?-(uvmy&1):(uvmy&1));
+ }
+
+ mx >>= 1;
+ my >>= 1;
+ dxy = ((my & 1) << 1) | (mx & 1);
+
+ dsp->avg_pixels_tab[0][dxy](s->dest[0], srcY, s->linesize, 16);
+
+ if(s->flags & CODEC_FLAG_GRAY) return;
+ /* Chroma MC always uses qpel blilinear */
+ uvdxy = ((uvmy & 3) << 2) | (uvmx & 3);
+ uvmx = (uvmx&3)<<1;
+ uvmy = (uvmy&3)<<1;
+ dsp->avg_h264_chroma_pixels_tab[0](s->dest[1], srcU, s->uvlinesize, 8, uvmx, uvmy);
+ dsp->avg_h264_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy);
+}
+
+static 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][0] =
+ s->current_picture.motion_val[0][xy][1] =
+ s->current_picture.motion_val[1][xy][0] =
+ s->current_picture.motion_val[1][xy][1] = 0;
+ return;
+ }
+ 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);
+ if(direct) {
+ 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];
+ 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->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->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];
+}
+
+/** Get predicted DC value for I-frames only
+ * prediction dir: left=0, top=1
+ * @param s MpegEncContext
+ * @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[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_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, scale;
+ int16_t *dc_val;
+ int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
+ int q1, q2 = 0;
+
+ /* 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];
+ /* scale predictors if needed */
+ q1 = s->current_picture.qscale_table[mb_pos];
+ 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] * vc1_dqscale[s->y_dc_scale_table[q1] - 1] + 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] * vc1_dqscale[s->y_dc_scale_table[q1] - 1] + 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] * vc1_dqscale[s->y_dc_scale_table[q1] - 1] + 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;
+}
+
+
+/**
+ * @defgroup std_mb 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
+ * @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, vc1_ac_coeff_table[codingset].table, AC_VLC_BITS, 3);
+ if (index != 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];
+ if(get_bits(gb, 1))
+ level = -level;
+ } else {
+ escape = decode210(gb);
+ if (escape != 2) {
+ index = get_vlc2(gb, 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_bits(gb, 1))
+ level = -level;
+ } else {
+ int sign;
+ lst = get_bits(gb, 1);
+ 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_prefix(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_bits(gb, 1);
+ 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 coded are AC coeffs present or not
+ * @param codingset set of VLC to decode data
+ */
+static int vc1_decode_i_block(VC1Context *v, DCTELEM 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 run_diff, 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_bits(gb, 1) - 1;
+ }
+ if (get_bits(gb, 1))
+ 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 ? */
+ run_diff = 0;
+ i = 0;
+ if (!coded) {
+ goto not_coded;
+ }
+
+ //AC Decoding
+ i = 1;
+
+ {
+ int last = 0, skip, value;
+ const int8_t *zz_table;
+ int scale;
+ int k;
+
+ scale = v->pq * 2 + v->halfpq;
+
+ if(v->s.ac_pred) {
+ if(!dc_pred_dir)
+ zz_table = vc1_horizontal_zz;
+ else
+ zz_table = vc1_vertical_zz;
+ } else
+ zz_table = vc1_normal_zz;
+
+ 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 << 3] += ac_val[k];
+ } else { //top
+ for(k = 1; k < 8; k++)
+ block[k] += ac_val[k + 8];
+ }
+ }
+ /* save AC coeffs for further prediction */
+ for(k = 1; k < 8; k++) {
+ ac_val2[k] = block[k << 3];
+ ac_val2[k + 8] = block[k];
+ }
+
+ /* 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;
+
+ 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 << 3] = ac_val[k] * scale;
+ if(!v->pquantizer && block[k << 3])
+ block[k << 3] += (block[k << 3] < 0) ? -v->pq : v->pq;
+ }
+ } else { //top
+ for(k = 1; k < 8; k++) {
+ block[k] = ac_val[k + 8] * scale;
+ if(!v->pquantizer && block[k])
+ block[k] += (block[k] < 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 coded are AC coeffs present or not
+ * @param codingset set of VLC to decode data
+ */
+static int vc1_decode_i_block_adv(VC1Context *v, DCTELEM 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 run_diff, i;
+ int16_t *dc_val;
+ 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_bits(gb, 1) - 1;
+ }
+ if (get_bits(gb, 1))
+ 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;
+ }
+ /* Skip ? */
+ run_diff = 0;
+ i = 0;
+
+ //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) q2 = s->current_picture.qscale_table[mb_pos - 1];
+ if(!dc_pred_dir && a_avail) q2 = s->current_picture.qscale_table[mb_pos - s->mb_stride];
+ if(n && n<4) q2 = q1;
+
+ if(coded) {
+ int last = 0, skip, value;
+ const int8_t *zz_table;
+ int k;
+
+ if(v->s.ac_pred) {
+ if(!dc_pred_dir)
+ zz_table = vc1_horizontal_zz;
+ else
+ zz_table = vc1_vertical_zz;
+ } else
+ zz_table = vc1_normal_zz;
+
+ 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(dc_pred_dir) { //left
+ for(k = 1; k < 8; k++)
+ block[k << 3] += (ac_val[k] * q2 * vc1_dqscale[q1 - 1] + 0x20000) >> 18;
+ } else { //top
+ for(k = 1; k < 8; k++)
+ block[k] += (ac_val[k + 8] * q2 * vc1_dqscale[q1 - 1] + 0x20000) >> 18;
+ }
+ } else {
+ if(dc_pred_dir) { //left
+ for(k = 1; k < 8; k++)
+ block[k << 3] += ac_val[k];
+ } else { //top
+ for(k = 1; k < 8; k++)
+ block[k] += ac_val[k + 8];
+ }
+ }
+ }
+ /* save AC coeffs for further prediction */
+ for(k = 1; k < 8; k++) {
+ ac_val2[k] = block[k << 3];
+ ac_val2[k + 8] = block[k];
+ }
+
+ /* 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;
+ for(k = 1; k < 8; k++)
+ ac_val2[k] = (ac_val2[k] * q2 * 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;
+ for(k = 1; k < 8; k++)
+ ac_val2[k + 8] = (ac_val2[k + 8] * q2 * 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 << 3] = ac_val2[k] * scale;
+ if(!v->pquantizer && block[k << 3])
+ block[k << 3] += (block[k << 3] < 0) ? -mquant : mquant;
+ }
+ } else { //top
+ for(k = 1; k < 8; k++) {
+ block[k] = ac_val2[k + 8] * scale;
+ if(!v->pquantizer && block[k])
+ block[k] += (block[k] < 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 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, DCTELEM 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 run_diff, i;
+ int16_t *dc_val;
+ 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;
+
+ /* 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_bits(gb, 1) - 1;
+ }
+ if (get_bits(gb, 1))
+ 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;
+ }
+ /* Skip ? */
+ run_diff = 0;
+ i = 0;
+
+ //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) q2 = s->current_picture.qscale_table[mb_pos - 1];
+ if(!dc_pred_dir && a_avail) q2 = s->current_picture.qscale_table[mb_pos - s->mb_stride];
+ if(n && n<4) q2 = q1;
+
+ if(coded) {
+ int last = 0, skip, value;
+ const int8_t *zz_table;
+ int k;
+
+ zz_table = vc1_simple_progressive_8x8_zz;
+
+ 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(dc_pred_dir) { //left
+ for(k = 1; k < 8; k++)
+ block[k << 3] += (ac_val[k] * q2 * vc1_dqscale[q1 - 1] + 0x20000) >> 18;
+ } else { //top
+ for(k = 1; k < 8; k++)
+ block[k] += (ac_val[k + 8] * q2 * vc1_dqscale[q1 - 1] + 0x20000) >> 18;
+ }
+ } else {
+ if(dc_pred_dir) { //left
+ for(k = 1; k < 8; k++)
+ block[k << 3] += ac_val[k];
+ } else { //top
+ for(k = 1; k < 8; k++)
+ block[k] += ac_val[k + 8];
+ }
+ }
+ }
+ /* save AC coeffs for further prediction */
+ for(k = 1; k < 8; k++) {
+ ac_val2[k] = block[k << 3];
+ ac_val2[k + 8] = block[k];
+ }
+
+ /* 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;
+ for(k = 1; k < 8; k++)
+ ac_val2[k] = (ac_val2[k] * q2 * 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;
+ for(k = 1; k < 8; k++)
+ ac_val2[k + 8] = (ac_val2[k + 8] * q2 * 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 << 3] = ac_val2[k] * scale;
+ if(!v->pquantizer && block[k << 3])
+ block[k << 3] += (block[k << 3] < 0) ? -mquant : mquant;
+ }
+ } else { //top
+ for(k = 1; k < 8; k++) {
+ block[k] = ac_val2[k + 8] * scale;
+ if(!v->pquantizer && block[k])
+ block[k] += (block[k] < 0) ? -mquant : mquant;
+ }
+ }
+ i = 63;
+ }
+ }
+ s->block_last_index[n] = i;
+
+ return 0;
+}
+
+/** Decode P block
+ */
+static int vc1_decode_p_block(VC1Context *v, DCTELEM block[64], int n, int mquant, int ttmb, int first_block)
+{
+ 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;
+
+ if(ttmb == -1) {
+ ttblk = ttblk_to_tt[v->tt_index][get_vlc2(gb, vc1_ttblk_vlc[v->tt_index].table, VC1_TTBLK_VLC_BITS, 1)];
+ }
+ if(ttblk == TT_4X4) {
+ subblkpat = ~(get_vlc2(gb, 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))) {
+ 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->halfpq;
+
+ // 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:
+ i = 0;
+ last = 0;
+ while (!last) {
+ vc1_decode_ac_coeff(v, &last, &skip, &value, v->codingset2);
+ i += skip;
+ if(i > 63)
+ break;
+ idx = vc1_simple_progressive_8x8_zz[i++];
+ block[idx] = value * scale;
+ if(!v->pquantizer)
+ block[idx] += (block[idx] < 0) ? -mquant : mquant;
+ }
+ s->dsp.vc1_inv_trans_8x8(block);
+ break;
+ case TT_4X4:
+ 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;
+ idx = vc1_simple_progressive_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))))
+ s->dsp.vc1_inv_trans_4x4(block, j);
+ }
+ break;
+ case TT_8X4:
+ 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->profile < PROFILE_ADVANCED)
+ idx = vc1_simple_progressive_8x4_zz[i++];
+ else
+ idx = vc1_adv_progressive_8x4_zz[i++];
+ block[idx + off] = value * scale;
+ if(!v->pquantizer)
+ block[idx + off] += (block[idx + off] < 0) ? -mquant : mquant;
+ }
+ if(!(subblkpat & (1 << (1 - j))))
+ s->dsp.vc1_inv_trans_8x4(block, j);
+ }
+ break;
+ case TT_4X8:
+ 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->profile < PROFILE_ADVANCED)
+ idx = vc1_simple_progressive_4x8_zz[i++];
+ else
+ idx = vc1_adv_progressive_4x8_zz[i++];
+ block[idx + off] = value * scale;
+ if(!v->pquantizer)
+ block[idx + off] += (block[idx + off] < 0) ? -mquant : mquant;
+ }
+ if(!(subblkpat & (1 << (1 - j))))
+ s->dsp.vc1_inv_trans_4x8(block, j);
+ }
+ break;
+ }
+ return 0;
+}
+
+
+/** Decode one P-frame MB (in Simple/Main profile)
+ */
+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 status;
+
+ static const int size_table[6] = { 0, 2, 3, 4, 5, 8 },
+ offset_table[6] = { 0, 1, 3, 7, 15, 31 };
+ int mb_has_coeffs = 1; /* last_flag */
+ int dmv_x, dmv_y; /* Differential MV components */
+ int index, index1; /* LUT indices */
+ int val, sign; /* temp values */
+ int first_block = 1;
+ int dst_idx, off;
+ int skipped, fourmv;
+
+ mquant = v->pq; /* Loosy 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];
+
+ s->dsp.clear_blocks(s->block[0]);
+
+ 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(s, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0]);
+
+ /* FIXME Set DC val for inter block ? */
+ if (s->mb_intra && !mb_has_coeffs)
+ {
+ GET_MQUANT();
+ s->ac_pred = get_bits(gb, 1);
+ cbp = 0;
+ }
+ else if (mb_has_coeffs)
+ {
+ if (s->mb_intra) s->ac_pred = get_bits(gb, 1);
+ 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, 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;
+ s->dsp.vc1_inv_trans_8x8(s->block[i]);
+ if(v->rangeredfrm) for(j = 0; j < 64; j++) s->block[i][j] <<= 1;
+ for(j = 0; j < 64; j++) s->block[i][j] += 128;
+ s->dsp.put_pixels_clamped(s->block[i], s->dest[dst_idx] + off, s->linesize >> ((i & 4) >> 2));
+ if(v->pq >= 9 && v->overlap) {
+ if(v->c_avail)
+ s->dsp.vc1_h_overlap(s->dest[dst_idx] + off, s->linesize >> ((i & 4) >> 2));
+ if(v->a_avail)
+ s->dsp.vc1_v_overlap(s->dest[dst_idx] + off, s->linesize >> ((i & 4) >> 2));
+ }
+ } else if(val) {
+ vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, first_block);
+ if(!v->ttmbf && ttmb < 8) ttmb = -1;
+ first_block = 0;
+ if((i<4) || !(s->flags & CODEC_FLAG_GRAY))
+ s->dsp.add_pixels_clamped(s->block[i], s->dest[dst_idx] + off, (i&4)?s->uvlinesize:s->linesize);
+ }
+ }
+ }
+ 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(s, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0]);
+ vc1_mc_1mv(v, 0);
+ return 0;
+ }
+ } //1MV mode
+ 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(s, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, v->mb_type[0]);
+ if(!s->mb_intra) vc1_mc_4mv_luma(v, i);
+ 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);
+ 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
+ if(!intra_count && !coded_inter) return 0;
+ dst_idx = 0;
+ 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_bits(gb, 1);
+ else s->ac_pred = 0;
+ }
+ if (!v->ttmbf && coded_inter)
+ ttmb = get_vlc2(gb, 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;
+ s->dsp.vc1_inv_trans_8x8(s->block[i]);
+ if(v->rangeredfrm) for(j = 0; j < 64; j++) s->block[i][j] <<= 1;
+ for(j = 0; j < 64; j++) s->block[i][j] += 128;
+ s->dsp.put_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)
+ s->dsp.vc1_h_overlap(s->dest[dst_idx] + off, s->linesize >> ((i & 4) >> 2));
+ if(v->a_avail)
+ s->dsp.vc1_v_overlap(s->dest[dst_idx] + off, s->linesize >> ((i & 4) >> 2));
+ }
+ } else if(is_coded[i]) {
+ status = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, first_block);
+ if(!v->ttmbf && ttmb < 8) ttmb = -1;
+ first_block = 0;
+ if((i<4) || !(s->flags & CODEC_FLAG_GRAY))
+ s->dsp.add_pixels_clamped(s->block[i], s->dest[dst_idx] + off, (i&4)?s->uvlinesize:s->linesize);
+ }
+ }
+ return status;
+ }
+ 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(s, i, 0, 0, 0, v->range_x, v->range_y, v->mb_type[0]);
+ vc1_mc_4mv_luma(v, i);
+ }
+ vc1_mc_4mv_chroma(v);
+ s->current_picture.qscale_table[mb_pos] = 0;
+ return 0;
+ }
+ }
+
+ /* Should never happen */
+ return -1;
+}
+
+/** 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 */
+
+ static const int size_table[6] = { 0, 2, 3, 4, 5, 8 },
+ offset_table[6] = { 0, 1, 3, 7, 15, 31 };
+ int mb_has_coeffs = 0; /* last_flag */
+ int index, index1; /* LUT indices */
+ 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; /* Loosy 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];
+
+ s->dsp.clear_blocks(s->block[0]);
+ 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;
+ mb_has_coeffs = 0;
+ s->current_picture.qscale_table[mb_pos] = mquant;
+ if(!v->ttmbf)
+ ttmb = get_vlc2(gb, 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, 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;
+ s->dsp.vc1_inv_trans_8x8(s->block[i]);
+ if(v->rangeredfrm) for(j = 0; j < 64; j++) s->block[i][j] <<= 1;
+ for(j = 0; j < 64; j++) s->block[i][j] += 128;
+ s->dsp.put_pixels_clamped(s->block[i], s->dest[dst_idx] + off, s->linesize >> ((i & 4) >> 2));
+ } else if(val) {
+ vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, first_block);
+ if(!v->ttmbf && ttmb < 8) ttmb = -1;
+ first_block = 0;
+ if((i<4) || !(s->flags & CODEC_FLAG_GRAY))
+ s->dsp.add_pixels_clamped(s->block[i], s->dest[dst_idx] + off, (i&4)?s->uvlinesize:s->linesize);
+ }
+ }
+}
+
+/** 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;
+ ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END));
+ for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) {
+ for(s->mb_x = 0; s->mb_x < s->mb_width; s->mb_x++) {
+ ff_init_block_index(s);
+ ff_update_block_index(s);
+ 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_bits(&v->s.gb, 1);
+
+ 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);
+
+ s->dsp.vc1_inv_trans_8x8(s->block[k]);
+ if(v->pq >= 9 && v->overlap) {
+ for(j = 0; j < 64; j++) s->block[k][j] += 128;
+ }
+ }
+
+ vc1_put_block(v, s->block);
+ if(v->pq >= 9 && v->overlap) {
+ if(s->mb_x) {
+ s->dsp.vc1_h_overlap(s->dest[0], s->linesize);
+ s->dsp.vc1_h_overlap(s->dest[0] + 8 * s->linesize, s->linesize);
+ if(!(s->flags & CODEC_FLAG_GRAY)) {
+ s->dsp.vc1_h_overlap(s->dest[1], s->uvlinesize);
+ s->dsp.vc1_h_overlap(s->dest[2], s->uvlinesize);
+ }
+ }
+ s->dsp.vc1_h_overlap(s->dest[0] + 8, s->linesize);
+ s->dsp.vc1_h_overlap(s->dest[0] + 8 * s->linesize + 8, s->linesize);
+ if(!s->first_slice_line) {
+ s->dsp.vc1_v_overlap(s->dest[0], s->linesize);
+ s->dsp.vc1_v_overlap(s->dest[0] + 8, s->linesize);
+ if(!(s->flags & CODEC_FLAG_GRAY)) {
+ s->dsp.vc1_v_overlap(s->dest[1], s->uvlinesize);
+ s->dsp.vc1_v_overlap(s->dest[2], s->uvlinesize);
+ }
+ }
+ s->dsp.vc1_v_overlap(s->dest[0] + 8 * s->linesize, s->linesize);
+ s->dsp.vc1_v_overlap(s->dest[0] + 8 * s->linesize + 8, s->linesize);
+ }
+
+ if(get_bits_count(&s->gb) > v->bits) {
+ av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i\n", get_bits_count(&s->gb), v->bits);
+ return;
+ }
+ }
+ ff_draw_horiz_band(s, s->mb_y * 16, 16);
+ s->first_slice_line = 0;
+ }
+}
+
+/** Decode blocks of I-frame for advanced profile
+ */
+static void vc1_decode_i_blocks_adv(VC1Context *v)
+{
+ int k, j;
+ MpegEncContext *s = &v->s;
+ int cbp, val;
+ uint8_t *coded_val;
+ int mb_pos;
+ int mquant = v->pq;
+ int mqdiff;
+ int overlap;
+ 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;
+ ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END));
+ for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) {
+ for(s->mb_x = 0; s->mb_x < s->mb_width; s->mb_x++) {
+ ff_init_block_index(s);
+ ff_update_block_index(s);
+ s->dsp.clear_blocks(s->block[0]);
+ mb_pos = s->mb_x + s->mb_y * s->mb_stride;
+ s->current_picture.mb_type[mb_pos] = MB_TYPE_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;
+
+ // do actual MB decoding and displaying
+ 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_bits(&v->s.gb, 1);
+ else
+ v->s.ac_pred = v->acpred_plane[mb_pos];
+
+ if(v->condover == CONDOVER_SELECT) {
+ if(v->overflg_is_raw)
+ overlap = get_bits(&v->s.gb, 1);
+ else
+ overlap = v->over_flags_plane[mb_pos];
+ } else
+ overlap = (v->condover == CONDOVER_ALL);
+
+ 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, s->block[k], k, val, (k<4)? v->codingset : v->codingset2, mquant);
+
+ s->dsp.vc1_inv_trans_8x8(s->block[k]);
+ for(j = 0; j < 64; j++) s->block[k][j] += 128;
+ }
+
+ vc1_put_block(v, s->block);
+ if(overlap) {
+ if(s->mb_x) {
+ s->dsp.vc1_h_overlap(s->dest[0], s->linesize);
+ s->dsp.vc1_h_overlap(s->dest[0] + 8 * s->linesize, s->linesize);
+ if(!(s->flags & CODEC_FLAG_GRAY)) {
+ s->dsp.vc1_h_overlap(s->dest[1], s->uvlinesize);
+ s->dsp.vc1_h_overlap(s->dest[2], s->uvlinesize);
+ }
+ }
+ s->dsp.vc1_h_overlap(s->dest[0] + 8, s->linesize);
+ s->dsp.vc1_h_overlap(s->dest[0] + 8 * s->linesize + 8, s->linesize);
+ if(!s->first_slice_line) {
+ s->dsp.vc1_v_overlap(s->dest[0], s->linesize);
+ s->dsp.vc1_v_overlap(s->dest[0] + 8, s->linesize);
+ if(!(s->flags & CODEC_FLAG_GRAY)) {
+ s->dsp.vc1_v_overlap(s->dest[1], s->uvlinesize);
+ s->dsp.vc1_v_overlap(s->dest[2], s->uvlinesize);
+ }
+ }
+ s->dsp.vc1_v_overlap(s->dest[0] + 8 * s->linesize, s->linesize);
+ s->dsp.vc1_v_overlap(s->dest[0] + 8 * s->linesize + 8, s->linesize);
+ }
+
+ if(get_bits_count(&s->gb) > v->bits) {
+ av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i\n", get_bits_count(&s->gb), v->bits);
+ return;
+ }
+ }
+ ff_draw_horiz_band(s, s->mb_y * 16, 16);
+ s->first_slice_line = 0;
+ }
+}
+
+static void vc1_decode_p_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;
+ }
+
+ ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END));
+ s->first_slice_line = 1;
+ for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) {
+ for(s->mb_x = 0; s->mb_x < s->mb_width; s->mb_x++) {
+ ff_init_block_index(s);
+ ff_update_block_index(s);
+ s->dsp.clear_blocks(s->block[0]);
+
+ vc1_decode_p_mb(v);
+ if(get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) {
+ 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;
+ }
+ }
+ ff_draw_horiz_band(s, s->mb_y * 16, 16);
+ s->first_slice_line = 0;
+ }
+}
+
+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;
+ }
+
+ ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END));
+ s->first_slice_line = 1;
+ for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) {
+ for(s->mb_x = 0; s->mb_x < s->mb_width; s->mb_x++) {
+ ff_init_block_index(s);
+ ff_update_block_index(s);
+ s->dsp.clear_blocks(s->block[0]);
+
+ vc1_decode_b_mb(v);
+ if(get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) {
+ 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;
+ }
+ }
+ ff_draw_horiz_band(s, s->mb_y * 16, 16);
+ s->first_slice_line = 0;
+ }
+}
+
+static void vc1_decode_skip_blocks(VC1Context *v)
+{
+ MpegEncContext *s = &v->s;
+
+ ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END));
+ s->first_slice_line = 1;
+ for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) {
+ s->mb_x = 0;
+ ff_init_block_index(s);
+ ff_update_block_index(s);
+ memcpy(s->dest[0], s->last_picture.data[0] + s->mb_y * 16 * s->linesize, s->linesize * 16);
+ memcpy(s->dest[1], s->last_picture.data[1] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8);
+ memcpy(s->dest[2], s->last_picture.data[2] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8);
+ ff_draw_horiz_band(s, s->mb_y * 16, 16);
+ s->first_slice_line = 0;
+ }
+ s->pict_type = P_TYPE;
+}
+
+static void vc1_decode_blocks(VC1Context *v)
+{
+
+ v->s.esc3_level_length = 0;
+
+ switch(v->s.pict_type) {
+ case I_TYPE:
+ if(v->profile == PROFILE_ADVANCED)
+ vc1_decode_i_blocks_adv(v);
+ else
+ vc1_decode_i_blocks(v);
+ break;
+ case P_TYPE:
+ if(v->p_frame_skipped)
+ vc1_decode_skip_blocks(v);
+ else
+ vc1_decode_p_blocks(v);
+ break;
+ case B_TYPE:
+ if(v->bi_type)
+ vc1_decode_i_blocks(v);
+ else
+ vc1_decode_b_blocks(v);
+ break;
+ }
+}
+
+
+/** Initialize a VC1/WMV3 decoder
+ * @todo TODO: Handle VC-1 IDUs (Transport level?)
+ * @todo TODO: Decypher remaining bits in extra_data
+ */
+static int vc1_decode_init(AVCodecContext *avctx)
+{
+ VC1Context *v = avctx->priv_data;
+ MpegEncContext *s = &v->s;
+ GetBitContext gb;
+
+ if (!avctx->extradata_size || !avctx->extradata) return -1;
+ if (!(avctx->flags & CODEC_FLAG_GRAY))
+ avctx->pix_fmt = PIX_FMT_YUV420P;
+ else
+ avctx->pix_fmt = PIX_FMT_GRAY8;
+ v->s.avctx = avctx;
+ avctx->flags |= CODEC_FLAG_EMU_EDGE;
+ v->s.flags |= CODEC_FLAG_EMU_EDGE;
+
+ if(ff_h263_decode_init(avctx) < 0)
+ return -1;
+ if (vc1_init_common(v) < 0) return -1;
+
+ avctx->coded_width = avctx->width;
+ avctx->coded_height = avctx->height;
+ if (avctx->codec_id == CODEC_ID_WMV3)
+ {
+ 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 (decode_sequence_header(avctx, &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
+ int edata_size = avctx->extradata_size;
+ uint8_t *edata = avctx->extradata;
+
+ if(avctx->extradata_size < 16) {
+ av_log(avctx, AV_LOG_ERROR, "Extradata size too small: %i\n", edata_size);
+ return -1;
+ }
+ while(edata_size > 8) {
+ // test if we've found header
+ if(BE_32(edata) == 0x0000010F) {
+ edata += 4;
+ edata_size -= 4;
+ break;
+ }
+ edata_size--;
+ edata++;
+ }
+
+ init_get_bits(&gb, edata, edata_size*8);
+
+ if (decode_sequence_header(avctx, &gb) < 0)
+ return -1;
+
+ while(edata_size > 8) {
+ // test if we've found entry point
+ if(BE_32(edata) == 0x0000010E) {
+ edata += 4;
+ edata_size -= 4;
+ break;
+ }
+ edata_size--;
+ edata++;
+ }
+
+ init_get_bits(&gb, edata, edata_size*8);
+
+ if (decode_entry_point(avctx, &gb) < 0)
+ return -1;
+ }
+ avctx->has_b_frames= !!(avctx->max_b_frames);
+ s->low_delay = !avctx->has_b_frames;
+
+ s->mb_width = (avctx->coded_width+15)>>4;
+ s->mb_height = (avctx->coded_height+15)>>4;
+
+ /* 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->acpred_plane = av_malloc(s->mb_stride * s->mb_height);
+ v->over_flags_plane = av_malloc(s->mb_stride * s->mb_height);
+
+ /* 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);
+
+ /* 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;
+ }
+
+ 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 *data_size,
+ uint8_t *buf, int buf_size)
+{
+ VC1Context *v = avctx->priv_data;
+ MpegEncContext *s = &v->s;
+ AVFrame *pict = data;
+ uint8_t *buf2 = NULL;
+
+ /* no supplementary picture */
+ if (buf_size == 0) {
+ /* special case for last picture */
+ if (s->low_delay==0 && s->next_picture_ptr) {
+ *pict= *(AVFrame*)s->next_picture_ptr;
+ s->next_picture_ptr= NULL;
+
+ *data_size = sizeof(AVFrame);
+ }
+
+ return 0;
+ }
+
+ //we need to set current_picture_ptr before reading the header, otherwise we cant store anyting im there
+ if(s->current_picture_ptr==NULL || s->current_picture_ptr->data[0]){
+ int i= ff_find_unused_picture(s, 0);
+ s->current_picture_ptr= &s->picture[i];
+ }
+
+ //for advanced profile we need to unescape buffer
+ if (avctx->codec_id == CODEC_ID_VC1) {
+ int i, buf_size2;
+ buf2 = av_malloc(buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ buf_size2 = 0;
+ for(i = 0; i < buf_size; i++) {
+ if(buf[i] == 3 && i >= 2 && !buf[i-1] && !buf[i-2] && i < buf_size-1 && buf[i+1] < 4) {
+ buf2[buf_size2++] = buf[i+1];
+ i++;
+ } else
+ buf2[buf_size2++] = buf[i];
+ }
+ init_get_bits(&s->gb, buf2, buf_size2*8);
+ } else
+ init_get_bits(&s->gb, buf, buf_size*8);
+ // do parse frame header
+ if(v->profile < PROFILE_ADVANCED) {
+ if(vc1_parse_frame_header(v, &s->gb) == -1) {
+ av_free(buf2);
+ return -1;
+ }
+ } else {
+ if(vc1_parse_frame_header_adv(v, &s->gb) == -1) {
+ av_free(buf2);
+ return -1;
+ }
+ }
+
+ if(s->pict_type != I_TYPE && !v->res_rtm_flag){
+ av_free(buf2);
+ return -1;
+ }
+
+ // for hurry_up==5
+ s->current_picture.pict_type= s->pict_type;
+ s->current_picture.key_frame= s->pict_type == I_TYPE;
+
+ /* skip B-frames if we don't have reference frames */
+ if(s->last_picture_ptr==NULL && (s->pict_type==B_TYPE || s->dropable)){
+ av_free(buf2);
+ return -1;//buf_size;
+ }
+ /* skip b frames if we are in a hurry */
+ if(avctx->hurry_up && s->pict_type==B_TYPE) return -1;//buf_size;
+ if( (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type==B_TYPE)
+ || (avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type!=I_TYPE)
+ || avctx->skip_frame >= AVDISCARD_ALL) {
+ av_free(buf2);
+ return buf_size;
+ }
+ /* skip everything if we are in a hurry>=5 */
+ if(avctx->hurry_up>=5) {
+ av_free(buf2);
+ return -1;//buf_size;
+ }
+
+ if(s->next_p_frame_damaged){
+ if(s->pict_type==B_TYPE)
+ return buf_size;
+ else
+ s->next_p_frame_damaged=0;
+ }
+
+ if(MPV_frame_start(s, avctx) < 0) {
+ av_free(buf2);
+ return -1;
+ }
+
+ ff_er_frame_start(s);
+
+ v->bits = buf_size * 8;
+ vc1_decode_blocks(v);
+//av_log(s->avctx, AV_LOG_INFO, "Consumed %i/%i bits\n", get_bits_count(&s->gb), buf_size*8);
+// if(get_bits_count(&s->gb) > buf_size * 8)
+// return -1;
+ ff_er_frame_end(s);
+
+ MPV_frame_end(s);
+
+assert(s->current_picture.pict_type == s->current_picture_ptr->pict_type);
+assert(s->current_picture.pict_type == s->pict_type);
+ if (s->pict_type == B_TYPE || s->low_delay) {
+ *pict= *(AVFrame*)s->current_picture_ptr;
+ } else if (s->last_picture_ptr != NULL) {
+ *pict= *(AVFrame*)s->last_picture_ptr;
+ }
+
+ if(s->last_picture_ptr || s->low_delay){
+ *data_size = sizeof(AVFrame);
+ ff_print_debug_info(s, pict);
+ }
+
+ /* Return the Picture timestamp as the frame number */
+ /* we substract 1 because it is added on utils.c */
+ avctx->frame_number = s->picture_number - 1;
+
+ av_free(buf2);
+ return buf_size;
+}
+
+
+/** Close a VC1/WMV3 decoder
+ * @warning Initial try at using MpegEncContext stuff
+ */
+static int vc1_decode_end(AVCodecContext *avctx)
+{
+ VC1Context *v = avctx->priv_data;
+
+ av_freep(&v->hrd_rate);
+ av_freep(&v->hrd_buffer);
+ MPV_common_end(&v->s);
+ av_freep(&v->mv_type_mb_plane);
+ av_freep(&v->direct_mb_plane);
+ av_freep(&v->acpred_plane);
+ av_freep(&v->over_flags_plane);
+ av_freep(&v->mb_type_base);
+ return 0;
+}
+
+
+AVCodec vc1_decoder = {
+ "vc1",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_VC1,
+ sizeof(VC1Context),
+ vc1_decode_init,
+ NULL,
+ vc1_decode_end,
+ vc1_decode_frame,
+ CODEC_CAP_DELAY,
+ NULL
+};
+
+AVCodec wmv3_decoder = {
+ "wmv3",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_WMV3,
+ sizeof(VC1Context),
+ vc1_decode_init,
+ NULL,
+ vc1_decode_end,
+ vc1_decode_frame,
+ CODEC_CAP_DELAY,
+ NULL
+};
diff --git a/contrib/ffmpeg/libavcodec/vc1acdata.h b/contrib/ffmpeg/libavcodec/vc1acdata.h
new file mode 100644
index 000000000..a6acecd78
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vc1acdata.h
@@ -0,0 +1,585 @@
+/*
+ * 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
+ */
+
+#define AC_MODES 8
+
+static const int vc1_ac_sizes[AC_MODES] = {
+ 186, 169, 133, 149, 103, 103, 163, 175
+};
+
+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}
+}
+};
+
+/* 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
+}
+};
diff --git a/contrib/ffmpeg/libavcodec/vc1data.h b/contrib/ffmpeg/libavcodec/vc1data.h
new file mode 100644
index 000000000..70e88b525
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vc1data.h
@@ -0,0 +1,652 @@
+/*
+ * 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 vc1data.h
+ * VC-1 tables.
+ */
+
+#ifndef VC1DATA_H
+#define VC1DATA_H
+
+#if 0 //original bfraction from vc9data.h, not conforming to standard
+/* Denominator used for vc1_bfraction_lut */
+#define B_FRACTION_DEN 840
+
+/* bfraction is fractional, we scale to the GCD 3*5*7*8 = 840 */
+const int16_t 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
+/* Denominator used for vc1_bfraction_lut */
+#define B_FRACTION_DEN 256
+
+/* pre-computed scales for all bfractions and base=256 */
+static const int16_t 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
+
+static const uint8_t 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
+};
+static const uint8_t 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
+static const AVRational 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... */
+static const uint8_t vc1_imode_codes[7] = {
+ 0, 2, 1, 3, 1, 2, 3
+};
+static const uint8_t vc1_imode_bits[7] = {
+ 4, 2, 3, 2, 4, 3, 3
+};
+
+/* Normal-2 imode */
+static const uint8_t vc1_norm2_codes[4] = {
+ 0, 4, 5, 3
+};
+static const uint8_t vc1_norm2_bits[4] = {
+ 1, 3, 3, 2
+};
+
+static const uint16_t 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,
+};
+
+static const uint8_t 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,
+};
+/* Normal-6 imode */
+static const uint8_t vc1_norm6_spec[64][5] = {
+{ 0, 1, 1 },
+{ 1, 2, 4 },
+{ 2, 3, 4 },
+{ 3, 0, 8 },
+{ 4, 4, 4 },
+{ 5, 1, 8 },
+{ 6, 2, 8 },
+{ 7, 2, 5, 7, 5 },
+{ 8, 5, 4 },
+{ 9, 3, 8 },
+{10, 4, 8 },
+{11, 2, 5, 11, 5 },
+{12, 5, 8 },
+{13, 2, 5, 13, 5 },
+{14, 2, 5, 14, 5 },
+{15, 3, 5, 14, 8 },
+{16, 6, 4 },
+{17, 6, 8 },
+{18, 7, 8 },
+{19, 2, 5, 19, 5 },
+{20, 8, 8 },
+{21, 2, 5, 21, 5 },
+{22, 2, 5, 22, 5 },
+{23, 3, 5, 13, 8 },
+{24, 9, 8 },
+{25, 2, 5, 25, 5 },
+{26, 2, 5, 26, 5 },
+{27, 3, 5, 12, 8 },
+{28, 2, 5, 28, 5 },
+{29, 3, 5, 11, 8 },
+{30, 3, 5, 10, 8 },
+{31, 3, 5, 7, 4 },
+{32, 7, 4 },
+{33, 10, 8 },
+{34, 11, 8 },
+{35, 2, 5, 3, 5 },
+{36, 12, 8 },
+{37, 2, 5, 5, 5 },
+{38, 2, 5, 6, 5 },
+{39, 3, 5, 9, 8 },
+{40, 13, 8 },
+{41, 2, 5, 9, 5 },
+{42, 2, 5, 10, 5 },
+{43, 3, 5, 8, 8 },
+{44, 2, 5, 12, 5 },
+{45, 3, 5, 7, 8 },
+{46, 3, 5, 6, 8 },
+{47, 3, 5, 6, 4 },
+{48, 14, 8 },
+{49, 2, 5, 17, 5 },
+{50, 2, 5, 18, 5 },
+{51, 3, 5, 5, 8 },
+{52, 2, 5, 20, 5 },
+{53, 3, 5, 4, 8 },
+{54, 3, 5, 3, 8 },
+{55, 3, 5, 5, 4 },
+{56, 2, 5, 24, 5 },
+{57, 3, 5, 2, 8 },
+{58, 3, 5, 1, 8 },
+{59, 3, 5, 4, 4 },
+{60, 3, 5, 0, 8 },
+{61, 3, 5, 3, 4 },
+{62, 3, 5, 2, 4 },
+{63, 3, 5, 1, 1 },
+};
+
+/* 4MV Block pattern VLC tables */
+static const uint8_t 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, 19}
+};
+static const uint8_t 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}
+};
+
+const uint8_t 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 */
+#if 1 // Looks like original tables are not conforming to standard at all. Are they used for old WMV?
+static const uint16_t 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
+ }
+};
+
+static const uint8_t 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
+ }
+};
+#else
+static const uint16_t vc1_cbpcy_p_codes[4][64] = {
+ {
+ 0, 1, 1, 4, 5, 1, 12, 4, 13, 14, 10, 11, 12, 7, 13, 2,
+ 15, 1, 96, 1, 49, 97, 2, 100, 3, 4, 5, 101, 102, 52, 53, 4,
+ 6, 7, 54, 103, 8, 9, 10, 110, 11, 12, 111, 56, 114, 58, 115, 5,
+ 13, 7, 8, 9, 10, 11, 12, 30, 13, 14, 15, 118, 119, 62, 63, 3
+ },
+ {
+ 0, 1, 2, 1, 3, 1, 16, 17, 5, 18, 12, 19, 13, 1, 28, 58,
+ 1, 1, 1, 2, 3, 2, 3, 236, 237, 4, 5, 238, 6, 7, 239, 8,
+ 9, 240, 10, 11, 121, 122, 12, 13, 14, 15, 241, 246, 16, 17, 124, 63,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 247, 125
+ },
+ {
+ 0, 1, 2, 3, 2, 3, 1, 4, 5, 24, 7, 13, 16, 17, 9, 5,
+ 25, 1, 1, 1, 2, 3, 96, 194, 1, 2, 98, 99, 195, 200, 101, 26,
+ 201, 102, 412, 413, 414, 54, 220, 111, 221, 3, 224, 113, 225, 114, 230, 29,
+ 231, 415, 240, 4, 241, 484, 5, 243, 3, 244, 245, 485, 492, 493, 247, 31
+ },
+ {
+ 0, 1, 1, 1, 2, 2, 3, 4, 3, 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, 28, 29, 30, 31
+ }
+};
+static const uint8_t vc1_cbpcy_p_bits[4][64] = {
+ {
+ 13, 6, 5, 6, 6, 7, 7, 5, 7, 7, 6, 6, 6, 5, 6, 3,
+ 7, 8, 8, 13, 7, 8, 13, 8, 13, 13, 13, 8, 8, 7, 7, 3,
+ 13, 13, 7, 8, 13, 13, 13, 8, 13, 13, 8, 7, 8, 7, 8, 3,
+ 13, 12, 12, 12, 12, 12, 12, 6, 12, 12, 12, 8, 8, 7, 7, 2
+ },
+ {
+ 14, 3, 3, 5, 3, 4, 5, 5, 3, 5, 4, 5, 4, 6, 5, 6,
+ 8, 14, 13, 8, 8, 13, 13, 8, 8, 13, 13, 8, 13, 13, 8, 13,
+ 13, 8, 13, 13, 7, 7, 13, 13, 13, 13, 8, 8, 13, 13, 7, 6,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 8, 7
+ },
+ {
+ 13, 5, 5, 5, 4, 4, 6, 4, 4, 6, 4, 5, 5, 5, 4, 3,
+ 6, 8, 10, 9, 8, 8, 7, 8, 13, 13, 7, 7, 8, 8, 7, 5,
+ 8, 7, 9, 9, 9, 6, 8, 7, 8, 13, 8, 7, 8, 7, 8, 5,
+ 8, 9, 8, 13, 8, 9, 13, 8, 12, 8, 8, 9, 9, 9, 8, 5
+ },
+ {
+ 9, 2, 3, 9, 2, 9, 9, 9, 2, 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, 8, 8, 8, 8
+ }
+};
+#endif
+
+/* 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 */
+static const uint16_t 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
+ }
+};
+
+static const uint8_t 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 */
+static const uint8_t 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}
+};
+static const uint8_t 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 */
+static const uint8_t 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}
+};
+static const uint8_t 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 */
+static const uint16_t 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 */
+ }
+};
+static const uint8_t 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 */
+
+/* Scantables/ZZ scan are at 11.9 (p262) and 8.1.1.12 (p10) */
+static const int8_t vc1_normal_zz[64] = {
+ 0, 8, 1, 2, 9, 16, 24, 17,
+ 10, 3, 4, 11, 18, 25, 32, 40,
+ 33, 48, 26, 19, 12, 5, 6, 13,
+ 20, 27, 34, 41, 56, 49, 57, 42,
+ 35, 28, 21, 14, 7, 15, 22, 29,
+ 36, 43, 50, 58, 51, 59, 44, 37,
+ 30, 23, 31, 38, 45, 52, 60, 53,
+ 61, 46, 39, 47, 54, 62, 55, 63
+};
+
+static const int8_t vc1_horizontal_zz [64] = /* Table 227 */
+{
+ 0, 1, 8, 2, 3, 9, 16, 24,
+ 17, 10, 4, 5, 11, 18, 25, 32,
+ 40, 48, 33, 26, 19, 12, 6, 7,
+ 13, 20, 27, 34, 41, 56, 49, 57,
+ 42, 35, 28, 21, 14, 15, 22, 29,
+ 36, 43, 50, 58, 51, 44, 37, 30,
+ 23, 31, 38, 45, 52, 59, 60, 53,
+ 46, 39, 47, 54, 61, 62, 55, 63
+};
+
+static const int8_t vc1_vertical_zz [64] = /* Table 228 */
+{
+ 0, 8, 16, 1, 24, 32, 40, 9,
+ 2, 3, 10, 17, 25, 48, 56, 41,
+ 33, 26, 18, 11, 4, 5, 12, 19,
+ 27, 34, 49, 57, 50, 42, 35, 28,
+ 20, 13, 6, 7, 14, 21, 29, 36,
+ 43, 51, 58, 59, 52, 44, 37, 30,
+ 22, 15, 23, 31, 38, 45, 60, 53,
+ 46, 39, 47, 54, 61, 62, 55, 63
+};
+
+static const int8_t vc1_simple_progressive_8x8_zz [64] =
+/* Table 229 */
+{
+ 0, 8, 1, 2, 9, 16, 24, 17,
+ 10, 3, 4, 11, 18, 25, 32, 40,
+ 48, 56, 41, 33, 26, 19, 12, 5,
+ 6, 13, 20, 27, 34, 49, 57, 58,
+ 50, 42, 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
+};
+
+static const int8_t vc1_simple_progressive_8x4_zz [32] = /* Table 230 */
+{
+ 0, 1, 2, 8, 3, 9, 10, 16,
+ 4, 11, 17, 24, 18, 12, 5, 19,
+ 25, 13, 20, 26, 27, 6, 21, 28,
+ 14, 22, 29, 7, 30, 15, 23, 31
+};
+
+static const int8_t vc1_simple_progressive_4x8_zz [32] = /* Table 231 */
+{
+ 0, 8, 1, 16,
+ 9, 24, 17, 2,
+ 32, 10, 25, 40,
+ 18, 48, 33, 26,
+ 56, 41, 34, 3,
+ 49, 57, 11, 42,
+ 19, 50, 27, 58,
+ 35, 43, 51, 59
+};
+
+/* Table 232 */
+static const int8_t vc1_simple_progressive_4x4_zz [16] =
+{
+ 0, 8, 16, 1,
+ 9, 24, 17, 2,
+ 10, 18, 25, 3,
+ 11, 26, 19, 27
+};
+
+static const int8_t 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
+};
+
+static const int8_t 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
+};
+
+static const int8_t 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
+};
+
+static const int8_t 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
+};
+
+static const int8_t 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
+};
+
+static const int8_t 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 */
+static const int32_t 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
+};
+#endif /* VC1DATA_H */
diff --git a/contrib/ffmpeg/libavcodec/vc1dsp.c b/contrib/ffmpeg/libavcodec/vc1dsp.c
new file mode 100644
index 000000000..9139ffb28
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vc1dsp.c
@@ -0,0 +1,463 @@
+/*
+ * 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 vc1dsp.c
+ * VC-1 and WMV3 decoder
+ *
+ */
+
+#include "dsputil.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] = b - d2;
+ src[0] = 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] = b - d2;
+ src[0] = c + d2;
+ src[1] = d + d1;
+ src += stride;
+ rnd = !rnd;
+ }
+}
+
+
+/** Do inverse transform on 8x8 block
+*/
+static void vc1_inv_trans_8x8_c(DCTELEM block[64])
+{
+ int i;
+ register int t1,t2,t3,t4,t5,t6,t7,t8;
+ DCTELEM *src, *dst;
+
+ src = block;
+ dst = block;
+ for(i = 0; i < 8; i++){
+ t1 = 12 * (src[0] + src[4]);
+ t2 = 12 * (src[0] - src[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 + 4) >> 3;
+ dst[1] = (t6 + t2 + 4) >> 3;
+ dst[2] = (t7 + t3 + 4) >> 3;
+ dst[3] = (t8 + t4 + 4) >> 3;
+ dst[4] = (t8 - t4 + 4) >> 3;
+ dst[5] = (t7 - t3 + 4) >> 3;
+ dst[6] = (t6 - t2 + 4) >> 3;
+ dst[7] = (t5 - t1 + 4) >> 3;
+
+ src += 8;
+ dst += 8;
+ }
+
+ src = block;
+ dst = block;
+ for(i = 0; i < 8; i++){
+ t1 = 12 * (src[ 0] + src[32]);
+ t2 = 12 * (src[ 0] - src[32]);
+ 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 + 64) >> 7;
+ dst[ 8] = (t6 + t2 + 64) >> 7;
+ dst[16] = (t7 + t3 + 64) >> 7;
+ dst[24] = (t8 + t4 + 64) >> 7;
+ dst[32] = (t8 - t4 + 64 + 1) >> 7;
+ dst[40] = (t7 - t3 + 64 + 1) >> 7;
+ dst[48] = (t6 - t2 + 64 + 1) >> 7;
+ dst[56] = (t5 - t1 + 64 + 1) >> 7;
+
+ src++;
+ dst++;
+ }
+}
+
+/** Do inverse transform on 8x4 part of block
+*/
+static void vc1_inv_trans_8x4_c(DCTELEM block[64], int n)
+{
+ int i;
+ register int t1,t2,t3,t4,t5,t6,t7,t8;
+ DCTELEM *src, *dst;
+ int off;
+
+ off = n * 32;
+ src = block + off;
+ dst = block + off;
+ for(i = 0; i < 4; i++){
+ t1 = 12 * (src[0] + src[4]);
+ t2 = 12 * (src[0] - src[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 + 4) >> 3;
+ dst[1] = (t6 + t2 + 4) >> 3;
+ dst[2] = (t7 + t3 + 4) >> 3;
+ dst[3] = (t8 + t4 + 4) >> 3;
+ dst[4] = (t8 - t4 + 4) >> 3;
+ dst[5] = (t7 - t3 + 4) >> 3;
+ dst[6] = (t6 - t2 + 4) >> 3;
+ dst[7] = (t5 - t1 + 4) >> 3;
+
+ src += 8;
+ dst += 8;
+ }
+
+ src = block + off;
+ dst = block + off;
+ for(i = 0; i < 8; i++){
+ t1 = 17 * (src[ 0] + src[16]);
+ t2 = 17 * (src[ 0] - src[16]);
+ t3 = 22 * src[ 8];
+ t4 = 22 * src[24];
+ t5 = 10 * src[ 8];
+ t6 = 10 * src[24];
+
+ dst[ 0] = (t1 + t3 + t6 + 64) >> 7;
+ dst[ 8] = (t2 - t4 + t5 + 64) >> 7;
+ dst[16] = (t2 + t4 - t5 + 64) >> 7;
+ dst[24] = (t1 - t3 - t6 + 64) >> 7;
+
+ src ++;
+ dst ++;
+ }
+}
+
+/** Do inverse transform on 4x8 parts of block
+*/
+static void vc1_inv_trans_4x8_c(DCTELEM block[64], int n)
+{
+ int i;
+ register int t1,t2,t3,t4,t5,t6,t7,t8;
+ DCTELEM *src, *dst;
+ int off;
+
+ off = n * 4;
+ src = block + off;
+ dst = block + off;
+ for(i = 0; i < 8; i++){
+ t1 = 17 * (src[0] + src[2]);
+ t2 = 17 * (src[0] - src[2]);
+ t3 = 22 * src[1];
+ t4 = 22 * src[3];
+ t5 = 10 * src[1];
+ t6 = 10 * src[3];
+
+ dst[0] = (t1 + t3 + t6 + 4) >> 3;
+ dst[1] = (t2 - t4 + t5 + 4) >> 3;
+ dst[2] = (t2 + t4 - t5 + 4) >> 3;
+ dst[3] = (t1 - t3 - t6 + 4) >> 3;
+
+ src += 8;
+ dst += 8;
+ }
+
+ src = block + off;
+ dst = block + off;
+ for(i = 0; i < 4; i++){
+ t1 = 12 * (src[ 0] + src[32]);
+ t2 = 12 * (src[ 0] - src[32]);
+ 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 + 64) >> 7;
+ dst[ 8] = (t6 + t2 + 64) >> 7;
+ dst[16] = (t7 + t3 + 64) >> 7;
+ dst[24] = (t8 + t4 + 64) >> 7;
+ dst[32] = (t8 - t4 + 64 + 1) >> 7;
+ dst[40] = (t7 - t3 + 64 + 1) >> 7;
+ dst[48] = (t6 - t2 + 64 + 1) >> 7;
+ dst[56] = (t5 - t1 + 64 + 1) >> 7;
+
+ src++;
+ dst++;
+ }
+}
+
+/** Do inverse transform on 4x4 part of block
+*/
+static void vc1_inv_trans_4x4_c(DCTELEM block[64], int n)
+{
+ int i;
+ register int t1,t2,t3,t4,t5,t6;
+ DCTELEM *src, *dst;
+ int off;
+
+ off = (n&1) * 4 + (n&2) * 16;
+ src = block + off;
+ dst = block + off;
+ for(i = 0; i < 4; i++){
+ t1 = 17 * (src[0] + src[2]);
+ t2 = 17 * (src[0] - src[2]);
+ t3 = 22 * src[1];
+ t4 = 22 * src[3];
+ t5 = 10 * src[1];
+ t6 = 10 * src[3];
+
+ dst[0] = (t1 + t3 + t6 + 4) >> 3;
+ dst[1] = (t2 - t4 + t5 + 4) >> 3;
+ dst[2] = (t2 + t4 - t5 + 4) >> 3;
+ dst[3] = (t1 - t3 - t6 + 4) >> 3;
+
+ src += 8;
+ dst += 8;
+ }
+
+ src = block + off;
+ dst = block + off;
+ for(i = 0; i < 4; i++){
+ t1 = 17 * (src[ 0] + src[16]);
+ t2 = 17 * (src[ 0] - src[16]);
+ t3 = 22 * src[ 8];
+ t4 = 22 * src[24];
+ t5 = 10 * src[ 8];
+ t6 = 10 * src[24];
+
+ dst[ 0] = (t1 + t3 + t6 + 64) >> 7;
+ dst[ 8] = (t2 - t4 + t5 + 64) >> 7;
+ dst[16] = (t2 + t4 - t5 + 64) >> 7;
+ dst[24] = (t1 - t3 - t6 + 64) >> 7;
+
+ src ++;
+ dst ++;
+ }
+}
+
+/* motion compensation functions */
+
+/** Filter used to interpolate fractional pel values
+ */
+static 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
+ */
+static void vc1_mspel_mc(uint8_t *dst, const uint8_t *src, int stride, int mode, int rnd)
+{
+ int i, j;
+ uint8_t tmp[8*11], *tptr;
+ int m, r;
+
+ m = (mode & 3);
+ r = rnd;
+ src -= stride;
+ tptr = tmp;
+ for(j = 0; j < 11; j++) {
+ for(i = 0; i < 8; i++)
+ tptr[i] = clip_uint8(vc1_mspel_filter(src + i, 1, m, r));
+ src += stride;
+ tptr += 8;
+ }
+ r = 1 - rnd;
+ m = (mode >> 2) & 3;
+
+ tptr = tmp + 8;
+ for(j = 0; j < 8; j++) {
+ for(i = 0; i < 8; i++)
+ dst[i] = clip_uint8(vc1_mspel_filter(tptr + i, 8, m, r));
+ dst += stride;
+ tptr += 8;
+ }
+}
+
+/* pixel functions - really are entry points to vc1_mspel_mc */
+
+/* this one is defined in dsputil.c */
+void ff_put_vc1_mspel_mc00_c(uint8_t *dst, const uint8_t *src, int stride, int rnd);
+
+static void ff_put_vc1_mspel_mc10_c(uint8_t *dst, const uint8_t *src, int stride, int rnd) {
+ vc1_mspel_mc(dst, src, stride, 0x1, rnd);
+}
+
+static void ff_put_vc1_mspel_mc20_c(uint8_t *dst, const uint8_t *src, int stride, int rnd) {
+ vc1_mspel_mc(dst, src, stride, 0x2, rnd);
+}
+
+static void ff_put_vc1_mspel_mc30_c(uint8_t *dst, const uint8_t *src, int stride, int rnd) {
+ vc1_mspel_mc(dst, src, stride, 0x3, rnd);
+}
+
+static void ff_put_vc1_mspel_mc01_c(uint8_t *dst, const uint8_t *src, int stride, int rnd) {
+ vc1_mspel_mc(dst, src, stride, 0x4, rnd);
+}
+
+static void ff_put_vc1_mspel_mc11_c(uint8_t *dst, const uint8_t *src, int stride, int rnd) {
+ vc1_mspel_mc(dst, src, stride, 0x5, rnd);
+}
+
+static void ff_put_vc1_mspel_mc21_c(uint8_t *dst, const uint8_t *src, int stride, int rnd) {
+ vc1_mspel_mc(dst, src, stride, 0x6, rnd);
+}
+
+static void ff_put_vc1_mspel_mc31_c(uint8_t *dst, const uint8_t *src, int stride, int rnd) {
+ vc1_mspel_mc(dst, src, stride, 0x7, rnd);
+}
+
+static void ff_put_vc1_mspel_mc02_c(uint8_t *dst, const uint8_t *src, int stride, int rnd) {
+ vc1_mspel_mc(dst, src, stride, 0x8, rnd);
+}
+
+static void ff_put_vc1_mspel_mc12_c(uint8_t *dst, const uint8_t *src, int stride, int rnd) {
+ vc1_mspel_mc(dst, src, stride, 0x9, rnd);
+}
+
+static void ff_put_vc1_mspel_mc22_c(uint8_t *dst, const uint8_t *src, int stride, int rnd) {
+ vc1_mspel_mc(dst, src, stride, 0xA, rnd);
+}
+
+static void ff_put_vc1_mspel_mc32_c(uint8_t *dst, const uint8_t *src, int stride, int rnd) {
+ vc1_mspel_mc(dst, src, stride, 0xB, rnd);
+}
+
+static void ff_put_vc1_mspel_mc03_c(uint8_t *dst, const uint8_t *src, int stride, int rnd) {
+ vc1_mspel_mc(dst, src, stride, 0xC, rnd);
+}
+
+static void ff_put_vc1_mspel_mc13_c(uint8_t *dst, const uint8_t *src, int stride, int rnd) {
+ vc1_mspel_mc(dst, src, stride, 0xD, rnd);
+}
+
+static void ff_put_vc1_mspel_mc23_c(uint8_t *dst, const uint8_t *src, int stride, int rnd) {
+ vc1_mspel_mc(dst, src, stride, 0xE, rnd);
+}
+
+static void ff_put_vc1_mspel_mc33_c(uint8_t *dst, const uint8_t *src, int stride, int rnd) {
+ vc1_mspel_mc(dst, src, stride, 0xF, rnd);
+}
+
+void ff_vc1dsp_init(DSPContext* dsp, AVCodecContext *avctx) {
+ 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_h_overlap = vc1_h_overlap_c;
+ dsp->vc1_v_overlap = vc1_v_overlap_c;
+
+ dsp->put_vc1_mspel_pixels_tab[ 0] = ff_put_vc1_mspel_mc00_c;
+ dsp->put_vc1_mspel_pixels_tab[ 1] = ff_put_vc1_mspel_mc10_c;
+ dsp->put_vc1_mspel_pixels_tab[ 2] = ff_put_vc1_mspel_mc20_c;
+ dsp->put_vc1_mspel_pixels_tab[ 3] = ff_put_vc1_mspel_mc30_c;
+ dsp->put_vc1_mspel_pixels_tab[ 4] = ff_put_vc1_mspel_mc01_c;
+ dsp->put_vc1_mspel_pixels_tab[ 5] = ff_put_vc1_mspel_mc11_c;
+ dsp->put_vc1_mspel_pixels_tab[ 6] = ff_put_vc1_mspel_mc21_c;
+ dsp->put_vc1_mspel_pixels_tab[ 7] = ff_put_vc1_mspel_mc31_c;
+ dsp->put_vc1_mspel_pixels_tab[ 8] = ff_put_vc1_mspel_mc02_c;
+ dsp->put_vc1_mspel_pixels_tab[ 9] = ff_put_vc1_mspel_mc12_c;
+ dsp->put_vc1_mspel_pixels_tab[10] = ff_put_vc1_mspel_mc22_c;
+ dsp->put_vc1_mspel_pixels_tab[11] = ff_put_vc1_mspel_mc32_c;
+ dsp->put_vc1_mspel_pixels_tab[12] = ff_put_vc1_mspel_mc03_c;
+ dsp->put_vc1_mspel_pixels_tab[13] = ff_put_vc1_mspel_mc13_c;
+ dsp->put_vc1_mspel_pixels_tab[14] = ff_put_vc1_mspel_mc23_c;
+ dsp->put_vc1_mspel_pixels_tab[15] = ff_put_vc1_mspel_mc33_c;
+}
diff --git a/contrib/ffmpeg/libavcodec/vcr1.c b/contrib/ffmpeg/libavcodec/vcr1.c
new file mode 100644
index 000000000..62bf12320
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vcr1.c
@@ -0,0 +1,190 @@
+/*
+ * 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 vcr1.c
+ * ati vcr1 codec.
+ */
+
+#include "avcodec.h"
+#include "mpegvideo.h"
+
+//#undef NDEBUG
+//#include <assert.h>
+
+typedef struct VCR1Context{
+ AVCodecContext *avctx;
+ AVFrame picture;
+ int delta[16];
+ int offset[4];
+} VCR1Context;
+
+static int decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ VCR1Context * const a = avctx->priv_data;
+ AVFrame *picture = data;
+ AVFrame * const p= (AVFrame*)&a->picture;
+ uint8_t *bytestream= buf;
+ int i, x, y;
+
+ if(p->data[0])
+ avctx->release_buffer(avctx, p);
+
+ p->reference= 0;
+ if(avctx->get_buffer(avctx, p) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+ p->pict_type= I_TYPE;
+ 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= &a->picture.data[0][ y*a->picture.linesize[0] ];
+
+ if((y&3) == 0){
+ uint8_t *cb= &a->picture.data[1][ (y>>2)*a->picture.linesize[1] ];
+ uint8_t *cr= &a->picture.data[2][ (y>>2)*a->picture.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;
+ }
+ }
+ }
+
+ *picture= *(AVFrame*)&a->picture;
+ *data_size = sizeof(AVPicture);
+
+ emms_c();
+
+ return buf_size;
+}
+
+#if 0
+static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
+ VCR1Context * const a = avctx->priv_data;
+ AVFrame *pict = data;
+ AVFrame * const p= (AVFrame*)&a->picture;
+ int size;
+ int mb_x, mb_y;
+
+ *p = *pict;
+ p->pict_type= I_TYPE;
+ p->key_frame= 1;
+
+ emms_c();
+
+ align_put_bits(&a->pb);
+ while(get_bit_count(&a->pb)&31)
+ put_bits(&a->pb, 8, 0);
+
+ size= get_bit_count(&a->pb)/32;
+
+ return size*4;
+}
+#endif
+
+static void common_init(AVCodecContext *avctx){
+ VCR1Context * const a = avctx->priv_data;
+
+ avctx->coded_frame= (AVFrame*)&a->picture;
+ a->avctx= avctx;
+}
+
+static int decode_init(AVCodecContext *avctx){
+
+ common_init(avctx);
+
+ avctx->pix_fmt= PIX_FMT_YUV410P;
+
+ return 0;
+}
+
+#if 0
+static int encode_init(AVCodecContext *avctx){
+
+ common_init(avctx);
+
+ return 0;
+}
+#endif
+
+AVCodec vcr1_decoder = {
+ "vcr1",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_VCR1,
+ sizeof(VCR1Context),
+ decode_init,
+ NULL,
+ NULL,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
+#if 0
+#ifdef CONFIG_ENCODERS
+
+AVCodec vcr1_encoder = {
+ "vcr1",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_VCR1,
+ sizeof(VCR1Context),
+ encode_init,
+ encode_frame,
+ //encode_end,
+};
+
+#endif //CONFIG_ENCODERS
+#endif
diff --git a/contrib/ffmpeg/libavcodec/vmdav.c b/contrib/ffmpeg/libavcodec/vmdav.c
new file mode 100644
index 000000000..a9937144e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vmdav.c
@@ -0,0 +1,572 @@
+/*
+ * 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 vmdvideo.c
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.h"
+
+#define VMD_HEADER_SIZE 0x330
+#define PALETTE_COUNT 256
+
+/*
+ * Video Decoder
+ */
+
+typedef struct VmdVideoContext {
+
+ AVCodecContext *avctx;
+ DSPContext dsp;
+ AVFrame frame;
+ AVFrame prev_frame;
+
+ unsigned char *buf;
+ int size;
+
+ unsigned char palette[PALETTE_COUNT * 4];
+ unsigned char *unpack_buffer;
+ int unpack_buffer_size;
+
+} VmdVideoContext;
+
+#define QUEUE_SIZE 0x1000
+#define QUEUE_MASK 0x0FFF
+
+static void lz_unpack(unsigned char *src, unsigned char *dest, int dest_len)
+{
+ unsigned char *s;
+ 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;
+ d = dest;
+ d_end = d + dest_len;
+ dataleft = LE_32(s);
+ s += 4;
+ memset(queue, 0x20, QUEUE_SIZE);
+ if (LE_32(s) == 0x56781234) {
+ s += 4;
+ qpos = 0x111;
+ speclen = 0xF + 3;
+ } else {
+ qpos = 0xFEE;
+ speclen = 100; /* no speclen */
+ }
+
+ while (dataleft > 0) {
+ tag = *s++;
+ if ((tag == 0xFF) && (dataleft > 8)) {
+ if (d + 8 > d_end)
+ 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 + 1 > d_end)
+ return;
+ queue[qpos++] = *d++ = *s++;
+ qpos &= QUEUE_MASK;
+ dataleft--;
+ } else {
+ chainofs = *s++;
+ chainofs |= ((*s & 0xF0) << 4);
+ chainlen = (*s++ & 0x0F) + 3;
+ if (chainlen == speclen)
+ chainlen = *s++ + 0xF + 3;
+ if (d + chainlen > d_end)
+ 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(unsigned char *src, unsigned char *dest,
+ int src_len, int dest_len)
+{
+ unsigned char *ps;
+ unsigned char *pd;
+ int i, l;
+ unsigned char *dest_end = dest + dest_len;
+
+ ps = src;
+ pd = dest;
+ if (src_len & 1)
+ *pd++ = *ps++;
+
+ src_len >>= 1;
+ i = 0;
+ do {
+ l = *ps++;
+ if (l & 0x80) {
+ l = (l & 0x7F) * 2;
+ if (pd + l > dest_end)
+ return (ps - src);
+ memcpy(pd, ps, l);
+ ps += l;
+ pd += l;
+ } else {
+ if (pd + i > dest_end)
+ return (ps - src);
+ for (i = 0; i < l; i++) {
+ *pd++ = ps[0];
+ *pd++ = ps[1];
+ }
+ ps += 2;
+ }
+ i += l;
+ } while (i < src_len);
+
+ return (ps - src);
+}
+
+static void vmd_decode(VmdVideoContext *s)
+{
+ int i;
+ unsigned int *palette32;
+ unsigned char r, g, b;
+
+ /* point to the start of the encoded data */
+ unsigned char *p = s->buf + 16;
+
+ unsigned char *pb;
+ 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;
+ int dp_size;
+
+ frame_x = LE_16(&s->buf[6]);
+ frame_y = LE_16(&s->buf[8]);
+ frame_width = LE_16(&s->buf[10]) - frame_x + 1;
+ frame_height = LE_16(&s->buf[12]) - frame_y + 1;
+
+ /* if only a certain region will be updated, copy the entire previous
+ * frame before the decode */
+ if (frame_x || frame_y || (frame_width != s->avctx->width) ||
+ (frame_height != s->avctx->height)) {
+
+ memcpy(s->frame.data[0], s->prev_frame.data[0],
+ s->avctx->height * s->frame.linesize[0]);
+ }
+
+ /* check if there is a new palette */
+ if (s->buf[15] & 0x02) {
+ 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] = (r << 16) | (g << 8) | (b);
+ }
+ s->size -= (256 * 3 + 2);
+ }
+ if (s->size >= 0) {
+ /* originally UnpackFrame in VAG's code */
+ pb = p;
+ meth = *pb++;
+ if (meth & 0x80) {
+ lz_unpack(pb, s->unpack_buffer, s->unpack_buffer_size);
+ meth &= 0x7F;
+ pb = s->unpack_buffer;
+ }
+
+ dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
+ dp_size = s->frame.linesize[0] * s->avctx->height;
+ 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 {
+ len = *pb++;
+ if (len & 0x80) {
+ len = (len & 0x7F) + 1;
+ if (ofs + len > frame_width)
+ return;
+ memcpy(&dp[ofs], pb, len);
+ pb += len;
+ ofs += len;
+ } else {
+ /* interframe pixel copy */
+ if (ofs + len + 1 > frame_width)
+ 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, "VMD video: offset > width (%d > %d)\n",
+ ofs, frame_width);
+ break;
+ }
+ dp += s->frame.linesize[0];
+ pp += s->prev_frame.linesize[0];
+ }
+ break;
+
+ case 2:
+ for (i = 0; i < frame_height; i++) {
+ memcpy(dp, pb, frame_width);
+ pb += frame_width;
+ dp += s->frame.linesize[0];
+ pp += s->prev_frame.linesize[0];
+ }
+ break;
+
+ case 3:
+ for (i = 0; i < frame_height; i++) {
+ ofs = 0;
+ do {
+ len = *pb++;
+ if (len & 0x80) {
+ len = (len & 0x7F) + 1;
+ if (*pb++ == 0xFF)
+ len = rle_unpack(pb, &dp[ofs], len, frame_width - ofs);
+ else
+ memcpy(&dp[ofs], pb, len);
+ pb += len;
+ ofs += len;
+ } else {
+ /* interframe pixel copy */
+ if (ofs + len + 1 > frame_width)
+ 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, "VMD video: offset > width (%d > %d)\n",
+ ofs, frame_width);
+ }
+ dp += s->frame.linesize[0];
+ pp += s->prev_frame.linesize[0];
+ }
+ break;
+ }
+ }
+}
+
+static int vmdvideo_decode_init(AVCodecContext *avctx)
+{
+ VmdVideoContext *s = (VmdVideoContext *)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 = PIX_FMT_PAL8;
+ avctx->has_b_frames = 0;
+ dsputil_init(&s->dsp, avctx);
+
+ /* make sure the VMD header made it */
+ if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
+ av_log(s->avctx, AV_LOG_ERROR, "VMD video: expected extradata size of %d\n",
+ VMD_HEADER_SIZE);
+ return -1;
+ }
+ vmd_header = (unsigned char *)avctx->extradata;
+
+ s->unpack_buffer_size = LE_32(&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);
+ }
+
+ s->frame.data[0] = s->prev_frame.data[0] = NULL;
+
+ return 0;
+}
+
+static int vmdvideo_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data;
+
+ s->buf = buf;
+ s->size = buf_size;
+
+ if (buf_size < 16)
+ return buf_size;
+
+ s->frame.reference = 1;
+ if (avctx->get_buffer(avctx, &s->frame)) {
+ av_log(s->avctx, AV_LOG_ERROR, "VMD Video: get_buffer() failed\n");
+ return -1;
+ }
+
+ vmd_decode(s);
+
+ /* make the palette available on the way out */
+ memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
+
+ if (s->prev_frame.data[0])
+ avctx->release_buffer(avctx, &s->prev_frame);
+
+ /* shuffle frames */
+ s->prev_frame = s->frame;
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = s->frame;
+
+ /* report that the buffer was completely consumed */
+ return buf_size;
+}
+
+static int vmdvideo_decode_end(AVCodecContext *avctx)
+{
+ VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data;
+
+ if (s->prev_frame.data[0])
+ avctx->release_buffer(avctx, &s->prev_frame);
+ av_free(s->unpack_buffer);
+
+ return 0;
+}
+
+
+/*
+ * Audio Decoder
+ */
+
+typedef struct VmdAudioContext {
+ AVCodecContext *avctx;
+ int channels;
+ int bits;
+ int block_align;
+ int predictors[2];
+} VmdAudioContext;
+
+static 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 int vmdaudio_decode_init(AVCodecContext *avctx)
+{
+ VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data;
+
+ s->avctx = avctx;
+ s->channels = avctx->channels;
+ s->bits = avctx->bits_per_sample;
+ s->block_align = avctx->block_align;
+
+ av_log(s->avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, block align = %d, sample rate = %d\n",
+ s->channels, s->bits, s->block_align, avctx->sample_rate);
+
+ return 0;
+}
+
+static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data,
+ uint8_t *buf, int stereo)
+{
+ int i;
+ int chan = 0;
+ int16_t *out = (int16_t*)data;
+
+ for(i = 0; i < s->block_align; i++) {
+ if(buf[i] & 0x80)
+ s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F];
+ else
+ s->predictors[chan] += vmdaudio_table[buf[i]];
+ s->predictors[chan] = clip(s->predictors[chan], -32768, 32767);
+ out[i] = s->predictors[chan];
+ chan ^= stereo;
+ }
+}
+
+static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
+ uint8_t *buf, int silence)
+{
+ int bytes_decoded = 0;
+ int i;
+
+// if (silence)
+// av_log(s->avctx, AV_LOG_INFO, "silent block!\n");
+ if (s->channels == 2) {
+
+ /* stereo handling */
+ if (silence) {
+ memset(data, 0, s->block_align * 2);
+ } else {
+ if (s->bits == 16)
+ vmdaudio_decode_audio(s, data, buf, 1);
+ else {
+ /* copy the data but convert it to signed */
+ for (i = 0; i < s->block_align; i++){
+ *data++ = buf[i] + 0x80;
+ *data++ = buf[i] + 0x80;
+ }
+ }
+ }
+ } else {
+ bytes_decoded = s->block_align * 2;
+
+ /* mono handling */
+ if (silence) {
+ memset(data, 0, s->block_align * 2);
+ } else {
+ if (s->bits == 16) {
+ vmdaudio_decode_audio(s, data, buf, 0);
+ } else {
+ /* copy the data but convert it to signed */
+ for (i = 0; i < s->block_align; i++){
+ *data++ = buf[i] + 0x80;
+ *data++ = buf[i] + 0x80;
+ }
+ }
+ }
+ }
+
+ return s->block_align * 2;
+}
+
+static int vmdaudio_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data;
+ unsigned char *output_samples = (unsigned char *)data;
+
+ /* point to the start of the encoded data */
+ unsigned char *p = buf + 16;
+
+ if (buf_size < 16)
+ return buf_size;
+
+ if (buf[6] == 1) {
+ /* the chunk contains audio */
+ *data_size = vmdaudio_loadsound(s, output_samples, p, 0);
+ } else if (buf[6] == 2) {
+ /* the chunk may contain audio */
+ p += 4;
+ *data_size = vmdaudio_loadsound(s, output_samples, p, (buf_size == 16));
+ output_samples += (s->block_align * s->bits / 8);
+ } else if (buf[6] == 3) {
+ /* silent chunk */
+ *data_size = vmdaudio_loadsound(s, output_samples, p, 1);
+ }
+
+ return buf_size;
+}
+
+
+/*
+ * Public Data Structures
+ */
+
+AVCodec vmdvideo_decoder = {
+ "vmdvideo",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_VMDVIDEO,
+ sizeof(VmdVideoContext),
+ vmdvideo_decode_init,
+ NULL,
+ vmdvideo_decode_end,
+ vmdvideo_decode_frame,
+ CODEC_CAP_DR1,
+};
+
+AVCodec vmdaudio_decoder = {
+ "vmdaudio",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_VMDAUDIO,
+ sizeof(VmdAudioContext),
+ vmdaudio_decode_init,
+ NULL,
+ NULL,
+ vmdaudio_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/vmnc.c b/contrib/ffmpeg/libavcodec/vmnc.c
new file mode 100644
index 000000000..7b5f567e7
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vmnc.c
@@ -0,0 +1,525 @@
+/*
+ * 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 vmnc.c
+ * VMware Screen Codec (VMnc) decoder
+ * As Alex Beregszaszi discovered, this is effectively RFB data dump
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "common.h"
+#include "avcodec.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 always_inline int vmnc_get_pixel(uint8_t* buf, int bpp, int be) {
+ switch(bpp * 2 + be) {
+ case 2:
+ case 3: return *buf;
+ case 4: return LE_16(buf);
+ case 5: return BE_16(buf);
+ case 8: return LE_32(buf);
+ case 9: return BE_32(buf);
+ default: return 0;
+ }
+}
+
+static void load_cursor(VmncContext *c, 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 colour */
+static 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 always_inline void paint_raw(uint8_t *dst, int w, int h, 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, 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;
+ 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 *data_size, uint8_t *buf, int buf_size)
+{
+ VmncContext * const c = (VmncContext *)avctx->priv_data;
+ uint8_t *outptr;
+ uint8_t *src = buf;
+ int dx, dy, w, h, depth, enc, chunks, res, size_left;
+
+ c->pic.reference = 1;
+ c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
+ if(avctx->reget_buffer(avctx, &c->pic) < 0){
+ av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+ return -1;
+ }
+
+ c->pic.key_frame = 0;
+ c->pic.pict_type = FF_P_TYPE;
+
+ //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 = BE_16(src); src += 2;
+ while(chunks--) {
+ dx = BE_16(src); src += 2;
+ dy = BE_16(src); src += 2;
+ w = BE_16(src); src += 2;
+ h = BE_16(src); src += 2;
+ enc = BE_32(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(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 = FF_I_TYPE;
+ 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);
+ }
+ }
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = c->pic;
+
+ /* always report that the buffer was completely consumed */
+ return buf_size;
+}
+
+
+
+/*
+ *
+ * Init VMnc decoder
+ *
+ */
+static int decode_init(AVCodecContext *avctx)
+{
+ VmncContext * const c = (VmncContext *)avctx->priv_data;
+
+ c->avctx = avctx;
+ avctx->has_b_frames = 0;
+
+ c->pic.data[0] = NULL;
+ c->width = avctx->width;
+ c->height = avctx->height;
+
+ if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
+ return 1;
+ }
+ c->bpp = avctx->bits_per_sample;
+ c->bpp2 = c->bpp/8;
+
+ switch(c->bpp){
+ case 8:
+ avctx->pix_fmt = PIX_FMT_PAL8;
+ break;
+ case 16:
+ avctx->pix_fmt = PIX_FMT_RGB555;
+ break;
+ case 32:
+ avctx->pix_fmt = PIX_FMT_RGB32;
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n", c->bpp);
+ }
+
+ return 0;
+}
+
+
+
+/*
+ *
+ * Uninit VMnc decoder
+ *
+ */
+static int decode_end(AVCodecContext *avctx)
+{
+ VmncContext * const c = (VmncContext *)avctx->priv_data;
+
+ if (c->pic.data[0])
+ avctx->release_buffer(avctx, &c->pic);
+
+ av_free(c->curbits);
+ av_free(c->curmask);
+ av_free(c->screendta);
+ return 0;
+}
+
+AVCodec vmnc_decoder = {
+ "VMware video",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_VMNC,
+ sizeof(VmncContext),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame
+};
+
diff --git a/contrib/ffmpeg/libavcodec/vorbis.c b/contrib/ffmpeg/libavcodec/vorbis.c
new file mode 100644
index 000000000..ca8d0a956
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vorbis.c
@@ -0,0 +1,1814 @@
+/**
+ * @file vorbis.c
+ * 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
+ *
+ */
+
+#undef V_DEBUG
+//#define V_DEBUG
+//#define AV_DEBUG(...) av_log(NULL, AV_LOG_INFO, __VA_ARGS__)
+
+#include <math.h>
+
+#define ALT_BITSTREAM_READER_LE
+#include "avcodec.h"
+#include "bitstream.h"
+#include "dsputil.h"
+
+#include "vorbis.h"
+
+#define V_NB_BITS 8
+#define V_NB_BITS2 11
+#define V_MAX_VLCS (1<<16)
+
+#ifndef V_DEBUG
+#define AV_DEBUG(...)
+#endif
+
+#undef NDEBUG
+#include <assert.h>
+
+typedef struct {
+ uint_fast8_t dimensions;
+ uint_fast8_t lookup_type;
+ uint_fast8_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
+uint_fast8_t (* vorbis_floor_decode_func)
+ (struct vorbis_context_s *, vorbis_floor_data *, float *);
+typedef struct {
+ uint_fast8_t floor_type;
+ vorbis_floor_decode_func decode;
+ union vorbis_floor_u
+ {
+ struct vorbis_floor0_s
+ {
+ uint_fast8_t order;
+ uint_fast16_t rate;
+ uint_fast16_t bark_map_size;
+ int_fast32_t * map[2];
+ uint_fast32_t map_size[2];
+ uint_fast8_t amplitude_bits;
+ uint_fast8_t amplitude_offset;
+ uint_fast8_t num_books;
+ uint_fast8_t * book_list;
+ float * lsp;
+ } t0;
+ struct vorbis_floor1_s
+ {
+ uint_fast8_t partitions;
+ uint_fast8_t maximum_class;
+ uint_fast8_t partition_class[32];
+ uint_fast8_t class_dimensions[16];
+ uint_fast8_t class_subclasses[16];
+ uint_fast8_t class_masterbook[16];
+ int_fast16_t subclass_books[16][8];
+ uint_fast8_t multiplier;
+ uint_fast16_t x_list_dim;
+ floor1_entry_t * list;
+ } t1;
+ } data;
+} vorbis_floor;
+
+typedef struct {
+ uint_fast16_t type;
+ uint_fast32_t begin;
+ uint_fast32_t end;
+ uint_fast32_t partition_size;
+ uint_fast8_t classifications;
+ uint_fast8_t classbook;
+ int_fast16_t books[64][8];
+ uint_fast8_t maxpass;
+} vorbis_residue;
+
+typedef struct {
+ uint_fast8_t submaps;
+ uint_fast16_t coupling_steps;
+ uint_fast8_t *magnitude;
+ uint_fast8_t *angle;
+ uint_fast8_t *mux;
+ uint_fast8_t submap_floor[16];
+ uint_fast8_t submap_residue[16];
+} vorbis_mapping;
+
+typedef struct {
+ uint_fast8_t blockflag;
+ uint_fast16_t windowtype;
+ uint_fast16_t transformtype;
+ uint_fast8_t mapping;
+} vorbis_mode;
+
+typedef struct vorbis_context_s {
+ AVCodecContext *avccontext;
+ GetBitContext gb;
+ DSPContext dsp;
+
+ MDCTContext mdct[2];
+ uint_fast8_t first_frame;
+ uint_fast32_t version;
+ uint_fast8_t audio_channels;
+ uint_fast32_t audio_samplerate;
+ uint_fast32_t bitrate_maximum;
+ uint_fast32_t bitrate_nominal;
+ uint_fast32_t bitrate_minimum;
+ uint_fast32_t blocksize[2];
+ const float * win[2];
+ uint_fast16_t codebook_count;
+ vorbis_codebook *codebooks;
+ uint_fast8_t floor_count;
+ vorbis_floor *floors;
+ uint_fast8_t residue_count;
+ vorbis_residue *residues;
+ uint_fast8_t mapping_count;
+ vorbis_mapping *mappings;
+ uint_fast8_t mode_count;
+ vorbis_mode *modes;
+ uint_fast8_t mode_number; // mode number for the current packet
+ float *channel_residues;
+ float *channel_floors;
+ float *saved;
+ uint_fast16_t saved_start;
+ float *ret;
+ float *buf;
+ float *buf_tmp;
+ uint_fast32_t add_bias; // for float->int conversion
+ uint_fast32_t exp_bias;
+} vorbis_context;
+
+/* Helper functions */
+
+#define BARK(x) \
+ (13.1f*atan(0.00074f*(x))+2.24f*atan(1.85e-8f*(x)*(x))+1e-4f*(x))
+
+unsigned int ff_vorbis_nth_root(unsigned int x, unsigned int n) { // x^(1/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);
+}
+
+static float vorbisfloat2float(uint_fast32_t val) {
+ double mant=val&0x1fffff;
+ long exp=(val&0x7fe00000L)>>21;
+ if (val&0x80000000) mant=-mant;
+ return(ldexp(mant, exp-20-768));
+}
+
+
+// Generate vlc codes from vorbis huffman code lengths
+
+int ff_vorbis_len2vlc(uint8_t *bits, uint32_t *codes, uint_fast32_t num) {
+ uint_fast32_t exit_at_level[33]={404,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+ uint_fast8_t i,j;
+ uint_fast32_t code,p;
+
+#ifdef V_DEBUG
+ GetBitContext gb;
+#endif
+
+ for(p=0;(bits[p]==0) && (p<num);++p);
+ if (p==num) {
+// av_log(vc->avccontext, AV_LOG_INFO, "An empty codebook. Heh?! \n");
+ return 0;
+ }
+
+ codes[p]=0;
+ for(i=0;i<bits[p];++i) {
+ exit_at_level[i+1]=1<<i;
+ }
+
+#ifdef V_DEBUG
+ av_log(NULL, AV_LOG_INFO, " %d. of %d code len %d code %d - ", p, num, bits[p], codes[p]);
+ init_get_bits(&gb, (uint_fast8_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]==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) return 1; // overspecified tree
+ 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 V_DEBUG
+ av_log(NULL, AV_LOG_INFO, " %d. code len %d code %d - ", p, bits[p], codes[p]);
+ init_get_bits(&gb, (uint_fast8_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;
+}
+
+void ff_vorbis_ready_floor1_list(floor1_entry_t * 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[list[i].sort].x > list[list[j].sort].x) {
+ int tmp = list[i].sort;
+ list[i].sort = list[j].sort;
+ list[j].sort = tmp;
+ }
+ }
+ }
+}
+
+// Free all allocated memory -----------------------------------------
+
+static void vorbis_free(vorbis_context *vc) {
+ int_fast16_t i;
+
+ av_freep(&vc->channel_residues);
+ av_freep(&vc->channel_floors);
+ av_freep(&vc->saved);
+ av_freep(&vc->ret);
+ av_freep(&vc->buf);
+ av_freep(&vc->buf_tmp);
+
+ av_freep(&vc->residues);
+ av_freep(&vc->modes);
+
+ ff_mdct_end(&vc->mdct[0]);
+ ff_mdct_end(&vc->mdct[1]);
+
+ for(i=0;i<vc->codebook_count;++i) {
+ av_free(vc->codebooks[i].codevectors);
+ free_vlc(&vc->codebooks[i].vlc);
+ }
+ av_freep(&vc->codebooks);
+
+ 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);
+
+ 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);
+
+ if(vc->exp_bias){
+ av_freep(&vc->win[0]);
+ av_freep(&vc->win[1]);
+ }
+}
+
+// Parse setup header -------------------------------------------------
+
+// Process codebooks part
+
+static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) {
+ uint_fast16_t cb;
+ uint8_t *tmp_vlc_bits;
+ uint32_t *tmp_vlc_codes;
+ GetBitContext *gb=&vc->gb;
+
+ vc->codebook_count=get_bits(gb,8)+1;
+
+ AV_DEBUG(" Codebooks: %d \n", vc->codebook_count);
+
+ vc->codebooks=(vorbis_codebook *)av_mallocz(vc->codebook_count * sizeof(vorbis_codebook));
+ tmp_vlc_bits=(uint8_t *)av_mallocz(V_MAX_VLCS * sizeof(uint8_t));
+ tmp_vlc_codes=(uint32_t *)av_mallocz(V_MAX_VLCS * sizeof(uint32_t));
+
+ for(cb=0;cb<vc->codebook_count;++cb) {
+ vorbis_codebook *codebook_setup=&vc->codebooks[cb];
+ uint_fast8_t ordered;
+ uint_fast32_t t, used_entries=0;
+ uint_fast32_t entries;
+
+ AV_DEBUG(" %d. Codebook \n", cb);
+
+ if (get_bits(gb, 24)!=0x564342) {
+ av_log(vc->avccontext, AV_LOG_ERROR, " %"PRIdFAST16". Codebook setup data corrupt. \n", cb);
+ goto error;
+ }
+
+ codebook_setup->dimensions=get_bits(gb, 16);
+ if (codebook_setup->dimensions>16) {
+ av_log(vc->avccontext, AV_LOG_ERROR, " %"PRIdFAST16". Codebook's dimension is too large (%d). \n", cb, codebook_setup->dimensions);
+ goto error;
+ }
+ entries=get_bits(gb, 24);
+ if (entries>V_MAX_VLCS) {
+ av_log(vc->avccontext, AV_LOG_ERROR, " %"PRIdFAST16". Codebook has too many entries (%"PRIdFAST32"). \n", cb, entries);
+ goto error;
+ }
+
+ ordered=get_bits1(gb);
+
+ AV_DEBUG(" codebook_dimensions %d, codebook_entries %d \n", codebook_setup->dimensions, entries);
+
+ if (!ordered) {
+ uint_fast16_t ce;
+ uint_fast8_t flag;
+ uint_fast8_t sparse=get_bits1(gb);
+
+ AV_DEBUG(" not ordered \n");
+
+ if (sparse) {
+ AV_DEBUG(" 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_DEBUG(" not sparse \n");
+
+ used_entries=entries;
+ for(ce=0;ce<entries;++ce) {
+ tmp_vlc_bits[ce]=get_bits(gb, 5)+1;
+ }
+ }
+ } else {
+ uint_fast16_t current_entry=0;
+ uint_fast8_t current_length=get_bits(gb, 5)+1;
+
+ AV_DEBUG(" ordered, current length: %d \n", current_length); //FIXME
+
+ used_entries=entries;
+ for(;current_entry<used_entries;++current_length) {
+ uint_fast16_t i, number;
+
+ AV_DEBUG(" number bits: %d ", ilog(entries - current_entry));
+
+ number=get_bits(gb, ilog(entries - current_entry));
+
+ AV_DEBUG(" number: %d \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->avccontext, AV_LOG_ERROR, " More codelengths than codes in codebook. \n");
+ goto error;
+ }
+ }
+
+ codebook_setup->lookup_type=get_bits(gb, 4);
+
+ AV_DEBUG(" 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) {
+ uint_fast16_t i, j, k;
+ uint_fast16_t codebook_lookup_values=ff_vorbis_nth_root(entries, codebook_setup->dimensions);
+ uint_fast16_t codebook_multiplicands[codebook_lookup_values];
+
+ float codebook_minimum_value=vorbisfloat2float(get_bits_long(gb, 32));
+ float codebook_delta_value=vorbisfloat2float(get_bits_long(gb, 32));
+ uint_fast8_t codebook_value_bits=get_bits(gb, 4)+1;
+ uint_fast8_t codebook_sequence_p=get_bits1(gb);
+
+ AV_DEBUG(" We expect %d numbers for building the codevectors. \n", codebook_lookup_values);
+ AV_DEBUG(" 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_DEBUG(" multiplicands*delta+minmum : %e \n", (float)codebook_multiplicands[i]*codebook_delta_value+codebook_minimum_value);
+ AV_DEBUG(" multiplicand %d \n", codebook_multiplicands[i]);
+ }
+
+// Weed out unused vlcs and build codevector vector
+ codebook_setup->codevectors=(float *)av_mallocz(used_entries*codebook_setup->dimensions * sizeof(float));
+ for(j=0, i=0;i<entries;++i) {
+ uint_fast8_t dim=codebook_setup->dimensions;
+
+ if (tmp_vlc_bits[i]) {
+ float last=0.0;
+ uint_fast32_t lookup_offset=i;
+
+#ifdef V_DEBUG
+ av_log(vc->avccontext, AV_LOG_INFO, "Lookup offset %d ,", i);
+#endif
+
+ for(k=0;k<dim;++k) {
+ uint_fast32_t 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];
+
+#ifdef V_DEBUG
+ av_log(vc->avccontext, AV_LOG_INFO, "real lookup offset %d, vector: ", j);
+ for(k=0;k<dim;++k) {
+ av_log(vc->avccontext, AV_LOG_INFO, " %f ", codebook_setup->codevectors[j*dim+k]);
+ }
+ av_log(vc->avccontext, AV_LOG_INFO, "\n");
+#endif
+
+ ++j;
+ }
+ }
+ if (j!=used_entries) {
+ av_log(vc->avccontext, AV_LOG_ERROR, "Bug in codevector vector building code. \n");
+ goto error;
+ }
+ entries=used_entries;
+ }
+ else if (codebook_setup->lookup_type>=2) {
+ av_log(vc->avccontext, AV_LOG_ERROR, "Codebook lookup type not supported. \n");
+ goto error;
+ }
+
+// Initialize VLC table
+ if (ff_vorbis_len2vlc(tmp_vlc_bits, tmp_vlc_codes, entries)) {
+ av_log(vc->avccontext, AV_LOG_ERROR, " Invalid code lengths while generating vlcs. \n");
+ 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 (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->avccontext, AV_LOG_ERROR, " Error generating vlc tables. \n");
+ goto error;
+ }
+ }
+
+ av_free(tmp_vlc_bits);
+ av_free(tmp_vlc_codes);
+ return 0;
+
+// Error:
+error:
+ av_free(tmp_vlc_bits);
+ av_free(tmp_vlc_codes);
+ return 1;
+}
+
+// Process time domain transforms part (unused in Vorbis I)
+
+static int vorbis_parse_setup_hdr_tdtransforms(vorbis_context *vc) {
+ GetBitContext *gb=&vc->gb;
+ uint_fast8_t i;
+ uint_fast8_t vorbis_time_count=get_bits(gb, 6)+1;
+
+ for(i=0;i<vorbis_time_count;++i) {
+ uint_fast16_t vorbis_tdtransform=get_bits(gb, 16);
+
+ AV_DEBUG(" Vorbis time domain transform %d: %d \n", vorbis_time_count, vorbis_tdtransform);
+
+ if (vorbis_tdtransform) {
+ av_log(vc->avccontext, AV_LOG_ERROR, "Vorbis time domain transform data nonzero. \n");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+// Process floors part
+
+static uint_fast8_t vorbis_floor0_decode(vorbis_context *vc,
+ vorbis_floor_data *vfu, float *vec);
+static void create_map( vorbis_context * vc, uint_fast8_t floor_number );
+static uint_fast8_t 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;
+ uint_fast16_t i,j,k;
+
+ vc->floor_count=get_bits(gb, 6)+1;
+
+ vc->floors=(vorbis_floor *)av_mallocz(vc->floor_count * sizeof(vorbis_floor));
+
+ for (i=0;i<vc->floor_count;++i) {
+ vorbis_floor *floor_setup=&vc->floors[i];
+
+ floor_setup->floor_type=get_bits(gb, 16);
+
+ AV_DEBUG(" %d. floor type %d \n", i, floor_setup->floor_type);
+
+ if (floor_setup->floor_type==1) {
+ uint_fast8_t maximum_class=0;
+ uint_fast8_t rangebits;
+ uint_fast16_t floor1_values=2;
+
+ floor_setup->decode=vorbis_floor1_decode;
+
+ floor_setup->data.t1.partitions=get_bits(gb, 5);
+
+ AV_DEBUG(" %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_DEBUG(" %d. floor %d partition class %d \n", i, j, floor_setup->data.t1.partition_class[j]);
+
+ }
+
+ AV_DEBUG(" maximum class %d \n", maximum_class);
+
+ floor_setup->data.t1.maximum_class=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_DEBUG(" %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]) {
+ floor_setup->data.t1.class_masterbook[j]=get_bits(gb, 8);
+
+ AV_DEBUG(" masterbook: %d \n", floor_setup->data.t1.class_masterbook[j]);
+ }
+
+ for(k=0;k<(1<<floor_setup->data.t1.class_subclasses[j]);++k) {
+ floor_setup->data.t1.subclass_books[j][k]=(int16_t)get_bits(gb, 8)-1;
+
+ AV_DEBUG(" 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=(floor1_entry_t *)av_mallocz(floor_setup->data.t1.x_list_dim * sizeof(floor1_entry_t));
+
+
+ rangebits=get_bits(gb, 4);
+ floor_setup->data.t1.list[0].x = 0;
+ floor_setup->data.t1.list[1].x = (1<<rangebits);
+
+ 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_DEBUG(" %d. floor1 Y coord. %d \n", floor1_values, floor_setup->data.t1.list[floor1_values].x);
+ }
+ }
+
+// Precalculate order of x coordinates - needed for decode
+ ff_vorbis_ready_floor1_list(floor_setup->data.t1.list, floor_setup->data.t1.x_list_dim);
+ }
+ else if(floor_setup->floor_type==0) {
+ uint_fast8_t max_codebook_dim=0;
+
+ floor_setup->decode=vorbis_floor0_decode;
+
+ floor_setup->data.t0.order=get_bits(gb, 8);
+ floor_setup->data.t0.rate=get_bits(gb, 16);
+ floor_setup->data.t0.bark_map_size=get_bits(gb, 16);
+ floor_setup->data.t0.amplitude_bits=get_bits(gb, 6);
+ /* zero would result in a div by zero later *
+ * 2^0 - 1 == 0 */
+ if (floor_setup->data.t0.amplitude_bits == 0) {
+ av_log(vc->avccontext, AV_LOG_ERROR,
+ "Floor 0 amplitude bits is 0.\n");
+ return 1;
+ }
+ 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 1; }
+ /* read book indexes */
+ {
+ int idx;
+ uint_fast8_t book_idx;
+ for (idx=0;idx<floor_setup->data.t0.num_books;++idx) {
+ book_idx=get_bits(gb, 8);
+ 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 (floor_setup->data.t0.book_list[idx]>vc->codebook_count)
+ return 1;
+ }
+ }
+
+ create_map( vc, i );
+
+ /* allocate mem for lsp coefficients */
+ {
+ /* 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(float));
+ if(!floor_setup->data.t0.lsp) { return 1; }
+ }
+
+#ifdef V_DEBUG /* debug output parsed headers */
+ AV_DEBUG("floor0 order: %u\n", floor_setup->data.t0.order);
+ AV_DEBUG("floor0 rate: %u\n", floor_setup->data.t0.rate);
+ AV_DEBUG("floor0 bark map size: %u\n",
+ floor_setup->data.t0.bark_map_size);
+ AV_DEBUG("floor0 amplitude bits: %u\n",
+ floor_setup->data.t0.amplitude_bits);
+ AV_DEBUG("floor0 amplitude offset: %u\n",
+ floor_setup->data.t0.amplitude_offset);
+ AV_DEBUG("floor0 number of books: %u\n",
+ floor_setup->data.t0.num_books);
+ AV_DEBUG("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_DEBUG( " Book %d: %u\n",
+ idx+1,
+ floor_setup->data.t0.book_list[idx] );
+ }
+ }
+#endif
+ }
+ else {
+ av_log(vc->avccontext, AV_LOG_ERROR, "Invalid floor type!\n");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+// Process residues part
+
+static int vorbis_parse_setup_hdr_residues(vorbis_context *vc){
+ GetBitContext *gb=&vc->gb;
+ uint_fast8_t i, j, k;
+
+ vc->residue_count=get_bits(gb, 6)+1;
+ vc->residues=(vorbis_residue *)av_mallocz(vc->residue_count * sizeof(vorbis_residue));
+
+ AV_DEBUG(" There are %d residues. \n", vc->residue_count);
+
+ for(i=0;i<vc->residue_count;++i) {
+ vorbis_residue *res_setup=&vc->residues[i];
+ uint_fast8_t cascade[64];
+ uint_fast8_t high_bits;
+ uint_fast8_t low_bits;
+
+ res_setup->type=get_bits(gb, 16);
+
+ AV_DEBUG(" %d. 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;
+ res_setup->classifications=get_bits(gb, 6)+1;
+ res_setup->classbook=get_bits(gb, 8);
+
+ AV_DEBUG(" 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_DEBUG(" %d class casscade 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)) {
+ res_setup->books[j][k]=get_bits(gb, 8);
+
+ AV_DEBUG(" %d class casscade depth %d 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;
+ uint_fast8_t i, j;
+
+ vc->mapping_count=get_bits(gb, 6)+1;
+ vc->mappings=(vorbis_mapping *)av_mallocz(vc->mapping_count * sizeof(vorbis_mapping));
+
+ AV_DEBUG(" 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->avccontext, AV_LOG_ERROR, "Other mappings than type 0 are not compliant with the Vorbis I specification. \n");
+ return 1;
+ }
+ 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=(uint_fast8_t *)av_mallocz(mapping_setup->coupling_steps * sizeof(uint_fast8_t));
+ mapping_setup->angle=(uint_fast8_t *)av_mallocz(mapping_setup->coupling_steps * sizeof(uint_fast8_t));
+ for(j=0;j<mapping_setup->coupling_steps;++j) {
+ mapping_setup->magnitude[j]=get_bits(gb, ilog(vc->audio_channels-1));
+ mapping_setup->angle[j]=get_bits(gb, ilog(vc->audio_channels-1));
+ // FIXME: sanity checks
+ }
+ } else {
+ mapping_setup->coupling_steps=0;
+ }
+
+ AV_DEBUG(" %d mapping coupling steps: %d \n", i, mapping_setup->coupling_steps);
+
+ if(get_bits(gb, 2)) {
+ av_log(vc->avccontext, AV_LOG_ERROR, "%d. mapping setup data invalid. \n", i);
+ return 1; // following spec.
+ }
+
+ if (mapping_setup->submaps>1) {
+ mapping_setup->mux=(uint_fast8_t *)av_mallocz(vc->audio_channels * sizeof(uint_fast8_t));
+ for(j=0;j<vc->audio_channels;++j) {
+ mapping_setup->mux[j]=get_bits(gb, 4);
+ }
+ }
+
+ for(j=0;j<mapping_setup->submaps;++j) {
+ get_bits(gb, 8); // FIXME check?
+ mapping_setup->submap_floor[j]=get_bits(gb, 8);
+ mapping_setup->submap_residue[j]=get_bits(gb, 8);
+
+ AV_DEBUG(" %d mapping %d submap : floor %d, residue %d \n", i, j, mapping_setup->submap_floor[j], mapping_setup->submap_residue[j]);
+ }
+ }
+ return 0;
+}
+
+// Process modes part
+
+static void create_map( vorbis_context * vc, uint_fast8_t floor_number )
+{
+ vorbis_floor * floors=vc->floors;
+ vorbis_floor0 * vf;
+ int idx;
+ int_fast8_t blockflag;
+ int_fast32_t * map;
+ int_fast32_t n; //TODO: could theoretically be smaller?
+
+ for (blockflag=0;blockflag<2;++blockflag)
+ {
+ n=vc->blocksize[blockflag]/2;
+ floors[floor_number].data.t0.map[blockflag]=
+ av_malloc((n+1) * sizeof(int_fast32_t)); // n+sentinel
+
+ 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;
+ }
+
+# ifdef V_DEBUG
+ for(idx=0;idx<=n;++idx) {
+ AV_DEBUG("floor0 map: map at pos %d is %d\n",
+ idx, map[idx]);
+ }
+# endif
+}
+
+static int vorbis_parse_setup_hdr_modes(vorbis_context *vc) {
+ GetBitContext *gb=&vc->gb;
+ uint_fast8_t i;
+
+ vc->mode_count=get_bits(gb, 6)+1;
+ vc->modes=(vorbis_mode *)av_mallocz(vc->mode_count * sizeof(vorbis_mode));
+
+ AV_DEBUG(" 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_bits(gb, 1);
+ mode_setup->windowtype=get_bits(gb, 16); //FIXME check
+ mode_setup->transformtype=get_bits(gb, 16); //FIXME check
+ mode_setup->mapping=get_bits(gb, 8); //FIXME check
+
+ AV_DEBUG(" %d 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;
+
+ 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->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (no vorbis signature). \n");
+ return 1;
+ }
+
+ if (vorbis_parse_setup_hdr_codebooks(vc)) {
+ av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (codebooks). \n");
+ return 2;
+ }
+ if (vorbis_parse_setup_hdr_tdtransforms(vc)) {
+ av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (time domain transforms). \n");
+ return 3;
+ }
+ if (vorbis_parse_setup_hdr_floors(vc)) {
+ av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (floors). \n");
+ return 4;
+ }
+ if (vorbis_parse_setup_hdr_residues(vc)) {
+ av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (residues). \n");
+ return 5;
+ }
+ if (vorbis_parse_setup_hdr_mappings(vc)) {
+ av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (mappings). \n");
+ return 6;
+ }
+ if (vorbis_parse_setup_hdr_modes(vc)) {
+ av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (modes). \n");
+ return 7;
+ }
+ if (!get_bits1(gb)) {
+ av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (framing flag). \n");
+ return 8; // framing flag bit unset error
+ }
+
+ return 0;
+}
+
+// Process the identification header
+
+static int vorbis_parse_id_hdr(vorbis_context *vc){
+ GetBitContext *gb=&vc->gb;
+ uint_fast8_t 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->avccontext, AV_LOG_ERROR, " Vorbis id header packet corrupt (no vorbis signature). \n");
+ return 1;
+ }
+
+ vc->version=get_bits_long(gb, 32); //FIXME check 0
+ vc->audio_channels=get_bits(gb, 8); //FIXME check >0
+ vc->audio_samplerate=get_bits_long(gb, 32); //FIXME check >0
+ 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);
+ vc->blocksize[0]=(1<<bl0);
+ vc->blocksize[1]=(1<<bl1);
+ if (bl0>13 || bl0<6 || bl1>13 || bl1<6 || bl1<bl0) {
+ av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis id header packet corrupt (illegal blocksize). \n");
+ return 3;
+ }
+ // output format int16
+ if (vc->blocksize[1]/2 * vc->audio_channels * 2 >
+ AVCODEC_MAX_AUDIO_FRAME_SIZE) {
+ av_log(vc->avccontext, AV_LOG_ERROR, "Vorbis channel count makes "
+ "output packets too large.\n");
+ return 4;
+ }
+ vc->win[0]=ff_vorbis_vwin[bl0-6];
+ vc->win[1]=ff_vorbis_vwin[bl1-6];
+
+ if(vc->exp_bias){
+ int i, j;
+ for(j=0; j<2; j++){
+ float *win = av_malloc(vc->blocksize[j]/2 * sizeof(float));
+ for(i=0; i<vc->blocksize[j]/2; i++)
+ win[i] = vc->win[j][i] * (1<<15);
+ vc->win[j] = win;
+ }
+ }
+
+ if ((get_bits1(gb)) == 0) {
+ av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis id header packet corrupt (framing flag not set). \n");
+ return 2;
+ }
+
+ vc->channel_residues=(float *)av_malloc((vc->blocksize[1]/2)*vc->audio_channels * sizeof(float));
+ vc->channel_floors=(float *)av_malloc((vc->blocksize[1]/2)*vc->audio_channels * sizeof(float));
+ vc->saved=(float *)av_malloc((vc->blocksize[1]/2)*vc->audio_channels * sizeof(float));
+ vc->ret=(float *)av_malloc((vc->blocksize[1]/2)*vc->audio_channels * sizeof(float));
+ vc->buf=(float *)av_malloc(vc->blocksize[1] * sizeof(float));
+ vc->buf_tmp=(float *)av_malloc(vc->blocksize[1] * sizeof(float));
+ vc->saved_start=0;
+
+ ff_mdct_init(&vc->mdct[0], bl0, 1);
+ ff_mdct_init(&vc->mdct[1], bl1, 1);
+
+ AV_DEBUG(" 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 int vorbis_decode_init(AVCodecContext *avccontext) {
+ vorbis_context *vc = avccontext->priv_data ;
+ uint8_t *headers = avccontext->extradata;
+ int headers_len=avccontext->extradata_size;
+ uint8_t *header_start[3];
+ int header_len[3];
+ GetBitContext *gb = &(vc->gb);
+ int i, j, hdr_type;
+
+ vc->avccontext = avccontext;
+ dsputil_init(&vc->dsp, avccontext);
+
+ if(vc->dsp.float_to_int16 == ff_float_to_int16_c) {
+ vc->add_bias = 385;
+ vc->exp_bias = 0;
+ } else {
+ vc->add_bias = 0;
+ vc->exp_bias = 15<<23;
+ }
+
+ if (!headers_len) {
+ av_log(avccontext, AV_LOG_ERROR, "Extradata corrupt.\n");
+ return -1;
+ }
+
+ if(headers[0] == 0 && headers[1] == 30) {
+ for(i = 0; i < 3; i++){
+ header_len[i] = *headers++ << 8;
+ header_len[i] += *headers++;
+ header_start[i] = headers;
+ headers += header_len[i];
+ }
+ } else if(headers[0] == 2) {
+ for(j=1,i=0;i<2;++i, ++j) {
+ header_len[i]=0;
+ while(j<headers_len && headers[j]==0xff) {
+ header_len[i]+=0xff;
+ ++j;
+ }
+ if (j>=headers_len) {
+ av_log(avccontext, AV_LOG_ERROR, "Extradata corrupt.\n");
+ return -1;
+ }
+ header_len[i]+=headers[j];
+ }
+ header_len[2]=headers_len-header_len[0]-header_len[1]-j;
+ headers+=j;
+ header_start[0] = headers;
+ header_start[1] = header_start[0] + header_len[0];
+ header_start[2] = header_start[1] + header_len[1];
+ } else {
+ av_log(avccontext, AV_LOG_ERROR, "Extradata corrupt.\n");
+ return -1;
+ }
+
+ init_get_bits(gb, header_start[0], header_len[0]*8);
+ hdr_type=get_bits(gb, 8);
+ if (hdr_type!=1) {
+ av_log(avccontext, AV_LOG_ERROR, "First header is not the id header.\n");
+ return -1;
+ }
+ if (vorbis_parse_id_hdr(vc)) {
+ av_log(avccontext, AV_LOG_ERROR, "Id header corrupt.\n");
+ vorbis_free(vc);
+ return -1;
+ }
+
+ init_get_bits(gb, header_start[2], header_len[2]*8);
+ hdr_type=get_bits(gb, 8);
+ if (hdr_type!=5) {
+ av_log(avccontext, AV_LOG_ERROR, "Third header is not the setup header.\n");
+ return -1;
+ }
+ if (vorbis_parse_setup_hdr(vc)) {
+ av_log(avccontext, AV_LOG_ERROR, "Setup header corrupt.\n");
+ vorbis_free(vc);
+ return -1;
+ }
+
+ avccontext->channels = vc->audio_channels;
+ avccontext->sample_rate = vc->audio_samplerate;
+
+ return 0 ;
+}
+
+// Decode audiopackets -------------------------------------------------
+
+// Read and decode floor
+
+static uint_fast8_t vorbis_floor0_decode(vorbis_context *vc,
+ vorbis_floor_data *vfu, float *vec) {
+ vorbis_floor0 * vf=&vfu->t0;
+ float * lsp=vf->lsp;
+ uint_fast32_t amplitude;
+ uint_fast32_t book_idx;
+ uint_fast8_t blockflag=vc->modes[vc->mode_number].blockflag;
+
+ amplitude=get_bits(&vc->gb, vf->amplitude_bits);
+ if (amplitude>0) {
+ float last = 0;
+ uint_fast16_t lsp_len = 0;
+ uint_fast16_t idx;
+ vorbis_codebook codebook;
+
+ book_idx=get_bits(&vc->gb, ilog(vf->num_books));
+ if ( book_idx >= vf->num_books ) {
+ av_log( vc->avccontext, AV_LOG_ERROR,
+ "floor0 dec: booknumber too high!\n" );
+ //FIXME: look above
+ }
+ AV_DEBUG( "floor0 dec: booknumber: %u\n", book_idx );
+ codebook=vc->codebooks[vf->book_list[book_idx]];
+
+ while (lsp_len<vf->order) {
+ int vec_off;
+
+ AV_DEBUG( "floor0 dec: book dimension: %d\n", codebook.dimensions );
+ AV_DEBUG( "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_DEBUG( "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;
+ }
+#ifdef V_DEBUG
+ /* DEBUG: output lsp coeffs */
+ {
+ int idx;
+ for ( idx = 0; idx < lsp_len; ++idx )
+ AV_DEBUG("floor0 dec: coeff at %d is %f\n", idx, lsp[idx] );
+ }
+#endif
+
+ /* 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_DEBUG("floor0 synth: map_size=%d; m=%d; wstep=%f\n",
+ vf->map_size, 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<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_DEBUG(" Floor0 decoded\n");
+
+ return 0;
+}
+
+static void render_line(int x0, int y0, int x1, int y1, float * buf, int n) {
+ int dy = y1 - y0;
+ int adx = x1 - x0;
+ int ady = FFABS(dy);
+ int base = dy / adx;
+ int x = x0;
+ int y = y0;
+ int err = 0;
+ int sy;
+ if (dy < 0) sy = base - 1;
+ else sy = base + 1;
+ ady = ady - FFABS(base) * adx;
+ if (x >= n) return;
+ buf[x] = ff_vorbis_floor1_inverse_db_table[y];
+ for (x = x0 + 1; x < x1; x++) {
+ if (x >= n) return;
+ err += ady;
+ if (err >= adx) {
+ err -= adx;
+ y += sy;
+ } else {
+ y += base;
+ }
+ buf[x] = ff_vorbis_floor1_inverse_db_table[y];
+ }
+}
+
+void ff_vorbis_floor1_render_list(floor1_entry_t * list, int values, uint_fast16_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]) {
+ render_line(lx, ly, list[pos].x, y_list[pos] * multiplier, out, samples);
+ lx = list[pos].x;
+ ly = y_list[pos] * multiplier;
+ }
+ if (lx >= samples) break;
+ }
+ if (lx < samples) render_line(lx, ly, samples, ly, out, samples);
+}
+
+static uint_fast8_t vorbis_floor1_decode(vorbis_context *vc, vorbis_floor_data *vfu, float *vec) {
+ vorbis_floor1 * vf=&vfu->t1;
+ GetBitContext *gb=&vc->gb;
+ uint_fast16_t range_v[4]={ 256, 128, 86, 64 };
+ uint_fast16_t range=range_v[vf->multiplier-1];
+ uint_fast16_t floor1_Y[vf->x_list_dim];
+ uint_fast16_t floor1_Y_final[vf->x_list_dim];
+ int floor1_flag[vf->x_list_dim];
+ uint_fast8_t class_;
+ uint_fast8_t cdim;
+ uint_fast8_t cbits;
+ uint_fast8_t csub;
+ uint_fast8_t cval;
+ int_fast16_t book;
+ uint_fast16_t offset;
+ uint_fast16_t i,j;
+ /*u*/int_fast16_t adx, ady, off, predicted; // WTF ? dy/adx= (unsigned)dy/adx ?
+ int_fast16_t dy, err;
+
+
+ if (!get_bits1(gb)) return 1; // silence
+
+// 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_DEBUG("floor 0 Y %d floor 1 Y %d \n", floor1_Y[0], floor1_Y[1]);
+
+ offset=2;
+ for(i=0;i<vf->partitions;++i) {
+ class_=vf->partition_class[i];
+ cdim=vf->class_dimensions[class_];
+ cbits=vf->class_subclasses[class_];
+ csub=(1<<cbits)-1;
+ cval=0;
+
+ AV_DEBUG("Cbits %d \n", cbits);
+
+ if (cbits) { // this reads all subclasses for this partition's class
+ cval=get_vlc2(gb, vc->codebooks[vf->class_masterbook[class_]].vlc.table,
+ vc->codebooks[vf->class_masterbook[class_]].nb_bits, 3);
+ }
+
+ for(j=0;j<cdim;++j) {
+ book=vf->subclass_books[class_][cval & csub];
+
+ AV_DEBUG("book %d Cbits %d cval %d 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_DEBUG(" 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) {
+ uint_fast16_t val, highroom, lowroom, room;
+ uint_fast16_t high_neigh_offs;
+ uint_fast16_t 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=(int16_t)err/(int16_t)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 mispelling
+ }
+ 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]=val-lowroom+predicted;
+ } else {
+ floor1_Y_final[i]=predicted-val+highroom-1;
+ }
+ } else {
+ if (val & 1) {
+ floor1_Y_final[i]=predicted-(val+1)/2;
+ } else {
+ floor1_Y_final[i]=predicted+val/2;
+ }
+ }
+ } else {
+ floor1_flag[i]=0;
+ floor1_Y_final[i]=predicted;
+ }
+
+ AV_DEBUG(" Decoded floor(%d) = %d / val %d \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_DEBUG(" Floor decoded\n");
+
+ return 0;
+}
+
+// Read and decode residue
+
+static int vorbis_residue_decode(vorbis_context *vc, vorbis_residue *vr, uint_fast8_t ch, uint_fast8_t *do_not_decode, float *vec, uint_fast16_t vlen) {
+ GetBitContext *gb=&vc->gb;
+ uint_fast8_t c_p_c=vc->codebooks[vr->classbook].dimensions;
+ uint_fast16_t n_to_read=vr->end-vr->begin;
+ uint_fast16_t ptns_to_read=n_to_read/vr->partition_size;
+ uint_fast8_t classifs[ptns_to_read*vc->audio_channels];
+ uint_fast8_t pass;
+ uint_fast8_t ch_used;
+ uint_fast8_t i,j,l;
+ uint_fast16_t k;
+
+ 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;
+ } else {
+ ch_used=ch;
+ }
+
+ AV_DEBUG(" 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?
+ uint_fast16_t voffset;
+ uint_fast16_t partition_count;
+ uint_fast16_t j_times_ptns_to_read;
+
+ voffset=vr->begin;
+ for(partition_count=0;partition_count<ptns_to_read;) { // SPEC error
+ if (!pass) {
+ uint_fast32_t inverse_class = ff_inverse[vr->classifications];
+ for(j_times_ptns_to_read=0, j=0;j<ch_used;++j) {
+ if (!do_not_decode[j]) {
+ uint_fast32_t temp=get_vlc2(gb, vc->codebooks[vr->classbook].vlc.table,
+ vc->codebooks[vr->classbook].nb_bits, 3);
+
+ AV_DEBUG("Classword: %d \n", temp);
+
+ assert(vr->classifications > 1 && temp<=65536); //needed for inverse[]
+ for(i=0;i<c_p_c;++i) {
+ uint_fast32_t temp2;
+
+ temp2=(((uint_fast64_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) {
+ uint_fast16_t voffs;
+
+ if (!do_not_decode[j]) {
+ uint_fast8_t vqclass=classifs[j_times_ptns_to_read+partition_count];
+ int_fast16_t vqbook=vr->books[vqclass][pass];
+
+ if (vqbook>=0) {
+ uint_fast16_t coffs;
+ unsigned dim= vc->codebooks[vqbook].dimensions; // not uint_fast8_t: 64bit is slower here on amd64
+ uint_fast16_t step= dim==1 ? vr->partition_size
+ : FASTDIV(vr->partition_size, dim);
+ 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]; // FPMATH
+ }
+ }
+ }
+ 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]; // FPMATH
+
+ AV_DEBUG(" 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 ]; // FPMATH
+ vec[voffs+k+vlen]+=codebook.codevectors[coffs+1]; // FPMATH
+ }
+ } 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 ]; // FPMATH
+ vec[voffs+vlen]+=codebook.codevectors[coffs+l+1]; // FPMATH
+
+ AV_DEBUG(" 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) {
+ voffs=voffset;
+
+ 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/ch+(voffs%ch)*vlen]+=codebook.codevectors[coffs+l]; // FPMATH FIXME use if and counter instead of / and %
+
+ AV_DEBUG(" 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 {
+ av_log(vc->avccontext, AV_LOG_ERROR, " Invalid residue type while residue decode?! \n");
+ return 1;
+ }
+ }
+ }
+ j_times_ptns_to_read+=ptns_to_read;
+ }
+ ++partition_count;
+ voffset+=vr->partition_size;
+ }
+ }
+ }
+ return 0;
+}
+
+void vorbis_inverse_coupling(float *mag, float *ang, int 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) {
+ GetBitContext *gb=&vc->gb;
+
+ uint_fast8_t previous_window=0,next_window=0;
+ uint_fast8_t mode_number;
+ uint_fast16_t blocksize;
+ int_fast32_t i,j;
+ uint_fast8_t no_residue[vc->audio_channels];
+ uint_fast8_t do_not_decode[vc->audio_channels];
+ vorbis_mapping *mapping;
+ float *ch_res_ptr=vc->channel_residues;
+ float *ch_floor_ptr=vc->channel_floors;
+ uint_fast8_t res_chan[vc->audio_channels];
+ uint_fast8_t res_num=0;
+ int_fast16_t retlen=0;
+ uint_fast16_t saved_start=0;
+ float fadd_bias = vc->add_bias;
+
+ if (get_bits1(gb)) {
+ av_log(vc->avccontext, AV_LOG_ERROR, "Not a Vorbis I audio packet.\n");
+ return -1; // packet type not audio
+ }
+
+ if (vc->mode_count==1) {
+ mode_number=0;
+ } else {
+ mode_number=get_bits(gb, ilog(vc->mode_count-1));
+ }
+ vc->mode_number=mode_number;
+ mapping=&vc->mappings[vc->modes[mode_number].mapping];
+
+ AV_DEBUG(" Mode number: %d , mapping: %d , blocktype %d \n", mode_number, vc->modes[mode_number].mapping, vc->modes[mode_number].blockflag);
+
+ if (vc->modes[mode_number].blockflag) {
+ previous_window=get_bits1(gb);
+ next_window=get_bits1(gb);
+ }
+
+ blocksize=vc->blocksize[vc->modes[mode_number].blockflag];
+ memset(ch_res_ptr, 0, sizeof(float)*vc->audio_channels*blocksize/2); //FIXME can this be removed ?
+ memset(ch_floor_ptr, 0, sizeof(float)*vc->audio_channels*blocksize/2); //FIXME can this be removed ?
+
+// Decode floor
+
+ for(i=0;i<vc->audio_channels;++i) {
+ vorbis_floor *floor;
+ if (mapping->submaps>1) {
+ floor=&vc->floors[mapping->submap_floor[mapping->mux[i]]];
+ } else {
+ floor=&vc->floors[mapping->submap_floor[0]];
+ }
+
+ no_residue[i]=floor->decode(vc, &floor->data, ch_floor_ptr);
+ ch_floor_ptr+=blocksize/2;
+ }
+
+// 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;
+ uint_fast8_t ch=0;
+
+ 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]];
+ vorbis_residue_decode(vc, residue, ch, do_not_decode, ch_res_ptr, blocksize/2);
+
+ ch_res_ptr+=ch*blocksize/2;
+ }
+
+// 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
+
+ for(j=0, ch_floor_ptr=vc->channel_floors;j<vc->audio_channels;++j,ch_floor_ptr+=blocksize/2) {
+ ch_res_ptr=vc->channel_residues+res_chan[j]*blocksize/2;
+ vc->dsp.vector_fmul(ch_floor_ptr, ch_res_ptr, blocksize/2);
+ }
+
+// MDCT, overlap/add, save data for next overlapping FPMATH
+
+ for(j=0;j<vc->audio_channels;++j) {
+ uint_fast8_t step=vc->audio_channels;
+ uint_fast16_t k;
+ float *saved=vc->saved+j*vc->blocksize[1]/2;
+ float *ret=vc->ret;
+ const float *lwin=vc->win[1];
+ const float *swin=vc->win[0];
+ float *buf=vc->buf;
+ float *buf_tmp=vc->buf_tmp;
+
+ ch_floor_ptr=vc->channel_floors+j*blocksize/2;
+
+ saved_start=vc->saved_start;
+
+ vc->mdct[0].fft.imdct_calc(&vc->mdct[vc->modes[mode_number].blockflag], buf, ch_floor_ptr, buf_tmp);
+
+ //FIXME process channels together, to allow faster simd vector_fmul_add_add?
+ if (vc->modes[mode_number].blockflag) {
+ // -- overlap/add
+ if (previous_window) {
+ vc->dsp.vector_fmul_add_add(ret+j, buf, lwin, saved, vc->add_bias, vc->blocksize[1]/2, step);
+ retlen=vc->blocksize[1]/2;
+ } else {
+ int len = (vc->blocksize[1]-vc->blocksize[0])/4;
+ buf += len;
+ vc->dsp.vector_fmul_add_add(ret+j, buf, swin, saved, vc->add_bias, vc->blocksize[0]/2, step);
+ k = vc->blocksize[0]/2*step + j;
+ buf += vc->blocksize[0]/2;
+ if(vc->exp_bias){
+ for(i=0; i<len; i++, k+=step)
+ ((uint32_t*)ret)[k] = ((uint32_t*)buf)[i] + vc->exp_bias; // ret[k]=buf[i]*(1<<bias)
+ } else {
+ for(i=0; i<len; i++, k+=step)
+ ret[k] = buf[i] + fadd_bias;
+ }
+ buf=vc->buf;
+ retlen=vc->blocksize[0]/2+len;
+ }
+ // -- save
+ if (next_window) {
+ buf += vc->blocksize[1]/2;
+ vc->dsp.vector_fmul_reverse(saved, buf, lwin, vc->blocksize[1]/2);
+ saved_start=0;
+ } else {
+ saved_start=(vc->blocksize[1]-vc->blocksize[0])/4;
+ buf += vc->blocksize[1]/2;
+ for(i=0; i<saved_start; i++)
+ ((uint32_t*)saved)[i] = ((uint32_t*)buf)[i] + vc->exp_bias;
+ vc->dsp.vector_fmul_reverse(saved+saved_start, buf+saved_start, swin, vc->blocksize[0]/2);
+ }
+ } else {
+ // --overlap/add
+ if(vc->add_bias) {
+ for(k=j, i=0;i<saved_start;++i, k+=step)
+ ret[k] = saved[i] + fadd_bias;
+ } else {
+ for(k=j, i=0;i<saved_start;++i, k+=step)
+ ret[k] = saved[i];
+ }
+ vc->dsp.vector_fmul_add_add(ret+k, buf, swin, saved+saved_start, vc->add_bias, vc->blocksize[0]/2, step);
+ retlen=saved_start+vc->blocksize[0]/2;
+ // -- save
+ buf += vc->blocksize[0]/2;
+ vc->dsp.vector_fmul_reverse(saved, buf, swin, vc->blocksize[0]/2);
+ saved_start=0;
+ }
+ }
+ vc->saved_start=saved_start;
+
+ return retlen*vc->audio_channels;
+}
+
+// Return the decoded audio packet through the standard api
+
+static int vorbis_decode_frame(AVCodecContext *avccontext,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ vorbis_context *vc = avccontext->priv_data ;
+ GetBitContext *gb = &(vc->gb);
+
+ int_fast16_t len;
+
+ if(!buf_size){
+ return 0;
+ }
+
+ AV_DEBUG("packet length %d \n", buf_size);
+
+ init_get_bits(gb, buf, buf_size*8);
+
+ len=vorbis_parse_audio_packet(vc);
+
+ if (len<=0) {
+ *data_size=0;
+ return buf_size;
+ }
+
+ if (!vc->first_frame) {
+ vc->first_frame=1;
+ *data_size=0;
+ return buf_size ;
+ }
+
+ AV_DEBUG("parsed %d bytes %d bits, returned %d samples (*ch*bits) \n", get_bits_count(gb)/8, get_bits_count(gb)%8, len);
+
+ vc->dsp.float_to_int16(data, vc->ret, len);
+ *data_size=len*2;
+
+ return buf_size ;
+}
+
+// Close decoder
+
+static int vorbis_decode_close(AVCodecContext *avccontext) {
+ vorbis_context *vc = avccontext->priv_data;
+
+ vorbis_free(vc);
+
+ return 0 ;
+}
+
+AVCodec vorbis_decoder = {
+ "vorbis",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_VORBIS,
+ sizeof(vorbis_context),
+ vorbis_decode_init,
+ NULL,
+ vorbis_decode_close,
+ vorbis_decode_frame,
+};
+
diff --git a/contrib/ffmpeg/libavcodec/vorbis.h b/contrib/ffmpeg/libavcodec/vorbis.h
new file mode 100644
index 000000000..cda909aa9
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vorbis.h
@@ -0,0 +1,43 @@
+/*
+ * copyright (c) 2006 Oded Shimon <ods15@ods15.dyndns.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
+ */
+
+#ifndef VORBIS_H
+#define VORBIS_H
+
+#include "avcodec.h"
+
+extern const float ff_vorbis_floor1_inverse_db_table[256];
+extern const float * ff_vorbis_vwin[8];
+
+typedef struct {
+ uint_fast16_t x;
+ uint_fast16_t sort;
+ uint_fast16_t low;
+ uint_fast16_t high;
+} floor1_entry_t;
+
+void ff_vorbis_ready_floor1_list(floor1_entry_t * 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, uint_fast32_t num);
+void ff_vorbis_floor1_render_list(floor1_entry_t * list, int values, uint_fast16_t * y_list, int * flag, int multiplier, float * out, int samples);
+
+#define ilog(i) av_log2(2*(i))
+
+#endif
diff --git a/contrib/ffmpeg/libavcodec/vorbis_data.c b/contrib/ffmpeg/libavcodec/vorbis_data.c
new file mode 100644
index 000000000..5dc9c5f00
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vorbis_data.c
@@ -0,0 +1,2155 @@
+/*
+ * 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 "vorbis.h"
+
+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,
+};
+
+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,
+};
+
+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,
+};
+
+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,
+};
+
+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,
+};
+
+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,
+};
+
+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,
+};
+
+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 * ff_vorbis_vwin[8] = { vwin64, vwin128, vwin256, vwin512, vwin1024, vwin2048, vwin4096, vwin8192 };
+
diff --git a/contrib/ffmpeg/libavcodec/vorbis_enc.c b/contrib/ffmpeg/libavcodec/vorbis_enc.c
new file mode 100644
index 000000000..636b0cfae
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vorbis_enc.c
@@ -0,0 +1,1087 @@
+/*
+ * copyright (c) 2006 Oded Shimon <ods15@ods15.dyndns.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file vorbis_enc.c
+ * Native Vorbis encoder.
+ * @author Oded Shimon <ods15@ods15.dyndns.org>
+ */
+
+#include <float.h>
+#include "avcodec.h"
+#include "dsputil.h"
+#include "vorbis.h"
+#include "vorbis_enc_data.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+typedef struct {
+ int nentries;
+ uint8_t * lens;
+ uint32_t * codewords;
+ int ndimentions;
+ float min;
+ float delta;
+ int seq_p;
+ int lookup;
+ int * quantlist;
+ float * dimentions;
+ float * pow2;
+} codebook_t;
+
+typedef struct {
+ int dim;
+ int subclass;
+ int masterbook;
+ int * books;
+} floor_class_t;
+
+typedef struct {
+ int partitions;
+ int * partition_to_class;
+ int nclasses;
+ floor_class_t * classes;
+ int multiplier;
+ int rangebits;
+ int values;
+ floor1_entry_t * list;
+} floor_t;
+
+typedef struct {
+ int type;
+ int begin;
+ int end;
+ int partition_size;
+ int classifications;
+ int classbook;
+ int8_t (*books)[8];
+ float (*maxes)[2];
+} residue_t;
+
+typedef struct {
+ int submaps;
+ int * mux;
+ int * floor;
+ int * residue;
+ int coupling_steps;
+ int * magnitude;
+ int * angle;
+} mapping_t;
+
+typedef struct {
+ int blockflag;
+ int mapping;
+} vorbis_mode_t;
+
+typedef struct {
+ int channels;
+ int sample_rate;
+ int log2_blocksize[2];
+ MDCTContext 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;
+ codebook_t * codebooks;
+
+ int nfloors;
+ floor_t * floors;
+
+ int nresidues;
+ residue_t * residues;
+
+ int nmappings;
+ mapping_t * mappings;
+
+ int nmodes;
+ vorbis_mode_t * modes;
+} venc_context_t;
+
+typedef struct {
+ int total;
+ int total_pos;
+ int pos;
+ uint8_t * buf_ptr;
+} PutBitContext;
+
+static inline void init_put_bits(PutBitContext * pb, uint8_t * buf, int buffer_len) {
+ pb->total = buffer_len * 8;
+ pb->total_pos = 0;
+ pb->pos = 0;
+ pb->buf_ptr = buf;
+}
+
+static void put_bits(PutBitContext * pb, int bits, uint64_t val) {
+ if ((pb->total_pos += bits) >= pb->total) return;
+ if (!bits) return;
+ if (pb->pos) {
+ if (pb->pos > bits) {
+ *pb->buf_ptr |= val << (8 - pb->pos);
+ pb->pos -= bits;
+ bits = 0;
+ } else {
+ *pb->buf_ptr++ |= (val << (8 - pb->pos)) & 0xFF;
+ val >>= pb->pos;
+ bits -= pb->pos;
+ pb->pos = 0;
+ }
+ }
+ for (; bits >= 8; bits -= 8) {
+ *pb->buf_ptr++ = val & 0xFF;
+ val >>= 8;
+ }
+ if (bits) {
+ *pb->buf_ptr = val;
+ pb->pos = 8 - bits;
+ }
+}
+
+static inline void flush_put_bits(PutBitContext * pb) {
+}
+
+static inline int put_bits_count(PutBitContext * pb) {
+ return pb->total_pos;
+}
+
+static inline void put_codeword(PutBitContext * pb, codebook_t * cb, int entry) {
+ assert(entry >= 0);
+ assert(entry < cb->nentries);
+ assert(cb->lens[entry]);
+ put_bits(pb, cb->lens[entry], cb->codewords[entry]);
+}
+
+static int cb_lookup_vals(int lookup, int dimentions, int entries) {
+ if (lookup == 1) return ff_vorbis_nth_root(entries, dimentions);
+ else if (lookup == 2) return dimentions * entries;
+ return 0;
+}
+
+static void ready_codebook(codebook_t * cb) {
+ int i;
+
+ ff_vorbis_len2vlc(cb->lens, cb->codewords, cb->nentries);
+
+ if (!cb->lookup)
+ cb->pow2 = cb->dimentions = NULL;
+ else {
+ int vals = cb_lookup_vals(cb->lookup, cb->ndimentions, cb->nentries);
+ cb->dimentions = av_malloc(sizeof(float) * cb->nentries * cb->ndimentions);
+ cb->pow2 = av_mallocz(sizeof(float) * cb->nentries);
+ for (i = 0; i < cb->nentries; i++) {
+ float last = 0;
+ int j;
+ int div = 1;
+ for (j = 0; j < cb->ndimentions; j++) {
+ int off;
+ if (cb->lookup == 1)
+ off = (i / div) % vals; // lookup type 1
+ else
+ off = i * cb->ndimentions + j; // lookup type 2
+
+ cb->dimentions[i * cb->ndimentions + j] = last + cb->min + cb->quantlist[off] * cb->delta;
+ if (cb->seq_p)
+ last = cb->dimentions[i * cb->ndimentions + j];
+ cb->pow2[i] += cb->dimentions[i * cb->ndimentions + j]*cb->dimentions[i * cb->ndimentions + j];
+ div *= vals;
+ }
+ cb->pow2[i] /= 2.;
+ }
+ }
+}
+
+static void ready_residue(residue_t * rc, venc_context_t * venc) {
+ int i;
+ assert(rc->type == 2);
+ rc->maxes = av_mallocz(sizeof(float[2]) * rc->classifications);
+ for (i = 0; i < rc->classifications; i++) {
+ int j;
+ codebook_t * cb;
+ for (j = 0; j < 8; j++)
+ if (rc->books[i][j] != -1) break;
+ if (j == 8) continue; // zero
+ cb = &venc->codebooks[rc->books[i][j]];
+ assert(cb->ndimentions >= 2);
+ assert(cb->lookup);
+
+ for (j = 0; j < cb->nentries; j++) {
+ float a;
+ if (!cb->lens[j]) continue;
+ a = fabs(cb->dimentions[j * cb->ndimentions]);
+ if (a > rc->maxes[i][0])
+ rc->maxes[i][0] = a;
+ a = fabs(cb->dimentions[j * cb->ndimentions + 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;
+ }
+}
+
+static void create_vorbis_context(venc_context_t * venc, AVCodecContext * avccontext) {
+ floor_t * fc;
+ residue_t * rc;
+ mapping_t * mc;
+ int i, book;
+
+ venc->channels = avccontext->channels;
+ venc->sample_rate = avccontext->sample_rate;
+ venc->log2_blocksize[0] = venc->log2_blocksize[1] = 11;
+
+ venc->ncodebooks = sizeof(cvectors)/sizeof(cvectors[0]);
+ venc->codebooks = av_malloc(sizeof(codebook_t) * venc->ncodebooks);
+
+ // codebook 0..14 - floor1 book, values 0..255
+ // codebook 15 residue masterbook
+ // codebook 16..29 residue
+ for (book = 0; book < venc->ncodebooks; book++) {
+ codebook_t * cb = &venc->codebooks[book];
+ int vals;
+ cb->ndimentions = 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);
+ 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->ndimentions, cb->nentries);
+ cb->quantlist = av_malloc(sizeof(int) * vals);
+ for (i = 0; i < vals; i++)
+ cb->quantlist[i] = cvectors[book].quant[i];
+ } else {
+ cb->quantlist = NULL;
+ }
+ ready_codebook(cb);
+ }
+
+ venc->nfloors = 1;
+ venc->floors = av_malloc(sizeof(floor_t) * venc->nfloors);
+
+ // just 1 floor
+ fc = &venc->floors[0];
+ fc->partitions = 8;
+ fc->partition_to_class = av_malloc(sizeof(int) * fc->partitions);
+ 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(floor_class_t) * fc->nclasses);
+ for (i = 0; i < fc->nclasses; i++) {
+ floor_class_t * 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);
+ 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(floor1_entry_t) * fc->values);
+ 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];
+ }
+ ff_vorbis_ready_floor1_list(fc->list, fc->values);
+
+ venc->nresidues = 1;
+ venc->residues = av_malloc(sizeof(residue_t) * venc->nresidues);
+
+ // 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);
+ {
+ 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);
+ }
+ ready_residue(rc, venc);
+
+ venc->nmappings = 1;
+ venc->mappings = av_malloc(sizeof(mapping_t) * venc->nmappings);
+
+ // single mapping
+ mc = &venc->mappings[0];
+ mc->submaps = 1;
+ mc->mux = av_malloc(sizeof(int) * venc->channels);
+ 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);
+ 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->coupling_steps) {
+ mc->magnitude[0] = 0;
+ mc->angle[0] = 1;
+ }
+
+ venc->nmodes = 1;
+ venc->modes = av_malloc(sizeof(vorbis_mode_t) * venc->nmodes);
+
+ // 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);
+
+ venc->win[0] = ff_vorbis_vwin[venc->log2_blocksize[0] - 6];
+ venc->win[1] = ff_vorbis_vwin[venc->log2_blocksize[1] - 6];
+
+ ff_mdct_init(&venc->mdct[0], venc->log2_blocksize[0], 0);
+ ff_mdct_init(&venc->mdct[1], venc->log2_blocksize[1], 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 |= (1 << 31); mant = -mant; }
+ res |= mant | (exp << 21);
+ put_bits(pb, 32, res);
+}
+
+static void put_codebook_header(PutBitContext * pb, codebook_t * cb) {
+ int i;
+ int ordered = 0;
+
+ put_bits(pb, 24, 0x564342); //magic
+ put_bits(pb, 16, cb->ndimentions);
+ 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->ndimentions, 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, floor_t * 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, residue_t * 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(venc_context_t * 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_bits(&pb, 32, 0); // version
+ put_bits(&pb, 8, venc->channels);
+ put_bits(&pb, 32, venc->sample_rate);
+ put_bits(&pb, 32, 0); // bitrate
+ put_bits(&pb, 32, 0); // bitrate
+ put_bits(&pb, 32, 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) + 7) / 8;
+ 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_bits(&pb, 32, 0); // vendor length TODO
+ put_bits(&pb, 32, 0); // amount of comments
+ put_bits(&pb, 1, 1); // framing
+
+ flush_put_bits(&pb);
+ hlens[1] = (put_bits_count(&pb) + 7) / 8;
+ 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++) {
+ mapping_t * 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) + 7) / 8;
+
+ len = hlens[0] + hlens[1] + hlens[2];
+ p = *out = av_mallocz(64 + len + len/255);
+
+ *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(floor_t * 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(venc_context_t * venc, floor_t * fc, float * coeffs, uint_fast16_t * posts, int samples) {
+ int range = 255 / fc->multiplier + 1;
+ int i;
+ float tot_average = 0.;
+ float averages[fc->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 *= pow(tot_average / average, 0.5) * pow(1.25, position/200.); // 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 void floor_encode(venc_context_t * venc, floor_t * fc, PutBitContext * pb, uint_fast16_t * posts, float * floor, int samples) {
+ int range = 255 / fc->multiplier + 1;
+ int coded[fc->values]; // first 2 values are unused
+ int i, counter;
+
+ 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++) {
+ floor_class_t * c = &fc->classes[fc->partition_to_class[i]];
+ int k, cval = 0, csub = 1<<c->subclass;
+ if (c->subclass) {
+ codebook_t * 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 thats 0
+ if (coded[counter + k] < maxval) break;
+ }
+ assert(l != csub);
+ cval |= l << cshift;
+ cshift += c->subclass;
+ }
+ put_codeword(pb, book, cval);
+ }
+ 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;
+ put_codeword(pb, &venc->codebooks[book], entry);
+ }
+ }
+
+ ff_vorbis_floor1_render_list(fc->list, fc->values, posts, coded, fc->multiplier, floor, samples);
+}
+
+static float * put_vector(codebook_t * book, PutBitContext * pb, float * num) {
+ int i, entry = -1;
+ float distance = FLT_MAX;
+ assert(book->dimentions);
+ for (i = 0; i < book->nentries; i++) {
+ float * vec = book->dimentions + i * book->ndimentions, d = book->pow2[i];
+ int j;
+ if (!book->lens[i]) continue;
+ for (j = 0; j < book->ndimentions; j++)
+ d -= vec[j] * num[j];
+ if (distance > d) {
+ entry = i;
+ distance = d;
+ }
+ }
+ put_codeword(pb, book, entry);
+ return &book->dimentions[entry * book->ndimentions];
+}
+
+static void residue_encode(venc_context_t * venc, residue_t * 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[channels][partitions];
+ int classwords = venc->codebooks[rc->classbook].ndimentions;
+
+ 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++) {
+ codebook_t * book = &venc->codebooks[rc->classbook];
+ int entry = 0;
+ for (i = 0; i < classwords; i++) {
+ entry *= rc->classifications;
+ entry += classes[j][p + i];
+ }
+ put_codeword(pb, book, entry);
+ }
+ for (i = 0; i < classwords && p < partitions; i++, p++) {
+ for (j = 0; j < channels; j++) {
+ int nbook = rc->books[classes[j][p]][pass];
+ codebook_t * 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->ndimentions));
+
+ if (rc->type == 0) {
+ for (k = 0; k < psize; k += book->ndimentions) {
+ float * a = put_vector(book, pb, &buf[k]);
+ int l;
+ for (l = 0; l < book->ndimentions; 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->ndimentions) {
+ int dim, a2 = a1, b2 = b1;
+ float vec[book->ndimentions], * pv = vec;
+ for (dim = book->ndimentions; dim--; ) {
+ *pv++ = coeffs[a2 + b2];
+ if ((a2 += samples) == s) {
+ a2=0;
+ b2++;
+ }
+ }
+ pv = put_vector(book, pb, vec);
+ for (dim = book->ndimentions; dim--; ) {
+ coeffs[a1 + b1] -= *pv++;
+ if ((a1 += samples) == s) {
+ a1=0;
+ b1++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static int apply_window_and_mdct(venc_context_t * venc, signed short * audio, int samples) {
+ int i, j, 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;
+ j = channel;
+ for (i = 0; i < samples; i++, j += venc->channels)
+ offset[i] = audio[j] / 32768. / 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++) {
+ ff_mdct_calc(&venc->mdct[0], venc->coeffs + channel*window_len, venc->samples + channel*window_len*2, venc->floor/*tmp*/);
+ }
+
+ if (samples) {
+ for (channel = 0; channel < venc->channels; channel++) {
+ float * offset = venc->saved + channel*window_len;
+ j = channel;
+ for (i = 0; i < samples; i++, j += venc->channels)
+ offset[i] = audio[j] / 32768. / n * win[i];
+ }
+ venc->have_saved = 1;
+ } else {
+ venc->have_saved = 0;
+ }
+ return 1;
+}
+
+static int vorbis_encode_init(AVCodecContext * avccontext)
+{
+ venc_context_t * venc = avccontext->priv_data;
+
+ if (avccontext->channels != 2) {
+ av_log(avccontext, AV_LOG_ERROR, "Current FFmpeg Vorbis encoder only supports 2 channels.\n");
+ return -1;
+ }
+
+ create_vorbis_context(venc, avccontext);
+
+ if (avccontext->flags & CODEC_FLAG_QSCALE)
+ venc->quality = avccontext->global_quality / (float)FF_QP2LAMBDA / 10.;
+ else
+ venc->quality = 1.;
+ venc->quality *= venc->quality;
+
+ avccontext->extradata_size = put_main_header(venc, (uint8_t**)&avccontext->extradata);
+
+ avccontext->frame_size = 1 << (venc->log2_blocksize[0] - 1);
+
+ avccontext->coded_frame = avcodec_alloc_frame();
+ avccontext->coded_frame->key_frame = 1;
+
+ return 0;
+}
+
+static int vorbis_encode_frame(AVCodecContext * avccontext, unsigned char * packets, int buf_size, void *data)
+{
+ venc_context_t * venc = avccontext->priv_data;
+ signed short * audio = data;
+ int samples = data ? avccontext->frame_size : 0;
+ vorbis_mode_t * mode;
+ mapping_t * mapping;
+ PutBitContext pb;
+ int i;
+
+ if (!apply_window_and_mdct(venc, audio, samples)) return 0;
+ samples = 1 << (venc->log2_blocksize[0] - 1);
+
+ init_put_bits(&pb, packets, buf_size);
+
+ 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++) {
+ floor_t * fc = &venc->floors[mapping->floor[mapping->mux[i]]];
+ uint_fast16_t posts[fc->values];
+ floor_fit(venc, fc, &venc->coeffs[i * samples], posts, samples);
+ floor_encode(venc, fc, &pb, posts, &venc->floor[i * samples], samples);
+ }
+
+ 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;
+ }
+ }
+
+ residue_encode(venc, &venc->residues[mapping->residue[mapping->mux[0]]], &pb, venc->coeffs, samples, venc->channels);
+
+ flush_put_bits(&pb);
+ return (put_bits_count(&pb) + 7) / 8;
+}
+
+
+static int vorbis_encode_close(AVCodecContext * avccontext)
+{
+ venc_context_t * venc = avccontext->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].dimentions);
+ 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(&avccontext->coded_frame);
+ av_freep(&avccontext->extradata);
+
+ return 0 ;
+}
+
+AVCodec vorbis_encoder = {
+ "vorbis",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_VORBIS,
+ sizeof(venc_context_t),
+ vorbis_encode_init,
+ vorbis_encode_frame,
+ vorbis_encode_close,
+ .capabilities= CODEC_CAP_DELAY,
+};
diff --git a/contrib/ffmpeg/libavcodec/vorbis_enc_data.h b/contrib/ffmpeg/libavcodec/vorbis_enc_data.h
new file mode 100644
index 000000000..e56dc5df5
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vorbis_enc_data.h
@@ -0,0 +1,498 @@
+/*
+ * copyright (c) 2006 Oded Shimon <ods15@ods15.dyndns.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+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;
+} floor_classes[] = {
+ { 3, 0, 0, (const int[]){ 4 } },
+ { 4, 1, 0, (const int[]){ 5, 6 } },
+ { 3, 1, 1, (const int[]){ 7, 8 } },
+ { 4, 2, 2, (const int[]){ -1, 9, 10, 11 } },
+ { 3, 2, 3, (const int[]){ -1, 12, 13, 14 } },
+};
diff --git a/contrib/ffmpeg/libavcodec/vp3.c b/contrib/ffmpeg/libavcodec/vp3.c
new file mode 100644
index 000000000..6a398693a
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vp3.c
@@ -0,0 +1,2659 @@
+/*
+ * 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 vp3.c
+ * On2 VP3 Video Decoder
+ *
+ * VP3 Video Decoder by Mike Melanson (mike at multimedia.cx)
+ * For more information about the VP3 coding process, visit:
+ * http://multimedia.cx/
+ *
+ * Theora decoder by Alex Beregszaszi
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+#include "vp3data.h"
+
+#define FRAGMENT_PIXELS 8
+
+/*
+ * Debugging Variables
+ *
+ * Define one or more of the following compile-time variables to 1 to obtain
+ * elaborate information about certain aspects of the decoding process.
+ *
+ * KEYFRAMES_ONLY: set this to 1 to only see keyframes (VP3 slideshow mode)
+ * DEBUG_VP3: high-level decoding flow
+ * DEBUG_INIT: initialization parameters
+ * DEBUG_DEQUANTIZERS: display how the dequanization tables are built
+ * DEBUG_BLOCK_CODING: unpacking the superblock/macroblock/fragment coding
+ * DEBUG_MODES: unpacking the coding modes for individual fragments
+ * DEBUG_VECTORS: display the motion vectors
+ * DEBUG_TOKEN: display exhaustive information about each DCT token
+ * DEBUG_VLC: display the VLCs as they are extracted from the stream
+ * DEBUG_DC_PRED: display the process of reversing DC prediction
+ * DEBUG_IDCT: show every detail of the IDCT process
+ */
+
+#define KEYFRAMES_ONLY 0
+
+#define DEBUG_VP3 0
+#define DEBUG_INIT 0
+#define DEBUG_DEQUANTIZERS 0
+#define DEBUG_BLOCK_CODING 0
+#define DEBUG_MODES 0
+#define DEBUG_VECTORS 0
+#define DEBUG_TOKEN 0
+#define DEBUG_VLC 0
+#define DEBUG_DC_PRED 0
+#define DEBUG_IDCT 0
+
+#if DEBUG_VP3
+#define debug_vp3(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
+#else
+static inline void debug_vp3(const char *format, ...) { }
+#endif
+
+#if DEBUG_INIT
+#define debug_init(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
+#else
+static inline void debug_init(const char *format, ...) { }
+#endif
+
+#if DEBUG_DEQUANTIZERS
+#define debug_dequantizers(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
+#else
+static inline void debug_dequantizers(const char *format, ...) { }
+#endif
+
+#if DEBUG_BLOCK_CODING
+#define debug_block_coding(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
+#else
+static inline void debug_block_coding(const char *format, ...) { }
+#endif
+
+#if DEBUG_MODES
+#define debug_modes(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
+#else
+static inline void debug_modes(const char *format, ...) { }
+#endif
+
+#if DEBUG_VECTORS
+#define debug_vectors(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
+#else
+static inline void debug_vectors(const char *format, ...) { }
+#endif
+
+#if DEBUG_TOKEN
+#define debug_token(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
+#else
+static inline void debug_token(const char *format, ...) { }
+#endif
+
+#if DEBUG_VLC
+#define debug_vlc(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
+#else
+static inline void debug_vlc(const char *format, ...) { }
+#endif
+
+#if DEBUG_DC_PRED
+#define debug_dc_pred(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
+#else
+static inline void debug_dc_pred(const char *format, ...) { }
+#endif
+
+#if DEBUG_IDCT
+#define debug_idct(args...) av_log(NULL, AV_LOG_DEBUG, ## args)
+#else
+static inline void debug_idct(const char *format, ...) { }
+#endif
+
+typedef struct Coeff {
+ struct Coeff *next;
+ DCTELEM coeff;
+ uint8_t index;
+} Coeff;
+
+//FIXME split things out into their own arrays
+typedef struct Vp3Fragment {
+ Coeff *next_coeff;
+ /* address of first pixel taking into account which plane the fragment
+ * lives on as well as the plane stride */
+ int first_pixel;
+ /* this is the macroblock that the fragment belongs to */
+ uint16_t macroblock;
+ uint8_t coding_method;
+ uint8_t coeff_count;
+ int8_t motion_x;
+ int8_t motion_y;
+} Vp3Fragment;
+
+#define SB_NOT_CODED 0
+#define SB_PARTIALLY_CODED 1
+#define SB_FULLY_CODED 2
+
+#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
+
+/* There are 6 preset schemes, plus a free-form scheme */
+static int ModeAlphabet[7][CODING_MODE_COUNT] =
+{
+ /* this is the custom scheme */
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+
+ /* 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 },
+
+};
+
+#define MIN_DEQUANT_VAL 2
+
+typedef struct Vp3DecodeContext {
+ AVCodecContext *avctx;
+ int theora, theora_tables;
+ int version;
+ int width, height;
+ AVFrame golden_frame;
+ AVFrame last_frame;
+ AVFrame current_frame;
+ int keyframe;
+ DSPContext dsp;
+ int flipped_image;
+
+ int qis[3];
+ int nqis;
+ int quality_index;
+ int last_quality_index;
+
+ int superblock_count;
+ int superblock_width;
+ int superblock_height;
+ int y_superblock_width;
+ int y_superblock_height;
+ int c_superblock_width;
+ int c_superblock_height;
+ 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;
+ int fragment_height;
+
+ Vp3Fragment *all_fragments;
+ Coeff *coeffs;
+ Coeff *next_coeff;
+ int fragment_start[3];
+
+ ScanTable scantable;
+
+ /* 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 indices into the all_fragments array indicating
+ * which of the fragments are coded */
+ int *coded_fragment_list;
+ int coded_fragment_list_index;
+ int pixel_addresses_inited;
+
+ 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[2][4][64]); //<qmat[is_inter][plane]
+
+ /* This table contains superblock_count * 16 entries. Each set of 16
+ * numbers corresponds to the fragment indices 0..15 of the superblock.
+ * An entry will be -1 to indicate that no entry corresponds to that
+ * index. */
+ int *superblock_fragments;
+
+ /* This table contains superblock_count * 4 entries. Each set of 4
+ * numbers corresponds to the macroblock indices 0..3 of the superblock.
+ * An entry will be -1 to indicate that no entry corresponds to that
+ * index. */
+ int *superblock_macroblocks;
+
+ /* This table contains macroblock_count * 6 entries. Each set of 6
+ * numbers corresponds to the fragment indices 0..5 which comprise
+ * the macroblock (4 Y fragments and 2 C fragments). */
+ int *macroblock_fragments;
+ /* This is an array that indicates how a particular macroblock
+ * is coded. */
+ unsigned char *macroblock_coding;
+
+ int first_coded_y_fragment;
+ int first_coded_c_fragment;
+ int last_coded_y_fragment;
+ int last_coded_c_fragment;
+
+ uint8_t edge_emu_buffer[9*2048]; //FIXME dynamic alloc
+ int8_t qscale_table[2048]; //FIXME dynamic alloc (width+15)/16
+
+ /* Huffman decode */
+ int hti;
+ unsigned int hbits;
+ int entries;
+ int huff_code_size;
+ uint16_t huffman_table[80][32][2];
+
+ uint32_t filter_limit_values[64];
+ int bounding_values_array[256];
+} Vp3DecodeContext;
+
+static int theora_decode_tables(AVCodecContext *avctx, GetBitContext *gb);
+
+/************************************************************************
+ * VP3 specific functions
+ ************************************************************************/
+
+/*
+ * This function sets up all of the various blocks mappings:
+ * superblocks <-> fragments, macroblocks <-> fragments,
+ * superblocks <-> macroblocks
+ *
+ * Returns 0 is successful; returns 1 if *anything* went wrong.
+ */
+static int init_block_mapping(Vp3DecodeContext *s)
+{
+ int i, j;
+ signed int hilbert_walk_mb[4];
+
+ int current_fragment = 0;
+ int current_width = 0;
+ int current_height = 0;
+ int right_edge = 0;
+ int bottom_edge = 0;
+ int superblock_row_inc = 0;
+ int *hilbert = NULL;
+ int mapping_index = 0;
+
+ int current_macroblock;
+ int c_fragment;
+
+ signed char travel_width[16] = {
+ 1, 1, 0, -1,
+ 0, 0, 1, 0,
+ 1, 0, 1, 0,
+ 0, -1, 0, 1
+ };
+
+ signed char travel_height[16] = {
+ 0, 0, 1, 0,
+ 1, 1, 0, -1,
+ 0, 1, 0, -1,
+ -1, 0, -1, 0
+ };
+
+ signed char travel_width_mb[4] = {
+ 1, 0, 1, 0
+ };
+
+ signed char travel_height_mb[4] = {
+ 0, 1, 0, -1
+ };
+
+ debug_vp3(" vp3: initialize block mapping tables\n");
+
+ hilbert_walk_mb[0] = 1;
+ hilbert_walk_mb[1] = s->macroblock_width;
+ hilbert_walk_mb[2] = 1;
+ hilbert_walk_mb[3] = -s->macroblock_width;
+
+ /* iterate through each superblock (all planes) and map the fragments */
+ for (i = 0; i < s->superblock_count; i++) {
+ debug_init(" superblock %d (u starts @ %d, v starts @ %d)\n",
+ i, s->u_superblock_start, s->v_superblock_start);
+
+ /* time to re-assign the limits? */
+ if (i == 0) {
+
+ /* start of Y superblocks */
+ right_edge = s->fragment_width;
+ bottom_edge = s->fragment_height;
+ current_width = -1;
+ current_height = 0;
+ superblock_row_inc = 3 * s->fragment_width -
+ (s->y_superblock_width * 4 - s->fragment_width);
+
+ /* the first operation for this variable is to advance by 1 */
+ current_fragment = -1;
+
+ } else if (i == s->u_superblock_start) {
+
+ /* start of U superblocks */
+ right_edge = s->fragment_width / 2;
+ bottom_edge = s->fragment_height / 2;
+ current_width = -1;
+ current_height = 0;
+ superblock_row_inc = 3 * (s->fragment_width / 2) -
+ (s->c_superblock_width * 4 - s->fragment_width / 2);
+
+ /* the first operation for this variable is to advance by 1 */
+ current_fragment = s->fragment_start[1] - 1;
+
+ } else if (i == s->v_superblock_start) {
+
+ /* start of V superblocks */
+ right_edge = s->fragment_width / 2;
+ bottom_edge = s->fragment_height / 2;
+ current_width = -1;
+ current_height = 0;
+ superblock_row_inc = 3 * (s->fragment_width / 2) -
+ (s->c_superblock_width * 4 - s->fragment_width / 2);
+
+ /* the first operation for this variable is to advance by 1 */
+ current_fragment = s->fragment_start[2] - 1;
+
+ }
+
+ if (current_width >= right_edge - 1) {
+ /* reset width and move to next superblock row */
+ current_width = -1;
+ current_height += 4;
+
+ /* fragment is now at the start of a new superblock row */
+ current_fragment += superblock_row_inc;
+ }
+
+ /* iterate through all 16 fragments in a superblock */
+ for (j = 0; j < 16; j++) {
+ current_fragment += travel_width[j] + right_edge * travel_height[j];
+ current_width += travel_width[j];
+ current_height += travel_height[j];
+
+ /* check if the fragment is in bounds */
+ if ((current_width < right_edge) &&
+ (current_height < bottom_edge)) {
+ s->superblock_fragments[mapping_index] = current_fragment;
+ debug_init(" mapping fragment %d to superblock %d, position %d (%d/%d x %d/%d)\n",
+ s->superblock_fragments[mapping_index], i, j,
+ current_width, right_edge, current_height, bottom_edge);
+ } else {
+ s->superblock_fragments[mapping_index] = -1;
+ debug_init(" superblock %d, position %d has no fragment (%d/%d x %d/%d)\n",
+ i, j,
+ current_width, right_edge, current_height, bottom_edge);
+ }
+
+ mapping_index++;
+ }
+ }
+
+ /* initialize the superblock <-> macroblock mapping; iterate through
+ * all of the Y plane superblocks to build this mapping */
+ right_edge = s->macroblock_width;
+ bottom_edge = s->macroblock_height;
+ current_width = -1;
+ current_height = 0;
+ superblock_row_inc = s->macroblock_width -
+ (s->y_superblock_width * 2 - s->macroblock_width);;
+ hilbert = hilbert_walk_mb;
+ mapping_index = 0;
+ current_macroblock = -1;
+ for (i = 0; i < s->u_superblock_start; i++) {
+
+ if (current_width >= right_edge - 1) {
+ /* reset width and move to next superblock row */
+ current_width = -1;
+ current_height += 2;
+
+ /* macroblock is now at the start of a new superblock row */
+ current_macroblock += superblock_row_inc;
+ }
+
+ /* iterate through each potential macroblock in the superblock */
+ for (j = 0; j < 4; j++) {
+ current_macroblock += hilbert_walk_mb[j];
+ current_width += travel_width_mb[j];
+ current_height += travel_height_mb[j];
+
+ /* check if the macroblock is in bounds */
+ if ((current_width < right_edge) &&
+ (current_height < bottom_edge)) {
+ s->superblock_macroblocks[mapping_index] = current_macroblock;
+ debug_init(" mapping macroblock %d to superblock %d, position %d (%d/%d x %d/%d)\n",
+ s->superblock_macroblocks[mapping_index], i, j,
+ current_width, right_edge, current_height, bottom_edge);
+ } else {
+ s->superblock_macroblocks[mapping_index] = -1;
+ debug_init(" superblock %d, position %d has no macroblock (%d/%d x %d/%d)\n",
+ i, j,
+ current_width, right_edge, current_height, bottom_edge);
+ }
+
+ mapping_index++;
+ }
+ }
+
+ /* initialize the macroblock <-> fragment mapping */
+ current_fragment = 0;
+ current_macroblock = 0;
+ mapping_index = 0;
+ for (i = 0; i < s->fragment_height; i += 2) {
+
+ for (j = 0; j < s->fragment_width; j += 2) {
+
+ debug_init(" macroblock %d contains fragments: ", current_macroblock);
+ s->all_fragments[current_fragment].macroblock = current_macroblock;
+ s->macroblock_fragments[mapping_index++] = current_fragment;
+ debug_init("%d ", current_fragment);
+
+ if (j + 1 < s->fragment_width) {
+ s->all_fragments[current_fragment + 1].macroblock = current_macroblock;
+ s->macroblock_fragments[mapping_index++] = current_fragment + 1;
+ debug_init("%d ", current_fragment + 1);
+ } else
+ s->macroblock_fragments[mapping_index++] = -1;
+
+ if (i + 1 < s->fragment_height) {
+ s->all_fragments[current_fragment + s->fragment_width].macroblock =
+ current_macroblock;
+ s->macroblock_fragments[mapping_index++] =
+ current_fragment + s->fragment_width;
+ debug_init("%d ", current_fragment + s->fragment_width);
+ } else
+ s->macroblock_fragments[mapping_index++] = -1;
+
+ if ((j + 1 < s->fragment_width) && (i + 1 < s->fragment_height)) {
+ s->all_fragments[current_fragment + s->fragment_width + 1].macroblock =
+ current_macroblock;
+ s->macroblock_fragments[mapping_index++] =
+ current_fragment + s->fragment_width + 1;
+ debug_init("%d ", current_fragment + s->fragment_width + 1);
+ } else
+ s->macroblock_fragments[mapping_index++] = -1;
+
+ /* C planes */
+ c_fragment = s->fragment_start[1] +
+ (i * s->fragment_width / 4) + (j / 2);
+ s->all_fragments[c_fragment].macroblock = s->macroblock_count;
+ s->macroblock_fragments[mapping_index++] = c_fragment;
+ debug_init("%d ", c_fragment);
+
+ c_fragment = s->fragment_start[2] +
+ (i * s->fragment_width / 4) + (j / 2);
+ s->all_fragments[c_fragment].macroblock = s->macroblock_count;
+ s->macroblock_fragments[mapping_index++] = c_fragment;
+ debug_init("%d ", c_fragment);
+
+ debug_init("\n");
+
+ if (j + 2 <= s->fragment_width)
+ current_fragment += 2;
+ else
+ current_fragment++;
+ current_macroblock++;
+ }
+
+ current_fragment += s->fragment_width;
+ }
+
+ return 0; /* successful path out */
+}
+
+/*
+ * This function wipes out all of the fragment data.
+ */
+static void init_frame(Vp3DecodeContext *s, GetBitContext *gb)
+{
+ int i;
+
+ /* zero out all of the fragment information */
+ s->coded_fragment_list_index = 0;
+ for (i = 0; i < s->fragment_count; i++) {
+ s->all_fragments[i].coeff_count = 0;
+ s->all_fragments[i].motion_x = 127;
+ s->all_fragments[i].motion_y = 127;
+ s->all_fragments[i].next_coeff= NULL;
+ s->coeffs[i].index=
+ s->coeffs[i].coeff=0;
+ s->coeffs[i].next= NULL;
+ }
+}
+
+/*
+ * This function sets up the dequantization tables used for a particular
+ * frame.
+ */
+static void init_dequantizer(Vp3DecodeContext *s)
+{
+ int ac_scale_factor = s->coded_ac_scale_factor[s->quality_index];
+ int dc_scale_factor = s->coded_dc_scale_factor[s->quality_index];
+ int i, plane, inter, qri, bmi, bmj, qistart;
+
+ debug_vp3(" vp3: initializing dequantization tables\n");
+
+ for(inter=0; inter<2; inter++){
+ for(plane=0; plane<3; plane++){
+ int sum=0;
+ for(qri=0; qri<s->qr_count[inter][plane]; qri++){
+ sum+= s->qr_size[inter][plane][qri];
+ if(s->quality_index <= 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->quality_index)*s->base_matrix[bmi][i]
+ - 2*(qistart-s->quality_index)*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[inter][plane][i]= clip((qscale * coeff)/100 * 4, qmin, 4096);
+ }
+ }
+ }
+
+ memset(s->qscale_table, (FFMAX(s->qmat[0][0][1], s->qmat[0][1][1])+8)/16, 512); //FIXME finetune
+}
+
+/*
+ * This function initializes the loop filter boundary limits if the frame's
+ * quality index is different from the previous frame's.
+ */
+static void init_loop_filter(Vp3DecodeContext *s)
+{
+ int *bounding_values= s->bounding_values_array+127;
+ int filter_limit;
+ int x;
+
+ filter_limit = s->filter_limit_values[s->quality_index];
+
+ /* set up the bounding values */
+ memset(s->bounding_values_array, 0, 256 * sizeof(int));
+ for (x = 0; x < filter_limit; x++) {
+ bounding_values[-x - filter_limit] = -filter_limit + x;
+ bounding_values[-x] = -x;
+ bounding_values[x] = x;
+ bounding_values[x + filter_limit] = filter_limit - x;
+ }
+}
+
+/*
+ * This function unpacks all of the superblock/macroblock/fragment coding
+ * information from the bitstream.
+ */
+static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb)
+{
+ int bit = 0;
+ int current_superblock = 0;
+ int current_run = 0;
+ int decode_fully_flags = 0;
+ int decode_partial_blocks = 0;
+ int first_c_fragment_seen;
+
+ int i, j;
+ int current_fragment;
+
+ debug_vp3(" vp3: unpacking superblock coding\n");
+
+ if (s->keyframe) {
+
+ debug_vp3(" keyframe-- all superblocks are fully coded\n");
+ memset(s->superblock_coding, SB_FULLY_CODED, s->superblock_count);
+
+ } else {
+
+ /* unpack the list of partially-coded superblocks */
+ bit = get_bits(gb, 1);
+ /* toggle the bit because as soon as the first run length is
+ * fetched the bit will be toggled again */
+ bit ^= 1;
+ while (current_superblock < s->superblock_count) {
+ if (current_run-- == 0) {
+ bit ^= 1;
+ current_run = get_vlc2(gb,
+ s->superblock_run_length_vlc.table, 6, 2);
+ if (current_run == 33)
+ current_run += get_bits(gb, 12);
+ debug_block_coding(" setting superblocks %d..%d to %s\n",
+ current_superblock,
+ current_superblock + current_run - 1,
+ (bit) ? "partially coded" : "not coded");
+
+ /* if any of the superblocks are not partially coded, flag
+ * a boolean to decode the list of fully-coded superblocks */
+ if (bit == 0) {
+ decode_fully_flags = 1;
+ } else {
+
+ /* make a note of the fact that there are partially coded
+ * superblocks */
+ decode_partial_blocks = 1;
+ }
+ }
+ s->superblock_coding[current_superblock++] = bit;
+ }
+
+ /* unpack the list of fully coded superblocks if any of the blocks were
+ * not marked as partially coded in the previous step */
+ if (decode_fully_flags) {
+
+ current_superblock = 0;
+ current_run = 0;
+ bit = get_bits(gb, 1);
+ /* toggle the bit because as soon as the first run length is
+ * fetched the bit will be toggled again */
+ bit ^= 1;
+ while (current_superblock < s->superblock_count) {
+
+ /* skip any superblocks already marked as partially coded */
+ if (s->superblock_coding[current_superblock] == SB_NOT_CODED) {
+
+ if (current_run-- == 0) {
+ bit ^= 1;
+ current_run = get_vlc2(gb,
+ s->superblock_run_length_vlc.table, 6, 2);
+ if (current_run == 33)
+ current_run += get_bits(gb, 12);
+ }
+
+ debug_block_coding(" setting superblock %d to %s\n",
+ current_superblock,
+ (bit) ? "fully coded" : "not coded");
+ s->superblock_coding[current_superblock] = 2*bit;
+ }
+ current_superblock++;
+ }
+ }
+
+ /* if there were partial blocks, initialize bitstream for
+ * unpacking fragment codings */
+ if (decode_partial_blocks) {
+
+ current_run = 0;
+ bit = get_bits(gb, 1);
+ /* 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->coded_fragment_list_index = 0;
+ s->next_coeff= s->coeffs + s->fragment_count;
+ s->first_coded_y_fragment = s->first_coded_c_fragment = 0;
+ s->last_coded_y_fragment = s->last_coded_c_fragment = -1;
+ first_c_fragment_seen = 0;
+ memset(s->macroblock_coding, MODE_COPY, s->macroblock_count);
+ for (i = 0; i < s->superblock_count; 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 >= s->fragment_count) {
+ av_log(s->avctx, AV_LOG_ERROR, " vp3:unpack_superblocks(): bad fragment number (%d >= %d)\n",
+ current_fragment, s->fragment_count);
+ return 1;
+ }
+ if (current_fragment != -1) {
+ if (s->superblock_coding[i] == SB_NOT_CODED) {
+
+ /* copy all the fragments from the prior frame */
+ s->all_fragments[current_fragment].coding_method =
+ MODE_COPY;
+
+ } else 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);
+ }
+
+ if (bit) {
+ /* default mode; actual mode will be decoded in
+ * the next phase */
+ s->all_fragments[current_fragment].coding_method =
+ MODE_INTER_NO_MV;
+ s->all_fragments[current_fragment].next_coeff= s->coeffs + current_fragment;
+ s->coded_fragment_list[s->coded_fragment_list_index] =
+ current_fragment;
+ if ((current_fragment >= s->fragment_start[1]) &&
+ (s->last_coded_y_fragment == -1) &&
+ (!first_c_fragment_seen)) {
+ s->first_coded_c_fragment = s->coded_fragment_list_index;
+ s->last_coded_y_fragment = s->first_coded_c_fragment - 1;
+ first_c_fragment_seen = 1;
+ }
+ s->coded_fragment_list_index++;
+ s->macroblock_coding[s->all_fragments[current_fragment].macroblock] = MODE_INTER_NO_MV;
+ debug_block_coding(" superblock %d is partially coded, fragment %d is coded\n",
+ i, current_fragment);
+ } else {
+ /* not coded; copy this fragment from the prior frame */
+ s->all_fragments[current_fragment].coding_method =
+ MODE_COPY;
+ debug_block_coding(" superblock %d is partially coded, fragment %d is not coded\n",
+ i, current_fragment);
+ }
+
+ } else {
+
+ /* fragments are fully coded in this superblock; actual
+ * coding will be determined in next step */
+ s->all_fragments[current_fragment].coding_method =
+ MODE_INTER_NO_MV;
+ s->all_fragments[current_fragment].next_coeff= s->coeffs + current_fragment;
+ s->coded_fragment_list[s->coded_fragment_list_index] =
+ current_fragment;
+ if ((current_fragment >= s->fragment_start[1]) &&
+ (s->last_coded_y_fragment == -1) &&
+ (!first_c_fragment_seen)) {
+ s->first_coded_c_fragment = s->coded_fragment_list_index;
+ s->last_coded_y_fragment = s->first_coded_c_fragment - 1;
+ first_c_fragment_seen = 1;
+ }
+ s->coded_fragment_list_index++;
+ s->macroblock_coding[s->all_fragments[current_fragment].macroblock] = MODE_INTER_NO_MV;
+ debug_block_coding(" superblock %d is fully coded, fragment %d is coded\n",
+ i, current_fragment);
+ }
+ }
+ }
+ }
+
+ if (!first_c_fragment_seen)
+ /* only Y fragments coded in this frame */
+ s->last_coded_y_fragment = s->coded_fragment_list_index - 1;
+ else
+ /* end the list of coded C fragments */
+ s->last_coded_c_fragment = s->coded_fragment_list_index - 1;
+
+ debug_block_coding(" %d total coded fragments, y: %d -> %d, c: %d -> %d\n",
+ s->coded_fragment_list_index,
+ s->first_coded_y_fragment,
+ s->last_coded_y_fragment,
+ s->first_coded_c_fragment,
+ s->last_coded_c_fragment);
+
+ 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;
+ int scheme;
+ int current_macroblock;
+ int current_fragment;
+ int coding_mode;
+
+ debug_vp3(" vp3: unpacking encoding modes\n");
+
+ if (s->keyframe) {
+ debug_vp3(" keyframe-- all blocks are coded as INTRA\n");
+
+ 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);
+ debug_modes(" using mode alphabet %d\n", scheme);
+
+ /* is it a custom coding scheme? */
+ if (scheme == 0) {
+ debug_modes(" custom mode alphabet ahead:\n");
+ for (i = 0; i < 8; i++)
+ ModeAlphabet[scheme][get_bits(gb, 3)] = i;
+ }
+
+ for (i = 0; i < 8; i++)
+ debug_modes(" mode[%d][%d] = %d\n", scheme, i,
+ ModeAlphabet[scheme][i]);
+
+ /* iterate through all of the macroblocks that contain 1 or more
+ * coded fragments */
+ for (i = 0; i < s->u_superblock_start; i++) {
+
+ for (j = 0; j < 4; j++) {
+ current_macroblock = s->superblock_macroblocks[i * 4 + j];
+ if ((current_macroblock == -1) ||
+ (s->macroblock_coding[current_macroblock] == MODE_COPY))
+ continue;
+ if (current_macroblock >= s->macroblock_count) {
+ av_log(s->avctx, AV_LOG_ERROR, " vp3:unpack_modes(): bad macroblock number (%d >= %d)\n",
+ current_macroblock, s->macroblock_count);
+ return 1;
+ }
+
+ /* mode 7 means get 3 bits for each coding mode */
+ if (scheme == 7)
+ coding_mode = get_bits(gb, 3);
+ else
+ coding_mode = ModeAlphabet[scheme]
+ [get_vlc2(gb, s->mode_code_vlc.table, 3, 3)];
+
+ s->macroblock_coding[current_macroblock] = coding_mode;
+ for (k = 0; k < 6; k++) {
+ current_fragment =
+ s->macroblock_fragments[current_macroblock * 6 + k];
+ if (current_fragment == -1)
+ continue;
+ if (current_fragment >= s->fragment_count) {
+ av_log(s->avctx, AV_LOG_ERROR, " vp3:unpack_modes(): bad fragment number (%d >= %d)\n",
+ current_fragment, s->fragment_count);
+ return 1;
+ }
+ if (s->all_fragments[current_fragment].coding_method !=
+ MODE_COPY)
+ s->all_fragments[current_fragment].coding_method =
+ coding_mode;
+ }
+
+ debug_modes(" coding method for macroblock starting @ fragment %d = %d\n",
+ s->macroblock_fragments[current_macroblock * 6], coding_mode);
+ }
+ }
+ }
+
+ 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 i, j, k;
+ int coding_mode;
+ int motion_x[6];
+ int motion_y[6];
+ 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;
+
+ debug_vp3(" vp3: unpacking motion vectors\n");
+ if (s->keyframe) {
+
+ debug_vp3(" keyframe-- there are no motion vectors\n");
+
+ } else {
+
+ memset(motion_x, 0, 6 * sizeof(int));
+ memset(motion_y, 0, 6 * sizeof(int));
+
+ /* coding mode 0 is the VLC scheme; 1 is the fixed code scheme */
+ coding_mode = get_bits(gb, 1);
+ debug_vectors(" using %s scheme for unpacking motion vectors\n",
+ (coding_mode == 0) ? "VLC" : "fixed-length");
+
+ /* iterate through all of the macroblocks that contain 1 or more
+ * coded fragments */
+ for (i = 0; i < s->u_superblock_start; i++) {
+
+ for (j = 0; j < 4; j++) {
+ current_macroblock = s->superblock_macroblocks[i * 4 + j];
+ if ((current_macroblock == -1) ||
+ (s->macroblock_coding[current_macroblock] == MODE_COPY))
+ continue;
+ if (current_macroblock >= s->macroblock_count) {
+ av_log(s->avctx, AV_LOG_ERROR, " vp3:unpack_vectors(): bad macroblock number (%d >= %d)\n",
+ current_macroblock, s->macroblock_count);
+ return 1;
+ }
+
+ current_fragment = s->macroblock_fragments[current_macroblock * 6];
+ if (current_fragment >= s->fragment_count) {
+ av_log(s->avctx, AV_LOG_ERROR, " vp3:unpack_vectors(): bad fragment number (%d >= %d\n",
+ current_fragment, s->fragment_count);
+ return 1;
+ }
+ 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)];
+ }
+
+ for (k = 1; k < 6; k++) {
+ motion_x[k] = motion_x[0];
+ motion_y[k] = motion_y[0];
+ }
+
+ /* 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:
+ /* fetch 4 vectors from the bitstream, one for each
+ * Y fragment, then average for the C fragment vectors */
+ motion_x[4] = motion_y[4] = 0;
+ for (k = 0; k < 4; k++) {
+ 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)];
+ }
+ motion_x[4] += motion_x[k];
+ motion_y[4] += motion_y[k];
+ }
+
+ motion_x[5]=
+ motion_x[4]= RSHIFT(motion_x[4], 2);
+ motion_y[5]=
+ motion_y[4]= RSHIFT(motion_y[4], 2);
+
+ /* vector maintenance; vector[3] is treated as the
+ * last vector in this case */
+ prior_last_motion_x = last_motion_x;
+ prior_last_motion_y = last_motion_y;
+ last_motion_x = motion_x[3];
+ last_motion_y = motion_y[3];
+ 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;
+ for (k = 1; k < 6; k++) {
+ motion_x[k] = motion_x[0];
+ motion_y[k] = motion_y[0];
+ }
+
+ /* 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;
+ for (k = 1; k < 6; k++) {
+ motion_x[k] = motion_x[0];
+ motion_y[k] = motion_y[0];
+ }
+
+ /* 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 */
+ memset(motion_x, 0, 6 * sizeof(int));
+ memset(motion_y, 0, 6 * sizeof(int));
+
+ /* no vector maintenance */
+ break;
+ }
+
+ /* assign the motion vectors to the correct fragments */
+ debug_vectors(" vectors for macroblock starting @ fragment %d (coding method %d):\n",
+ current_fragment,
+ s->macroblock_coding[current_macroblock]);
+ for (k = 0; k < 6; k++) {
+ current_fragment =
+ s->macroblock_fragments[current_macroblock * 6 + k];
+ if (current_fragment == -1)
+ continue;
+ if (current_fragment >= s->fragment_count) {
+ av_log(s->avctx, AV_LOG_ERROR, " vp3:unpack_vectors(): bad fragment number (%d >= %d)\n",
+ current_fragment, s->fragment_count);
+ return 1;
+ }
+ s->all_fragments[current_fragment].motion_x = motion_x[k];
+ s->all_fragments[current_fragment].motion_y = motion_y[k];
+ debug_vectors(" vector %d: fragment %d = (%d, %d)\n",
+ k, current_fragment, motion_x[k], motion_y[k]);
+ }
+ }
+ }
+ }
+
+ 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 first_fragment, int last_fragment,
+ int eob_run)
+{
+ int i;
+ int token;
+ int zero_run = 0;
+ DCTELEM coeff = 0;
+ Vp3Fragment *fragment;
+ uint8_t *perm= s->scantable.permutated;
+ int bits_to_get;
+
+ if ((first_fragment >= s->fragment_count) ||
+ (last_fragment >= s->fragment_count)) {
+
+ av_log(s->avctx, AV_LOG_ERROR, " vp3:unpack_vlcs(): bad fragment number (%d -> %d ?)\n",
+ first_fragment, last_fragment);
+ return 0;
+ }
+
+ for (i = first_fragment; i <= last_fragment; i++) {
+
+ fragment = &s->all_fragments[s->coded_fragment_list[i]];
+ if (fragment->coeff_count > coeff_index)
+ continue;
+
+ if (!eob_run) {
+ /* decode a VLC into a token */
+ token = get_vlc2(gb, table->table, 5, 3);
+ debug_vlc(" token = %2d, ", token);
+ /* use the token to get a zero run, a coefficient, and an eob run */
+ if (token <= 6) {
+ eob_run = eob_run_base[token];
+ if (eob_run_get_bits[token])
+ eob_run += get_bits(gb, eob_run_get_bits[token]);
+ coeff = zero_run = 0;
+ } else {
+ bits_to_get = coeff_get_bits[token];
+ if (!bits_to_get)
+ coeff = coeff_tables[token][0];
+ else
+ coeff = coeff_tables[token][get_bits(gb, 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 (!eob_run) {
+ fragment->coeff_count += zero_run;
+ if (fragment->coeff_count < 64){
+ fragment->next_coeff->coeff= coeff;
+ fragment->next_coeff->index= perm[fragment->coeff_count++]; //FIXME perm here already?
+ fragment->next_coeff->next= s->next_coeff;
+ s->next_coeff->next=NULL;
+ fragment->next_coeff= s->next_coeff++;
+ }
+ debug_vlc(" fragment %d coeff = %d\n",
+ s->coded_fragment_list[i], fragment->next_coeff[coeff_index]);
+ } else {
+ fragment->coeff_count |= 128;
+ debug_vlc(" fragment %d eob with %d coefficients\n",
+ s->coded_fragment_list[i], fragment->coeff_count&127);
+ eob_run--;
+ }
+ }
+
+ return eob_run;
+}
+
+/*
+ * 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;
+
+ /* fetch the DC table indices */
+ dc_y_table = get_bits(gb, 4);
+ dc_c_table = get_bits(gb, 4);
+
+ /* unpack the Y plane DC coefficients */
+ debug_vp3(" vp3: unpacking Y plane DC coefficients using table %d\n",
+ dc_y_table);
+ residual_eob_run = unpack_vlcs(s, gb, &s->dc_vlc[dc_y_table], 0,
+ s->first_coded_y_fragment, s->last_coded_y_fragment, residual_eob_run);
+
+ /* unpack the C plane DC coefficients */
+ debug_vp3(" vp3: unpacking C plane DC coefficients using table %d\n",
+ dc_c_table);
+ residual_eob_run = unpack_vlcs(s, gb, &s->dc_vlc[dc_c_table], 0,
+ s->first_coded_c_fragment, s->last_coded_c_fragment, residual_eob_run);
+
+ /* fetch the AC table indices */
+ ac_y_table = get_bits(gb, 4);
+ ac_c_table = get_bits(gb, 4);
+
+ /* unpack the group 1 AC coefficients (coeffs 1-5) */
+ for (i = 1; i <= 5; i++) {
+
+ debug_vp3(" vp3: unpacking level %d Y plane AC coefficients using table %d\n",
+ i, ac_y_table);
+ residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_1[ac_y_table], i,
+ s->first_coded_y_fragment, s->last_coded_y_fragment, residual_eob_run);
+
+ debug_vp3(" vp3: unpacking level %d C plane AC coefficients using table %d\n",
+ i, ac_c_table);
+ residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_1[ac_c_table], i,
+ s->first_coded_c_fragment, s->last_coded_c_fragment, residual_eob_run);
+ }
+
+ /* unpack the group 2 AC coefficients (coeffs 6-14) */
+ for (i = 6; i <= 14; i++) {
+
+ debug_vp3(" vp3: unpacking level %d Y plane AC coefficients using table %d\n",
+ i, ac_y_table);
+ residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_2[ac_y_table], i,
+ s->first_coded_y_fragment, s->last_coded_y_fragment, residual_eob_run);
+
+ debug_vp3(" vp3: unpacking level %d C plane AC coefficients using table %d\n",
+ i, ac_c_table);
+ residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_2[ac_c_table], i,
+ s->first_coded_c_fragment, s->last_coded_c_fragment, residual_eob_run);
+ }
+
+ /* unpack the group 3 AC coefficients (coeffs 15-27) */
+ for (i = 15; i <= 27; i++) {
+
+ debug_vp3(" vp3: unpacking level %d Y plane AC coefficients using table %d\n",
+ i, ac_y_table);
+ residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_3[ac_y_table], i,
+ s->first_coded_y_fragment, s->last_coded_y_fragment, residual_eob_run);
+
+ debug_vp3(" vp3: unpacking level %d C plane AC coefficients using table %d\n",
+ i, ac_c_table);
+ residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_3[ac_c_table], i,
+ s->first_coded_c_fragment, s->last_coded_c_fragment, residual_eob_run);
+ }
+
+ /* unpack the group 4 AC coefficients (coeffs 28-63) */
+ for (i = 28; i <= 63; i++) {
+
+ debug_vp3(" vp3: unpacking level %d Y plane AC coefficients using table %d\n",
+ i, ac_y_table);
+ residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_4[ac_y_table], i,
+ s->first_coded_y_fragment, s->last_coded_y_fragment, residual_eob_run);
+
+ debug_vp3(" vp3: unpacking level %d C plane AC coefficients using table %d\n",
+ i, ac_c_table);
+ residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_4[ac_c_table], i,
+ s->first_coded_c_fragment, s->last_coded_c_fragment, 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 FRAME_CODED(x) (s->all_fragments[x].coding_method != MODE_COPY)
+#define DC_COEFF(u) (s->coeffs[u].index ? 0 : s->coeffs[u].coeff) //FIXME do somethin to simplify this
+
+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;
+
+ /* indices 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
+ */
+ 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. */
+ unsigned char compatible_frame[8] = {
+ 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 */
+ };
+ int current_frame_type;
+
+ /* there is a last DC predictor for each of the 3 frame types */
+ short last_dc[3];
+
+ int transform = 0;
+
+ debug_vp3(" vp3: reversing DC prediction\n");
+
+ 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];
+ debug_dc_pred(" frag %d: orig DC = %d, ",
+ i, DC_COEFF(i));
+
+ transform= 0;
+ if(x){
+ l= i-1;
+ vl = DC_COEFF(l);
+ if(FRAME_CODED(l) && COMPATIBLE_FRAME(l))
+ transform |= PL;
+ }
+ if(y){
+ u= i-fragment_width;
+ vu = DC_COEFF(u);
+ if(FRAME_CODED(u) && COMPATIBLE_FRAME(u))
+ transform |= PU;
+ if(x){
+ ul= i-fragment_width-1;
+ vul = DC_COEFF(ul);
+ if(FRAME_CODED(ul) && COMPATIBLE_FRAME(ul))
+ transform |= PUL;
+ }
+ if(x + 1 < fragment_width){
+ ur= i-fragment_width+1;
+ vur = DC_COEFF(ur);
+ if(FRAME_CODED(ur) && COMPATIBLE_FRAME(ur))
+ transform |= PUR;
+ }
+ }
+
+ debug_dc_pred("transform = %d, ", transform);
+
+ if (transform == 0) {
+
+ /* if there were no fragments to predict from, use last
+ * DC saved */
+ predicted_dc = last_dc[current_frame_type];
+ debug_dc_pred("from last DC (%d) = %d\n",
+ current_frame_type, DC_COEFF(i));
+
+ } 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 == 13) || (transform == 15)) {
+ 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;
+ }
+
+ debug_dc_pred("from pred DC = %d\n",
+ DC_COEFF(i));
+ }
+
+ /* at long last, apply the predictor */
+ if(s->coeffs[i].index){
+ *s->next_coeff= s->coeffs[i];
+ s->coeffs[i].index=0;
+ s->coeffs[i].coeff=0;
+ s->coeffs[i].next= s->next_coeff++;
+ }
+ s->coeffs[i].coeff += predicted_dc;
+ /* save the DC */
+ last_dc[current_frame_type] = DC_COEFF(i);
+ if(DC_COEFF(i) && !(s->all_fragments[i].coeff_count&127)){
+ s->all_fragments[i].coeff_count= 129;
+// s->all_fragments[i].next_coeff= s->next_coeff;
+ s->coeffs[i].next= s->next_coeff;
+ (s->next_coeff++)->next=NULL;
+ }
+ }
+ }
+ }
+}
+
+
+static void horizontal_filter(unsigned char *first_pixel, int stride,
+ int *bounding_values);
+static void vertical_filter(unsigned char *first_pixel, int stride,
+ int *bounding_values);
+
+/*
+ * Perform the final rendering for a particular slice of data.
+ * The slice number ranges from 0..(macroblock_height - 1).
+ */
+static void render_slice(Vp3DecodeContext *s, int slice)
+{
+ int x;
+ int m, n;
+ int16_t *dequantizer;
+ DECLARE_ALIGNED_16(DCTELEM, block[64]);
+ int motion_x = 0xdeadbeef, motion_y = 0xdeadbeef;
+ int motion_halfpel_index;
+ uint8_t *motion_source;
+ int plane;
+ int current_macroblock_entry = slice * s->macroblock_width * 6;
+
+ if (slice >= s->macroblock_height)
+ return;
+
+ for (plane = 0; plane < 3; plane++) {
+ uint8_t *output_plane = s->current_frame.data [plane];
+ uint8_t * last_plane = s-> last_frame.data [plane];
+ uint8_t *golden_plane = s-> golden_frame.data [plane];
+ int stride = s->current_frame.linesize[plane];
+ int plane_width = s->width >> !!plane;
+ int plane_height = s->height >> !!plane;
+ int y = slice * FRAGMENT_PIXELS << !plane ;
+ int slice_height = y + (FRAGMENT_PIXELS << !plane);
+ int i = s->macroblock_fragments[current_macroblock_entry + plane + 3*!!plane];
+
+ if (!s->flipped_image) stride = -stride;
+
+
+ if(FFABS(stride) > 2048)
+ return; //various tables are fixed size
+
+ /* for each fragment row in the slice (both of them)... */
+ for (; y < slice_height; y += 8) {
+
+ /* for each fragment in a row... */
+ for (x = 0; x < plane_width; x += 8, i++) {
+
+ if ((i < 0) || (i >= s->fragment_count)) {
+ av_log(s->avctx, AV_LOG_ERROR, " vp3:render_slice(): bad fragment number (%d)\n", i);
+ return;
+ }
+
+ /* transform if this block was coded */
+ if ((s->all_fragments[i].coding_method != MODE_COPY) &&
+ !((s->avctx->flags & CODEC_FLAG_GRAY) && plane)) {
+
+ 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 += s->all_fragments[i].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 = s->all_fragments[i].motion_x;
+ motion_y = s->all_fragments[i].motion_y;
+ if(plane){
+ motion_x= (motion_x>>1) | (motion_x&1);
+ motion_y= (motion_y>>1) | (motion_y&1);
+ }
+
+ src_x= (motion_x>>1) + x;
+ src_y= (motion_y>>1) + y;
+ if ((motion_x == 127) || (motion_y == 127))
+ av_log(s->avctx, AV_LOG_ERROR, " help! got invalid motion vector! (%X, %X)\n", motion_x, motion_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 -= 9*stride;
+ else temp += 9*stride;
+
+ ff_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->dsp.put_no_rnd_pixels_tab[1][motion_halfpel_index](
+ output_plane + s->all_fragments[i].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->dsp.put_no_rnd_pixels_l2[1](
+ output_plane + s->all_fragments[i].first_pixel,
+ motion_source - d,
+ motion_source + stride + 1 + d,
+ stride, 8);
+ }
+ dequantizer = s->qmat[1][plane];
+ }else{
+ dequantizer = s->qmat[0][plane];
+ }
+
+ /* dequantize the DCT coefficients */
+ debug_idct("fragment %d, coding mode %d, DC = %d, dequant = %d:\n",
+ i, s->all_fragments[i].coding_method,
+ DC_COEFF(i), dequantizer[0]);
+
+ if(s->avctx->idct_algo==FF_IDCT_VP3){
+ Coeff *coeff= s->coeffs + i;
+ memset(block, 0, sizeof(block));
+ while(coeff->next){
+ block[coeff->index]= coeff->coeff * dequantizer[coeff->index];
+ coeff= coeff->next;
+ }
+ }else{
+ Coeff *coeff= s->coeffs + i;
+ memset(block, 0, sizeof(block));
+ while(coeff->next){
+ block[coeff->index]= (coeff->coeff * dequantizer[coeff->index] + 2)>>2;
+ coeff= coeff->next;
+ }
+ }
+
+ /* invert DCT and place (or add) in final output */
+
+ if (s->all_fragments[i].coding_method == MODE_INTRA) {
+ if(s->avctx->idct_algo!=FF_IDCT_VP3)
+ block[0] += 128<<3;
+ s->dsp.idct_put(
+ output_plane + s->all_fragments[i].first_pixel,
+ stride,
+ block);
+ } else {
+ s->dsp.idct_add(
+ output_plane + s->all_fragments[i].first_pixel,
+ stride,
+ block);
+ }
+
+ debug_idct("block after idct_%s():\n",
+ (s->all_fragments[i].coding_method == MODE_INTRA)?
+ "put" : "add");
+ for (m = 0; m < 8; m++) {
+ for (n = 0; n < 8; n++) {
+ debug_idct(" %3d", *(output_plane +
+ s->all_fragments[i].first_pixel + (m * stride + n)));
+ }
+ debug_idct("\n");
+ }
+ debug_idct("\n");
+
+ } else {
+
+ /* copy directly from the previous frame */
+ s->dsp.put_pixels_tab[1][0](
+ output_plane + s->all_fragments[i].first_pixel,
+ last_plane + s->all_fragments[i].first_pixel,
+ stride, 8);
+
+ }
+#if 0
+ /* perform the left edge filter if:
+ * - the fragment is not on the left column
+ * - the fragment is coded in this frame
+ * - the fragment is not coded in this frame but the left
+ * fragment is coded in this frame (this is done instead
+ * of a right edge filter when rendering the left fragment
+ * since this fragment is not available yet) */
+ if ((x > 0) &&
+ ((s->all_fragments[i].coding_method != MODE_COPY) ||
+ ((s->all_fragments[i].coding_method == MODE_COPY) &&
+ (s->all_fragments[i - 1].coding_method != MODE_COPY)) )) {
+ horizontal_filter(
+ output_plane + s->all_fragments[i].first_pixel + 7*stride,
+ -stride, s->bounding_values_array + 127);
+ }
+
+ /* perform the top edge filter if:
+ * - the fragment is not on the top row
+ * - the fragment is coded in this frame
+ * - the fragment is not coded in this frame but the above
+ * fragment is coded in this frame (this is done instead
+ * of a bottom edge filter when rendering the above
+ * fragment since this fragment is not available yet) */
+ if ((y > 0) &&
+ ((s->all_fragments[i].coding_method != MODE_COPY) ||
+ ((s->all_fragments[i].coding_method == MODE_COPY) &&
+ (s->all_fragments[i - fragment_width].coding_method != MODE_COPY)) )) {
+ vertical_filter(
+ output_plane + s->all_fragments[i].first_pixel - stride,
+ -stride, s->bounding_values_array + 127);
+ }
+#endif
+ }
+ }
+ }
+
+ /* 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);
+ */
+
+ emms_c();
+}
+
+static void horizontal_filter(unsigned char *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] = clip_uint8(first_pixel[-1] + filter_value);
+ first_pixel[ 0] = clip_uint8(first_pixel[ 0] - filter_value);
+ }
+}
+
+static void vertical_filter(unsigned char *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] = clip_uint8(first_pixel[nstride] + filter_value);
+ first_pixel[0] = clip_uint8(first_pixel[0] - filter_value);
+ }
+}
+
+static void apply_loop_filter(Vp3DecodeContext *s)
+{
+ int plane;
+ int x, y;
+ int *bounding_values= s->bounding_values_array+127;
+
+#if 0
+ int bounding_values_array[256];
+ int filter_limit;
+
+ /* find the right loop limit value */
+ for (x = 63; x >= 0; x--) {
+ if (vp31_ac_scale_factor[x] >= s->quality_index)
+ break;
+ }
+ filter_limit = vp31_filter_limit_values[s->quality_index];
+
+ /* set up the bounding values */
+ memset(bounding_values_array, 0, 256 * sizeof(int));
+ for (x = 0; x < filter_limit; x++) {
+ bounding_values[-x - filter_limit] = -filter_limit + x;
+ bounding_values[-x] = -x;
+ bounding_values[x] = x;
+ bounding_values[x + filter_limit] = filter_limit - x;
+ }
+#endif
+
+ for (plane = 0; plane < 3; plane++) {
+ int width = s->fragment_width >> !!plane;
+ int height = s->fragment_height >> !!plane;
+ int fragment = s->fragment_start [plane];
+ int stride = s->current_frame.linesize[plane];
+ uint8_t *plane_data = s->current_frame.data [plane];
+ if (!s->flipped_image) stride = -stride;
+
+ for (y = 0; y < height; y++) {
+
+ for (x = 0; x < width; x++) {
+START_TIMER
+ /* do not perform left edge filter for left columns frags */
+ if ((x > 0) &&
+ (s->all_fragments[fragment].coding_method != MODE_COPY)) {
+ horizontal_filter(
+ plane_data + s->all_fragments[fragment].first_pixel,
+ stride, bounding_values);
+ }
+
+ /* do not perform top edge filter for top row fragments */
+ if ((y > 0) &&
+ (s->all_fragments[fragment].coding_method != MODE_COPY)) {
+ vertical_filter(
+ plane_data + s->all_fragments[fragment].first_pixel,
+ 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].coding_method != MODE_COPY) &&
+ (s->all_fragments[fragment + 1].coding_method == MODE_COPY)) {
+ horizontal_filter(
+ plane_data + s->all_fragments[fragment + 1].first_pixel,
+ 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].coding_method != MODE_COPY) &&
+ (s->all_fragments[fragment + width].coding_method == MODE_COPY)) {
+ vertical_filter(
+ plane_data + s->all_fragments[fragment + width].first_pixel,
+ stride, bounding_values);
+ }
+
+ fragment++;
+STOP_TIMER("loop filter")
+ }
+ }
+ }
+}
+
+/*
+ * This function computes the first pixel addresses for each fragment.
+ * This function needs to be invoked after the first frame is allocated
+ * so that it has access to the plane strides.
+ */
+static void vp3_calculate_pixel_addresses(Vp3DecodeContext *s)
+{
+
+ int i, x, y;
+
+ /* figure out the first pixel addresses for each of the fragments */
+ /* Y plane */
+ i = 0;
+ for (y = s->fragment_height; y > 0; y--) {
+ for (x = 0; x < s->fragment_width; x++) {
+ s->all_fragments[i++].first_pixel =
+ s->golden_frame.linesize[0] * y * FRAGMENT_PIXELS -
+ s->golden_frame.linesize[0] +
+ x * FRAGMENT_PIXELS;
+ debug_init(" fragment %d, first pixel @ %d\n",
+ i-1, s->all_fragments[i-1].first_pixel);
+ }
+ }
+
+ /* U plane */
+ i = s->fragment_start[1];
+ for (y = s->fragment_height / 2; y > 0; y--) {
+ for (x = 0; x < s->fragment_width / 2; x++) {
+ s->all_fragments[i++].first_pixel =
+ s->golden_frame.linesize[1] * y * FRAGMENT_PIXELS -
+ s->golden_frame.linesize[1] +
+ x * FRAGMENT_PIXELS;
+ debug_init(" fragment %d, first pixel @ %d\n",
+ i-1, s->all_fragments[i-1].first_pixel);
+ }
+ }
+
+ /* V plane */
+ i = s->fragment_start[2];
+ for (y = s->fragment_height / 2; y > 0; y--) {
+ for (x = 0; x < s->fragment_width / 2; x++) {
+ s->all_fragments[i++].first_pixel =
+ s->golden_frame.linesize[2] * y * FRAGMENT_PIXELS -
+ s->golden_frame.linesize[2] +
+ x * FRAGMENT_PIXELS;
+ debug_init(" fragment %d, first pixel @ %d\n",
+ i-1, s->all_fragments[i-1].first_pixel);
+ }
+ }
+}
+
+/* FIXME: this should be merged with the above! */
+static void theora_calculate_pixel_addresses(Vp3DecodeContext *s)
+{
+
+ int i, x, y;
+
+ /* figure out the first pixel addresses for each of the fragments */
+ /* Y plane */
+ i = 0;
+ for (y = 1; y <= s->fragment_height; y++) {
+ for (x = 0; x < s->fragment_width; x++) {
+ s->all_fragments[i++].first_pixel =
+ s->golden_frame.linesize[0] * y * FRAGMENT_PIXELS -
+ s->golden_frame.linesize[0] +
+ x * FRAGMENT_PIXELS;
+ debug_init(" fragment %d, first pixel @ %d\n",
+ i-1, s->all_fragments[i-1].first_pixel);
+ }
+ }
+
+ /* U plane */
+ i = s->fragment_start[1];
+ for (y = 1; y <= s->fragment_height / 2; y++) {
+ for (x = 0; x < s->fragment_width / 2; x++) {
+ s->all_fragments[i++].first_pixel =
+ s->golden_frame.linesize[1] * y * FRAGMENT_PIXELS -
+ s->golden_frame.linesize[1] +
+ x * FRAGMENT_PIXELS;
+ debug_init(" fragment %d, first pixel @ %d\n",
+ i-1, s->all_fragments[i-1].first_pixel);
+ }
+ }
+
+ /* V plane */
+ i = s->fragment_start[2];
+ for (y = 1; y <= s->fragment_height / 2; y++) {
+ for (x = 0; x < s->fragment_width / 2; x++) {
+ s->all_fragments[i++].first_pixel =
+ s->golden_frame.linesize[2] * y * FRAGMENT_PIXELS -
+ s->golden_frame.linesize[2] +
+ x * FRAGMENT_PIXELS;
+ debug_init(" fragment %d, first pixel @ %d\n",
+ i-1, s->all_fragments[i-1].first_pixel);
+ }
+ }
+}
+
+/*
+ * This is the ffmpeg/libavcodec API init function.
+ */
+static int vp3_decode_init(AVCodecContext *avctx)
+{
+ Vp3DecodeContext *s = avctx->priv_data;
+ int i, inter, plane;
+ int c_width;
+ int c_height;
+ int y_superblock_count;
+ int c_superblock_count;
+
+ if (avctx->codec_tag == MKTAG('V','P','3','0'))
+ s->version = 0;
+ else
+ s->version = 1;
+
+ s->avctx = avctx;
+ s->width = (avctx->width + 15) & 0xFFFFFFF0;
+ s->height = (avctx->height + 15) & 0xFFFFFFF0;
+ avctx->pix_fmt = PIX_FMT_YUV420P;
+ avctx->has_b_frames = 0;
+ if(avctx->idct_algo==FF_IDCT_AUTO)
+ avctx->idct_algo=FF_IDCT_VP3;
+ dsputil_init(&s->dsp, avctx);
+
+ ff_init_scantable(s->dsp.idct_permutation, &s->scantable, ff_zigzag_direct);
+
+ /* initialize to an impossible value which will force a recalculation
+ * in the first frame decode */
+ s->quality_index = -1;
+
+ s->y_superblock_width = (s->width + 31) / 32;
+ s->y_superblock_height = (s->height + 31) / 32;
+ y_superblock_count = s->y_superblock_width * s->y_superblock_height;
+
+ /* work out the dimensions for the C planes */
+ c_width = s->width / 2;
+ c_height = s->height / 2;
+ s->c_superblock_width = (c_width + 31) / 32;
+ s->c_superblock_height = (c_height + 31) / 32;
+ c_superblock_count = s->c_superblock_width * s->c_superblock_height;
+
+ s->superblock_count = y_superblock_count + (c_superblock_count * 2);
+ s->u_superblock_start = y_superblock_count;
+ s->v_superblock_start = s->u_superblock_start + c_superblock_count;
+ s->superblock_coding = av_malloc(s->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 = s->width / FRAGMENT_PIXELS;
+ s->fragment_height = s->height / FRAGMENT_PIXELS;
+
+ /* fragment count covers all 8x8 blocks for all 3 planes */
+ s->fragment_count = s->fragment_width * s->fragment_height * 3 / 2;
+ s->fragment_start[1] = s->fragment_width * s->fragment_height;
+ s->fragment_start[2] = s->fragment_width * s->fragment_height * 5 / 4;
+
+ debug_init(" Y plane: %d x %d\n", s->width, s->height);
+ debug_init(" C plane: %d x %d\n", c_width, c_height);
+ debug_init(" Y superblocks: %d x %d, %d total\n",
+ s->y_superblock_width, s->y_superblock_height, y_superblock_count);
+ debug_init(" C superblocks: %d x %d, %d total\n",
+ s->c_superblock_width, s->c_superblock_height, c_superblock_count);
+ debug_init(" total superblocks = %d, U starts @ %d, V starts @ %d\n",
+ s->superblock_count, s->u_superblock_start, s->v_superblock_start);
+ debug_init(" macroblocks: %d x %d, %d total\n",
+ s->macroblock_width, s->macroblock_height, s->macroblock_count);
+ debug_init(" %d fragments, %d x %d, u starts @ %d, v starts @ %d\n",
+ s->fragment_count,
+ s->fragment_width,
+ s->fragment_height,
+ s->fragment_start[1],
+ s->fragment_start[2]);
+
+ s->all_fragments = av_malloc(s->fragment_count * sizeof(Vp3Fragment));
+ s->coeffs = av_malloc(s->fragment_count * sizeof(Coeff) * 65);
+ s->coded_fragment_list = av_malloc(s->fragment_count * sizeof(int));
+ s->pixel_addresses_inited = 0;
+
+ 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], 5, 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], 5, 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], 5, 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], 5, 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], 5, 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 */
+ init_vlc(&s->dc_vlc[i], 5, 32,
+ &s->huffman_table[i][0][1], 4, 2,
+ &s->huffman_table[i][0][0], 4, 2, 0);
+
+ /* group 1 AC histograms */
+ init_vlc(&s->ac_vlc_1[i], 5, 32,
+ &s->huffman_table[i+16][0][1], 4, 2,
+ &s->huffman_table[i+16][0][0], 4, 2, 0);
+
+ /* group 2 AC histograms */
+ init_vlc(&s->ac_vlc_2[i], 5, 32,
+ &s->huffman_table[i+16*2][0][1], 4, 2,
+ &s->huffman_table[i+16*2][0][0], 4, 2, 0);
+
+ /* group 3 AC histograms */
+ init_vlc(&s->ac_vlc_3[i], 5, 32,
+ &s->huffman_table[i+16*3][0][1], 4, 2,
+ &s->huffman_table[i+16*3][0][0], 4, 2, 0);
+
+ /* group 4 AC histograms */
+ init_vlc(&s->ac_vlc_4[i], 5, 32,
+ &s->huffman_table[i+16*4][0][1], 4, 2,
+ &s->huffman_table[i+16*4][0][0], 4, 2, 0);
+ }
+ }
+
+ 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);
+
+ /* work out the block mapping tables */
+ s->superblock_fragments = av_malloc(s->superblock_count * 16 * sizeof(int));
+ s->superblock_macroblocks = av_malloc(s->superblock_count * 4 * sizeof(int));
+ s->macroblock_fragments = av_malloc(s->macroblock_count * 6 * sizeof(int));
+ s->macroblock_coding = av_malloc(s->macroblock_count + 1);
+ init_block_mapping(s);
+
+ for (i = 0; i < 3; i++) {
+ s->current_frame.data[i] = NULL;
+ s->last_frame.data[i] = NULL;
+ s->golden_frame.data[i] = NULL;
+ }
+
+ return 0;
+}
+
+/*
+ * This is the ffmpeg/libavcodec API frame decode function.
+ */
+static int vp3_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ Vp3DecodeContext *s = avctx->priv_data;
+ GetBitContext gb;
+ static int counter = 0;
+ int i;
+
+ init_get_bits(&gb, buf, buf_size * 8);
+
+ if (s->theora && get_bits1(&gb))
+ {
+#if 1
+ av_log(avctx, AV_LOG_ERROR, "Header packet passed to frame decoder, skipping\n");
+ return -1;
+#else
+ int ptype = get_bits(&gb, 7);
+
+ skip_bits(&gb, 6*8); /* "theora" */
+
+ switch(ptype)
+ {
+ case 1:
+ theora_decode_comments(avctx, &gb);
+ break;
+ case 2:
+ theora_decode_tables(avctx, &gb);
+ init_dequantizer(s);
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "Unknown Theora config packet: %d\n", ptype);
+ }
+ return buf_size;
+#endif
+ }
+
+ s->keyframe = !get_bits1(&gb);
+ if (!s->theora)
+ skip_bits(&gb, 1);
+ s->last_quality_index = s->quality_index;
+
+ s->nqis=0;
+ do{
+ s->qis[s->nqis++]= get_bits(&gb, 6);
+ } while(s->theora >= 0x030200 && s->nqis<3 && get_bits1(&gb));
+
+ s->quality_index= s->qis[0];
+
+ 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":"", counter, s->quality_index);
+ counter++;
+
+ if (s->quality_index != s->last_quality_index) {
+ init_dequantizer(s);
+ init_loop_filter(s);
+ }
+
+ 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 (counter == 1)
+ 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? */
+ }
+
+ if (s->last_frame.data[0] == s->golden_frame.data[0]) {
+ if (s->golden_frame.data[0])
+ avctx->release_buffer(avctx, &s->golden_frame);
+ s->last_frame= s->golden_frame; /* ensure that we catch any access to this released frame */
+ } else {
+ if (s->golden_frame.data[0])
+ avctx->release_buffer(avctx, &s->golden_frame);
+ if (s->last_frame.data[0])
+ avctx->release_buffer(avctx, &s->last_frame);
+ }
+
+ s->golden_frame.reference = 3;
+ if(avctx->get_buffer(avctx, &s->golden_frame) < 0) {
+ av_log(s->avctx, AV_LOG_ERROR, "vp3: get_buffer() failed\n");
+ return -1;
+ }
+
+ /* golden frame is also the current frame */
+ s->current_frame= s->golden_frame;
+
+ /* time to figure out pixel addresses? */
+ if (!s->pixel_addresses_inited)
+ {
+ if (!s->flipped_image)
+ vp3_calculate_pixel_addresses(s);
+ else
+ theora_calculate_pixel_addresses(s);
+ s->pixel_addresses_inited = 1;
+ }
+ } else {
+ /* allocate a new current frame */
+ s->current_frame.reference = 3;
+ if (!s->pixel_addresses_inited) {
+ av_log(s->avctx, AV_LOG_ERROR, "vp3: first frame not a keyframe\n");
+ return -1;
+ }
+ if(avctx->get_buffer(avctx, &s->current_frame) < 0) {
+ av_log(s->avctx, AV_LOG_ERROR, "vp3: get_buffer() failed\n");
+ return -1;
+ }
+ }
+
+ s->current_frame.qscale_table= s->qscale_table; //FIXME allocate individual tables per AVFrame
+ s->current_frame.qstride= 0;
+
+ {START_TIMER
+ init_frame(s, &gb);
+ STOP_TIMER("init_frame")}
+
+#if KEYFRAMES_ONLY
+if (!s->keyframe) {
+
+ memcpy(s->current_frame.data[0], s->golden_frame.data[0],
+ s->current_frame.linesize[0] * s->height);
+ memcpy(s->current_frame.data[1], s->golden_frame.data[1],
+ s->current_frame.linesize[1] * s->height / 2);
+ memcpy(s->current_frame.data[2], s->golden_frame.data[2],
+ s->current_frame.linesize[2] * s->height / 2);
+
+} else {
+#endif
+
+ {START_TIMER
+ if (unpack_superblocks(s, &gb)){
+ av_log(s->avctx, AV_LOG_ERROR, "error in unpack_superblocks\n");
+ return -1;
+ }
+ STOP_TIMER("unpack_superblocks")}
+ {START_TIMER
+ if (unpack_modes(s, &gb)){
+ av_log(s->avctx, AV_LOG_ERROR, "error in unpack_modes\n");
+ return -1;
+ }
+ STOP_TIMER("unpack_modes")}
+ {START_TIMER
+ if (unpack_vectors(s, &gb)){
+ av_log(s->avctx, AV_LOG_ERROR, "error in unpack_vectors\n");
+ return -1;
+ }
+ STOP_TIMER("unpack_vectors")}
+ {START_TIMER
+ if (unpack_dct_coeffs(s, &gb)){
+ av_log(s->avctx, AV_LOG_ERROR, "error in unpack_dct_coeffs\n");
+ return -1;
+ }
+ STOP_TIMER("unpack_dct_coeffs")}
+ {START_TIMER
+
+ reverse_dc_prediction(s, 0, s->fragment_width, s->fragment_height);
+ if ((avctx->flags & CODEC_FLAG_GRAY) == 0) {
+ reverse_dc_prediction(s, s->fragment_start[1],
+ s->fragment_width / 2, s->fragment_height / 2);
+ reverse_dc_prediction(s, s->fragment_start[2],
+ s->fragment_width / 2, s->fragment_height / 2);
+ }
+ STOP_TIMER("reverse_dc_prediction")}
+ {START_TIMER
+
+ for (i = 0; i < s->macroblock_height; i++)
+ render_slice(s, i);
+ STOP_TIMER("render_fragments")}
+
+ {START_TIMER
+ apply_loop_filter(s);
+ STOP_TIMER("apply_loop_filter")}
+#if KEYFRAMES_ONLY
+}
+#endif
+
+ *data_size=sizeof(AVFrame);
+ *(AVFrame*)data= s->current_frame;
+
+ /* release the last frame, if it is allocated and if it is not the
+ * golden frame */
+ if ((s->last_frame.data[0]) &&
+ (s->last_frame.data[0] != s->golden_frame.data[0]))
+ avctx->release_buffer(avctx, &s->last_frame);
+
+ /* shuffle frames (last = current) */
+ s->last_frame= s->current_frame;
+ s->current_frame.data[0]= NULL; /* ensure that we catch any access to this released frame */
+
+ return buf_size;
+}
+
+/*
+ * This is the ffmpeg/libavcodec API module cleanup function.
+ */
+static int vp3_decode_end(AVCodecContext *avctx)
+{
+ Vp3DecodeContext *s = avctx->priv_data;
+
+ av_free(s->all_fragments);
+ av_free(s->coeffs);
+ av_free(s->coded_fragment_list);
+ av_free(s->superblock_fragments);
+ av_free(s->superblock_macroblocks);
+ av_free(s->macroblock_fragments);
+ av_free(s->macroblock_coding);
+
+ /* release all frames */
+ if (s->golden_frame.data[0] && s->golden_frame.data[0] != s->last_frame.data[0])
+ avctx->release_buffer(avctx, &s->golden_frame);
+ if (s->last_frame.data[0])
+ avctx->release_buffer(avctx, &s->last_frame);
+ /* no need to release the current_frame since it will always be pointing
+ * to the same frame as either the golden or last frame */
+
+ return 0;
+}
+
+static int read_huffman_tree(AVCodecContext *avctx, GetBitContext *gb)
+{
+ Vp3DecodeContext *s = avctx->priv_data;
+
+ if (get_bits(gb, 1)) {
+ 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_log(avctx, AV_LOG_DEBUG, "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;
+ read_huffman_tree(avctx, gb);
+ s->hbits |= 1;
+ read_huffman_tree(avctx, gb);
+ s->hbits >>= 1;
+ s->huff_code_size--;
+ }
+ return 0;
+}
+
+static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb)
+{
+ Vp3DecodeContext *s = avctx->priv_data;
+
+ s->theora = get_bits_long(gb, 24);
+ av_log(avctx, AV_LOG_INFO, "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 (<alpha3) Theora bitstream, flipped image\n");
+ }
+
+ s->width = get_bits(gb, 16) << 4;
+ s->height = get_bits(gb, 16) << 4;
+
+ if(avcodec_check_dimensions(avctx, s->width, s->height)){
+ 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 >= 0x030400)
+ {
+ skip_bits(gb, 32); /* total number of superblocks in a frame */
+ // fixme, the next field is 36bits long
+ skip_bits(gb, 32); /* total number of blocks in a frame */
+ skip_bits(gb, 4); /* total number of blocks in a frame */
+ skip_bits(gb, 32); /* total number of macroblocks in a frame */
+
+ skip_bits(gb, 24); /* frame width */
+ skip_bits(gb, 24); /* frame height */
+ }
+ else
+ {
+ skip_bits(gb, 24); /* frame width */
+ skip_bits(gb, 24); /* frame height */
+ }
+
+ if (s->theora >= 0x030200) {
+ skip_bits(gb, 8); /* offset x */
+ skip_bits(gb, 8); /* offset y */
+ }
+
+ skip_bits(gb, 32); /* fps numerator */
+ skip_bits(gb, 32); /* fps denumerator */
+ skip_bits(gb, 24); /* aspect numerator */
+ skip_bits(gb, 24); /* aspect denumerator */
+
+ if (s->theora < 0x030200)
+ skip_bits(gb, 5); /* keyframe frequency force */
+ skip_bits(gb, 8); /* colorspace */
+ if (s->theora >= 0x030400)
+ skip_bits(gb, 2); /* pixel format: 420,res,422,444 */
+ skip_bits(gb, 24); /* bitrate */
+
+ skip_bits(gb, 6); /* quality hint */
+
+ if (s->theora >= 0x030200)
+ {
+ skip_bits(gb, 5); /* keyframe frequency force */
+
+ if (s->theora < 0x030400)
+ skip_bits(gb, 5); /* spare bits */
+ }
+
+// align_get_bits(gb);
+
+ avctx->width = s->width;
+ avctx->height = s->height;
+
+ 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 */
+ 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; n<matrices; n++){
+ for (i = 0; i < 64; i++)
+ s->base_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_bits(gb, 1);
+ if (!newqr) {
+ int qtj, plj;
+ if(inter && get_bits(gb, 1)){
+ 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_bits(gb, 1)) {
+ s->hbits = 0;
+ read_huffman_tree(avctx, gb);
+ s->hbits = 1;
+ read_huffman_tree(avctx, gb);
+ }
+ }
+
+ s->theora_tables = 1;
+
+ return 0;
+}
+
+static int theora_decode_init(AVCodecContext *avctx)
+{
+ Vp3DecodeContext *s = avctx->priv_data;
+ GetBitContext gb;
+ int ptype;
+ uint8_t *p= avctx->extradata;
+ int op_bytes, i;
+
+ s->theora = 1;
+
+ if (!avctx->extradata_size)
+ {
+ av_log(avctx, AV_LOG_ERROR, "Missing extradata!\n");
+ return -1;
+ }
+
+ for(i=0;i<3;i++) {
+ op_bytes = *(p++)<<8;
+ op_bytes += *(p++);
+
+ init_get_bits(&gb, p, op_bytes);
+ p += op_bytes;
+
+ ptype = get_bits(&gb, 8);
+ debug_vp3("Theora headerpacket type: %x\n", ptype);
+
+ if (!(ptype & 0x80))
+ {
+ av_log(avctx, AV_LOG_ERROR, "Invalid extradata!\n");
+// return -1;
+ }
+
+ // FIXME: check for this aswell
+ skip_bits(&gb, 6*8); /* "theora" */
+
+ switch(ptype)
+ {
+ case 0x80:
+ theora_decode_header(avctx, &gb);
+ break;
+ case 0x81:
+// FIXME: is this needed? it breaks sometimes
+// theora_decode_comments(avctx, gb);
+ break;
+ case 0x82:
+ theora_decode_tables(avctx, &gb);
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "Unknown Theora config packet: %d\n", ptype&~0x80);
+ break;
+ }
+ if(8*op_bytes != get_bits_count(&gb))
+ av_log(avctx, AV_LOG_ERROR, "%d bits left in packet %X\n", 8*op_bytes - get_bits_count(&gb), ptype);
+ if (s->theora < 0x030200)
+ break;
+ }
+
+ vp3_decode_init(avctx);
+ return 0;
+}
+
+AVCodec vp3_decoder = {
+ "vp3",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_VP3,
+ sizeof(Vp3DecodeContext),
+ vp3_decode_init,
+ NULL,
+ vp3_decode_end,
+ vp3_decode_frame,
+ 0,
+ NULL
+};
+
+#ifndef CONFIG_LIBTHEORA
+AVCodec theora_decoder = {
+ "theora",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_THEORA,
+ sizeof(Vp3DecodeContext),
+ theora_decode_init,
+ NULL,
+ vp3_decode_end,
+ vp3_decode_frame,
+ 0,
+ NULL
+};
+#endif
diff --git a/contrib/ffmpeg/libavcodec/vp3data.h b/contrib/ffmpeg/libavcodec/vp3data.h
new file mode 100644
index 000000000..d69ddfa28
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vp3data.h
@@ -0,0 +1,3178 @@
+/*
+ * 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 VP3DATA_H
+#define VP3DATA_H
+
+/* 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 uint32_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 *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 /* VP3DATA_H */
diff --git a/contrib/ffmpeg/libavcodec/vp3dsp.c b/contrib/ffmpeg/libavcodec/vp3dsp.c
new file mode 100644
index 000000000..a48515a5e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vp3dsp.c
@@ -0,0 +1,225 @@
+/*
+ * 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 vp3dsp.c
+ * Standard C DSP-oriented functions cribbed from the original VP3
+ * source code.
+ */
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.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 always_inline void idct(uint8_t *dst, int stride, int16_t *input, int type)
+{
+ int16_t *ip = input;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ 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] | 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]));
+ F = M(xC4S4, (ip[0] - ip[4]));
+
+ 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. */
+ ip[0] = Gd + Cd ;
+ ip[7] = Gd - Cd ;
+
+ ip[1] = Add + Hd;
+ ip[2] = Add - Hd;
+
+ ip[3] = Ed + Dd ;
+ ip[4] = Ed - Dd ;
+
+ ip[5] = Fd + Bdd;
+ ip[6] = Fd - Bdd;
+ }
+
+ ip += 8; /* next row */
+ }
+
+ ip = input;
+
+ for ( i = 0; i < 8; i++) {
+ /* Check for non-zero values (bitwise or faster than ||) */
+ if ( 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])) + 8;
+ F = M(xC4S4, (ip[0*8] - ip[4*8])) + 8;
+
+ if(type==1){ //HACK
+ E += 16*128;
+ F += 16*128;
+ }
+
+ 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. */
+ if(type==0){
+ ip[0*8] = (Gd + Cd ) >> 4;
+ ip[7*8] = (Gd - Cd ) >> 4;
+
+ ip[1*8] = (Add + Hd ) >> 4;
+ ip[2*8] = (Add - Hd ) >> 4;
+
+ ip[3*8] = (Ed + Dd ) >> 4;
+ ip[4*8] = (Ed - Dd ) >> 4;
+
+ ip[5*8] = (Fd + Bdd ) >> 4;
+ ip[6*8] = (Fd - Bdd ) >> 4;
+ }else if(type==1){
+ dst[0*stride] = cm[(Gd + Cd ) >> 4];
+ dst[7*stride] = cm[(Gd - Cd ) >> 4];
+
+ dst[1*stride] = cm[(Add + Hd ) >> 4];
+ dst[2*stride] = cm[(Add - Hd ) >> 4];
+
+ dst[3*stride] = cm[(Ed + Dd ) >> 4];
+ dst[4*stride] = cm[(Ed - Dd ) >> 4];
+
+ dst[5*stride] = cm[(Fd + Bdd ) >> 4];
+ dst[6*stride] = cm[(Fd - Bdd ) >> 4];
+ }else{
+ dst[0*stride] = cm[dst[0*stride] + ((Gd + Cd ) >> 4)];
+ dst[7*stride] = cm[dst[7*stride] + ((Gd - Cd ) >> 4)];
+
+ dst[1*stride] = cm[dst[1*stride] + ((Add + Hd ) >> 4)];
+ dst[2*stride] = cm[dst[2*stride] + ((Add - Hd ) >> 4)];
+
+ dst[3*stride] = cm[dst[3*stride] + ((Ed + Dd ) >> 4)];
+ dst[4*stride] = cm[dst[4*stride] + ((Ed - Dd ) >> 4)];
+
+ dst[5*stride] = cm[dst[5*stride] + ((Fd + Bdd ) >> 4)];
+ dst[6*stride] = cm[dst[6*stride] + ((Fd - Bdd ) >> 4)];
+ }
+
+ } else {
+ if(type==0){
+ ip[0*8] =
+ ip[1*8] =
+ ip[2*8] =
+ ip[3*8] =
+ ip[4*8] =
+ ip[5*8] =
+ ip[6*8] =
+ ip[7*8] = ((xC4S4 * ip[0*8] + (IdctAdjustBeforeShift<<16))>>20);
+ }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]= 128 + ((xC4S4 * ip[0*8] + (IdctAdjustBeforeShift<<16))>>20);
+ }else{
+ if(ip[0*8]){
+ int v= ((xC4S4 * ip[0*8] + (IdctAdjustBeforeShift<<16))>>20);
+ dst[0*stride] = cm[dst[0*stride] + v];
+ dst[1*stride] = cm[dst[1*stride] + v];
+ dst[2*stride] = cm[dst[2*stride] + v];
+ dst[3*stride] = cm[dst[3*stride] + v];
+ dst[4*stride] = cm[dst[4*stride] + v];
+ dst[5*stride] = cm[dst[5*stride] + v];
+ dst[6*stride] = cm[dst[6*stride] + v];
+ dst[7*stride] = cm[dst[7*stride] + v];
+ }
+ }
+ }
+
+ ip++; /* next column */
+ dst++;
+ }
+}
+
+void ff_vp3_idct_c(DCTELEM *block/* align 16*/){
+ idct(NULL, 0, block, 0);
+}
+
+void ff_vp3_idct_put_c(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/){
+ idct(dest, line_size, block, 1);
+}
+
+void ff_vp3_idct_add_c(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/){
+ idct(dest, line_size, block, 2);
+}
diff --git a/contrib/ffmpeg/libavcodec/vp5.c b/contrib/ffmpeg/libavcodec/vp5.c
new file mode 100644
index 000000000..ac953c7aa
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vp5.c
@@ -0,0 +1,290 @@
+/**
+ * @file vp5.c
+ * VP5 compatible video decoder
+ *
+ * Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "avcodec.h"
+#include "dsputil.h"
+#include "bitstream.h"
+#include "mpegvideo.h"
+
+#include "vp56.h"
+#include "vp56data.h"
+#include "vp5data.h"
+
+
+static int vp5_parse_header(vp56_context_t *s, uint8_t *buf, int buf_size,
+ int *golden_frame)
+{
+ vp56_range_coder_t *c = &s->c;
+ int rows, cols;
+
+ vp56_init_range_decoder(&s->c, buf, buf_size);
+ s->frames[VP56_FRAME_CURRENT].key_frame = !vp56_rac_get(c);
+ vp56_rac_get(c);
+ 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 0;
+ vp56_rac_gets(c, 2);
+ if (vp56_rac_get(c)) {
+ av_log(s->avctx, AV_LOG_ERROR, "interlacing not supported\n");
+ return 0;
+ }
+ rows = vp56_rac_gets(c, 8); /* number of stored macroblock rows */
+ cols = vp56_rac_gets(c, 8); /* number of stored macroblock cols */
+ 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 (16*cols != s->avctx->coded_width ||
+ 16*rows != s->avctx->coded_height) {
+ avcodec_set_dimensions(s->avctx, 16*cols, 16*rows);
+ return 2;
+ }
+ }
+ return 1;
+}
+
+/* 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 void vp5_parse_vector_adjustment(vp56_context_t *s, vp56_mv_t *vect)
+{
+ vp56_range_coder_t *c = &s->c;
+ int comp, di;
+
+ for (comp=0; comp<2; comp++) {
+ int delta = 0;
+ if (vp56_rac_get_prob(c, s->vector_model_dct[comp])) {
+ int sign = vp56_rac_get_prob(c, s->vector_model_sig[comp]);
+ di = vp56_rac_get_prob(c, s->vector_model_pdi[comp][0]);
+ di |= vp56_rac_get_prob(c, s->vector_model_pdi[comp][1]) << 1;
+ delta = vp56_rac_get_tree(c, vp56_pva_tree,
+ s->vector_model_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(vp56_context_t *s)
+{
+ vp56_range_coder_t *c = &s->c;
+ int comp, node;
+
+ for (comp=0; comp<2; comp++) {
+ if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][0]))
+ s->vector_model_dct[comp] = vp56_rac_gets_nn(c, 7);
+ if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][1]))
+ s->vector_model_sig[comp] = vp56_rac_gets_nn(c, 7);
+ if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][2]))
+ s->vector_model_pdi[comp][0] = vp56_rac_gets_nn(c, 7);
+ if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][3]))
+ s->vector_model_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]))
+ s->vector_model_pdv[comp][node] = vp56_rac_gets_nn(c, 7);
+}
+
+static void vp5_parse_coeff_models(vp56_context_t *s)
+{
+ vp56_range_coder_t *c = &s->c;
+ 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);
+ s->coeff_model_dccv[pt][node] = def_prob[node];
+ } else if (s->frames[VP56_FRAME_CURRENT].key_frame) {
+ s->coeff_model_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);
+ s->coeff_model_ract[pt][ct][cg][node] = def_prob[node];
+ } else if (s->frames[VP56_FRAME_CURRENT].key_frame) {
+ s->coeff_model_ract[pt][ct][cg][node] = def_prob[node];
+ }
+
+ /* coeff_model_dcct is a linear combination of coeff_model_dccv */
+ for (pt=0; pt<2; pt++)
+ for (ctx=0; ctx<36; ctx++)
+ for (node=0; node<5; node++)
+ s->coeff_model_dcct[pt][ctx][node] = clip(((s->coeff_model_dccv[pt][node] * vp5_dccv_lc[node][ctx][0] + 128) >> 8) + vp5_dccv_lc[node][ctx][1], 1, 254);
+
+ /* coeff_model_acct is a linear combination of coeff_model_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++)
+ s->coeff_model_acct[pt][ct][cg][ctx][node] = clip(((s->coeff_model_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);
+}
+
+static void vp5_parse_coeff(vp56_context_t *s)
+{
+ vp56_range_coder_t *c = &s->c;
+ uint8_t *permute = s->scantable.permutated;
+ uint8_t *model, *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[vp56_b6to4[b]][0]
+ + s->above_blocks[s->above_block_idx[b]].not_null_dc;
+ model = s->coeff_model_dccv[pt];
+ model2 = s->coeff_model_dcct[pt][ctx];
+
+ for (coeff_idx=0; coeff_idx<64; ) {
+ 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[vp56_b6to4[b]][coeff_idx] = 4;
+ idx = vp56_rac_get_tree(c, vp56_pc_tree, model);
+ sign = vp56_rac_get(c);
+ coeff = vp56_coeff_bias[idx];
+ for (i=vp56_coeff_bit_length[idx]; i>=0; i--)
+ coeff += vp56_rac_get_prob(c, vp56_coeff_parse_table[idx][i]) << i;
+ } else {
+ if (vp56_rac_get_prob(c, model2[4])) {
+ coeff = 3 + vp56_rac_get_prob(c, model[5]);
+ s->coeff_ctx[vp56_b6to4[b]][coeff_idx] = 3;
+ } else {
+ coeff = 2;
+ s->coeff_ctx[vp56_b6to4[b]][coeff_idx] = 2;
+ }
+ sign = vp56_rac_get(c);
+ }
+ ct = 2;
+ } else {
+ ct = 1;
+ s->coeff_ctx[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[vp56_b6to4[b]][coeff_idx] = 0;
+ }
+
+ cg = vp5_coeff_groups[++coeff_idx];
+ ctx = s->coeff_ctx[vp56_b6to4[b]][coeff_idx];
+ model = s->coeff_model_ract[pt][ct][cg];
+ model2 = cg > 2 ? model : s->coeff_model_acct[pt][ct][cg][ctx];
+ }
+
+ ctx_last = FFMIN(s->coeff_ctx_last[vp56_b6to4[b]], 24);
+ s->coeff_ctx_last[vp56_b6to4[b]] = coeff_idx;
+ if (coeff_idx < ctx_last)
+ for (i=coeff_idx; i<=ctx_last; i++)
+ s->coeff_ctx[vp56_b6to4[b]][i] = 5;
+ s->above_blocks[s->above_block_idx[b]].not_null_dc = s->coeff_ctx[vp56_b6to4[b]][0];
+ }
+}
+
+static void vp5_default_models_init(vp56_context_t *s)
+{
+ int i;
+
+ for (i=0; i<2; i++) {
+ s->vector_model_sig[i] = 0x80;
+ s->vector_model_dct[i] = 0x80;
+ s->vector_model_pdi[i][0] = 0x55;
+ s->vector_model_pdi[i][1] = 0x80;
+ }
+ memcpy(s->mb_types_stats, vp56_def_mb_types_stats, sizeof(s->mb_types_stats));
+ memset(s->vector_model_pdv, 0x80, sizeof(s->vector_model_pdv));
+}
+
+static int vp5_decode_init(AVCodecContext *avctx)
+{
+ vp56_context_t *s = avctx->priv_data;
+
+ vp56_init(s, avctx, 1);
+ s->vp56_coord_div = vp5_coord_div;
+ s->parse_vector_adjustment = vp5_parse_vector_adjustment;
+ s->adjust = vp5_adjust;
+ 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 vp5_decoder = {
+ "vp5",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_VP5,
+ sizeof(vp56_context_t),
+ vp5_decode_init,
+ NULL,
+ vp56_free,
+ vp56_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/vp56.c b/contrib/ffmpeg/libavcodec/vp56.c
new file mode 100644
index 000000000..eb78d02e4
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vp56.c
@@ -0,0 +1,665 @@
+/**
+ * @file vp56.c
+ * VP5 and VP6 compatible video decoder (common features)
+ *
+ * Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avcodec.h"
+
+#include "vp56.h"
+#include "vp56data.h"
+
+
+void vp56_init_dequant(vp56_context_t *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(vp56_context_t *s, int row, int col,
+ vp56_frame_t ref_frame)
+{
+ int nb_pred = 0;
+ vp56_mv_t vect[2] = {{0,0}, {0,0}};
+ int pos, offset;
+ vp56_mv_t 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(vp56_context_t *s)
+{
+ vp56_range_coder_t *c = &s->c;
+ 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(s->mb_types_stats[ctx],vp56_pre_def_mb_type_stats[idx][ctx],
+ sizeof(s->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);
+ s->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 * s->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 */
+ s->mb_type_model[ctx][type][0] = 255 - (255 * s->mb_types_stats[ctx][type][0]) / (1 + s->mb_types_stats[ctx][type][0] + s->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;
+
+ s->mb_type_model[ctx][type][1] = 1 + 255 * p0234/(1+p0234+p156789);
+ s->mb_type_model[ctx][type][2] = 1 + 255 * p02 / (1+p0234);
+ s->mb_type_model[ctx][type][3] = 1 + 255 * p17 / (1+p156789);
+ s->mb_type_model[ctx][type][4] = 1 + 255 * p[0] / (1+p02);
+ s->mb_type_model[ctx][type][5] = 1 + 255 * p[3] / (1+p34);
+ s->mb_type_model[ctx][type][6] = 1 + 255 * p[1] / (1+p17);
+ s->mb_type_model[ctx][type][7] = 1 + 255 * p56 / (1+p5689);
+ s->mb_type_model[ctx][type][8] = 1 + 255 * p[5] / (1+p56);
+ s->mb_type_model[ctx][type][9] = 1 + 255 * p[8] / (1+p89);
+
+ /* restore initial value */
+ p[type] = 100 * s->mb_types_stats[ctx][type][1];
+ }
+ }
+}
+
+static vp56_mb_t vp56_parse_mb_type(vp56_context_t *s,
+ vp56_mb_t prev_type, int ctx)
+{
+ uint8_t *mb_type_model = s->mb_type_model[ctx][prev_type];
+ vp56_range_coder_t *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(vp56_context_t *s, int row, int col)
+{
+ vp56_mv_t 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] = (vp56_mv_t) {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 == 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] = (vp56_mv_t) {mv.x/4, mv.y/4};
+ }
+}
+
+static vp56_mb_t vp56_decode_mv(vp56_context_t *s, int row, int col)
+{
+ vp56_mv_t *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(vp56_context_t *s, vp56_frame_t ref_frame)
+{
+ int idx = s->scantable.permutated[0];
+ int i;
+
+ for (i=0; i<6; i++) {
+ vp56_ref_dc_t *ab = &s->above_blocks[s->above_block_idx[i]];
+ vp56_ref_dc_t *lb = &s->left_block[vp56_b6to4[i]];
+ int count = 0;
+ int dc = 0;
+
+ 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 == CODEC_ID_VP5) {
+ if (count < 2 && ref_frame == ab[-1].ref_frame) {
+ dc += ab[-1].dc_coeff;
+ count++;
+ }
+ if (count < 2 && ref_frame == ab[1].ref_frame) {
+ dc += ab[1].dc_coeff;
+ count++;
+ }
+ }
+ if (count == 0)
+ dc = s->prev_dc[vp56_b6to3[i]][ref_frame];
+ else if (count == 2)
+ dc /= 2;
+
+ s->block_coeff[i][idx] += dc;
+ s->prev_dc[vp56_b6to3[i]][ref_frame] = s->block_coeff[i][idx];
+ ab->dc_coeff = s->block_coeff[i][idx];
+ ab->ref_frame = ref_frame;
+ lb->dc_coeff = s->block_coeff[i][idx];
+ lb->ref_frame = ref_frame;
+ s->block_coeff[i][idx] *= s->dequant_dc;
+ }
+}
+
+static void vp56_edge_filter(vp56_context_t *s, uint8_t *yuv,
+ int pix_inc, int line_inc, 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 = s->adjust(v, t);
+ yuv[-pix_inc] = clip_uint8(yuv[-pix_inc] + v);
+ yuv[0] = clip_uint8(yuv[0] - v);
+ yuv += line_inc;
+ }
+}
+
+static void vp56_deblock_filter(vp56_context_t *s, uint8_t *yuv,
+ int stride, int dx, int dy)
+{
+ int t = vp56_filter_threshold[s->quantizer];
+ if (dx) vp56_edge_filter(s, yuv + 10-dx , 1, stride, t);
+ if (dy) vp56_edge_filter(s, yuv + stride*(10-dy), stride, 1, t);
+}
+
+static void vp56_mc(vp56_context_t *s, int b, uint8_t *src,
+ int stride, int x, int y)
+{
+ int plane = vp56_b6to3[b];
+ 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]) {
+ ff_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->dsp.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->dsp.put_no_rnd_pixels_l2[1](dst, src_block+src_offset,
+ src_block+src_offset+overlap_offset,
+ stride, 8);
+ } else {
+ s->dsp.put_pixels_tab[1][0](dst, src_block+src_offset, stride, 8);
+ }
+}
+
+static void vp56_decode_mb(vp56_context_t *s, int row, int col)
+{
+ AVFrame *frame_current, *frame_ref;
+ vp56_mb_t mb_type;
+ vp56_frame_t ref_frame;
+ int b, plan, 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];
+
+ memset(s->block_coeff, 0, sizeof(s->block_coeff));
+
+ s->parse_coeff(s);
+
+ vp56_add_predictors_dc(s, ref_frame);
+
+ frame_current = &s->frames[VP56_FRAME_CURRENT];
+ frame_ref = &s->frames[ref_frame];
+
+ switch (mb_type) {
+ case VP56_MB_INTRA:
+ for (b=0; b<6; b++) {
+ plan = vp56_b6to3[b];
+ s->dsp.idct_put(frame_current->data[plan] + s->block_offset[b],
+ s->stride[plan], s->block_coeff[b]);
+ }
+ break;
+
+ case VP56_MB_INTER_NOVEC_PF:
+ case VP56_MB_INTER_NOVEC_GF:
+ for (b=0; b<6; b++) {
+ plan = vp56_b6to3[b];
+ off = s->block_offset[b];
+ s->dsp.put_pixels_tab[1][0](frame_current->data[plan] + off,
+ frame_ref->data[plan] + off,
+ s->stride[plan], 8);
+ s->dsp.idct_add(frame_current->data[plan] + off,
+ s->stride[plan], 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; b<6; b++) {
+ int x_off = b==1 || b==3 ? 8 : 0;
+ int y_off = b==2 || b==3 ? 8 : 0;
+ plan = vp56_b6to3[b];
+ vp56_mc(s, b, frame_ref->data[plan], s->stride[plan],
+ 16*col+x_off, 16*row+y_off);
+ s->dsp.idct_add(frame_current->data[plan] + s->block_offset[b],
+ s->stride[plan], s->block_coeff[b]);
+ }
+ break;
+ }
+}
+
+static int vp56_size_changed(AVCodecContext *avctx, vp56_context_t *s)
+{
+ int stride = s->frames[VP56_FRAME_CURRENT].linesize[0];
+ int i;
+
+ s->plane_width[0] = s->avctx->coded_width;
+ s->plane_width[1] = s->plane_width[2] = s->avctx->coded_width/2;
+ s->plane_height[0] = s->avctx->coded_height;
+ s->plane_height[1] = s->plane_height[2] = s->avctx->coded_height/2;
+
+ for (i=0; i<3; i++)
+ s->stride[i] = s->flip * s->frames[VP56_FRAME_CURRENT].linesize[i];
+
+ s->mb_width = (s->avctx->coded_width+15) / 16;
+ s->mb_height = (s->avctx->coded_height+15) / 16;
+
+ if (s->mb_width > 1000 || s->mb_height > 1000) {
+ 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;
+
+ return 0;
+}
+
+int vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ vp56_context_t *s = avctx->priv_data;
+ AVFrame *const p = &s->frames[VP56_FRAME_CURRENT];
+ AVFrame *picture = data;
+ int mb_row, mb_col, mb_row_flip, mb_offset = 0;
+ int block, y, uv, stride_y, stride_uv;
+ int golden_frame = 0;
+ int res;
+
+ res = s->parse_header(s, buf, buf_size, &golden_frame);
+ if (!res)
+ return -1;
+
+ p->reference = 1;
+ if (avctx->get_buffer(avctx, p) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ if (res == 2)
+ if (vp56_size_changed(avctx, s)) {
+ avctx->release_buffer(avctx, p);
+ return -1;
+ }
+
+ if (p->key_frame) {
+ p->pict_type = FF_I_TYPE;
+ s->default_models_init(s);
+ for (block=0; block<s->mb_height*s->mb_width; block++)
+ s->macroblocks[block].type = VP56_MB_INTRA;
+ } else {
+ p->pict_type = FF_P_TYPE;
+ vp56_parse_mb_type_models(s);
+ s->parse_vector_models(s);
+ s->mb_type = VP56_MB_INTER_NOVEC_PF;
+ }
+
+ s->parse_coeff_models(s);
+
+ 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 = -1;
+ 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 = 0;
+ s->above_blocks[3*s->mb_width + 4].ref_frame = 0;
+
+ 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_row<s->mb_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 = -1;
+ s->left_block[block].dc_coeff = 0;
+ s->left_block[block].not_null_dc = 0;
+ memset(s->coeff_ctx[block], 0, 64*sizeof(s->coeff_ctx[block][0]));
+ }
+ 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_col<s->mb_width; mb_col++) {
+ vp56_decode_mb(s, mb_row, mb_col);
+
+ 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;
+ }
+ }
+ }
+
+ if (s->frames[VP56_FRAME_PREVIOUS].data[0]
+ && (s->frames[VP56_FRAME_PREVIOUS].data[0]
+ != s->frames[VP56_FRAME_GOLDEN].data[0])) {
+ avctx->release_buffer(avctx, &s->frames[VP56_FRAME_PREVIOUS]);
+ }
+ if (p->key_frame || golden_frame) {
+ if (s->frames[VP56_FRAME_GOLDEN].data[0])
+ avctx->release_buffer(avctx, &s->frames[VP56_FRAME_GOLDEN]);
+ s->frames[VP56_FRAME_GOLDEN] = *p;
+ }
+ s->frames[VP56_FRAME_PREVIOUS] = *p;
+
+ *picture = *p;
+ *data_size = sizeof(AVPicture);
+
+ return buf_size;
+}
+
+void vp56_init(vp56_context_t *s, AVCodecContext *avctx, int flip)
+{
+ int i;
+
+ s->avctx = avctx;
+ avctx->pix_fmt = PIX_FMT_YUV420P;
+
+ if (s->avctx->idct_algo == FF_IDCT_AUTO)
+ s->avctx->idct_algo = FF_IDCT_VP3;
+ dsputil_init(&s->dsp, s->avctx);
+ ff_init_scantable(s->dsp.idct_permutation, &s->scantable,ff_zigzag_direct);
+
+ avcodec_set_dimensions(s->avctx, 0, 0);
+
+ for (i=0; i<3; i++)
+ s->frames[i].data[0] = NULL;
+ s->edge_emu_buffer_alloc = NULL;
+
+ s->above_blocks = NULL;
+ s->macroblocks = NULL;
+ s->quantizer = -1;
+ s->deblock_filtering = 1;
+
+ s->filter = NULL;
+
+ if (flip) {
+ s->flip = -1;
+ s->frbi = 2;
+ s->srbi = 0;
+ } else {
+ s->flip = 1;
+ s->frbi = 0;
+ s->srbi = 2;
+ }
+}
+
+int vp56_free(AVCodecContext *avctx)
+{
+ vp56_context_t *s = avctx->priv_data;
+
+ av_free(s->above_blocks);
+ av_free(s->macroblocks);
+ av_free(s->edge_emu_buffer_alloc);
+ if (s->frames[VP56_FRAME_GOLDEN].data[0]
+ && (s->frames[VP56_FRAME_PREVIOUS].data[0]
+ != s->frames[VP56_FRAME_GOLDEN].data[0]))
+ avctx->release_buffer(avctx, &s->frames[VP56_FRAME_GOLDEN]);
+ if (s->frames[VP56_FRAME_PREVIOUS].data[0])
+ avctx->release_buffer(avctx, &s->frames[VP56_FRAME_PREVIOUS]);
+ return 0;
+}
diff --git a/contrib/ffmpeg/libavcodec/vp56.h b/contrib/ffmpeg/libavcodec/vp56.h
new file mode 100644
index 000000000..d6808b1e5
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vp56.h
@@ -0,0 +1,248 @@
+/**
+ * @file vp56.h
+ * VP5 and VP6 compatible video decoder (common features)
+ *
+ * Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef VP56_H
+#define VP56_H
+
+#include "vp56data.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+
+typedef struct vp56_context vp56_context_t;
+typedef struct vp56_mv vp56_mv_t;
+
+typedef void (*vp56_parse_vector_adjustment_t)(vp56_context_t *s,
+ vp56_mv_t *vect);
+typedef int (*vp56_adjust_t)(int v, int t);
+typedef void (*vp56_filter_t)(vp56_context_t *s, uint8_t *dst, uint8_t *src,
+ int offset1, int offset2, int stride,
+ vp56_mv_t mv, int mask, int select, int luma);
+typedef void (*vp56_parse_coeff_t)(vp56_context_t *s);
+typedef void (*vp56_default_models_init_t)(vp56_context_t *s);
+typedef void (*vp56_parse_vector_models_t)(vp56_context_t *s);
+typedef void (*vp56_parse_coeff_models_t)(vp56_context_t *s);
+typedef int (*vp56_parse_header_t)(vp56_context_t *s, uint8_t *buf,
+ int buf_size, int *golden_frame);
+
+typedef struct {
+ int high;
+ int bits;
+ const uint8_t *buffer;
+ unsigned long code_word;
+} vp56_range_coder_t;
+
+typedef struct {
+ uint8_t not_null_dc;
+ vp56_frame_t ref_frame;
+ DCTELEM dc_coeff;
+} vp56_ref_dc_t;
+
+struct vp56_mv {
+ int x;
+ int y;
+};
+
+typedef struct {
+ uint8_t type;
+ vp56_mv_t mv;
+} vp56_macroblock_t;
+
+struct vp56_context {
+ AVCodecContext *avctx;
+ DSPContext dsp;
+ ScanTable scantable;
+ AVFrame frames[3];
+ uint8_t *edge_emu_buffer_alloc;
+ uint8_t *edge_emu_buffer;
+ vp56_range_coder_t c;
+
+ /* frame info */
+ int plane_width[3];
+ int plane_height[3];
+ 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 */
+ vp56_ref_dc_t *above_blocks;
+ vp56_ref_dc_t left_block[4];
+ int above_block_idx[6];
+ DCTELEM prev_dc[3][3]; /* [plan][ref_frame] */
+
+ /* blocks / macroblock */
+ vp56_mb_t mb_type;
+ vp56_macroblock_t *macroblocks;
+ DECLARE_ALIGNED_16(DCTELEM, block_coeff[6][64]);
+ uint8_t coeff_reorder[64]; /* used in vp6 only */
+ uint8_t coeff_index_to_pos[64]; /* used in vp6 only */
+
+ /* motion vectors */
+ vp56_mv_t mv[6]; /* vectors for each block in MB */
+ vp56_mv_t vector_candidate[2];
+ int vector_candidate_pos;
+
+ /* filtering hints */
+ int deblock_filtering;
+ int filter_selection;
+ int filter_mode;
+ int max_vector_length;
+ int sample_variance_threshold;
+
+ /* AC models */
+ uint8_t vector_model_sig[2]; /* delta sign */
+ uint8_t vector_model_dct[2]; /* delta coding types */
+ uint8_t vector_model_pdi[2][2]; /* predefined delta init */
+ uint8_t vector_model_pdv[2][7]; /* predefined delta values */
+ uint8_t vector_model_fdv[2][8]; /* 8 bit delta value definition */
+ uint8_t mb_type_model[3][10][10]; /* model for decoding MB type */
+ uint8_t coeff_model_dccv[2][11]; /* DC coeff value */
+ uint8_t coeff_model_ract[2][3][6][11]; /* Run/AC coding type and AC coeff value */
+ uint8_t coeff_model_acct[2][3][3][6][5];/* vp5 only AC coding type for coding group < 3 */
+ uint8_t coeff_model_dcct[2][36][5]; /* DC coeff coding type */
+ uint8_t coeff_model_runv[2][14]; /* run value (vp6 only) */
+ uint8_t mb_types_stats[3][10][2]; /* contextual, next MB type stats */
+ uint8_t coeff_ctx[4][64]; /* used in vp5 only */
+ uint8_t coeff_ctx_last[4]; /* used in vp5 only */
+
+ /* 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[3]; /* stride for each plan */
+
+ const uint8_t *vp56_coord_div;
+ vp56_parse_vector_adjustment_t parse_vector_adjustment;
+ vp56_adjust_t adjust;
+ vp56_filter_t filter;
+ vp56_parse_coeff_t parse_coeff;
+ vp56_default_models_init_t default_models_init;
+ vp56_parse_vector_models_t parse_vector_models;
+ vp56_parse_coeff_models_t parse_coeff_models;
+ vp56_parse_header_t parse_header;
+};
+
+
+void vp56_init(vp56_context_t *s, AVCodecContext *avctx, int flip);
+int vp56_free(AVCodecContext *avctx);
+void vp56_init_dequant(vp56_context_t *s, int quantizer);
+int vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
+ uint8_t *buf, int buf_size);
+
+
+/**
+ * vp56 specific range coder implementation
+ */
+
+static inline void vp56_init_range_decoder(vp56_range_coder_t *c,
+ const uint8_t *buf, int buf_size)
+{
+ c->high = 255;
+ c->bits = 8;
+ c->buffer = buf;
+ c->code_word = *c->buffer++ << 8;
+ c->code_word |= *c->buffer++;
+}
+
+static inline int vp56_rac_get_prob(vp56_range_coder_t *c, uint8_t prob)
+{
+ unsigned int low = 1 + (((c->high - 1) * prob) / 256);
+ unsigned int low_shift = low << 8;
+ int bit = c->code_word >= low_shift;
+
+ if (bit) {
+ c->high -= low;
+ c->code_word -= low_shift;
+ } else {
+ c->high = low;
+ }
+
+ /* normalize */
+ while (c->high < 128) {
+ c->high <<= 1;
+ c->code_word <<= 1;
+ if (--c->bits == 0) {
+ c->bits = 8;
+ c->code_word |= *c->buffer++;
+ }
+ }
+ return bit;
+}
+
+static inline int vp56_rac_get(vp56_range_coder_t *c)
+{
+ /* equiprobable */
+ int low = (c->high + 1) >> 1;
+ unsigned int low_shift = low << 8;
+ int bit = c->code_word >= low_shift;
+ if (bit) {
+ c->high = (c->high - low) << 1;
+ c->code_word -= low_shift;
+ } else {
+ c->high = low << 1;
+ }
+
+ /* normalize */
+ c->code_word <<= 1;
+ if (--c->bits == 0) {
+ c->bits = 8;
+ c->code_word |= *c->buffer++;
+ }
+ return bit;
+}
+
+static inline int vp56_rac_gets(vp56_range_coder_t *c, int bits)
+{
+ int value = 0;
+
+ while (bits--) {
+ value = (value << 1) | vp56_rac_get(c);
+ }
+
+ return value;
+}
+
+static inline int vp56_rac_gets_nn(vp56_range_coder_t *c, int bits)
+{
+ int v = vp56_rac_gets(c, 7) << 1;
+ return v + !v;
+}
+
+static inline int vp56_rac_get_tree(vp56_range_coder_t *c,
+ const vp56_tree_t *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;
+}
+
+#endif /* VP56_H */
diff --git a/contrib/ffmpeg/libavcodec/vp56data.c b/contrib/ffmpeg/libavcodec/vp56data.c
new file mode 100644
index 000000000..e75c6d1ce
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vp56data.c
@@ -0,0 +1,66 @@
+/**
+ * @file vp56data.c
+ * VP5 and VP6 compatible video decoder (common data)
+ *
+ * Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "vp56data.h"
+
+const uint8_t vp56_b6to3[] = { 0, 0, 0, 0, 1, 2 };
+const uint8_t vp56_b6to4[] = { 0, 0, 1, 1, 2, 3 };
+
+const uint8_t 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 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 vp56_tree_t 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 vp56_tree_t vp56_pc_tree[] = {
+ { 4, 6},
+ { 2, 7}, {-0}, {-1},
+ { 4, 8},
+ { 2, 9}, {-2}, {-3},
+ { 2,10}, {-4}, {-5},
+};
+
+const uint8_t vp56_coeff_bias[] = { 5, 7, 11, 19, 35, 67 };
+const uint8_t vp56_coeff_bit_length[] = { 0, 1, 2, 3, 4, 10 };
diff --git a/contrib/ffmpeg/libavcodec/vp56data.h b/contrib/ffmpeg/libavcodec/vp56data.h
new file mode 100644
index 000000000..dbf92dd68
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vp56data.h
@@ -0,0 +1,248 @@
+/**
+ * @file vp56data.h
+ * VP5 and VP6 compatible video decoder (common data)
+ *
+ * Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef VP56DATA_H
+#define VP56DATA_H
+
+#include "common.h"
+
+typedef enum {
+ VP56_FRAME_CURRENT = 0,
+ VP56_FRAME_PREVIOUS = 1,
+ VP56_FRAME_GOLDEN = 2,
+} vp56_frame_t;
+
+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 */
+} vp56_mb_t;
+
+typedef struct {
+ int8_t val;
+ int8_t prob_idx;
+} vp56_tree_t;
+
+extern const uint8_t vp56_b6to3[];
+extern const uint8_t vp56_b6to4[];
+extern const uint8_t vp56_coeff_parse_table[6][11];
+extern const uint8_t vp56_def_mb_types_stats[3][10][2];
+extern const vp56_tree_t vp56_pva_tree[];
+extern const vp56_tree_t vp56_pc_tree[];
+extern const uint8_t vp56_coeff_bias[];
+extern const uint8_t vp56_coeff_bit_length[];
+
+static const vp56_frame_t 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 vp56_tree_t vp56_pmbtm_tree[] = {
+ { 4, 0},
+ { 2, 1}, {-8}, {-4},
+ { 8, 2},
+ { 6, 3},
+ { 4, 4},
+ { 2, 5}, {-24}, {-20}, {-16}, {-12}, {-0},
+};
+
+static const vp56_tree_t 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 /* VP56DATA */
diff --git a/contrib/ffmpeg/libavcodec/vp5data.h b/contrib/ffmpeg/libavcodec/vp5data.h
new file mode 100644
index 000000000..effc17c2c
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vp5data.h
@@ -0,0 +1,173 @@
+/**
+ * @file vp5data.h
+ * VP5 compatible video decoder
+ *
+ * Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef VP5DATA_H
+#define VP5DATA_H
+
+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 /* VP5DATA_H */
diff --git a/contrib/ffmpeg/libavcodec/vp6.c b/contrib/ffmpeg/libavcodec/vp6.c
new file mode 100644
index 000000000..b7ff004cc
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vp6.c
@@ -0,0 +1,522 @@
+/**
+ * @file vp6.c
+ * VP6 compatible video decoder
+ *
+ * Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ *
+ * The VP6F decoder accept an optional 1 byte extradata. It is composed of:
+ * - upper 4bits: difference between encoded width and visible width
+ * - lower 4bits: difference between encoded height and visible height
+ */
+
+#include <stdlib.h>
+
+#include "avcodec.h"
+#include "dsputil.h"
+#include "bitstream.h"
+#include "mpegvideo.h"
+
+#include "vp56.h"
+#include "vp56data.h"
+#include "vp6data.h"
+
+
+static int vp6_parse_header(vp56_context_t *s, uint8_t *buf, int buf_size,
+ int *golden_frame)
+{
+ vp56_range_coder_t *c = &s->c;
+ int parse_filter_info;
+ int rows, cols;
+ int res = 1;
+
+ if (buf[0] & 1)
+ return 0;
+
+ s->frames[VP56_FRAME_CURRENT].key_frame = !(buf[0] & 0x80);
+ vp56_init_dequant(s, (buf[0] >> 1) & 0x3F);
+
+ if (s->frames[VP56_FRAME_CURRENT].key_frame) {
+ if ((buf[1] & 0xFE) != 0x46) /* would be 0x36 for VP61 */
+ return 0;
+ if (buf[1] & 1) {
+ av_log(s->avctx, AV_LOG_ERROR, "interlacing not supported\n");
+ return 0;
+ }
+
+ 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 (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 = 2;
+ }
+
+ vp56_init_range_decoder(c, buf+6, buf_size-6);
+ vp56_rac_gets(c, 2);
+
+ parse_filter_info = 1;
+ } else {
+ vp56_init_range_decoder(c, buf+1, buf_size-1);
+
+ *golden_frame = vp56_rac_get(c);
+ s->deblock_filtering = vp56_rac_get(c);
+ if (s->deblock_filtering)
+ vp56_rac_get(c);
+ 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);
+ 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;
+ }
+ s->filter_selection = vp56_rac_gets(c, 4);
+ }
+
+ vp56_rac_get(c);
+ return res;
+}
+
+static void vp6_coeff_order_table_init(vp56_context_t *s)
+{
+ int i, pos, idx = 1;
+
+ s->coeff_index_to_pos[0] = 0;
+ for (i=0; i<16; i++)
+ for (pos=1; pos<64; pos++)
+ if (s->coeff_reorder[pos] == i)
+ s->coeff_index_to_pos[idx++] = pos;
+}
+
+static void vp6_default_models_init(vp56_context_t *s)
+{
+ s->vector_model_dct[0] = 0xA2;
+ s->vector_model_dct[1] = 0xA4;
+ s->vector_model_sig[0] = 0x80;
+ s->vector_model_sig[1] = 0x80;
+
+ memcpy(s->mb_types_stats, vp56_def_mb_types_stats, sizeof(s->mb_types_stats));
+ memcpy(s->vector_model_fdv, vp6_def_fdv_vector_model, sizeof(s->vector_model_fdv));
+ memcpy(s->vector_model_pdv, vp6_def_pdv_vector_model, sizeof(s->vector_model_pdv));
+ memcpy(s->coeff_model_runv, vp6_def_runv_coeff_model, sizeof(s->coeff_model_runv));
+ memcpy(s->coeff_reorder, vp6_def_coeff_reorder, sizeof(s->coeff_reorder));
+
+ vp6_coeff_order_table_init(s);
+}
+
+static void vp6_parse_vector_models(vp56_context_t *s)
+{
+ vp56_range_coder_t *c = &s->c;
+ int comp, node;
+
+ for (comp=0; comp<2; comp++) {
+ if (vp56_rac_get_prob(c, vp6_sig_dct_pct[comp][0]))
+ s->vector_model_dct[comp] = vp56_rac_gets_nn(c, 7);
+ if (vp56_rac_get_prob(c, vp6_sig_dct_pct[comp][1]))
+ s->vector_model_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]))
+ s->vector_model_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]))
+ s->vector_model_fdv[comp][node] = vp56_rac_gets_nn(c, 7);
+}
+
+static void vp6_parse_coeff_models(vp56_context_t *s)
+{
+ vp56_range_coder_t *c = &s->c;
+ 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);
+ s->coeff_model_dccv[pt][node] = def_prob[node];
+ } else if (s->frames[VP56_FRAME_CURRENT].key_frame) {
+ s->coeff_model_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]))
+ s->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]))
+ s->coeff_model_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);
+ s->coeff_model_ract[pt][ct][cg][node] = def_prob[node];
+ } else if (s->frames[VP56_FRAME_CURRENT].key_frame) {
+ s->coeff_model_ract[pt][ct][cg][node] = def_prob[node];
+ }
+
+ /* coeff_model_dcct is a linear combination of coeff_model_dccv */
+ for (pt=0; pt<2; pt++)
+ for (ctx=0; ctx<3; ctx++)
+ for (node=0; node<5; node++)
+ s->coeff_model_dcct[pt][ctx][node] = clip(((s->coeff_model_dccv[pt][node] * vp6_dccv_lc[ctx][node][0] + 128) >> 8) + vp6_dccv_lc[ctx][node][1], 1, 255);
+}
+
+static void vp6_parse_vector_adjustment(vp56_context_t *s, vp56_mv_t *vect)
+{
+ vp56_range_coder_t *c = &s->c;
+ int comp;
+
+ *vect = (vp56_mv_t) {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, s->vector_model_dct[comp])) {
+ static const uint8_t prob_order[] = {0, 1, 2, 7, 6, 5, 4};
+ for (i=0; i<sizeof(prob_order); i++) {
+ int j = prob_order[i];
+ delta |= vp56_rac_get_prob(c, s->vector_model_fdv[comp][j])<<j;
+ }
+ if (delta & 0xF0)
+ delta |= vp56_rac_get_prob(c, s->vector_model_fdv[comp][3])<<3;
+ else
+ delta |= 8;
+ } else {
+ delta = vp56_rac_get_tree(c, vp56_pva_tree,
+ s->vector_model_pdv[comp]);
+ }
+
+ if (delta && vp56_rac_get_prob(c, s->vector_model_sig[comp]))
+ delta = -delta;
+
+ if (!comp)
+ vect->x += delta;
+ else
+ vect->y += delta;
+ }
+}
+
+static void vp6_parse_coeff(vp56_context_t *s)
+{
+ vp56_range_coder_t *c = &s->c;
+ uint8_t *permute = s->scantable.permutated;
+ uint8_t *model, *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[vp56_b6to4[b]].not_null_dc
+ + s->above_blocks[s->above_block_idx[b]].not_null_dc;
+ model = s->coeff_model_dccv[pt];
+ model2 = s->coeff_model_dcct[pt][ctx];
+
+ for (coeff_idx=0; coeff_idx<64; ) {
+ if ((coeff_idx>1 && ct==0) || vp56_rac_get_prob(c, model2[0])) {
+ /* parse a coeff */
+ if (coeff_idx == 0) {
+ s->left_block[vp56_b6to4[b]].not_null_dc = 1;
+ s->above_blocks[s->above_block_idx[b]].not_null_dc = 1;
+ }
+
+ if (vp56_rac_get_prob(c, model2[2])) {
+ if (vp56_rac_get_prob(c, model2[3])) {
+ idx = vp56_rac_get_tree(c, vp56_pc_tree, model);
+ coeff = vp56_coeff_bias[idx];
+ for (i=vp56_coeff_bit_length[idx]; i>=0; i--)
+ coeff += vp56_rac_get_prob(c, vp56_coeff_parse_table[idx][i]) << i;
+ } else {
+ if (vp56_rac_get_prob(c, model2[4]))
+ coeff = 3 + vp56_rac_get_prob(c, model[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 = s->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) {
+ s->left_block[vp56_b6to4[b]].not_null_dc = 0;
+ s->above_blocks[s->above_block_idx[b]].not_null_dc = 0;
+ } else {
+ if (!vp56_rac_get_prob(c, model2[1]))
+ break;
+
+ model3 = s->coeff_model_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;
+ }
+ }
+
+ cg = vp6_coeff_groups[coeff_idx+=run];
+ model = model2 = s->coeff_model_ract[pt][ct][cg];
+ }
+ }
+}
+
+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;
+}
+
+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) / (16*16);
+}
+
+static void vp6_filter_hv2(vp56_context_t *s, uint8_t *dst, uint8_t *src,
+ int stride, int delta, int16_t weight)
+{
+ s->dsp.put_pixels_tab[1][0](dst, src, stride, 8);
+ s->dsp.biweight_h264_pixels_tab[3](dst, src+delta, stride, 2,
+ 8-weight, weight, 0);
+}
+
+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] = 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(vp56_context_t *s, uint8_t *dst, uint8_t *src,
+ int stride, int h_weight, int v_weight)
+{
+ uint8_t *tmp = s->edge_emu_buffer+16;
+ int x, xmax;
+
+ s->dsp.put_pixels_tab[1][0](tmp, src, stride, 8);
+ s->dsp.biweight_h264_pixels_tab[3](tmp, src+1, stride, 2,
+ 8-h_weight, h_weight, 0);
+ /* we need a 8x9 block to do vertical filter, so compute one more line */
+ for (x=8*stride, xmax=x+8; x<xmax; x++)
+ tmp[x] = (src[x]*(8-h_weight) + src[x+1]*h_weight + 4) >> 3;
+
+ s->dsp.put_pixels_tab[1][0](dst, tmp, stride, 8);
+ s->dsp.biweight_h264_pixels_tab[3](dst, tmp+stride, stride, 2,
+ 8-v_weight, v_weight, 0);
+}
+
+static void vp6_filter_diag4(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] = 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] = 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;
+ }
+}
+
+static void vp6_filter(vp56_context_t *s, uint8_t *dst, uint8_t *src,
+ int offset1, int offset2, int stride,
+ vp56_mv_t 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 if ((mv.x^mv.y) >> 31) { /* lower-left or upper-right combine */
+ vp6_filter_diag4(dst, src+offset1-1, stride,
+ vp6_block_copy_filter[select][x8],
+ vp6_block_copy_filter[select][y8]);
+ } else { /* lower-right or upper-left combine */
+ vp6_filter_diag4(dst, src+offset1, stride,
+ vp6_block_copy_filter[select][x8],
+ vp6_block_copy_filter[select][y8]);
+ }
+ } else {
+ if (!y8) { /* left or right combine */
+ vp6_filter_hv2(s, dst, src+offset1, stride, 1, x8);
+ } else if (!x8) { /* above or below combine */
+ vp6_filter_hv2(s, dst, src+offset1, stride, stride, y8);
+ } else if ((mv.x^mv.y) >> 31) { /* lower-left or upper-right combine */
+ vp6_filter_diag2(s, dst, src+offset1-1, stride, x8, y8);
+ } else { /* lower-right or upper-left combine */
+ vp6_filter_diag2(s, dst, src+offset1, stride, x8, y8);
+ }
+ }
+}
+
+static int vp6_decode_init(AVCodecContext *avctx)
+{
+ vp56_context_t *s = avctx->priv_data;
+
+ vp56_init(s, avctx, avctx->codec->id == CODEC_ID_VP6);
+ s->vp56_coord_div = vp6_coord_div;
+ s->parse_vector_adjustment = vp6_parse_vector_adjustment;
+ s->adjust = vp6_adjust;
+ s->filter = vp6_filter;
+ s->parse_coeff = vp6_parse_coeff;
+ 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;
+
+ return 0;
+}
+
+AVCodec vp6_decoder = {
+ "vp6",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_VP6,
+ sizeof(vp56_context_t),
+ vp6_decode_init,
+ NULL,
+ vp56_free,
+ vp56_decode_frame,
+};
+
+/* flash version, not flipped upside-down */
+AVCodec vp6f_decoder = {
+ "vp6f",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_VP6F,
+ sizeof(vp56_context_t),
+ vp6_decode_init,
+ NULL,
+ vp56_free,
+ vp56_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/vp6data.h b/contrib/ffmpeg/libavcodec/vp6data.h
new file mode 100644
index 000000000..ba4c7abf7
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vp6data.h
@@ -0,0 +1,292 @@
+/**
+ * @file vp6data.h
+ * VP6 compatible video decoder
+ *
+ * Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef VP6DATA_H
+#define 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[16][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 } },
+};
+
+static const vp56_tree_t 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 };
+
+#endif /* VP6DATA_H */
diff --git a/contrib/ffmpeg/libavcodec/vqavideo.c b/contrib/ffmpeg/libavcodec/vqavideo.c
new file mode 100644
index 000000000..912ced0df
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/vqavideo.c
@@ -0,0 +1,625 @@
+/*
+ * 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 vqavideo.c
+ * VQA Video Decoder by Mike Melanson (melanson@pcisys.net)
+ * For more information about the VQA format, visit:
+ * 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 indices. If the 12-bit indices 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+#include "dsputil.h"
+
+#define PALETTE_COUNT 256
+#define VQA_HEADER_SIZE 0x2A
+#define CHUNK_PREAMBLE_SIZE 8
+
+/* 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')
+
+#define VQA_DEBUG 0
+
+#if VQA_DEBUG
+#define vqa_debug printf
+#else
+static inline void vqa_debug(const char *format, ...) { }
+#endif
+
+typedef struct VqaContext {
+
+ AVCodecContext *avctx;
+ DSPContext dsp;
+ AVFrame frame;
+
+ unsigned char *buf;
+ int size;
+
+ 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 int vqa_decode_init(AVCodecContext *avctx)
+{
+ VqaContext *s = (VqaContext *)avctx->priv_data;
+ unsigned char *vqa_header;
+ int i, j, codebook_index;;
+
+ s->avctx = avctx;
+ avctx->pix_fmt = PIX_FMT_PAL8;
+ avctx->has_b_frames = 0;
+ dsputil_init(&s->dsp, avctx);
+
+ /* make sure the extradata made it */
+ if (s->avctx->extradata_size != VQA_HEADER_SIZE) {
+ av_log(s->avctx, AV_LOG_ERROR, " VQA video: expected extradata size of %d\n", VQA_HEADER_SIZE);
+ return -1;
+ }
+
+ /* load up the VQA parameters from the header */
+ vqa_header = (unsigned char *)s->avctx->extradata;
+ s->vqa_version = vqa_header[0];
+ s->width = LE_16(&vqa_header[6]);
+ s->height = LE_16(&vqa_header[8]);
+ if(avcodec_check_dimensions(avctx, s->width, s->height)){
+ s->width= s->height= 0;
+ return -1;
+ }
+ s->vector_width = vqa_header[10];
+ s->vector_height = vqa_header[11];
+ s->partial_count = s->partial_countdown = vqa_header[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 -1;
+ }
+
+ /* allocate codebooks */
+ s->codebook_size = MAX_CODEBOOK_SIZE;
+ s->codebook = av_malloc(s->codebook_size);
+ s->next_codebook_buffer = av_malloc(s->codebook_size);
+
+ /* 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;
+
+ /* 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);
+
+ s->frame.data[0] = NULL;
+
+ return 0;
+}
+
+#define CHECK_COUNT() \
+ if (dest_index + count > dest_size) { \
+ av_log(NULL, AV_LOG_ERROR, " VQA video: decode_format80 problem: next op would overflow dest_index\n"); \
+ av_log(NULL, AV_LOG_ERROR, " VQA video: current dest_index = %d, count = %d, dest_size = %d\n", \
+ dest_index, count, dest_size); \
+ return; \
+ }
+
+static void decode_format80(unsigned char *src, int src_size,
+ unsigned char *dest, int dest_size, int check_size) {
+
+ int src_index = 0;
+ int dest_index = 0;
+ int count;
+ int src_pos;
+ unsigned char color;
+ int i;
+
+ while (src_index < src_size) {
+
+ vqa_debug(" opcode %02X: ", src[src_index]);
+
+ /* 0x80 means that frame is finished */
+ if (src[src_index] == 0x80)
+ return;
+
+ if (dest_index >= dest_size) {
+ av_log(NULL, AV_LOG_ERROR, " VQA video: decode_format80 problem: dest_index (%d) exceeded dest_size (%d)\n",
+ dest_index, dest_size);
+ return;
+ }
+
+ if (src[src_index] == 0xFF) {
+
+ src_index++;
+ count = LE_16(&src[src_index]);
+ src_index += 2;
+ src_pos = LE_16(&src[src_index]);
+ src_index += 2;
+ vqa_debug("(1) copy %X bytes from absolute pos %X\n", count, src_pos);
+ CHECK_COUNT();
+ for (i = 0; i < count; i++)
+ dest[dest_index + i] = dest[src_pos + i];
+ dest_index += count;
+
+ } else if (src[src_index] == 0xFE) {
+
+ src_index++;
+ count = LE_16(&src[src_index]);
+ src_index += 2;
+ color = src[src_index++];
+ vqa_debug("(2) set %X bytes to %02X\n", count, color);
+ CHECK_COUNT();
+ memset(&dest[dest_index], color, count);
+ dest_index += count;
+
+ } else if ((src[src_index] & 0xC0) == 0xC0) {
+
+ count = (src[src_index++] & 0x3F) + 3;
+ src_pos = LE_16(&src[src_index]);
+ src_index += 2;
+ vqa_debug("(3) copy %X bytes from absolute pos %X\n", count, src_pos);
+ CHECK_COUNT();
+ for (i = 0; i < count; i++)
+ dest[dest_index + i] = dest[src_pos + i];
+ dest_index += count;
+
+ } else if (src[src_index] > 0x80) {
+
+ count = src[src_index++] & 0x3F;
+ vqa_debug("(4) copy %X bytes from source to dest\n", count);
+ CHECK_COUNT();
+ memcpy(&dest[dest_index], &src[src_index], count);
+ src_index += count;
+ dest_index += count;
+
+ } else {
+
+ count = ((src[src_index] & 0x70) >> 4) + 3;
+ src_pos = BE_16(&src[src_index]) & 0x0FFF;
+ src_index += 2;
+ vqa_debug("(5) copy %X bytes from relpos %X\n", count, src_pos);
+ CHECK_COUNT();
+ 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(NULL, AV_LOG_ERROR, " VQA video: decode_format80 problem: decode finished with dest_index (%d) < dest_size (%d)\n",
+ dest_index, dest_size);
+}
+
+static void vqa_decode_chunk(VqaContext *s)
+{
+ 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 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 (index < s->size) {
+
+ chunk_type = BE_32(&s->buf[index]);
+ chunk_size = BE_32(&s->buf[index + 4]);
+
+ 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, " VQA video: 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;
+ index += (CHUNK_PREAMBLE_SIZE + 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, " VQA video: problem: found both CPL0 and CPLZ chunks\n");
+ return;
+ }
+
+ /* 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) {
+
+ chunk_size = BE_32(&s->buf[cpl0_chunk + 4]);
+ /* sanity check the palette size */
+ if (chunk_size / 3 > 256) {
+ av_log(s->avctx, AV_LOG_ERROR, " VQA video: problem: found a palette chunk with %d colors\n",
+ chunk_size / 3);
+ return;
+ }
+ cpl0_chunk += CHUNK_PREAMBLE_SIZE;
+ for (i = 0; i < chunk_size / 3; i++) {
+ /* scale by 4 to transform 6-bit palette -> 8-bit */
+ r = s->buf[cpl0_chunk++] * 4;
+ g = s->buf[cpl0_chunk++] * 4;
+ b = s->buf[cpl0_chunk++] * 4;
+ s->palette[i] = (r << 16) | (g << 8) | (b);
+ }
+ }
+
+ /* 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, " VQA video: problem: found both CBF0 and CBFZ chunks\n");
+ return;
+ }
+
+ /* decompress the full codebook chunk */
+ if (cbfz_chunk != -1) {
+
+ chunk_size = BE_32(&s->buf[cbfz_chunk + 4]);
+ cbfz_chunk += CHUNK_PREAMBLE_SIZE;
+ decode_format80(&s->buf[cbfz_chunk], chunk_size,
+ s->codebook, s->codebook_size, 0);
+ }
+
+ /* copy a full codebook */
+ if (cbf0_chunk != -1) {
+
+ chunk_size = BE_32(&s->buf[cbf0_chunk + 4]);
+ /* sanity check the full codebook size */
+ if (chunk_size > MAX_CODEBOOK_SIZE) {
+ av_log(s->avctx, AV_LOG_ERROR, " VQA video: problem: CBF0 chunk too large (0x%X bytes)\n",
+ chunk_size);
+ return;
+ }
+ cbf0_chunk += CHUNK_PREAMBLE_SIZE;
+
+ memcpy(s->codebook, &s->buf[cbf0_chunk], 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, " VQA video: problem: no VPTZ chunk found\n");
+ return;
+ }
+
+ chunk_size = BE_32(&s->buf[vptz_chunk + 4]);
+ vptz_chunk += CHUNK_PREAMBLE_SIZE;
+ decode_format80(&s->buf[vptz_chunk], chunk_size,
+ s->decode_buffer, s->decode_buffer_size, 1);
+
+ /* render the final PAL8 frame */
+ if (s->vector_height == 4)
+ index_shift = 4;
+ else
+ index_shift = 3;
+ for (y = 0; y < s->frame.linesize[0] * s->height;
+ y += s->frame.linesize[0] * s->vector_height) {
+
+ for (x = y; x < y + s->width; x += 4, lobytes++, hibytes++) {
+ pixel_ptr = x;
+
+ /* get the vector index, the method for which varies according to
+ * VQA file version */
+ switch (s->vqa_version) {
+
+ case 1:
+/* still need sample media for this case (only one game, "Legend of
+ * Kyrandia III : Malcolm's Revenge", is known to use this version) */
+ 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--) {
+ s->frame.data[0][pixel_ptr + 0] = 255 - lobyte;
+ s->frame.data[0][pixel_ptr + 1] = 255 - lobyte;
+ s->frame.data[0][pixel_ptr + 2] = 255 - lobyte;
+ s->frame.data[0][pixel_ptr + 3] = 255 - lobyte;
+ pixel_ptr += s->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--) {
+ s->frame.data[0][pixel_ptr + 0] = s->codebook[vector_index++];
+ s->frame.data[0][pixel_ptr + 1] = s->codebook[vector_index++];
+ s->frame.data[0][pixel_ptr + 2] = s->codebook[vector_index++];
+ s->frame.data[0][pixel_ptr + 3] = s->codebook[vector_index++];
+ pixel_ptr += s->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, " VQA video: problem: found both CBP0 and CBPZ chunks\n");
+ return;
+ }
+
+ if (cbp0_chunk != -1) {
+
+ chunk_size = BE_32(&s->buf[cbp0_chunk + 4]);
+ cbp0_chunk += CHUNK_PREAMBLE_SIZE;
+
+ /* accumulate partial codebook */
+ memcpy(&s->next_codebook_buffer[s->next_codebook_buffer_index],
+ &s->buf[cbp0_chunk], 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) {
+
+ chunk_size = BE_32(&s->buf[cbpz_chunk + 4]);
+ cbpz_chunk += CHUNK_PREAMBLE_SIZE;
+
+ /* accumulate partial codebook */
+ memcpy(&s->next_codebook_buffer[s->next_codebook_buffer_index],
+ &s->buf[cbpz_chunk], chunk_size);
+ s->next_codebook_buffer_index += chunk_size;
+
+ s->partial_countdown--;
+ if (s->partial_countdown == 0) {
+
+ /* decompress codebook */
+ decode_format80(s->next_codebook_buffer,
+ s->next_codebook_buffer_index,
+ s->codebook, s->codebook_size, 0);
+
+ /* reset accounting */
+ s->next_codebook_buffer_index = 0;
+ s->partial_countdown = s->partial_count;
+ }
+ }
+}
+
+static int vqa_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ VqaContext *s = (VqaContext *)avctx->priv_data;
+
+ s->buf = buf;
+ s->size = buf_size;
+
+ if (s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ if (avctx->get_buffer(avctx, &s->frame)) {
+ av_log(s->avctx, AV_LOG_ERROR, " VQA Video: get_buffer() failed\n");
+ return -1;
+ }
+
+ vqa_decode_chunk(s);
+
+ /* make the palette available on the way out */
+ memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
+ s->frame.palette_has_changed = 1;
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = s->frame;
+
+ /* report that the buffer was completely consumed */
+ return buf_size;
+}
+
+static int vqa_decode_end(AVCodecContext *avctx)
+{
+ VqaContext *s = (VqaContext *)avctx->priv_data;
+
+ av_free(s->codebook);
+ av_free(s->next_codebook_buffer);
+ av_free(s->decode_buffer);
+
+ if (s->frame.data[0])
+ avctx->release_buffer(avctx, &s->frame);
+
+ return 0;
+}
+
+AVCodec vqa_decoder = {
+ "vqavideo",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_WS_VQA,
+ sizeof(VqaContext),
+ vqa_decode_init,
+ NULL,
+ vqa_decode_end,
+ vqa_decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/w32thread.c b/contrib/ffmpeg/libavcodec/w32thread.c
new file mode 100644
index 000000000..e749a64af
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/w32thread.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 "avcodec.h"
+#include "common.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <process.h>
+
+typedef struct ThreadContext{
+ AVCodecContext *avctx;
+ HANDLE thread;
+ HANDLE work_sem;
+ HANDLE done_sem;
+ int (*func)(AVCodecContext *c, void *arg);
+ void *arg;
+ int ret;
+}ThreadContext;
+
+
+static unsigned __stdcall thread_func(void *v){
+ ThreadContext *c= v;
+
+ for(;;){
+//printf("thread_func %X enter wait\n", (int)v); fflush(stdout);
+ WaitForSingleObject(c->work_sem, INFINITE);
+//printf("thread_func %X after wait (func=%X)\n", (int)v, (int)c->func); fflush(stdout);
+ if(c->func)
+ c->ret= c->func(c->avctx, c->arg);
+ else
+ return 0;
+//printf("thread_func %X signal complete\n", (int)v); fflush(stdout);
+ ReleaseSemaphore(c->done_sem, 1, 0);
+ }
+
+ return 0;
+}
+
+/**
+ * free what has been allocated by avcodec_thread_init().
+ * must be called after decoding has finished, especially dont call while avcodec_thread_execute() is running
+ */
+void avcodec_thread_free(AVCodecContext *s){
+ ThreadContext *c= s->thread_opaque;
+ int i;
+
+ for(i=0; i<s->thread_count; i++){
+
+ c[i].func= NULL;
+ ReleaseSemaphore(c[i].work_sem, 1, 0);
+ WaitForSingleObject(c[i].thread, INFINITE);
+ if(c[i].work_sem) CloseHandle(c[i].work_sem);
+ if(c[i].done_sem) CloseHandle(c[i].done_sem);
+ }
+
+ av_freep(&s->thread_opaque);
+}
+
+int avcodec_thread_execute(AVCodecContext *s, int (*func)(AVCodecContext *c2, void *arg2),void **arg, int *ret, int count){
+ ThreadContext *c= s->thread_opaque;
+ int i;
+
+ assert(s == c->avctx);
+ assert(count <= s->thread_count);
+
+ /* note, we can be certain that this is not called with the same AVCodecContext by different threads at the same time */
+
+ for(i=0; i<count; i++){
+ c[i].arg= arg[i];
+ c[i].func= func;
+ c[i].ret= 12345;
+
+ ReleaseSemaphore(c[i].work_sem, 1, 0);
+ }
+ for(i=0; i<count; i++){
+ WaitForSingleObject(c[i].done_sem, INFINITE);
+
+ c[i].func= NULL;
+ if(ret) ret[i]= c[i].ret;
+ }
+ return 0;
+}
+
+int avcodec_thread_init(AVCodecContext *s, int thread_count){
+ int i;
+ ThreadContext *c;
+ uint32_t threadid;
+
+ s->thread_count= thread_count;
+
+ assert(!s->thread_opaque);
+ c= av_mallocz(sizeof(ThreadContext)*thread_count);
+ s->thread_opaque= c;
+
+ for(i=0; i<thread_count; i++){
+//printf("init semaphors %d\n", i); fflush(stdout);
+ c[i].avctx= s;
+
+ if(!(c[i].work_sem = CreateSemaphore(NULL, 0, s->thread_count, NULL)))
+ goto fail;
+ if(!(c[i].done_sem = CreateSemaphore(NULL, 0, s->thread_count, NULL)))
+ goto fail;
+
+//printf("create thread %d\n", i); fflush(stdout);
+ c[i].thread = (HANDLE)_beginthreadex(NULL, 0, thread_func, &c[i], 0, &threadid );
+ if( !c[i].thread ) goto fail;
+ }
+//printf("init done\n"); fflush(stdout);
+
+ s->execute= avcodec_thread_execute;
+
+ return 0;
+fail:
+ avcodec_thread_free(s);
+ return -1;
+}
diff --git a/contrib/ffmpeg/libavcodec/wavpack.c b/contrib/ffmpeg/libavcodec/wavpack.c
new file mode 100644
index 000000000..5a54f7d0e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/wavpack.c
@@ -0,0 +1,556 @@
+/*
+ * WavPack lossless audio 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
+ */
+#define ALT_BITSTREAM_READER_LE
+#include "avcodec.h"
+#include "bitstream.h"
+
+/**
+ * @file wavpack.c
+ * WavPack lossless audio decoder
+ */
+
+#define WV_JOINT 0x0010
+
+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_FLT,
+ WP_ID_CHANINFO
+};
+
+#define MAX_TERMS 16
+
+typedef struct Decorr {
+ int delta;
+ int value;
+ int weightA;
+ int weightB;
+ int samplesA[8];
+ int samplesB[8];
+} Decorr;
+
+typedef struct WavpackContext {
+ AVCodecContext *avctx;
+ int stereo;
+ int joint;
+ uint32_t CRC;
+ GetBitContext gb;
+ int data_size; // in bits
+ int samples;
+ int median[6];
+ int terms;
+ Decorr decorr[MAX_TERMS];
+ int zero, one, zeroes;
+} 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 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 inline int get_unary(GetBitContext *gb){
+ int r=0;
+ while(get_bits1(gb) && r<33)r++;
+ return r;
+}
+
+// macros for manipulating median values
+#define GET_MED(n) ((median[n] >> 4) + 1)
+#define DEC_MED(n) median[n] -= ((median[n] + (128>>n) - 2) / (128>>n)) * 2
+#define INC_MED(n) median[n] += ((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 always_inline int get_tail(GetBitContext *gb, int k)
+{
+ int p, e, res;
+
+ if(k<1 || k>65535)return 0;
+ p = av_log2_16bit(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 int wv_get_value(WavpackContext *ctx, GetBitContext *gb, int *median, int *last)
+{
+ int t, t2;
+ int sign, base, add, ret;
+
+ *last = 0;
+
+ if((ctx->median[0] < 2U) && (ctx->median[3] < 2U) && !ctx->zero && !ctx->one){
+ if(ctx->zeroes){
+ ctx->zeroes--;
+ if(ctx->zeroes)
+ return 0;
+ }else{
+ t = get_unary(gb);
+ if(t >= 2) t = get_bits(gb, t - 1) | (1 << (t-1));
+ ctx->zeroes = t;
+ if(ctx->zeroes){
+ memset(ctx->median, 0, sizeof(ctx->median));
+ return 0;
+ }
+ }
+ }
+
+ if(get_bits_count(gb) >= ctx->data_size){
+ *last = 1;
+ return 0;
+ }
+
+ if(ctx->zero){
+ t = 0;
+ ctx->zero = 0;
+ }else{
+ t = get_unary(gb);
+ if(get_bits_count(gb) >= ctx->data_size){
+ *last = 1;
+ return 0;
+ }
+ if(t == 16) {
+ t2 = get_unary(gb);
+ if(t2 < 2) t += t2;
+ else 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(!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);
+ }
+ ret = base + get_tail(gb, add);
+ sign = get_bits1(gb);
+ return sign ? ~ret : ret;
+}
+
+static int wv_unpack_stereo(WavpackContext *s, GetBitContext *gb, int16_t *dst)
+{
+ int i, j, count = 0;
+ int last, t;
+ int A, B, L, L2, R, R2;
+ int pos = 0;
+ uint32_t crc = 0xFFFFFFFF;
+
+ s->one = s->zero = s->zeroes = 0;
+ do{
+ L = wv_get_value(s, gb, s->median, &last);
+ if(last) break;
+ R = wv_get_value(s, gb, s->median + 3, &last);
+ if(last) break;
+ for(i = 0; i < s->terms; i++){
+ t = s->decorr[i].value;
+ j = 0;
+ 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;
+ }
+ 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){
+ 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;
+ 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{
+ 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;
+ }
+
+ 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;
+ *dst++ = L;
+ *dst++ = R;
+
+ count++;
+ }while(!last && count < s->samples);
+
+ if(crc != s->CRC){
+ av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");
+ return -1;
+ }
+ return count * 2;
+}
+
+static int wv_unpack_mono(WavpackContext *s, GetBitContext *gb, int16_t *dst)
+{
+ int i, j, count = 0;
+ int last, t;
+ int A, S, T;
+ int pos = 0;
+ uint32_t crc = 0xFFFFFFFF;
+
+ s->one = s->zero = s->zeroes = 0;
+ do{
+ T = wv_get_value(s, gb, s->median, &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;
+ }
+ 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;
+ *dst++ = S;
+ count++;
+ }while(!last && count < s->samples);
+
+ if(crc != s->CRC){
+ av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");
+ return -1;
+ }
+ return count;
+}
+
+static int wavpack_decode_init(AVCodecContext *avctx)
+{
+ WavpackContext *s = avctx->priv_data;
+
+ s->avctx = avctx;
+ s->stereo = (avctx->channels == 2);
+
+ return 0;
+}
+
+static int wavpack_decode_close(AVCodecContext *avctx)
+{
+// WavpackContext *s = avctx->priv_data;
+
+ return 0;
+}
+
+static int wavpack_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ WavpackContext *s = avctx->priv_data;
+ int16_t *samples = data;
+ int samplecount;
+ int got_terms = 0, got_weights = 0, got_samples = 0, got_entropy = 0, got_bs = 0;
+ uint8_t* buf_end = buf + buf_size;
+ int i, j, id, size, ssize, weights, t;
+
+ if (buf_size == 0) return 0;
+
+ memset(s->decorr, 0, MAX_TERMS * sizeof(Decorr));
+
+ s->samples = LE_32(buf); buf += 4;
+ if(!s->samples) return buf_size;
+ /* should not happen but who knows */
+ if(s->samples * 2 * avctx->channels > AVCODEC_MAX_AUDIO_FRAME_SIZE){
+ av_log(avctx, AV_LOG_ERROR, "Packet size is too big to be handled in lavc!\n");
+ return -1;
+ }
+ s->joint = LE_32(buf) & WV_JOINT; buf += 4;
+ s->CRC = LE_32(buf); buf += 4;
+ // 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:
+ s->terms = size;
+ if(s->terms > MAX_TERMS){
+ av_log(avctx, AV_LOG_ERROR, "Too many decorrelation terms\n");
+ buf += ssize;
+ continue;
+ }
+ 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;
+ 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){
+ 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); i--) {
+ if(s->decorr[i].value > 8){
+ s->decorr[i].samplesA[0] = wp_exp2(LE_16(buf)); buf += 2;
+ s->decorr[i].samplesA[1] = wp_exp2(LE_16(buf)); buf += 2;
+ if(s->stereo){
+ s->decorr[i].samplesB[0] = wp_exp2(LE_16(buf)); buf += 2;
+ s->decorr[i].samplesB[1] = wp_exp2(LE_16(buf)); buf += 2;
+ t += 4;
+ }
+ t += 4;
+ }else if(s->decorr[i].value < 0){
+ s->decorr[i].samplesA[0] = wp_exp2(LE_16(buf)); buf += 2;
+ s->decorr[i].samplesB[0] = wp_exp2(LE_16(buf)); buf += 2;
+ t += 4;
+ }else{
+ for(j = 0; j < s->decorr[i].value; j++){
+ s->decorr[i].samplesA[j] = wp_exp2(LE_16(buf)); buf += 2;
+ if(s->stereo){
+ s->decorr[i].samplesB[j] = wp_exp2(LE_16(buf)); buf += 2;
+ }
+ }
+ t += s->decorr[i].value * 2 * avctx->channels;
+ }
+ }
+ got_samples = 1;
+ break;
+ case WP_ID_ENTROPY:
+ if(size != 6 * avctx->channels){
+ av_log(avctx, AV_LOG_ERROR, "Entropy vars size should be %i, got %i", 6 * avctx->channels, size);
+ buf += ssize;
+ continue;
+ }
+ for(i = 0; i < 3 * avctx->channels; i++){
+ s->median[i] = wp_exp2(LE_16(buf));
+ buf += 2;
+ }
+ got_entropy = 1;
+ break;
+ case WP_ID_DATA:
+ init_get_bits(&s->gb, buf, size * 8);
+ s->data_size = size * 8;
+ buf += size;
+ got_bs = 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(!got_bs){
+ av_log(avctx, AV_LOG_ERROR, "Packed samples not found\n");
+ return -1;
+ }
+
+ if(s->stereo)
+ samplecount = wv_unpack_stereo(s, &s->gb, samples);
+ else
+ samplecount = wv_unpack_mono(s, &s->gb, samples);
+ *data_size = samplecount * 2;
+
+ return buf_size;
+}
+
+AVCodec wavpack_decoder = {
+ "wavpack",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_WAVPACK,
+ sizeof(WavpackContext),
+ wavpack_decode_init,
+ NULL,
+ wavpack_decode_close,
+ wavpack_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/wmadata.h b/contrib/ffmpeg/libavcodec/wmadata.h
new file mode 100644
index 000000000..35e545ce6
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/wmadata.h
@@ -0,0 +1,1433 @@
+/*
+ * 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 wmadata.h
+ * Various WMA tables.
+ */
+
+static const uint16_t 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, },
+};
+
+static const uint16_t 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,
+};
+
+static const uint8_t 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,
+};
+
+static const float 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 scale_huffcodes[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,
+};
+
+static const uint8_t scale_huffbits[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 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), coef0_huffcodes, coef0_huffbits, levels0,
+ },
+ {
+ sizeof(coef1_huffbits), coef1_huffcodes, coef1_huffbits, levels1,
+ },
+ {
+ sizeof(coef2_huffbits), coef2_huffcodes, coef2_huffbits, levels2,
+ },
+ {
+ sizeof(coef3_huffbits), coef3_huffcodes, coef3_huffbits, levels3,
+ },
+ {
+ sizeof(coef4_huffbits), coef4_huffcodes, coef4_huffbits, levels4,
+ },
+ {
+ sizeof(coef5_huffbits), coef5_huffcodes, coef5_huffbits, levels5,
+ },
+};
diff --git a/contrib/ffmpeg/libavcodec/wmadec.c b/contrib/ffmpeg/libavcodec/wmadec.c
new file mode 100644
index 000000000..684aea2c8
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/wmadec.c
@@ -0,0 +1,1337 @@
+/*
+ * 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 wmadec.c
+ * 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 "bitstream.h"
+#include "dsputil.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
+
+#define VLCBITS 9
+#define VLCMAX ((22+VLCBITS-1)/VLCBITS)
+
+#define EXPVLCBITS 8
+#define EXPMAX ((19+EXPVLCBITS-1)/EXPVLCBITS)
+
+#define HGAINVLCBITS 9
+#define HGAINMAX ((13+HGAINVLCBITS-1)/HGAINVLCBITS)
+
+typedef struct WMADecodeContext {
+ GetBitContext gb;
+ int sample_rate;
+ int nb_channels;
+ int bit_rate;
+ int version; /* 1 = 0x160 (WMAV1), 2 = 0x161 (WMAV2) */
+ int block_align;
+ 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 */
+ VLC coef_vlc[2];
+ uint16_t *run_table[2];
+ uint16_t *level_table[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 */
+ DECLARE_ALIGNED_16(float, exponents[MAX_CHANNELS][BLOCK_MAX_SIZE]);
+ float max_exponent[MAX_CHANNELS];
+ int16_t coefs1[MAX_CHANNELS][BLOCK_MAX_SIZE];
+ DECLARE_ALIGNED_16(float, coefs[MAX_CHANNELS][BLOCK_MAX_SIZE]);
+ MDCTContext mdct_ctx[BLOCK_NB_SIZES];
+ float *windows[BLOCK_NB_SIZES];
+ DECLARE_ALIGNED_16(FFTSample, mdct_tmp[BLOCK_MAX_SIZE]); /* temporary storage for imdct */
+ /* output buffer for one frame and the last for IMDCT windowing */
+ DECLARE_ALIGNED_16(float, frame_out[MAX_CHANNELS][BLOCK_MAX_SIZE * 2]);
+ /* last frame info */
+ uint8_t last_superframe[MAX_CODED_SUPERFRAME_SIZE + 4]; /* 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)];
+ DSPContext dsp;
+
+#ifdef TRACE
+ int frame_count;
+#endif
+} WMADecodeContext;
+
+typedef struct CoefVLCTable {
+ int n; /* total number of codes */
+ 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;
+
+static void wma_lsp_to_curve_init(WMADecodeContext *s, int frame_len);
+
+#include "wmadata.h"
+
+#ifdef TRACE
+static void dump_shorts(const char *name, const short *tab, int n)
+{
+ int i;
+
+ tprintf("%s[%d]:\n", name, n);
+ for(i=0;i<n;i++) {
+ if ((i & 7) == 0)
+ tprintf("%4d: ", i);
+ tprintf(" %5d.0", tab[i]);
+ if ((i & 7) == 7)
+ tprintf("\n");
+ }
+}
+
+static void dump_floats(const char *name, int prec, const float *tab, int n)
+{
+ int i;
+
+ tprintf("%s[%d]:\n", name, n);
+ for(i=0;i<n;i++) {
+ if ((i & 7) == 0)
+ tprintf("%4d: ", i);
+ tprintf(" %8.*f", prec, tab[i]);
+ if ((i & 7) == 7)
+ tprintf("\n");
+ }
+ if ((i & 7) != 0)
+ tprintf("\n");
+}
+#endif
+
+/* XXX: use same run/length optimization as mpeg decoders */
+static void init_coef_vlc(VLC *vlc,
+ uint16_t **prun_table, uint16_t **plevel_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;
+ const uint16_t *p;
+ int i, l, j, 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));
+ p = levels_table;
+ i = 2;
+ level = 1;
+ while (i < n) {
+ l = *p++;
+ for(j=0;j<l;j++) {
+ run_table[i] = j;
+ level_table[i] = level;
+ i++;
+ }
+ level++;
+ }
+ *prun_table = run_table;
+ *plevel_table = level_table;
+}
+
+static int wma_decode_init(AVCodecContext * avctx)
+{
+ WMADecodeContext *s = avctx->priv_data;
+ int i, flags1, flags2;
+ float *window;
+ uint8_t *extradata;
+ float bps1, high_freq;
+ volatile float bps;
+ int sample_rate1;
+ int coef_vlc_table;
+
+ s->sample_rate = avctx->sample_rate;
+ s->nb_channels = avctx->channels;
+ s->bit_rate = avctx->bit_rate;
+ s->block_align = avctx->block_align;
+
+ dsputil_init(&s->dsp, avctx);
+
+ if (avctx->codec->id == CODEC_ID_WMAV1) {
+ s->version = 1;
+ } else {
+ s->version = 2;
+ }
+
+ /* extract flag infos */
+ flags1 = 0;
+ flags2 = 0;
+ extradata = avctx->extradata;
+ if (s->version == 1 && avctx->extradata_size >= 4) {
+ flags1 = extradata[0] | (extradata[1] << 8);
+ flags2 = extradata[2] | (extradata[3] << 8);
+ } else if (s->version == 2 && avctx->extradata_size >= 6) {
+ flags1 = extradata[0] | (extradata[1] << 8) |
+ (extradata[2] << 16) | (extradata[3] << 24);
+ flags2 = extradata[4] | (extradata[5] << 8);
+ }
+ s->use_exp_vlc = flags2 & 0x0001;
+ s->use_bit_reservoir = flags2 & 0x0002;
+ s->use_variable_block_len = flags2 & 0x0004;
+
+ /* compute MDCT block size */
+ if (s->sample_rate <= 16000) {
+ s->frame_len_bits = 9;
+ } else if (s->sample_rate <= 22050 ||
+ (s->sample_rate <= 32000 && s->version == 1)) {
+ s->frame_len_bits = 10;
+ } else {
+ s->frame_len_bits = 11;
+ }
+ s->frame_len = 1 << s->frame_len_bits;
+ if (s->use_variable_block_len) {
+ int nb_max, nb;
+ nb = ((flags2 >> 3) & 3) + 1;
+ if ((s->bit_rate / s->nb_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 dependant parameters */
+ s->use_noise_coding = 1;
+ high_freq = s->sample_rate * 0.5;
+
+ /* if version 2, then the rates are normalized */
+ sample_rate1 = s->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)s->bit_rate / (float)(s->nb_channels * s->sample_rate);
+ s->byte_offset_bits = av_log2((int)(bps * s->frame_len / 8.0 + 0.5)) + 2;
+
+ /* compute high frequency value and choose if noise coding should
+ be activated */
+ bps1 = bps;
+ if (s->nb_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;
+ }
+ }
+ dprintf("flags1=0x%x flags2=0x%x\n", flags1, flags2);
+ dprintf("version=%d channels=%d sample_rate=%d bitrate=%d block_align=%d\n",
+ s->version, s->nb_channels, s->sample_rate, s->bit_rate,
+ s->block_align);
+ dprintf("bps=%f bps1=%f high_freq=%f bitoffset=%d\n",
+ bps, bps1, high_freq, s->byte_offset_bits);
+ dprintf("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 = wma_critical_freqs[i];
+ b = s->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 (s->sample_rate >= 44100)
+ table = exponent_band_44100[a];
+ else if (s->sample_rate >= 32000)
+ table = exponent_band_32000[a];
+ else if (s->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 = wma_critical_freqs[i];
+ b = s->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) /
+ s->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("%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(" %d", s->exponent_high_bands[k][j]);
+ tprintf("\n");
+#endif
+ }
+ }
+
+#ifdef TRACE
+ {
+ int i, j;
+ for(i = 0; i < s->nb_block_sizes; i++) {
+ tprintf("%5d: n=%2d:",
+ s->frame_len >> i,
+ s->exponent_sizes[i]);
+ for(j=0;j<s->exponent_sizes[i];j++)
+ tprintf(" %d", s->exponent_bands[i][j]);
+ tprintf("\n");
+ }
+ }
+#endif
+
+ /* 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);
+
+ /* init MDCT windows : simple sinus window */
+ for(i = 0; i < s->nb_block_sizes; i++) {
+ int n, j;
+ float alpha;
+ n = 1 << (s->frame_len_bits - i);
+ window = av_malloc(sizeof(float) * n);
+ alpha = M_PI / (2.0 * n);
+ for(j=0;j<n;j++) {
+ window[n - j - 1] = sin((j + 0.5) * alpha);
+ }
+ s->windows[i] = window;
+ }
+
+ 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
+ init_vlc(&s->hgain_vlc, HGAINVLCBITS, sizeof(hgain_huffbits),
+ hgain_huffbits, 1, 1,
+ hgain_huffcodes, 2, 2, 0);
+ }
+
+ if (s->use_exp_vlc) {
+ init_vlc(&s->exp_vlc, EXPVLCBITS, sizeof(scale_huffbits),
+ scale_huffbits, 1, 1,
+ scale_huffcodes, 4, 4, 0);
+ } else {
+ wma_lsp_to_curve_init(s, s->frame_len);
+ }
+
+ /* choose the VLC tables for the coefficients */
+ coef_vlc_table = 2;
+ if (s->sample_rate >= 32000) {
+ if (bps1 < 0.72)
+ coef_vlc_table = 0;
+ else if (bps1 < 1.16)
+ coef_vlc_table = 1;
+ }
+
+ init_coef_vlc(&s->coef_vlc[0], &s->run_table[0], &s->level_table[0],
+ &coef_vlcs[coef_vlc_table * 2]);
+ init_coef_vlc(&s->coef_vlc[1], &s->run_table[1], &s->level_table[1],
+ &coef_vlcs[coef_vlc_table * 2 + 1]);
+ return 0;
+}
+
+/* interpolate values for a bigger or smaller block. The block must
+ have multiple sizes */
+static void interpolate_array(float *scale, int old_size, int new_size)
+{
+ int i, j, jincr, k;
+ float v;
+
+ if (new_size > old_size) {
+ jincr = new_size / old_size;
+ j = new_size;
+ for(i = old_size - 1; i >=0; i--) {
+ v = scale[i];
+ k = jincr;
+ do {
+ scale[--j] = v;
+ } while (--k);
+ }
+ } else if (new_size < old_size) {
+ j = 0;
+ jincr = old_size / new_size;
+ for(i = 0; i < new_size; i++) {
+ scale[i] = scale[j];
+ j += jincr;
+ }
+ }
+}
+
+/* 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(WMADecodeContext *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(WMADecodeContext *s, int frame_len)
+{
+ float wdel, a, b;
+ int i, e, m;
+
+ wdel = M_PI / frame_len;
+ for(i=0;i<frame_len;i++)
+ s->lsp_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;
+ }
+#if 0
+ for(i=1;i<20;i++) {
+ float v, r1, r2;
+ v = 5.0 / i;
+ r1 = pow_m1_4(s, v);
+ r2 = pow(v,-0.25);
+ printf("%f^-0.25=%f e=%f\n", v, r1, r2 - r1);
+ }
+#endif
+}
+
+/* NOTE: We use the same code as Vorbis here */
+/* XXX: optimize it further with SSE/3Dnow */
+static void wma_lsp_to_curve(WMADecodeContext *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;i<n;i++) {
+ p = 0.5f;
+ q = 0.5f;
+ w = s->lsp_cos_table[i];
+ for(j=1;j<NB_LSP_COEFS;j+=2){
+ q *= w - lsp[j - 1];
+ p *= w - lsp[j];
+ }
+ p *= p * (2.0f - w);
+ q *= q * (2.0f + w);
+ v = p + q;
+ v = pow_m1_4(s, v);
+ if (v > 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(WMADecodeContext *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] = lsp_codebook[i][val];
+ }
+
+ wma_lsp_to_curve(s, s->exponents[ch], &s->max_exponent[ch],
+ s->block_len, lsp_coefs);
+}
+
+/* decode exponents coded with VLC codes */
+static int decode_exp_vlc(WMADecodeContext *s, int ch)
+{
+ int last_exp, n, code;
+ const uint16_t *ptr, *band_ptr;
+ float v, *q, max_scale, *q_end;
+
+ band_ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits];
+ ptr = band_ptr;
+ q = s->exponents[ch];
+ q_end = q + s->block_len;
+ max_scale = 0;
+ if (s->version == 1) {
+ last_exp = get_bits(&s->gb, 5) + 10;
+ /* XXX: use a table */
+ v = pow(10, last_exp * (1.0 / 16.0));
+ max_scale = v;
+ n = *ptr++;
+ do {
+ *q++ = v;
+ } while (--n);
+ }
+ last_exp = 36;
+ while (q < q_end) {
+ code = get_vlc2(&s->gb, s->exp_vlc.table, EXPVLCBITS, EXPMAX);
+ if (code < 0)
+ return -1;
+ /* NOTE: this offset is the same as MPEG4 AAC ! */
+ last_exp += code - 60;
+ /* XXX: use a table */
+ v = pow(10, last_exp * (1.0 / 16.0));
+ if (v > max_scale)
+ max_scale = v;
+ n = *ptr++;
+ do {
+ *q++ = v;
+ } while (--n);
+ }
+ s->max_exponent[ch] = max_scale;
+ return 0;
+}
+
+/* return 0 if OK. return 1 if last block of frame. return -1 if
+ unrecorrable error. */
+static int wma_decode_block(WMADecodeContext *s)
+{
+ int n, v, a, ch, code, bsize;
+ int coef_nb_bits, total_gain, parse_exponents;
+ DECLARE_ALIGNED_16(float, window[BLOCK_MAX_SIZE * 2]);
+ int nb_coefs[MAX_CHANNELS];
+ float mdct_norm;
+
+#ifdef TRACE
+ tprintf("***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)
+ return -1;
+ s->prev_block_len_bits = s->frame_len_bits - v;
+ v = get_bits(&s->gb, n);
+ if (v >= s->nb_block_sizes)
+ 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)
+ 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;
+ }
+
+ /* 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)
+ return -1;
+
+ if (s->nb_channels == 2) {
+ s->ms_stereo = get_bits(&s->gb, 1);
+ }
+ v = 0;
+ for(ch = 0; ch < s->nb_channels; ch++) {
+ a = get_bits(&s->gb, 1);
+ s->channel_coded[ch] = a;
+ v |= a;
+ }
+ /* if no channel coded, no need to go further */
+ /* XXX: fix potential framing problems */
+ if (!v)
+ goto next;
+
+ bsize = s->frame_len_bits - s->block_len_bits;
+
+ /* 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;
+ }
+
+ if (total_gain < 15)
+ coef_nb_bits = 13;
+ else if (total_gain < 32)
+ coef_nb_bits = 12;
+ else if (total_gain < 40)
+ coef_nb_bits = 11;
+ else if (total_gain < 45)
+ coef_nb_bits = 10;
+ else
+ coef_nb_bits = 9;
+
+ /* compute number of coefficients */
+ n = s->coefs_end[bsize] - s->coefs_start;
+ for(ch = 0; ch < s->nb_channels; ch++)
+ nb_coefs[ch] = n;
+
+ /* complex coding */
+ if (s->use_noise_coding) {
+
+ for(ch = 0; ch < s->nb_channels; ch++) {
+ if (s->channel_coded[ch]) {
+ int i, n, a;
+ n = s->exponent_high_sizes[bsize];
+ for(i=0;i<n;i++) {
+ a = get_bits(&s->gb, 1);
+ 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->nb_channels; ch++) {
+ if (s->channel_coded[ch]) {
+ int i, n, val, code;
+
+ n = s->exponent_high_sizes[bsize];
+ val = (int)0x80000000;
+ for(i=0;i<n;i++) {
+ if (s->high_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)
+ return -1;
+ val += code - 18;
+ }
+ s->high_band_values[ch][i] = val;
+ }
+ }
+ }
+ }
+ }
+
+ /* exposant can be interpolated in short blocks. */
+ parse_exponents = 1;
+ if (s->block_len_bits != s->frame_len_bits) {
+ parse_exponents = get_bits(&s->gb, 1);
+ }
+
+ if (parse_exponents) {
+ for(ch = 0; ch < s->nb_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);
+ }
+ }
+ }
+ } else {
+ for(ch = 0; ch < s->nb_channels; ch++) {
+ if (s->channel_coded[ch]) {
+ interpolate_array(s->exponents[ch], 1 << s->prev_block_len_bits,
+ s->block_len);
+ }
+ }
+ }
+
+ /* parse spectral coefficients : just RLE encoding */
+ for(ch = 0; ch < s->nb_channels; ch++) {
+ if (s->channel_coded[ch]) {
+ VLC *coef_vlc;
+ int level, run, sign, tindex;
+ int16_t *ptr, *eptr;
+ const uint16_t *level_table, *run_table;
+
+ /* special VLC tables are used for ms stereo because
+ there is potentially less energy there */
+ tindex = (ch == 1 && s->ms_stereo);
+ coef_vlc = &s->coef_vlc[tindex];
+ run_table = s->run_table[tindex];
+ level_table = s->level_table[tindex];
+ /* XXX: optimize */
+ ptr = &s->coefs1[ch][0];
+ eptr = ptr + nb_coefs[ch];
+ memset(ptr, 0, s->block_len * sizeof(int16_t));
+ for(;;) {
+ code = get_vlc2(&s->gb, coef_vlc->table, VLCBITS, VLCMAX);
+ if (code < 0)
+ return -1;
+ if (code == 1) {
+ /* EOB */
+ break;
+ } else if (code == 0) {
+ /* escape */
+ level = get_bits(&s->gb, coef_nb_bits);
+ /* NOTE: this is rather suboptimal. reading
+ block_len_bits would be better */
+ run = get_bits(&s->gb, s->frame_len_bits);
+ } else {
+ /* normal code */
+ run = run_table[code];
+ level = level_table[code];
+ }
+ sign = get_bits(&s->gb, 1);
+ if (!sign)
+ level = -level;
+ ptr += run;
+ if (ptr >= eptr)
+ {
+ av_log(NULL, AV_LOG_ERROR, "overflow in spectral RLE, ignoring\n");
+ break;
+ }
+ *ptr++ = level;
+ /* NOTE: EOB can be omitted */
+ if (ptr >= eptr)
+ break;
+ }
+ }
+ if (s->version == 1 && s->nb_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->nb_channels; ch++) {
+ if (s->channel_coded[ch]) {
+ int16_t *coefs1;
+ float *coefs, *exponents, mult, mult1, noise, *exp_ptr;
+ int i, j, n, n1, last_high_band;
+ float exp_power[HIGH_BAND_MAX_SIZE];
+
+ coefs1 = s->coefs1[ch];
+ exponents = s->exponents[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++) * mult1;
+ s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1);
+ }
+
+ n1 = s->exponent_high_sizes[bsize];
+
+ /* compute power of high bands */
+ exp_ptr = exponents +
+ s->high_band_start[bsize] -
+ s->coefs_start;
+ last_high_band = 0; /* avoid warning */
+ for(j=0;j<n1;j++) {
+ n = s->exponent_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 = exp_ptr[i];
+ e2 += v * v;
+ }
+ exp_power[j] = e2 / n;
+ last_high_band = j;
+ tprintf("%d: power=%f (%d)\n", j, exp_power[j], n);
+ }
+ exp_ptr += n;
+ }
+
+ /* main freqs and high freqs */
+ for(j=-1;j<n1;j++) {
+ if (j < 0) {
+ n = s->high_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++ = (*exponents++) * noise * mult1;
+ }
+ } 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++) * mult;
+ }
+ }
+ }
+
+ /* very high freqs : noise */
+ n = s->block_len - s->coefs_end[bsize];
+ mult1 = mult * exponents[-1];
+ 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] * 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->nb_channels; ch++) {
+ if (s->channel_coded[ch]) {
+ dump_floats("exponents", 3, s->exponents[ch], s->block_len);
+ dump_floats("coefs", 1, s->coefs[ch], s->block_len);
+ }
+ }
+#endif
+
+ if (s->ms_stereo && s->channel_coded[1]) {
+ float a, b;
+ int i;
+
+ /* 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("rare ms-stereo case happened\n");
+ memset(s->coefs[0], 0, sizeof(float) * s->block_len);
+ s->channel_coded[0] = 1;
+ }
+
+ for(i = 0; i < s->block_len; i++) {
+ a = s->coefs[0][i];
+ b = s->coefs[1][i];
+ s->coefs[0][i] = a + b;
+ s->coefs[1][i] = a - b;
+ }
+ }
+
+ /* build the window : we ensure that when the windows overlap
+ their squared sum is always 1 (MDCT reconstruction rule) */
+ /* XXX: merge with output */
+ {
+ int i, next_block_len, block_len, prev_block_len, n;
+ float *wptr;
+
+ block_len = s->block_len;
+ prev_block_len = 1 << s->prev_block_len_bits;
+ next_block_len = 1 << s->next_block_len_bits;
+
+ /* right part */
+ wptr = window + block_len;
+ if (block_len <= next_block_len) {
+ for(i=0;i<block_len;i++)
+ *wptr++ = s->windows[bsize][i];
+ } else {
+ /* overlap */
+ n = (block_len / 2) - (next_block_len / 2);
+ for(i=0;i<n;i++)
+ *wptr++ = 1.0;
+ for(i=0;i<next_block_len;i++)
+ *wptr++ = s->windows[s->frame_len_bits - s->next_block_len_bits][i];
+ for(i=0;i<n;i++)
+ *wptr++ = 0.0;
+ }
+
+ /* left part */
+ wptr = window + block_len;
+ if (block_len <= prev_block_len) {
+ for(i=0;i<block_len;i++)
+ *--wptr = s->windows[bsize][i];
+ } else {
+ /* overlap */
+ n = (block_len / 2) - (prev_block_len / 2);
+ for(i=0;i<n;i++)
+ *--wptr = 1.0;
+ for(i=0;i<prev_block_len;i++)
+ *--wptr = s->windows[s->frame_len_bits - s->prev_block_len_bits][i];
+ for(i=0;i<n;i++)
+ *--wptr = 0.0;
+ }
+ }
+
+
+ for(ch = 0; ch < s->nb_channels; ch++) {
+ if (s->channel_coded[ch]) {
+ DECLARE_ALIGNED_16(FFTSample, output[BLOCK_MAX_SIZE * 2]);
+ float *ptr;
+ int n4, index, n;
+
+ n = s->block_len;
+ n4 = s->block_len / 2;
+ s->mdct_ctx[bsize].fft.imdct_calc(&s->mdct_ctx[bsize],
+ output, s->coefs[ch], s->mdct_tmp);
+
+ /* XXX: optimize all that by build the window and
+ multipying/adding at the same time */
+
+ /* multiply by the window and add in the frame */
+ index = (s->frame_len / 2) + s->block_pos - n4;
+ ptr = &s->frame_out[ch][index];
+ s->dsp.vector_fmul_add_add(ptr,window,output,ptr,0,2*n,1);
+
+ /* specific fast case for ms-stereo : add to second
+ channel if it is not coded */
+ if (s->ms_stereo && !s->channel_coded[1]) {
+ ptr = &s->frame_out[1][index];
+ s->dsp.vector_fmul_add_add(ptr,window,output,ptr,0,2*n,1);
+ }
+ }
+ }
+ next:
+ /* 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(WMADecodeContext *s, int16_t *samples)
+{
+ int ret, i, n, a, ch, incr;
+ int16_t *ptr;
+ float *iptr;
+
+#ifdef TRACE
+ tprintf("***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;
+ }
+
+ /* convert frame to integer */
+ n = s->frame_len;
+ incr = s->nb_channels;
+ for(ch = 0; ch < s->nb_channels; ch++) {
+ ptr = samples + ch;
+ iptr = s->frame_out[ch];
+
+ for(i=0;i<n;i++) {
+ a = lrintf(*iptr++);
+ if (a > 32767)
+ a = 32767;
+ else if (a < -32768)
+ a = -32768;
+ *ptr = a;
+ ptr += incr;
+ }
+ /* prepare for next block */
+ memmove(&s->frame_out[ch][0], &s->frame_out[ch][s->frame_len],
+ s->frame_len * sizeof(float));
+ /* XXX: suppress this */
+ memset(&s->frame_out[ch][s->frame_len], 0,
+ s->frame_len * sizeof(float));
+ }
+
+#ifdef TRACE
+ dump_shorts("samples", samples, n * s->nb_channels);
+#endif
+ return 0;
+}
+
+static int wma_decode_superframe(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ WMADecodeContext *s = avctx->priv_data;
+ int nb_frames, bit_offset, i, pos, len;
+ uint8_t *q;
+ int16_t *samples;
+
+ tprintf("***decode_superframe:\n");
+
+ if(buf_size==0){
+ s->last_superframe_len = 0;
+ return 0;
+ }
+
+ samples = data;
+
+ init_get_bits(&s->gb, buf, buf_size*8);
+
+ if (s->use_bit_reservoir) {
+ /* read super frame header */
+ get_bits(&s->gb, 4); /* super frame index */
+ nb_frames = get_bits(&s->gb, 4) - 1;
+
+ bit_offset = get_bits(&s->gb, s->byte_offset_bits + 3);
+
+ if (s->last_superframe_len > 0) {
+ // printf("skip=%d\n", s->last_bitoffset);
+ /* 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);
+ }
+
+ /* XXX: bit_offset bits into last frame */
+ init_get_bits(&s->gb, s->last_superframe, MAX_CODED_SUPERFRAME_SIZE*8);
+ /* 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) < 0)
+ goto fail;
+ samples += s->nb_channels * s->frame_len;
+ }
+
+ /* read each frame starting from bit_offset */
+ pos = bit_offset + 4 + 4 + s->byte_offset_bits + 3;
+ init_get_bits(&s->gb, buf + (pos >> 3), (MAX_CODED_SUPERFRAME_SIZE - (pos >> 3))*8);
+ len = pos & 7;
+ if (len > 0)
+ skip_bits(&s->gb, len);
+
+ s->reset_block_lengths = 1;
+ for(i=0;i<nb_frames;i++) {
+ if (wma_decode_frame(s, samples) < 0)
+ goto fail;
+ samples += s->nb_channels * s->frame_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) {
+ goto fail;
+ }
+ s->last_superframe_len = len;
+ memcpy(s->last_superframe, buf + pos, len);
+ } else {
+ /* single frame decode */
+ if (wma_decode_frame(s, samples) < 0)
+ goto fail;
+ samples += s->nb_channels * s->frame_len;
+ }
+ *data_size = (int8_t *)samples - (int8_t *)data;
+ return s->block_align;
+ fail:
+ /* when error, we reset the bit reservoir */
+ s->last_superframe_len = 0;
+ return -1;
+}
+
+static int wma_decode_end(AVCodecContext *avctx)
+{
+ WMADecodeContext *s = avctx->priv_data;
+ int i;
+
+ for(i = 0; i < s->nb_block_sizes; i++)
+ ff_mdct_end(&s->mdct_ctx[i]);
+ for(i = 0; i < s->nb_block_sizes; i++)
+ av_free(s->windows[i]);
+
+ if (s->use_exp_vlc) {
+ free_vlc(&s->exp_vlc);
+ }
+ if (s->use_noise_coding) {
+ free_vlc(&s->hgain_vlc);
+ }
+ for(i = 0;i < 2; i++) {
+ free_vlc(&s->coef_vlc[i]);
+ av_free(s->run_table[i]);
+ av_free(s->level_table[i]);
+ }
+
+ return 0;
+}
+
+AVCodec wmav1_decoder =
+{
+ "wmav1",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_WMAV1,
+ sizeof(WMADecodeContext),
+ wma_decode_init,
+ NULL,
+ wma_decode_end,
+ wma_decode_superframe,
+};
+
+AVCodec wmav2_decoder =
+{
+ "wmav2",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_WMAV2,
+ sizeof(WMADecodeContext),
+ wma_decode_init,
+ NULL,
+ wma_decode_end,
+ wma_decode_superframe,
+};
diff --git a/contrib/ffmpeg/libavcodec/wmv2.c b/contrib/ffmpeg/libavcodec/wmv2.c
new file mode 100644
index 000000000..5abc51775
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/wmv2.c
@@ -0,0 +1,855 @@
+/*
+ * 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 wmv2.c
+ * wmv2 codec.
+ */
+
+#include "simple_idct.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;
+ int j_type_bit;
+ int j_type;
+ int flag3;
+ int flag63;
+ 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_8(DCTELEM, abt_block2[6][64]);
+}Wmv2Context;
+
+static void wmv2_common_init(Wmv2Context * w){
+ MpegEncContext * const s= &w->s;
+
+ ff_init_scantable(s->dsp.idct_permutation, &w->abt_scantable[0], wmv2_scantableA);
+ ff_init_scantable(s->dsp.idct_permutation, &w->abt_scantable[1], wmv2_scantableB);
+}
+
+#ifdef CONFIG_ENCODERS
+
+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, w->flag3=1);
+ 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 int wmv2_encode_init(AVCodecContext *avctx){
+ Wmv2Context * const w= avctx->priv_data;
+
+ if(MPV_encode_init(avctx) < 0)
+ return -1;
+
+ wmv2_common_init(w);
+
+ avctx->extradata_size= 4;
+ avctx->extradata= av_mallocz(avctx->extradata_size + 10);
+ encode_ext_header(w);
+
+ return 0;
+}
+
+#if 0 /* unused, remove? */
+static int wmv2_encode_end(AVCodecContext *avctx){
+
+ if(MPV_encode_end(avctx) < 0)
+ return -1;
+
+ avctx->extradata_size= 0;
+ av_freep(&avctx->extradata);
+
+ return 0;
+}
+#endif
+
+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 == I_TYPE){
+ 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->use_skip_mb_code = 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;
+
+ assert(s->flipflop_rounding);
+
+ if (s->pict_type == I_TYPE) {
+ assert(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){
+ code012(&s->pb, s->rl_chroma_table_index);
+ 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);
+
+ 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){
+ 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){
+ 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 idential to wmv1 but thats just because we dont use the useless M$ crap features
+// its duplicated here in case someone wants to add support for these carp features
+void ff_wmv2_encode_mb(MpegEncContext * s,
+ DCTELEM 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;
+
+ 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,
+ wmv2_inter_table[w->cbp_table_index][cbp + 64][1],
+ wmv2_inter_table[w->cbp_table_index][cbp + 64][0]);
+
+ /* motion vector */
+ h263_pred_motion(s, 0, 0, &pred_x, &pred_y);
+ 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 = coded_block_pred(s, i, &coded_block);
+ *coded_block = val;
+ val = val ^ pred;
+ }
+ coded_cbp |= val << (5 - i);
+ }
+#if 0
+ if (coded_cbp)
+ printf("cbp=%x %x\n", cbp, coded_cbp);
+#endif
+
+ if (s->pict_type == I_TYPE) {
+ 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,
+ wmv2_inter_table[w->cbp_table_index][cbp][1],
+ 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, table_inter_intra[s->h263_aic_dir][1], table_inter_intra[s->h263_aic_dir][0]);
+ }
+ }
+
+ for (i = 0; i < 6; i++) {
+ msmpeg4_encode_block(s, block[i], i);
+ }
+}
+#endif //CONFIG_ENCODERS
+
+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_y<s->mb_height; mb_y++){
+ for(mb_x=0; mb_x<s->mb_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_y<s->mb_height; mb_y++){
+ for(mb_x=0; mb_x<s->mb_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_y<s->mb_height; mb_y++){
+ if(get_bits1(&s->gb)){
+ for(mb_x=0; mb_x<s->mb_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_x<s->mb_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_x<s->mb_width; mb_x++){
+ if(get_bits1(&s->gb)){
+ for(mb_y=0; mb_y<s->mb_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_y<s->mb_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, s->avctx->extradata_size*8);
+
+ fps = get_bits(&gb, 5);
+ s->bit_rate = get_bits(&gb, 11)*1024;
+ w->mspel_bit = get_bits1(&gb);
+ w->flag3 = 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, flag3:%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, w->flag3,
+ code);
+ }
+ return 0;
+}
+
+int ff_wmv2_decode_picture_header(MpegEncContext * s)
+{
+ Wmv2Context * const w= (Wmv2Context*)s;
+ int code;
+
+#if 0
+{
+int i;
+for(i=0; i<s->gb.size*8; i++)
+ printf("%d", get_bits1(&s->gb));
+// get_bits1(&s->gb);
+printf("END\n");
+return -1;
+}
+#endif
+ if(s->picture_number==0)
+ decode_ext_header(w);
+
+ s->pict_type = get_bits(&s->gb, 1) + 1;
+ if(s->pict_type == I_TYPE){
+ 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 == I_TYPE) {
+ 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)
+// return wmv2_decode_j_picture(w); //FIXME
+
+ if(w->j_type){
+ av_log(s->avctx, AV_LOG_ERROR, "J-type picture is not supported\n");
+ 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= 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;
+
+//printf("%d %d ", *mx_ptr, *my_ptr);
+
+ 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, DCTELEM *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);
+#if 0
+ if(w->per_block_abt)
+ printf("B%d", w->abt_type);
+#endif
+ 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) ];
+// printf("S%d", sub_cbp);
+
+ if(sub_cbp&1){
+ if (msmpeg4_decode_block(s, block, n, 1, scantable) < 0)
+ return -1;
+ }
+
+ if(sub_cbp&2){
+ if (msmpeg4_decode_block(s, w->abt_block2[n], n, 1, scantable) < 0)
+ return -1;
+ }
+ s->block_last_index[n] = 63;
+
+ return 0;
+ }else{
+ return msmpeg4_decode_block(s, block, n, 1, s->inter_scantable.permutated);
+ }
+}
+
+static void wmv2_add_block(Wmv2Context *w, DCTELEM *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:
+ s->dsp.idct_add (dst, stride, block1);
+ break;
+ case 1:
+ simple_idct84_add(dst , stride, block1);
+ simple_idct84_add(dst + 4*stride, stride, w->abt_block2[n]);
+ memset(w->abt_block2[n], 0, 64*sizeof(DCTELEM));
+ break;
+ case 2:
+ simple_idct48_add(dst , stride, block1);
+ simple_idct48_add(dst + 4 , stride, w->abt_block2[n]);
+ memset(w->abt_block2[n], 0, 64*sizeof(DCTELEM));
+ break;
+ default:
+ av_log(s->avctx, AV_LOG_ERROR, "internal error in WMV2 abt\n");
+ }
+ }
+}
+
+void ff_wmv2_add_mb(MpegEncContext *s, DCTELEM 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 = clip(src_x, -16, s->width);
+ src_y = clip(src_y, -16, s->height);
+ 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){
+ ff_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 = clip(src_x, -8, s->width >> 1);
+ if (src_x == (s->width >> 1))
+ dxy &= ~1;
+ src_y = 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){
+ ff_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){
+ ff_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);
+}
+
+
+static int wmv2_decode_mb(MpegEncContext *s, DCTELEM 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 == P_TYPE) {
+ 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, 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 = coded_block_pred(s, i, &coded_val);
+ val = val ^ pred;
+ *coded_val = val;
+ }
+ cbp |= val << (5 - i);
+ }
+ }
+
+ if (!s->mb_intra) {
+ int mx, my;
+//printf("P at %d %d\n", s->mb_x, s->mb_y);
+ 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==P_TYPE)
+// printf("%d%d ", s->inter_intra_pred, cbp);
+//printf("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, inter_intra_vlc.table, INTER_INTRA_VLC_BITS, 1);
+// printf("%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 (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 int wmv2_decode_init(AVCodecContext *avctx){
+ Wmv2Context * const w= avctx->priv_data;
+
+ if(ff_h263_decode_init(avctx) < 0)
+ return -1;
+
+ wmv2_common_init(w);
+
+ return 0;
+}
+
+AVCodec wmv2_decoder = {
+ "wmv2",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_WMV2,
+ sizeof(Wmv2Context),
+ wmv2_decode_init,
+ NULL,
+ ff_h263_decode_end,
+ ff_h263_decode_frame,
+ CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1,
+};
+
+#ifdef CONFIG_ENCODERS
+AVCodec wmv2_encoder = {
+ "wmv2",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_WMV2,
+ sizeof(Wmv2Context),
+ wmv2_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+};
+#endif
diff --git a/contrib/ffmpeg/libavcodec/wnv1.c b/contrib/ffmpeg/libavcodec/wnv1.c
new file mode 100644
index 000000000..46b31a5c5
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/wnv1.c
@@ -0,0 +1,146 @@
+/*
+ * 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 wnv1.c
+ * Winnov WNV1 codec.
+ */
+
+#include "avcodec.h"
+#include "common.h"
+#include "bitstream.h"
+
+
+typedef struct WNV1Context{
+ AVCodecContext *avctx;
+ AVFrame pic;
+
+ int shift;
+ GetBitContext gb;
+} WNV1Context;
+
+static 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 *data_size,
+ uint8_t *buf, int buf_size)
+{
+ WNV1Context * const l = avctx->priv_data;
+ AVFrame * const p= (AVFrame*)&l->pic;
+ unsigned char *Y,*U,*V;
+ int i, j;
+ int prev_y = 0, prev_u = 0, prev_v = 0;
+
+ if(p->data[0])
+ avctx->release_buffer(avctx, p);
+
+ p->reference = 0;
+ if(avctx->get_buffer(avctx, p) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+ p->key_frame = 1;
+
+ for(i=8; i<buf_size; i++)
+ buf[i]= ff_reverse[ buf[i] ]; //FIXME ensure that the buffer is modifyable or use a temp one
+ init_get_bits(&l->gb, buf+8, (buf_size-8)*8);
+
+ if (buf[2] >> 4 == 6)
+ l->shift = 2;
+ else {
+ l->shift = 8 - (buf[2] >> 4);
+ if (l->shift > 4) {
+ av_log(avctx, AV_LOG_ERROR, "Unknown WNV1 frame header value %i, please upload file for study\n", buf[2] >> 4);
+ l->shift = 4;
+ }
+ if (l->shift < 1) {
+ av_log(avctx, AV_LOG_ERROR, "Unknown WNV1 frame header value %i, please upload file for study\n", 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];
+ }
+
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = l->pic;
+
+ return buf_size;
+}
+
+static int decode_init(AVCodecContext *avctx){
+ WNV1Context * const l = avctx->priv_data;
+
+ l->avctx = avctx;
+ avctx->pix_fmt = PIX_FMT_YUV422P;
+
+ if(!code_vlc.table){
+ init_vlc(&code_vlc, CODE_VLC_BITS, 16,
+ &code_tab[0][1], 4, 2,
+ &code_tab[0][0], 4, 2, 1);
+ }
+
+ return 0;
+}
+
+AVCodec wnv1_decoder = {
+ "wnv1",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_WNV1,
+ sizeof(WNV1Context),
+ decode_init,
+ NULL,
+ NULL,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/ws-snd1.c b/contrib/ffmpeg/libavcodec/ws-snd1.c
new file mode 100644
index 000000000..eb4fe81d3
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/ws-snd1.c
@@ -0,0 +1,144 @@
+/*
+ * 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 "avcodec.h"
+
+/**
+ * @file ws-snd.c
+ * Westwood SNDx codecs.
+ *
+ * Reference documents about VQA format and its audio codecs
+ * can be found here:
+ * http://www.multimedia.cx
+ */
+
+static const char ws_adpcm_2bit[] = { -2, -1, 0, 1};
+static const char ws_adpcm_4bit[] = {
+ -9, -8, -6, -5, -4, -3, -2, -1,
+ 0, 1, 2, 3, 4, 5, 6, 8 };
+
+#define CLIP8(a) if(a>127)a=127;if(a<-128)a=-128;
+
+static int ws_snd_decode_init(AVCodecContext * avctx)
+{
+// WSSNDContext *c = avctx->priv_data;
+
+ return 0;
+}
+
+static int ws_snd_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+// WSSNDContext *c = avctx->priv_data;
+
+ int in_size, out_size;
+ int sample = 0;
+ int i;
+ short *samples = data;
+
+ if (!buf_size)
+ return 0;
+
+ out_size = LE_16(&buf[0]);
+ *data_size = out_size * 2;
+ in_size = LE_16(&buf[2]);
+ buf += 4;
+
+ if (in_size == out_size) {
+ for (i = 0; i < out_size; i++)
+ *samples++ = (*buf++ - 0x80) << 8;
+ return buf_size;
+ }
+
+ while (out_size > 0) {
+ int code;
+ uint8_t count;
+ code = (*buf) >> 6;
+ count = (*buf) & 0x3F;
+ buf++;
+ switch(code) {
+ case 0: /* ADPCM 2-bit */
+ for (count++; count > 0; count--) {
+ code = *buf++;
+ sample += ws_adpcm_2bit[code & 0x3];
+ CLIP8(sample);
+ *samples++ = sample << 8;
+ sample += ws_adpcm_2bit[(code >> 2) & 0x3];
+ CLIP8(sample);
+ *samples++ = sample << 8;
+ sample += ws_adpcm_2bit[(code >> 4) & 0x3];
+ CLIP8(sample);
+ *samples++ = sample << 8;
+ sample += ws_adpcm_2bit[(code >> 6) & 0x3];
+ CLIP8(sample);
+ *samples++ = sample << 8;
+ out_size -= 4;
+ }
+ break;
+ case 1: /* ADPCM 4-bit */
+ for (count++; count > 0; count--) {
+ code = *buf++;
+ sample += ws_adpcm_4bit[code & 0xF];
+ CLIP8(sample);
+ *samples++ = sample << 8;
+ sample += ws_adpcm_4bit[code >> 4];
+ CLIP8(sample);
+ *samples++ = sample << 8;
+ out_size -= 2;
+ }
+ break;
+ case 2: /* no compression */
+ if (count & 0x20) { /* big delta */
+ char t;
+ t = count;
+ t <<= 3;
+ sample += t >> 3;
+ *samples++ = sample << 8;
+ out_size--;
+ } else { /* copy */
+ for (count++; count > 0; count--) {
+ *samples++ = (*buf++ - 0x80) << 8;
+ out_size--;
+ }
+ sample = buf[-1] - 0x80;
+ }
+ break;
+ default: /* run */
+ for(count++; count > 0; count--) {
+ *samples++ = sample << 8;
+ out_size--;
+ }
+ }
+ }
+
+ return buf_size;
+}
+
+AVCodec ws_snd1_decoder = {
+ "ws_snd1",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_WESTWOOD_SND1,
+ 0,
+ ws_snd_decode_init,
+ NULL,
+ NULL,
+ ws_snd_decode_frame,
+};
diff --git a/contrib/ffmpeg/libavcodec/x264.c b/contrib/ffmpeg/libavcodec/x264.c
new file mode 100644
index 000000000..b08678779
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/x264.c
@@ -0,0 +1,299 @@
+/*
+ * H.264 encoding using the x264 library
+ * Copyright (C) 2005 Mans Rullgard <mru@inprovide.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 <x264.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct X264Context {
+ x264_param_t params;
+ x264_t *enc;
+ x264_picture_t pic;
+ AVFrame out_pic;
+} 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_ERROR,
+ [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(uint8_t *buf, int size, x264_nal_t *nals, int nnal)
+{
+ uint8_t *p = buf;
+ int i;
+
+ for(i = 0; i < nnal; i++){
+ int s = x264_nal_encode(p, &size, 1, nals + i);
+ if(s < 0)
+ return -1;
+ p += s;
+ }
+
+ return p - buf;
+}
+
+static int
+X264_frame(AVCodecContext *ctx, uint8_t *buf, int bufsize, void *data)
+{
+ X264Context *x4 = ctx->priv_data;
+ AVFrame *frame = data;
+ x264_nal_t *nal;
+ int nnal, i;
+ x264_picture_t pic_out;
+
+ x4->pic.img.i_csp = X264_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 = X264_TYPE_AUTO;
+ }
+
+ if(x264_encoder_encode(x4->enc, &nal, &nnal, frame? &x4->pic: NULL,
+ &pic_out))
+ return -1;
+
+ bufsize = encode_nals(buf, bufsize, nal, nnal);
+ if(bufsize < 0)
+ return -1;
+
+ /* FIXME: dts */
+ x4->out_pic.pts = pic_out.i_pts;
+
+ switch(pic_out.i_type){
+ case X264_TYPE_IDR:
+ case X264_TYPE_I:
+ x4->out_pic.pict_type = FF_I_TYPE;
+ break;
+ case X264_TYPE_P:
+ x4->out_pic.pict_type = FF_P_TYPE;
+ break;
+ case X264_TYPE_B:
+ case X264_TYPE_BREF:
+ x4->out_pic.pict_type = FF_B_TYPE;
+ break;
+ }
+
+ x4->out_pic.key_frame = pic_out.i_type == X264_TYPE_IDR;
+ x4->out_pic.quality = (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA;
+
+ return bufsize;
+}
+
+static int
+X264_close(AVCodecContext *avctx)
+{
+ X264Context *x4 = avctx->priv_data;
+
+ if(x4->enc)
+ x264_encoder_close(x4->enc);
+
+ return 0;
+}
+
+static int
+X264_init(AVCodecContext *avctx)
+{
+ X264Context *x4 = avctx->priv_data;
+
+ x264_param_default(&x4->params);
+
+ x4->params.pf_log = X264_log;
+ x4->params.p_log_private = avctx;
+
+ x4->params.i_keyint_max = avctx->gop_size;
+ x4->params.rc.i_bitrate = avctx->bit_rate / 1000;
+ 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(avctx->crf){
+ x4->params.rc.i_rc_method = X264_RC_CRF;
+ x4->params.rc.f_rf_constant = avctx->crf;
+ }else if(avctx->cqp > -1){
+ x4->params.rc.i_rc_method = X264_RC_CQP;
+ x4->params.rc.i_qp_constant = avctx->cqp;
+ }
+ }
+
+ // if neither crf nor cqp modes are selected we have to enable the RC
+ // we do it this way because we cannot check if the bitrate has been set
+ if(!(avctx->crf || (avctx->cqp > -1))) x4->params.rc.i_rc_method = X264_RC_ABR;
+
+ x4->params.i_bframe = avctx->max_b_frames;
+ x4->params.b_cabac = avctx->coder_type == FF_CODER_TYPE_AC;
+ x4->params.b_bframe_adaptive = avctx->b_frame_strategy;
+ x4->params.i_bframe_bias = avctx->bframebias;
+ x4->params.b_bframe_pyramid = (avctx->flags2 & CODEC_FLAG2_BPYRAMID);
+ avctx->has_b_frames= (avctx->flags2 & CODEC_FLAG2_BPYRAMID) ? 2 : !!avctx->max_b_frames;
+
+ 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.i_deblocking_filter_alphac0 = avctx->deblockalpha;
+ x4->params.i_deblocking_filter_beta = avctx->deblockbeta;
+
+ 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.rc.f_complexity_blur = avctx->complexityblur;
+
+ 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;
+ x4->params.i_fps_num = avctx->time_base.den;
+ x4->params.i_fps_den = avctx->time_base.num;
+
+ x4->params.analyse.inter = 0;
+ if(avctx->partitions){
+ if(avctx->partitions & X264_PART_I4X4)
+ x4->params.analyse.inter |= X264_ANALYSE_I4x4;
+ if(avctx->partitions & X264_PART_I8X8)
+ x4->params.analyse.inter |= X264_ANALYSE_I8x8;
+ if(avctx->partitions & X264_PART_P8X8)
+ x4->params.analyse.inter |= X264_ANALYSE_PSUB16x16;
+ if(avctx->partitions & X264_PART_P4X4)
+ x4->params.analyse.inter |= X264_ANALYSE_PSUB8x8;
+ if(avctx->partitions & X264_PART_B8X8)
+ x4->params.analyse.inter |= X264_ANALYSE_BSUB16x16;
+ }
+
+ x4->params.analyse.i_direct_mv_pred = avctx->directpred;
+
+ x4->params.analyse.b_weighted_bipred = (avctx->flags2 & CODEC_FLAG2_WPRED);
+
+ 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 x4->params.analyse.i_me_method = X264_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_bframe_rdo = (avctx->flags2 & CODEC_FLAG2_BRDO);
+ x4->params.analyse.b_mixed_references =
+ (avctx->flags2 & CODEC_FLAG2_MIXED_REFS);
+ x4->params.analyse.b_chroma_me = (avctx->me_cmp & FF_CMP_CHROMA);
+ x4->params.analyse.b_transform_8x8 = (avctx->flags2 & CODEC_FLAG2_8X8DCT);
+ x4->params.analyse.b_fast_pskip = (avctx->flags2 & CODEC_FLAG2_FASTPSKIP);
+
+ 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 != 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;
+ }
+ else x4->params.rc.f_vbv_buffer_init = 0.9;
+
+ 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.rc.psz_rc_eq = avctx->rc_eq;
+
+ x4->params.analyse.b_psnr = (avctx->flags & CODEC_FLAG_PSNR);
+ x4->params.i_log_level = X264_LOG_DEBUG;
+
+ x4->params.b_aud = (avctx->flags2 & CODEC_FLAG2_AUD);
+
+ x4->params.i_threads = avctx->thread_count;
+
+ if(avctx->flags & CODEC_FLAG_GLOBAL_HEADER){
+ x4->params.b_repeat_headers = 0;
+ }
+
+ 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;
+ int nnal, i, s = 0;
+
+ x264_encoder_headers(x4->enc, &nal, &nnal);
+
+ /* 5 bytes NAL header + worst case escaping */
+ for(i = 0; i < nnal; i++)
+ s += 5 + nal[i].i_payload * 4 / 3;
+
+ avctx->extradata = av_malloc(s);
+ avctx->extradata_size = encode_nals(avctx->extradata, s, nal, nnal);
+ }
+
+ return 0;
+}
+
+AVCodec x264_encoder = {
+ .name = "h264",
+ .type = CODEC_TYPE_VIDEO,
+ .id = CODEC_ID_H264,
+ .priv_data_size = sizeof(X264Context),
+ .init = X264_init,
+ .encode = X264_frame,
+ .close = X264_close,
+ .capabilities = CODEC_CAP_DELAY,
+ .pix_fmts = (enum PixelFormat[]) { PIX_FMT_YUV420P, -1 }
+};
diff --git a/contrib/ffmpeg/libavcodec/xan.c b/contrib/ffmpeg/libavcodec/xan.c
new file mode 100644
index 000000000..56ce87a95
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/xan.c
@@ -0,0 +1,492 @@
+/*
+ * 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.c
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "avcodec.h"
+
+typedef struct XanContext {
+
+ AVCodecContext *avctx;
+ AVFrame last_frame;
+ AVFrame current_frame;
+
+ unsigned char *buf;
+ int size;
+
+ /* scratch space */
+ unsigned char *buffer1;
+ int buffer1_size;
+ unsigned char *buffer2;
+ int buffer2_size;
+
+ int frame_size;
+
+} XanContext;
+
+static int xan_decode_init(AVCodecContext *avctx)
+{
+ XanContext *s = avctx->priv_data;
+
+ s->avctx = avctx;
+ s->frame_size = 0;
+
+ if ((avctx->codec->id == CODEC_ID_XAN_WC3) &&
+ (s->avctx->palctrl == NULL)) {
+ av_log(avctx, AV_LOG_ERROR, " WC3 Xan video: palette expected.\n");
+ return -1;
+ }
+
+ avctx->pix_fmt = PIX_FMT_PAL8;
+ avctx->has_b_frames = 0;
+
+ if(avcodec_check_dimensions(avctx, avctx->width, avctx->height))
+ return -1;
+
+ s->buffer1_size = avctx->width * avctx->height;
+ s->buffer1 = av_malloc(s->buffer1_size);
+ s->buffer2_size = avctx->width * avctx->height;
+ s->buffer2 = av_malloc(s->buffer2_size);
+ if (!s->buffer1 || !s->buffer2)
+ return -1;
+
+ return 0;
+}
+
+/* This function is used in lieu of memcpy(). This decoder can not use
+ * memcpy because the memory locations often overlap and
+ * memcpy doesn't like that; it's not uncommon, for example, for
+ * dest = src+1, to turn byte A into pattern AAAAAAAA.
+ * This was originally repz movsb in Intel x86 ASM. */
+static inline void bytecopy(unsigned char *dest, unsigned char *src, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ dest[i] = src[i];
+}
+
+static int xan_huffman_decode(unsigned char *dest, unsigned char *src,
+ int dest_len)
+{
+ unsigned char byte = *src++;
+ unsigned char ival = byte + 0x16;
+ unsigned char * ptr = src + byte*2;
+ unsigned char val = ival;
+ int counter = 0;
+ unsigned char *dest_end = dest + dest_len;
+
+ unsigned char bits = *ptr++;
+
+ while ( val != 0x16 ) {
+ if ( (1 << counter) & bits )
+ val = src[byte + val - 0x17];
+ else
+ val = src[val - 0x17];
+
+ if ( val < 0x16 ) {
+ if (dest + 1 > dest_end)
+ return 0;
+ *dest++ = val;
+ val = ival;
+ }
+
+ if (counter++ == 7) {
+ counter = 0;
+ bits = *ptr++;
+ }
+ }
+
+ return 0;
+}
+
+static void xan_unpack(unsigned char *dest, unsigned char *src, int dest_len)
+{
+ unsigned char opcode;
+ int size;
+ int offset;
+ int byte1, byte2, byte3;
+ unsigned char *dest_end = dest + dest_len;
+
+ for (;;) {
+ opcode = *src++;
+
+ if ( (opcode & 0x80) == 0 ) {
+
+ offset = *src++;
+
+ size = opcode & 3;
+ if (dest + size > dest_end)
+ return;
+ bytecopy(dest, src, size); dest += size; src += size;
+
+ size = ((opcode & 0x1c) >> 2) + 3;
+ if (dest + size > dest_end)
+ return;
+ bytecopy (dest, dest - (((opcode & 0x60) << 3) + offset + 1), size);
+ dest += size;
+
+ } else if ( (opcode & 0x40) == 0 ) {
+
+ byte1 = *src++;
+ byte2 = *src++;
+
+ size = byte1 >> 6;
+ if (dest + size > dest_end)
+ return;
+ bytecopy (dest, src, size); dest += size; src += size;
+
+ size = (opcode & 0x3f) + 4;
+ if (dest + size > dest_end)
+ return;
+ bytecopy (dest, dest - (((byte1 & 0x3f) << 8) + byte2 + 1), size);
+ dest += size;
+
+ } else if ( (opcode & 0x20) == 0 ) {
+
+ byte1 = *src++;
+ byte2 = *src++;
+ byte3 = *src++;
+
+ size = opcode & 3;
+ if (dest + size > dest_end)
+ return;
+ bytecopy (dest, src, size); dest += size; src += size;
+
+ size = byte3 + 5 + ((opcode & 0xc) << 6);
+ if (dest + size > dest_end)
+ return;
+ bytecopy (dest,
+ dest - ((((opcode & 0x10) >> 4) << 0x10) + 1 + (byte1 << 8) + byte2),
+ size);
+ dest += size;
+ } else {
+ size = ((opcode & 0x1f) << 2) + 4;
+
+ if (size > 0x70)
+ break;
+
+ if (dest + size > dest_end)
+ return;
+ bytecopy (dest, src, size); dest += size; src += size;
+ }
+ }
+
+ size = opcode & 3;
+ bytecopy(dest, src, size); dest += size; src += size;
+}
+
+static void inline xan_wc3_output_pixel_run(XanContext *s,
+ 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 = s->current_frame.data[0];
+ stride = s->current_frame.linesize[0];
+ line_inc = stride - width;
+ index = y * stride + x;
+ current_x = x;
+ while((pixel_count--) && (index < s->frame_size)) {
+
+ /* don't do a memcpy() here; keyframes generally copy an entire
+ * frame of data and the stride needs to be accounted for */
+ palette_plane[index++] = *pixel_buffer++;
+
+ current_x++;
+ if (current_x >= width) {
+ index += line_inc;
+ current_x = 0;
+ }
+ }
+}
+
+static void inline xan_wc3_copy_pixel_run(XanContext *s,
+ 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;
+
+ palette_plane = s->current_frame.data[0];
+ prev_palette_plane = s->last_frame.data[0];
+ stride = s->current_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)) {
+
+ palette_plane[curframe_index++] =
+ prev_palette_plane[prevframe_index++];
+
+ curframe_x++;
+ if (curframe_x >= width) {
+ curframe_index += line_inc;
+ curframe_x = 0;
+ }
+
+ prevframe_x++;
+ if (prevframe_x >= width) {
+ prevframe_index += line_inc;
+ prevframe_x = 0;
+ }
+ }
+}
+
+static void xan_wc3_decode_frame(XanContext *s) {
+
+ 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;
+ int opcode_buffer_size = s->buffer1_size;
+ unsigned char *imagedata_buffer = s->buffer2;
+ int imagedata_buffer_size = s->buffer2_size;
+
+ /* pointers to segments inside the compressed chunk */
+ unsigned char *huffman_segment;
+ unsigned char *size_segment;
+ unsigned char *vector_segment;
+ unsigned char *imagedata_segment;
+
+ huffman_segment = s->buf + LE_16(&s->buf[0]);
+ size_segment = s->buf + LE_16(&s->buf[2]);
+ vector_segment = s->buf + LE_16(&s->buf[4]);
+ imagedata_segment = s->buf + LE_16(&s->buf[6]);
+
+ xan_huffman_decode(opcode_buffer, huffman_segment, opcode_buffer_size);
+
+ if (imagedata_segment[0] == 2)
+ xan_unpack(imagedata_buffer, &imagedata_segment[1],
+ imagedata_buffer_size);
+ else
+ imagedata_buffer = &imagedata_segment[1];
+
+ /* use the decoded data segments to build the frame */
+ x = y = 0;
+ while (total_pixels) {
+
+ 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:
+ size = *size_segment++;
+ break;
+
+ case 10:
+ case 20:
+ size = BE_16(&size_segment[0]);
+ size_segment += 2;
+ break;
+
+ case 11:
+ case 21:
+ size = (size_segment[0] << 16) | (size_segment[1] << 8) |
+ size_segment[2];
+ size_segment += 3;
+ break;
+ }
+
+ if (opcode < 12) {
+ flag ^= 1;
+ if (flag) {
+ /* run of (size) pixels is unchanged from last frame */
+ xan_wc3_copy_pixel_run(s, x, y, size, 0, 0);
+ } else {
+ /* output a run of pixels from imagedata_buffer */
+ xan_wc3_output_pixel_run(s, imagedata_buffer, x, y, size);
+ imagedata_buffer += size;
+ }
+ } else {
+ /* run-based motion compensation from last frame */
+ motion_x = (*vector_segment >> 4) & 0xF;
+ motion_y = *vector_segment & 0xF;
+ vector_segment++;
+
+ /* sign extension */
+ if (motion_x & 0x8)
+ motion_x |= 0xFFFFFFF0;
+ if (motion_y & 0x8)
+ motion_y |= 0xFFFFFFF0;
+
+ /* copy a run of pixels from the previous frame */
+ xan_wc3_copy_pixel_run(s, x, y, size, motion_x, motion_y);
+
+ flag = 0;
+ }
+
+ /* coordinate accounting */
+ total_pixels -= size;
+ while (size) {
+ if (x + size >= width) {
+ y++;
+ size -= (width - x);
+ x = 0;
+ } else {
+ x += size;
+ size = 0;
+ }
+ }
+ }
+}
+
+static void xan_wc4_decode_frame(XanContext *s) {
+}
+
+static int xan_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ XanContext *s = avctx->priv_data;
+ AVPaletteControl *palette_control = avctx->palctrl;
+
+ if (avctx->get_buffer(avctx, &s->current_frame)) {
+ av_log(s->avctx, AV_LOG_ERROR, " Xan Video: get_buffer() failed\n");
+ return -1;
+ }
+ s->current_frame.reference = 3;
+
+ if (!s->frame_size)
+ s->frame_size = s->current_frame.linesize[0] * s->avctx->height;
+
+ palette_control->palette_changed = 0;
+ memcpy(s->current_frame.data[1], palette_control->palette,
+ AVPALETTE_SIZE);
+ s->current_frame.palette_has_changed = 1;
+
+ s->buf = buf;
+ s->size = buf_size;
+
+ if (avctx->codec->id == CODEC_ID_XAN_WC3)
+ xan_wc3_decode_frame(s);
+ else if (avctx->codec->id == CODEC_ID_XAN_WC4)
+ xan_wc4_decode_frame(s);
+
+ /* release the last frame if it is allocated */
+ if (s->last_frame.data[0])
+ avctx->release_buffer(avctx, &s->last_frame);
+
+ /* shuffle frames */
+ s->last_frame = s->current_frame;
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = s->current_frame;
+
+ /* always report that the buffer was completely consumed */
+ return buf_size;
+}
+
+static int xan_decode_end(AVCodecContext *avctx)
+{
+ XanContext *s = avctx->priv_data;
+
+ /* release the last frame */
+ if (s->last_frame.data[0])
+ avctx->release_buffer(avctx, &s->last_frame);
+
+ av_free(s->buffer1);
+ av_free(s->buffer2);
+
+ return 0;
+}
+
+AVCodec xan_wc3_decoder = {
+ "xan_wc3",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_XAN_WC3,
+ sizeof(XanContext),
+ xan_decode_init,
+ NULL,
+ xan_decode_end,
+ xan_decode_frame,
+ CODEC_CAP_DR1,
+};
+
+/*
+AVCodec xan_wc4_decoder = {
+ "xan_wc4",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_XAN_WC4,
+ sizeof(XanContext),
+ xan_decode_init,
+ NULL,
+ xan_decode_end,
+ xan_decode_frame,
+ CODEC_CAP_DR1,
+};
+*/
diff --git a/contrib/ffmpeg/libavcodec/xl.c b/contrib/ffmpeg/libavcodec/xl.c
new file mode 100644
index 000000000..67ad237e1
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/xl.c
@@ -0,0 +1,140 @@
+/*
+ * 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 xl.c
+ * Miro VideoXL codec.
+ */
+
+#include "avcodec.h"
+#include "mpegvideo.h"
+
+typedef struct VideoXLContext{
+ AVCodecContext *avctx;
+ AVFrame pic;
+} VideoXLContext;
+
+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 *data_size,
+ uint8_t *buf, int buf_size)
+{
+ VideoXLContext * const a = avctx->priv_data;
+ AVFrame * const p= (AVFrame*)&a->pic;
+ uint8_t *Y, *U, *V;
+ int i, j;
+ int stride;
+ uint32_t val;
+ int y0, y1, y2, y3, c0, c1;
+
+ if(p->data[0])
+ avctx->release_buffer(avctx, p);
+
+ p->reference = 0;
+ if(avctx->get_buffer(avctx, p) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+ p->pict_type= I_TYPE;
+ p->key_frame= 1;
+
+ Y = a->pic.data[0];
+ U = a->pic.data[1];
+ V = a->pic.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 = LE_32(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 += a->pic.linesize[0];
+ U += a->pic.linesize[1];
+ V += a->pic.linesize[2];
+ }
+
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = a->pic;
+
+ return buf_size;
+}
+
+static int decode_init(AVCodecContext *avctx){
+// VideoXLContext * const a = avctx->priv_data;
+
+ avctx->pix_fmt= PIX_FMT_YUV411P;
+
+ return 0;
+}
+
+AVCodec xl_decoder = {
+ "xl",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_VIXL,
+ sizeof(VideoXLContext),
+ decode_init,
+ NULL,
+ NULL,
+ decode_frame,
+ CODEC_CAP_DR1,
+};
diff --git a/contrib/ffmpeg/libavcodec/xvid_internal.h b/contrib/ffmpeg/libavcodec/xvid_internal.h
new file mode 100644
index 000000000..49c59c205
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/xvid_internal.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 XVID_INTERNAL_H
+#define XVID_INTERNAL_H
+
+/**
+ * @file xvid_internal.h
+ * common functions for use with the XviD wrappers
+ */
+
+
+int av_tempfile(char *prefix, char **filename);
+
+#endif /* XVID_INTERNAL_H */
diff --git a/contrib/ffmpeg/libavcodec/xvid_rc.c b/contrib/ffmpeg/libavcodec/xvid_rc.c
new file mode 100644
index 000000000..6a0029e6d
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/xvid_rc.c
@@ -0,0 +1,148 @@
+/*
+ * xvid Rate control wrapper for lavc video encoders
+ *
+ * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <xvid.h>
+#include <unistd.h>
+#include "avcodec.h"
+#include "xvid_internal.h"
+//#include "dsputil.h"
+#include "mpegvideo.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+extern unsigned int xvid_debug;
+
+int ff_xvid_rate_control_init(MpegEncContext *s){
+ char *tmp_name;
+ int fd, i;
+ xvid_plg_create_t xvid_plg_create;
+ xvid_plugin_2pass2_t xvid_2pass2;
+
+//xvid_debug=-1;
+
+ fd=av_tempfile("xvidrc.", &tmp_name);
+ if (fd == -1) {
+ av_log(NULL, AV_LOG_ERROR, "Can't create temporary pass2 file.\n");
+ return -1;
+ }
+
+ for(i=0; i<s->rc_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);
+
+//av_log(NULL, AV_LOG_ERROR, "%s\n", tmp);
+ write(fd, tmp, strlen(tmp));
+ }
+
+ close(fd);
+
+ memset(&xvid_2pass2, 0, sizeof(xvid_2pass2));
+ 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;
+
+ memset(&xvid_plg_create, 0, sizeof(xvid_plg_create));
+ 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;
+
+ memset(&xvid_plg_data, 0, sizeof(xvid_plg_data));
+ 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 0
+ xvid_plg_data.stats.hlength= X
+#endif
+
+ 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 == B_TYPE) //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/contrib/ffmpeg/libavcodec/xvidff.c b/contrib/ffmpeg/libavcodec/xvidff.c
new file mode 100644
index 000000000..590fe4b30
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/xvidff.c
@@ -0,0 +1,768 @@
+/*
+ * Interface to xvidcore for mpeg4 encoding
+ * Copyright (c) 2004 Adam Thayer <krevnik@comcast.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 xvidmpeg4.c
+ * Interface to xvidcore for MPEG-4 compliant encoding.
+ * @author Adam Thayer (krevnik@comcast.net)
+ */
+
+#include <xvid.h>
+#include <unistd.h>
+#include "common.h"
+#include "avcodec.h"
+#include "xvid_internal.h"
+
+/**
+ * Buffer management macros.
+ */
+#define BUFFER_SIZE 1024
+#define BUFFER_REMAINING(x) (BUFFER_SIZE - strlen(x))
+#define BUFFER_CAT(x) (&((x)[strlen(x)]))
+
+/* For PPC Use */
+#if HAVE_ALTIVEC==1
+extern int has_altivec(void);
+#endif
+
+/**
+ * Structure for the private XviD context.
+ * This stores all the private context for the codec.
+ */
+typedef struct xvid_context {
+ void *encoder_handle; /** Handle for XviD Encoder */
+ int xsize, ysize; /** Frame 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 */
+ unsigned char *intra_matrix; /** P-Frame Quant Matrix */
+ unsigned char *inter_matrix; /** I-Frame Quant Matrix */
+} xvid_context_t;
+
+/**
+ * Structure for the private first-pass plugin.
+ */
+typedef struct xvid_ff_pass1 {
+ int version; /** XviD version */
+ xvid_context_t *context; /** Pointer to private context */
+} xvid_ff_pass1_t;
+
+/* Prototypes - See function implementation for details */
+int xvid_strip_vol_header(AVCodecContext *avctx, unsigned char *frame, unsigned int header_len, unsigned int frame_len);
+int xvid_ff_2pass(void *ref, int opt, void *p1, void *p2);
+void xvid_correct_framerate(AVCodecContext *avctx);
+
+/**
+ * Creates the private context for the encoder.
+ * All buffers are allocated, settings are loaded from the user,
+ * and the encoder context created.
+ *
+ * @param avctx AVCodecContext pointer to context
+ * @return Returns 0 on success, -1 on failure
+ */
+int ff_xvid_encode_init(AVCodecContext *avctx) {
+ int xerr, i;
+ int xvid_flags = avctx->flags;
+ xvid_context_t *x = avctx->priv_data;
+ uint16_t *intra, *inter;
+ int fd;
+
+ xvid_plugin_single_t single;
+ xvid_ff_pass1_t rc2pass1;
+ xvid_plugin_2pass2_t rc2pass2;
+ xvid_gbl_init_t xvid_gbl_init;
+ xvid_enc_create_t xvid_enc_create;
+ xvid_enc_plugin_t plugins[7];
+
+ /* 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( xvid_flags & CODEC_FLAG_TRELLIS_QUANT)
+ 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;
+ }
+
+ memset(&xvid_gbl_init, 0, sizeof(xvid_gbl_init));
+ xvid_gbl_init.version = XVID_VERSION;
+ xvid_gbl_init.debug = 0;
+
+#ifdef ARCH_POWERPC
+ /* XviD's PPC support is borked, use libavcodec to detect */
+#if HAVE_ALTIVEC==1
+ if( has_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 */
+ memset(&xvid_enc_create, 0, sizeof(xvid_enc_create));
+ 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 or threads */
+ xvid_enc_create.zones = NULL;
+ xvid_enc_create.num_zones = 0;
+ xvid_enc_create.num_threads = 0;
+
+ 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 ) {
+ memset(&rc2pass1, 0, sizeof(xvid_ff_pass1_t));
+ 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");
+ return -1;
+ }
+ 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 ) {
+ memset(&rc2pass2, 0, sizeof(xvid_plugin_2pass2_t));
+ rc2pass2.version = XVID_VERSION;
+ rc2pass2.bitrate = avctx->bit_rate;
+
+ fd = av_tempfile("xvidff.", &(x->twopassfile));
+ if( fd == -1 ) {
+ av_log(avctx, AV_LOG_ERROR,
+ "XviD: Cannot write 2-pass pipe\n");
+ return -1;
+ }
+
+ if( avctx->stats_in == NULL ) {
+ av_log(avctx, AV_LOG_ERROR,
+ "XviD: No 2-pass information loaded for second pass\n");
+ return -1;
+ }
+
+ if( strlen(avctx->stats_in) >
+ write(fd, avctx->stats_in, strlen(avctx->stats_in)) ) {
+ close(fd);
+ av_log(avctx, AV_LOG_ERROR,
+ "XviD: Cannot write to 2-pass pipe\n");
+ return -1;
+ }
+
+ close(fd);
+ 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! */
+ memset(&single, 0, sizeof(xvid_plugin_single_t));
+ 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 = CODEC_ID_MPEG4;
+ } else {
+ /* We are claiming to be XviD */
+ x->quicktime_format = 0;
+ if(!avctx->codec_tag)
+ avctx->codec_tag = ff_get_fourcc("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");
+ return -1;
+ }
+
+ x->encoder_handle = xvid_enc_create.handle;
+ avctx->coded_frame = &x->encoded_picture;
+
+ return 0;
+}
+
+/**
+ * Encodes a single frame.
+ *
+ * @param avctx AVCodecContext pointer to context
+ * @param frame Pointer to encoded frame buffer
+ * @param buf_size Size of encoded frame buffer
+ * @param data Pointer to AVFrame of unencoded frame
+ * @return Returns 0 on success, -1 on failure
+ */
+int ff_xvid_encode_frame(AVCodecContext *avctx,
+ unsigned char *frame, int buf_size, void *data) {
+ int xerr, i;
+ char *tmp;
+ xvid_context_t *x = avctx->priv_data;
+ AVFrame *picture = data;
+ AVFrame *p = &(x->encoded_picture);
+
+ xvid_enc_frame_t xvid_enc_frame;
+ xvid_enc_stats_t xvid_enc_stats;
+
+ /* Start setting up the frame */
+ memset(&xvid_enc_frame, 0, sizeof(xvid_enc_frame));
+ xvid_enc_frame.version = XVID_VERSION;
+ memset(&xvid_enc_stats, 0, sizeof(xvid_enc_stats));
+ xvid_enc_stats.version = XVID_VERSION;
+ *p = *picture;
+
+ /* Let XviD know where to put the frame. */
+ xvid_enc_frame.bitstream = frame;
+ xvid_enc_frame.length = buf_size;
+
+ /* Initialize input image fields */
+ if( avctx->pix_fmt != 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 = XVID_TYPE_AUTO;
+
+ /* 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( 0 <= xerr ) {
+ p->quality = xvid_enc_stats.quant * FF_QP2LAMBDA;
+ if( xvid_enc_stats.type == XVID_TYPE_PVOP )
+ p->pict_type = FF_P_TYPE;
+ else if( xvid_enc_stats.type == XVID_TYPE_BVOP )
+ p->pict_type = FF_B_TYPE;
+ else if( xvid_enc_stats.type == XVID_TYPE_SVOP )
+ p->pict_type = FF_S_TYPE;
+ else
+ p->pict_type = FF_I_TYPE;
+ if( xvid_enc_frame.out_flags & XVID_KEYFRAME ) {
+ p->key_frame = 1;
+ if( x->quicktime_format )
+ return xvid_strip_vol_header(avctx, frame,
+ xvid_enc_stats.hlength, xerr);
+ } else
+ p->key_frame = 0;
+
+ return xerr;
+ } else {
+ av_log(avctx, AV_LOG_ERROR, "XviD: Encoding Error Occurred: %i\n", xerr);
+ return -1;
+ }
+}
+
+/**
+ * Destroys the private context for the encoder.
+ * All buffers are freed, and the XviD encoder context is destroyed.
+ *
+ * @param avctx AVCodecContext pointer to context
+ * @return Returns 0, success guaranteed
+ */
+int ff_xvid_encode_close(AVCodecContext *avctx) {
+ xvid_context_t *x = avctx->priv_data;
+
+ xvid_encore(x->encoder_handle, XVID_ENC_DESTROY, NULL, NULL);
+
+ if( avctx->extradata != NULL )
+ av_free(avctx->extradata);
+ if( x->twopassbuffer != NULL ) {
+ av_free(x->twopassbuffer);
+ av_free(x->old_twopassbuffer);
+ }
+ if( x->twopassfile != NULL )
+ av_free(x->twopassfile);
+ if( x->intra_matrix != NULL )
+ av_free(x->intra_matrix);
+ if( x->inter_matrix != NULL )
+ av_free(x->inter_matrix);
+
+ return 0;
+}
+
+/**
+ * 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
+ */
+int xvid_strip_vol_header(AVCodecContext *avctx,
+ unsigned char *frame,
+ unsigned int header_len,
+ unsigned int frame_len) {
+ int vo_len = 0, i;
+
+ for( i = 0; i < header_len - 3; i++ ) {
+ if( frame[i] == 0x00 &&
+ frame[i+1] == 0x00 &&
+ frame[i+2] == 0x01 &&
+ frame[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, frame, vo_len);
+ avctx->extradata_size = vo_len;
+ }
+ /* Less dangerous now, memmove properly copies the two
+ chunks of overlapping data */
+ memmove(frame, &(frame[vo_len]), frame_len - vo_len);
+ return frame_len - vo_len;
+ } else
+ return frame_len;
+}
+
+/**
+ * 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.
+ */
+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 = ff_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 = ff_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;
+ }
+}
+
+/*
+ * 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.
+ */
+
+/**
+ * Initializes 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) {
+ xvid_ff_pass1_t *x = (xvid_ff_pass1_t *)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;
+}
+
+/**
+ * Destroys 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(xvid_context_t *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;
+}
+
+/**
+ * Enables 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(xvid_context_t *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;
+}
+
+/**
+ * Captures statistic data and writes 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(xvid_context_t *ref,
+ xvid_plg_data_t *param) {
+ char *log = ref->twopassbuffer;
+ 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
+ */
+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;
+ }
+}
+
+/**
+ * XviD codec definition for libavcodec.
+ */
+AVCodec xvid_encoder = {
+ "xvid",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_XVID,
+ sizeof(xvid_context_t),
+ ff_xvid_encode_init,
+ ff_xvid_encode_frame,
+ ff_xvid_encode_close,
+ .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
+};
diff --git a/contrib/ffmpeg/libavcodec/xvmcvideo.c b/contrib/ffmpeg/libavcodec/xvmcvideo.c
new file mode 100644
index 000000000..4a0677f6e
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/xvmcvideo.c
@@ -0,0 +1,318 @@
+/*
+ * 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 <limits.h>
+
+//avcodec include
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+#ifdef USE_FASTMEMCPY
+#include "libvo/fastmemcpy.h"
+#endif
+
+#ifdef HAVE_XVMC
+
+//X11 includes are in the xvmc_render.h
+//by replacing it with none-X one
+//XvMC emulation could be performed
+
+#include "xvmc_render.h"
+
+//#include "xvmc_debug.h"
+
+//set s->block
+inline void XVMC_init_block(MpegEncContext *s){
+xvmc_render_state_t * render;
+ render = (xvmc_render_state_t*)s->current_picture.data[2];
+ assert(render != NULL);
+ if( (render == NULL) || (render->magic != MP_XVMC_RENDER_MAGIC) ){
+ assert(0);
+ return;//make sure that this is render packet
+ }
+ s->block =(DCTELEM *)(render->data_blocks+(render->next_free_data_block_num)*64);
+}
+
+void XVMC_pack_pblocks(MpegEncContext *s, int cbp){
+int i,j;
+const int mb_block_count = 4+(1<<s->chroma_format);
+
+ j=0;
+ cbp<<= 12-mb_block_count;
+ for(i=0; i<mb_block_count; i++){
+ if(cbp & (1<<11)) {
+ s->pblocks[i] = (short *)(&s->block[(j++)]);
+ }else{
+ s->pblocks[i] = NULL;
+ }
+ cbp+=cbp;
+// printf("s->pblocks[%d]=%p ,s->block=%p cbp=%d\n",i,s->pblocks[i],s->block,cbp);
+ }
+}
+
+//these functions should be called on every new field or/and frame
+//They should be safe if they are called few times for same field!
+int XVMC_field_start(MpegEncContext*s, AVCodecContext *avctx){
+xvmc_render_state_t * render,* last, * next;
+
+ assert(avctx != NULL);
+
+ render = (xvmc_render_state_t*)s->current_picture.data[2];
+ assert(render != NULL);
+ if( (render == NULL) || (render->magic != MP_XVMC_RENDER_MAGIC) )
+ return -1;//make sure that this is render packet
+
+ render->picture_structure = s->picture_structure;
+ render->flags = (s->first_field)? 0: XVMC_SECOND_FIELD;
+
+//make sure that all data is drawn by XVMC_end_frame
+ assert(render->filled_mv_blocks_num==0);
+
+ render->p_future_surface = NULL;
+ render->p_past_surface = NULL;
+
+ switch(s->pict_type){
+ case I_TYPE:
+ return 0;// no prediction from other frames
+ case B_TYPE:
+ next = (xvmc_render_state_t*)s->next_picture.data[2];
+ assert(next!=NULL);
+ assert(next->state & MP_XVMC_STATE_PREDICTION);
+ if(next == NULL) return -1;
+ if(next->magic != MP_XVMC_RENDER_MAGIC) return -1;
+ render->p_future_surface = next->p_surface;
+ //no return here, going to set forward prediction
+ case P_TYPE:
+ last = (xvmc_render_state_t*)s->last_picture.data[2];
+ if(last == NULL)// && !s->first_field)
+ last = render;//predict second field from the first
+ if(last->magic != MP_XVMC_RENDER_MAGIC) return -1;
+ assert(last->state & MP_XVMC_STATE_PREDICTION);
+ render->p_past_surface = last->p_surface;
+ return 0;
+ }
+
+return -1;
+}
+
+void XVMC_field_end(MpegEncContext *s){
+xvmc_render_state_t * render;
+ render = (xvmc_render_state_t*)s->current_picture.data[2];
+ assert(render != NULL);
+
+ if(render->filled_mv_blocks_num > 0){
+// printf("xvmcvideo.c: rendering %d left blocks after last slice!!!\n",render->filled_mv_blocks_num );
+ ff_draw_horiz_band(s,0,0);
+ }
+}
+
+void XVMC_decode_mb(MpegEncContext *s){
+XvMCMacroBlock * mv_block;
+xvmc_render_state_t * 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 hurrt
+ s->current_picture.qscale_table[mb_xy] = s->qscale;
+
+//START OF XVMC specific code
+ render = (xvmc_render_state_t*)s->current_picture.data[2];
+ assert(render!=NULL);
+ assert(render->magic==MP_XVMC_RENDER_MAGIC);
+ assert(render->mv_blocks);
+
+ //take the next free macroblock
+ mv_block = &render->mv_blocks[render->start_mv_blocks_num +
+ render->filled_mv_blocks_num ];
+
+// memset(mv_block,0,sizeof(XvMCMacroBlock));
+
+ mv_block->x = s->mb_x;
+ mv_block->y = s->mb_y;
+ mv_block->dct_type = s->interlaced_dct;//XVMC_DCT_TYPE_FRAME/FIELD;
+// mv_block->motion_type = 0; //zero to silense warnings
+ 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 referenses
+ if(s->mv_type == MV_TYPE_FIELD || s->mv_type == MV_TYPE_16X8){
+ if( s->field_select[0][0] ) mv_block->motion_vertical_field_select|=1;
+ if( s->field_select[1][0] ) mv_block->motion_vertical_field_select|=2;
+ if( s->field_select[0][1] ) mv_block->motion_vertical_field_select|=4;
+ if( s->field_select[1][1] ) mv_block->motion_vertical_field_select|=8;
+ }
+ }//!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 alwasy full chroma block
+ for(i=4; i<blocks_per_mb; i++){
+ memset(s->pblocks[i],0,sizeof(short)*8*8);//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->idct && !render->unsigned_intra)) )
+ s->pblocks[i][0]-=1<<10;
+ if(!render->idct){
+ s->dsp.idct(s->pblocks[i]);
+ //!!TODO!clip!!!
+ }
+//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(short)*8*8);
+ }else{
+/* if(s->pblocks[i] != &render->data_blocks[
+ (render->next_free_data_block_num)*64]){
+ printf("ERROR mb(%d,%d) s->pblocks[i]=%p data_block[]=%p\n",
+ s->mb_x,s->mb_y, s->pblocks[i],
+ &render->data_blocks[(render->next_free_data_block_num)*64]);
+ }*/
+ }
+ render->next_free_data_block_num++;
+ }
+ }
+ render->filled_mv_blocks_num++;
+
+ assert(render->filled_mv_blocks_num <= render->total_number_of_mv_blocks);
+ assert(render->next_free_data_block_num <= render->total_number_of_data_blocks);
+
+
+ if(render->filled_mv_blocks_num >= render->total_number_of_mv_blocks)
+ ff_draw_horiz_band(s,0,0);
+
+// DumpRenderInfo(render);
+// DumpMBlockInfo(mv_block);
+
+}
+
+#endif
diff --git a/contrib/ffmpeg/libavcodec/zmbv.c b/contrib/ffmpeg/libavcodec/zmbv.c
new file mode 100644
index 000000000..fe3745e09
--- /dev/null
+++ b/contrib/ffmpeg/libavcodec/zmbv.c
@@ -0,0 +1,692 @@
+/*
+ * 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 zmbv.c
+ * Zip Motion Blocks Video decoder
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "common.h"
+#include "avcodec.h"
+
+#ifdef CONFIG_ZLIB
+#include <zlib.h>
+#endif
+
+#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;
+ AVFrame pic;
+
+ 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 bw, bh, bx, by;
+ int decomp_len;
+#ifdef CONFIG_ZLIB
+ z_stream zstream;
+#endif
+ 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 %i 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 %i 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 %i 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 *data_size, uint8_t *buf, int buf_size)
+{
+ ZmbvContext * const c = (ZmbvContext *)avctx->priv_data;
+ uint8_t *outptr;
+#ifdef CONFIG_ZLIB
+ int zret = Z_OK; // Zlib return code
+#endif
+ int len = buf_size;
+ int hi_ver, lo_ver;
+
+ if(c->pic.data[0])
+ avctx->release_buffer(avctx, &c->pic);
+
+ c->pic.reference = 1;
+ c->pic.buffer_hints = FF_BUFFER_HINTS_VALID;
+ if(avctx->get_buffer(avctx, &c->pic) < 0){
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
+
+ outptr = c->pic.data[0]; // Output image pointer
+
+ /* parse header */
+ c->flags = buf[0];
+ buf++; len--;
+ if(c->flags & ZMBV_KEYFRAME) {
+ hi_ver = buf[0];
+ lo_ver = buf[1];
+ c->comp = buf[2];
+ c->fmt = buf[3];
+ c->bw = buf[4];
+ c->bh = buf[5];
+
+ 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) {
+ av_log(avctx, AV_LOG_ERROR, "Unsupported version %i.%i\n", hi_ver, lo_ver);
+ return -1;
+ }
+ if(c->bw == 0 || c->bh == 0) {
+ av_log(avctx, AV_LOG_ERROR, "Unsupported block size %ix%i\n", c->bw, c->bh);
+ }
+ if(c->comp != 0 && c->comp != 1) {
+ av_log(avctx, AV_LOG_ERROR, "Unsupported compression type %i\n", c->comp);
+ return -1;
+ }
+
+ switch(c->fmt) {
+ case ZMBV_FMT_8BPP:
+ c->bpp = 8;
+ c->decode_intra = zmbv_decode_intra;
+ c->decode_xor = zmbv_decode_xor_8;
+ break;
+ case ZMBV_FMT_15BPP:
+ case ZMBV_FMT_16BPP:
+ c->bpp = 16;
+ c->decode_intra = zmbv_decode_intra;
+ c->decode_xor = zmbv_decode_xor_16;
+ break;
+#ifdef ZMBV_ENABLE_24BPP
+ case ZMBV_FMT_24BPP:
+ c->bpp = 24;
+ c->decode_intra = zmbv_decode_intra;
+ c->decode_xor = zmbv_decode_xor_24;
+ break;
+#endif //ZMBV_ENABLE_24BPP
+ case ZMBV_FMT_32BPP:
+ c->bpp = 32;
+ c->decode_intra = zmbv_decode_intra;
+ c->decode_xor = zmbv_decode_xor_32;
+ break;
+ default:
+ c->decode_intra = NULL;
+ c->decode_xor = NULL;
+ av_log(avctx, AV_LOG_ERROR, "Unsupported (for now) format %i\n", c->fmt);
+ return -1;
+ }
+#ifdef CONFIG_ZLIB
+ zret = inflateReset(&c->zstream);
+ if (zret != Z_OK) {
+ av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret);
+ return -1;
+ }
+#else
+ av_log(avctx, AV_LOG_ERROR, "BUG! Zlib support not compiled in frame decoder.\n");
+ return -1;
+#endif /* CONFIG_ZLIB */
+ c->cur = av_realloc(c->cur, avctx->width * avctx->height * (c->bpp / 8));
+ c->prev = av_realloc(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->decode_intra == NULL) {
+ av_log(avctx, AV_LOG_ERROR, "Error! Got no format or no keyframe!\n");
+ return -1;
+ }
+
+ if(c->comp == 0) { //Uncompressed data
+ memcpy(c->decomp_buf, buf, len);
+ c->decomp_size = 1;
+ } else { // ZLIB-compressed data
+#ifdef CONFIG_ZLIB
+ c->zstream.total_in = c->zstream.total_out = 0;
+ c->zstream.next_in = buf;
+ c->zstream.avail_in = len;
+ c->zstream.next_out = c->decomp_buf;
+ c->zstream.avail_out = c->decomp_size;
+ inflate(&c->zstream, Z_FINISH);
+ c->decomp_len = c->zstream.total_out;
+#else
+ av_log(avctx, AV_LOG_ERROR, "BUG! Zlib support not compiled in frame decoder.\n");
+ return -1;
+#endif
+ }
+ if(c->flags & ZMBV_KEYFRAME) {
+ c->pic.key_frame = 1;
+ c->pic.pict_type = FF_I_TYPE;
+ c->decode_intra(c);
+ } else {
+ c->pic.key_frame = 0;
+ c->pic.pict_type = FF_P_TYPE;
+ c->decode_xor(c);
+ }
+
+ /* update frames */
+ {
+ uint8_t *out, *src;
+ int i, j;
+
+ out = c->pic.data[0];
+ src = c->cur;
+ switch(c->fmt) {
+ case ZMBV_FMT_8BPP:
+ for(j = 0; j < c->height; j++) {
+ for(i = 0; i < c->width; i++) {
+ out[i * 3 + 0] = c->pal[(*src) * 3 + 0];
+ out[i * 3 + 1] = c->pal[(*src) * 3 + 1];
+ out[i * 3 + 2] = c->pal[(*src) * 3 + 2];
+ *src++;
+ }
+ out += c->pic.linesize[0];
+ }
+ break;
+ case ZMBV_FMT_15BPP:
+ for(j = 0; j < c->height; j++) {
+ for(i = 0; i < c->width; i++) {
+ uint16_t tmp = LE_16(src);
+ src += 2;
+ out[i * 3 + 0] = (tmp & 0x7C00) >> 7;
+ out[i * 3 + 1] = (tmp & 0x03E0) >> 2;
+ out[i * 3 + 2] = (tmp & 0x001F) << 3;
+ }
+ out += c->pic.linesize[0];
+ }
+ break;
+ case ZMBV_FMT_16BPP:
+ for(j = 0; j < c->height; j++) {
+ for(i = 0; i < c->width; i++) {
+ uint16_t tmp = LE_16(src);
+ src += 2;
+ out[i * 3 + 0] = (tmp & 0xF800) >> 8;
+ out[i * 3 + 1] = (tmp & 0x07E0) >> 3;
+ out[i * 3 + 2] = (tmp & 0x001F) << 3;
+ }
+ out += c->pic.linesize[0];
+ }
+ break;
+#ifdef ZMBV_ENABLE_24BPP
+ case ZMBV_FMT_24BPP:
+ for(j = 0; j < c->height; j++) {
+ memcpy(out, src, c->width * 3);
+ src += c->width * 3;
+ out += c->pic.linesize[0];
+ }
+ break;
+#endif //ZMBV_ENABLE_24BPP
+ case ZMBV_FMT_32BPP:
+ for(j = 0; j < c->height; j++) {
+ for(i = 0; i < c->width; i++) {
+ uint32_t tmp = LE_32(src);
+ src += 4;
+ out[i * 3 + 0] = tmp >> 16;
+ out[i * 3 + 1] = tmp >> 8;
+ out[i * 3 + 2] = tmp >> 0;
+ }
+ out += c->pic.linesize[0];
+ }
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "Cannot handle format %i\n", c->fmt);
+ }
+ memcpy(c->prev, c->cur, c->width * c->height * (c->bpp / 8));
+ }
+ *data_size = sizeof(AVFrame);
+ *(AVFrame*)data = c->pic;
+
+ /* always report that the buffer was completely consumed */
+ return buf_size;
+}
+
+
+
+/*
+ *
+ * Init zmbv decoder
+ *
+ */
+static int decode_init(AVCodecContext *avctx)
+{
+ ZmbvContext * const c = (ZmbvContext *)avctx->priv_data;
+ int zret; // Zlib return code
+
+ c->avctx = avctx;
+ avctx->has_b_frames = 0;
+
+ c->pic.data[0] = NULL;
+ c->width = avctx->width;
+ c->height = avctx->height;
+
+ if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
+ return 1;
+ }
+ c->bpp = avctx->bits_per_sample;
+
+#ifdef CONFIG_ZLIB
+ // Needed if zlib unused or init aborted before inflateInit
+ memset(&(c->zstream), 0, sizeof(z_stream));
+#else
+ av_log(avctx, AV_LOG_ERROR, "Zlib support not compiled.\n");
+ return 1;
+#endif
+ avctx->pix_fmt = PIX_FMT_RGB24;
+ c->decomp_size = (avctx->width + 255) * 4 * (avctx->height + 64);
+
+ /* 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 1;
+ }
+ }
+
+#ifdef CONFIG_ZLIB
+ 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 1;
+ }
+#endif
+
+ return 0;
+}
+
+
+
+/*
+ *
+ * Uninit zmbv decoder
+ *
+ */
+static int decode_end(AVCodecContext *avctx)
+{
+ ZmbvContext * const c = (ZmbvContext *)avctx->priv_data;
+
+ av_freep(&c->decomp_buf);
+
+ if (c->pic.data[0])
+ avctx->release_buffer(avctx, &c->pic);
+#ifdef CONFIG_ZLIB
+ inflateEnd(&(c->zstream));
+#endif
+ av_freep(&c->cur);
+ av_freep(&c->prev);
+
+ return 0;
+}
+
+AVCodec zmbv_decoder = {
+ "zmbv",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_ZMBV,
+ sizeof(ZmbvContext),
+ decode_init,
+ NULL,
+ decode_end,
+ decode_frame
+};
+
diff --git a/contrib/ffmpeg/libavformat/4xm.c b/contrib/ffmpeg/libavformat/4xm.c
new file mode 100644
index 000000000..12e7d9ee4
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/4xm.c
@@ -0,0 +1,331 @@
+/*
+ * 4X Technologies .4xm File Demuxer (no muxer)
+ * 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 4xm.c
+ * 4X Technologies file demuxer
+ * by Mike Melanson (melanson@pcisys.net)
+ * for more information on the .4xm file format, visit:
+ * http://www.pcisys.net/~melanson/codecs/
+ */
+
+#include "avformat.h"
+
+#define RIFF_TAG MKTAG('R', 'I', 'F', 'F')
+#define _4XMV_TAG MKTAG('4', 'X', 'M', 'V')
+#define LIST_TAG MKTAG('L', 'I', 'S', 'T')
+#define HEAD_TAG MKTAG('H', 'E', 'A', 'D')
+#define TRK__TAG MKTAG('T', 'R', 'K', '_')
+#define MOVI_TAG MKTAG('M', 'O', 'V', 'I')
+#define VTRK_TAG MKTAG('V', 'T', 'R', 'K')
+#define STRK_TAG MKTAG('S', 'T', 'R', 'K')
+#define std__TAG MKTAG('s', 't', 'd', '_')
+#define name_TAG MKTAG('n', 'a', 'm', 'e')
+#define vtrk_TAG MKTAG('v', 't', 'r', 'k')
+#define strk_TAG MKTAG('s', 't', 'r', 'k')
+#define ifrm_TAG MKTAG('i', 'f', 'r', 'm')
+#define pfrm_TAG MKTAG('p', 'f', 'r', 'm')
+#define cfrm_TAG MKTAG('c', 'f', 'r', 'm')
+#define snd__TAG MKTAG('s', 'n', 'd', '_')
+
+#define vtrk_SIZE 0x44
+#define strk_SIZE 0x28
+
+#define GET_LIST_HEADER() \
+ fourcc_tag = get_le32(pb); \
+ size = get_le32(pb); \
+ if (fourcc_tag != LIST_TAG) \
+ return AVERROR_INVALIDDATA; \
+ fourcc_tag = get_le32(pb);
+
+typedef struct AudioTrack {
+ int sample_rate;
+ int bits;
+ int channels;
+ int stream_index;
+ int adpcm;
+} AudioTrack;
+
+typedef struct FourxmDemuxContext {
+ int width;
+ int height;
+ int video_stream_index;
+ int track_count;
+ AudioTrack *tracks;
+ int selected_track;
+
+ int64_t audio_pts;
+ int64_t video_pts;
+ float fps;
+} FourxmDemuxContext;
+
+static int fourxm_probe(AVProbeData *p)
+{
+ if (p->buf_size < 12)
+ return 0;
+
+ if ((LE_32(&p->buf[0]) != RIFF_TAG) ||
+ (LE_32(&p->buf[8]) != _4XMV_TAG))
+ return 0;
+
+ return AVPROBE_SCORE_MAX;
+}
+
+static int fourxm_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ ByteIOContext *pb = &s->pb;
+ unsigned int fourcc_tag;
+ unsigned int size;
+ int header_size;
+ FourxmDemuxContext *fourxm = (FourxmDemuxContext *)s->priv_data;
+ unsigned char *header;
+ int i;
+ int current_track = -1;
+ AVStream *st;
+
+ fourxm->track_count = 0;
+ fourxm->tracks = NULL;
+ fourxm->selected_track = 0;
+ fourxm->fps = 1.0;
+
+ /* skip the first 3 32-bit numbers */
+ url_fseek(pb, 12, SEEK_CUR);
+
+ /* check for LIST-HEAD */
+ GET_LIST_HEADER();
+ header_size = size - 4;
+ if (fourcc_tag != HEAD_TAG)
+ return AVERROR_INVALIDDATA;
+
+ /* allocate space for the header and load the whole thing */
+ header = av_malloc(header_size);
+ if (!header)
+ return AVERROR_NOMEM;
+ if (get_buffer(pb, header, header_size) != header_size)
+ return AVERROR_IO;
+
+ /* take the lazy approach and search for any and all vtrk and strk chunks */
+ for (i = 0; i < header_size - 8; i++) {
+ fourcc_tag = LE_32(&header[i]);
+ size = LE_32(&header[i + 4]);
+
+ if (fourcc_tag == std__TAG) {
+ fourxm->fps = av_int2flt(LE_32(&header[i + 12]));
+ } else if (fourcc_tag == vtrk_TAG) {
+ /* check that there is enough data */
+ if (size != vtrk_SIZE) {
+ av_free(header);
+ return AVERROR_INVALIDDATA;
+ }
+ fourxm->width = LE_32(&header[i + 36]);
+ fourxm->height = LE_32(&header[i + 40]);
+ i += 8 + size;
+
+ /* allocate a new AVStream */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ av_set_pts_info(st, 60, 1, fourxm->fps);
+
+ fourxm->video_stream_index = st->index;
+
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_4XM;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->width = fourxm->width;
+ st->codec->height = fourxm->height;
+
+ } else if (fourcc_tag == strk_TAG) {
+ /* check that there is enough data */
+ if (size != strk_SIZE) {
+ av_free(header);
+ return AVERROR_INVALIDDATA;
+ }
+ current_track = LE_32(&header[i + 8]);
+ if (current_track + 1 > fourxm->track_count) {
+ fourxm->track_count = current_track + 1;
+ if((unsigned)fourxm->track_count >= UINT_MAX / sizeof(AudioTrack))
+ return -1;
+ fourxm->tracks = av_realloc(fourxm->tracks,
+ fourxm->track_count * sizeof(AudioTrack));
+ if (!fourxm->tracks) {
+ av_free(header);
+ return AVERROR_NOMEM;
+ }
+ }
+ fourxm->tracks[current_track].adpcm = LE_32(&header[i + 12]);
+ fourxm->tracks[current_track].channels = LE_32(&header[i + 36]);
+ fourxm->tracks[current_track].sample_rate = LE_32(&header[i + 40]);
+ fourxm->tracks[current_track].bits = LE_32(&header[i + 44]);
+ i += 8 + size;
+
+ /* allocate a new AVStream */
+ st = av_new_stream(s, current_track);
+ if (!st)
+ return AVERROR_NOMEM;
+
+ av_set_pts_info(st, 60, 1, fourxm->tracks[current_track].sample_rate);
+
+ fourxm->tracks[current_track].stream_index = st->index;
+
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_tag = 0;
+ st->codec->channels = fourxm->tracks[current_track].channels;
+ st->codec->sample_rate = fourxm->tracks[current_track].sample_rate;
+ st->codec->bits_per_sample = fourxm->tracks[current_track].bits;
+ st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
+ st->codec->bits_per_sample;
+ st->codec->block_align = st->codec->channels * st->codec->bits_per_sample;
+ if (fourxm->tracks[current_track].adpcm)
+ st->codec->codec_id = CODEC_ID_ADPCM_4XM;
+ else if (st->codec->bits_per_sample == 8)
+ st->codec->codec_id = CODEC_ID_PCM_U8;
+ else
+ st->codec->codec_id = CODEC_ID_PCM_S16LE;
+ }
+ }
+
+ av_free(header);
+
+ /* skip over the LIST-MOVI chunk (which is where the stream should be */
+ GET_LIST_HEADER();
+ if (fourcc_tag != MOVI_TAG)
+ return AVERROR_INVALIDDATA;
+
+ /* initialize context members */
+ fourxm->video_pts = -1; /* first frame will push to 0 */
+ fourxm->audio_pts = 0;
+
+ return 0;
+}
+
+static int fourxm_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ FourxmDemuxContext *fourxm = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ unsigned int fourcc_tag;
+ unsigned int size, out_size;
+ int ret = 0;
+ int track_number;
+ int packet_read = 0;
+ unsigned char header[8];
+ int audio_frame_count;
+
+ while (!packet_read) {
+
+ if ((ret = get_buffer(&s->pb, header, 8)) < 0)
+ return ret;
+ fourcc_tag = LE_32(&header[0]);
+ size = LE_32(&header[4]);
+ if (url_feof(pb))
+ return AVERROR_IO;
+ switch (fourcc_tag) {
+
+ case LIST_TAG:
+ /* this is a good time to bump the video pts */
+ fourxm->video_pts ++;
+
+ /* skip the LIST-* tag and move on to the next fourcc */
+ get_le32(pb);
+ break;
+
+ case ifrm_TAG:
+ case pfrm_TAG:
+ case cfrm_TAG:{
+
+ /* allocate 8 more bytes than 'size' to account for fourcc
+ * and size */
+ if (size + 8 < size || av_new_packet(pkt, size + 8))
+ return AVERROR_IO;
+ pkt->stream_index = fourxm->video_stream_index;
+ pkt->pts = fourxm->video_pts;
+ pkt->pos = url_ftell(&s->pb);
+ memcpy(pkt->data, header, 8);
+ ret = get_buffer(&s->pb, &pkt->data[8], size);
+
+ if (ret < 0)
+ av_free_packet(pkt);
+ else
+ packet_read = 1;
+ break;
+ }
+
+ case snd__TAG:
+ track_number = get_le32(pb);
+ out_size= get_le32(pb);
+ size-=8;
+
+ if (track_number == fourxm->selected_track) {
+ ret= av_get_packet(&s->pb, pkt, size);
+ if(ret<0)
+ return AVERROR_IO;
+ pkt->stream_index =
+ fourxm->tracks[fourxm->selected_track].stream_index;
+ pkt->pts = fourxm->audio_pts;
+ packet_read = 1;
+
+ /* pts accounting */
+ audio_frame_count = size;
+ if (fourxm->tracks[fourxm->selected_track].adpcm)
+ audio_frame_count -=
+ 2 * (fourxm->tracks[fourxm->selected_track].channels);
+ audio_frame_count /=
+ fourxm->tracks[fourxm->selected_track].channels;
+ if (fourxm->tracks[fourxm->selected_track].adpcm)
+ audio_frame_count *= 2;
+ else
+ audio_frame_count /=
+ (fourxm->tracks[fourxm->selected_track].bits / 8);
+ fourxm->audio_pts += audio_frame_count;
+
+ } else {
+ url_fseek(pb, size, SEEK_CUR);
+ }
+ break;
+
+ default:
+ url_fseek(pb, size, SEEK_CUR);
+ break;
+ }
+ }
+ return ret;
+}
+
+static int fourxm_read_close(AVFormatContext *s)
+{
+ FourxmDemuxContext *fourxm = (FourxmDemuxContext *)s->priv_data;
+
+ av_free(fourxm->tracks);
+
+ return 0;
+}
+
+AVInputFormat fourxm_demuxer = {
+ "4xm",
+ "4X Technologies format",
+ sizeof(FourxmDemuxContext),
+ fourxm_probe,
+ fourxm_read_header,
+ fourxm_read_packet,
+ fourxm_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/Makefile b/contrib/ffmpeg/libavformat/Makefile
new file mode 100644
index 000000000..fd2ac2a29
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/Makefile
@@ -0,0 +1,197 @@
+#
+# libavformat Makefile
+# (c) 2000-2003 Fabrice Bellard
+#
+include ../config.mak
+
+CFLAGS+=-I$(SRC_PATH)/libavcodec
+
+OBJS= utils.o cutils.o os_support.o allformats.o
+
+HEADERS = avformat.h avio.h rtp.h rtsp.h rtspcodes.h
+
+# muxers/demuxers
+OBJS-$(CONFIG_FOURXM_DEMUXER) += 4xm.o
+OBJS-$(CONFIG_ADTS_MUXER) += adtsenc.o
+OBJS-$(CONFIG_AIFF_DEMUXER) += aiff.o riff.o
+OBJS-$(CONFIG_AIFF_MUXER) += aiff.o riff.o
+OBJS-$(CONFIG_AMR_DEMUXER) += amr.o
+OBJS-$(CONFIG_AMR_MUXER) += amr.o
+OBJS-$(CONFIG_ASF_DEMUXER) += asf.o riff.o
+OBJS-$(CONFIG_ASF_MUXER) += asf-enc.o riff.o
+OBJS-$(CONFIG_ASF_STREAM_MUXER) += asf-enc.o riff.o
+OBJS-$(CONFIG_AU_DEMUXER) += au.o riff.o
+OBJS-$(CONFIG_AU_MUXER) += au.o riff.o
+OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o riff.o
+OBJS-$(CONFIG_AVI_MUXER) += avienc.o riff.o
+OBJS-$(CONFIG_AVISYNTH) += avisynth.o
+OBJS-$(CONFIG_AVS_DEMUXER) += avs.o vocdec.o voc.o riff.o
+OBJS-$(CONFIG_CRC_MUXER) += crc.o
+OBJS-$(CONFIG_FRAMECRC_MUXER) += crc.o
+OBJS-$(CONFIG_DAUD_DEMUXER) += daud.o
+OBJS-$(CONFIG_DSICIN_DEMUXER) += dsicin.o
+OBJS-$(CONFIG_DV_DEMUXER) += dv.o
+OBJS-$(CONFIG_DV_MUXER) += dvenc.o
+OBJS-$(CONFIG_EA_DEMUXER) += electronicarts.o
+OBJS-$(CONFIG_FFM_DEMUXER) += ffm.o
+OBJS-$(CONFIG_FFM_MUXER) += ffm.o
+OBJS-$(CONFIG_FLIC_DEMUXER) += flic.o
+OBJS-$(CONFIG_FLV_DEMUXER) += flvdec.o
+OBJS-$(CONFIG_FLV_MUXER) += flvenc.o
+OBJS-$(CONFIG_GIF_MUXER) += gif.o
+OBJS-$(CONFIG_GIF_DEMUXER) += gifdec.o
+OBJS-$(CONFIG_GXF_DEMUXER) += gxf.o
+OBJS-$(CONFIG_IDCIN_DEMUXER) += idcin.o
+OBJS-$(CONFIG_ROQ_DEMUXER) += idroq.o
+OBJS-$(CONFIG_IMAGE2_DEMUXER) += img2.o
+OBJS-$(CONFIG_IMAGE2PIPE_DEMUXER) += img2.o
+OBJS-$(CONFIG_IMAGE2_MUXER) += img2.o
+OBJS-$(CONFIG_IMAGE2PIPE_MUXER) += img2.o
+OBJS-$(CONFIG_IPMOVIE_DEMUXER) += ipmovie.o
+OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroska.o riff.o
+OBJS-$(CONFIG_MM_DEMUXER) += mm.o
+OBJS-$(CONFIG_MMF_DEMUXER) += mmf.o riff.o
+OBJS-$(CONFIG_MMF_MUXER) += mmf.o riff.o
+OBJS-$(CONFIG_MOV_DEMUXER) += mov.o riff.o isom.o
+OBJS-$(CONFIG_MOV_MUXER) += movenc.o riff.o isom.o
+OBJS-$(CONFIG_MTV_DEMUXER) += mtv.o
+OBJS-$(CONFIG_TGP_MUXER) += movenc.o riff.o isom.o
+OBJS-$(CONFIG_MP4_MUXER) += movenc.o riff.o isom.o
+OBJS-$(CONFIG_PSP_MUXER) += movenc.o riff.o isom.o
+OBJS-$(CONFIG_TG2_MUXER) += movenc.o riff.o isom.o
+OBJS-$(CONFIG_MP3_DEMUXER) += mp3.o
+OBJS-$(CONFIG_MP2_MUXER) += mp3.o
+OBJS-$(CONFIG_MP3_MUXER) += mp3.o
+OBJS-$(CONFIG_MPEG1SYSTEM_MUXER) += mpeg.o
+OBJS-$(CONFIG_MPEG1VCD_MUXER) += mpeg.o
+OBJS-$(CONFIG_MPEG2VOB_MUXER) += mpeg.o
+OBJS-$(CONFIG_MPEG2SVCD_MUXER) += mpeg.o
+OBJS-$(CONFIG_MPEG2DVD_MUXER) += mpeg.o
+OBJS-$(CONFIG_MPEGPS_DEMUXER) += mpeg.o
+OBJS-$(CONFIG_MPEGTS_DEMUXER) += mpegts.o
+OBJS-$(CONFIG_MPEGTS_MUXER) += mpegtsenc.o
+OBJS-$(CONFIG_MPJPEG_MUXER) += mpjpeg.o
+OBJS-$(CONFIG_MXF_DEMUXER) += mxf.o
+OBJS-$(CONFIG_NSV_DEMUXER) += nsvdec.o riff.o
+OBJS-$(CONFIG_NUV_DEMUXER) += nuv.o riff.o
+OBJS-$(CONFIG_OGG_DEMUXER) += ogg2.o \
+ oggparsevorbis.o \
+ oggparsetheora.o \
+ oggparseflac.o \
+ oggparseogm.o \
+ riff.o
+OBJS-$(CONFIG_STR_DEMUXER) += psxstr.o
+OBJS-$(CONFIG_SHORTEN_DEMUXER) += raw.o
+OBJS-$(CONFIG_FLAC_DEMUXER) += raw.o
+OBJS-$(CONFIG_FLAC_MUXER) += raw.o
+OBJS-$(CONFIG_AC3_DEMUXER) += raw.o
+OBJS-$(CONFIG_AC3_MUXER) += raw.o
+OBJS-$(CONFIG_DTS_DEMUXER) += raw.o
+OBJS-$(CONFIG_AAC_DEMUXER) += raw.o
+OBJS-$(CONFIG_H261_DEMUXER) += raw.o
+OBJS-$(CONFIG_H261_MUXER) += raw.o
+OBJS-$(CONFIG_H263_DEMUXER) += raw.o
+OBJS-$(CONFIG_H263_MUXER) += raw.o
+OBJS-$(CONFIG_M4V_DEMUXER) += raw.o
+OBJS-$(CONFIG_M4V_MUXER) += raw.o
+OBJS-$(CONFIG_H264_DEMUXER) += raw.o
+OBJS-$(CONFIG_H264_MUXER) += raw.o
+OBJS-$(CONFIG_MPEGVIDEO_DEMUXER) += raw.o
+OBJS-$(CONFIG_MPEG1VIDEO_MUXER) += raw.o
+OBJS-$(CONFIG_MPEG2VIDEO_MUXER) += raw.o
+OBJS-$(CONFIG_MJPEG_DEMUXER) += raw.o
+OBJS-$(CONFIG_INGENIENT_DEMUXER) += raw.o
+OBJS-$(CONFIG_MJPEG_MUXER) += raw.o
+OBJS-$(CONFIG_RAWVIDEO_DEMUXER) += raw.o
+OBJS-$(CONFIG_RAWVIDEO_MUXER) += raw.o
+OBJS-$(CONFIG_NULL_MUXER) += raw.o
+OBJS-$(CONFIG_RM_DEMUXER) += rm.o
+OBJS-$(CONFIG_RM_MUXER) += rm.o
+OBJS-$(CONFIG_SEGAFILM_DEMUXER) += segafilm.o
+OBJS-$(CONFIG_VMD_DEMUXER) += sierravmd.o
+OBJS-$(CONFIG_SMACKER_DEMUXER) += smacker.o
+OBJS-$(CONFIG_SOL_DEMUXER) += sol.o
+OBJS-$(CONFIG_SWF_DEMUXER) += swf.o
+OBJS-$(CONFIG_SWF_MUXER) += swf.o
+OBJS-$(CONFIG_TIERTEXSEQ_DEMUXER) += tiertexseq.o
+OBJS-$(CONFIG_TTA_DEMUXER) += tta.o
+OBJS-$(CONFIG_VOC_DEMUXER) += vocdec.o voc.o riff.o
+OBJS-$(CONFIG_VOC_MUXER) += vocenc.o voc.o riff.o
+OBJS-$(CONFIG_WAV_DEMUXER) += wav.o riff.o
+OBJS-$(CONFIG_WAV_MUXER) += wav.o riff.o
+OBJS-$(CONFIG_WC3_DEMUXER) += wc3movie.o
+OBJS-$(CONFIG_WSAUD_DEMUXER) += westwood.o
+OBJS-$(CONFIG_WSVQA_DEMUXER) += westwood.o
+OBJS-$(CONFIG_WV_DEMUXER) += wv.o
+OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER) += yuv4mpeg.o
+OBJS-$(CONFIG_YUV4MPEGPIPE_DEMUXER) += yuv4mpeg.o
+
+OBJS+= framehook.o
+
+ifeq ($(CONFIG_VIDEO4LINUX),yes)
+OBJS-$(CONFIG_VIDEO_GRAB_DEVICE_DEMUXER) += grab.o
+endif
+
+ifeq ($(CONFIG_VIDEO4LINUX2),yes)
+OBJS-$(CONFIG_V4L2_DEMUXER) += v4l2.o
+endif
+
+ifeq ($(CONFIG_BKTR),yes)
+OBJS-$(CONFIG_VIDEO_GRAB_DEVICE_DEMUXER) += grab_bktr.o
+endif
+
+ifeq ($(CONFIG_DV1394),yes)
+OBJS-$(CONFIG_DV1394_DEMUXER) += dv1394.o
+endif
+
+ifeq ($(CONFIG_DC1394),yes)
+OBJS-$(CONFIG_DC1394_DEMUXER) += dc1394.o
+endif
+
+ifeq ($(CONFIG_AUDIO_OSS),yes)
+OBJS-$(CONFIG_AUDIO_DEMUXER) += audio.o
+OBJS-$(CONFIG_AUDIO_MUXER) += audio.o
+endif
+
+EXTRALIBS := -L$(BUILD_ROOT)/libavutil -lavutil$(BUILDSUF) \
+ -lavcodec$(BUILDSUF) -L$(BUILD_ROOT)/libavcodec $(EXTRALIBS)
+
+ifeq ($(CONFIG_AUDIO_BEOS),yes)
+CPPOBJS+= beosaudio.o
+endif
+
+# protocols I/O
+OBJS+= avio.o aviobuf.o
+
+ifeq ($(CONFIG_PROTOCOLS),yes)
+OBJS+= file.o
+ifeq ($(CONFIG_NETWORK),yes)
+OBJS+= udp.o tcp.o http.o rtsp.o rtp.o rtpproto.o mpegts.o base64.o rtp_h264.o
+endif
+endif
+
+ifeq ($(CONFIG_LIBNUT),yes)
+OBJS-$(CONFIG_NUT_DEMUXER) += libnut.o riff.o
+OBJS-$(CONFIG_NUT_MUXER) += libnut.o riff.o
+else
+OBJS-$(CONFIG_NUT_DEMUXER) += nutdec.o riff.o
+#OBJS-$(CONFIG_NUT_MUXER) += nutenc.o riff.o
+endif
+
+ifeq ($(CONFIG_LIBOGG),yes)
+OBJS-$(CONFIG_OGG_MUXER) += ogg.o
+endif
+
+ifeq ($(CONFIG_GPL),yes)
+OBJS-$(CONFIG_GXF_MUXER) += gxfenc.o
+endif
+
+OBJS += $(OBJS-yes)
+
+NAME=avformat
+ifeq ($(BUILD_SHARED),yes)
+LIBVERSION=$(LAVFVERSION)
+LIBMAJOR=$(LAVFMAJOR)
+endif
+
+include ../common.mak
diff --git a/contrib/ffmpeg/libavformat/adtsenc.c b/contrib/ffmpeg/libavformat/adtsenc.c
new file mode 100644
index 000000000..1ef683838
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/adtsenc.c
@@ -0,0 +1,123 @@
+/*
+ * ADTS muxer.
+ * Copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@smartjog.com>
+ * Mans Rullgard <mru@inprovide.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 "avformat.h"
+#include "bitstream.h"
+
+#define ADTS_HEADER_SIZE 7
+
+typedef struct {
+ int write_adts;
+ int objecttype;
+ int sample_rate_index;
+ int channel_conf;
+} ADTSContext;
+
+static int decode_extradata(ADTSContext *adts, uint8_t *buf, int size)
+{
+ GetBitContext gb;
+
+ init_get_bits(&gb, buf, size * 8);
+ adts->objecttype = get_bits(&gb, 5) - 1;
+ adts->sample_rate_index = get_bits(&gb, 4);
+ adts->channel_conf = get_bits(&gb, 4);
+
+ adts->write_adts = 1;
+
+ return 0;
+}
+
+static int adts_write_header(AVFormatContext *s)
+{
+ ADTSContext *adts = s->priv_data;
+ AVCodecContext *avc = s->streams[0]->codec;
+
+ if(avc->extradata_size > 0)
+ decode_extradata(adts, avc->extradata, avc->extradata_size);
+
+ return 0;
+}
+
+static int adts_write_frame_header(AVFormatContext *s, int size)
+{
+ ADTSContext *ctx = s->priv_data;
+ PutBitContext pb;
+ uint8_t buf[ADTS_HEADER_SIZE];
+
+ init_put_bits(&pb, buf, ADTS_HEADER_SIZE);
+
+ /* adts_fixed_header */
+ put_bits(&pb, 12, 0xfff); /* syncword */
+ put_bits(&pb, 1, 0); /* ID */
+ put_bits(&pb, 2, 0); /* layer */
+ put_bits(&pb, 1, 1); /* protection_absent */
+ put_bits(&pb, 2, ctx->objecttype); /* profile_objecttype */
+ put_bits(&pb, 4, ctx->sample_rate_index);
+ put_bits(&pb, 1, 0); /* private_bit */
+ put_bits(&pb, 3, ctx->channel_conf); /* channel_configuration */
+ put_bits(&pb, 1, 0); /* original_copy */
+ put_bits(&pb, 1, 0); /* home */
+
+ /* adts_variable_header */
+ put_bits(&pb, 1, 0); /* copyright_identification_bit */
+ put_bits(&pb, 1, 0); /* copyright_identification_start */
+ put_bits(&pb, 13, ADTS_HEADER_SIZE + size); /* aac_frame_length */
+ put_bits(&pb, 11, 0x7ff); /* adts_buffer_fullness */
+ put_bits(&pb, 2, 0); /* number_of_raw_data_blocks_in_frame */
+
+ flush_put_bits(&pb);
+ put_buffer(&s->pb, buf, ADTS_HEADER_SIZE);
+
+ return 0;
+}
+
+static int adts_write_trailer(AVFormatContext *s)
+{
+ return 0;
+}
+
+static int adts_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ ADTSContext *adts = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+
+ if (!pkt->size)
+ return 0;
+ if(adts->write_adts)
+ adts_write_frame_header(s, pkt->size);
+ put_buffer(pb, pkt->data, pkt->size);
+ put_flush_packet(pb);
+
+ return 0;
+}
+
+AVOutputFormat adts_muxer = {
+ "adts",
+ "ADTS AAC",
+ "audio/aac",
+ "aac",
+ sizeof(ADTSContext),
+ CODEC_ID_AAC,
+ CODEC_ID_NONE,
+ adts_write_header,
+ adts_write_packet,
+ adts_write_trailer,
+};
diff --git a/contrib/ffmpeg/libavformat/aiff.c b/contrib/ffmpeg/libavformat/aiff.c
new file mode 100644
index 000000000..e4cf66c3b
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/aiff.c
@@ -0,0 +1,436 @@
+/*
+ * AIFF/AIFF-C muxer and demuxer
+ * Copyright (c) 2006 Patrick Guimond
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "avformat.h"
+#include "allformats.h"
+#include "riff.h"
+#include "intfloat_readwrite.h"
+
+static const CodecTag codec_aiff_tags[] = {
+ { CODEC_ID_PCM_S16BE, MKTAG('N','O','N','E') },
+ { CODEC_ID_PCM_S8, MKTAG('N','O','N','E') },
+ { CODEC_ID_PCM_S24BE, MKTAG('N','O','N','E') },
+ { CODEC_ID_PCM_S32BE, MKTAG('N','O','N','E') },
+ { CODEC_ID_PCM_ALAW, MKTAG('a','l','a','w') },
+ { CODEC_ID_PCM_ALAW, MKTAG('A','L','A','W') },
+ { CODEC_ID_PCM_MULAW, MKTAG('u','l','a','w') },
+ { CODEC_ID_PCM_MULAW, MKTAG('U','L','A','W') },
+ { CODEC_ID_MACE3, MKTAG('M','A','C','3') },
+ { CODEC_ID_MACE6, MKTAG('M','A','C','6') },
+ { CODEC_ID_GSM, MKTAG('G','S','M',' ') },
+ { CODEC_ID_ADPCM_G726, MKTAG('G','7','2','6') },
+ { 0, 0 },
+};
+
+#define AIFF 0
+#define AIFF_C_VERSION1 0xA2805140
+
+static int aiff_codec_get_id (int bps)
+{
+ if (bps <= 8)
+ return CODEC_ID_PCM_S8;
+ if (bps <= 16)
+ return CODEC_ID_PCM_S16BE;
+ if (bps <= 24)
+ return CODEC_ID_PCM_S24BE;
+ if (bps <= 32)
+ return CODEC_ID_PCM_S32BE;
+
+ /* bigger than 32 isn't allowed */
+ return 0;
+}
+
+/* returns the size of the found tag */
+static int get_tag(ByteIOContext *pb, uint32_t * tag)
+{
+ int size;
+
+ if (url_feof(pb))
+ return AVERROR_IO;
+
+ *tag = get_le32(pb);
+ size = get_be32(pb);
+
+ if (size < 0)
+ size = 0x7fffffff;
+
+ return size;
+}
+
+/* Metadata string read */
+static void get_meta(ByteIOContext *pb, char * str, int strsize, int size)
+{
+ int res;
+
+ if (size > strsize-1)
+ res = get_buffer(pb, (uint8_t*)str, strsize-1);
+ else
+ res = get_buffer(pb, (uint8_t*)str, size);
+
+ if (res < 0)
+ return;
+
+ str[res] = 0;
+ if (size & 1)
+ size++;
+ size -= res;
+ if (size);
+ url_fskip(pb, size);
+}
+
+/* Returns the number of sound data frames or negative on error */
+static unsigned int get_aiff_header(ByteIOContext *pb, AVCodecContext *codec,
+ int size, unsigned version)
+{
+ AVExtFloat ext;
+ double sample_rate;
+ unsigned int num_frames;
+
+
+ if (size & 1)
+ size++;
+
+ codec->codec_type = CODEC_TYPE_AUDIO;
+ codec->channels = get_be16(pb);
+ num_frames = get_be32(pb);
+ codec->bits_per_sample = get_be16(pb);
+
+ get_buffer(pb, (uint8_t*)&ext, sizeof(ext));/* Sample rate is in */
+ sample_rate = av_ext2dbl(ext); /* 80 bits BE IEEE extended float */
+ codec->sample_rate = sample_rate;
+ size -= 18;
+
+ /* Got an AIFF-C? */
+ if (version == AIFF_C_VERSION1) {
+ codec->codec_tag = get_le32(pb);
+ codec->codec_id = codec_get_id (codec_aiff_tags, codec->codec_tag);
+
+ if (codec->codec_id == CODEC_ID_PCM_S16BE) {
+ codec->codec_id = aiff_codec_get_id (codec->bits_per_sample);
+ codec->bits_per_sample = av_get_bits_per_sample(codec->codec_id);
+ }
+
+ size -= 4;
+ } else {
+ /* Need the codec type */
+ codec->codec_id = aiff_codec_get_id (codec->bits_per_sample);
+ codec->bits_per_sample = av_get_bits_per_sample(codec->codec_id);
+ }
+
+ if (!codec->codec_id)
+ return AVERROR_INVALIDDATA;
+
+ /* Block align needs to be computed in all cases, as the definition
+ * is specific to applications -> here we use the WAVE format definition */
+ codec->block_align = (codec->bits_per_sample * codec->channels) >> 3;
+
+ codec->bit_rate = codec->sample_rate * (codec->block_align << 3);
+
+ /* Chunk is over */
+ if (size)
+ url_fseek(pb, size, SEEK_CUR);
+
+ return num_frames;
+}
+
+#ifdef CONFIG_MUXERS
+typedef struct {
+ offset_t form;
+ offset_t frames;
+ offset_t ssnd;
+} AIFFOutputContext;
+
+static int aiff_write_header(AVFormatContext *s)
+{
+ AIFFOutputContext *aiff = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVCodecContext *enc = s->streams[0]->codec;
+ AVExtFloat sample_rate;
+
+ /* First verify if format is ok */
+ enc->codec_tag = codec_get_tag(codec_aiff_tags, enc->codec_id);
+ if (!enc->codec_tag) {
+ av_free(aiff);
+ return -1;
+ }
+
+ /* FORM AIFF header */
+ put_tag(pb, "FORM");
+ aiff->form = url_ftell(pb);
+ put_be32(pb, 0); /* file length */
+ put_tag(pb, "AIFC");
+
+ /* Version chunk */
+ put_tag(pb, "FVER");
+ put_be32(pb, 4);
+ put_be32(pb, 0xA2805140);
+
+ /* Common chunk */
+ put_tag(pb, "COMM");
+ put_be32(pb, 24); /* size */
+ put_be16(pb, enc->channels); /* Number of channels */
+
+ aiff->frames = url_ftell(pb);
+ put_be32(pb, 0); /* Number of frames */
+
+ if (!enc->bits_per_sample)
+ enc->bits_per_sample = av_get_bits_per_sample(enc->codec_id);
+ if (!enc->bits_per_sample) {
+ av_log(s, AV_LOG_ERROR, "could not compute bits per sample\n");
+ return -1;
+ }
+ if (!enc->block_align)
+ enc->block_align = (enc->bits_per_sample * enc->channels) >> 3;
+
+ put_be16(pb, enc->bits_per_sample); /* Sample size */
+
+ sample_rate = av_dbl2ext((double)enc->sample_rate);
+ put_buffer(pb, (uint8_t*)&sample_rate, sizeof(sample_rate));
+
+ put_le32(pb, enc->codec_tag);
+ put_be16(pb, 0);
+
+ /* Sound data chunk */
+ put_tag(pb, "SSND");
+ aiff->ssnd = url_ftell(pb); /* Sound chunk size */
+ put_be32(pb, 0); /* Sound samples data size */
+ put_be32(pb, 0); /* Data offset */
+ put_be32(pb, 0); /* Block-size (block align) */
+
+ av_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate);
+
+ /* Data is starting here */
+ put_flush_packet(pb);
+
+ return 0;
+}
+
+static int aiff_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ ByteIOContext *pb = &s->pb;
+ put_buffer(pb, pkt->data, pkt->size);
+ return 0;
+}
+
+static int aiff_write_trailer(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+ AIFFOutputContext *aiff = s->priv_data;
+ AVCodecContext *enc = s->streams[0]->codec;
+
+ /* Chunks sizes must be even */
+ offset_t file_size, end_size;
+ end_size = file_size = url_ftell(pb);
+ if (file_size & 1) {
+ put_byte(pb, 0);
+ end_size++;
+ }
+
+ if (!url_is_streamed(&s->pb)) {
+ /* File length */
+ url_fseek(pb, aiff->form, SEEK_SET);
+ put_be32(pb, (uint32_t)(file_size - aiff->form - 4));
+
+ /* Number of sample frames */
+ url_fseek(pb, aiff->frames, SEEK_SET);
+ put_be32(pb, ((uint32_t)(file_size-aiff->ssnd-12))/enc->block_align);
+
+ /* Sound Data chunk size */
+ url_fseek(pb, aiff->ssnd, SEEK_SET);
+ put_be32(pb, (uint32_t)(file_size - aiff->ssnd - 4));
+
+ /* return to the end */
+ url_fseek(pb, end_size, SEEK_SET);
+
+ put_flush_packet(pb);
+ }
+
+ return 0;
+}
+#endif //CONFIG_MUXERS
+
+static int aiff_probe(AVProbeData *p)
+{
+ /* check file header */
+ if (p->buf_size < 16)
+ return 0;
+ if (p->buf[0] == 'F' && p->buf[1] == 'O' &&
+ p->buf[2] == 'R' && p->buf[3] == 'M' &&
+ p->buf[8] == 'A' && p->buf[9] == 'I' &&
+ p->buf[10] == 'F' && (p->buf[11] == 'F' || p->buf[11] == 'C'))
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+/* aiff input */
+static int aiff_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ int size, filesize, offset;
+ uint32_t tag;
+ unsigned version = AIFF_C_VERSION1;
+ ByteIOContext *pb = &s->pb;
+ AVStream * st = s->streams[0];
+
+ /* check FORM header */
+ filesize = get_tag(pb, &tag);
+ if (filesize < 0 || tag != MKTAG('F', 'O', 'R', 'M'))
+ return AVERROR_INVALIDDATA;
+
+ /* AIFF data type */
+ tag = get_le32(pb);
+ if (tag == MKTAG('A', 'I', 'F', 'F')) /* Got an AIFF file */
+ version = AIFF;
+ else if (tag != MKTAG('A', 'I', 'F', 'C')) /* An AIFF-C file then */
+ return AVERROR_INVALIDDATA;
+
+ filesize -= 4;
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+
+ while (filesize > 0) {
+ /* parse different chunks */
+ size = get_tag(pb, &tag);
+ if (size < 0)
+ return size;
+
+ filesize -= size + 8;
+
+ switch (tag) {
+ case MKTAG('C', 'O', 'M', 'M'): /* Common chunk */
+ /* Then for the complete header info */
+ st->nb_frames = get_aiff_header (pb, st->codec, size, version);
+ if (st->nb_frames < 0)
+ return st->nb_frames;
+ break;
+
+ case MKTAG('F', 'V', 'E', 'R'): /* Version chunk */
+ version = get_be32(pb);
+ break;
+
+ case MKTAG('N', 'A', 'M', 'E'): /* Sample name chunk */
+ get_meta (pb, s->title, sizeof(s->title), size);
+ break;
+
+ case MKTAG('A', 'U', 'T', 'H'): /* Author chunk */
+ get_meta (pb, s->author, sizeof(s->author), size);
+ break;
+
+ case MKTAG('(', 'c', ')', ' '): /* Copyright chunk */
+ get_meta (pb, s->copyright, sizeof(s->copyright), size);
+ break;
+
+ case MKTAG('A', 'N', 'N', 'O'): /* Annotation chunk */
+ get_meta (pb, s->comment, sizeof(s->comment), size);
+ break;
+
+ case MKTAG('S', 'S', 'N', 'D'): /* Sampled sound chunk */
+ get_be32(pb); /* Block align... don't care */
+ offset = get_be32(pb); /* Offset of sound data */
+ goto got_sound;
+
+ default: /* Jump */
+ if (size & 1) /* Always even aligned */
+ size++;
+ url_fskip (pb, size);
+ }
+ }
+
+ /* End of loop and didn't get sound */
+ return AVERROR_INVALIDDATA;
+
+got_sound:
+ /* Now positioned, get the sound data start and end */
+ if (st->nb_frames)
+ s->file_size = st->nb_frames * st->codec->block_align;
+
+ av_set_pts_info(st, 64, 1, st->codec->sample_rate);
+ st->start_time = 0;
+ st->duration = st->nb_frames;
+
+ /* Position the stream at the first block */
+ url_fskip(pb, offset);
+
+ return 0;
+}
+
+#define MAX_SIZE 4096
+
+static int aiff_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ AVStream *st = s->streams[0];
+ int res;
+
+ /* End of stream may be reached */
+ if (url_feof(&s->pb))
+ return AVERROR_IO;
+
+ /* Now for that packet */
+ res = av_get_packet(&s->pb, pkt, (MAX_SIZE / st->codec->block_align) * st->codec->block_align);
+ if (res < 0)
+ return res;
+
+ /* Only one stream in an AIFF file */
+ pkt->stream_index = 0;
+ return 0;
+}
+
+static int aiff_read_close(AVFormatContext *s)
+{
+ return 0;
+}
+
+static int aiff_read_seek(AVFormatContext *s,
+ int stream_index, int64_t timestamp, int flags)
+{
+ return pcm_read_seek(s, stream_index, timestamp, flags);
+}
+
+#ifdef CONFIG_AIFF_DEMUXER
+AVInputFormat aiff_demuxer = {
+ "aiff",
+ "Audio IFF",
+ 0,
+ aiff_probe,
+ aiff_read_header,
+ aiff_read_packet,
+ aiff_read_close,
+ aiff_read_seek,
+};
+#endif
+
+#ifdef CONFIG_AIFF_MUXER
+AVOutputFormat aiff_muxer = {
+ "aiff",
+ "Audio IFF",
+ "audio/aiff",
+ "aif,aiff,afc,aifc",
+ sizeof(AIFFOutputContext),
+ CODEC_ID_PCM_S16BE,
+ CODEC_ID_NONE,
+ aiff_write_header,
+ aiff_write_packet,
+ aiff_write_trailer,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/allformats.c b/contrib/ffmpeg/libavformat/allformats.c
new file mode 100644
index 000000000..f4b16adff
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/allformats.c
@@ -0,0 +1,182 @@
+/*
+ * Register all the formats and protocols
+ * 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 "avformat.h"
+#include "allformats.h"
+
+#define REGISTER_MUXER(X,x) \
+ if(ENABLE_##X##_MUXER) av_register_output_format(&x##_muxer)
+#define REGISTER_DEMUXER(X,x) \
+ if(ENABLE_##X##_DEMUXER) av_register_input_format(&x##_demuxer)
+#define REGISTER_MUXDEMUX(X,x) REGISTER_MUXER(X,x); REGISTER_DEMUXER(X,x)
+
+/* If you do not call this function, then you can select exactly which
+ formats you want to support */
+
+/**
+ * Initialize libavcodec and register all the codecs and formats.
+ */
+void av_register_all(void)
+{
+ static int inited = 0;
+
+ if (inited != 0)
+ return;
+ inited = 1;
+
+ avcodec_init();
+ avcodec_register_all();
+
+ REGISTER_DEMUXER (AAC, aac);
+ REGISTER_MUXDEMUX(AC3, ac3);
+ REGISTER_MUXER (ADTS, adts);
+ REGISTER_MUXDEMUX(AIFF, aiff);
+ REGISTER_MUXDEMUX(AMR, amr);
+ REGISTER_MUXDEMUX(ASF, asf);
+ REGISTER_MUXER (ASF_STREAM, asf_stream);
+ REGISTER_MUXDEMUX(AU, au);
+#if defined(CONFIG_AUDIO_OSS) || defined(CONFIG_AUDIO_BEOS)
+ REGISTER_MUXDEMUX(AUDIO, audio);
+#endif
+ REGISTER_MUXDEMUX(AVI, avi);
+#ifdef CONFIG_AVISYNTH
+ av_register_input_format(&avisynth_demuxer);
+#endif
+ REGISTER_DEMUXER (AVS, avs);
+ REGISTER_MUXER (CRC, crc);
+ REGISTER_DEMUXER (DAUD, daud);
+#ifdef CONFIG_DC1394
+ REGISTER_DEMUXER (DC1394, dc1394);
+#endif
+ REGISTER_DEMUXER (DSICIN, dsicin);
+ REGISTER_DEMUXER (DTS, dts);
+ REGISTER_MUXDEMUX(DV, dv);
+#ifdef CONFIG_DV1394
+ REGISTER_DEMUXER (DV1394, dv1394);
+#endif
+ REGISTER_DEMUXER (EA, ea);
+ REGISTER_MUXDEMUX(FFM, ffm);
+ REGISTER_MUXDEMUX(FLAC, flac);
+ REGISTER_DEMUXER (FLIC, flic);
+ REGISTER_MUXDEMUX(FLV, flv);
+ REGISTER_DEMUXER (FOURXM, fourxm);
+ REGISTER_MUXER (FRAMECRC, framecrc);
+ REGISTER_MUXDEMUX(GIF, gif);
+ REGISTER_DEMUXER (GXF, gxf);
+#ifdef CONFIG_GPL
+ REGISTER_MUXER (GXF, gxf);
+#endif
+ REGISTER_MUXDEMUX(H261, h261);
+ REGISTER_MUXDEMUX(H263, h263);
+ REGISTER_MUXDEMUX(H264, h264);
+ REGISTER_DEMUXER (IDCIN, idcin);
+ REGISTER_MUXDEMUX(IMAGE2, image2);
+ REGISTER_MUXDEMUX(IMAGE2PIPE, image2pipe);
+ REGISTER_DEMUXER (INGENIENT, ingenient);
+ REGISTER_DEMUXER (IPMOVIE, ipmovie);
+ REGISTER_MUXDEMUX(M4V, m4v);
+ REGISTER_DEMUXER (MATROSKA, matroska);
+ REGISTER_MUXDEMUX(MJPEG, mjpeg);
+ REGISTER_DEMUXER (MM, mm);
+ REGISTER_MUXDEMUX(MMF, mmf);
+ REGISTER_MUXDEMUX(MOV, mov);
+ REGISTER_MUXER (MP2, mp2);
+ REGISTER_MUXDEMUX(MP3, mp3);
+ REGISTER_MUXER (MP4, mp4);
+ REGISTER_MUXER (MPEG1SYSTEM, mpeg1system);
+ REGISTER_MUXER (MPEG1VCD, mpeg1vcd);
+ REGISTER_MUXER (MPEG1VIDEO, mpeg1video);
+ REGISTER_MUXER (MPEG2DVD, mpeg2dvd);
+ REGISTER_MUXER (MPEG2SVCD, mpeg2svcd);
+ REGISTER_MUXER (MPEG2VIDEO, mpeg2video);
+ REGISTER_MUXER (MPEG2VOB, mpeg2vob);
+ REGISTER_DEMUXER (MPEGPS, mpegps);
+ REGISTER_MUXDEMUX(MPEGTS, mpegts);
+ REGISTER_DEMUXER (MPEGVIDEO, mpegvideo);
+ REGISTER_MUXER (MPJPEG, mpjpeg);
+ REGISTER_DEMUXER (MTV, mtv);
+ REGISTER_DEMUXER (MXF, mxf);
+ REGISTER_DEMUXER (NSV, nsv);
+ REGISTER_MUXER (NULL, null);
+ REGISTER_DEMUXER (NUT, nut);
+#ifdef CONFIG_LIBNUT
+ REGISTER_MUXER (NUT, nut);
+#endif
+ REGISTER_DEMUXER (NUV, nuv);
+ REGISTER_DEMUXER (OGG, ogg);
+#ifdef CONFIG_LIBOGG
+ REGISTER_MUXER (OGG, ogg);
+#endif
+ REGISTER_MUXDEMUX(PCM_ALAW, pcm_alaw);
+ REGISTER_MUXDEMUX(PCM_MULAW, pcm_mulaw);
+ REGISTER_MUXDEMUX(PCM_S16BE, pcm_s16be);
+ REGISTER_MUXDEMUX(PCM_S16LE, pcm_s16le);
+ REGISTER_MUXDEMUX(PCM_S8, pcm_s8);
+ REGISTER_MUXDEMUX(PCM_U16BE, pcm_u16be);
+ REGISTER_MUXDEMUX(PCM_U16LE, pcm_u16le);
+ REGISTER_MUXDEMUX(PCM_U8, pcm_u8);
+ REGISTER_MUXER (PSP, psp);
+ REGISTER_MUXDEMUX(RAWVIDEO, rawvideo);
+ REGISTER_MUXDEMUX(RM, rm);
+ REGISTER_DEMUXER (ROQ, roq);
+#ifdef CONFIG_NETWORK
+ REGISTER_DEMUXER (REDIR, redir);
+ REGISTER_MUXER (RTP, rtp);
+ REGISTER_DEMUXER (RTSP, rtsp);
+ REGISTER_DEMUXER (SDP, sdp);
+ av_register_rtp_dynamic_payload_handlers();
+#endif
+ REGISTER_DEMUXER (SEGAFILM, segafilm);
+ REGISTER_DEMUXER (SHORTEN, shorten);
+ REGISTER_DEMUXER (SMACKER, smacker);
+ REGISTER_DEMUXER (SOL, sol);
+ REGISTER_DEMUXER (STR, str);
+ REGISTER_MUXDEMUX(SWF, swf);
+ REGISTER_MUXER (TG2, tg2);
+ REGISTER_MUXER (TGP, tgp);
+ REGISTER_DEMUXER (TIERTEXSEQ, tiertexseq);
+ REGISTER_DEMUXER (TTA, tta);
+#ifdef CONFIG_VIDEO4LINUX2
+ REGISTER_DEMUXER (V4L2, v4l2);
+#endif
+#if defined(CONFIG_VIDEO4LINUX) || defined(CONFIG_BKTR)
+ REGISTER_DEMUXER (VIDEO_GRAB_DEVICE, video_grab_device);
+#endif
+ REGISTER_DEMUXER (VMD, vmd);
+ REGISTER_MUXDEMUX(VOC, voc);
+ REGISTER_MUXDEMUX(WAV, wav);
+ REGISTER_DEMUXER (WC3, wc3);
+ REGISTER_DEMUXER (WSAUD, wsaud);
+ REGISTER_DEMUXER (WSVQA, wsvqa);
+ REGISTER_DEMUXER (WV, wv);
+ REGISTER_MUXDEMUX(YUV4MPEGPIPE, yuv4mpegpipe);
+
+#ifdef CONFIG_PROTOCOLS
+ /* file protocols */
+ register_protocol(&file_protocol);
+ register_protocol(&pipe_protocol);
+#ifdef CONFIG_NETWORK
+ register_protocol(&udp_protocol);
+ register_protocol(&rtp_protocol);
+ register_protocol(&tcp_protocol);
+ register_protocol(&http_protocol);
+#endif
+#endif
+}
diff --git a/contrib/ffmpeg/libavformat/allformats.h b/contrib/ffmpeg/libavformat/allformats.h
new file mode 100644
index 000000000..a138841c9
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/allformats.h
@@ -0,0 +1,176 @@
+/*
+ * Register all the formats and protocols.
+ * 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 ALLFORMATS_H
+#define ALLFORMATS_H
+
+extern AVInputFormat fourxm_demuxer;
+extern AVOutputFormat adts_muxer;
+extern AVInputFormat aiff_demuxer;
+extern AVOutputFormat aiff_muxer;
+extern AVInputFormat amr_demuxer;
+extern AVOutputFormat amr_muxer;
+extern AVInputFormat asf_demuxer;
+extern AVOutputFormat asf_muxer;
+extern AVOutputFormat asf_stream_muxer;
+extern AVInputFormat au_demuxer;
+extern AVOutputFormat au_muxer;
+extern AVInputFormat audio_demuxer;
+extern AVOutputFormat audio_muxer;
+extern AVInputFormat avi_demuxer;
+extern AVOutputFormat avi_muxer;
+extern AVInputFormat avisynth_demuxer;
+extern AVInputFormat avs_demuxer;
+extern AVOutputFormat crc_muxer;
+extern AVOutputFormat framecrc_muxer;
+extern AVInputFormat daud_demuxer;
+extern AVInputFormat dc1394_demuxer;
+extern AVInputFormat dsicin_demuxer;
+extern AVInputFormat dv1394_demuxer;
+extern AVInputFormat dv_demuxer;
+extern AVOutputFormat dv_muxer;
+extern AVInputFormat ea_demuxer;
+extern AVInputFormat ffm_demuxer;
+extern AVOutputFormat ffm_muxer;
+extern AVInputFormat flic_demuxer;
+extern AVInputFormat flv_demuxer;
+extern AVOutputFormat flv_muxer;
+extern AVOutputFormat gif_muxer;
+extern AVInputFormat gif_demuxer;
+extern AVInputFormat video_grab_device_demuxer;
+extern AVInputFormat gxf_demuxer;
+extern AVOutputFormat gxf_muxer;
+extern AVInputFormat idcin_demuxer;
+extern AVInputFormat roq_demuxer;
+extern AVInputFormat image2_demuxer;
+extern AVInputFormat image2pipe_demuxer;
+extern AVOutputFormat image2_muxer;
+extern AVOutputFormat image2pipe_muxer;
+extern AVInputFormat image_demuxer;
+extern AVInputFormat imagepipe_demuxer;
+extern AVOutputFormat image_muxer;
+extern AVOutputFormat imagepipe_muxer;
+extern AVInputFormat ipmovie_demuxer;
+extern AVInputFormat matroska_demuxer;
+extern AVInputFormat mm_demuxer;
+extern AVInputFormat mmf_demuxer;
+extern AVOutputFormat mmf_muxer;
+extern AVInputFormat mov_demuxer;
+extern AVOutputFormat mov_muxer;
+extern AVOutputFormat tgp_muxer;
+extern AVOutputFormat mp4_muxer;
+extern AVOutputFormat psp_muxer;
+extern AVOutputFormat tg2_muxer;
+extern AVInputFormat mp3_demuxer;
+extern AVOutputFormat mp2_muxer;
+extern AVOutputFormat mp3_muxer;
+extern AVOutputFormat mpeg1system_muxer;
+extern AVOutputFormat mpeg1vcd_muxer;
+extern AVOutputFormat mpeg2vob_muxer;
+extern AVOutputFormat mpeg2svcd_muxer;
+extern AVOutputFormat mpeg2dvd_muxer;
+extern AVInputFormat mpegps_demuxer;
+extern AVInputFormat mpegts_demuxer;
+extern AVOutputFormat mpegts_muxer;
+extern AVOutputFormat mpjpeg_muxer;
+extern AVInputFormat mtv_demuxer;
+extern AVInputFormat mxf_demuxer;
+extern AVInputFormat nsv_demuxer;
+extern AVInputFormat nut_demuxer;
+extern AVOutputFormat nut_muxer;
+extern AVInputFormat nuv_demuxer;
+extern AVInputFormat ogg_demuxer;
+extern AVOutputFormat ogg_muxer;
+extern AVInputFormat str_demuxer;
+extern AVInputFormat shorten_demuxer;
+extern AVInputFormat flac_demuxer;
+extern AVOutputFormat flac_muxer;
+extern AVInputFormat ac3_demuxer;
+extern AVOutputFormat ac3_muxer;
+extern AVInputFormat dts_demuxer;
+extern AVInputFormat aac_demuxer;
+extern AVInputFormat h261_demuxer;
+extern AVOutputFormat h261_muxer;
+extern AVInputFormat h263_demuxer;
+extern AVOutputFormat h263_muxer;
+extern AVInputFormat m4v_demuxer;
+extern AVOutputFormat m4v_muxer;
+extern AVInputFormat h264_demuxer;
+extern AVOutputFormat h264_muxer;
+extern AVInputFormat mpegvideo_demuxer;
+extern AVOutputFormat mpeg1video_muxer;
+extern AVOutputFormat mpeg2video_muxer;
+extern AVInputFormat mjpeg_demuxer;
+extern AVInputFormat ingenient_demuxer;
+extern AVOutputFormat mjpeg_muxer;
+extern AVInputFormat pcm_s16le_demuxer;
+extern AVOutputFormat pcm_s16le_muxer;
+extern AVInputFormat pcm_s16be_demuxer;
+extern AVOutputFormat pcm_s16be_muxer;
+extern AVInputFormat pcm_u16le_demuxer;
+extern AVOutputFormat pcm_u16le_muxer;
+extern AVInputFormat pcm_u16be_demuxer;
+extern AVOutputFormat pcm_u16be_muxer;
+extern AVInputFormat pcm_s8_demuxer;
+extern AVOutputFormat pcm_s8_muxer;
+extern AVInputFormat pcm_u8_demuxer;
+extern AVOutputFormat pcm_u8_muxer;
+extern AVInputFormat pcm_mulaw_demuxer;
+extern AVOutputFormat pcm_mulaw_muxer;
+extern AVInputFormat pcm_alaw_demuxer;
+extern AVOutputFormat pcm_alaw_muxer;
+extern AVInputFormat rawvideo_demuxer;
+extern AVOutputFormat rawvideo_muxer;
+extern AVOutputFormat null_muxer;
+extern AVInputFormat rm_demuxer;
+extern AVOutputFormat rm_muxer;
+extern AVInputFormat sdp_demuxer;
+extern AVInputFormat redir_demuxer;
+extern AVInputFormat segafilm_demuxer;
+extern AVInputFormat vmd_demuxer;
+extern AVInputFormat smacker_demuxer;
+extern AVInputFormat sol_demuxer;
+extern AVInputFormat swf_demuxer;
+extern AVOutputFormat swf_muxer;
+extern AVInputFormat tta_demuxer;
+extern AVInputFormat v4l2_demuxer;
+extern AVInputFormat voc_demuxer;
+extern AVOutputFormat voc_muxer;
+extern AVInputFormat wav_demuxer;
+extern AVOutputFormat wav_muxer;
+extern AVInputFormat wc3_demuxer;
+extern AVInputFormat wsaud_demuxer;
+extern AVInputFormat wsvqa_demuxer;
+extern AVInputFormat wv_demuxer;
+extern AVOutputFormat yuv4mpegpipe_muxer;
+extern AVInputFormat yuv4mpegpipe_demuxer;
+extern AVInputFormat tiertexseq_demuxer;
+
+/* raw.c */
+int pcm_read_seek(AVFormatContext *s,
+ int stream_index, int64_t timestamp, int flags);
+
+/* rtsp.c */
+int redir_open(AVFormatContext **ic_ptr, ByteIOContext *f);
+/* rtp.c */
+void av_register_rtp_dynamic_payload_handlers();
+
+#endif
diff --git a/contrib/ffmpeg/libavformat/amr.c b/contrib/ffmpeg/libavformat/amr.c
new file mode 100644
index 000000000..635a898fa
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/amr.c
@@ -0,0 +1,201 @@
+/*
+ * amr file format
+ * Copyright (c) 2001 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
+ */
+
+/*
+Write and read amr data according to RFC3267, http://www.ietf.org/rfc/rfc3267.txt?number=3267
+
+Only mono files are supported.
+
+*/
+#include "avformat.h"
+
+static const char AMR_header [] = "#!AMR\n";
+static const char AMRWB_header [] = "#!AMR-WB\n";
+
+#ifdef CONFIG_MUXERS
+static int amr_write_header(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+ AVCodecContext *enc = s->streams[0]->codec;
+
+ s->priv_data = NULL;
+
+ if (enc->codec_id == CODEC_ID_AMR_NB)
+ {
+ put_tag(pb, AMR_header); /* magic number */
+ }
+ else if(enc->codec_id == CODEC_ID_AMR_WB)
+ {
+ put_tag(pb, AMRWB_header); /* magic number */
+ }
+ else
+ {
+ return -1;
+ }
+ put_flush_packet(pb);
+ return 0;
+}
+
+static int amr_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ put_buffer(&s->pb, pkt->data, pkt->size);
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+static int amr_write_trailer(AVFormatContext *s)
+{
+ return 0;
+}
+#endif /* CONFIG_MUXERS */
+
+static int amr_probe(AVProbeData *p)
+{
+ //Only check for "#!AMR" which could be amr-wb, amr-nb.
+ //This will also trigger multichannel files: "#!AMR_MC1.0\n" and
+ //"#!AMR-WB_MC1.0\n" (not supported)
+
+ if (p->buf_size < 5)
+ return 0;
+ if(memcmp(p->buf,AMR_header,5)==0)
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+/* amr input */
+static int amr_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ ByteIOContext *pb = &s->pb;
+ AVStream *st;
+ uint8_t header[9];
+
+ get_buffer(pb, header, 6);
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ {
+ return AVERROR_NOMEM;
+ }
+ if(memcmp(header,AMR_header,6)!=0)
+ {
+ get_buffer(pb, header+6, 3);
+ if(memcmp(header,AMRWB_header,9)!=0)
+ {
+ return -1;
+ }
+
+ st->codec->codec_tag = MKTAG('s', 'a', 'w', 'b');
+ st->codec->codec_id = CODEC_ID_AMR_WB;
+ st->codec->sample_rate = 16000;
+ }
+ else
+ {
+ st->codec->codec_tag = MKTAG('s', 'a', 'm', 'r');
+ st->codec->codec_id = CODEC_ID_AMR_NB;
+ st->codec->sample_rate = 8000;
+ }
+ st->codec->channels = 1;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ av_set_pts_info(st, 64, 1, st->codec->sample_rate);
+
+ return 0;
+}
+
+static int amr_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ AVCodecContext *enc = s->streams[0]->codec;
+ int read, size, toc, mode;
+
+ if (url_feof(&s->pb))
+ {
+ return AVERROR_IO;
+ }
+
+//FIXME this is wrong, this should rather be in a AVParset
+ toc=get_byte(&s->pb);
+ mode = (toc >> 3) & 0x0F;
+
+ if (enc->codec_id == CODEC_ID_AMR_NB)
+ {
+ static const uint8_t packed_size[16] = {12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0};
+
+ size=packed_size[mode]+1;
+ }
+ else if(enc->codec_id == CODEC_ID_AMR_WB)
+ {
+ static uint8_t packed_size[16] = {18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1};
+
+ size=packed_size[mode];
+ }
+ else
+ {
+ assert(0);
+ }
+
+ if ( (size==0) || av_new_packet(pkt, size))
+ {
+ return AVERROR_IO;
+ }
+
+ pkt->stream_index = 0;
+ pkt->pos= url_ftell(&s->pb);
+ pkt->data[0]=toc;
+ pkt->duration= enc->codec_id == CODEC_ID_AMR_NB ? 160 : 320;
+ read = get_buffer(&s->pb, pkt->data+1, size-1);
+
+ if (read != size-1)
+ {
+ av_free_packet(pkt);
+ return AVERROR_IO;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_AMR_DEMUXER
+AVInputFormat amr_demuxer = {
+ "amr",
+ "3gpp amr file format",
+ 0, /*priv_data_size*/
+ amr_probe,
+ amr_read_header,
+ amr_read_packet,
+ NULL,
+};
+#endif
+
+#ifdef CONFIG_AMR_MUXER
+AVOutputFormat amr_muxer = {
+ "amr",
+ "3gpp amr file format",
+ "audio/amr",
+ "amr",
+ 0,
+ CODEC_ID_AMR_NB,
+ CODEC_ID_NONE,
+ amr_write_header,
+ amr_write_packet,
+ amr_write_trailer,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/asf-enc.c b/contrib/ffmpeg/libavformat/asf-enc.c
new file mode 100644
index 000000000..3ef67507f
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/asf-enc.c
@@ -0,0 +1,866 @@
+/*
+ * Adaptive stream format muxer
+ * 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 "avformat.h"
+#include "riff.h"
+#include "asf.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+
+#define ASF_INDEXED_INTERVAL 10000000
+#define ASF_INDEX_BLOCK 600
+
+#define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2
+#define ASF_PACKET_ERROR_CORRECTION_FLAGS (\
+ ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT | \
+ ASF_PACKET_ERROR_CORRECTION_DATA_SIZE\
+ )
+
+#if (ASF_PACKET_ERROR_CORRECTION_FLAGS != 0)
+# define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 1
+#else
+# define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 0
+#endif
+
+#define ASF_PPI_PROPERTY_FLAGS (\
+ ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE | \
+ ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_DWORD | \
+ ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE | \
+ ASF_PL_FLAG_STREAM_NUMBER_LENGTH_FIELD_IS_BYTE \
+ )
+
+#define ASF_PPI_LENGTH_TYPE_FLAGS 0
+
+#define ASF_PAYLOAD_FLAGS ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD
+
+#if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
+# define ASF_PPI_SEQUENCE_FIELD_SIZE 1
+#endif
+#if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
+# define ASF_PPI_SEQUENCE_FIELD_SIZE 2
+#endif
+#if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
+# define ASF_PPI_SEQUENCE_FIELD_SIZE 4
+#endif
+#ifndef ASF_PPI_SEQUENCE_FIELD_SIZE
+# define ASF_PPI_SEQUENCE_FIELD_SIZE 0
+#endif
+
+
+#if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
+# define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 1
+#endif
+#if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
+# define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 2
+#endif
+#if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
+# define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 4
+#endif
+#ifndef ASF_PPI_PACKET_LENGTH_FIELD_SIZE
+# define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 0
+#endif
+
+#if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
+# define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 1
+#endif
+#if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
+# define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 2
+#endif
+#if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
+# define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 4
+#endif
+#ifndef ASF_PPI_PADDING_LENGTH_FIELD_SIZE
+# define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 0
+#endif
+
+#if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
+# define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 1
+#endif
+#if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
+# define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 2
+#endif
+#if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
+# define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 4
+#endif
+#ifndef ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE
+# define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 0
+#endif
+
+#if (ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE))
+# define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 1
+#endif
+#if (ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE))
+# define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 2
+#endif
+#if (ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE))
+# define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 4
+#endif
+#ifndef ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE
+# define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 0
+#endif
+
+#if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
+# define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 1
+#endif
+#if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
+# define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 2
+#endif
+#if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
+# define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 4
+#endif
+#ifndef ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE
+# define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 0
+#endif
+
+#if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_BYTE == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE))
+# define ASF_PAYLOAD_LENGTH_FIELD_SIZE 1
+#endif
+#if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE))
+# define ASF_PAYLOAD_LENGTH_FIELD_SIZE 2
+#endif
+#ifndef ASF_PAYLOAD_LENGTH_FIELD_SIZE
+# define ASF_PAYLOAD_LENGTH_FIELD_SIZE 0
+#endif
+
+#define PACKET_HEADER_MIN_SIZE (\
+ ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE + \
+ ASF_PACKET_ERROR_CORRECTION_DATA_SIZE + \
+ 1 + /*Length Type Flags*/ \
+ 1 + /*Property Flags*/ \
+ ASF_PPI_PACKET_LENGTH_FIELD_SIZE + \
+ ASF_PPI_SEQUENCE_FIELD_SIZE + \
+ ASF_PPI_PADDING_LENGTH_FIELD_SIZE + \
+ 4 + /*Send Time Field*/ \
+ 2 /*Duration Field*/ \
+ )
+
+
+// Replicated Data shall be at least 8 bytes long.
+#define ASF_PAYLOAD_REPLICATED_DATA_LENGTH 0x08
+
+#define PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD (\
+ 1 + /*Stream Number*/ \
+ ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE + \
+ ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE + \
+ ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE + \
+ ASF_PAYLOAD_REPLICATED_DATA_LENGTH \
+ )
+
+#define PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS (\
+ 1 + /*Stream Number*/ \
+ ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE + \
+ ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE + \
+ ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE + \
+ ASF_PAYLOAD_REPLICATED_DATA_LENGTH + \
+ ASF_PAYLOAD_LENGTH_FIELD_SIZE \
+ )
+
+#define SINGLE_PAYLOAD_DATA_LENGTH (\
+ PACKET_SIZE - \
+ PACKET_HEADER_MIN_SIZE - \
+ PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD \
+ )
+
+#define MULTI_PAYLOAD_CONSTANT (\
+ PACKET_SIZE - \
+ PACKET_HEADER_MIN_SIZE - \
+ 1 - /*Payload Flags*/ \
+ 2*PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS \
+ )
+
+static int preroll_time = 2000;
+
+static const uint8_t error_spread_ADPCM_G726[] = { 0x01, 0x90, 0x01, 0x90, 0x01, 0x01, 0x00, 0x00 };
+
+static void put_guid(ByteIOContext *s, const GUID *g)
+{
+ int i;
+
+ put_le32(s, g->v1);
+ put_le16(s, g->v2);
+ put_le16(s, g->v3);
+ for(i=0;i<8;i++)
+ put_byte(s, g->v4[i]);
+}
+
+static void put_str16(ByteIOContext *s, const char *tag)
+{
+ int c;
+
+ put_le16(s,strlen(tag) + 1);
+ for(;;) {
+ c = (uint8_t)*tag++;
+ put_le16(s, c);
+ if (c == '\0')
+ break;
+ }
+}
+
+static void put_str16_nolen(ByteIOContext *s, const char *tag)
+{
+ int c;
+
+ for(;;) {
+ c = (uint8_t)*tag++;
+ put_le16(s, c);
+ if (c == '\0')
+ break;
+ }
+}
+
+static int64_t put_header(ByteIOContext *pb, const GUID *g)
+{
+ int64_t pos;
+
+ pos = url_ftell(pb);
+ put_guid(pb, g);
+ put_le64(pb, 24);
+ return pos;
+}
+
+/* update header size */
+static void end_header(ByteIOContext *pb, int64_t pos)
+{
+ int64_t pos1;
+
+ pos1 = url_ftell(pb);
+ url_fseek(pb, pos + 16, SEEK_SET);
+ put_le64(pb, pos1 - pos);
+ url_fseek(pb, pos1, SEEK_SET);
+}
+
+/* write an asf chunk (only used in streaming case) */
+static void put_chunk(AVFormatContext *s, int type, int payload_length, int flags)
+{
+ ASFContext *asf = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int length;
+
+ length = payload_length + 8;
+ put_le16(pb, type);
+ put_le16(pb, length); //size
+ put_le32(pb, asf->seqno);//sequence number
+ put_le16(pb, flags); /* unknown bytes */
+ put_le16(pb, length); //size_confirm
+ asf->seqno++;
+}
+
+/* convert from unix to windows time */
+static int64_t unix_to_file_time(int ti)
+{
+ int64_t t;
+
+ t = ti * int64_t_C(10000000);
+ t += int64_t_C(116444736000000000);
+ return t;
+}
+
+/* write the header (used two times if non streamed) */
+static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data_chunk_size)
+{
+ ASFContext *asf = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int header_size, n, extra_size, extra_size2, wav_extra_size, file_time;
+ int has_title;
+ AVCodecContext *enc;
+ int64_t header_offset, cur_pos, hpos;
+ int bit_rate;
+ int64_t duration;
+
+ duration = asf->duration + preroll_time * 10000;
+ has_title = (s->title[0] || s->author[0] || s->copyright[0] || s->comment[0]);
+
+ bit_rate = 0;
+ for(n=0;n<s->nb_streams;n++) {
+ enc = s->streams[n]->codec;
+
+ av_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */
+
+ bit_rate += enc->bit_rate;
+ }
+
+ if (asf->is_streamed) {
+ put_chunk(s, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */
+ }
+
+ put_guid(pb, &asf_header);
+ put_le64(pb, -1); /* header length, will be patched after */
+ put_le32(pb, 3 + has_title + s->nb_streams); /* number of chunks in header */
+ put_byte(pb, 1); /* ??? */
+ put_byte(pb, 2); /* ??? */
+
+ /* file header */
+ header_offset = url_ftell(pb);
+ hpos = put_header(pb, &file_header);
+ put_guid(pb, &my_guid);
+ put_le64(pb, file_size);
+ file_time = 0;
+ put_le64(pb, unix_to_file_time(file_time));
+ put_le64(pb, asf->nb_packets); /* number of packets */
+ put_le64(pb, duration); /* end time stamp (in 100ns units) */
+ put_le64(pb, duration); /* duration (in 100ns units) */
+ put_le32(pb, preroll_time); /* start time stamp */
+ put_le32(pb, 0); /* ??? */
+ put_le32(pb, asf->is_streamed ? 1 : 0); /* ??? */
+ put_le32(pb, asf->packet_size); /* packet size */
+ put_le32(pb, asf->packet_size); /* packet size */
+ put_le32(pb, bit_rate); /* Nominal data rate in bps */
+ end_header(pb, hpos);
+
+ /* unknown headers */
+ hpos = put_header(pb, &head1_guid);
+ put_guid(pb, &head2_guid);
+ put_le32(pb, 6);
+ put_le16(pb, 0);
+ end_header(pb, hpos);
+
+ /* title and other infos */
+ if (has_title) {
+ hpos = put_header(pb, &comment_header);
+ if ( s->title[0] ) { put_le16(pb, 2 * (strlen(s->title ) + 1)); } else { put_le16(pb, 0); }
+ if ( s->author[0] ) { put_le16(pb, 2 * (strlen(s->author ) + 1)); } else { put_le16(pb, 0); }
+ if ( s->copyright[0] ) { put_le16(pb, 2 * (strlen(s->copyright) + 1)); } else { put_le16(pb, 0); }
+ if ( s->comment[0] ) { put_le16(pb, 2 * (strlen(s->comment ) + 1)); } else { put_le16(pb, 0); }
+ put_le16(pb, 0);
+ if ( s->title[0] ) put_str16_nolen(pb, s->title);
+ if ( s->author[0] ) put_str16_nolen(pb, s->author);
+ if ( s->copyright[0] ) put_str16_nolen(pb, s->copyright);
+ if ( s->comment[0] ) put_str16_nolen(pb, s->comment);
+ end_header(pb, hpos);
+ }
+
+ /* stream headers */
+ for(n=0;n<s->nb_streams;n++) {
+ int64_t es_pos;
+ const uint8_t *er_spr = NULL;
+ int er_spr_len = 0;
+ // ASFStream *stream = &asf->streams[n];
+
+ enc = s->streams[n]->codec;
+ asf->streams[n].num = n + 1;
+ asf->streams[n].seq = 0;
+
+
+ if (enc->codec_type == CODEC_TYPE_AUDIO) {
+ if (enc->codec_id == CODEC_ID_ADPCM_G726) {
+ er_spr = error_spread_ADPCM_G726;
+ er_spr_len = sizeof(error_spread_ADPCM_G726);
+ }
+ }
+
+ switch(enc->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ wav_extra_size = 0;
+ extra_size = 18 + wav_extra_size;
+ extra_size2 = er_spr_len;
+ break;
+ default:
+ case CODEC_TYPE_VIDEO:
+ wav_extra_size = enc->extradata_size;
+ extra_size = 0x33 + wav_extra_size;
+ extra_size2 = 0;
+ break;
+ }
+
+ hpos = put_header(pb, &stream_header);
+ if (enc->codec_type == CODEC_TYPE_AUDIO) {
+ put_guid(pb, &audio_stream);
+ if ((er_spr != NULL) && (er_spr_len != 0)) {
+ put_guid(pb, &audio_conceal_spread);
+ } else {
+ put_guid(pb, &video_conceal_none);
+ }
+ } else {
+ put_guid(pb, &video_stream);
+ put_guid(pb, &video_conceal_none);
+ }
+ put_le64(pb, 0); /* ??? */
+ es_pos = url_ftell(pb);
+ put_le32(pb, extra_size); /* wav header len */
+ put_le32(pb, extra_size2); /* additional data len */
+ put_le16(pb, n + 1); /* stream number */
+ put_le32(pb, 0); /* ??? */
+
+ if (enc->codec_type == CODEC_TYPE_AUDIO) {
+ /* WAVEFORMATEX header */
+ int wavsize = put_wav_header(pb, enc);
+ if ((enc->codec_id != CODEC_ID_MP3) && (enc->codec_id != CODEC_ID_MP2) && (enc->codec_id != CODEC_ID_ADPCM_IMA_WAV) && (enc->extradata_size==0)) {
+ wavsize += 2;
+ put_le16(pb, 0);
+ }
+
+ if (wavsize < 0)
+ return -1;
+ if (wavsize != extra_size) {
+ cur_pos = url_ftell(pb);
+ url_fseek(pb, es_pos, SEEK_SET);
+ put_le32(pb, wavsize); /* wav header len */
+ url_fseek(pb, cur_pos, SEEK_SET);
+ }
+ /* ERROR Correction */
+ if ((er_spr != NULL) && (er_spr_len != 0))
+ put_buffer(pb, er_spr, er_spr_len);
+ } else {
+ put_le32(pb, enc->width);
+ put_le32(pb, enc->height);
+ put_byte(pb, 2); /* ??? */
+ put_le16(pb, 40 + enc->extradata_size); /* size */
+
+ /* BITMAPINFOHEADER header */
+ put_bmp_header(pb, enc, codec_bmp_tags, 1);
+ }
+ end_header(pb, hpos);
+ }
+
+ /* media comments */
+
+ hpos = put_header(pb, &codec_comment_header);
+ put_guid(pb, &codec_comment1_header);
+ put_le32(pb, s->nb_streams);
+ for(n=0;n<s->nb_streams;n++) {
+ AVCodec *p;
+
+ enc = s->streams[n]->codec;
+ p = avcodec_find_encoder(enc->codec_id);
+
+ put_le16(pb, asf->streams[n].num);
+ put_str16(pb, p ? p->name : enc->codec_name);
+ put_le16(pb, 0); /* no parameters */
+
+
+ /* id */
+ if (enc->codec_type == CODEC_TYPE_AUDIO) {
+ put_le16(pb, 2);
+ if(!enc->codec_tag)
+ enc->codec_tag = codec_get_tag(codec_wav_tags, enc->codec_id);
+ if(!enc->codec_tag)
+ return -1;
+ put_le16(pb, enc->codec_tag);
+ } else {
+ put_le16(pb, 4);
+ if(!enc->codec_tag)
+ enc->codec_tag = codec_get_tag(codec_bmp_tags, enc->codec_id);
+ if(!enc->codec_tag)
+ return -1;
+ put_le32(pb, enc->codec_tag);
+ }
+ }
+ end_header(pb, hpos);
+
+ /* patch the header size fields */
+
+ cur_pos = url_ftell(pb);
+ header_size = cur_pos - header_offset;
+ if (asf->is_streamed) {
+ header_size += 8 + 30 + 50;
+
+ url_fseek(pb, header_offset - 10 - 30, SEEK_SET);
+ put_le16(pb, header_size);
+ url_fseek(pb, header_offset - 2 - 30, SEEK_SET);
+ put_le16(pb, header_size);
+
+ header_size -= 8 + 30 + 50;
+ }
+ header_size += 24 + 6;
+ url_fseek(pb, header_offset - 14, SEEK_SET);
+ put_le64(pb, header_size);
+ url_fseek(pb, cur_pos, SEEK_SET);
+
+ /* movie chunk, followed by packets of packet_size */
+ asf->data_offset = cur_pos;
+ put_guid(pb, &data_header);
+ put_le64(pb, data_chunk_size);
+ put_guid(pb, &my_guid);
+ put_le64(pb, asf->nb_packets); /* nb packets */
+ put_byte(pb, 1); /* ??? */
+ put_byte(pb, 1); /* ??? */
+ return 0;
+}
+
+static int asf_write_header(AVFormatContext *s)
+{
+ ASFContext *asf = s->priv_data;
+
+ asf->packet_size = PACKET_SIZE;
+ asf->nb_packets = 0;
+
+ asf->last_indexed_pts = 0;
+ asf->index_ptr = (ASFIndex*)av_malloc( sizeof(ASFIndex) * ASF_INDEX_BLOCK );
+ asf->nb_index_memory_alloc = ASF_INDEX_BLOCK;
+ asf->nb_index_count = 0;
+ asf->maximum_packet = 0;
+
+ if (asf_write_header1(s, 0, 50) < 0) {
+ //av_free(asf);
+ return -1;
+ }
+
+ put_flush_packet(&s->pb);
+
+ asf->packet_nb_payloads = 0;
+ asf->prev_packet_sent_time = 0;
+ asf->packet_timestamp_start = -1;
+ asf->packet_timestamp_end = -1;
+ init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size, 1,
+ NULL, NULL, NULL, NULL);
+
+ return 0;
+}
+
+static int asf_write_stream_header(AVFormatContext *s)
+{
+ ASFContext *asf = s->priv_data;
+
+ asf->is_streamed = 1;
+
+ return asf_write_header(s);
+}
+
+static int put_payload_parsing_info(
+ AVFormatContext *s,
+ unsigned int sendtime,
+ unsigned int duration,
+ int nb_payloads,
+ int padsize
+ )
+{
+ ASFContext *asf = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int ppi_size, i;
+ unsigned char *start_ppi_ptr = pb->buf_ptr;
+
+ int iLengthTypeFlags = ASF_PPI_LENGTH_TYPE_FLAGS;
+
+ put_byte(pb, ASF_PACKET_ERROR_CORRECTION_FLAGS);
+ for (i = 0; i < ASF_PACKET_ERROR_CORRECTION_DATA_SIZE; i++){
+ put_byte(pb, 0x0);
+ }
+
+ if (asf->multi_payloads_present)
+ iLengthTypeFlags |= ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT;
+
+ if (padsize > 0) {
+ if (padsize < 256)
+ iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE;
+ else
+ iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD;
+ }
+ put_byte(pb, iLengthTypeFlags);
+
+ put_byte(pb, ASF_PPI_PROPERTY_FLAGS);
+
+ if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD)
+ put_le16(pb, padsize - 2);
+ if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE)
+ put_byte(pb, padsize - 1);
+
+ put_le32(pb, sendtime);
+ put_le16(pb, duration);
+ if (asf->multi_payloads_present)
+ put_byte(pb, nb_payloads | ASF_PAYLOAD_FLAGS);
+
+ ppi_size = pb->buf_ptr - start_ppi_ptr;
+
+ return ppi_size;
+}
+
+static void flush_packet(AVFormatContext *s)
+{
+ ASFContext *asf = s->priv_data;
+ int packet_hdr_size, packet_filled_size;
+
+ if (asf->is_streamed) {
+ put_chunk(s, 0x4424, asf->packet_size, 0);
+ }
+
+ packet_hdr_size = put_payload_parsing_info(
+ s,
+ asf->packet_timestamp_start,
+ asf->packet_timestamp_end - asf->packet_timestamp_start,
+ asf->packet_nb_payloads,
+ asf->packet_size_left
+ );
+
+ packet_filled_size = PACKET_SIZE - packet_hdr_size - asf->packet_size_left;
+ memset(asf->packet_buf + packet_filled_size, 0, asf->packet_size_left);
+
+ put_buffer(&s->pb, asf->packet_buf, asf->packet_size - packet_hdr_size);
+
+ put_flush_packet(&s->pb);
+ asf->nb_packets++;
+ asf->packet_nb_payloads = 0;
+ asf->prev_packet_sent_time = asf->packet_timestamp_start;
+ asf->packet_timestamp_start = -1;
+ asf->packet_timestamp_end = -1;
+ init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size, 1,
+ NULL, NULL, NULL, NULL);
+}
+
+static void put_payload_header(
+ AVFormatContext *s,
+ ASFStream *stream,
+ int presentation_time,
+ int m_obj_size,
+ int m_obj_offset,
+ int payload_len,
+ int flags
+ )
+{
+ ASFContext *asf = s->priv_data;
+ ByteIOContext *pb = &asf->pb;
+ int val;
+
+ val = stream->num;
+ if (flags & PKT_FLAG_KEY)
+ val |= ASF_PL_FLAG_KEY_FRAME;
+ put_byte(pb, val);
+
+ put_byte(pb, stream->seq); //Media object number
+ put_le32(pb, m_obj_offset); //Offset Into Media Object
+
+ // Replicated Data shall be at least 8 bytes long.
+ // The first 4 bytes of data shall contain the
+ // Size of the Media Object that the payload belongs to.
+ // The next 4 bytes of data shall contain the
+ // Presentation Time for the media object that the payload belongs to.
+ put_byte(pb, ASF_PAYLOAD_REPLICATED_DATA_LENGTH);
+
+ put_le32(pb, m_obj_size); //Replicated Data - Media Object Size
+ put_le32(pb, presentation_time);//Replicated Data - Presentation Time
+
+ if (asf->multi_payloads_present){
+ put_le16(pb, payload_len); //payload length
+ }
+}
+
+static void put_frame(
+ AVFormatContext *s,
+ ASFStream *stream,
+ int timestamp,
+ const uint8_t *buf,
+ int m_obj_size,
+ int flags
+ )
+{
+ ASFContext *asf = s->priv_data;
+ int m_obj_offset, payload_len, frag_len1;
+
+ m_obj_offset = 0;
+ while (m_obj_offset < m_obj_size) {
+ payload_len = m_obj_size - m_obj_offset;
+ if (asf->packet_timestamp_start == -1) {
+ asf->multi_payloads_present = (payload_len < MULTI_PAYLOAD_CONSTANT);
+
+ if (asf->multi_payloads_present){
+ asf->packet_size_left = PACKET_SIZE; //For debug
+ asf->packet_size_left = PACKET_SIZE - PACKET_HEADER_MIN_SIZE - 1;
+ frag_len1 = MULTI_PAYLOAD_CONSTANT - 1;
+ }
+ else {
+ asf->packet_size_left = PACKET_SIZE - PACKET_HEADER_MIN_SIZE;
+ frag_len1 = SINGLE_PAYLOAD_DATA_LENGTH;
+ }
+ if (asf->prev_packet_sent_time > timestamp)
+ asf->packet_timestamp_start = asf->prev_packet_sent_time;
+ else
+ asf->packet_timestamp_start = timestamp;
+ }
+ else {
+ // multi payloads
+ frag_len1 = asf->packet_size_left - PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS;
+
+ if (asf->prev_packet_sent_time > timestamp)
+ asf->packet_timestamp_start = asf->prev_packet_sent_time;
+ else if (asf->packet_timestamp_start >= timestamp)
+ asf->packet_timestamp_start = timestamp;
+ }
+ if (frag_len1 > 0) {
+ if (payload_len > frag_len1)
+ payload_len = frag_len1;
+ else if (payload_len == (frag_len1 - 1))
+ payload_len = frag_len1 - 2; //additional byte need to put padding length
+
+ put_payload_header(s, stream, timestamp+preroll_time, m_obj_size, m_obj_offset, payload_len, flags);
+ put_buffer(&asf->pb, buf, payload_len);
+
+ if (asf->multi_payloads_present)
+ asf->packet_size_left -= (payload_len + PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS);
+ else
+ asf->packet_size_left -= (payload_len + PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD);
+ asf->packet_timestamp_end = timestamp;
+
+ asf->packet_nb_payloads++;
+ } else {
+ payload_len = 0;
+ }
+ m_obj_offset += payload_len;
+ buf += payload_len;
+
+ if (!asf->multi_payloads_present)
+ flush_packet(s);
+ else if (asf->packet_size_left <= (PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS + 1))
+ flush_packet(s);
+ }
+ stream->seq++;
+}
+
+static int asf_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ ASFContext *asf = s->priv_data;
+ ASFStream *stream;
+ int64_t duration;
+ AVCodecContext *codec;
+ int64_t packet_st,pts;
+ int start_sec,i;
+
+ codec = s->streams[pkt->stream_index]->codec;
+ stream = &asf->streams[pkt->stream_index];
+
+ //XXX /FIXME use duration from AVPacket (quick hack by)
+ pts = (pkt->pts != AV_NOPTS_VALUE) ? pkt->pts : pkt->dts;
+ if (pts == AV_NOPTS_VALUE) {
+ if (codec->codec_type == CODEC_TYPE_AUDIO) {
+ duration = (codec->frame_number * (int64_t)codec->frame_size * int64_t_C(10000000)) /
+ codec->sample_rate;
+ } else {
+ duration = av_rescale(codec->frame_number * (int64_t)codec->time_base.num, 10000000, codec->time_base.den);
+ }
+ } else {
+ duration = pts * 10000;
+ }
+ if (duration > asf->duration)
+ asf->duration = duration;
+
+ packet_st = asf->nb_packets;
+ put_frame(s, stream, pkt->pts, pkt->data, pkt->size, pkt->flags);
+
+ /* check index */
+ if ((!asf->is_streamed) && (codec->codec_type == CODEC_TYPE_VIDEO) && (pkt->flags & PKT_FLAG_KEY)) {
+ start_sec = (int)(duration / int64_t_C(10000000));
+ if (start_sec != (int)(asf->last_indexed_pts / int64_t_C(10000000))) {
+ for(i=asf->nb_index_count;i<start_sec;i++) {
+ if (i>=asf->nb_index_memory_alloc) {
+ asf->nb_index_memory_alloc += ASF_INDEX_BLOCK;
+ asf->index_ptr = (ASFIndex*)av_realloc( asf->index_ptr, sizeof(ASFIndex) * asf->nb_index_memory_alloc );
+ }
+ // store
+ asf->index_ptr[i].packet_number = (uint32_t)packet_st;
+ asf->index_ptr[i].packet_count = (uint16_t)(asf->nb_packets-packet_st);
+ if (asf->maximum_packet < (uint16_t)(asf->nb_packets-packet_st))
+ asf->maximum_packet = (uint16_t)(asf->nb_packets-packet_st);
+ }
+ asf->nb_index_count = start_sec;
+ asf->last_indexed_pts = duration;
+ }
+ }
+ return 0;
+}
+
+//
+static int asf_write_index(AVFormatContext *s, ASFIndex *index, uint16_t max, uint32_t count)
+{
+ ByteIOContext *pb = &s->pb;
+ int i;
+
+ put_guid(pb, &simple_index_header);
+ put_le64(pb, 24 + 16 + 8 + 4 + 4 + (4 + 2)*count);
+ put_guid(pb, &my_guid);
+ put_le64(pb, ASF_INDEXED_INTERVAL);
+ put_le32(pb, max);
+ put_le32(pb, count);
+ for(i=0; i<count; i++) {
+ put_le32(pb, index[i].packet_number);
+ put_le16(pb, index[i].packet_count);
+ }
+
+ return 0;
+}
+
+static int asf_write_trailer(AVFormatContext *s)
+{
+ ASFContext *asf = s->priv_data;
+ int64_t file_size,data_size;
+
+ /* flush the current packet */
+ if (asf->pb.buf_ptr > asf->pb.buffer)
+ flush_packet(s);
+
+ /* write index */
+ data_size = url_ftell(&s->pb);
+ if ((!asf->is_streamed) && (asf->nb_index_count != 0)) {
+ asf_write_index(s, asf->index_ptr, asf->maximum_packet, asf->nb_index_count);
+ }
+ put_flush_packet(&s->pb);
+
+ if (asf->is_streamed) {
+ put_chunk(s, 0x4524, 0, 0); /* end of stream */
+ } else {
+ /* rewrite an updated header */
+ file_size = url_ftell(&s->pb);
+ url_fseek(&s->pb, 0, SEEK_SET);
+ asf_write_header1(s, file_size, data_size - asf->data_offset);
+ }
+
+ put_flush_packet(&s->pb);
+ av_free(asf->index_ptr);
+ return 0;
+}
+
+#ifdef CONFIG_ASF_MUXER
+AVOutputFormat asf_muxer = {
+ "asf",
+ "asf format",
+ "video/x-ms-asf",
+ "asf,wmv,wma",
+ sizeof(ASFContext),
+#ifdef CONFIG_MP3LAME
+ CODEC_ID_MP3,
+#else
+ CODEC_ID_MP2,
+#endif
+ CODEC_ID_MSMPEG4V3,
+ asf_write_header,
+ asf_write_packet,
+ asf_write_trailer,
+ .flags = AVFMT_GLOBALHEADER,
+};
+#endif
+
+#ifdef CONFIG_ASF_STREAM_MUXER
+AVOutputFormat asf_stream_muxer = {
+ "asf_stream",
+ "asf format",
+ "video/x-ms-asf",
+ "asf,wmv,wma",
+ sizeof(ASFContext),
+#ifdef CONFIG_MP3LAME
+ CODEC_ID_MP3,
+#else
+ CODEC_ID_MP2,
+#endif
+ CODEC_ID_MSMPEG4V3,
+ asf_write_stream_header,
+ asf_write_packet,
+ asf_write_trailer,
+ .flags = AVFMT_GLOBALHEADER,
+};
+#endif //CONFIG_ASF_STREAM_MUXER
diff --git a/contrib/ffmpeg/libavformat/asf.c b/contrib/ffmpeg/libavformat/asf.c
new file mode 100644
index 000000000..f63e4b695
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/asf.c
@@ -0,0 +1,951 @@
+/*
+ * ASF compatible demuxer
+ * 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 "avformat.h"
+#include "riff.h"
+#include "mpegaudio.h"
+#include "asf.h"
+#include "common.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+#define FRAME_HEADER_SIZE 17
+// Fix Me! FRAME_HEADER_SIZE may be different.
+
+static const GUID index_guid = {
+ 0x33000890, 0xe5b1, 0x11cf, { 0x89, 0xf4, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb },
+};
+
+/**********************************/
+/* decoding */
+
+//#define DEBUG
+
+#ifdef DEBUG
+#define PRINT_IF_GUID(g,cmp) \
+if (!memcmp(g, &cmp, sizeof(GUID))) \
+ printf("(GUID: %s) ", #cmp)
+
+static void print_guid(const GUID *g)
+{
+ int i;
+ PRINT_IF_GUID(g, asf_header);
+ else PRINT_IF_GUID(g, file_header);
+ else PRINT_IF_GUID(g, stream_header);
+ else PRINT_IF_GUID(g, audio_stream);
+ else PRINT_IF_GUID(g, audio_conceal_none);
+ else PRINT_IF_GUID(g, video_stream);
+ else PRINT_IF_GUID(g, video_conceal_none);
+ else PRINT_IF_GUID(g, command_stream);
+ else PRINT_IF_GUID(g, comment_header);
+ else PRINT_IF_GUID(g, codec_comment_header);
+ else PRINT_IF_GUID(g, codec_comment1_header);
+ else PRINT_IF_GUID(g, data_header);
+ else PRINT_IF_GUID(g, index_guid);
+ else PRINT_IF_GUID(g, head1_guid);
+ else PRINT_IF_GUID(g, head2_guid);
+ else PRINT_IF_GUID(g, my_guid);
+ else PRINT_IF_GUID(g, ext_stream_header);
+ else PRINT_IF_GUID(g, extended_content_header);
+ else PRINT_IF_GUID(g, ext_stream_embed_stream_header);
+ else PRINT_IF_GUID(g, ext_stream_audio_stream);
+ else
+ printf("(GUID: unknown) ");
+ printf("0x%08x, 0x%04x, 0x%04x, {", g->v1, g->v2, g->v3);
+ for(i=0;i<8;i++)
+ printf(" 0x%02x,", g->v4[i]);
+ printf("}\n");
+}
+#undef PRINT_IF_GUID
+#endif
+
+static void get_guid(ByteIOContext *s, GUID *g)
+{
+ int i;
+
+ g->v1 = get_le32(s);
+ g->v2 = get_le16(s);
+ g->v3 = get_le16(s);
+ for(i=0;i<8;i++)
+ g->v4[i] = get_byte(s);
+}
+
+#if 0
+static void get_str16(ByteIOContext *pb, char *buf, int buf_size)
+{
+ int len, c;
+ char *q;
+
+ len = get_le16(pb);
+ q = buf;
+ while (len > 0) {
+ c = get_le16(pb);
+ if ((q - buf) < buf_size - 1)
+ *q++ = c;
+ len--;
+ }
+ *q = '\0';
+}
+#endif
+
+static void get_str16_nolen(ByteIOContext *pb, int len, char *buf, int buf_size)
+{
+ char* q = buf;
+ len /= 2;
+ while (len--) {
+ uint8_t tmp;
+ PUT_UTF8(get_le16(pb), tmp, if (q - buf < buf_size - 1) *q++ = tmp;)
+ }
+ *q = '\0';
+}
+
+static int asf_probe(AVProbeData *pd)
+{
+ GUID g;
+ const unsigned char *p;
+ int i;
+
+ /* check file header */
+ if (pd->buf_size <= 32)
+ return 0;
+ p = pd->buf;
+ g.v1 = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+ p += 4;
+ g.v2 = p[0] | (p[1] << 8);
+ p += 2;
+ g.v3 = p[0] | (p[1] << 8);
+ p += 2;
+ for(i=0;i<8;i++)
+ g.v4[i] = *p++;
+
+ if (!memcmp(&g, &asf_header, sizeof(GUID)))
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ ASFContext *asf = s->priv_data;
+ GUID g;
+ ByteIOContext *pb = &s->pb;
+ AVStream *st;
+ ASFStream *asf_st;
+ int size, i;
+ int64_t gsize;
+
+ get_guid(pb, &g);
+ if (memcmp(&g, &asf_header, sizeof(GUID)))
+ goto fail;
+ get_le64(pb);
+ get_le32(pb);
+ get_byte(pb);
+ get_byte(pb);
+ memset(&asf->asfid2avid, -1, sizeof(asf->asfid2avid));
+ for(;;) {
+ get_guid(pb, &g);
+ gsize = get_le64(pb);
+#ifdef DEBUG
+ printf("%08"PRIx64": ", url_ftell(pb) - 24);
+ print_guid(&g);
+ printf(" size=0x%"PRIx64"\n", gsize);
+#endif
+ if (gsize < 24)
+ goto fail;
+ if (!memcmp(&g, &file_header, sizeof(GUID))) {
+ get_guid(pb, &asf->hdr.guid);
+ asf->hdr.file_size = get_le64(pb);
+ asf->hdr.create_time = get_le64(pb);
+ asf->hdr.packets_count = get_le64(pb);
+ asf->hdr.send_time = get_le64(pb);
+ asf->hdr.play_time = get_le64(pb);
+ asf->hdr.preroll = get_le32(pb);
+ asf->hdr.ignore = get_le32(pb);
+ asf->hdr.flags = get_le32(pb);
+ asf->hdr.min_pktsize = get_le32(pb);
+ asf->hdr.max_pktsize = get_le32(pb);
+ asf->hdr.max_bitrate = get_le32(pb);
+ asf->packet_size = asf->hdr.max_pktsize;
+ asf->nb_packets = asf->hdr.packets_count;
+ } else if (!memcmp(&g, &stream_header, sizeof(GUID))) {
+ int type, type_specific_size, sizeX;
+ uint64_t total_size;
+ unsigned int tag1;
+ int64_t pos1, pos2;
+ int test_for_ext_stream_audio;
+
+ pos1 = url_ftell(pb);
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ goto fail;
+ av_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */
+ asf_st = av_mallocz(sizeof(ASFStream));
+ if (!asf_st)
+ goto fail;
+ st->priv_data = asf_st;
+ st->start_time = asf->hdr.preroll;
+ st->duration = asf->hdr.send_time /
+ (10000000 / 1000) - st->start_time;
+ get_guid(pb, &g);
+
+ test_for_ext_stream_audio = 0;
+ if (!memcmp(&g, &audio_stream, sizeof(GUID))) {
+ type = CODEC_TYPE_AUDIO;
+ } else if (!memcmp(&g, &video_stream, sizeof(GUID))) {
+ type = CODEC_TYPE_VIDEO;
+ } else if (!memcmp(&g, &command_stream, sizeof(GUID))) {
+ type = CODEC_TYPE_UNKNOWN;
+ } else if (!memcmp(&g, &ext_stream_embed_stream_header, sizeof(GUID))) {
+ test_for_ext_stream_audio = 1;
+ type = CODEC_TYPE_UNKNOWN;
+ } else {
+ goto fail;
+ }
+ get_guid(pb, &g);
+ total_size = get_le64(pb);
+ type_specific_size = get_le32(pb);
+ get_le32(pb);
+ st->id = get_le16(pb) & 0x7f; /* stream id */
+ // mapping of asf ID to AV stream ID;
+ asf->asfid2avid[st->id] = s->nb_streams - 1;
+
+ get_le32(pb);
+
+ if (test_for_ext_stream_audio) {
+ get_guid(pb, &g);
+ if (!memcmp(&g, &ext_stream_audio_stream, sizeof(GUID))) {
+ type = CODEC_TYPE_AUDIO;
+ get_guid(pb, &g);
+ get_le32(pb);
+ get_le32(pb);
+ get_le32(pb);
+ get_guid(pb, &g);
+ get_le32(pb);
+ }
+ }
+
+ st->codec->codec_type = type;
+ if (type == CODEC_TYPE_AUDIO) {
+ get_wav_header(pb, st->codec, type_specific_size);
+ st->need_parsing = 1;
+ /* We have to init the frame size at some point .... */
+ pos2 = url_ftell(pb);
+ if (gsize > (pos2 + 8 - pos1 + 24)) {
+ asf_st->ds_span = get_byte(pb);
+ asf_st->ds_packet_size = get_le16(pb);
+ asf_st->ds_chunk_size = get_le16(pb);
+ asf_st->ds_data_size = get_le16(pb);
+ asf_st->ds_silence_data = get_byte(pb);
+ }
+ //printf("Descrambling: ps:%d cs:%d ds:%d s:%d sd:%d\n",
+ // asf_st->ds_packet_size, asf_st->ds_chunk_size,
+ // asf_st->ds_data_size, asf_st->ds_span, asf_st->ds_silence_data);
+ if (asf_st->ds_span > 1) {
+ if (!asf_st->ds_chunk_size
+ || (asf_st->ds_packet_size/asf_st->ds_chunk_size <= 1))
+ asf_st->ds_span = 0; // disable descrambling
+ }
+ switch (st->codec->codec_id) {
+ case CODEC_ID_MP3:
+ st->codec->frame_size = MPA_FRAME_SIZE;
+ break;
+ case CODEC_ID_PCM_S16LE:
+ case CODEC_ID_PCM_S16BE:
+ case CODEC_ID_PCM_U16LE:
+ case CODEC_ID_PCM_U16BE:
+ case CODEC_ID_PCM_S8:
+ case CODEC_ID_PCM_U8:
+ case CODEC_ID_PCM_ALAW:
+ case CODEC_ID_PCM_MULAW:
+ st->codec->frame_size = 1;
+ break;
+ default:
+ /* This is probably wrong, but it prevents a crash later */
+ st->codec->frame_size = 1;
+ break;
+ }
+ } else if (type == CODEC_TYPE_VIDEO) {
+ get_le32(pb);
+ get_le32(pb);
+ get_byte(pb);
+ size = get_le16(pb); /* size */
+ sizeX= get_le32(pb); /* size */
+ st->codec->width = get_le32(pb);
+ st->codec->height = get_le32(pb);
+ /* not available for asf */
+ get_le16(pb); /* panes */
+ st->codec->bits_per_sample = get_le16(pb); /* depth */
+ tag1 = get_le32(pb);
+ url_fskip(pb, 20);
+// av_log(NULL, AV_LOG_DEBUG, "size:%d tsize:%d sizeX:%d\n", size, total_size, sizeX);
+ size= sizeX;
+ if (size > 40) {
+ st->codec->extradata_size = size - 40;
+ st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
+ }
+
+ /* Extract palette from extradata if bpp <= 8 */
+ /* This code assumes that extradata contains only palette */
+ /* This is true for all paletted codecs implemented in ffmpeg */
+ if (st->codec->extradata_size && (st->codec->bits_per_sample <= 8)) {
+ st->codec->palctrl = av_mallocz(sizeof(AVPaletteControl));
+#ifdef WORDS_BIGENDIAN
+ for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)/4; i++)
+ st->codec->palctrl->palette[i] = bswap_32(((uint32_t*)st->codec->extradata)[i]);
+#else
+ memcpy(st->codec->palctrl->palette, st->codec->extradata,
+ FFMIN(st->codec->extradata_size, AVPALETTE_SIZE));
+#endif
+ st->codec->palctrl->palette_changed = 1;
+ }
+
+ st->codec->codec_tag = tag1;
+ st->codec->codec_id = codec_get_id(codec_bmp_tags, tag1);
+ if(tag1 == MKTAG('D', 'V', 'R', ' '))
+ st->need_parsing = 1;
+ }
+ pos2 = url_ftell(pb);
+ url_fskip(pb, gsize - (pos2 - pos1 + 24));
+ } else if (!memcmp(&g, &data_header, sizeof(GUID))) {
+ asf->data_object_offset = url_ftell(pb);
+ if (gsize != (uint64_t)-1 && gsize >= 24) {
+ asf->data_object_size = gsize - 24;
+ } else {
+ asf->data_object_size = (uint64_t)-1;
+ }
+ break;
+ } else if (!memcmp(&g, &comment_header, sizeof(GUID))) {
+ int len1, len2, len3, len4, len5;
+
+ len1 = get_le16(pb);
+ len2 = get_le16(pb);
+ len3 = get_le16(pb);
+ len4 = get_le16(pb);
+ len5 = get_le16(pb);
+ get_str16_nolen(pb, len1, s->title, sizeof(s->title));
+ get_str16_nolen(pb, len2, s->author, sizeof(s->author));
+ get_str16_nolen(pb, len3, s->copyright, sizeof(s->copyright));
+ get_str16_nolen(pb, len4, s->comment, sizeof(s->comment));
+ url_fskip(pb, len5);
+ } else if (!memcmp(&g, &extended_content_header, sizeof(GUID))) {
+ int desc_count, i;
+
+ desc_count = get_le16(pb);
+ for(i=0;i<desc_count;i++)
+ {
+ int name_len,value_type,value_len;
+ uint64_t value_num = 0;
+ char *name, *value;
+
+ name_len = get_le16(pb);
+ name = (char *)av_malloc(name_len * 2);
+ get_str16_nolen(pb, name_len, name, name_len * 2);
+ value_type = get_le16(pb);
+ value_len = get_le16(pb);
+ if ((value_type == 0) || (value_type == 1)) // unicode or byte
+ {
+ value = (char *)av_malloc(value_len * 2);
+ get_str16_nolen(pb, value_len, value,
+ value_len * 2);
+ if (strcmp(name,"WM/AlbumTitle")==0) { pstrcpy(s->album, sizeof(s->album), value); }
+ av_free(value);
+ }
+ if ((value_type >= 2) && (value_type <= 5)) // boolean or DWORD or QWORD or WORD
+ {
+ if (value_type==2) value_num = get_le32(pb);
+ if (value_type==3) value_num = get_le32(pb);
+ if (value_type==4) value_num = get_le64(pb);
+ if (value_type==5) value_num = get_le16(pb);
+ if (strcmp(name,"WM/Track")==0) s->track = value_num + 1;
+ if (strcmp(name,"WM/TrackNumber")==0) s->track = value_num;
+ }
+ av_free(name);
+ }
+ } else if (!memcmp(&g, &ext_stream_header, sizeof(GUID))) {
+ int ext_len, payload_ext_ct, stream_ct;
+ uint32_t ext_d;
+ int64_t pos_ex_st;
+ pos_ex_st = url_ftell(pb);
+
+ get_le64(pb);
+ get_le64(pb);
+ get_le32(pb);
+ get_le32(pb);
+ get_le32(pb);
+ get_le32(pb);
+ get_le32(pb);
+ get_le32(pb);
+ get_le32(pb);
+ get_le32(pb);
+ get_le16(pb);
+ get_le16(pb);
+ get_le64(pb);
+ stream_ct = get_le16(pb);
+ payload_ext_ct = get_le16(pb);
+
+ for (i=0; i<stream_ct; i++){
+ get_le16(pb);
+ ext_len = get_le16(pb);
+ url_fseek(pb, ext_len, SEEK_CUR);
+ }
+
+ for (i=0; i<payload_ext_ct; i++){
+ get_guid(pb, &g);
+ ext_d=get_le16(pb);
+ ext_len=get_le32(pb);
+ url_fseek(pb, ext_len, SEEK_CUR);
+ }
+
+ // there could be a optional stream properties object to follow
+ // if so the next iteration will pick it up
+ } else if (!memcmp(&g, &head1_guid, sizeof(GUID))) {
+ int v1, v2;
+ get_guid(pb, &g);
+ v1 = get_le32(pb);
+ v2 = get_le16(pb);
+#if 0
+ } else if (!memcmp(&g, &codec_comment_header, sizeof(GUID))) {
+ int len, v1, n, num;
+ char str[256], *q;
+ char tag[16];
+
+ get_guid(pb, &g);
+ print_guid(&g);
+
+ n = get_le32(pb);
+ for(i=0;i<n;i++) {
+ num = get_le16(pb); /* stream number */
+ get_str16(pb, str, sizeof(str));
+ get_str16(pb, str, sizeof(str));
+ len = get_le16(pb);
+ q = tag;
+ while (len > 0) {
+ v1 = get_byte(pb);
+ if ((q - tag) < sizeof(tag) - 1)
+ *q++ = v1;
+ len--;
+ }
+ *q = '\0';
+ }
+#endif
+ } else if (url_feof(pb)) {
+ goto fail;
+ } else {
+ url_fseek(pb, gsize - 24, SEEK_CUR);
+ }
+ }
+ get_guid(pb, &g);
+ get_le64(pb);
+ get_byte(pb);
+ get_byte(pb);
+ if (url_feof(pb))
+ goto fail;
+ asf->data_offset = url_ftell(pb);
+ asf->packet_size_left = 0;
+
+ return 0;
+
+ fail:
+ for(i=0;i<s->nb_streams;i++) {
+ AVStream *st = s->streams[i];
+ if (st) {
+ av_free(st->priv_data);
+ av_free(st->codec->extradata);
+ }
+ av_free(st);
+ }
+ return -1;
+}
+
+#define DO_2BITS(bits, var, defval) \
+ switch (bits & 3) \
+ { \
+ case 3: var = get_le32(pb); rsize += 4; break; \
+ case 2: var = get_le16(pb); rsize += 2; break; \
+ case 1: var = get_byte(pb); rsize++; break; \
+ default: var = defval; break; \
+ }
+
+static int asf_get_packet(AVFormatContext *s)
+{
+ ASFContext *asf = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ uint32_t packet_length, padsize;
+ int rsize = 9;
+ int c;
+
+ assert((url_ftell(&s->pb) - s->data_offset) % asf->packet_size == 0);
+
+ c = get_byte(pb);
+ if (c != 0x82) {
+ if (!url_feof(pb))
+ av_log(s, AV_LOG_ERROR, "ff asf bad header %x at:%"PRId64"\n", c, url_ftell(pb));
+ }
+ if ((c & 0x0f) == 2) { // always true for now
+ if (get_le16(pb) != 0) {
+ if (!url_feof(pb))
+ av_log(s, AV_LOG_ERROR, "ff asf bad non zero\n");
+ return AVERROR_IO;
+ }
+ rsize+=2;
+/* }else{
+ if (!url_feof(pb))
+ printf("ff asf bad header %x at:%"PRId64"\n", c, url_ftell(pb));
+ return AVERROR_IO;*/
+ }
+
+ asf->packet_flags = get_byte(pb);
+ asf->packet_property = get_byte(pb);
+
+ DO_2BITS(asf->packet_flags >> 5, packet_length, asf->packet_size);
+ DO_2BITS(asf->packet_flags >> 1, padsize, 0); // sequence ignored
+ DO_2BITS(asf->packet_flags >> 3, padsize, 0); // padding length
+
+ //the following checks prevent overflows and infinite loops
+ if(packet_length >= (1U<<29)){
+ av_log(s, AV_LOG_ERROR, "invalid packet_length %d at:%"PRId64"\n", packet_length, url_ftell(pb));
+ return 0; // FIXME this should be -1
+ }
+ if(padsize >= (1U<<29)){
+ av_log(s, AV_LOG_ERROR, "invalid padsize %d at:%"PRId64"\n", padsize, url_ftell(pb));
+ return 0; // FIXME this should be -1
+ }
+
+ asf->packet_timestamp = get_le32(pb);
+ get_le16(pb); /* duration */
+ // rsize has at least 11 bytes which have to be present
+
+ if (asf->packet_flags & 0x01) {
+ asf->packet_segsizetype = get_byte(pb); rsize++;
+ asf->packet_segments = asf->packet_segsizetype & 0x3f;
+ } else {
+ asf->packet_segments = 1;
+ asf->packet_segsizetype = 0x80;
+ }
+ asf->packet_size_left = packet_length - padsize - rsize;
+ if (packet_length < asf->hdr.min_pktsize)
+ padsize += asf->hdr.min_pktsize - packet_length;
+ asf->packet_padsize = padsize;
+#ifdef DEBUG
+ printf("packet: size=%d padsize=%d left=%d\n", asf->packet_size, asf->packet_padsize, asf->packet_size_left);
+#endif
+ return 0;
+}
+
+static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ ASFContext *asf = s->priv_data;
+ ASFStream *asf_st = 0;
+ ByteIOContext *pb = &s->pb;
+ //static int pc = 0;
+ for (;;) {
+ int rsize = 0;
+ if (asf->packet_size_left < FRAME_HEADER_SIZE
+ || asf->packet_segments < 1) {
+ //asf->packet_size_left <= asf->packet_padsize) {
+ int ret = asf->packet_size_left + asf->packet_padsize;
+ //printf("PacketLeftSize:%d Pad:%d Pos:%"PRId64"\n", asf->packet_size_left, asf->packet_padsize, url_ftell(pb));
+ if((url_ftell(&s->pb) + ret - s->data_offset) % asf->packet_size)
+ ret += asf->packet_size - ((url_ftell(&s->pb) + ret - s->data_offset) % asf->packet_size);
+ assert(ret>=0);
+ /* fail safe */
+ url_fskip(pb, ret);
+ asf->packet_pos= url_ftell(&s->pb);
+ if (asf->data_object_size != (uint64_t)-1 &&
+ (asf->packet_pos - asf->data_object_offset >= asf->data_object_size))
+ return AVERROR_IO; /* Do not exceed the size of the data object */
+ ret = asf_get_packet(s);
+ //printf("READ ASF PACKET %d r:%d c:%d\n", ret, asf->packet_size_left, pc++);
+ if (ret < 0 || url_feof(pb))
+ return AVERROR_IO;
+ asf->packet_time_start = 0;
+ continue;
+ }
+ if (asf->packet_time_start == 0) {
+ /* read frame header */
+ int num = get_byte(pb);
+ asf->packet_segments--;
+ rsize++;
+ asf->packet_key_frame = (num & 0x80) >> 7;
+ asf->stream_index = asf->asfid2avid[num & 0x7f];
+ // sequence should be ignored!
+ DO_2BITS(asf->packet_property >> 4, asf->packet_seq, 0);
+ DO_2BITS(asf->packet_property >> 2, asf->packet_frag_offset, 0);
+ DO_2BITS(asf->packet_property, asf->packet_replic_size, 0);
+//printf("key:%d stream:%d seq:%d offset:%d replic_size:%d\n", asf->packet_key_frame, asf->stream_index, asf->packet_seq, //asf->packet_frag_offset, asf->packet_replic_size);
+ if (asf->packet_replic_size > 1) {
+ assert(asf->packet_replic_size >= 8);
+ // it should be always at least 8 bytes - FIXME validate
+ asf->packet_obj_size = get_le32(pb);
+ asf->packet_frag_timestamp = get_le32(pb); // timestamp
+ if (asf->packet_replic_size > 8)
+ url_fskip(pb, asf->packet_replic_size - 8);
+ rsize += asf->packet_replic_size; // FIXME - check validity
+ } else if (asf->packet_replic_size==1){
+ // multipacket - frag_offset is begining timestamp
+ asf->packet_time_start = asf->packet_frag_offset;
+ asf->packet_frag_offset = 0;
+ asf->packet_frag_timestamp = asf->packet_timestamp;
+
+ asf->packet_time_delta = get_byte(pb);
+ rsize++;
+ }else{
+ assert(asf->packet_replic_size==0);
+ }
+ if (asf->packet_flags & 0x01) {
+ DO_2BITS(asf->packet_segsizetype >> 6, asf->packet_frag_size, 0); // 0 is illegal
+#undef DO_2BITS
+ //printf("Fragsize %d\n", asf->packet_frag_size);
+ } else {
+ asf->packet_frag_size = asf->packet_size_left - rsize;
+ //printf("Using rest %d %d %d\n", asf->packet_frag_size, asf->packet_size_left, rsize);
+ }
+ if (asf->packet_replic_size == 1) {
+ asf->packet_multi_size = asf->packet_frag_size;
+ if (asf->packet_multi_size > asf->packet_size_left) {
+ asf->packet_segments = 0;
+ continue;
+ }
+ }
+ asf->packet_size_left -= rsize;
+ //printf("___objsize____ %d %d rs:%d\n", asf->packet_obj_size, asf->packet_frag_offset, rsize);
+
+ if (asf->stream_index < 0
+ || s->streams[asf->stream_index]->discard >= AVDISCARD_ALL
+ || (!asf->packet_key_frame && s->streams[asf->stream_index]->discard >= AVDISCARD_NONKEY)
+ ) {
+ asf->packet_time_start = 0;
+ /* unhandled packet (should not happen) */
+ url_fskip(pb, asf->packet_frag_size);
+ asf->packet_size_left -= asf->packet_frag_size;
+ if(asf->stream_index < 0)
+ av_log(s, AV_LOG_ERROR, "ff asf skip %d %d\n", asf->packet_frag_size, num & 0x7f);
+ continue;
+ }
+ asf->asf_st = s->streams[asf->stream_index]->priv_data;
+ }
+ asf_st = asf->asf_st;
+
+ if ((asf->packet_frag_offset != asf_st->frag_offset
+ || (asf->packet_frag_offset
+ && asf->packet_seq != asf_st->seq)) // seq should be ignored
+ ) {
+ /* cannot continue current packet: free it */
+ // FIXME better check if packet was already allocated
+ av_log(s, AV_LOG_INFO, "ff asf parser skips: %d - %d o:%d - %d %d %d fl:%d\n",
+ asf_st->pkt.size,
+ asf->packet_obj_size,
+ asf->packet_frag_offset, asf_st->frag_offset,
+ asf->packet_seq, asf_st->seq, asf->packet_frag_size);
+ if (asf_st->pkt.size)
+ av_free_packet(&asf_st->pkt);
+ asf_st->frag_offset = 0;
+ if (asf->packet_frag_offset != 0) {
+ url_fskip(pb, asf->packet_frag_size);
+ av_log(s, AV_LOG_INFO, "ff asf parser skipping %db\n", asf->packet_frag_size);
+ asf->packet_size_left -= asf->packet_frag_size;
+ continue;
+ }
+ }
+ if (asf->packet_replic_size == 1) {
+ // frag_offset is here used as the begining timestamp
+ asf->packet_frag_timestamp = asf->packet_time_start;
+ asf->packet_time_start += asf->packet_time_delta;
+ asf->packet_obj_size = asf->packet_frag_size = get_byte(pb);
+ asf->packet_size_left--;
+ asf->packet_multi_size--;
+ if (asf->packet_multi_size < asf->packet_obj_size)
+ {
+ asf->packet_time_start = 0;
+ url_fskip(pb, asf->packet_multi_size);
+ asf->packet_size_left -= asf->packet_multi_size;
+ continue;
+ }
+ asf->packet_multi_size -= asf->packet_obj_size;
+ //printf("COMPRESS size %d %d %d ms:%d\n", asf->packet_obj_size, asf->packet_frag_timestamp, asf->packet_size_left, asf->packet_multi_size);
+ }
+ if (asf_st->frag_offset == 0) {
+ /* new packet */
+ av_new_packet(&asf_st->pkt, asf->packet_obj_size);
+ asf_st->seq = asf->packet_seq;
+ asf_st->pkt.pts = asf->packet_frag_timestamp;
+ asf_st->pkt.stream_index = asf->stream_index;
+ asf_st->pkt.pos =
+ asf_st->packet_pos= asf->packet_pos;
+//printf("new packet: stream:%d key:%d packet_key:%d audio:%d size:%d\n",
+//asf->stream_index, asf->packet_key_frame, asf_st->pkt.flags & PKT_FLAG_KEY,
+//s->streams[asf->stream_index]->codec->codec_type == CODEC_TYPE_AUDIO, asf->packet_obj_size);
+ if (s->streams[asf->stream_index]->codec->codec_type == CODEC_TYPE_AUDIO)
+ asf->packet_key_frame = 1;
+ if (asf->packet_key_frame)
+ asf_st->pkt.flags |= PKT_FLAG_KEY;
+ }
+
+ /* read data */
+ //printf("READ PACKET s:%d os:%d o:%d,%d l:%d DATA:%p\n",
+ // asf->packet_size, asf_st->pkt.size, asf->packet_frag_offset,
+ // asf_st->frag_offset, asf->packet_frag_size, asf_st->pkt.data);
+ asf->packet_size_left -= asf->packet_frag_size;
+ if (asf->packet_size_left < 0)
+ continue;
+ get_buffer(pb, asf_st->pkt.data + asf->packet_frag_offset,
+ asf->packet_frag_size);
+ asf_st->frag_offset += asf->packet_frag_size;
+ /* test if whole packet is read */
+ if (asf_st->frag_offset == asf_st->pkt.size) {
+ /* return packet */
+ if (asf_st->ds_span > 1) {
+ /* packet descrambling */
+ uint8_t *newdata = av_malloc(asf_st->pkt.size);
+ if (newdata) {
+ int offset = 0;
+ while (offset < asf_st->pkt.size) {
+ int off = offset / asf_st->ds_chunk_size;
+ int row = off / asf_st->ds_span;
+ int col = off % asf_st->ds_span;
+ int idx = row + col * asf_st->ds_packet_size / asf_st->ds_chunk_size;
+ //printf("off:%d row:%d col:%d idx:%d\n", off, row, col, idx);
+ memcpy(newdata + offset,
+ asf_st->pkt.data + idx * asf_st->ds_chunk_size,
+ asf_st->ds_chunk_size);
+ offset += asf_st->ds_chunk_size;
+ }
+ av_free(asf_st->pkt.data);
+ asf_st->pkt.data = newdata;
+ }
+ }
+ asf_st->frag_offset = 0;
+ memcpy(pkt, &asf_st->pkt, sizeof(AVPacket));
+ //printf("packet %d %d\n", asf_st->pkt.size, asf->packet_frag_size);
+ asf_st->pkt.size = 0;
+ asf_st->pkt.data = 0;
+ break; // packet completed
+ }
+ }
+ return 0;
+}
+
+static int asf_read_close(AVFormatContext *s)
+{
+ int i;
+
+ for(i=0;i<s->nb_streams;i++) {
+ AVStream *st = s->streams[i];
+ av_free(st->priv_data);
+ av_free(st->codec->palctrl);
+ }
+ return 0;
+}
+
+// Added to support seeking after packets have been read
+// If information is not reset, read_packet fails due to
+// leftover information from previous reads
+static void asf_reset_header(AVFormatContext *s)
+{
+ ASFContext *asf = s->priv_data;
+ ASFStream *asf_st;
+ int i;
+
+ asf->packet_nb_frames = 0;
+ asf->packet_timestamp_start = -1;
+ asf->packet_timestamp_end = -1;
+ asf->packet_size_left = 0;
+ asf->packet_segments = 0;
+ asf->packet_flags = 0;
+ asf->packet_property = 0;
+ asf->packet_timestamp = 0;
+ asf->packet_segsizetype = 0;
+ asf->packet_segments = 0;
+ asf->packet_seq = 0;
+ asf->packet_replic_size = 0;
+ asf->packet_key_frame = 0;
+ asf->packet_padsize = 0;
+ asf->packet_frag_offset = 0;
+ asf->packet_frag_size = 0;
+ asf->packet_frag_timestamp = 0;
+ asf->packet_multi_size = 0;
+ asf->packet_obj_size = 0;
+ asf->packet_time_delta = 0;
+ asf->packet_time_start = 0;
+
+ for(i=0; i<s->nb_streams; i++){
+ asf_st= s->streams[i]->priv_data;
+ av_free_packet(&asf_st->pkt);
+ asf_st->frag_offset=0;
+ asf_st->seq=0;
+ }
+ asf->asf_st= NULL;
+}
+
+static int64_t asf_read_pts(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit)
+{
+ ASFContext *asf = s->priv_data;
+ AVPacket pkt1, *pkt = &pkt1;
+ ASFStream *asf_st;
+ int64_t pts;
+ int64_t pos= *ppos;
+ int i;
+ int64_t start_pos[s->nb_streams];
+
+ for(i=0; i<s->nb_streams; i++){
+ start_pos[i]= pos;
+ }
+
+ pos= (pos+asf->packet_size-1-s->data_offset)/asf->packet_size*asf->packet_size+ s->data_offset;
+ *ppos= pos;
+ url_fseek(&s->pb, pos, SEEK_SET);
+
+//printf("asf_read_pts\n");
+ asf_reset_header(s);
+ for(;;){
+ if (av_read_frame(s, pkt) < 0){
+ av_log(s, AV_LOG_INFO, "seek failed\n");
+ return AV_NOPTS_VALUE;
+ }
+
+ pts= pkt->pts;
+
+ av_free_packet(pkt);
+ if(pkt->flags&PKT_FLAG_KEY){
+ i= pkt->stream_index;
+
+ asf_st= s->streams[i]->priv_data;
+
+ assert((asf_st->packet_pos - s->data_offset) % asf->packet_size == 0);
+ pos= asf_st->packet_pos;
+
+ av_add_index_entry(s->streams[i], pos, pts, pkt->size, pos - start_pos[i] + 1, AVINDEX_KEYFRAME);
+ start_pos[i]= asf_st->packet_pos + 1;
+
+ if(pkt->stream_index == stream_index)
+ break;
+ }
+ }
+
+ *ppos= pos;
+//printf("found keyframe at %"PRId64" stream %d stamp:%"PRId64"\n", *ppos, stream_index, pts);
+
+ return pts;
+}
+
+static void asf_build_simple_index(AVFormatContext *s, int stream_index)
+{
+ GUID g;
+ ASFContext *asf = s->priv_data;
+ int64_t gsize, itime;
+ int64_t pos, current_pos, index_pts;
+ int i;
+ int pct,ict;
+
+ current_pos = url_ftell(&s->pb);
+
+ url_fseek(&s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET);
+ get_guid(&s->pb, &g);
+ if (!memcmp(&g, &index_guid, sizeof(GUID))) {
+ gsize = get_le64(&s->pb);
+ get_guid(&s->pb, &g);
+ itime=get_le64(&s->pb);
+ pct=get_le32(&s->pb);
+ ict=get_le32(&s->pb);
+ av_log(NULL, AV_LOG_DEBUG, "itime:0x%"PRIx64", pct:%d, ict:%d\n",itime,pct,ict);
+
+ for (i=0;i<ict;i++){
+ int pktnum=get_le32(&s->pb);
+ int pktct =get_le16(&s->pb);
+ av_log(NULL, AV_LOG_DEBUG, "pktnum:%d, pktct:%d\n", pktnum, pktct);
+
+ pos=s->data_offset + asf->packet_size*(int64_t)pktnum;
+ index_pts=av_rescale(itime, i, 10000);
+
+ av_add_index_entry(s->streams[stream_index], pos, index_pts, asf->packet_size, 0, AVINDEX_KEYFRAME);
+ }
+ asf->index_read= 1;
+ }
+ url_fseek(&s->pb, current_pos, SEEK_SET);
+}
+
+static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags)
+{
+ ASFContext *asf = s->priv_data;
+ AVStream *st = s->streams[stream_index];
+ int64_t pos;
+ int index;
+
+ if (asf->packet_size <= 0)
+ return -1;
+
+ if (!asf->index_read)
+ asf_build_simple_index(s, stream_index);
+
+ if(!(asf->index_read && st->index_entries)){
+ if(av_seek_frame_binary(s, stream_index, pts, flags)<0)
+ return -1;
+ }else{
+ index= av_index_search_timestamp(st, pts, flags);
+ if(index<0)
+ return -1;
+
+ /* find the position */
+ pos = st->index_entries[index].pos;
+ pts = st->index_entries[index].timestamp;
+
+ // various attempts to find key frame have failed so far
+ // asf_reset_header(s);
+ // url_fseek(&s->pb, pos, SEEK_SET);
+ // key_pos = pos;
+ // for(i=0;i<16;i++){
+ // pos = url_ftell(&s->pb);
+ // if (av_read_frame(s, &pkt) < 0){
+ // av_log(s, AV_LOG_INFO, "seek failed\n");
+ // return -1;
+ // }
+ // asf_st = s->streams[stream_index]->priv_data;
+ // pos += st->parser->frame_offset;
+ //
+ // if (pkt.size > b) {
+ // b = pkt.size;
+ // key_pos = pos;
+ // }
+ //
+ // av_free_packet(&pkt);
+ // }
+
+ /* do the seek */
+ av_log(NULL, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos);
+ url_fseek(&s->pb, pos, SEEK_SET);
+ }
+ asf_reset_header(s);
+ return 0;
+}
+
+AVInputFormat asf_demuxer = {
+ "asf",
+ "asf format",
+ sizeof(ASFContext),
+ asf_probe,
+ asf_read_header,
+ asf_read_packet,
+ asf_read_close,
+ asf_read_seek,
+ asf_read_pts,
+};
diff --git a/contrib/ffmpeg/libavformat/asf.h b/contrib/ffmpeg/libavformat/asf.h
new file mode 100644
index 000000000..bbe88801a
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/asf.h
@@ -0,0 +1,285 @@
+/*
+ * 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
+ */
+#define PACKET_SIZE 3200
+
+typedef struct {
+ int num;
+ unsigned char seq;
+ /* use for reading */
+ AVPacket pkt;
+ int frag_offset;
+ int timestamp;
+ int64_t duration;
+
+ int ds_span; /* descrambling */
+ int ds_packet_size;
+ int ds_chunk_size;
+ int ds_data_size;
+ int ds_silence_data;
+
+ int64_t packet_pos;
+
+} ASFStream;
+
+typedef struct {
+ uint32_t v1;
+ uint16_t v2;
+ uint16_t v3;
+ uint8_t v4[8];
+} GUID;
+
+typedef struct {
+ GUID guid; // generated by client computer
+ uint64_t file_size; // in bytes
+ // invalid if broadcasting
+ uint64_t create_time; // time of creation, in 100-nanosecond units since 1.1.1601
+ // invalid if broadcasting
+ uint64_t packets_count; // how many packets are there in the file
+ // invalid if broadcasting
+ uint64_t play_time; // play time, in 100-nanosecond units
+ // invalid if broadcasting
+ uint64_t send_time; // time to send file, in 100-nanosecond units
+ // invalid if broadcasting (could be ignored)
+ uint32_t preroll; // timestamp of the first packet, in milliseconds
+ // if nonzero - substract from time
+ uint32_t ignore; // preroll is 64bit - but let's just ignore it
+ uint32_t flags; // 0x01 - broadcast
+ // 0x02 - seekable
+ // rest is reserved should be 0
+ uint32_t min_pktsize; // size of a data packet
+ // invalid if broadcasting
+ uint32_t max_pktsize; // shall be the same as for min_pktsize
+ // invalid if broadcasting
+ uint32_t max_bitrate; // bandwith of stream in bps
+ // should be the sum of bitrates of the
+ // individual media streams
+} ASFMainHeader;
+
+
+typedef struct {
+ uint32_t packet_number;
+ uint16_t packet_count;
+} ASFIndex;
+
+
+typedef struct {
+ uint32_t seqno;
+ unsigned int packet_size;
+ int is_streamed;
+ int asfid2avid[128]; /* conversion table from asf ID 2 AVStream ID */
+ ASFStream streams[128]; /* it's max number and it's not that big */
+ /* non streamed additonnal info */
+ int64_t nb_packets;
+ int64_t duration; /* in 100ns units */
+ /* packet filling */
+ unsigned char multi_payloads_present;
+ int packet_size_left;
+ int prev_packet_sent_time;
+ int packet_timestamp_start;
+ int packet_timestamp_end;
+ unsigned int packet_nb_payloads;
+ int packet_nb_frames;
+ uint8_t packet_buf[PACKET_SIZE];
+ ByteIOContext pb;
+ /* only for reading */
+ uint64_t data_offset; /* begining of the first data packet */
+ uint64_t data_object_offset; /* data object offset (excl. GUID & size)*/
+ uint64_t data_object_size; /* size of the data object */
+ int index_read;
+
+ ASFMainHeader hdr;
+
+ int packet_flags;
+ int packet_property;
+ int packet_timestamp;
+ int packet_segsizetype;
+ int packet_segments;
+ int packet_seq;
+ int packet_replic_size;
+ int packet_key_frame;
+ int packet_padsize;
+ int packet_frag_offset;
+ int packet_frag_size;
+ int packet_frag_timestamp;
+ int packet_multi_size;
+ int packet_obj_size;
+ int packet_time_delta;
+ int packet_time_start;
+ int64_t packet_pos;
+
+ int stream_index;
+
+
+ int64_t last_indexed_pts;
+ ASFIndex* index_ptr;
+ uint32_t nb_index_count;
+ uint32_t nb_index_memory_alloc;
+ uint16_t maximum_packet;
+
+ ASFStream* asf_st; /* currently decoded stream */
+} ASFContext;
+
+static const GUID asf_header = {
+ 0x75B22630, 0x668E, 0x11CF, { 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C },
+};
+
+static const GUID file_header = {
+ 0x8CABDCA1, 0xA947, 0x11CF, { 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 },
+};
+
+static const GUID stream_header = {
+ 0xB7DC0791, 0xA9B7, 0x11CF, { 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 },
+};
+
+static const GUID ext_stream_header = {
+ 0x14E6A5CB, 0xC672, 0x4332, { 0x83, 0x99, 0xA9, 0x69, 0x52, 0x06, 0x5B, 0x5A },
+};
+
+static const GUID audio_stream = {
+ 0xF8699E40, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
+};
+
+static const GUID audio_conceal_none = {
+ // 0x49f1a440, 0x4ece, 0x11d0, { 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 },
+ // New value lifted from avifile
+ 0x20fb5700, 0x5b55, 0x11cf, { 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b },
+};
+
+static const GUID audio_conceal_spread = {
+ 0xBFC3CD50, 0x618F, 0x11CF, { 0x8B, 0xB2, 0x00, 0xAA, 0x00, 0xB4, 0xE2, 0x20 },
+};
+
+static const GUID video_stream = {
+ 0xBC19EFC0, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
+};
+
+static const GUID video_conceal_none = {
+ 0x20FB5700, 0x5B55, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
+};
+
+static const GUID command_stream = {
+ 0x59DACFC0, 0x59E6, 0x11D0, { 0xA3, 0xAC, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 },
+};
+
+static const GUID comment_header = {
+ 0x75b22633, 0x668e, 0x11cf, { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c },
+};
+
+static const GUID codec_comment_header = {
+ 0x86D15240, 0x311D, 0x11D0, { 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 },
+};
+static const GUID codec_comment1_header = {
+ 0x86d15241, 0x311d, 0x11d0, { 0xa3, 0xa4, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 },
+};
+
+static const GUID data_header = {
+ 0x75b22636, 0x668e, 0x11cf, { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c },
+};
+
+static const GUID head1_guid = {
+ 0x5fbf03b5, 0xa92e, 0x11cf, { 0x8e, 0xe3, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 },
+};
+
+static const GUID head2_guid = {
+ 0xabd3d211, 0xa9ba, 0x11cf, { 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 },
+};
+
+static const GUID extended_content_header = {
+ 0xD2D0A440, 0xE307, 0x11D2, { 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5E, 0xA8, 0x50 },
+};
+
+static const GUID simple_index_header = {
+ 0x33000890, 0xE5B1, 0x11CF, { 0x89, 0xF4, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xCB },
+};
+
+static const GUID ext_stream_embed_stream_header = {
+ 0x3afb65e2, 0x47ef, 0x40f2, { 0xac, 0x2c, 0x70, 0xa9, 0x0d, 0x71, 0xd3, 0x43}
+};
+
+static const GUID ext_stream_audio_stream = {
+ 0x31178c9d, 0x03e1, 0x4528, { 0xb5, 0x82, 0x3d, 0xf9, 0xdb, 0x22, 0xf5, 0x03}
+};
+
+/* I am not a number !!! This GUID is the one found on the PC used to
+ generate the stream */
+static const GUID my_guid = {
+ 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 },
+};
+
+#define ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT 0x80 //1000 0000
+
+
+// ASF data packet structure
+// =========================
+//
+//
+// -----------------------------------
+// | Error Correction Data | Optional
+// -----------------------------------
+// | Payload Parsing Information (PPI) |
+// -----------------------------------
+// | Payload Data |
+// -----------------------------------
+// | Padding Data |
+// -----------------------------------
+
+
+// PPI_FLAG - Payload parsing information flags
+#define ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT 1
+
+#define ASF_PPI_FLAG_SEQUENCE_FIELD_IS_BYTE 0x02 //0000 0010
+#define ASF_PPI_FLAG_SEQUENCE_FIELD_IS_WORD 0x04 //0000 0100
+#define ASF_PPI_FLAG_SEQUENCE_FIELD_IS_DWORD 0x06 //0000 0110
+#define ASF_PPI_MASK_SEQUENCE_FIELD_SIZE 0x06 //0000 0110
+
+#define ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE 0x08 //0000 1000
+#define ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD 0x10 //0001 0000
+#define ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_DWORD 0x18 //0001 1000
+#define ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE 0x18 //0001 1000
+
+#define ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_BYTE 0x20 //0010 0000
+#define ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_WORD 0x40 //0100 0000
+#define ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_DWORD 0x60 //0110 0000
+#define ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE 0x60 //0110 0000
+
+// PL_FLAG - Payload flags
+#define ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE 0x01 //0000 0001
+#define ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_WORD 0x02 //0000 0010
+#define ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_DWORD 0x03 //0000 0011
+#define ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE 0x03 //0000 0011
+
+#define ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_BYTE 0x04 //0000 0100
+#define ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_WORD 0x08 //0000 1000
+#define ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_DWORD 0x0c //0000 1100
+#define ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE 0x0c //0000 1100
+
+#define ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE 0x10 //0001 0000
+#define ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_WORD 0x20 //0010 0000
+#define ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_DWORD 0x30 //0011 0000
+#define ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE 0x30 //0011 0000
+
+#define ASF_PL_FLAG_STREAM_NUMBER_LENGTH_FIELD_IS_BYTE 0x40 //0100 0000
+#define ASF_PL_MASK_STREAM_NUMBER_LENGTH_FIELD_SIZE 0xc0 //1100 0000
+
+#define ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_BYTE 0x40 //0100 0000
+#define ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD 0x80 //1000 0000
+#define ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE 0xc0 //1100 0000
+
+#define ASF_PL_FLAG_KEY_FRAME 0x80 //1000 0000
diff --git a/contrib/ffmpeg/libavformat/au.c b/contrib/ffmpeg/libavformat/au.c
new file mode 100644
index 000000000..27c7cdc85
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/au.c
@@ -0,0 +1,209 @@
+/*
+ * AU muxer and demuxer
+ * 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
+ */
+
+/*
+ * First version by Francois Revol revol@free.fr
+ *
+ * Reference documents:
+ * http://www.opengroup.org/public/pubs/external/auformat.html
+ * http://www.goice.co.jp/member/mo/formats/au.html
+ */
+
+#include "avformat.h"
+#include "allformats.h"
+#include "riff.h"
+
+/* if we don't know the size in advance */
+#define AU_UNKOWN_SIZE ((uint32_t)(~0))
+
+/* The ffmpeg codecs we support, and the IDs they have in the file */
+static const CodecTag codec_au_tags[] = {
+ { CODEC_ID_PCM_MULAW, 1 },
+ { CODEC_ID_PCM_S16BE, 3 },
+ { CODEC_ID_PCM_ALAW, 27 },
+ { 0, 0 },
+};
+
+#ifdef CONFIG_MUXERS
+/* AUDIO_FILE header */
+static int put_au_header(ByteIOContext *pb, AVCodecContext *enc)
+{
+ if(!enc->codec_tag)
+ enc->codec_tag = codec_get_tag(codec_au_tags, enc->codec_id);
+ if(!enc->codec_tag)
+ return -1;
+ put_tag(pb, ".snd"); /* magic number */
+ put_be32(pb, 24); /* header size */
+ put_be32(pb, AU_UNKOWN_SIZE); /* data size */
+ put_be32(pb, (uint32_t)enc->codec_tag); /* codec ID */
+ put_be32(pb, enc->sample_rate);
+ put_be32(pb, (uint32_t)enc->channels);
+ return 0;
+}
+
+static int au_write_header(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+
+ s->priv_data = NULL;
+
+ /* format header */
+ if (put_au_header(pb, s->streams[0]->codec) < 0) {
+ return -1;
+ }
+
+ put_flush_packet(pb);
+
+ return 0;
+}
+
+static int au_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ ByteIOContext *pb = &s->pb;
+ put_buffer(pb, pkt->data, pkt->size);
+ return 0;
+}
+
+static int au_write_trailer(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+ offset_t file_size;
+
+ if (!url_is_streamed(&s->pb)) {
+
+ /* update file size */
+ file_size = url_ftell(pb);
+ url_fseek(pb, 8, SEEK_SET);
+ put_be32(pb, (uint32_t)(file_size - 24));
+ url_fseek(pb, file_size, SEEK_SET);
+
+ put_flush_packet(pb);
+ }
+
+ return 0;
+}
+#endif //CONFIG_MUXERS
+
+static int au_probe(AVProbeData *p)
+{
+ /* check file header */
+ if (p->buf_size <= 24)
+ return 0;
+ if (p->buf[0] == '.' && p->buf[1] == 's' &&
+ p->buf[2] == 'n' && p->buf[3] == 'd')
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+/* au input */
+static int au_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ int size;
+ unsigned int tag;
+ ByteIOContext *pb = &s->pb;
+ unsigned int id, codec, channels, rate;
+ AVStream *st;
+
+ /* check ".snd" header */
+ tag = get_le32(pb);
+ if (tag != MKTAG('.', 's', 'n', 'd'))
+ return -1;
+ size = get_be32(pb); /* header size */
+ get_be32(pb); /* data size */
+
+ id = get_be32(pb);
+ rate = get_be32(pb);
+ channels = get_be32(pb);
+
+ codec = codec_get_id(codec_au_tags, id);
+
+ if (size >= 24) {
+ /* skip unused data */
+ url_fseek(pb, size - 24, SEEK_CUR);
+ }
+
+ /* now we are ready: build format streams */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return -1;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_tag = id;
+ st->codec->codec_id = codec;
+ st->codec->channels = channels;
+ st->codec->sample_rate = rate;
+ av_set_pts_info(st, 64, 1, rate);
+ return 0;
+}
+
+#define MAX_SIZE 4096
+
+static int au_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ int ret;
+
+ if (url_feof(&s->pb))
+ return AVERROR_IO;
+ ret= av_get_packet(&s->pb, pkt, MAX_SIZE);
+ if (ret < 0)
+ return AVERROR_IO;
+ pkt->stream_index = 0;
+
+ /* note: we need to modify the packet size here to handle the last
+ packet */
+ pkt->size = ret;
+ return 0;
+}
+
+static int au_read_close(AVFormatContext *s)
+{
+ return 0;
+}
+
+#ifdef CONFIG_AU_DEMUXER
+AVInputFormat au_demuxer = {
+ "au",
+ "SUN AU Format",
+ 0,
+ au_probe,
+ au_read_header,
+ au_read_packet,
+ au_read_close,
+ pcm_read_seek,
+};
+#endif
+
+#ifdef CONFIG_AU_MUXER
+AVOutputFormat au_muxer = {
+ "au",
+ "SUN AU Format",
+ "audio/basic",
+ "au",
+ 0,
+ CODEC_ID_PCM_S16BE,
+ CODEC_ID_NONE,
+ au_write_header,
+ au_write_packet,
+ au_write_trailer,
+};
+#endif //CONFIG_AU_MUXER
diff --git a/contrib/ffmpeg/libavformat/audio.c b/contrib/ffmpeg/libavformat/audio.c
new file mode 100644
index 000000000..1dfccccb8
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/audio.c
@@ -0,0 +1,352 @@
+/*
+ * Linux audio play and grab interface
+ * 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 "avformat.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef __OpenBSD__
+#include <soundcard.h>
+#else
+#include <sys/soundcard.h>
+#endif
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+
+#define AUDIO_BLOCK_SIZE 4096
+
+typedef struct {
+ int fd;
+ int sample_rate;
+ int channels;
+ int frame_size; /* in bytes ! */
+ int codec_id;
+ int flip_left : 1;
+ uint8_t buffer[AUDIO_BLOCK_SIZE];
+ int buffer_ptr;
+} AudioData;
+
+static int audio_open(AudioData *s, int is_output, const char *audio_device)
+{
+ int audio_fd;
+ int tmp, err;
+ char *flip = getenv("AUDIO_FLIP_LEFT");
+
+ /* open linux audio device */
+ if (!audio_device)
+#ifdef __OpenBSD__
+ audio_device = "/dev/sound";
+#else
+ audio_device = "/dev/dsp";
+#endif
+
+ if (is_output)
+ audio_fd = open(audio_device, O_WRONLY);
+ else
+ audio_fd = open(audio_device, O_RDONLY);
+ if (audio_fd < 0) {
+ perror(audio_device);
+ return AVERROR_IO;
+ }
+
+ if (flip && *flip == '1') {
+ s->flip_left = 1;
+ }
+
+ /* non blocking mode */
+ if (!is_output)
+ fcntl(audio_fd, F_SETFL, O_NONBLOCK);
+
+ s->frame_size = AUDIO_BLOCK_SIZE;
+#if 0
+ tmp = (NB_FRAGMENTS << 16) | FRAGMENT_BITS;
+ err = ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &tmp);
+ if (err < 0) {
+ perror("SNDCTL_DSP_SETFRAGMENT");
+ }
+#endif
+
+ /* select format : favour native format */
+ err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
+
+#ifdef WORDS_BIGENDIAN
+ if (tmp & AFMT_S16_BE) {
+ tmp = AFMT_S16_BE;
+ } else if (tmp & AFMT_S16_LE) {
+ tmp = AFMT_S16_LE;
+ } else {
+ tmp = 0;
+ }
+#else
+ if (tmp & AFMT_S16_LE) {
+ tmp = AFMT_S16_LE;
+ } else if (tmp & AFMT_S16_BE) {
+ tmp = AFMT_S16_BE;
+ } else {
+ tmp = 0;
+ }
+#endif
+
+ switch(tmp) {
+ case AFMT_S16_LE:
+ s->codec_id = CODEC_ID_PCM_S16LE;
+ break;
+ case AFMT_S16_BE:
+ s->codec_id = CODEC_ID_PCM_S16BE;
+ break;
+ default:
+ av_log(NULL, AV_LOG_ERROR, "Soundcard does not support 16 bit sample format\n");
+ close(audio_fd);
+ return AVERROR_IO;
+ }
+ err=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp);
+ if (err < 0) {
+ perror("SNDCTL_DSP_SETFMT");
+ goto fail;
+ }
+
+ tmp = (s->channels == 2);
+ err = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
+ if (err < 0) {
+ perror("SNDCTL_DSP_STEREO");
+ goto fail;
+ }
+ if (tmp)
+ s->channels = 2;
+
+ tmp = s->sample_rate;
+ err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);
+ if (err < 0) {
+ perror("SNDCTL_DSP_SPEED");
+ goto fail;
+ }
+ s->sample_rate = tmp; /* store real sample rate */
+ s->fd = audio_fd;
+
+ return 0;
+ fail:
+ close(audio_fd);
+ return AVERROR_IO;
+}
+
+static int audio_close(AudioData *s)
+{
+ close(s->fd);
+ return 0;
+}
+
+/* sound output support */
+static int audio_write_header(AVFormatContext *s1)
+{
+ AudioData *s = s1->priv_data;
+ AVStream *st;
+ int ret;
+
+ st = s1->streams[0];
+ s->sample_rate = st->codec->sample_rate;
+ s->channels = st->codec->channels;
+ ret = audio_open(s, 1, NULL);
+ if (ret < 0) {
+ return AVERROR_IO;
+ } else {
+ return 0;
+ }
+}
+
+static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt)
+{
+ AudioData *s = s1->priv_data;
+ int len, ret;
+ int size= pkt->size;
+ uint8_t *buf= pkt->data;
+
+ while (size > 0) {
+ len = AUDIO_BLOCK_SIZE - s->buffer_ptr;
+ if (len > size)
+ len = size;
+ memcpy(s->buffer + s->buffer_ptr, buf, len);
+ s->buffer_ptr += len;
+ if (s->buffer_ptr >= AUDIO_BLOCK_SIZE) {
+ for(;;) {
+ ret = write(s->fd, s->buffer, AUDIO_BLOCK_SIZE);
+ if (ret > 0)
+ break;
+ if (ret < 0 && (errno != EAGAIN && errno != EINTR))
+ return AVERROR_IO;
+ }
+ s->buffer_ptr = 0;
+ }
+ buf += len;
+ size -= len;
+ }
+ return 0;
+}
+
+static int audio_write_trailer(AVFormatContext *s1)
+{
+ AudioData *s = s1->priv_data;
+
+ audio_close(s);
+ return 0;
+}
+
+/* grab support */
+
+static int audio_read_header(AVFormatContext *s1, AVFormatParameters *ap)
+{
+ AudioData *s = s1->priv_data;
+ AVStream *st;
+ int ret;
+
+ if (ap->sample_rate <= 0 || ap->channels <= 0)
+ return -1;
+
+ st = av_new_stream(s1, 0);
+ if (!st) {
+ return -ENOMEM;
+ }
+ s->sample_rate = ap->sample_rate;
+ s->channels = ap->channels;
+
+ ret = audio_open(s, 0, ap->device);
+ if (ret < 0) {
+ av_free(st);
+ return AVERROR_IO;
+ }
+
+ /* take real parameters */
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = s->codec_id;
+ st->codec->sample_rate = s->sample_rate;
+ st->codec->channels = s->channels;
+
+ av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
+ return 0;
+}
+
+static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
+{
+ AudioData *s = s1->priv_data;
+ int ret, bdelay;
+ int64_t cur_time;
+ struct audio_buf_info abufi;
+
+ if (av_new_packet(pkt, s->frame_size) < 0)
+ return AVERROR_IO;
+ for(;;) {
+ struct timeval tv;
+ fd_set fds;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 30 * 1000; /* 30 msecs -- a bit shorter than 1 frame at 30fps */
+
+ FD_ZERO(&fds);
+ FD_SET(s->fd, &fds);
+
+ /* This will block until data is available or we get a timeout */
+ (void) select(s->fd + 1, &fds, 0, 0, &tv);
+
+ ret = read(s->fd, pkt->data, pkt->size);
+ if (ret > 0)
+ break;
+ if (ret == -1 && (errno == EAGAIN || errno == EINTR)) {
+ av_free_packet(pkt);
+ pkt->size = 0;
+ pkt->pts = av_gettime();
+ return 0;
+ }
+ if (!(ret == 0 || (ret == -1 && (errno == EAGAIN || errno == EINTR)))) {
+ av_free_packet(pkt);
+ return AVERROR_IO;
+ }
+ }
+ pkt->size = ret;
+
+ /* compute pts of the start of the packet */
+ cur_time = av_gettime();
+ bdelay = ret;
+ if (ioctl(s->fd, SNDCTL_DSP_GETISPACE, &abufi) == 0) {
+ bdelay += abufi.bytes;
+ }
+ /* substract time represented by the number of bytes in the audio fifo */
+ cur_time -= (bdelay * 1000000LL) / (s->sample_rate * s->channels);
+
+ /* convert to wanted units */
+ pkt->pts = cur_time;
+
+ if (s->flip_left && s->channels == 2) {
+ int i;
+ short *p = (short *) pkt->data;
+
+ for (i = 0; i < ret; i += 4) {
+ *p = ~*p;
+ p += 2;
+ }
+ }
+ return 0;
+}
+
+static int audio_read_close(AVFormatContext *s1)
+{
+ AudioData *s = s1->priv_data;
+
+ audio_close(s);
+ return 0;
+}
+
+#ifdef CONFIG_AUDIO_DEMUXER
+AVInputFormat audio_demuxer = {
+ "audio_device",
+ "audio grab and output",
+ sizeof(AudioData),
+ NULL,
+ audio_read_header,
+ audio_read_packet,
+ audio_read_close,
+ .flags = AVFMT_NOFILE,
+};
+#endif
+
+#ifdef CONFIG_AUDIO_MUXER
+AVOutputFormat audio_muxer = {
+ "audio_device",
+ "audio grab and output",
+ "",
+ "",
+ sizeof(AudioData),
+ /* XXX: we make the assumption that the soundcard accepts this format */
+ /* XXX: find better solution with "preinit" method, needed also in
+ other formats */
+#ifdef WORDS_BIGENDIAN
+ CODEC_ID_PCM_S16BE,
+#else
+ CODEC_ID_PCM_S16LE,
+#endif
+ CODEC_ID_NONE,
+ audio_write_header,
+ audio_write_packet,
+ audio_write_trailer,
+ .flags = AVFMT_NOFILE,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/avformat.h b/contrib/ffmpeg/libavformat/avformat.h
new file mode 100644
index 000000000..5dc41d273
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/avformat.h
@@ -0,0 +1,539 @@
+/*
+ * 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 AVFORMAT_H
+#define AVFORMAT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LIBAVFORMAT_VERSION_INT ((51<<16)+(6<<8)+0)
+#define LIBAVFORMAT_VERSION 51.6.0
+#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT
+
+#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION)
+
+#include <time.h>
+#include <stdio.h> /* FILE */
+#include "avcodec.h"
+
+#include "avio.h"
+
+/* packet functions */
+
+#ifndef MAXINT64
+#define MAXINT64 int64_t_C(0x7fffffffffffffff)
+#endif
+
+#ifndef MININT64
+#define MININT64 int64_t_C(0x8000000000000000)
+#endif
+
+typedef struct AVPacket {
+ int64_t pts; ///< presentation time stamp in time_base units
+ int64_t dts; ///< decompression time stamp in time_base units
+ uint8_t *data;
+ int size;
+ int stream_index;
+ int flags;
+ int duration; ///< presentation duration in time_base units (0 if not available)
+ void (*destruct)(struct AVPacket *);
+ void *priv;
+ int64_t pos; ///< byte position in stream, -1 if unknown
+} AVPacket;
+#define PKT_FLAG_KEY 0x0001
+
+void av_destruct_packet_nofree(AVPacket *pkt);
+void av_destruct_packet(AVPacket *pkt);
+
+/* initialize optional fields of a packet */
+static inline void av_init_packet(AVPacket *pkt)
+{
+ pkt->pts = AV_NOPTS_VALUE;
+ pkt->dts = AV_NOPTS_VALUE;
+ pkt->pos = -1;
+ pkt->duration = 0;
+ pkt->flags = 0;
+ pkt->stream_index = 0;
+ pkt->destruct= av_destruct_packet_nofree;
+}
+
+int av_new_packet(AVPacket *pkt, int size);
+int av_get_packet(ByteIOContext *s, AVPacket *pkt, int size);
+int av_dup_packet(AVPacket *pkt);
+
+/**
+ * Free a packet
+ *
+ * @param pkt packet to free
+ */
+static inline void av_free_packet(AVPacket *pkt)
+{
+ if (pkt && pkt->destruct) {
+ pkt->destruct(pkt);
+ }
+}
+
+/*************************************************/
+/* fractional numbers for exact pts handling */
+
+/* the exact value of the fractional number is: 'val + num / den'. num
+ is assumed to be such as 0 <= num < den */
+typedef struct AVFrac {
+ int64_t val, num, den;
+} AVFrac attribute_deprecated;
+
+/*************************************************/
+/* input/output formats */
+
+struct AVFormatContext;
+
+/* this structure contains the data a format has to probe a file */
+typedef struct AVProbeData {
+ const char *filename;
+ unsigned char *buf;
+ int buf_size;
+} AVProbeData;
+
+#define AVPROBE_SCORE_MAX 100 ///< max score, half of that is used for file extension based detection
+
+typedef struct AVFormatParameters {
+ AVRational time_base;
+ int sample_rate;
+ int channels;
+ int width;
+ int height;
+ enum PixelFormat pix_fmt;
+ int channel; /* used to select dv channel */
+ const char *device; /* video, audio or DV device */
+ const char *standard; /* tv standard, NTSC, PAL, SECAM */
+ int mpeg2ts_raw:1; /* force raw MPEG2 transport stream output, if possible */
+ int mpeg2ts_compute_pcr:1; /* compute exact PCR for each transport
+ stream packet (only meaningful if
+ mpeg2ts_raw is TRUE */
+ int initial_pause:1; /* do not begin to play the stream
+ immediately (RTSP only) */
+ int prealloced_context:1;
+ enum CodecID video_codec_id;
+ enum CodecID audio_codec_id;
+} AVFormatParameters;
+
+#define AVFMT_NOFILE 0x0001 /* no file should be opened */
+#define AVFMT_NEEDNUMBER 0x0002 /* needs '%d' in filename */
+#define AVFMT_SHOW_IDS 0x0008 /* show format stream IDs numbers */
+#define AVFMT_RAWPICTURE 0x0020 /* format wants AVPicture structure for
+ raw picture data */
+#define AVFMT_GLOBALHEADER 0x0040 /* format wants global header */
+#define AVFMT_NOTIMESTAMPS 0x0080 /* format doesnt need / has any timestamps */
+
+typedef struct AVOutputFormat {
+ const char *name;
+ const char *long_name;
+ const char *mime_type;
+ const char *extensions; /* comma separated extensions */
+ /* size of private data so that it can be allocated in the wrapper */
+ int priv_data_size;
+ /* output support */
+ enum CodecID audio_codec; /* default audio codec */
+ enum CodecID video_codec; /* default video codec */
+ int (*write_header)(struct AVFormatContext *);
+ int (*write_packet)(struct AVFormatContext *, AVPacket *pkt);
+ int (*write_trailer)(struct AVFormatContext *);
+ /* can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_GLOBALHEADER */
+ int flags;
+ /* currently only used to set pixel format if not YUV420P */
+ int (*set_parameters)(struct AVFormatContext *, AVFormatParameters *);
+ int (*interleave_packet)(struct AVFormatContext *, AVPacket *out, AVPacket *in, int flush);
+ /* private fields */
+ struct AVOutputFormat *next;
+} AVOutputFormat;
+
+typedef struct AVInputFormat {
+ const char *name;
+ const char *long_name;
+ /* size of private data so that it can be allocated in the wrapper */
+ int priv_data_size;
+ /* tell if a given file has a chance of being parsing by this format */
+ int (*read_probe)(AVProbeData *);
+ /* read the format header and initialize the AVFormatContext
+ structure. Return 0 if OK. 'ap' if non NULL contains
+ additionnal paramters. Only used in raw format right
+ now. 'av_new_stream' should be called to create new streams. */
+ int (*read_header)(struct AVFormatContext *,
+ AVFormatParameters *ap);
+ /* read one packet and put it in 'pkt'. pts and flags are also
+ set. 'av_new_stream' can be called only if the flag
+ AVFMTCTX_NOHEADER is used. */
+ int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
+ /* close the stream. The AVFormatContext and AVStreams are not
+ freed by this function */
+ int (*read_close)(struct AVFormatContext *);
+ /**
+ * seek to a given timestamp relative to the frames in
+ * stream component stream_index
+ * @param stream_index must not be -1
+ * @param flags selects which direction should be preferred if no exact
+ * match is available
+ */
+ int (*read_seek)(struct AVFormatContext *,
+ int stream_index, int64_t timestamp, int flags);
+ /**
+ * gets the next timestamp in AV_TIME_BASE units.
+ */
+ int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index,
+ int64_t *pos, int64_t pos_limit);
+ /* can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER */
+ int flags;
+ /* if extensions are defined, then no probe is done. You should
+ usually not use extension format guessing because it is not
+ reliable enough */
+ const char *extensions;
+ /* general purpose read only value that the format can use */
+ int value;
+
+ /* start/resume playing - only meaningful if using a network based format
+ (RTSP) */
+ int (*read_play)(struct AVFormatContext *);
+
+ /* pause playing - only meaningful if using a network based format
+ (RTSP) */
+ int (*read_pause)(struct AVFormatContext *);
+
+ /* private fields */
+ struct AVInputFormat *next;
+} AVInputFormat;
+
+typedef struct AVIndexEntry {
+ int64_t pos;
+ int64_t timestamp;
+#define AVINDEX_KEYFRAME 0x0001
+ int flags:2;
+ int size:30; //yeah trying to keep the size of this small to reduce memory requirements (its 24 vs 32 byte due to possible 8byte align)
+ int min_distance; /* min distance between this and the previous keyframe, used to avoid unneeded searching */
+} AVIndexEntry;
+
+typedef struct AVStream {
+ int index; /* stream index in AVFormatContext */
+ int id; /* format specific stream id */
+ AVCodecContext *codec; /* codec context */
+ /**
+ * real base frame rate of the stream.
+ * this is the lowest framerate with which all timestamps can be
+ * represented accurately (its the least common multiple of all
+ * framerates in the stream), Note, this value is just a guess!
+ * for example if the timebase is 1/90000 and all frames have either
+ * approximately 3600 or 1800 timer ticks then r_frame_rate will be 50/1
+ */
+ AVRational r_frame_rate;
+ void *priv_data;
+ /* internal data used in av_find_stream_info() */
+ int64_t codec_info_duration;
+ int codec_info_nb_frames;
+ /* encoding: PTS generation when outputing stream */
+ AVFrac pts;
+
+ /**
+ * 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.
+ */
+ AVRational time_base;
+ int pts_wrap_bits; /* number of bits in pts (used for wrapping control) */
+ /* ffmpeg.c private use */
+ int stream_copy; /* if TRUE, just copy stream */
+ enum AVDiscard discard; ///< selects which packets can be discarded at will and dont need to be demuxed
+ //FIXME move stuff to a flags field?
+ /* quality, as it has been removed from AVCodecContext and put in AVVideoFrame
+ * MN:dunno if thats the right place, for it */
+ float quality;
+ /* decoding: position of the first frame of the component, in
+ AV_TIME_BASE fractional seconds. */
+ int64_t start_time;
+ /* decoding: duration of the stream, in AV_TIME_BASE fractional
+ seconds. */
+ int64_t duration;
+
+ char language[4]; /* ISO 639 3-letter language code (empty string if undefined) */
+
+ /* av_read_frame() support */
+ int need_parsing; ///< 1->full parsing needed, 2->only parse headers dont repack
+ struct AVCodecParserContext *parser;
+
+ int64_t cur_dts;
+ int last_IP_duration;
+ int64_t last_IP_pts;
+ /* av_seek_frame() support */
+ AVIndexEntry *index_entries; /* only used if the format does not
+ support seeking natively */
+ int nb_index_entries;
+ unsigned int index_entries_allocated_size;
+
+ int64_t nb_frames; ///< number of frames in this stream if known or 0
+
+#define MAX_REORDER_DELAY 4
+ int64_t pts_buffer[MAX_REORDER_DELAY+1];
+} AVStream;
+
+#define AVFMTCTX_NOHEADER 0x0001 /* signal that no header is present
+ (streams are added dynamically) */
+
+#define MAX_STREAMS 20
+
+/* format I/O context */
+typedef struct AVFormatContext {
+ const AVClass *av_class; /* set by av_alloc_format_context */
+ /* can only be iformat or oformat, not both at the same time */
+ struct AVInputFormat *iformat;
+ struct AVOutputFormat *oformat;
+ void *priv_data;
+ ByteIOContext pb;
+ int nb_streams;
+ AVStream *streams[MAX_STREAMS];
+ char filename[1024]; /* input or output filename */
+ /* stream info */
+ int64_t timestamp;
+ char title[512];
+ char author[512];
+ char copyright[512];
+ char comment[512];
+ char album[512];
+ int year; /* ID3 year, 0 if none */
+ int track; /* track number, 0 if none */
+ char genre[32]; /* ID3 genre */
+
+ int ctx_flags; /* format specific flags, see AVFMTCTX_xx */
+ /* private data for pts handling (do not modify directly) */
+ /* This buffer is only needed when packets were already buffered but
+ not decoded, for example to get the codec parameters in mpeg
+ streams */
+ struct AVPacketList *packet_buffer;
+
+ /* decoding: position of the first frame of the component, in
+ AV_TIME_BASE fractional seconds. NEVER set this value directly:
+ it is deduced from the AVStream values. */
+ int64_t start_time;
+ /* decoding: duration of the stream, in AV_TIME_BASE fractional
+ seconds. NEVER set this value directly: it is deduced from the
+ AVStream values. */
+ int64_t duration;
+ /* decoding: total file size. 0 if unknown */
+ int64_t file_size;
+ /* decoding: total stream bitrate in bit/s, 0 if not
+ available. Never set it directly if the file_size and the
+ duration are known as ffmpeg can compute it automatically. */
+ int bit_rate;
+
+ /* av_read_frame() support */
+ AVStream *cur_st;
+ const uint8_t *cur_ptr;
+ int cur_len;
+ AVPacket cur_pkt;
+
+ /* av_seek_frame() support */
+ int64_t data_offset; /* offset of the first packet */
+ int index_built;
+
+ int mux_rate;
+ int packet_size;
+ int preload;
+ int max_delay;
+
+#define AVFMT_NOOUTPUTLOOP -1
+#define AVFMT_INFINITEOUTPUTLOOP 0
+ /* number of times to loop output in formats that support it */
+ int loop_output;
+
+ int flags;
+#define AVFMT_FLAG_GENPTS 0x0001 ///< generate pts if missing even if it requires parsing future frames
+#define AVFMT_FLAG_IGNIDX 0x0002 ///< ignore index
+
+ int loop_input;
+ /* decoding: size of data to probe; encoding unused */
+ unsigned int probesize;
+} AVFormatContext;
+
+typedef struct AVPacketList {
+ AVPacket pkt;
+ struct AVPacketList *next;
+} AVPacketList;
+
+extern AVInputFormat *first_iformat;
+extern AVOutputFormat *first_oformat;
+
+enum CodecID av_guess_image2_codec(const char *filename);
+
+/* XXX: use automatic init with either ELF sections or C file parser */
+/* modules */
+
+#include "rtp.h"
+
+#include "rtsp.h"
+
+/* utils.c */
+void av_register_input_format(AVInputFormat *format);
+void av_register_output_format(AVOutputFormat *format);
+AVOutputFormat *guess_stream_format(const char *short_name,
+ const char *filename, const char *mime_type);
+AVOutputFormat *guess_format(const char *short_name,
+ const char *filename, const char *mime_type);
+enum CodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name,
+ const char *filename, const char *mime_type, enum CodecType type);
+
+void av_hex_dump(FILE *f, uint8_t *buf, int size);
+void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload);
+
+void av_register_all(void);
+
+/* media file input */
+AVInputFormat *av_find_input_format(const char *short_name);
+AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened);
+int av_open_input_stream(AVFormatContext **ic_ptr,
+ ByteIOContext *pb, const char *filename,
+ AVInputFormat *fmt, AVFormatParameters *ap);
+int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
+ AVInputFormat *fmt,
+ int buf_size,
+ AVFormatParameters *ap);
+/* no av_open for output, so applications will need this: */
+AVFormatContext *av_alloc_format_context(void);
+
+#define AVERROR_UNKNOWN (-1) /* unknown error */
+#define AVERROR_IO (-2) /* i/o error */
+#define AVERROR_NUMEXPECTED (-3) /* number syntax expected in filename */
+#define AVERROR_INVALIDDATA (-4) /* invalid data found */
+#define AVERROR_NOMEM (-5) /* not enough memory */
+#define AVERROR_NOFMT (-6) /* unknown format */
+#define AVERROR_NOTSUPP (-7) /* operation not supported */
+
+int av_find_stream_info(AVFormatContext *ic);
+int av_read_packet(AVFormatContext *s, AVPacket *pkt);
+int av_read_frame(AVFormatContext *s, AVPacket *pkt);
+int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags);
+int av_read_play(AVFormatContext *s);
+int av_read_pause(AVFormatContext *s);
+void av_close_input_file(AVFormatContext *s);
+AVStream *av_new_stream(AVFormatContext *s, int id);
+void av_set_pts_info(AVStream *s, int pts_wrap_bits,
+ int pts_num, int pts_den);
+
+#define AVSEEK_FLAG_BACKWARD 1 ///< seek backward
+#define AVSEEK_FLAG_BYTE 2 ///< seeking based on position in bytes
+#define AVSEEK_FLAG_ANY 4 ///< seek to any frame, even non keyframes
+
+int av_find_default_stream_index(AVFormatContext *s);
+int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags);
+int av_add_index_entry(AVStream *st,
+ int64_t pos, int64_t timestamp, int size, int distance, int flags);
+int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags);
+void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp);
+int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, int64_t pos_min, int64_t pos_max, int64_t pos_limit, int64_t ts_min, int64_t ts_max, int flags, int64_t *ts_ret, int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t ));
+
+/* media file output */
+int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap);
+int av_write_header(AVFormatContext *s);
+int av_write_frame(AVFormatContext *s, AVPacket *pkt);
+int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt);
+int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush);
+
+int av_write_trailer(AVFormatContext *s);
+
+void dump_format(AVFormatContext *ic,
+ int index,
+ const char *url,
+ int is_output);
+int parse_image_size(int *width_ptr, int *height_ptr, const char *str);
+int parse_frame_rate(int *frame_rate, int *frame_rate_base, const char *arg);
+int64_t parse_date(const char *datestr, int duration);
+
+int64_t av_gettime(void);
+
+/* ffm specific for ffserver */
+#define FFM_PACKET_SIZE 4096
+offset_t ffm_read_write_index(int fd);
+void ffm_write_write_index(int fd, offset_t pos);
+void ffm_set_write_index(AVFormatContext *s, offset_t pos, offset_t file_size);
+
+int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info);
+
+int av_get_frame_filename(char *buf, int buf_size,
+ const char *path, int number);
+int av_filename_number_test(const char *filename);
+
+/* grab specific */
+int video_grab_init(void);
+int audio_init(void);
+
+/* DV1394 */
+int dv1394_init(void);
+int dc1394_init(void);
+
+#ifdef HAVE_AV_CONFIG_H
+
+#include "os_support.h"
+
+int strstart(const char *str, const char *val, const char **ptr);
+int stristart(const char *str, const char *val, const char **ptr);
+void pstrcpy(char *buf, int buf_size, const char *str);
+char *pstrcat(char *buf, int buf_size, const char *s);
+
+void __dynarray_add(unsigned long **tab_ptr, int *nb_ptr, unsigned long elem);
+
+#ifdef __GNUC__
+#define dynarray_add(tab, nb_ptr, elem)\
+do {\
+ typeof(tab) _tab = (tab);\
+ typeof(elem) _elem = (elem);\
+ (void)sizeof(**_tab == _elem); /* check that types are compatible */\
+ __dynarray_add((unsigned long **)_tab, nb_ptr, (unsigned long)_elem);\
+} while(0)
+#else
+#define dynarray_add(tab, nb_ptr, elem)\
+do {\
+ __dynarray_add((unsigned long **)(tab), nb_ptr, (unsigned long)(elem));\
+} while(0)
+#endif
+
+time_t mktimegm(struct tm *tm);
+struct tm *brktimegm(time_t secs, struct tm *tm);
+const char *small_strptime(const char *p, const char *fmt,
+ struct tm *dt);
+
+struct in_addr;
+int resolve_host(struct in_addr *sin_addr, const char *hostname);
+
+void url_split(char *proto, int proto_size,
+ char *authorization, int authorization_size,
+ char *hostname, int hostname_size,
+ int *port_ptr,
+ char *path, int path_size,
+ const char *url);
+
+int match_ext(const char *filename, const char *extensions);
+
+#endif /* HAVE_AV_CONFIG_H */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVFORMAT_H */
+
diff --git a/contrib/ffmpeg/libavformat/avi.h b/contrib/ffmpeg/libavformat/avi.h
new file mode 100644
index 000000000..2c360689b
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/avi.h
@@ -0,0 +1,39 @@
+/*
+ * 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 FFMPEG_AVI_H
+#define FFMPEG_AVI_H
+
+#include "avcodec.h"
+
+#define AVIF_HASINDEX 0x00000010 // Index at end of file?
+#define AVIF_MUSTUSEINDEX 0x00000020
+#define AVIF_ISINTERLEAVED 0x00000100
+#define AVIF_TRUSTCKTYPE 0x00000800 // Use CKType to find key frames?
+#define AVIF_WASCAPTUREFILE 0x00010000
+#define AVIF_COPYRIGHTED 0x00020000
+
+#define AVI_MAX_RIFF_SIZE 0x40000000LL
+#define AVI_MASTER_INDEX_SIZE 256
+
+/* index flags */
+#define AVIIF_INDEX 0x10
+
+#endif /* FFMPEG_AVI_H */
diff --git a/contrib/ffmpeg/libavformat/avidec.c b/contrib/ffmpeg/libavformat/avidec.c
new file mode 100644
index 000000000..d1af79fa3
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/avidec.c
@@ -0,0 +1,989 @@
+/*
+ * AVI demuxer
+ * 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
+ */
+#include "avformat.h"
+#include "avi.h"
+#include "dv.h"
+#include "riff.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+//#define DEBUG
+//#define DEBUG_SEEK
+
+typedef struct AVIStream {
+ int64_t frame_offset; /* current frame (video) or byte (audio) counter
+ (used to compute the pts) */
+ int remaining;
+ int packet_size;
+
+ int scale;
+ int rate;
+ int sample_size; /* size of one sample (or packet) (in the rate/scale sense) in bytes */
+
+ int64_t cum_len; /* temporary storage (used during seek) */
+
+ int prefix; ///< normally 'd'<<8 + 'c' or 'w'<<8 + 'b'
+ int prefix_count;
+} AVIStream;
+
+typedef struct {
+ int64_t riff_end;
+ int64_t movi_end;
+ offset_t movi_list;
+ int index_loaded;
+ int is_odml;
+ int non_interleaved;
+ int stream_index;
+ DVDemuxContext* dv_demux;
+} AVIContext;
+
+static int avi_load_index(AVFormatContext *s);
+static int guess_ni_flag(AVFormatContext *s);
+
+#ifdef DEBUG
+static void print_tag(const char *str, unsigned int tag, int size)
+{
+ printf("%s: tag=%c%c%c%c size=0x%x\n",
+ str, tag & 0xff,
+ (tag >> 8) & 0xff,
+ (tag >> 16) & 0xff,
+ (tag >> 24) & 0xff,
+ size);
+}
+#endif
+
+static int get_riff(AVIContext *avi, ByteIOContext *pb)
+{
+ uint32_t tag;
+ /* check RIFF header */
+ tag = get_le32(pb);
+
+ if (tag != MKTAG('R', 'I', 'F', 'F'))
+ return -1;
+ avi->riff_end = get_le32(pb); /* RIFF chunk size */
+ avi->riff_end += url_ftell(pb); /* RIFF chunk end */
+ tag = get_le32(pb);
+ if (tag != MKTAG('A', 'V', 'I', ' ') && tag != MKTAG('A', 'V', 'I', 'X'))
+ return -1;
+
+ return 0;
+}
+
+static int read_braindead_odml_indx(AVFormatContext *s, int frame_num){
+ AVIContext *avi = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int longs_pre_entry= get_le16(pb);
+ int index_sub_type = get_byte(pb);
+ int index_type = get_byte(pb);
+ int entries_in_use = get_le32(pb);
+ int chunk_id = get_le32(pb);
+ int64_t base = get_le64(pb);
+ int stream_id= 10*((chunk_id&0xFF) - '0') + (((chunk_id>>8)&0xFF) - '0');
+ AVStream *st;
+ AVIStream *ast;
+ int i;
+ int64_t last_pos= -1;
+ int64_t filesize= url_fsize(&s->pb);
+
+#ifdef DEBUG_SEEK
+ av_log(s, AV_LOG_ERROR, "longs_pre_entry:%d index_type:%d entries_in_use:%d chunk_id:%X base:%16"PRIX64"\n",
+ longs_pre_entry,index_type, entries_in_use, chunk_id, base);
+#endif
+
+ if(stream_id > s->nb_streams || stream_id < 0)
+ return -1;
+ st= s->streams[stream_id];
+ ast = st->priv_data;
+
+ if(index_sub_type)
+ return -1;
+
+ get_le32(pb);
+
+ if(index_type && longs_pre_entry != 2)
+ return -1;
+ if(index_type>1)
+ return -1;
+
+ if(filesize > 0 && base >= filesize){
+ av_log(s, AV_LOG_ERROR, "ODML index invalid\n");
+ if(base>>32 == (base & 0xFFFFFFFF) && (base & 0xFFFFFFFF) < filesize && filesize <= 0xFFFFFFFF)
+ base &= 0xFFFFFFFF;
+ else
+ return -1;
+ }
+
+ for(i=0; i<entries_in_use; i++){
+ if(index_type){
+ int64_t pos= get_le32(pb) + base - 8;
+ int len = get_le32(pb);
+ int key= len >= 0;
+ len &= 0x7FFFFFFF;
+
+#ifdef DEBUG_SEEK
+ av_log(s, AV_LOG_ERROR, "pos:%"PRId64", len:%X\n", pos, len);
+#endif
+ if(last_pos == pos || pos == base - 8)
+ avi->non_interleaved= 1;
+ else
+ av_add_index_entry(st, pos, ast->cum_len / FFMAX(1, ast->sample_size), len, 0, key ? AVINDEX_KEYFRAME : 0);
+
+ if(ast->sample_size)
+ ast->cum_len += len;
+ else
+ ast->cum_len ++;
+ last_pos= pos;
+ }else{
+ int64_t offset, pos;
+ int duration;
+ offset = get_le64(pb);
+ get_le32(pb); /* size */
+ duration = get_le32(pb);
+ pos = url_ftell(pb);
+
+ url_fseek(pb, offset+8, SEEK_SET);
+ read_braindead_odml_indx(s, frame_num);
+ frame_num += duration;
+
+ url_fseek(pb, pos, SEEK_SET);
+ }
+ }
+ avi->index_loaded=1;
+ return 0;
+}
+
+static void clean_index(AVFormatContext *s){
+ int i;
+ int64_t j;
+
+ for(i=0; i<s->nb_streams; i++){
+ AVStream *st = s->streams[i];
+ AVIStream *ast = st->priv_data;
+ int n= st->nb_index_entries;
+ int max= ast->sample_size;
+ int64_t pos, size, ts;
+
+ if(n != 1 || ast->sample_size==0)
+ continue;
+
+ while(max < 1024) max+=max;
+
+ pos= st->index_entries[0].pos;
+ size= st->index_entries[0].size;
+ ts= st->index_entries[0].timestamp;
+
+ for(j=0; j<size; j+=max){
+ av_add_index_entry(st, pos+j, ts + j/ast->sample_size, FFMIN(max, size-j), 0, AVINDEX_KEYFRAME);
+ }
+ }
+}
+
+static int avi_read_tag(ByteIOContext *pb, char *buf, int maxlen, unsigned int size)
+{
+ offset_t i = url_ftell(pb);
+ size += (size & 1);
+ get_strz(pb, buf, maxlen);
+ url_fseek(pb, i+size, SEEK_SET);
+ return 0;
+}
+
+static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ AVIContext *avi = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ uint32_t tag, tag1, handler;
+ int codec_type, stream_index, frame_period, bit_rate;
+ unsigned int size, nb_frames;
+ int i, n;
+ AVStream *st;
+ AVIStream *ast = NULL;
+ char str_track[4];
+
+ avi->stream_index= -1;
+
+ if (get_riff(avi, pb) < 0)
+ return -1;
+
+ /* first list tag */
+ stream_index = -1;
+ codec_type = -1;
+ frame_period = 0;
+ for(;;) {
+ if (url_feof(pb))
+ goto fail;
+ tag = get_le32(pb);
+ size = get_le32(pb);
+#ifdef DEBUG
+ print_tag("tag", tag, size);
+#endif
+
+ switch(tag) {
+ case MKTAG('L', 'I', 'S', 'T'):
+ /* ignored, except when start of video packets */
+ tag1 = get_le32(pb);
+#ifdef DEBUG
+ print_tag("list", tag1, 0);
+#endif
+ if (tag1 == MKTAG('m', 'o', 'v', 'i')) {
+ avi->movi_list = url_ftell(pb) - 4;
+ if(size) avi->movi_end = avi->movi_list + size + (size & 1);
+ else avi->movi_end = url_fsize(pb);
+#ifdef DEBUG
+ printf("movi end=%"PRIx64"\n", avi->movi_end);
+#endif
+ goto end_of_header;
+ }
+ break;
+ case MKTAG('d', 'm', 'l', 'h'):
+ avi->is_odml = 1;
+ url_fskip(pb, size + (size & 1));
+ break;
+ case MKTAG('a', 'v', 'i', 'h'):
+ /* avi header */
+ /* using frame_period is bad idea */
+ frame_period = get_le32(pb);
+ bit_rate = get_le32(pb) * 8;
+ get_le32(pb);
+ avi->non_interleaved |= get_le32(pb) & AVIF_MUSTUSEINDEX;
+
+ url_fskip(pb, 2 * 4);
+ n = get_le32(pb);
+ for(i=0;i<n;i++) {
+ AVIStream *ast;
+ st = av_new_stream(s, i);
+ if (!st)
+ goto fail;
+
+ ast = av_mallocz(sizeof(AVIStream));
+ if (!ast)
+ goto fail;
+ st->priv_data = ast;
+ }
+ url_fskip(pb, size - 7 * 4);
+ break;
+ case MKTAG('s', 't', 'r', 'h'):
+ /* stream header */
+ stream_index++;
+ tag1 = get_le32(pb);
+ handler = get_le32(pb); /* codec tag */
+#ifdef DEBUG
+ print_tag("strh", tag1, -1);
+#endif
+ if(tag1 == MKTAG('i', 'a', 'v', 's') || tag1 == MKTAG('i', 'v', 'a', 's')){
+ /*
+ * After some consideration -- I don't think we
+ * have to support anything but DV in a type1 AVIs.
+ */
+ if (s->nb_streams != 1)
+ goto fail;
+
+ if (handler != MKTAG('d', 'v', 's', 'd') &&
+ handler != MKTAG('d', 'v', 'h', 'd') &&
+ handler != MKTAG('d', 'v', 's', 'l'))
+ goto fail;
+
+ ast = s->streams[0]->priv_data;
+ av_freep(&s->streams[0]->codec->extradata);
+ av_freep(&s->streams[0]);
+ s->nb_streams = 0;
+ if (ENABLE_DV_DEMUXER) {
+ avi->dv_demux = dv_init_demux(s);
+ if (!avi->dv_demux)
+ goto fail;
+ }
+ s->streams[0]->priv_data = ast;
+ url_fskip(pb, 3 * 4);
+ ast->scale = get_le32(pb);
+ ast->rate = get_le32(pb);
+ stream_index = s->nb_streams - 1;
+ url_fskip(pb, size - 7*4);
+ break;
+ }
+
+ if (stream_index >= s->nb_streams) {
+ url_fskip(pb, size - 8);
+ /* ignore padding stream */
+ if (tag1 == MKTAG('p', 'a', 'd', 's'))
+ stream_index--;
+ break;
+ }
+ st = s->streams[stream_index];
+ ast = st->priv_data;
+ st->codec->stream_codec_tag= handler;
+
+ get_le32(pb); /* flags */
+ get_le16(pb); /* priority */
+ get_le16(pb); /* language */
+ get_le32(pb); /* initial frame */
+ ast->scale = get_le32(pb);
+ ast->rate = get_le32(pb);
+ if(ast->scale && ast->rate){
+ }else if(frame_period){
+ ast->rate = 1000000;
+ ast->scale = frame_period;
+ }else{
+ ast->rate = 25;
+ ast->scale = 1;
+ }
+ av_set_pts_info(st, 64, ast->scale, ast->rate);
+
+ ast->cum_len=get_le32(pb); /* start */
+ nb_frames = get_le32(pb);
+
+ st->start_time = 0;
+ st->duration = nb_frames;
+ get_le32(pb); /* buffer size */
+ get_le32(pb); /* quality */
+ ast->sample_size = get_le32(pb); /* sample ssize */
+ ast->cum_len *= FFMAX(1, ast->sample_size);
+// av_log(NULL, AV_LOG_DEBUG, "%d %d %d %d\n", ast->rate, ast->scale, ast->start, ast->sample_size);
+
+ switch(tag1) {
+ case MKTAG('v', 'i', 'd', 's'):
+ codec_type = CODEC_TYPE_VIDEO;
+
+ ast->sample_size = 0;
+ break;
+ case MKTAG('a', 'u', 'd', 's'):
+ codec_type = CODEC_TYPE_AUDIO;
+ break;
+ case MKTAG('t', 'x', 't', 's'):
+ //FIXME
+ codec_type = CODEC_TYPE_DATA; //CODEC_TYPE_SUB ? FIXME
+ break;
+ case MKTAG('p', 'a', 'd', 's'):
+ codec_type = CODEC_TYPE_UNKNOWN;
+ stream_index--;
+ break;
+ default:
+ av_log(s, AV_LOG_ERROR, "unknown stream type %X\n", tag1);
+ goto fail;
+ }
+ ast->frame_offset= ast->cum_len;
+ url_fskip(pb, size - 12 * 4);
+ break;
+ case MKTAG('s', 't', 'r', 'f'):
+ /* stream header */
+ if (stream_index >= s->nb_streams || avi->dv_demux) {
+ url_fskip(pb, size);
+ } else {
+ st = s->streams[stream_index];
+ switch(codec_type) {
+ case CODEC_TYPE_VIDEO:
+ get_le32(pb); /* size */
+ st->codec->width = get_le32(pb);
+ st->codec->height = get_le32(pb);
+ get_le16(pb); /* panes */
+ st->codec->bits_per_sample= get_le16(pb); /* depth */
+ tag1 = get_le32(pb);
+ get_le32(pb); /* ImageSize */
+ get_le32(pb); /* XPelsPerMeter */
+ get_le32(pb); /* YPelsPerMeter */
+ get_le32(pb); /* ClrUsed */
+ get_le32(pb); /* ClrImportant */
+
+ if(size > 10*4 && size<(1<<30)){
+ st->codec->extradata_size= size - 10*4;
+ st->codec->extradata= av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
+ }
+
+ if(st->codec->extradata_size & 1) //FIXME check if the encoder really did this correctly
+ get_byte(pb);
+
+ /* Extract palette from extradata if bpp <= 8 */
+ /* This code assumes that extradata contains only palette */
+ /* This is true for all paletted codecs implemented in ffmpeg */
+ if (st->codec->extradata_size && (st->codec->bits_per_sample <= 8)) {
+ st->codec->palctrl = av_mallocz(sizeof(AVPaletteControl));
+#ifdef WORDS_BIGENDIAN
+ for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)/4; i++)
+ st->codec->palctrl->palette[i] = bswap_32(((uint32_t*)st->codec->extradata)[i]);
+#else
+ memcpy(st->codec->palctrl->palette, st->codec->extradata,
+ FFMIN(st->codec->extradata_size, AVPALETTE_SIZE));
+#endif
+ st->codec->palctrl->palette_changed = 1;
+ }
+
+#ifdef DEBUG
+ print_tag("video", tag1, 0);
+#endif
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_tag = tag1;
+ st->codec->codec_id = codec_get_id(codec_bmp_tags, tag1);
+ st->need_parsing = 2; //only parse headers dont do slower repacketization, this is needed to get the pict type which is needed for generating correct pts
+// url_fskip(pb, size - 5 * 4);
+ break;
+ case CODEC_TYPE_AUDIO:
+ get_wav_header(pb, st->codec, size);
+ if(ast->sample_size && st->codec->block_align && ast->sample_size % st->codec->block_align)
+ av_log(s, AV_LOG_DEBUG, "invalid sample size or block align detected\n");
+ if (size%2) /* 2-aligned (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) */
+ url_fskip(pb, 1);
+ /* Force parsing as several audio frames can be in
+ * one packet. */
+ st->need_parsing = 1;
+ /* ADTS header is in extradata, AAC without header must be stored as exact frames, parser not needed and it will fail */
+ if (st->codec->codec_id == CODEC_ID_AAC && st->codec->extradata_size)
+ st->need_parsing = 0;
+ /* AVI files with Xan DPCM audio (wrongly) declare PCM
+ * audio in the header but have Axan as stream_code_tag. */
+ if (st->codec->stream_codec_tag == ff_get_fourcc("Axan")){
+ st->codec->codec_id = CODEC_ID_XAN_DPCM;
+ st->codec->codec_tag = 0;
+ }
+ break;
+ default:
+ st->codec->codec_type = CODEC_TYPE_DATA;
+ st->codec->codec_id= CODEC_ID_NONE;
+ st->codec->codec_tag= 0;
+ url_fskip(pb, size);
+ break;
+ }
+ }
+ break;
+ case MKTAG('i', 'n', 'd', 'x'):
+ i= url_ftell(pb);
+ if(!url_is_streamed(pb) && !(s->flags & AVFMT_FLAG_IGNIDX)){
+ read_braindead_odml_indx(s, 0);
+ }
+ url_fseek(pb, i+size, SEEK_SET);
+ break;
+ case MKTAG('I', 'N', 'A', 'M'):
+ avi_read_tag(pb, s->title, sizeof(s->title), size);
+ break;
+ case MKTAG('I', 'A', 'R', 'T'):
+ avi_read_tag(pb, s->author, sizeof(s->author), size);
+ break;
+ case MKTAG('I', 'C', 'O', 'P'):
+ avi_read_tag(pb, s->copyright, sizeof(s->copyright), size);
+ break;
+ case MKTAG('I', 'C', 'M', 'T'):
+ avi_read_tag(pb, s->comment, sizeof(s->comment), size);
+ break;
+ case MKTAG('I', 'G', 'N', 'R'):
+ avi_read_tag(pb, s->genre, sizeof(s->genre), size);
+ break;
+ case MKTAG('I', 'P', 'R', 'D'):
+ avi_read_tag(pb, s->album, sizeof(s->album), size);
+ break;
+ case MKTAG('I', 'P', 'R', 'T'):
+ avi_read_tag(pb, str_track, sizeof(str_track), size);
+ sscanf(str_track, "%d", &s->track);
+ break;
+ default:
+ /* skip tag */
+ size += (size & 1);
+ url_fskip(pb, size);
+ break;
+ }
+ }
+ end_of_header:
+ /* check stream number */
+ if (stream_index != s->nb_streams - 1) {
+ fail:
+ for(i=0;i<s->nb_streams;i++) {
+ av_freep(&s->streams[i]->codec->extradata);
+ av_freep(&s->streams[i]);
+ }
+ return -1;
+ }
+
+ if(!avi->index_loaded && !url_is_streamed(pb))
+ avi_load_index(s);
+ avi->index_loaded = 1;
+ avi->non_interleaved |= guess_ni_flag(s);
+ if(avi->non_interleaved)
+ clean_index(s);
+
+ return 0;
+}
+
+static int avi_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ AVIContext *avi = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int n, d[8], size;
+ offset_t i, sync;
+ void* dstr;
+
+ if (ENABLE_DV_DEMUXER && avi->dv_demux) {
+ size = dv_get_packet(avi->dv_demux, pkt);
+ if (size >= 0)
+ return size;
+ }
+
+ if(avi->non_interleaved){
+ int best_stream_index = 0;
+ AVStream *best_st= NULL;
+ AVIStream *best_ast;
+ int64_t best_ts= INT64_MAX;
+ int i;
+
+ for(i=0; i<s->nb_streams; i++){
+ AVStream *st = s->streams[i];
+ AVIStream *ast = st->priv_data;
+ int64_t ts= ast->frame_offset;
+
+ if(ast->sample_size)
+ ts /= ast->sample_size;
+ ts= av_rescale(ts, AV_TIME_BASE * (int64_t)st->time_base.num, st->time_base.den);
+
+// av_log(NULL, AV_LOG_DEBUG, "%"PRId64" %d/%d %"PRId64"\n", ts, st->time_base.num, st->time_base.den, ast->frame_offset);
+ if(ts < best_ts){
+ best_ts= ts;
+ best_st= st;
+ best_stream_index= i;
+ }
+ }
+ best_ast = best_st->priv_data;
+ best_ts= av_rescale(best_ts, best_st->time_base.den, AV_TIME_BASE * (int64_t)best_st->time_base.num); //FIXME a little ugly
+ if(best_ast->remaining)
+ i= av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
+ else
+ i= av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY);
+
+// av_log(NULL, AV_LOG_DEBUG, "%d\n", i);
+ if(i>=0){
+ int64_t pos= best_st->index_entries[i].pos;
+ pos += best_ast->packet_size - best_ast->remaining;
+ url_fseek(&s->pb, pos + 8, SEEK_SET);
+// av_log(NULL, AV_LOG_DEBUG, "pos=%"PRId64"\n", pos);
+
+ assert(best_ast->remaining <= best_ast->packet_size);
+
+ avi->stream_index= best_stream_index;
+ if(!best_ast->remaining)
+ best_ast->packet_size=
+ best_ast->remaining= best_st->index_entries[i].size;
+ }
+ }
+
+resync:
+ if(avi->stream_index >= 0){
+ AVStream *st= s->streams[ avi->stream_index ];
+ AVIStream *ast= st->priv_data;
+ int size;
+
+ if(ast->sample_size <= 1) // minorityreport.AVI block_align=1024 sample_size=1 IMA-ADPCM
+ size= INT_MAX;
+ else if(ast->sample_size < 32)
+ size= 64*ast->sample_size;
+ else
+ size= ast->sample_size;
+
+ if(size > ast->remaining)
+ size= ast->remaining;
+ av_get_packet(pb, pkt, size);
+
+ if (ENABLE_DV_DEMUXER && avi->dv_demux) {
+ dstr = pkt->destruct;
+ size = dv_produce_packet(avi->dv_demux, pkt,
+ pkt->data, pkt->size);
+ pkt->destruct = dstr;
+ pkt->flags |= PKT_FLAG_KEY;
+ } else {
+ /* XXX: how to handle B frames in avi ? */
+ pkt->dts = ast->frame_offset;
+// pkt->dts += ast->start;
+ if(ast->sample_size)
+ pkt->dts /= ast->sample_size;
+//av_log(NULL, AV_LOG_DEBUG, "dts:%"PRId64" offset:%"PRId64" %d/%d smpl_siz:%d base:%d st:%d size:%d\n", pkt->dts, ast->frame_offset, ast->scale, ast->rate, ast->sample_size, AV_TIME_BASE, avi->stream_index, size);
+ pkt->stream_index = avi->stream_index;
+
+ if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ if(st->index_entries){
+ AVIndexEntry *e;
+ int index;
+
+ index= av_index_search_timestamp(st, pkt->dts, 0);
+ e= &st->index_entries[index];
+
+ if(index >= 0 && e->timestamp == ast->frame_offset){
+ if (e->flags & AVINDEX_KEYFRAME)
+ pkt->flags |= PKT_FLAG_KEY;
+ }
+ } else {
+ /* if no index, better to say that all frames
+ are key frames */
+ pkt->flags |= PKT_FLAG_KEY;
+ }
+ } else {
+ pkt->flags |= PKT_FLAG_KEY;
+ }
+ if(ast->sample_size)
+ ast->frame_offset += pkt->size;
+ else
+ ast->frame_offset++;
+ }
+ ast->remaining -= size;
+ if(!ast->remaining){
+ avi->stream_index= -1;
+ ast->packet_size= 0;
+ if (size & 1) {
+ get_byte(pb);
+ size++;
+ }
+ }
+
+ return size;
+ }
+
+ memset(d, -1, sizeof(int)*8);
+ for(i=sync=url_ftell(pb); !url_feof(pb); i++) {
+ int j;
+
+ if (i >= avi->movi_end) {
+ if (avi->is_odml) {
+ url_fskip(pb, avi->riff_end - i);
+ avi->riff_end = avi->movi_end = url_fsize(pb);
+ } else
+ break;
+ }
+
+ for(j=0; j<7; j++)
+ d[j]= d[j+1];
+ d[7]= get_byte(pb);
+
+ size= d[4] + (d[5]<<8) + (d[6]<<16) + (d[7]<<24);
+
+ if( d[2] >= '0' && d[2] <= '9'
+ && d[3] >= '0' && d[3] <= '9'){
+ n= (d[2] - '0') * 10 + (d[3] - '0');
+ }else{
+ n= 100; //invalid stream id
+ }
+//av_log(NULL, AV_LOG_DEBUG, "%X %X %X %X %X %X %X %X %"PRId64" %d %d\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], i, size, n);
+ if(i + size > avi->movi_end || d[0]<0)
+ continue;
+
+ //parse ix##
+ if( (d[0] == 'i' && d[1] == 'x' && n < s->nb_streams)
+ //parse JUNK
+ ||(d[0] == 'J' && d[1] == 'U' && d[2] == 'N' && d[3] == 'K')){
+ url_fskip(pb, size);
+//av_log(NULL, AV_LOG_DEBUG, "SKIP\n");
+ goto resync;
+ }
+
+ if( d[0] >= '0' && d[0] <= '9'
+ && d[1] >= '0' && d[1] <= '9'){
+ n= (d[0] - '0') * 10 + (d[1] - '0');
+ }else{
+ n= 100; //invalid stream id
+ }
+
+ //parse ##dc/##wb
+ if(n < s->nb_streams){
+ AVStream *st;
+ AVIStream *ast;
+ st = s->streams[n];
+ ast = st->priv_data;
+
+ if( (st->discard >= AVDISCARD_DEFAULT && size==0)
+ /*|| (st->discard >= AVDISCARD_NONKEY && !(pkt->flags & PKT_FLAG_KEY))*/ //FIXME needs a little reordering
+ || st->discard >= AVDISCARD_ALL){
+ if(ast->sample_size) ast->frame_offset += pkt->size;
+ else ast->frame_offset++;
+ url_fskip(pb, size);
+ goto resync;
+ }
+
+ if( ((ast->prefix_count<5 || sync+9 > i) && d[2]<128 && d[3]<128) ||
+ d[2]*256+d[3] == ast->prefix /*||
+ (d[2] == 'd' && d[3] == 'c') ||
+ (d[2] == 'w' && d[3] == 'b')*/) {
+
+//av_log(NULL, AV_LOG_DEBUG, "OK\n");
+ if(d[2]*256+d[3] == ast->prefix)
+ ast->prefix_count++;
+ else{
+ ast->prefix= d[2]*256+d[3];
+ ast->prefix_count= 0;
+ }
+
+ avi->stream_index= n;
+ ast->packet_size= size + 8;
+ ast->remaining= size;
+ goto resync;
+ }
+ }
+ /* palette changed chunk */
+ if ( d[0] >= '0' && d[0] <= '9'
+ && d[1] >= '0' && d[1] <= '9'
+ && ((d[2] == 'p' && d[3] == 'c'))
+ && n < s->nb_streams && i + size <= avi->movi_end) {
+
+ AVStream *st;
+ int first, clr, flags, k, p;
+
+ st = s->streams[n];
+
+ first = get_byte(pb);
+ clr = get_byte(pb);
+ if(!clr) /* all 256 colors used */
+ clr = 256;
+ flags = get_le16(pb);
+ p = 4;
+ for (k = first; k < clr + first; k++) {
+ int r, g, b;
+ r = get_byte(pb);
+ g = get_byte(pb);
+ b = get_byte(pb);
+ get_byte(pb);
+ st->codec->palctrl->palette[k] = b + (g << 8) + (r << 16);
+ }
+ st->codec->palctrl->palette_changed = 1;
+ goto resync;
+ }
+
+ }
+
+ return -1;
+}
+
+/* XXX: we make the implicit supposition that the position are sorted
+ for each stream */
+static int avi_read_idx1(AVFormatContext *s, int size)
+{
+ AVIContext *avi = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int nb_index_entries, i;
+ AVStream *st;
+ AVIStream *ast;
+ unsigned int index, tag, flags, pos, len;
+ unsigned last_pos= -1;
+
+ nb_index_entries = size / 16;
+ if (nb_index_entries <= 0)
+ return -1;
+
+ /* read the entries and sort them in each stream component */
+ for(i = 0; i < nb_index_entries; i++) {
+ tag = get_le32(pb);
+ flags = get_le32(pb);
+ pos = get_le32(pb);
+ len = get_le32(pb);
+#if defined(DEBUG_SEEK)
+ av_log(NULL, AV_LOG_DEBUG, "%d: tag=0x%x flags=0x%x pos=0x%x len=%d/",
+ i, tag, flags, pos, len);
+#endif
+ if(i==0 && pos > avi->movi_list)
+ avi->movi_list= 0; //FIXME better check
+ pos += avi->movi_list;
+
+ index = ((tag & 0xff) - '0') * 10;
+ index += ((tag >> 8) & 0xff) - '0';
+ if (index >= s->nb_streams)
+ continue;
+ st = s->streams[index];
+ ast = st->priv_data;
+
+#if defined(DEBUG_SEEK)
+ av_log(NULL, AV_LOG_DEBUG, "%d cum_len=%"PRId64"\n", len, ast->cum_len);
+#endif
+ if(last_pos == pos)
+ avi->non_interleaved= 1;
+ else
+ av_add_index_entry(st, pos, ast->cum_len / FFMAX(1, ast->sample_size), len, 0, (flags&AVIIF_INDEX) ? AVINDEX_KEYFRAME : 0);
+ if(ast->sample_size)
+ ast->cum_len += len;
+ else
+ ast->cum_len ++;
+ last_pos= pos;
+ }
+ return 0;
+}
+
+static int guess_ni_flag(AVFormatContext *s){
+ int i;
+ int64_t last_start=0;
+ int64_t first_end= INT64_MAX;
+
+ for(i=0; i<s->nb_streams; i++){
+ AVStream *st = s->streams[i];
+ int n= st->nb_index_entries;
+
+ if(n <= 0)
+ continue;
+
+ if(st->index_entries[0].pos > last_start)
+ last_start= st->index_entries[0].pos;
+ if(st->index_entries[n-1].pos < first_end)
+ first_end= st->index_entries[n-1].pos;
+ }
+ return last_start > first_end;
+}
+
+static int avi_load_index(AVFormatContext *s)
+{
+ AVIContext *avi = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ uint32_t tag, size;
+ offset_t pos= url_ftell(pb);
+
+ url_fseek(pb, avi->movi_end, SEEK_SET);
+#ifdef DEBUG_SEEK
+ printf("movi_end=0x%"PRIx64"\n", avi->movi_end);
+#endif
+ for(;;) {
+ if (url_feof(pb))
+ break;
+ tag = get_le32(pb);
+ size = get_le32(pb);
+#ifdef DEBUG_SEEK
+ printf("tag=%c%c%c%c size=0x%x\n",
+ tag & 0xff,
+ (tag >> 8) & 0xff,
+ (tag >> 16) & 0xff,
+ (tag >> 24) & 0xff,
+ size);
+#endif
+ switch(tag) {
+ case MKTAG('i', 'd', 'x', '1'):
+ if (avi_read_idx1(s, size) < 0)
+ goto skip;
+ else
+ goto the_end;
+ break;
+ default:
+ skip:
+ size += (size & 1);
+ url_fskip(pb, size);
+ break;
+ }
+ }
+ the_end:
+ url_fseek(pb, pos, SEEK_SET);
+ return 0;
+}
+
+static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
+{
+ AVIContext *avi = s->priv_data;
+ AVStream *st;
+ int i, index;
+ int64_t pos;
+
+ if (!avi->index_loaded) {
+ /* we only load the index on demand */
+ avi_load_index(s);
+ avi->index_loaded = 1;
+ }
+ assert(stream_index>= 0);
+
+ st = s->streams[stream_index];
+ index= av_index_search_timestamp(st, timestamp, flags);
+ if(index<0)
+ return -1;
+
+ /* find the position */
+ pos = st->index_entries[index].pos;
+ timestamp = st->index_entries[index].timestamp;
+
+// av_log(NULL, AV_LOG_DEBUG, "XX %"PRId64" %d %"PRId64"\n", timestamp, index, st->index_entries[index].timestamp);
+
+ for(i = 0; i < s->nb_streams; i++) {
+ AVStream *st2 = s->streams[i];
+ AVIStream *ast2 = st2->priv_data;
+
+ ast2->packet_size=
+ ast2->remaining= 0;
+
+ if (st2->nb_index_entries <= 0)
+ continue;
+
+// assert(st2->codec->block_align);
+ assert(st2->time_base.den == ast2->rate);
+ assert(st2->time_base.num == ast2->scale);
+ index = av_index_search_timestamp(
+ st2,
+ av_rescale(timestamp, st2->time_base.den*(int64_t)st->time_base.num, st->time_base.den * (int64_t)st2->time_base.num),
+ flags | AVSEEK_FLAG_BACKWARD);
+ if(index<0)
+ index=0;
+
+ if(!avi->non_interleaved){
+ while(index>0 && st2->index_entries[index].pos > pos)
+ index--;
+ while(index+1 < st2->nb_index_entries && st2->index_entries[index].pos < pos)
+ index++;
+ }
+
+// av_log(NULL, AV_LOG_DEBUG, "%"PRId64" %d %"PRId64"\n", timestamp, index, st2->index_entries[index].timestamp);
+ /* extract the current frame number */
+ ast2->frame_offset = st2->index_entries[index].timestamp;
+ if(ast2->sample_size)
+ ast2->frame_offset *=ast2->sample_size;
+ }
+
+ if (ENABLE_DV_DEMUXER && avi->dv_demux)
+ dv_flush_audio_packets(avi->dv_demux);
+ /* do the seek */
+ url_fseek(&s->pb, pos, SEEK_SET);
+ avi->stream_index= -1;
+ return 0;
+}
+
+static int avi_read_close(AVFormatContext *s)
+{
+ int i;
+ AVIContext *avi = s->priv_data;
+
+ for(i=0;i<s->nb_streams;i++) {
+ AVStream *st = s->streams[i];
+ AVIStream *ast = st->priv_data;
+ av_free(ast);
+ av_free(st->codec->palctrl);
+ }
+
+ if (avi->dv_demux)
+ av_free(avi->dv_demux);
+
+ return 0;
+}
+
+static int avi_probe(AVProbeData *p)
+{
+ /* check file header */
+ if (p->buf_size <= 32)
+ return 0;
+ if (p->buf[0] == 'R' && p->buf[1] == 'I' &&
+ p->buf[2] == 'F' && p->buf[3] == 'F' &&
+ p->buf[8] == 'A' && p->buf[9] == 'V' &&
+ p->buf[10] == 'I' && p->buf[11] == ' ')
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+AVInputFormat avi_demuxer = {
+ "avi",
+ "avi format",
+ sizeof(AVIContext),
+ avi_probe,
+ avi_read_header,
+ avi_read_packet,
+ avi_read_close,
+ avi_read_seek,
+};
diff --git a/contrib/ffmpeg/libavformat/avienc.c b/contrib/ffmpeg/libavformat/avienc.c
new file mode 100644
index 000000000..296608704
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/avienc.c
@@ -0,0 +1,580 @@
+/*
+ * AVI muxer
+ * 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
+ */
+#include "avformat.h"
+#include "avi.h"
+#include "riff.h"
+
+/*
+ * TODO:
+ * - fill all fields if non streamed (nb_frames for example)
+ */
+
+#ifdef CONFIG_AVI_MUXER
+typedef struct AVIIentry {
+ unsigned int flags, pos, len;
+} AVIIentry;
+
+#define AVI_INDEX_CLUSTER_SIZE 16384
+
+typedef struct AVIIndex {
+ offset_t indx_start;
+ int entry;
+ int ents_allocated;
+ AVIIentry** cluster;
+} AVIIndex;
+
+typedef struct {
+ offset_t riff_start, movi_list, odml_list;
+ offset_t frames_hdr_all, frames_hdr_strm[MAX_STREAMS];
+ int audio_strm_length[MAX_STREAMS];
+ int riff_id;
+ int packet_count[MAX_STREAMS];
+
+ AVIIndex indexes[MAX_STREAMS];
+} AVIContext;
+
+static inline AVIIentry* avi_get_ientry(AVIIndex* idx, int ent_id)
+{
+ int cl = ent_id / AVI_INDEX_CLUSTER_SIZE;
+ int id = ent_id % AVI_INDEX_CLUSTER_SIZE;
+ return &idx->cluster[cl][id];
+}
+
+static offset_t avi_start_new_riff(AVIContext *avi, ByteIOContext *pb,
+ const char* riff_tag, const char* list_tag)
+{
+ offset_t loff;
+ int i;
+
+ avi->riff_id++;
+ for (i=0; i<MAX_STREAMS; i++)
+ avi->indexes[i].entry = 0;
+
+ avi->riff_start = start_tag(pb, "RIFF");
+ put_tag(pb, riff_tag);
+ loff = start_tag(pb, "LIST");
+ put_tag(pb, list_tag);
+ return loff;
+}
+
+static char* avi_stream2fourcc(char* tag, int index, enum CodecType type)
+{
+ tag[0] = '0';
+ tag[1] = '0' + index;
+ if (type == CODEC_TYPE_VIDEO) {
+ tag[2] = 'd';
+ tag[3] = 'c';
+ } else {
+ tag[2] = 'w';
+ tag[3] = 'b';
+ }
+ tag[4] = '\0';
+ return tag;
+}
+
+static void avi_write_info_tag(ByteIOContext *pb, const char *tag, const char *str)
+{
+ int len = strlen(str);
+ if (len > 0) {
+ len++;
+ put_tag(pb, tag);
+ put_le32(pb, len);
+ put_strz(pb, str);
+ if (len & 1)
+ put_byte(pb, 0);
+ }
+}
+
+static int avi_write_counters(AVFormatContext* s, int riff_id)
+{
+ ByteIOContext *pb = &s->pb;
+ AVIContext *avi = s->priv_data;
+ int n, au_byterate, au_ssize, au_scale, nb_frames = 0;
+ offset_t file_size;
+ AVCodecContext* stream;
+
+ file_size = url_ftell(pb);
+ for(n = 0; n < s->nb_streams; n++) {
+ assert(avi->frames_hdr_strm[n]);
+ stream = s->streams[n]->codec;
+ url_fseek(pb, avi->frames_hdr_strm[n], SEEK_SET);
+ ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale);
+ if(au_ssize == 0) {
+ put_le32(pb, avi->packet_count[n]);
+ } else {
+ put_le32(pb, avi->audio_strm_length[n] / au_ssize);
+ }
+ if(stream->codec_type == CODEC_TYPE_VIDEO)
+ nb_frames = FFMAX(nb_frames, avi->packet_count[n]);
+ }
+ if(riff_id == 1) {
+ assert(avi->frames_hdr_all);
+ url_fseek(pb, avi->frames_hdr_all, SEEK_SET);
+ put_le32(pb, nb_frames);
+ }
+ url_fseek(pb, file_size, SEEK_SET);
+
+ return 0;
+}
+
+static int avi_write_header(AVFormatContext *s)
+{
+ AVIContext *avi = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale;
+ AVCodecContext *stream, *video_enc;
+ offset_t list1, list2, strh, strf;
+
+ /* header list */
+ avi->riff_id = 0;
+ list1 = avi_start_new_riff(avi, pb, "AVI ", "hdrl");
+
+ /* avi header */
+ put_tag(pb, "avih");
+ put_le32(pb, 14 * 4);
+ bitrate = 0;
+
+ video_enc = NULL;
+ for(n=0;n<s->nb_streams;n++) {
+ stream = s->streams[n]->codec;
+ bitrate += stream->bit_rate;
+ if (stream->codec_type == CODEC_TYPE_VIDEO)
+ video_enc = stream;
+ }
+
+ nb_frames = 0;
+
+ if(video_enc){
+ put_le32(pb, (uint32_t)(int64_t_C(1000000) * video_enc->time_base.num / video_enc->time_base.den));
+ } else {
+ put_le32(pb, 0);
+ }
+ put_le32(pb, bitrate / 8); /* XXX: not quite exact */
+ put_le32(pb, 0); /* padding */
+ if (url_is_streamed(pb))
+ put_le32(pb, AVIF_TRUSTCKTYPE | AVIF_ISINTERLEAVED); /* flags */
+ else
+ put_le32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */
+ avi->frames_hdr_all = url_ftell(pb); /* remember this offset to fill later */
+ put_le32(pb, nb_frames); /* nb frames, filled later */
+ put_le32(pb, 0); /* initial frame */
+ put_le32(pb, s->nb_streams); /* nb streams */
+ put_le32(pb, 1024 * 1024); /* suggested buffer size */
+ if(video_enc){
+ put_le32(pb, video_enc->width);
+ put_le32(pb, video_enc->height);
+ } else {
+ put_le32(pb, 0);
+ put_le32(pb, 0);
+ }
+ put_le32(pb, 0); /* reserved */
+ put_le32(pb, 0); /* reserved */
+ put_le32(pb, 0); /* reserved */
+ put_le32(pb, 0); /* reserved */
+
+ /* stream list */
+ for(i=0;i<n;i++) {
+ list2 = start_tag(pb, "LIST");
+ put_tag(pb, "strl");
+
+ stream = s->streams[i]->codec;
+
+ /* FourCC should really be set by the codec itself */
+ if (! stream->codec_tag) {
+ stream->codec_tag = codec_get_bmp_tag(stream->codec_id);
+ }
+
+ /* stream generic header */
+ strh = start_tag(pb, "strh");
+ switch(stream->codec_type) {
+ case CODEC_TYPE_VIDEO: put_tag(pb, "vids"); break;
+ case CODEC_TYPE_AUDIO: put_tag(pb, "auds"); break;
+// case CODEC_TYPE_TEXT : put_tag(pb, "txts"); break;
+ case CODEC_TYPE_DATA : put_tag(pb, "dats"); break;
+ }
+ if(stream->codec_type == CODEC_TYPE_VIDEO)
+ put_le32(pb, stream->codec_tag);
+ else
+ put_le32(pb, 1);
+ put_le32(pb, 0); /* flags */
+ put_le16(pb, 0); /* priority */
+ put_le16(pb, 0); /* language */
+ put_le32(pb, 0); /* initial frame */
+
+ ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale);
+
+ put_le32(pb, au_scale); /* scale */
+ put_le32(pb, au_byterate); /* rate */
+ av_set_pts_info(s->streams[i], 64, au_scale, au_byterate);
+
+ put_le32(pb, 0); /* start */
+ avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */
+ if (url_is_streamed(pb))
+ put_le32(pb, AVI_MAX_RIFF_SIZE); /* FIXME: this may be broken, but who cares */
+ else
+ put_le32(pb, 0); /* length, XXX: filled later */
+
+ /* suggested buffer size */ //FIXME set at the end to largest chunk
+ if(stream->codec_type == CODEC_TYPE_VIDEO)
+ put_le32(pb, 1024 * 1024);
+ else if(stream->codec_type == CODEC_TYPE_AUDIO)
+ put_le32(pb, 12 * 1024);
+ else
+ put_le32(pb, 0);
+ put_le32(pb, -1); /* quality */
+ put_le32(pb, au_ssize); /* sample size */
+ put_le32(pb, 0);
+ put_le16(pb, stream->width);
+ put_le16(pb, stream->height);
+ end_tag(pb, strh);
+
+ if(stream->codec_type != CODEC_TYPE_DATA){
+ strf = start_tag(pb, "strf");
+ switch(stream->codec_type) {
+ case CODEC_TYPE_VIDEO:
+ put_bmp_header(pb, stream, codec_bmp_tags, 0);
+ break;
+ case CODEC_TYPE_AUDIO:
+ if (put_wav_header(pb, stream) < 0) {
+ av_free(avi);
+ return -1;
+ }
+ break;
+ default:
+ return -1;
+ }
+ end_tag(pb, strf);
+ }
+
+ if (!url_is_streamed(pb)) {
+ unsigned char tag[5];
+ int j;
+
+ /* Starting to lay out AVI OpenDML master index.
+ * We want to make it JUNK entry for now, since we'd
+ * like to get away without making AVI an OpenDML one
+ * for compatibility reasons.
+ */
+ avi->indexes[i].entry = avi->indexes[i].ents_allocated = 0;
+ avi->indexes[i].indx_start = start_tag(pb, "JUNK");
+ put_le16(pb, 4); /* wLongsPerEntry */
+ put_byte(pb, 0); /* bIndexSubType (0 == frame index) */
+ put_byte(pb, 0); /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */
+ put_le32(pb, 0); /* nEntriesInUse (will fill out later on) */
+ put_tag(pb, avi_stream2fourcc(&tag[0], i, stream->codec_type));
+ /* dwChunkId */
+ put_le64(pb, 0); /* dwReserved[3]
+ put_le32(pb, 0); Must be 0. */
+ for (j=0; j < AVI_MASTER_INDEX_SIZE * 2; j++)
+ put_le64(pb, 0);
+ end_tag(pb, avi->indexes[i].indx_start);
+ }
+
+ end_tag(pb, list2);
+ }
+
+ if (!url_is_streamed(pb)) {
+ /* AVI could become an OpenDML one, if it grows beyond 2Gb range */
+ avi->odml_list = start_tag(pb, "JUNK");
+ put_tag(pb, "odml");
+ put_tag(pb, "dmlh");
+ put_le32(pb, 248);
+ for (i = 0; i < 248; i+= 4)
+ put_le32(pb, 0);
+ end_tag(pb, avi->odml_list);
+ }
+
+ end_tag(pb, list1);
+
+ list2 = start_tag(pb, "LIST");
+ put_tag(pb, "INFO");
+ avi_write_info_tag(pb, "INAM", s->title);
+ avi_write_info_tag(pb, "IART", s->author);
+ avi_write_info_tag(pb, "ICOP", s->copyright);
+ avi_write_info_tag(pb, "ICMT", s->comment);
+ avi_write_info_tag(pb, "IPRD", s->album);
+ avi_write_info_tag(pb, "IGNR", s->genre);
+ if (s->track) {
+ char str_track[4];
+ snprintf(str_track, 4, "%d", s->track);
+ avi_write_info_tag(pb, "IPRT", str_track);
+ }
+ if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT))
+ avi_write_info_tag(pb, "ISFT", LIBAVFORMAT_IDENT);
+ end_tag(pb, list2);
+
+ /* some padding for easier tag editing */
+ list2 = start_tag(pb, "JUNK");
+ for (i = 0; i < 1016; i += 4)
+ put_le32(pb, 0);
+ end_tag(pb, list2);
+
+ avi->movi_list = start_tag(pb, "LIST");
+ put_tag(pb, "movi");
+
+ put_flush_packet(pb);
+
+ return 0;
+}
+
+static int avi_write_ix(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+ AVIContext *avi = s->priv_data;
+ char tag[5];
+ char ix_tag[] = "ix00";
+ int i, j;
+
+ assert(!url_is_streamed(pb));
+
+ if (avi->riff_id > AVI_MASTER_INDEX_SIZE)
+ return -1;
+
+ for (i=0;i<s->nb_streams;i++) {
+ offset_t ix, pos;
+
+ avi_stream2fourcc(&tag[0], i, s->streams[i]->codec->codec_type);
+ ix_tag[3] = '0' + i;
+
+ /* Writing AVI OpenDML leaf index chunk */
+ ix = url_ftell(pb);
+ put_tag(pb, &ix_tag[0]); /* ix?? */
+ put_le32(pb, avi->indexes[i].entry * 8 + 24);
+ /* chunk size */
+ put_le16(pb, 2); /* wLongsPerEntry */
+ put_byte(pb, 0); /* bIndexSubType (0 == frame index) */
+ put_byte(pb, 1); /* bIndexType (1 == AVI_INDEX_OF_CHUNKS) */
+ put_le32(pb, avi->indexes[i].entry);
+ /* nEntriesInUse */
+ put_tag(pb, &tag[0]); /* dwChunkId */
+ put_le64(pb, avi->movi_list);/* qwBaseOffset */
+ put_le32(pb, 0); /* dwReserved_3 (must be 0) */
+
+ for (j=0; j<avi->indexes[i].entry; j++) {
+ AVIIentry* ie = avi_get_ientry(&avi->indexes[i], j);
+ put_le32(pb, ie->pos + 8);
+ put_le32(pb, ((uint32_t)ie->len & ~0x80000000) |
+ (ie->flags & 0x10 ? 0 : 0x80000000));
+ }
+ put_flush_packet(pb);
+ pos = url_ftell(pb);
+
+ /* Updating one entry in the AVI OpenDML master index */
+ url_fseek(pb, avi->indexes[i].indx_start - 8, SEEK_SET);
+ put_tag(pb, "indx"); /* enabling this entry */
+ url_fskip(pb, 8);
+ put_le32(pb, avi->riff_id); /* nEntriesInUse */
+ url_fskip(pb, 16*avi->riff_id);
+ put_le64(pb, ix); /* qwOffset */
+ put_le32(pb, pos - ix); /* dwSize */
+ put_le32(pb, avi->indexes[i].entry); /* dwDuration */
+
+ url_fseek(pb, pos, SEEK_SET);
+ }
+ return 0;
+}
+
+static int avi_write_idx1(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+ AVIContext *avi = s->priv_data;
+ offset_t idx_chunk;
+ int i;
+ char tag[5];
+
+ if (!url_is_streamed(pb)) {
+ AVIIentry* ie = 0, *tie;
+ int entry[MAX_STREAMS];
+ int empty, stream_id = -1;
+
+ idx_chunk = start_tag(pb, "idx1");
+ memset(&entry[0], 0, sizeof(entry));
+ do {
+ empty = 1;
+ for (i=0; i<s->nb_streams; i++) {
+ if (avi->indexes[i].entry <= entry[i])
+ continue;
+
+ tie = avi_get_ientry(&avi->indexes[i], entry[i]);
+ if (empty || tie->pos < ie->pos) {
+ ie = tie;
+ stream_id = i;
+ }
+ empty = 0;
+ }
+ if (!empty) {
+ avi_stream2fourcc(&tag[0], stream_id,
+ s->streams[stream_id]->codec->codec_type);
+ put_tag(pb, &tag[0]);
+ put_le32(pb, ie->flags);
+ put_le32(pb, ie->pos);
+ put_le32(pb, ie->len);
+ entry[stream_id]++;
+ }
+ } while (!empty);
+ end_tag(pb, idx_chunk);
+
+ avi_write_counters(s, avi->riff_id);
+ }
+ return 0;
+}
+
+static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ AVIContext *avi = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ unsigned char tag[5];
+ unsigned int flags=0;
+ const int stream_index= pkt->stream_index;
+ AVCodecContext *enc= s->streams[stream_index]->codec;
+ int size= pkt->size;
+
+// av_log(s, AV_LOG_DEBUG, "%"PRId64" %d %d\n", pkt->dts, avi->packet_count[stream_index], stream_index);
+ while(enc->block_align==0 && pkt->dts != AV_NOPTS_VALUE && pkt->dts > avi->packet_count[stream_index]){
+ AVPacket empty_packet;
+
+ av_init_packet(&empty_packet);
+ empty_packet.size= 0;
+ empty_packet.data= NULL;
+ empty_packet.stream_index= stream_index;
+ avi_write_packet(s, &empty_packet);
+// av_log(s, AV_LOG_DEBUG, "dup %"PRId64" %d\n", pkt->dts, avi->packet_count[stream_index]);
+ }
+ avi->packet_count[stream_index]++;
+
+ // Make sure to put an OpenDML chunk when the file size exceeds the limits
+ if (!url_is_streamed(pb) &&
+ (url_ftell(pb) - avi->riff_start > AVI_MAX_RIFF_SIZE)) {
+
+ avi_write_ix(s);
+ end_tag(pb, avi->movi_list);
+
+ if (avi->riff_id == 1)
+ avi_write_idx1(s);
+
+ end_tag(pb, avi->riff_start);
+ avi->movi_list = avi_start_new_riff(avi, pb, "AVIX", "movi");
+ }
+
+ avi_stream2fourcc(&tag[0], stream_index, enc->codec_type);
+ if(pkt->flags&PKT_FLAG_KEY)
+ flags = 0x10;
+ if (enc->codec_type == CODEC_TYPE_AUDIO) {
+ avi->audio_strm_length[stream_index] += size;
+ }
+
+ if (!url_is_streamed(&s->pb)) {
+ AVIIndex* idx = &avi->indexes[stream_index];
+ int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE;
+ int id = idx->entry % AVI_INDEX_CLUSTER_SIZE;
+ if (idx->ents_allocated <= idx->entry) {
+ idx->cluster = av_realloc(idx->cluster, (cl+1)*sizeof(void*));
+ if (!idx->cluster)
+ return -1;
+ idx->cluster[cl] = av_malloc(AVI_INDEX_CLUSTER_SIZE*sizeof(AVIIentry));
+ if (!idx->cluster[cl])
+ return -1;
+ idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE;
+ }
+
+ idx->cluster[cl][id].flags = flags;
+ idx->cluster[cl][id].pos = url_ftell(pb) - avi->movi_list;
+ idx->cluster[cl][id].len = size;
+ idx->entry++;
+ }
+
+ put_buffer(pb, tag, 4);
+ put_le32(pb, size);
+ put_buffer(pb, pkt->data, size);
+ if (size & 1)
+ put_byte(pb, 0);
+
+ put_flush_packet(pb);
+ return 0;
+}
+
+static int avi_write_trailer(AVFormatContext *s)
+{
+ AVIContext *avi = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int res = 0;
+ int i, j, n, nb_frames;
+ offset_t file_size;
+
+ if (!url_is_streamed(pb))
+ {
+ if (avi->riff_id == 1) {
+ end_tag(pb, avi->movi_list);
+ res = avi_write_idx1(s);
+ end_tag(pb, avi->riff_start);
+ } else {
+ avi_write_ix(s);
+ end_tag(pb, avi->movi_list);
+ end_tag(pb, avi->riff_start);
+
+ file_size = url_ftell(pb);
+ url_fseek(pb, avi->odml_list - 8, SEEK_SET);
+ put_tag(pb, "LIST"); /* Making this AVI OpenDML one */
+ url_fskip(pb, 16);
+
+ for (n=nb_frames=0;n<s->nb_streams;n++) {
+ AVCodecContext *stream = s->streams[n]->codec;
+ if (stream->codec_type == CODEC_TYPE_VIDEO) {
+ if (nb_frames < avi->packet_count[n])
+ nb_frames = avi->packet_count[n];
+ } else {
+ if (stream->codec_id == CODEC_ID_MP2 || stream->codec_id == CODEC_ID_MP3) {
+ nb_frames += avi->packet_count[n];
+ }
+ }
+ }
+ put_le32(pb, nb_frames);
+ url_fseek(pb, file_size, SEEK_SET);
+
+ avi_write_counters(s, avi->riff_id);
+ }
+ }
+ put_flush_packet(pb);
+
+ for (i=0; i<MAX_STREAMS; i++) {
+ for (j=0; j<avi->indexes[i].ents_allocated/AVI_INDEX_CLUSTER_SIZE; j++)
+ av_free(avi->indexes[i].cluster[j]);
+ av_free(avi->indexes[i].cluster);
+ avi->indexes[i].cluster = NULL;
+ avi->indexes[i].ents_allocated = avi->indexes[i].entry = 0;
+ }
+
+ return res;
+}
+
+AVOutputFormat avi_muxer = {
+ "avi",
+ "avi format",
+ "video/x-msvideo",
+ "avi",
+ sizeof(AVIContext),
+ CODEC_ID_MP2,
+ CODEC_ID_MPEG4,
+ avi_write_header,
+ avi_write_packet,
+ avi_write_trailer,
+};
+#endif //CONFIG_AVI_MUXER
diff --git a/contrib/ffmpeg/libavformat/avio.c b/contrib/ffmpeg/libavformat/avio.c
new file mode 100644
index 000000000..a2b8a8325
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/avio.c
@@ -0,0 +1,192 @@
+/*
+ * Unbuffered io for ffmpeg system
+ * 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
+ */
+#include "avformat.h"
+
+static int default_interrupt_cb(void);
+
+URLProtocol *first_protocol = NULL;
+URLInterruptCB *url_interrupt_cb = default_interrupt_cb;
+
+int register_protocol(URLProtocol *protocol)
+{
+ URLProtocol **p;
+ p = &first_protocol;
+ while (*p != NULL) p = &(*p)->next;
+ *p = protocol;
+ protocol->next = NULL;
+ return 0;
+}
+
+int url_open(URLContext **puc, const char *filename, int flags)
+{
+ URLContext *uc;
+ URLProtocol *up;
+ const char *p;
+ char proto_str[128], *q;
+ int err;
+
+ p = filename;
+ q = proto_str;
+ while (*p != '\0' && *p != ':') {
+ /* protocols can only contain alphabetic chars */
+ if (!isalpha(*p))
+ goto file_proto;
+ if ((q - proto_str) < sizeof(proto_str) - 1)
+ *q++ = *p;
+ p++;
+ }
+ /* if the protocol has length 1, we consider it is a dos drive */
+ if (*p == '\0' || (q - proto_str) <= 1) {
+ file_proto:
+ strcpy(proto_str, "file");
+ } else {
+ *q = '\0';
+ }
+
+ up = first_protocol;
+ while (up != NULL) {
+ if (!strcmp(proto_str, up->name))
+ goto found;
+ up = up->next;
+ }
+ err = -ENOENT;
+ goto fail;
+ found:
+ uc = av_malloc(sizeof(URLContext) + strlen(filename));
+ if (!uc) {
+ err = -ENOMEM;
+ goto fail;
+ }
+ strcpy(uc->filename, filename);
+ uc->prot = up;
+ uc->flags = flags;
+ uc->is_streamed = 0; /* default = not streamed */
+ uc->max_packet_size = 0; /* default: stream file */
+ err = up->url_open(uc, filename, flags);
+ if (err < 0) {
+ av_free(uc);
+ *puc = NULL;
+ return err;
+ }
+ *puc = uc;
+ return 0;
+ fail:
+ *puc = NULL;
+ return err;
+}
+
+int url_read(URLContext *h, unsigned char *buf, int size)
+{
+ int ret;
+ if (h->flags & URL_WRONLY)
+ return AVERROR_IO;
+ ret = h->prot->url_read(h, buf, size);
+ return ret;
+}
+
+#if defined(CONFIG_MUXERS) || defined(CONFIG_PROTOCOLS)
+int url_write(URLContext *h, unsigned char *buf, int size)
+{
+ int ret;
+ if (!(h->flags & (URL_WRONLY | URL_RDWR)))
+ return AVERROR_IO;
+ /* avoid sending too big packets */
+ if (h->max_packet_size && size > h->max_packet_size)
+ return AVERROR_IO;
+ ret = h->prot->url_write(h, buf, size);
+ return ret;
+}
+#endif //CONFIG_MUXERS || CONFIG_PROTOCOLS
+
+offset_t url_seek(URLContext *h, offset_t pos, int whence)
+{
+ offset_t ret;
+
+ if (!h->prot->url_seek)
+ return -EPIPE;
+ ret = h->prot->url_seek(h, pos, whence);
+ return ret;
+}
+
+int url_close(URLContext *h)
+{
+ int ret;
+
+ ret = h->prot->url_close(h);
+ av_free(h);
+ return ret;
+}
+
+int url_exist(const char *filename)
+{
+ URLContext *h;
+ if (url_open(&h, filename, URL_RDONLY) < 0)
+ return 0;
+ url_close(h);
+ return 1;
+}
+
+offset_t url_filesize(URLContext *h)
+{
+ offset_t pos, size;
+
+ pos = url_seek(h, 0, SEEK_CUR);
+ size = url_seek(h, -1, SEEK_END)+1;
+ url_seek(h, pos, SEEK_SET);
+ return size;
+}
+
+/*
+ * Return the maximum packet size associated to packetized file
+ * handle. If the file is not packetized (stream like http or file on
+ * disk), then 0 is returned.
+ *
+ * @param h file handle
+ * @return maximum packet size in bytes
+ */
+int url_get_max_packet_size(URLContext *h)
+{
+ return h->max_packet_size;
+}
+
+void url_get_filename(URLContext *h, char *buf, int buf_size)
+{
+ pstrcpy(buf, buf_size, h->filename);
+}
+
+
+static int default_interrupt_cb(void)
+{
+ return 0;
+}
+
+/**
+ * The callback is called in blocking functions to test regulary if
+ * asynchronous interruption is needed. -EINTR is returned in this
+ * case by the interrupted function. 'NULL' means no interrupt
+ * callback is given.
+ */
+void url_set_interrupt_cb(URLInterruptCB *interrupt_cb)
+{
+ if (!interrupt_cb)
+ interrupt_cb = default_interrupt_cb;
+ url_interrupt_cb = interrupt_cb;
+}
diff --git a/contrib/ffmpeg/libavformat/avio.h b/contrib/ffmpeg/libavformat/avio.h
new file mode 100644
index 000000000..f0fd1a85c
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/avio.h
@@ -0,0 +1,201 @@
+/*
+ * unbuffered io for ffmpeg system
+ * 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 AVIO_H
+#define AVIO_H
+
+/* output byte stream handling */
+
+typedef int64_t offset_t;
+
+/* unbuffered I/O */
+
+struct URLContext {
+ struct URLProtocol *prot;
+ int flags;
+ int is_streamed; /* true if streamed (no seek possible), default = false */
+ int max_packet_size; /* if non zero, the stream is packetized with this max packet size */
+ void *priv_data;
+ char filename[1]; /* specified filename */
+};
+
+typedef struct URLContext URLContext;
+
+typedef struct URLPollEntry {
+ URLContext *handle;
+ int events;
+ int revents;
+} URLPollEntry;
+
+#define URL_RDONLY 0
+#define URL_WRONLY 1
+#define URL_RDWR 2
+
+typedef int URLInterruptCB(void);
+
+int url_open(URLContext **h, const char *filename, int flags);
+int url_read(URLContext *h, unsigned char *buf, int size);
+int url_write(URLContext *h, unsigned char *buf, int size);
+offset_t url_seek(URLContext *h, offset_t pos, int whence);
+int url_close(URLContext *h);
+int url_exist(const char *filename);
+offset_t url_filesize(URLContext *h);
+int url_get_max_packet_size(URLContext *h);
+void url_get_filename(URLContext *h, char *buf, int buf_size);
+
+/* the callback is called in blocking functions to test regulary if
+ asynchronous interruption is needed. -EINTR is returned in this
+ case by the interrupted function. 'NULL' means no interrupt
+ callback is given. */
+void url_set_interrupt_cb(URLInterruptCB *interrupt_cb);
+
+/* not implemented */
+int url_poll(URLPollEntry *poll_table, int n, int timeout);
+
+typedef struct URLProtocol {
+ const char *name;
+ int (*url_open)(URLContext *h, const char *filename, int flags);
+ int (*url_read)(URLContext *h, unsigned char *buf, int size);
+ int (*url_write)(URLContext *h, unsigned char *buf, int size);
+ offset_t (*url_seek)(URLContext *h, offset_t pos, int whence);
+ int (*url_close)(URLContext *h);
+ struct URLProtocol *next;
+} URLProtocol;
+
+extern URLProtocol *first_protocol;
+extern URLInterruptCB *url_interrupt_cb;
+
+int register_protocol(URLProtocol *protocol);
+
+typedef struct {
+ unsigned char *buffer;
+ int buffer_size;
+ unsigned char *buf_ptr, *buf_end;
+ void *opaque;
+ int (*read_packet)(void *opaque, uint8_t *buf, int buf_size);
+ int (*write_packet)(void *opaque, uint8_t *buf, int buf_size);
+ offset_t (*seek)(void *opaque, offset_t offset, int whence);
+ offset_t pos; /* position in the file of the current buffer */
+ int must_flush; /* true if the next seek should flush */
+ int eof_reached; /* true if eof reached */
+ int write_flag; /* true if open for writing */
+ int is_streamed;
+ int max_packet_size;
+ unsigned long checksum;
+ unsigned char *checksum_ptr;
+ unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);
+ int error; ///< contains the error code or 0 if no error happened
+} ByteIOContext;
+
+int init_put_byte(ByteIOContext *s,
+ unsigned char *buffer,
+ int buffer_size,
+ int write_flag,
+ void *opaque,
+ int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
+ int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
+ offset_t (*seek)(void *opaque, offset_t offset, int whence));
+
+void put_byte(ByteIOContext *s, int b);
+void put_buffer(ByteIOContext *s, const unsigned char *buf, int size);
+void put_le64(ByteIOContext *s, uint64_t val);
+void put_be64(ByteIOContext *s, uint64_t val);
+void put_le32(ByteIOContext *s, unsigned int val);
+void put_be32(ByteIOContext *s, unsigned int val);
+void put_le24(ByteIOContext *s, unsigned int val);
+void put_be24(ByteIOContext *s, unsigned int val);
+void put_le16(ByteIOContext *s, unsigned int val);
+void put_be16(ByteIOContext *s, unsigned int val);
+void put_tag(ByteIOContext *s, const char *tag);
+
+void put_strz(ByteIOContext *s, const char *buf);
+
+offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence);
+void url_fskip(ByteIOContext *s, offset_t offset);
+offset_t url_ftell(ByteIOContext *s);
+offset_t url_fsize(ByteIOContext *s);
+int url_feof(ByteIOContext *s);
+int url_ferror(ByteIOContext *s);
+
+#define URL_EOF (-1)
+int url_fgetc(ByteIOContext *s);
+#ifdef __GNUC__
+int url_fprintf(ByteIOContext *s, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
+#else
+int url_fprintf(ByteIOContext *s, const char *fmt, ...);
+#endif
+char *url_fgets(ByteIOContext *s, char *buf, int buf_size);
+
+void put_flush_packet(ByteIOContext *s);
+
+int get_buffer(ByteIOContext *s, unsigned char *buf, int size);
+int get_partial_buffer(ByteIOContext *s, unsigned char *buf, int size);
+int get_byte(ByteIOContext *s);
+unsigned int get_le24(ByteIOContext *s);
+unsigned int get_le32(ByteIOContext *s);
+uint64_t get_le64(ByteIOContext *s);
+unsigned int get_le16(ByteIOContext *s);
+
+char *get_strz(ByteIOContext *s, char *buf, int maxlen);
+unsigned int get_be16(ByteIOContext *s);
+unsigned int get_be24(ByteIOContext *s);
+unsigned int get_be32(ByteIOContext *s);
+uint64_t get_be64(ByteIOContext *s);
+
+static inline int url_is_streamed(ByteIOContext *s)
+{
+ return s->is_streamed;
+}
+
+int url_fdopen(ByteIOContext *s, URLContext *h);
+int url_setbufsize(ByteIOContext *s, int buf_size);
+int url_fopen(ByteIOContext *s, const char *filename, int flags);
+int url_fclose(ByteIOContext *s);
+URLContext *url_fileno(ByteIOContext *s);
+int url_fget_max_packet_size(ByteIOContext *s);
+
+int url_open_buf(ByteIOContext *s, uint8_t *buf, int buf_size, int flags);
+int url_close_buf(ByteIOContext *s);
+
+int url_open_dyn_buf(ByteIOContext *s);
+int url_open_dyn_packet_buf(ByteIOContext *s, int max_packet_size);
+int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer);
+
+unsigned long get_checksum(ByteIOContext *s);
+void init_checksum(ByteIOContext *s, unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), unsigned long checksum);
+
+/* file.c */
+extern URLProtocol file_protocol;
+extern URLProtocol pipe_protocol;
+
+/* udp.c */
+extern URLProtocol udp_protocol;
+int udp_set_remote_url(URLContext *h, const char *uri);
+int udp_get_local_port(URLContext *h);
+int udp_get_file_handle(URLContext *h);
+
+/* tcp.c */
+extern URLProtocol tcp_protocol;
+
+/* http.c */
+extern URLProtocol http_protocol;
+
+#endif
+
diff --git a/contrib/ffmpeg/libavformat/aviobuf.c b/contrib/ffmpeg/libavformat/aviobuf.c
new file mode 100644
index 000000000..866641ad0
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/aviobuf.c
@@ -0,0 +1,790 @@
+/*
+ * Buffered I/O for ffmpeg system
+ * 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 "avformat.h"
+#include "avio.h"
+#include <stdarg.h>
+
+#define IO_BUFFER_SIZE 32768
+
+static void fill_buffer(ByteIOContext *s);
+
+int init_put_byte(ByteIOContext *s,
+ unsigned char *buffer,
+ int buffer_size,
+ int write_flag,
+ void *opaque,
+ int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
+ int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
+ offset_t (*seek)(void *opaque, offset_t offset, int whence))
+{
+ s->buffer = buffer;
+ s->buffer_size = buffer_size;
+ s->buf_ptr = buffer;
+ s->write_flag = write_flag;
+ if (!s->write_flag)
+ s->buf_end = buffer;
+ else
+ s->buf_end = buffer + buffer_size;
+ s->opaque = opaque;
+ s->write_packet = write_packet;
+ s->read_packet = read_packet;
+ s->seek = seek;
+ s->pos = 0;
+ s->must_flush = 0;
+ s->eof_reached = 0;
+ s->error = 0;
+ s->is_streamed = 0;
+ s->max_packet_size = 0;
+ s->update_checksum= NULL;
+ if(!read_packet && !write_flag){
+ s->pos = buffer_size;
+ s->buf_end = s->buffer + buffer_size;
+ }
+ return 0;
+}
+
+static void flush_buffer(ByteIOContext *s)
+{
+ if (s->buf_ptr > s->buffer) {
+ if (s->write_packet && !s->error){
+ int ret= s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer);
+ if(ret < 0){
+ s->error = ret;
+ }
+ }
+ if(s->update_checksum){
+ s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
+ s->checksum_ptr= s->buffer;
+ }
+ s->pos += s->buf_ptr - s->buffer;
+ }
+ s->buf_ptr = s->buffer;
+}
+
+void put_byte(ByteIOContext *s, int b)
+{
+ *(s->buf_ptr)++ = b;
+ if (s->buf_ptr >= s->buf_end)
+ flush_buffer(s);
+}
+
+void put_buffer(ByteIOContext *s, const unsigned char *buf, int size)
+{
+ int len;
+
+ while (size > 0) {
+ len = (s->buf_end - s->buf_ptr);
+ if (len > size)
+ len = size;
+ memcpy(s->buf_ptr, buf, len);
+ s->buf_ptr += len;
+
+ if (s->buf_ptr >= s->buf_end)
+ flush_buffer(s);
+
+ buf += len;
+ size -= len;
+ }
+}
+
+void put_flush_packet(ByteIOContext *s)
+{
+ flush_buffer(s);
+ s->must_flush = 0;
+}
+
+offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence)
+{
+ offset_t offset1;
+ offset_t pos= s->pos - (s->write_flag ? 0 : (s->buf_end - s->buffer));
+
+ if (whence != SEEK_CUR && whence != SEEK_SET)
+ return -EINVAL;
+
+ if (whence == SEEK_CUR) {
+ offset1 = pos + (s->buf_ptr - s->buffer);
+ if (offset == 0)
+ return offset1;
+ offset += offset1;
+ }
+ offset1 = offset - pos;
+ if (!s->must_flush &&
+ offset1 >= 0 && offset1 < (s->buf_end - s->buffer)) {
+ /* can do the seek inside the buffer */
+ s->buf_ptr = s->buffer + offset1;
+ } else if(s->is_streamed && !s->write_flag &&
+ offset1 >= 0 && offset1 < (s->buf_end - s->buffer) + (1<<16)){
+ while(s->pos < offset && !s->eof_reached)
+ fill_buffer(s);
+ s->buf_ptr = s->buf_end + offset - s->pos;
+ } else {
+#if defined(CONFIG_MUXERS) || defined(CONFIG_NETWORK)
+ if (s->write_flag) {
+ flush_buffer(s);
+ s->must_flush = 1;
+ } else
+#endif /* defined(CONFIG_MUXERS) || defined(CONFIG_NETWORK) */
+ {
+ s->buf_end = s->buffer;
+ }
+ s->buf_ptr = s->buffer;
+ if (!s->seek || s->seek(s->opaque, offset, SEEK_SET) == (offset_t)-EPIPE)
+ return -EPIPE;
+ s->pos = offset;
+ }
+ s->eof_reached = 0;
+ return offset;
+}
+
+void url_fskip(ByteIOContext *s, offset_t offset)
+{
+ url_fseek(s, offset, SEEK_CUR);
+}
+
+offset_t url_ftell(ByteIOContext *s)
+{
+ return url_fseek(s, 0, SEEK_CUR);
+}
+
+offset_t url_fsize(ByteIOContext *s)
+{
+ offset_t size;
+
+ if (!s->seek)
+ return -EPIPE;
+ size = s->seek(s->opaque, -1, SEEK_END) + 1;
+ s->seek(s->opaque, s->pos, SEEK_SET);
+ return size;
+}
+
+int url_feof(ByteIOContext *s)
+{
+ return s->eof_reached;
+}
+
+int url_ferror(ByteIOContext *s)
+{
+ return s->error;
+}
+
+#if defined(CONFIG_MUXERS) || defined(CONFIG_PROTOCOLS)
+void put_le32(ByteIOContext *s, unsigned int val)
+{
+ put_byte(s, val);
+ put_byte(s, val >> 8);
+ put_byte(s, val >> 16);
+ put_byte(s, val >> 24);
+}
+
+void put_be32(ByteIOContext *s, unsigned int val)
+{
+ put_byte(s, val >> 24);
+ put_byte(s, val >> 16);
+ put_byte(s, val >> 8);
+ put_byte(s, val);
+}
+
+void put_strz(ByteIOContext *s, const char *str)
+{
+ if (str)
+ put_buffer(s, (const unsigned char *) str, strlen(str) + 1);
+ else
+ put_byte(s, 0);
+}
+
+void put_le64(ByteIOContext *s, uint64_t val)
+{
+ put_le32(s, (uint32_t)(val & 0xffffffff));
+ put_le32(s, (uint32_t)(val >> 32));
+}
+
+void put_be64(ByteIOContext *s, uint64_t val)
+{
+ put_be32(s, (uint32_t)(val >> 32));
+ put_be32(s, (uint32_t)(val & 0xffffffff));
+}
+
+void put_le16(ByteIOContext *s, unsigned int val)
+{
+ put_byte(s, val);
+ put_byte(s, val >> 8);
+}
+
+void put_be16(ByteIOContext *s, unsigned int val)
+{
+ put_byte(s, val >> 8);
+ put_byte(s, val);
+}
+
+void put_le24(ByteIOContext *s, unsigned int val)
+{
+ put_le16(s, val & 0xffff);
+ put_byte(s, val >> 16);
+}
+
+void put_be24(ByteIOContext *s, unsigned int val)
+{
+ put_be16(s, val >> 8);
+ put_byte(s, val);
+}
+
+void put_tag(ByteIOContext *s, const char *tag)
+{
+ while (*tag) {
+ put_byte(s, *tag++);
+ }
+}
+#endif //CONFIG_MUXERS || CONFIG_PROTOCOLS
+
+/* Input stream */
+
+static void fill_buffer(ByteIOContext *s)
+{
+ int len;
+
+ /* no need to do anything if EOF already reached */
+ if (s->eof_reached)
+ return;
+
+ if(s->update_checksum){
+ if(s->buf_end > s->checksum_ptr)
+ s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_end - s->checksum_ptr);
+ s->checksum_ptr= s->buffer;
+ }
+
+ len = s->read_packet(s->opaque, s->buffer, s->buffer_size);
+ if (len <= 0) {
+ /* do not modify buffer if EOF reached so that a seek back can
+ be done without rereading data */
+ s->eof_reached = 1;
+ if(len<0)
+ s->error= len;
+ } else {
+ s->pos += len;
+ s->buf_ptr = s->buffer;
+ s->buf_end = s->buffer + len;
+ }
+}
+
+unsigned long get_checksum(ByteIOContext *s){
+ s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
+ s->update_checksum= NULL;
+ return s->checksum;
+}
+
+void init_checksum(ByteIOContext *s, unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), unsigned long checksum){
+ s->update_checksum= update_checksum;
+ if(s->update_checksum){
+ s->checksum= checksum;
+ s->checksum_ptr= s->buf_ptr;
+ }
+}
+
+/* NOTE: return 0 if EOF, so you cannot use it if EOF handling is
+ necessary */
+/* XXX: put an inline version */
+int get_byte(ByteIOContext *s)
+{
+ if (s->buf_ptr < s->buf_end) {
+ return *s->buf_ptr++;
+ } else {
+ fill_buffer(s);
+ if (s->buf_ptr < s->buf_end)
+ return *s->buf_ptr++;
+ else
+ return 0;
+ }
+}
+
+/* NOTE: return URL_EOF (-1) if EOF */
+int url_fgetc(ByteIOContext *s)
+{
+ if (s->buf_ptr < s->buf_end) {
+ return *s->buf_ptr++;
+ } else {
+ fill_buffer(s);
+ if (s->buf_ptr < s->buf_end)
+ return *s->buf_ptr++;
+ else
+ return URL_EOF;
+ }
+}
+
+int get_buffer(ByteIOContext *s, unsigned char *buf, int size)
+{
+ int len, size1;
+
+ size1 = size;
+ while (size > 0) {
+ len = s->buf_end - s->buf_ptr;
+ if (len > size)
+ len = size;
+ if (len == 0) {
+ if(size > s->buffer_size && !s->update_checksum){
+ len = s->read_packet(s->opaque, buf, size);
+ if (len <= 0) {
+ /* do not modify buffer if EOF reached so that a seek back can
+ be done without rereading data */
+ s->eof_reached = 1;
+ if(len<0)
+ s->error= len;
+ break;
+ } else {
+ s->pos += len;
+ size -= len;
+ buf += len;
+ s->buf_ptr = s->buffer;
+ s->buf_end = s->buffer/* + len*/;
+ }
+ }else{
+ fill_buffer(s);
+ len = s->buf_end - s->buf_ptr;
+ if (len == 0)
+ break;
+ }
+ } else {
+ memcpy(buf, s->buf_ptr, len);
+ buf += len;
+ s->buf_ptr += len;
+ size -= len;
+ }
+ }
+ return size1 - size;
+}
+
+int get_partial_buffer(ByteIOContext *s, unsigned char *buf, int size)
+{
+ int len;
+
+ if(size<0)
+ return -1;
+
+ len = s->buf_end - s->buf_ptr;
+ if (len == 0) {
+ fill_buffer(s);
+ len = s->buf_end - s->buf_ptr;
+ }
+ if (len > size)
+ len = size;
+ memcpy(buf, s->buf_ptr, len);
+ s->buf_ptr += len;
+ return len;
+}
+
+unsigned int get_le16(ByteIOContext *s)
+{
+ unsigned int val;
+ val = get_byte(s);
+ val |= get_byte(s) << 8;
+ return val;
+}
+
+unsigned int get_le24(ByteIOContext *s)
+{
+ unsigned int val;
+ val = get_le16(s);
+ val |= get_byte(s) << 16;
+ return val;
+}
+
+unsigned int get_le32(ByteIOContext *s)
+{
+ unsigned int val;
+ val = get_le16(s);
+ val |= get_le16(s) << 16;
+ return val;
+}
+
+uint64_t get_le64(ByteIOContext *s)
+{
+ uint64_t val;
+ val = (uint64_t)get_le32(s);
+ val |= (uint64_t)get_le32(s) << 32;
+ return val;
+}
+
+unsigned int get_be16(ByteIOContext *s)
+{
+ unsigned int val;
+ val = get_byte(s) << 8;
+ val |= get_byte(s);
+ return val;
+}
+
+unsigned int get_be24(ByteIOContext *s)
+{
+ unsigned int val;
+ val = get_be16(s) << 8;
+ val |= get_byte(s);
+ return val;
+}
+unsigned int get_be32(ByteIOContext *s)
+{
+ unsigned int val;
+ val = get_be16(s) << 16;
+ val |= get_be16(s);
+ return val;
+}
+
+char *get_strz(ByteIOContext *s, char *buf, int maxlen)
+{
+ int i = 0;
+ char c;
+
+ while ((c = get_byte(s))) {
+ if (i < maxlen-1)
+ buf[i++] = c;
+ }
+
+ buf[i] = 0; /* Ensure null terminated, but may be truncated */
+
+ return buf;
+}
+
+uint64_t get_be64(ByteIOContext *s)
+{
+ uint64_t val;
+ val = (uint64_t)get_be32(s) << 32;
+ val |= (uint64_t)get_be32(s);
+ return val;
+}
+
+/* link with avio functions */
+
+#ifdef CONFIG_MUXERS
+static int url_write_packet(void *opaque, uint8_t *buf, int buf_size)
+{
+ URLContext *h = opaque;
+ return url_write(h, buf, buf_size);
+}
+#else
+#define url_write_packet NULL
+#endif //CONFIG_MUXERS
+
+static int url_read_packet(void *opaque, uint8_t *buf, int buf_size)
+{
+ URLContext *h = opaque;
+ return url_read(h, buf, buf_size);
+}
+
+static offset_t url_seek_packet(void *opaque, offset_t offset, int whence)
+{
+ URLContext *h = opaque;
+ return url_seek(h, offset, whence);
+ //return 0;
+}
+
+int url_fdopen(ByteIOContext *s, URLContext *h)
+{
+ uint8_t *buffer;
+ int buffer_size, max_packet_size;
+
+
+ max_packet_size = url_get_max_packet_size(h);
+ if (max_packet_size) {
+ buffer_size = max_packet_size; /* no need to bufferize more than one packet */
+ } else {
+ buffer_size = IO_BUFFER_SIZE;
+ }
+ buffer = av_malloc(buffer_size);
+ if (!buffer)
+ return -ENOMEM;
+
+ if (init_put_byte(s, buffer, buffer_size,
+ (h->flags & URL_WRONLY || h->flags & URL_RDWR), h,
+ url_read_packet, url_write_packet, url_seek_packet) < 0) {
+ av_free(buffer);
+ return AVERROR_IO;
+ }
+ s->is_streamed = h->is_streamed;
+ s->max_packet_size = max_packet_size;
+ return 0;
+}
+
+/* XXX: must be called before any I/O */
+int url_setbufsize(ByteIOContext *s, int buf_size)
+{
+ uint8_t *buffer;
+ buffer = av_malloc(buf_size);
+ if (!buffer)
+ return -ENOMEM;
+
+ av_free(s->buffer);
+ s->buffer = buffer;
+ s->buffer_size = buf_size;
+ s->buf_ptr = buffer;
+ if (!s->write_flag)
+ s->buf_end = buffer;
+ else
+ s->buf_end = buffer + buf_size;
+ return 0;
+}
+
+/* NOTE: when opened as read/write, the buffers are only used for
+ reading */
+int url_fopen(ByteIOContext *s, const char *filename, int flags)
+{
+ URLContext *h;
+ int err;
+
+ err = url_open(&h, filename, flags);
+ if (err < 0)
+ return err;
+ err = url_fdopen(s, h);
+ if (err < 0) {
+ url_close(h);
+ return err;
+ }
+ return 0;
+}
+
+int url_fclose(ByteIOContext *s)
+{
+ URLContext *h = s->opaque;
+
+ av_free(s->buffer);
+ memset(s, 0, sizeof(ByteIOContext));
+ return url_close(h);
+}
+
+URLContext *url_fileno(ByteIOContext *s)
+{
+ return s->opaque;
+}
+
+#ifdef CONFIG_MUXERS
+/* XXX: currently size is limited */
+int url_fprintf(ByteIOContext *s, const char *fmt, ...)
+{
+ va_list ap;
+ char buf[4096];
+ int ret;
+
+ va_start(ap, fmt);
+ ret = vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ put_buffer(s, buf, strlen(buf));
+ return ret;
+}
+#endif //CONFIG_MUXERS
+
+/* note: unlike fgets, the EOL character is not returned and a whole
+ line is parsed. return NULL if first char read was EOF */
+char *url_fgets(ByteIOContext *s, char *buf, int buf_size)
+{
+ int c;
+ char *q;
+
+ c = url_fgetc(s);
+ if (c == EOF)
+ return NULL;
+ q = buf;
+ for(;;) {
+ if (c == EOF || c == '\n')
+ break;
+ if ((q - buf) < buf_size - 1)
+ *q++ = c;
+ c = url_fgetc(s);
+ }
+ if (buf_size > 0)
+ *q = '\0';
+ return buf;
+}
+
+/*
+ * Return the maximum packet size associated to packetized buffered file
+ * handle. If the file is not packetized (stream like http or file on
+ * disk), then 0 is returned.
+ *
+ * @param h buffered file handle
+ * @return maximum packet size in bytes
+ */
+int url_fget_max_packet_size(ByteIOContext *s)
+{
+ return s->max_packet_size;
+}
+
+/* url_open_dyn_buf and url_close_dyn_buf are used in rtp.c to send a response
+ * back to the server even if CONFIG_MUXERS is not set. */
+#if defined(CONFIG_MUXERS) || defined(CONFIG_NETWORK)
+/* buffer handling */
+int url_open_buf(ByteIOContext *s, uint8_t *buf, int buf_size, int flags)
+{
+ return init_put_byte(s, buf, buf_size,
+ (flags & URL_WRONLY || flags & URL_RDWR),
+ NULL, NULL, NULL, NULL);
+}
+
+/* return the written or read size */
+int url_close_buf(ByteIOContext *s)
+{
+ put_flush_packet(s);
+ return s->buf_ptr - s->buffer;
+}
+
+/* output in a dynamic buffer */
+
+typedef struct DynBuffer {
+ int pos, size, allocated_size;
+ uint8_t *buffer;
+ int io_buffer_size;
+ uint8_t io_buffer[1];
+} DynBuffer;
+
+static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size)
+{
+ DynBuffer *d = opaque;
+ int new_size, new_allocated_size;
+
+ /* reallocate buffer if needed */
+ new_size = d->pos + buf_size;
+ new_allocated_size = d->allocated_size;
+ if(new_size < d->pos || new_size > INT_MAX/2)
+ return -1;
+ while (new_size > new_allocated_size) {
+ if (!new_allocated_size)
+ new_allocated_size = new_size;
+ else
+ new_allocated_size += new_allocated_size / 2 + 1;
+ }
+
+ if (new_allocated_size > d->allocated_size) {
+ d->buffer = av_realloc(d->buffer, new_allocated_size);
+ if(d->buffer == NULL)
+ return -1234;
+ d->allocated_size = new_allocated_size;
+ }
+ memcpy(d->buffer + d->pos, buf, buf_size);
+ d->pos = new_size;
+ if (d->pos > d->size)
+ d->size = d->pos;
+ return buf_size;
+}
+
+static int dyn_packet_buf_write(void *opaque, uint8_t *buf, int buf_size)
+{
+ unsigned char buf1[4];
+ int ret;
+
+ /* packetized write: output the header */
+ buf1[0] = (buf_size >> 24);
+ buf1[1] = (buf_size >> 16);
+ buf1[2] = (buf_size >> 8);
+ buf1[3] = (buf_size);
+ ret= dyn_buf_write(opaque, buf1, 4);
+ if(ret < 0)
+ return ret;
+
+ /* then the data */
+ return dyn_buf_write(opaque, buf, buf_size);
+}
+
+static offset_t dyn_buf_seek(void *opaque, offset_t offset, int whence)
+{
+ DynBuffer *d = opaque;
+
+ if (whence == SEEK_CUR)
+ offset += d->pos;
+ else if (whence == SEEK_END)
+ offset += d->size;
+ if (offset < 0 || offset > 0x7fffffffLL)
+ return -1;
+ d->pos = offset;
+ return 0;
+}
+
+static int url_open_dyn_buf_internal(ByteIOContext *s, int max_packet_size)
+{
+ DynBuffer *d;
+ int io_buffer_size, ret;
+
+ if (max_packet_size)
+ io_buffer_size = max_packet_size;
+ else
+ io_buffer_size = 1024;
+
+ if(sizeof(DynBuffer) + io_buffer_size < io_buffer_size)
+ return -1;
+ d = av_malloc(sizeof(DynBuffer) + io_buffer_size);
+ if (!d)
+ return -1;
+ d->io_buffer_size = io_buffer_size;
+ d->buffer = NULL;
+ d->pos = 0;
+ d->size = 0;
+ d->allocated_size = 0;
+ ret = init_put_byte(s, d->io_buffer, io_buffer_size,
+ 1, d, NULL,
+ max_packet_size ? dyn_packet_buf_write : dyn_buf_write,
+ max_packet_size ? NULL : dyn_buf_seek);
+ if (ret == 0) {
+ s->max_packet_size = max_packet_size;
+ }
+ return ret;
+}
+
+/*
+ * Open a write only memory stream.
+ *
+ * @param s new IO context
+ * @return zero if no error.
+ */
+int url_open_dyn_buf(ByteIOContext *s)
+{
+ return url_open_dyn_buf_internal(s, 0);
+}
+
+/*
+ * Open a write only packetized memory stream with a maximum packet
+ * size of 'max_packet_size'. The stream is stored in a memory buffer
+ * with a big endian 4 byte header giving the packet size in bytes.
+ *
+ * @param s new IO context
+ * @param max_packet_size maximum packet size (must be > 0)
+ * @return zero if no error.
+ */
+int url_open_dyn_packet_buf(ByteIOContext *s, int max_packet_size)
+{
+ if (max_packet_size <= 0)
+ return -1;
+ return url_open_dyn_buf_internal(s, max_packet_size);
+}
+
+/*
+ * Return the written size and a pointer to the buffer. The buffer
+ * must be freed with av_free().
+ * @param s IO context
+ * @param pointer to a byte buffer
+ * @return the length of the byte buffer
+ */
+int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer)
+{
+ DynBuffer *d = s->opaque;
+ int size;
+
+ put_flush_packet(s);
+
+ *pbuffer = d->buffer;
+ size = d->size;
+ av_free(d);
+ return size;
+}
+#endif /* CONFIG_MUXERS || CONFIG_NETWORK */
diff --git a/contrib/ffmpeg/libavformat/avisynth.c b/contrib/ffmpeg/libavformat/avisynth.c
new file mode 100644
index 000000000..1afcdea5e
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/avisynth.c
@@ -0,0 +1,222 @@
+/*
+ * AVISynth support for ffmpeg system
+ * Copyright (c) 2006 DivX, 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
+ */
+
+#include "avformat.h"
+#include "riff.h"
+
+#include <windows.h>
+#include <vfw.h>
+
+typedef struct {
+ PAVISTREAM handle;
+ AVISTREAMINFO info;
+ DWORD read;
+ LONG chunck_size;
+ LONG chunck_samples;
+} AVISynthStream;
+
+typedef struct {
+ PAVIFILE file;
+ AVISynthStream *streams;
+ int nb_streams;
+ int next_stream;
+} AVISynthContext;
+
+static int avisynth_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ AVISynthContext *avs = s->priv_data;
+ HRESULT res;
+ AVIFILEINFO info;
+ DWORD id;
+ AVStream *st;
+ AVISynthStream *stream;
+
+ AVIFileInit();
+
+ res = AVIFileOpen(&avs->file, s->filename, OF_READ|OF_SHARE_DENY_WRITE, NULL);
+ if (res != S_OK)
+ {
+ av_log(s, AV_LOG_ERROR, "AVIFileOpen failed with error %ld", res);
+ AVIFileExit();
+ return -1;
+ }
+
+ res = AVIFileInfo(avs->file, &info, sizeof(info));
+ if (res != S_OK)
+ {
+ av_log(s, AV_LOG_ERROR, "AVIFileInfo failed with error %ld", res);
+ AVIFileExit();
+ return -1;
+ }
+
+ avs->streams = av_mallocz(info.dwStreams * sizeof(AVISynthStream));
+
+ for (id=0; id<info.dwStreams; id++)
+ {
+ stream = &avs->streams[id];
+ stream->read = 0;
+ if (AVIFileGetStream(avs->file, &stream->handle, 0, id) == S_OK)
+ {
+ if (AVIStreamInfo(stream->handle, &stream->info, sizeof(stream->info)) == S_OK)
+ {
+ if (stream->info.fccType == streamtypeAUDIO)
+ {
+ WAVEFORMATEX wvfmt;
+ LONG struct_size = sizeof(WAVEFORMATEX);
+ if (AVIStreamReadFormat(stream->handle, 0, &wvfmt, &struct_size) != S_OK)
+ continue;
+
+ st = av_new_stream(s, id);
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+
+ st->codec->block_align = wvfmt.nBlockAlign;
+ st->codec->channels = wvfmt.nChannels;
+ st->codec->sample_rate = wvfmt.nSamplesPerSec;
+ st->codec->bit_rate = wvfmt.nAvgBytesPerSec * 8;
+ st->codec->bits_per_sample = wvfmt.wBitsPerSample;
+
+ stream->chunck_samples = wvfmt.nSamplesPerSec * (uint64_t)info.dwScale / (uint64_t)info.dwRate;
+ stream->chunck_size = stream->chunck_samples * wvfmt.nChannels * wvfmt.wBitsPerSample / 8;
+
+ st->codec->codec_tag = wvfmt.wFormatTag;
+ st->codec->codec_id = wav_codec_get_id(wvfmt.wFormatTag, st->codec->bits_per_sample);
+ }
+ else if (stream->info.fccType == streamtypeVIDEO)
+ {
+ BITMAPINFO imgfmt;
+ LONG struct_size = sizeof(BITMAPINFO);
+
+ stream->chunck_size = stream->info.dwSampleSize;
+ stream->chunck_samples = 1;
+
+ if (AVIStreamReadFormat(stream->handle, 0, &imgfmt, &struct_size) != S_OK)
+ continue;
+
+ st = av_new_stream(s, id);
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->r_frame_rate.num = stream->info.dwRate;
+ st->r_frame_rate.den = stream->info.dwScale;
+
+ st->codec->width = imgfmt.bmiHeader.biWidth;
+ st->codec->height = imgfmt.bmiHeader.biHeight;
+
+ st->codec->bits_per_sample = imgfmt.bmiHeader.biBitCount;
+ st->codec->bit_rate = (uint64_t)stream->info.dwSampleSize * (uint64_t)stream->info.dwRate * 8 / (uint64_t)stream->info.dwScale;
+ st->codec->codec_tag = imgfmt.bmiHeader.biCompression;
+ st->codec->codec_id = codec_get_id(codec_bmp_tags, imgfmt.bmiHeader.biCompression);
+
+ st->duration = stream->info.dwLength;
+ }
+ else
+ {
+ AVIStreamRelease(stream->handle);
+ continue;
+ }
+
+ avs->nb_streams++;
+
+ st->codec->stream_codec_tag = stream->info.fccHandler;
+
+ av_set_pts_info(st, 64, info.dwScale, info.dwRate);
+ st->start_time = stream->info.dwStart;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int avisynth_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ AVISynthContext *avs = s->priv_data;
+ HRESULT res;
+ AVISynthStream *stream;
+ int stream_id = avs->next_stream;
+ LONG read_size;
+
+ // handle interleaving manually...
+ stream = &avs->streams[stream_id];
+
+ if (stream->read >= stream->info.dwLength)
+ return AVERROR_IO;
+
+ if (av_new_packet(pkt, stream->chunck_size))
+ return AVERROR_IO;
+ pkt->stream_index = stream_id;
+ pkt->pts = avs->streams[stream_id].read / avs->streams[stream_id].chunck_samples;
+
+ res = AVIStreamRead(stream->handle, stream->read, stream->chunck_samples, pkt->data, stream->chunck_size, &read_size, NULL);
+
+ pkt->pts = stream->read;
+ pkt->size = read_size;
+
+ stream->read += stream->chunck_samples;
+
+ // prepare for the next stream to read
+ do {
+ avs->next_stream = (avs->next_stream+1) % avs->nb_streams;
+ } while (avs->next_stream != stream_id && s->streams[avs->next_stream]->discard >= AVDISCARD_ALL);
+
+ return (res == S_OK) ? pkt->size : -1;
+}
+
+static int avisynth_read_close(AVFormatContext *s)
+{
+ AVISynthContext *avs = s->priv_data;
+ int i;
+
+ for (i=0;i<avs->nb_streams;i++)
+ {
+ AVIStreamRelease(avs->streams[i].handle);
+ }
+
+ av_free(avs->streams);
+ AVIFileRelease(avs->file);
+ AVIFileExit();
+ return 0;
+}
+
+static int avisynth_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags)
+{
+ AVISynthContext *avs = s->priv_data;
+ int stream_id;
+
+ for (stream_id = 0; stream_id < avs->nb_streams; stream_id++)
+ {
+ avs->streams[stream_id].read = pts * avs->streams[stream_id].chunck_samples;
+ }
+
+ return 0;
+}
+
+AVInputFormat avisynth_demuxer = {
+ "avs",
+ "AVISynth",
+ sizeof(AVISynthContext),
+ NULL,
+ avisynth_read_header,
+ avisynth_read_packet,
+ avisynth_read_close,
+ avisynth_read_seek,
+ NULL,
+ 0,
+ "avs",
+};
diff --git a/contrib/ffmpeg/libavformat/avs.c b/contrib/ffmpeg/libavformat/avs.c
new file mode 100644
index 000000000..0fa77deff
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/avs.c
@@ -0,0 +1,227 @@
+/*
+ * AVS demuxer.
+ * Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avformat.h"
+#include "voc.h"
+
+
+typedef struct avs_format {
+ voc_dec_context_t voc;
+ AVStream *st_video;
+ AVStream *st_audio;
+ int width;
+ int height;
+ int bits_per_sample;
+ int fps;
+ int nb_frames;
+ int remaining_frame_size;
+ int remaining_audio_size;
+} avs_format_t;
+
+typedef enum avs_block_type {
+ AVS_VIDEO = 0x01,
+ AVS_AUDIO = 0x02,
+ AVS_PALETTE = 0x03,
+ AVS_GAME_DATA = 0x04,
+} avs_block_type_t;
+
+static int avs_probe(AVProbeData * p)
+{
+ const uint8_t *d;
+
+ if (p->buf_size < 2)
+ return 0;
+ d = p->buf;
+ if (d[0] == 'w' && d[1] == 'W' && d[2] == 0x10 && d[3] == 0)
+ return 50;
+
+ return 0;
+}
+
+static int avs_read_header(AVFormatContext * s, AVFormatParameters * ap)
+{
+ avs_format_t *avs = s->priv_data;
+
+ s->ctx_flags |= AVFMTCTX_NOHEADER;
+
+ url_fskip(&s->pb, 4);
+ avs->width = get_le16(&s->pb);
+ avs->height = get_le16(&s->pb);
+ avs->bits_per_sample = get_le16(&s->pb);
+ avs->fps = get_le16(&s->pb);
+ avs->nb_frames = get_le32(&s->pb);
+ avs->remaining_frame_size = 0;
+ avs->remaining_audio_size = 0;
+
+ avs->st_video = avs->st_audio = NULL;
+
+ if (avs->width != 318 || avs->height != 198)
+ av_log(s, AV_LOG_ERROR, "This avs pretend to be %dx%d "
+ "when the avs format is supposed to be 318x198 only.\n",
+ avs->width, avs->height);
+
+ return 0;
+}
+
+static int
+avs_read_video_packet(AVFormatContext * s, AVPacket * pkt,
+ avs_block_type_t type, int sub_type, int size,
+ uint8_t * palette, int palette_size)
+{
+ avs_format_t *avs = s->priv_data;
+ int ret;
+
+ ret = av_new_packet(pkt, size + palette_size);
+ if (ret < 0)
+ return ret;
+
+ if (palette_size) {
+ pkt->data[0] = 0x00;
+ pkt->data[1] = 0x03;
+ pkt->data[2] = palette_size & 0xFF;
+ pkt->data[3] = (palette_size >> 8) & 0xFF;
+ memcpy(pkt->data + 4, palette, palette_size - 4);
+ }
+
+ pkt->data[palette_size + 0] = sub_type;
+ pkt->data[palette_size + 1] = type;
+ pkt->data[palette_size + 2] = size & 0xFF;
+ pkt->data[palette_size + 3] = (size >> 8) & 0xFF;
+ ret = get_buffer(&s->pb, pkt->data + palette_size + 4, size - 4) + 4;
+ if (ret < size) {
+ av_free_packet(pkt);
+ return AVERROR_IO;
+ }
+
+ pkt->size = ret + palette_size;
+ pkt->stream_index = avs->st_video->index;
+ if (sub_type == 0)
+ pkt->flags |= PKT_FLAG_KEY;
+
+ return 0;
+}
+
+static int avs_read_audio_packet(AVFormatContext * s, AVPacket * pkt)
+{
+ avs_format_t *avs = s->priv_data;
+ int ret, size;
+
+ size = url_ftell(&s->pb);
+ ret = voc_get_packet(s, pkt, avs->st_audio, avs->remaining_audio_size);
+ size = url_ftell(&s->pb) - size;
+ avs->remaining_audio_size -= size;
+
+ if (ret == AVERROR_IO)
+ return 0; /* this indicate EOS */
+ if (ret < 0)
+ return ret;
+
+ pkt->stream_index = avs->st_audio->index;
+ pkt->flags |= PKT_FLAG_KEY;
+
+ return size;
+}
+
+static int avs_read_packet(AVFormatContext * s, AVPacket * pkt)
+{
+ avs_format_t *avs = s->priv_data;
+ int sub_type = 0, size = 0;
+ avs_block_type_t type = 0;
+ int palette_size = 0;
+ uint8_t palette[4 + 3 * 256];
+ int ret;
+
+ if (avs->remaining_audio_size > 0)
+ if (avs_read_audio_packet(s, pkt) > 0)
+ return 0;
+
+ while (1) {
+ if (avs->remaining_frame_size <= 0) {
+ if (!get_le16(&s->pb)) /* found EOF */
+ return AVERROR_IO;
+ avs->remaining_frame_size = get_le16(&s->pb) - 4;
+ }
+
+ while (avs->remaining_frame_size > 0) {
+ sub_type = get_byte(&s->pb);
+ type = get_byte(&s->pb);
+ size = get_le16(&s->pb);
+ avs->remaining_frame_size -= size;
+
+ switch (type) {
+ case AVS_PALETTE:
+ ret = get_buffer(&s->pb, palette, size - 4);
+ if (ret < size - 4)
+ return AVERROR_IO;
+ palette_size = size;
+ break;
+
+ case AVS_VIDEO:
+ if (!avs->st_video) {
+ avs->st_video = av_new_stream(s, AVS_VIDEO);
+ if (avs->st_video == NULL)
+ return AVERROR_NOMEM;
+ avs->st_video->codec->codec_type = CODEC_TYPE_VIDEO;
+ avs->st_video->codec->codec_id = CODEC_ID_AVS;
+ avs->st_video->codec->width = avs->width;
+ avs->st_video->codec->height = avs->height;
+ avs->st_video->codec->bits_per_sample=avs->bits_per_sample;
+ avs->st_video->nb_frames = avs->nb_frames;
+ avs->st_video->codec->time_base = (AVRational) {
+ 1, avs->fps};
+ }
+ return avs_read_video_packet(s, pkt, type, sub_type, size,
+ palette, palette_size);
+
+ case AVS_AUDIO:
+ if (!avs->st_audio) {
+ avs->st_audio = av_new_stream(s, AVS_AUDIO);
+ if (avs->st_audio == NULL)
+ return AVERROR_NOMEM;
+ avs->st_audio->codec->codec_type = CODEC_TYPE_AUDIO;
+ }
+ avs->remaining_audio_size = size - 4;
+ size = avs_read_audio_packet(s, pkt);
+ if (size != 0)
+ return size;
+ break;
+
+ default:
+ url_fskip(&s->pb, size - 4);
+ }
+ }
+ }
+}
+
+static int avs_read_close(AVFormatContext * s)
+{
+ return 0;
+}
+
+AVInputFormat avs_demuxer = {
+ "avs",
+ "avs format",
+ sizeof(avs_format_t),
+ avs_probe,
+ avs_read_header,
+ avs_read_packet,
+ avs_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/barpainet.h b/contrib/ffmpeg/libavformat/barpainet.h
new file mode 100644
index 000000000..b50bf82b6
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/barpainet.h
@@ -0,0 +1,45 @@
+/*
+ * copyright (c) 2002 Francois Revol
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 BARPA_INET_H
+#define BARPA_INET_H
+
+#include "config.h"
+
+#ifdef CONFIG_BEOS_NETSERVER
+
+# include <socket.h>
+int inet_aton (const char * str, struct in_addr * add);
+# define PF_INET AF_INET
+# define SO_SNDBUF 0x40000001
+
+/* fake */
+struct ip_mreq {
+ struct in_addr imr_multiaddr; /* IP multicast address of group */
+ struct in_addr imr_interface; /* local IP address of interface */
+};
+
+#include <netdb.h>
+
+#else
+# include <arpa/inet.h>
+#endif
+
+#endif /* BARPA_INET_H */
diff --git a/contrib/ffmpeg/libavformat/base64.c b/contrib/ffmpeg/libavformat/base64.c
new file mode 100644
index 000000000..6279244d3
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/base64.c
@@ -0,0 +1,231 @@
+/*
+ * Base64.c
+ * Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.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 base64.c
+ * @brief Base64 Encode/Decode
+ * @author Ryan Martell <rdm4@martellventures.com> (with lots of Michael)
+ */
+
+#include "common.h"
+#include "base64.h"
+
+/* ---------------- private code */
+static uint8_t map2[] =
+{
+ 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36,
+ 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 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,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 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
+};
+
+int av_base64_decode(uint8_t * out, const char *in, int out_length)
+{
+ int i, v;
+ uint8_t *dst = out;
+
+ v = 0;
+ for (i = 0; in[i] && in[i] != '='; i++) {
+ unsigned int index= in[i]-43;
+ if (index>=(sizeof(map2)/sizeof(map2[0])) || map2[index] == 0xff)
+ return -1;
+ v = (v << 6) + map2[index];
+ if (i & 3) {
+ if (dst - out < out_length) {
+ *dst++ = v >> (6 - 2 * (i & 3));
+ }
+ }
+ }
+
+ return (dst - out);
+}
+
+/*****************************************************************************
+* b64_encode: stolen from VLC's http.c
+* simplified by michael
+* fixed edge cases and made it work from data (vs. strings) by ryan.
+*****************************************************************************/
+
+char *av_base64_encode(uint8_t * src, int len)
+{
+ static const char b64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ char *ret, *dst;
+ unsigned i_bits = 0;
+ int i_shift = 0;
+ int bytes_remaining = len;
+
+ if (len < UINT_MAX / 4) {
+ ret = dst = av_malloc(len * 4 / 3 + 12);
+ } else
+ return NULL;
+
+ if (len) { // special edge case, what should we really do here?
+ while (bytes_remaining) {
+ i_bits = (i_bits << 8) + *src++;
+ bytes_remaining--;
+ i_shift += 8;
+
+ do {
+ *dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f];
+ i_shift -= 6;
+ } while (i_shift > 6 || (bytes_remaining == 0 && i_shift > 0));
+ }
+ while ((dst - ret) & 3)
+ *dst++ = '=';
+ }
+ *dst = '\0';
+
+ return ret;
+}
+
+// #define TEST_BASE64
+
+#ifdef TEST_BASE64
+#include "avutil.h"
+
+int b64test()
+{
+ int numerr = 0;
+ int len;
+ int numtest = 1;
+ uint8_t decode[1000];
+ struct test {
+ void *data;
+ int len;
+ const char *result;
+ } *t, tests[] = {
+ {
+ "", 0, ""}, {
+ "1", 1, "MQ=="}, {
+ "22", 2, "MjI="}, {
+ "333", 3, "MzMz"}, {
+ "4444", 4, "NDQ0NA=="}, {
+ "55555", 5, "NTU1NTU="}, {
+ "abc:def", 7, "YWJjOmRlZg=="}, {
+ NULL}
+ };
+ for (t = tests; t->data; t++) {
+ char *str;
+
+ av_log(NULL, AV_LOG_ERROR, "Encoding %s...\n", (char *) t->data);
+ str = av_base64_encode(t->data, t->len);
+ if (str) {
+ av_log(NULL, AV_LOG_ERROR, "Encoded to %s...\n", str);
+ if (strcmp(str, t->result) != 0) {
+ av_log(NULL, AV_LOG_ERROR, "failed test %d: %s != %s\n",
+ numtest, str, t->result);
+ numerr++;
+ }
+ av_free(str);
+ }
+
+ av_log(NULL, AV_LOG_ERROR, "Done encoding, about to decode...\n");
+ len = av_base64_decode(decode, t->result, sizeof(decode));
+ if (len != t->len) {
+ av_log(NULL, AV_LOG_ERROR, "failed test %d: len %d != %d\n",
+ numtest, len, t->len);
+ numerr++;
+ } else if (memcmp(decode, t->data, t->len) != 0) {
+ av_log(NULL, AV_LOG_ERROR, "failed test %d: data\n", numtest);
+ numerr++;
+ } else {
+ av_log(NULL, AV_LOG_ERROR, "Decoded to %s\n",
+ (char *) t->data);
+ }
+ numtest++;
+ }
+
+#undef srand
+#undef rand
+
+ {
+ int test_count;
+ srand(123141); // time(NULL));
+ for (test_count = 0; test_count < 100; test_count++) {
+ int size = rand() % 1024;
+ int ii;
+ uint8_t *data;
+ char *encoded_result;
+
+ av_log(NULL, AV_LOG_ERROR, "Test %d: Size %d bytes...",
+ test_count, size);
+ data = (uint8_t *) av_malloc(size);
+ for (ii = 0; ii < size; ii++) {
+ data[ii] = rand() % 255;
+ }
+
+ encoded_result = av_base64_encode(data, size);
+ if (encoded_result) {
+ int decode_buffer_size = size + 10; // try without 10 as well
+ uint8_t *decode_buffer = av_malloc(decode_buffer_size);
+ if (decode_buffer) {
+ int decoded_size =
+ av_base64_decode(decode_buffer, encoded_result,
+ decode_buffer_size);
+
+ if (decoded_size != size) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Decoded/Encoded size mismatch (%d != %d)\n",
+ decoded_size, size);
+ } else {
+ if (memcmp(decode_buffer, data, decoded_size) == 0) {
+ av_log(NULL, AV_LOG_ERROR, "Passed!\n");
+ } else {
+ av_log(NULL, AV_LOG_ERROR,
+ "Failed (Data differs)!\n");
+ }
+ }
+ av_free(decode_buffer);
+ }
+
+ av_free(encoded_result);
+ }
+ }
+ }
+
+ // these are invalid strings, that it currently decodes (which it probably shouldn't?)
+ {
+ uint8_t str[32];
+ if (av_base64_decode(str, "M=M=", sizeof(str)) != -1) {
+ av_log(NULL, AV_LOG_ERROR,
+ "failed test %d: successful decode of `M=M='\n",
+ numtest++);
+ numerr++;
+ }
+ if (av_base64_decode(str, "MQ===", sizeof(str)) != -1) {
+ av_log(NULL, AV_LOG_ERROR,
+ "failed test %d: successful decode of `MQ==='\n",
+ numtest++);
+ numerr++;
+ }
+ }
+
+ return numerr;
+}
+#endif
+
diff --git a/contrib/ffmpeg/libavformat/base64.h b/contrib/ffmpeg/libavformat/base64.h
new file mode 100644
index 000000000..03d43afe4
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/base64.h
@@ -0,0 +1,24 @@
+/*
+ * Base64.c
+ * Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.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
+ */
+
+int av_base64_decode(uint8_t * out, const char *in, int out_length); // param order as strncpy()
+char *av_base64_encode(uint8_t * src, int len); // src is not a string, it's data.
+
diff --git a/contrib/ffmpeg/libavformat/beosaudio.cpp b/contrib/ffmpeg/libavformat/beosaudio.cpp
new file mode 100644
index 000000000..6ac45ebb2
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/beosaudio.cpp
@@ -0,0 +1,465 @@
+/*
+ * BeOS audio play interface
+ * 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 <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include <Application.h>
+#include <SoundPlayer.h>
+
+extern "C" {
+#include "avformat.h"
+}
+
+#ifdef HAVE_BSOUNDRECORDER
+#include <SoundRecorder.h>
+using namespace BPrivate::Media::Experimental;
+#endif
+
+/* enable performance checks */
+//#define PERF_CHECK
+
+/* enable Media Kit latency checks */
+//#define LATENCY_CHECK
+
+#define AUDIO_BLOCK_SIZE 4096
+#define AUDIO_BLOCK_COUNT 8
+
+#define AUDIO_BUFFER_SIZE (AUDIO_BLOCK_SIZE*AUDIO_BLOCK_COUNT)
+
+typedef struct {
+ int fd; // UNUSED
+ int sample_rate;
+ int channels;
+ int frame_size; /* in bytes ! */
+ CodecID codec_id;
+ uint8_t buffer[AUDIO_BUFFER_SIZE];
+ int buffer_ptr;
+ /* ring buffer */
+ sem_id input_sem;
+ int input_index;
+ sem_id output_sem;
+ int output_index;
+ BSoundPlayer *player;
+#ifdef HAVE_BSOUNDRECORDER
+ BSoundRecorder *recorder;
+#endif
+ int has_quit; /* signal callbacks not to wait */
+ volatile bigtime_t starve_time;
+} AudioData;
+
+static thread_id main_thid;
+static thread_id bapp_thid;
+static int own_BApp_created = 0;
+static int refcount = 0;
+
+/* create the BApplication and Run() it */
+static int32 bapp_thread(void *arg)
+{
+ new BApplication("application/x-vnd.ffmpeg");
+ own_BApp_created = 1;
+ be_app->Run();
+ /* kill the process group */
+// kill(0, SIGINT);
+// kill(main_thid, SIGHUP);
+ return B_OK;
+}
+
+/* create the BApplication only if needed */
+static void create_bapp_if_needed(void)
+{
+ if (refcount++ == 0) {
+ /* needed by libmedia */
+ if (be_app == NULL) {
+ bapp_thid = spawn_thread(bapp_thread, "ffmpeg BApplication", B_NORMAL_PRIORITY, NULL);
+ resume_thread(bapp_thid);
+ while (!own_BApp_created)
+ snooze(50000);
+ }
+ }
+}
+
+static void destroy_bapp_if_needed(void)
+{
+ if (--refcount == 0 && own_BApp_created) {
+ be_app->Lock();
+ be_app->Quit();
+ be_app = NULL;
+ }
+}
+
+/* called back by BSoundPlayer */
+static void audioplay_callback(void *cookie, void *buffer, size_t bufferSize, const media_raw_audio_format &format)
+{
+ AudioData *s;
+ size_t len, amount;
+ unsigned char *buf = (unsigned char *)buffer;
+
+ s = (AudioData *)cookie;
+ if (s->has_quit)
+ return;
+ while (bufferSize > 0) {
+#ifdef PERF_CHECK
+ bigtime_t t;
+ t = system_time();
+#endif
+ len = MIN(AUDIO_BLOCK_SIZE, bufferSize);
+ if (acquire_sem_etc(s->output_sem, len, B_CAN_INTERRUPT, 0LL) < B_OK) {
+ s->has_quit = 1;
+ s->player->SetHasData(false);
+ return;
+ }
+ amount = MIN(len, (AUDIO_BUFFER_SIZE - s->output_index));
+ memcpy(buf, &s->buffer[s->output_index], amount);
+ s->output_index += amount;
+ if (s->output_index >= AUDIO_BUFFER_SIZE) {
+ s->output_index %= AUDIO_BUFFER_SIZE;
+ memcpy(buf + amount, &s->buffer[s->output_index], len - amount);
+ s->output_index += len-amount;
+ s->output_index %= AUDIO_BUFFER_SIZE;
+ }
+ release_sem_etc(s->input_sem, len, 0);
+#ifdef PERF_CHECK
+ t = system_time() - t;
+ s->starve_time = MAX(s->starve_time, t);
+#endif
+ buf += len;
+ bufferSize -= len;
+ }
+}
+
+#ifdef HAVE_BSOUNDRECORDER
+/* called back by BSoundRecorder */
+static void audiorecord_callback(void *cookie, bigtime_t timestamp, void *buffer, size_t bufferSize, const media_multi_audio_format &format)
+{
+ AudioData *s;
+ size_t len, amount;
+ unsigned char *buf = (unsigned char *)buffer;
+
+ s = (AudioData *)cookie;
+ if (s->has_quit)
+ return;
+
+ while (bufferSize > 0) {
+ len = MIN(bufferSize, AUDIO_BLOCK_SIZE);
+ //printf("acquire_sem(input, %d)\n", len);
+ if (acquire_sem_etc(s->input_sem, len, B_CAN_INTERRUPT, 0LL) < B_OK) {
+ s->has_quit = 1;
+ return;
+ }
+ amount = MIN(len, (AUDIO_BUFFER_SIZE - s->input_index));
+ memcpy(&s->buffer[s->input_index], buf, amount);
+ s->input_index += amount;
+ if (s->input_index >= AUDIO_BUFFER_SIZE) {
+ s->input_index %= AUDIO_BUFFER_SIZE;
+ memcpy(&s->buffer[s->input_index], buf + amount, len - amount);
+ s->input_index += len - amount;
+ }
+ release_sem_etc(s->output_sem, len, 0);
+ //printf("release_sem(output, %d)\n", len);
+ buf += len;
+ bufferSize -= len;
+ }
+}
+#endif
+
+static int audio_open(AudioData *s, int is_output, const char *audio_device)
+{
+ int p[2];
+ int ret;
+ media_raw_audio_format format;
+ media_multi_audio_format iformat;
+
+#ifndef HAVE_BSOUNDRECORDER
+ if (!is_output)
+ return -EIO; /* not for now */
+#endif
+ s->input_sem = create_sem(AUDIO_BUFFER_SIZE, "ffmpeg_ringbuffer_input");
+ if (s->input_sem < B_OK)
+ return -EIO;
+ s->output_sem = create_sem(0, "ffmpeg_ringbuffer_output");
+ if (s->output_sem < B_OK) {
+ delete_sem(s->input_sem);
+ return -EIO;
+ }
+ s->input_index = 0;
+ s->output_index = 0;
+ create_bapp_if_needed();
+ s->frame_size = AUDIO_BLOCK_SIZE;
+ /* bump up the priority (avoid realtime though) */
+ set_thread_priority(find_thread(NULL), B_DISPLAY_PRIORITY+1);
+#ifdef HAVE_BSOUNDRECORDER
+ if (!is_output) {
+ bool wait_for_input = false;
+ if (audio_device && !strcmp(audio_device, "wait:"))
+ wait_for_input = true;
+ s->recorder = new BSoundRecorder(&iformat, wait_for_input, "ffmpeg input", audiorecord_callback);
+ if (wait_for_input && (s->recorder->InitCheck() == B_OK)) {
+ s->recorder->WaitForIncomingConnection(&iformat);
+ }
+ if (s->recorder->InitCheck() != B_OK || iformat.format != media_raw_audio_format::B_AUDIO_SHORT) {
+ delete s->recorder;
+ s->recorder = NULL;
+ if (s->input_sem)
+ delete_sem(s->input_sem);
+ if (s->output_sem)
+ delete_sem(s->output_sem);
+ return -EIO;
+ }
+ s->codec_id = (iformat.byte_order == B_MEDIA_LITTLE_ENDIAN)?CODEC_ID_PCM_S16LE:CODEC_ID_PCM_S16BE;
+ s->channels = iformat.channel_count;
+ s->sample_rate = (int)iformat.frame_rate;
+ s->frame_size = iformat.buffer_size;
+ s->recorder->SetCookie(s);
+ s->recorder->SetVolume(1.0);
+ s->recorder->Start();
+ return 0;
+ }
+#endif
+ format = media_raw_audio_format::wildcard;
+ format.format = media_raw_audio_format::B_AUDIO_SHORT;
+ format.byte_order = B_HOST_IS_LENDIAN ? B_MEDIA_LITTLE_ENDIAN : B_MEDIA_BIG_ENDIAN;
+ format.channel_count = s->channels;
+ format.buffer_size = s->frame_size;
+ format.frame_rate = s->sample_rate;
+ s->player = new BSoundPlayer(&format, "ffmpeg output", audioplay_callback);
+ if (s->player->InitCheck() != B_OK) {
+ delete s->player;
+ s->player = NULL;
+ if (s->input_sem)
+ delete_sem(s->input_sem);
+ if (s->output_sem)
+ delete_sem(s->output_sem);
+ return -EIO;
+ }
+ s->player->SetCookie(s);
+ s->player->SetVolume(1.0);
+ s->player->Start();
+ s->player->SetHasData(true);
+ return 0;
+}
+
+static int audio_close(AudioData *s)
+{
+ if (s->input_sem)
+ delete_sem(s->input_sem);
+ if (s->output_sem)
+ delete_sem(s->output_sem);
+ s->has_quit = 1;
+ if (s->player) {
+ s->player->Stop();
+ }
+ if (s->player)
+ delete s->player;
+#ifdef HAVE_BSOUNDRECORDER
+ if (s->recorder)
+ delete s->recorder;
+#endif
+ destroy_bapp_if_needed();
+ return 0;
+}
+
+/* sound output support */
+static int audio_write_header(AVFormatContext *s1)
+{
+ AudioData *s = (AudioData *)s1->priv_data;
+ AVStream *st;
+ int ret;
+
+ st = s1->streams[0];
+ s->sample_rate = st->codec->sample_rate;
+ s->channels = st->codec->channels;
+ ret = audio_open(s, 1, NULL);
+ if (ret < 0)
+ return -EIO;
+ return 0;
+}
+
+static int audio_write_packet(AVFormatContext *s1, int stream_index,
+ const uint8_t *buf, int size, int64_t force_pts)
+{
+ AudioData *s = (AudioData *)s1->priv_data;
+ int len, ret;
+#ifdef LATENCY_CHECK
+bigtime_t lat1, lat2;
+lat1 = s->player->Latency();
+#endif
+#ifdef PERF_CHECK
+ bigtime_t t = s->starve_time;
+ s->starve_time = 0;
+ printf("starve_time: %lld \n", t);
+#endif
+ while (size > 0) {
+ int amount;
+ len = MIN(size, AUDIO_BLOCK_SIZE);
+ if (acquire_sem_etc(s->input_sem, len, B_CAN_INTERRUPT, 0LL) < B_OK)
+ return -EIO;
+ amount = MIN(len, (AUDIO_BUFFER_SIZE - s->input_index));
+ memcpy(&s->buffer[s->input_index], buf, amount);
+ s->input_index += amount;
+ if (s->input_index >= AUDIO_BUFFER_SIZE) {
+ s->input_index %= AUDIO_BUFFER_SIZE;
+ memcpy(&s->buffer[s->input_index], buf + amount, len - amount);
+ s->input_index += len - amount;
+ }
+ release_sem_etc(s->output_sem, len, 0);
+ buf += len;
+ size -= len;
+ }
+#ifdef LATENCY_CHECK
+lat2 = s->player->Latency();
+printf("#### BSoundPlayer::Latency(): before= %lld, after= %lld\n", lat1, lat2);
+#endif
+ return 0;
+}
+
+static int audio_write_trailer(AVFormatContext *s1)
+{
+ AudioData *s = (AudioData *)s1->priv_data;
+
+ audio_close(s);
+ return 0;
+}
+
+/* grab support */
+
+static int audio_read_header(AVFormatContext *s1, AVFormatParameters *ap)
+{
+ AudioData *s = (AudioData *)s1->priv_data;
+ AVStream *st;
+ int ret;
+
+ if (!ap || ap->sample_rate <= 0 || ap->channels <= 0)
+ return -1;
+
+ st = av_new_stream(s1, 0);
+ if (!st) {
+ return -ENOMEM;
+ }
+ s->sample_rate = ap->sample_rate;
+ s->channels = ap->channels;
+
+ ret = audio_open(s, 0, ap->device);
+ if (ret < 0) {
+ av_free(st);
+ return -EIO;
+ }
+ /* take real parameters */
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = s->codec_id;
+ st->codec->sample_rate = s->sample_rate;
+ st->codec->channels = s->channels;
+ return 0;
+ av_set_pts_info(s1, 48, 1, 1000000); /* 48 bits pts in us */
+}
+
+static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
+{
+ AudioData *s = (AudioData *)s1->priv_data;
+ int size;
+ size_t len, amount;
+ unsigned char *buf;
+ status_t err;
+
+ if (av_new_packet(pkt, s->frame_size) < 0)
+ return -EIO;
+ buf = (unsigned char *)pkt->data;
+ size = pkt->size;
+ while (size > 0) {
+ len = MIN(AUDIO_BLOCK_SIZE, size);
+ //printf("acquire_sem(output, %d)\n", len);
+ while ((err=acquire_sem_etc(s->output_sem, len, B_CAN_INTERRUPT, 0LL)) == B_INTERRUPTED);
+ if (err < B_OK) {
+ av_free_packet(pkt);
+ return -EIO;
+ }
+ amount = MIN(len, (AUDIO_BUFFER_SIZE - s->output_index));
+ memcpy(buf, &s->buffer[s->output_index], amount);
+ s->output_index += amount;
+ if (s->output_index >= AUDIO_BUFFER_SIZE) {
+ s->output_index %= AUDIO_BUFFER_SIZE;
+ memcpy(buf + amount, &s->buffer[s->output_index], len - amount);
+ s->output_index += len-amount;
+ s->output_index %= AUDIO_BUFFER_SIZE;
+ }
+ release_sem_etc(s->input_sem, len, 0);
+ //printf("release_sem(input, %d)\n", len);
+ buf += len;
+ size -= len;
+ }
+ //XXX: add pts info
+ return 0;
+}
+
+static int audio_read_close(AVFormatContext *s1)
+{
+ AudioData *s = (AudioData *)s1->priv_data;
+
+ audio_close(s);
+ return 0;
+}
+
+static AVInputFormat audio_demuxer = {
+ "audio_device",
+ "audio grab and output",
+ sizeof(AudioData),
+ NULL,
+ audio_read_header,
+ audio_read_packet,
+ audio_read_close,
+ NULL,
+ AVFMT_NOFILE,
+};
+
+AVOutputFormat audio_muxer = {
+ "audio_device",
+ "audio grab and output",
+ "",
+ "",
+ sizeof(AudioData),
+#ifdef WORDS_BIGENDIAN
+ CODEC_ID_PCM_S16BE,
+#else
+ CODEC_ID_PCM_S16LE,
+#endif
+ CODEC_ID_NONE,
+ audio_write_header,
+ audio_write_packet,
+ audio_write_trailer,
+ AVFMT_NOFILE,
+};
+
+extern "C" {
+
+int audio_init(void)
+{
+ main_thid = find_thread(NULL);
+ av_register_input_format(&audio_demuxer);
+ av_register_output_format(&audio_muxer);
+ return 0;
+}
+
+} // "C"
+
diff --git a/contrib/ffmpeg/libavformat/crc.c b/contrib/ffmpeg/libavformat/crc.c
new file mode 100644
index 000000000..bdbe8bcff
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/crc.c
@@ -0,0 +1,98 @@
+/*
+ * CRC decoder (for codec/format testing)
+ * 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 "avformat.h"
+#include "adler32.h"
+
+#ifdef CONFIG_CRC_MUXER
+typedef struct CRCState {
+ uint32_t crcval;
+} CRCState;
+
+static int crc_write_header(struct AVFormatContext *s)
+{
+ CRCState *crc = s->priv_data;
+
+ /* init CRC */
+ crc->crcval = 1;
+
+ return 0;
+}
+
+static int crc_write_packet(struct AVFormatContext *s, AVPacket *pkt)
+{
+ CRCState *crc = s->priv_data;
+ crc->crcval = av_adler32_update(crc->crcval, pkt->data, pkt->size);
+ return 0;
+}
+
+static int crc_write_trailer(struct AVFormatContext *s)
+{
+ CRCState *crc = s->priv_data;
+ char buf[64];
+
+ snprintf(buf, sizeof(buf), "CRC=0x%08x\n", crc->crcval);
+ put_buffer(&s->pb, buf, strlen(buf));
+ put_flush_packet(&s->pb);
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_FRAMECRC_MUXER
+static int framecrc_write_packet(struct AVFormatContext *s, AVPacket *pkt)
+{
+ uint32_t crc = av_adler32_update(0, pkt->data, pkt->size);
+ char buf[256];
+
+ snprintf(buf, sizeof(buf), "%d, %"PRId64", %d, 0x%08x\n", pkt->stream_index, pkt->dts, pkt->size, crc);
+ put_buffer(&s->pb, buf, strlen(buf));
+ put_flush_packet(&s->pb);
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_CRC_MUXER
+AVOutputFormat crc_muxer = {
+ "crc",
+ "crc testing format",
+ NULL,
+ "",
+ sizeof(CRCState),
+ CODEC_ID_PCM_S16LE,
+ CODEC_ID_RAWVIDEO,
+ crc_write_header,
+ crc_write_packet,
+ crc_write_trailer,
+};
+#endif
+#ifdef CONFIG_FRAMECRC_MUXER
+AVOutputFormat framecrc_muxer = {
+ "framecrc",
+ "framecrc testing format",
+ NULL,
+ "",
+ 0,
+ CODEC_ID_PCM_S16LE,
+ CODEC_ID_RAWVIDEO,
+ NULL,
+ framecrc_write_packet,
+ NULL,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/cutils.c b/contrib/ffmpeg/libavformat/cutils.c
new file mode 100644
index 000000000..45959ec39
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/cutils.c
@@ -0,0 +1,275 @@
+/*
+ * Various simple utilities for ffmpeg system
+ * 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 "avformat.h"
+
+#if !defined(CONFIG_NOCUTILS)
+/**
+ * Return TRUE if val is a prefix of str. If it returns TRUE, ptr is
+ * set to the next character in 'str' after the prefix.
+ *
+ * @param str input string
+ * @param val prefix to test
+ * @param ptr updated after the prefix in str in there is a match
+ * @return TRUE if there is a match
+ */
+int strstart(const char *str, const char *val, const char **ptr)
+{
+ const char *p, *q;
+ p = str;
+ q = val;
+ while (*q != '\0') {
+ if (*p != *q)
+ return 0;
+ p++;
+ q++;
+ }
+ if (ptr)
+ *ptr = p;
+ return 1;
+}
+
+/**
+ * Return TRUE if val is a prefix of str (case independent). If it
+ * returns TRUE, ptr is set to the next character in 'str' after the
+ * prefix.
+ *
+ * @param str input string
+ * @param val prefix to test
+ * @param ptr updated after the prefix in str in there is a match
+ * @return TRUE if there is a match */
+int stristart(const char *str, const char *val, const char **ptr)
+{
+ const char *p, *q;
+ p = str;
+ q = val;
+ while (*q != '\0') {
+ if (toupper(*(const unsigned char *)p) != toupper(*(const unsigned char *)q))
+ return 0;
+ p++;
+ q++;
+ }
+ if (ptr)
+ *ptr = p;
+ return 1;
+}
+
+/**
+ * Copy the string str to buf. If str length is bigger than buf_size -
+ * 1 then it is clamped to buf_size - 1.
+ * NOTE: this function does what strncpy should have done to be
+ * useful. NEVER use strncpy.
+ *
+ * @param buf destination buffer
+ * @param buf_size size of destination buffer
+ * @param str source string
+ */
+void pstrcpy(char *buf, int buf_size, const char *str)
+{
+ int c;
+ char *q = buf;
+
+ if (buf_size <= 0)
+ return;
+
+ for(;;) {
+ c = *str++;
+ if (c == 0 || q >= buf + buf_size - 1)
+ break;
+ *q++ = c;
+ }
+ *q = '\0';
+}
+
+/* strcat and truncate. */
+char *pstrcat(char *buf, int buf_size, const char *s)
+{
+ int len;
+ len = strlen(buf);
+ if (len < buf_size)
+ pstrcpy(buf + len, buf_size - len, s);
+ return buf;
+}
+
+#endif
+
+/* add one element to a dynamic array */
+void __dynarray_add(unsigned long **tab_ptr, int *nb_ptr, unsigned long elem)
+{
+ int nb, nb_alloc;
+ unsigned long *tab;
+
+ nb = *nb_ptr;
+ tab = *tab_ptr;
+ if ((nb & (nb - 1)) == 0) {
+ if (nb == 0)
+ nb_alloc = 1;
+ else
+ nb_alloc = nb * 2;
+ tab = av_realloc(tab, nb_alloc * sizeof(unsigned long));
+ *tab_ptr = tab;
+ }
+ tab[nb++] = elem;
+ *nb_ptr = nb;
+}
+
+time_t mktimegm(struct tm *tm)
+{
+ time_t t;
+
+ int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
+
+ if (m < 3) {
+ m += 12;
+ y--;
+ }
+
+ t = 86400 *
+ (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469);
+
+ t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
+
+ return t;
+}
+
+#define ISLEAP(y) (((y) % 4 == 0) && (((y) % 100) != 0 || ((y) % 400) == 0))
+#define LEAPS_COUNT(y) ((y)/4 - (y)/100 + (y)/400)
+
+/* this is our own gmtime_r. it differs from its POSIX counterpart in a
+ couple of places, though. */
+struct tm *brktimegm(time_t secs, struct tm *tm)
+{
+ int days, y, ny, m;
+ int md[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+ days = secs / 86400;
+ secs %= 86400;
+ tm->tm_hour = secs / 3600;
+ tm->tm_min = (secs % 3600) / 60;
+ tm->tm_sec = secs % 60;
+
+ /* oh well, may be someone some day will invent a formula for this stuff */
+ y = 1970; /* start "guessing" */
+ while (days >= (ISLEAP(y)?366:365)) {
+ ny = (y + days/366);
+ days -= (ny - y) * 365 + LEAPS_COUNT(ny - 1) - LEAPS_COUNT(y - 1);
+ y = ny;
+ }
+ md[1] = ISLEAP(y)?29:28;
+ for (m=0; days >= md[m]; m++)
+ days -= md[m];
+
+ tm->tm_year = y; /* unlike gmtime_r we store complete year here */
+ tm->tm_mon = m+1; /* unlike gmtime_r tm_mon is from 1 to 12 */
+ tm->tm_mday = days+1;
+
+ return tm;
+}
+
+/* get a positive number between n_min and n_max, for a maximum length
+ of len_max. Return -1 if error. */
+static int date_get_num(const char **pp,
+ int n_min, int n_max, int len_max)
+{
+ int i, val, c;
+ const char *p;
+
+ p = *pp;
+ val = 0;
+ for(i = 0; i < len_max; i++) {
+ c = *p;
+ if (!isdigit(c))
+ break;
+ val = (val * 10) + c - '0';
+ p++;
+ }
+ /* no number read ? */
+ if (p == *pp)
+ return -1;
+ if (val < n_min || val > n_max)
+ return -1;
+ *pp = p;
+ return val;
+}
+
+/* small strptime for ffmpeg */
+const char *small_strptime(const char *p, const char *fmt,
+ struct tm *dt)
+{
+ int c, val;
+
+ for(;;) {
+ c = *fmt++;
+ if (c == '\0') {
+ return p;
+ } else if (c == '%') {
+ c = *fmt++;
+ switch(c) {
+ case 'H':
+ val = date_get_num(&p, 0, 23, 2);
+ if (val == -1)
+ return NULL;
+ dt->tm_hour = val;
+ break;
+ case 'M':
+ val = date_get_num(&p, 0, 59, 2);
+ if (val == -1)
+ return NULL;
+ dt->tm_min = val;
+ break;
+ case 'S':
+ val = date_get_num(&p, 0, 59, 2);
+ if (val == -1)
+ return NULL;
+ dt->tm_sec = val;
+ break;
+ case 'Y':
+ val = date_get_num(&p, 0, 9999, 4);
+ if (val == -1)
+ return NULL;
+ dt->tm_year = val - 1900;
+ break;
+ case 'm':
+ val = date_get_num(&p, 1, 12, 2);
+ if (val == -1)
+ return NULL;
+ dt->tm_mon = val - 1;
+ break;
+ case 'd':
+ val = date_get_num(&p, 1, 31, 2);
+ if (val == -1)
+ return NULL;
+ dt->tm_mday = val;
+ break;
+ case '%':
+ goto match;
+ default:
+ return NULL;
+ }
+ } else {
+ match:
+ if (c != *p)
+ return NULL;
+ p++;
+ }
+ }
+ return p;
+}
+
diff --git a/contrib/ffmpeg/libavformat/daud.c b/contrib/ffmpeg/libavformat/daud.c
new file mode 100644
index 000000000..ec81b7b1c
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/daud.c
@@ -0,0 +1,58 @@
+/*
+ * D-Cinema audio demuxer
+ * Copyright (c) 2005 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 "avformat.h"
+
+static int daud_header(AVFormatContext *s, AVFormatParameters *ap) {
+ AVStream *st = av_new_stream(s, 0);
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_PCM_S24DAUD;
+ st->codec->codec_tag = MKTAG('d', 'a', 'u', 'd');
+ st->codec->channels = 6;
+ st->codec->sample_rate = 96000;
+ st->codec->bit_rate = 3 * 6 * 96000 * 8;
+ st->codec->block_align = 3 * 6;
+ st->codec->bits_per_sample = 24;
+ return 0;
+}
+
+static int daud_packet(AVFormatContext *s, AVPacket *pkt) {
+ ByteIOContext *pb = &s->pb;
+ int ret, size;
+ if (url_feof(pb))
+ return AVERROR_IO;
+ size = get_be16(pb);
+ get_be16(pb); // unknown
+ ret = av_get_packet(pb, pkt, size);
+ pkt->stream_index = 0;
+ return ret;
+}
+
+AVInputFormat daud_demuxer = {
+ "daud",
+ "D-Cinema audio format",
+ 0,
+ NULL,
+ daud_header,
+ daud_packet,
+ NULL,
+ NULL,
+ .extensions = "302",
+};
diff --git a/contrib/ffmpeg/libavformat/dc1394.c b/contrib/ffmpeg/libavformat/dc1394.c
new file mode 100644
index 000000000..5098c0fdf
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/dc1394.c
@@ -0,0 +1,193 @@
+/*
+ * IIDC1394 grab interface (uses libdc1394 and libraw1394)
+ * Copyright (c) 2004 Roman Shaposhnik
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avformat.h"
+
+#include <libraw1394/raw1394.h>
+#include <libdc1394/dc1394_control.h>
+
+#undef free
+
+typedef struct dc1394_data {
+ raw1394handle_t handle;
+ dc1394_cameracapture camera;
+ int current_frame;
+ int fps;
+
+ AVPacket packet;
+} dc1394_data;
+
+struct dc1394_frame_format {
+ int width;
+ int height;
+ enum PixelFormat pix_fmt;
+ int frame_size_id;
+} dc1394_frame_formats[] = {
+ { 320, 240, PIX_FMT_UYVY422, MODE_320x240_YUV422 },
+ { 640, 480, PIX_FMT_UYVY411, MODE_640x480_YUV411 },
+ { 640, 480, PIX_FMT_UYVY422, MODE_640x480_YUV422 },
+ { 0, 0, 0, MODE_320x240_YUV422 } /* default -- gotta be the last one */
+};
+
+struct dc1394_frame_rate {
+ int frame_rate;
+ int frame_rate_id;
+} dc1394_frame_rates[] = {
+ { 1875, FRAMERATE_1_875 },
+ { 3750, FRAMERATE_3_75 },
+ { 7500, FRAMERATE_7_5 },
+ { 15000, FRAMERATE_15 },
+ { 30000, FRAMERATE_30 },
+ { 60000, FRAMERATE_60 },
+ { 0, FRAMERATE_30 } /* default -- gotta be the last one */
+};
+
+static int dc1394_read_header(AVFormatContext *c, AVFormatParameters * ap)
+{
+ dc1394_data* dc1394 = c->priv_data;
+ AVStream* vst;
+ nodeid_t* camera_nodes;
+ int res;
+ struct dc1394_frame_format *fmt;
+ struct dc1394_frame_rate *fps;
+
+ for (fmt = dc1394_frame_formats; fmt->width; fmt++)
+ if (fmt->pix_fmt == ap->pix_fmt && fmt->width == ap->width && fmt->height == ap->height)
+ break;
+
+ for (fps = dc1394_frame_rates; fps->frame_rate; fps++)
+ if (fps->frame_rate == av_rescale(1000, ap->time_base.den, ap->time_base.num))
+ break;
+
+ /* create a video stream */
+ vst = av_new_stream(c, 0);
+ if (!vst)
+ return -1;
+ av_set_pts_info(vst, 64, 1, 1000);
+ vst->codec->codec_type = CODEC_TYPE_VIDEO;
+ vst->codec->codec_id = CODEC_ID_RAWVIDEO;
+ vst->codec->time_base.den = fps->frame_rate;
+ vst->codec->time_base.num = 1000;
+ vst->codec->width = fmt->width;
+ vst->codec->height = fmt->height;
+ vst->codec->pix_fmt = fmt->pix_fmt;
+
+ /* packet init */
+ av_init_packet(&dc1394->packet);
+ dc1394->packet.size = avpicture_get_size(fmt->pix_fmt, fmt->width, fmt->height);
+ dc1394->packet.stream_index = vst->index;
+ dc1394->packet.flags |= PKT_FLAG_KEY;
+
+ dc1394->current_frame = 0;
+ dc1394->fps = fps->frame_rate;
+
+ vst->codec->bit_rate = av_rescale(dc1394->packet.size * 8, fps->frame_rate, 1000);
+
+ /* Now lets prep the hardware */
+ dc1394->handle = dc1394_create_handle(0); /* FIXME: gotta have ap->port */
+ if (!dc1394->handle) {
+ av_log(c, AV_LOG_ERROR, "Can't acquire dc1394 handle on port %d\n", 0 /* ap->port */);
+ goto out;
+ }
+ camera_nodes = dc1394_get_camera_nodes(dc1394->handle, &res, 1);
+ if (!camera_nodes || camera_nodes[ap->channel] == DC1394_NO_CAMERA) {
+ av_log(c, AV_LOG_ERROR, "There's no IIDC camera on the channel %d\n", ap->channel);
+ goto out_handle;
+ }
+ res = dc1394_dma_setup_capture(dc1394->handle, camera_nodes[ap->channel],
+ 0,
+ FORMAT_VGA_NONCOMPRESSED,
+ fmt->frame_size_id,
+ SPEED_400,
+ fps->frame_rate_id, 8, 1,
+ ap->device,
+ &dc1394->camera);
+ dc1394_free_camera_nodes(camera_nodes);
+ if (res != DC1394_SUCCESS) {
+ av_log(c, AV_LOG_ERROR, "Can't prepare camera for the DMA capture\n");
+ goto out_handle;
+ }
+
+ res = dc1394_start_iso_transmission(dc1394->handle, dc1394->camera.node);
+ if (res != DC1394_SUCCESS) {
+ av_log(c, AV_LOG_ERROR, "Can't start isochronous transmission\n");
+ goto out_handle_dma;
+ }
+
+ return 0;
+
+out_handle_dma:
+ dc1394_dma_unlisten(dc1394->handle, &dc1394->camera);
+ dc1394_dma_release_camera(dc1394->handle, &dc1394->camera);
+out_handle:
+ dc1394_destroy_handle(dc1394->handle);
+out:
+ return -1;
+}
+
+static int dc1394_read_packet(AVFormatContext *c, AVPacket *pkt)
+{
+ struct dc1394_data *dc1394 = c->priv_data;
+ int res;
+
+ /* discard stale frame */
+ if (dc1394->current_frame++) {
+ if (dc1394_dma_done_with_buffer(&dc1394->camera) != DC1394_SUCCESS)
+ av_log(c, AV_LOG_ERROR, "failed to release %d frame\n", dc1394->current_frame);
+ }
+
+ res = dc1394_dma_single_capture(&dc1394->camera);
+
+ if (res == DC1394_SUCCESS) {
+ dc1394->packet.data = (uint8_t *)(dc1394->camera.capture_buffer);
+ dc1394->packet.pts = (dc1394->current_frame * 1000000) / dc1394->fps;
+ res = dc1394->packet.size;
+ } else {
+ av_log(c, AV_LOG_ERROR, "DMA capture failed\n");
+ dc1394->packet.data = NULL;
+ res = -1;
+ }
+
+ *pkt = dc1394->packet;
+ return res;
+}
+
+static int dc1394_close(AVFormatContext * context)
+{
+ struct dc1394_data *dc1394 = context->priv_data;
+
+ dc1394_stop_iso_transmission(dc1394->handle, dc1394->camera.node);
+ dc1394_dma_unlisten(dc1394->handle, &dc1394->camera);
+ dc1394_dma_release_camera(dc1394->handle, &dc1394->camera);
+ dc1394_destroy_handle(dc1394->handle);
+
+ return 0;
+}
+
+AVInputFormat dc1394_demuxer = {
+ .name = "dc1394",
+ .long_name = "dc1394 A/V grab",
+ .priv_data_size = sizeof(struct dc1394_data),
+ .read_header = dc1394_read_header,
+ .read_packet = dc1394_read_packet,
+ .read_close = dc1394_close,
+ .flags = AVFMT_NOFILE
+};
diff --git a/contrib/ffmpeg/libavformat/dsicin.c b/contrib/ffmpeg/libavformat/dsicin.c
new file mode 100644
index 000000000..f274eadf8
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/dsicin.c
@@ -0,0 +1,224 @@
+/*
+ * Delphine Software International CIN File Demuxer
+ * 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 dsicin.c
+ * Delphine Software International CIN file demuxer
+ */
+
+#include "avformat.h"
+
+
+typedef struct CinFileHeader {
+ int video_frame_size;
+ int video_frame_width;
+ int video_frame_height;
+ int audio_frequency;
+ int audio_bits;
+ int audio_stereo;
+ int audio_frame_size;
+} CinFileHeader;
+
+typedef struct CinFrameHeader {
+ int audio_frame_type;
+ int video_frame_type;
+ int pal_colors_count;
+ int audio_frame_size;
+ int video_frame_size;
+} CinFrameHeader;
+
+typedef struct CinDemuxContext {
+ int audio_stream_index;
+ int video_stream_index;
+ CinFileHeader file_header;
+ int64_t audio_stream_pts;
+ int64_t video_stream_pts;
+ CinFrameHeader frame_header;
+ int audio_buffer_size;
+} CinDemuxContext;
+
+
+static int cin_probe(AVProbeData *p)
+{
+ if (p->buf_size < 18)
+ return 0;
+
+ /* header starts with this special marker */
+ if (LE_32(&p->buf[0]) != 0x55AA0000)
+ return 0;
+
+ /* for accuracy, check some header field values */
+ if (LE_32(&p->buf[12]) != 22050 || p->buf[16] != 16 || p->buf[17] != 0)
+ return 0;
+
+ return AVPROBE_SCORE_MAX;
+}
+
+static int cin_read_file_header(CinDemuxContext *cin, ByteIOContext *pb) {
+ CinFileHeader *hdr = &cin->file_header;
+
+ if (get_le32(pb) != 0x55AA0000)
+ return AVERROR_INVALIDDATA;
+
+ hdr->video_frame_size = get_le32(pb);
+ hdr->video_frame_width = get_le16(pb);
+ hdr->video_frame_height = get_le16(pb);
+ hdr->audio_frequency = get_le32(pb);
+ hdr->audio_bits = get_byte(pb);
+ hdr->audio_stereo = get_byte(pb);
+ hdr->audio_frame_size = get_le16(pb);
+
+ if (hdr->audio_frequency != 22050 || hdr->audio_bits != 16 || hdr->audio_stereo != 0)
+ return AVERROR_INVALIDDATA;
+
+ return 0;
+}
+
+static int cin_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ int rc;
+ CinDemuxContext *cin = (CinDemuxContext *)s->priv_data;
+ CinFileHeader *hdr = &cin->file_header;
+ ByteIOContext *pb = &s->pb;
+ AVStream *st;
+
+ rc = cin_read_file_header(cin, pb);
+ if (rc)
+ return rc;
+
+ cin->video_stream_pts = 0;
+ cin->audio_stream_pts = 0;
+ cin->audio_buffer_size = 0;
+
+ /* initialize the video decoder stream */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+
+ av_set_pts_info(st, 32, 1, 12);
+ cin->video_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_DSICINVIDEO;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->width = hdr->video_frame_width;
+ st->codec->height = hdr->video_frame_height;
+
+ /* initialize the audio decoder stream */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+
+ av_set_pts_info(st, 32, 1, 22050);
+ cin->audio_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_DSICINAUDIO;
+ st->codec->codec_tag = 0; /* no tag */
+ st->codec->channels = 1;
+ st->codec->sample_rate = 22050;
+ st->codec->bits_per_sample = 16;
+ st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_sample * st->codec->channels;
+ st->codec->block_align = st->codec->channels * st->codec->bits_per_sample;
+
+ return 0;
+}
+
+static int cin_read_frame_header(CinDemuxContext *cin, ByteIOContext *pb) {
+ CinFrameHeader *hdr = &cin->frame_header;
+
+ hdr->video_frame_type = get_byte(pb);
+ hdr->audio_frame_type = get_byte(pb);
+ hdr->pal_colors_count = get_le16(pb);
+ hdr->video_frame_size = get_le32(pb);
+ hdr->audio_frame_size = get_le32(pb);
+
+ if (url_feof(pb) || url_ferror(pb))
+ return AVERROR_IO;
+
+ if (get_le32(pb) != 0xAA55AA55)
+ return AVERROR_INVALIDDATA;
+
+ return 0;
+}
+
+static int cin_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ CinDemuxContext *cin = (CinDemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ CinFrameHeader *hdr = &cin->frame_header;
+ int rc, palette_type, pkt_size;
+
+ if (cin->audio_buffer_size == 0) {
+ rc = cin_read_frame_header(cin, pb);
+ if (rc)
+ return rc;
+
+ if ((int16_t)hdr->pal_colors_count < 0) {
+ hdr->pal_colors_count = -(int16_t)hdr->pal_colors_count;
+ palette_type = 1;
+ } else {
+ palette_type = 0;
+ }
+
+ /* palette and video packet */
+ pkt_size = (palette_type + 3) * hdr->pal_colors_count + hdr->video_frame_size;
+
+ if (av_new_packet(pkt, 4 + pkt_size))
+ return AVERROR_NOMEM;
+
+ pkt->stream_index = cin->video_stream_index;
+ pkt->pts = cin->video_stream_pts++;
+
+ pkt->data[0] = palette_type;
+ pkt->data[1] = hdr->pal_colors_count & 0xFF;
+ pkt->data[2] = hdr->pal_colors_count >> 8;
+ pkt->data[3] = hdr->video_frame_type;
+
+ if (get_buffer(pb, &pkt->data[4], pkt_size) != pkt_size)
+ return AVERROR_IO;
+
+ /* sound buffer will be processed on next read_packet() call */
+ cin->audio_buffer_size = hdr->audio_frame_size;
+ return 0;
+ }
+
+ /* audio packet */
+ if (av_new_packet(pkt, cin->audio_buffer_size))
+ return AVERROR_NOMEM;
+
+ pkt->stream_index = cin->audio_stream_index;
+ pkt->pts = cin->audio_stream_pts;
+ cin->audio_stream_pts += cin->audio_buffer_size * 2 / cin->file_header.audio_frame_size;
+
+ if (get_buffer(pb, pkt->data, cin->audio_buffer_size) != cin->audio_buffer_size)
+ return AVERROR_IO;
+
+ cin->audio_buffer_size = 0;
+ return 0;
+}
+
+AVInputFormat dsicin_demuxer = {
+ "dsicin",
+ "Delphine Software International CIN format",
+ sizeof(CinDemuxContext),
+ cin_probe,
+ cin_read_header,
+ cin_read_packet,
+};
diff --git a/contrib/ffmpeg/libavformat/dv.c b/contrib/ffmpeg/libavformat/dv.c
new file mode 100644
index 000000000..3ff8a3fe2
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/dv.c
@@ -0,0 +1,451 @@
+/*
+ * General DV muxer/demuxer
+ * Copyright (c) 2003 Roman Shaposhnik
+ *
+ * Many thanks to Dan Dennedy <dan@dennedy.org> for providing wealth
+ * of DV technical info.
+ *
+ * Raw DV format
+ * Copyright (c) 2002 Fabrice Bellard.
+ *
+ * 50 Mbps (DVCPRO50) support
+ * Copyright (c) 2006 Daniel Maas <dmaas@maasdigital.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 <time.h>
+#include "avformat.h"
+#include "dvdata.h"
+#include "dv.h"
+
+struct DVDemuxContext {
+ const DVprofile* sys; /* Current DV profile. E.g.: 525/60, 625/50 */
+ AVFormatContext* fctx;
+ AVStream* vst;
+ AVStream* ast[2];
+ AVPacket audio_pkt[2];
+ uint8_t audio_buf[2][8192];
+ int ach;
+ int frames;
+ uint64_t abytes;
+};
+
+static inline uint16_t dv_audio_12to16(uint16_t sample)
+{
+ uint16_t shift, result;
+
+ sample = (sample < 0x800) ? sample : sample | 0xf000;
+ shift = (sample & 0xf00) >> 8;
+
+ if (shift < 0x2 || shift > 0xd) {
+ result = sample;
+ } else if (shift < 0x8) {
+ shift--;
+ result = (sample - (256 * shift)) << shift;
+ } else {
+ shift = 0xe - shift;
+ result = ((sample + ((256 * shift) + 1)) << shift) - 1;
+ }
+
+ return result;
+}
+
+/*
+ * This is the dumbest implementation of all -- it simply looks at
+ * a fixed offset and if pack isn't there -- fails. We might want
+ * to have a fallback mechanism for complete search of missing packs.
+ */
+static const uint8_t* dv_extract_pack(uint8_t* frame, enum dv_pack_type t)
+{
+ int offs;
+
+ switch (t) {
+ case dv_audio_source:
+ offs = (80*6 + 80*16*3 + 3);
+ break;
+ case dv_audio_control:
+ offs = (80*6 + 80*16*4 + 3);
+ break;
+ case dv_video_control:
+ offs = (80*5 + 48 + 5);
+ break;
+ default:
+ return NULL;
+ }
+
+ return (frame[offs] == t ? &frame[offs] : NULL);
+}
+
+/*
+ * There's a couple of assumptions being made here:
+ * 1. By default we silence erroneous (0x8000/16bit 0x800/12bit) audio samples.
+ * We can pass them upwards when ffmpeg will be ready to deal with them.
+ * 2. We don't do software emphasis.
+ * 3. Audio is always returned as 16bit linear samples: 12bit nonlinear samples
+ * are converted into 16bit linear ones.
+ */
+static int dv_extract_audio(uint8_t* frame, uint8_t* pcm, uint8_t* pcm2,
+ const DVprofile *sys)
+{
+ int size, chan, i, j, d, of, smpls, freq, quant, half_ch;
+ uint16_t lc, rc;
+ const uint8_t* as_pack;
+
+ as_pack = dv_extract_pack(frame, dv_audio_source);
+ if (!as_pack) /* No audio ? */
+ return 0;
+
+ smpls = as_pack[1] & 0x3f; /* samples in this frame - min. samples */
+ freq = (as_pack[4] >> 3) & 0x07; /* 0 - 48KHz, 1 - 44,1kHz, 2 - 32 kHz */
+ quant = as_pack[4] & 0x07; /* 0 - 16bit linear, 1 - 12bit nonlinear */
+
+ if (quant > 1)
+ return -1; /* Unsupported quantization */
+
+ size = (sys->audio_min_samples[freq] + smpls) * 4; /* 2ch, 2bytes */
+ half_ch = sys->difseg_size/2;
+
+ /* for each DIF channel */
+ for (chan = 0; chan < sys->n_difchan; chan++) {
+ /* for each DIF segment */
+ for (i = 0; i < sys->difseg_size; i++) {
+ frame += 6 * 80; /* skip DIF segment header */
+ if (quant == 1 && i == half_ch) {
+ /* next stereo channel (12bit mode only) */
+ if (!pcm2)
+ break;
+ else
+ pcm = pcm2;
+ }
+
+ /* for each AV sequence */
+ for (j = 0; j < 9; j++) {
+ for (d = 8; d < 80; d += 2) {
+ if (quant == 0) { /* 16bit quantization */
+ of = sys->audio_shuffle[i][j] + (d - 8)/2 * sys->audio_stride;
+ if (of*2 >= size)
+ continue;
+
+ pcm[of*2] = frame[d+1]; // FIXME: may be we have to admit
+ pcm[of*2+1] = frame[d]; // that DV is a big endian PCM
+ if (pcm[of*2+1] == 0x80 && pcm[of*2] == 0x00)
+ pcm[of*2+1] = 0;
+ } else { /* 12bit quantization */
+ lc = ((uint16_t)frame[d] << 4) |
+ ((uint16_t)frame[d+2] >> 4);
+ rc = ((uint16_t)frame[d+1] << 4) |
+ ((uint16_t)frame[d+2] & 0x0f);
+ lc = (lc == 0x800 ? 0 : dv_audio_12to16(lc));
+ rc = (rc == 0x800 ? 0 : dv_audio_12to16(rc));
+
+ of = sys->audio_shuffle[i%half_ch][j] + (d - 8)/3 * sys->audio_stride;
+ if (of*2 >= size)
+ continue;
+
+ pcm[of*2] = lc & 0xff; // FIXME: may be we have to admit
+ pcm[of*2+1] = lc >> 8; // that DV is a big endian PCM
+ of = sys->audio_shuffle[i%half_ch+half_ch][j] +
+ (d - 8)/3 * sys->audio_stride;
+ pcm[of*2] = rc & 0xff; // FIXME: may be we have to admit
+ pcm[of*2+1] = rc >> 8; // that DV is a big endian PCM
+ ++d;
+ }
+ }
+
+ frame += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */
+ }
+ }
+
+ /* next stereo channel (50Mbps only) */
+ if(!pcm2)
+ break;
+ pcm = pcm2;
+ }
+
+ return size;
+}
+
+static int dv_extract_audio_info(DVDemuxContext* c, uint8_t* frame)
+{
+ const uint8_t* as_pack;
+ int freq, stype, smpls, quant, i, ach;
+
+ as_pack = dv_extract_pack(frame, dv_audio_source);
+ if (!as_pack || !c->sys) { /* No audio ? */
+ c->ach = 0;
+ return 0;
+ }
+
+ smpls = as_pack[1] & 0x3f; /* samples in this frame - min. samples */
+ freq = (as_pack[4] >> 3) & 0x07; /* 0 - 48KHz, 1 - 44,1kHz, 2 - 32 kHz */
+ stype = (as_pack[3] & 0x1f); /* 0 - 2CH, 2 - 4CH */
+ quant = as_pack[4] & 0x07; /* 0 - 16bit linear, 1 - 12bit nonlinear */
+
+ /* note: ach counts PAIRS of channels (i.e. stereo channels) */
+ ach = (stype == 2 || (quant && (freq == 2))) ? 2 : 1;
+
+ /* Dynamic handling of the audio streams in DV */
+ for (i=0; i<ach; i++) {
+ if (!c->ast[i]) {
+ c->ast[i] = av_new_stream(c->fctx, 0);
+ if (!c->ast[i])
+ break;
+ av_set_pts_info(c->ast[i], 64, 1, 30000);
+ c->ast[i]->codec->codec_type = CODEC_TYPE_AUDIO;
+ c->ast[i]->codec->codec_id = CODEC_ID_PCM_S16LE;
+
+ av_init_packet(&c->audio_pkt[i]);
+ c->audio_pkt[i].size = 0;
+ c->audio_pkt[i].data = c->audio_buf[i];
+ c->audio_pkt[i].stream_index = c->ast[i]->index;
+ c->audio_pkt[i].flags |= PKT_FLAG_KEY;
+ }
+ c->ast[i]->codec->sample_rate = dv_audio_frequency[freq];
+ c->ast[i]->codec->channels = 2;
+ c->ast[i]->codec->bit_rate = 2 * dv_audio_frequency[freq] * 16;
+ c->ast[i]->start_time = 0;
+ }
+ c->ach = i;
+
+ return (c->sys->audio_min_samples[freq] + smpls) * 4; /* 2ch, 2bytes */;
+}
+
+static int dv_extract_video_info(DVDemuxContext *c, uint8_t* frame)
+{
+ const uint8_t* vsc_pack;
+ AVCodecContext* avctx;
+ int apt, is16_9;
+ int size = 0;
+
+ if (c->sys) {
+ avctx = c->vst->codec;
+
+ av_set_pts_info(c->vst, 64, c->sys->frame_rate_base, c->sys->frame_rate);
+ avctx->time_base= (AVRational){c->sys->frame_rate_base, c->sys->frame_rate};
+ if(!avctx->width){
+ avctx->width = c->sys->width;
+ avctx->height = c->sys->height;
+ }
+ avctx->pix_fmt = c->sys->pix_fmt;
+
+ /* finding out SAR is a little bit messy */
+ vsc_pack = dv_extract_pack(frame, dv_video_control);
+ apt = frame[4] & 0x07;
+ is16_9 = (vsc_pack && ((vsc_pack[2] & 0x07) == 0x02 ||
+ (!apt && (vsc_pack[2] & 0x07) == 0x07)));
+ avctx->sample_aspect_ratio = c->sys->sar[is16_9];
+ avctx->bit_rate = av_rescale(c->sys->frame_size * 8,
+ c->sys->frame_rate,
+ c->sys->frame_rate_base);
+ size = c->sys->frame_size;
+ }
+ return size;
+}
+
+/*
+ * The following 3 functions constitute our interface to the world
+ */
+
+DVDemuxContext* dv_init_demux(AVFormatContext *s)
+{
+ DVDemuxContext *c;
+
+ c = av_mallocz(sizeof(DVDemuxContext));
+ if (!c)
+ return NULL;
+
+ c->vst = av_new_stream(s, 0);
+ if (!c->vst) {
+ av_free(c);
+ return NULL;
+ }
+
+ c->sys = NULL;
+ c->fctx = s;
+ c->ast[0] = c->ast[1] = NULL;
+ c->ach = 0;
+ c->frames = 0;
+ c->abytes = 0;
+
+ c->vst->codec->codec_type = CODEC_TYPE_VIDEO;
+ c->vst->codec->codec_id = CODEC_ID_DVVIDEO;
+ c->vst->codec->bit_rate = 25000000;
+ c->vst->start_time = 0;
+
+ return c;
+}
+
+int dv_get_packet(DVDemuxContext *c, AVPacket *pkt)
+{
+ int size = -1;
+ int i;
+
+ for (i=0; i<c->ach; i++) {
+ if (c->ast[i] && c->audio_pkt[i].size) {
+ *pkt = c->audio_pkt[i];
+ c->audio_pkt[i].size = 0;
+ size = pkt->size;
+ break;
+ }
+ }
+
+ return size;
+}
+
+int dv_produce_packet(DVDemuxContext *c, AVPacket *pkt,
+ uint8_t* buf, int buf_size)
+{
+ int size, i;
+
+ if (buf_size < DV_PROFILE_BYTES ||
+ !(c->sys = dv_frame_profile(buf)) ||
+ buf_size < c->sys->frame_size) {
+ return -1; /* Broken frame, or not enough data */
+ }
+
+ /* Queueing audio packet */
+ /* FIXME: in case of no audio/bad audio we have to do something */
+ size = dv_extract_audio_info(c, buf);
+ for (i=0; i<c->ach; i++) {
+ c->audio_pkt[i].size = size;
+ c->audio_pkt[i].pts = c->abytes * 30000*8 / c->ast[i]->codec->bit_rate;
+ }
+ dv_extract_audio(buf, c->audio_buf[0], c->audio_buf[1], c->sys);
+ c->abytes += size;
+
+ /* Now it's time to return video packet */
+ size = dv_extract_video_info(c, buf);
+ av_init_packet(pkt);
+ pkt->data = buf;
+ pkt->size = size;
+ pkt->flags |= PKT_FLAG_KEY;
+ pkt->stream_index = c->vst->id;
+ pkt->pts = c->frames;
+
+ c->frames++;
+
+ return size;
+}
+
+static int64_t dv_frame_offset(AVFormatContext *s, DVDemuxContext *c,
+ int64_t timestamp, int flags)
+{
+ // FIXME: sys may be wrong if last dv_read_packet() failed (buffer is junk)
+ const DVprofile* sys = dv_codec_profile(c->vst->codec);
+ int64_t offset;
+ int64_t size = url_fsize(&s->pb);
+ int64_t max_offset = ((size-1) / sys->frame_size) * sys->frame_size;
+
+ offset = sys->frame_size * timestamp;
+
+ if (offset > max_offset) offset = max_offset;
+ else if (offset < 0) offset = 0;
+
+ return offset;
+}
+
+void dv_flush_audio_packets(DVDemuxContext *c)
+{
+ c->audio_pkt[0].size = c->audio_pkt[1].size = 0;
+}
+
+/************************************************************
+ * Implementation of the easiest DV storage of all -- raw DV.
+ ************************************************************/
+
+typedef struct RawDVContext {
+ DVDemuxContext* dv_demux;
+ uint8_t buf[DV_MAX_FRAME_SIZE];
+} RawDVContext;
+
+static int dv_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ RawDVContext *c = s->priv_data;
+
+ c->dv_demux = dv_init_demux(s);
+ if (!c->dv_demux)
+ return -1;
+
+ if (get_buffer(&s->pb, c->buf, DV_PROFILE_BYTES) <= 0 ||
+ url_fseek(&s->pb, -DV_PROFILE_BYTES, SEEK_CUR) < 0)
+ return AVERROR_IO;
+
+ c->dv_demux->sys = dv_frame_profile(c->buf);
+ s->bit_rate = av_rescale(c->dv_demux->sys->frame_size * 8,
+ c->dv_demux->sys->frame_rate,
+ c->dv_demux->sys->frame_rate_base);
+
+ return 0;
+}
+
+
+static int dv_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ int size;
+ RawDVContext *c = s->priv_data;
+
+ size = dv_get_packet(c->dv_demux, pkt);
+
+ if (size < 0) {
+ size = c->dv_demux->sys->frame_size;
+ if (get_buffer(&s->pb, c->buf, size) <= 0)
+ return AVERROR_IO;
+
+ size = dv_produce_packet(c->dv_demux, pkt, c->buf, size);
+ }
+
+ return size;
+}
+
+static int dv_read_seek(AVFormatContext *s, int stream_index,
+ int64_t timestamp, int flags)
+{
+ RawDVContext *r = s->priv_data;
+ DVDemuxContext *c = r->dv_demux;
+ int64_t offset= dv_frame_offset(s, c, timestamp, flags);
+
+ c->frames= offset / c->sys->frame_size;
+ if (c->ach)
+ c->abytes= av_rescale(c->frames,
+ c->ast[0]->codec->bit_rate * (int64_t)c->sys->frame_rate_base,
+ 8*c->sys->frame_rate);
+
+ dv_flush_audio_packets(c);
+ return url_fseek(&s->pb, offset, SEEK_SET);
+}
+
+static int dv_read_close(AVFormatContext *s)
+{
+ RawDVContext *c = s->priv_data;
+ av_free(c->dv_demux);
+ return 0;
+}
+
+#ifdef CONFIG_DV_DEMUXER
+AVInputFormat dv_demuxer = {
+ "dv",
+ "DV video format",
+ sizeof(RawDVContext),
+ NULL,
+ dv_read_header,
+ dv_read_packet,
+ dv_read_close,
+ dv_read_seek,
+ .extensions = "dv,dif",
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/dv.h b/contrib/ffmpeg/libavformat/dv.h
new file mode 100644
index 000000000..f39d22c9f
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/dv.h
@@ -0,0 +1,37 @@
+/*
+ * General DV muxer/demuxer
+ * Copyright (c) 2003 Roman Shaposhnik
+ *
+ * Many thanks to Dan Dennedy <dan@dennedy.org> for providing wealth
+ * of DV technical info.
+ *
+ * Raw DV format
+ * 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
+ */
+
+typedef struct DVDemuxContext DVDemuxContext;
+DVDemuxContext* dv_init_demux(AVFormatContext* s);
+int dv_get_packet(DVDemuxContext*, AVPacket *);
+int dv_produce_packet(DVDemuxContext*, AVPacket*, uint8_t*, int);
+void dv_flush_audio_packets(DVDemuxContext*);
+
+typedef struct DVMuxContext DVMuxContext;
+DVMuxContext* dv_init_mux(AVFormatContext* s);
+int dv_assemble_frame(DVMuxContext *c, AVStream*, const uint8_t*, int, uint8_t**);
+void dv_delete_mux(DVMuxContext*);
diff --git a/contrib/ffmpeg/libavformat/dv1394.c b/contrib/ffmpeg/libavformat/dv1394.c
new file mode 100644
index 000000000..f00d47435
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/dv1394.c
@@ -0,0 +1,240 @@
+/*
+ * Linux DV1394 interface
+ * Copyright (c) 2003 Max Krasnyansky <maxk@qualcomm.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 <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include "avformat.h"
+
+#undef DV1394_DEBUG
+
+#include "dv1394.h"
+#include "dv.h"
+
+struct dv1394_data {
+ int fd;
+ int channel;
+ int format;
+
+ void *ring; /* Ring buffer */
+ int index; /* Current frame index */
+ int avail; /* Number of frames available for reading */
+ int done; /* Number of completed frames */
+
+ DVDemuxContext* dv_demux; /* Generic DV muxing/demuxing context */
+};
+
+/*
+ * The trick here is to kludge around well known problem with kernel Ooopsing
+ * when you try to capture PAL on a device node configure for NTSC. That's
+ * why we have to configure the device node for PAL, and then read only NTSC
+ * amount of data.
+ */
+static int dv1394_reset(struct dv1394_data *dv)
+{
+ struct dv1394_init init;
+
+ init.channel = dv->channel;
+ init.api_version = DV1394_API_VERSION;
+ init.n_frames = DV1394_RING_FRAMES;
+ init.format = DV1394_PAL;
+
+ if (ioctl(dv->fd, DV1394_INIT, &init) < 0)
+ return -1;
+
+ dv->avail = dv->done = 0;
+ return 0;
+}
+
+static int dv1394_start(struct dv1394_data *dv)
+{
+ /* Tell DV1394 driver to enable receiver */
+ if (ioctl(dv->fd, DV1394_START_RECEIVE, 0) < 0) {
+ perror("Failed to start receiver");
+ return -1;
+ }
+ return 0;
+}
+
+static int dv1394_read_header(AVFormatContext * context, AVFormatParameters * ap)
+{
+ struct dv1394_data *dv = context->priv_data;
+ const char *video_device;
+
+ dv->dv_demux = dv_init_demux(context);
+ if (!dv->dv_demux)
+ goto failed;
+
+ if (ap->standard && !strcasecmp(ap->standard, "pal"))
+ dv->format = DV1394_PAL;
+ else
+ dv->format = DV1394_NTSC;
+
+ if (ap->channel)
+ dv->channel = ap->channel;
+ else
+ dv->channel = DV1394_DEFAULT_CHANNEL;
+
+ /* Open and initialize DV1394 device */
+ video_device = ap->device;
+ if (!video_device)
+ video_device = "/dev/dv1394/0";
+ dv->fd = open(video_device, O_RDONLY);
+ if (dv->fd < 0) {
+ perror("Failed to open DV interface");
+ goto failed;
+ }
+
+ if (dv1394_reset(dv) < 0) {
+ perror("Failed to initialize DV interface");
+ goto failed;
+ }
+
+ dv->ring = mmap(NULL, DV1394_PAL_FRAME_SIZE * DV1394_RING_FRAMES,
+ PROT_READ, MAP_PRIVATE, dv->fd, 0);
+ if (dv->ring == MAP_FAILED) {
+ perror("Failed to mmap DV ring buffer");
+ goto failed;
+ }
+
+ if (dv1394_start(dv) < 0)
+ goto failed;
+
+ return 0;
+
+failed:
+ close(dv->fd);
+ return AVERROR_IO;
+}
+
+static int dv1394_read_packet(AVFormatContext *context, AVPacket *pkt)
+{
+ struct dv1394_data *dv = context->priv_data;
+ int size;
+
+ size = dv_get_packet(dv->dv_demux, pkt);
+ if (size > 0)
+ return size;
+
+ if (!dv->avail) {
+ struct dv1394_status s;
+ struct pollfd p;
+
+ if (dv->done) {
+ /* Request more frames */
+ if (ioctl(dv->fd, DV1394_RECEIVE_FRAMES, dv->done) < 0) {
+ /* This usually means that ring buffer overflowed.
+ * We have to reset :(.
+ */
+
+ av_log(context, AV_LOG_ERROR, "DV1394: Ring buffer overflow. Reseting ..\n");
+
+ dv1394_reset(dv);
+ dv1394_start(dv);
+ }
+ dv->done = 0;
+ }
+
+ /* Wait until more frames are available */
+restart_poll:
+ p.fd = dv->fd;
+ p.events = POLLIN | POLLERR | POLLHUP;
+ if (poll(&p, 1, -1) < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ goto restart_poll;
+ perror("Poll failed");
+ return AVERROR_IO;
+ }
+
+ if (ioctl(dv->fd, DV1394_GET_STATUS, &s) < 0) {
+ perror("Failed to get status");
+ return AVERROR_IO;
+ }
+#ifdef DV1394_DEBUG
+ av_log(context, AV_LOG_DEBUG, "DV1394: status\n"
+ "\tactive_frame\t%d\n"
+ "\tfirst_clear_frame\t%d\n"
+ "\tn_clear_frames\t%d\n"
+ "\tdropped_frames\t%d\n",
+ s.active_frame, s.first_clear_frame,
+ s.n_clear_frames, s.dropped_frames);
+#endif
+
+ dv->avail = s.n_clear_frames;
+ dv->index = s.first_clear_frame;
+ dv->done = 0;
+
+ if (s.dropped_frames) {
+ av_log(context, AV_LOG_ERROR, "DV1394: Frame drop detected (%d). Reseting ..\n",
+ s.dropped_frames);
+
+ dv1394_reset(dv);
+ dv1394_start(dv);
+ }
+ }
+
+#ifdef DV1394_DEBUG
+ av_log(context, AV_LOG_DEBUG, "index %d, avail %d, done %d\n", dv->index, dv->avail,
+ dv->done);
+#endif
+
+ size = dv_produce_packet(dv->dv_demux, pkt,
+ dv->ring + (dv->index * DV1394_PAL_FRAME_SIZE),
+ DV1394_PAL_FRAME_SIZE);
+ dv->index = (dv->index + 1) % DV1394_RING_FRAMES;
+ dv->done++; dv->avail--;
+
+ return size;
+}
+
+static int dv1394_close(AVFormatContext * context)
+{
+ struct dv1394_data *dv = context->priv_data;
+
+ /* Shutdown DV1394 receiver */
+ if (ioctl(dv->fd, DV1394_SHUTDOWN, 0) < 0)
+ perror("Failed to shutdown DV1394");
+
+ /* Unmap ring buffer */
+ if (munmap(dv->ring, DV1394_NTSC_FRAME_SIZE * DV1394_RING_FRAMES) < 0)
+ perror("Failed to munmap DV1394 ring buffer");
+
+ close(dv->fd);
+ av_free(dv->dv_demux);
+
+ return 0;
+}
+
+AVInputFormat dv1394_demuxer = {
+ .name = "dv1394",
+ .long_name = "dv1394 A/V grab",
+ .priv_data_size = sizeof(struct dv1394_data),
+ .read_header = dv1394_read_header,
+ .read_packet = dv1394_read_packet,
+ .read_close = dv1394_close,
+ .flags = AVFMT_NOFILE
+};
diff --git a/contrib/ffmpeg/libavformat/dv1394.h b/contrib/ffmpeg/libavformat/dv1394.h
new file mode 100644
index 000000000..f7db40108
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/dv1394.h
@@ -0,0 +1,357 @@
+/*
+ * dv1394.h - DV input/output over IEEE 1394 on OHCI chips
+ * Copyright (C)2001 Daniel Maas <dmaas@dcine.com>
+ * receive, proc_fs by Dan Dennedy <dan@dennedy.org>
+ *
+ * based on:
+ * video1394.h - driver for OHCI 1394 boards
+ * Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
+ * Peter Schlaile <udbz@rz.uni-karlsruhe.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
+ *
+ */
+
+#ifndef _DV_1394_H
+#define _DV_1394_H
+
+#define DV1394_DEFAULT_CHANNEL 63
+#define DV1394_DEFAULT_CARD 0
+#define DV1394_RING_FRAMES 20
+
+#define DV1394_WIDTH 720
+#define DV1394_NTSC_HEIGHT 480
+#define DV1394_PAL_HEIGHT 576
+
+/* This is the public user-space interface. Try not to break it. */
+
+#define DV1394_API_VERSION 0x20011127
+
+/* ********************
+ ** **
+ ** DV1394 API **
+ ** **
+ ********************
+
+ There are two methods of operating the DV1394 DV output device.
+
+ 1)
+
+ The simplest is an interface based on write(): simply write
+ full DV frames of data to the device, and they will be transmitted
+ as quickly as possible. The FD may be set for non-blocking I/O,
+ in which case you can use select() or poll() to wait for output
+ buffer space.
+
+ To set the DV output parameters (e.g. whether you want NTSC or PAL
+ video), use the DV1394_INIT ioctl, passing in the parameters you
+ want in a struct dv1394_init.
+
+ Example 1:
+ To play a raw .DV file: cat foo.DV > /dev/dv1394
+ (cat will use write() internally)
+
+ Example 2:
+ static struct dv1394_init init = {
+ 0x63, (broadcast channel)
+ 4, (four-frame ringbuffer)
+ DV1394_NTSC, (send NTSC video)
+ 0, 0 (default empty packet rate)
+ }
+
+ ioctl(fd, DV1394_INIT, &init);
+
+ while(1) {
+ read( <a raw DV file>, buf, DV1394_NTSC_FRAME_SIZE );
+ write( <the dv1394 FD>, buf, DV1394_NTSC_FRAME_SIZE );
+ }
+
+ 2)
+
+ For more control over buffering, and to avoid unnecessary copies
+ of the DV data, you can use the more sophisticated the mmap() interface.
+ First, call the DV1394_INIT ioctl to specify your parameters,
+ including the number of frames in the ringbuffer. Then, calling mmap()
+ on the dv1394 device will give you direct access to the ringbuffer
+ from which the DV card reads your frame data.
+
+ The ringbuffer is simply one large, contiguous region of memory
+ containing two or more frames of packed DV data. Each frame of DV data
+ is 120000 bytes (NTSC) or 144000 bytes (PAL).
+
+ Fill one or more frames in the ringbuffer, then use the DV1394_SUBMIT_FRAMES
+ ioctl to begin I/O. You can use either the DV1394_WAIT_FRAMES ioctl
+ or select()/poll() to wait until the frames are transmitted. Next, you'll
+ need to call the DV1394_GET_STATUS ioctl to determine which ringbuffer
+ frames are clear (ready to be filled with new DV data). Finally, use
+ DV1394_SUBMIT_FRAMES again to send the new data to the DV output.
+
+
+ Example: here is what a four-frame ringbuffer might look like
+ during DV transmission:
+
+
+ frame 0 frame 1 frame 2 frame 3
+
+ *--------------------------------------*
+ | CLEAR | DV data | DV data | CLEAR |
+ *--------------------------------------*
+ <ACTIVE>
+
+ transmission goes in this direction --->>>
+
+
+ The DV hardware is currently transmitting the data in frame 1.
+ Once frame 1 is finished, it will automatically transmit frame 2.
+ (if frame 2 finishes before frame 3 is submitted, the device
+ will continue to transmit frame 2, and will increase the dropped_frames
+ counter each time it repeats the transmission).
+
+
+ If you called DV1394_GET_STATUS at this instant, you would
+ receive the following values:
+
+ n_frames = 4
+ active_frame = 1
+ first_clear_frame = 3
+ n_clear_frames = 2
+
+ At this point, you should write new DV data into frame 3 and optionally
+ frame 0. Then call DV1394_SUBMIT_FRAMES to inform the device that
+ it may transmit the new frames.
+
+ ERROR HANDLING
+
+ An error (buffer underflow/overflow or a break in the DV stream due
+ to a 1394 bus reset) can be detected by checking the dropped_frames
+ field of struct dv1394_status (obtained through the
+ DV1394_GET_STATUS ioctl).
+
+ The best way to recover from such an error is to re-initialize
+ dv1394, either by using the DV1394_INIT ioctl call, or closing the
+ file descriptor and opening it again. (note that you must unmap all
+ ringbuffer mappings when closing the file descriptor, or else
+ dv1394 will still be considered 'in use').
+
+ MAIN LOOP
+
+ For maximum efficiency and robustness against bus errors, you are
+ advised to model the main loop of your application after the
+ following pseudo-code example:
+
+ (checks of system call return values omitted for brevity; always
+ check return values in your code!)
+
+ while( frames left ) {
+
+ struct pollfd *pfd = ...;
+
+ pfd->fd = dv1394_fd;
+ pfd->revents = 0;
+ pfd->events = POLLOUT | POLLIN; (OUT for transmit, IN for receive)
+
+ (add other sources of I/O here)
+
+ poll(pfd, 1, -1); (or select(); add a timeout if you want)
+
+ if(pfd->revents) {
+ struct dv1394_status status;
+
+ ioctl(dv1394_fd, DV1394_GET_STATUS, &status);
+
+ if(status.dropped_frames > 0) {
+ reset_dv1394();
+ } else {
+ for(int i = 0; i < status.n_clear_frames; i++) {
+ copy_DV_frame();
+ }
+ }
+ }
+ }
+
+ where copy_DV_frame() reads or writes on the dv1394 file descriptor
+ (read/write mode) or copies data to/from the mmap ringbuffer and
+ then calls ioctl(DV1394_SUBMIT_FRAMES) to notify dv1394 that new
+ frames are availble (mmap mode).
+
+ reset_dv1394() is called in the event of a buffer
+ underflow/overflow or a halt in the DV stream (e.g. due to a 1394
+ bus reset). To guarantee recovery from the error, this function
+ should close the dv1394 file descriptor (and munmap() all
+ ringbuffer mappings, if you are using them), then re-open the
+ dv1394 device (and re-map the ringbuffer).
+
+*/
+
+
+/* maximum number of frames in the ringbuffer */
+#define DV1394_MAX_FRAMES 32
+
+/* number of *full* isochronous packets per DV frame */
+#define DV1394_NTSC_PACKETS_PER_FRAME 250
+#define DV1394_PAL_PACKETS_PER_FRAME 300
+
+/* size of one frame's worth of DV data, in bytes */
+#define DV1394_NTSC_FRAME_SIZE (480 * DV1394_NTSC_PACKETS_PER_FRAME)
+#define DV1394_PAL_FRAME_SIZE (480 * DV1394_PAL_PACKETS_PER_FRAME)
+
+
+/* ioctl() commands */
+
+enum {
+ /* I don't like using 0 as a valid ioctl() */
+ DV1394_INVALID = 0,
+
+
+ /* get the driver ready to transmit video.
+ pass a struct dv1394_init* as the parameter (see below),
+ or NULL to get default parameters */
+ DV1394_INIT,
+
+
+ /* stop transmitting video and free the ringbuffer */
+ DV1394_SHUTDOWN,
+
+
+ /* submit N new frames to be transmitted, where
+ the index of the first new frame is first_clear_buffer,
+ and the index of the last new frame is
+ (first_clear_buffer + N) % n_frames */
+ DV1394_SUBMIT_FRAMES,
+
+
+ /* block until N buffers are clear (pass N as the parameter)
+ Because we re-transmit the last frame on underrun, there
+ will at most be n_frames - 1 clear frames at any time */
+ DV1394_WAIT_FRAMES,
+
+ /* capture new frames that have been received, where
+ the index of the first new frame is first_clear_buffer,
+ and the index of the last new frame is
+ (first_clear_buffer + N) % n_frames */
+ DV1394_RECEIVE_FRAMES,
+
+
+ DV1394_START_RECEIVE,
+
+
+ /* pass a struct dv1394_status* as the parameter (see below) */
+ DV1394_GET_STATUS,
+};
+
+
+
+enum pal_or_ntsc {
+ DV1394_NTSC = 0,
+ DV1394_PAL
+};
+
+
+
+
+/* this is the argument to DV1394_INIT */
+struct dv1394_init {
+ /* DV1394_API_VERSION */
+ unsigned int api_version;
+
+ /* isochronous transmission channel to use */
+ unsigned int channel;
+
+ /* number of frames in the ringbuffer. Must be at least 2
+ and at most DV1394_MAX_FRAMES. */
+ unsigned int n_frames;
+
+ /* send/receive PAL or NTSC video format */
+ enum pal_or_ntsc format;
+
+ /* the following are used only for transmission */
+
+ /* set these to zero unless you want a
+ non-default empty packet rate (see below) */
+ unsigned long cip_n;
+ unsigned long cip_d;
+
+ /* set this to zero unless you want a
+ non-default SYT cycle offset (default = 3 cycles) */
+ unsigned int syt_offset;
+};
+
+/* NOTE: you may only allocate the DV frame ringbuffer once each time
+ you open the dv1394 device. DV1394_INIT will fail if you call it a
+ second time with different 'n_frames' or 'format' arguments (which
+ would imply a different size for the ringbuffer). If you need a
+ different buffer size, simply close and re-open the device, then
+ initialize it with your new settings. */
+
+/* Q: What are cip_n and cip_d? */
+
+/*
+ A: DV video streams do not utilize 100% of the potential bandwidth offered
+ by IEEE 1394 (FireWire). To achieve the correct rate of data transmission,
+ DV devices must periodically insert empty packets into the 1394 data stream.
+ Typically there is one empty packet per 14-16 data-carrying packets.
+
+ Some DV devices will accept a wide range of empty packet rates, while others
+ require a precise rate. If the dv1394 driver produces empty packets at
+ a rate that your device does not accept, you may see ugly patterns on the
+ DV output, or even no output at all.
+
+ The default empty packet insertion rate seems to work for many people; if
+ your DV output is stable, you can simply ignore this discussion. However,
+ we have exposed the empty packet rate as a parameter to support devices that
+ do not work with the default rate.
+
+ The decision to insert an empty packet is made with a numerator/denominator
+ algorithm. Empty packets are produced at an average rate of CIP_N / CIP_D.
+ You can alter the empty packet rate by passing non-zero values for cip_n
+ and cip_d to the INIT ioctl.
+
+ */
+
+
+
+struct dv1394_status {
+ /* this embedded init struct returns the current dv1394
+ parameters in use */
+ struct dv1394_init init;
+
+ /* the ringbuffer frame that is currently being
+ displayed. (-1 if the device is not transmitting anything) */
+ int active_frame;
+
+ /* index of the first buffer (ahead of active_frame) that
+ is ready to be filled with data */
+ unsigned int first_clear_frame;
+
+ /* how many buffers, including first_clear_buffer, are
+ ready to be filled with data */
+ unsigned int n_clear_frames;
+
+ /* how many times the DV stream has underflowed, overflowed,
+ or otherwise encountered an error, since the previous call
+ to DV1394_GET_STATUS */
+ unsigned int dropped_frames;
+
+ /* N.B. The dropped_frames counter is only a lower bound on the actual
+ number of dropped frames, with the special case that if dropped_frames
+ is zero, then it is guaranteed that NO frames have been dropped
+ since the last call to DV1394_GET_STATUS.
+ */
+};
+
+
+#endif /* _DV_1394_H */
diff --git a/contrib/ffmpeg/libavformat/dvenc.c b/contrib/ffmpeg/libavformat/dvenc.c
new file mode 100644
index 000000000..79cee7af6
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/dvenc.c
@@ -0,0 +1,407 @@
+/*
+ * General DV muxer/demuxer
+ * Copyright (c) 2003 Roman Shaposhnik
+ *
+ * Many thanks to Dan Dennedy <dan@dennedy.org> for providing wealth
+ * of DV technical info.
+ *
+ * Raw DV format
+ * Copyright (c) 2002 Fabrice Bellard.
+ *
+ * 50 Mbps (DVCPRO50) support
+ * Copyright (c) 2006 Daniel Maas <dmaas@maasdigital.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 <time.h>
+#include "avformat.h"
+#include "dvdata.h"
+#include "dv.h"
+#include "fifo.h"
+
+struct DVMuxContext {
+ const DVprofile* sys; /* Current DV profile. E.g.: 525/60, 625/50 */
+ int n_ast; /* Number of stereo audio streams (up to 2) */
+ AVStream *ast[2]; /* Stereo audio streams */
+ AVFifoBuffer audio_data[2]; /* Fifo for storing excessive amounts of PCM */
+ int frames; /* Number of a current frame */
+ time_t start_time; /* Start time of recording */
+ int has_audio; /* frame under contruction has audio */
+ int has_video; /* frame under contruction has video */
+ uint8_t frame_buf[DV_MAX_FRAME_SIZE]; /* frame under contruction */
+};
+
+static const int dv_aaux_packs_dist[12][9] = {
+ { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
+ { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
+ { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
+ { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
+ { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
+ { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
+ { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
+};
+
+static int dv_audio_frame_size(const DVprofile* sys, int frame)
+{
+ return sys->audio_samples_dist[frame % (sizeof(sys->audio_samples_dist)/
+ sizeof(sys->audio_samples_dist[0]))];
+}
+
+static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* buf)
+{
+ struct tm tc;
+ time_t ct;
+ int ltc_frame;
+
+ buf[0] = (uint8_t)pack_id;
+ switch (pack_id) {
+ case dv_timecode:
+ ct = (time_t)(c->frames / ((float)c->sys->frame_rate /
+ (float)c->sys->frame_rate_base));
+ brktimegm(ct, &tc);
+ /*
+ * LTC drop-frame frame counter drops two frames (0 and 1) every
+ * minute, unless it is exactly divisible by 10
+ */
+ ltc_frame = (c->frames + 2*ct/60 - 2*ct/600) % c->sys->ltc_divisor;
+ buf[1] = (0 << 7) | /* Color fame: 0 - unsync; 1 - sync mode */
+ (1 << 6) | /* Drop frame timecode: 0 - nondrop; 1 - drop */
+ ((ltc_frame / 10) << 4) | /* Tens of frames */
+ (ltc_frame % 10); /* Units of frames */
+ buf[2] = (1 << 7) | /* Biphase mark polarity correction: 0 - even; 1 - odd */
+ ((tc.tm_sec / 10) << 4) | /* Tens of seconds */
+ (tc.tm_sec % 10); /* Units of seconds */
+ buf[3] = (1 << 7) | /* Binary group flag BGF0 */
+ ((tc.tm_min / 10) << 4) | /* Tens of minutes */
+ (tc.tm_min % 10); /* Units of minutes */
+ buf[4] = (1 << 7) | /* Binary group flag BGF2 */
+ (1 << 6) | /* Binary group flag BGF1 */
+ ((tc.tm_hour / 10) << 4) | /* Tens of hours */
+ (tc.tm_hour % 10); /* Units of hours */
+ break;
+ case dv_audio_source: /* AAUX source pack */
+ buf[1] = (0 << 7) | /* locked mode */
+ (1 << 6) | /* reserved -- always 1 */
+ (dv_audio_frame_size(c->sys, c->frames) -
+ c->sys->audio_min_samples[0]);
+ /* # of samples */
+ buf[2] = (0 << 7) | /* multi-stereo */
+ (0 << 5) | /* #of audio channels per block: 0 -- 1 channel */
+ (0 << 4) | /* pair bit: 0 -- one pair of channels */
+ 0; /* audio mode */
+ buf[3] = (1 << 7) | /* res */
+ (1 << 6) | /* multi-language flag */
+ (c->sys->dsf << 5) | /* system: 60fields/50fields */
+ (c->sys->n_difchan & 2); /* definition: 0 -- 25Mbps, 2 -- 50Mbps */
+ buf[4] = (1 << 7) | /* emphasis: 1 -- off */
+ (0 << 6) | /* emphasis time constant: 0 -- reserved */
+ (0 << 3) | /* frequency: 0 -- 48Khz, 1 -- 44,1Khz, 2 -- 32Khz */
+ 0; /* quantization: 0 -- 16bit linear, 1 -- 12bit nonlinear */
+ break;
+ case dv_audio_control:
+ buf[1] = (0 << 6) | /* copy protection: 0 -- unrestricted */
+ (1 << 4) | /* input source: 1 -- digital input */
+ (3 << 2) | /* compression: 3 -- no information */
+ 0; /* misc. info/SMPTE emphasis off */
+ buf[2] = (1 << 7) | /* recording start point: 1 -- no */
+ (1 << 6) | /* recording end point: 1 -- no */
+ (1 << 3) | /* recording mode: 1 -- original */
+ 7;
+ buf[3] = (1 << 7) | /* direction: 1 -- forward */
+ (c->sys->pix_fmt == PIX_FMT_YUV420P ? 0x20 : /* speed */
+ c->sys->ltc_divisor*4);
+ buf[4] = (1 << 7) | /* reserved -- always 1 */
+ 0x7f; /* genre category */
+ break;
+ case dv_audio_recdate:
+ case dv_video_recdate: /* VAUX recording date */
+ ct = c->start_time + (time_t)(c->frames /
+ ((float)c->sys->frame_rate / (float)c->sys->frame_rate_base));
+ brktimegm(ct, &tc);
+ buf[1] = 0xff; /* ds, tm, tens of time zone, units of time zone */
+ /* 0xff is very likely to be "unknown" */
+ buf[2] = (3 << 6) | /* reserved -- always 1 */
+ ((tc.tm_mday / 10) << 4) | /* Tens of day */
+ (tc.tm_mday % 10); /* Units of day */
+ buf[3] = /* we set high 4 bits to 0, shouldn't we set them to week? */
+ ((tc.tm_mon / 10) << 4) | /* Tens of month */
+ (tc.tm_mon % 10); /* Units of month */
+ buf[4] = (((tc.tm_year % 100) / 10) << 4) | /* Tens of year */
+ (tc.tm_year % 10); /* Units of year */
+ break;
+ case dv_audio_rectime: /* AAUX recording time */
+ case dv_video_rectime: /* VAUX recording time */
+ ct = c->start_time + (time_t)(c->frames /
+ ((float)c->sys->frame_rate / (float)c->sys->frame_rate_base));
+ brktimegm(ct, &tc);
+ buf[1] = (3 << 6) | /* reserved -- always 1 */
+ 0x3f; /* tens of frame, units of frame: 0x3f - "unknown" ? */
+ buf[2] = (1 << 7) | /* reserved -- always 1 */
+ ((tc.tm_sec / 10) << 4) | /* Tens of seconds */
+ (tc.tm_sec % 10); /* Units of seconds */
+ buf[3] = (1 << 7) | /* reserved -- always 1 */
+ ((tc.tm_min / 10) << 4) | /* Tens of minutes */
+ (tc.tm_min % 10); /* Units of minutes */
+ buf[4] = (3 << 6) | /* reserved -- always 1 */
+ ((tc.tm_hour / 10) << 4) | /* Tens of hours */
+ (tc.tm_hour % 10); /* Units of hours */
+ break;
+ default:
+ buf[1] = buf[2] = buf[3] = buf[4] = 0xff;
+ }
+ return 5;
+}
+
+static void dv_inject_audio(DVMuxContext *c, int channel, uint8_t* frame_ptr)
+{
+ int i, j, d, of, size;
+ size = 4 * dv_audio_frame_size(c->sys, c->frames);
+ frame_ptr += channel * c->sys->difseg_size * 150 * 80;
+ for (i = 0; i < c->sys->difseg_size; i++) {
+ frame_ptr += 6 * 80; /* skip DIF segment header */
+ for (j = 0; j < 9; j++) {
+ dv_write_pack(dv_aaux_packs_dist[i][j], c, &frame_ptr[3]);
+ for (d = 8; d < 80; d+=2) {
+ of = c->sys->audio_shuffle[i][j] + (d - 8)/2 * c->sys->audio_stride;
+ if (of*2 >= size)
+ continue;
+
+ frame_ptr[d] = av_fifo_peek(&c->audio_data[channel], of*2+1); // FIXME: may be we have to admit
+ frame_ptr[d+1] = av_fifo_peek(&c->audio_data[channel], of*2); // that DV is a big endian PCM
+ }
+ frame_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */
+ }
+ }
+}
+
+static void dv_inject_metadata(DVMuxContext *c, uint8_t* frame)
+{
+ int j, k;
+ uint8_t* buf;
+
+ for (buf = frame; buf < frame + c->sys->frame_size; buf += 150 * 80) {
+ /* DV subcode: 2nd and 3d DIFs */
+ for (j = 80; j < 80 * 3; j += 80) {
+ for (k = 6; k < 6 * 8; k += 8)
+ dv_write_pack(dv_timecode, c, &buf[j+k]);
+
+ if (((long)(buf-frame)/(c->sys->frame_size/(c->sys->difseg_size*c->sys->n_difchan))%c->sys->difseg_size) > 5) { /* FIXME: is this really needed ? */
+ dv_write_pack(dv_video_recdate, c, &buf[j+14]);
+ dv_write_pack(dv_video_rectime, c, &buf[j+22]);
+ dv_write_pack(dv_video_recdate, c, &buf[j+38]);
+ dv_write_pack(dv_video_rectime, c, &buf[j+46]);
+ }
+ }
+
+ /* DV VAUX: 4th, 5th and 6th 3DIFs */
+ for (j = 80*3 + 3; j < 80*6; j += 80) {
+ dv_write_pack(dv_video_recdate, c, &buf[j+5*2]);
+ dv_write_pack(dv_video_rectime, c, &buf[j+5*3]);
+ dv_write_pack(dv_video_recdate, c, &buf[j+5*11]);
+ dv_write_pack(dv_video_rectime, c, &buf[j+5*12]);
+ }
+ }
+}
+
+/*
+ * The following 3 functions constitute our interface to the world
+ */
+
+int dv_assemble_frame(DVMuxContext *c, AVStream* st,
+ const uint8_t* data, int data_size, uint8_t** frame)
+{
+ int i, reqasize;
+
+ *frame = &c->frame_buf[0];
+ reqasize = 4 * dv_audio_frame_size(c->sys, c->frames);
+
+ switch (st->codec->codec_type) {
+ case CODEC_TYPE_VIDEO:
+ /* FIXME: we have to have more sensible approach than this one */
+ if (c->has_video)
+ av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient audio data or severe sync problem.\n", c->frames);
+
+ memcpy(*frame, data, c->sys->frame_size);
+ c->has_video = 1;
+ break;
+ case CODEC_TYPE_AUDIO:
+ for (i = 0; i < c->n_ast && st != c->ast[i]; i++);
+
+ /* FIXME: we have to have more sensible approach than this one */
+ if (av_fifo_size(&c->audio_data[i]) + data_size >= 100*AVCODEC_MAX_AUDIO_FRAME_SIZE)
+ av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames);
+ av_fifo_write(&c->audio_data[i], data, data_size);
+
+ /* Lets see if we've got enough audio for one DV frame */
+ c->has_audio |= ((reqasize <= av_fifo_size(&c->audio_data[i])) << i);
+
+ break;
+ default:
+ break;
+ }
+
+ /* Lets see if we have enough data to construct one DV frame */
+ if (c->has_video == 1 && c->has_audio + 1 == 1<<c->n_ast) {
+ dv_inject_metadata(c, *frame);
+ for (i=0; i<c->n_ast; i++) {
+ dv_inject_audio(c, i, *frame);
+ av_fifo_drain(&c->audio_data[i], reqasize);
+ }
+
+ c->has_video = 0;
+ c->has_audio = 0;
+ c->frames++;
+
+ return c->sys->frame_size;
+ }
+
+ return 0;
+}
+
+DVMuxContext* dv_init_mux(AVFormatContext* s)
+{
+ DVMuxContext *c = (DVMuxContext *)s->priv_data;
+ AVStream *vst = NULL;
+ int i;
+
+ /* we support at most 1 video and 2 audio streams */
+ if (s->nb_streams > 3)
+ return NULL;
+
+ c->n_ast = 0;
+ c->ast[0] = c->ast[1] = NULL;
+
+ /* We have to sort out where audio and where video stream is */
+ for (i=0; i<s->nb_streams; i++) {
+ switch (s->streams[i]->codec->codec_type) {
+ case CODEC_TYPE_VIDEO:
+ vst = s->streams[i];
+ break;
+ case CODEC_TYPE_AUDIO:
+ c->ast[c->n_ast++] = s->streams[i];
+ break;
+ default:
+ goto bail_out;
+ }
+ }
+
+ /* Some checks -- DV format is very picky about its incoming streams */
+ if (!vst || vst->codec->codec_id != CODEC_ID_DVVIDEO)
+ goto bail_out;
+ for (i=0; i<c->n_ast; i++) {
+ if (c->ast[i] && (c->ast[i]->codec->codec_id != CODEC_ID_PCM_S16LE ||
+ c->ast[i]->codec->sample_rate != 48000 ||
+ c->ast[i]->codec->channels != 2))
+ goto bail_out;
+ }
+ c->sys = dv_codec_profile(vst->codec);
+ if (!c->sys)
+ goto bail_out;
+
+ if((c->n_ast > 1) && (c->sys->n_difchan < 2)) {
+ /* only 1 stereo pair is allowed in 25Mbps mode */
+ goto bail_out;
+ }
+
+ /* Ok, everything seems to be in working order */
+ c->frames = 0;
+ c->has_audio = 0;
+ c->has_video = 0;
+ c->start_time = (time_t)s->timestamp;
+
+ for (i=0; i<c->n_ast; i++) {
+ if (c->ast[i] && av_fifo_init(&c->audio_data[i], 100*AVCODEC_MAX_AUDIO_FRAME_SIZE) < 0) {
+ while (i>0) {
+ i--;
+ av_fifo_free(&c->audio_data[i]);
+ }
+ goto bail_out;
+ }
+ }
+
+ return c;
+
+bail_out:
+ return NULL;
+}
+
+void dv_delete_mux(DVMuxContext *c)
+{
+ int i;
+ for (i=0; i < c->n_ast; i++)
+ av_fifo_free(&c->audio_data[i]);
+}
+
+#ifdef CONFIG_MUXERS
+static int dv_write_header(AVFormatContext *s)
+{
+ if (!dv_init_mux(s)) {
+ av_log(s, AV_LOG_ERROR, "Can't initialize DV format!\n"
+ "Make sure that you supply exactly two streams:\n"
+ " video: 25fps or 29.97fps, audio: 2ch/48Khz/PCM\n"
+ " (50Mbps allows an optional second audio stream)\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int dv_write_packet(struct AVFormatContext *s, AVPacket *pkt)
+{
+ uint8_t* frame;
+ int fsize;
+
+ fsize = dv_assemble_frame((DVMuxContext *)s->priv_data, s->streams[pkt->stream_index],
+ pkt->data, pkt->size, &frame);
+ if (fsize > 0) {
+ put_buffer(&s->pb, frame, fsize);
+ put_flush_packet(&s->pb);
+ }
+ return 0;
+}
+
+/*
+ * We might end up with some extra A/V data without matching counterpart.
+ * E.g. video data without enough audio to write the complete frame.
+ * Currently we simply drop the last frame. I don't know whether this
+ * is the best strategy of all
+ */
+static int dv_write_trailer(struct AVFormatContext *s)
+{
+ dv_delete_mux((DVMuxContext *)s->priv_data);
+ return 0;
+}
+#endif /* CONFIG_MUXERS */
+
+#ifdef CONFIG_DV_MUXER
+AVOutputFormat dv_muxer = {
+ "dv",
+ "DV video format",
+ NULL,
+ "dv",
+ sizeof(DVMuxContext),
+ CODEC_ID_PCM_S16LE,
+ CODEC_ID_DVVIDEO,
+ dv_write_header,
+ dv_write_packet,
+ dv_write_trailer,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/electronicarts.c b/contrib/ffmpeg/libavformat/electronicarts.c
new file mode 100644
index 000000000..943f75b42
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/electronicarts.c
@@ -0,0 +1,291 @@
+/* Electronic Arts Multimedia File Demuxer
+ * 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 electronicarts.c
+ * Electronic Arts Multimedia file demuxer (WVE/UV2/etc.)
+ * by Robin Kay (komadori at gekkou.co.uk)
+ */
+
+#include "avformat.h"
+
+#define SCHl_TAG MKTAG('S', 'C', 'H', 'l')
+#define PT00_TAG MKTAG('P', 'T', 0x0, 0x0)
+#define SCDl_TAG MKTAG('S', 'C', 'D', 'l')
+#define pIQT_TAG MKTAG('p', 'I', 'Q', 'T')
+#define SCEl_TAG MKTAG('S', 'C', 'E', 'l')
+#define _TAG MKTAG('', '', '', '')
+
+#define EA_SAMPLE_RATE 22050
+#define EA_BITS_PER_SAMPLE 16
+#define EA_PREAMBLE_SIZE 8
+
+typedef struct EaDemuxContext {
+ int width;
+ int height;
+ int video_stream_index;
+ int track_count;
+
+ int audio_stream_index;
+ int audio_frame_counter;
+
+ int64_t audio_pts;
+ int64_t video_pts;
+ int video_pts_inc;
+ float fps;
+
+ int num_channels;
+ int num_samples;
+ int compression_type;
+} EaDemuxContext;
+
+static uint32_t read_arbitary(ByteIOContext *pb) {
+ uint8_t size, byte;
+ int i;
+ uint32_t word;
+
+ size = get_byte(pb);
+
+ word = 0;
+ for (i = 0; i < size; i++) {
+ byte = get_byte(pb);
+ word <<= 8;
+ word |= byte;
+ }
+
+ return word;
+}
+
+/*
+ * Process WVE file header
+ * Returns 1 if the WVE file is valid and successfully opened, 0 otherwise
+ */
+static int process_ea_header(AVFormatContext *s) {
+ int inHeader;
+ uint32_t blockid, size;
+ EaDemuxContext *ea = (EaDemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+
+ if (get_buffer(pb, (void*)&blockid, 4) != 4) {
+ return 0;
+ }
+ if (le2me_32(blockid) != SCHl_TAG) {
+ return 0;
+ }
+
+ if (get_buffer(pb, (void*)&size, 4) != 4) {
+ return 0;
+ }
+ size = le2me_32(size);
+
+ if (get_buffer(pb, (void*)&blockid, 4) != 4) {
+ return 0;
+ }
+ if (le2me_32(blockid) != PT00_TAG) {
+ av_log (s, AV_LOG_ERROR, "PT header missing\n");
+ return 0;
+ }
+
+ inHeader = 1;
+ while (inHeader) {
+ int inSubheader;
+ uint8_t byte;
+ byte = get_byte(pb) & 0xFF;
+
+ switch (byte) {
+ case 0xFD:
+ av_log (s, AV_LOG_INFO, "entered audio subheader\n");
+ inSubheader = 1;
+ while (inSubheader) {
+ uint8_t subbyte;
+ subbyte = get_byte(pb) & 0xFF;
+
+ switch (subbyte) {
+ case 0x82:
+ ea->num_channels = read_arbitary(pb);
+ av_log (s, AV_LOG_INFO, "num_channels (element 0x82) set to 0x%08x\n", ea->num_channels);
+ break;
+ case 0x83:
+ ea->compression_type = read_arbitary(pb);
+ av_log (s, AV_LOG_INFO, "compression_type (element 0x83) set to 0x%08x\n", ea->compression_type);
+ break;
+ case 0x85:
+ ea->num_samples = read_arbitary(pb);
+ av_log (s, AV_LOG_INFO, "num_samples (element 0x85) set to 0x%08x\n", ea->num_samples);
+ break;
+ case 0x8A:
+ av_log (s, AV_LOG_INFO, "element 0x%02x set to 0x%08x\n", subbyte, read_arbitary(pb));
+ av_log (s, AV_LOG_INFO, "exited audio subheader\n");
+ inSubheader = 0;
+ break;
+ default:
+ av_log (s, AV_LOG_INFO, "element 0x%02x set to 0x%08x\n", subbyte, read_arbitary(pb));
+ break;
+ }
+ }
+ break;
+ case 0xFF:
+ av_log (s, AV_LOG_INFO, "end of header block reached\n");
+ inHeader = 0;
+ break;
+ default:
+ av_log (s, AV_LOG_INFO, "header element 0x%02x set to 0x%08x\n", byte, read_arbitary(pb));
+ break;
+ }
+ }
+
+ if ((ea->num_channels != 2) || (ea->compression_type != 7)) {
+ av_log (s, AV_LOG_ERROR, "unsupported stream type\n");
+ return 0;
+ }
+
+ /* skip to the start of the data */
+ url_fseek(pb, size, SEEK_SET);
+
+ return 1;
+}
+
+
+static int ea_probe(AVProbeData *p)
+{
+ if (p->buf_size < 4)
+ return 0;
+
+ if (LE_32(&p->buf[0]) != SCHl_TAG)
+ return 0;
+
+ return AVPROBE_SCORE_MAX;
+}
+
+static int ea_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ EaDemuxContext *ea = (EaDemuxContext *)s->priv_data;
+ AVStream *st;
+
+ if (!process_ea_header(s))
+ return AVERROR_IO;
+
+#if 0
+ /* initialize the video decoder stream */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ av_set_pts_info(st, 33, 1, 90000);
+ ea->video_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_EA_MJPEG;
+ st->codec->codec_tag = 0; /* no fourcc */
+#endif
+
+ /* initialize the audio decoder stream */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ av_set_pts_info(st, 33, 1, EA_SAMPLE_RATE);
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_ADPCM_EA;
+ st->codec->codec_tag = 0; /* no tag */
+ st->codec->channels = ea->num_channels;
+ st->codec->sample_rate = EA_SAMPLE_RATE;
+ st->codec->bits_per_sample = EA_BITS_PER_SAMPLE;
+ st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
+ st->codec->bits_per_sample / 4;
+ st->codec->block_align = st->codec->channels * st->codec->bits_per_sample;
+
+ ea->audio_stream_index = st->index;
+ ea->audio_frame_counter = 0;
+
+ return 1;
+}
+
+static int ea_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ EaDemuxContext *ea = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int ret = 0;
+ int packet_read = 0;
+ unsigned char preamble[EA_PREAMBLE_SIZE];
+ unsigned int chunk_type, chunk_size;
+
+ while (!packet_read) {
+
+ if (get_buffer(pb, preamble, EA_PREAMBLE_SIZE) != EA_PREAMBLE_SIZE)
+ return AVERROR_IO;
+ chunk_type = LE_32(&preamble[0]);
+ chunk_size = LE_32(&preamble[4]) - EA_PREAMBLE_SIZE;
+
+ switch (chunk_type) {
+ /* audio data */
+ case SCDl_TAG:
+ ret = av_get_packet(pb, pkt, chunk_size);
+ if (ret != chunk_size)
+ ret = AVERROR_IO;
+ else {
+ pkt->stream_index = ea->audio_stream_index;
+ pkt->pts = 90000;
+ pkt->pts *= ea->audio_frame_counter;
+ pkt->pts /= EA_SAMPLE_RATE;
+
+ /* 2 samples/byte, 1 or 2 samples per frame depending
+ * on stereo; chunk also has 12-byte header */
+ ea->audio_frame_counter += ((chunk_size - 12) * 2) /
+ ea->num_channels;
+ }
+
+ packet_read = 1;
+ break;
+
+ /* ending tag */
+ case SCEl_TAG:
+ ret = AVERROR_IO;
+ packet_read = 1;
+ break;
+
+ default:
+ url_fseek(pb, chunk_size, SEEK_CUR);
+ break;
+ }
+
+ /* ending packet */
+ if (chunk_type == SCEl_TAG) {
+ }
+ }
+
+ return ret;
+}
+
+static int ea_read_close(AVFormatContext *s)
+{
+// EaDemuxContext *ea = (EaDemuxContext *)s->priv_data;
+
+ return 0;
+}
+
+AVInputFormat ea_demuxer = {
+ "ea",
+ "Electronic Arts Multimedia Format",
+ sizeof(EaDemuxContext),
+ ea_probe,
+ ea_read_header,
+ ea_read_packet,
+ ea_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/ffm.c b/contrib/ffmpeg/libavformat/ffm.c
new file mode 100644
index 000000000..539b45d5f
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/ffm.c
@@ -0,0 +1,792 @@
+/*
+ * FFM (ffserver live feed) muxer and demuxer
+ * 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
+ */
+#include "avformat.h"
+#include <unistd.h>
+
+/* The FFM file is made of blocks of fixed size */
+#define FFM_HEADER_SIZE 14
+#define PACKET_ID 0x666d
+
+/* each packet contains frames (which can span several packets */
+#define FRAME_HEADER_SIZE 8
+#define FLAG_KEY_FRAME 0x01
+
+typedef struct FFMStream {
+ int64_t pts;
+} FFMStream;
+
+enum {
+ READ_HEADER,
+ READ_DATA,
+};
+
+typedef struct FFMContext {
+ /* only reading mode */
+ offset_t write_index, file_size;
+ int read_state;
+ uint8_t header[FRAME_HEADER_SIZE];
+
+ /* read and write */
+ int first_packet; /* true if first packet, needed to set the discontinuity tag */
+ int first_frame_in_packet; /* true if first frame in packet, needed to know if PTS information is valid */
+ int packet_size;
+ int frame_offset;
+ int64_t pts;
+ uint8_t *packet_ptr, *packet_end;
+ uint8_t packet[FFM_PACKET_SIZE];
+} FFMContext;
+
+static int64_t get_pts(AVFormatContext *s, offset_t pos);
+
+/* disable pts hack for testing */
+int ffm_nopts = 0;
+
+#ifdef CONFIG_MUXERS
+static void flush_packet(AVFormatContext *s)
+{
+ FFMContext *ffm = s->priv_data;
+ int fill_size, h;
+ ByteIOContext *pb = &s->pb;
+
+ fill_size = ffm->packet_end - ffm->packet_ptr;
+ memset(ffm->packet_ptr, 0, fill_size);
+
+ if (url_ftell(pb) % ffm->packet_size)
+ av_abort();
+
+ /* put header */
+ put_be16(pb, PACKET_ID);
+ put_be16(pb, fill_size);
+ put_be64(pb, ffm->pts);
+ h = ffm->frame_offset;
+ if (ffm->first_packet)
+ h |= 0x8000;
+ put_be16(pb, h);
+ put_buffer(pb, ffm->packet, ffm->packet_end - ffm->packet);
+ put_flush_packet(pb);
+
+ /* prepare next packet */
+ ffm->frame_offset = 0; /* no key frame */
+ ffm->pts = 0; /* no pts */
+ ffm->packet_ptr = ffm->packet;
+ ffm->first_packet = 0;
+}
+
+/* 'first' is true if first data of a frame */
+static void ffm_write_data(AVFormatContext *s,
+ const uint8_t *buf, int size,
+ int64_t pts, int first)
+{
+ FFMContext *ffm = s->priv_data;
+ int len;
+
+ if (first && ffm->frame_offset == 0)
+ ffm->frame_offset = ffm->packet_ptr - ffm->packet + FFM_HEADER_SIZE;
+ if (first && ffm->pts == 0)
+ ffm->pts = pts;
+
+ /* write as many packets as needed */
+ while (size > 0) {
+ len = ffm->packet_end - ffm->packet_ptr;
+ if (len > size)
+ len = size;
+ memcpy(ffm->packet_ptr, buf, len);
+
+ ffm->packet_ptr += len;
+ buf += len;
+ size -= len;
+ if (ffm->packet_ptr >= ffm->packet_end) {
+ /* special case : no pts in packet : we leave the current one */
+ if (ffm->pts == 0)
+ ffm->pts = pts;
+
+ flush_packet(s);
+ }
+ }
+}
+
+static int ffm_write_header(AVFormatContext *s)
+{
+ FFMContext *ffm = s->priv_data;
+ AVStream *st;
+ FFMStream *fst;
+ ByteIOContext *pb = &s->pb;
+ AVCodecContext *codec;
+ int bit_rate, i;
+
+ ffm->packet_size = FFM_PACKET_SIZE;
+
+ /* header */
+ put_le32(pb, MKTAG('F', 'F', 'M', '1'));
+ put_be32(pb, ffm->packet_size);
+ /* XXX: store write position in other file ? */
+ put_be64(pb, ffm->packet_size); /* current write position */
+
+ put_be32(pb, s->nb_streams);
+ bit_rate = 0;
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+ bit_rate += st->codec->bit_rate;
+ }
+ put_be32(pb, bit_rate);
+
+ /* list of streams */
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+ fst = av_mallocz(sizeof(FFMStream));
+ if (!fst)
+ goto fail;
+ av_set_pts_info(st, 64, 1, 1000000);
+ st->priv_data = fst;
+
+ codec = st->codec;
+ /* generic info */
+ put_be32(pb, codec->codec_id);
+ put_byte(pb, codec->codec_type);
+ put_be32(pb, codec->bit_rate);
+ put_be32(pb, st->quality);
+ put_be32(pb, codec->flags);
+ put_be32(pb, codec->flags2);
+ put_be32(pb, codec->debug);
+ /* specific info */
+ switch(codec->codec_type) {
+ case CODEC_TYPE_VIDEO:
+ put_be32(pb, codec->time_base.num);
+ put_be32(pb, codec->time_base.den);
+ put_be16(pb, codec->width);
+ put_be16(pb, codec->height);
+ put_be16(pb, codec->gop_size);
+ put_be32(pb, codec->pix_fmt);
+ put_byte(pb, codec->qmin);
+ put_byte(pb, codec->qmax);
+ put_byte(pb, codec->max_qdiff);
+ put_be16(pb, (int) (codec->qcompress * 10000.0));
+ put_be16(pb, (int) (codec->qblur * 10000.0));
+ put_be32(pb, codec->bit_rate_tolerance);
+ put_strz(pb, codec->rc_eq);
+ put_be32(pb, codec->rc_max_rate);
+ put_be32(pb, codec->rc_min_rate);
+ put_be32(pb, codec->rc_buffer_size);
+ put_be64(pb, av_dbl2int(codec->i_quant_factor));
+ put_be64(pb, av_dbl2int(codec->b_quant_factor));
+ put_be64(pb, av_dbl2int(codec->i_quant_offset));
+ put_be64(pb, av_dbl2int(codec->b_quant_offset));
+ put_be32(pb, codec->dct_algo);
+ put_be32(pb, codec->strict_std_compliance);
+ put_be32(pb, codec->max_b_frames);
+ put_be32(pb, codec->luma_elim_threshold);
+ put_be32(pb, codec->chroma_elim_threshold);
+ put_be32(pb, codec->mpeg_quant);
+ put_be32(pb, codec->intra_dc_precision);
+ put_be32(pb, codec->me_method);
+ put_be32(pb, codec->mb_decision);
+ put_be32(pb, codec->nsse_weight);
+ put_be32(pb, codec->frame_skip_cmp);
+ put_be64(pb, av_dbl2int(codec->rc_buffer_aggressivity));
+ break;
+ case CODEC_TYPE_AUDIO:
+ put_be32(pb, codec->sample_rate);
+ put_le16(pb, codec->channels);
+ put_le16(pb, codec->frame_size);
+ break;
+ default:
+ return -1;
+ }
+ /* hack to have real time */
+ if (ffm_nopts)
+ fst->pts = 0;
+ else
+ fst->pts = av_gettime();
+ }
+
+ /* flush until end of block reached */
+ while ((url_ftell(pb) % ffm->packet_size) != 0)
+ put_byte(pb, 0);
+
+ put_flush_packet(pb);
+
+ /* init packet mux */
+ ffm->packet_ptr = ffm->packet;
+ ffm->packet_end = ffm->packet + ffm->packet_size - FFM_HEADER_SIZE;
+ assert(ffm->packet_end >= ffm->packet);
+ ffm->frame_offset = 0;
+ ffm->pts = 0;
+ ffm->first_packet = 1;
+
+ return 0;
+ fail:
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+ av_freep(&st->priv_data);
+ }
+ return -1;
+}
+
+static int ffm_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ AVStream *st = s->streams[pkt->stream_index];
+ FFMStream *fst = st->priv_data;
+ int64_t pts;
+ uint8_t header[FRAME_HEADER_SIZE];
+ int duration;
+ int size= pkt->size;
+
+ //XXX/FIXME use duration from pkt
+ if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
+ duration = ((float)st->codec->frame_size / st->codec->sample_rate * 1000000.0);
+ } else {
+ duration = (1000000.0 * st->codec->time_base.num / (float)st->codec->time_base.den);
+ }
+
+ pts = fst->pts;
+ /* packet size & key_frame */
+ header[0] = pkt->stream_index;
+ header[1] = 0;
+ if (pkt->flags & PKT_FLAG_KEY)
+ header[1] |= FLAG_KEY_FRAME;
+ header[2] = (size >> 16) & 0xff;
+ header[3] = (size >> 8) & 0xff;
+ header[4] = size & 0xff;
+ header[5] = (duration >> 16) & 0xff;
+ header[6] = (duration >> 8) & 0xff;
+ header[7] = duration & 0xff;
+ ffm_write_data(s, header, FRAME_HEADER_SIZE, pts, 1);
+ ffm_write_data(s, pkt->data, size, pts, 0);
+
+ fst->pts += duration;
+ return 0;
+}
+
+static int ffm_write_trailer(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+ FFMContext *ffm = s->priv_data;
+
+ /* flush packets */
+ if (ffm->packet_ptr > ffm->packet)
+ flush_packet(s);
+
+ put_flush_packet(pb);
+
+ if (!url_is_streamed(pb)) {
+ int64_t size;
+ /* update the write offset */
+ size = url_ftell(pb);
+ url_fseek(pb, 8, SEEK_SET);
+ put_be64(pb, size);
+ put_flush_packet(pb);
+ }
+
+ return 0;
+}
+#endif //CONFIG_MUXERS
+
+/* ffm demux */
+
+static int ffm_is_avail_data(AVFormatContext *s, int size)
+{
+ FFMContext *ffm = s->priv_data;
+ offset_t pos, avail_size;
+ int len;
+
+ len = ffm->packet_end - ffm->packet_ptr;
+ if (!ffm_nopts) {
+ /* XXX: I don't understand this test, so I disabled it for testing */
+ if (size <= len)
+ return 1;
+ }
+ pos = url_ftell(&s->pb);
+ if (pos == ffm->write_index) {
+ /* exactly at the end of stream */
+ return 0;
+ } else if (pos < ffm->write_index) {
+ avail_size = ffm->write_index - pos;
+ } else {
+ avail_size = (ffm->file_size - pos) + (ffm->write_index - FFM_PACKET_SIZE);
+ }
+ avail_size = (avail_size / ffm->packet_size) * (ffm->packet_size - FFM_HEADER_SIZE) + len;
+ if (size <= avail_size)
+ return 1;
+ else
+ return 0;
+}
+
+/* first is true if we read the frame header */
+static int ffm_read_data(AVFormatContext *s,
+ uint8_t *buf, int size, int first)
+{
+ FFMContext *ffm = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int len, fill_size, size1, frame_offset;
+
+ size1 = size;
+ while (size > 0) {
+ redo:
+ len = ffm->packet_end - ffm->packet_ptr;
+ if (len > size)
+ len = size;
+ if (len == 0) {
+ if (url_ftell(pb) == ffm->file_size)
+ url_fseek(pb, ffm->packet_size, SEEK_SET);
+ retry_read:
+ get_be16(pb); /* PACKET_ID */
+ fill_size = get_be16(pb);
+ ffm->pts = get_be64(pb);
+ ffm->first_frame_in_packet = 1;
+ frame_offset = get_be16(pb);
+ get_buffer(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE);
+ ffm->packet_end = ffm->packet + (ffm->packet_size - FFM_HEADER_SIZE - fill_size);
+ if (ffm->packet_end < ffm->packet)
+ return -1;
+ /* if first packet or resynchronization packet, we must
+ handle it specifically */
+ if (ffm->first_packet || (frame_offset & 0x8000)) {
+ if (!frame_offset) {
+ /* This packet has no frame headers in it */
+ if (url_ftell(pb) >= ffm->packet_size * 3) {
+ url_fseek(pb, -ffm->packet_size * 2, SEEK_CUR);
+ goto retry_read;
+ }
+ /* This is bad, we cannot find a valid frame header */
+ return 0;
+ }
+ ffm->first_packet = 0;
+ if ((frame_offset & 0x7ffff) < FFM_HEADER_SIZE)
+ return -1;
+ ffm->packet_ptr = ffm->packet + (frame_offset & 0x7fff) - FFM_HEADER_SIZE;
+ if (!first)
+ break;
+ } else {
+ ffm->packet_ptr = ffm->packet;
+ }
+ goto redo;
+ }
+ memcpy(buf, ffm->packet_ptr, len);
+ buf += len;
+ ffm->packet_ptr += len;
+ size -= len;
+ first = 0;
+ }
+ return size1 - size;
+}
+
+
+static void adjust_write_index(AVFormatContext *s)
+{
+ FFMContext *ffm = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int64_t pts;
+ //offset_t orig_write_index = ffm->write_index;
+ offset_t pos_min, pos_max;
+ int64_t pts_start;
+ offset_t ptr = url_ftell(pb);
+
+
+ pos_min = 0;
+ pos_max = ffm->file_size - 2 * FFM_PACKET_SIZE;
+
+ pts_start = get_pts(s, pos_min);
+
+ pts = get_pts(s, pos_max);
+
+ if (pts - 100000 > pts_start)
+ goto end;
+
+ ffm->write_index = FFM_PACKET_SIZE;
+
+ pts_start = get_pts(s, pos_min);
+
+ pts = get_pts(s, pos_max);
+
+ if (pts - 100000 <= pts_start) {
+ while (1) {
+ offset_t newpos;
+ int64_t newpts;
+
+ newpos = ((pos_max + pos_min) / (2 * FFM_PACKET_SIZE)) * FFM_PACKET_SIZE;
+
+ if (newpos == pos_min)
+ break;
+
+ newpts = get_pts(s, newpos);
+
+ if (newpts - 100000 <= pts) {
+ pos_max = newpos;
+ pts = newpts;
+ } else {
+ pos_min = newpos;
+ }
+ }
+ ffm->write_index += pos_max;
+ }
+
+ //printf("Adjusted write index from %"PRId64" to %"PRId64": pts=%0.6f\n", orig_write_index, ffm->write_index, pts / 1000000.);
+ //printf("pts range %0.6f - %0.6f\n", get_pts(s, 0) / 1000000. , get_pts(s, ffm->file_size - 2 * FFM_PACKET_SIZE) / 1000000. );
+
+ end:
+ url_fseek(pb, ptr, SEEK_SET);
+}
+
+
+static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ FFMContext *ffm = s->priv_data;
+ AVStream *st;
+ FFMStream *fst;
+ ByteIOContext *pb = &s->pb;
+ AVCodecContext *codec;
+ int i, nb_streams;
+ uint32_t tag;
+
+ /* header */
+ tag = get_le32(pb);
+ if (tag != MKTAG('F', 'F', 'M', '1'))
+ goto fail;
+ ffm->packet_size = get_be32(pb);
+ if (ffm->packet_size != FFM_PACKET_SIZE)
+ goto fail;
+ ffm->write_index = get_be64(pb);
+ /* get also filesize */
+ if (!url_is_streamed(pb)) {
+ ffm->file_size = url_fsize(pb);
+ adjust_write_index(s);
+ } else {
+ ffm->file_size = (uint64_t_C(1) << 63) - 1;
+ }
+
+ nb_streams = get_be32(pb);
+ get_be32(pb); /* total bitrate */
+ /* read each stream */
+ for(i=0;i<nb_streams;i++) {
+ char rc_eq_buf[128];
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ goto fail;
+ fst = av_mallocz(sizeof(FFMStream));
+ if (!fst)
+ goto fail;
+ s->streams[i] = st;
+
+ av_set_pts_info(st, 64, 1, 1000000);
+
+ st->priv_data = fst;
+
+ codec = st->codec;
+ /* generic info */
+ codec->codec_id = get_be32(pb);
+ codec->codec_type = get_byte(pb); /* codec_type */
+ codec->bit_rate = get_be32(pb);
+ st->quality = get_be32(pb);
+ codec->flags = get_be32(pb);
+ codec->flags2 = get_be32(pb);
+ codec->debug = get_be32(pb);
+ /* specific info */
+ switch(codec->codec_type) {
+ case CODEC_TYPE_VIDEO:
+ codec->time_base.num = get_be32(pb);
+ codec->time_base.den = get_be32(pb);
+ codec->width = get_be16(pb);
+ codec->height = get_be16(pb);
+ codec->gop_size = get_be16(pb);
+ codec->pix_fmt = get_be32(pb);
+ codec->qmin = get_byte(pb);
+ codec->qmax = get_byte(pb);
+ codec->max_qdiff = get_byte(pb);
+ codec->qcompress = get_be16(pb) / 10000.0;
+ codec->qblur = get_be16(pb) / 10000.0;
+ codec->bit_rate_tolerance = get_be32(pb);
+ codec->rc_eq = av_strdup(get_strz(pb, rc_eq_buf, sizeof(rc_eq_buf)));
+ codec->rc_max_rate = get_be32(pb);
+ codec->rc_min_rate = get_be32(pb);
+ codec->rc_buffer_size = get_be32(pb);
+ codec->i_quant_factor = av_int2dbl(get_be64(pb));
+ codec->b_quant_factor = av_int2dbl(get_be64(pb));
+ codec->i_quant_offset = av_int2dbl(get_be64(pb));
+ codec->b_quant_offset = av_int2dbl(get_be64(pb));
+ codec->dct_algo = get_be32(pb);
+ codec->strict_std_compliance = get_be32(pb);
+ codec->max_b_frames = get_be32(pb);
+ codec->luma_elim_threshold = get_be32(pb);
+ codec->chroma_elim_threshold = get_be32(pb);
+ codec->mpeg_quant = get_be32(pb);
+ codec->intra_dc_precision = get_be32(pb);
+ codec->me_method = get_be32(pb);
+ codec->mb_decision = get_be32(pb);
+ codec->nsse_weight = get_be32(pb);
+ codec->frame_skip_cmp = get_be32(pb);
+ codec->rc_buffer_aggressivity = av_int2dbl(get_be64(pb));
+ break;
+ case CODEC_TYPE_AUDIO:
+ codec->sample_rate = get_be32(pb);
+ codec->channels = get_le16(pb);
+ codec->frame_size = get_le16(pb);
+ break;
+ default:
+ goto fail;
+ }
+
+ }
+
+ /* get until end of block reached */
+ while ((url_ftell(pb) % ffm->packet_size) != 0)
+ get_byte(pb);
+
+ /* init packet demux */
+ ffm->packet_ptr = ffm->packet;
+ ffm->packet_end = ffm->packet;
+ ffm->frame_offset = 0;
+ ffm->pts = 0;
+ ffm->read_state = READ_HEADER;
+ ffm->first_packet = 1;
+ return 0;
+ fail:
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+ if (st) {
+ av_freep(&st->priv_data);
+ av_free(st);
+ }
+ }
+ return -1;
+}
+
+/* return < 0 if eof */
+static int ffm_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ int size;
+ FFMContext *ffm = s->priv_data;
+ int duration;
+
+ switch(ffm->read_state) {
+ case READ_HEADER:
+ if (!ffm_is_avail_data(s, FRAME_HEADER_SIZE)) {
+ return -EAGAIN;
+ }
+#if 0
+ printf("pos=%08"PRIx64" spos=%"PRIx64", write_index=%"PRIx64" size=%"PRIx64"\n",
+ url_ftell(&s->pb), s->pb.pos, ffm->write_index, ffm->file_size);
+#endif
+ if (ffm_read_data(s, ffm->header, FRAME_HEADER_SIZE, 1) !=
+ FRAME_HEADER_SIZE)
+ return -EAGAIN;
+#if 0
+ {
+ int i;
+ for(i=0;i<FRAME_HEADER_SIZE;i++)
+ printf("%02x ", ffm->header[i]);
+ printf("\n");
+ }
+#endif
+ ffm->read_state = READ_DATA;
+ /* fall thru */
+ case READ_DATA:
+ size = (ffm->header[2] << 16) | (ffm->header[3] << 8) | ffm->header[4];
+ if (!ffm_is_avail_data(s, size)) {
+ return -EAGAIN;
+ }
+
+ duration = (ffm->header[5] << 16) | (ffm->header[6] << 8) | ffm->header[7];
+
+ av_new_packet(pkt, size);
+ pkt->stream_index = ffm->header[0];
+ pkt->pos = url_ftell(&s->pb);
+ if (ffm->header[1] & FLAG_KEY_FRAME)
+ pkt->flags |= PKT_FLAG_KEY;
+
+ ffm->read_state = READ_HEADER;
+ if (ffm_read_data(s, pkt->data, size, 0) != size) {
+ /* bad case: desynchronized packet. we cancel all the packet loading */
+ av_free_packet(pkt);
+ return -EAGAIN;
+ }
+ if (ffm->first_frame_in_packet)
+ {
+ pkt->pts = ffm->pts;
+ ffm->first_frame_in_packet = 0;
+ }
+ pkt->duration = duration;
+ break;
+ }
+ return 0;
+}
+
+//#define DEBUG_SEEK
+
+/* pos is between 0 and file_size - FFM_PACKET_SIZE. It is translated
+ by the write position inside this function */
+static void ffm_seek1(AVFormatContext *s, offset_t pos1)
+{
+ FFMContext *ffm = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ offset_t pos;
+
+ pos = pos1 + ffm->write_index;
+ if (pos >= ffm->file_size)
+ pos -= (ffm->file_size - FFM_PACKET_SIZE);
+#ifdef DEBUG_SEEK
+ printf("seek to %"PRIx64" -> %"PRIx64"\n", pos1, pos);
+#endif
+ url_fseek(pb, pos, SEEK_SET);
+}
+
+static int64_t get_pts(AVFormatContext *s, offset_t pos)
+{
+ ByteIOContext *pb = &s->pb;
+ int64_t pts;
+
+ ffm_seek1(s, pos);
+ url_fskip(pb, 4);
+ pts = get_be64(pb);
+#ifdef DEBUG_SEEK
+ printf("pts=%0.6f\n", pts / 1000000.0);
+#endif
+ return pts;
+}
+
+/* seek to a given time in the file. The file read pointer is
+ positionned at or before pts. XXX: the following code is quite
+ approximative */
+static int ffm_seek(AVFormatContext *s, int stream_index, int64_t wanted_pts, int flags)
+{
+ FFMContext *ffm = s->priv_data;
+ offset_t pos_min, pos_max, pos;
+ int64_t pts_min, pts_max, pts;
+ double pos1;
+
+#ifdef DEBUG_SEEK
+ printf("wanted_pts=%0.6f\n", wanted_pts / 1000000.0);
+#endif
+ /* find the position using linear interpolation (better than
+ dichotomy in typical cases) */
+ pos_min = 0;
+ pos_max = ffm->file_size - 2 * FFM_PACKET_SIZE;
+ while (pos_min <= pos_max) {
+ pts_min = get_pts(s, pos_min);
+ pts_max = get_pts(s, pos_max);
+ /* linear interpolation */
+ pos1 = (double)(pos_max - pos_min) * (double)(wanted_pts - pts_min) /
+ (double)(pts_max - pts_min);
+ pos = (((int64_t)pos1) / FFM_PACKET_SIZE) * FFM_PACKET_SIZE;
+ if (pos <= pos_min)
+ pos = pos_min;
+ else if (pos >= pos_max)
+ pos = pos_max;
+ pts = get_pts(s, pos);
+ /* check if we are lucky */
+ if (pts == wanted_pts) {
+ goto found;
+ } else if (pts > wanted_pts) {
+ pos_max = pos - FFM_PACKET_SIZE;
+ } else {
+ pos_min = pos + FFM_PACKET_SIZE;
+ }
+ }
+ pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max;
+ if (pos > 0)
+ pos -= FFM_PACKET_SIZE;
+ found:
+ ffm_seek1(s, pos);
+ return 0;
+}
+
+#ifdef CONFIG_FFSERVER
+offset_t ffm_read_write_index(int fd)
+{
+ uint8_t buf[8];
+ offset_t pos;
+ int i;
+
+ lseek(fd, 8, SEEK_SET);
+ read(fd, buf, 8);
+ pos = 0;
+ for(i=0;i<8;i++)
+ pos |= (int64_t)buf[i] << (56 - i * 8);
+ return pos;
+}
+
+void ffm_write_write_index(int fd, offset_t pos)
+{
+ uint8_t buf[8];
+ int i;
+
+ for(i=0;i<8;i++)
+ buf[i] = (pos >> (56 - i * 8)) & 0xff;
+ lseek(fd, 8, SEEK_SET);
+ write(fd, buf, 8);
+}
+
+void ffm_set_write_index(AVFormatContext *s, offset_t pos, offset_t file_size)
+{
+ FFMContext *ffm = s->priv_data;
+ ffm->write_index = pos;
+ ffm->file_size = file_size;
+}
+#endif // CONFIG_FFSERVER
+
+static int ffm_read_close(AVFormatContext *s)
+{
+ AVStream *st;
+ int i;
+
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+ av_freep(&st->priv_data);
+ }
+ return 0;
+}
+
+static int ffm_probe(AVProbeData *p)
+{
+ if (p->buf_size >= 4 &&
+ p->buf[0] == 'F' && p->buf[1] == 'F' && p->buf[2] == 'M' &&
+ p->buf[3] == '1')
+ return AVPROBE_SCORE_MAX + 1;
+ return 0;
+}
+
+#ifdef CONFIG_FFM_DEMUXER
+AVInputFormat ffm_demuxer = {
+ "ffm",
+ "ffm format",
+ sizeof(FFMContext),
+ ffm_probe,
+ ffm_read_header,
+ ffm_read_packet,
+ ffm_read_close,
+ ffm_seek,
+};
+#endif
+#ifdef CONFIG_FFM_MUXER
+AVOutputFormat ffm_muxer = {
+ "ffm",
+ "ffm format",
+ "",
+ "ffm",
+ sizeof(FFMContext),
+ /* not really used */
+ CODEC_ID_MP2,
+ CODEC_ID_MPEG1VIDEO,
+ ffm_write_header,
+ ffm_write_packet,
+ ffm_write_trailer,
+};
+#endif //CONFIG_FFM_MUXER
diff --git a/contrib/ffmpeg/libavformat/file.c b/contrib/ffmpeg/libavformat/file.c
new file mode 100644
index 000000000..db671698f
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/file.c
@@ -0,0 +1,140 @@
+/*
+ * Buffered file io for ffmpeg system
+ * 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
+ */
+#include "avformat.h"
+#include <fcntl.h>
+#ifndef __MINGW32__
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#else
+#include <io.h>
+#define open(fname,oflag,pmode) _open(fname,oflag,pmode)
+#endif /* __MINGW32__ */
+
+
+/* standard file protocol */
+
+static int file_open(URLContext *h, const char *filename, int flags)
+{
+ int access;
+ int fd;
+
+ strstart(filename, "file:", &filename);
+
+ if (flags & URL_RDWR) {
+ access = O_CREAT | O_TRUNC | O_RDWR;
+ } else if (flags & URL_WRONLY) {
+ access = O_CREAT | O_TRUNC | O_WRONLY;
+ } else {
+ access = O_RDONLY;
+ }
+#if defined(__MINGW32__) || defined(CONFIG_OS2) || defined(__CYGWIN__)
+ access |= O_BINARY;
+#endif
+ fd = open(filename, access, 0666);
+ if (fd < 0)
+ return -ENOENT;
+ h->priv_data = (void *)(size_t)fd;
+ return 0;
+}
+
+static int file_read(URLContext *h, unsigned char *buf, int size)
+{
+ int fd = (size_t)h->priv_data;
+ return read(fd, buf, size);
+}
+
+static int file_write(URLContext *h, unsigned char *buf, int size)
+{
+ int fd = (size_t)h->priv_data;
+ return write(fd, buf, size);
+}
+
+/* XXX: use llseek */
+static offset_t file_seek(URLContext *h, offset_t pos, int whence)
+{
+ int fd = (size_t)h->priv_data;
+#if defined(__MINGW32__)
+ return _lseeki64(fd, pos, whence);
+#else
+ return lseek(fd, pos, whence);
+#endif
+}
+
+static int file_close(URLContext *h)
+{
+ int fd = (size_t)h->priv_data;
+ return close(fd);
+}
+
+URLProtocol file_protocol = {
+ "file",
+ file_open,
+ file_read,
+ file_write,
+ file_seek,
+ file_close,
+};
+
+/* pipe protocol */
+
+static int pipe_open(URLContext *h, const char *filename, int flags)
+{
+ int fd;
+
+ if (flags & URL_WRONLY) {
+ fd = 1;
+ } else {
+ fd = 0;
+ }
+#if defined(__MINGW32__) || defined(CONFIG_OS2) || defined(__CYGWIN__)
+ setmode(fd, O_BINARY);
+#endif
+ h->priv_data = (void *)(size_t)fd;
+ h->is_streamed = 1;
+ return 0;
+}
+
+static int pipe_read(URLContext *h, unsigned char *buf, int size)
+{
+ int fd = (size_t)h->priv_data;
+ return read(fd, buf, size);
+}
+
+static int pipe_write(URLContext *h, unsigned char *buf, int size)
+{
+ int fd = (size_t)h->priv_data;
+ return write(fd, buf, size);
+}
+
+static int pipe_close(URLContext *h)
+{
+ return 0;
+}
+
+URLProtocol pipe_protocol = {
+ "pipe",
+ pipe_open,
+ pipe_read,
+ pipe_write,
+ NULL,
+ pipe_close,
+};
diff --git a/contrib/ffmpeg/libavformat/flic.c b/contrib/ffmpeg/libavformat/flic.c
new file mode 100644
index 000000000..ac32e7392
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/flic.c
@@ -0,0 +1,221 @@
+/*
+ * FLI/FLC Animation File Demuxer
+ * 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 flic.c
+ * FLI/FLC file demuxer
+ * 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 demuxer handles standard 0xAF11- and 0xAF12-type FLIs. It also
+ * handles special FLIs from the PC game "Magic Carpet".
+ */
+
+#include "avformat.h"
+
+#define FLIC_FILE_MAGIC_1 0xAF11
+#define FLIC_FILE_MAGIC_2 0xAF12
+#define FLIC_FILE_MAGIC_3 0xAF44 /* Flic Type for Extended FLX Format which
+ originated in Dave's Targa Animator (DTA) */
+#define FLIC_CHUNK_MAGIC_1 0xF1FA
+#define FLIC_CHUNK_MAGIC_2 0xF5FA
+#define FLIC_MC_PTS_INC 6000 /* pts increment for Magic Carpet game FLIs */
+#define FLIC_DEFAULT_PTS_INC 6000 /* for FLIs that have 0 speed */
+
+#define FLIC_HEADER_SIZE 128
+#define FLIC_PREAMBLE_SIZE 6
+
+typedef struct FlicDemuxContext {
+ int frame_pts_inc;
+ int64_t pts;
+ int video_stream_index;
+} FlicDemuxContext;
+
+static int flic_probe(AVProbeData *p)
+{
+ int magic_number;
+
+ if (p->buf_size < 6)
+ return 0;
+
+ magic_number = LE_16(&p->buf[4]);
+ if ((magic_number != FLIC_FILE_MAGIC_1) &&
+ (magic_number != FLIC_FILE_MAGIC_2) &&
+ (magic_number != FLIC_FILE_MAGIC_3))
+ return 0;
+
+ return AVPROBE_SCORE_MAX;
+}
+
+static int flic_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ FlicDemuxContext *flic = (FlicDemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ unsigned char header[FLIC_HEADER_SIZE];
+ AVStream *st;
+ int speed;
+ int magic_number;
+
+ flic->pts = 0;
+
+ /* load the whole header and pull out the width and height */
+ if (get_buffer(pb, header, FLIC_HEADER_SIZE) != FLIC_HEADER_SIZE)
+ return AVERROR_IO;
+
+ magic_number = LE_16(&header[4]);
+ speed = LE_32(&header[0x10]);
+
+ /* initialize the decoder streams */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ flic->video_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_FLIC;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->width = LE_16(&header[0x08]);
+ st->codec->height = LE_16(&header[0x0A]);
+
+ if (!st->codec->width || !st->codec->height)
+ return AVERROR_INVALIDDATA;
+
+ /* send over the whole 128-byte FLIC header */
+ st->codec->extradata_size = FLIC_HEADER_SIZE;
+ st->codec->extradata = av_malloc(FLIC_HEADER_SIZE);
+ memcpy(st->codec->extradata, header, FLIC_HEADER_SIZE);
+
+ av_set_pts_info(st, 33, 1, 90000);
+
+ /* Time to figure out the framerate: If there is a FLIC chunk magic
+ * number at offset 0x10, assume this is from the Bullfrog game,
+ * Magic Carpet. */
+ if (LE_16(&header[0x10]) == FLIC_CHUNK_MAGIC_1) {
+
+ flic->frame_pts_inc = FLIC_MC_PTS_INC;
+
+ /* rewind the stream since the first chunk is at offset 12 */
+ url_fseek(pb, 12, SEEK_SET);
+
+ /* send over abbreviated FLIC header chunk */
+ av_free(st->codec->extradata);
+ st->codec->extradata_size = 12;
+ st->codec->extradata = av_malloc(12);
+ memcpy(st->codec->extradata, header, 12);
+
+ } else if (magic_number == FLIC_FILE_MAGIC_1) {
+ /*
+ * in this case, the speed (n) is number of 1/70s ticks between frames:
+ *
+ * pts n * frame #
+ * -------- = ----------- => pts = n * (90000/70) * frame #
+ * 90000 70
+ *
+ * therefore, the frame pts increment = n * 1285.7
+ */
+ flic->frame_pts_inc = speed * 1285.7;
+ } else if ((magic_number == FLIC_FILE_MAGIC_2) ||
+ (magic_number == FLIC_FILE_MAGIC_3)) {
+ /*
+ * in this case, the speed (n) is number of milliseconds between frames:
+ *
+ * pts n * frame #
+ * -------- = ----------- => pts = n * 90 * frame #
+ * 90000 1000
+ *
+ * therefore, the frame pts increment = n * 90
+ */
+ flic->frame_pts_inc = speed * 90;
+ } else
+ return AVERROR_INVALIDDATA;
+
+ if (flic->frame_pts_inc == 0)
+ flic->frame_pts_inc = FLIC_DEFAULT_PTS_INC;
+
+ return 0;
+}
+
+static int flic_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ FlicDemuxContext *flic = (FlicDemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int packet_read = 0;
+ unsigned int size;
+ int magic;
+ int ret = 0;
+ unsigned char preamble[FLIC_PREAMBLE_SIZE];
+
+ while (!packet_read) {
+
+ if ((ret = get_buffer(pb, preamble, FLIC_PREAMBLE_SIZE)) !=
+ FLIC_PREAMBLE_SIZE) {
+ ret = AVERROR_IO;
+ break;
+ }
+
+ size = LE_32(&preamble[0]);
+ magic = LE_16(&preamble[4]);
+
+ if (((magic == FLIC_CHUNK_MAGIC_1) || (magic == FLIC_CHUNK_MAGIC_2)) && size > FLIC_PREAMBLE_SIZE) {
+ if (av_new_packet(pkt, size)) {
+ ret = AVERROR_IO;
+ break;
+ }
+ pkt->stream_index = flic->video_stream_index;
+ pkt->pts = flic->pts;
+ pkt->pos = url_ftell(pb);
+ memcpy(pkt->data, preamble, FLIC_PREAMBLE_SIZE);
+ ret = get_buffer(pb, pkt->data + FLIC_PREAMBLE_SIZE,
+ size - FLIC_PREAMBLE_SIZE);
+ if (ret != size - FLIC_PREAMBLE_SIZE) {
+ av_free_packet(pkt);
+ ret = AVERROR_IO;
+ }
+ flic->pts += flic->frame_pts_inc;
+ packet_read = 1;
+ } else {
+ /* not interested in this chunk */
+ url_fseek(pb, size - 6, SEEK_CUR);
+ }
+ }
+
+ return ret;
+}
+
+static int flic_read_close(AVFormatContext *s)
+{
+// FlicDemuxContext *flic = (FlicDemuxContext *)s->priv_data;
+
+ return 0;
+}
+
+AVInputFormat flic_demuxer = {
+ "flic",
+ "FLI/FLC/FLX animation format",
+ sizeof(FlicDemuxContext),
+ flic_probe,
+ flic_read_header,
+ flic_read_packet,
+ flic_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/flvdec.c b/contrib/ffmpeg/libavformat/flvdec.c
new file mode 100644
index 000000000..a1c2aa4eb
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/flvdec.c
@@ -0,0 +1,259 @@
+/*
+ * FLV demuxer
+ * 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
+ *
+ *
+ * This demuxer will generate a 1 byte extradata for VP6F content.
+ * It is composed of:
+ * - upper 4bits: difference between encoded width and visible width
+ * - lower 4bits: difference between encoded height and visible height
+ */
+#include "avformat.h"
+
+static int flv_probe(AVProbeData *p)
+{
+ const uint8_t *d;
+
+ if (p->buf_size < 6)
+ return 0;
+ d = p->buf;
+ if (d[0] == 'F' && d[1] == 'L' && d[2] == 'V') {
+ return 50;
+ }
+ return 0;
+}
+
+static int flv_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ int offset, flags, size;
+
+ s->ctx_flags |= AVFMTCTX_NOHEADER; //ok we have a header but theres no fps, codec type, sample_rate, ...
+
+ url_fskip(&s->pb, 4);
+ flags = get_byte(&s->pb);
+
+ offset = get_be32(&s->pb);
+
+ if(!url_is_streamed(&s->pb)){
+ const int fsize= url_fsize(&s->pb);
+ url_fseek(&s->pb, fsize-4, SEEK_SET);
+ size= get_be32(&s->pb);
+ url_fseek(&s->pb, fsize-3-size, SEEK_SET);
+ if(size == get_be24(&s->pb) + 11){
+ s->duration= get_be24(&s->pb) * (int64_t)AV_TIME_BASE / 1000;
+ }
+ }
+
+ url_fseek(&s->pb, offset, SEEK_SET);
+
+ s->start_time = 0;
+
+ return 0;
+}
+
+static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ int ret, i, type, size, pts, flags, is_audio, next, pos;
+ AVStream *st = NULL;
+
+ for(;;){
+ pos = url_ftell(&s->pb);
+ url_fskip(&s->pb, 4); /* size of previous packet */
+ type = get_byte(&s->pb);
+ size = get_be24(&s->pb);
+ pts = get_be24(&s->pb);
+// av_log(s, AV_LOG_DEBUG, "type:%d, size:%d, pts:%d\n", type, size, pts);
+ if (url_feof(&s->pb))
+ return AVERROR_IO;
+ url_fskip(&s->pb, 4); /* reserved */
+ flags = 0;
+
+ if(size == 0)
+ continue;
+
+ next= size + url_ftell(&s->pb);
+
+ if (type == 8) {
+ is_audio=1;
+ flags = get_byte(&s->pb);
+ } else if (type == 9) {
+ is_audio=0;
+ flags = get_byte(&s->pb);
+ } else if (type == 18 && size > 13+1+4) {
+ url_fskip(&s->pb, 13); //onMetaData blah
+ if(get_byte(&s->pb) == 8){
+ url_fskip(&s->pb, 4);
+ }
+ while(url_ftell(&s->pb) + 5 < next){
+ char tmp[128];
+ int type, len;
+ double d= 0;
+
+ len= get_be16(&s->pb);
+ if(len >= sizeof(tmp) || !len)
+ break;
+ get_buffer(&s->pb, tmp, len);
+ tmp[len]=0;
+
+ type= get_byte(&s->pb);
+ if(type==0){
+ d= av_int2dbl(get_be64(&s->pb));
+ }else if(type==2){
+ len= get_be16(&s->pb);
+ if(len >= sizeof(tmp))
+ break;
+ url_fskip(&s->pb, len);
+ }else if(type==8){
+ //array
+ break;
+ }else if(type==11){
+ d= av_int2dbl(get_be64(&s->pb));
+ get_be16(&s->pb);
+ }
+
+ if(!strcmp(tmp, "duration")){
+ s->duration = d*AV_TIME_BASE;
+ }else if(!strcmp(tmp, "videodatarate")){
+ }else if(!strcmp(tmp, "audiodatarate")){
+ }
+ }
+ url_fseek(&s->pb, next, SEEK_SET);
+ continue;
+ } else {
+ /* skip packet */
+ av_log(s, AV_LOG_ERROR, "skipping flv packet: type %d, size %d, flags %d\n", type, size, flags);
+ url_fseek(&s->pb, next, SEEK_SET);
+ continue;
+ }
+
+ /* now find stream */
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+ if (st->id == is_audio)
+ break;
+ }
+ if(i == s->nb_streams){
+ st = av_new_stream(s, is_audio);
+ if (!st)
+ return AVERROR_NOMEM;
+
+ av_set_pts_info(st, 24, 1, 1000); /* 24 bit pts in ms */
+ st->codec->time_base= (AVRational){1,1000};
+ }
+// av_log(NULL, AV_LOG_DEBUG, "%d %X %d \n", is_audio, flags, st->discard);
+ if( (st->discard >= AVDISCARD_NONKEY && !((flags >> 4)==1 || is_audio))
+ ||(st->discard >= AVDISCARD_BIDIR && ((flags >> 4)==3 && !is_audio))
+ || st->discard >= AVDISCARD_ALL
+ ){
+ url_fseek(&s->pb, next, SEEK_SET);
+ continue;
+ }
+ if ((flags >> 4)==1)
+ av_add_index_entry(st, pos, pts, size, 0, AVINDEX_KEYFRAME);
+ break;
+ }
+
+ if(is_audio){
+ if(st->codec->sample_rate == 0){
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->channels = (flags&1)+1;
+ if((flags >> 4) == 5)
+ st->codec->sample_rate= 8000;
+ else
+ st->codec->sample_rate = (44100<<((flags>>2)&3))>>3;
+ switch(flags >> 4){/* 0: uncompressed 1: ADPCM 2: mp3 5: Nellymoser 8kHz mono 6: Nellymoser*/
+ case 0: if (flags&2) st->codec->codec_id = CODEC_ID_PCM_S16BE;
+ else st->codec->codec_id = CODEC_ID_PCM_S8; break;
+ case 1: st->codec->codec_id = CODEC_ID_ADPCM_SWF; break;
+ case 2: st->codec->codec_id = CODEC_ID_MP3; st->need_parsing = 1; break;
+ // this is not listed at FLV but at SWF, strange...
+ case 3: if (flags&2) st->codec->codec_id = CODEC_ID_PCM_S16LE;
+ else st->codec->codec_id = CODEC_ID_PCM_S8; break;
+ default:
+ av_log(s, AV_LOG_INFO, "Unsupported audio codec (%x)\n", flags >> 4);
+ st->codec->codec_tag= (flags >> 4);
+ }
+ st->codec->bits_per_sample = (flags & 2) ? 16 : 8;
+ }
+ }else{
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ switch(flags & 0xF){
+ case 2: st->codec->codec_id = CODEC_ID_FLV1; break;
+ case 3: st->codec->codec_id = CODEC_ID_FLASHSV; break;
+ case 4:
+ st->codec->codec_id = CODEC_ID_VP6F;
+ if (st->codec->extradata_size != 1) {
+ st->codec->extradata_size = 1;
+ st->codec->extradata = av_malloc(1);
+ }
+ /* width and height adjustment */
+ st->codec->extradata[0] = get_byte(&s->pb);
+ size--;
+ break;
+ default:
+ av_log(s, AV_LOG_INFO, "Unsupported video codec (%x)\n", flags & 0xf);
+ st->codec->codec_tag= flags & 0xF;
+ }
+ }
+
+ ret= av_get_packet(&s->pb, pkt, size - 1);
+ if (ret <= 0) {
+ return AVERROR_IO;
+ }
+ /* note: we need to modify the packet size here to handle the last
+ packet */
+ pkt->size = ret;
+ pkt->pts = pts;
+ pkt->stream_index = st->index;
+
+ if (is_audio || ((flags >> 4)==1))
+ pkt->flags |= PKT_FLAG_KEY;
+
+ return ret;
+}
+
+static int flv_read_close(AVFormatContext *s)
+{
+ return 0;
+}
+
+static int flv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
+{
+ AVStream *st = s->streams[stream_index];
+ int index = av_index_search_timestamp(st, timestamp, flags);
+ if (index < 0)
+ return -1;
+ url_fseek(&s->pb, st->index_entries[index].pos, SEEK_SET);
+
+ return 0;
+}
+
+AVInputFormat flv_demuxer = {
+ "flv",
+ "flv format",
+ 0,
+ flv_probe,
+ flv_read_header,
+ flv_read_packet,
+ flv_read_close,
+ flv_read_seek,
+ .extensions = "flv",
+ .value = CODEC_ID_FLV1,
+};
diff --git a/contrib/ffmpeg/libavformat/flvenc.c b/contrib/ffmpeg/libavformat/flvenc.c
new file mode 100644
index 000000000..0b09d9830
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/flvenc.c
@@ -0,0 +1,284 @@
+/*
+ * FLV muxer
+ * 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 "avformat.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+typedef struct FLVContext {
+ int hasAudio;
+ int hasVideo;
+ int reserved;
+ offset_t duration_offset;
+ offset_t filesize_offset;
+ int64_t duration;
+} FLVContext;
+
+static int get_audio_flags(AVCodecContext *enc){
+ int flags = (enc->bits_per_sample == 16) ? 0x2 : 0x0;
+
+ switch (enc->sample_rate) {
+ case 44100:
+ flags |= 0x0C;
+ break;
+ case 22050:
+ flags |= 0x08;
+ break;
+ case 11025:
+ flags |= 0x04;
+ break;
+ case 8000: //nellymoser only
+ case 5512: //not mp3
+ flags |= 0x00;
+ break;
+ default:
+ av_log(enc, AV_LOG_ERROR, "flv doesnt support that sample rate, choose from (44100, 22050, 11025)\n");
+ return -1;
+ }
+
+ if (enc->channels > 1) {
+ flags |= 0x01;
+ }
+
+ switch(enc->codec_id){
+ case CODEC_ID_MP3:
+ flags |= 0x20 | 0x2;
+ break;
+ case CODEC_ID_PCM_S8:
+ break;
+ case CODEC_ID_PCM_S16BE:
+ flags |= 0x2;
+ break;
+ case CODEC_ID_PCM_S16LE:
+ flags |= 0x30 | 0x2;
+ break;
+ case CODEC_ID_ADPCM_SWF:
+ flags |= 0x10;
+ break;
+ case 0:
+ flags |= enc->codec_tag<<4;
+ break;
+ default:
+ av_log(enc, AV_LOG_ERROR, "codec not compatible with flv\n");
+ return -1;
+ }
+
+ return flags;
+}
+
+#define AMF_DOUBLE 0
+#define AMF_BOOLEAN 1
+#define AMF_STRING 2
+#define AMF_OBJECT 3
+#define AMF_MIXED_ARRAY 8
+#define AMF_ARRAY 10
+#define AMF_DATE 11
+
+static void put_amf_string(ByteIOContext *pb, const char *str)
+{
+ size_t len = strlen(str);
+ put_be16(pb, len);
+ put_buffer(pb, str, len);
+}
+
+static void put_amf_double(ByteIOContext *pb, double d)
+{
+ put_byte(pb, AMF_DOUBLE);
+ put_be64(pb, av_dbl2int(d));
+}
+
+static int flv_write_header(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+ FLVContext *flv = s->priv_data;
+ int i, width, height, samplerate;
+ double framerate = 0.0;
+ int metadata_size_pos, data_size;
+
+ flv->hasAudio = 0;
+ flv->hasVideo = 0;
+
+ put_tag(pb,"FLV");
+ put_byte(pb,1);
+ put_byte(pb,0); // delayed write
+ put_be32(pb,9);
+ put_be32(pb,0);
+
+ for(i=0; i<s->nb_streams; i++){
+ AVCodecContext *enc = s->streams[i]->codec;
+ if (enc->codec_type == CODEC_TYPE_VIDEO) {
+ width = enc->width;
+ height = enc->height;
+ if (s->streams[i]->r_frame_rate.den && s->streams[i]->r_frame_rate.num) {
+ framerate = av_q2d(s->streams[i]->r_frame_rate);
+ } else {
+ framerate = 1/av_q2d(s->streams[i]->codec->time_base);
+ }
+ flv->hasVideo=1;
+ } else {
+ flv->hasAudio=1;
+ samplerate = enc->sample_rate;
+ }
+ av_set_pts_info(s->streams[i], 24, 1, 1000); /* 24 bit pts in ms */
+ if(enc->codec_tag == 5){
+ put_byte(pb,8); // message type
+ put_be24(pb,0); // include flags
+ put_be24(pb,0); // time stamp
+ put_be32(pb,0); // reserved
+ put_be32(pb,11); // size
+ flv->reserved=5;
+ }
+ if(enc->codec_type == CODEC_TYPE_AUDIO && get_audio_flags(enc)<0)
+ return -1;
+ }
+
+ /* write meta_tag */
+ put_byte(pb, 18); // tag type META
+ metadata_size_pos= url_ftell(pb);
+ put_be24(pb, 0); // size of data part (sum of all parts below)
+ put_be24(pb, 0); // time stamp
+ put_be32(pb, 0); // reserved
+
+ /* now data of data_size size */
+
+ /* first event name as a string */
+ put_byte(pb, AMF_STRING); // 1 byte
+ put_amf_string(pb, "onMetaData"); // 12 bytes
+
+ /* mixed array (hash) with size and string/type/data tuples */
+ put_byte(pb, AMF_MIXED_ARRAY);
+ put_be32(pb, 4*flv->hasVideo + flv->hasAudio + 2); // +2 for duration and file size
+
+ put_amf_string(pb, "duration");
+ flv->duration_offset= url_ftell(pb);
+ put_amf_double(pb, 0); // delayed write
+
+ if(flv->hasVideo){
+ put_amf_string(pb, "width");
+ put_amf_double(pb, width);
+
+ put_amf_string(pb, "height");
+ put_amf_double(pb, height);
+
+ put_amf_string(pb, "videodatarate");
+ put_amf_double(pb, s->bit_rate / 1024.0);
+
+ put_amf_string(pb, "framerate");
+ put_amf_double(pb, framerate);
+ }
+
+ if(flv->hasAudio){
+ put_amf_string(pb, "audiosamplerate");
+ put_amf_double(pb, samplerate);
+ }
+
+ put_amf_string(pb, "filesize");
+ flv->filesize_offset= url_ftell(pb);
+ put_amf_double(pb, 0); // delayed write
+
+ put_amf_string(pb, "");
+ put_byte(pb, 9); // end marker 1 byte
+
+ /* write total size of tag */
+ data_size= url_ftell(pb) - metadata_size_pos - 10;
+ url_fseek(pb, metadata_size_pos, SEEK_SET);
+ put_be24(pb, data_size);
+ url_fseek(pb, data_size + 10 - 3, SEEK_CUR);
+ put_be32(pb, data_size + 11);
+
+ return 0;
+}
+
+static int flv_write_trailer(AVFormatContext *s)
+{
+ int64_t file_size;
+ int flags = 0;
+
+ ByteIOContext *pb = &s->pb;
+ FLVContext *flv = s->priv_data;
+
+ file_size = url_ftell(pb);
+ flags |= flv->hasAudio ? 4 : 0;
+ flags |= flv->hasVideo ? 1 : 0;
+ url_fseek(pb, 4, SEEK_SET);
+ put_byte(pb,flags);
+
+ /* update informations */
+ url_fseek(pb, flv->duration_offset, SEEK_SET);
+ put_amf_double(pb, flv->duration / (double)1000);
+ url_fseek(pb, flv->filesize_offset, SEEK_SET);
+ put_amf_double(pb, file_size);
+
+ url_fseek(pb, file_size, SEEK_SET);
+ return 0;
+}
+
+static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ ByteIOContext *pb = &s->pb;
+ AVCodecContext *enc = s->streams[pkt->stream_index]->codec;
+ FLVContext *flv = s->priv_data;
+ int size= pkt->size;
+ int flags;
+
+// av_log(s, AV_LOG_DEBUG, "type:%d pts: %"PRId64" size:%d\n", enc->codec_type, timestamp, size);
+
+ if (enc->codec_type == CODEC_TYPE_VIDEO) {
+ put_byte(pb, 9);
+ flags = 2; // choose h263
+ flags |= pkt->flags & PKT_FLAG_KEY ? 0x10 : 0x20; // add keyframe indicator
+ } else {
+ assert(enc->codec_type == CODEC_TYPE_AUDIO);
+ flags = get_audio_flags(enc);
+
+ assert(size);
+
+ put_byte(pb, 8);
+ }
+
+ put_be24(pb,size+1); // include flags
+ put_be24(pb,pkt->pts);
+ put_be32(pb,flv->reserved);
+ put_byte(pb,flags);
+ put_buffer(pb, pkt->data, size);
+ put_be32(pb,size+1+11); // previous tag size
+ flv->duration = pkt->pts + pkt->duration;
+
+ put_flush_packet(pb);
+ return 0;
+}
+
+AVOutputFormat flv_muxer = {
+ "flv",
+ "flv format",
+ "video/x-flv",
+ "flv",
+ sizeof(FLVContext),
+#ifdef CONFIG_MP3LAME
+ CODEC_ID_MP3,
+#else // CONFIG_MP3LAME
+ CODEC_ID_NONE,
+#endif // CONFIG_MP3LAME
+ CODEC_ID_FLV1,
+ flv_write_header,
+ flv_write_packet,
+ flv_write_trailer,
+};
diff --git a/contrib/ffmpeg/libavformat/framehook.c b/contrib/ffmpeg/libavformat/framehook.c
new file mode 100644
index 000000000..03bbc95f6
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/framehook.c
@@ -0,0 +1,121 @@
+/*
+ * Video processing hooks
+ * 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 <errno.h>
+#include "config.h"
+#include "avformat.h"
+#include "framehook.h"
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+
+typedef struct _FrameHookEntry {
+ struct _FrameHookEntry *next;
+ FrameHookConfigureFn Configure;
+ FrameHookProcessFn Process;
+ FrameHookReleaseFn Release;
+ void *ctx;
+} FrameHookEntry;
+
+static FrameHookEntry *first_hook;
+
+/* Returns 0 on OK */
+int frame_hook_add(int argc, char *argv[])
+{
+#ifdef CONFIG_VHOOK
+ void *loaded;
+ FrameHookEntry *fhe, **fhep;
+
+ if (argc < 1) {
+ return ENOENT;
+ }
+
+ loaded = dlopen(argv[0], RTLD_NOW);
+ if (!loaded) {
+ av_log(NULL, AV_LOG_ERROR, "%s\n", dlerror());
+ return -1;
+ }
+
+ fhe = av_mallocz(sizeof(*fhe));
+ if (!fhe) {
+ return errno;
+ }
+
+ fhe->Configure = dlsym(loaded, "Configure");
+ fhe->Process = dlsym(loaded, "Process");
+ fhe->Release = dlsym(loaded, "Release"); /* Optional */
+
+ if (!fhe->Process) {
+ av_log(NULL, AV_LOG_ERROR, "Failed to find Process entrypoint in %s\n", argv[0]);
+ return -1;
+ }
+
+ if (!fhe->Configure && argc > 1) {
+ av_log(NULL, AV_LOG_ERROR, "Failed to find Configure entrypoint in %s\n", argv[0]);
+ return -1;
+ }
+
+ if (argc > 1 || fhe->Configure) {
+ if (fhe->Configure(&fhe->ctx, argc, argv)) {
+ av_log(NULL, AV_LOG_ERROR, "Failed to Configure %s\n", argv[0]);
+ return -1;
+ }
+ }
+
+ for (fhep = &first_hook; *fhep; fhep = &((*fhep)->next)) {
+ }
+
+ *fhep = fhe;
+
+ return 0;
+#else
+ av_log(NULL, AV_LOG_ERROR, "Video hooking not compiled into this version\n");
+ return 1;
+#endif
+}
+
+void frame_hook_process(AVPicture *pict, enum PixelFormat pix_fmt, int width, int height)
+{
+ if (first_hook) {
+ FrameHookEntry *fhe;
+ int64_t pts = av_gettime();
+
+ for (fhe = first_hook; fhe; fhe = fhe->next) {
+ fhe->Process(fhe->ctx, pict, pix_fmt, width, height, pts);
+ }
+ }
+}
+
+void frame_hook_release(void)
+{
+ FrameHookEntry *fhe;
+ FrameHookEntry *fhenext;
+
+ for (fhe = first_hook; fhe; fhe = fhenext) {
+ fhenext = fhe->next;
+ if (fhe->Release)
+ fhe->Release(fhe->ctx);
+ av_free(fhe);
+ }
+
+ first_hook = NULL;
+}
diff --git a/contrib/ffmpeg/libavformat/framehook.h b/contrib/ffmpeg/libavformat/framehook.h
new file mode 100644
index 000000000..d843ddb85
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/framehook.h
@@ -0,0 +1,50 @@
+/*
+ * video processing hooks
+ * 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
+ */
+
+#ifndef _FRAMEHOOK_H
+#define _FRAMEHOOK_H
+
+/*
+ * Prototypes for interface to .so that implement a video processing hook
+ */
+
+#include "avcodec.h"
+
+/* Function must be called 'Configure' */
+typedef int (FrameHookConfigure)(void **ctxp, int argc, char *argv[]);
+typedef FrameHookConfigure *FrameHookConfigureFn;
+extern FrameHookConfigure Configure;
+
+/* Function must be called 'Process' */
+typedef void (FrameHookProcess)(void *ctx, struct AVPicture *pict, enum PixelFormat pix_fmt, int width, int height, int64_t pts);
+typedef FrameHookProcess *FrameHookProcessFn;
+extern FrameHookProcess Process;
+
+/* Function must be called 'Release' */
+typedef void (FrameHookRelease)(void *ctx);
+typedef FrameHookRelease *FrameHookReleaseFn;
+extern FrameHookRelease Release;
+
+extern int frame_hook_add(int argc, char *argv[]);
+extern void frame_hook_process(struct AVPicture *pict, enum PixelFormat pix_fmt, int width, int height);
+extern void frame_hook_release(void);
+
+#endif
diff --git a/contrib/ffmpeg/libavformat/gif.c b/contrib/ffmpeg/libavformat/gif.c
new file mode 100644
index 000000000..1083710d5
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/gif.c
@@ -0,0 +1,419 @@
+/*
+ * Animated GIF muxer
+ * 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
+ */
+
+/*
+ * First version by Francois Revol revol@free.fr
+ *
+ * Features and limitations:
+ * - currently no compression is performed,
+ * in fact the size of the data is 9/8 the size of the image in 8bpp
+ * - 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
+ *
+ * this url claims to have an LZW algorithm not covered by Unisys patent:
+ * http://www.msg.net/utility/whirlgif/gifencod.html
+ * could help reduce the size of the files _a lot_...
+ * some sites mentions an RLE type compression also.
+ */
+
+#include "avformat.h"
+#include "bitstream.h"
+
+/* bitstream minipacket size */
+#define GIF_CHUNKS 100
+
+/* slows down the decoding (and some browsers don't like it) */
+/* update on the 'some browsers don't like it issue from above: this was probably due to missing 'Data Sub-block Terminator' (byte 19) in the app_header */
+#define GIF_ADD_APP_HEADER // required to enable looping of animated gif
+
+typedef struct {
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+} rgb_triplet;
+
+/* we use the standard 216 color palette */
+
+/* this script was used to create the palette:
+ * for r in 00 33 66 99 cc ff; do for g in 00 33 66 99 cc ff; do echo -n " "; for b in 00 33 66 99 cc ff; do
+ * echo -n "{ 0x$r, 0x$g, 0x$b }, "; done; echo ""; done; done
+ */
+
+static const rgb_triplet gif_clut[216] = {
+ { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x33 }, { 0x00, 0x00, 0x66 }, { 0x00, 0x00, 0x99 }, { 0x00, 0x00, 0xcc }, { 0x00, 0x00, 0xff },
+ { 0x00, 0x33, 0x00 }, { 0x00, 0x33, 0x33 }, { 0x00, 0x33, 0x66 }, { 0x00, 0x33, 0x99 }, { 0x00, 0x33, 0xcc }, { 0x00, 0x33, 0xff },
+ { 0x00, 0x66, 0x00 }, { 0x00, 0x66, 0x33 }, { 0x00, 0x66, 0x66 }, { 0x00, 0x66, 0x99 }, { 0x00, 0x66, 0xcc }, { 0x00, 0x66, 0xff },
+ { 0x00, 0x99, 0x00 }, { 0x00, 0x99, 0x33 }, { 0x00, 0x99, 0x66 }, { 0x00, 0x99, 0x99 }, { 0x00, 0x99, 0xcc }, { 0x00, 0x99, 0xff },
+ { 0x00, 0xcc, 0x00 }, { 0x00, 0xcc, 0x33 }, { 0x00, 0xcc, 0x66 }, { 0x00, 0xcc, 0x99 }, { 0x00, 0xcc, 0xcc }, { 0x00, 0xcc, 0xff },
+ { 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0x33 }, { 0x00, 0xff, 0x66 }, { 0x00, 0xff, 0x99 }, { 0x00, 0xff, 0xcc }, { 0x00, 0xff, 0xff },
+ { 0x33, 0x00, 0x00 }, { 0x33, 0x00, 0x33 }, { 0x33, 0x00, 0x66 }, { 0x33, 0x00, 0x99 }, { 0x33, 0x00, 0xcc }, { 0x33, 0x00, 0xff },
+ { 0x33, 0x33, 0x00 }, { 0x33, 0x33, 0x33 }, { 0x33, 0x33, 0x66 }, { 0x33, 0x33, 0x99 }, { 0x33, 0x33, 0xcc }, { 0x33, 0x33, 0xff },
+ { 0x33, 0x66, 0x00 }, { 0x33, 0x66, 0x33 }, { 0x33, 0x66, 0x66 }, { 0x33, 0x66, 0x99 }, { 0x33, 0x66, 0xcc }, { 0x33, 0x66, 0xff },
+ { 0x33, 0x99, 0x00 }, { 0x33, 0x99, 0x33 }, { 0x33, 0x99, 0x66 }, { 0x33, 0x99, 0x99 }, { 0x33, 0x99, 0xcc }, { 0x33, 0x99, 0xff },
+ { 0x33, 0xcc, 0x00 }, { 0x33, 0xcc, 0x33 }, { 0x33, 0xcc, 0x66 }, { 0x33, 0xcc, 0x99 }, { 0x33, 0xcc, 0xcc }, { 0x33, 0xcc, 0xff },
+ { 0x33, 0xff, 0x00 }, { 0x33, 0xff, 0x33 }, { 0x33, 0xff, 0x66 }, { 0x33, 0xff, 0x99 }, { 0x33, 0xff, 0xcc }, { 0x33, 0xff, 0xff },
+ { 0x66, 0x00, 0x00 }, { 0x66, 0x00, 0x33 }, { 0x66, 0x00, 0x66 }, { 0x66, 0x00, 0x99 }, { 0x66, 0x00, 0xcc }, { 0x66, 0x00, 0xff },
+ { 0x66, 0x33, 0x00 }, { 0x66, 0x33, 0x33 }, { 0x66, 0x33, 0x66 }, { 0x66, 0x33, 0x99 }, { 0x66, 0x33, 0xcc }, { 0x66, 0x33, 0xff },
+ { 0x66, 0x66, 0x00 }, { 0x66, 0x66, 0x33 }, { 0x66, 0x66, 0x66 }, { 0x66, 0x66, 0x99 }, { 0x66, 0x66, 0xcc }, { 0x66, 0x66, 0xff },
+ { 0x66, 0x99, 0x00 }, { 0x66, 0x99, 0x33 }, { 0x66, 0x99, 0x66 }, { 0x66, 0x99, 0x99 }, { 0x66, 0x99, 0xcc }, { 0x66, 0x99, 0xff },
+ { 0x66, 0xcc, 0x00 }, { 0x66, 0xcc, 0x33 }, { 0x66, 0xcc, 0x66 }, { 0x66, 0xcc, 0x99 }, { 0x66, 0xcc, 0xcc }, { 0x66, 0xcc, 0xff },
+ { 0x66, 0xff, 0x00 }, { 0x66, 0xff, 0x33 }, { 0x66, 0xff, 0x66 }, { 0x66, 0xff, 0x99 }, { 0x66, 0xff, 0xcc }, { 0x66, 0xff, 0xff },
+ { 0x99, 0x00, 0x00 }, { 0x99, 0x00, 0x33 }, { 0x99, 0x00, 0x66 }, { 0x99, 0x00, 0x99 }, { 0x99, 0x00, 0xcc }, { 0x99, 0x00, 0xff },
+ { 0x99, 0x33, 0x00 }, { 0x99, 0x33, 0x33 }, { 0x99, 0x33, 0x66 }, { 0x99, 0x33, 0x99 }, { 0x99, 0x33, 0xcc }, { 0x99, 0x33, 0xff },
+ { 0x99, 0x66, 0x00 }, { 0x99, 0x66, 0x33 }, { 0x99, 0x66, 0x66 }, { 0x99, 0x66, 0x99 }, { 0x99, 0x66, 0xcc }, { 0x99, 0x66, 0xff },
+ { 0x99, 0x99, 0x00 }, { 0x99, 0x99, 0x33 }, { 0x99, 0x99, 0x66 }, { 0x99, 0x99, 0x99 }, { 0x99, 0x99, 0xcc }, { 0x99, 0x99, 0xff },
+ { 0x99, 0xcc, 0x00 }, { 0x99, 0xcc, 0x33 }, { 0x99, 0xcc, 0x66 }, { 0x99, 0xcc, 0x99 }, { 0x99, 0xcc, 0xcc }, { 0x99, 0xcc, 0xff },
+ { 0x99, 0xff, 0x00 }, { 0x99, 0xff, 0x33 }, { 0x99, 0xff, 0x66 }, { 0x99, 0xff, 0x99 }, { 0x99, 0xff, 0xcc }, { 0x99, 0xff, 0xff },
+ { 0xcc, 0x00, 0x00 }, { 0xcc, 0x00, 0x33 }, { 0xcc, 0x00, 0x66 }, { 0xcc, 0x00, 0x99 }, { 0xcc, 0x00, 0xcc }, { 0xcc, 0x00, 0xff },
+ { 0xcc, 0x33, 0x00 }, { 0xcc, 0x33, 0x33 }, { 0xcc, 0x33, 0x66 }, { 0xcc, 0x33, 0x99 }, { 0xcc, 0x33, 0xcc }, { 0xcc, 0x33, 0xff },
+ { 0xcc, 0x66, 0x00 }, { 0xcc, 0x66, 0x33 }, { 0xcc, 0x66, 0x66 }, { 0xcc, 0x66, 0x99 }, { 0xcc, 0x66, 0xcc }, { 0xcc, 0x66, 0xff },
+ { 0xcc, 0x99, 0x00 }, { 0xcc, 0x99, 0x33 }, { 0xcc, 0x99, 0x66 }, { 0xcc, 0x99, 0x99 }, { 0xcc, 0x99, 0xcc }, { 0xcc, 0x99, 0xff },
+ { 0xcc, 0xcc, 0x00 }, { 0xcc, 0xcc, 0x33 }, { 0xcc, 0xcc, 0x66 }, { 0xcc, 0xcc, 0x99 }, { 0xcc, 0xcc, 0xcc }, { 0xcc, 0xcc, 0xff },
+ { 0xcc, 0xff, 0x00 }, { 0xcc, 0xff, 0x33 }, { 0xcc, 0xff, 0x66 }, { 0xcc, 0xff, 0x99 }, { 0xcc, 0xff, 0xcc }, { 0xcc, 0xff, 0xff },
+ { 0xff, 0x00, 0x00 }, { 0xff, 0x00, 0x33 }, { 0xff, 0x00, 0x66 }, { 0xff, 0x00, 0x99 }, { 0xff, 0x00, 0xcc }, { 0xff, 0x00, 0xff },
+ { 0xff, 0x33, 0x00 }, { 0xff, 0x33, 0x33 }, { 0xff, 0x33, 0x66 }, { 0xff, 0x33, 0x99 }, { 0xff, 0x33, 0xcc }, { 0xff, 0x33, 0xff },
+ { 0xff, 0x66, 0x00 }, { 0xff, 0x66, 0x33 }, { 0xff, 0x66, 0x66 }, { 0xff, 0x66, 0x99 }, { 0xff, 0x66, 0xcc }, { 0xff, 0x66, 0xff },
+ { 0xff, 0x99, 0x00 }, { 0xff, 0x99, 0x33 }, { 0xff, 0x99, 0x66 }, { 0xff, 0x99, 0x99 }, { 0xff, 0x99, 0xcc }, { 0xff, 0x99, 0xff },
+ { 0xff, 0xcc, 0x00 }, { 0xff, 0xcc, 0x33 }, { 0xff, 0xcc, 0x66 }, { 0xff, 0xcc, 0x99 }, { 0xff, 0xcc, 0xcc }, { 0xff, 0xcc, 0xff },
+ { 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0x33 }, { 0xff, 0xff, 0x66 }, { 0xff, 0xff, 0x99 }, { 0xff, 0xff, 0xcc }, { 0xff, 0xff, 0xff },
+};
+
+/* The GIF format uses reversed order for bitstreams... */
+/* at least they don't use PDP_ENDIAN :) */
+/* so we 'extend' PutBitContext. hmmm, OOP :) */
+/* seems this thing changed slightly since I wrote it... */
+
+#ifdef ALT_BITSTREAM_WRITER
+# error no ALT_BITSTREAM_WRITER support for now
+#endif
+
+static void gif_put_bits_rev(PutBitContext *s, int n, unsigned int value)
+{
+ unsigned int bit_buf;
+ int bit_cnt;
+
+ // printf("put_bits=%d %x\n", n, value);
+ assert(n == 32 || value < (1U << n));
+
+ bit_buf = s->bit_buf;
+ bit_cnt = 32 - s->bit_left; /* XXX:lazyness... was = s->bit_cnt; */
+
+ // printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf);
+ /* XXX: optimize */
+ if (n < (32-bit_cnt)) {
+ bit_buf |= value << (bit_cnt);
+ bit_cnt+=n;
+ } else {
+ bit_buf |= value << (bit_cnt);
+
+ *s->buf_ptr = bit_buf & 0xff;
+ s->buf_ptr[1] = (bit_buf >> 8) & 0xff;
+ s->buf_ptr[2] = (bit_buf >> 16) & 0xff;
+ s->buf_ptr[3] = (bit_buf >> 24) & 0xff;
+
+ //printf("bitbuf = %08x\n", bit_buf);
+ s->buf_ptr+=4;
+ if (s->buf_ptr >= s->buf_end)
+ puts("bit buffer overflow !!"); // should never happen ! who got rid of the callback ???
+// flush_buffer_rev(s);
+ bit_cnt=bit_cnt + n - 32;
+ if (bit_cnt == 0) {
+ bit_buf = 0;
+ } else {
+ bit_buf = value >> (n - bit_cnt);
+ }
+ }
+
+ s->bit_buf = bit_buf;
+ s->bit_left = 32 - bit_cnt;
+}
+
+/* pad the end of the output stream with zeros */
+static void gif_flush_put_bits_rev(PutBitContext *s)
+{
+ while (s->bit_left < 32) {
+ /* XXX: should test end of buffer */
+ *s->buf_ptr++=s->bit_buf & 0xff;
+ s->bit_buf>>=8;
+ s->bit_left+=8;
+ }
+// flush_buffer_rev(s);
+ s->bit_left=32;
+ s->bit_buf=0;
+}
+
+/* !RevPutBitContext */
+
+/* GIF header */
+static int gif_image_write_header(ByteIOContext *pb,
+ int width, int height, int loop_count,
+ uint32_t *palette)
+{
+ int i;
+ unsigned int v;
+
+ put_tag(pb, "GIF");
+ put_tag(pb, "89a");
+ put_le16(pb, width);
+ put_le16(pb, height);
+
+ put_byte(pb, 0xf7); /* flags: global clut, 256 entries */
+ put_byte(pb, 0x1f); /* background color index */
+ put_byte(pb, 0); /* aspect ratio */
+
+ /* the global palette */
+ if (!palette) {
+ put_buffer(pb, (const unsigned char *)gif_clut, 216*3);
+ for(i=0;i<((256-216)*3);i++)
+ put_byte(pb, 0);
+ } else {
+ for(i=0;i<256;i++) {
+ v = palette[i];
+ put_byte(pb, (v >> 16) & 0xff);
+ put_byte(pb, (v >> 8) & 0xff);
+ put_byte(pb, (v) & 0xff);
+ }
+ }
+
+ /* update: this is the 'NETSCAPE EXTENSION' that allows for looped animated gif
+ see http://members.aol.com/royalef/gifabout.htm#net-extension
+
+ byte 1 : 33 (hex 0x21) GIF Extension code
+ byte 2 : 255 (hex 0xFF) Application Extension Label
+ byte 3 : 11 (hex (0x0B) Length of Application Block
+ (eleven bytes of data to follow)
+ bytes 4 to 11 : "NETSCAPE"
+ bytes 12 to 14 : "2.0"
+ byte 15 : 3 (hex 0x03) Length of Data Sub-Block
+ (three bytes of data to follow)
+ byte 16 : 1 (hex 0x01)
+ bytes 17 to 18 : 0 to 65535, an unsigned integer in
+ lo-hi byte format. This indicate the
+ number of iterations the loop should
+ be executed.
+ bytes 19 : 0 (hex 0x00) a Data Sub-block Terminator
+ */
+
+ /* application extension header */
+#ifdef GIF_ADD_APP_HEADER
+ if (loop_count >= 0 && loop_count <= 65535) {
+ put_byte(pb, 0x21);
+ put_byte(pb, 0xff);
+ put_byte(pb, 0x0b);
+ put_tag(pb, "NETSCAPE2.0"); // bytes 4 to 14
+ put_byte(pb, 0x03); // byte 15
+ put_byte(pb, 0x01); // byte 16
+ put_le16(pb, (uint16_t)loop_count);
+ put_byte(pb, 0x00); // byte 19
+ }
+#endif
+ return 0;
+}
+
+/* this is maybe slow, but allows for extensions */
+static inline unsigned char gif_clut_index(uint8_t r, uint8_t g, uint8_t b)
+{
+ return ((((r)/47)%6)*6*6+(((g)/47)%6)*6+(((b)/47)%6));
+}
+
+
+static int gif_image_write_image(ByteIOContext *pb,
+ int x1, int y1, int width, int height,
+ const uint8_t *buf, int linesize, int pix_fmt)
+{
+ PutBitContext p;
+ uint8_t buffer[200]; /* 100 * 9 / 8 = 113 */
+ int i, left, w, v;
+ const uint8_t *ptr;
+ /* image block */
+
+ put_byte(pb, 0x2c);
+ put_le16(pb, x1);
+ put_le16(pb, y1);
+ put_le16(pb, width);
+ put_le16(pb, height);
+ put_byte(pb, 0x00); /* flags */
+ /* no local clut */
+
+ put_byte(pb, 0x08);
+
+ left= width * height;
+
+ init_put_bits(&p, buffer, 130);
+
+/*
+ * the thing here is the bitstream is written as little packets, with a size byte before
+ * but it's still the same bitstream between packets (no flush !)
+ */
+ ptr = buf;
+ w = width;
+ while(left>0) {
+
+ gif_put_bits_rev(&p, 9, 0x0100); /* clear code */
+
+ for(i=(left<GIF_CHUNKS)?left:GIF_CHUNKS;i;i--) {
+ if (pix_fmt == PIX_FMT_RGB24) {
+ v = gif_clut_index(ptr[0], ptr[1], ptr[2]);
+ ptr+=3;
+ } else {
+ v = *ptr++;
+ }
+ gif_put_bits_rev(&p, 9, v);
+ if (--w == 0) {
+ w = width;
+ buf += linesize;
+ ptr = buf;
+ }
+ }
+
+ if(left<=GIF_CHUNKS) {
+ gif_put_bits_rev(&p, 9, 0x101); /* end of stream */
+ gif_flush_put_bits_rev(&p);
+ }
+ if(pbBufPtr(&p) - p.buf > 0) {
+ put_byte(pb, pbBufPtr(&p) - p.buf); /* byte count of the packet */
+ put_buffer(pb, p.buf, pbBufPtr(&p) - p.buf); /* the actual buffer */
+ p.buf_ptr = p.buf; /* dequeue the bytes off the bitstream */
+ }
+ left-=GIF_CHUNKS;
+ }
+ put_byte(pb, 0x00); /* end of image block */
+
+ return 0;
+}
+
+typedef struct {
+ int64_t time, file_time;
+ uint8_t buffer[100]; /* data chunks */
+} GIFContext;
+
+static int gif_write_header(AVFormatContext *s)
+{
+ GIFContext *gif = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVCodecContext *enc, *video_enc;
+ int i, width, height, loop_count /*, rate*/;
+
+/* XXX: do we reject audio streams or just ignore them ?
+ if(s->nb_streams > 1)
+ return -1;
+*/
+ gif->time = 0;
+ gif->file_time = 0;
+
+ video_enc = NULL;
+ for(i=0;i<s->nb_streams;i++) {
+ enc = s->streams[i]->codec;
+ if (enc->codec_type != CODEC_TYPE_AUDIO)
+ video_enc = enc;
+ }
+
+ if (!video_enc) {
+ av_free(gif);
+ return -1;
+ } else {
+ width = video_enc->width;
+ height = video_enc->height;
+ loop_count = s->loop_output;
+// rate = video_enc->time_base.den;
+ }
+
+ if (video_enc->pix_fmt != PIX_FMT_RGB24) {
+ av_log(s, AV_LOG_ERROR, "ERROR: gif only handles the rgb24 pixel format. Use -pix_fmt rgb24.\n");
+ return AVERROR_IO;
+ }
+
+ gif_image_write_header(pb, width, height, loop_count, NULL);
+
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+static int gif_write_video(AVFormatContext *s,
+ AVCodecContext *enc, const uint8_t *buf, int size)
+{
+ ByteIOContext *pb = &s->pb;
+ GIFContext *gif = s->priv_data;
+ int jiffies;
+ int64_t delay;
+
+ /* graphic control extension block */
+ put_byte(pb, 0x21);
+ put_byte(pb, 0xf9);
+ put_byte(pb, 0x04); /* block size */
+ put_byte(pb, 0x04); /* flags */
+
+ /* 1 jiffy is 1/70 s */
+ /* the delay_time field indicates the number of jiffies - 1 */
+ delay = gif->file_time - gif->time;
+
+ /* XXX: should use delay, in order to be more accurate */
+ /* instead of using the same rounded value each time */
+ /* XXX: don't even remember if I really use it for now */
+ jiffies = (70*enc->time_base.num/enc->time_base.den) - 1;
+
+ put_le16(pb, jiffies);
+
+ put_byte(pb, 0x1f); /* transparent color index */
+ put_byte(pb, 0x00);
+
+ gif_image_write_image(pb, 0, 0, enc->width, enc->height,
+ buf, enc->width * 3, PIX_FMT_RGB24);
+
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+static int gif_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
+ if (codec->codec_type == CODEC_TYPE_AUDIO)
+ return 0; /* just ignore audio */
+ else
+ return gif_write_video(s, codec, pkt->data, pkt->size);
+}
+
+static int gif_write_trailer(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+
+ put_byte(pb, 0x3b);
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+AVOutputFormat gif_muxer = {
+ "gif",
+ "GIF Animation",
+ "image/gif",
+ "gif",
+ sizeof(GIFContext),
+ CODEC_ID_NONE,
+ CODEC_ID_RAWVIDEO,
+ gif_write_header,
+ gif_write_packet,
+ gif_write_trailer,
+};
diff --git a/contrib/ffmpeg/libavformat/gifdec.c b/contrib/ffmpeg/libavformat/gifdec.c
new file mode 100644
index 000000000..692ca6466
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/gifdec.c
@@ -0,0 +1,593 @@
+/*
+ * GIF demuxer
+ * 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 "avformat.h"
+
+//#define DEBUG
+
+#define MAXBITS 12
+#define SIZTABLE (1<<MAXBITS)
+
+#define GCE_DISPOSAL_NONE 0
+#define GCE_DISPOSAL_INPLACE 1
+#define GCE_DISPOSAL_BACKGROUND 2
+#define GCE_DISPOSAL_RESTORE 3
+
+typedef struct GifState {
+ int screen_width;
+ int screen_height;
+ int bits_per_pixel;
+ int background_color_index;
+ int transparent_color_index;
+ int color_resolution;
+ uint8_t *image_buf;
+ int image_linesize;
+ uint32_t *image_palette;
+ int pix_fmt;
+
+ /* after the frame is displayed, the disposal method is used */
+ int gce_disposal;
+ /* delay during which the frame is shown */
+ int gce_delay;
+
+ /* LZW compatible decoder */
+ ByteIOContext *f;
+ int eob_reached;
+ uint8_t *pbuf, *ebuf;
+ int bbits;
+ unsigned int bbuf;
+
+ int cursize; /* The current code size */
+ int curmask;
+ int codesize;
+ int clear_code;
+ int end_code;
+ int newcodes; /* First available code */
+ int top_slot; /* Highest code for current size */
+ int slot; /* Last read code */
+ int fc, oc;
+ uint8_t *sp;
+ uint8_t stack[SIZTABLE];
+ uint8_t suffix[SIZTABLE];
+ uint16_t prefix[SIZTABLE];
+
+ /* aux buffers */
+ uint8_t global_palette[256 * 3];
+ uint8_t local_palette[256 * 3];
+ uint8_t buf[256];
+} GifState;
+
+
+static const uint8_t gif87a_sig[6] = "GIF87a";
+static const uint8_t gif89a_sig[6] = "GIF89a";
+
+static const uint16_t mask[17] =
+{
+ 0x0000, 0x0001, 0x0003, 0x0007,
+ 0x000F, 0x001F, 0x003F, 0x007F,
+ 0x00FF, 0x01FF, 0x03FF, 0x07FF,
+ 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
+};
+
+/* Probe gif video format or gif image format. The current heuristic
+ supposes the gif87a is always a single image. For gif89a, we
+ consider it as a video only if a GCE extension is present in the
+ first kilobyte. */
+static int gif_video_probe(AVProbeData * pd)
+{
+ const uint8_t *p, *p_end;
+ int bits_per_pixel, has_global_palette, ext_code, ext_len;
+ int gce_flags, gce_disposal;
+
+ if (pd->buf_size < 24 ||
+ memcmp(pd->buf, gif89a_sig, 6) != 0)
+ return 0;
+ p_end = pd->buf + pd->buf_size;
+ p = pd->buf + 6;
+ bits_per_pixel = (p[4] & 0x07) + 1;
+ has_global_palette = (p[4] & 0x80);
+ p += 7;
+ if (has_global_palette)
+ p += (1 << bits_per_pixel) * 3;
+ for(;;) {
+ if (p >= p_end)
+ return 0;
+ if (*p != '!')
+ break;
+ p++;
+ if (p >= p_end)
+ return 0;
+ ext_code = *p++;
+ if (p >= p_end)
+ return 0;
+ ext_len = *p++;
+ if (ext_code == 0xf9) {
+ if (p >= p_end)
+ return 0;
+ /* if GCE extension found with gce_disposal != 0: it is
+ likely to be an animation */
+ gce_flags = *p++;
+ gce_disposal = (gce_flags >> 2) & 0x7;
+ if (gce_disposal != 0)
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+ }
+ for(;;) {
+ if (ext_len == 0)
+ break;
+ p += ext_len;
+ if (p >= p_end)
+ return 0;
+ ext_len = *p++;
+ }
+ }
+ return 0;
+}
+
+static void GLZWDecodeInit(GifState * s, int csize)
+{
+ /* read buffer */
+ s->eob_reached = 0;
+ s->pbuf = s->buf;
+ s->ebuf = s->buf;
+ s->bbuf = 0;
+ s->bbits = 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 = 0;
+ s->sp = s->stack;
+}
+
+/* XXX: optimize */
+static inline int GetCode(GifState * s)
+{
+ int c, sizbuf;
+ uint8_t *ptr;
+
+ while (s->bbits < s->cursize) {
+ ptr = s->pbuf;
+ if (ptr >= s->ebuf) {
+ if (!s->eob_reached) {
+ sizbuf = get_byte(s->f);
+ s->ebuf = s->buf + sizbuf;
+ s->pbuf = s->buf;
+ if (sizbuf > 0) {
+ get_buffer(s->f, s->buf, sizbuf);
+ } else {
+ s->eob_reached = 1;
+ }
+ }
+ ptr = s->pbuf;
+ }
+ s->bbuf |= ptr[0] << s->bbits;
+ ptr++;
+ s->pbuf = ptr;
+ s->bbits += 8;
+ }
+ c = s->bbuf & s->curmask;
+ s->bbuf >>= s->cursize;
+ s->bbits -= s->cursize;
+ return c;
+}
+
+/* NOTE: the algorithm here is inspired from the LZW GIF decoder
+ written by Steven A. Bennett in 1987. */
+/* return the number of byte decoded */
+static int GLZWDecode(GifState * s, uint8_t * buf, int len)
+{
+ int l, c, code, oc, fc;
+ uint8_t *sp;
+
+ if (s->end_code < 0)
+ return 0;
+
+ l = len;
+ sp = s->sp;
+ oc = s->oc;
+ fc = s->fc;
+
+ while (sp > s->stack) {
+ *buf++ = *(--sp);
+ if ((--l) == 0)
+ goto the_end;
+ }
+
+ for (;;) {
+ c = GetCode(s);
+ if (c == s->end_code) {
+ s->end_code = -1;
+ 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;
+ while ((c = GetCode(s)) == s->clear_code);
+ if (c == s->end_code) {
+ s->end_code = -1;
+ break;
+ }
+ /* test error */
+ if (c >= s->slot)
+ c = 0;
+ fc = oc = c;
+ *buf++ = c;
+ if ((--l) == 0)
+ break;
+ } else {
+ code = c;
+ if (code >= s->slot) {
+ *sp++ = fc;
+ code = oc;
+ }
+ while (code >= s->newcodes) {
+ *sp++ = s->suffix[code];
+ code = s->prefix[code];
+ }
+ *sp++ = code;
+ if (s->slot < s->top_slot) {
+ s->suffix[s->slot] = fc = code;
+ s->prefix[s->slot++] = oc;
+ oc = c;
+ }
+ if (s->slot >= s->top_slot) {
+ if (s->cursize < MAXBITS) {
+ s->top_slot <<= 1;
+ s->curmask = mask[++s->cursize];
+ }
+ }
+ while (sp > s->stack) {
+ *buf++ = *(--sp);
+ if ((--l) == 0)
+ goto the_end;
+ }
+ }
+ }
+ the_end:
+ s->sp = sp;
+ s->oc = oc;
+ s->fc = fc;
+ return len - l;
+}
+
+static int gif_read_image(GifState *s)
+{
+ ByteIOContext *f = s->f;
+ int left, top, width, height, bits_per_pixel, code_size, flags;
+ int is_interleaved, has_local_palette, y, x, pass, y1, linesize, n, i;
+ uint8_t *ptr, *line, *d, *spal, *palette, *sptr, *ptr1;
+
+ left = get_le16(f);
+ top = get_le16(f);
+ width = get_le16(f);
+ height = get_le16(f);
+ flags = get_byte(f);
+ is_interleaved = flags & 0x40;
+ has_local_palette = flags & 0x80;
+ bits_per_pixel = (flags & 0x07) + 1;
+#ifdef DEBUG
+ printf("gif: image x=%d y=%d w=%d h=%d\n", left, top, width, height);
+#endif
+
+ if (has_local_palette) {
+ get_buffer(f, s->local_palette, 3 * (1 << bits_per_pixel));
+ palette = s->local_palette;
+ } else {
+ palette = s->global_palette;
+ bits_per_pixel = s->bits_per_pixel;
+ }
+
+ /* verify that all the image is inside the screen dimensions */
+ if (left + width > s->screen_width ||
+ top + height > s->screen_height)
+ return -EINVAL;
+
+ /* build the palette */
+ if (s->pix_fmt == PIX_FMT_RGB24) {
+ line = av_malloc(width);
+ if (!line)
+ return -ENOMEM;
+ } else {
+ n = (1 << bits_per_pixel);
+ spal = palette;
+ for(i = 0; i < n; i++) {
+ s->image_palette[i] = (0xff << 24) |
+ (spal[0] << 16) | (spal[1] << 8) | (spal[2]);
+ spal += 3;
+ }
+ for(; i < 256; i++)
+ s->image_palette[i] = (0xff << 24);
+ /* handle transparency */
+ if (s->transparent_color_index >= 0)
+ s->image_palette[s->transparent_color_index] = 0;
+ line = NULL;
+ }
+
+ /* now get the image data */
+ s->f = f;
+ code_size = get_byte(f);
+ GLZWDecodeInit(s, code_size);
+
+ /* read all the image */
+ linesize = s->image_linesize;
+ ptr1 = s->image_buf + top * linesize + (left * 3);
+ ptr = ptr1;
+ pass = 0;
+ y1 = 0;
+ for (y = 0; y < height; y++) {
+ if (s->pix_fmt == PIX_FMT_RGB24) {
+ /* transcode to RGB24 */
+ GLZWDecode(s, line, width);
+ d = ptr;
+ sptr = line;
+ for(x = 0; x < width; x++) {
+ spal = palette + sptr[0] * 3;
+ d[0] = spal[0];
+ d[1] = spal[1];
+ d[2] = spal[2];
+ d += 3;
+ sptr++;
+ }
+ } else {
+ GLZWDecode(s, ptr, width);
+ }
+ if (is_interleaved) {
+ switch(pass) {
+ default:
+ case 0:
+ case 1:
+ y1 += 8;
+ ptr += linesize * 8;
+ if (y1 >= height) {
+ y1 = 4;
+ if (pass == 0)
+ ptr = ptr1 + linesize * 4;
+ else
+ ptr = ptr1 + linesize * 2;
+ 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;
+ }
+ }
+ av_free(line);
+
+ /* read the garbage data until end marker is found */
+ while (!s->eob_reached)
+ GetCode(s);
+ return 0;
+}
+
+static int gif_read_extension(GifState *s)
+{
+ ByteIOContext *f = s->f;
+ int ext_code, ext_len, i, gce_flags, gce_transparent_index;
+
+ /* extension */
+ ext_code = get_byte(f);
+ ext_len = get_byte(f);
+#ifdef DEBUG
+ printf("gif: ext_code=0x%x len=%d\n", ext_code, ext_len);
+#endif
+ switch(ext_code) {
+ case 0xf9:
+ if (ext_len != 4)
+ goto discard_ext;
+ s->transparent_color_index = -1;
+ gce_flags = get_byte(f);
+ s->gce_delay = get_le16(f);
+ gce_transparent_index = get_byte(f);
+ if (gce_flags & 0x01)
+ s->transparent_color_index = gce_transparent_index;
+ else
+ s->transparent_color_index = -1;
+ s->gce_disposal = (gce_flags >> 2) & 0x7;
+#ifdef DEBUG
+ printf("gif: gce_flags=%x delay=%d tcolor=%d disposal=%d\n",
+ gce_flags, s->gce_delay,
+ s->transparent_color_index, s->gce_disposal);
+#endif
+ ext_len = get_byte(f);
+ break;
+ }
+
+ /* NOTE: many extension blocks can come after */
+ discard_ext:
+ while (ext_len != 0) {
+ for (i = 0; i < ext_len; i++)
+ get_byte(f);
+ ext_len = get_byte(f);
+#ifdef DEBUG
+ printf("gif: ext_len1=%d\n", ext_len);
+#endif
+ }
+ return 0;
+}
+
+static int gif_read_header1(GifState *s)
+{
+ ByteIOContext *f = s->f;
+ uint8_t sig[6];
+ int ret, v, n;
+ int has_global_palette;
+
+ /* read gif signature */
+ ret = get_buffer(f, sig, 6);
+ if (ret != 6)
+ return -1;
+ if (memcmp(sig, gif87a_sig, 6) != 0 &&
+ memcmp(sig, gif89a_sig, 6) != 0)
+ return -1;
+
+ /* read screen header */
+ s->transparent_color_index = -1;
+ s->screen_width = get_le16(f);
+ s->screen_height = get_le16(f);
+ if( (unsigned)s->screen_width > 32767
+ || (unsigned)s->screen_height > 32767){
+ av_log(NULL, AV_LOG_ERROR, "picture size too large\n");
+ return -1;
+ }
+
+ v = get_byte(f);
+ s->color_resolution = ((v & 0x70) >> 4) + 1;
+ has_global_palette = (v & 0x80);
+ s->bits_per_pixel = (v & 0x07) + 1;
+ s->background_color_index = get_byte(f);
+ get_byte(f); /* ignored */
+#ifdef DEBUG
+ printf("gif: screen_w=%d screen_h=%d bpp=%d global_palette=%d\n",
+ s->screen_width, s->screen_height, s->bits_per_pixel,
+ has_global_palette);
+#endif
+ if (has_global_palette) {
+ n = 1 << s->bits_per_pixel;
+ get_buffer(f, s->global_palette, n * 3);
+ }
+ return 0;
+}
+
+static int gif_parse_next_image(GifState *s)
+{
+ ByteIOContext *f = s->f;
+ int ret, code;
+
+ for (;;) {
+ code = url_fgetc(f);
+#ifdef DEBUG
+ printf("gif: code=%02x '%c'\n", code, code);
+#endif
+ switch (code) {
+ case ',':
+ if (gif_read_image(s) < 0)
+ return AVERROR_IO;
+ ret = 0;
+ goto the_end;
+ case ';':
+ /* end of image */
+ ret = AVERROR_IO;
+ goto the_end;
+ case '!':
+ if (gif_read_extension(s) < 0)
+ return AVERROR_IO;
+ break;
+ case EOF:
+ default:
+ /* error or errneous EOF */
+ ret = AVERROR_IO;
+ goto the_end;
+ }
+ }
+ the_end:
+ return ret;
+}
+
+static int gif_read_header(AVFormatContext * s1,
+ AVFormatParameters * ap)
+{
+ GifState *s = s1->priv_data;
+ ByteIOContext *f = &s1->pb;
+ AVStream *st;
+
+ s->f = f;
+ if (gif_read_header1(s) < 0)
+ return -1;
+
+ /* allocate image buffer */
+ s->image_linesize = s->screen_width * 3;
+ s->image_buf = av_malloc(s->screen_height * s->image_linesize);
+ if (!s->image_buf)
+ return -ENOMEM;
+ s->pix_fmt = PIX_FMT_RGB24;
+ /* now we are ready: build format streams */
+ st = av_new_stream(s1, 0);
+ if (!st)
+ return -1;
+
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_RAWVIDEO;
+ st->codec->time_base.den = 5;
+ st->codec->time_base.num = 1;
+ /* XXX: check if screen size is always valid */
+ st->codec->width = s->screen_width;
+ st->codec->height = s->screen_height;
+ st->codec->pix_fmt = PIX_FMT_RGB24;
+ return 0;
+}
+
+static int gif_read_packet(AVFormatContext * s1,
+ AVPacket * pkt)
+{
+ GifState *s = s1->priv_data;
+ int ret;
+
+ ret = gif_parse_next_image(s);
+ if (ret < 0)
+ return ret;
+
+ /* XXX: avoid copying */
+ if (av_new_packet(pkt, s->screen_width * s->screen_height * 3)) {
+ return AVERROR_IO;
+ }
+ pkt->stream_index = 0;
+ memcpy(pkt->data, s->image_buf, s->screen_width * s->screen_height * 3);
+ return 0;
+}
+
+static int gif_read_close(AVFormatContext *s1)
+{
+ GifState *s = s1->priv_data;
+ av_free(s->image_buf);
+ return 0;
+}
+
+AVInputFormat gif_demuxer =
+{
+ "gif",
+ "gif format",
+ sizeof(GifState),
+ gif_video_probe,
+ gif_read_header,
+ gif_read_packet,
+ gif_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/grab.c b/contrib/ffmpeg/libavformat/grab.c
new file mode 100644
index 000000000..4e85772e5
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/grab.c
@@ -0,0 +1,860 @@
+/*
+ * Linux video grab interface
+ * 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 "avformat.h"
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#define _LINUX_TIME_H 1
+#include <linux/videodev.h>
+#include <time.h>
+
+typedef struct {
+ int fd;
+ int frame_format; /* see VIDEO_PALETTE_xxx */
+ int use_mmap;
+ int width, height;
+ int frame_rate;
+ int frame_rate_base;
+ int64_t time_frame;
+ int frame_size;
+ struct video_capability video_cap;
+ struct video_audio audio_saved;
+ uint8_t *video_buf;
+ struct video_mbuf gb_buffers;
+ struct video_mmap gb_buf;
+ int gb_frame;
+
+ /* ATI All In Wonder specific stuff */
+ /* XXX: remove and merge in libavcodec/imgconvert.c */
+ int aiw_enabled;
+ int deint;
+ int halfw;
+ uint8_t *src_mem;
+ uint8_t *lum_m4_mem;
+} VideoData;
+
+static int aiw_init(VideoData *s);
+static int aiw_read_picture(VideoData *s, uint8_t *data);
+static int aiw_close(VideoData *s);
+
+static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
+{
+ VideoData *s = s1->priv_data;
+ AVStream *st;
+ int width, height;
+ int video_fd, frame_size;
+ int ret, frame_rate, frame_rate_base;
+ int desired_palette, desired_depth;
+ struct video_tuner tuner;
+ struct video_audio audio;
+ struct video_picture pict;
+ const char *video_device;
+ int j;
+
+ if (ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) {
+ av_log(s1, AV_LOG_ERROR, "Bad capture size (%dx%d) or wrong time base (%d)\n",
+ ap->width, ap->height, ap->time_base.den);
+
+ return -1;
+ }
+
+ width = ap->width;
+ height = ap->height;
+ frame_rate = ap->time_base.den;
+ frame_rate_base = ap->time_base.num;
+
+ if((unsigned)width > 32767 || (unsigned)height > 32767) {
+ av_log(s1, AV_LOG_ERROR, "Capture size is out of range: %dx%d\n",
+ width, height);
+
+ return -1;
+ }
+
+ st = av_new_stream(s1, 0);
+ if (!st)
+ return -ENOMEM;
+ av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
+
+ s->width = width;
+ s->height = height;
+ s->frame_rate = frame_rate;
+ s->frame_rate_base = frame_rate_base;
+
+ video_device = ap->device;
+ if (!video_device)
+ video_device = "/dev/video";
+ video_fd = open(video_device, O_RDWR);
+ if (video_fd < 0) {
+ perror(video_device);
+ goto fail;
+ }
+
+ if (ioctl(video_fd,VIDIOCGCAP, &s->video_cap) < 0) {
+ perror("VIDIOCGCAP");
+ goto fail;
+ }
+
+ if (!(s->video_cap.type & VID_TYPE_CAPTURE)) {
+ av_log(s1, AV_LOG_ERROR, "Fatal: grab device does not handle capture\n");
+ goto fail;
+ }
+
+ desired_palette = -1;
+ desired_depth = -1;
+ if (ap->pix_fmt == PIX_FMT_YUV420P) {
+ desired_palette = VIDEO_PALETTE_YUV420P;
+ desired_depth = 12;
+ } else if (ap->pix_fmt == PIX_FMT_YUV422) {
+ desired_palette = VIDEO_PALETTE_YUV422;
+ desired_depth = 16;
+ } else if (ap->pix_fmt == PIX_FMT_BGR24) {
+ desired_palette = VIDEO_PALETTE_RGB24;
+ desired_depth = 24;
+ }
+
+ /* set tv standard */
+ if (ap->standard && !ioctl(video_fd, VIDIOCGTUNER, &tuner)) {
+ if (!strcasecmp(ap->standard, "pal"))
+ tuner.mode = VIDEO_MODE_PAL;
+ else if (!strcasecmp(ap->standard, "secam"))
+ tuner.mode = VIDEO_MODE_SECAM;
+ else
+ tuner.mode = VIDEO_MODE_NTSC;
+ ioctl(video_fd, VIDIOCSTUNER, &tuner);
+ }
+
+ /* unmute audio */
+ audio.audio = 0;
+ ioctl(video_fd, VIDIOCGAUDIO, &audio);
+ memcpy(&s->audio_saved, &audio, sizeof(audio));
+ audio.flags &= ~VIDEO_AUDIO_MUTE;
+ ioctl(video_fd, VIDIOCSAUDIO, &audio);
+
+ ioctl(video_fd, VIDIOCGPICT, &pict);
+#if 0
+ printf("v4l: colour=%d hue=%d brightness=%d constrast=%d whiteness=%d\n",
+ pict.colour,
+ pict.hue,
+ pict.brightness,
+ pict.contrast,
+ pict.whiteness);
+#endif
+ /* try to choose a suitable video format */
+ pict.palette = desired_palette;
+ pict.depth= desired_depth;
+ if (desired_palette == -1 || (ret = ioctl(video_fd, VIDIOCSPICT, &pict)) < 0) {
+ pict.palette=VIDEO_PALETTE_YUV420P;
+ pict.depth=12;
+ ret = ioctl(video_fd, VIDIOCSPICT, &pict);
+ if (ret < 0) {
+ pict.palette=VIDEO_PALETTE_YUV422;
+ pict.depth=16;
+ ret = ioctl(video_fd, VIDIOCSPICT, &pict);
+ if (ret < 0) {
+ pict.palette=VIDEO_PALETTE_RGB24;
+ pict.depth=24;
+ ret = ioctl(video_fd, VIDIOCSPICT, &pict);
+ if (ret < 0)
+ pict.palette=VIDEO_PALETTE_GREY;
+ pict.depth=8;
+ ret = ioctl(video_fd, VIDIOCSPICT, &pict);
+ if (ret < 0)
+ goto fail1;
+ }
+ }
+ }
+
+ ret = ioctl(video_fd,VIDIOCGMBUF,&s->gb_buffers);
+ if (ret < 0) {
+ /* try to use read based access */
+ struct video_window win;
+ int val;
+
+ win.x = 0;
+ win.y = 0;
+ win.width = width;
+ win.height = height;
+ win.chromakey = -1;
+ win.flags = 0;
+
+ ioctl(video_fd, VIDIOCSWIN, &win);
+
+ s->frame_format = pict.palette;
+
+ val = 1;
+ ioctl(video_fd, VIDIOCCAPTURE, &val);
+
+ s->time_frame = av_gettime() * s->frame_rate / s->frame_rate_base;
+ s->use_mmap = 0;
+
+ /* ATI All In Wonder automatic activation */
+ if (!strcmp(s->video_cap.name, "Km")) {
+ if (aiw_init(s) < 0)
+ goto fail;
+ s->aiw_enabled = 1;
+ /* force 420P format because convertion from YUV422 to YUV420P
+ is done in this driver (ugly) */
+ s->frame_format = VIDEO_PALETTE_YUV420P;
+ }
+ } else {
+ s->video_buf = mmap(0,s->gb_buffers.size,PROT_READ|PROT_WRITE,MAP_SHARED,video_fd,0);
+ if ((unsigned char*)-1 == s->video_buf) {
+ perror("mmap");
+ goto fail;
+ }
+ s->gb_frame = 0;
+ s->time_frame = av_gettime() * s->frame_rate / s->frame_rate_base;
+
+ /* start to grab the first frame */
+ s->gb_buf.frame = s->gb_frame % s->gb_buffers.frames;
+ s->gb_buf.height = height;
+ s->gb_buf.width = width;
+ s->gb_buf.format = pict.palette;
+
+ ret = ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf);
+ if (ret < 0) {
+ if (errno != EAGAIN) {
+ fail1:
+ av_log(s1, AV_LOG_ERROR, "Fatal: grab device does not support suitable format\n");
+ } else {
+ av_log(s1, AV_LOG_ERROR,"Fatal: grab device does not receive any video signal\n");
+ }
+ goto fail;
+ }
+ for (j = 1; j < s->gb_buffers.frames; j++) {
+ s->gb_buf.frame = j;
+ ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf);
+ }
+ s->frame_format = s->gb_buf.format;
+ s->use_mmap = 1;
+ }
+
+ switch(s->frame_format) {
+ case VIDEO_PALETTE_YUV420P:
+ frame_size = (width * height * 3) / 2;
+ st->codec->pix_fmt = PIX_FMT_YUV420P;
+ break;
+ case VIDEO_PALETTE_YUV422:
+ frame_size = width * height * 2;
+ st->codec->pix_fmt = PIX_FMT_YUV422;
+ break;
+ case VIDEO_PALETTE_RGB24:
+ frame_size = width * height * 3;
+ st->codec->pix_fmt = PIX_FMT_BGR24; /* NOTE: v4l uses BGR24, not RGB24 ! */
+ break;
+ case VIDEO_PALETTE_GREY:
+ frame_size = width * height * 1;
+ st->codec->pix_fmt = PIX_FMT_GRAY8;
+ break;
+ default:
+ goto fail;
+ }
+ s->fd = video_fd;
+ s->frame_size = frame_size;
+
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_RAWVIDEO;
+ st->codec->width = width;
+ st->codec->height = height;
+ st->codec->time_base.den = frame_rate;
+ st->codec->time_base.num = frame_rate_base;
+ st->codec->bit_rate = frame_size * 1/av_q2d(st->codec->time_base) * 8;
+
+ return 0;
+ fail:
+ if (video_fd >= 0)
+ close(video_fd);
+ av_free(st);
+ return AVERROR_IO;
+}
+
+static int v4l_mm_read_picture(VideoData *s, uint8_t *buf)
+{
+ uint8_t *ptr;
+
+ while (ioctl(s->fd, VIDIOCSYNC, &s->gb_frame) < 0 &&
+ (errno == EAGAIN || errno == EINTR));
+
+ ptr = s->video_buf + s->gb_buffers.offsets[s->gb_frame];
+ memcpy(buf, ptr, s->frame_size);
+
+ /* Setup to capture the next frame */
+ s->gb_buf.frame = s->gb_frame;
+ if (ioctl(s->fd, VIDIOCMCAPTURE, &s->gb_buf) < 0) {
+ if (errno == EAGAIN)
+ av_log(NULL, AV_LOG_ERROR, "Cannot Sync\n");
+ else
+ perror("VIDIOCMCAPTURE");
+ return AVERROR_IO;
+ }
+
+ /* This is now the grabbing frame */
+ s->gb_frame = (s->gb_frame + 1) % s->gb_buffers.frames;
+
+ return s->frame_size;
+}
+
+static int grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
+{
+ VideoData *s = s1->priv_data;
+ int64_t curtime, delay;
+ struct timespec ts;
+
+ /* Calculate the time of the next frame */
+ s->time_frame += int64_t_C(1000000);
+
+ /* wait based on the frame rate */
+ for(;;) {
+ curtime = av_gettime();
+ delay = s->time_frame * s->frame_rate_base / s->frame_rate - curtime;
+ if (delay <= 0) {
+ if (delay < int64_t_C(-1000000) * s->frame_rate_base / s->frame_rate) {
+ /* printf("grabbing is %d frames late (dropping)\n", (int) -(delay / 16666)); */
+ s->time_frame += int64_t_C(1000000);
+ }
+ break;
+ }
+ ts.tv_sec = delay / 1000000;
+ ts.tv_nsec = (delay % 1000000) * 1000;
+ nanosleep(&ts, NULL);
+ }
+
+ if (av_new_packet(pkt, s->frame_size) < 0)
+ return AVERROR_IO;
+
+ pkt->pts = curtime;
+
+ /* read one frame */
+ if (s->aiw_enabled) {
+ return aiw_read_picture(s, pkt->data);
+ } else if (s->use_mmap) {
+ return v4l_mm_read_picture(s, pkt->data);
+ } else {
+ if (read(s->fd, pkt->data, pkt->size) != pkt->size)
+ return AVERROR_IO;
+ return s->frame_size;
+ }
+}
+
+static int grab_read_close(AVFormatContext *s1)
+{
+ VideoData *s = s1->priv_data;
+
+ if (s->aiw_enabled)
+ aiw_close(s);
+
+ if (s->use_mmap)
+ munmap(s->video_buf, s->gb_buffers.size);
+
+ /* mute audio. we must force it because the BTTV driver does not
+ return its state correctly */
+ s->audio_saved.flags |= VIDEO_AUDIO_MUTE;
+ ioctl(s->fd, VIDIOCSAUDIO, &s->audio_saved);
+
+ close(s->fd);
+ return 0;
+}
+
+AVInputFormat video_grab_device_demuxer = {
+ "video4linux",
+ "video grab",
+ sizeof(VideoData),
+ NULL,
+ grab_read_header,
+ grab_read_packet,
+ grab_read_close,
+ .flags = AVFMT_NOFILE,
+};
+
+/* All in Wonder specific stuff */
+/* XXX: remove and merge in libavcodec/imgconvert.c */
+
+static int aiw_init(VideoData *s)
+{
+ int width, height;
+
+ width = s->width;
+ height = s->height;
+
+ if ((width == s->video_cap.maxwidth && height == s->video_cap.maxheight) ||
+ (width == s->video_cap.maxwidth && height == s->video_cap.maxheight*2) ||
+ (width == s->video_cap.maxwidth/2 && height == s->video_cap.maxheight)) {
+
+ s->deint=0;
+ s->halfw=0;
+ if (height == s->video_cap.maxheight*2) s->deint=1;
+ if (width == s->video_cap.maxwidth/2) s->halfw=1;
+ } else {
+ av_log(NULL, AV_LOG_ERROR, "\nIncorrect Grab Size Supplied - Supported Sizes Are:\n");
+ av_log(NULL, AV_LOG_ERROR, " %dx%d %dx%d %dx%d\n\n",
+ s->video_cap.maxwidth,s->video_cap.maxheight,
+ s->video_cap.maxwidth,s->video_cap.maxheight*2,
+ s->video_cap.maxwidth/2,s->video_cap.maxheight);
+ goto fail;
+ }
+
+ if (s->halfw == 0) {
+ s->src_mem = av_malloc(s->width*2);
+ } else {
+ s->src_mem = av_malloc(s->width*4);
+ }
+ if (!s->src_mem) goto fail;
+
+ s->lum_m4_mem = av_malloc(s->width);
+ if (!s->lum_m4_mem)
+ goto fail;
+ return 0;
+ fail:
+ av_freep(&s->src_mem);
+ av_freep(&s->lum_m4_mem);
+ return -1;
+}
+
+#ifdef HAVE_MMX
+#include "libavcodec/i386/mmx.h"
+
+#define LINE_WITH_UV \
+ movq_m2r(ptr[0],mm0); \
+ movq_m2r(ptr[8],mm1); \
+ movq_r2r(mm0, mm4); \
+ punpcklbw_r2r(mm1,mm0); \
+ punpckhbw_r2r(mm1,mm4); \
+ movq_r2r(mm0,mm5); \
+ punpcklbw_r2r(mm4,mm0); \
+ punpckhbw_r2r(mm4,mm5); \
+ movq_r2r(mm0,mm1); \
+ punpcklbw_r2r(mm5,mm1); \
+ movq_r2m(mm1,lum[0]); \
+ movq_m2r(ptr[16],mm2); \
+ movq_m2r(ptr[24],mm1); \
+ movq_r2r(mm2,mm4); \
+ punpcklbw_r2r(mm1,mm2); \
+ punpckhbw_r2r(mm1,mm4); \
+ movq_r2r(mm2,mm3); \
+ punpcklbw_r2r(mm4,mm2); \
+ punpckhbw_r2r(mm4,mm3); \
+ movq_r2r(mm2,mm1); \
+ punpcklbw_r2r(mm3,mm1); \
+ movq_r2m(mm1,lum[8]); \
+ punpckhdq_r2r(mm2,mm0); \
+ punpckhdq_r2r(mm3,mm5); \
+ movq_r2m(mm0,cb[0]); \
+ movq_r2m(mm5,cr[0]);
+
+#define LINE_NO_UV \
+ movq_m2r(ptr[0],mm0);\
+ movq_m2r(ptr[8],mm1);\
+ movq_r2r(mm0, mm4);\
+ punpcklbw_r2r(mm1,mm0); \
+ punpckhbw_r2r(mm1,mm4);\
+ movq_r2r(mm0,mm5);\
+ punpcklbw_r2r(mm4,mm0);\
+ punpckhbw_r2r(mm4,mm5);\
+ movq_r2r(mm0,mm1);\
+ punpcklbw_r2r(mm5,mm1);\
+ movq_r2m(mm1,lum[0]);\
+ movq_m2r(ptr[16],mm2);\
+ movq_m2r(ptr[24],mm1);\
+ movq_r2r(mm2,mm4);\
+ punpcklbw_r2r(mm1,mm2);\
+ punpckhbw_r2r(mm1,mm4);\
+ movq_r2r(mm2,mm3);\
+ punpcklbw_r2r(mm4,mm2);\
+ punpckhbw_r2r(mm4,mm3);\
+ movq_r2r(mm2,mm1);\
+ punpcklbw_r2r(mm3,mm1);\
+ movq_r2m(mm1,lum[8]);
+
+#define LINE_WITHUV_AVG \
+ movq_m2r(ptr[0], mm0);\
+ movq_m2r(ptr[8], mm1);\
+ movq_r2r(mm0, mm4);\
+ punpcklbw_r2r(mm1,mm0);\
+ punpckhbw_r2r(mm1,mm4);\
+ movq_r2r(mm0,mm5);\
+ punpcklbw_r2r(mm4,mm0);\
+ punpckhbw_r2r(mm4,mm5);\
+ movq_r2r(mm0,mm1);\
+ movq_r2r(mm5,mm2);\
+ punpcklbw_r2r(mm7,mm1);\
+ punpcklbw_r2r(mm7,mm2);\
+ paddw_r2r(mm6,mm1);\
+ paddw_r2r(mm2,mm1);\
+ psraw_i2r(1,mm1);\
+ packuswb_r2r(mm7,mm1);\
+ movd_r2m(mm1,lum[0]);\
+ movq_m2r(ptr[16],mm2);\
+ movq_m2r(ptr[24],mm1);\
+ movq_r2r(mm2,mm4);\
+ punpcklbw_r2r(mm1,mm2);\
+ punpckhbw_r2r(mm1,mm4);\
+ movq_r2r(mm2,mm3);\
+ punpcklbw_r2r(mm4,mm2);\
+ punpckhbw_r2r(mm4,mm3);\
+ movq_r2r(mm2,mm1);\
+ movq_r2r(mm3,mm4);\
+ punpcklbw_r2r(mm7,mm1);\
+ punpcklbw_r2r(mm7,mm4);\
+ paddw_r2r(mm6,mm1);\
+ paddw_r2r(mm4,mm1);\
+ psraw_i2r(1,mm1);\
+ packuswb_r2r(mm7,mm1);\
+ movd_r2m(mm1,lum[4]);\
+ punpckhbw_r2r(mm7,mm0);\
+ punpckhbw_r2r(mm7,mm2);\
+ paddw_r2r(mm6,mm0);\
+ paddw_r2r(mm2,mm0);\
+ psraw_i2r(1,mm0);\
+ packuswb_r2r(mm7,mm0);\
+ punpckhbw_r2r(mm7,mm5);\
+ punpckhbw_r2r(mm7,mm3);\
+ paddw_r2r(mm6,mm5);\
+ paddw_r2r(mm3,mm5);\
+ psraw_i2r(1,mm5);\
+ packuswb_r2r(mm7,mm5);\
+ movd_r2m(mm0,cb[0]);\
+ movd_r2m(mm5,cr[0]);
+
+#define LINE_NOUV_AVG \
+ movq_m2r(ptr[0],mm0);\
+ movq_m2r(ptr[8],mm1);\
+ pand_r2r(mm5,mm0);\
+ pand_r2r(mm5,mm1);\
+ pmaddwd_r2r(mm6,mm0);\
+ pmaddwd_r2r(mm6,mm1);\
+ packssdw_r2r(mm1,mm0);\
+ paddw_r2r(mm6,mm0);\
+ psraw_i2r(1,mm0);\
+ movq_m2r(ptr[16],mm2);\
+ movq_m2r(ptr[24],mm3);\
+ pand_r2r(mm5,mm2);\
+ pand_r2r(mm5,mm3);\
+ pmaddwd_r2r(mm6,mm2);\
+ pmaddwd_r2r(mm6,mm3);\
+ packssdw_r2r(mm3,mm2);\
+ paddw_r2r(mm6,mm2);\
+ psraw_i2r(1,mm2);\
+ packuswb_r2r(mm2,mm0);\
+ movq_r2m(mm0,lum[0]);
+
+#define DEINT_LINE_LUM(ptroff) \
+ movd_m2r(lum_m4[(ptroff)],mm0);\
+ movd_m2r(lum_m3[(ptroff)],mm1);\
+ movd_m2r(lum_m2[(ptroff)],mm2);\
+ movd_m2r(lum_m1[(ptroff)],mm3);\
+ movd_m2r(lum[(ptroff)],mm4);\
+ punpcklbw_r2r(mm7,mm0);\
+ movd_r2m(mm2,lum_m4[(ptroff)]);\
+ punpcklbw_r2r(mm7,mm1);\
+ punpcklbw_r2r(mm7,mm2);\
+ punpcklbw_r2r(mm7,mm3);\
+ punpcklbw_r2r(mm7,mm4);\
+ psllw_i2r(2,mm1);\
+ psllw_i2r(1,mm2);\
+ paddw_r2r(mm6,mm1);\
+ psllw_i2r(2,mm3);\
+ paddw_r2r(mm2,mm1);\
+ paddw_r2r(mm4,mm0);\
+ paddw_r2r(mm3,mm1);\
+ psubusw_r2r(mm0,mm1);\
+ psrlw_i2r(3,mm1);\
+ packuswb_r2r(mm7,mm1);\
+ movd_r2m(mm1,lum_m2[(ptroff)]);
+
+#else
+#include "libavcodec/dsputil.h"
+
+#define LINE_WITH_UV \
+ lum[0]=ptr[0];lum[1]=ptr[2];lum[2]=ptr[4];lum[3]=ptr[6];\
+ cb[0]=ptr[1];cb[1]=ptr[5];\
+ cr[0]=ptr[3];cr[1]=ptr[7];\
+ lum[4]=ptr[8];lum[5]=ptr[10];lum[6]=ptr[12];lum[7]=ptr[14];\
+ cb[2]=ptr[9];cb[3]=ptr[13];\
+ cr[2]=ptr[11];cr[3]=ptr[15];\
+ lum[8]=ptr[16];lum[9]=ptr[18];lum[10]=ptr[20];lum[11]=ptr[22];\
+ cb[4]=ptr[17];cb[5]=ptr[21];\
+ cr[4]=ptr[19];cr[5]=ptr[23];\
+ lum[12]=ptr[24];lum[13]=ptr[26];lum[14]=ptr[28];lum[15]=ptr[30];\
+ cb[6]=ptr[25];cb[7]=ptr[29];\
+ cr[6]=ptr[27];cr[7]=ptr[31];
+
+#define LINE_NO_UV \
+ lum[0]=ptr[0];lum[1]=ptr[2];lum[2]=ptr[4];lum[3]=ptr[6];\
+ lum[4]=ptr[8];lum[5]=ptr[10];lum[6]=ptr[12];lum[7]=ptr[14];\
+ lum[8]=ptr[16];lum[9]=ptr[18];lum[10]=ptr[20];lum[11]=ptr[22];\
+ lum[12]=ptr[24];lum[13]=ptr[26];lum[14]=ptr[28];lum[15]=ptr[30];
+
+#define LINE_WITHUV_AVG \
+ sum=(ptr[0]+ptr[2]+1) >> 1;lum[0]=sum; \
+ sum=(ptr[4]+ptr[6]+1) >> 1;lum[1]=sum; \
+ sum=(ptr[1]+ptr[5]+1) >> 1;cb[0]=sum; \
+ sum=(ptr[3]+ptr[7]+1) >> 1;cr[0]=sum; \
+ sum=(ptr[8]+ptr[10]+1) >> 1;lum[2]=sum; \
+ sum=(ptr[12]+ptr[14]+1) >> 1;lum[3]=sum; \
+ sum=(ptr[9]+ptr[13]+1) >> 1;cb[1]=sum; \
+ sum=(ptr[11]+ptr[15]+1) >> 1;cr[1]=sum; \
+ sum=(ptr[16]+ptr[18]+1) >> 1;lum[4]=sum; \
+ sum=(ptr[20]+ptr[22]+1) >> 1;lum[5]=sum; \
+ sum=(ptr[17]+ptr[21]+1) >> 1;cb[2]=sum; \
+ sum=(ptr[19]+ptr[23]+1) >> 1;cr[2]=sum; \
+ sum=(ptr[24]+ptr[26]+1) >> 1;lum[6]=sum; \
+ sum=(ptr[28]+ptr[30]+1) >> 1;lum[7]=sum; \
+ sum=(ptr[25]+ptr[29]+1) >> 1;cb[3]=sum; \
+ sum=(ptr[27]+ptr[31]+1) >> 1;cr[3]=sum;
+
+#define LINE_NOUV_AVG \
+ sum=(ptr[0]+ptr[2]+1) >> 1;lum[0]=sum; \
+ sum=(ptr[4]+ptr[6]+1) >> 1;lum[1]=sum; \
+ sum=(ptr[8]+ptr[10]+1) >> 1;lum[2]=sum; \
+ sum=(ptr[12]+ptr[14]+1) >> 1;lum[3]=sum; \
+ sum=(ptr[16]+ptr[18]+1) >> 1;lum[4]=sum; \
+ sum=(ptr[20]+ptr[22]+1) >> 1;lum[5]=sum; \
+ sum=(ptr[24]+ptr[26]+1) >> 1;lum[6]=sum; \
+ sum=(ptr[28]+ptr[30]+1) >> 1;lum[7]=sum;
+
+#define DEINT_LINE_LUM(ptroff) \
+ sum=(-lum_m4[(ptroff)]+(lum_m3[(ptroff)]<<2)+(lum_m2[(ptroff)]<<1)+(lum_m1[(ptroff)]<<2)-lum[(ptroff)]); \
+ lum_m4[(ptroff)]=lum_m2[(ptroff)];\
+ lum_m2[(ptroff)]=cm[(sum+4)>>3];\
+ sum=(-lum_m4[(ptroff)+1]+(lum_m3[(ptroff)+1]<<2)+(lum_m2[(ptroff)+1]<<1)+(lum_m1[(ptroff)+1]<<2)-lum[(ptroff)+1]); \
+ lum_m4[(ptroff)+1]=lum_m2[(ptroff)+1];\
+ lum_m2[(ptroff)+1]=cm[(sum+4)>>3];\
+ sum=(-lum_m4[(ptroff)+2]+(lum_m3[(ptroff)+2]<<2)+(lum_m2[(ptroff)+2]<<1)+(lum_m1[(ptroff)+2]<<2)-lum[(ptroff)+2]); \
+ lum_m4[(ptroff)+2]=lum_m2[(ptroff)+2];\
+ lum_m2[(ptroff)+2]=cm[(sum+4)>>3];\
+ sum=(-lum_m4[(ptroff)+3]+(lum_m3[(ptroff)+3]<<2)+(lum_m2[(ptroff)+3]<<1)+(lum_m1[(ptroff)+3]<<2)-lum[(ptroff)+3]); \
+ lum_m4[(ptroff)+3]=lum_m2[(ptroff)+3];\
+ lum_m2[(ptroff)+3]=cm[(sum+4)>>3];
+
+#endif
+
+
+/* Read two fields separately. */
+static int aiw_read_picture(VideoData *s, uint8_t *data)
+{
+ uint8_t *ptr, *lum, *cb, *cr;
+ int h;
+#ifndef HAVE_MMX
+ int sum;
+#endif
+ uint8_t* src = s->src_mem;
+ uint8_t *ptrend = &src[s->width*2];
+ lum=data;
+ cb=&lum[s->width*s->height];
+ cr=&cb[(s->width*s->height)/4];
+ if (s->deint == 0 && s->halfw == 0) {
+ while (read(s->fd,src,s->width*2) < 0) {
+ usleep(100);
+ }
+ for (h = 0; h < s->height-2; h+=2) {
+ for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
+ LINE_WITH_UV
+ }
+ read(s->fd,src,s->width*2);
+ for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16) {
+ LINE_NO_UV
+ }
+ read(s->fd,src,s->width*2);
+ }
+ /*
+ * Do last two lines
+ */
+ for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
+ LINE_WITH_UV
+ }
+ read(s->fd,src,s->width*2);
+ for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16) {
+ LINE_NO_UV
+ }
+ /* drop second field */
+ while (read(s->fd,src,s->width*2) < 0) {
+ usleep(100);
+ }
+ for (h = 0; h < s->height - 1; h++) {
+ read(s->fd,src,s->width*2);
+ }
+ } else if (s->halfw == 1) {
+#ifdef HAVE_MMX
+ mmx_t rounder;
+ mmx_t masker;
+ rounder.uw[0]=1;
+ rounder.uw[1]=1;
+ rounder.uw[2]=1;
+ rounder.uw[3]=1;
+ masker.ub[0]=0xff;
+ masker.ub[1]=0;
+ masker.ub[2]=0xff;
+ masker.ub[3]=0;
+ masker.ub[4]=0xff;
+ masker.ub[5]=0;
+ masker.ub[6]=0xff;
+ masker.ub[7]=0;
+ pxor_r2r(mm7,mm7);
+ movq_m2r(rounder,mm6);
+#endif
+ while (read(s->fd,src,s->width*4) < 0) {
+ usleep(100);
+ }
+ ptrend = &src[s->width*4];
+ for (h = 0; h < s->height-2; h+=2) {
+ for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=8, cb+=4, cr+=4) {
+ LINE_WITHUV_AVG
+ }
+ read(s->fd,src,s->width*4);
+#ifdef HAVE_MMX
+ movq_m2r(masker,mm5);
+#endif
+ for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=8) {
+ LINE_NOUV_AVG
+ }
+ read(s->fd,src,s->width*4);
+ }
+ /*
+ * Do last two lines
+ */
+ for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=8, cb+=4, cr+=4) {
+ LINE_WITHUV_AVG
+ }
+ read(s->fd,src,s->width*4);
+#ifdef HAVE_MMX
+ movq_m2r(masker,mm5);
+#endif
+ for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=8) {
+ LINE_NOUV_AVG
+ }
+ /* drop second field */
+ while (read(s->fd,src,s->width*4) < 0) {
+ usleep(100);
+ }
+ for (h = 0; h < s->height - 1; h++) {
+ read(s->fd,src,s->width*4);
+ }
+ } else {
+ uint8_t *lum_m1, *lum_m2, *lum_m3, *lum_m4;
+#ifdef HAVE_MMX
+ mmx_t rounder;
+ rounder.uw[0]=4;
+ rounder.uw[1]=4;
+ rounder.uw[2]=4;
+ rounder.uw[3]=4;
+ movq_m2r(rounder,mm6);
+ pxor_r2r(mm7,mm7);
+#else
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+#endif
+
+ /* read two fields and deinterlace them */
+ while (read(s->fd,src,s->width*2) < 0) {
+ usleep(100);
+ }
+ for (h = 0; h < (s->height/2)-2; h+=2) {
+ for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
+ LINE_WITH_UV
+ }
+ read(s->fd,src,s->width*2);
+ /* skip a luminance line - will be filled in later */
+ lum += s->width;
+ for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
+ LINE_WITH_UV
+ }
+ /* skip a luminance line - will be filled in later */
+ lum += s->width;
+ read(s->fd,src,s->width*2);
+ }
+ /*
+ * Do last two lines
+ */
+ for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
+ LINE_WITH_UV
+ }
+ /* skip a luminance line - will be filled in later */
+ lum += s->width;
+ read(s->fd,src,s->width*2);
+ for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
+ LINE_WITH_UV
+ }
+ /*
+ *
+ * SECOND FIELD
+ *
+ */
+ lum=&data[s->width];
+ while (read(s->fd,src,s->width*2) < 0) {
+ usleep(10);
+ }
+ /* First (and last) two lines not interlaced */
+ for (h = 0; h < 2; h++) {
+ for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16) {
+ LINE_NO_UV
+ }
+ read(s->fd,src,s->width*2);
+ /* skip a luminance line */
+ lum += s->width;
+ }
+ lum_m1=&lum[-s->width];
+ lum_m2=&lum_m1[-s->width];
+ lum_m3=&lum_m2[-s->width];
+ memmove(s->lum_m4_mem,&lum_m3[-s->width],s->width);
+ for (; h < (s->height/2)-1; h++) {
+ lum_m4=s->lum_m4_mem;
+ for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16,lum_m1+=16,lum_m2+=16,lum_m3+=16,lum_m4+=16) {
+ LINE_NO_UV
+
+ DEINT_LINE_LUM(0)
+ DEINT_LINE_LUM(4)
+ DEINT_LINE_LUM(8)
+ DEINT_LINE_LUM(12)
+ }
+ read(s->fd,src,s->width*2);
+ /* skip a luminance line */
+ lum += s->width;
+ lum_m1 += s->width;
+ lum_m2 += s->width;
+ lum_m3 += s->width;
+ // lum_m4 += s->width;
+ }
+ /*
+ * Do last line
+ */
+ lum_m4=s->lum_m4_mem;
+ for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, lum_m1+=16, lum_m2+=16, lum_m3+=16, lum_m4+=16) {
+ LINE_NO_UV
+
+ DEINT_LINE_LUM(0)
+ DEINT_LINE_LUM(4)
+ DEINT_LINE_LUM(8)
+ DEINT_LINE_LUM(12)
+ }
+ }
+#ifdef HAVE_MMX
+ emms();
+#endif
+ return s->frame_size;
+}
+
+static int aiw_close(VideoData *s)
+{
+ av_freep(&s->lum_m4_mem);
+ av_freep(&s->src_mem);
+ return 0;
+}
diff --git a/contrib/ffmpeg/libavformat/grab_bktr.c b/contrib/ffmpeg/libavformat/grab_bktr.c
new file mode 100644
index 000000000..214599490
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/grab_bktr.c
@@ -0,0 +1,330 @@
+/*
+ * *BSD video grab interface
+ * Copyright (c) 2002 Steve O'Hara-Smith
+ * based on
+ * Linux video grab interface
+ * Copyright (c) 2000,2001 Gerard Lantau.
+ * and
+ * simple_grab.c Copyright (c) 1999 Roger Hardiman
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "avformat.h"
+#if defined(__FreeBSD__)
+# if __FreeBSD__ >= 502100
+# include <dev/bktr/ioctl_meteor.h>
+# include <dev/bktr/ioctl_bt848.h>
+# else
+# include <machine/ioctl_meteor.h>
+# include <machine/ioctl_bt848.h>
+# endif
+#elif defined(__FreeBSD_kernel__)
+# include <dev/bktr/ioctl_meteor.h>
+# include <dev/bktr/ioctl_bt848.h>
+#elif defined(__DragonFly__)
+# include <dev/video/meteor/ioctl_meteor.h>
+# include <dev/video/bktr/ioctl_bt848.h>
+#else
+# include <dev/ic/bt8xx.h>
+#endif
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <signal.h>
+
+typedef struct {
+ int video_fd;
+ int tuner_fd;
+ int width, height;
+ int frame_rate;
+ int frame_rate_base;
+ u_int64_t per_frame;
+} VideoData;
+
+
+#define PAL 1
+#define PALBDGHI 1
+#define NTSC 2
+#define NTSCM 2
+#define SECAM 3
+#define PALN 4
+#define PALM 5
+#define NTSCJ 6
+
+/* PAL is 768 x 576. NTSC is 640 x 480 */
+#define PAL_HEIGHT 576
+#define SECAM_HEIGHT 576
+#define NTSC_HEIGHT 480
+
+#ifndef VIDEO_FORMAT
+#define VIDEO_FORMAT NTSC
+#endif
+
+static int bktr_dev[] = { METEOR_DEV0, METEOR_DEV1, METEOR_DEV2,
+ METEOR_DEV3, METEOR_DEV_SVIDEO };
+
+uint8_t *video_buf;
+size_t video_buf_size;
+u_int64_t last_frame_time;
+volatile sig_atomic_t nsignals;
+
+
+static void catchsignal(int signal)
+{
+ nsignals++;
+ return;
+}
+
+static int bktr_init(const char *video_device, int width, int height,
+ int format, int *video_fd, int *tuner_fd, int idev, double frequency)
+{
+ struct meteor_geomet geo;
+ int h_max;
+ long ioctl_frequency;
+ char *arg;
+ int c;
+ struct sigaction act, old;
+
+ if (idev < 0 || idev > 4)
+ {
+ arg = getenv ("BKTR_DEV");
+ if (arg)
+ idev = atoi (arg);
+ if (idev < 0 || idev > 4)
+ idev = 1;
+ }
+
+ if (format < 1 || format > 6)
+ {
+ arg = getenv ("BKTR_FORMAT");
+ if (arg)
+ format = atoi (arg);
+ if (format < 1 || format > 6)
+ format = VIDEO_FORMAT;
+ }
+
+ if (frequency <= 0)
+ {
+ arg = getenv ("BKTR_FREQUENCY");
+ if (arg)
+ frequency = atof (arg);
+ if (frequency <= 0)
+ frequency = 0.0;
+ }
+
+ memset(&act, 0, sizeof(act));
+ sigemptyset(&act.sa_mask);
+ act.sa_handler = catchsignal;
+ sigaction(SIGUSR1, &act, &old);
+
+ *tuner_fd = open("/dev/tuner0", O_RDONLY);
+ if (*tuner_fd < 0)
+ perror("Warning: Tuner not opened, continuing");
+
+ *video_fd = open(video_device, O_RDONLY);
+ if (*video_fd < 0) {
+ perror(video_device);
+ return -1;
+ }
+
+ geo.rows = height;
+ geo.columns = width;
+ geo.frames = 1;
+ geo.oformat = METEOR_GEO_YUV_422 | METEOR_GEO_YUV_12;
+
+ switch (format) {
+ case PAL: h_max = PAL_HEIGHT; c = BT848_IFORM_F_PALBDGHI; break;
+ case PALN: h_max = PAL_HEIGHT; c = BT848_IFORM_F_PALN; break;
+ case PALM: h_max = PAL_HEIGHT; c = BT848_IFORM_F_PALM; break;
+ case SECAM: h_max = SECAM_HEIGHT; c = BT848_IFORM_F_SECAM; break;
+ case NTSC: h_max = NTSC_HEIGHT; c = BT848_IFORM_F_NTSCM; break;
+ case NTSCJ: h_max = NTSC_HEIGHT; c = BT848_IFORM_F_NTSCJ; break;
+ default: h_max = PAL_HEIGHT; c = BT848_IFORM_F_PALBDGHI; break;
+ }
+
+ if (height <= h_max / 2)
+ geo.oformat |= METEOR_GEO_EVEN_ONLY;
+
+ if (ioctl(*video_fd, METEORSETGEO, &geo) < 0) {
+ perror("METEORSETGEO");
+ return -1;
+ }
+
+ if (ioctl(*video_fd, BT848SFMT, &c) < 0) {
+ perror("BT848SFMT");
+ return -1;
+ }
+
+ c = bktr_dev[idev];
+ if (ioctl(*video_fd, METEORSINPUT, &c) < 0) {
+ perror("METEORSINPUT");
+ return -1;
+ }
+
+ video_buf_size = width * height * 12 / 8;
+
+ video_buf = (uint8_t *)mmap((caddr_t)0, video_buf_size,
+ PROT_READ, MAP_SHARED, *video_fd, (off_t)0);
+ if (video_buf == MAP_FAILED) {
+ perror("mmap");
+ return -1;
+ }
+
+ if (frequency != 0.0) {
+ ioctl_frequency = (unsigned long)(frequency*16);
+ if (ioctl(*tuner_fd, TVTUNER_SETFREQ, &ioctl_frequency) < 0)
+ perror("TVTUNER_SETFREQ");
+ }
+
+ c = AUDIO_UNMUTE;
+ if (ioctl(*tuner_fd, BT848_SAUDIO, &c) < 0)
+ perror("TVTUNER_SAUDIO");
+
+ c = METEOR_CAP_CONTINOUS;
+ ioctl(*video_fd, METEORCAPTUR, &c);
+
+ c = SIGUSR1;
+ ioctl(*video_fd, METEORSSIGNAL, &c);
+
+ return 0;
+}
+
+static void bktr_getframe(u_int64_t per_frame)
+{
+ u_int64_t curtime;
+
+ curtime = av_gettime();
+ if (!last_frame_time
+ || ((last_frame_time + per_frame) > curtime)) {
+ if (!usleep(last_frame_time + per_frame + per_frame / 8 - curtime)) {
+ if (!nsignals)
+ av_log(NULL, AV_LOG_INFO,
+ "SLEPT NO signals - %d microseconds late\n",
+ (int)(av_gettime() - last_frame_time - per_frame));
+ }
+ }
+ nsignals = 0;
+ last_frame_time = curtime;
+}
+
+
+/* note: we support only one picture read at a time */
+static int grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
+{
+ VideoData *s = s1->priv_data;
+
+ if (av_new_packet(pkt, video_buf_size) < 0)
+ return -EIO;
+
+ bktr_getframe(s->per_frame);
+
+ pkt->pts = av_gettime();
+ memcpy(pkt->data, video_buf, video_buf_size);
+
+ return video_buf_size;
+}
+
+static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
+{
+ VideoData *s = s1->priv_data;
+ AVStream *st;
+ int width, height;
+ int frame_rate;
+ int frame_rate_base;
+ int format = -1;
+ const char *video_device;
+
+ if (ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0)
+ return -1;
+
+ width = ap->width;
+ height = ap->height;
+ frame_rate = ap->time_base.den;
+ frame_rate_base = ap->time_base.num;
+
+ video_device = ap->device;
+ if (!video_device)
+ video_device = "/dev/bktr0";
+
+ st = av_new_stream(s1, 0);
+ if (!st)
+ return -ENOMEM;
+ av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in use */
+
+ s->width = width;
+ s->height = height;
+ s->frame_rate = frame_rate;
+ s->frame_rate_base = frame_rate_base;
+ s->per_frame = ((u_int64_t)1000000 * s->frame_rate_base) / s->frame_rate;
+
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->pix_fmt = PIX_FMT_YUV420P;
+ st->codec->codec_id = CODEC_ID_RAWVIDEO;
+ st->codec->width = width;
+ st->codec->height = height;
+ st->codec->time_base.den = frame_rate;
+ st->codec->time_base.num = frame_rate_base;
+
+ if (ap->standard) {
+ if (!strcasecmp(ap->standard, "pal"))
+ format = PAL;
+ else if (!strcasecmp(ap->standard, "secam"))
+ format = SECAM;
+ else if (!strcasecmp(ap->standard, "ntsc"))
+ format = NTSC;
+ }
+
+ if (bktr_init(video_device, width, height, format,
+ &(s->video_fd), &(s->tuner_fd), -1, 0.0) < 0)
+ return -EIO;
+
+ nsignals = 0;
+ last_frame_time = 0;
+
+ return 0;
+}
+
+static int grab_read_close(AVFormatContext *s1)
+{
+ VideoData *s = s1->priv_data;
+ int c;
+
+ c = METEOR_CAP_STOP_CONT;
+ ioctl(s->video_fd, METEORCAPTUR, &c);
+ close(s->video_fd);
+
+ c = AUDIO_MUTE;
+ ioctl(s->tuner_fd, BT848_SAUDIO, &c);
+ close(s->tuner_fd);
+
+ munmap((caddr_t)video_buf, video_buf_size);
+
+ return 0;
+}
+
+AVInputFormat video_grab_device_demuxer = {
+ "bktr",
+ "video grab",
+ sizeof(VideoData),
+ NULL,
+ grab_read_header,
+ grab_read_packet,
+ grab_read_close,
+ .flags = AVFMT_NOFILE,
+};
diff --git a/contrib/ffmpeg/libavformat/gxf.c b/contrib/ffmpeg/libavformat/gxf.c
new file mode 100644
index 000000000..897cdade0
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/gxf.c
@@ -0,0 +1,525 @@
+/*
+ * GXF demuxer.
+ * 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 "avformat.h"
+#include "common.h"
+
+typedef enum {
+ PKT_MAP = 0xbc,
+ PKT_MEDIA = 0xbf,
+ PKT_EOS = 0xfb,
+ PKT_FLT = 0xfc,
+ PKT_UMF = 0xfd
+} pkt_type_t;
+
+typedef enum {
+ MAT_NAME = 0x40,
+ MAT_FIRST_FIELD = 0x41,
+ MAT_LAST_FIELD = 0x42,
+ MAT_MARK_IN = 0x43,
+ MAT_MARK_OUT = 0x44,
+ MAT_SIZE = 0x45
+} mat_tag_t;
+
+typedef enum {
+ TRACK_NAME = 0x4c,
+ TRACK_AUX = 0x4d,
+ TRACK_VER = 0x4e,
+ TRACK_MPG_AUX = 0x4f,
+ TRACK_FPS = 0x50,
+ TRACK_LINES = 0x51,
+ TRACK_FPF = 0x52
+} track_tag_t;
+
+typedef struct {
+ int64_t first_field;
+ int64_t last_field;
+ AVRational frames_per_second;
+ int32_t fields_per_frame;
+} st_info_t;
+
+/**
+ * \brief parses a packet header, extracting type and length
+ * \param pb ByteIOContext to read header from
+ * \param type detected packet type is stored here
+ * \param length detected packet length, excluding header is stored here
+ * \return 0 if header not found or contains invalid data, 1 otherwise
+ */
+static int parse_packet_header(ByteIOContext *pb, pkt_type_t *type, int *length) {
+ if (get_be32(pb))
+ return 0;
+ if (get_byte(pb) != 1)
+ return 0;
+ *type = get_byte(pb);
+ *length = get_be32(pb);
+ if ((*length >> 24) || *length < 16)
+ return 0;
+ *length -= 16;
+ if (get_be32(pb))
+ return 0;
+ if (get_byte(pb) != 0xe1)
+ return 0;
+ if (get_byte(pb) != 0xe2)
+ return 0;
+ return 1;
+}
+
+/**
+ * \brief check if file starts with a PKT_MAP header
+ */
+static int gxf_probe(AVProbeData *p) {
+ static const uint8_t startcode[] = {0, 0, 0, 0, 1, 0xbc}; // start with map packet
+ static const uint8_t endcode[] = {0, 0, 0, 0, 0xe1, 0xe2};
+ if (p->buf_size < 16)
+ return 0;
+ if (!memcmp(p->buf, startcode, sizeof(startcode)) &&
+ !memcmp(&p->buf[16 - sizeof(endcode)], endcode, sizeof(endcode)))
+ return AVPROBE_SCORE_MAX;
+ return 0;
+}
+
+/**
+ * \brief gets the stream index for the track with the specified id, creates new
+ * stream if not found
+ * \param stream id of stream to find / add
+ * \param format stream format identifier
+ */
+static int get_sindex(AVFormatContext *s, int id, int format) {
+ int i;
+ AVStream *st = NULL;
+ for (i = 0; i < s->nb_streams; i++) {
+ if (s->streams[i]->id == id)
+ return i;
+ }
+ st = av_new_stream(s, id);
+ switch (format) {
+ case 3:
+ case 4:
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_MJPEG;
+ break;
+ case 13:
+ case 15:
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_DVVIDEO;
+ break;
+ case 14:
+ case 16:
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_DVVIDEO;
+ break;
+ case 11:
+ case 12:
+ case 20:
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_MPEG2VIDEO;
+ st->need_parsing = 2; // get keyframe flag etc.
+ break;
+ case 22:
+ case 23:
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_MPEG1VIDEO;
+ st->need_parsing = 2; // get keyframe flag etc.
+ break;
+ case 9:
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_PCM_S24LE;
+ st->codec->channels = 1;
+ st->codec->sample_rate = 48000;
+ st->codec->bit_rate = 3 * 1 * 48000 * 8;
+ st->codec->block_align = 3 * 1;
+ st->codec->bits_per_sample = 24;
+ break;
+ case 10:
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_PCM_S16LE;
+ st->codec->channels = 1;
+ st->codec->sample_rate = 48000;
+ st->codec->bit_rate = 2 * 1 * 48000 * 8;
+ st->codec->block_align = 2 * 1;
+ st->codec->bits_per_sample = 16;
+ break;
+ case 17:
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_AC3;
+ st->codec->channels = 2;
+ st->codec->sample_rate = 48000;
+ break;
+ // timecode tracks:
+ case 7:
+ case 8:
+ case 24:
+ st->codec->codec_type = CODEC_TYPE_DATA;
+ st->codec->codec_id = CODEC_ID_NONE;
+ break;
+ default:
+ st->codec->codec_type = CODEC_TYPE_UNKNOWN;
+ st->codec->codec_id = CODEC_ID_NONE;
+ break;
+ }
+ return s->nb_streams - 1;
+}
+
+/**
+ * \brief filters out interesting tags from material information.
+ * \param len lenght of tag section, will be adjusted to contain remaining bytes
+ * \param si struct to store collected information into
+ */
+static void gxf_material_tags(ByteIOContext *pb, int *len, st_info_t *si) {
+ si->first_field = AV_NOPTS_VALUE;
+ si->last_field = AV_NOPTS_VALUE;
+ while (*len >= 2) {
+ mat_tag_t tag = get_byte(pb);
+ int tlen = get_byte(pb);
+ *len -= 2;
+ if (tlen > *len)
+ return;
+ *len -= tlen;
+ if (tlen == 4) {
+ uint32_t value = get_be32(pb);
+ if (tag == MAT_FIRST_FIELD)
+ si->first_field = value;
+ else if (tag == MAT_LAST_FIELD)
+ si->last_field = value;
+ } else
+ url_fskip(pb, tlen);
+ }
+}
+
+/**
+ * \brief convert fps tag value to AVRational fps
+ * \param fps fps value from tag
+ * \return fps as AVRational, or 0 / 0 if unknown
+ */
+static AVRational fps_tag2avr(int32_t fps) {
+ extern const AVRational ff_frame_rate_tab[];
+ if (fps < 1 || fps > 9) fps = 9;
+ return ff_frame_rate_tab[9 - fps]; // values have opposite order
+}
+
+/**
+ * \brief convert UMF attributes flags to AVRational fps
+ * \param fps fps value from flags
+ * \return fps as AVRational, or 0 / 0 if unknown
+ */
+static AVRational fps_umf2avr(uint32_t flags) {
+ static const AVRational map[] = {{50, 1}, {60000, 1001}, {24, 1},
+ {25, 1}, {30000, 1001}};
+ int idx = av_log2((flags & 0x7c0) >> 6);
+ return map[idx];
+}
+
+/**
+ * \brief filters out interesting tags from track information.
+ * \param len length of tag section, will be adjusted to contain remaining bytes
+ * \param si struct to store collected information into
+ */
+static void gxf_track_tags(ByteIOContext *pb, int *len, st_info_t *si) {
+ si->frames_per_second = (AVRational){0, 0};
+ si->fields_per_frame = 0;
+ while (*len >= 2) {
+ track_tag_t tag = get_byte(pb);
+ int tlen = get_byte(pb);
+ *len -= 2;
+ if (tlen > *len)
+ return;
+ *len -= tlen;
+ if (tlen == 4) {
+ uint32_t value = get_be32(pb);
+ if (tag == TRACK_FPS)
+ si->frames_per_second = fps_tag2avr(value);
+ else if (tag == TRACK_FPF && (value == 1 || value == 2))
+ si->fields_per_frame = value;
+ } else
+ url_fskip(pb, tlen);
+ }
+}
+
+/**
+ * \brief read index from FLT packet into stream 0 av_index
+ */
+static void gxf_read_index(AVFormatContext *s, int pkt_len) {
+ ByteIOContext *pb = &s->pb;
+ AVStream *st = s->streams[0];
+ uint32_t fields_per_map = get_le32(pb);
+ uint32_t map_cnt = get_le32(pb);
+ int i;
+ pkt_len -= 8;
+ if (map_cnt > 1000) {
+ av_log(s, AV_LOG_ERROR, "GXF: too many index entries %u (%x)\n", map_cnt, map_cnt);
+ map_cnt = 1000;
+ }
+ if (pkt_len < 4 * map_cnt) {
+ av_log(s, AV_LOG_ERROR, "GXF: invalid index length\n");
+ url_fskip(pb, pkt_len);
+ return;
+ }
+ pkt_len -= 4 * map_cnt;
+ av_add_index_entry(st, 0, 0, 0, 0, 0);
+ for (i = 0; i < map_cnt; i++)
+ av_add_index_entry(st, (uint64_t)get_le32(pb) * 1024,
+ i * (uint64_t)fields_per_map + 1, 0, 0, 0);
+ url_fskip(pb, pkt_len);
+}
+
+static int gxf_header(AVFormatContext *s, AVFormatParameters *ap) {
+ ByteIOContext *pb = &s->pb;
+ pkt_type_t pkt_type;
+ int map_len;
+ int len;
+ AVRational main_timebase = {0, 0};
+ st_info_t si;
+ int i;
+ if (!parse_packet_header(pb, &pkt_type, &map_len) || pkt_type != PKT_MAP) {
+ av_log(s, AV_LOG_ERROR, "GXF: map packet not found\n");
+ return 0;
+ }
+ map_len -= 2;
+ if (get_byte(pb) != 0x0e0 || get_byte(pb) != 0xff) {
+ av_log(s, AV_LOG_ERROR, "GXF: unknown version or invalid map preamble\n");
+ return 0;
+ }
+ map_len -= 2;
+ len = get_be16(pb); // length of material data section
+ if (len > map_len) {
+ av_log(s, AV_LOG_ERROR, "GXF: material data longer than map data\n");
+ return 0;
+ }
+ map_len -= len;
+ gxf_material_tags(pb, &len, &si);
+ url_fskip(pb, len);
+ map_len -= 2;
+ len = get_be16(pb); // length of track description
+ if (len > map_len) {
+ av_log(s, AV_LOG_ERROR, "GXF: track description longer than map data\n");
+ return 0;
+ }
+ map_len -= len;
+ while (len > 0) {
+ int track_type, track_id, track_len;
+ AVStream *st;
+ int idx;
+ len -= 4;
+ track_type = get_byte(pb);
+ track_id = get_byte(pb);
+ track_len = get_be16(pb);
+ len -= track_len;
+ gxf_track_tags(pb, &track_len, &si);
+ url_fskip(pb, track_len);
+ if (!(track_type & 0x80)) {
+ av_log(s, AV_LOG_ERROR, "GXF: invalid track type %x\n", track_type);
+ continue;
+ }
+ track_type &= 0x7f;
+ if ((track_id & 0xc0) != 0xc0) {
+ av_log(s, AV_LOG_ERROR, "GXF: invalid track id %x\n", track_id);
+ continue;
+ }
+ track_id &= 0x3f;
+ idx = get_sindex(s, track_id, track_type);
+ if (idx < 0) continue;
+ st = s->streams[idx];
+ if (!main_timebase.num || !main_timebase.den) {
+ main_timebase.num = si.frames_per_second.den;
+ main_timebase.den = si.frames_per_second.num * si.fields_per_frame;
+ }
+ st->start_time = si.first_field;
+ if (si.first_field != AV_NOPTS_VALUE && si.last_field != AV_NOPTS_VALUE)
+ st->duration = si.last_field - si.first_field;
+ }
+ if (len < 0)
+ av_log(s, AV_LOG_ERROR, "GXF: invalid track description length specified\n");
+ if (map_len)
+ url_fskip(pb, map_len);
+ if (!parse_packet_header(pb, &pkt_type, &len)) {
+ av_log(s, AV_LOG_ERROR, "GXF: sync lost in header\n");
+ return -1;
+ }
+ if (pkt_type == PKT_FLT) {
+ gxf_read_index(s, len);
+ if (!parse_packet_header(pb, &pkt_type, &len)) {
+ av_log(s, AV_LOG_ERROR, "GXF: sync lost in header\n");
+ return -1;
+ }
+ }
+ if (pkt_type == PKT_UMF) {
+ if (len >= 9) {
+ AVRational fps;
+ len -= 9;
+ url_fskip(pb, 5);
+ fps = fps_umf2avr(get_le32(pb));
+ if (!main_timebase.num || !main_timebase.den) {
+ // this may not always be correct, but simply the best we can get
+ main_timebase.num = fps.den;
+ main_timebase.den = fps.num;
+ }
+ } else
+ av_log(s, AV_LOG_INFO, "GXF: UMF packet too short\n");
+ } else
+ av_log(s, AV_LOG_INFO, "GXF: UMF packet missing\n");
+ url_fskip(pb, len);
+ for (i = 0; i < s->nb_streams; i++) {
+ AVStream *st = s->streams[i];
+ if (main_timebase.num && main_timebase.den)
+ st->time_base = main_timebase;
+ else {
+ st->start_time = st->duration = AV_NOPTS_VALUE;
+ }
+ }
+ return 0;
+}
+
+#define READ_ONE() \
+ { \
+ if (!max_interval-- || url_feof(pb)) \
+ goto out; \
+ tmp = tmp << 8 | get_byte(pb); \
+ }
+
+/**
+ * \brief resync the stream on the next media packet with specified properties
+ * \param max_interval how many bytes to search for matching packet at most
+ * \param track track id the media packet must belong to, -1 for any
+ * \param timestamp minimum timestamp (== field number) the packet must have, -1 for any
+ * \return timestamp of packet found
+ */
+static int64_t gxf_resync_media(AVFormatContext *s, uint64_t max_interval, int track, int timestamp) {
+ uint32_t tmp;
+ uint64_t last_pos;
+ uint64_t last_found_pos = 0;
+ int cur_track;
+ int64_t cur_timestamp = AV_NOPTS_VALUE;
+ int len;
+ ByteIOContext *pb = &s->pb;
+ pkt_type_t type;
+ tmp = get_be32(pb);
+start:
+ while (tmp)
+ READ_ONE();
+ READ_ONE();
+ if (tmp != 1)
+ goto start;
+ last_pos = url_ftell(pb);
+ url_fseek(pb, -5, SEEK_CUR);
+ if (!parse_packet_header(pb, &type, &len) || type != PKT_MEDIA) {
+ url_fseek(pb, last_pos, SEEK_SET);
+ goto start;
+ }
+ get_byte(pb);
+ cur_track = get_byte(pb);
+ cur_timestamp = get_be32(pb);
+ last_found_pos = url_ftell(pb) - 16 - 6;
+ if ((track >= 0 && track != cur_track) || (timestamp >= 0 && timestamp > cur_timestamp)) {
+ url_fseek(pb, last_pos, SEEK_SET);
+ goto start;
+ }
+out:
+ if (last_found_pos)
+ url_fseek(pb, last_found_pos, SEEK_SET);
+ return cur_timestamp;
+}
+
+static int gxf_packet(AVFormatContext *s, AVPacket *pkt) {
+ ByteIOContext *pb = &s->pb;
+ pkt_type_t pkt_type;
+ int pkt_len;
+ while (!url_feof(pb)) {
+ int track_type, track_id, ret;
+ int field_nr;
+ if (!parse_packet_header(pb, &pkt_type, &pkt_len)) {
+ if (!url_feof(pb))
+ av_log(s, AV_LOG_ERROR, "GXF: sync lost\n");
+ return -1;
+ }
+ if (pkt_type == PKT_FLT) {
+ gxf_read_index(s, pkt_len);
+ continue;
+ }
+ if (pkt_type != PKT_MEDIA) {
+ url_fskip(pb, pkt_len);
+ continue;
+ }
+ if (pkt_len < 16) {
+ av_log(s, AV_LOG_ERROR, "GXF: invalid media packet length\n");
+ continue;
+ }
+ pkt_len -= 16;
+ track_type = get_byte(pb);
+ track_id = get_byte(pb);
+ field_nr = get_be32(pb);
+ get_be32(pb); // field information
+ get_be32(pb); // "timeline" field number
+ get_byte(pb); // flags
+ get_byte(pb); // reserved
+ // NOTE: there is also data length information in the
+ // field information, it might be better to take this into account
+ // as well.
+ ret = av_get_packet(pb, pkt, pkt_len);
+ pkt->stream_index = get_sindex(s, track_id, track_type);
+ pkt->dts = field_nr;
+ return ret;
+ }
+ return AVERROR_IO;
+}
+
+static int gxf_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) {
+ uint64_t pos;
+ uint64_t maxlen = 100 * 1024 * 1024;
+ AVStream *st = s->streams[0];
+ int64_t start_time = s->streams[stream_index]->start_time;
+ int64_t found;
+ int idx;
+ if (timestamp < start_time) timestamp = start_time;
+ idx = av_index_search_timestamp(st, timestamp - start_time,
+ AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
+ if (idx < 0)
+ return -1;
+ pos = st->index_entries[idx].pos;
+ if (idx < st->nb_index_entries - 2)
+ maxlen = st->index_entries[idx + 2].pos - pos;
+ maxlen = FFMAX(maxlen, 200 * 1024);
+ url_fseek(&s->pb, pos, SEEK_SET);
+ found = gxf_resync_media(s, maxlen, -1, timestamp);
+ if (FFABS(found - timestamp) > 4)
+ return -1;
+ return 0;
+}
+
+static int64_t gxf_read_timestamp(AVFormatContext *s, int stream_index,
+ int64_t *pos, int64_t pos_limit) {
+ ByteIOContext *pb = &s->pb;
+ int64_t res;
+ url_fseek(pb, *pos, SEEK_SET);
+ res = gxf_resync_media(s, pos_limit - *pos, -1, -1);
+ *pos = url_ftell(pb);
+ return res;
+}
+
+AVInputFormat gxf_demuxer = {
+ "gxf",
+ "GXF format",
+ 0,
+ gxf_probe,
+ gxf_header,
+ gxf_packet,
+ NULL,
+ gxf_seek,
+ gxf_read_timestamp,
+};
diff --git a/contrib/ffmpeg/libavformat/gxf.h b/contrib/ffmpeg/libavformat/gxf.h
new file mode 100644
index 000000000..0e2a31ca4
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/gxf.h
@@ -0,0 +1,34 @@
+/*
+ * GXF demuxer
+ * 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 FFMPEG_GXF_H
+#define FFMPEG_GXF_H
+
+/* gxf.c */
+typedef enum {
+ PKT_MAP = 0xbc,
+ PKT_MEDIA = 0xbf,
+ PKT_EOS = 0xfb,
+ PKT_FLT = 0xfc,
+ PKT_UMF = 0xfd
+} pkt_type_t;
+
+#endif /* FFMPEG_GXF_H */
diff --git a/contrib/ffmpeg/libavformat/gxfenc.c b/contrib/ffmpeg/libavformat/gxfenc.c
new file mode 100644
index 000000000..fef5ec104
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/gxfenc.c
@@ -0,0 +1,829 @@
+/*
+ * GXF muxer.
+ * Copyright (c) 2006 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot 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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avformat.h"
+#include "gxf.h"
+#include "riff.h"
+#include "fifo.h"
+
+#define GXF_AUDIO_PACKET_SIZE 65536
+
+typedef struct GXFStreamContext {
+ AVCodecContext *codec;
+ AVFifoBuffer audio_buffer;
+ uint32_t track_type;
+ uint32_t sample_size;
+ uint32_t sample_rate;
+ uint16_t media_type;
+ uint16_t media_info;
+ uint8_t index;
+ int frame_rate_index;
+ int lines_index;
+ int fields;
+ int iframes;
+ int pframes;
+ int bframes;
+ int p_per_gop;
+ int b_per_gop;
+ int first_gop_closed;
+ int64_t current_dts;
+ int dts_delay;
+} GXFStreamContext;
+
+typedef struct GXFContext {
+ uint32_t nb_frames;
+ uint32_t material_flags;
+ uint16_t audio_tracks;
+ uint16_t mpeg_tracks;
+ int64_t creation_time;
+ uint32_t umf_start_offset;
+ uint32_t umf_track_offset;
+ uint32_t umf_media_offset;
+ uint32_t umf_user_data_offset;
+ uint32_t umf_user_data_size;
+ uint32_t umf_length;
+ uint16_t umf_track_size;
+ uint16_t umf_media_size;
+ int audio_written;
+ int sample_rate;
+ int flags;
+ AVFormatContext *fc;
+ GXFStreamContext streams[48];
+} GXFContext;
+
+typedef struct GXF_Lines {
+ int height;
+ int index;
+} GXF_Lines;
+
+
+/* FIXME check if it is relevant */
+static const GXF_Lines gxf_lines_tab[] = {
+ { 480, 1 }, /* NTSC */
+ { 512, 1 }, /* NTSC + VBI */
+ { 576, 2 }, /* PAL */
+ { 608, 2 }, /* PAL + VBI */
+ { 1080, 4 },
+ { 720, 6 },
+};
+
+static const CodecTag gxf_media_types[] = {
+ { CODEC_ID_MJPEG , 3 }, /* NTSC */
+ { CODEC_ID_MJPEG , 4 }, /* PAL */
+ { CODEC_ID_PCM_S24LE , 9 },
+ { CODEC_ID_PCM_S16LE , 10 },
+ { CODEC_ID_MPEG2VIDEO, 11 }, /* NTSC */
+ { CODEC_ID_MPEG2VIDEO, 12 }, /* PAL */
+ { CODEC_ID_DVVIDEO , 13 }, /* NTSC */
+ { CODEC_ID_DVVIDEO , 14 }, /* PAL */
+ { CODEC_ID_DVVIDEO , 15 }, /* 50M NTSC */
+ { CODEC_ID_DVVIDEO , 16 }, /* 50M PAL */
+ { CODEC_ID_AC3 , 17 },
+ //{ CODEC_ID_NONE, , 18 }, /* Non compressed 24 bit audio */
+ { CODEC_ID_MPEG2VIDEO, 20 }, /* MPEG HD */
+ { CODEC_ID_MPEG1VIDEO, 22 }, /* NTSC */
+ { CODEC_ID_MPEG1VIDEO, 23 }, /* PAL */
+ { 0, 0 },
+};
+
+#define SERVER_PATH "/space/"
+#define ES_NAME_PATTERN "ES."
+
+static int gxf_find_lines_index(GXFStreamContext *ctx)
+{
+ int i;
+
+ for (i = 0; i < 6; ++i) {
+ if (ctx->codec->height == gxf_lines_tab[i].height) {
+ ctx->lines_index = gxf_lines_tab[i].index;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static void gxf_write_padding(ByteIOContext *pb, offset_t to_pad)
+{
+ for (; to_pad > 0; to_pad--) {
+ put_byte(pb, 0);
+ }
+}
+
+static offset_t updatePacketSize(ByteIOContext *pb, offset_t pos)
+{
+ offset_t curpos;
+ int size;
+
+ size = url_ftell(pb) - pos;
+ if (size % 4) {
+ gxf_write_padding(pb, 4 - size % 4);
+ size = url_ftell(pb) - pos;
+ }
+ curpos = url_ftell(pb);
+ url_fseek(pb, pos + 6, SEEK_SET);
+ put_be32(pb, size);
+ url_fseek(pb, curpos, SEEK_SET);
+ return curpos - pos;
+}
+
+static offset_t updateSize(ByteIOContext *pb, offset_t pos)
+{
+ offset_t curpos;
+
+ curpos = url_ftell(pb);
+ url_fseek(pb, pos, SEEK_SET);
+ put_be16(pb, curpos - pos - 2);
+ url_fseek(pb, curpos, SEEK_SET);
+ return curpos - pos;
+}
+
+static void gxf_write_packet_header(ByteIOContext *pb, pkt_type_t type)
+{
+ put_be32(pb, 0); /* packet leader for synchro */
+ put_byte(pb, 1);
+ put_byte(pb, type); /* map packet */
+ put_be32(pb, 0); /* size */
+ put_be32(pb, 0); /* reserved */
+ put_byte(pb, 0xE1); /* trailer 1 */
+ put_byte(pb, 0xE2); /* trailer 2 */
+}
+
+static int gxf_write_mpeg_auxiliary(ByteIOContext *pb, GXFStreamContext *ctx)
+{
+ char buffer[1024];
+ int size;
+
+ if (ctx->iframes) {
+ ctx->p_per_gop = ctx->pframes / ctx->iframes;
+ if (ctx->pframes % ctx->iframes)
+ ctx->p_per_gop++;
+ if (ctx->pframes)
+ ctx->b_per_gop = ctx->bframes / ctx->pframes;
+ if (ctx->p_per_gop > 9)
+ ctx->p_per_gop = 9; /* ensure value won't take more than one char */
+ if (ctx->b_per_gop > 9)
+ ctx->b_per_gop = 9; /* ensure value won't take more than one char */
+ }
+ size = snprintf(buffer, 1024, "Ver 1\nBr %.6f\nIpg 1\nPpi %d\nBpiop %d\n"
+ "Pix 0\nCf %d\nCg %d\nSl 7\nnl16 %d\nVi 1\nf1 1\n",
+ (float)ctx->codec->bit_rate, ctx->p_per_gop, ctx->b_per_gop,
+ ctx->codec->pix_fmt == PIX_FMT_YUV422P ? 2 : 1, ctx->first_gop_closed == 1,
+ ctx->codec->height / 16);
+ put_byte(pb, 0x4F);
+ put_byte(pb, size + 1);
+ put_buffer(pb, (uint8_t *)buffer, size + 1);
+ return size + 3;
+}
+
+static int gxf_write_timecode_auxiliary(ByteIOContext *pb, GXFStreamContext *ctx)
+{
+ /* FIXME implement that */
+ put_byte(pb, 0); /* fields */
+ put_byte(pb, 0); /* seconds */
+ put_byte(pb, 0); /* minutes */
+ put_byte(pb, 0); /* flags + hours */
+ /* reserved */
+ put_be32(pb, 0);
+ return 8;
+}
+
+static int gxf_write_track_description(ByteIOContext *pb, GXFStreamContext *stream)
+{
+ offset_t pos;
+
+ /* track description section */
+ put_byte(pb, stream->media_type + 0x80);
+ put_byte(pb, stream->index + 0xC0);
+
+ pos = url_ftell(pb);
+ put_be16(pb, 0); /* size */
+
+ /* media file name */
+ put_byte(pb, 0x4C);
+ put_byte(pb, strlen(ES_NAME_PATTERN) + 3);
+ put_tag(pb, ES_NAME_PATTERN);
+ put_be16(pb, stream->media_info);
+ put_byte(pb, 0);
+
+ if (stream->codec->codec_id != CODEC_ID_MPEG2VIDEO) {
+ /* auxiliary information */
+ put_byte(pb, 0x4D);
+ put_byte(pb, 8);
+ if (stream->codec->codec_id == CODEC_ID_NONE)
+ gxf_write_timecode_auxiliary(pb, stream);
+ else
+ put_le64(pb, 0);
+ }
+
+ /* file system version */
+ put_byte(pb, 0x4E);
+ put_byte(pb, 4);
+ put_be32(pb, 0);
+
+ if (stream->codec->codec_id == CODEC_ID_MPEG2VIDEO)
+ gxf_write_mpeg_auxiliary(pb, stream);
+
+ /* frame rate */
+ put_byte(pb, 0x50);
+ put_byte(pb, 4);
+ put_be32(pb, stream->frame_rate_index);
+
+ /* lines per frame */
+ put_byte(pb, 0x51);
+ put_byte(pb, 4);
+ put_be32(pb, stream->lines_index);
+
+ /* fields per frame */
+ put_byte(pb, 0x52);
+ put_byte(pb, 4);
+ put_be32(pb, stream->fields);
+
+ return updateSize(pb, pos);
+}
+
+static int gxf_write_material_data_section(ByteIOContext *pb, GXFContext *ctx)
+{
+ offset_t pos;
+ const char *filename = strrchr(ctx->fc->filename, '/');
+
+ pos = url_ftell(pb);
+ put_be16(pb, 0); /* size */
+
+ /* name */
+ if (filename)
+ filename++;
+ else
+ filename = ctx->fc->filename;
+ put_byte(pb, 0x40);
+ put_byte(pb, strlen(SERVER_PATH) + strlen(filename) + 1);
+ put_tag(pb, SERVER_PATH);
+ put_tag(pb, filename);
+ put_byte(pb, 0);
+
+ /* first field */
+ put_byte(pb, 0x41);
+ put_byte(pb, 4);
+ put_be32(pb, 0);
+
+ /* last field */
+ put_byte(pb, 0x42);
+ put_byte(pb, 4);
+ put_be32(pb, ctx->nb_frames);
+
+ /* reserved */
+ put_byte(pb, 0x43);
+ put_byte(pb, 4);
+ put_be32(pb, 0);
+
+ put_byte(pb, 0x44);
+ put_byte(pb, 4);
+ put_be32(pb, ctx->nb_frames);
+
+ /* estimated size */
+ put_byte(pb, 0x45);
+ put_byte(pb, 4);
+ put_be32(pb, url_fsize(pb) / 1024);
+
+ return updateSize(pb, pos);
+}
+
+static int gxf_write_track_description_section(ByteIOContext *pb, GXFContext *ctx)
+{
+ offset_t pos;
+ int i;
+
+ pos = url_ftell(pb);
+ put_be16(pb, 0); /* size */
+ for (i = 0; i < ctx->fc->nb_streams; ++i)
+ gxf_write_track_description(pb, &ctx->streams[i]);
+ return updateSize(pb, pos);
+}
+
+static int gxf_write_map_packet(ByteIOContext *pb, GXFContext *ctx)
+{
+ offset_t pos = url_ftell(pb);
+
+ gxf_write_packet_header(pb, PKT_MAP);
+
+ /* preamble */
+ put_byte(pb, 0xE0); /* version */
+ put_byte(pb, 0xFF); /* reserved */
+
+ gxf_write_material_data_section(pb, ctx);
+ gxf_write_track_description_section(pb, ctx);
+
+ return updatePacketSize(pb, pos);
+}
+
+#if 0
+static int gxf_write_flt_packet(ByteIOContext *pb, GXFContext *ctx)
+{
+ offset_t pos = url_ftell(pb);
+ int i;
+
+ gxf_write_packet_header(pb, PKT_FLT);
+
+ put_le32(pb, 1000); /* number of fields */
+ put_le32(pb, 0); /* number of active flt entries */
+
+ for (i = 0; i < 1000; ++i) {
+ put_le32(pb, 0);
+ }
+ return updatePacketSize(pb, pos);
+}
+#endif
+
+static int gxf_write_umf_material_description(ByteIOContext *pb, GXFContext *ctx)
+{
+ put_le32(pb, ctx->flags);
+ put_le32(pb, ctx->nb_frames); /* length of the longest track */
+ put_le32(pb, ctx->nb_frames); /* length of the shortest track */
+ put_le32(pb, 0); /* mark in */
+ put_le32(pb, ctx->nb_frames); /* mark out */
+ put_le32(pb, 0); /* timecode mark in */
+ put_le32(pb, ctx->nb_frames); /* timecode mark out */
+ put_le64(pb, ctx->fc->timestamp); /* modification time */
+ put_le64(pb, ctx->fc->timestamp); /* creation time */
+ put_le16(pb, 0); /* reserved */
+ put_le16(pb, 0); /* reserved */
+ put_le16(pb, ctx->audio_tracks);
+ put_le16(pb, 0); /* timecode track count */
+ put_le16(pb, 0); /* reserved */
+ put_le16(pb, ctx->mpeg_tracks);
+ return 48;
+}
+
+static int gxf_write_umf_payload(ByteIOContext *pb, GXFContext *ctx)
+{
+ put_le32(pb, ctx->umf_length); /* total length of the umf data */
+ put_le32(pb, 3); /* version */
+ put_le32(pb, ctx->fc->nb_streams);
+ put_le32(pb, ctx->umf_track_offset); /* umf track section offset */
+ put_le32(pb, ctx->umf_track_size);
+ put_le32(pb, ctx->fc->nb_streams);
+ put_le32(pb, ctx->umf_media_offset);
+ put_le32(pb, ctx->umf_media_size);
+ put_le32(pb, ctx->umf_user_data_offset); /* user data offset */
+ put_le32(pb, ctx->umf_user_data_size); /* user data size */
+ put_le32(pb, 0); /* reserved */
+ put_le32(pb, 0); /* reserved */
+ return 48;
+}
+
+static int gxf_write_umf_track_description(ByteIOContext *pb, GXFContext *ctx)
+{
+ offset_t pos = url_ftell(pb);
+ int tracks[255]={0};
+ int i;
+
+ ctx->umf_track_offset = pos - ctx->umf_start_offset;
+ for (i = 0; i < ctx->fc->nb_streams; ++i) {
+ AVStream *st = ctx->fc->streams[i];
+ GXFStreamContext *sc = &ctx->streams[i];
+ int id = 0;
+
+ switch (st->codec->codec_id) {
+ case CODEC_ID_MPEG1VIDEO: id= 'L'; break;
+ case CODEC_ID_MPEG2VIDEO: id= 'M'; break;
+ case CODEC_ID_PCM_S16LE: id= 'A'; break;
+ case CODEC_ID_DVVIDEO: id= sc->track_type == 6 ? 'E' : 'D'; break;
+ case CODEC_ID_MJPEG: id= 'V'; break;
+ default: break;
+ }
+ sc->media_info= id << 8;
+ /* FIXME first 10 audio tracks are 0 to 9 next 22 are A to V */
+ sc->media_info |= '0' + (tracks[id]++);
+ put_le16(pb, sc->media_info);
+ put_le16(pb, 1);
+ }
+ return url_ftell(pb) - pos;
+}
+
+static int gxf_write_umf_media_mpeg(ByteIOContext *pb, GXFStreamContext *stream)
+{
+ if (stream->codec->pix_fmt == PIX_FMT_YUV422P)
+ put_le32(pb, 2);
+ else
+ put_le32(pb, 1); /* default to 420 */
+ put_le32(pb, stream->first_gop_closed == 1); /* closed = 1, open = 0, unknown = 255 */
+ put_le32(pb, 3); /* top = 1, bottom = 2, frame = 3, unknown = 0 */
+ put_le32(pb, 1); /* I picture per GOP */
+ put_le32(pb, stream->p_per_gop);
+ put_le32(pb, stream->b_per_gop);
+ if (stream->codec->codec_id == CODEC_ID_MPEG2VIDEO)
+ put_le32(pb, 2);
+ else if (stream->codec->codec_id == CODEC_ID_MPEG1VIDEO)
+ put_le32(pb, 1);
+ else
+ put_le32(pb, 0);
+ put_le32(pb, 0); /* reserved */
+ return 32;
+}
+
+static int gxf_write_umf_media_timecode(ByteIOContext *pb, GXFStreamContext *track)
+{
+ /* FIXME implement */
+ put_be32(pb, 0); /* drop frame flag */
+ put_be32(pb, 0); /* reserved */
+ put_be32(pb, 0); /* reserved */
+ put_be32(pb, 0); /* reserved */
+ put_be32(pb, 0); /* reserved */
+ put_be32(pb, 0); /* reserved */
+ put_be32(pb, 0); /* reserved */
+ put_be32(pb, 0); /* reserved */
+ return 32;
+}
+
+static int gxf_write_umf_media_dv(ByteIOContext *pb, GXFStreamContext *track)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ put_be32(pb, 0);
+ }
+ return 32;
+}
+
+static int gxf_write_umf_media_audio(ByteIOContext *pb, GXFStreamContext *track)
+{
+ put_le64(pb, av_dbl2int(1)); /* sound level to begin to */
+ put_le64(pb, av_dbl2int(1)); /* sound level to begin to */
+ put_le32(pb, 0); /* number of fields over which to ramp up sound level */
+ put_le32(pb, 0); /* number of fields over which to ramp down sound level */
+ put_le32(pb, 0); /* reserved */
+ put_le32(pb, 0); /* reserved */
+ return 32;
+}
+
+#if 0
+static int gxf_write_umf_media_mjpeg(ByteIOContext *pb, GXFStreamContext *track)
+{
+ put_be64(pb, 0); /* FIXME FLOAT max chroma quant level */
+ put_be64(pb, 0); /* FIXME FLOAT max luma quant level */
+ put_be64(pb, 0); /* FIXME FLOAT min chroma quant level */
+ put_be64(pb, 0); /* FIXME FLOAT min luma quant level */
+ return 32;
+}
+#endif
+
+static int gxf_write_umf_media_description(ByteIOContext *pb, GXFContext *ctx)
+{
+ offset_t pos;
+ int i;
+
+ pos = url_ftell(pb);
+ ctx->umf_media_offset = pos - ctx->umf_start_offset;
+ for (i = 0; i < ctx->fc->nb_streams; ++i) {
+ GXFStreamContext *sc = &ctx->streams[i];
+ char buffer[88];
+ offset_t startpos, curpos;
+ int path_size = strlen(ES_NAME_PATTERN);
+
+ memset(buffer, 0, 88);
+ startpos = url_ftell(pb);
+ put_le16(pb, 0); /* length */
+ put_le16(pb, sc->media_info);
+ put_le16(pb, 0); /* reserved */
+ put_le16(pb, 0); /* reserved */
+ put_le32(pb, ctx->nb_frames);
+ put_le32(pb, 0); /* attributes rw, ro */
+ put_le32(pb, 0); /* mark in */
+ put_le32(pb, ctx->nb_frames); /* mark out */
+ strncpy(buffer, ES_NAME_PATTERN, path_size);
+ put_buffer(pb, (uint8_t *)buffer, path_size);
+ put_be16(pb, sc->media_info);
+ put_buffer(pb, (uint8_t *)buffer + path_size + 2, 88 - path_size - 2);
+ put_le32(pb, sc->track_type);
+ put_le32(pb, sc->sample_rate);
+ put_le32(pb, sc->sample_size);
+ put_le32(pb, 0); /* reserved */
+ switch (sc->codec->codec_id) {
+ case CODEC_ID_MPEG2VIDEO:
+ gxf_write_umf_media_mpeg(pb, sc);
+ break;
+ case CODEC_ID_PCM_S16LE:
+ gxf_write_umf_media_audio(pb, sc);
+ break;
+ case CODEC_ID_DVVIDEO:
+ gxf_write_umf_media_dv(pb, sc);
+ break;
+ default:
+ gxf_write_umf_media_timecode(pb, sc); /* 8 0bytes */
+ }
+ curpos = url_ftell(pb);
+ url_fseek(pb, startpos, SEEK_SET);
+ put_le16(pb, curpos - startpos);
+ url_fseek(pb, curpos, SEEK_SET);
+ }
+ return url_ftell(pb) - pos;
+}
+
+static int gxf_write_umf_user_data(ByteIOContext *pb, GXFContext *ctx)
+{
+ offset_t pos = url_ftell(pb);
+ ctx->umf_user_data_offset = pos - ctx->umf_start_offset;
+ put_le32(pb, 20);
+ put_le32(pb, 0);
+ put_le16(pb, 0);
+ put_le16(pb, 0);
+ put_le32(pb, 0);
+ put_byte(pb, 0);
+ put_byte(pb, 0);
+ put_byte(pb, 0);
+ put_byte(pb, 0);
+ return 20;
+}
+
+static int gxf_write_umf_packet(ByteIOContext *pb, GXFContext *ctx)
+{
+ offset_t pos = url_ftell(pb);
+
+ gxf_write_packet_header(pb, PKT_UMF);
+
+ /* preamble */
+ put_byte(pb, 3); /* first and last (only) packet */
+ put_be32(pb, ctx->umf_length); /* data length */
+
+ ctx->umf_start_offset = url_ftell(pb);
+ gxf_write_umf_payload(pb, ctx);
+ gxf_write_umf_material_description(pb, ctx);
+ ctx->umf_track_size = gxf_write_umf_track_description(pb, ctx);
+ ctx->umf_media_size = gxf_write_umf_media_description(pb, ctx);
+ ctx->umf_user_data_size = gxf_write_umf_user_data(pb, ctx);
+ ctx->umf_length = url_ftell(pb) - ctx->umf_start_offset;
+ return updatePacketSize(pb, pos);
+}
+
+static int gxf_write_header(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+ GXFContext *gxf = s->priv_data;
+ int i;
+
+ gxf->fc = s;
+ gxf->flags |= 0x00080000; /* material is simple clip */
+ for (i = 0; i < s->nb_streams; ++i) {
+ AVStream *st = s->streams[i];
+ GXFStreamContext *sc = &gxf->streams[i];
+
+ sc->codec = st->codec;
+ sc->index = i;
+ sc->media_type = codec_get_tag(gxf_media_types, sc->codec->codec_id);
+ if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
+ if (st->codec->codec_id != CODEC_ID_PCM_S16LE) {
+ av_log(s, AV_LOG_ERROR, "only 16 BIT PCM LE allowed for now\n");
+ return -1;
+ }
+ if (st->codec->sample_rate != 48000) {
+ av_log(s, AV_LOG_ERROR, "only 48000hz sampling rate is allowed\n");
+ return -1;
+ }
+ if (st->codec->channels != 1) {
+ av_log(s, AV_LOG_ERROR, "only mono tracks are allowed\n");
+ return -1;
+ }
+ sc->track_type = 2;
+ sc->sample_rate = st->codec->sample_rate;
+ av_set_pts_info(st, 64, 1, sc->sample_rate);
+ sc->sample_size = 16;
+ sc->frame_rate_index = -2;
+ sc->lines_index = -2;
+ sc->fields = -2;
+ gxf->audio_tracks++;
+ gxf->flags |= 0x04000000; /* audio is 16 bit pcm */
+ av_fifo_init(&sc->audio_buffer, 3*GXF_AUDIO_PACKET_SIZE);
+ } else if (sc->codec->codec_type == CODEC_TYPE_VIDEO) {
+ /* FIXME check from time_base ? */
+ if (sc->codec->height == 480 || sc->codec->height == 512) { /* NTSC or NTSC+VBI */
+ sc->frame_rate_index = 5;
+ sc->sample_rate = 60;
+ gxf->flags |= 0x00000080;
+ } else { /* assume PAL */
+ sc->frame_rate_index = 6;
+ sc->media_type++;
+ sc->sample_rate = 50;
+ gxf->flags |= 0x00000040;
+ }
+ gxf->sample_rate = sc->sample_rate;
+ av_set_pts_info(st, 64, 1, sc->sample_rate);
+ if (gxf_find_lines_index(sc) < 0)
+ sc->lines_index = -1;
+ sc->sample_size = st->codec->bit_rate;
+ sc->fields = 2; /* interlaced */
+ switch (sc->codec->codec_id) {
+ case CODEC_ID_MPEG2VIDEO:
+ sc->first_gop_closed = -1;
+ sc->track_type = 4;
+ gxf->mpeg_tracks++;
+ gxf->flags |= 0x00008000;
+ break;
+ case CODEC_ID_DVVIDEO:
+ if (sc->codec->pix_fmt == PIX_FMT_YUV422P) {
+ sc->media_type += 2;
+ sc->track_type = 6;
+ gxf->flags |= 0x00002000;
+ } else {
+ sc->track_type = 5;
+ gxf->flags |= 0x00001000;
+ }
+ break;
+ default:
+ av_log(s, AV_LOG_ERROR, "video codec not supported\n");
+ return -1;
+ }
+ }
+ }
+ gxf_write_map_packet(pb, gxf);
+ //gxf_write_flt_packet(pb, gxf);
+ gxf_write_umf_packet(pb, gxf);
+ put_flush_packet(pb);
+ return 0;
+}
+
+static int gxf_write_eos_packet(ByteIOContext *pb, GXFContext *ctx)
+{
+ offset_t pos = url_ftell(pb);
+
+ gxf_write_packet_header(pb, PKT_EOS);
+ return updatePacketSize(pb, pos);
+}
+
+static int gxf_write_trailer(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+ GXFContext *gxf = s->priv_data;
+ offset_t end;
+ int i;
+
+ for (i = 0; i < s->nb_streams; ++i) {
+ if (s->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) {
+ av_fifo_free(&gxf->streams[i].audio_buffer);
+ }
+ if (s->streams[i]->codec->frame_number > gxf->nb_frames)
+ gxf->nb_frames = 2 * s->streams[i]->codec->frame_number;
+ }
+
+ gxf_write_eos_packet(pb, gxf);
+ end = url_ftell(pb);
+ url_fseek(pb, 0, SEEK_SET);
+ /* overwrite map and umf packets with new values */
+ gxf_write_map_packet(pb, gxf);
+ //gxf_write_flt_packet(pb, gxf);
+ gxf_write_umf_packet(pb, gxf);
+ url_fseek(pb, end, SEEK_SET);
+ return 0;
+}
+
+static int gxf_parse_mpeg_frame(GXFStreamContext *sc, const uint8_t *buf, int size)
+{
+ uint32_t c=-1;
+ int i;
+ for(i=0; i<size-4 && c!=0x100; i++){
+ c = (c<<8) + buf[i];
+ if(c == 0x1B8 && sc->first_gop_closed == -1) /* GOP start code */
+ sc->first_gop_closed= (buf[i+4]>>6)&1;
+ }
+ return (buf[i+1]>>3)&7;
+}
+
+static int gxf_write_media_preamble(ByteIOContext *pb, GXFContext *ctx, AVPacket *pkt, int size)
+{
+ GXFStreamContext *sc = &ctx->streams[pkt->stream_index];
+ int64_t dts = av_rescale(pkt->dts, ctx->sample_rate, sc->sample_rate);
+
+ put_byte(pb, sc->media_type);
+ put_byte(pb, sc->index);
+ put_be32(pb, dts);
+ if (sc->codec->codec_type == CODEC_TYPE_AUDIO) {
+ put_be16(pb, 0);
+ put_be16(pb, size / 2);
+ } else if (sc->codec->codec_id == CODEC_ID_MPEG2VIDEO) {
+ int frame_type = gxf_parse_mpeg_frame(sc, pkt->data, pkt->size);
+ if (frame_type == FF_I_TYPE) {
+ put_byte(pb, 0x0d);
+ sc->iframes++;
+ } else if (frame_type == FF_B_TYPE) {
+ put_byte(pb, 0x0f);
+ sc->bframes++;
+ } else {
+ put_byte(pb, 0x0e);
+ sc->pframes++;
+ }
+ put_be24(pb, size);
+ } else if (sc->codec->codec_id == CODEC_ID_DVVIDEO) {
+ put_byte(pb, size / 4096);
+ put_be24(pb, 0);
+ } else
+ put_be32(pb, size);
+ put_be32(pb, dts);
+ put_byte(pb, 1); /* flags */
+ put_byte(pb, 0); /* reserved */
+ return 16;
+}
+
+static int gxf_write_media_packet(ByteIOContext *pb, GXFContext *ctx, AVPacket *pkt)
+{
+ GXFStreamContext *sc = &ctx->streams[pkt->stream_index];
+ offset_t pos = url_ftell(pb);
+ int padding = 0;
+
+ gxf_write_packet_header(pb, PKT_MEDIA);
+ if (sc->codec->codec_id == CODEC_ID_MPEG2VIDEO && pkt->size % 4) /* MPEG-2 frames must be padded */
+ padding = 4 - pkt->size % 4;
+ else if (sc->codec->codec_type == CODEC_TYPE_AUDIO)
+ padding = GXF_AUDIO_PACKET_SIZE - pkt->size;
+ gxf_write_media_preamble(pb, ctx, pkt, pkt->size + padding);
+ put_buffer(pb, pkt->data, pkt->size);
+ gxf_write_padding(pb, padding);
+ return updatePacketSize(pb, pos);
+}
+
+static int gxf_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ GXFContext *gxf = s->priv_data;
+
+ gxf_write_media_packet(&s->pb, gxf, pkt);
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+static int gxf_new_audio_packet(GXFContext *gxf, GXFStreamContext *sc, AVPacket *pkt, int flush)
+{
+ int size = flush ? av_fifo_size(&sc->audio_buffer) : GXF_AUDIO_PACKET_SIZE;
+
+ if (!size)
+ return 0;
+ av_new_packet(pkt, size);
+ av_fifo_read(&sc->audio_buffer, pkt->data, size);
+ pkt->stream_index = sc->index;
+ pkt->dts = sc->current_dts;
+ sc->current_dts += size / 2; /* we only support 16 bit pcm mono for now */
+ return size;
+}
+
+static int gxf_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
+{
+ GXFContext *gxf = s->priv_data;
+ AVPacket new_pkt;
+ int i;
+
+ for (i = 0; i < s->nb_streams; i++) {
+ AVStream *st = s->streams[i];
+ GXFStreamContext *sc = &gxf->streams[i];
+ if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
+ if (pkt && pkt->stream_index == i) {
+ av_fifo_write(&sc->audio_buffer, pkt->data, pkt->size);
+ pkt = NULL;
+ }
+ if (flush || av_fifo_size(&sc->audio_buffer) >= GXF_AUDIO_PACKET_SIZE) {
+ if (!pkt && gxf_new_audio_packet(gxf, sc, &new_pkt, flush) > 0) {
+ pkt = &new_pkt;
+ break; /* add pkt right now into list */
+ }
+ }
+ } else if (pkt) {
+ /* adjust dts if negative */
+ if (pkt->dts < 0 && !sc->dts_delay) {
+ /* XXX: rescale if codec time base is different from stream time base */
+ sc->dts_delay = av_rescale_q(pkt->dts, st->codec->time_base, st->time_base);
+ pkt->dts = sc->dts_delay; /* set to 0 */
+ }
+ pkt->dts -= sc->dts_delay;
+ }
+ }
+ return av_interleave_packet_per_dts(s, out, pkt, flush);
+}
+
+AVOutputFormat gxf_muxer = {
+ "gxf",
+ "GXF format",
+ NULL,
+ "gxf",
+ sizeof(GXFContext),
+ CODEC_ID_PCM_S16LE,
+ CODEC_ID_MPEG2VIDEO,
+ gxf_write_header,
+ gxf_write_packet,
+ gxf_write_trailer,
+ 0,
+ NULL,
+ gxf_interleave_packet,
+};
diff --git a/contrib/ffmpeg/libavformat/http.c b/contrib/ffmpeg/libavformat/http.c
new file mode 100644
index 000000000..34dd5031a
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/http.c
@@ -0,0 +1,289 @@
+/*
+ * HTTP protocol for ffmpeg client
+ * 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 "avformat.h"
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifndef __BEOS__
+# include <arpa/inet.h>
+#else
+# include "barpainet.h"
+#endif
+#include <netdb.h>
+
+#include "base64.h"
+
+/* XXX: POST protocol is not completly implemented because ffmpeg use
+ only a subset of it */
+
+//#define DEBUG
+
+/* used for protocol handling */
+#define BUFFER_SIZE 1024
+#define URL_SIZE 4096
+
+typedef struct {
+ URLContext *hd;
+ unsigned char buffer[BUFFER_SIZE], *buf_ptr, *buf_end;
+ int line_count;
+ int http_code;
+ char location[URL_SIZE];
+} HTTPContext;
+
+static int http_connect(URLContext *h, const char *path, const char *hoststr,
+ const char *auth);
+static int http_write(URLContext *h, uint8_t *buf, int size);
+
+
+/* return non zero if error */
+static int http_open(URLContext *h, const char *uri, int flags)
+{
+ const char *path, *proxy_path;
+ char hostname[1024], hoststr[1024];
+ char auth[1024];
+ char path1[1024];
+ char buf[1024];
+ int port, use_proxy, err;
+ HTTPContext *s;
+ URLContext *hd = NULL;
+
+ h->is_streamed = 1;
+
+ s = av_malloc(sizeof(HTTPContext));
+ if (!s) {
+ return -ENOMEM;
+ }
+ h->priv_data = s;
+
+ proxy_path = getenv("http_proxy");
+ use_proxy = (proxy_path != NULL) && !getenv("no_proxy") &&
+ strstart(proxy_path, "http://", NULL);
+
+ /* fill the dest addr */
+ redo:
+ /* needed in any case to build the host string */
+ url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port,
+ path1, sizeof(path1), uri);
+ if (port > 0) {
+ snprintf(hoststr, sizeof(hoststr), "%s:%d", hostname, port);
+ } else {
+ pstrcpy(hoststr, sizeof(hoststr), hostname);
+ }
+
+ if (use_proxy) {
+ url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port,
+ NULL, 0, proxy_path);
+ path = uri;
+ } else {
+ if (path1[0] == '\0')
+ path = "/";
+ else
+ path = path1;
+ }
+ if (port < 0)
+ port = 80;
+
+ snprintf(buf, sizeof(buf), "tcp://%s:%d", hostname, port);
+ err = url_open(&hd, buf, URL_RDWR);
+ if (err < 0)
+ goto fail;
+
+ s->hd = hd;
+ if (http_connect(h, path, hoststr, auth) < 0)
+ goto fail;
+ if (s->http_code == 303 && s->location[0] != '\0') {
+ /* url moved, get next */
+ uri = s->location;
+ url_close(hd);
+ goto redo;
+ }
+ return 0;
+ fail:
+ if (hd)
+ url_close(hd);
+ av_free(s);
+ return AVERROR_IO;
+}
+
+static int http_getc(HTTPContext *s)
+{
+ int len;
+ if (s->buf_ptr >= s->buf_end) {
+ len = url_read(s->hd, s->buffer, BUFFER_SIZE);
+ if (len < 0) {
+ return AVERROR_IO;
+ } else if (len == 0) {
+ return -1;
+ } else {
+ s->buf_ptr = s->buffer;
+ s->buf_end = s->buffer + len;
+ }
+ }
+ return *s->buf_ptr++;
+}
+
+static int process_line(HTTPContext *s, char *line, int line_count)
+{
+ char *tag, *p;
+
+ /* end of header */
+ if (line[0] == '\0')
+ return 0;
+
+ p = line;
+ if (line_count == 0) {
+ while (!isspace(*p) && *p != '\0')
+ p++;
+ while (isspace(*p))
+ p++;
+ s->http_code = strtol(p, NULL, 10);
+#ifdef DEBUG
+ printf("http_code=%d\n", s->http_code);
+#endif
+ } else {
+ while (*p != '\0' && *p != ':')
+ p++;
+ if (*p != ':')
+ return 1;
+
+ *p = '\0';
+ tag = line;
+ p++;
+ while (isspace(*p))
+ p++;
+ if (!strcmp(tag, "Location")) {
+ strcpy(s->location, p);
+ }
+ }
+ return 1;
+}
+
+static int http_connect(URLContext *h, const char *path, const char *hoststr,
+ const char *auth)
+{
+ HTTPContext *s = h->priv_data;
+ int post, err, ch;
+ char line[1024], *q;
+ char *auth_b64;
+
+
+ /* send http header */
+ post = h->flags & URL_WRONLY;
+
+ auth_b64 = av_base64_encode((uint8_t *)auth, strlen(auth));
+ snprintf(s->buffer, sizeof(s->buffer),
+ "%s %s HTTP/1.0\r\n"
+ "User-Agent: %s\r\n"
+ "Accept: */*\r\n"
+ "Host: %s\r\n"
+ "Authorization: Basic %s\r\n"
+ "\r\n",
+ post ? "POST" : "GET",
+ path,
+ LIBAVFORMAT_IDENT,
+ hoststr,
+ auth_b64);
+
+ av_freep(&auth_b64);
+ if (http_write(h, s->buffer, strlen(s->buffer)) < 0)
+ return AVERROR_IO;
+
+ /* init input buffer */
+ s->buf_ptr = s->buffer;
+ s->buf_end = s->buffer;
+ s->line_count = 0;
+ s->location[0] = '\0';
+ if (post) {
+ sleep(1);
+ return 0;
+ }
+
+ /* wait for header */
+ q = line;
+ for(;;) {
+ ch = http_getc(s);
+ if (ch < 0)
+ return AVERROR_IO;
+ if (ch == '\n') {
+ /* process line */
+ if (q > line && q[-1] == '\r')
+ q--;
+ *q = '\0';
+#ifdef DEBUG
+ printf("header='%s'\n", line);
+#endif
+ err = process_line(s, line, s->line_count);
+ if (err < 0)
+ return err;
+ if (err == 0)
+ return 0;
+ s->line_count++;
+ q = line;
+ } else {
+ if ((q - line) < sizeof(line) - 1)
+ *q++ = ch;
+ }
+ }
+}
+
+
+static int http_read(URLContext *h, uint8_t *buf, int size)
+{
+ HTTPContext *s = h->priv_data;
+ int len;
+
+ /* read bytes from input buffer first */
+ len = s->buf_end - s->buf_ptr;
+ if (len > 0) {
+ if (len > size)
+ len = size;
+ memcpy(buf, s->buf_ptr, len);
+ s->buf_ptr += len;
+ } else {
+ len = url_read(s->hd, buf, size);
+ }
+ return len;
+}
+
+/* used only when posting data */
+static int http_write(URLContext *h, uint8_t *buf, int size)
+{
+ HTTPContext *s = h->priv_data;
+ return url_write(s->hd, buf, size);
+}
+
+static int http_close(URLContext *h)
+{
+ HTTPContext *s = h->priv_data;
+ url_close(s->hd);
+ av_free(s);
+ return 0;
+}
+
+URLProtocol http_protocol = {
+ "http",
+ http_open,
+ http_read,
+ http_write,
+ NULL, /* seek */
+ http_close,
+};
diff --git a/contrib/ffmpeg/libavformat/idcin.c b/contrib/ffmpeg/libavformat/idcin.c
new file mode 100644
index 000000000..48d1e250d
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/idcin.c
@@ -0,0 +1,301 @@
+/*
+ * Id Quake II CIN File Demuxer
+ * 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 idcin.c
+ * Id Quake II CIN file demuxer by Mike Melanson (melanson@pcisys.net)
+ * For more information about the Id CIN format, visit:
+ * http://www.csse.monash.edu.au/~timf/
+ *
+ * CIN is a somewhat quirky and ill-defined format. Here are some notes
+ * for anyone trying to understand the technical details of this format:
+ *
+ * The format has no definite file signature. This is problematic for a
+ * general-purpose media player that wants to automatically detect file
+ * types. However, a CIN file does start with 5 32-bit numbers that
+ * specify audio and video parameters. This demuxer gets around the lack
+ * of file signature by performing sanity checks on those parameters.
+ * Probabalistically, this is a reasonable solution since the number of
+ * valid combinations of the 5 parameters is a very small subset of the
+ * total 160-bit number space.
+ *
+ * Refer to the function idcin_probe() for the precise A/V parameters
+ * that this demuxer allows.
+ *
+ * Next, each audio and video frame has a duration of 1/14 sec. If the
+ * audio sample rate is a multiple of the common frequency 22050 Hz it will
+ * divide evenly by 14. However, if the sample rate is 11025 Hz:
+ * 11025 (samples/sec) / 14 (frames/sec) = 787.5 (samples/frame)
+ * The way the CIN stores audio in this case is by storing 787 sample
+ * frames in the first audio frame and 788 sample frames in the second
+ * audio frame. Therefore, the total number of bytes in an audio frame
+ * is given as:
+ * audio frame #0: 787 * (bytes/sample) * (# channels) bytes in frame
+ * audio frame #1: 788 * (bytes/sample) * (# channels) bytes in frame
+ * audio frame #2: 787 * (bytes/sample) * (# channels) bytes in frame
+ * audio frame #3: 788 * (bytes/sample) * (# channels) bytes in frame
+ *
+ * Finally, not all Id CIN creation tools agree on the resolution of the
+ * color palette, apparently. Some creation tools specify red, green, and
+ * blue palette components in terms of 6-bit VGA color DAC values which
+ * range from 0..63. Other tools specify the RGB components as full 8-bit
+ * values that range from 0..255. Since there are no markers in the file to
+ * differentiate between the two variants, this demuxer uses the following
+ * heuristic:
+ * - load the 768 palette bytes from disk
+ * - assume that they will need to be shifted left by 2 bits to
+ * transform them from 6-bit values to 8-bit values
+ * - scan through all 768 palette bytes
+ * - if any bytes exceed 63, do not shift the bytes at all before
+ * transmitting them to the video decoder
+ */
+
+#include "avformat.h"
+
+#define HUFFMAN_TABLE_SIZE (64 * 1024)
+#define FRAME_PTS_INC (90000 / 14)
+
+typedef struct IdcinDemuxContext {
+ int video_stream_index;
+ int audio_stream_index;
+ int audio_chunk_size1;
+ int audio_chunk_size2;
+
+ /* demux state variables */
+ int current_audio_chunk;
+ int next_chunk_is_video;
+ int audio_present;
+
+ int64_t pts;
+
+ AVPaletteControl palctrl;
+} IdcinDemuxContext;
+
+static int idcin_probe(AVProbeData *p)
+{
+ unsigned int number;
+
+ /*
+ * This is what you could call a "probabilistic" file check: Id CIN
+ * files don't have a definite file signature. In lieu of such a marker,
+ * perform sanity checks on the 5 32-bit header fields:
+ * width, height: greater than 0, less than or equal to 1024
+ * audio sample rate: greater than or equal to 8000, less than or
+ * equal to 48000, or 0 for no audio
+ * audio sample width (bytes/sample): 0 for no audio, or 1 or 2
+ * audio channels: 0 for no audio, or 1 or 2
+ */
+
+ /* cannot proceed without 20 bytes */
+ if (p->buf_size < 20)
+ return 0;
+
+ /* check the video width */
+ number = LE_32(&p->buf[0]);
+ if ((number == 0) || (number > 1024))
+ return 0;
+
+ /* check the video height */
+ number = LE_32(&p->buf[4]);
+ if ((number == 0) || (number > 1024))
+ return 0;
+
+ /* check the audio sample rate */
+ number = LE_32(&p->buf[8]);
+ if ((number != 0) && ((number < 8000) | (number > 48000)))
+ return 0;
+
+ /* check the audio bytes/sample */
+ number = LE_32(&p->buf[12]);
+ if (number > 2)
+ return 0;
+
+ /* check the audio channels */
+ number = LE_32(&p->buf[16]);
+ if (number > 2)
+ return 0;
+
+ /* return half certainly since this check is a bit sketchy */
+ return AVPROBE_SCORE_MAX / 2;
+}
+
+static int idcin_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ ByteIOContext *pb = &s->pb;
+ IdcinDemuxContext *idcin = (IdcinDemuxContext *)s->priv_data;
+ AVStream *st;
+ unsigned int width, height;
+ unsigned int sample_rate, bytes_per_sample, channels;
+
+ /* get the 5 header parameters */
+ width = get_le32(pb);
+ height = get_le32(pb);
+ sample_rate = get_le32(pb);
+ bytes_per_sample = get_le32(pb);
+ channels = get_le32(pb);
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ av_set_pts_info(st, 33, 1, 90000);
+ idcin->video_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_IDCIN;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->width = width;
+ st->codec->height = height;
+
+ /* load up the Huffman tables into extradata */
+ st->codec->extradata_size = HUFFMAN_TABLE_SIZE;
+ st->codec->extradata = av_malloc(HUFFMAN_TABLE_SIZE);
+ if (get_buffer(pb, st->codec->extradata, HUFFMAN_TABLE_SIZE) !=
+ HUFFMAN_TABLE_SIZE)
+ return AVERROR_IO;
+ /* save a reference in order to transport the palette */
+ st->codec->palctrl = &idcin->palctrl;
+
+ /* if sample rate is 0, assume no audio */
+ if (sample_rate) {
+ idcin->audio_present = 1;
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ av_set_pts_info(st, 33, 1, 90000);
+ idcin->audio_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_tag = 1;
+ st->codec->channels = channels;
+ st->codec->sample_rate = sample_rate;
+ st->codec->bits_per_sample = bytes_per_sample * 8;
+ st->codec->bit_rate = sample_rate * bytes_per_sample * 8 * channels;
+ st->codec->block_align = bytes_per_sample * channels;
+ if (bytes_per_sample == 1)
+ st->codec->codec_id = CODEC_ID_PCM_U8;
+ else
+ st->codec->codec_id = CODEC_ID_PCM_S16LE;
+
+ if (sample_rate % 14 != 0) {
+ idcin->audio_chunk_size1 = (sample_rate / 14) *
+ bytes_per_sample * channels;
+ idcin->audio_chunk_size2 = (sample_rate / 14 + 1) *
+ bytes_per_sample * channels;
+ } else {
+ idcin->audio_chunk_size1 = idcin->audio_chunk_size2 =
+ (sample_rate / 14) * bytes_per_sample * channels;
+ }
+ idcin->current_audio_chunk = 0;
+ } else
+ idcin->audio_present = 1;
+
+ idcin->next_chunk_is_video = 1;
+ idcin->pts = 0;
+
+ return 0;
+}
+
+static int idcin_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ int ret;
+ unsigned int command;
+ unsigned int chunk_size;
+ IdcinDemuxContext *idcin = (IdcinDemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int i;
+ int palette_scale;
+ unsigned char r, g, b;
+ unsigned char palette_buffer[768];
+
+ if (url_feof(&s->pb))
+ return AVERROR_IO;
+
+ if (idcin->next_chunk_is_video) {
+ command = get_le32(pb);
+ if (command == 2) {
+ return AVERROR_IO;
+ } else if (command == 1) {
+ /* trigger a palette change */
+ idcin->palctrl.palette_changed = 1;
+ if (get_buffer(pb, palette_buffer, 768) != 768)
+ return AVERROR_IO;
+ /* scale the palette as necessary */
+ palette_scale = 2;
+ for (i = 0; i < 768; i++)
+ if (palette_buffer[i] > 63) {
+ palette_scale = 0;
+ break;
+ }
+
+ for (i = 0; i < 256; i++) {
+ r = palette_buffer[i * 3 ] << palette_scale;
+ g = palette_buffer[i * 3 + 1] << palette_scale;
+ b = palette_buffer[i * 3 + 2] << palette_scale;
+ idcin->palctrl.palette[i] = (r << 16) | (g << 8) | (b);
+ }
+ }
+
+ chunk_size = get_le32(pb);
+ /* skip the number of decoded bytes (always equal to width * height) */
+ url_fseek(pb, 4, SEEK_CUR);
+ chunk_size -= 4;
+ ret= av_get_packet(pb, pkt, chunk_size);
+ if (ret != chunk_size)
+ return AVERROR_IO;
+ pkt->stream_index = idcin->video_stream_index;
+ pkt->pts = idcin->pts;
+ } else {
+ /* send out the audio chunk */
+ if (idcin->current_audio_chunk)
+ chunk_size = idcin->audio_chunk_size2;
+ else
+ chunk_size = idcin->audio_chunk_size1;
+ ret= av_get_packet(pb, pkt, chunk_size);
+ if (ret != chunk_size)
+ return AVERROR_IO;
+ pkt->stream_index = idcin->audio_stream_index;
+ pkt->pts = idcin->pts;
+
+ idcin->current_audio_chunk ^= 1;
+ idcin->pts += FRAME_PTS_INC;
+ }
+
+ if (idcin->audio_present)
+ idcin->next_chunk_is_video ^= 1;
+
+ return ret;
+}
+
+static int idcin_read_close(AVFormatContext *s)
+{
+
+ return 0;
+}
+
+AVInputFormat idcin_demuxer = {
+ "idcin",
+ "Id CIN format",
+ sizeof(IdcinDemuxContext),
+ idcin_probe,
+ idcin_read_header,
+ idcin_read_packet,
+ idcin_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/idroq.c b/contrib/ffmpeg/libavformat/idroq.c
new file mode 100644
index 000000000..419696c9a
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/idroq.c
@@ -0,0 +1,291 @@
+/*
+ * Id RoQ (.roq) File Demuxer
+ * 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 idroq.c
+ * Id RoQ format file demuxer
+ * by Mike Melanson (melanson@pcisys.net)
+ * for more information on the .roq file format, visit:
+ * http://www.csse.monash.edu.au/~timf/
+ */
+
+#include "avformat.h"
+
+#define RoQ_MAGIC_NUMBER 0x1084
+#define RoQ_CHUNK_PREAMBLE_SIZE 8
+#define RoQ_AUDIO_SAMPLE_RATE 22050
+#define RoQ_CHUNKS_TO_SCAN 30
+
+#define RoQ_INFO 0x1001
+#define RoQ_QUAD_CODEBOOK 0x1002
+#define RoQ_QUAD_VQ 0x1011
+#define RoQ_SOUND_MONO 0x1020
+#define RoQ_SOUND_STEREO 0x1021
+
+typedef struct RoqDemuxContext {
+
+ int width;
+ int height;
+ int audio_channels;
+ int framerate;
+ int frame_pts_inc;
+
+ int video_stream_index;
+ int audio_stream_index;
+
+ int64_t video_pts;
+ unsigned int audio_frame_count;
+
+} RoqDemuxContext;
+
+static int roq_probe(AVProbeData *p)
+{
+ if (p->buf_size < 6)
+ return 0;
+
+ if ((LE_16(&p->buf[0]) != RoQ_MAGIC_NUMBER) ||
+ (LE_32(&p->buf[2]) != 0xFFFFFFFF))
+ return 0;
+
+ return AVPROBE_SCORE_MAX;
+}
+
+static int roq_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ RoqDemuxContext *roq = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVStream *st;
+ unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
+ int i;
+ unsigned int chunk_size;
+ unsigned int chunk_type;
+
+ /* get the main header */
+ if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
+ RoQ_CHUNK_PREAMBLE_SIZE)
+ return AVERROR_IO;
+ roq->framerate = LE_16(&preamble[6]);
+ roq->frame_pts_inc = 90000 / roq->framerate;
+
+ /* init private context parameters */
+ roq->width = roq->height = roq->audio_channels = roq->video_pts =
+ roq->audio_frame_count = 0;
+
+ /* scan the first n chunks searching for A/V parameters */
+ for (i = 0; i < RoQ_CHUNKS_TO_SCAN; i++) {
+ if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
+ RoQ_CHUNK_PREAMBLE_SIZE)
+ return AVERROR_IO;
+
+ chunk_type = LE_16(&preamble[0]);
+ chunk_size = LE_32(&preamble[2]);
+
+ switch (chunk_type) {
+
+ case RoQ_INFO:
+ /* fetch the width and height; reuse the preamble bytes */
+ if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
+ RoQ_CHUNK_PREAMBLE_SIZE)
+ return AVERROR_IO;
+ roq->width = LE_16(&preamble[0]);
+ roq->height = LE_16(&preamble[2]);
+ break;
+
+ case RoQ_QUAD_CODEBOOK:
+ case RoQ_QUAD_VQ:
+ /* ignore during this scan */
+ url_fseek(pb, chunk_size, SEEK_CUR);
+ break;
+
+ case RoQ_SOUND_MONO:
+ roq->audio_channels = 1;
+ url_fseek(pb, chunk_size, SEEK_CUR);
+ break;
+
+ case RoQ_SOUND_STEREO:
+ roq->audio_channels = 2;
+ url_fseek(pb, chunk_size, SEEK_CUR);
+ break;
+
+ default:
+ av_log(s, AV_LOG_ERROR, " unknown RoQ chunk type (%04X)\n", LE_16(&preamble[0]));
+ return AVERROR_INVALIDDATA;
+ break;
+ }
+
+ /* if all necessary parameters have been gathered, exit early */
+ if ((roq->width && roq->height) && roq->audio_channels)
+ break;
+ }
+
+ /* seek back to the first chunk */
+ url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_SET);
+
+ /* initialize the decoders */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ /* set the pts reference (1 pts = 1/90000) */
+ av_set_pts_info(st, 33, 1, 90000);
+ roq->video_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_ROQ;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->width = roq->width;
+ st->codec->height = roq->height;
+
+ if (roq->audio_channels) {
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ av_set_pts_info(st, 33, 1, 90000);
+ roq->audio_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_ROQ_DPCM;
+ st->codec->codec_tag = 0; /* no tag */
+ st->codec->channels = roq->audio_channels;
+ st->codec->sample_rate = RoQ_AUDIO_SAMPLE_RATE;
+ st->codec->bits_per_sample = 16;
+ st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
+ st->codec->bits_per_sample;
+ st->codec->block_align = st->codec->channels * st->codec->bits_per_sample;
+ }
+
+ return 0;
+}
+
+static int roq_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ RoqDemuxContext *roq = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int ret = 0;
+ unsigned int chunk_size;
+ unsigned int chunk_type;
+ unsigned int codebook_size;
+ unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
+ int packet_read = 0;
+ offset_t codebook_offset;
+
+ while (!packet_read) {
+
+ if (url_feof(&s->pb))
+ return AVERROR_IO;
+
+ /* get the next chunk preamble */
+ if ((ret = get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE)) !=
+ RoQ_CHUNK_PREAMBLE_SIZE)
+ return AVERROR_IO;
+
+ chunk_type = LE_16(&preamble[0]);
+ chunk_size = LE_32(&preamble[2]);
+ if(chunk_size > INT_MAX)
+ return AVERROR_INVALIDDATA;
+
+ switch (chunk_type) {
+
+ case RoQ_INFO:
+ /* don't care about this chunk anymore */
+ url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_CUR);
+ break;
+
+ case RoQ_QUAD_CODEBOOK:
+ /* packet needs to contain both this codebook and next VQ chunk */
+ codebook_offset = url_ftell(pb) - RoQ_CHUNK_PREAMBLE_SIZE;
+ codebook_size = chunk_size;
+ url_fseek(pb, codebook_size, SEEK_CUR);
+ if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
+ RoQ_CHUNK_PREAMBLE_SIZE)
+ return AVERROR_IO;
+ chunk_size = LE_32(&preamble[2]) + RoQ_CHUNK_PREAMBLE_SIZE * 2 +
+ codebook_size;
+
+ /* rewind */
+ url_fseek(pb, codebook_offset, SEEK_SET);
+
+ /* load up the packet */
+ ret= av_get_packet(pb, pkt, chunk_size);
+ if (ret != chunk_size)
+ return AVERROR_IO;
+ pkt->stream_index = roq->video_stream_index;
+ pkt->pts = roq->video_pts;
+
+ roq->video_pts += roq->frame_pts_inc;
+ packet_read = 1;
+ break;
+
+ case RoQ_SOUND_MONO:
+ case RoQ_SOUND_STEREO:
+ case RoQ_QUAD_VQ:
+ /* load up the packet */
+ if (av_new_packet(pkt, chunk_size + RoQ_CHUNK_PREAMBLE_SIZE))
+ return AVERROR_IO;
+ /* copy over preamble */
+ memcpy(pkt->data, preamble, RoQ_CHUNK_PREAMBLE_SIZE);
+
+ if (chunk_type == RoQ_QUAD_VQ) {
+ pkt->stream_index = roq->video_stream_index;
+ pkt->pts = roq->video_pts;
+ roq->video_pts += roq->frame_pts_inc;
+ } else {
+ pkt->stream_index = roq->audio_stream_index;
+ pkt->pts = roq->audio_frame_count;
+ pkt->pts *= 90000;
+ pkt->pts /= RoQ_AUDIO_SAMPLE_RATE;
+ roq->audio_frame_count += (chunk_size / roq->audio_channels);
+ }
+
+ pkt->pos= url_ftell(pb);
+ ret = get_buffer(pb, pkt->data + RoQ_CHUNK_PREAMBLE_SIZE,
+ chunk_size);
+ if (ret != chunk_size)
+ ret = AVERROR_IO;
+
+ packet_read = 1;
+ break;
+
+ default:
+ av_log(s, AV_LOG_ERROR, " unknown RoQ chunk (%04X)\n", chunk_type);
+ return AVERROR_INVALIDDATA;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int roq_read_close(AVFormatContext *s)
+{
+// RoqDemuxContext *roq = (RoqDemuxContext *)s->priv_data;
+
+ return 0;
+}
+
+AVInputFormat roq_demuxer = {
+ "RoQ",
+ "Id RoQ format",
+ sizeof(RoqDemuxContext),
+ roq_probe,
+ roq_read_header,
+ roq_read_packet,
+ roq_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/img.c b/contrib/ffmpeg/libavformat/img.c
new file mode 100644
index 000000000..5223c691e
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/img.c
@@ -0,0 +1,400 @@
+/*
+ * Image format
+ * 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 "avformat.h"
+
+typedef struct {
+ int width;
+ int height;
+ int img_first;
+ int img_last;
+ int img_number;
+ int img_count;
+ int img_size;
+ AVImageFormat *img_fmt;
+ int pix_fmt;
+ int is_pipe;
+ char path[1024];
+ /* temporary usage */
+ void *ptr;
+} VideoData;
+
+
+/* return -1 if no image found */
+static int find_image_range(int *pfirst_index, int *plast_index,
+ const char *path)
+{
+ char buf[1024];
+ int range, last_index, range1, first_index;
+
+ /* find the first image */
+ for(first_index = 0; first_index < 5; first_index++) {
+ if (av_get_frame_filename(buf, sizeof(buf), path, first_index) < 0)
+ goto fail;
+ if (url_exist(buf))
+ break;
+ }
+ if (first_index == 5)
+ goto fail;
+
+ /* find the last image */
+ last_index = first_index;
+ for(;;) {
+ range = 0;
+ for(;;) {
+ if (!range)
+ range1 = 1;
+ else
+ range1 = 2 * range;
+ if (av_get_frame_filename(buf, sizeof(buf), path,
+ last_index + range1) < 0)
+ goto fail;
+ if (!url_exist(buf))
+ break;
+ range = range1;
+ /* just in case... */
+ if (range >= (1 << 30))
+ goto fail;
+ }
+ /* we are sure than image last_index + range exists */
+ if (!range)
+ break;
+ last_index += range;
+ }
+ *pfirst_index = first_index;
+ *plast_index = last_index;
+ return 0;
+ fail:
+ return -1;
+}
+
+
+static int image_probe(AVProbeData *p)
+{
+ if (av_filename_number_test(p->filename) && guess_image_format(p->filename))
+ return AVPROBE_SCORE_MAX-1;
+ else
+ return 0;
+}
+
+static int read_header_alloc_cb(void *opaque, AVImageInfo *info)
+{
+ VideoData *s = opaque;
+
+ s->width = info->width;
+ s->height = info->height;
+ s->pix_fmt = info->pix_fmt;
+ /* stop image reading but no error */
+ return 1;
+}
+
+static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap)
+{
+ VideoData *s = s1->priv_data;
+ int ret, first_index, last_index;
+ char buf[1024];
+ ByteIOContext pb1, *f = &pb1;
+ AVStream *st;
+
+ st = av_new_stream(s1, 0);
+ if (!st) {
+ return -ENOMEM;
+ }
+
+ if (ap->image_format)
+ s->img_fmt = ap->image_format;
+
+ pstrcpy(s->path, sizeof(s->path), s1->filename);
+ s->img_number = 0;
+ s->img_count = 0;
+
+ /* find format */
+ if (s1->iformat->flags & AVFMT_NOFILE)
+ s->is_pipe = 0;
+ else
+ s->is_pipe = 1;
+
+ if (!ap->time_base.num) {
+ st->codec->time_base= (AVRational){1,25};
+ } else {
+ st->codec->time_base= ap->time_base;
+ }
+
+ if (!s->is_pipe) {
+ if (find_image_range(&first_index, &last_index, s->path) < 0)
+ goto fail;
+ s->img_first = first_index;
+ s->img_last = last_index;
+ s->img_number = first_index;
+ /* compute duration */
+ st->start_time = 0;
+ st->duration = last_index - first_index + 1;
+ if (av_get_frame_filename(buf, sizeof(buf), s->path, s->img_number) < 0)
+ goto fail;
+ if (url_fopen(f, buf, URL_RDONLY) < 0)
+ goto fail;
+ } else {
+ f = &s1->pb;
+ }
+
+ ret = av_read_image(f, s1->filename, s->img_fmt, read_header_alloc_cb, s);
+ if (ret < 0)
+ goto fail1;
+
+ if (!s->is_pipe) {
+ url_fclose(f);
+ } else {
+ url_fseek(f, 0, SEEK_SET);
+ }
+
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_RAWVIDEO;
+ st->codec->width = s->width;
+ st->codec->height = s->height;
+ st->codec->pix_fmt = s->pix_fmt;
+ s->img_size = avpicture_get_size(s->pix_fmt, (s->width+15)&(~15), (s->height+15)&(~15));
+
+ return 0;
+ fail1:
+ if (!s->is_pipe)
+ url_fclose(f);
+ fail:
+ return AVERROR_IO;
+}
+
+static int read_packet_alloc_cb(void *opaque, AVImageInfo *info)
+{
+ VideoData *s = opaque;
+
+ if (info->width != s->width ||
+ info->height != s->height)
+ return -1;
+ avpicture_fill(&info->pict, s->ptr, info->pix_fmt, (info->width+15)&(~15), (info->height+15)&(~15));
+ return 0;
+}
+
+static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
+{
+ VideoData *s = s1->priv_data;
+ char filename[1024];
+ int ret;
+ ByteIOContext f1, *f;
+
+ if (!s->is_pipe) {
+ /* loop over input */
+ if (s1->loop_input && s->img_number > s->img_last) {
+ s->img_number = s->img_first;
+ }
+ if (av_get_frame_filename(filename, sizeof(filename),
+ s->path, s->img_number) < 0)
+ return AVERROR_IO;
+ f = &f1;
+ if (url_fopen(f, filename, URL_RDONLY) < 0)
+ return AVERROR_IO;
+ } else {
+ f = &s1->pb;
+ if (url_feof(f))
+ return AVERROR_IO;
+ }
+
+ av_new_packet(pkt, s->img_size);
+ pkt->stream_index = 0;
+
+ s->ptr = pkt->data;
+ ret = av_read_image(f, filename, s->img_fmt, read_packet_alloc_cb, s);
+ if (!s->is_pipe) {
+ url_fclose(f);
+ }
+
+ if (ret < 0) {
+ av_free_packet(pkt);
+ return AVERROR_IO; /* signal EOF */
+ } else {
+ /* XXX: computing this pts is not necessary as it is done in
+ the generic code too */
+ pkt->pts = av_rescale((int64_t)s->img_count * s1->streams[0]->codec->time_base.num, s1->streams[0]->time_base.den, s1->streams[0]->codec->time_base.den) / s1->streams[0]->time_base.num;
+ s->img_count++;
+ s->img_number++;
+ return 0;
+ }
+}
+
+static int img_read_close(AVFormatContext *s1)
+{
+ return 0;
+}
+
+/******************************************************/
+/* image output */
+
+static int img_set_parameters(AVFormatContext *s, AVFormatParameters *ap)
+{
+ VideoData *img = s->priv_data;
+ AVStream *st;
+ AVImageFormat *img_fmt;
+ int i;
+
+ /* find output image format */
+ if (ap->image_format) {
+ img_fmt = ap->image_format;
+ } else {
+ img_fmt = guess_image_format(s->filename);
+ }
+ if (!img_fmt)
+ return -1;
+
+ if (s->nb_streams != 1)
+ return -1;
+
+ st = s->streams[0];
+ /* we select the first matching format */
+ for(i=0;i<PIX_FMT_NB;i++) {
+ if (img_fmt->supported_pixel_formats & (1 << i))
+ break;
+ }
+ if (i >= PIX_FMT_NB)
+ return -1;
+ img->img_fmt = img_fmt;
+ img->pix_fmt = i;
+ st->codec->pix_fmt = img->pix_fmt;
+ return 0;
+}
+
+static int img_write_header(AVFormatContext *s)
+{
+ VideoData *img = s->priv_data;
+
+ img->img_number = 1;
+ pstrcpy(img->path, sizeof(img->path), s->filename);
+
+ /* find format */
+ if (s->oformat->flags & AVFMT_NOFILE)
+ img->is_pipe = 0;
+ else
+ img->is_pipe = 1;
+
+ return 0;
+}
+
+static int img_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ VideoData *img = s->priv_data;
+ AVStream *st = s->streams[pkt->stream_index];
+ ByteIOContext pb1, *pb;
+ AVPicture *picture;
+ int width, height, ret;
+ char filename[1024];
+ AVImageInfo info;
+
+ width = st->codec->width;
+ height = st->codec->height;
+
+ picture = (AVPicture *)pkt->data;
+
+ if (!img->is_pipe) {
+ if (av_get_frame_filename(filename, sizeof(filename),
+ img->path, img->img_number) < 0)
+ return AVERROR_IO;
+ pb = &pb1;
+ if (url_fopen(pb, filename, URL_WRONLY) < 0)
+ return AVERROR_IO;
+ } else {
+ pb = &s->pb;
+ }
+ info.width = width;
+ info.height = height;
+ info.pix_fmt = st->codec->pix_fmt;
+ info.interleaved = 0; /* FIXME: there should be a way to set it right */
+ info.pict = *picture;
+ ret = av_write_image(pb, img->img_fmt, &info);
+ if (!img->is_pipe) {
+ url_fclose(pb);
+ }
+
+ img->img_number++;
+ return 0;
+}
+
+static int img_write_trailer(AVFormatContext *s)
+{
+ return 0;
+}
+
+/* input */
+#ifdef CONFIG_IMAGE_DEMUXER
+AVInputFormat image_demuxer = {
+ "image",
+ "image sequence",
+ sizeof(VideoData),
+ image_probe,
+ img_read_header,
+ img_read_packet,
+ img_read_close,
+ NULL,
+ NULL,
+ AVFMT_NOFILE | AVFMT_NEEDNUMBER,
+};
+#endif
+#ifdef CONFIG_IMAGEPIPE_DEMUXER
+AVInputFormat imagepipe_demuxer = {
+ "imagepipe",
+ "piped image sequence",
+ sizeof(VideoData),
+ NULL, /* no probe */
+ img_read_header,
+ img_read_packet,
+ img_read_close,
+ NULL,
+};
+#endif
+
+/* output */
+#ifdef CONFIG_IMAGE_MUXER
+AVOutputFormat image_muxer = {
+ "image",
+ "image sequence",
+ "",
+ "",
+ sizeof(VideoData),
+ CODEC_ID_NONE,
+ CODEC_ID_RAWVIDEO,
+ img_write_header,
+ img_write_packet,
+ img_write_trailer,
+ AVFMT_NOFILE | AVFMT_NEEDNUMBER | AVFMT_RAWPICTURE,
+ img_set_parameters,
+};
+#endif
+#ifdef CONFIG_IMAGEPIPE_MUXER
+AVOutputFormat imagepipe_muxer = {
+ "imagepipe",
+ "piped image sequence",
+ "",
+ "",
+ sizeof(VideoData),
+ CODEC_ID_NONE,
+ CODEC_ID_RAWVIDEO,
+ img_write_header,
+ img_write_packet,
+ img_write_trailer,
+ AVFMT_RAWPICTURE,
+ img_set_parameters,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/img2.c b/contrib/ffmpeg/libavformat/img2.c
new file mode 100644
index 000000000..303190ad2
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/img2.c
@@ -0,0 +1,425 @@
+/*
+ * Image format
+ * Copyright (c) 2000, 2001, 2002 Fabrice Bellard.
+ * 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 "avformat.h"
+
+typedef struct {
+ int img_first;
+ int img_last;
+ int img_number;
+ int img_count;
+ int is_pipe;
+ char path[1024];
+} VideoData;
+
+typedef struct {
+ enum CodecID id;
+ const char *str;
+} IdStrMap;
+
+static const IdStrMap img_tags[] = {
+ { CODEC_ID_MJPEG , "jpeg"},
+ { CODEC_ID_MJPEG , "jpg"},
+ { CODEC_ID_LJPEG , "ljpg"},
+ { CODEC_ID_PNG , "png"},
+ { CODEC_ID_PPM , "ppm"},
+ { CODEC_ID_PGM , "pgm"},
+ { CODEC_ID_PGMYUV , "pgmyuv"},
+ { CODEC_ID_PBM , "pbm"},
+ { CODEC_ID_PAM , "pam"},
+ { CODEC_ID_MPEG1VIDEO, "mpg1-img"},
+ { CODEC_ID_MPEG2VIDEO, "mpg2-img"},
+ { CODEC_ID_MPEG4 , "mpg4-img"},
+ { CODEC_ID_FFV1 , "ffv1-img"},
+ { CODEC_ID_RAWVIDEO , "y"},
+ { CODEC_ID_BMP , "bmp"},
+ { CODEC_ID_GIF , "gif"},
+ { CODEC_ID_TARGA , "tga"},
+ { CODEC_ID_TIFF , "tiff"},
+ {0, NULL}
+};
+
+static int sizes[][2] = {
+ { 640, 480 },
+ { 720, 480 },
+ { 720, 576 },
+ { 352, 288 },
+ { 352, 240 },
+ { 160, 128 },
+ { 512, 384 },
+ { 640, 352 },
+ { 640, 240 },
+};
+
+static int infer_size(int *width_ptr, int *height_ptr, int size)
+{
+ int i;
+
+ for(i=0;i<sizeof(sizes)/sizeof(sizes[0]);i++) {
+ if ((sizes[i][0] * sizes[i][1]) == size) {
+ *width_ptr = sizes[i][0];
+ *height_ptr = sizes[i][1];
+ return 0;
+ }
+ }
+ return -1;
+}
+static enum CodecID av_str2id(const IdStrMap *tags, const char *str)
+{
+ str= strrchr(str, '.');
+ if(!str) return CODEC_ID_NONE;
+ str++;
+
+ while (tags->id) {
+ int i;
+ for(i=0; toupper(tags->str[i]) == toupper(str[i]); i++){
+ if(tags->str[i]==0 && str[i]==0)
+ return tags->id;
+ }
+
+ tags++;
+ }
+ return CODEC_ID_NONE;
+}
+
+/* return -1 if no image found */
+static int find_image_range(int *pfirst_index, int *plast_index,
+ const char *path)
+{
+ char buf[1024];
+ int range, last_index, range1, first_index;
+
+ /* find the first image */
+ for(first_index = 0; first_index < 5; first_index++) {
+ if (av_get_frame_filename(buf, sizeof(buf), path, first_index) < 0){
+ *pfirst_index =
+ *plast_index = 1;
+ return 0;
+ }
+ if (url_exist(buf))
+ break;
+ }
+ if (first_index == 5)
+ goto fail;
+
+ /* find the last image */
+ last_index = first_index;
+ for(;;) {
+ range = 0;
+ for(;;) {
+ if (!range)
+ range1 = 1;
+ else
+ range1 = 2 * range;
+ if (av_get_frame_filename(buf, sizeof(buf), path,
+ last_index + range1) < 0)
+ goto fail;
+ if (!url_exist(buf))
+ break;
+ range = range1;
+ /* just in case... */
+ if (range >= (1 << 30))
+ goto fail;
+ }
+ /* we are sure than image last_index + range exists */
+ if (!range)
+ break;
+ last_index += range;
+ }
+ *pfirst_index = first_index;
+ *plast_index = last_index;
+ return 0;
+ fail:
+ return -1;
+}
+
+
+static int image_probe(AVProbeData *p)
+{
+ if (av_filename_number_test(p->filename) && av_str2id(img_tags, p->filename))
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+enum CodecID av_guess_image2_codec(const char *filename){
+ return av_str2id(img_tags, filename);
+}
+
+static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap)
+{
+ VideoData *s = s1->priv_data;
+ int first_index, last_index;
+ AVStream *st;
+
+ s1->ctx_flags |= AVFMTCTX_NOHEADER;
+
+ st = av_new_stream(s1, 0);
+ if (!st) {
+ return -ENOMEM;
+ }
+
+ pstrcpy(s->path, sizeof(s->path), s1->filename);
+ s->img_number = 0;
+ s->img_count = 0;
+
+ /* find format */
+ if (s1->iformat->flags & AVFMT_NOFILE)
+ s->is_pipe = 0;
+ else{
+ s->is_pipe = 1;
+ st->need_parsing= 1;
+ }
+
+ if (!ap->time_base.num) {
+ av_set_pts_info(st, 60, 1, 25);
+ } else {
+ av_set_pts_info(st, 60, ap->time_base.num, ap->time_base.den);
+ }
+
+ if(ap->width && ap->height){
+ st->codec->width = ap->width;
+ st->codec->height= ap->height;
+ }
+
+ if (!s->is_pipe) {
+ if (find_image_range(&first_index, &last_index, s->path) < 0)
+ return AVERROR_IO;
+ s->img_first = first_index;
+ s->img_last = last_index;
+ s->img_number = first_index;
+ /* compute duration */
+ st->start_time = 0;
+ st->duration = last_index - first_index + 1;
+ }
+
+ if(ap->video_codec_id){
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = ap->video_codec_id;
+ }else if(ap->audio_codec_id){
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = ap->audio_codec_id;
+ }else{
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = av_str2id(img_tags, s->path);
+ }
+ if(st->codec->codec_type == CODEC_TYPE_VIDEO && ap->pix_fmt != PIX_FMT_NONE)
+ st->codec->pix_fmt = ap->pix_fmt;
+
+ return 0;
+}
+
+static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
+{
+ VideoData *s = s1->priv_data;
+ char filename[1024];
+ int i;
+ int size[3]={0}, ret[3]={0};
+ ByteIOContext f1[3], *f[3]= {&f1[0], &f1[1], &f1[2]};
+ AVCodecContext *codec= s1->streams[0]->codec;
+
+ if (!s->is_pipe) {
+ /* loop over input */
+ if (s1->loop_input && s->img_number > s->img_last) {
+ s->img_number = s->img_first;
+ }
+ if (av_get_frame_filename(filename, sizeof(filename),
+ s->path, s->img_number)<0 && s->img_number > 1)
+ return AVERROR_IO;
+ for(i=0; i<3; i++){
+ if (url_fopen(f[i], filename, URL_RDONLY) < 0)
+ return AVERROR_IO;
+ size[i]= url_fsize(f[i]);
+
+ if(codec->codec_id != CODEC_ID_RAWVIDEO)
+ break;
+ filename[ strlen(filename) - 1 ]= 'U' + i;
+ }
+
+ if(codec->codec_id == CODEC_ID_RAWVIDEO && !codec->width)
+ infer_size(&codec->width, &codec->height, size[0]);
+ } else {
+ f[0] = &s1->pb;
+ if (url_feof(f[0]))
+ return AVERROR_IO;
+ size[0]= 4096;
+ }
+
+ av_new_packet(pkt, size[0] + size[1] + size[2]);
+ pkt->stream_index = 0;
+ pkt->flags |= PKT_FLAG_KEY;
+
+ pkt->size= 0;
+ for(i=0; i<3; i++){
+ if(size[i]){
+ ret[i]= get_buffer(f[i], pkt->data + pkt->size, size[i]);
+ if (!s->is_pipe)
+ url_fclose(f[i]);
+ if(ret[i]>0)
+ pkt->size += ret[i];
+ }
+ }
+
+ if (ret[0] <= 0 || ret[1]<0 || ret[2]<0) {
+ av_free_packet(pkt);
+ return AVERROR_IO; /* signal EOF */
+ } else {
+ s->img_count++;
+ s->img_number++;
+ return 0;
+ }
+}
+
+static int img_read_close(AVFormatContext *s1)
+{
+ return 0;
+}
+
+#ifdef CONFIG_MUXERS
+/******************************************************/
+/* image output */
+
+static int img_write_header(AVFormatContext *s)
+{
+ VideoData *img = s->priv_data;
+
+ img->img_number = 1;
+ pstrcpy(img->path, sizeof(img->path), s->filename);
+
+ /* find format */
+ if (s->oformat->flags & AVFMT_NOFILE)
+ img->is_pipe = 0;
+ else
+ img->is_pipe = 1;
+
+ return 0;
+}
+
+static int img_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ VideoData *img = s->priv_data;
+ ByteIOContext pb1[3], *pb[3]= {&pb1[0], &pb1[1], &pb1[2]};
+ char filename[1024];
+ AVCodecContext *codec= s->streams[ pkt->stream_index ]->codec;
+ int i;
+
+ if (!img->is_pipe) {
+ if (av_get_frame_filename(filename, sizeof(filename),
+ img->path, img->img_number) < 0 && img->img_number>1)
+ return AVERROR_IO;
+ for(i=0; i<3; i++){
+ if (url_fopen(pb[i], filename, URL_WRONLY) < 0)
+ return AVERROR_IO;
+
+ if(codec->codec_id != CODEC_ID_RAWVIDEO)
+ break;
+ filename[ strlen(filename) - 1 ]= 'U' + i;
+ }
+ } else {
+ pb[0] = &s->pb;
+ }
+
+ if(codec->codec_id == CODEC_ID_RAWVIDEO){
+ int ysize = codec->width * codec->height;
+ put_buffer(pb[0], pkt->data , ysize);
+ put_buffer(pb[1], pkt->data + ysize, (pkt->size - ysize)/2);
+ put_buffer(pb[2], pkt->data + ysize +(pkt->size - ysize)/2, (pkt->size - ysize)/2);
+ put_flush_packet(pb[1]);
+ put_flush_packet(pb[2]);
+ url_fclose(pb[1]);
+ url_fclose(pb[2]);
+ }else{
+ put_buffer(pb[0], pkt->data, pkt->size);
+ }
+ put_flush_packet(pb[0]);
+ if (!img->is_pipe) {
+ url_fclose(pb[0]);
+ }
+
+ img->img_number++;
+ return 0;
+}
+
+static int img_write_trailer(AVFormatContext *s)
+{
+ return 0;
+}
+
+#endif /* CONFIG_MUXERS */
+
+/* input */
+#ifdef CONFIG_IMAGE2_DEMUXER
+AVInputFormat image2_demuxer = {
+ "image2",
+ "image2 sequence",
+ sizeof(VideoData),
+ image_probe,
+ img_read_header,
+ img_read_packet,
+ img_read_close,
+ NULL,
+ NULL,
+ AVFMT_NOFILE,
+};
+#endif
+#ifdef CONFIG_IMAGE2PIPE_DEMUXER
+AVInputFormat image2pipe_demuxer = {
+ "image2pipe",
+ "piped image2 sequence",
+ sizeof(VideoData),
+ NULL, /* no probe */
+ img_read_header,
+ img_read_packet,
+ img_read_close,
+ NULL,
+};
+#endif
+
+/* output */
+#ifdef CONFIG_IMAGE2_MUXER
+AVOutputFormat image2_muxer = {
+ "image2",
+ "image2 sequence",
+ "",
+ "",
+ sizeof(VideoData),
+ CODEC_ID_NONE,
+ CODEC_ID_MJPEG,
+ img_write_header,
+ img_write_packet,
+ img_write_trailer,
+ AVFMT_NOFILE,
+};
+#endif
+#ifdef CONFIG_IMAGE2PIPE_MUXER
+AVOutputFormat image2pipe_muxer = {
+ "image2pipe",
+ "piped image2 sequence",
+ "",
+ "",
+ sizeof(VideoData),
+ CODEC_ID_NONE,
+ CODEC_ID_MJPEG,
+ img_write_header,
+ img_write_packet,
+ img_write_trailer,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/ipmovie.c b/contrib/ffmpeg/libavformat/ipmovie.c
new file mode 100644
index 000000000..3c0459938
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/ipmovie.c
@@ -0,0 +1,625 @@
+/*
+ * Interplay MVE File Demuxer
+ * 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 ipmovie.c
+ * Interplay MVE file demuxer
+ * by Mike Melanson (melanson@pcisys.net)
+ * For more information regarding the Interplay MVE file format, visit:
+ * http://www.pcisys.net/~melanson/codecs/
+ * The aforementioned site also contains a command line utility for parsing
+ * IP MVE files so that you can get a good idea of the typical structure of
+ * such files. This demuxer is not the best example to use if you are trying
+ * to write your own as it uses a rather roundabout approach for splitting
+ * up and sending out the chunks.
+ */
+
+#include "avformat.h"
+
+/* debugging support: #define DEBUG_IPMOVIE as non-zero to see extremely
+ * verbose information about the demux process */
+#define DEBUG_IPMOVIE 0
+
+#if DEBUG_IPMOVIE
+#define debug_ipmovie printf
+#else
+static inline void debug_ipmovie(const char *format, ...) { }
+#endif
+
+#define IPMOVIE_SIGNATURE "Interplay MVE File\x1A\0"
+#define IPMOVIE_SIGNATURE_SIZE 20
+#define CHUNK_PREAMBLE_SIZE 4
+#define OPCODE_PREAMBLE_SIZE 4
+
+#define CHUNK_INIT_AUDIO 0x0000
+#define CHUNK_AUDIO_ONLY 0x0001
+#define CHUNK_INIT_VIDEO 0x0002
+#define CHUNK_VIDEO 0x0003
+#define CHUNK_SHUTDOWN 0x0004
+#define CHUNK_END 0x0005
+/* these last types are used internally */
+#define CHUNK_DONE 0xFFFC
+#define CHUNK_NOMEM 0xFFFD
+#define CHUNK_EOF 0xFFFE
+#define CHUNK_BAD 0xFFFF
+
+#define OPCODE_END_OF_STREAM 0x00
+#define OPCODE_END_OF_CHUNK 0x01
+#define OPCODE_CREATE_TIMER 0x02
+#define OPCODE_INIT_AUDIO_BUFFERS 0x03
+#define OPCODE_START_STOP_AUDIO 0x04
+#define OPCODE_INIT_VIDEO_BUFFERS 0x05
+#define OPCODE_UNKNOWN_06 0x06
+#define OPCODE_SEND_BUFFER 0x07
+#define OPCODE_AUDIO_FRAME 0x08
+#define OPCODE_SILENCE_FRAME 0x09
+#define OPCODE_INIT_VIDEO_MODE 0x0A
+#define OPCODE_CREATE_GRADIENT 0x0B
+#define OPCODE_SET_PALETTE 0x0C
+#define OPCODE_SET_PALETTE_COMPRESSED 0x0D
+#define OPCODE_UNKNOWN_0E 0x0E
+#define OPCODE_SET_DECODING_MAP 0x0F
+#define OPCODE_UNKNOWN_10 0x10
+#define OPCODE_VIDEO_DATA 0x11
+#define OPCODE_UNKNOWN_12 0x12
+#define OPCODE_UNKNOWN_13 0x13
+#define OPCODE_UNKNOWN_14 0x14
+#define OPCODE_UNKNOWN_15 0x15
+
+#define PALETTE_COUNT 256
+
+typedef struct IPMVEContext {
+
+ unsigned char *buf;
+ int buf_size;
+
+ float fps;
+ int frame_pts_inc;
+
+ unsigned int video_width;
+ unsigned int video_height;
+ int64_t video_pts;
+
+ unsigned int audio_bits;
+ unsigned int audio_channels;
+ unsigned int audio_sample_rate;
+ unsigned int audio_type;
+ unsigned int audio_frame_count;
+
+ int video_stream_index;
+ int audio_stream_index;
+
+ offset_t audio_chunk_offset;
+ int audio_chunk_size;
+ offset_t video_chunk_offset;
+ int video_chunk_size;
+ offset_t decode_map_chunk_offset;
+ int decode_map_chunk_size;
+
+ offset_t next_chunk_offset;
+
+ AVPaletteControl palette_control;
+
+} IPMVEContext;
+
+static int load_ipmovie_packet(IPMVEContext *s, ByteIOContext *pb,
+ AVPacket *pkt) {
+
+ int chunk_type;
+ int64_t audio_pts = 0;
+
+ if (s->audio_chunk_offset) {
+
+ /* adjust for PCM audio by skipping chunk header */
+ if (s->audio_type != CODEC_ID_INTERPLAY_DPCM) {
+ s->audio_chunk_offset += 6;
+ s->audio_chunk_size -= 6;
+ }
+
+ url_fseek(pb, s->audio_chunk_offset, SEEK_SET);
+ s->audio_chunk_offset = 0;
+
+ /* figure out the audio pts */
+ audio_pts = 90000;
+ audio_pts *= s->audio_frame_count;
+ audio_pts /= s->audio_sample_rate;
+
+ if (s->audio_chunk_size != av_get_packet(pb, pkt, s->audio_chunk_size))
+ return CHUNK_EOF;
+
+ pkt->stream_index = s->audio_stream_index;
+ pkt->pts = audio_pts;
+
+ /* audio frame maintenance */
+ if (s->audio_type != CODEC_ID_INTERPLAY_DPCM)
+ s->audio_frame_count +=
+ (s->audio_chunk_size / s->audio_channels / (s->audio_bits / 8));
+ else
+ s->audio_frame_count +=
+ (s->audio_chunk_size - 6) / s->audio_channels;
+
+ debug_ipmovie("sending audio frame with pts %"PRId64" (%d audio frames)\n",
+ audio_pts, s->audio_frame_count);
+
+ chunk_type = CHUNK_VIDEO;
+
+ } else if (s->decode_map_chunk_offset) {
+
+ /* send both the decode map and the video data together */
+
+ if (av_new_packet(pkt, s->decode_map_chunk_size + s->video_chunk_size))
+ return CHUNK_NOMEM;
+
+ pkt->pos= s->decode_map_chunk_offset;
+ url_fseek(pb, s->decode_map_chunk_offset, SEEK_SET);
+ s->decode_map_chunk_offset = 0;
+
+ if (get_buffer(pb, pkt->data, s->decode_map_chunk_size) !=
+ s->decode_map_chunk_size) {
+ av_free_packet(pkt);
+ return CHUNK_EOF;
+ }
+
+ url_fseek(pb, s->video_chunk_offset, SEEK_SET);
+ s->video_chunk_offset = 0;
+
+ if (get_buffer(pb, pkt->data + s->decode_map_chunk_size,
+ s->video_chunk_size) != s->video_chunk_size) {
+ av_free_packet(pkt);
+ return CHUNK_EOF;
+ }
+
+ pkt->stream_index = s->video_stream_index;
+ pkt->pts = s->video_pts;
+
+ debug_ipmovie("sending video frame with pts %"PRId64"\n",
+ pkt->pts);
+
+ s->video_pts += s->frame_pts_inc;
+
+ chunk_type = CHUNK_VIDEO;
+
+ } else {
+
+ url_fseek(pb, s->next_chunk_offset, SEEK_SET);
+ chunk_type = CHUNK_DONE;
+
+ }
+
+ return chunk_type;
+}
+
+/* This function loads and processes a single chunk in an IP movie file.
+ * It returns the type of chunk that was processed. */
+static int process_ipmovie_chunk(IPMVEContext *s, ByteIOContext *pb,
+ AVPacket *pkt)
+{
+ unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
+ int chunk_type;
+ int chunk_size;
+ unsigned char opcode_preamble[OPCODE_PREAMBLE_SIZE];
+ unsigned char opcode_type;
+ unsigned char opcode_version;
+ int opcode_size;
+ unsigned char scratch[1024];
+ int i, j;
+ int first_color, last_color;
+ int audio_flags;
+ unsigned char r, g, b;
+
+ /* see if there are any pending packets */
+ chunk_type = load_ipmovie_packet(s, pb, pkt);
+ if ((chunk_type == CHUNK_VIDEO) && (chunk_type != CHUNK_DONE))
+ return chunk_type;
+
+ /* read the next chunk, wherever the file happens to be pointing */
+ if (url_feof(pb))
+ return CHUNK_EOF;
+ if (get_buffer(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
+ CHUNK_PREAMBLE_SIZE)
+ return CHUNK_BAD;
+ chunk_size = LE_16(&chunk_preamble[0]);
+ chunk_type = LE_16(&chunk_preamble[2]);
+
+ debug_ipmovie("chunk type 0x%04X, 0x%04X bytes: ", chunk_type, chunk_size);
+
+ switch (chunk_type) {
+
+ case CHUNK_INIT_AUDIO:
+ debug_ipmovie("initialize audio\n");
+ break;
+
+ case CHUNK_AUDIO_ONLY:
+ debug_ipmovie("audio only\n");
+ break;
+
+ case CHUNK_INIT_VIDEO:
+ debug_ipmovie("initialize video\n");
+ break;
+
+ case CHUNK_VIDEO:
+ debug_ipmovie("video (and audio)\n");
+ break;
+
+ case CHUNK_SHUTDOWN:
+ debug_ipmovie("shutdown\n");
+ break;
+
+ case CHUNK_END:
+ debug_ipmovie("end\n");
+ break;
+
+ default:
+ debug_ipmovie("invalid chunk\n");
+ chunk_type = CHUNK_BAD;
+ break;
+
+ }
+
+ while ((chunk_size > 0) && (chunk_type != CHUNK_BAD)) {
+
+ /* read the next chunk, wherever the file happens to be pointing */
+ if (url_feof(pb)) {
+ chunk_type = CHUNK_EOF;
+ break;
+ }
+ if (get_buffer(pb, opcode_preamble, CHUNK_PREAMBLE_SIZE) !=
+ CHUNK_PREAMBLE_SIZE) {
+ chunk_type = CHUNK_BAD;
+ break;
+ }
+
+ opcode_size = LE_16(&opcode_preamble[0]);
+ opcode_type = opcode_preamble[2];
+ opcode_version = opcode_preamble[3];
+
+ chunk_size -= OPCODE_PREAMBLE_SIZE;
+ chunk_size -= opcode_size;
+ if (chunk_size < 0) {
+ debug_ipmovie("chunk_size countdown just went negative\n");
+ chunk_type = CHUNK_BAD;
+ break;
+ }
+
+ debug_ipmovie(" opcode type %02X, version %d, 0x%04X bytes: ",
+ opcode_type, opcode_version, opcode_size);
+ switch (opcode_type) {
+
+ case OPCODE_END_OF_STREAM:
+ debug_ipmovie("end of stream\n");
+ url_fseek(pb, opcode_size, SEEK_CUR);
+ break;
+
+ case OPCODE_END_OF_CHUNK:
+ debug_ipmovie("end of chunk\n");
+ url_fseek(pb, opcode_size, SEEK_CUR);
+ break;
+
+ case OPCODE_CREATE_TIMER:
+ debug_ipmovie("create timer\n");
+ if ((opcode_version > 0) || (opcode_size > 6)) {
+ debug_ipmovie("bad create_timer opcode\n");
+ chunk_type = CHUNK_BAD;
+ break;
+ }
+ if (get_buffer(pb, scratch, opcode_size) !=
+ opcode_size) {
+ chunk_type = CHUNK_BAD;
+ break;
+ }
+ s->fps = 1000000.0 / (LE_32(&scratch[0]) * LE_16(&scratch[4]));
+ s->frame_pts_inc = 90000 / s->fps;
+ debug_ipmovie(" %.2f frames/second (timer div = %d, subdiv = %d)\n",
+ s->fps, LE_32(&scratch[0]), LE_16(&scratch[4]));
+ break;
+
+ case OPCODE_INIT_AUDIO_BUFFERS:
+ debug_ipmovie("initialize audio buffers\n");
+ if ((opcode_version > 1) || (opcode_size > 10)) {
+ debug_ipmovie("bad init_audio_buffers opcode\n");
+ chunk_type = CHUNK_BAD;
+ break;
+ }
+ if (get_buffer(pb, scratch, opcode_size) !=
+ opcode_size) {
+ chunk_type = CHUNK_BAD;
+ break;
+ }
+ s->audio_sample_rate = LE_16(&scratch[4]);
+ audio_flags = LE_16(&scratch[2]);
+ /* bit 0 of the flags: 0 = mono, 1 = stereo */
+ s->audio_channels = (audio_flags & 1) + 1;
+ /* bit 1 of the flags: 0 = 8 bit, 1 = 16 bit */
+ s->audio_bits = (((audio_flags >> 1) & 1) + 1) * 8;
+ /* bit 2 indicates compressed audio in version 1 opcode */
+ if ((opcode_version == 1) && (audio_flags & 0x4))
+ s->audio_type = CODEC_ID_INTERPLAY_DPCM;
+ else if (s->audio_bits == 16)
+ s->audio_type = CODEC_ID_PCM_S16LE;
+ else
+ s->audio_type = CODEC_ID_PCM_U8;
+ debug_ipmovie("audio: %d bits, %d Hz, %s, %s format\n",
+ s->audio_bits,
+ s->audio_sample_rate,
+ (s->audio_channels == 2) ? "stereo" : "mono",
+ (s->audio_type == CODEC_ID_INTERPLAY_DPCM) ?
+ "Interplay audio" : "PCM");
+ break;
+
+ case OPCODE_START_STOP_AUDIO:
+ debug_ipmovie("start/stop audio\n");
+ url_fseek(pb, opcode_size, SEEK_CUR);
+ break;
+
+ case OPCODE_INIT_VIDEO_BUFFERS:
+ debug_ipmovie("initialize video buffers\n");
+ if ((opcode_version > 2) || (opcode_size > 8)) {
+ debug_ipmovie("bad init_video_buffers opcode\n");
+ chunk_type = CHUNK_BAD;
+ break;
+ }
+ if (get_buffer(pb, scratch, opcode_size) !=
+ opcode_size) {
+ chunk_type = CHUNK_BAD;
+ break;
+ }
+ s->video_width = LE_16(&scratch[0]) * 8;
+ s->video_height = LE_16(&scratch[2]) * 8;
+ debug_ipmovie("video resolution: %d x %d\n",
+ s->video_width, s->video_height);
+ break;
+
+ case OPCODE_UNKNOWN_06:
+ case OPCODE_UNKNOWN_0E:
+ case OPCODE_UNKNOWN_10:
+ case OPCODE_UNKNOWN_12:
+ case OPCODE_UNKNOWN_13:
+ case OPCODE_UNKNOWN_14:
+ case OPCODE_UNKNOWN_15:
+ debug_ipmovie("unknown (but documented) opcode %02X\n", opcode_type);
+ url_fseek(pb, opcode_size, SEEK_CUR);
+ break;
+
+ case OPCODE_SEND_BUFFER:
+ debug_ipmovie("send buffer\n");
+ url_fseek(pb, opcode_size, SEEK_CUR);
+ break;
+
+ case OPCODE_AUDIO_FRAME:
+ debug_ipmovie("audio frame\n");
+
+ /* log position and move on for now */
+ s->audio_chunk_offset = url_ftell(pb);
+ s->audio_chunk_size = opcode_size;
+ url_fseek(pb, opcode_size, SEEK_CUR);
+ break;
+
+ case OPCODE_SILENCE_FRAME:
+ debug_ipmovie("silence frame\n");
+ url_fseek(pb, opcode_size, SEEK_CUR);
+ break;
+
+ case OPCODE_INIT_VIDEO_MODE:
+ debug_ipmovie("initialize video mode\n");
+ url_fseek(pb, opcode_size, SEEK_CUR);
+ break;
+
+ case OPCODE_CREATE_GRADIENT:
+ debug_ipmovie("create gradient\n");
+ url_fseek(pb, opcode_size, SEEK_CUR);
+ break;
+
+ case OPCODE_SET_PALETTE:
+ debug_ipmovie("set palette\n");
+ /* check for the logical maximum palette size
+ * (3 * 256 + 4 bytes) */
+ if (opcode_size > 0x304) {
+ debug_ipmovie("demux_ipmovie: set_palette opcode too large\n");
+ chunk_type = CHUNK_BAD;
+ break;
+ }
+ if (get_buffer(pb, scratch, opcode_size) != opcode_size) {
+ chunk_type = CHUNK_BAD;
+ break;
+ }
+
+ /* load the palette into internal data structure */
+ first_color = LE_16(&scratch[0]);
+ last_color = first_color + LE_16(&scratch[2]) - 1;
+ /* sanity check (since they are 16 bit values) */
+ if ((first_color > 0xFF) || (last_color > 0xFF)) {
+ debug_ipmovie("demux_ipmovie: set_palette indices out of range (%d -> %d)\n",
+ first_color, last_color);
+ chunk_type = CHUNK_BAD;
+ break;
+ }
+ j = 4; /* offset of first palette data */
+ for (i = first_color; i <= last_color; i++) {
+ /* the palette is stored as a 6-bit VGA palette, thus each
+ * component is shifted up to a 8-bit range */
+ r = scratch[j++] * 4;
+ g = scratch[j++] * 4;
+ b = scratch[j++] * 4;
+ s->palette_control.palette[i] = (r << 16) | (g << 8) | (b);
+ }
+ /* indicate a palette change */
+ s->palette_control.palette_changed = 1;
+ break;
+
+ case OPCODE_SET_PALETTE_COMPRESSED:
+ debug_ipmovie("set palette compressed\n");
+ url_fseek(pb, opcode_size, SEEK_CUR);
+ break;
+
+ case OPCODE_SET_DECODING_MAP:
+ debug_ipmovie("set decoding map\n");
+
+ /* log position and move on for now */
+ s->decode_map_chunk_offset = url_ftell(pb);
+ s->decode_map_chunk_size = opcode_size;
+ url_fseek(pb, opcode_size, SEEK_CUR);
+ break;
+
+ case OPCODE_VIDEO_DATA:
+ debug_ipmovie("set video data\n");
+
+ /* log position and move on for now */
+ s->video_chunk_offset = url_ftell(pb);
+ s->video_chunk_size = opcode_size;
+ url_fseek(pb, opcode_size, SEEK_CUR);
+ break;
+
+ default:
+ debug_ipmovie("*** unknown opcode type\n");
+ chunk_type = CHUNK_BAD;
+ break;
+
+ }
+ }
+
+ /* make a note of where the stream is sitting */
+ s->next_chunk_offset = url_ftell(pb);
+
+ /* dispatch the first of any pending packets */
+ if ((chunk_type == CHUNK_VIDEO) || (chunk_type == CHUNK_AUDIO_ONLY))
+ chunk_type = load_ipmovie_packet(s, pb, pkt);
+
+ return chunk_type;
+}
+
+static int ipmovie_probe(AVProbeData *p)
+{
+ if (p->buf_size < IPMOVIE_SIGNATURE_SIZE)
+ return 0;
+ if (strncmp(p->buf, IPMOVIE_SIGNATURE, IPMOVIE_SIGNATURE_SIZE) != 0)
+ return 0;
+
+ return AVPROBE_SCORE_MAX;
+}
+
+static int ipmovie_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ IPMVEContext *ipmovie = (IPMVEContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVPacket pkt;
+ AVStream *st;
+ unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
+ int chunk_type;
+
+ /* initialize private context members */
+ ipmovie->video_pts = ipmovie->audio_frame_count = 0;
+ ipmovie->audio_chunk_offset = ipmovie->video_chunk_offset =
+ ipmovie->decode_map_chunk_offset = 0;
+
+ /* on the first read, this will position the stream at the first chunk */
+ ipmovie->next_chunk_offset = IPMOVIE_SIGNATURE_SIZE + 6;
+
+ /* process the first chunk which should be CHUNK_INIT_VIDEO */
+ if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_VIDEO)
+ return AVERROR_INVALIDDATA;
+
+ /* peek ahead to the next chunk-- if it is an init audio chunk, process
+ * it; if it is the first video chunk, this is a silent file */
+ if (get_buffer(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
+ CHUNK_PREAMBLE_SIZE)
+ return AVERROR_IO;
+ chunk_type = LE_16(&chunk_preamble[2]);
+ url_fseek(pb, -CHUNK_PREAMBLE_SIZE, SEEK_CUR);
+
+ if (chunk_type == CHUNK_VIDEO)
+ ipmovie->audio_type = 0; /* no audio */
+ else if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_AUDIO)
+ return AVERROR_INVALIDDATA;
+
+ /* initialize the stream decoders */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ av_set_pts_info(st, 33, 1, 90000);
+ ipmovie->video_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_INTERPLAY_VIDEO;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->width = ipmovie->video_width;
+ st->codec->height = ipmovie->video_height;
+
+ /* palette considerations */
+ st->codec->palctrl = &ipmovie->palette_control;
+
+ if (ipmovie->audio_type) {
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ av_set_pts_info(st, 33, 1, 90000);
+ ipmovie->audio_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = ipmovie->audio_type;
+ st->codec->codec_tag = 0; /* no tag */
+ st->codec->channels = ipmovie->audio_channels;
+ st->codec->sample_rate = ipmovie->audio_sample_rate;
+ st->codec->bits_per_sample = ipmovie->audio_bits;
+ st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
+ st->codec->bits_per_sample;
+ if (st->codec->codec_id == CODEC_ID_INTERPLAY_DPCM)
+ st->codec->bit_rate /= 2;
+ st->codec->block_align = st->codec->channels * st->codec->bits_per_sample;
+ }
+
+ return 0;
+}
+
+static int ipmovie_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ IPMVEContext *ipmovie = (IPMVEContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int ret;
+
+ ret = process_ipmovie_chunk(ipmovie, pb, pkt);
+ if (ret == CHUNK_BAD)
+ ret = AVERROR_INVALIDDATA;
+ else if (ret == CHUNK_EOF)
+ ret = AVERROR_IO;
+ else if (ret == CHUNK_NOMEM)
+ ret = AVERROR_NOMEM;
+ else
+ ret = 0;
+
+ return ret;
+}
+
+static int ipmovie_read_close(AVFormatContext *s)
+{
+// IPMVEContext *ipmovie = (IPMVEContext *)s->priv_data;
+
+ return 0;
+}
+
+AVInputFormat ipmovie_demuxer = {
+ "ipmovie",
+ "Interplay MVE format",
+ sizeof(IPMVEContext),
+ ipmovie_probe,
+ ipmovie_read_header,
+ ipmovie_read_packet,
+ ipmovie_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/isom.c b/contrib/ffmpeg/libavformat/isom.c
new file mode 100644
index 000000000..d4e923853
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/isom.c
@@ -0,0 +1,131 @@
+/*
+ * ISO Media common code
+ * Copyright (c) 2001 Fabrice Bellard.
+ * Copyright (c) 2002 Francois Revol <revol@free.fr>
+ * Copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@free.fr>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avformat.h"
+#include "riff.h"
+#include "isom.h"
+
+/* http://gpac.sourceforge.net/tutorial/mediatypes.htm */
+const CodecTag ff_mov_obj_type[] = {
+ { CODEC_ID_MPEG4 , 32 },
+ { CODEC_ID_H264 , 33 },
+ { CODEC_ID_AAC , 64 },
+ { CODEC_ID_MPEG2VIDEO, 96 }, /* MPEG2 Simple */
+ { CODEC_ID_MPEG2VIDEO, 97 }, /* MPEG2 Main */
+ { CODEC_ID_MPEG2VIDEO, 98 }, /* MPEG2 SNR */
+ { CODEC_ID_MPEG2VIDEO, 99 }, /* MPEG2 Spatial */
+ { CODEC_ID_MPEG2VIDEO, 100 }, /* MPEG2 High */
+ { CODEC_ID_MPEG2VIDEO, 101 }, /* MPEG2 422 */
+ { CODEC_ID_AAC , 102 }, /* MPEG2 AAC Main */
+ { CODEC_ID_AAC , 103 }, /* MPEG2 AAC Low */
+ { CODEC_ID_AAC , 104 }, /* MPEG2 AAC SSR */
+ { CODEC_ID_MP3 , 105 },
+ { CODEC_ID_MPEG1VIDEO, 106 },
+ { CODEC_ID_MP2 , 107 },
+ { CODEC_ID_MJPEG , 108 },
+ { CODEC_ID_PCM_S16LE , 224 },
+ { CODEC_ID_VORBIS , 221 },
+ { CODEC_ID_QCELP , 225 },
+ { CODEC_ID_AC3 , 226 },
+ { CODEC_ID_PCM_ALAW , 227 },
+ { CODEC_ID_PCM_MULAW , 228 },
+ { CODEC_ID_PCM_S16BE , 230 },
+ { CODEC_ID_H263 , 242 },
+ { CODEC_ID_H261 , 243 },
+ { 0, 0 },
+};
+
+/* map numeric codes from mdhd atom to ISO 639 */
+/* cf. QTFileFormat.pdf p253, qtff.pdf p205 */
+/* http://developer.apple.com/documentation/mac/Text/Text-368.html */
+/* deprecated by putting the code as 3*5bit ascii */
+static const char *mov_mdhd_language_map[] = {
+ /* 0-9 */
+ "eng", "fra", "ger", "ita", "dut", "sve", "spa", "dan", "por", "nor",
+ "heb", "jpn", "ara", "fin", "gre", "ice", "mlt", "tur", "hr "/*scr*/, "chi"/*ace?*/,
+ "urd", "hin", "tha", "kor", "lit", "pol", "hun", "est", "lav", NULL,
+ "fo ", NULL, "rus", "chi", NULL, "iri", "alb", "ron", "ces", "slk",
+ "slv", "yid", "sr ", "mac", "bul", "ukr", "bel", "uzb", "kaz", "aze",
+ /*?*/
+ "aze", "arm", "geo", "mol", "kir", "tgk", "tuk", "mon", NULL, "pus",
+ "kur", "kas", "snd", "tib", "nep", "san", "mar", "ben", "asm", "guj",
+ "pa ", "ori", "mal", "kan", "tam", "tel", NULL, "bur", "khm", "lao",
+ /* roman? arabic? */
+ "vie", "ind", "tgl", "may", "may", "amh", "tir", "orm", "som", "swa",
+ /*==rundi?*/
+ NULL, "run", NULL, "mlg", "epo", NULL, NULL, NULL, NULL, NULL,
+ /* 100 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "wel", "baq",
+ "cat", "lat", "que", "grn", "aym", "tat", "uig", "dzo", "jav"
+};
+
+int ff_mov_iso639_to_lang(const char *lang, int mp4)
+{
+ int i, code = 0;
+
+ /* old way, only for QT? */
+ for (i = 0; !mp4 && (i < (sizeof(mov_mdhd_language_map)/sizeof(char *))); i++) {
+ if (mov_mdhd_language_map[i] && !strcmp(lang, mov_mdhd_language_map[i]))
+ return i;
+ }
+ /* XXX:can we do that in mov too? */
+ if (!mp4)
+ return 0;
+ /* handle undefined as such */
+ if (lang[0] == '\0')
+ lang = "und";
+ /* 5bit ascii */
+ for (i = 0; i < 3; i++) {
+ unsigned char c = (unsigned char)lang[i];
+ if (c < 0x60)
+ return 0;
+ if (c > 0x60 + 0x1f)
+ return 0;
+ code <<= 5;
+ code |= (c - 0x60);
+ }
+ return code;
+}
+
+int ff_mov_lang_to_iso639(int code, char *to)
+{
+ int i;
+ /* is it the mangled iso code? */
+ /* see http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt */
+ if (code > 138) {
+ for (i = 2; i >= 0; i--) {
+ to[i] = 0x60 + (code & 0x1f);
+ code >>= 5;
+ }
+ return 1;
+ }
+ /* old fashion apple lang code */
+ if (code >= (sizeof(mov_mdhd_language_map)/sizeof(char *)))
+ return 0;
+ if (!mov_mdhd_language_map[code])
+ return 0;
+ strncpy(to, mov_mdhd_language_map[code], 4);
+ return 1;
+}
diff --git a/contrib/ffmpeg/libavformat/isom.h b/contrib/ffmpeg/libavformat/isom.h
new file mode 100644
index 000000000..85cbbdc6c
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/isom.h
@@ -0,0 +1,38 @@
+/*
+ * ISO Media common code
+ * copyright (c) 2001 Fabrice Bellard.
+ * copyright (c) 2002 Francois Revol <revol@free.fr>
+ * copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@free.fr>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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_ISOM_H
+#define FFMPEG_ISOM_H
+
+/* isom.c */
+extern const CodecTag ff_mov_obj_type[];
+
+int ff_mov_iso639_to_lang(const char *lang, int mp4);
+int ff_mov_lang_to_iso639(int code, char *to);
+
+typedef struct Time2Sample{
+ int count;
+ int duration;
+}Time2Sample;
+
+#endif /* FFMPEG_ISOM_H */
diff --git a/contrib/ffmpeg/libavformat/jpeg.c b/contrib/ffmpeg/libavformat/jpeg.c
new file mode 100644
index 000000000..b5fc043c9
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/jpeg.c
@@ -0,0 +1,240 @@
+/*
+ * JPEG 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 "avformat.h"
+
+static int jpeg_probe(AVProbeData *pd)
+{
+ if (pd->buf_size >= 64 &&
+ pd->buf[0] == 0xff && pd->buf[1] == 0xd8 && pd->buf[2] == 0xff)
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+typedef struct JpegOpaque {
+ int (*alloc_cb)(void *opaque, AVImageInfo *info);
+ void *opaque;
+ int ret_code;
+} JpegOpaque;
+
+/* called by the codec to allocate the image */
+static int jpeg_get_buffer(AVCodecContext *c, AVFrame *picture)
+{
+ JpegOpaque *jctx = c->opaque;
+ AVImageInfo info1, *info = &info1;
+ int ret, i;
+
+ info->width = c->width;
+ info->height = c->height;
+ switch(c->pix_fmt) {
+ case PIX_FMT_YUV420P:
+ info->pix_fmt = PIX_FMT_YUVJ420P;
+ break;
+ case PIX_FMT_YUV422P:
+ info->pix_fmt = PIX_FMT_YUVJ422P;
+ break;
+ case PIX_FMT_YUV444P:
+ info->pix_fmt = PIX_FMT_YUVJ444P;
+ break;
+ default:
+ return -1;
+ }
+ ret = jctx->alloc_cb(jctx->opaque, info);
+ if (ret) {
+ jctx->ret_code = ret;
+ return -1;
+ } else {
+ for(i=0;i<3;i++) {
+ picture->data[i] = info->pict.data[i];
+ picture->linesize[i] = info->pict.linesize[i];
+ }
+ return 0;
+ }
+}
+
+static void jpeg_img_copy(uint8_t *dst, int dst_wrap,
+ uint8_t *src, int src_wrap,
+ int width, int height)
+{
+ for(;height > 0; height--) {
+ memcpy(dst, src, width);
+ dst += dst_wrap;
+ src += src_wrap;
+ }
+}
+
+/* XXX: libavcodec is broken for truncated jpegs! */
+#define IO_BUF_SIZE (1024*1024)
+
+static int jpeg_read(ByteIOContext *f,
+ int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
+{
+ AVCodecContext *c;
+ AVFrame *picture, picture1;
+ int len, size, got_picture, i;
+ uint8_t *inbuf_ptr, inbuf[IO_BUF_SIZE];
+ JpegOpaque jctx;
+
+ jctx.alloc_cb = alloc_cb;
+ jctx.opaque = opaque;
+ jctx.ret_code = -1; /* default return code is error */
+
+ c = avcodec_alloc_context();
+ if (!c)
+ return -1;
+ picture= avcodec_alloc_frame();
+ if (!picture) {
+ av_free(c);
+ return -1;
+ }
+ c->opaque = &jctx;
+ c->get_buffer = jpeg_get_buffer;
+ c->flags |= CODEC_FLAG_TRUNCATED; /* we dont send complete frames */
+ if (avcodec_open(c, &mjpeg_decoder) < 0)
+ goto fail1;
+ for(;;) {
+ size = get_buffer(f, inbuf, sizeof(inbuf));
+ if (size == 0)
+ break;
+ inbuf_ptr = inbuf;
+ while (size > 0) {
+ len = avcodec_decode_video(c, &picture1, &got_picture,
+ inbuf_ptr, size);
+ if (len < 0)
+ goto fail;
+ if (got_picture)
+ goto the_end;
+ size -= len;
+ inbuf_ptr += len;
+ }
+ }
+ the_end:
+ /* XXX: currently, the mjpeg decoder does not use AVFrame, so we
+ must do it by hand */
+ if (jpeg_get_buffer(c, picture) < 0)
+ goto fail;
+ for(i=0;i<3;i++) {
+ int w, h;
+ w = c->width;
+ h = c->height;
+ if (i >= 1) {
+ switch(c->pix_fmt) {
+ default:
+ case PIX_FMT_YUV420P:
+ w = (w + 1) >> 1;
+ h = (h + 1) >> 1;
+ break;
+ case PIX_FMT_YUV422P:
+ w = (w + 1) >> 1;
+ break;
+ case PIX_FMT_YUV444P:
+ break;
+ }
+ }
+ jpeg_img_copy(picture->data[i], picture->linesize[i],
+ picture1.data[i], picture1.linesize[i],
+ w, h);
+ }
+ jctx.ret_code = 0;
+ fail:
+ avcodec_close(c);
+ fail1:
+ av_free(picture);
+ av_free(c);
+ return jctx.ret_code;
+}
+
+#if defined(CONFIG_MUXERS) && defined(CONFIG_MJPEG_ENCODER)
+static int jpeg_write(ByteIOContext *pb, AVImageInfo *info)
+{
+ AVCodecContext *c;
+ uint8_t *outbuf = NULL;
+ int outbuf_size, ret, size, i;
+ AVFrame *picture;
+
+ ret = -1;
+ c = avcodec_alloc_context();
+ if (!c)
+ return -1;
+ picture = avcodec_alloc_frame();
+ if (!picture)
+ goto fail2;
+ c->width = info->width;
+ c->height = info->height;
+ /* XXX: currently move that to the codec ? */
+ switch(info->pix_fmt) {
+ case PIX_FMT_YUVJ420P:
+ c->pix_fmt = PIX_FMT_YUV420P;
+ break;
+ case PIX_FMT_YUVJ422P:
+ c->pix_fmt = PIX_FMT_YUV422P;
+ break;
+ case PIX_FMT_YUVJ444P:
+ c->pix_fmt = PIX_FMT_YUV444P;
+ break;
+ default:
+ goto fail1;
+ }
+ for(i=0;i<3;i++) {
+ picture->data[i] = info->pict.data[i];
+ picture->linesize[i] = info->pict.linesize[i];
+ }
+ /* set the quality */
+ picture->quality = 3; /* XXX: a parameter should be used */
+ c->flags |= CODEC_FLAG_QSCALE;
+
+ if (avcodec_open(c, &mjpeg_encoder) < 0)
+ goto fail1;
+
+ /* XXX: needs to sort out that size problem */
+ outbuf_size = 1000000;
+ outbuf = av_malloc(outbuf_size);
+
+ size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
+ if (size < 0)
+ goto fail;
+ put_buffer(pb, outbuf, size);
+ put_flush_packet(pb);
+ ret = 0;
+
+ fail:
+ avcodec_close(c);
+ av_free(outbuf);
+ fail1:
+ av_free(picture);
+ fail2:
+ av_free(c);
+ return ret;
+}
+#endif //CONFIG_MUXERS
+
+AVImageFormat jpeg_image_format = {
+ "jpeg",
+ "jpg,jpeg",
+ jpeg_probe,
+ jpeg_read,
+ (1 << PIX_FMT_YUVJ420P) | (1 << PIX_FMT_YUVJ422P) | (1 << PIX_FMT_YUVJ444P),
+#if defined(CONFIG_MUXERS) && defined(CONFIG_MJPEG_ENCODER)
+ jpeg_write,
+#else
+ NULL,
+#endif //CONFIG_MUXERS
+};
diff --git a/contrib/ffmpeg/libavformat/libnut.c b/contrib/ffmpeg/libavformat/libnut.c
new file mode 100644
index 000000000..d4e7201ab
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/libnut.c
@@ -0,0 +1,283 @@
+#include "avformat.h"
+#include "riff.h"
+#include <libnut.h>
+
+#define ID_STRING "nut/multimedia container"
+#define ID_LENGTH (strlen(ID_STRING) + 1)
+
+typedef struct {
+ nut_context_t * nut;
+ nut_stream_header_t * s;
+} NUTContext;
+
+static const CodecTag nut_tags[] = {
+ { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
+ { CODEC_ID_MP3, MKTAG('m', 'p', '3', ' ') },
+ { CODEC_ID_VORBIS, MKTAG('v', 'r', 'b', 's') },
+ { 0, 0 },
+};
+
+#ifdef CONFIG_MUXERS
+static int av_write(void * h, size_t len, const uint8_t * buf) {
+ ByteIOContext * bc = h;
+ put_buffer(bc, buf, len);
+ //put_flush_packet(bc);
+ return len;
+}
+
+static int nut_write_header(AVFormatContext * avf) {
+ NUTContext * priv = avf->priv_data;
+ ByteIOContext * bc = &avf->pb;
+ nut_muxer_opts_t mopts = {
+ .output = {
+ .priv = bc,
+ .write = av_write,
+ },
+ .alloc = { av_malloc, av_realloc, av_free },
+ .write_index = 1,
+ .realtime_stream = 0,
+ .max_distance = 32768,
+ .fti = NULL,
+ };
+ nut_stream_header_t * s;
+ int i;
+
+ priv->s = s = av_mallocz((avf->nb_streams + 1) * sizeof*s);
+
+ for (i = 0; i < avf->nb_streams; i++) {
+ AVCodecContext * codec = avf->streams[i]->codec;
+ int j;
+ int fourcc = 0;
+ int nom, denom, ssize;
+
+ s[i].type = codec->codec_type == CODEC_TYPE_VIDEO ? NUT_VIDEO_CLASS : NUT_AUDIO_CLASS;
+
+ if (codec->codec_tag) fourcc = codec->codec_tag;
+ else fourcc = codec_get_tag(nut_tags, codec->codec_id);
+
+ if (!fourcc) {
+ if (codec->codec_type == CODEC_TYPE_VIDEO) fourcc = codec_get_bmp_tag(codec->codec_id);
+ if (codec->codec_type == CODEC_TYPE_AUDIO) fourcc = codec_get_wav_tag(codec->codec_id);
+ }
+
+ s[i].fourcc_len = 4;
+ s[i].fourcc = av_malloc(s[i].fourcc_len);
+ for (j = 0; j < s[i].fourcc_len; j++) s[i].fourcc[j] = (fourcc >> (j*8)) & 0xFF;
+
+ ff_parse_specific_params(codec, &nom, &ssize, &denom);
+ av_set_pts_info(avf->streams[i], 60, denom, nom);
+
+ s[i].time_base.nom = denom;
+ s[i].time_base.den = nom;
+
+ s[i].fixed_fps = 0;
+ s[i].decode_delay = codec->has_b_frames;
+ s[i].codec_specific_len = codec->extradata_size;
+ s[i].codec_specific = codec->extradata;
+
+ if (codec->codec_type == CODEC_TYPE_VIDEO) {
+ s[i].width = codec->width;
+ s[i].height = codec->height;
+ s[i].sample_width = 0;
+ s[i].sample_height = 0;
+ s[i].colorspace_type = 0;
+ } else {
+ s[i].samplerate_nom = codec->sample_rate;
+ s[i].samplerate_denom = 1;
+ s[i].channel_count = codec->channels;
+ }
+ }
+
+ s[avf->nb_streams].type = -1;
+ priv->nut = nut_muxer_init(&mopts, s, NULL);
+
+ return 0;
+}
+
+static int nut_write_packet(AVFormatContext * avf, AVPacket * pkt) {
+ NUTContext * priv = avf->priv_data;
+ nut_packet_t p;
+
+ p.len = pkt->size;
+ p.stream = pkt->stream_index;
+ p.pts = pkt->pts;
+ p.flags = pkt->flags & PKT_FLAG_KEY ? NUT_FLAG_KEY : 0;
+ p.next_pts = 0;
+
+ nut_write_frame_reorder(priv->nut, &p, pkt->data);
+
+ return 0;
+}
+
+static int nut_write_trailer(AVFormatContext * avf) {
+ ByteIOContext * bc = &avf->pb;
+ NUTContext * priv = avf->priv_data;
+ int i;
+
+ nut_muxer_uninit_reorder(priv->nut);
+ put_flush_packet(bc);
+
+ for(i = 0; priv->s[i].type != -1; i++ ) av_freep(&priv->s[i].fourcc);
+ av_freep(&priv->s);
+
+ return 0;
+}
+
+AVOutputFormat nut_muxer = {
+ "nut",
+ "nut format",
+ "video/x-nut",
+ "nut",
+ sizeof(NUTContext),
+ CODEC_ID_VORBIS,
+ CODEC_ID_MPEG4,
+ nut_write_header,
+ nut_write_packet,
+ nut_write_trailer,
+ .flags = AVFMT_GLOBALHEADER,
+};
+#endif //CONFIG_MUXERS
+
+static int nut_probe(AVProbeData *p) {
+ if (p->buf_size >= ID_LENGTH && !memcmp(p->buf, ID_STRING, ID_LENGTH)) return AVPROBE_SCORE_MAX;
+
+ return 0;
+}
+
+static size_t av_read(void * h, size_t len, uint8_t * buf) {
+ ByteIOContext * bc = h;
+ return get_buffer(bc, buf, len);
+}
+
+static off_t av_seek(void * h, long long pos, int whence) {
+ ByteIOContext * bc = h;
+ if (whence == SEEK_END) {
+ pos = url_fsize(bc) + pos;
+ whence = SEEK_SET;
+ }
+ return url_fseek(bc, pos, whence);
+}
+
+static int nut_read_header(AVFormatContext * avf, AVFormatParameters * ap) {
+ NUTContext * priv = avf->priv_data;
+ ByteIOContext * bc = &avf->pb;
+ nut_demuxer_opts_t dopts = {
+ .input = {
+ .priv = bc,
+ .seek = av_seek,
+ .read = av_read,
+ .eof = NULL,
+ .file_pos = 0,
+ },
+ .alloc = { av_malloc, av_realloc, av_free },
+ .read_index = 1,
+ .cache_syncpoints = 1,
+ };
+ nut_context_t * nut = priv->nut = nut_demuxer_init(&dopts);
+ nut_stream_header_t * s;
+ int ret, i;
+
+ if ((ret = nut_read_headers(nut, &s, NULL))) {
+ av_log(avf, AV_LOG_ERROR, " NUT error: %s\n", nut_error(ret));
+ nut_demuxer_uninit(nut);
+ return -1;
+ }
+
+ priv->s = s;
+
+ for (i = 0; s[i].type != -1 && i < 2; i++) {
+ AVStream * st = av_new_stream(avf, i);
+ int j;
+
+ for (j = 0; j < s[i].fourcc_len && j < 8; j++) st->codec->codec_tag |= s[i].fourcc[j]<<(j*8);
+
+ st->codec->has_b_frames = s[i].decode_delay;
+
+ st->codec->extradata_size = s[i].codec_specific_len;
+ if (st->codec->extradata_size) {
+ st->codec->extradata = av_mallocz(st->codec->extradata_size);
+ memcpy(st->codec->extradata, s[i].codec_specific, st->codec->extradata_size);
+ }
+
+ av_set_pts_info(avf->streams[i], 60, s[i].time_base.nom, s[i].time_base.den);
+ st->start_time = 0;
+ st->duration = s[i].max_pts;
+
+ st->codec->codec_id = codec_get_id(nut_tags, st->codec->codec_tag);
+
+ switch(s[i].type) {
+ case NUT_AUDIO_CLASS:
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ if (st->codec->codec_id == CODEC_ID_NONE) st->codec->codec_id = codec_get_wav_id(st->codec->codec_tag);
+
+ st->codec->channels = s[i].channel_count;
+ st->codec->sample_rate = s[i].samplerate_nom / s[i].samplerate_denom;
+ break;
+ case NUT_VIDEO_CLASS:
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ if (st->codec->codec_id == CODEC_ID_NONE) st->codec->codec_id = codec_get_bmp_id(st->codec->codec_tag);
+
+ st->codec->width = s[i].width;
+ st->codec->height = s[i].height;
+ st->codec->sample_aspect_ratio.num = s[i].sample_width;
+ st->codec->sample_aspect_ratio.den = s[i].sample_height;
+ break;
+ }
+ if (st->codec->codec_id == CODEC_ID_NONE) av_log(avf, AV_LOG_ERROR, "Unknown codec?!\n");
+ }
+
+ return 0;
+}
+
+static int nut_read_packet(AVFormatContext * avf, AVPacket * pkt) {
+ NUTContext * priv = avf->priv_data;
+ nut_packet_t pd;
+ int ret;
+
+ ret = nut_read_next_packet(priv->nut, &pd);
+
+ if (ret || av_new_packet(pkt, pd.len) < 0) {
+ if (ret != NUT_ERR_EOF)
+ av_log(avf, AV_LOG_ERROR, " NUT error: %s\n", nut_error(ret));
+ return -1;
+ }
+
+ if (pd.flags & NUT_FLAG_KEY) pkt->flags |= PKT_FLAG_KEY;
+ pkt->pts = pd.pts;
+ pkt->stream_index = pd.stream;
+ pkt->pos = url_ftell(&avf->pb);
+
+ ret = nut_read_frame(priv->nut, &pd.len, pkt->data);
+
+ return ret;
+}
+
+static int nut_read_seek(AVFormatContext * avf, int stream_index, int64_t target_ts, int flags) {
+ NUTContext * priv = avf->priv_data;
+ int active_streams[] = { stream_index, -1 };
+ double time_pos = target_ts * priv->s[stream_index].time_base.nom / (double)priv->s[stream_index].time_base.den;
+
+ if (nut_seek(priv->nut, time_pos, 2*!(flags & AVSEEK_FLAG_BACKWARD), active_streams)) return -1;
+
+ return 0;
+}
+
+static int nut_read_close(AVFormatContext *s) {
+ NUTContext * priv = s->priv_data;
+
+ nut_demuxer_uninit(priv->nut);
+
+ return 0;
+}
+
+AVInputFormat nut_demuxer = {
+ "nut",
+ "nut format",
+ sizeof(NUTContext),
+ nut_probe,
+ nut_read_header,
+ nut_read_packet,
+ nut_read_close,
+ nut_read_seek,
+ .extensions = "nut",
+};
diff --git a/contrib/ffmpeg/libavformat/matroska.c b/contrib/ffmpeg/libavformat/matroska.c
new file mode 100644
index 000000000..0cd119e71
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/matroska.c
@@ -0,0 +1,2767 @@
+/*
+ * Matroska file demuxer (no muxer yet)
+ * 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 matroska.c
+ * Matroska file demuxer
+ * by Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * with a little help from Moritz Bunkus <moritz@bunkus.org>
+ * Specs available on the matroska project page:
+ * http://www.matroska.org/.
+ */
+
+#include "avformat.h"
+/* For codec_get_bmp_id and codec_get_wav_id. */
+#include "riff.h"
+#include "intfloat_readwrite.h"
+
+/* EBML version supported */
+#define EBML_VERSION 1
+
+/* top-level master-IDs */
+#define EBML_ID_HEADER 0x1A45DFA3
+
+/* IDs in the HEADER master */
+#define EBML_ID_EBMLVERSION 0x4286
+#define EBML_ID_EBMLREADVERSION 0x42F7
+#define EBML_ID_EBMLMAXIDLENGTH 0x42F2
+#define EBML_ID_EBMLMAXSIZELENGTH 0x42F3
+#define EBML_ID_DOCTYPE 0x4282
+#define EBML_ID_DOCTYPEVERSION 0x4287
+#define EBML_ID_DOCTYPEREADVERSION 0x4285
+
+/* general EBML types */
+#define EBML_ID_VOID 0xEC
+
+/*
+ * Matroska element IDs. max. 32-bit.
+ */
+
+/* toplevel segment */
+#define MATROSKA_ID_SEGMENT 0x18538067
+
+/* matroska top-level master IDs */
+#define MATROSKA_ID_INFO 0x1549A966
+#define MATROSKA_ID_TRACKS 0x1654AE6B
+#define MATROSKA_ID_CUES 0x1C53BB6B
+#define MATROSKA_ID_TAGS 0x1254C367
+#define MATROSKA_ID_SEEKHEAD 0x114D9B74
+#define MATROSKA_ID_CLUSTER 0x1F43B675
+
+/* IDs in the info master */
+#define MATROSKA_ID_TIMECODESCALE 0x2AD7B1
+#define MATROSKA_ID_DURATION 0x4489
+#define MATROSKA_ID_TITLE 0x7BA9
+#define MATROSKA_ID_WRITINGAPP 0x5741
+#define MATROSKA_ID_MUXINGAPP 0x4D80
+#define MATROSKA_ID_DATEUTC 0x4461
+
+/* ID in the tracks master */
+#define MATROSKA_ID_TRACKENTRY 0xAE
+
+/* IDs in the trackentry master */
+#define MATROSKA_ID_TRACKNUMBER 0xD7
+#define MATROSKA_ID_TRACKUID 0x73C5
+#define MATROSKA_ID_TRACKTYPE 0x83
+#define MATROSKA_ID_TRACKAUDIO 0xE1
+#define MATROSKA_ID_TRACKVIDEO 0xE0
+#define MATROSKA_ID_CODECID 0x86
+#define MATROSKA_ID_CODECPRIVATE 0x63A2
+#define MATROSKA_ID_CODECNAME 0x258688
+#define MATROSKA_ID_CODECINFOURL 0x3B4040
+#define MATROSKA_ID_CODECDOWNLOADURL 0x26B240
+#define MATROSKA_ID_TRACKNAME 0x536E
+#define MATROSKA_ID_TRACKLANGUAGE 0x22B59C
+#define MATROSKA_ID_TRACKFLAGENABLED 0xB9
+#define MATROSKA_ID_TRACKFLAGDEFAULT 0x88
+#define MATROSKA_ID_TRACKFLAGLACING 0x9C
+#define MATROSKA_ID_TRACKMINCACHE 0x6DE7
+#define MATROSKA_ID_TRACKMAXCACHE 0x6DF8
+#define MATROSKA_ID_TRACKDEFAULTDURATION 0x23E383
+
+/* IDs in the trackvideo master */
+#define MATROSKA_ID_VIDEOFRAMERATE 0x2383E3
+#define MATROSKA_ID_VIDEODISPLAYWIDTH 0x54B0
+#define MATROSKA_ID_VIDEODISPLAYHEIGHT 0x54BA
+#define MATROSKA_ID_VIDEOPIXELWIDTH 0xB0
+#define MATROSKA_ID_VIDEOPIXELHEIGHT 0xBA
+#define MATROSKA_ID_VIDEOFLAGINTERLACED 0x9A
+#define MATROSKA_ID_VIDEOSTEREOMODE 0x53B9
+#define MATROSKA_ID_VIDEOASPECTRATIO 0x54B3
+#define MATROSKA_ID_VIDEOCOLOURSPACE 0x2EB524
+
+/* IDs in the trackaudio master */
+#define MATROSKA_ID_AUDIOSAMPLINGFREQ 0xB5
+#define MATROSKA_ID_AUDIOOUTSAMPLINGFREQ 0x78B5
+
+#define MATROSKA_ID_AUDIOBITDEPTH 0x6264
+#define MATROSKA_ID_AUDIOCHANNELS 0x9F
+
+/* ID in the cues master */
+#define MATROSKA_ID_POINTENTRY 0xBB
+
+/* IDs in the pointentry master */
+#define MATROSKA_ID_CUETIME 0xB3
+#define MATROSKA_ID_CUETRACKPOSITION 0xB7
+
+/* IDs in the cuetrackposition master */
+#define MATROSKA_ID_CUETRACK 0xF7
+#define MATROSKA_ID_CUECLUSTERPOSITION 0xF1
+
+/* IDs in the tags master */
+/* TODO */
+
+/* IDs in the seekhead master */
+#define MATROSKA_ID_SEEKENTRY 0x4DBB
+
+/* IDs in the seekpoint master */
+#define MATROSKA_ID_SEEKID 0x53AB
+#define MATROSKA_ID_SEEKPOSITION 0x53AC
+
+/* IDs in the cluster master */
+#define MATROSKA_ID_CLUSTERTIMECODE 0xE7
+#define MATROSKA_ID_BLOCKGROUP 0xA0
+
+/* IDs in the blockgroup master */
+#define MATROSKA_ID_BLOCK 0xA1
+#define MATROSKA_ID_BLOCKDURATION 0x9B
+#define MATROSKA_ID_BLOCKREFERENCE 0xFB
+
+typedef enum {
+ MATROSKA_TRACK_TYPE_VIDEO = 0x1,
+ MATROSKA_TRACK_TYPE_AUDIO = 0x2,
+ MATROSKA_TRACK_TYPE_COMPLEX = 0x3,
+ MATROSKA_TRACK_TYPE_LOGO = 0x10,
+ MATROSKA_TRACK_TYPE_SUBTITLE = 0x11,
+ MATROSKA_TRACK_TYPE_CONTROL = 0x20,
+} MatroskaTrackType;
+
+typedef enum {
+ MATROSKA_EYE_MODE_MONO = 0x0,
+ MATROSKA_EYE_MODE_RIGHT = 0x1,
+ MATROSKA_EYE_MODE_LEFT = 0x2,
+ MATROSKA_EYE_MODE_BOTH = 0x3,
+} MatroskaEyeMode;
+
+typedef enum {
+ MATROSKA_ASPECT_RATIO_MODE_FREE = 0x0,
+ MATROSKA_ASPECT_RATIO_MODE_KEEP = 0x1,
+ MATROSKA_ASPECT_RATIO_MODE_FIXED = 0x2,
+} MatroskaAspectRatioMode;
+
+/*
+ * These aren't in any way "matroska-form" things,
+ * it's just something I use in the muxer/demuxer.
+ */
+
+typedef enum {
+ MATROSKA_TRACK_ENABLED = (1<<0),
+ MATROSKA_TRACK_DEFAULT = (1<<1),
+ MATROSKA_TRACK_LACING = (1<<2),
+ MATROSKA_TRACK_REAL_V = (1<<4),
+ MATROSKA_TRACK_SHIFT = (1<<16)
+} MatroskaTrackFlags;
+
+typedef enum {
+ MATROSKA_VIDEOTRACK_INTERLACED = (MATROSKA_TRACK_SHIFT<<0)
+} MatroskaVideoTrackFlags;
+
+/*
+ * Matroska Codec IDs. Strings.
+ */
+
+typedef struct CodecTags{
+ const char *str;
+ enum CodecID id;
+}CodecTags;
+
+#define MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC "V_MS/VFW/FOURCC"
+#define MATROSKA_CODEC_ID_AUDIO_ACM "A_MS/ACM"
+
+static CodecTags codec_tags[]={
+// {"V_MS/VFW/FOURCC" , CODEC_ID_NONE},
+ {"V_UNCOMPRESSED" , CODEC_ID_RAWVIDEO},
+ {"V_MPEG4/ISO/SP" , CODEC_ID_MPEG4},
+ {"V_MPEG4/ISO/ASP" , CODEC_ID_MPEG4},
+ {"V_MPEG4/ISO/AP" , CODEC_ID_MPEG4},
+ {"V_MPEG4/ISO/AVC" , CODEC_ID_H264},
+ {"V_MPEG4/MS/V3" , CODEC_ID_MSMPEG4V3},
+ {"V_MPEG1" , CODEC_ID_MPEG1VIDEO},
+ {"V_MPEG2" , CODEC_ID_MPEG2VIDEO},
+ {"V_MJPEG" , CODEC_ID_MJPEG},
+ {"V_REAL/RV10" , CODEC_ID_RV10},
+ {"V_REAL/RV20" , CODEC_ID_RV20},
+ {"V_REAL/RV30" , CODEC_ID_RV30},
+ {"V_REAL/RV40" , CODEC_ID_RV40},
+/* TODO: Real/Quicktime */
+
+// {"A_MS/ACM" , CODEC_ID_NONE},
+ {"A_MPEG/L1" , CODEC_ID_MP3},
+ {"A_MPEG/L2" , CODEC_ID_MP3},
+ {"A_MPEG/L3" , CODEC_ID_MP3},
+ {"A_PCM/INT/BIG" , CODEC_ID_PCM_U16BE},
+ {"A_PCM/INT/LIT" , CODEC_ID_PCM_U16LE},
+// {"A_PCM/FLOAT/IEEE" , CODEC_ID_NONE},
+ {"A_AC3" , CODEC_ID_AC3},
+ {"A_DTS" , CODEC_ID_DTS},
+ {"A_VORBIS" , CODEC_ID_VORBIS},
+ {"A_AAC" , CODEC_ID_AAC},
+ {"A_FLAC" , CODEC_ID_FLAC},
+ {"A_WAVPACK4" , CODEC_ID_WAVPACK},
+ {"A_TTA1" , CODEC_ID_TTA},
+ {NULL , CODEC_ID_NONE}
+/* TODO: AC3-9/10 (?), Real, Musepack, Quicktime */
+};
+
+/* max. depth in the EBML tree structure */
+#define EBML_MAX_DEPTH 16
+
+typedef struct Track {
+ MatroskaTrackType type;
+
+ /* Unique track number and track ID. stream_index is the index that
+ * the calling app uses for this track. */
+ uint32_t num,
+ uid,
+ stream_index;
+
+ char *name,
+ *language;
+
+ char *codec_id,
+ *codec_name;
+
+ unsigned char *codec_priv;
+ int codec_priv_size;
+
+ int64_t default_duration;
+ MatroskaTrackFlags flags;
+} MatroskaTrack;
+
+typedef struct MatroskaVideoTrack {
+ MatroskaTrack track;
+
+ int pixel_width,
+ pixel_height,
+ display_width,
+ display_height;
+
+ uint32_t fourcc;
+
+ MatroskaAspectRatioMode ar_mode;
+ MatroskaEyeMode eye_mode;
+
+ //..
+} MatroskaVideoTrack;
+
+typedef struct MatroskaAudioTrack {
+ MatroskaTrack track;
+
+ int channels,
+ bitdepth,
+ internal_samplerate,
+ samplerate;
+ //..
+} MatroskaAudioTrack;
+
+typedef struct MatroskaSubtitleTrack {
+ MatroskaTrack track;
+
+ //..
+} MatroskaSubtitleTrack;
+
+typedef struct MatroskaLevel {
+ uint64_t start, length;
+} MatroskaLevel;
+
+typedef struct MatroskaDemuxIndex {
+ uint64_t pos; /* of the corresponding *cluster*! */
+ uint16_t track; /* reference to 'num' */
+ uint64_t time; /* in nanoseconds */
+} MatroskaDemuxIndex;
+
+typedef struct MatroskaDemuxContext {
+ AVFormatContext *ctx;
+
+ /* ebml stuff */
+ int num_levels;
+ MatroskaLevel levels[EBML_MAX_DEPTH];
+ int level_up;
+
+ /* matroska stuff */
+ char *writing_app,
+ *muxing_app;
+ int64_t created;
+
+ /* timescale in the file */
+ int64_t time_scale;
+
+ /* position (time, ns) */
+ int64_t pos;
+
+ /* num_streams is the number of streams that av_new_stream() was called
+ * for ( = that are available to the calling program). */
+ int num_tracks, num_streams;
+ MatroskaTrack *tracks[MAX_STREAMS];
+
+ /* cache for ID peeking */
+ uint32_t peek_id;
+
+ /* byte position of the segment inside the stream */
+ offset_t segment_start;
+
+ /* The packet queue. */
+ AVPacket **packets;
+ int num_packets;
+
+ /* have we already parse metadata/cues/clusters? */
+ int metadata_parsed,
+ index_parsed,
+ done;
+
+ /* The index for seeking. */
+ int num_indexes;
+ MatroskaDemuxIndex *index;
+} MatroskaDemuxContext;
+
+/*
+ * The first few functions handle EBML file parsing. The rest
+ * is the document interpretation. Matroska really just is a
+ * EBML file.
+ */
+
+/*
+ * Return: the amount of levels in the hierarchy that the
+ * current element lies higher than the previous one.
+ * The opposite isn't done - that's auto-done using master
+ * element reading.
+ */
+
+static int
+ebml_read_element_level_up (MatroskaDemuxContext *matroska)
+{
+ ByteIOContext *pb = &matroska->ctx->pb;
+ offset_t pos = url_ftell(pb);
+ int num = 0;
+
+ while (matroska->num_levels > 0) {
+ MatroskaLevel *level = &matroska->levels[matroska->num_levels - 1];
+
+ if (pos >= level->start + level->length) {
+ matroska->num_levels--;
+ num++;
+ } else {
+ break;
+ }
+ }
+
+ return num;
+}
+
+/*
+ * Read: an "EBML number", which is defined as a variable-length
+ * array of bytes. The first byte indicates the length by giving a
+ * number of 0-bits followed by a one. The position of the first
+ * "one" bit inside the first byte indicates the length of this
+ * number.
+ * Returns: num. of bytes read. < 0 on error.
+ */
+
+static int
+ebml_read_num (MatroskaDemuxContext *matroska,
+ int max_size,
+ uint64_t *number)
+{
+ ByteIOContext *pb = &matroska->ctx->pb;
+ int len_mask = 0x80, read = 1, n = 1;
+ int64_t total = 0;
+
+ /* the first byte tells us the length in bytes - get_byte() can normally
+ * return 0, but since that's not a valid first ebmlID byte, we can
+ * use it safely here to catch EOS. */
+ if (!(total = get_byte(pb))) {
+ /* we might encounter EOS here */
+ if (!url_feof(pb)) {
+ offset_t pos = url_ftell(pb);
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Read error at pos. %"PRIu64" (0x%"PRIx64")\n",
+ pos, pos);
+ }
+ return AVERROR_IO; /* EOS or actual I/O error */
+ }
+
+ /* get the length of the EBML number */
+ while (read <= max_size && !(total & len_mask)) {
+ read++;
+ len_mask >>= 1;
+ }
+ if (read > max_size) {
+ offset_t pos = url_ftell(pb) - 1;
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Invalid EBML number size tag 0x%02x at pos %"PRIu64" (0x%"PRIx64")\n",
+ (uint8_t) total, pos, pos);
+ return AVERROR_INVALIDDATA;
+ }
+
+ /* read out length */
+ total &= ~len_mask;
+ while (n++ < read)
+ total = (total << 8) | get_byte(pb);
+
+ *number = total;
+
+ return read;
+}
+
+/*
+ * Read: the element content data ID.
+ * Return: the number of bytes read or < 0 on error.
+ */
+
+static int
+ebml_read_element_id (MatroskaDemuxContext *matroska,
+ uint32_t *id,
+ int *level_up)
+{
+ int read;
+ uint64_t total;
+
+ /* if we re-call this, use our cached ID */
+ if (matroska->peek_id != 0) {
+ if (level_up)
+ *level_up = 0;
+ *id = matroska->peek_id;
+ return 0;
+ }
+
+ /* read out the "EBML number", include tag in ID */
+ if ((read = ebml_read_num(matroska, 4, &total)) < 0)
+ return read;
+ *id = matroska->peek_id = total | (1 << (read * 7));
+
+ /* level tracking */
+ if (level_up)
+ *level_up = ebml_read_element_level_up(matroska);
+
+ return read;
+}
+
+/*
+ * Read: element content length.
+ * Return: the number of bytes read or < 0 on error.
+ */
+
+static int
+ebml_read_element_length (MatroskaDemuxContext *matroska,
+ uint64_t *length)
+{
+ /* clear cache since we're now beyond that data point */
+ matroska->peek_id = 0;
+
+ /* read out the "EBML number", include tag in ID */
+ return ebml_read_num(matroska, 8, length);
+}
+
+/*
+ * Return: the ID of the next element, or 0 on error.
+ * Level_up contains the amount of levels that this
+ * next element lies higher than the previous one.
+ */
+
+static uint32_t
+ebml_peek_id (MatroskaDemuxContext *matroska,
+ int *level_up)
+{
+ uint32_t id;
+
+ assert(level_up != NULL);
+
+ if (ebml_read_element_id(matroska, &id, level_up) < 0)
+ return 0;
+
+ return id;
+}
+
+/*
+ * Seek to a given offset.
+ * 0 is success, -1 is failure.
+ */
+
+static int
+ebml_read_seek (MatroskaDemuxContext *matroska,
+ offset_t offset)
+{
+ ByteIOContext *pb = &matroska->ctx->pb;
+
+ /* clear ID cache, if any */
+ matroska->peek_id = 0;
+
+ return (url_fseek(pb, offset, SEEK_SET) == offset) ? 0 : -1;
+}
+
+/*
+ * Skip the next element.
+ * 0 is success, -1 is failure.
+ */
+
+static int
+ebml_read_skip (MatroskaDemuxContext *matroska)
+{
+ ByteIOContext *pb = &matroska->ctx->pb;
+ uint32_t id;
+ uint64_t length;
+ int res;
+
+ if ((res = ebml_read_element_id(matroska, &id, NULL)) < 0 ||
+ (res = ebml_read_element_length(matroska, &length)) < 0)
+ return res;
+
+ url_fskip(pb, length);
+
+ return 0;
+}
+
+/*
+ * Read the next element as an unsigned int.
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_uint (MatroskaDemuxContext *matroska,
+ uint32_t *id,
+ uint64_t *num)
+{
+ ByteIOContext *pb = &matroska->ctx->pb;
+ int n = 0, size, res;
+ uint64_t rlength;
+
+ if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
+ (res = ebml_read_element_length(matroska, &rlength)) < 0)
+ return res;
+ size = rlength;
+ if (size < 1 || size > 8) {
+ offset_t pos = url_ftell(pb);
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Invalid uint element size %d at position %"PRId64" (0x%"PRIx64")\n",
+ size, pos, pos);
+ return AVERROR_INVALIDDATA;
+ }
+
+ /* big-endian ordening; build up number */
+ *num = 0;
+ while (n++ < size)
+ *num = (*num << 8) | get_byte(pb);
+
+ return 0;
+}
+
+/*
+ * Read the next element as a signed int.
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_sint (MatroskaDemuxContext *matroska,
+ uint32_t *id,
+ int64_t *num)
+{
+ ByteIOContext *pb = &matroska->ctx->pb;
+ int size, n = 1, negative = 0, res;
+ uint64_t rlength;
+
+ if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
+ (res = ebml_read_element_length(matroska, &rlength)) < 0)
+ return res;
+ size = rlength;
+ if (size < 1 || size > 8) {
+ offset_t pos = url_ftell(pb);
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Invalid sint element size %d at position %"PRId64" (0x%"PRIx64")\n",
+ size, pos, pos);
+ return AVERROR_INVALIDDATA;
+ }
+ if ((*num = get_byte(pb)) & 0x80) {
+ negative = 1;
+ *num &= ~0x80;
+ }
+ *num = 0;
+ while (n++ < size)
+ *num = (*num << 8) | get_byte(pb);
+
+ /* make signed */
+ if (negative)
+ *num = *num - (1LL << ((8 * size) - 1));
+
+ return 0;
+}
+
+/*
+ * Read the next element as a float.
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_float (MatroskaDemuxContext *matroska,
+ uint32_t *id,
+ double *num)
+{
+ ByteIOContext *pb = &matroska->ctx->pb;
+ int size, res;
+ uint64_t rlength;
+
+ if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
+ (res = ebml_read_element_length(matroska, &rlength)) < 0)
+ return res;
+ size = rlength;
+
+ if (size == 4) {
+ *num= av_int2flt(get_be32(pb));
+ } else if(size==8){
+ *num= av_int2dbl(get_be64(pb));
+ } else{
+ offset_t pos = url_ftell(pb);
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Invalid float element size %d at position %"PRIu64" (0x%"PRIx64")\n",
+ size, pos, pos);
+ return AVERROR_INVALIDDATA;
+ }
+
+ return 0;
+}
+
+/*
+ * Read the next element as an ASCII string.
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_ascii (MatroskaDemuxContext *matroska,
+ uint32_t *id,
+ char **str)
+{
+ ByteIOContext *pb = &matroska->ctx->pb;
+ int size, res;
+ uint64_t rlength;
+
+ if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
+ (res = ebml_read_element_length(matroska, &rlength)) < 0)
+ return res;
+ size = rlength;
+
+ /* ebml strings are usually not 0-terminated, so we allocate one
+ * byte more, read the string and NULL-terminate it ourselves. */
+ if (size < 0 || !(*str = av_malloc(size + 1))) {
+ av_log(matroska->ctx, AV_LOG_ERROR, "Memory allocation failed\n");
+ return AVERROR_NOMEM;
+ }
+ if (get_buffer(pb, (uint8_t *) *str, size) != size) {
+ offset_t pos = url_ftell(pb);
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Read error at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos);
+ return AVERROR_IO;
+ }
+ (*str)[size] = '\0';
+
+ return 0;
+}
+
+/*
+ * Read the next element as a UTF-8 string.
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_utf8 (MatroskaDemuxContext *matroska,
+ uint32_t *id,
+ char **str)
+{
+ return ebml_read_ascii(matroska, id, str);
+}
+
+/*
+ * Read the next element as a date (nanoseconds since 1/1/2000).
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_date (MatroskaDemuxContext *matroska,
+ uint32_t *id,
+ int64_t *date)
+{
+ return ebml_read_sint(matroska, id, date);
+}
+
+/*
+ * Read the next element, but only the header. The contents
+ * are supposed to be sub-elements which can be read separately.
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_master (MatroskaDemuxContext *matroska,
+ uint32_t *id)
+{
+ ByteIOContext *pb = &matroska->ctx->pb;
+ uint64_t length;
+ MatroskaLevel *level;
+ int res;
+
+ if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
+ (res = ebml_read_element_length(matroska, &length)) < 0)
+ return res;
+
+ /* protect... (Heaven forbids that the '>' is true) */
+ if (matroska->num_levels >= EBML_MAX_DEPTH) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "File moves beyond max. allowed depth (%d)\n", EBML_MAX_DEPTH);
+ return AVERROR_NOTSUPP;
+ }
+
+ /* remember level */
+ level = &matroska->levels[matroska->num_levels++];
+ level->start = url_ftell(pb);
+ level->length = length;
+
+ return 0;
+}
+
+/*
+ * Read the next element as binary data.
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_binary (MatroskaDemuxContext *matroska,
+ uint32_t *id,
+ uint8_t **binary,
+ int *size)
+{
+ ByteIOContext *pb = &matroska->ctx->pb;
+ uint64_t rlength;
+ int res;
+
+ if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 ||
+ (res = ebml_read_element_length(matroska, &rlength)) < 0)
+ return res;
+ *size = rlength;
+
+ if (!(*binary = av_malloc(*size))) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Memory allocation error\n");
+ return AVERROR_NOMEM;
+ }
+
+ if (get_buffer(pb, *binary, *size) != *size) {
+ offset_t pos = url_ftell(pb);
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Read error at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos);
+ return AVERROR_IO;
+ }
+
+ return 0;
+}
+
+/*
+ * Read signed/unsigned "EBML" numbers.
+ * Return: number of bytes processed, < 0 on error.
+ * XXX: use ebml_read_num().
+ */
+
+static int
+matroska_ebmlnum_uint (uint8_t *data,
+ uint32_t size,
+ uint64_t *num)
+{
+ int len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
+ uint64_t total;
+
+ if (size <= 0)
+ return AVERROR_INVALIDDATA;
+
+ total = data[0];
+ while (read <= 8 && !(total & len_mask)) {
+ read++;
+ len_mask >>= 1;
+ }
+ if (read > 8)
+ return AVERROR_INVALIDDATA;
+
+ if ((total &= (len_mask - 1)) == len_mask - 1)
+ num_ffs++;
+ if (size < read)
+ return AVERROR_INVALIDDATA;
+ while (n < read) {
+ if (data[n] == 0xff)
+ num_ffs++;
+ total = (total << 8) | data[n];
+ n++;
+ }
+
+ if (read == num_ffs)
+ *num = (uint64_t)-1;
+ else
+ *num = total;
+
+ return read;
+}
+
+/*
+ * Same as above, but signed.
+ */
+
+static int
+matroska_ebmlnum_sint (uint8_t *data,
+ uint32_t size,
+ int64_t *num)
+{
+ uint64_t unum;
+ int res;
+
+ /* read as unsigned number first */
+ if ((res = matroska_ebmlnum_uint(data, size, &unum)) < 0)
+ return res;
+
+ /* make signed (weird way) */
+ if (unum == (uint64_t)-1)
+ *num = INT64_MAX;
+ else
+ *num = unum - ((1LL << ((7 * res) - 1)) - 1);
+
+ return res;
+}
+
+/*
+ * Read an EBML header.
+ * 0 is success, < 0 is failure.
+ */
+
+static int
+ebml_read_header (MatroskaDemuxContext *matroska,
+ char **doctype,
+ int *version)
+{
+ uint32_t id;
+ int level_up, res = 0;
+
+ /* default init */
+ if (doctype)
+ *doctype = NULL;
+ if (version)
+ *version = 1;
+
+ if (!(id = ebml_peek_id(matroska, &level_up)) ||
+ level_up != 0 || id != EBML_ID_HEADER) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "This is not an EBML file (id=0x%x/0x%x)\n", id, EBML_ID_HEADER);
+ return AVERROR_INVALIDDATA;
+ }
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ return res;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &level_up)))
+ return AVERROR_IO;
+
+ /* end-of-header */
+ if (level_up)
+ break;
+
+ switch (id) {
+ /* is our read version uptodate? */
+ case EBML_ID_EBMLREADVERSION: {
+ uint64_t num;
+
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ return res;
+ if (num > EBML_VERSION) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "EBML version %"PRIu64" (> %d) is not supported\n",
+ num, EBML_VERSION);
+ return AVERROR_INVALIDDATA;
+ }
+ break;
+ }
+
+ /* we only handle 8 byte lengths at max */
+ case EBML_ID_EBMLMAXSIZELENGTH: {
+ uint64_t num;
+
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ return res;
+ if (num > sizeof(uint64_t)) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Integers of size %"PRIu64" (> %zd) not supported\n",
+ num, sizeof(uint64_t));
+ return AVERROR_INVALIDDATA;
+ }
+ break;
+ }
+
+ /* we handle 4 byte IDs at max */
+ case EBML_ID_EBMLMAXIDLENGTH: {
+ uint64_t num;
+
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ return res;
+ if (num > sizeof(uint32_t)) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "IDs of size %"PRIu64" (> %zu) not supported\n",
+ num, sizeof(uint32_t));
+ return AVERROR_INVALIDDATA;
+ }
+ break;
+ }
+
+ case EBML_ID_DOCTYPE: {
+ char *text;
+
+ if ((res = ebml_read_ascii(matroska, &id, &text)) < 0)
+ return res;
+ if (doctype) {
+ if (*doctype)
+ av_free(*doctype);
+ *doctype = text;
+ } else
+ av_free(text);
+ break;
+ }
+
+ case EBML_ID_DOCTYPEREADVERSION: {
+ uint64_t num;
+
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ return res;
+ if (version)
+ *version = num;
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown data type 0x%x in EBML header", id);
+ /* pass-through */
+
+ case EBML_ID_VOID:
+ /* we ignore these two, as they don't tell us anything we
+ * care about */
+ case EBML_ID_EBMLVERSION:
+ case EBML_ID_DOCTYPEVERSION:
+ res = ebml_read_skip (matroska);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Put one packet in an application-supplied AVPacket struct.
+ * Returns 0 on success or -1 on failure.
+ */
+
+static int
+matroska_deliver_packet (MatroskaDemuxContext *matroska,
+ AVPacket *pkt)
+{
+ if (matroska->num_packets > 0) {
+ memcpy(pkt, matroska->packets[0], sizeof(AVPacket));
+ av_free(matroska->packets[0]);
+ if (matroska->num_packets > 1) {
+ memmove(&matroska->packets[0], &matroska->packets[1],
+ (matroska->num_packets - 1) * sizeof(AVPacket *));
+ matroska->packets =
+ av_realloc(matroska->packets, (matroska->num_packets - 1) *
+ sizeof(AVPacket *));
+ } else {
+ av_freep(&matroska->packets);
+ }
+ matroska->num_packets--;
+ return 0;
+ }
+
+ return -1;
+}
+
+/*
+ * Put a packet into our internal queue. Will be delivered to the
+ * user/application during the next get_packet() call.
+ */
+
+static void
+matroska_queue_packet (MatroskaDemuxContext *matroska,
+ AVPacket *pkt)
+{
+ matroska->packets =
+ av_realloc(matroska->packets, (matroska->num_packets + 1) *
+ sizeof(AVPacket *));
+ matroska->packets[matroska->num_packets] = pkt;
+ matroska->num_packets++;
+}
+
+/*
+ * Autodetecting...
+ */
+
+static int
+matroska_probe (AVProbeData *p)
+{
+ uint64_t total = 0;
+ int len_mask = 0x80, size = 1, n = 1;
+ uint8_t probe_data[] = { 'm', 'a', 't', 'r', 'o', 's', 'k', 'a' };
+
+ if (p->buf_size < 5)
+ return 0;
+
+ /* ebml header? */
+ if ((p->buf[0] << 24 | p->buf[1] << 16 |
+ p->buf[2] << 8 | p->buf[3]) != EBML_ID_HEADER)
+ return 0;
+
+ /* length of header */
+ total = p->buf[4];
+ while (size <= 8 && !(total & len_mask)) {
+ size++;
+ len_mask >>= 1;
+ }
+ if (size > 8)
+ return 0;
+ total &= (len_mask - 1);
+ while (n < size)
+ total = (total << 8) | p->buf[4 + n++];
+
+ /* does the probe data contain the whole header? */
+ if (p->buf_size < 4 + size + total)
+ return 0;
+
+ /* the header must contain the document type 'matroska'. For now,
+ * we don't parse the whole header but simply check for the
+ * availability of that array of characters inside the header.
+ * Not fully fool-proof, but good enough. */
+ for (n = 4 + size; n < 4 + size + total - sizeof(probe_data); n++)
+ if (!memcmp (&p->buf[n], probe_data, sizeof(probe_data)))
+ return AVPROBE_SCORE_MAX;
+
+ return 0;
+}
+
+/*
+ * From here on, it's all XML-style DTD stuff... Needs no comments.
+ */
+
+static int
+matroska_parse_info (MatroskaDemuxContext *matroska)
+{
+ int res = 0;
+ uint32_t id;
+
+ av_log(matroska->ctx, AV_LOG_DEBUG, "Parsing info...\n");
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR_IO;
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* cluster timecode */
+ case MATROSKA_ID_TIMECODESCALE: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ matroska->time_scale = num;
+ break;
+ }
+
+ case MATROSKA_ID_DURATION: {
+ double num;
+ if ((res = ebml_read_float(matroska, &id, &num)) < 0)
+ break;
+ matroska->ctx->duration = num * matroska->time_scale * 1000 / AV_TIME_BASE;
+ break;
+ }
+
+ case MATROSKA_ID_TITLE: {
+ char *text;
+ if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
+ break;
+ strncpy(matroska->ctx->title, text,
+ sizeof(matroska->ctx->title)-1);
+ av_free(text);
+ break;
+ }
+
+ case MATROSKA_ID_WRITINGAPP: {
+ char *text;
+ if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
+ break;
+ matroska->writing_app = text;
+ break;
+ }
+
+ case MATROSKA_ID_MUXINGAPP: {
+ char *text;
+ if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
+ break;
+ matroska->muxing_app = text;
+ break;
+ }
+
+ case MATROSKA_ID_DATEUTC: {
+ int64_t time;
+ if ((res = ebml_read_date(matroska, &id, &time)) < 0)
+ break;
+ matroska->created = time;
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown entry 0x%x in info header\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ return res;
+}
+
+static int
+matroska_add_stream (MatroskaDemuxContext *matroska)
+{
+ int res = 0;
+ uint32_t id;
+ MatroskaTrack *track;
+
+ av_log(matroska->ctx, AV_LOG_DEBUG, "parsing track, adding stream..,\n");
+
+ /* Allocate a generic track. As soon as we know its type we'll realloc. */
+ track = av_mallocz(sizeof(MatroskaTrack));
+ matroska->num_tracks++;
+
+ /* start with the master */
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ return res;
+
+ /* try reading the trackentry headers */
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR_IO;
+ break;
+ } else if (matroska->level_up > 0) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* track number (unique stream ID) */
+ case MATROSKA_ID_TRACKNUMBER: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ track->num = num;
+ break;
+ }
+
+ /* track UID (unique identifier) */
+ case MATROSKA_ID_TRACKUID: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ track->uid = num;
+ break;
+ }
+
+ /* track type (video, audio, combined, subtitle, etc.) */
+ case MATROSKA_ID_TRACKTYPE: {
+ uint64_t num;
+ if (track->type != 0) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "More than one tracktype in an entry - skip\n");
+ break;
+ }
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ track->type = num;
+
+ /* ok, so we're actually going to reallocate this thing */
+ switch (track->type) {
+ case MATROSKA_TRACK_TYPE_VIDEO:
+ track = (MatroskaTrack *)
+ av_realloc(track, sizeof(MatroskaVideoTrack));
+ break;
+ case MATROSKA_TRACK_TYPE_AUDIO:
+ track = (MatroskaTrack *)
+ av_realloc(track, sizeof(MatroskaAudioTrack));
+ ((MatroskaAudioTrack *)track)->channels = 1;
+ ((MatroskaAudioTrack *)track)->samplerate = 8000;
+ break;
+ case MATROSKA_TRACK_TYPE_SUBTITLE:
+ track = (MatroskaTrack *)
+ av_realloc(track, sizeof(MatroskaSubtitleTrack));
+ break;
+ case MATROSKA_TRACK_TYPE_COMPLEX:
+ case MATROSKA_TRACK_TYPE_LOGO:
+ case MATROSKA_TRACK_TYPE_CONTROL:
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown or unsupported track type 0x%x\n",
+ track->type);
+ track->type = 0;
+ break;
+ }
+ matroska->tracks[matroska->num_tracks - 1] = track;
+ break;
+ }
+
+ /* tracktype specific stuff for video */
+ case MATROSKA_ID_TRACKVIDEO: {
+ MatroskaVideoTrack *videotrack;
+ if (track->type != MATROSKA_TRACK_TYPE_VIDEO) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "video data in non-video track - ignoring\n");
+ res = AVERROR_INVALIDDATA;
+ break;
+ } else if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ videotrack = (MatroskaVideoTrack *)track;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR_IO;
+ break;
+ } else if (matroska->level_up > 0) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* fixme, this should be one-up, but I get it here */
+ case MATROSKA_ID_TRACKDEFAULTDURATION: {
+ uint64_t num;
+ if ((res = ebml_read_uint (matroska, &id,
+ &num)) < 0)
+ break;
+ track->default_duration = num;
+ break;
+ }
+
+ /* video framerate */
+ case MATROSKA_ID_VIDEOFRAMERATE: {
+ double num;
+ if ((res = ebml_read_float(matroska, &id,
+ &num)) < 0)
+ break;
+ track->default_duration = 1000000000 * (1. / num);
+ break;
+ }
+
+ /* width of the size to display the video at */
+ case MATROSKA_ID_VIDEODISPLAYWIDTH: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ videotrack->display_width = num;
+ break;
+ }
+
+ /* height of the size to display the video at */
+ case MATROSKA_ID_VIDEODISPLAYHEIGHT: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ videotrack->display_height = num;
+ break;
+ }
+
+ /* width of the video in the file */
+ case MATROSKA_ID_VIDEOPIXELWIDTH: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ videotrack->pixel_width = num;
+ break;
+ }
+
+ /* height of the video in the file */
+ case MATROSKA_ID_VIDEOPIXELHEIGHT: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ videotrack->pixel_height = num;
+ break;
+ }
+
+ /* whether the video is interlaced */
+ case MATROSKA_ID_VIDEOFLAGINTERLACED: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ if (num)
+ track->flags |=
+ MATROSKA_VIDEOTRACK_INTERLACED;
+ else
+ track->flags &=
+ ~MATROSKA_VIDEOTRACK_INTERLACED;
+ break;
+ }
+
+ /* stereo mode (whether the video has two streams,
+ * where one is for the left eye and the other for
+ * the right eye, which creates a 3D-like
+ * effect) */
+ case MATROSKA_ID_VIDEOSTEREOMODE: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ if (num != MATROSKA_EYE_MODE_MONO &&
+ num != MATROSKA_EYE_MODE_LEFT &&
+ num != MATROSKA_EYE_MODE_RIGHT &&
+ num != MATROSKA_EYE_MODE_BOTH) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Ignoring unknown eye mode 0x%x\n",
+ (uint32_t) num);
+ break;
+ }
+ videotrack->eye_mode = num;
+ break;
+ }
+
+ /* aspect ratio behaviour */
+ case MATROSKA_ID_VIDEOASPECTRATIO: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ if (num != MATROSKA_ASPECT_RATIO_MODE_FREE &&
+ num != MATROSKA_ASPECT_RATIO_MODE_KEEP &&
+ num != MATROSKA_ASPECT_RATIO_MODE_FIXED) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Ignoring unknown aspect ratio 0x%x\n",
+ (uint32_t) num);
+ break;
+ }
+ videotrack->ar_mode = num;
+ break;
+ }
+
+ /* colourspace (only matters for raw video)
+ * fourcc */
+ case MATROSKA_ID_VIDEOCOLOURSPACE: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ videotrack->fourcc = num;
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown video track header entry "
+ "0x%x - ignoring\n", id);
+ /* pass-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+ break;
+ }
+
+ /* tracktype specific stuff for audio */
+ case MATROSKA_ID_TRACKAUDIO: {
+ MatroskaAudioTrack *audiotrack;
+ if (track->type != MATROSKA_TRACK_TYPE_AUDIO) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "audio data in non-audio track - ignoring\n");
+ res = AVERROR_INVALIDDATA;
+ break;
+ } else if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ audiotrack = (MatroskaAudioTrack *)track;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR_IO;
+ break;
+ } else if (matroska->level_up > 0) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* samplerate */
+ case MATROSKA_ID_AUDIOSAMPLINGFREQ: {
+ double num;
+ if ((res = ebml_read_float(matroska, &id,
+ &num)) < 0)
+ break;
+ audiotrack->internal_samplerate =
+ audiotrack->samplerate = num;
+ break;
+ }
+
+ case MATROSKA_ID_AUDIOOUTSAMPLINGFREQ: {
+ double num;
+ if ((res = ebml_read_float(matroska, &id,
+ &num)) < 0)
+ break;
+ audiotrack->samplerate = num;
+ break;
+ }
+
+ /* bitdepth */
+ case MATROSKA_ID_AUDIOBITDEPTH: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ audiotrack->bitdepth = num;
+ break;
+ }
+
+ /* channels */
+ case MATROSKA_ID_AUDIOCHANNELS: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id,
+ &num)) < 0)
+ break;
+ audiotrack->channels = num;
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown audio track header entry "
+ "0x%x - ignoring\n", id);
+ /* pass-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+ break;
+ }
+
+ /* codec identifier */
+ case MATROSKA_ID_CODECID: {
+ char *text;
+ if ((res = ebml_read_ascii(matroska, &id, &text)) < 0)
+ break;
+ track->codec_id = text;
+ break;
+ }
+
+ /* codec private data */
+ case MATROSKA_ID_CODECPRIVATE: {
+ uint8_t *data;
+ int size;
+ if ((res = ebml_read_binary(matroska, &id, &data, &size) < 0))
+ break;
+ track->codec_priv = data;
+ track->codec_priv_size = size;
+ break;
+ }
+
+ /* name of the codec */
+ case MATROSKA_ID_CODECNAME: {
+ char *text;
+ if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
+ break;
+ track->codec_name = text;
+ break;
+ }
+
+ /* name of this track */
+ case MATROSKA_ID_TRACKNAME: {
+ char *text;
+ if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
+ break;
+ track->name = text;
+ break;
+ }
+
+ /* language (matters for audio/subtitles, mostly) */
+ case MATROSKA_ID_TRACKLANGUAGE: {
+ char *text;
+ if ((res = ebml_read_utf8(matroska, &id, &text)) < 0)
+ break;
+ track->language = text;
+ break;
+ }
+
+ /* whether this is actually used */
+ case MATROSKA_ID_TRACKFLAGENABLED: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ if (num)
+ track->flags |= MATROSKA_TRACK_ENABLED;
+ else
+ track->flags &= ~MATROSKA_TRACK_ENABLED;
+ break;
+ }
+
+ /* whether it's the default for this track type */
+ case MATROSKA_ID_TRACKFLAGDEFAULT: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ if (num)
+ track->flags |= MATROSKA_TRACK_DEFAULT;
+ else
+ track->flags &= ~MATROSKA_TRACK_DEFAULT;
+ break;
+ }
+
+ /* lacing (like MPEG, where blocks don't end/start on frame
+ * boundaries) */
+ case MATROSKA_ID_TRACKFLAGLACING: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ if (num)
+ track->flags |= MATROSKA_TRACK_LACING;
+ else
+ track->flags &= ~MATROSKA_TRACK_LACING;
+ break;
+ }
+
+ /* default length (in time) of one data block in this track */
+ case MATROSKA_ID_TRACKDEFAULTDURATION: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ track->default_duration = num;
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown track header entry 0x%x - ignoring\n", id);
+ /* pass-through */
+
+ case EBML_ID_VOID:
+ /* we ignore these because they're nothing useful. */
+ case MATROSKA_ID_CODECINFOURL:
+ case MATROSKA_ID_CODECDOWNLOADURL:
+ case MATROSKA_ID_TRACKMINCACHE:
+ case MATROSKA_ID_TRACKMAXCACHE:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ return res;
+}
+
+static int
+matroska_parse_tracks (MatroskaDemuxContext *matroska)
+{
+ int res = 0;
+ uint32_t id;
+
+ av_log(matroska->ctx, AV_LOG_DEBUG, "parsing tracks...\n");
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR_IO;
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* one track within the "all-tracks" header */
+ case MATROSKA_ID_TRACKENTRY:
+ res = matroska_add_stream(matroska);
+ break;
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown entry 0x%x in track header\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ return res;
+}
+
+static int
+matroska_parse_index (MatroskaDemuxContext *matroska)
+{
+ int res = 0;
+ uint32_t id;
+ MatroskaDemuxIndex idx;
+
+ av_log(matroska->ctx, AV_LOG_DEBUG, "parsing index...\n");
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR_IO;
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* one single index entry ('point') */
+ case MATROSKA_ID_POINTENTRY:
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+
+ /* in the end, we hope to fill one entry with a
+ * timestamp, a file position and a tracknum */
+ idx.pos = (uint64_t) -1;
+ idx.time = (uint64_t) -1;
+ idx.track = (uint16_t) -1;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR_IO;
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* one single index entry ('point') */
+ case MATROSKA_ID_CUETIME: {
+ uint64_t time;
+ if ((res = ebml_read_uint(matroska, &id,
+ &time)) < 0)
+ break;
+ idx.time = time * matroska->time_scale;
+ break;
+ }
+
+ /* position in the file + track to which it
+ * belongs */
+ case MATROSKA_ID_CUETRACKPOSITION:
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id (matroska,
+ &matroska->level_up))) {
+ res = AVERROR_IO;
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* track number */
+ case MATROSKA_ID_CUETRACK: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska,
+ &id, &num)) < 0)
+ break;
+ idx.track = num;
+ break;
+ }
+
+ /* position in file */
+ case MATROSKA_ID_CUECLUSTERPOSITION: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska,
+ &id, &num)) < 0)
+ break;
+ idx.pos = num;
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown entry 0x%x in "
+ "CuesTrackPositions\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ break;
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown entry 0x%x in cuespoint "
+ "index\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ /* so let's see if we got what we wanted */
+ if (idx.pos != (uint64_t) -1 &&
+ idx.time != (uint64_t) -1 &&
+ idx.track != (uint16_t) -1) {
+ if (matroska->num_indexes % 32 == 0) {
+ /* re-allocate bigger index */
+ matroska->index =
+ av_realloc(matroska->index,
+ (matroska->num_indexes + 32) *
+ sizeof(MatroskaDemuxIndex));
+ }
+ matroska->index[matroska->num_indexes] = idx;
+ matroska->num_indexes++;
+ }
+ break;
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown entry 0x%x in cues header\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ return res;
+}
+
+static int
+matroska_parse_metadata (MatroskaDemuxContext *matroska)
+{
+ int res = 0;
+ uint32_t id;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR_IO;
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* Hm, this is unsupported... */
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown entry 0x%x in metadata header\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ return res;
+}
+
+static int
+matroska_parse_seekhead (MatroskaDemuxContext *matroska)
+{
+ int res = 0;
+ uint32_t id;
+
+ av_log(matroska->ctx, AV_LOG_DEBUG, "parsing seekhead...\n");
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR_IO;
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ case MATROSKA_ID_SEEKENTRY: {
+ uint32_t seek_id = 0, peek_id_cache = 0;
+ uint64_t seek_pos = (uint64_t) -1, t;
+
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR_IO;
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ case MATROSKA_ID_SEEKID:
+ res = ebml_read_uint(matroska, &id, &t);
+ seek_id = t;
+ break;
+
+ case MATROSKA_ID_SEEKPOSITION:
+ res = ebml_read_uint(matroska, &id, &seek_pos);
+ break;
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown seekhead ID 0x%x\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ if (!seek_id || seek_pos == (uint64_t) -1) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Incomplete seekhead entry (0x%x/%"PRIu64")\n",
+ seek_id, seek_pos);
+ break;
+ }
+
+ switch (seek_id) {
+ case MATROSKA_ID_CUES:
+ case MATROSKA_ID_TAGS: {
+ uint32_t level_up = matroska->level_up;
+ offset_t before_pos;
+ uint64_t length;
+ MatroskaLevel level;
+
+ /* remember the peeked ID and the current position */
+ peek_id_cache = matroska->peek_id;
+ before_pos = url_ftell(&matroska->ctx->pb);
+
+ /* seek */
+ if ((res = ebml_read_seek(matroska, seek_pos +
+ matroska->segment_start)) < 0)
+ return res;
+
+ /* we don't want to lose our seekhead level, so we add
+ * a dummy. This is a crude hack. */
+ if (matroska->num_levels == EBML_MAX_DEPTH) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Max EBML element depth (%d) reached, "
+ "cannot parse further.\n", EBML_MAX_DEPTH);
+ return AVERROR_UNKNOWN;
+ }
+
+ level.start = 0;
+ level.length = (uint64_t)-1;
+ matroska->levels[matroska->num_levels] = level;
+ matroska->num_levels++;
+
+ /* check ID */
+ if (!(id = ebml_peek_id (matroska,
+ &matroska->level_up)))
+ goto finish;
+ if (id != seek_id) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "We looked for ID=0x%x but got "
+ "ID=0x%x (pos=%"PRIu64")",
+ seek_id, id, seek_pos +
+ matroska->segment_start);
+ goto finish;
+ }
+
+ /* read master + parse */
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ goto finish;
+ switch (id) {
+ case MATROSKA_ID_CUES:
+ if (!(res = matroska_parse_index(matroska)) ||
+ url_feof(&matroska->ctx->pb)) {
+ matroska->index_parsed = 1;
+ res = 0;
+ }
+ break;
+ case MATROSKA_ID_TAGS:
+ if (!(res = matroska_parse_metadata(matroska)) ||
+ url_feof(&matroska->ctx->pb)) {
+ matroska->metadata_parsed = 1;
+ res = 0;
+ }
+ break;
+ }
+
+ finish:
+ /* remove dummy level */
+ while (matroska->num_levels) {
+ matroska->num_levels--;
+ length =
+ matroska->levels[matroska->num_levels].length;
+ if (length == (uint64_t)-1)
+ break;
+ }
+
+ /* seek back */
+ if ((res = ebml_read_seek(matroska, before_pos)) < 0)
+ return res;
+ matroska->peek_id = peek_id_cache;
+ matroska->level_up = level_up;
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Ignoring seekhead entry for ID=0x%x\n",
+ seek_id);
+ break;
+ }
+
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown seekhead ID 0x%x\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ return res;
+}
+
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
+
+static int
+matroska_aac_profile (char *codec_id)
+{
+ static const char *aac_profiles[] = {
+ "MAIN", "LC", "SSR"
+ };
+ int profile;
+
+ for (profile=0; profile<ARRAY_SIZE(aac_profiles); profile++)
+ if (strstr(codec_id, aac_profiles[profile]))
+ break;
+ return profile + 1;
+}
+
+static int
+matroska_aac_sri (int samplerate)
+{
+ static const int aac_sample_rates[] = {
+ 96000, 88200, 64000, 48000, 44100, 32000,
+ 24000, 22050, 16000, 12000, 11025, 8000,
+ };
+ int sri;
+
+ for (sri=0; sri<ARRAY_SIZE(aac_sample_rates); sri++)
+ if (aac_sample_rates[sri] == samplerate)
+ break;
+ return sri;
+}
+
+static int
+matroska_read_header (AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ MatroskaDemuxContext *matroska = s->priv_data;
+ char *doctype;
+ int version, last_level, res = 0;
+ uint32_t id;
+
+ matroska->ctx = s;
+
+ /* First read the EBML header. */
+ doctype = NULL;
+ if ((res = ebml_read_header(matroska, &doctype, &version)) < 0)
+ return res;
+ if ((doctype == NULL) || strcmp(doctype, "matroska")) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Wrong EBML doctype ('%s' != 'matroska').\n",
+ doctype ? doctype : "(none)");
+ if (doctype)
+ av_free(doctype);
+ return AVERROR_NOFMT;
+ }
+ av_free(doctype);
+ if (version != 1) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "Matroska demuxer version 1 too old for file version %d\n",
+ version);
+ return AVERROR_NOFMT;
+ }
+
+ /* The next thing is a segment. */
+ while (1) {
+ if (!(id = ebml_peek_id(matroska, &last_level)))
+ return AVERROR_IO;
+ if (id == MATROSKA_ID_SEGMENT)
+ break;
+
+ /* oi! */
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Expected a Segment ID (0x%x), but received 0x%x!\n",
+ MATROSKA_ID_SEGMENT, id);
+ if ((res = ebml_read_skip(matroska)) < 0)
+ return res;
+ }
+
+ /* We now have a Matroska segment.
+ * Seeks are from the beginning of the segment,
+ * after the segment ID/length. */
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ return res;
+ matroska->segment_start = url_ftell(&s->pb);
+
+ matroska->time_scale = 1000000;
+ /* we've found our segment, start reading the different contents in here */
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR_IO;
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* stream info */
+ case MATROSKA_ID_INFO: {
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ res = matroska_parse_info(matroska);
+ break;
+ }
+
+ /* track info headers */
+ case MATROSKA_ID_TRACKS: {
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ res = matroska_parse_tracks(matroska);
+ break;
+ }
+
+ /* stream index */
+ case MATROSKA_ID_CUES: {
+ if (!matroska->index_parsed) {
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ res = matroska_parse_index(matroska);
+ } else
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ /* metadata */
+ case MATROSKA_ID_TAGS: {
+ if (!matroska->metadata_parsed) {
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ res = matroska_parse_metadata(matroska);
+ } else
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ /* file index (if seekable, seek to Cues/Tags to parse it) */
+ case MATROSKA_ID_SEEKHEAD: {
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ res = matroska_parse_seekhead(matroska);
+ break;
+ }
+
+ case MATROSKA_ID_CLUSTER: {
+ /* Do not read the master - this will be done in the next
+ * call to matroska_read_packet. */
+ res = 1;
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown matroska file header ID 0x%x\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ /* Have we found a cluster? */
+ if (ebml_peek_id(matroska, NULL) == MATROSKA_ID_CLUSTER) {
+ int i, j;
+ MatroskaTrack *track;
+ AVStream *st;
+
+ for (i = 0; i < matroska->num_tracks; i++) {
+ enum CodecID codec_id = CODEC_ID_NONE;
+ uint8_t *extradata = NULL;
+ int extradata_size = 0;
+ int extradata_offset = 0;
+ track = matroska->tracks[i];
+
+ /* libavformat does not really support subtitles.
+ * Also apply some sanity checks. */
+ if ((track->type == MATROSKA_TRACK_TYPE_SUBTITLE) ||
+ (track->codec_id == NULL))
+ continue;
+
+ for(j=0; codec_tags[j].str; j++){
+ if(!strncmp(codec_tags[j].str, track->codec_id,
+ strlen(codec_tags[j].str))){
+ codec_id= codec_tags[j].id;
+ break;
+ }
+ }
+
+ /* Set the FourCC from the CodecID. */
+ /* This is the MS compatibility mode which stores a
+ * BITMAPINFOHEADER in the CodecPrivate. */
+ if (!strcmp(track->codec_id,
+ MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC) &&
+ (track->codec_priv_size >= 40) &&
+ (track->codec_priv != NULL)) {
+ unsigned char *p;
+
+ /* Offset of biCompression. Stored in LE. */
+ p = (unsigned char *)track->codec_priv + 16;
+ ((MatroskaVideoTrack *)track)->fourcc = (p[3] << 24) |
+ (p[2] << 16) | (p[1] << 8) | p[0];
+ codec_id = codec_get_bmp_id(((MatroskaVideoTrack *)track)->fourcc);
+
+ }
+
+ /* This is the MS compatibility mode which stores a
+ * WAVEFORMATEX in the CodecPrivate. */
+ else if (!strcmp(track->codec_id,
+ MATROSKA_CODEC_ID_AUDIO_ACM) &&
+ (track->codec_priv_size >= 18) &&
+ (track->codec_priv != NULL)) {
+ unsigned char *p;
+ uint16_t tag;
+
+ /* Offset of wFormatTag. Stored in LE. */
+ p = (unsigned char *)track->codec_priv;
+ tag = (p[1] << 8) | p[0];
+ codec_id = codec_get_wav_id(tag);
+
+ }
+
+ else if (codec_id == CODEC_ID_AAC && !track->codec_priv_size) {
+ MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *) track;
+ int profile = matroska_aac_profile(track->codec_id);
+ int sri = matroska_aac_sri(audiotrack->internal_samplerate);
+ extradata = av_malloc(5);
+ if (extradata == NULL)
+ return AVERROR_NOMEM;
+ extradata[0] = (profile << 3) | ((sri&0x0E) >> 1);
+ extradata[1] = ((sri&0x01) << 7) | (audiotrack->channels<<3);
+ if (strstr(track->codec_id, "SBR")) {
+ sri = matroska_aac_sri(audiotrack->samplerate);
+ extradata[2] = 0x56;
+ extradata[3] = 0xE5;
+ extradata[4] = 0x80 | (sri<<3);
+ extradata_size = 5;
+ } else {
+ extradata_size = 2;
+ }
+ }
+
+ else if (codec_id == CODEC_ID_TTA) {
+ MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *) track;
+ ByteIOContext b;
+ extradata_size = 30;
+ extradata = av_mallocz(extradata_size);
+ if (extradata == NULL)
+ return AVERROR_NOMEM;
+ init_put_byte(&b, extradata, extradata_size, 1,
+ NULL, NULL, NULL, NULL);
+ put_buffer(&b, (uint8_t *) "TTA1", 4);
+ put_le16(&b, 1);
+ put_le16(&b, audiotrack->channels);
+ put_le16(&b, audiotrack->bitdepth);
+ put_le32(&b, audiotrack->samplerate);
+ put_le32(&b, matroska->ctx->duration * audiotrack->samplerate);
+ }
+
+ else if (codec_id == CODEC_ID_RV10 || codec_id == CODEC_ID_RV20 ||
+ codec_id == CODEC_ID_RV30 || codec_id == CODEC_ID_RV40) {
+ extradata_offset = 26;
+ track->codec_priv_size -= extradata_offset;
+ track->flags |= MATROSKA_TRACK_REAL_V;
+ }
+
+ if (codec_id == CODEC_ID_NONE) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown/unsupported CodecID %s.\n",
+ track->codec_id);
+ }
+
+ track->stream_index = matroska->num_streams;
+
+ matroska->num_streams++;
+ st = av_new_stream(s, track->stream_index);
+ if (st == NULL)
+ return AVERROR_NOMEM;
+ av_set_pts_info(st, 64, matroska->time_scale, 1000*1000*1000); /* 64 bit pts in ns */
+
+ st->codec->codec_id = codec_id;
+
+ if (track->default_duration)
+ av_reduce(&st->codec->time_base.num, &st->codec->time_base.den,
+ track->default_duration, 1000000000, 30000);
+
+ if(extradata){
+ st->codec->extradata = extradata;
+ st->codec->extradata_size = extradata_size;
+ } else if(track->codec_priv && track->codec_priv_size > 0){
+ st->codec->extradata = av_malloc(track->codec_priv_size);
+ if(st->codec->extradata == NULL)
+ return AVERROR_NOMEM;
+ st->codec->extradata_size = track->codec_priv_size;
+ memcpy(st->codec->extradata,track->codec_priv+extradata_offset,
+ track->codec_priv_size);
+ }
+
+ if (track->type == MATROSKA_TRACK_TYPE_VIDEO) {
+ MatroskaVideoTrack *videotrack = (MatroskaVideoTrack *)track;
+
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_tag = videotrack->fourcc;
+ st->codec->width = videotrack->pixel_width;
+ st->codec->height = videotrack->pixel_height;
+ if (videotrack->display_width == 0)
+ videotrack->display_width= videotrack->pixel_width;
+ if (videotrack->display_height == 0)
+ videotrack->display_height= videotrack->pixel_height;
+ av_reduce(&st->codec->sample_aspect_ratio.num,
+ &st->codec->sample_aspect_ratio.den,
+ st->codec->height * videotrack->display_width,
+ st->codec-> width * videotrack->display_height,
+ 255);
+ } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
+ MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)track;
+
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->sample_rate = audiotrack->samplerate;
+ st->codec->channels = audiotrack->channels;
+ } else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) {
+ st->codec->codec_type = CODEC_TYPE_SUBTITLE;
+ }
+
+ /* What do we do with private data? E.g. for Vorbis. */
+ }
+ res = 0;
+ }
+
+ return res;
+}
+
+static int
+matroska_find_track_by_num (MatroskaDemuxContext *matroska,
+ int num)
+{
+ int i;
+
+ for (i = 0; i < matroska->num_tracks; i++)
+ if (matroska->tracks[i]->num == num)
+ return i;
+
+ return -1;
+}
+
+static inline int
+rv_offset(uint8_t *data, int slice, int slices)
+{
+ return LE_32(data+8*slice+4) + 8*slices;
+}
+
+static int
+matroska_parse_blockgroup (MatroskaDemuxContext *matroska,
+ uint64_t cluster_time)
+{
+ int res = 0;
+ uint32_t id;
+ AVPacket *pkt = NULL;
+ int is_keyframe = PKT_FLAG_KEY, last_num_packets = matroska->num_packets;
+ uint64_t duration = AV_NOPTS_VALUE;
+ int track = -1;
+
+ av_log(matroska->ctx, AV_LOG_DEBUG, "parsing blockgroup...\n");
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR_IO;
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* one block inside the group. Note, block parsing is one
+ * of the harder things, so this code is a bit complicated.
+ * See http://www.matroska.org/ for documentation. */
+ case MATROSKA_ID_BLOCK: {
+ uint8_t *data, *origdata;
+ int size;
+ int16_t block_time;
+ uint32_t *lace_size = NULL;
+ int n, flags, laces = 0;
+ uint64_t num;
+ int64_t pos= url_ftell(&matroska->ctx->pb);
+
+ if ((res = ebml_read_binary(matroska, &id, &data, &size)) < 0)
+ break;
+ origdata = data;
+
+ /* first byte(s): tracknum */
+ if ((n = matroska_ebmlnum_uint(data, size, &num)) < 0) {
+ av_log(matroska->ctx, AV_LOG_ERROR,
+ "EBML block data error\n");
+ av_free(origdata);
+ break;
+ }
+ data += n;
+ size -= n;
+
+ /* fetch track from num */
+ track = matroska_find_track_by_num(matroska, num);
+ if (size <= 3 || track < 0 || track >= matroska->num_tracks) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Invalid stream %d or size %u\n", track, size);
+ av_free(origdata);
+ break;
+ }
+ if(matroska->ctx->streams[ matroska->tracks[track]->stream_index ]->discard >= AVDISCARD_ALL){
+ av_free(origdata);
+ break;
+ }
+
+ /* block_time (relative to cluster time) */
+ block_time = (data[0] << 8) | data[1];
+ data += 2;
+ size -= 2;
+ flags = *data;
+ data += 1;
+ size -= 1;
+ switch ((flags & 0x06) >> 1) {
+ case 0x0: /* no lacing */
+ laces = 1;
+ lace_size = av_mallocz(sizeof(int));
+ lace_size[0] = size;
+ break;
+
+ case 0x1: /* xiph lacing */
+ case 0x2: /* fixed-size lacing */
+ case 0x3: /* EBML lacing */
+ if (size == 0) {
+ res = -1;
+ break;
+ }
+ laces = (*data) + 1;
+ data += 1;
+ size -= 1;
+ lace_size = av_mallocz(laces * sizeof(int));
+
+ switch ((flags & 0x06) >> 1) {
+ case 0x1: /* xiph lacing */ {
+ uint8_t temp;
+ uint32_t total = 0;
+ for (n = 0; res == 0 && n < laces - 1; n++) {
+ while (1) {
+ if (size == 0) {
+ res = -1;
+ break;
+ }
+ temp = *data;
+ lace_size[n] += temp;
+ data += 1;
+ size -= 1;
+ if (temp != 0xff)
+ break;
+ }
+ total += lace_size[n];
+ }
+ lace_size[n] = size - total;
+ break;
+ }
+
+ case 0x2: /* fixed-size lacing */
+ for (n = 0; n < laces; n++)
+ lace_size[n] = size / laces;
+ break;
+
+ case 0x3: /* EBML lacing */ {
+ uint32_t total;
+ n = matroska_ebmlnum_uint(data, size, &num);
+ if (n < 0) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "EBML block data error\n");
+ break;
+ }
+ data += n;
+ size -= n;
+ total = lace_size[0] = num;
+ for (n = 1; res == 0 && n < laces - 1; n++) {
+ int64_t snum;
+ int r;
+ r = matroska_ebmlnum_sint (data, size,
+ &snum);
+ if (r < 0) {
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "EBML block data error\n");
+ break;
+ }
+ data += r;
+ size -= r;
+ lace_size[n] = lace_size[n - 1] + snum;
+ total += lace_size[n];
+ }
+ lace_size[n] = size - total;
+ break;
+ }
+ }
+ break;
+ }
+
+ if (res == 0) {
+ int real_v = matroska->tracks[track]->flags & MATROSKA_TRACK_REAL_V;
+ for (n = 0; n < laces; n++) {
+ uint64_t timecode = AV_NOPTS_VALUE;
+ int slice, slices = 1;
+
+ if (real_v) {
+ slices = *data++ + 1;
+ lace_size[n]--;
+ }
+ if (cluster_time != (uint64_t)-1 && n == 0) {
+ if (cluster_time + block_time >= 0)
+ timecode = (cluster_time + block_time) * matroska->time_scale;
+ }
+ /* FIXME: duration */
+
+ for (slice=0; slice<slices; slice++) {
+ int slice_size, slice_offset = 0;
+ if (real_v)
+ slice_offset = rv_offset(data, slice, slices);
+ if (slice+1 == slices)
+ slice_size = lace_size[n] - slice_offset;
+ else
+ slice_size = rv_offset(data, slice+1, slices) - slice_offset;
+ pkt = av_mallocz(sizeof(AVPacket));
+ /* XXX: prevent data copy... */
+ if (av_new_packet(pkt, slice_size) < 0) {
+ res = AVERROR_NOMEM;
+ n = laces-1;
+ break;
+ }
+ memcpy (pkt->data, data+slice_offset, slice_size);
+
+ if (n == 0)
+ pkt->flags = is_keyframe;
+ pkt->stream_index =
+ matroska->tracks[track]->stream_index;
+
+ pkt->pts = timecode;
+ pkt->pos = pos;
+
+ matroska_queue_packet(matroska, pkt);
+ }
+ data += lace_size[n];
+ }
+ }
+
+ av_free(lace_size);
+ av_free(origdata);
+ break;
+ }
+
+ case MATROSKA_ID_BLOCKDURATION: {
+ if ((res = ebml_read_uint(matroska, &id, &duration)) < 0)
+ break;
+ break;
+ }
+
+ case MATROSKA_ID_BLOCKREFERENCE:
+ /* We've found a reference, so not even the first frame in
+ * the lace is a key frame. */
+ is_keyframe = 0;
+ if (last_num_packets != matroska->num_packets)
+ matroska->packets[last_num_packets]->flags = 0;
+ res = ebml_read_skip(matroska);
+ break;
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown entry 0x%x in blockgroup data\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ if (pkt)
+ {
+ if (duration != AV_NOPTS_VALUE)
+ pkt->duration = duration;
+ else if (track >= 0 && track < matroska->num_tracks)
+ pkt->duration = matroska->tracks[track]->default_duration / matroska->time_scale;
+ }
+
+ return res;
+}
+
+static int
+matroska_parse_cluster (MatroskaDemuxContext *matroska)
+{
+ int res = 0;
+ uint32_t id;
+ uint64_t cluster_time = 0;
+
+ av_log(matroska->ctx, AV_LOG_DEBUG,
+ "parsing cluster at %"PRId64"\n", url_ftell(&matroska->ctx->pb));
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR_IO;
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ /* cluster timecode */
+ case MATROSKA_ID_CLUSTERTIMECODE: {
+ uint64_t num;
+ if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
+ break;
+ cluster_time = num;
+ break;
+ }
+
+ /* a group of blocks inside a cluster */
+ case MATROSKA_ID_BLOCKGROUP:
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ res = matroska_parse_blockgroup(matroska, cluster_time);
+ break;
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown entry 0x%x in cluster data\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ return res;
+}
+
+static int
+matroska_read_packet (AVFormatContext *s,
+ AVPacket *pkt)
+{
+ MatroskaDemuxContext *matroska = s->priv_data;
+ int res = 0;
+ uint32_t id;
+
+ /* Do we still have a packet queued? */
+ if (matroska_deliver_packet(matroska, pkt) == 0)
+ return 0;
+
+ /* Have we already reached the end? */
+ if (matroska->done)
+ return AVERROR_IO;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR_IO;
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ case MATROSKA_ID_CLUSTER:
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ if ((res = matroska_parse_cluster(matroska)) == 0)
+ res = 1; /* Parsed one cluster, let's get out. */
+ break;
+
+ default:
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ if (res == -1)
+ matroska->done = 1;
+
+ return matroska_deliver_packet(matroska, pkt);
+}
+
+static int
+matroska_read_close (AVFormatContext *s)
+{
+ MatroskaDemuxContext *matroska = s->priv_data;
+ int n = 0;
+
+ av_free(matroska->writing_app);
+ av_free(matroska->muxing_app);
+ av_free(matroska->index);
+
+ if (matroska->packets != NULL) {
+ for (n = 0; n < matroska->num_packets; n++) {
+ av_free_packet(matroska->packets[n]);
+ av_free(matroska->packets[n]);
+ }
+ av_free(matroska->packets);
+ }
+
+ for (n = 0; n < matroska->num_tracks; n++) {
+ MatroskaTrack *track = matroska->tracks[n];
+ av_free(track->codec_id);
+ av_free(track->codec_name);
+ av_free(track->codec_priv);
+ av_free(track->name);
+ av_free(track->language);
+
+ av_free(track);
+ }
+
+ return 0;
+}
+
+AVInputFormat matroska_demuxer = {
+ "matroska",
+ "Matroska file format",
+ sizeof(MatroskaDemuxContext),
+ matroska_probe,
+ matroska_read_header,
+ matroska_read_packet,
+ matroska_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/mm.c b/contrib/ffmpeg/libavformat/mm.c
new file mode 100644
index 000000000..a3c637fb2
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/mm.c
@@ -0,0 +1,212 @@
+/*
+ * American Laser Games MM Format Demuxer
+ * Copyright (c) 2006 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 mm.c
+ * American Laser Games MM Format Demuxer
+ * by Peter Ross (suxen_drol at hotmail dot com)
+ *
+ * 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 "avformat.h"
+
+#define MM_PREAMBLE_SIZE 6
+
+#define MM_TYPE_HEADER 0x0
+#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_AUDIO 0x15
+#define MM_TYPE_PALETTE 0x31
+
+#define MM_HEADER_LEN_V 0x16 /* video only */
+#define MM_HEADER_LEN_AV 0x18 /* video + audio */
+
+#define MM_PALETTE_COUNT 128
+#define MM_PALETTE_SIZE (MM_PALETTE_COUNT*3)
+
+typedef struct {
+ AVPaletteControl palette_control;
+ unsigned int audio_pts, video_pts;
+} MmDemuxContext;
+
+static int mm_probe(AVProbeData *p)
+{
+ /* the first chunk is always the header */
+ if (p->buf_size < MM_PREAMBLE_SIZE)
+ return 0;
+ if (LE_16(&p->buf[0]) != MM_TYPE_HEADER)
+ return 0;
+ if (LE_32(&p->buf[2]) != MM_HEADER_LEN_V && LE_32(&p->buf[2]) != MM_HEADER_LEN_AV)
+ return 0;
+
+ /* only return half certainty since this check is a bit sketchy */
+ return AVPROBE_SCORE_MAX / 2;
+}
+
+static int mm_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ MmDemuxContext *mm = (MmDemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVStream *st;
+
+ unsigned int type, length;
+ unsigned int frame_rate, width, height;
+
+ type = get_le16(pb);
+ length = get_le32(pb);
+
+ if (type != MM_TYPE_HEADER)
+ return AVERROR_INVALIDDATA;
+
+ /* read header */
+ get_le16(pb); /* total number of chunks */
+ frame_rate = get_le16(pb);
+ get_le16(pb); /* ibm-pc video bios mode */
+ width = get_le16(pb);
+ height = get_le16(pb);
+ url_fseek(pb, length - 10, SEEK_CUR); /* unknown data */
+
+ /* video stream */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_MMVIDEO;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->width = width;
+ st->codec->height = height;
+ st->codec->palctrl = &mm->palette_control;
+ av_set_pts_info(st, 64, 1, frame_rate);
+
+ /* audio stream */
+ if (length == MM_HEADER_LEN_AV) {
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->codec_id = CODEC_ID_PCM_U8;
+ st->codec->channels = 1;
+ st->codec->sample_rate = 8000;
+ av_set_pts_info(st, 64, 1, 8000); /* 8000 hz */
+ }
+
+ mm->palette_control.palette_changed = 0;
+ mm->audio_pts = 0;
+ mm->video_pts = 0;
+ return 0;
+}
+
+static int mm_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ MmDemuxContext *mm = (MmDemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ unsigned char preamble[MM_PREAMBLE_SIZE];
+ unsigned char pal[MM_PALETTE_SIZE];
+ unsigned int type, length;
+ int i;
+
+ while(1) {
+
+ if (get_buffer(pb, preamble, MM_PREAMBLE_SIZE) != MM_PREAMBLE_SIZE) {
+ return AVERROR_IO;
+ }
+
+ type = LE_16(&preamble[0]);
+ length = LE_16(&preamble[2]);
+
+ switch(type) {
+ case MM_TYPE_PALETTE :
+ url_fseek(pb, 4, SEEK_CUR); /* unknown data */
+ if (get_buffer(pb, pal, MM_PALETTE_SIZE) != MM_PALETTE_SIZE)
+ return AVERROR_IO;
+ url_fseek(pb, length - (4 + MM_PALETTE_SIZE), SEEK_CUR);
+
+ for (i=0; i<MM_PALETTE_COUNT; i++) {
+ int r = pal[i*3 + 0];
+ int g = pal[i*3 + 1];
+ int b = pal[i*3 + 2];
+ mm->palette_control.palette[i] = (r << 16) | (g << 8) | (b);
+ /* repeat palette, where each components is multiplied by four */
+ mm->palette_control.palette[i+128] = (r << 18) | (g << 10) | (b<<2);
+ }
+ mm->palette_control.palette_changed = 1;
+ break;
+
+ case MM_TYPE_INTER :
+ case MM_TYPE_INTRA :
+ case MM_TYPE_INTRA_HH :
+ case MM_TYPE_INTER_HH :
+ case MM_TYPE_INTRA_HHV :
+ case MM_TYPE_INTER_HHV :
+ /* output preamble + data */
+ if (av_new_packet(pkt, length + MM_PREAMBLE_SIZE))
+ return AVERROR_NOMEM;
+ memcpy(pkt->data, preamble, MM_PREAMBLE_SIZE);
+ if (get_buffer(pb, pkt->data + MM_PREAMBLE_SIZE, length) != length)
+ return AVERROR_IO;
+ pkt->size = length + MM_PREAMBLE_SIZE;
+ pkt->stream_index = 0;
+ pkt->pts = mm->video_pts++;
+ return 0;
+
+ case MM_TYPE_AUDIO :
+ if (av_get_packet(&s->pb, pkt, length)<0)
+ return AVERROR_NOMEM;
+ pkt->size = length;
+ pkt->stream_index = 1;
+ pkt->pts = mm->audio_pts++;
+ return 0;
+
+ default :
+ av_log(NULL, AV_LOG_INFO, "mm: unknown chunk type 0x%x\n", type);
+ url_fseek(pb, length, SEEK_CUR);
+ }
+ }
+
+ return 0;
+}
+
+static int mm_read_close(AVFormatContext *s)
+{
+ return 0;
+}
+
+AVInputFormat mm_demuxer = {
+ "mm",
+ "American Laser Games MM format",
+ sizeof(MmDemuxContext),
+ mm_probe,
+ mm_read_header,
+ mm_read_packet,
+ mm_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/mmf.c b/contrib/ffmpeg/libavformat/mmf.c
new file mode 100644
index 000000000..40b1a497c
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/mmf.c
@@ -0,0 +1,331 @@
+/*
+ * Yamaha SMAF format
+ * Copyright (c) 2005 Vidar Madsen
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "avformat.h"
+#include "allformats.h"
+#include "riff.h"
+
+typedef struct {
+ offset_t atrpos, atsqpos, awapos;
+ offset_t data_size;
+} MMFContext;
+
+static int mmf_rates[] = { 4000, 8000, 11025, 22050, 44100 };
+
+static int mmf_rate_code(int rate)
+{
+ int i;
+ for(i = 0; i < 5; i++)
+ if(mmf_rates[i] == rate)
+ return i;
+ return -1;
+}
+
+static int mmf_rate(int code)
+{
+ if((code < 0) || (code > 4))
+ return -1;
+ return mmf_rates[code];
+}
+
+#ifdef CONFIG_MUXERS
+/* Copy of end_tag() from avienc.c, but for big-endian chunk size */
+static void end_tag_be(ByteIOContext *pb, offset_t start)
+{
+ offset_t pos;
+
+ pos = url_ftell(pb);
+ url_fseek(pb, start - 4, SEEK_SET);
+ put_be32(pb, (uint32_t)(pos - start));
+ url_fseek(pb, pos, SEEK_SET);
+}
+
+static int mmf_write_header(AVFormatContext *s)
+{
+ MMFContext *mmf = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ offset_t pos;
+ int rate;
+
+ rate = mmf_rate_code(s->streams[0]->codec->sample_rate);
+ if(rate < 0) {
+ av_log(s, AV_LOG_ERROR, "Unsupported sample rate %d\n", s->streams[0]->codec->sample_rate);
+ return -1;
+ }
+
+ put_tag(pb, "MMMD");
+ put_be32(pb, 0);
+ pos = start_tag(pb, "CNTI");
+ put_byte(pb, 0); /* class */
+ put_byte(pb, 0); /* type */
+ put_byte(pb, 0); /* code type */
+ put_byte(pb, 0); /* status */
+ put_byte(pb, 0); /* counts */
+ put_tag(pb, "VN:libavcodec,"); /* metadata ("ST:songtitle,VN:version,...") */
+ end_tag_be(pb, pos);
+
+ put_buffer(pb, "ATR\x00", 4);
+ put_be32(pb, 0);
+ mmf->atrpos = url_ftell(pb);
+ put_byte(pb, 0); /* format type */
+ put_byte(pb, 0); /* sequence type */
+ put_byte(pb, (0 << 7) | (1 << 4) | rate); /* (channel << 7) | (format << 4) | rate */
+ put_byte(pb, 0); /* wave base bit */
+ put_byte(pb, 2); /* time base d */
+ put_byte(pb, 2); /* time base g */
+
+ put_tag(pb, "Atsq");
+ put_be32(pb, 16);
+ mmf->atsqpos = url_ftell(pb);
+ /* Will be filled on close */
+ put_buffer(pb, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16);
+
+ mmf->awapos = start_tag(pb, "Awa\x01");
+
+ av_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate);
+
+ put_flush_packet(pb);
+
+ return 0;
+}
+
+static int mmf_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ ByteIOContext *pb = &s->pb;
+ put_buffer(pb, pkt->data, pkt->size);
+ return 0;
+}
+
+/* Write a variable-length symbol */
+static void put_varlength(ByteIOContext *pb, int val)
+{
+ if(val < 128)
+ put_byte(pb, val);
+ else {
+ val -= 128;
+ put_byte(pb, 0x80 | val >> 7);
+ put_byte(pb, 0x7f & val);
+ }
+}
+
+static int mmf_write_trailer(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+ MMFContext *mmf = s->priv_data;
+ offset_t pos, size;
+ int gatetime;
+
+ if (!url_is_streamed(&s->pb)) {
+ /* Fill in length fields */
+ end_tag_be(pb, mmf->awapos);
+ end_tag_be(pb, mmf->atrpos);
+ end_tag_be(pb, 8);
+
+ pos = url_ftell(pb);
+ size = pos - mmf->awapos;
+
+ /* Fill Atsq chunk */
+ url_fseek(pb, mmf->atsqpos, SEEK_SET);
+
+ /* "play wav" */
+ put_byte(pb, 0); /* start time */
+ put_byte(pb, 1); /* (channel << 6) | wavenum */
+ gatetime = size * 500 / s->streams[0]->codec->sample_rate;
+ put_varlength(pb, gatetime); /* duration */
+
+ /* "nop" */
+ put_varlength(pb, gatetime); /* start time */
+ put_buffer(pb, "\xff\x00", 2); /* nop */
+
+ /* "end of sequence" */
+ put_buffer(pb, "\x00\x00\x00\x00", 4);
+
+ url_fseek(pb, pos, SEEK_SET);
+
+ put_flush_packet(pb);
+ }
+ return 0;
+}
+#endif //CONFIG_MUXERS
+
+static int mmf_probe(AVProbeData *p)
+{
+ /* check file header */
+ if (p->buf_size <= 32)
+ return 0;
+ if (p->buf[0] == 'M' && p->buf[1] == 'M' &&
+ p->buf[2] == 'M' && p->buf[3] == 'D' &&
+ p->buf[8] == 'C' && p->buf[9] == 'N' &&
+ p->buf[10] == 'T' && p->buf[11] == 'I')
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+/* mmf input */
+static int mmf_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ MMFContext *mmf = s->priv_data;
+ unsigned int tag;
+ ByteIOContext *pb = &s->pb;
+ AVStream *st;
+ offset_t file_size, size;
+ int rate, params;
+
+ tag = get_le32(pb);
+ if (tag != MKTAG('M', 'M', 'M', 'D'))
+ return -1;
+ file_size = get_be32(pb);
+
+ /* Skip some unused chunks that may or may not be present */
+ for(;; url_fseek(pb, size, SEEK_CUR)) {
+ tag = get_le32(pb);
+ size = get_be32(pb);
+ if(tag == MKTAG('C','N','T','I')) continue;
+ if(tag == MKTAG('O','P','D','A')) continue;
+ break;
+ }
+
+ /* Tag = "ATRx", where "x" = track number */
+ if ((tag & 0xffffff) == MKTAG('M', 'T', 'R', 0)) {
+ av_log(s, AV_LOG_ERROR, "MIDI like format found, unsupported\n");
+ return -1;
+ }
+ if ((tag & 0xffffff) != MKTAG('A', 'T', 'R', 0)) {
+ av_log(s, AV_LOG_ERROR, "Unsupported SMAF chunk %08x\n", tag);
+ return -1;
+ }
+
+ get_byte(pb); /* format type */
+ get_byte(pb); /* sequence type */
+ params = get_byte(pb); /* (channel << 7) | (format << 4) | rate */
+ rate = mmf_rate(params & 0x0f);
+ if(rate < 0) {
+ av_log(s, AV_LOG_ERROR, "Invalid sample rate\n");
+ return -1;
+ }
+ get_byte(pb); /* wave base bit */
+ get_byte(pb); /* time base d */
+ get_byte(pb); /* time base g */
+
+ /* Skip some unused chunks that may or may not be present */
+ for(;; url_fseek(pb, size, SEEK_CUR)) {
+ tag = get_le32(pb);
+ size = get_be32(pb);
+ if(tag == MKTAG('A','t','s','q')) continue;
+ if(tag == MKTAG('A','s','p','I')) continue;
+ break;
+ }
+
+ /* Make sure it's followed by an Awa chunk, aka wave data */
+ if ((tag & 0xffffff) != MKTAG('A', 'w', 'a', 0)) {
+ av_log(s, AV_LOG_ERROR, "Unexpected SMAF chunk %08x\n", tag);
+ return -1;
+ }
+ mmf->data_size = size;
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_ADPCM_YAMAHA;
+ st->codec->sample_rate = rate;
+ st->codec->channels = 1;
+ st->codec->bits_per_sample = 4;
+ st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_sample;
+
+ av_set_pts_info(st, 64, 1, st->codec->sample_rate);
+
+ return 0;
+}
+
+#define MAX_SIZE 4096
+
+static int mmf_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ MMFContext *mmf = s->priv_data;
+ AVStream *st;
+ int ret, size;
+
+ if (url_feof(&s->pb))
+ return AVERROR_IO;
+ st = s->streams[0];
+
+ size = MAX_SIZE;
+ if(size > mmf->data_size)
+ size = mmf->data_size;
+
+ if(!size)
+ return AVERROR_IO;
+
+ if (av_new_packet(pkt, size))
+ return AVERROR_IO;
+ pkt->stream_index = 0;
+
+ ret = get_buffer(&s->pb, pkt->data, pkt->size);
+ if (ret < 0)
+ av_free_packet(pkt);
+
+ mmf->data_size -= ret;
+
+ pkt->size = ret;
+ return ret;
+}
+
+static int mmf_read_close(AVFormatContext *s)
+{
+ return 0;
+}
+
+static int mmf_read_seek(AVFormatContext *s,
+ int stream_index, int64_t timestamp, int flags)
+{
+ return pcm_read_seek(s, stream_index, timestamp, flags);
+}
+
+#ifdef CONFIG_MMF_DEMUXER
+AVInputFormat mmf_demuxer = {
+ "mmf",
+ "mmf format",
+ sizeof(MMFContext),
+ mmf_probe,
+ mmf_read_header,
+ mmf_read_packet,
+ mmf_read_close,
+ mmf_read_seek,
+};
+#endif
+#ifdef CONFIG_MMF_MUXER
+AVOutputFormat mmf_muxer = {
+ "mmf",
+ "mmf format",
+ "application/vnd.smaf",
+ "mmf",
+ sizeof(MMFContext),
+ CODEC_ID_ADPCM_YAMAHA,
+ CODEC_ID_NONE,
+ mmf_write_header,
+ mmf_write_packet,
+ mmf_write_trailer,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/mov.c b/contrib/ffmpeg/libavformat/mov.c
new file mode 100644
index 000000000..3ceac64b1
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/mov.c
@@ -0,0 +1,1798 @@
+/*
+ * MOV demuxer
+ * 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
+ */
+
+#include <limits.h>
+
+//#define DEBUG
+
+#include "avformat.h"
+#include "riff.h"
+#include "isom.h"
+#include "dv.h"
+
+#ifdef CONFIG_ZLIB
+#include <zlib.h>
+#endif
+
+/*
+ * First version by Francois Revol revol@free.fr
+ * Seek function by Gael Chardon gael.dev@4now.net
+ *
+ * Features and limitations:
+ * - reads most of the QT files I have (at least the structure),
+ * the exceptions are .mov with zlib compressed headers ('cmov' section). It shouldn't be hard to implement.
+ * FIXED, Francois Revol, 07/17/2002
+ * - ffmpeg has nearly none of the usual QuickTime codecs,
+ * although I succesfully dumped raw and mp3 audio tracks off .mov files.
+ * Sample QuickTime files with mp3 audio can be found at: http://www.3ivx.com/showcase.html
+ * - .mp4 parsing is still hazardous, although the format really is QuickTime with some minor changes
+ * (to make .mov parser crash maybe ?), despite what they say in the MPEG FAQ at
+ * http://mpeg.telecomitalialab.com/faq.htm
+ * - the code is quite ugly... maybe I won't do it recursive next time :-)
+ * - seek is not supported with files that contain edit list
+ *
+ * Funny I didn't know about http://sourceforge.net/projects/qt-ffmpeg/
+ * when coding this :) (it's a writer anyway)
+ *
+ * Reference documents:
+ * http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
+ * Apple:
+ * http://developer.apple.com/documentation/QuickTime/QTFF/
+ * http://developer.apple.com/documentation/QuickTime/QTFF/qtff.pdf
+ * QuickTime is a trademark of Apple (AFAIK :))
+ */
+
+#include "qtpalette.h"
+
+
+#undef NDEBUG
+#include <assert.h>
+
+static const CodecTag mov_video_tags[] = {
+/* { CODEC_ID_, MKTAG('c', 'v', 'i', 'd') }, *//* Cinepak */
+/* { CODEC_ID_H263, MKTAG('r', 'a', 'w', ' ') }, *//* Uncompressed RGB */
+/* { CODEC_ID_H263, MKTAG('Y', 'u', 'v', '2') }, *//* Uncompressed YUV422 */
+/* { CODEC_ID_RAWVIDEO, MKTAG('A', 'V', 'U', 'I') }, *//* YUV with alpha-channel (AVID Uncompressed) */
+/* Graphics */
+/* Animation */
+/* Apple video */
+/* Kodak Photo CD */
+ { CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') }, /* PhotoJPEG */
+ { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'e', 'g') }, /* MPEG */
+ { CODEC_ID_MJPEG, MKTAG('m', 'j', 'p', 'a') }, /* Motion-JPEG (format A) */
+ { CODEC_ID_MJPEGB, MKTAG('m', 'j', 'p', 'b') }, /* Motion-JPEG (format B) */
+ { CODEC_ID_MJPEG, MKTAG('A', 'V', 'D', 'J') }, /* MJPEG with alpha-channel (AVID JFIF meridien compressed) */
+/* { CODEC_ID_MJPEG, MKTAG('A', 'V', 'R', 'n') }, *//* MJPEG with alpha-channel (AVID ABVB/Truevision NuVista) */
+ { CODEC_ID_GIF, MKTAG('g', 'i', 'f', ' ') }, /* embedded gif files as frames (usually one "click to play movie" frame) */
+/* Sorenson video */
+ { CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') }, /* Sorenson Video v1 */
+ { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', '1') }, /* Sorenson Video v1 */
+ { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', 'i') }, /* Sorenson Video v1 (from QT specs)*/
+ { CODEC_ID_SVQ3, MKTAG('S', 'V', 'Q', '3') }, /* Sorenson Video v3 */
+ { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
+ { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') }, /* OpenDiVX *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */
+ { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') },
+ { CODEC_ID_MPEG4, MKTAG('3', 'I', 'V', '2') }, /* experimental: 3IVX files before ivx D4 4.5.1 */
+/* { CODEC_ID_, MKTAG('I', 'V', '5', '0') }, *//* Indeo 5.0 */
+ { CODEC_ID_H263, MKTAG('h', '2', '6', '3') }, /* H263 */
+ { CODEC_ID_H263, MKTAG('s', '2', '6', '3') }, /* H263 ?? works */
+ { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') }, /* DV NTSC */
+ { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', 'p') }, /* DV PAL */
+ { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') }, /* On2 VP3 */
+ { CODEC_ID_RPZA, MKTAG('r', 'p', 'z', 'a') }, /* Apple Video (RPZA) */
+ { CODEC_ID_CINEPAK, MKTAG('c', 'v', 'i', 'd') }, /* Cinepak */
+ { CODEC_ID_8BPS, MKTAG('8', 'B', 'P', 'S') }, /* Planar RGB (8BPS) */
+ { CODEC_ID_SMC, MKTAG('s', 'm', 'c', ' ') }, /* Apple Graphics (SMC) */
+ { CODEC_ID_QTRLE, MKTAG('r', 'l', 'e', ' ') }, /* Apple Animation (RLE) */
+ { CODEC_ID_QDRAW, MKTAG('q', 'd', 'r', 'w') }, /* QuickDraw */
+ { CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, /* AVC-1/H.264 */
+ { CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '2') }, /* MPEG2 produced by Sony HD camera */
+ { CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '3') }, /* HDV produced by FCP */
+ { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'n') }, /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
+ { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'p') }, /* MPEG2 IMX PAL 625/50 50mb/s produced by FCP */
+ { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'n') }, /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
+ { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'p') }, /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
+ { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'p', 'p') }, /* DVCPRO PAL produced by FCP */
+ //{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '5') }, /* DVCPRO HD 50i produced by FCP */
+ //{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '6') }, /* DVCPRO HD 60i produced by FCP */
+ { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'p') }, /* DVCPRO50 PAL produced by FCP */
+ { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'n') }, /* DVCPRO50 NTSC produced by FCP */
+ { CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', 'v') }, /* AVID DV */
+ //{ CODEC_ID_JPEG2000, MKTAG('m', 'j', 'p', '2') }, /* JPEG 2000 produced by FCP */
+ { CODEC_ID_TARGA, MKTAG('t', 'g', 'a', ' ') }, /* Truevision Targa */
+ { CODEC_ID_TIFF, MKTAG('t', 'i', 'f', 'f') }, /* TIFF embedded in MOV */
+ { CODEC_ID_RAWVIDEO, MKTAG('2', 'v', 'u', 'y') }, /* UNCOMPRESSED 8BIT 4:2:2 */
+ { CODEC_ID_NONE, 0 },
+};
+
+static const CodecTag mov_audio_tags[] = {
+ { CODEC_ID_PCM_S32BE, MKTAG('i', 'n', '3', '2') },
+ { CODEC_ID_PCM_S24BE, MKTAG('i', 'n', '2', '4') },
+ { CODEC_ID_PCM_S16BE, MKTAG('N', 'O', 'N', 'E') }, /* uncompressed */
+ { CODEC_ID_PCM_S16BE, MKTAG('t', 'w', 'o', 's') }, /* 16 bits */
+ { CODEC_ID_PCM_U8, MKTAG('r', 'a', 'w', ' ') }, /* 8 bits unsigned */
+ { CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') }, /* */
+ { CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') }, /* */
+ { CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') }, /* */
+ { CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') }, /* IMA-4 ADPCM */
+ { CODEC_ID_ADPCM_MS, MKTAG('m', 's', 0x00, 0x02) }, /* MS ADPCM */
+ { CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') }, /* Macintosh Audio Compression and Expansion 3:1 */
+ { CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') }, /* Macintosh Audio Compression and Expansion 6:1 */
+
+ { CODEC_ID_MP3, MKTAG('.', 'm', 'p', '3') }, /* MPEG layer 3 */ /* sample files at http://www.3ivx.com/showcase.html use this tag */
+ { CODEC_ID_MP2, 0x6D730055 }, /* MPEG layer 3 */
+ { CODEC_ID_MP2, 0x5500736D }, /* MPEG layer 3 *//* XXX: check endianness */
+/* { CODEC_ID_OGG_VORBIS, MKTAG('O', 'g', 'g', 'S') }, *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */
+/* MP4 tags */
+ { CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') }, /* MPEG-4 AAC */
+ /* The standard for mpeg4 audio is still not normalised AFAIK anyway */
+ { CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') }, /* AMR-NB 3gp */
+ { CODEC_ID_AMR_WB, MKTAG('s', 'a', 'w', 'b') }, /* AMR-WB 3gp */
+ { CODEC_ID_AC3, MKTAG('m', 's', 0x20, 0x00) }, /* Dolby AC-3 */
+ { CODEC_ID_ALAC,MKTAG('a', 'l', 'a', 'c') }, /* Apple Lossless */
+ { CODEC_ID_QDM2,MKTAG('Q', 'D', 'M', '2') }, /* QDM2 */
+ { CODEC_ID_DVAUDIO, MKTAG('v', 'd', 'v', 'a') },
+ { CODEC_ID_DVAUDIO, MKTAG('d', 'v', 'c', 'a') },
+ { CODEC_ID_PCM_S16LE, MKTAG('l', 'p', 'c', 'm') },
+ { CODEC_ID_NONE, 0 },
+};
+
+/* the QuickTime file format is quite convoluted...
+ * it has lots of index tables, each indexing something in another one...
+ * Here we just use what is needed to read the chunks
+ */
+
+typedef struct MOV_sample_to_chunk_tbl {
+ long first;
+ long count;
+ long id;
+} MOV_sample_to_chunk_tbl;
+
+typedef struct {
+ uint32_t type;
+ int64_t offset;
+ int64_t size; /* total size (excluding the size and type fields) */
+} MOV_atom_t;
+
+typedef struct {
+ int seed;
+ int flags;
+ int size;
+ void* clrs;
+} MOV_ctab_t;
+
+typedef struct MOV_mdat_atom_s {
+ offset_t offset;
+ int64_t size;
+} MOV_mdat_atom_t;
+
+typedef struct {
+ uint8_t version;
+ uint32_t flags; // 24bit
+
+ /* 0x03 ESDescrTag */
+ uint16_t es_id;
+#define MP4ODescrTag 0x01
+#define MP4IODescrTag 0x02
+#define MP4ESDescrTag 0x03
+#define MP4DecConfigDescrTag 0x04
+#define MP4DecSpecificDescrTag 0x05
+#define MP4SLConfigDescrTag 0x06
+#define MP4ContentIdDescrTag 0x07
+#define MP4SupplContentIdDescrTag 0x08
+#define MP4IPIPtrDescrTag 0x09
+#define MP4IPMPPtrDescrTag 0x0A
+#define MP4IPMPDescrTag 0x0B
+#define MP4RegistrationDescrTag 0x0D
+#define MP4ESIDIncDescrTag 0x0E
+#define MP4ESIDRefDescrTag 0x0F
+#define MP4FileIODescrTag 0x10
+#define MP4FileODescrTag 0x11
+#define MP4ExtProfileLevelDescrTag 0x13
+#define MP4ExtDescrTagsStart 0x80
+#define MP4ExtDescrTagsEnd 0xFE
+ uint8_t stream_priority;
+
+ /* 0x04 DecConfigDescrTag */
+ uint8_t object_type_id;
+ uint8_t stream_type;
+ /* XXX: really streamType is
+ * only 6bit, followed by:
+ * 1bit upStream
+ * 1bit reserved
+ */
+ uint32_t buffer_size_db; // 24
+ uint32_t max_bitrate;
+ uint32_t avg_bitrate;
+
+ /* 0x05 DecSpecificDescrTag */
+ uint8_t decoder_cfg_len;
+ uint8_t *decoder_cfg;
+
+ /* 0x06 SLConfigDescrTag */
+ uint8_t sl_config_len;
+ uint8_t *sl_config;
+} MOV_esds_t;
+
+struct MOVParseTableEntry;
+
+typedef struct MOVStreamContext {
+ int ffindex; /* the ffmpeg stream id */
+ long next_chunk;
+ long chunk_count;
+ int64_t *chunk_offsets;
+ int stts_count;
+ Time2Sample *stts_data;
+ int ctts_count;
+ Time2Sample *ctts_data;
+ int edit_count; /* number of 'edit' (elst atom) */
+ long sample_to_chunk_sz;
+ MOV_sample_to_chunk_tbl *sample_to_chunk;
+ int sample_to_ctime_index;
+ int sample_to_ctime_sample;
+ long sample_size;
+ long sample_count;
+ long *sample_sizes;
+ long keyframe_count;
+ long *keyframes;
+ int time_scale;
+ int time_rate;
+ long current_sample;
+ MOV_esds_t esds;
+ AVRational sample_size_v1;
+ int dv_audio_container;
+} MOVStreamContext;
+
+typedef struct MOVContext {
+ AVFormatContext *fc;
+ int time_scale;
+ int64_t duration; /* duration of the longest track */
+ int found_moov; /* when both 'moov' and 'mdat' sections has been found */
+ int found_mdat; /* we suppose we have enough data to read the file */
+ int64_t mdat_size;
+ int64_t mdat_offset;
+ int total_streams;
+ /* some streams listed here aren't presented to the ffmpeg API, since they aren't either video nor audio
+ * but we need the info to be able to skip data from those streams in the 'mdat' section
+ */
+ MOVStreamContext *streams[MAX_STREAMS];
+
+ int ctab_size;
+ MOV_ctab_t **ctab; /* color tables */
+ const struct MOVParseTableEntry *parse_table; /* could be eventually used to change the table */
+ /* NOTE: for recursion save to/ restore from local variable! */
+
+ AVPaletteControl palette_control;
+ MOV_mdat_atom_t *mdat_list;
+ int mdat_count;
+ DVDemuxContext *dv_demux;
+ AVFormatContext *dv_fctx;
+ int isom; /* 1 if file is ISO Media (mp4/3gp) */
+} MOVContext;
+
+
+/* XXX: it's the first time I make a recursive parser I think... sorry if it's ugly :P */
+
+/* those functions parse an atom */
+/* return code:
+ 1: found what I wanted, exit
+ 0: continue to parse next atom
+ -1: error occured, exit
+ */
+typedef int (*mov_parse_function)(MOVContext *ctx, ByteIOContext *pb, MOV_atom_t atom);
+
+/* links atom IDs to parse functions */
+typedef struct MOVParseTableEntry {
+ uint32_t type;
+ mov_parse_function func;
+} MOVParseTableEntry;
+
+static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ int64_t total_size = 0;
+ MOV_atom_t a;
+ int i;
+ int err = 0;
+
+ a.offset = atom.offset;
+
+ if (atom.size < 0)
+ atom.size = 0x7fffffffffffffffLL;
+ while(((total_size + 8) < atom.size) && !url_feof(pb) && !err) {
+ a.size = atom.size;
+ a.type=0L;
+ if(atom.size >= 8) {
+ a.size = get_be32(pb);
+ a.type = get_le32(pb);
+ }
+ total_size += 8;
+ a.offset += 8;
+ dprintf("type: %08x %.4s sz: %"PRIx64" %"PRIx64" %"PRIx64"\n", a.type, (char*)&a.type, a.size, atom.size, total_size);
+ if (a.size == 1) { /* 64 bit extended size */
+ a.size = get_be64(pb) - 8;
+ a.offset += 8;
+ total_size += 8;
+ }
+ if (a.size == 0) {
+ a.size = atom.size - total_size;
+ if (a.size <= 8)
+ break;
+ }
+ for (i = 0; c->parse_table[i].type != 0L
+ && c->parse_table[i].type != a.type; i++)
+ /* empty */;
+
+ a.size -= 8;
+
+ if(a.size < 0)
+ break;
+
+ if (c->parse_table[i].type == 0) { /* skip leaf atoms data */
+ url_fskip(pb, a.size);
+ } else {
+ offset_t start_pos = url_ftell(pb);
+ int64_t left;
+ err = (c->parse_table[i].func)(c, pb, a);
+ left = a.size - url_ftell(pb) + start_pos;
+ if (left > 0) /* skip garbage at atom end */
+ url_fskip(pb, left);
+ }
+
+ a.offset += a.size;
+ total_size += a.size;
+ }
+
+ if (!err && total_size < atom.size && atom.size < 0x7ffff) {
+ url_fskip(pb, atom.size - total_size);
+ }
+
+ return err;
+}
+
+static int mov_read_ctab(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+#if 1
+ url_fskip(pb, atom.size); // for now
+#else
+ VERY VERY BROKEN, NEVER execute this, needs rewrite
+ unsigned int len;
+ MOV_ctab_t *t;
+ c->ctab = av_realloc(c->ctab, ++c->ctab_size);
+ t = c->ctab[c->ctab_size];
+ t->seed = get_be32(pb);
+ t->flags = get_be16(pb);
+ t->size = get_be16(pb) + 1;
+ len = 2 * t->size * 4;
+ if (len > 0) {
+ t->clrs = av_malloc(len); // 16bit A R G B
+ if (t->clrs)
+ get_buffer(pb, t->clrs, len);
+ }
+#endif
+
+ return 0;
+}
+
+static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+ uint32_t type;
+ uint32_t ctype;
+
+ get_byte(pb); /* version */
+ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
+
+ /* component type */
+ ctype = get_le32(pb);
+ type = get_le32(pb); /* component subtype */
+
+ dprintf("ctype= %c%c%c%c (0x%08lx)\n", *((char *)&ctype), ((char *)&ctype)[1], ((char *)&ctype)[2], ((char *)&ctype)[3], (long) ctype);
+ dprintf("stype= %c%c%c%c\n", *((char *)&type), ((char *)&type)[1], ((char *)&type)[2], ((char *)&type)[3]);
+ if(!ctype)
+ c->isom = 1;
+ if(type == MKTAG('v', 'i', 'd', 'e'))
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ else if(type == MKTAG('s', 'o', 'u', 'n'))
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ else if(type == MKTAG('m', '1', 'a', ' '))
+ st->codec->codec_id = CODEC_ID_MP2;
+ else if(type == MKTAG('s', 'u', 'b', 'p')) {
+ st->codec->codec_type = CODEC_TYPE_SUBTITLE;
+ st->codec->codec_id = CODEC_ID_DVD_SUBTITLE;
+ }
+ get_be32(pb); /* component manufacture */
+ get_be32(pb); /* component flags */
+ get_be32(pb); /* component flags mask */
+
+ if(atom.size <= 24)
+ return 0; /* nothing left to read */
+
+ url_fskip(pb, atom.size - (url_ftell(pb) - atom.offset));
+ return 0;
+}
+
+static int mov_mp4_read_descr_len(ByteIOContext *pb)
+{
+ int len = 0;
+ int count = 4;
+ while (count--) {
+ int c = get_byte(pb);
+ len = (len << 7) | (c & 0x7f);
+ if (!(c & 0x80))
+ break;
+ }
+ return len;
+}
+
+static int mov_mp4_read_descr(ByteIOContext *pb, int *tag)
+{
+ int len;
+ *tag = get_byte(pb);
+ len = mov_mp4_read_descr_len(pb);
+ dprintf("MPEG4 description: tag=0x%02x len=%d\n", *tag, len);
+ return len;
+}
+
+static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+ MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+ int tag, len;
+
+ /* Well, broken but suffisant for some MP4 streams */
+ get_be32(pb); /* version + flags */
+ len = mov_mp4_read_descr(pb, &tag);
+ if (tag == MP4ESDescrTag) {
+ get_be16(pb); /* ID */
+ get_byte(pb); /* priority */
+ } else
+ get_be16(pb); /* ID */
+
+ len = mov_mp4_read_descr(pb, &tag);
+ if (tag == MP4DecConfigDescrTag) {
+ sc->esds.object_type_id = get_byte(pb);
+ sc->esds.stream_type = get_byte(pb);
+ sc->esds.buffer_size_db = get_be24(pb);
+ sc->esds.max_bitrate = get_be32(pb);
+ sc->esds.avg_bitrate = get_be32(pb);
+
+ st->codec->codec_id= codec_get_id(ff_mov_obj_type, sc->esds.object_type_id);
+ dprintf("esds object type id %d\n", sc->esds.object_type_id);
+ len = mov_mp4_read_descr(pb, &tag);
+ if (tag == MP4DecSpecificDescrTag) {
+ dprintf("Specific MPEG4 header len=%d\n", len);
+ st->codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
+ if (st->codec->extradata) {
+ get_buffer(pb, st->codec->extradata, len);
+ st->codec->extradata_size = len;
+ /* from mplayer */
+ if ((*st->codec->extradata >> 3) == 29) {
+ st->codec->codec_id = CODEC_ID_MP3ON4;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/* this atom contains actual media data */
+static int mov_read_mdat(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ if(atom.size == 0) /* wrong one (MP4) */
+ return 0;
+ c->mdat_list = av_realloc(c->mdat_list, (c->mdat_count + 1) * sizeof(*c->mdat_list));
+ c->mdat_list[c->mdat_count].offset = atom.offset;
+ c->mdat_list[c->mdat_count].size = atom.size;
+ c->mdat_count++;
+ c->found_mdat=1;
+ c->mdat_offset = atom.offset;
+ c->mdat_size = atom.size;
+ if(c->found_moov)
+ return 1; /* found both, just go */
+ url_fskip(pb, atom.size);
+ return 0; /* now go for moov */
+}
+
+static int mov_read_ftyp(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ uint32_t type = get_le32(pb);
+
+ if (type != MKTAG('q','t',' ',' '))
+ c->isom = 1;
+ av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
+ get_be32(pb); /* minor version */
+ url_fskip(pb, atom.size - 8);
+ return 0;
+}
+
+/* this atom should contain all header atoms */
+static int mov_read_moov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ int err;
+
+ err = mov_read_default(c, pb, atom);
+ /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */
+ /* so we don't parse the whole file if over a network */
+ c->found_moov=1;
+ if(c->found_mdat)
+ return 1; /* found both, just go */
+ return 0; /* now go for mdat */
+}
+
+
+static int mov_read_mdhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+ MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+ int version = get_byte(pb);
+ int lang;
+
+ if (version > 1)
+ return 1; /* unsupported */
+
+ get_byte(pb); get_byte(pb);
+ get_byte(pb); /* flags */
+
+ if (version == 1) {
+ get_be64(pb);
+ get_be64(pb);
+ } else {
+ get_be32(pb); /* creation time */
+ get_be32(pb); /* modification time */
+ }
+
+ sc->time_scale = get_be32(pb);
+ st->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */
+
+ lang = get_be16(pb); /* language */
+ ff_mov_lang_to_iso639(lang, st->language);
+ get_be16(pb); /* quality */
+
+ return 0;
+}
+
+static int mov_read_mvhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ int version = get_byte(pb); /* version */
+ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
+
+ if (version == 1) {
+ get_be64(pb);
+ get_be64(pb);
+ } else {
+ get_be32(pb); /* creation time */
+ get_be32(pb); /* modification time */
+ }
+ c->time_scale = get_be32(pb); /* time scale */
+#ifdef DEBUG
+ av_log(NULL, AV_LOG_DEBUG, "time scale = %i\n", c->time_scale);
+#endif
+ c->duration = (version == 1) ? get_be64(pb) : get_be32(pb); /* duration */
+ get_be32(pb); /* preferred scale */
+
+ get_be16(pb); /* preferred volume */
+
+ url_fskip(pb, 10); /* reserved */
+
+ url_fskip(pb, 36); /* display matrix */
+
+ get_be32(pb); /* preview time */
+ get_be32(pb); /* preview duration */
+ get_be32(pb); /* poster time */
+ get_be32(pb); /* selection time */
+ get_be32(pb); /* selection duration */
+ get_be32(pb); /* current time */
+ get_be32(pb); /* next track ID */
+
+ return 0;
+}
+
+static int mov_read_smi(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+
+ if((uint64_t)atom.size > (1<<30))
+ return -1;
+
+ // currently SVQ3 decoder expect full STSD header - so let's fake it
+ // this should be fixed and just SMI header should be passed
+ av_free(st->codec->extradata);
+ st->codec->extradata_size = 0x5a + atom.size;
+ st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+
+ if (st->codec->extradata) {
+ strcpy(st->codec->extradata, "SVQ3"); // fake
+ get_buffer(pb, st->codec->extradata + 0x5a, atom.size);
+ dprintf("Reading SMI %"PRId64" %s\n", atom.size, st->codec->extradata + 0x5a);
+ } else
+ url_fskip(pb, atom.size);
+
+ return 0;
+}
+
+static int mov_read_enda(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+ int little_endian = get_be16(pb);
+
+ if (little_endian) {
+ switch (st->codec->codec_id) {
+ case CODEC_ID_PCM_S24BE:
+ st->codec->codec_id = CODEC_ID_PCM_S24LE;
+ break;
+ case CODEC_ID_PCM_S32BE:
+ st->codec->codec_id = CODEC_ID_PCM_S32LE;
+ break;
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+static int mov_read_alac(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+
+ // currently ALAC decoder expect full atom header - so let's fake it
+ // this should be fixed and just ALAC header should be passed
+
+ av_free(st->codec->extradata);
+ st->codec->extradata_size = 36;
+ st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+
+ if (st->codec->extradata) {
+ strcpy(st->codec->extradata + 4, "alac"); // fake
+ get_buffer(pb, st->codec->extradata + 8, 36 - 8);
+ dprintf("Reading alac %d %s\n", st->codec->extradata_size, st->codec->extradata);
+ } else
+ url_fskip(pb, atom.size);
+ return 0;
+}
+
+static int mov_read_wave(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+
+ if((uint64_t)atom.size > (1<<30))
+ return -1;
+
+ if (st->codec->codec_id == CODEC_ID_QDM2) {
+ // pass all frma atom to codec, needed at least for QDM2
+ av_free(st->codec->extradata);
+ st->codec->extradata_size = atom.size;
+ st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+
+ if (st->codec->extradata) {
+ get_buffer(pb, st->codec->extradata, atom.size);
+ } else
+ url_fskip(pb, atom.size);
+ } else if (atom.size > 8) { /* to read frma, esds atoms */
+ mov_read_default(c, pb, atom);
+ } else
+ url_fskip(pb, atom.size);
+ return 0;
+}
+
+static int mov_read_jp2h(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+
+ if((uint64_t)atom.size > (1<<30))
+ return -1;
+
+ av_free(st->codec->extradata);
+
+ st->codec->extradata_size = atom.size + 8;
+ st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+
+ /* pass all jp2h atom to codec */
+ if (st->codec->extradata) {
+ strcpy(st->codec->extradata + 4, "jp2h");
+ get_buffer(pb, st->codec->extradata + 8, atom.size);
+ } else
+ url_fskip(pb, atom.size);
+ return 0;
+}
+
+static int mov_read_avcC(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+
+ if((uint64_t)atom.size > (1<<30))
+ return -1;
+
+ av_free(st->codec->extradata);
+
+ st->codec->extradata_size = atom.size;
+ st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+
+ if (st->codec->extradata) {
+ get_buffer(pb, st->codec->extradata, atom.size);
+ } else
+ url_fskip(pb, atom.size);
+
+ return 0;
+}
+
+static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+ MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+ unsigned int i, entries;
+
+ get_byte(pb); /* version */
+ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
+
+ entries = get_be32(pb);
+
+ if(entries >= UINT_MAX/sizeof(int64_t))
+ return -1;
+
+ sc->chunk_count = entries;
+ sc->chunk_offsets = av_malloc(entries * sizeof(int64_t));
+ if (!sc->chunk_offsets)
+ return -1;
+ if (atom.type == MKTAG('s', 't', 'c', 'o')) {
+ for(i=0; i<entries; i++) {
+ sc->chunk_offsets[i] = get_be32(pb);
+ }
+ } else if (atom.type == MKTAG('c', 'o', '6', '4')) {
+ for(i=0; i<entries; i++) {
+ sc->chunk_offsets[i] = get_be64(pb);
+ }
+ } else
+ return -1;
+
+ return 0;
+}
+
+static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+ MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+ int entries, frames_per_sample;
+ uint32_t format;
+ uint8_t codec_name[32];
+
+ /* for palette traversal */
+ int color_depth;
+ int color_start;
+ int color_count;
+ int color_end;
+ int color_index;
+ int color_dec;
+ int color_greyscale;
+ unsigned char *color_table;
+ int j;
+ unsigned char r, g, b;
+
+ get_byte(pb); /* version */
+ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
+
+ entries = get_be32(pb);
+
+ while(entries--) { //Parsing Sample description table
+ enum CodecID id;
+ MOV_atom_t a = { 0, 0, 0 };
+ offset_t start_pos = url_ftell(pb);
+ int size = get_be32(pb); /* size */
+ format = get_le32(pb); /* data format */
+
+ get_be32(pb); /* reserved */
+ get_be16(pb); /* reserved */
+ get_be16(pb); /* index */
+
+ if (st->codec->codec_tag) {
+ /* multiple fourcc, just skip for now */
+ url_fskip(pb, size - (url_ftell(pb) - start_pos));
+ continue;
+ }
+
+ st->codec->codec_tag = format;
+ id = codec_get_id(mov_audio_tags, format);
+ if (st->codec->codec_type != CODEC_TYPE_VIDEO && id > 0) {
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ } else if (st->codec->codec_type != CODEC_TYPE_AUDIO && /* do not overwrite codec type */
+ format && format != MKTAG('m', 'p', '4', 's')) { /* skip old asf mpeg4 tag */
+ id = codec_get_id(mov_video_tags, format);
+ if (id <= 0)
+ id = codec_get_id(codec_bmp_tags, format);
+ if (id > 0)
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ }
+
+ dprintf("size=%d 4CC= %c%c%c%c codec_type=%d\n",
+ size,
+ (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff, (format >> 24) & 0xff,
+ st->codec->codec_type);
+
+ if(st->codec->codec_type==CODEC_TYPE_VIDEO) {
+ st->codec->codec_id = id;
+ get_be16(pb); /* version */
+ get_be16(pb); /* revision level */
+ get_be32(pb); /* vendor */
+ get_be32(pb); /* temporal quality */
+ get_be32(pb); /* spacial quality */
+
+ st->codec->width = get_be16(pb); /* width */
+ st->codec->height = get_be16(pb); /* height */
+
+ get_be32(pb); /* horiz resolution */
+ get_be32(pb); /* vert resolution */
+ get_be32(pb); /* data size, always 0 */
+ frames_per_sample = get_be16(pb); /* frames per samples */
+#ifdef DEBUG
+ av_log(NULL, AV_LOG_DEBUG, "frames/samples = %d\n", frames_per_sample);
+#endif
+ get_buffer(pb, codec_name, 32); /* codec name, pascal string (FIXME: true for mp4?) */
+ if (codec_name[0] <= 31) {
+ memcpy(st->codec->codec_name, &codec_name[1],codec_name[0]);
+ st->codec->codec_name[codec_name[0]] = 0;
+ }
+
+ st->codec->bits_per_sample = get_be16(pb); /* depth */
+ st->codec->color_table_id = get_be16(pb); /* colortable id */
+
+ /* figure out the palette situation */
+ color_depth = st->codec->bits_per_sample & 0x1F;
+ color_greyscale = st->codec->bits_per_sample & 0x20;
+
+ /* if the depth is 2, 4, or 8 bpp, file is palettized */
+ if ((color_depth == 2) || (color_depth == 4) ||
+ (color_depth == 8)) {
+
+ if (color_greyscale) {
+
+ /* compute the greyscale palette */
+ color_count = 1 << color_depth;
+ color_index = 255;
+ color_dec = 256 / (color_count - 1);
+ for (j = 0; j < color_count; j++) {
+ r = g = b = color_index;
+ c->palette_control.palette[j] =
+ (r << 16) | (g << 8) | (b);
+ color_index -= color_dec;
+ if (color_index < 0)
+ color_index = 0;
+ }
+
+ } else if (st->codec->color_table_id & 0x08) {
+
+ /* if flag bit 3 is set, use the default palette */
+ color_count = 1 << color_depth;
+ if (color_depth == 2)
+ color_table = ff_qt_default_palette_4;
+ else if (color_depth == 4)
+ color_table = ff_qt_default_palette_16;
+ else
+ color_table = ff_qt_default_palette_256;
+
+ for (j = 0; j < color_count; j++) {
+ r = color_table[j * 4 + 0];
+ g = color_table[j * 4 + 1];
+ b = color_table[j * 4 + 2];
+ c->palette_control.palette[j] =
+ (r << 16) | (g << 8) | (b);
+ }
+
+ } else {
+
+ /* load the palette from the file */
+ color_start = get_be32(pb);
+ color_count = get_be16(pb);
+ color_end = get_be16(pb);
+ for (j = color_start; j <= color_end; j++) {
+ /* each R, G, or B component is 16 bits;
+ * only use the top 8 bits; skip alpha bytes
+ * up front */
+ get_byte(pb);
+ get_byte(pb);
+ r = get_byte(pb);
+ get_byte(pb);
+ g = get_byte(pb);
+ get_byte(pb);
+ b = get_byte(pb);
+ get_byte(pb);
+ c->palette_control.palette[j] =
+ (r << 16) | (g << 8) | (b);
+ }
+ }
+
+ st->codec->palctrl = &c->palette_control;
+ st->codec->palctrl->palette_changed = 1;
+ } else
+ st->codec->palctrl = NULL;
+ } else if(st->codec->codec_type==CODEC_TYPE_AUDIO) {
+ int bits_per_sample;
+ uint16_t version = get_be16(pb);
+
+ st->codec->codec_id = id;
+ get_be16(pb); /* revision level */
+ get_be32(pb); /* vendor */
+
+ st->codec->channels = get_be16(pb); /* channel count */
+ dprintf("audio channels %d\n", st->codec->channels);
+ st->codec->bits_per_sample = get_be16(pb); /* sample size */
+ /* do we need to force to 16 for AMR ? */
+
+ /* handle specific s8 codec */
+ get_be16(pb); /* compression id = 0*/
+ get_be16(pb); /* packet size = 0 */
+
+ st->codec->sample_rate = ((get_be32(pb) >> 16));
+
+ switch (st->codec->codec_id) {
+ case CODEC_ID_PCM_S8:
+ case CODEC_ID_PCM_U8:
+ if (st->codec->bits_per_sample == 16)
+ st->codec->codec_id = CODEC_ID_PCM_S16BE;
+ break;
+ case CODEC_ID_PCM_S16LE:
+ case CODEC_ID_PCM_S16BE:
+ if (st->codec->bits_per_sample == 8)
+ st->codec->codec_id = CODEC_ID_PCM_S8;
+ else if (st->codec->bits_per_sample == 24)
+ st->codec->codec_id = CODEC_ID_PCM_S24BE;
+ break;
+ default:
+ break;
+ }
+
+ //Read QT version 1 fields. In version 0 theese dont exist
+ dprintf("version =%d, isom =%d\n",version,c->isom);
+ if(!c->isom) {
+ if(version==1) {
+ sc->sample_size_v1.den = get_be32(pb); /* samples per packet */
+ get_be32(pb); /* bytes per packet */
+ sc->sample_size_v1.num = get_be32(pb); /* bytes per frame */
+ get_be32(pb); /* bytes per sample */
+ } else if(version==2) {
+ get_be32(pb); /* sizeof struct only */
+ st->codec->sample_rate = av_int2dbl(get_be64(pb)); /* float 64 */
+ st->codec->channels = get_be32(pb);
+ get_be32(pb); /* always 0x7F000000 */
+ get_be32(pb); /* bits per channel if sound is uncompressed */
+ get_be32(pb); /* lcpm format specific flag */
+ get_be32(pb); /* bytes per audio packet if constant */
+ get_be32(pb); /* lpcm frames per audio packet if constant */
+ }
+ }
+
+ bits_per_sample = av_get_bits_per_sample(st->codec->codec_id);
+ if (bits_per_sample) {
+ st->codec->bits_per_sample = bits_per_sample;
+ sc->sample_size = (bits_per_sample >> 3) * st->codec->channels;
+ }
+ } else {
+ /* other codec type, just skip (rtp, mp4s, tmcd ...) */
+ url_fskip(pb, size - (url_ftell(pb) - start_pos));
+ }
+ /* this will read extra atoms at the end (wave, alac, damr, avcC, SMI ...) */
+ a.size = size - (url_ftell(pb) - start_pos);
+ if (a.size > 8)
+ mov_read_default(c, pb, a);
+ else if (a.size > 0)
+ url_fskip(pb, a.size);
+ }
+
+ if(st->codec->codec_type==CODEC_TYPE_AUDIO && st->codec->sample_rate==0 && sc->time_scale>1) {
+ st->codec->sample_rate= sc->time_scale;
+ }
+
+ /* special codec parameters handling */
+ switch (st->codec->codec_id) {
+#ifdef CONFIG_H261_DECODER
+ case CODEC_ID_H261:
+#endif
+#ifdef CONFIG_H263_DECODER
+ case CODEC_ID_H263:
+#endif
+#ifdef CONFIG_MPEG4_DECODER
+ case CODEC_ID_MPEG4:
+#endif
+ st->codec->width= 0; /* let decoder init width/height */
+ st->codec->height= 0;
+ break;
+#ifdef CONFIG_FAAD
+ case CODEC_ID_AAC:
+#endif
+#ifdef CONFIG_VORBIS_DECODER
+ case CODEC_ID_VORBIS:
+#endif
+ case CODEC_ID_MP3ON4:
+ st->codec->sample_rate= 0; /* let decoder init parameters properly */
+ break;
+#ifdef CONFIG_DV_DEMUXER
+ case CODEC_ID_DVAUDIO:
+ c->dv_fctx = av_alloc_format_context();
+ c->dv_demux = dv_init_demux(c->dv_fctx);
+ if (!c->dv_demux) {
+ av_log(c->fc, AV_LOG_ERROR, "dv demux context init error\n");
+ return -1;
+ }
+ sc->dv_audio_container = 1;
+ st->codec->codec_id = CODEC_ID_PCM_S16LE;
+ break;
+#endif
+ /* no ifdef since parameters are always those */
+ case CODEC_ID_AMR_WB:
+ st->codec->sample_rate= 16000;
+ st->codec->channels= 1; /* really needed */
+ break;
+ case CODEC_ID_AMR_NB:
+ st->codec->sample_rate= 8000;
+ st->codec->channels= 1; /* really needed */
+ break;
+ case CODEC_ID_MP2:
+ st->codec->codec_type = CODEC_TYPE_AUDIO; /* force type after stsd for m1a hdlr */
+ st->need_parsing = 1;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+ MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+ unsigned int i, entries;
+
+ get_byte(pb); /* version */
+ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
+
+ entries = get_be32(pb);
+
+ if(entries >= UINT_MAX / sizeof(MOV_sample_to_chunk_tbl))
+ return -1;
+
+#ifdef DEBUG
+av_log(NULL, AV_LOG_DEBUG, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);
+#endif
+ sc->sample_to_chunk_sz = entries;
+ sc->sample_to_chunk = av_malloc(entries * sizeof(MOV_sample_to_chunk_tbl));
+ if (!sc->sample_to_chunk)
+ return -1;
+ for(i=0; i<entries; i++) {
+ sc->sample_to_chunk[i].first = get_be32(pb);
+ sc->sample_to_chunk[i].count = get_be32(pb);
+ sc->sample_to_chunk[i].id = get_be32(pb);
+ }
+ return 0;
+}
+
+static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+ MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+ unsigned int i, entries;
+
+ get_byte(pb); /* version */
+ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
+
+ entries = get_be32(pb);
+
+ if(entries >= UINT_MAX / sizeof(long))
+ return -1;
+
+ sc->keyframe_count = entries;
+#ifdef DEBUG
+ av_log(NULL, AV_LOG_DEBUG, "keyframe_count = %ld\n", sc->keyframe_count);
+#endif
+ sc->keyframes = av_malloc(entries * sizeof(long));
+ if (!sc->keyframes)
+ return -1;
+ for(i=0; i<entries; i++) {
+ sc->keyframes[i] = get_be32(pb);
+#ifdef DEBUG
+/* av_log(NULL, AV_LOG_DEBUG, "keyframes[]=%ld\n", sc->keyframes[i]); */
+#endif
+ }
+ return 0;
+}
+
+static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+ MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+ unsigned int i, entries, sample_size;
+
+ get_byte(pb); /* version */
+ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
+
+ sample_size = get_be32(pb);
+ if (!sc->sample_size) /* do not overwrite value computed in stsd */
+ sc->sample_size = sample_size;
+ entries = get_be32(pb);
+ if(entries >= UINT_MAX / sizeof(long))
+ return -1;
+
+ sc->sample_count = entries;
+ if (sample_size)
+ return 0;
+
+#ifdef DEBUG
+ av_log(NULL, AV_LOG_DEBUG, "sample_size = %ld sample_count = %ld\n", sc->sample_size, sc->sample_count);
+#endif
+ sc->sample_sizes = av_malloc(entries * sizeof(long));
+ if (!sc->sample_sizes)
+ return -1;
+ for(i=0; i<entries; i++) {
+ sc->sample_sizes[i] = get_be32(pb);
+#ifdef DEBUG
+ av_log(NULL, AV_LOG_DEBUG, "sample_sizes[]=%ld\n", sc->sample_sizes[i]);
+#endif
+ }
+ return 0;
+}
+
+static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+ MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+ unsigned int i, entries;
+ int64_t duration=0;
+ int64_t total_sample_count=0;
+
+ get_byte(pb); /* version */
+ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
+ entries = get_be32(pb);
+ if(entries >= UINT_MAX / sizeof(Time2Sample))
+ return -1;
+
+ sc->stts_count = entries;
+ sc->stts_data = av_malloc(entries * sizeof(Time2Sample));
+
+#ifdef DEBUG
+av_log(NULL, AV_LOG_DEBUG, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries);
+#endif
+
+ sc->time_rate=0;
+
+ for(i=0; i<entries; i++) {
+ int sample_duration;
+ int sample_count;
+
+ sample_count=get_be32(pb);
+ sample_duration = get_be32(pb);
+ sc->stts_data[i].count= sample_count;
+ sc->stts_data[i].duration= sample_duration;
+
+ sc->time_rate= ff_gcd(sc->time_rate, sample_duration);
+
+ dprintf("sample_count=%d, sample_duration=%d\n",sample_count,sample_duration);
+
+ duration+=(int64_t)sample_duration*sample_count;
+ total_sample_count+=sample_count;
+ }
+
+ st->nb_frames= total_sample_count;
+ if(duration)
+ st->duration= duration;
+ return 0;
+}
+
+static int mov_read_ctts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+ MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+ unsigned int i, entries;
+
+ get_byte(pb); /* version */
+ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
+ entries = get_be32(pb);
+ if(entries >= UINT_MAX / sizeof(Time2Sample))
+ return -1;
+
+ sc->ctts_count = entries;
+ sc->ctts_data = av_malloc(entries * sizeof(Time2Sample));
+
+ dprintf("track[%i].ctts.entries = %i\n", c->fc->nb_streams-1, entries);
+
+ for(i=0; i<entries; i++) {
+ int count =get_be32(pb);
+ int duration =get_be32(pb);
+
+ if (duration < 0) {
+ av_log(c->fc, AV_LOG_ERROR, "negative ctts, ignoring\n");
+ sc->ctts_count = 0;
+ url_fskip(pb, 8 * (entries - i - 1));
+ break;
+ }
+ sc->ctts_data[i].count = count;
+ sc->ctts_data[i].duration= duration;
+
+ sc->time_rate= ff_gcd(sc->time_rate, duration);
+ }
+ return 0;
+}
+
+static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st;
+ MOVStreamContext *sc;
+
+ st = av_new_stream(c->fc, c->fc->nb_streams);
+ if (!st) return -2;
+ sc = av_mallocz(sizeof(MOVStreamContext));
+ if (!sc) {
+ av_free(st);
+ return -1;
+ }
+
+ st->priv_data = sc;
+ st->codec->codec_type = CODEC_TYPE_DATA;
+ st->start_time = 0; /* XXX: check */
+ c->streams[c->fc->nb_streams-1] = sc;
+
+ return mov_read_default(c, pb, atom);
+}
+
+static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+ int version = get_byte(pb);
+
+ get_byte(pb); get_byte(pb);
+ get_byte(pb); /* flags */
+ /*
+ MOV_TRACK_ENABLED 0x0001
+ MOV_TRACK_IN_MOVIE 0x0002
+ MOV_TRACK_IN_PREVIEW 0x0004
+ MOV_TRACK_IN_POSTER 0x0008
+ */
+
+ if (version == 1) {
+ get_be64(pb);
+ get_be64(pb);
+ } else {
+ get_be32(pb); /* creation time */
+ get_be32(pb); /* modification time */
+ }
+ st->id = (int)get_be32(pb); /* track id (NOT 0 !)*/
+ get_be32(pb); /* reserved */
+ st->start_time = 0; /* check */
+ (version == 1) ? get_be64(pb) : get_be32(pb); /* highlevel (considering edits) duration in movie timebase */
+ get_be32(pb); /* reserved */
+ get_be32(pb); /* reserved */
+
+ get_be16(pb); /* layer */
+ get_be16(pb); /* alternate group */
+ get_be16(pb); /* volume */
+ get_be16(pb); /* reserved */
+
+ url_fskip(pb, 36); /* display matrix */
+
+ /* those are fixed-point */
+ get_be32(pb); /* track width */
+ get_be32(pb); /* track height */
+
+ return 0;
+}
+
+/* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
+/* like the files created with Adobe Premiere 5.0, for samples see */
+/* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
+static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ int err;
+
+ if (atom.size < 8)
+ return 0; /* continue */
+ if (get_be32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */
+ url_fskip(pb, atom.size - 4);
+ return 0;
+ }
+ atom.type = get_le32(pb);
+ atom.offset += 8;
+ atom.size -= 8;
+ if (atom.type != MKTAG('m', 'd', 'a', 't')) {
+ url_fskip(pb, atom.size);
+ return 0;
+ }
+ err = mov_read_mdat(c, pb, atom);
+ return err;
+}
+
+static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+#ifdef CONFIG_ZLIB
+ ByteIOContext ctx;
+ uint8_t *cmov_data;
+ uint8_t *moov_data; /* uncompressed data */
+ long cmov_len, moov_len;
+ int ret;
+
+ get_be32(pb); /* dcom atom */
+ if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' ))
+ return -1;
+ if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) {
+ av_log(NULL, AV_LOG_ERROR, "unknown compression for cmov atom !");
+ return -1;
+ }
+ get_be32(pb); /* cmvd atom */
+ if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' ))
+ return -1;
+ moov_len = get_be32(pb); /* uncompressed size */
+ cmov_len = atom.size - 6 * 4;
+
+ cmov_data = av_malloc(cmov_len);
+ if (!cmov_data)
+ return -1;
+ moov_data = av_malloc(moov_len);
+ if (!moov_data) {
+ av_free(cmov_data);
+ return -1;
+ }
+ get_buffer(pb, cmov_data, cmov_len);
+ if(uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
+ return -1;
+ if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, NULL, NULL, NULL) != 0)
+ return -1;
+ atom.type = MKTAG( 'm', 'o', 'o', 'v' );
+ atom.offset = 0;
+ atom.size = moov_len;
+#ifdef DEBUG
+// { int fd = open("/tmp/uncompheader.mov", O_WRONLY | O_CREAT); write(fd, moov_data, moov_len); close(fd); }
+#endif
+ ret = mov_read_default(c, &ctx, atom);
+ av_free(moov_data);
+ av_free(cmov_data);
+ return ret;
+#else
+ av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n");
+ return -1;
+#endif
+}
+
+/* edit list atom */
+static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+ int i, edit_count;
+
+ get_byte(pb); /* version */
+ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
+ edit_count= c->streams[c->fc->nb_streams-1]->edit_count = get_be32(pb); /* entries */
+
+ for(i=0; i<edit_count; i++){
+ get_be32(pb); /* Track duration */
+ get_be32(pb); /* Media time */
+ get_be32(pb); /* Media rate */
+ }
+ dprintf("track[%i].edit_count = %i\n", c->fc->nb_streams-1, c->streams[c->fc->nb_streams-1]->edit_count);
+ return 0;
+}
+
+static const MOVParseTableEntry mov_default_parse_table[] = {
+/* mp4 atoms */
+{ MKTAG( 'c', 'o', '6', '4' ), mov_read_stco },
+{ MKTAG( 'c', 't', 't', 's' ), mov_read_ctts }, /* composition time to sample */
+{ MKTAG( 'e', 'd', 't', 's' ), mov_read_default },
+{ MKTAG( 'e', 'l', 's', 't' ), mov_read_elst },
+{ MKTAG( 'e', 'n', 'd', 'a' ), mov_read_enda },
+{ MKTAG( 'f', 't', 'y', 'p' ), mov_read_ftyp },
+{ MKTAG( 'h', 'd', 'l', 'r' ), mov_read_hdlr },
+{ MKTAG( 'j', 'p', '2', 'h' ), mov_read_jp2h },
+{ MKTAG( 'm', 'd', 'a', 't' ), mov_read_mdat },
+{ MKTAG( 'm', 'd', 'h', 'd' ), mov_read_mdhd },
+{ MKTAG( 'm', 'd', 'i', 'a' ), mov_read_default },
+{ MKTAG( 'm', 'i', 'n', 'f' ), mov_read_default },
+{ MKTAG( 'm', 'o', 'o', 'v' ), mov_read_moov },
+{ MKTAG( 'm', 'v', 'h', 'd' ), mov_read_mvhd },
+{ MKTAG( 'S', 'M', 'I', ' ' ), mov_read_smi }, /* Sorenson extension ??? */
+{ MKTAG( 'a', 'l', 'a', 'c' ), mov_read_alac }, /* alac specific atom */
+{ MKTAG( 'a', 'v', 'c', 'C' ), mov_read_avcC },
+{ MKTAG( 's', 't', 'b', 'l' ), mov_read_default },
+{ MKTAG( 's', 't', 'c', 'o' ), mov_read_stco },
+{ MKTAG( 's', 't', 's', 'c' ), mov_read_stsc },
+{ MKTAG( 's', 't', 's', 'd' ), mov_read_stsd }, /* sample description */
+{ MKTAG( 's', 't', 's', 's' ), mov_read_stss }, /* sync sample */
+{ MKTAG( 's', 't', 's', 'z' ), mov_read_stsz }, /* sample size */
+{ MKTAG( 's', 't', 't', 's' ), mov_read_stts },
+{ MKTAG( 't', 'k', 'h', 'd' ), mov_read_tkhd }, /* track header */
+{ MKTAG( 't', 'r', 'a', 'k' ), mov_read_trak },
+{ MKTAG( 'w', 'a', 'v', 'e' ), mov_read_wave },
+{ MKTAG( 'c', 't', 'a', 'b' ), mov_read_ctab },
+{ MKTAG( 'e', 's', 'd', 's' ), mov_read_esds },
+{ MKTAG( 'w', 'i', 'd', 'e' ), mov_read_wide }, /* place holder */
+{ MKTAG( 'c', 'm', 'o', 'v' ), mov_read_cmov },
+{ 0L, NULL }
+};
+
+static void mov_free_stream_context(MOVStreamContext *sc)
+{
+ if(sc) {
+ av_freep(&sc->ctts_data);
+ av_freep(&sc);
+ }
+}
+
+/* XXX: is it sufficient ? */
+static int mov_probe(AVProbeData *p)
+{
+ unsigned int offset;
+ uint32_t tag;
+ int score = 0;
+
+ /* check file header */
+ if (p->buf_size <= 12)
+ return 0;
+ offset = 0;
+ for(;;) {
+ /* ignore invalid offset */
+ if ((offset + 8) > (unsigned int)p->buf_size)
+ return score;
+ tag = LE_32(p->buf + offset + 4);
+ switch(tag) {
+ /* check for obvious tags */
+ case MKTAG( 'j', 'P', ' ', ' ' ): /* jpeg 2000 signature */
+ case MKTAG( 'm', 'o', 'o', 'v' ):
+ case MKTAG( 'm', 'd', 'a', 't' ):
+ case MKTAG( 'p', 'n', 'o', 't' ): /* detect movs with preview pics like ew.mov and april.mov */
+ case MKTAG( 'u', 'd', 't', 'a' ): /* Packet Video PVAuthor adds this and a lot of more junk */
+ return AVPROBE_SCORE_MAX;
+ /* those are more common words, so rate then a bit less */
+ case MKTAG( 'w', 'i', 'd', 'e' ):
+ case MKTAG( 'f', 'r', 'e', 'e' ):
+ case MKTAG( 'j', 'u', 'n', 'k' ):
+ case MKTAG( 'p', 'i', 'c', 't' ):
+ return AVPROBE_SCORE_MAX - 5;
+ case MKTAG( 'f', 't', 'y', 'p' ):
+ case MKTAG( 's', 'k', 'i', 'p' ):
+ case MKTAG( 'u', 'u', 'i', 'd' ):
+ offset = BE_32(p->buf+offset) + offset;
+ /* if we only find those cause probedata is too small at least rate them */
+ score = AVPROBE_SCORE_MAX - 50;
+ break;
+ default:
+ /* unrecognized tag */
+ return score;
+ }
+ }
+ return score;
+}
+
+static void mov_build_index(MOVContext *mov, AVStream *st)
+{
+ MOVStreamContext *sc = st->priv_data;
+ offset_t current_offset;
+ int64_t current_dts = 0;
+ int stts_index = 0;
+ int stsc_index = 0;
+ int stss_index = 0;
+ int i, j, k;
+
+ if (sc->sample_sizes || st->codec->codec_type == CODEC_TYPE_VIDEO || sc->dv_audio_container) {
+ int keyframe, sample_size;
+ int current_sample = 0;
+ int stts_sample = 0;
+ int distance = 0;
+
+ st->nb_frames = sc->sample_count;
+ for (i = 0; i < sc->chunk_count; i++) {
+ current_offset = sc->chunk_offsets[i];
+ if (stsc_index + 1 < sc->sample_to_chunk_sz && i + 1 == sc->sample_to_chunk[stsc_index + 1].first)
+ stsc_index++;
+ for (j = 0; j < sc->sample_to_chunk[stsc_index].count; j++) {
+ keyframe = !sc->keyframe_count || current_sample + 1 == sc->keyframes[stss_index];
+ if (keyframe) {
+ distance = 0;
+ if (stss_index + 1 < sc->keyframe_count)
+ stss_index++;
+ }
+ sample_size = sc->sample_size > 0 ? sc->sample_size : sc->sample_sizes[current_sample];
+ dprintf("AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", size %d, distance %d, keyframe %d\n",
+ st->index, current_sample, current_offset, current_dts, sample_size, distance, keyframe);
+ av_add_index_entry(st, current_offset, current_dts, sample_size, distance, keyframe ? AVINDEX_KEYFRAME : 0);
+ current_offset += sample_size;
+ assert(sc->stts_data[stts_index].duration % sc->time_rate == 0);
+ current_dts += sc->stts_data[stts_index].duration / sc->time_rate;
+ distance++;
+ stts_sample++;
+ if (current_sample + 1 < sc->sample_count)
+ current_sample++;
+ if (stts_index + 1 < sc->stts_count && stts_sample == sc->stts_data[stts_index].count) {
+ stts_sample = 0;
+ stts_index++;
+ }
+ }
+ }
+ } else { /* read whole chunk */
+ int chunk_samples, chunk_size, chunk_duration;
+
+ for (i = 0; i < sc->chunk_count; i++) {
+ current_offset = sc->chunk_offsets[i];
+ if (stsc_index + 1 < sc->sample_to_chunk_sz && i + 1 == sc->sample_to_chunk[stsc_index + 1].first)
+ stsc_index++;
+ chunk_samples = sc->sample_to_chunk[stsc_index].count;
+ /* get chunk size */
+ if (sc->sample_size > 1 || st->codec->codec_id == CODEC_ID_PCM_U8 || st->codec->codec_id == CODEC_ID_PCM_S8)
+ chunk_size = chunk_samples * sc->sample_size;
+ else if (sc->sample_size_v1.den > 0 && (chunk_samples * sc->sample_size_v1.num % sc->sample_size_v1.den == 0))
+ chunk_size = chunk_samples * sc->sample_size_v1.num / sc->sample_size_v1.den;
+ else { /* workaround to find nearest next chunk offset */
+ chunk_size = INT_MAX;
+ for (j = 0; j < mov->total_streams; j++) {
+ MOVStreamContext *msc = mov->streams[j];
+
+ for (k = msc->next_chunk; k < msc->chunk_count; k++) {
+ if (msc->chunk_offsets[k] > current_offset && msc->chunk_offsets[k] - current_offset < chunk_size) {
+ chunk_size = msc->chunk_offsets[k] - current_offset;
+ msc->next_chunk = k;
+ break;
+ }
+ }
+ }
+ /* check for last chunk */
+ if (chunk_size == INT_MAX)
+ for (j = 0; j < mov->mdat_count; j++) {
+ dprintf("mdat %d, offset %"PRIx64", size %"PRId64", current offset %"PRIx64"\n",
+ j, mov->mdat_list[j].offset, mov->mdat_list[j].size, current_offset);
+ if (mov->mdat_list[j].offset <= current_offset && mov->mdat_list[j].offset + mov->mdat_list[j].size > current_offset)
+ chunk_size = mov->mdat_list[j].offset + mov->mdat_list[j].size - current_offset;
+ }
+ assert(chunk_size != INT_MAX);
+ for (j = 0; j < mov->total_streams; j++) {
+ mov->streams[j]->next_chunk = 0;
+ }
+ }
+ av_add_index_entry(st, current_offset, current_dts, chunk_size, 0, AVINDEX_KEYFRAME);
+ /* get chunk duration */
+ chunk_duration = 0;
+ while (chunk_samples > 0) {
+ if (chunk_samples < sc->stts_data[stts_index].count) {
+ chunk_duration += sc->stts_data[stts_index].duration * chunk_samples;
+ sc->stts_data[stts_index].count -= chunk_samples;
+ break;
+ } else {
+ chunk_duration += sc->stts_data[stts_index].duration * chunk_samples;
+ chunk_samples -= sc->stts_data[stts_index].count;
+ if (stts_index + 1 < sc->stts_count) {
+ stts_index++;
+ }
+ }
+ }
+ dprintf("AVIndex stream %d, chunk %d, offset %"PRIx64", dts %"PRId64", size %d, duration %d\n",
+ st->index, i, current_offset, current_dts, chunk_size, chunk_duration);
+ assert(chunk_duration % sc->time_rate == 0);
+ current_dts += chunk_duration / sc->time_rate;
+ }
+ }
+ /* adjust sample count to avindex entries */
+ sc->sample_count = st->nb_index_entries;
+}
+
+static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ MOVContext *mov = (MOVContext *) s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int i, err;
+ MOV_atom_t atom = { 0, 0, 0 };
+
+ mov->fc = s;
+ mov->parse_table = mov_default_parse_table;
+
+ if(!url_is_streamed(pb)) /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
+ atom.size = url_fsize(pb);
+ else
+ atom.size = 0x7FFFFFFFFFFFFFFFLL;
+
+ /* check MOV header */
+ err = mov_read_default(mov, pb, atom);
+ if (err<0 || (!mov->found_moov && !mov->found_mdat)) {
+ av_log(s, AV_LOG_ERROR, "mov: header not found !!! (err:%d, moov:%d, mdat:%d) pos:%"PRId64"\n",
+ err, mov->found_moov, mov->found_mdat, url_ftell(pb));
+ return -1;
+ }
+ dprintf("on_parse_exit_offset=%d\n", (int) url_ftell(pb));
+
+ /* some cleanup : make sure we are on the mdat atom */
+ if(!url_is_streamed(pb) && (url_ftell(pb) != mov->mdat_offset))
+ url_fseek(pb, mov->mdat_offset, SEEK_SET);
+
+ mov->total_streams = s->nb_streams;
+
+ for(i=0; i<mov->total_streams; i++) {
+ MOVStreamContext *sc = mov->streams[i];
+
+ if(!sc->time_rate)
+ sc->time_rate=1;
+ if(!sc->time_scale)
+ sc->time_scale= mov->time_scale;
+ av_set_pts_info(s->streams[i], 64, sc->time_rate, sc->time_scale);
+
+ if(s->streams[i]->duration != AV_NOPTS_VALUE){
+ assert(s->streams[i]->duration % sc->time_rate == 0);
+ s->streams[i]->duration /= sc->time_rate;
+ }
+ sc->ffindex = i;
+ mov_build_index(mov, s->streams[i]);
+ }
+
+ for(i=0; i<mov->total_streams; i++) {
+ /* dont need those anymore */
+ av_freep(&mov->streams[i]->chunk_offsets);
+ av_freep(&mov->streams[i]->sample_to_chunk);
+ av_freep(&mov->streams[i]->sample_sizes);
+ av_freep(&mov->streams[i]->keyframes);
+ av_freep(&mov->streams[i]->stts_data);
+ }
+ av_freep(&mov->mdat_list);
+ return 0;
+}
+
+static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ MOVContext *mov = s->priv_data;
+ MOVStreamContext *sc = 0;
+ AVIndexEntry *sample = 0;
+ int64_t best_dts = INT64_MAX;
+ int i;
+
+ for (i = 0; i < mov->total_streams; i++) {
+ MOVStreamContext *msc = mov->streams[i];
+
+ if (s->streams[i]->discard != AVDISCARD_ALL && msc->current_sample < msc->sample_count) {
+ AVIndexEntry *current_sample = &s->streams[i]->index_entries[msc->current_sample];
+ int64_t dts = av_rescale(current_sample->timestamp * (int64_t)msc->time_rate, AV_TIME_BASE, msc->time_scale);
+
+ dprintf("stream %d, sample %ld, dts %"PRId64"\n", i, msc->current_sample, dts);
+ if (dts < best_dts) {
+ sample = current_sample;
+ best_dts = dts;
+ sc = msc;
+ }
+ }
+ }
+ if (!sample)
+ return -1;
+ /* must be done just before reading, to avoid infinite loop on sample */
+ sc->current_sample++;
+ if (sample->pos >= url_fsize(&s->pb)) {
+ av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n", sc->ffindex, sample->pos);
+ return -1;
+ }
+#ifdef CONFIG_DV_DEMUXER
+ if (sc->dv_audio_container) {
+ dv_get_packet(mov->dv_demux, pkt);
+ dprintf("dv audio pkt size %d\n", pkt->size);
+ } else {
+#endif
+ url_fseek(&s->pb, sample->pos, SEEK_SET);
+ av_get_packet(&s->pb, pkt, sample->size);
+#ifdef CONFIG_DV_DEMUXER
+ if (mov->dv_demux) {
+ void *pkt_destruct_func = pkt->destruct;
+ dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size);
+ pkt->destruct = pkt_destruct_func;
+ }
+ }
+#endif
+ pkt->stream_index = sc->ffindex;
+ pkt->dts = sample->timestamp;
+ if (sc->ctts_data) {
+ assert(sc->ctts_data[sc->sample_to_ctime_index].duration % sc->time_rate == 0);
+ pkt->pts = pkt->dts + sc->ctts_data[sc->sample_to_ctime_index].duration / sc->time_rate;
+ /* update ctts context */
+ sc->sample_to_ctime_sample++;
+ if (sc->sample_to_ctime_index < sc->ctts_count && sc->ctts_data[sc->sample_to_ctime_index].count == sc->sample_to_ctime_sample) {
+ sc->sample_to_ctime_index++;
+ sc->sample_to_ctime_sample = 0;
+ }
+ } else {
+ pkt->pts = pkt->dts;
+ }
+ pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? PKT_FLAG_KEY : 0;
+ pkt->pos = sample->pos;
+ dprintf("stream %d, pts %"PRId64", dts %"PRId64", pos 0x%"PRIx64", duration %d\n", pkt->stream_index, pkt->pts, pkt->dts, pkt->pos, pkt->duration);
+ return 0;
+}
+
+static int mov_seek_stream(AVStream *st, int64_t timestamp, int flags)
+{
+ MOVStreamContext *sc = st->priv_data;
+ int sample, time_sample;
+ int i;
+
+ sample = av_index_search_timestamp(st, timestamp, flags);
+ dprintf("stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
+ if (sample < 0) /* not sure what to do */
+ return -1;
+ sc->current_sample = sample;
+ dprintf("stream %d, found sample %ld\n", st->index, sc->current_sample);
+ /* adjust ctts index */
+ if (sc->ctts_data) {
+ time_sample = 0;
+ for (i = 0; i < sc->ctts_count; i++) {
+ time_sample += sc->ctts_data[i].count;
+ if (time_sample >= sc->current_sample) {
+ sc->sample_to_ctime_index = i;
+ sc->sample_to_ctime_sample = time_sample - sc->current_sample;
+ break;
+ }
+ }
+ }
+ return sample;
+}
+
+static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
+{
+ AVStream *st;
+ int64_t seek_timestamp, timestamp;
+ int sample;
+ int i;
+
+ if (stream_index >= s->nb_streams)
+ return -1;
+
+ st = s->streams[stream_index];
+ sample = mov_seek_stream(st, sample_time, flags);
+ if (sample < 0)
+ return -1;
+
+ /* adjust seek timestamp to found sample timestamp */
+ seek_timestamp = st->index_entries[sample].timestamp;
+
+ for (i = 0; i < s->nb_streams; i++) {
+ st = s->streams[i];
+ if (stream_index == i || st->discard == AVDISCARD_ALL)
+ continue;
+
+ timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
+ mov_seek_stream(st, timestamp, flags);
+ }
+ return 0;
+}
+
+static int mov_read_close(AVFormatContext *s)
+{
+ int i;
+ MOVContext *mov = (MOVContext *) s->priv_data;
+ for(i=0; i<mov->total_streams; i++)
+ mov_free_stream_context(mov->streams[i]);
+ /* free color tabs */
+ for(i=0; i<mov->ctab_size; i++)
+ av_freep(&mov->ctab[i]);
+ if(mov->dv_demux){
+ for(i=0; i<mov->dv_fctx->nb_streams; i++){
+ av_freep(&mov->dv_fctx->streams[i]->codec);
+ av_freep(&mov->dv_fctx->streams[i]);
+ }
+ av_freep(&mov->dv_fctx);
+ av_freep(&mov->dv_demux);
+ }
+ av_freep(&mov->ctab);
+ return 0;
+}
+
+AVInputFormat mov_demuxer = {
+ "mov,mp4,m4a,3gp,3g2,mj2",
+ "QuickTime/MPEG4/Motion JPEG 2000 format",
+ sizeof(MOVContext),
+ mov_probe,
+ mov_read_header,
+ mov_read_packet,
+ mov_read_close,
+ mov_read_seek,
+};
diff --git a/contrib/ffmpeg/libavformat/movenc.c b/contrib/ffmpeg/libavformat/movenc.c
new file mode 100644
index 000000000..736d1594a
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/movenc.c
@@ -0,0 +1,1724 @@
+/*
+ * MOV, 3GP, MP4 muxer
+ * Copyright (c) 2003 Thomas Raivio.
+ * Copyright (c) 2004 Gildas Bazin <gbazin at videolan dot 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
+ */
+#include "avformat.h"
+#include "riff.h"
+#include "avio.h"
+#include "isom.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+#define MOV_INDEX_CLUSTER_SIZE 16384
+#define globalTimescale 1000
+
+#define MODE_MP4 0
+#define MODE_MOV 1
+#define MODE_3GP 2
+#define MODE_PSP 3 // example working PSP command line:
+// ffmpeg -i testinput.avi -f psp -r 14.985 -s 320x240 -b 768 -ar 24000 -ab 32 M4V00001.MP4
+#define MODE_3G2 4
+
+typedef struct MOVIentry {
+ unsigned int flags, size;
+ uint64_t pos;
+ unsigned int samplesInChunk;
+ char key_frame;
+ unsigned int entries;
+ int64_t cts;
+ int64_t dts;
+} MOVIentry;
+
+typedef struct MOVIndex {
+ int mode;
+ int entry;
+ long timescale;
+ long time;
+ int64_t trackDuration;
+ long sampleCount;
+ long sampleDuration;
+ long sampleSize;
+ int hasKeyframes;
+ int hasBframes;
+ int language;
+ int trackID;
+ int tag;
+ AVCodecContext *enc;
+
+ int vosLen;
+ uint8_t *vosData;
+ MOVIentry *cluster;
+ int audio_vbr;
+} MOVTrack;
+
+typedef struct MOVContext {
+ int mode;
+ int64_t time;
+ int nb_streams;
+ offset_t mdat_pos;
+ uint64_t mdat_size;
+ long timescale;
+ MOVTrack tracks[MAX_STREAMS];
+} MOVContext;
+
+//FIXME supprt 64bit varaint with wide placeholders
+static offset_t updateSize (ByteIOContext *pb, offset_t pos)
+{
+ offset_t curpos = url_ftell(pb);
+ url_fseek(pb, pos, SEEK_SET);
+ put_be32(pb, curpos - pos); /* rewrite size */
+ url_fseek(pb, curpos, SEEK_SET);
+
+ return curpos - pos;
+}
+
+/* Chunk offset atom */
+static int mov_write_stco_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ int i;
+ int mode64 = 0; // use 32 bit size variant if possible
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); /* size */
+ if (pos > UINT32_MAX) {
+ mode64 = 1;
+ put_tag(pb, "co64");
+ } else
+ put_tag(pb, "stco");
+ put_be32(pb, 0); /* version & flags */
+ put_be32(pb, track->entry); /* entry count */
+ for (i=0; i<track->entry; i++) {
+ if(mode64 == 1)
+ put_be64(pb, track->cluster[i].pos);
+ else
+ put_be32(pb, track->cluster[i].pos);
+ }
+ return updateSize (pb, pos);
+}
+
+/* Sample size atom */
+static int mov_write_stsz_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ int equalChunks = 1;
+ int i, j, entries = 0, tst = -1, oldtst = -1;
+
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "stsz");
+ put_be32(pb, 0); /* version & flags */
+
+ for (i=0; i<track->entry; i++) {
+ tst = track->cluster[i].size/track->cluster[i].entries;
+ if(oldtst != -1 && tst != oldtst) {
+ equalChunks = 0;
+ }
+ oldtst = tst;
+ entries += track->cluster[i].entries;
+ }
+ if (equalChunks) {
+ int sSize = track->cluster[0].size/track->cluster[0].entries;
+ put_be32(pb, sSize); // sample size
+ put_be32(pb, entries); // sample count
+ }
+ else {
+ put_be32(pb, 0); // sample size
+ put_be32(pb, entries); // sample count
+ for (i=0; i<track->entry; i++) {
+ for ( j=0; j<track->cluster[i].entries; j++) {
+ put_be32(pb, track->cluster[i].size /
+ track->cluster[i].entries);
+ }
+ }
+ }
+ return updateSize (pb, pos);
+}
+
+/* Sample to chunk atom */
+static int mov_write_stsc_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ int index = 0, oldval = -1, i;
+ offset_t entryPos, curpos;
+
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "stsc");
+ put_be32(pb, 0); // version & flags
+ entryPos = url_ftell(pb);
+ put_be32(pb, track->entry); // entry count
+ for (i=0; i<track->entry; i++) {
+ if(oldval != track->cluster[i].samplesInChunk)
+ {
+ put_be32(pb, i+1); // first chunk
+ put_be32(pb, track->cluster[i].samplesInChunk); // samples per chunk
+ put_be32(pb, 0x1); // sample description index
+ oldval = track->cluster[i].samplesInChunk;
+ index++;
+ }
+ }
+ curpos = url_ftell(pb);
+ url_fseek(pb, entryPos, SEEK_SET);
+ put_be32(pb, index); // rewrite size
+ url_fseek(pb, curpos, SEEK_SET);
+
+ return updateSize (pb, pos);
+}
+
+/* Sync sample atom */
+static int mov_write_stss_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ offset_t curpos, entryPos;
+ int i, index = 0;
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); // size
+ put_tag(pb, "stss");
+ put_be32(pb, 0); // version & flags
+ entryPos = url_ftell(pb);
+ put_be32(pb, track->entry); // entry count
+ for (i=0; i<track->entry; i++) {
+ if(track->cluster[i].key_frame == 1) {
+ put_be32(pb, i+1);
+ index++;
+ }
+ }
+ curpos = url_ftell(pb);
+ url_fseek(pb, entryPos, SEEK_SET);
+ put_be32(pb, index); // rewrite size
+ url_fseek(pb, curpos, SEEK_SET);
+ return updateSize (pb, pos);
+}
+
+static int mov_write_amr_tag(ByteIOContext *pb, MOVTrack *track)
+{
+ put_be32(pb, 0x11); /* size */
+ if (track->mode == MODE_MOV) put_tag(pb, "samr");
+ else put_tag(pb, "damr");
+ put_tag(pb, "FFMP");
+ put_byte(pb, 0); /* decoder version */
+
+ put_be16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */
+ put_byte(pb, 0x00); /* Mode change period (no restriction) */
+ put_byte(pb, 0x01); /* Frames per sample */
+ return 0x11;
+}
+
+static int mov_write_enda_tag(ByteIOContext *pb)
+{
+ put_be32(pb, 10);
+ put_tag(pb, "enda");
+ put_be16(pb, 1); /* little endian */
+ return 10;
+}
+
+static unsigned int descrLength(unsigned int len)
+{
+ int i;
+ for(i=1; len>>(7*i); i++);
+ return len + 1 + i;
+}
+
+static void putDescr(ByteIOContext *pb, int tag, unsigned int size)
+{
+ int i= descrLength(size) - size - 2;
+ put_byte(pb, tag);
+ for(; i>0; i--)
+ put_byte(pb, (size>>(7*i)) | 0x80);
+ put_byte(pb, size & 0x7F);
+}
+
+static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic
+{
+ offset_t pos = url_ftell(pb);
+ int decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;
+
+ put_be32(pb, 0); // size
+ put_tag(pb, "esds");
+ put_be32(pb, 0); // Version
+
+ // ES descriptor
+ putDescr(pb, 0x03, 3 + descrLength(13 + decoderSpecificInfoLen) +
+ descrLength(1));
+ put_be16(pb, track->trackID);
+ put_byte(pb, 0x00); // flags (= no flags)
+
+ // DecoderConfig descriptor
+ putDescr(pb, 0x04, 13 + decoderSpecificInfoLen);
+
+ // Object type indication
+ put_byte(pb, codec_get_tag(ff_mov_obj_type, track->enc->codec_id));
+
+ // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
+ // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
+ if(track->enc->codec_type == CODEC_TYPE_AUDIO)
+ put_byte(pb, 0x15); // flags (= Audiostream)
+ else
+ put_byte(pb, 0x11); // flags (= Visualstream)
+
+ put_byte(pb, track->enc->rc_buffer_size>>(3+16)); // Buffersize DB (24 bits)
+ put_be16(pb, (track->enc->rc_buffer_size>>3)&0xFFFF); // Buffersize DB
+
+ put_be32(pb, FFMAX(track->enc->bit_rate, track->enc->rc_max_rate)); // maxbitrate (FIXME should be max rate in any 1 sec window)
+ if(track->enc->rc_max_rate != track->enc->rc_min_rate || track->enc->rc_min_rate==0)
+ put_be32(pb, 0); // vbr
+ else
+ put_be32(pb, track->enc->rc_max_rate); // avg bitrate
+
+ if (track->vosLen)
+ {
+ // DecoderSpecific info descriptor
+ putDescr(pb, 0x05, track->vosLen);
+ put_buffer(pb, track->vosData, track->vosLen);
+ }
+
+
+ // SL descriptor
+ putDescr(pb, 0x06, 1);
+ put_byte(pb, 0x02);
+ return updateSize (pb, pos);
+}
+
+static int mov_write_wave_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ offset_t pos = url_ftell(pb);
+
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "wave");
+
+ put_be32(pb, 12); /* size */
+ put_tag(pb, "frma");
+ put_le32(pb, track->tag);
+
+ if (track->enc->codec_id == CODEC_ID_AAC) {
+ /* useless atom needed by mplayer, ipod, not needed by quicktime */
+ put_be32(pb, 12); /* size */
+ put_tag(pb, "mp4a");
+ put_be32(pb, 0);
+ mov_write_esds_tag(pb, track);
+ } else if (track->enc->codec_id == CODEC_ID_PCM_S24LE ||
+ track->enc->codec_id == CODEC_ID_PCM_S32LE) {
+ mov_write_enda_tag(pb);
+ } else if (track->enc->codec_id == CODEC_ID_AMR_NB) {
+ mov_write_amr_tag(pb, track);
+ }
+
+ put_be32(pb, 8); /* size */
+ put_be32(pb, 0); /* null tag */
+
+ return updateSize (pb, pos);
+}
+
+static const CodecTag codec_movaudio_tags[] = {
+ { CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') },
+ { CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') },
+ { CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') },
+ { CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') },
+ { CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') },
+ { CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') },
+ { CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') },
+ { CODEC_ID_AMR_WB, MKTAG('s', 'a', 'w', 'b') },
+ { CODEC_ID_PCM_S16BE, MKTAG('t', 'w', 'o', 's') },
+ { CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') },
+ { CODEC_ID_PCM_S24BE, MKTAG('i', 'n', '2', '4') },
+ { CODEC_ID_PCM_S24LE, MKTAG('i', 'n', '2', '4') },
+ { CODEC_ID_PCM_S32BE, MKTAG('i', 'n', '3', '2') },
+ { CODEC_ID_PCM_S32LE, MKTAG('i', 'n', '3', '2') },
+ { CODEC_ID_MP3, MKTAG('.', 'm', 'p', '3') },
+ { CODEC_ID_NONE, 0 },
+};
+
+static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ offset_t pos = url_ftell(pb);
+ int version = track->mode == MODE_MOV &&
+ (track->audio_vbr ||
+ track->enc->codec_id == CODEC_ID_PCM_S32LE ||
+ track->enc->codec_id == CODEC_ID_PCM_S24LE);
+
+ put_be32(pb, 0); /* size */
+ put_le32(pb, track->tag); // store it byteswapped
+ put_be32(pb, 0); /* Reserved */
+ put_be16(pb, 0); /* Reserved */
+ put_be16(pb, 1); /* Data-reference index, XXX == 1 */
+
+ /* SoundDescription */
+ put_be16(pb, version); /* Version */
+ put_be16(pb, 0); /* Revision level */
+ put_be32(pb, 0); /* Reserved */
+
+ put_be16(pb, track->mode == MODE_MOV ? track->enc->channels : 2); /* Number of channels */
+ /* FIXME 8 bit for 'raw ' in mov */
+ put_be16(pb, 16); /* Reserved */
+
+ put_be16(pb, track->mode == MODE_MOV && track->audio_vbr ? -2 : 0); /* compression ID */
+ put_be16(pb, 0); /* packet size (= 0) */
+ put_be16(pb, track->timescale); /* Time scale */
+ put_be16(pb, 0); /* Reserved */
+
+ if(version == 1) { /* SoundDescription V1 extended info */
+ put_be32(pb, track->enc->frame_size); /* Samples per packet */
+ put_be32(pb, track->sampleSize / track->enc->channels); /* Bytes per packet */
+ put_be32(pb, track->sampleSize); /* Bytes per frame */
+ put_be32(pb, 2); /* Bytes per sample */
+ }
+
+ if(track->mode == MODE_MOV &&
+ (track->enc->codec_id == CODEC_ID_AAC ||
+ track->enc->codec_id == CODEC_ID_AMR_NB ||
+ track->enc->codec_id == CODEC_ID_PCM_S24LE ||
+ track->enc->codec_id == CODEC_ID_PCM_S32LE))
+ mov_write_wave_tag(pb, track);
+ else if(track->enc->codec_id == CODEC_ID_AAC)
+ mov_write_esds_tag(pb, track);
+ else if(track->enc->codec_id == CODEC_ID_AMR_NB)
+ mov_write_amr_tag(pb, track);
+
+ return updateSize (pb, pos);
+}
+
+static int mov_write_d263_tag(ByteIOContext *pb)
+{
+ put_be32(pb, 0xf); /* size */
+ put_tag(pb, "d263");
+ put_tag(pb, "FFMP");
+ put_byte(pb, 0); /* decoder version */
+ /* FIXME use AVCodecContext level/profile, when encoder will set values */
+ put_byte(pb, 0xa); /* level */
+ put_byte(pb, 0); /* profile */
+ return 0xf;
+}
+
+/* TODO: No idea about these values */
+static int mov_write_svq3_tag(ByteIOContext *pb)
+{
+ put_be32(pb, 0x15);
+ put_tag(pb, "SMI ");
+ put_tag(pb, "SEQH");
+ put_be32(pb, 0x5);
+ put_be32(pb, 0xe2c0211d);
+ put_be32(pb, 0xc0000000);
+ put_byte(pb, 0);
+ return 0x15;
+}
+
+static uint8_t *avc_find_startcode( uint8_t *p, uint8_t *end )
+{
+ uint8_t *a = p + 4 - ((int)p & 3);
+
+ for( end -= 3; p < a && p < end; p++ ) {
+ if( p[0] == 0 && p[1] == 0 && p[2] == 1 )
+ return p;
+ }
+
+ for( end -= 3; p < end; p += 4 ) {
+ uint32_t x = *(uint32_t*)p;
+// if( (x - 0x01000100) & (~x) & 0x80008000 ) // little endian
+// if( (x - 0x00010001) & (~x) & 0x00800080 ) // big endian
+ if( (x - 0x01010101) & (~x) & 0x80808080 ) { // generic
+ if( p[1] == 0 ) {
+ if( p[0] == 0 && p[2] == 1 )
+ return p-1;
+ if( p[2] == 0 && p[3] == 1 )
+ return p;
+ }
+ if( p[3] == 0 ) {
+ if( p[2] == 0 && p[4] == 1 )
+ return p+1;
+ if( p[4] == 0 && p[5] == 1 )
+ return p+2;
+ }
+ }
+ }
+
+ for( end += 3; p < end; p++ ) {
+ if( p[0] == 0 && p[1] == 0 && p[2] == 1 )
+ return p;
+ }
+
+ return end + 3;
+}
+
+static void avc_parse_nal_units(uint8_t **buf, int *size)
+{
+ ByteIOContext pb;
+ uint8_t *p = *buf;
+ uint8_t *end = p + *size;
+ uint8_t *nal_start, *nal_end;
+
+ url_open_dyn_buf(&pb);
+ nal_start = avc_find_startcode(p, end);
+ while (nal_start < end) {
+ while(!*(nal_start++));
+ nal_end = avc_find_startcode(nal_start, end);
+ put_be32(&pb, nal_end - nal_start);
+ put_buffer(&pb, nal_start, nal_end - nal_start);
+ nal_start = nal_end;
+ }
+ av_freep(buf);
+ *size = url_close_dyn_buf(&pb, buf);
+}
+
+static int mov_write_avcc_tag(ByteIOContext *pb, MOVTrack *track)
+{
+ offset_t pos = url_ftell(pb);
+
+ put_be32(pb, 0);
+ put_tag(pb, "avcC");
+ if (track->vosLen > 6) {
+ /* check for h264 start code */
+ if (BE_32(track->vosData) == 0x00000001) {
+ uint8_t *buf, *end;
+ uint32_t sps_size=0, pps_size=0;
+ uint8_t *sps=0, *pps=0;
+
+ avc_parse_nal_units(&track->vosData, &track->vosLen);
+ buf = track->vosData;
+ end = track->vosData + track->vosLen;
+
+ /* look for sps and pps */
+ while (buf < end) {
+ unsigned int size;
+ uint8_t nal_type;
+ size = BE_32(buf);
+ nal_type = buf[4] & 0x1f;
+ if (nal_type == 7) { /* SPS */
+ sps = buf + 4;
+ sps_size = size;
+ } else if (nal_type == 8) { /* PPS */
+ pps = buf + 4;
+ pps_size = size;
+ }
+ buf += size + 4;
+ }
+ assert(sps);
+ assert(pps);
+
+ put_byte(pb, 1); /* version */
+ put_byte(pb, sps[1]); /* profile */
+ put_byte(pb, sps[2]); /* profile compat */
+ put_byte(pb, sps[3]); /* level */
+ put_byte(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */
+ put_byte(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */
+
+ put_be16(pb, sps_size);
+ put_buffer(pb, sps, sps_size);
+ put_byte(pb, 1); /* number of pps */
+ put_be16(pb, pps_size);
+ put_buffer(pb, pps, pps_size);
+ } else {
+ put_buffer(pb, track->vosData, track->vosLen);
+ }
+ }
+ return updateSize(pb, pos);
+}
+
+static const CodecTag codec_movvideo_tags[] = {
+ { CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') },
+ { CODEC_ID_SVQ3, MKTAG('S', 'V', 'Q', '3') },
+ { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
+ { CODEC_ID_H263, MKTAG('h', '2', '6', '3') },
+ { CODEC_ID_H263, MKTAG('s', '2', '6', '3') },
+ { CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') },
+ /* special handling in mov_find_video_codec_tag */
+ { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') }, /* DV NTSC */
+ { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', 'p') }, /* DV PAL */
+ { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'p', 'p') }, /* DVCPRO PAL */
+ { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'n') }, /* DVCPRO50 NTSC */
+ { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'p') }, /* DVCPRO50 PAL */
+ { CODEC_ID_NONE, 0 },
+};
+
+static int mov_find_video_codec_tag(AVFormatContext *s, MOVTrack *track)
+{
+ int tag = track->enc->codec_tag;
+ if (!tag) {
+ if (track->enc->codec_id == CODEC_ID_DVVIDEO) {
+ if (track->enc->height == 480) { /* NTSC */
+ if (track->enc->pix_fmt == PIX_FMT_YUV422P)
+ tag = MKTAG('d', 'v', '5', 'n');
+ else
+ tag = MKTAG('d', 'v', 'c', ' ');
+ } else { /* assume PAL */
+ if (track->enc->pix_fmt == PIX_FMT_YUV422P)
+ tag = MKTAG('d', 'v', '5', 'p');
+ else if (track->enc->pix_fmt == PIX_FMT_YUV420P)
+ tag = MKTAG('d', 'v', 'c', 'p');
+ else
+ tag = MKTAG('d', 'v', 'p', 'p');
+ }
+ } else if (track->enc->codec_id == CODEC_ID_H263) {
+ if (track->mode == MODE_MOV)
+ tag = MKTAG('h', '2', '6', '3');
+ else
+ tag = MKTAG('s', '2', '6', '3');
+ } else {
+ tag = codec_get_tag(codec_movvideo_tags, track->enc->codec_id);
+ }
+ }
+ // if no mac fcc found, try with Microsoft tags
+ if (!tag) {
+ tag = codec_get_tag(codec_bmp_tags, track->enc->codec_id);
+ if (tag) {
+ av_log(s, AV_LOG_INFO, "Warning, using MS style video codec tag, the file may be unplayable!\n");
+ }
+ }
+ assert(tag);
+ return tag;
+}
+
+static int mov_find_audio_codec_tag(AVFormatContext *s, MOVTrack *track)
+{
+ int tag = track->enc->codec_tag;
+ if (!tag) {
+ tag = codec_get_tag(codec_movaudio_tags, track->enc->codec_id);
+ }
+ // if no mac fcc found, try with Microsoft tags
+ if (!tag) {
+ int ms_tag = codec_get_tag(codec_wav_tags, track->enc->codec_id);
+ if (ms_tag) {
+ tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
+ av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, the file may be unplayable!\n");
+ }
+ }
+ assert(tag);
+ return tag;
+}
+
+static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ offset_t pos = url_ftell(pb);
+ char compressor_name[32];
+
+ put_be32(pb, 0); /* size */
+ put_le32(pb, track->tag); // store it byteswapped
+ put_be32(pb, 0); /* Reserved */
+ put_be16(pb, 0); /* Reserved */
+ put_be16(pb, 1); /* Data-reference index */
+
+ put_be16(pb, 0); /* Codec stream version */
+ put_be16(pb, 0); /* Codec stream revision (=0) */
+ if (track->mode == MODE_MOV) {
+ put_tag(pb, "FFMP"); /* Vendor */
+ if(track->enc->codec_id == CODEC_ID_RAWVIDEO) {
+ put_be32(pb, 0); /* Temporal Quality */
+ put_be32(pb, 0x400); /* Spatial Quality = lossless*/
+ } else {
+ put_be32(pb, 0x200); /* Temporal Quality = normal */
+ put_be32(pb, 0x200); /* Spatial Quality = normal */
+ }
+ } else {
+ put_be32(pb, 0); /* Reserved */
+ put_be32(pb, 0); /* Reserved */
+ put_be32(pb, 0); /* Reserved */
+ }
+ put_be16(pb, track->enc->width); /* Video width */
+ put_be16(pb, track->enc->height); /* Video height */
+ put_be32(pb, 0x00480000); /* Horizontal resolution 72dpi */
+ put_be32(pb, 0x00480000); /* Vertical resolution 72dpi */
+ put_be32(pb, 0); /* Data size (= 0) */
+ put_be16(pb, 1); /* Frame count (= 1) */
+
+ memset(compressor_name,0,32);
+ /* FIXME not sure, ISO 14496-1 draft where it shall be set to 0 */
+ if (track->mode == MODE_MOV && track->enc->codec && track->enc->codec->name)
+ strncpy(compressor_name,track->enc->codec->name,31);
+ put_byte(pb, strlen(compressor_name));
+ put_buffer(pb, compressor_name, 31);
+
+ put_be16(pb, 0x18); /* Reserved */
+ put_be16(pb, 0xffff); /* Reserved */
+ if(track->enc->codec_id == CODEC_ID_MPEG4)
+ mov_write_esds_tag(pb, track);
+ else if(track->enc->codec_id == CODEC_ID_H263)
+ mov_write_d263_tag(pb);
+ else if(track->enc->codec_id == CODEC_ID_SVQ3)
+ mov_write_svq3_tag(pb);
+ else if(track->enc->codec_id == CODEC_ID_H264)
+ mov_write_avcc_tag(pb, track);
+
+ return updateSize (pb, pos);
+}
+
+static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "stsd");
+ put_be32(pb, 0); /* version & flags */
+ put_be32(pb, 1); /* entry count */
+ if (track->enc->codec_type == CODEC_TYPE_VIDEO)
+ mov_write_video_tag(pb, track);
+ else if (track->enc->codec_type == CODEC_TYPE_AUDIO)
+ mov_write_audio_tag(pb, track);
+ return updateSize(pb, pos);
+}
+
+static int mov_write_ctts_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ Time2Sample *ctts_entries;
+ uint32_t entries = 0;
+ uint32_t atom_size;
+ int i;
+
+ ctts_entries = av_malloc((track->entry + 1) * sizeof(*ctts_entries)); /* worst case */
+ ctts_entries[0].count = 1;
+ ctts_entries[0].duration = track->cluster[0].cts;
+ for (i=1; i<track->entry; i++) {
+ if (track->cluster[i].cts == ctts_entries[entries].duration) {
+ ctts_entries[entries].count++; /* compress */
+ } else {
+ entries++;
+ ctts_entries[entries].duration = track->cluster[i].cts;
+ ctts_entries[entries].count = 1;
+ }
+ }
+ entries++; /* last one */
+ atom_size = 16 + (entries * 8);
+ put_be32(pb, atom_size); /* size */
+ put_tag(pb, "ctts");
+ put_be32(pb, 0); /* version & flags */
+ put_be32(pb, entries); /* entry count */
+ for (i=0; i<entries; i++) {
+ put_be32(pb, ctts_entries[i].count);
+ put_be32(pb, ctts_entries[i].duration);
+ }
+ av_free(ctts_entries);
+ return atom_size;
+}
+
+/* Time to sample atom */
+static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ Time2Sample *stts_entries;
+ uint32_t entries = -1;
+ uint32_t atom_size;
+ int i;
+
+ if (track->enc->codec_type == CODEC_TYPE_AUDIO && !track->audio_vbr) {
+ stts_entries = av_malloc(sizeof(*stts_entries)); /* one entry */
+ stts_entries[0].count = track->sampleCount;
+ stts_entries[0].duration = 1;
+ entries = 1;
+ } else {
+ stts_entries = av_malloc(track->entry * sizeof(*stts_entries)); /* worst case */
+ for (i=0; i<track->entry; i++) {
+ int64_t duration = i + 1 == track->entry ?
+ track->trackDuration - track->cluster[i].dts + track->cluster[0].dts : /* readjusting */
+ track->cluster[i+1].dts - track->cluster[i].dts;
+ if (i && duration == stts_entries[entries].duration) {
+ stts_entries[entries].count++; /* compress */
+ } else {
+ entries++;
+ stts_entries[entries].duration = duration;
+ stts_entries[entries].count = 1;
+ }
+ }
+ entries++; /* last one */
+ }
+ atom_size = 16 + (entries * 8);
+ put_be32(pb, atom_size); /* size */
+ put_tag(pb, "stts");
+ put_be32(pb, 0); /* version & flags */
+ put_be32(pb, entries); /* entry count */
+ for (i=0; i<entries; i++) {
+ put_be32(pb, stts_entries[i].count);
+ put_be32(pb, stts_entries[i].duration);
+ }
+ av_free(stts_entries);
+ return atom_size;
+}
+
+static int mov_write_dref_tag(ByteIOContext *pb)
+{
+ put_be32(pb, 28); /* size */
+ put_tag(pb, "dref");
+ put_be32(pb, 0); /* version & flags */
+ put_be32(pb, 1); /* entry count */
+
+ put_be32(pb, 0xc); /* size */
+ put_tag(pb, "url ");
+ put_be32(pb, 1); /* version & flags */
+
+ return 28;
+}
+
+static int mov_write_stbl_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "stbl");
+ mov_write_stsd_tag(pb, track);
+ mov_write_stts_tag(pb, track);
+ if (track->enc->codec_type == CODEC_TYPE_VIDEO &&
+ track->hasKeyframes < track->entry)
+ mov_write_stss_tag(pb, track);
+ if (track->enc->codec_type == CODEC_TYPE_VIDEO &&
+ track->hasBframes)
+ mov_write_ctts_tag(pb, track);
+ mov_write_stsc_tag(pb, track);
+ mov_write_stsz_tag(pb, track);
+ mov_write_stco_tag(pb, track);
+ return updateSize(pb, pos);
+}
+
+static int mov_write_dinf_tag(ByteIOContext *pb)
+{
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "dinf");
+ mov_write_dref_tag(pb);
+ return updateSize(pb, pos);
+}
+
+static int mov_write_smhd_tag(ByteIOContext *pb)
+{
+ put_be32(pb, 16); /* size */
+ put_tag(pb, "smhd");
+ put_be32(pb, 0); /* version & flags */
+ put_be16(pb, 0); /* reserved (balance, normally = 0) */
+ put_be16(pb, 0); /* reserved */
+ return 16;
+}
+
+static int mov_write_vmhd_tag(ByteIOContext *pb)
+{
+ put_be32(pb, 0x14); /* size (always 0x14) */
+ put_tag(pb, "vmhd");
+ put_be32(pb, 0x01); /* version & flags */
+ put_be64(pb, 0); /* reserved (graphics mode = copy) */
+ return 0x14;
+}
+
+static int mov_write_hdlr_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ const char *descr, *hdlr, *hdlr_type;
+ offset_t pos = url_ftell(pb);
+
+ if (!track) { /* no media --> data handler */
+ hdlr = "dhlr";
+ hdlr_type = "url ";
+ descr = "DataHandler";
+ } else {
+ hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
+ if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
+ hdlr_type = "vide";
+ descr = "VideoHandler";
+ } else {
+ hdlr_type = "soun";
+ descr = "SoundHandler";
+ }
+ }
+
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "hdlr");
+ put_be32(pb, 0); /* Version & flags */
+ put_buffer(pb, hdlr, 4); /* handler */
+ put_tag(pb, hdlr_type); /* handler type */
+ put_be32(pb ,0); /* reserved */
+ put_be32(pb ,0); /* reserved */
+ put_be32(pb ,0); /* reserved */
+ put_byte(pb, strlen(descr)); /* string counter */
+ put_buffer(pb, descr, strlen(descr)); /* handler description */
+ return updateSize(pb, pos);
+}
+
+static int mov_write_minf_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "minf");
+ if(track->enc->codec_type == CODEC_TYPE_VIDEO)
+ mov_write_vmhd_tag(pb);
+ else
+ mov_write_smhd_tag(pb);
+ if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */
+ mov_write_hdlr_tag(pb, NULL);
+ mov_write_dinf_tag(pb);
+ mov_write_stbl_tag(pb, track);
+ return updateSize(pb, pos);
+}
+
+static int mov_write_mdhd_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ int version = track->trackDuration < INT32_MAX ? 0 : 1;
+
+ (version == 1) ? put_be32(pb, 44) : put_be32(pb, 32); /* size */
+ put_tag(pb, "mdhd");
+ put_byte(pb, version);
+ put_be24(pb, 0); /* flags */
+ if (version == 1) {
+ put_be64(pb, track->time);
+ put_be64(pb, track->time);
+ } else {
+ put_be32(pb, track->time); /* creation time */
+ put_be32(pb, track->time); /* modification time */
+ }
+ put_be32(pb, track->timescale); /* time scale (sample rate for audio) */
+ (version == 1) ? put_be64(pb, track->trackDuration) : put_be32(pb, track->trackDuration); /* duration */
+ put_be16(pb, track->language); /* language */
+ put_be16(pb, 0); /* reserved (quality) */
+ return 32;
+}
+
+static int mov_write_mdia_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "mdia");
+ mov_write_mdhd_tag(pb, track);
+ mov_write_hdlr_tag(pb, track);
+ mov_write_minf_tag(pb, track);
+ return updateSize(pb, pos);
+}
+
+static int mov_write_tkhd_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ int64_t duration = av_rescale_rnd(track->trackDuration, globalTimescale, track->timescale, AV_ROUND_UP);
+ int version = duration < INT32_MAX ? 0 : 1;
+
+ (version == 1) ? put_be32(pb, 104) : put_be32(pb, 92); /* size */
+ put_tag(pb, "tkhd");
+ put_byte(pb, version);
+ put_be24(pb, 0xf); /* flags (track enabled) */
+ if (version == 1) {
+ put_be64(pb, track->time);
+ put_be64(pb, track->time);
+ } else {
+ put_be32(pb, track->time); /* creation time */
+ put_be32(pb, track->time); /* modification time */
+ }
+ put_be32(pb, track->trackID); /* track-id */
+ put_be32(pb, 0); /* reserved */
+ (version == 1) ? put_be64(pb, duration) : put_be32(pb, duration);
+
+ put_be32(pb, 0); /* reserved */
+ put_be32(pb, 0); /* reserved */
+ put_be32(pb, 0x0); /* reserved (Layer & Alternate group) */
+ /* Volume, only for audio */
+ if(track->enc->codec_type == CODEC_TYPE_AUDIO)
+ put_be16(pb, 0x0100);
+ else
+ put_be16(pb, 0);
+ put_be16(pb, 0); /* reserved */
+
+ /* Matrix structure */
+ put_be32(pb, 0x00010000); /* reserved */
+ put_be32(pb, 0x0); /* reserved */
+ put_be32(pb, 0x0); /* reserved */
+ put_be32(pb, 0x0); /* reserved */
+ put_be32(pb, 0x00010000); /* reserved */
+ put_be32(pb, 0x0); /* reserved */
+ put_be32(pb, 0x0); /* reserved */
+ put_be32(pb, 0x0); /* reserved */
+ put_be32(pb, 0x40000000); /* reserved */
+
+ /* Track width and height, for visual only */
+ if(track->enc->codec_type == CODEC_TYPE_VIDEO) {
+ double sample_aspect_ratio = av_q2d(track->enc->sample_aspect_ratio);
+ if( !sample_aspect_ratio ) sample_aspect_ratio = 1;
+ put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000);
+ put_be32(pb, track->enc->height*0x10000);
+ }
+ else {
+ put_be32(pb, 0);
+ put_be32(pb, 0);
+ }
+ return 0x5c;
+}
+
+// This box seems important for the psp playback ... without it the movie seems to hang
+static int mov_write_edts_tag(ByteIOContext *pb, MOVTrack *track)
+{
+ put_be32(pb, 0x24); /* size */
+ put_tag(pb, "edts");
+ put_be32(pb, 0x1c); /* size */
+ put_tag(pb, "elst");
+ put_be32(pb, 0x0);
+ put_be32(pb, 0x1);
+
+ put_be32(pb, av_rescale_rnd(track->trackDuration, globalTimescale, track->timescale, AV_ROUND_UP)); /* duration ... doesn't seem to effect psp */
+
+ put_be32(pb, track->cluster[0].cts); /* first pts is cts since dts is 0 */
+ put_be32(pb, 0x00010000);
+ return 0x24;
+}
+
+// goes at the end of each track! ... Critical for PSP playback ("Incompatible data" without it)
+static int mov_write_uuid_tag_psp(ByteIOContext *pb, MOVTrack *mov)
+{
+ put_be32(pb, 0x34); /* size ... reports as 28 in mp4box! */
+ put_tag(pb, "uuid");
+ put_tag(pb, "USMT");
+ put_be32(pb, 0x21d24fce);
+ put_be32(pb, 0xbb88695c);
+ put_be32(pb, 0xfac9c740);
+ put_be32(pb, 0x1c); // another size here!
+ put_tag(pb, "MTDT");
+ put_be32(pb, 0x00010012);
+ put_be32(pb, 0x0a);
+ put_be32(pb, 0x55c40000);
+ put_be32(pb, 0x1);
+ put_be32(pb, 0x0);
+ return 0x34;
+}
+
+static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack* track)
+{
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "trak");
+ mov_write_tkhd_tag(pb, track);
+ if (track->mode == MODE_PSP || track->hasBframes)
+ mov_write_edts_tag(pb, track); // PSP Movies require edts box
+ mov_write_mdia_tag(pb, track);
+ if (track->mode == MODE_PSP)
+ mov_write_uuid_tag_psp(pb,track); // PSP Movies require this uuid box
+ return updateSize(pb, pos);
+}
+
+#if 0
+/* TODO: Not sorted out, but not necessary either */
+static int mov_write_iods_tag(ByteIOContext *pb, MOVContext *mov)
+{
+ put_be32(pb, 0x15); /* size */
+ put_tag(pb, "iods");
+ put_be32(pb, 0); /* version & flags */
+ put_be16(pb, 0x1007);
+ put_byte(pb, 0);
+ put_be16(pb, 0x4fff);
+ put_be16(pb, 0xfffe);
+ put_be16(pb, 0x01ff);
+ return 0x15;
+}
+#endif
+
+static int mov_write_mvhd_tag(ByteIOContext *pb, MOVContext *mov)
+{
+ int maxTrackID = 1, i;
+ int64_t maxTrackLenTemp, maxTrackLen = 0;
+ int version;
+
+ for (i=0; i<mov->nb_streams; i++) {
+ if(mov->tracks[i].entry > 0) {
+ maxTrackLenTemp = av_rescale_rnd(mov->tracks[i].trackDuration, globalTimescale, mov->tracks[i].timescale, AV_ROUND_UP);
+ if(maxTrackLen < maxTrackLenTemp)
+ maxTrackLen = maxTrackLenTemp;
+ if(maxTrackID < mov->tracks[i].trackID)
+ maxTrackID = mov->tracks[i].trackID;
+ }
+ }
+
+ version = maxTrackLen < UINT32_MAX ? 0 : 1;
+ (version == 1) ? put_be32(pb, 120) : put_be32(pb, 108); /* size */
+ put_tag(pb, "mvhd");
+ put_byte(pb, version);
+ put_be24(pb, 0); /* flags */
+ if (version == 1) {
+ put_be64(pb, mov->time);
+ put_be64(pb, mov->time);
+ } else {
+ put_be32(pb, mov->time); /* creation time */
+ put_be32(pb, mov->time); /* modification time */
+ }
+ put_be32(pb, mov->timescale); /* timescale */
+ (version == 1) ? put_be64(pb, maxTrackLen) : put_be32(pb, maxTrackLen); /* duration of longest track */
+
+ put_be32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
+ put_be16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
+ put_be16(pb, 0); /* reserved */
+ put_be32(pb, 0); /* reserved */
+ put_be32(pb, 0); /* reserved */
+
+ /* Matrix structure */
+ put_be32(pb, 0x00010000); /* reserved */
+ put_be32(pb, 0x0); /* reserved */
+ put_be32(pb, 0x0); /* reserved */
+ put_be32(pb, 0x0); /* reserved */
+ put_be32(pb, 0x00010000); /* reserved */
+ put_be32(pb, 0x0); /* reserved */
+ put_be32(pb, 0x0); /* reserved */
+ put_be32(pb, 0x0); /* reserved */
+ put_be32(pb, 0x40000000); /* reserved */
+
+ put_be32(pb, 0); /* reserved (preview time) */
+ put_be32(pb, 0); /* reserved (preview duration) */
+ put_be32(pb, 0); /* reserved (poster time) */
+ put_be32(pb, 0); /* reserved (selection time) */
+ put_be32(pb, 0); /* reserved (selection duration) */
+ put_be32(pb, 0); /* reserved (current time) */
+ put_be32(pb, maxTrackID+1); /* Next track id */
+ return 0x6c;
+}
+
+static int mov_write_itunes_hdlr_tag(ByteIOContext *pb, MOVContext* mov,
+ AVFormatContext *s)
+{
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "hdlr");
+ put_be32(pb, 0);
+ put_be32(pb, 0);
+ put_tag(pb, "mdir");
+ put_tag(pb, "appl");
+ put_be32(pb, 0);
+ put_be32(pb, 0);
+ put_be16(pb, 0);
+ return updateSize(pb, pos);
+}
+
+/* helper function to write a data tag with the specified string as data */
+static int mov_write_string_data_tag(ByteIOContext *pb, const char *data, int long_style)
+{
+ if(long_style){
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "data");
+ put_be32(pb, 1);
+ put_be32(pb, 0);
+ put_buffer(pb, data, strlen(data));
+ return updateSize(pb, pos);
+ }else{
+ put_be16(pb, strlen(data)); /* string length */
+ put_be16(pb, 0);
+ put_buffer(pb, data, strlen(data));
+ return strlen(data) + 4;
+ }
+}
+
+static int mov_write_string_tag(ByteIOContext *pb, const char *name, const char *value, int long_style){
+ int size = 0;
+ if ( value && value[0] ) {
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); /* size */
+ put_tag(pb, name);
+ mov_write_string_data_tag(pb, value, long_style);
+ size= updateSize(pb, pos);
+ }
+ return size;
+}
+
+/* iTunes year */
+static int mov_write_day_tag(ByteIOContext *pb, int year, int long_style)
+{
+ if(year){
+ char year_str[5];
+ snprintf(year_str, sizeof(year_str), "%04d", year);
+ return mov_write_string_tag(pb, "\251day", year_str, long_style);
+ }else
+ return 0;
+}
+
+/* iTunes track number */
+static int mov_write_trkn_tag(ByteIOContext *pb, MOVContext* mov,
+ AVFormatContext *s)
+{
+ int size = 0;
+ if ( s->track ) {
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "trkn");
+ {
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "data");
+ put_be32(pb, 0); // 8 bytes empty
+ put_be32(pb, 0);
+ put_be16(pb, 0); // empty
+ put_be16(pb, s->track); // track number
+ put_be16(pb, 0); // total track number
+ put_be16(pb, 0); // empty
+ updateSize(pb, pos);
+ }
+ size = updateSize(pb, pos);
+ }
+ return size;
+}
+
+/* iTunes meta data list */
+static int mov_write_ilst_tag(ByteIOContext *pb, MOVContext* mov,
+ AVFormatContext *s)
+{
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "ilst");
+ mov_write_string_tag(pb, "\251nam", s->title , 1);
+ mov_write_string_tag(pb, "\251ART", s->author , 1);
+ mov_write_string_tag(pb, "\251wrt", s->author , 1);
+ mov_write_string_tag(pb, "\251alb", s->album , 1);
+ mov_write_day_tag(pb, s->year ,1);
+ if(mov->tracks[0].enc && !(mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT))
+ mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 1);
+ mov_write_string_tag(pb, "\251cmt", s->comment , 1);
+ mov_write_string_tag(pb, "\251gen", s->genre , 1);
+ mov_write_trkn_tag(pb, mov, s);
+ return updateSize(pb, pos);
+}
+
+/* iTunes meta data tag */
+static int mov_write_meta_tag(ByteIOContext *pb, MOVContext* mov,
+ AVFormatContext *s)
+{
+ int size = 0;
+
+ // only save meta tag if required
+ if ( s->title[0] || s->author[0] || s->album[0] || s->year ||
+ s->comment[0] || s->genre[0] || s->track ) {
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "meta");
+ put_be32(pb, 0);
+ mov_write_itunes_hdlr_tag(pb, mov, s);
+ mov_write_ilst_tag(pb, mov, s);
+ size = updateSize(pb, pos);
+ }
+ return size;
+}
+
+static int mov_write_udta_tag(ByteIOContext *pb, MOVContext* mov,
+ AVFormatContext *s)
+{
+ offset_t pos = url_ftell(pb);
+ int i;
+
+ put_be32(pb, 0); /* size */
+ put_tag(pb, "udta");
+
+ /* iTunes meta data */
+ mov_write_meta_tag(pb, mov, s);
+
+ if(mov->mode == MODE_MOV){ // the title field breaks gtkpod with mp4 and my suspicion is that stuff isnt valid in mp4
+ /* Requirements */
+ for (i=0; i<mov->nb_streams; i++) {
+ if(mov->tracks[i].entry <= 0) continue;
+ if (mov->tracks[i].enc->codec_id == CODEC_ID_AAC ||
+ mov->tracks[i].enc->codec_id == CODEC_ID_MPEG4) {
+ mov_write_string_tag(pb, "\251req", "QuickTime 6.0 or greater", 0);
+ break;
+ }
+ }
+
+ mov_write_string_tag(pb, "\251nam", s->title , 0);
+ mov_write_string_tag(pb, "\251aut", s->author , 0);
+ mov_write_string_tag(pb, "\251alb", s->album , 0);
+ mov_write_day_tag(pb, s->year, 0);
+ if(mov->tracks[0].enc && !(mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT))
+ mov_write_string_tag(pb, "\251enc", LIBAVFORMAT_IDENT, 0);
+ mov_write_string_tag(pb, "\251des", s->comment , 0);
+ mov_write_string_tag(pb, "\251gen", s->genre , 0);
+ }
+
+ return updateSize(pb, pos);
+}
+
+static int utf8len(uint8_t *b){
+ int len=0;
+ int val;
+ while(*b){
+ GET_UTF8(val, *b++, return -1;)
+ len++;
+ }
+ return len;
+}
+
+static int ascii_to_wc (ByteIOContext *pb, uint8_t *b)
+{
+ int val;
+ while(*b){
+ GET_UTF8(val, *b++, return -1;)
+ put_be16(pb, val);
+ }
+ put_be16(pb, 0x00);
+ return 0;
+}
+
+static uint16_t language_code (const char *str)
+{
+ return ((((str[0]-0x60) & 0x1F)<<10) + (((str[1]-0x60) & 0x1F)<<5) + ((str[2]-0x60) & 0x1F));
+}
+
+static int mov_write_uuidusmt_tag (ByteIOContext *pb, AVFormatContext *s)
+{
+ size_t len, size;
+ offset_t pos, curpos;
+
+ size = 0;
+ if (s->title[0]) {
+ pos = url_ftell(pb);
+ put_be32(pb, 0); /* size placeholder*/
+ put_tag(pb, "uuid");
+ put_tag(pb, "USMT");
+ put_be32(pb, 0x21d24fce ); /* 96 bit UUID */
+ put_be32(pb, 0xbb88695c );
+ put_be32(pb, 0xfac9c740 );
+ size += 24;
+
+ put_be32(pb, 0); /* size placeholder*/
+ put_tag(pb, "MTDT");
+ put_be16(pb, 4);
+ size += 10;
+
+ // ?
+ put_be16(pb, 0x0C); /* size */
+ put_be32(pb, 0x0B); /* type */
+ put_be16(pb, language_code("und")); /* language */
+ put_be16(pb, 0x0); /* ? */
+ put_be16(pb, 0x021C); /* data */
+ size += 12;
+
+ // Encoder
+ len = utf8len(LIBAVCODEC_IDENT)+1;
+ if(len<=0)
+ goto not_utf8;
+ put_be16(pb, len*2+10); /* size */
+ put_be32(pb, 0x04); /* type */
+ put_be16(pb, language_code("eng")); /* language */
+ put_be16(pb, 0x01); /* ? */
+ ascii_to_wc(pb, LIBAVCODEC_IDENT);
+ size += len*2+10;
+
+ // Title
+ len = utf8len(s->title)+1;
+ if(len<=0)
+ goto not_utf8;
+ put_be16(pb, len*2+10); /* size */
+ put_be32(pb, 0x01); /* type */
+ put_be16(pb, language_code("eng")); /* language */
+ put_be16(pb, 0x01); /* ? */
+ ascii_to_wc (pb, s->title);
+ size += len*2+10;
+
+ // Date
+// snprintf(dt,32,"%04d/%02d/%02d %02d:%02d:%02d",t_st->tm_year+1900,t_st->tm_mon+1,t_st->tm_mday,t_st->tm_hour,t_st->tm_min,t_st->tm_sec);
+ len = utf8len("2006/04/01 11:11:11")+1;
+ if(len<=0)
+ goto not_utf8;
+ put_be16(pb, len*2+10); /* size */
+ put_be32(pb, 0x03); /* type */
+ put_be16(pb, language_code("und")); /* language */
+ put_be16(pb, 0x01); /* ? */
+ ascii_to_wc (pb, "2006/04/01 11:11:11");
+ size += len*2+10;
+
+ // size
+ curpos = url_ftell(pb);
+ url_fseek(pb, pos, SEEK_SET);
+ put_be32(pb, size);
+ url_fseek(pb, pos+24, SEEK_SET);
+ put_be32(pb, size-24);
+ url_fseek(pb, curpos, SEEK_SET);
+ }
+
+ return size;
+not_utf8:
+ av_log(s, AV_LOG_ERROR, "not utf8\n");
+ return -1;
+}
+
+static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov,
+ AVFormatContext *s)
+{
+ int i;
+ offset_t pos = url_ftell(pb);
+ put_be32(pb, 0); /* size placeholder*/
+ put_tag(pb, "moov");
+ mov->timescale = globalTimescale;
+
+ for (i=0; i<mov->nb_streams; i++) {
+ if(mov->tracks[i].entry <= 0) continue;
+
+ mov->tracks[i].time = mov->time;
+ mov->tracks[i].trackID = i+1;
+ }
+
+ mov_write_mvhd_tag(pb, mov);
+ //mov_write_iods_tag(pb, mov);
+ for (i=0; i<mov->nb_streams; i++) {
+ if(mov->tracks[i].entry > 0) {
+ mov_write_trak_tag(pb, &(mov->tracks[i]));
+ }
+ }
+
+ if (mov->mode == MODE_PSP)
+ mov_write_uuidusmt_tag(pb, s);
+ else
+ mov_write_udta_tag(pb, mov, s);
+
+ return updateSize(pb, pos);
+}
+
+static int mov_write_mdat_tag(ByteIOContext *pb, MOVContext* mov)
+{
+ put_be32(pb, 8); // placeholder for extended size field (64 bit)
+ put_tag(pb, mov->mode == MODE_MOV ? "wide" : "free");
+
+ mov->mdat_pos = url_ftell(pb);
+ put_be32(pb, 0); /* size placeholder*/
+ put_tag(pb, "mdat");
+ return 0;
+}
+
+/* TODO: This needs to be more general */
+static void mov_write_ftyp_tag (ByteIOContext *pb, AVFormatContext *s)
+{
+ MOVContext *mov = s->priv_data;
+
+ put_be32(pb, 0x14 ); /* size */
+ put_tag(pb, "ftyp");
+
+ if ( mov->mode == MODE_3GP )
+ put_tag(pb, "3gp4");
+ else if ( mov->mode == MODE_3G2 )
+ put_tag(pb, "3g2a");
+ else if ( mov->mode == MODE_PSP )
+ put_tag(pb, "MSNV");
+ else if ( mov->mode == MODE_MP4 )
+ put_tag(pb, "isom");
+ else
+ put_tag(pb, "qt ");
+
+ put_be32(pb, 0x200 );
+
+ if ( mov->mode == MODE_3GP )
+ put_tag(pb, "3gp4");
+ else if ( mov->mode == MODE_3G2 )
+ put_tag(pb, "3g2a");
+ else if ( mov->mode == MODE_PSP )
+ put_tag(pb, "MSNV");
+ else if ( mov->mode == MODE_MP4 )
+ put_tag(pb, "mp41");
+ else
+ put_tag(pb, "qt ");
+}
+
+static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s)
+{
+ AVCodecContext *VideoCodec = s->streams[0]->codec;
+ AVCodecContext *AudioCodec = s->streams[1]->codec;
+ int AudioRate = AudioCodec->sample_rate;
+ int FrameRate = ((VideoCodec->time_base.den) * (0x10000))/ (VideoCodec->time_base.num);
+ int audio_kbitrate= AudioCodec->bit_rate / 1000;
+ int video_kbitrate= FFMIN(VideoCodec->bit_rate / 1000, 800 - audio_kbitrate);
+
+ put_be32(pb, 0x94 ); /* size */
+ put_tag(pb, "uuid");
+ put_tag(pb, "PROF");
+
+ put_be32(pb, 0x21d24fce ); /* 96 bit UUID */
+ put_be32(pb, 0xbb88695c );
+ put_be32(pb, 0xfac9c740 );
+
+ put_be32(pb, 0x0 ); /* ? */
+ put_be32(pb, 0x3 ); /* 3 sections ? */
+
+ put_be32(pb, 0x14 ); /* size */
+ put_tag(pb, "FPRF");
+ put_be32(pb, 0x0 ); /* ? */
+ put_be32(pb, 0x0 ); /* ? */
+ put_be32(pb, 0x0 ); /* ? */
+
+ put_be32(pb, 0x2c ); /* size */
+ put_tag(pb, "APRF"); /* audio */
+ put_be32(pb, 0x0 );
+ put_be32(pb, 0x2 ); /* TrackID */
+ put_tag(pb, "mp4a");
+ put_be32(pb, 0x20f );
+ put_be32(pb, 0x0 );
+ put_be32(pb, audio_kbitrate);
+ put_be32(pb, audio_kbitrate);
+ put_be32(pb, AudioRate );
+ put_be32(pb, AudioCodec->channels );
+
+ put_be32(pb, 0x34 ); /* size */
+ put_tag(pb, "VPRF"); /* video */
+ put_be32(pb, 0x0 );
+ put_be32(pb, 0x1 ); /* TrackID */
+ if (VideoCodec->codec_id == CODEC_ID_H264) {
+ put_tag(pb, "avc1");
+ put_be16(pb, 0x014D );
+ put_be16(pb, 0x0015 );
+ } else {
+ put_tag(pb, "mp4v");
+ put_be16(pb, 0x0000 );
+ put_be16(pb, 0x0103 );
+ }
+ put_be32(pb, 0x0 );
+ put_be32(pb, video_kbitrate);
+ put_be32(pb, video_kbitrate);
+ put_be32(pb, FrameRate);
+ put_be32(pb, FrameRate);
+ put_be16(pb, VideoCodec->width);
+ put_be16(pb, VideoCodec->height);
+ put_be32(pb, 0x010001); /* ? */
+}
+
+static int mov_write_header(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+ MOVContext *mov = s->priv_data;
+ int i;
+
+ /* Default mode == MP4 */
+ mov->mode = MODE_MP4;
+
+ if (s->oformat != NULL) {
+ if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
+ else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3G2;
+ else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
+ else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP;
+
+ mov_write_ftyp_tag(pb,s);
+ if ( mov->mode == MODE_PSP ) {
+ if ( s->nb_streams != 2 ) {
+ av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
+ return -1;
+ }
+ mov_write_uuidprof_tag(pb,s);
+ }
+ }
+
+ for(i=0; i<s->nb_streams; i++){
+ AVStream *st= s->streams[i];
+ MOVTrack *track= &mov->tracks[i];
+
+ track->enc = st->codec;
+ track->language = ff_mov_iso639_to_lang(st->language, mov->mode != MODE_MOV);
+ track->mode = mov->mode;
+ if(st->codec->codec_type == CODEC_TYPE_VIDEO){
+ track->tag = mov_find_video_codec_tag(s, track);
+ track->timescale = st->codec->time_base.den;
+ track->sampleDuration = st->codec->time_base.num;
+ av_set_pts_info(st, 64, 1, st->codec->time_base.den);
+ }else if(st->codec->codec_type == CODEC_TYPE_AUDIO){
+ track->tag = mov_find_audio_codec_tag(s, track);
+ track->timescale = st->codec->sample_rate;
+ track->sampleDuration = st->codec->frame_size;
+ av_set_pts_info(st, 64, 1, st->codec->sample_rate);
+ switch(track->enc->codec_id){
+ case CODEC_ID_MP3:
+ case CODEC_ID_AAC:
+ case CODEC_ID_AMR_NB:
+ case CODEC_ID_AMR_WB:
+ track->audio_vbr = 1;
+ break;
+ default:
+ track->sampleSize = (av_get_bits_per_sample(st->codec->codec_id) >> 3) * st->codec->channels;
+ }
+ }
+ if (!track->sampleDuration) {
+ av_log(s, AV_LOG_ERROR, "track %d: sample duration is not set\n", i);
+ return -1;
+ }
+ }
+
+ mov_write_mdat_tag(pb, mov);
+ mov->time = s->timestamp + 0x7C25B080; //1970 based -> 1904 based
+ mov->nb_streams = s->nb_streams;
+
+ put_flush_packet(pb);
+
+ return 0;
+}
+
+static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ MOVContext *mov = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ MOVTrack *trk = &mov->tracks[pkt->stream_index];
+ AVCodecContext *enc = trk->enc;
+ unsigned int samplesInChunk = 0;
+ int size= pkt->size;
+
+ if (url_is_streamed(&s->pb)) return 0; /* Can't handle that */
+ if (!size) return 0; /* Discard 0 sized packets */
+
+ if (enc->codec_id == CODEC_ID_AMR_NB) {
+ /* We must find out how many AMR blocks there are in one packet */
+ static uint16_t packed_size[16] =
+ {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 0};
+ int len = 0;
+
+ while (len < size && samplesInChunk < 100) {
+ len += packed_size[(pkt->data[len] >> 3) & 0x0F];
+ samplesInChunk++;
+ }
+ if(samplesInChunk > 1){
+ av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, inplement a AVParser for it\n");
+ return -1;
+ }
+ } else if (trk->sampleSize)
+ samplesInChunk = size/trk->sampleSize;
+ else
+ samplesInChunk = 1;
+
+ /* copy extradata if it exists */
+ if (trk->vosLen == 0 && enc->extradata_size > 0) {
+ trk->vosLen = enc->extradata_size;
+ trk->vosData = av_malloc(trk->vosLen);
+ memcpy(trk->vosData, enc->extradata, trk->vosLen);
+ }
+
+ if (enc->codec_id == CODEC_ID_H264 && trk->vosLen > 0 && *(uint8_t *)trk->vosData != 1) {
+ /* from x264 or from bytestream h264 */
+ /* nal reformating needed */
+ avc_parse_nal_units(&pkt->data, &pkt->size);
+ assert(pkt->size);
+ size = pkt->size;
+ }
+
+ if (!(trk->entry % MOV_INDEX_CLUSTER_SIZE)) {
+ trk->cluster = av_realloc(trk->cluster, (trk->entry + MOV_INDEX_CLUSTER_SIZE) * sizeof(*trk->cluster));
+ if (!trk->cluster)
+ return -1;
+ }
+
+ trk->cluster[trk->entry].pos = url_ftell(pb);
+ trk->cluster[trk->entry].samplesInChunk = samplesInChunk;
+ trk->cluster[trk->entry].size = size;
+ trk->cluster[trk->entry].entries = samplesInChunk;
+ trk->cluster[trk->entry].dts = pkt->dts;
+ trk->trackDuration = pkt->dts - trk->cluster[0].dts + pkt->duration;
+
+ if(enc->codec_type == CODEC_TYPE_VIDEO) {
+ if (pkt->dts != pkt->pts)
+ trk->hasBframes = 1;
+ trk->cluster[trk->entry].cts = pkt->pts - pkt->dts;
+ trk->cluster[trk->entry].key_frame = !!(pkt->flags & PKT_FLAG_KEY);
+ if(trk->cluster[trk->entry].key_frame)
+ trk->hasKeyframes++;
+ }
+ trk->entry++;
+ trk->sampleCount += samplesInChunk;
+ mov->mdat_size += size;
+
+ put_buffer(pb, pkt->data, size);
+
+ put_flush_packet(pb);
+ return 0;
+}
+
+static int mov_write_trailer(AVFormatContext *s)
+{
+ MOVContext *mov = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int res = 0;
+ int i;
+
+ offset_t moov_pos = url_ftell(pb);
+
+ /* Write size of mdat tag */
+ if (mov->mdat_size+8 <= UINT32_MAX) {
+ url_fseek(pb, mov->mdat_pos, SEEK_SET);
+ put_be32(pb, mov->mdat_size+8);
+ } else {
+ /* overwrite 'wide' placeholder atom */
+ url_fseek(pb, mov->mdat_pos - 8, SEEK_SET);
+ put_be32(pb, 1); /* special value: real atom size will be 64 bit value after tag field */
+ put_tag(pb, "mdat");
+ put_be64(pb, mov->mdat_size+16);
+ }
+ url_fseek(pb, moov_pos, SEEK_SET);
+
+ mov_write_moov_tag(pb, mov, s);
+
+ for (i=0; i<mov->nb_streams; i++) {
+ av_freep(&mov->tracks[i].cluster);
+
+ if( mov->tracks[i].vosLen ) av_free( mov->tracks[i].vosData );
+
+ }
+
+ put_flush_packet(pb);
+
+ return res;
+}
+
+#ifdef CONFIG_MOV_MUXER
+AVOutputFormat mov_muxer = {
+ "mov",
+ "mov format",
+ NULL,
+ "mov",
+ sizeof(MOVContext),
+ CODEC_ID_AAC,
+ CODEC_ID_MPEG4,
+ mov_write_header,
+ mov_write_packet,
+ mov_write_trailer,
+ .flags = AVFMT_GLOBALHEADER,
+};
+#endif
+#ifdef CONFIG_TGP_MUXER
+AVOutputFormat tgp_muxer = {
+ "3gp",
+ "3gp format",
+ NULL,
+ "3gp",
+ sizeof(MOVContext),
+ CODEC_ID_AMR_NB,
+ CODEC_ID_H263,
+ mov_write_header,
+ mov_write_packet,
+ mov_write_trailer,
+ .flags = AVFMT_GLOBALHEADER,
+};
+#endif
+#ifdef CONFIG_MP4_MUXER
+AVOutputFormat mp4_muxer = {
+ "mp4",
+ "mp4 format",
+ "application/mp4",
+ "mp4,m4a",
+ sizeof(MOVContext),
+ CODEC_ID_AAC,
+ CODEC_ID_MPEG4,
+ mov_write_header,
+ mov_write_packet,
+ mov_write_trailer,
+ .flags = AVFMT_GLOBALHEADER,
+};
+#endif
+#ifdef CONFIG_PSP_MUXER
+AVOutputFormat psp_muxer = {
+ "psp",
+ "psp mp4 format",
+ NULL,
+ "mp4,psp",
+ sizeof(MOVContext),
+ CODEC_ID_AAC,
+ CODEC_ID_MPEG4,
+ mov_write_header,
+ mov_write_packet,
+ mov_write_trailer,
+ .flags = AVFMT_GLOBALHEADER,
+};
+#endif
+#ifdef CONFIG_TG2_MUXER
+AVOutputFormat tg2_muxer = {
+ "3g2",
+ "3gp2 format",
+ NULL,
+ "3g2",
+ sizeof(MOVContext),
+ CODEC_ID_AMR_NB,
+ CODEC_ID_H263,
+ mov_write_header,
+ mov_write_packet,
+ mov_write_trailer,
+ .flags = AVFMT_GLOBALHEADER,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/mp3.c b/contrib/ffmpeg/libavformat/mp3.c
new file mode 100644
index 000000000..723980c83
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/mp3.c
@@ -0,0 +1,430 @@
+/*
+ * MP3 muxer and demuxer
+ * 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 "avformat.h"
+#include "mpegaudio.h"
+
+#define ID3_HEADER_SIZE 10
+#define ID3_TAG_SIZE 128
+
+#define ID3_GENRE_MAX 125
+
+static const char *id3_genre_str[ID3_GENRE_MAX + 1] = {
+ [0] = "Blues",
+ [1] = "Classic Rock",
+ [2] = "Country",
+ [3] = "Dance",
+ [4] = "Disco",
+ [5] = "Funk",
+ [6] = "Grunge",
+ [7] = "Hip-Hop",
+ [8] = "Jazz",
+ [9] = "Metal",
+ [10] = "New Age",
+ [11] = "Oldies",
+ [12] = "Other",
+ [13] = "Pop",
+ [14] = "R&B",
+ [15] = "Rap",
+ [16] = "Reggae",
+ [17] = "Rock",
+ [18] = "Techno",
+ [19] = "Industrial",
+ [20] = "Alternative",
+ [21] = "Ska",
+ [22] = "Death Metal",
+ [23] = "Pranks",
+ [24] = "Soundtrack",
+ [25] = "Euro-Techno",
+ [26] = "Ambient",
+ [27] = "Trip-Hop",
+ [28] = "Vocal",
+ [29] = "Jazz+Funk",
+ [30] = "Fusion",
+ [31] = "Trance",
+ [32] = "Classical",
+ [33] = "Instrumental",
+ [34] = "Acid",
+ [35] = "House",
+ [36] = "Game",
+ [37] = "Sound Clip",
+ [38] = "Gospel",
+ [39] = "Noise",
+ [40] = "AlternRock",
+ [41] = "Bass",
+ [42] = "Soul",
+ [43] = "Punk",
+ [44] = "Space",
+ [45] = "Meditative",
+ [46] = "Instrumental Pop",
+ [47] = "Instrumental Rock",
+ [48] = "Ethnic",
+ [49] = "Gothic",
+ [50] = "Darkwave",
+ [51] = "Techno-Industrial",
+ [52] = "Electronic",
+ [53] = "Pop-Folk",
+ [54] = "Eurodance",
+ [55] = "Dream",
+ [56] = "Southern Rock",
+ [57] = "Comedy",
+ [58] = "Cult",
+ [59] = "Gangsta",
+ [60] = "Top 40",
+ [61] = "Christian Rap",
+ [62] = "Pop/Funk",
+ [63] = "Jungle",
+ [64] = "Native American",
+ [65] = "Cabaret",
+ [66] = "New Wave",
+ [67] = "Psychadelic",
+ [68] = "Rave",
+ [69] = "Showtunes",
+ [70] = "Trailer",
+ [71] = "Lo-Fi",
+ [72] = "Tribal",
+ [73] = "Acid Punk",
+ [74] = "Acid Jazz",
+ [75] = "Polka",
+ [76] = "Retro",
+ [77] = "Musical",
+ [78] = "Rock & Roll",
+ [79] = "Hard Rock",
+ [80] = "Folk",
+ [81] = "Folk-Rock",
+ [82] = "National Folk",
+ [83] = "Swing",
+ [84] = "Fast Fusion",
+ [85] = "Bebob",
+ [86] = "Latin",
+ [87] = "Revival",
+ [88] = "Celtic",
+ [89] = "Bluegrass",
+ [90] = "Avantgarde",
+ [91] = "Gothic Rock",
+ [92] = "Progressive Rock",
+ [93] = "Psychedelic Rock",
+ [94] = "Symphonic Rock",
+ [95] = "Slow Rock",
+ [96] = "Big Band",
+ [97] = "Chorus",
+ [98] = "Easy Listening",
+ [99] = "Acoustic",
+ [100] = "Humour",
+ [101] = "Speech",
+ [102] = "Chanson",
+ [103] = "Opera",
+ [104] = "Chamber Music",
+ [105] = "Sonata",
+ [106] = "Symphony",
+ [107] = "Booty Bass",
+ [108] = "Primus",
+ [109] = "Porn Groove",
+ [110] = "Satire",
+ [111] = "Slow Jam",
+ [112] = "Club",
+ [113] = "Tango",
+ [114] = "Samba",
+ [115] = "Folklore",
+ [116] = "Ballad",
+ [117] = "Power Ballad",
+ [118] = "Rhythmic Soul",
+ [119] = "Freestyle",
+ [120] = "Duet",
+ [121] = "Punk Rock",
+ [122] = "Drum Solo",
+ [123] = "A capella",
+ [124] = "Euro-House",
+ [125] = "Dance Hall",
+};
+
+/* buf must be ID3_HEADER_SIZE byte long */
+static int id3_match(const uint8_t *buf)
+{
+ return (buf[0] == 'I' &&
+ buf[1] == 'D' &&
+ buf[2] == '3' &&
+ buf[3] != 0xff &&
+ buf[4] != 0xff &&
+ (buf[6] & 0x80) == 0 &&
+ (buf[7] & 0x80) == 0 &&
+ (buf[8] & 0x80) == 0 &&
+ (buf[9] & 0x80) == 0);
+}
+
+static void id3_get_string(char *str, int str_size,
+ const uint8_t *buf, int buf_size)
+{
+ int i, c;
+ char *q;
+
+ q = str;
+ for(i = 0; i < buf_size; i++) {
+ c = buf[i];
+ if (c == '\0')
+ break;
+ if ((q - str) >= str_size - 1)
+ break;
+ *q++ = c;
+ }
+ *q = '\0';
+}
+
+/* 'buf' must be ID3_TAG_SIZE byte long */
+static int id3_parse_tag(AVFormatContext *s, const uint8_t *buf)
+{
+ char str[5];
+ int genre;
+
+ if (!(buf[0] == 'T' &&
+ buf[1] == 'A' &&
+ buf[2] == 'G'))
+ return -1;
+ id3_get_string(s->title, sizeof(s->title), buf + 3, 30);
+ id3_get_string(s->author, sizeof(s->author), buf + 33, 30);
+ id3_get_string(s->album, sizeof(s->album), buf + 63, 30);
+ id3_get_string(str, sizeof(str), buf + 93, 4);
+ s->year = atoi(str);
+ id3_get_string(s->comment, sizeof(s->comment), buf + 97, 30);
+ if (buf[125] == 0 && buf[126] != 0)
+ s->track = buf[126];
+ genre = buf[127];
+ if (genre <= ID3_GENRE_MAX)
+ pstrcpy(s->genre, sizeof(s->genre), id3_genre_str[genre]);
+ return 0;
+}
+
+static void id3_create_tag(AVFormatContext *s, uint8_t *buf)
+{
+ int v, i;
+
+ memset(buf, 0, ID3_TAG_SIZE); /* fail safe */
+ buf[0] = 'T';
+ buf[1] = 'A';
+ buf[2] = 'G';
+ strncpy(buf + 3, s->title, 30);
+ strncpy(buf + 33, s->author, 30);
+ strncpy(buf + 63, s->album, 30);
+ v = s->year;
+ if (v > 0) {
+ for(i = 0;i < 4; i++) {
+ buf[96 - i] = '0' + (v % 10);
+ v = v / 10;
+ }
+ }
+ strncpy(buf + 97, s->comment, 30);
+ if (s->track != 0) {
+ buf[125] = 0;
+ buf[126] = s->track;
+ }
+ for(i = 0; i <= ID3_GENRE_MAX; i++) {
+ if (!strcasecmp(s->genre, id3_genre_str[i])) {
+ buf[127] = i;
+ break;
+ }
+ }
+}
+
+/* mp3 read */
+
+static int mp3_read_probe(AVProbeData *p)
+{
+ int max_frames, first_frames;
+ int fsize, frames, sample_rate;
+ uint32_t header;
+ uint8_t *buf, *buf2, *end;
+ AVCodecContext avctx;
+
+ if(p->buf_size < ID3_HEADER_SIZE)
+ return 0;
+
+ if(id3_match(p->buf))
+ return AVPROBE_SCORE_MAX/2+1; // this must be less then mpeg-ps because some retards put id3 tage before mpeg-ps files
+
+ max_frames = 0;
+ buf = p->buf;
+ end = buf + FFMIN(4096, p->buf_size - sizeof(uint32_t));
+
+ for(; buf < end; buf++) {
+ buf2 = buf;
+
+ for(frames = 0; buf2 < end; frames++) {
+ header = (buf2[0] << 24) | (buf2[1] << 16) | (buf2[2] << 8) | buf2[3];
+ fsize = mpa_decode_header(&avctx, header, &sample_rate);
+ if(fsize < 0)
+ break;
+ buf2 += fsize;
+ }
+ max_frames = FFMAX(max_frames, frames);
+ if(buf == p->buf)
+ first_frames= frames;
+ }
+ if (first_frames>=3) return AVPROBE_SCORE_MAX/2+1;
+ else if(max_frames>=3) return AVPROBE_SCORE_MAX/4;
+ else if(max_frames>=1) return 1;
+ else return 0;
+}
+
+static int mp3_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ AVStream *st;
+ uint8_t buf[ID3_TAG_SIZE];
+ int len, ret, filesize;
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_MP3;
+ st->need_parsing = 1;
+
+ /* try to get the TAG */
+ if (!url_is_streamed(&s->pb)) {
+ /* XXX: change that */
+ filesize = url_fsize(&s->pb);
+ if (filesize > 128) {
+ url_fseek(&s->pb, filesize - 128, SEEK_SET);
+ ret = get_buffer(&s->pb, buf, ID3_TAG_SIZE);
+ if (ret == ID3_TAG_SIZE) {
+ id3_parse_tag(s, buf);
+ }
+ url_fseek(&s->pb, 0, SEEK_SET);
+ }
+ }
+
+ /* if ID3 header found, skip it */
+ ret = get_buffer(&s->pb, buf, ID3_HEADER_SIZE);
+ if (ret != ID3_HEADER_SIZE)
+ return -1;
+ if (id3_match(buf)) {
+ /* skip ID3 header */
+ len = ((buf[6] & 0x7f) << 21) |
+ ((buf[7] & 0x7f) << 14) |
+ ((buf[8] & 0x7f) << 7) |
+ (buf[9] & 0x7f);
+ url_fskip(&s->pb, len);
+ } else {
+ url_fseek(&s->pb, 0, SEEK_SET);
+ }
+
+ /* the parameters will be extracted from the compressed bitstream */
+ return 0;
+}
+
+#define MP3_PACKET_SIZE 1024
+
+static int mp3_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ int ret, size;
+ // AVStream *st = s->streams[0];
+
+ size= MP3_PACKET_SIZE;
+
+ ret= av_get_packet(&s->pb, pkt, size);
+
+ pkt->stream_index = 0;
+ if (ret <= 0) {
+ return AVERROR_IO;
+ }
+ /* note: we need to modify the packet size here to handle the last
+ packet */
+ pkt->size = ret;
+ return ret;
+}
+
+static int mp3_read_close(AVFormatContext *s)
+{
+ return 0;
+}
+
+#ifdef CONFIG_MUXERS
+/* simple formats */
+static int mp3_write_header(struct AVFormatContext *s)
+{
+ return 0;
+}
+
+static int mp3_write_packet(struct AVFormatContext *s, AVPacket *pkt)
+{
+ put_buffer(&s->pb, pkt->data, pkt->size);
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+static int mp3_write_trailer(struct AVFormatContext *s)
+{
+ uint8_t buf[ID3_TAG_SIZE];
+
+ /* write the id3 header */
+ if (s->title[0] != '\0') {
+ id3_create_tag(s, buf);
+ put_buffer(&s->pb, buf, ID3_TAG_SIZE);
+ put_flush_packet(&s->pb);
+ }
+ return 0;
+}
+#endif //CONFIG_MUXERS
+
+#ifdef CONFIG_MP3_DEMUXER
+AVInputFormat mp3_demuxer = {
+ "mp3",
+ "MPEG audio",
+ 0,
+ mp3_read_probe,
+ mp3_read_header,
+ mp3_read_packet,
+ mp3_read_close,
+ .extensions = "mp2,mp3,m2a", /* XXX: use probe */
+};
+#endif
+#ifdef CONFIG_MP2_MUXER
+AVOutputFormat mp2_muxer = {
+ "mp2",
+ "MPEG audio layer 2",
+ "audio/x-mpeg",
+#ifdef CONFIG_MP3LAME
+ "mp2,m2a",
+#else
+ "mp2,mp3,m2a",
+#endif
+ 0,
+ CODEC_ID_MP2,
+ 0,
+ mp3_write_header,
+ mp3_write_packet,
+ mp3_write_trailer,
+};
+#endif
+#ifdef CONFIG_MP3_MUXER
+AVOutputFormat mp3_muxer = {
+ "mp3",
+ "MPEG audio layer 3",
+ "audio/x-mpeg",
+ "mp3",
+ 0,
+ CODEC_ID_MP3,
+ 0,
+ mp3_write_header,
+ mp3_write_packet,
+ mp3_write_trailer,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/mpeg.c b/contrib/ffmpeg/libavformat/mpeg.c
new file mode 100644
index 000000000..709ce16f1
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/mpeg.c
@@ -0,0 +1,1824 @@
+/*
+ * MPEG1/2 muxer and demuxer
+ * 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 "avformat.h"
+#include "bitstream.h"
+#include "fifo.h"
+
+#define MAX_PAYLOAD_SIZE 4096
+//#define DEBUG_SEEK
+
+#undef NDEBUG
+#include <assert.h>
+
+typedef struct PacketDesc {
+ int64_t pts;
+ int64_t dts;
+ int size;
+ int unwritten_size;
+ int flags;
+ struct PacketDesc *next;
+} PacketDesc;
+
+typedef struct {
+ AVFifoBuffer fifo;
+ uint8_t id;
+ int max_buffer_size; /* in bytes */
+ int buffer_index;
+ PacketDesc *predecode_packet;
+ PacketDesc *premux_packet;
+ PacketDesc **next_packet;
+ int packet_number;
+ uint8_t lpcm_header[3];
+ int lpcm_align;
+ int bytes_to_iframe;
+ int align_iframe;
+ int64_t vobu_start_pts;
+} StreamInfo;
+
+typedef struct {
+ int packet_size; /* required packet size */
+ int packet_number;
+ int pack_header_freq; /* frequency (in packets^-1) at which we send pack headers */
+ int system_header_freq;
+ int system_header_size;
+ int mux_rate; /* bitrate in units of 50 bytes/s */
+ /* stream info */
+ int audio_bound;
+ int video_bound;
+ int is_mpeg2;
+ int is_vcd;
+ int is_svcd;
+ int is_dvd;
+ int64_t last_scr; /* current system clock */
+
+ double vcd_padding_bitrate; //FIXME floats
+ int64_t vcd_padding_bytes_written;
+
+} MpegMuxContext;
+
+#define PACK_START_CODE ((unsigned int)0x000001ba)
+#define SYSTEM_HEADER_START_CODE ((unsigned int)0x000001bb)
+#define SEQUENCE_END_CODE ((unsigned int)0x000001b7)
+#define PACKET_START_CODE_MASK ((unsigned int)0xffffff00)
+#define PACKET_START_CODE_PREFIX ((unsigned int)0x00000100)
+#define ISO_11172_END_CODE ((unsigned int)0x000001b9)
+
+/* mpeg2 */
+#define PROGRAM_STREAM_MAP 0x1bc
+#define PRIVATE_STREAM_1 0x1bd
+#define PADDING_STREAM 0x1be
+#define PRIVATE_STREAM_2 0x1bf
+
+
+#define AUDIO_ID 0xc0
+#define VIDEO_ID 0xe0
+#define AC3_ID 0x80
+#define DTS_ID 0x8a
+#define LPCM_ID 0xa0
+#define SUB_ID 0x20
+
+#define STREAM_TYPE_VIDEO_MPEG1 0x01
+#define STREAM_TYPE_VIDEO_MPEG2 0x02
+#define STREAM_TYPE_AUDIO_MPEG1 0x03
+#define STREAM_TYPE_AUDIO_MPEG2 0x04
+#define STREAM_TYPE_PRIVATE_SECTION 0x05
+#define STREAM_TYPE_PRIVATE_DATA 0x06
+#define STREAM_TYPE_AUDIO_AAC 0x0f
+#define STREAM_TYPE_VIDEO_MPEG4 0x10
+#define STREAM_TYPE_VIDEO_H264 0x1b
+
+#define STREAM_TYPE_AUDIO_AC3 0x81
+#define STREAM_TYPE_AUDIO_DTS 0x8a
+
+static const int lpcm_freq_tab[4] = { 48000, 96000, 44100, 32000 };
+
+#ifdef CONFIG_MUXERS
+AVOutputFormat mpeg1system_muxer;
+AVOutputFormat mpeg1vcd_muxer;
+AVOutputFormat mpeg2vob_muxer;
+AVOutputFormat mpeg2svcd_muxer;
+AVOutputFormat mpeg2dvd_muxer;
+
+static int put_pack_header(AVFormatContext *ctx,
+ uint8_t *buf, int64_t timestamp)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ PutBitContext pb;
+
+ init_put_bits(&pb, buf, 128);
+
+ put_bits(&pb, 32, PACK_START_CODE);
+ if (s->is_mpeg2) {
+ put_bits(&pb, 2, 0x1);
+ } else {
+ put_bits(&pb, 4, 0x2);
+ }
+ put_bits(&pb, 3, (uint32_t)((timestamp >> 30) & 0x07));
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 15, (uint32_t)((timestamp >> 15) & 0x7fff));
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 15, (uint32_t)((timestamp) & 0x7fff));
+ put_bits(&pb, 1, 1);
+ if (s->is_mpeg2) {
+ /* clock extension */
+ put_bits(&pb, 9, 0);
+ }
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 22, s->mux_rate);
+ put_bits(&pb, 1, 1);
+ if (s->is_mpeg2) {
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 5, 0x1f); /* reserved */
+ put_bits(&pb, 3, 0); /* stuffing length */
+ }
+ flush_put_bits(&pb);
+ return pbBufPtr(&pb) - pb.buf;
+}
+
+static int put_system_header(AVFormatContext *ctx, uint8_t *buf,int only_for_stream_id)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ int size, i, private_stream_coded, id;
+ PutBitContext pb;
+
+ init_put_bits(&pb, buf, 128);
+
+ put_bits(&pb, 32, SYSTEM_HEADER_START_CODE);
+ put_bits(&pb, 16, 0);
+ put_bits(&pb, 1, 1);
+
+ put_bits(&pb, 22, s->mux_rate); /* maximum bit rate of the multiplexed stream */
+ put_bits(&pb, 1, 1); /* marker */
+ if (s->is_vcd && only_for_stream_id==VIDEO_ID) {
+ /* This header applies only to the video stream (see VCD standard p. IV-7)*/
+ put_bits(&pb, 6, 0);
+ } else
+ put_bits(&pb, 6, s->audio_bound);
+
+ if (s->is_vcd) {
+ /* see VCD standard, p. IV-7*/
+ put_bits(&pb, 1, 0);
+ put_bits(&pb, 1, 1);
+ } else {
+ put_bits(&pb, 1, 0); /* variable bitrate*/
+ put_bits(&pb, 1, 0); /* non constrainted bit stream */
+ }
+
+ if (s->is_vcd || s->is_dvd) {
+ /* see VCD standard p IV-7 */
+ put_bits(&pb, 1, 1); /* audio locked */
+ put_bits(&pb, 1, 1); /* video locked */
+ } else {
+ put_bits(&pb, 1, 0); /* audio locked */
+ put_bits(&pb, 1, 0); /* video locked */
+ }
+
+ put_bits(&pb, 1, 1); /* marker */
+
+ if (s->is_vcd && only_for_stream_id==AUDIO_ID) {
+ /* This header applies only to the audio stream (see VCD standard p. IV-7)*/
+ put_bits(&pb, 5, 0);
+ } else
+ put_bits(&pb, 5, s->video_bound);
+
+ if (s->is_dvd) {
+ put_bits(&pb, 1, 0); /* packet_rate_restriction_flag */
+ put_bits(&pb, 7, 0x7f); /* reserved byte */
+ } else
+ put_bits(&pb, 8, 0xff); /* reserved byte */
+
+ /* DVD-Video Stream_bound entries
+ id (0xB9) video, maximum P-STD for stream 0xE0. (P-STD_buffer_bound_scale = 1)
+ id (0xB8) audio, maximum P-STD for any MPEG audio (0xC0 to 0xC7) streams. If there are none set to 4096 (32x128). (P-STD_buffer_bound_scale = 0)
+ id (0xBD) private stream 1 (audio other than MPEG and subpictures). (P-STD_buffer_bound_scale = 1)
+ id (0xBF) private stream 2, NAV packs, set to 2x1024. */
+ if (s->is_dvd) {
+
+ int P_STD_max_video = 0;
+ int P_STD_max_mpeg_audio = 0;
+ int P_STD_max_mpeg_PS1 = 0;
+
+ for(i=0;i<ctx->nb_streams;i++) {
+ StreamInfo *stream = ctx->streams[i]->priv_data;
+
+ id = stream->id;
+ if (id == 0xbd && stream->max_buffer_size > P_STD_max_mpeg_PS1) {
+ P_STD_max_mpeg_PS1 = stream->max_buffer_size;
+ } else if (id >= 0xc0 && id <= 0xc7 && stream->max_buffer_size > P_STD_max_mpeg_audio) {
+ P_STD_max_mpeg_audio = stream->max_buffer_size;
+ } else if (id == 0xe0 && stream->max_buffer_size > P_STD_max_video) {
+ P_STD_max_video = stream->max_buffer_size;
+ }
+ }
+
+ /* video */
+ put_bits(&pb, 8, 0xb9); /* stream ID */
+ put_bits(&pb, 2, 3);
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 13, P_STD_max_video / 1024);
+
+ /* audio */
+ if (P_STD_max_mpeg_audio == 0)
+ P_STD_max_mpeg_audio = 4096;
+ put_bits(&pb, 8, 0xb8); /* stream ID */
+ put_bits(&pb, 2, 3);
+ put_bits(&pb, 1, 0);
+ put_bits(&pb, 13, P_STD_max_mpeg_audio / 128);
+
+ /* private stream 1 */
+ put_bits(&pb, 8, 0xbd); /* stream ID */
+ put_bits(&pb, 2, 3);
+ put_bits(&pb, 1, 0);
+ put_bits(&pb, 13, P_STD_max_mpeg_PS1 / 128);
+
+ /* private stream 2 */
+ put_bits(&pb, 8, 0xbf); /* stream ID */
+ put_bits(&pb, 2, 3);
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 13, 2);
+ }
+ else {
+ /* audio stream info */
+ private_stream_coded = 0;
+ for(i=0;i<ctx->nb_streams;i++) {
+ StreamInfo *stream = ctx->streams[i]->priv_data;
+
+
+ /* For VCDs, only include the stream info for the stream
+ that the pack which contains this system belongs to.
+ (see VCD standard p. IV-7) */
+ if ( !s->is_vcd || stream->id==only_for_stream_id
+ || only_for_stream_id==0) {
+
+ id = stream->id;
+ if (id < 0xc0) {
+ /* special case for private streams (AC3 use that) */
+ if (private_stream_coded)
+ continue;
+ private_stream_coded = 1;
+ id = 0xbd;
+ }
+ put_bits(&pb, 8, id); /* stream ID */
+ put_bits(&pb, 2, 3);
+ if (id < 0xe0) {
+ /* audio */
+ put_bits(&pb, 1, 0);
+ put_bits(&pb, 13, stream->max_buffer_size / 128);
+ } else {
+ /* video */
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 13, stream->max_buffer_size / 1024);
+ }
+ }
+ }
+ }
+
+ flush_put_bits(&pb);
+ size = pbBufPtr(&pb) - pb.buf;
+ /* patch packet size */
+ buf[4] = (size - 6) >> 8;
+ buf[5] = (size - 6) & 0xff;
+
+ return size;
+}
+
+static int get_system_header_size(AVFormatContext *ctx)
+{
+ int buf_index, i, private_stream_coded;
+ StreamInfo *stream;
+ MpegMuxContext *s = ctx->priv_data;
+
+ if (s->is_dvd)
+ return 18; // DVD-Video system headers are 18 bytes fixed length.
+
+ buf_index = 12;
+ private_stream_coded = 0;
+ for(i=0;i<ctx->nb_streams;i++) {
+ stream = ctx->streams[i]->priv_data;
+ if (stream->id < 0xc0) {
+ if (private_stream_coded)
+ continue;
+ private_stream_coded = 1;
+ }
+ buf_index += 3;
+ }
+ return buf_index;
+}
+
+static int mpeg_mux_init(AVFormatContext *ctx)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ int bitrate, i, mpa_id, mpv_id, mps_id, ac3_id, dts_id, lpcm_id, j;
+ AVStream *st;
+ StreamInfo *stream;
+ int audio_bitrate;
+ int video_bitrate;
+
+ s->packet_number = 0;
+ s->is_vcd = (ctx->oformat == &mpeg1vcd_muxer);
+ s->is_svcd = (ctx->oformat == &mpeg2svcd_muxer);
+ s->is_mpeg2 = (ctx->oformat == &mpeg2vob_muxer || ctx->oformat == &mpeg2svcd_muxer || ctx->oformat == &mpeg2dvd_muxer);
+ s->is_dvd = (ctx->oformat == &mpeg2dvd_muxer);
+
+ if(ctx->packet_size)
+ s->packet_size = ctx->packet_size;
+ else
+ s->packet_size = 2048;
+
+ s->vcd_padding_bytes_written = 0;
+ s->vcd_padding_bitrate=0;
+
+ s->audio_bound = 0;
+ s->video_bound = 0;
+ mpa_id = AUDIO_ID;
+ ac3_id = AC3_ID;
+ dts_id = DTS_ID;
+ mpv_id = VIDEO_ID;
+ mps_id = SUB_ID;
+ lpcm_id = LPCM_ID;
+ for(i=0;i<ctx->nb_streams;i++) {
+ st = ctx->streams[i];
+ stream = av_mallocz(sizeof(StreamInfo));
+ if (!stream)
+ goto fail;
+ st->priv_data = stream;
+
+ av_set_pts_info(st, 64, 1, 90000);
+
+ switch(st->codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ if (st->codec->codec_id == CODEC_ID_AC3) {
+ stream->id = ac3_id++;
+ } else if (st->codec->codec_id == CODEC_ID_DTS) {
+ stream->id = dts_id++;
+ } else if (st->codec->codec_id == CODEC_ID_PCM_S16BE) {
+ stream->id = lpcm_id++;
+ for(j = 0; j < 4; j++) {
+ if (lpcm_freq_tab[j] == st->codec->sample_rate)
+ break;
+ }
+ if (j == 4)
+ goto fail;
+ if (st->codec->channels > 8)
+ return -1;
+ stream->lpcm_header[0] = 0x0c;
+ stream->lpcm_header[1] = (st->codec->channels - 1) | (j << 4);
+ stream->lpcm_header[2] = 0x80;
+ stream->lpcm_align = st->codec->channels * 2;
+ } else {
+ stream->id = mpa_id++;
+ }
+
+ /* This value HAS to be used for VCD (see VCD standard, p. IV-7).
+ Right now it is also used for everything else.*/
+ stream->max_buffer_size = 4 * 1024;
+ s->audio_bound++;
+ break;
+ case CODEC_TYPE_VIDEO:
+ stream->id = mpv_id++;
+ if (st->codec->rc_buffer_size)
+ stream->max_buffer_size = 6*1024 + st->codec->rc_buffer_size/8;
+ else
+ stream->max_buffer_size = 230*1024; //FIXME this is probably too small as default
+#if 0
+ /* see VCD standard, p. IV-7*/
+ stream->max_buffer_size = 46 * 1024;
+ else
+ /* This value HAS to be used for SVCD (see SVCD standard, p. 26 V.2.3.2).
+ Right now it is also used for everything else.*/
+ stream->max_buffer_size = 230 * 1024;
+#endif
+ s->video_bound++;
+ break;
+ case CODEC_TYPE_SUBTITLE:
+ stream->id = mps_id++;
+ stream->max_buffer_size = 16 * 1024;
+ break;
+ default:
+ return -1;
+ }
+ av_fifo_init(&stream->fifo, 16);
+ }
+ bitrate = 0;
+ audio_bitrate = 0;
+ video_bitrate = 0;
+ for(i=0;i<ctx->nb_streams;i++) {
+ int codec_rate;
+ st = ctx->streams[i];
+ stream = (StreamInfo*) st->priv_data;
+
+ if(st->codec->rc_max_rate || stream->id==VIDEO_ID)
+ codec_rate= st->codec->rc_max_rate;
+ else
+ codec_rate= st->codec->bit_rate;
+
+ if(!codec_rate)
+ codec_rate= (1<<21)*8*50/ctx->nb_streams;
+
+ bitrate += codec_rate;
+
+ if (stream->id==AUDIO_ID)
+ audio_bitrate += codec_rate;
+ else if (stream->id==VIDEO_ID)
+ video_bitrate += codec_rate;
+ }
+
+ if(ctx->mux_rate){
+ s->mux_rate= (ctx->mux_rate + (8 * 50) - 1) / (8 * 50);
+ } else {
+ /* we increase slightly the bitrate to take into account the
+ headers. XXX: compute it exactly */
+ bitrate += bitrate*5/100;
+ bitrate += 10000;
+ s->mux_rate = (bitrate + (8 * 50) - 1) / (8 * 50);
+ }
+
+ if (s->is_vcd) {
+ double overhead_rate;
+
+ /* The VCD standard mandates that the mux_rate field is 3528
+ (see standard p. IV-6).
+ The value is actually "wrong", i.e. if you calculate
+ it using the normal formula and the 75 sectors per second transfer
+ rate you get a different value because the real pack size is 2324,
+ not 2352. But the standard explicitly specifies that the mux_rate
+ field in the header must have this value.*/
+// s->mux_rate=2352 * 75 / 50; /* = 3528*/
+
+ /* The VCD standard states that the muxed stream must be
+ exactly 75 packs / second (the data rate of a single speed cdrom).
+ Since the video bitrate (probably 1150000 bits/sec) will be below
+ the theoretical maximum we have to add some padding packets
+ to make up for the lower data rate.
+ (cf. VCD standard p. IV-6 )*/
+
+ /* Add the header overhead to the data rate.
+ 2279 data bytes per audio pack, 2294 data bytes per video pack*/
+ overhead_rate = ((audio_bitrate / 8.0) / 2279) * (2324 - 2279);
+ overhead_rate += ((video_bitrate / 8.0) / 2294) * (2324 - 2294);
+ overhead_rate *= 8;
+
+ /* Add padding so that the full bitrate is 2324*75 bytes/sec */
+ s->vcd_padding_bitrate = 2324 * 75 * 8 - (bitrate + overhead_rate);
+ }
+
+ if (s->is_vcd || s->is_mpeg2)
+ /* every packet */
+ s->pack_header_freq = 1;
+ else
+ /* every 2 seconds */
+ s->pack_header_freq = 2 * bitrate / s->packet_size / 8;
+
+ /* the above seems to make pack_header_freq zero sometimes */
+ if (s->pack_header_freq == 0)
+ s->pack_header_freq = 1;
+
+ if (s->is_mpeg2)
+ /* every 200 packets. Need to look at the spec. */
+ s->system_header_freq = s->pack_header_freq * 40;
+ else if (s->is_vcd)
+ /* the standard mandates that there are only two system headers
+ in the whole file: one in the first packet of each stream.
+ (see standard p. IV-7 and IV-8) */
+ s->system_header_freq = 0x7fffffff;
+ else
+ s->system_header_freq = s->pack_header_freq * 5;
+
+ for(i=0;i<ctx->nb_streams;i++) {
+ stream = ctx->streams[i]->priv_data;
+ stream->packet_number = 0;
+ }
+ s->system_header_size = get_system_header_size(ctx);
+ s->last_scr = 0;
+ return 0;
+ fail:
+ for(i=0;i<ctx->nb_streams;i++) {
+ av_free(ctx->streams[i]->priv_data);
+ }
+ return -ENOMEM;
+}
+
+static inline void put_timestamp(ByteIOContext *pb, int id, int64_t timestamp)
+{
+ put_byte(pb,
+ (id << 4) |
+ (((timestamp >> 30) & 0x07) << 1) |
+ 1);
+ put_be16(pb, (uint16_t)((((timestamp >> 15) & 0x7fff) << 1) | 1));
+ put_be16(pb, (uint16_t)((((timestamp) & 0x7fff) << 1) | 1));
+}
+
+
+/* return the number of padding bytes that should be inserted into
+ the multiplexed stream.*/
+static int get_vcd_padding_size(AVFormatContext *ctx, int64_t pts)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ int pad_bytes = 0;
+
+ if (s->vcd_padding_bitrate > 0 && pts!=AV_NOPTS_VALUE)
+ {
+ int64_t full_pad_bytes;
+
+ full_pad_bytes = (int64_t)((s->vcd_padding_bitrate * (pts / 90000.0)) / 8.0); //FIXME this is wrong
+ pad_bytes = (int) (full_pad_bytes - s->vcd_padding_bytes_written);
+
+ if (pad_bytes<0)
+ /* might happen if we have already padded to a later timestamp. This
+ can occur if another stream has already advanced further.*/
+ pad_bytes=0;
+ }
+
+ return pad_bytes;
+}
+
+
+#if 0 /* unused, remove? */
+/* return the exact available payload size for the next packet for
+ stream 'stream_index'. 'pts' and 'dts' are only used to know if
+ timestamps are needed in the packet header. */
+static int get_packet_payload_size(AVFormatContext *ctx, int stream_index,
+ int64_t pts, int64_t dts)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ int buf_index;
+ StreamInfo *stream;
+
+ stream = ctx->streams[stream_index]->priv_data;
+
+ buf_index = 0;
+ if (((s->packet_number % s->pack_header_freq) == 0)) {
+ /* pack header size */
+ if (s->is_mpeg2)
+ buf_index += 14;
+ else
+ buf_index += 12;
+
+ if (s->is_vcd) {
+ /* there is exactly one system header for each stream in a VCD MPEG,
+ One in the very first video packet and one in the very first
+ audio packet (see VCD standard p. IV-7 and IV-8).*/
+
+ if (stream->packet_number==0)
+ /* The system headers refer only to the stream they occur in,
+ so they have a constant size.*/
+ buf_index += 15;
+
+ } else {
+ if ((s->packet_number % s->system_header_freq) == 0)
+ buf_index += s->system_header_size;
+ }
+ }
+
+ if ((s->is_vcd && stream->packet_number==0)
+ || (s->is_svcd && s->packet_number==0))
+ /* the first pack of each stream contains only the pack header,
+ the system header and some padding (see VCD standard p. IV-6)
+ Add the padding size, so that the actual payload becomes 0.*/
+ buf_index += s->packet_size - buf_index;
+ else {
+ /* packet header size */
+ buf_index += 6;
+ if (s->is_mpeg2) {
+ buf_index += 3;
+ if (stream->packet_number==0)
+ buf_index += 3; /* PES extension */
+ buf_index += 1; /* obligatory stuffing byte */
+ }
+ if (pts != AV_NOPTS_VALUE) {
+ if (dts != pts)
+ buf_index += 5 + 5;
+ else
+ buf_index += 5;
+
+ } else {
+ if (!s->is_mpeg2)
+ buf_index++;
+ }
+
+ if (stream->id < 0xc0) {
+ /* AC3/LPCM private data header */
+ buf_index += 4;
+ if (stream->id >= 0xa0) {
+ int n;
+ buf_index += 3;
+ /* NOTE: we round the payload size to an integer number of
+ LPCM samples */
+ n = (s->packet_size - buf_index) % stream->lpcm_align;
+ if (n)
+ buf_index += (stream->lpcm_align - n);
+ }
+ }
+
+ if (s->is_vcd && stream->id == AUDIO_ID)
+ /* The VCD standard demands that 20 zero bytes follow
+ each audio packet (see standard p. IV-8).*/
+ buf_index+=20;
+ }
+ return s->packet_size - buf_index;
+}
+#endif
+
+/* Write an MPEG padding packet header. */
+static void put_padding_packet(AVFormatContext *ctx, ByteIOContext *pb,int packet_bytes)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ int i;
+
+ put_be32(pb, PADDING_STREAM);
+ put_be16(pb, packet_bytes - 6);
+ if (!s->is_mpeg2) {
+ put_byte(pb, 0x0f);
+ packet_bytes -= 7;
+ } else
+ packet_bytes -= 6;
+
+ for(i=0;i<packet_bytes;i++)
+ put_byte(pb, 0xff);
+}
+
+static int get_nb_frames(AVFormatContext *ctx, StreamInfo *stream, int len){
+ int nb_frames=0;
+ PacketDesc *pkt_desc= stream->premux_packet;
+
+ while(len>0){
+ if(pkt_desc->size == pkt_desc->unwritten_size)
+ nb_frames++;
+ len -= pkt_desc->unwritten_size;
+ pkt_desc= pkt_desc->next;
+ }
+
+ return nb_frames;
+}
+
+/* flush the packet on stream stream_index */
+static int flush_packet(AVFormatContext *ctx, int stream_index,
+ int64_t pts, int64_t dts, int64_t scr, int trailer_size)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ StreamInfo *stream = ctx->streams[stream_index]->priv_data;
+ uint8_t *buf_ptr;
+ int size, payload_size, startcode, id, stuffing_size, i, header_len;
+ int packet_size;
+ uint8_t buffer[128];
+ int zero_trail_bytes = 0;
+ int pad_packet_bytes = 0;
+ int pes_flags;
+ int general_pack = 0; /*"general" pack without data specific to one stream?*/
+ int nb_frames;
+
+ id = stream->id;
+
+#if 0
+ printf("packet ID=%2x PTS=%0.3f\n",
+ id, pts / 90000.0);
+#endif
+
+ buf_ptr = buffer;
+
+ if ((s->packet_number % s->pack_header_freq) == 0 || s->last_scr != scr) {
+ /* output pack and systems header if needed */
+ size = put_pack_header(ctx, buf_ptr, scr);
+ buf_ptr += size;
+ s->last_scr= scr;
+
+ if (s->is_vcd) {
+ /* there is exactly one system header for each stream in a VCD MPEG,
+ One in the very first video packet and one in the very first
+ audio packet (see VCD standard p. IV-7 and IV-8).*/
+
+ if (stream->packet_number==0) {
+ size = put_system_header(ctx, buf_ptr, id);
+ buf_ptr += size;
+ }
+ } else if (s->is_dvd) {
+ if (stream->align_iframe || s->packet_number == 0){
+ int PES_bytes_to_fill = s->packet_size - size - 10;
+
+ if (pts != AV_NOPTS_VALUE) {
+ if (dts != pts)
+ PES_bytes_to_fill -= 5 + 5;
+ else
+ PES_bytes_to_fill -= 5;
+ }
+
+ if (stream->bytes_to_iframe == 0 || s->packet_number == 0) {
+ size = put_system_header(ctx, buf_ptr, 0);
+ buf_ptr += size;
+ size = buf_ptr - buffer;
+ put_buffer(&ctx->pb, buffer, size);
+
+ put_be32(&ctx->pb, PRIVATE_STREAM_2);
+ put_be16(&ctx->pb, 0x03d4); // length
+ put_byte(&ctx->pb, 0x00); // substream ID, 00=PCI
+ for (i = 0; i < 979; i++)
+ put_byte(&ctx->pb, 0x00);
+
+ put_be32(&ctx->pb, PRIVATE_STREAM_2);
+ put_be16(&ctx->pb, 0x03fa); // length
+ put_byte(&ctx->pb, 0x01); // substream ID, 01=DSI
+ for (i = 0; i < 1017; i++)
+ put_byte(&ctx->pb, 0x00);
+
+ memset(buffer, 0, 128);
+ buf_ptr = buffer;
+ s->packet_number++;
+ stream->align_iframe = 0;
+ scr += s->packet_size*90000LL / (s->mux_rate*50LL); //FIXME rounding and first few bytes of each packet
+ size = put_pack_header(ctx, buf_ptr, scr);
+ s->last_scr= scr;
+ buf_ptr += size;
+ /* GOP Start */
+ } else if (stream->bytes_to_iframe < PES_bytes_to_fill) {
+ pad_packet_bytes = PES_bytes_to_fill - stream->bytes_to_iframe;
+ }
+ }
+ } else {
+ if ((s->packet_number % s->system_header_freq) == 0) {
+ size = put_system_header(ctx, buf_ptr, 0);
+ buf_ptr += size;
+ }
+ }
+ }
+ size = buf_ptr - buffer;
+ put_buffer(&ctx->pb, buffer, size);
+
+ packet_size = s->packet_size - size;
+
+ if (s->is_vcd && id == AUDIO_ID)
+ /* The VCD standard demands that 20 zero bytes follow
+ each audio pack (see standard p. IV-8).*/
+ zero_trail_bytes += 20;
+
+ if ((s->is_vcd && stream->packet_number==0)
+ || (s->is_svcd && s->packet_number==0)) {
+ /* for VCD the first pack of each stream contains only the pack header,
+ the system header and lots of padding (see VCD standard p. IV-6).
+ In the case of an audio pack, 20 zero bytes are also added at
+ the end.*/
+ /* For SVCD we fill the very first pack to increase compatibility with
+ some DVD players. Not mandated by the standard.*/
+ if (s->is_svcd)
+ general_pack = 1; /* the system header refers to both streams and no stream data*/
+ pad_packet_bytes = packet_size - zero_trail_bytes;
+ }
+
+ packet_size -= pad_packet_bytes + zero_trail_bytes;
+
+ if (packet_size > 0) {
+
+ /* packet header size */
+ packet_size -= 6;
+
+ /* packet header */
+ if (s->is_mpeg2) {
+ header_len = 3;
+ if (stream->packet_number==0)
+ header_len += 3; /* PES extension */
+ header_len += 1; /* obligatory stuffing byte */
+ } else {
+ header_len = 0;
+ }
+ if (pts != AV_NOPTS_VALUE) {
+ if (dts != pts)
+ header_len += 5 + 5;
+ else
+ header_len += 5;
+ } else {
+ if (!s->is_mpeg2)
+ header_len++;
+ }
+
+ payload_size = packet_size - header_len;
+ if (id < 0xc0) {
+ startcode = PRIVATE_STREAM_1;
+ payload_size -= 1;
+ if (id >= 0x40) {
+ payload_size -= 3;
+ if (id >= 0xa0)
+ payload_size -= 3;
+ }
+ } else {
+ startcode = 0x100 + id;
+ }
+
+ stuffing_size = payload_size - av_fifo_size(&stream->fifo);
+
+ // first byte doesnt fit -> reset pts/dts + stuffing
+ if(payload_size <= trailer_size && pts != AV_NOPTS_VALUE){
+ int timestamp_len=0;
+ if(dts != pts)
+ timestamp_len += 5;
+ if(pts != AV_NOPTS_VALUE)
+ timestamp_len += s->is_mpeg2 ? 5 : 4;
+ pts=dts= AV_NOPTS_VALUE;
+ header_len -= timestamp_len;
+ if (s->is_dvd && stream->align_iframe) {
+ pad_packet_bytes += timestamp_len;
+ packet_size -= timestamp_len;
+ } else {
+ payload_size += timestamp_len;
+ }
+ stuffing_size += timestamp_len;
+ if(payload_size > trailer_size)
+ stuffing_size += payload_size - trailer_size;
+ }
+
+ if (pad_packet_bytes > 0 && pad_packet_bytes <= 7) { // can't use padding, so use stuffing
+ packet_size += pad_packet_bytes;
+ payload_size += pad_packet_bytes; // undo the previous adjustment
+ if (stuffing_size < 0) {
+ stuffing_size = pad_packet_bytes;
+ } else {
+ stuffing_size += pad_packet_bytes;
+ }
+ pad_packet_bytes = 0;
+ }
+
+ if (stuffing_size < 0)
+ stuffing_size = 0;
+ if (stuffing_size > 16) { /*<=16 for MPEG-1, <=32 for MPEG-2*/
+ pad_packet_bytes += stuffing_size;
+ packet_size -= stuffing_size;
+ payload_size -= stuffing_size;
+ stuffing_size = 0;
+ }
+
+ nb_frames= get_nb_frames(ctx, stream, payload_size - stuffing_size);
+
+ put_be32(&ctx->pb, startcode);
+
+ put_be16(&ctx->pb, packet_size);
+
+ if (!s->is_mpeg2)
+ for(i=0;i<stuffing_size;i++)
+ put_byte(&ctx->pb, 0xff);
+
+ if (s->is_mpeg2) {
+ put_byte(&ctx->pb, 0x80); /* mpeg2 id */
+
+ pes_flags=0;
+
+ if (pts != AV_NOPTS_VALUE) {
+ pes_flags |= 0x80;
+ if (dts != pts)
+ pes_flags |= 0x40;
+ }
+
+ /* Both the MPEG-2 and the SVCD standards demand that the
+ P-STD_buffer_size field be included in the first packet of
+ every stream. (see SVCD standard p. 26 V.2.3.1 and V.2.3.2
+ and MPEG-2 standard 2.7.7) */
+ if (stream->packet_number == 0)
+ pes_flags |= 0x01;
+
+ put_byte(&ctx->pb, pes_flags); /* flags */
+ put_byte(&ctx->pb, header_len - 3 + stuffing_size);
+
+ if (pes_flags & 0x80) /*write pts*/
+ put_timestamp(&ctx->pb, (pes_flags & 0x40) ? 0x03 : 0x02, pts);
+ if (pes_flags & 0x40) /*write dts*/
+ put_timestamp(&ctx->pb, 0x01, dts);
+
+ if (pes_flags & 0x01) { /*write pes extension*/
+ put_byte(&ctx->pb, 0x10); /* flags */
+
+ /* P-STD buffer info */
+ if (id == AUDIO_ID)
+ put_be16(&ctx->pb, 0x4000 | stream->max_buffer_size/128);
+ else
+ put_be16(&ctx->pb, 0x6000 | stream->max_buffer_size/1024);
+ }
+
+ } else {
+ if (pts != AV_NOPTS_VALUE) {
+ if (dts != pts) {
+ put_timestamp(&ctx->pb, 0x03, pts);
+ put_timestamp(&ctx->pb, 0x01, dts);
+ } else {
+ put_timestamp(&ctx->pb, 0x02, pts);
+ }
+ } else {
+ put_byte(&ctx->pb, 0x0f);
+ }
+ }
+
+ if (s->is_mpeg2) {
+ /* special stuffing byte that is always written
+ to prevent accidental generation of start codes. */
+ put_byte(&ctx->pb, 0xff);
+
+ for(i=0;i<stuffing_size;i++)
+ put_byte(&ctx->pb, 0xff);
+ }
+
+ if (startcode == PRIVATE_STREAM_1) {
+ put_byte(&ctx->pb, id);
+ if (id >= 0xa0) {
+ /* LPCM (XXX: check nb_frames) */
+ put_byte(&ctx->pb, 7);
+ put_be16(&ctx->pb, 4); /* skip 3 header bytes */
+ put_byte(&ctx->pb, stream->lpcm_header[0]);
+ put_byte(&ctx->pb, stream->lpcm_header[1]);
+ put_byte(&ctx->pb, stream->lpcm_header[2]);
+ } else if (id >= 0x40) {
+ /* AC3 */
+ put_byte(&ctx->pb, nb_frames);
+ put_be16(&ctx->pb, trailer_size+1);
+ }
+ }
+
+ /* output data */
+ if(av_fifo_generic_read(&stream->fifo, payload_size - stuffing_size, &put_buffer, &ctx->pb) < 0)
+ return -1;
+ stream->bytes_to_iframe -= payload_size - stuffing_size;
+ }else{
+ payload_size=
+ stuffing_size= 0;
+ }
+
+ if (pad_packet_bytes > 0)
+ put_padding_packet(ctx,&ctx->pb, pad_packet_bytes);
+
+ for(i=0;i<zero_trail_bytes;i++)
+ put_byte(&ctx->pb, 0x00);
+
+ put_flush_packet(&ctx->pb);
+
+ s->packet_number++;
+
+ /* only increase the stream packet number if this pack actually contains
+ something that is specific to this stream! I.e. a dedicated header
+ or some data.*/
+ if (!general_pack)
+ stream->packet_number++;
+
+ return payload_size - stuffing_size;
+}
+
+static void put_vcd_padding_sector(AVFormatContext *ctx)
+{
+ /* There are two ways to do this padding: writing a sector/pack
+ of 0 values, or writing an MPEG padding pack. Both seem to
+ work with most decoders, BUT the VCD standard only allows a 0-sector
+ (see standard p. IV-4, IV-5).
+ So a 0-sector it is...*/
+
+ MpegMuxContext *s = ctx->priv_data;
+ int i;
+
+ for(i=0;i<s->packet_size;i++)
+ put_byte(&ctx->pb, 0);
+
+ s->vcd_padding_bytes_written += s->packet_size;
+
+ put_flush_packet(&ctx->pb);
+
+ /* increasing the packet number is correct. The SCR of the following packs
+ is calculated from the packet_number and it has to include the padding
+ sector (it represents the sector index, not the MPEG pack index)
+ (see VCD standard p. IV-6)*/
+ s->packet_number++;
+}
+
+#if 0 /* unused, remove? */
+static int64_t get_vcd_scr(AVFormatContext *ctx,int stream_index,int64_t pts)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ int64_t scr;
+
+ /* Since the data delivery rate is constant, SCR is computed
+ using the formula C + i * 1200 where C is the start constant
+ and i is the pack index.
+ It is recommended that SCR 0 is at the beginning of the VCD front
+ margin (a sequence of empty Form 2 sectors on the CD).
+ It is recommended that the front margin is 30 sectors long, so
+ we use C = 30*1200 = 36000
+ (Note that even if the front margin is not 30 sectors the file
+ will still be correct according to the standard. It just won't have
+ the "recommended" value).*/
+ scr = 36000 + s->packet_number * 1200;
+
+ return scr;
+}
+#endif
+
+static int remove_decoded_packets(AVFormatContext *ctx, int64_t scr){
+// MpegMuxContext *s = ctx->priv_data;
+ int i;
+
+ for(i=0; i<ctx->nb_streams; i++){
+ AVStream *st = ctx->streams[i];
+ StreamInfo *stream = st->priv_data;
+ PacketDesc *pkt_desc= stream->predecode_packet;
+
+ while(pkt_desc && scr > pkt_desc->dts){ //FIXME > vs >=
+ if(stream->buffer_index < pkt_desc->size ||
+ stream->predecode_packet == stream->premux_packet){
+ av_log(ctx, AV_LOG_ERROR, "buffer underflow\n");
+ break;
+ }
+ stream->buffer_index -= pkt_desc->size;
+
+ stream->predecode_packet= pkt_desc->next;
+ av_freep(&pkt_desc);
+ }
+ }
+
+ return 0;
+}
+
+static int output_packet(AVFormatContext *ctx, int flush){
+ MpegMuxContext *s = ctx->priv_data;
+ AVStream *st;
+ StreamInfo *stream;
+ int i, avail_space, es_size, trailer_size;
+ int best_i= -1;
+ int best_score= INT_MIN;
+ int ignore_constraints=0;
+ int64_t scr= s->last_scr;
+ PacketDesc *timestamp_packet;
+ const int64_t max_delay= av_rescale(ctx->max_delay, 90000, AV_TIME_BASE);
+
+retry:
+ for(i=0; i<ctx->nb_streams; i++){
+ AVStream *st = ctx->streams[i];
+ StreamInfo *stream = st->priv_data;
+ const int avail_data= av_fifo_size(&stream->fifo);
+ const int space= stream->max_buffer_size - stream->buffer_index;
+ int rel_space= 1024*space / stream->max_buffer_size;
+ PacketDesc *next_pkt= stream->premux_packet;
+
+ /* for subtitle, a single PES packet must be generated,
+ so we flush after every single subtitle packet */
+ if(s->packet_size > avail_data && !flush
+ && st->codec->codec_type != CODEC_TYPE_SUBTITLE)
+ return 0;
+ if(avail_data==0)
+ continue;
+ assert(avail_data>0);
+
+ if(space < s->packet_size && !ignore_constraints)
+ continue;
+
+ if(next_pkt && next_pkt->dts - scr > max_delay)
+ continue;
+
+ if(rel_space > best_score){
+ best_score= rel_space;
+ best_i = i;
+ avail_space= space;
+ }
+ }
+
+ if(best_i < 0){
+ int64_t best_dts= INT64_MAX;
+
+ for(i=0; i<ctx->nb_streams; i++){
+ AVStream *st = ctx->streams[i];
+ StreamInfo *stream = st->priv_data;
+ PacketDesc *pkt_desc= stream->predecode_packet;
+ if(pkt_desc && pkt_desc->dts < best_dts)
+ best_dts= pkt_desc->dts;
+ }
+
+#if 0
+ av_log(ctx, AV_LOG_DEBUG, "bumping scr, scr:%f, dts:%f\n",
+ scr/90000.0, best_dts/90000.0);
+#endif
+ if(best_dts == INT64_MAX)
+ return 0;
+
+ if(scr >= best_dts+1 && !ignore_constraints){
+ av_log(ctx, AV_LOG_ERROR, "packet too large, ignoring buffer limits to mux it\n");
+ ignore_constraints= 1;
+ }
+ scr= FFMAX(best_dts+1, scr);
+ if(remove_decoded_packets(ctx, scr) < 0)
+ return -1;
+ goto retry;
+ }
+
+ assert(best_i >= 0);
+
+ st = ctx->streams[best_i];
+ stream = st->priv_data;
+
+ assert(av_fifo_size(&stream->fifo) > 0);
+
+ assert(avail_space >= s->packet_size || ignore_constraints);
+
+ timestamp_packet= stream->premux_packet;
+ if(timestamp_packet->unwritten_size == timestamp_packet->size){
+ trailer_size= 0;
+ }else{
+ trailer_size= timestamp_packet->unwritten_size;
+ timestamp_packet= timestamp_packet->next;
+ }
+
+ if(timestamp_packet){
+//av_log(ctx, AV_LOG_DEBUG, "dts:%f pts:%f scr:%f stream:%d\n", timestamp_packet->dts/90000.0, timestamp_packet->pts/90000.0, scr/90000.0, best_i);
+ es_size= flush_packet(ctx, best_i, timestamp_packet->pts, timestamp_packet->dts, scr, trailer_size);
+ }else{
+ assert(av_fifo_size(&stream->fifo) == trailer_size);
+ es_size= flush_packet(ctx, best_i, AV_NOPTS_VALUE, AV_NOPTS_VALUE, scr, trailer_size);
+ }
+
+ if (s->is_vcd) {
+ /* Write one or more padding sectors, if necessary, to reach
+ the constant overall bitrate.*/
+ int vcd_pad_bytes;
+
+ while((vcd_pad_bytes = get_vcd_padding_size(ctx,stream->premux_packet->pts) ) >= s->packet_size){ //FIXME pts cannot be correct here
+ put_vcd_padding_sector(ctx);
+ s->last_scr += s->packet_size*90000LL / (s->mux_rate*50LL); //FIXME rounding and first few bytes of each packet
+ }
+ }
+
+ stream->buffer_index += es_size;
+ s->last_scr += s->packet_size*90000LL / (s->mux_rate*50LL); //FIXME rounding and first few bytes of each packet
+
+ while(stream->premux_packet && stream->premux_packet->unwritten_size <= es_size){
+ es_size -= stream->premux_packet->unwritten_size;
+ stream->premux_packet= stream->premux_packet->next;
+ }
+ if(es_size)
+ stream->premux_packet->unwritten_size -= es_size;
+
+ if(remove_decoded_packets(ctx, s->last_scr) < 0)
+ return -1;
+
+ return 1;
+}
+
+static int mpeg_mux_write_packet(AVFormatContext *ctx, AVPacket *pkt)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ int stream_index= pkt->stream_index;
+ int size= pkt->size;
+ uint8_t *buf= pkt->data;
+ AVStream *st = ctx->streams[stream_index];
+ StreamInfo *stream = st->priv_data;
+ int64_t pts, dts;
+ PacketDesc *pkt_desc;
+ const int preload= av_rescale(ctx->preload, 90000, AV_TIME_BASE);
+ const int is_iframe = st->codec->codec_type == CODEC_TYPE_VIDEO && (pkt->flags & PKT_FLAG_KEY);
+
+ pts= pkt->pts;
+ dts= pkt->dts;
+
+ if(pts != AV_NOPTS_VALUE) pts += preload;
+ if(dts != AV_NOPTS_VALUE) dts += preload;
+
+//av_log(ctx, AV_LOG_DEBUG, "dts:%f pts:%f flags:%d stream:%d nopts:%d\n", dts/90000.0, pts/90000.0, pkt->flags, pkt->stream_index, pts != AV_NOPTS_VALUE);
+ if (!stream->premux_packet)
+ stream->next_packet = &stream->premux_packet;
+ *stream->next_packet=
+ pkt_desc= av_mallocz(sizeof(PacketDesc));
+ pkt_desc->pts= pts;
+ pkt_desc->dts= dts;
+ pkt_desc->unwritten_size=
+ pkt_desc->size= size;
+ if(!stream->predecode_packet)
+ stream->predecode_packet= pkt_desc;
+ stream->next_packet= &pkt_desc->next;
+
+ av_fifo_realloc(&stream->fifo, av_fifo_size(&stream->fifo) + size + 1);
+
+ if (s->is_dvd){
+ if (is_iframe && (s->packet_number == 0 || (pts - stream->vobu_start_pts >= 36000))) { // min VOBU length 0.4 seconds (mpucoder)
+ stream->bytes_to_iframe = av_fifo_size(&stream->fifo);
+ stream->align_iframe = 1;
+ stream->vobu_start_pts = pts;
+ } else {
+ stream->align_iframe = 0;
+ }
+ }
+
+ av_fifo_write(&stream->fifo, buf, size);
+
+ for(;;){
+ int ret= output_packet(ctx, 0);
+ if(ret<=0)
+ return ret;
+ }
+}
+
+static int mpeg_mux_end(AVFormatContext *ctx)
+{
+// MpegMuxContext *s = ctx->priv_data;
+ StreamInfo *stream;
+ int i;
+
+ for(;;){
+ int ret= output_packet(ctx, 1);
+ if(ret<0)
+ return ret;
+ else if(ret==0)
+ break;
+ }
+
+ /* End header according to MPEG1 systems standard. We do not write
+ it as it is usually not needed by decoders and because it
+ complicates MPEG stream concatenation. */
+ //put_be32(&ctx->pb, ISO_11172_END_CODE);
+ //put_flush_packet(&ctx->pb);
+
+ for(i=0;i<ctx->nb_streams;i++) {
+ stream = ctx->streams[i]->priv_data;
+
+ assert(av_fifo_size(&stream->fifo) == 0);
+ av_fifo_free(&stream->fifo);
+ }
+ return 0;
+}
+#endif //CONFIG_MUXERS
+
+/*********************************************/
+/* demux code */
+
+#define MAX_SYNC_SIZE 100000
+
+static int cdxa_probe(AVProbeData *p)
+{
+ /* check file header */
+ if (p->buf_size <= 32)
+ return 0;
+ if (p->buf[0] == 'R' && p->buf[1] == 'I' &&
+ p->buf[2] == 'F' && p->buf[3] == 'F' &&
+ p->buf[8] == 'C' && p->buf[9] == 'D' &&
+ p->buf[10] == 'X' && p->buf[11] == 'A')
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+static int mpegps_probe(AVProbeData *p)
+{
+ uint32_t code= -1;
+ int sys=0, pspack=0, priv1=0, vid=0, audio=0;
+ int i;
+ int score=0;
+
+ score = cdxa_probe(p);
+ if (score > 0) return score;
+
+ /* Search for MPEG stream */
+ for(i=0; i<p->buf_size; i++){
+ code = (code<<8) + p->buf[i];
+ if ((code & 0xffffff00) == 0x100) {
+ if(code == SYSTEM_HEADER_START_CODE) sys++;
+ else if(code == PRIVATE_STREAM_1) priv1++;
+ else if(code == PACK_START_CODE) pspack++;
+ else if((code & 0xf0) == VIDEO_ID) vid++;
+ else if((code & 0xe0) == AUDIO_ID) audio++;
+ }
+ }
+
+ if(vid || audio) /* invalid VDR files nd short PES streams */
+ score= AVPROBE_SCORE_MAX/4;
+
+//av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d\n", sys, priv1, pspack,vid, audio);
+ if(sys && sys*9 <= pspack*10)
+ return AVPROBE_SCORE_MAX/2+2; // +1 for .mpg
+ if((priv1 || vid || audio) && (priv1+vid+audio)*9 <= pspack*10)
+ return AVPROBE_SCORE_MAX/2+2; // +1 for .mpg
+ if((!!vid ^ !!audio) && (audio+vid > 1) && !sys && !pspack) /* PES stream */
+ return AVPROBE_SCORE_MAX/2+2;
+
+ //02-Penguin.flac has sys:0 priv1:0 pspack:0 vid:0 audio:1
+ return score;
+}
+
+
+typedef struct MpegDemuxContext {
+ int32_t header_state;
+ unsigned char psm_es_type[256];
+} MpegDemuxContext;
+
+static int mpegps_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ MpegDemuxContext *m = s->priv_data;
+ m->header_state = 0xff;
+ s->ctx_flags |= AVFMTCTX_NOHEADER;
+
+ /* no need to do more */
+ return 0;
+}
+
+static int64_t get_pts(ByteIOContext *pb, int c)
+{
+ int64_t pts;
+ int val;
+
+ if (c < 0)
+ c = get_byte(pb);
+ pts = (int64_t)((c >> 1) & 0x07) << 30;
+ val = get_be16(pb);
+ pts |= (int64_t)(val >> 1) << 15;
+ val = get_be16(pb);
+ pts |= (int64_t)(val >> 1);
+ return pts;
+}
+
+static int find_next_start_code(ByteIOContext *pb, int *size_ptr,
+ int32_t *header_state)
+{
+ unsigned int state, v;
+ int val, n;
+
+ state = *header_state;
+ n = *size_ptr;
+ while (n > 0) {
+ if (url_feof(pb))
+ break;
+ v = get_byte(pb);
+ n--;
+ if (state == 0x000001) {
+ state = ((state << 8) | v) & 0xffffff;
+ val = state;
+ goto found;
+ }
+ state = ((state << 8) | v) & 0xffffff;
+ }
+ val = -1;
+ found:
+ *header_state = state;
+ *size_ptr = n;
+ return val;
+}
+
+#if 0 /* unused, remove? */
+/* XXX: optimize */
+static int find_prev_start_code(ByteIOContext *pb, int *size_ptr)
+{
+ int64_t pos, pos_start;
+ int max_size, start_code;
+
+ max_size = *size_ptr;
+ pos_start = url_ftell(pb);
+
+ /* in order to go faster, we fill the buffer */
+ pos = pos_start - 16386;
+ if (pos < 0)
+ pos = 0;
+ url_fseek(pb, pos, SEEK_SET);
+ get_byte(pb);
+
+ pos = pos_start;
+ for(;;) {
+ pos--;
+ if (pos < 0 || (pos_start - pos) >= max_size) {
+ start_code = -1;
+ goto the_end;
+ }
+ url_fseek(pb, pos, SEEK_SET);
+ start_code = get_be32(pb);
+ if ((start_code & 0xffffff00) == 0x100)
+ break;
+ }
+ the_end:
+ *size_ptr = pos_start - pos;
+ return start_code;
+}
+#endif
+
+/**
+ * Extracts stream types from a program stream map
+ * According to ISO/IEC 13818-1 ('MPEG-2 Systems') table 2-35
+ *
+ * @return number of bytes occupied by PSM in the bitstream
+ */
+static long mpegps_psm_parse(MpegDemuxContext *m, ByteIOContext *pb)
+{
+ int psm_length, ps_info_length, es_map_length;
+
+ psm_length = get_be16(pb);
+ get_byte(pb);
+ get_byte(pb);
+ ps_info_length = get_be16(pb);
+
+ /* skip program_stream_info */
+ url_fskip(pb, ps_info_length);
+ es_map_length = get_be16(pb);
+
+ /* at least one es available? */
+ while (es_map_length >= 4){
+ unsigned char type = get_byte(pb);
+ unsigned char es_id = get_byte(pb);
+ uint16_t es_info_length = get_be16(pb);
+ /* remember mapping from stream id to stream type */
+ m->psm_es_type[es_id] = type;
+ /* skip program_stream_info */
+ url_fskip(pb, es_info_length);
+ es_map_length -= 4 + es_info_length;
+ }
+ get_be32(pb); /* crc32 */
+ return 2 + psm_length;
+}
+
+/* read the next PES header. Return its position in ppos
+ (if not NULL), and its start code, pts and dts.
+ */
+static int mpegps_read_pes_header(AVFormatContext *s,
+ int64_t *ppos, int *pstart_code,
+ int64_t *ppts, int64_t *pdts)
+{
+ MpegDemuxContext *m = s->priv_data;
+ int len, size, startcode, c, flags, header_len;
+ int64_t pts, dts, last_pos;
+
+ last_pos = -1;
+ redo:
+ /* next start code (should be immediately after) */
+ m->header_state = 0xff;
+ size = MAX_SYNC_SIZE;
+ startcode = find_next_start_code(&s->pb, &size, &m->header_state);
+ //printf("startcode=%x pos=0x%"PRIx64"\n", startcode, url_ftell(&s->pb));
+ if (startcode < 0)
+ return AVERROR_IO;
+ if (startcode == PACK_START_CODE)
+ goto redo;
+ if (startcode == SYSTEM_HEADER_START_CODE)
+ goto redo;
+ if (startcode == PADDING_STREAM ||
+ startcode == PRIVATE_STREAM_2) {
+ /* skip them */
+ len = get_be16(&s->pb);
+ url_fskip(&s->pb, len);
+ goto redo;
+ }
+ if (startcode == PROGRAM_STREAM_MAP) {
+ mpegps_psm_parse(m, &s->pb);
+ goto redo;
+ }
+
+ /* find matching stream */
+ if (!((startcode >= 0x1c0 && startcode <= 0x1df) ||
+ (startcode >= 0x1e0 && startcode <= 0x1ef) ||
+ (startcode == 0x1bd)))
+ goto redo;
+ if (ppos) {
+ *ppos = url_ftell(&s->pb) - 4;
+ }
+ len = get_be16(&s->pb);
+ pts = AV_NOPTS_VALUE;
+ dts = AV_NOPTS_VALUE;
+ /* stuffing */
+ for(;;) {
+ if (len < 1)
+ goto redo;
+ c = get_byte(&s->pb);
+ len--;
+ /* XXX: for mpeg1, should test only bit 7 */
+ if (c != 0xff)
+ break;
+ }
+ if ((c & 0xc0) == 0x40) {
+ /* buffer scale & size */
+ if (len < 2)
+ goto redo;
+ get_byte(&s->pb);
+ c = get_byte(&s->pb);
+ len -= 2;
+ }
+ if ((c & 0xf0) == 0x20) {
+ if (len < 4)
+ goto redo;
+ dts = pts = get_pts(&s->pb, c);
+ len -= 4;
+ } else if ((c & 0xf0) == 0x30) {
+ if (len < 9)
+ goto redo;
+ pts = get_pts(&s->pb, c);
+ dts = get_pts(&s->pb, -1);
+ len -= 9;
+ } else if ((c & 0xc0) == 0x80) {
+ /* mpeg 2 PES */
+#if 0 /* some streams have this field set for no apparent reason */
+ if ((c & 0x30) != 0) {
+ /* Encrypted multiplex not handled */
+ goto redo;
+ }
+#endif
+ flags = get_byte(&s->pb);
+ header_len = get_byte(&s->pb);
+ len -= 2;
+ if (header_len > len)
+ goto redo;
+ if ((flags & 0xc0) == 0x80) {
+ dts = pts = get_pts(&s->pb, -1);
+ if (header_len < 5)
+ goto redo;
+ header_len -= 5;
+ len -= 5;
+ } if ((flags & 0xc0) == 0xc0) {
+ pts = get_pts(&s->pb, -1);
+ dts = get_pts(&s->pb, -1);
+ if (header_len < 10)
+ goto redo;
+ header_len -= 10;
+ len -= 10;
+ }
+ len -= header_len;
+ while (header_len > 0) {
+ get_byte(&s->pb);
+ header_len--;
+ }
+ }
+ else if( c!= 0xf )
+ goto redo;
+
+ if (startcode == PRIVATE_STREAM_1 && !m->psm_es_type[startcode & 0xff]) {
+ if (len < 1)
+ goto redo;
+ startcode = get_byte(&s->pb);
+ len--;
+ if (startcode >= 0x80 && startcode <= 0xbf) {
+ /* audio: skip header */
+ if (len < 3)
+ goto redo;
+ get_byte(&s->pb);
+ get_byte(&s->pb);
+ get_byte(&s->pb);
+ len -= 3;
+ }
+ }
+ if(dts != AV_NOPTS_VALUE && ppos){
+ int i;
+ for(i=0; i<s->nb_streams; i++){
+ if(startcode == s->streams[i]->id) {
+ av_add_index_entry(s->streams[i], *ppos, dts, 0, 0, AVINDEX_KEYFRAME /* FIXME keyframe? */);
+ }
+ }
+ }
+
+ *pstart_code = startcode;
+ *ppts = pts;
+ *pdts = dts;
+ return len;
+}
+
+static int mpegps_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ MpegDemuxContext *m = s->priv_data;
+ AVStream *st;
+ int len, startcode, i, type, codec_id = 0, es_type;
+ int64_t pts, dts, dummy_pos; //dummy_pos is needed for the index building to work
+
+ redo:
+ len = mpegps_read_pes_header(s, &dummy_pos, &startcode, &pts, &dts);
+ if (len < 0)
+ return len;
+
+ /* now find stream */
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+ if (st->id == startcode)
+ goto found;
+ }
+
+ es_type = m->psm_es_type[startcode & 0xff];
+ if(es_type > 0){
+ if(es_type == STREAM_TYPE_VIDEO_MPEG1){
+ codec_id = CODEC_ID_MPEG2VIDEO;
+ type = CODEC_TYPE_VIDEO;
+ } else if(es_type == STREAM_TYPE_VIDEO_MPEG2){
+ codec_id = CODEC_ID_MPEG2VIDEO;
+ type = CODEC_TYPE_VIDEO;
+ } else if(es_type == STREAM_TYPE_AUDIO_MPEG1 ||
+ es_type == STREAM_TYPE_AUDIO_MPEG2){
+ codec_id = CODEC_ID_MP3;
+ type = CODEC_TYPE_AUDIO;
+ } else if(es_type == STREAM_TYPE_AUDIO_AAC){
+ codec_id = CODEC_ID_AAC;
+ type = CODEC_TYPE_AUDIO;
+ } else if(es_type == STREAM_TYPE_VIDEO_MPEG4){
+ codec_id = CODEC_ID_MPEG4;
+ type = CODEC_TYPE_VIDEO;
+ } else if(es_type == STREAM_TYPE_VIDEO_H264){
+ codec_id = CODEC_ID_H264;
+ type = CODEC_TYPE_VIDEO;
+ } else if(es_type == STREAM_TYPE_AUDIO_AC3){
+ codec_id = CODEC_ID_AC3;
+ type = CODEC_TYPE_AUDIO;
+ } else {
+ goto skip;
+ }
+ } else if (startcode >= 0x1e0 && startcode <= 0x1ef) {
+ static const unsigned char avs_seqh[4] = { 0, 0, 1, 0xb0 };
+ unsigned char buf[8];
+ get_buffer(&s->pb, buf, 8);
+ url_fseek(&s->pb, -8, SEEK_CUR);
+ if(!memcmp(buf, avs_seqh, 4) && (buf[6] != 0 || buf[7] != 1))
+ codec_id = CODEC_ID_CAVS;
+ else
+ codec_id = CODEC_ID_MPEG2VIDEO;
+ type = CODEC_TYPE_VIDEO;
+ } else if (startcode >= 0x1c0 && startcode <= 0x1df) {
+ type = CODEC_TYPE_AUDIO;
+ codec_id = CODEC_ID_MP2;
+ } else if (startcode >= 0x80 && startcode <= 0x87) {
+ type = CODEC_TYPE_AUDIO;
+ codec_id = CODEC_ID_AC3;
+ } else if (startcode >= 0x88 && startcode <= 0x9f) {
+ type = CODEC_TYPE_AUDIO;
+ codec_id = CODEC_ID_DTS;
+ } else if (startcode >= 0xa0 && startcode <= 0xbf) {
+ type = CODEC_TYPE_AUDIO;
+ codec_id = CODEC_ID_PCM_S16BE;
+ } else if (startcode >= 0x20 && startcode <= 0x3f) {
+ type = CODEC_TYPE_SUBTITLE;
+ codec_id = CODEC_ID_DVD_SUBTITLE;
+ } else {
+ skip:
+ /* skip packet */
+ url_fskip(&s->pb, len);
+ goto redo;
+ }
+ /* no stream found: add a new stream */
+ st = av_new_stream(s, startcode);
+ if (!st)
+ goto skip;
+ st->codec->codec_type = type;
+ st->codec->codec_id = codec_id;
+ if (codec_id != CODEC_ID_PCM_S16BE)
+ st->need_parsing = 1;
+ found:
+ if(st->discard >= AVDISCARD_ALL)
+ goto skip;
+ if (startcode >= 0xa0 && startcode <= 0xbf) {
+ int b1, freq;
+
+ /* for LPCM, we just skip the header and consider it is raw
+ audio data */
+ if (len <= 3)
+ goto skip;
+ get_byte(&s->pb); /* emphasis (1), muse(1), reserved(1), frame number(5) */
+ b1 = get_byte(&s->pb); /* quant (2), freq(2), reserved(1), channels(3) */
+ get_byte(&s->pb); /* dynamic range control (0x80 = off) */
+ len -= 3;
+ freq = (b1 >> 4) & 3;
+ st->codec->sample_rate = lpcm_freq_tab[freq];
+ st->codec->channels = 1 + (b1 & 7);
+ st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * 2;
+ }
+ av_new_packet(pkt, len);
+ get_buffer(&s->pb, pkt->data, pkt->size);
+ pkt->pts = pts;
+ pkt->dts = dts;
+ pkt->stream_index = st->index;
+#if 0
+ av_log(s, AV_LOG_DEBUG, "%d: pts=%0.3f dts=%0.3f size=%d\n",
+ pkt->stream_index, pkt->pts / 90000.0, pkt->dts / 90000.0, pkt->size);
+#endif
+
+ return 0;
+}
+
+static int mpegps_read_close(AVFormatContext *s)
+{
+ return 0;
+}
+
+static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index,
+ int64_t *ppos, int64_t pos_limit)
+{
+ int len, startcode;
+ int64_t pos, pts, dts;
+
+ pos = *ppos;
+#ifdef DEBUG_SEEK
+ printf("read_dts: pos=0x%"PRIx64" next=%d -> ", pos, find_next);
+#endif
+ url_fseek(&s->pb, pos, SEEK_SET);
+ for(;;) {
+ len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts);
+ if (len < 0) {
+#ifdef DEBUG_SEEK
+ printf("none (ret=%d)\n", len);
+#endif
+ return AV_NOPTS_VALUE;
+ }
+ if (startcode == s->streams[stream_index]->id &&
+ dts != AV_NOPTS_VALUE) {
+ break;
+ }
+ url_fskip(&s->pb, len);
+ }
+#ifdef DEBUG_SEEK
+ printf("pos=0x%"PRIx64" dts=0x%"PRIx64" %0.3f\n", pos, dts, dts / 90000.0);
+#endif
+ *ppos = pos;
+ return dts;
+}
+
+#ifdef CONFIG_MPEG1SYSTEM_MUXER
+AVOutputFormat mpeg1system_muxer = {
+ "mpeg",
+ "MPEG1 System format",
+ "video/mpeg",
+ "mpg,mpeg",
+ sizeof(MpegMuxContext),
+ CODEC_ID_MP2,
+ CODEC_ID_MPEG1VIDEO,
+ mpeg_mux_init,
+ mpeg_mux_write_packet,
+ mpeg_mux_end,
+};
+#endif
+#ifdef CONFIG_MPEG1VCD_MUXER
+AVOutputFormat mpeg1vcd_muxer = {
+ "vcd",
+ "MPEG1 System format (VCD)",
+ "video/mpeg",
+ NULL,
+ sizeof(MpegMuxContext),
+ CODEC_ID_MP2,
+ CODEC_ID_MPEG1VIDEO,
+ mpeg_mux_init,
+ mpeg_mux_write_packet,
+ mpeg_mux_end,
+};
+#endif
+#ifdef CONFIG_MPEG2VOB_MUXER
+AVOutputFormat mpeg2vob_muxer = {
+ "vob",
+ "MPEG2 PS format (VOB)",
+ "video/mpeg",
+ "vob",
+ sizeof(MpegMuxContext),
+ CODEC_ID_MP2,
+ CODEC_ID_MPEG2VIDEO,
+ mpeg_mux_init,
+ mpeg_mux_write_packet,
+ mpeg_mux_end,
+};
+#endif
+
+/* Same as mpeg2vob_mux except that the pack size is 2324 */
+#ifdef CONFIG_MPEG2SVCD_MUXER
+AVOutputFormat mpeg2svcd_muxer = {
+ "svcd",
+ "MPEG2 PS format (VOB)",
+ "video/mpeg",
+ "vob",
+ sizeof(MpegMuxContext),
+ CODEC_ID_MP2,
+ CODEC_ID_MPEG2VIDEO,
+ mpeg_mux_init,
+ mpeg_mux_write_packet,
+ mpeg_mux_end,
+};
+#endif
+
+/* Same as mpeg2vob_mux except the 'is_dvd' flag is set to produce NAV pkts */
+#ifdef CONFIG_MPEG2DVD_MUXER
+AVOutputFormat mpeg2dvd_muxer = {
+ "dvd",
+ "MPEG2 PS format (DVD VOB)",
+ "video/mpeg",
+ "dvd",
+ sizeof(MpegMuxContext),
+ CODEC_ID_MP2,
+ CODEC_ID_MPEG2VIDEO,
+ mpeg_mux_init,
+ mpeg_mux_write_packet,
+ mpeg_mux_end,
+};
+#endif
+
+#ifdef CONFIG_MPEGPS_DEMUXER
+AVInputFormat mpegps_demuxer = {
+ "mpeg",
+ "MPEG PS format",
+ sizeof(MpegDemuxContext),
+ mpegps_probe,
+ mpegps_read_header,
+ mpegps_read_packet,
+ mpegps_read_close,
+ NULL, //mpegps_read_seek,
+ mpegps_read_dts,
+ .flags = AVFMT_SHOW_IDS,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/mpegts.c b/contrib/ffmpeg/libavformat/mpegts.c
new file mode 100644
index 000000000..dd5f0adca
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/mpegts.c
@@ -0,0 +1,1527 @@
+/*
+ * MPEG2 transport stream (aka DVB) demuxer
+ * 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 "avformat.h"
+#include "crc.h"
+#include "mpegts.h"
+
+//#define DEBUG_SI
+//#define DEBUG_SEEK
+
+/* 1.0 second at 24Mbit/s */
+#define MAX_SCAN_PACKETS 32000
+
+/* maximum size in which we look for synchronisation if
+ synchronisation is lost */
+#define MAX_RESYNC_SIZE 4096
+
+typedef struct PESContext PESContext;
+
+static PESContext* add_pes_stream(MpegTSContext *ts, int pid, int stream_type);
+static AVStream* new_pes_av_stream(PESContext *pes, uint32_t code);
+
+enum MpegTSFilterType {
+ MPEGTS_PES,
+ MPEGTS_SECTION,
+};
+
+typedef void PESCallback(void *opaque, const uint8_t *buf, int len, int is_start);
+
+typedef struct MpegTSPESFilter {
+ PESCallback *pes_cb;
+ void *opaque;
+} MpegTSPESFilter;
+
+typedef void SectionCallback(void *opaque, const uint8_t *buf, int len);
+
+typedef void SetServiceCallback(void *opaque, int ret);
+
+typedef struct MpegTSSectionFilter {
+ int section_index;
+ int section_h_size;
+ uint8_t *section_buf;
+ int check_crc:1;
+ int end_of_section_reached:1;
+ SectionCallback *section_cb;
+ void *opaque;
+} MpegTSSectionFilter;
+
+typedef struct MpegTSFilter {
+ int pid;
+ int last_cc; /* last cc code (-1 if first packet) */
+ enum MpegTSFilterType type;
+ union {
+ MpegTSPESFilter pes_filter;
+ MpegTSSectionFilter section_filter;
+ } u;
+} MpegTSFilter;
+
+typedef struct MpegTSService {
+ int running:1;
+ int sid;
+ char *provider_name;
+ char *name;
+} MpegTSService;
+
+struct MpegTSContext {
+ /* user data */
+ AVFormatContext *stream;
+ int raw_packet_size; /* raw packet size, including FEC if present */
+ int auto_guess; /* if true, all pids are analized to find streams */
+ int set_service_ret;
+
+ int mpeg2ts_raw; /* force raw MPEG2 transport stream output, if possible */
+ int mpeg2ts_compute_pcr; /* compute exact PCR for each transport stream packet */
+
+ /* used to estimate the exact PCR */
+ int64_t cur_pcr;
+ int pcr_incr;
+ int pcr_pid;
+
+ /* data needed to handle file based ts */
+ int stop_parse; /* stop parsing loop */
+ AVPacket *pkt; /* packet containing av data */
+
+ /******************************************/
+ /* private mpegts data */
+ /* scan context */
+ MpegTSFilter *sdt_filter;
+ int nb_services;
+ MpegTSService **services;
+
+ /* set service context (XXX: allocated it ?) */
+ SetServiceCallback *set_service_cb;
+ void *set_service_opaque;
+ MpegTSFilter *pat_filter;
+ MpegTSFilter *pmt_filter;
+ int req_sid;
+
+ MpegTSFilter *pids[NB_PID_MAX];
+};
+
+static void write_section_data(AVFormatContext *s, MpegTSFilter *tss1,
+ const uint8_t *buf, int buf_size, int is_start)
+{
+ MpegTSSectionFilter *tss = &tss1->u.section_filter;
+ int len;
+
+ if (is_start) {
+ memcpy(tss->section_buf, buf, buf_size);
+ tss->section_index = buf_size;
+ tss->section_h_size = -1;
+ tss->end_of_section_reached = 0;
+ } else {
+ if (tss->end_of_section_reached)
+ return;
+ len = 4096 - tss->section_index;
+ if (buf_size < len)
+ len = buf_size;
+ memcpy(tss->section_buf + tss->section_index, buf, len);
+ tss->section_index += len;
+ }
+
+ /* compute section length if possible */
+ if (tss->section_h_size == -1 && tss->section_index >= 3) {
+ len = (((tss->section_buf[1] & 0xf) << 8) | tss->section_buf[2]) + 3;
+ if (len > 4096)
+ return;
+ tss->section_h_size = len;
+ }
+
+ if (tss->section_h_size != -1 && tss->section_index >= tss->section_h_size) {
+ tss->end_of_section_reached = 1;
+ if (!tss->check_crc ||
+ av_crc(av_crc04C11DB7, -1, tss->section_buf, tss->section_h_size) == 0)
+ tss->section_cb(tss->opaque, tss->section_buf, tss->section_h_size);
+ }
+}
+
+static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, unsigned int pid,
+ SectionCallback *section_cb, void *opaque,
+ int check_crc)
+
+{
+ MpegTSFilter *filter;
+ MpegTSSectionFilter *sec;
+
+#ifdef DEBUG_SI
+ printf("Filter: pid=0x%x\n", pid);
+#endif
+ if (pid >= NB_PID_MAX || ts->pids[pid])
+ return NULL;
+ filter = av_mallocz(sizeof(MpegTSFilter));
+ if (!filter)
+ return NULL;
+ ts->pids[pid] = filter;
+ filter->type = MPEGTS_SECTION;
+ filter->pid = pid;
+ filter->last_cc = -1;
+ sec = &filter->u.section_filter;
+ sec->section_cb = section_cb;
+ sec->opaque = opaque;
+ sec->section_buf = av_malloc(MAX_SECTION_SIZE);
+ sec->check_crc = check_crc;
+ if (!sec->section_buf) {
+ av_free(filter);
+ return NULL;
+ }
+ return filter;
+}
+
+static MpegTSFilter *mpegts_open_pes_filter(MpegTSContext *ts, unsigned int pid,
+ PESCallback *pes_cb,
+ void *opaque)
+{
+ MpegTSFilter *filter;
+ MpegTSPESFilter *pes;
+
+ if (pid >= NB_PID_MAX || ts->pids[pid])
+ return NULL;
+ filter = av_mallocz(sizeof(MpegTSFilter));
+ if (!filter)
+ return NULL;
+ ts->pids[pid] = filter;
+ filter->type = MPEGTS_PES;
+ filter->pid = pid;
+ filter->last_cc = -1;
+ pes = &filter->u.pes_filter;
+ pes->pes_cb = pes_cb;
+ pes->opaque = opaque;
+ return filter;
+}
+
+static void mpegts_close_filter(MpegTSContext *ts, MpegTSFilter *filter)
+{
+ int pid;
+
+ pid = filter->pid;
+ if (filter->type == MPEGTS_SECTION)
+ av_freep(&filter->u.section_filter.section_buf);
+ else if (filter->type == MPEGTS_PES)
+ av_freep(&filter->u.pes_filter.opaque);
+
+ av_free(filter);
+ ts->pids[pid] = NULL;
+}
+
+static int analyze(const uint8_t *buf, int size, int packet_size, int *index){
+ int stat[packet_size];
+ int i;
+ int x=0;
+ int best_score=0;
+
+ memset(stat, 0, packet_size*sizeof(int));
+
+ for(x=i=0; i<size; i++){
+ if(buf[i] == 0x47){
+ stat[x]++;
+ if(stat[x] > best_score){
+ best_score= stat[x];
+ if(index) *index= x;
+ }
+ }
+
+ x++;
+ if(x == packet_size) x= 0;
+ }
+
+ return best_score;
+}
+
+/* autodetect fec presence. Must have at least 1024 bytes */
+static int get_packet_size(const uint8_t *buf, int size)
+{
+ int score, fec_score, dvhs_score;
+
+ if (size < (TS_FEC_PACKET_SIZE * 5 + 1))
+ return -1;
+
+ score = analyze(buf, size, TS_PACKET_SIZE, NULL);
+ dvhs_score = analyze(buf, size, TS_DVHS_PACKET_SIZE, NULL);
+ fec_score= analyze(buf, size, TS_FEC_PACKET_SIZE, NULL);
+// av_log(NULL, AV_LOG_DEBUG, "score: %d, dvhs_score: %d, fec_score: %d \n", score, dvhs_score, fec_score);
+
+ if (score > fec_score && score > dvhs_score) return TS_PACKET_SIZE;
+ else if(dvhs_score > score && dvhs_score > fec_score) return TS_DVHS_PACKET_SIZE;
+ else if(score < fec_score && dvhs_score < fec_score) return TS_FEC_PACKET_SIZE;
+ else return -1;
+}
+
+typedef struct SectionHeader {
+ uint8_t tid;
+ uint16_t id;
+ uint8_t version;
+ uint8_t sec_num;
+ uint8_t last_sec_num;
+} SectionHeader;
+
+static inline int get8(const uint8_t **pp, const uint8_t *p_end)
+{
+ const uint8_t *p;
+ int c;
+
+ p = *pp;
+ if (p >= p_end)
+ return -1;
+ c = *p++;
+ *pp = p;
+ return c;
+}
+
+static inline int get16(const uint8_t **pp, const uint8_t *p_end)
+{
+ const uint8_t *p;
+ int c;
+
+ p = *pp;
+ if ((p + 1) >= p_end)
+ return -1;
+ c = (p[0] << 8) | p[1];
+ p += 2;
+ *pp = p;
+ return c;
+}
+
+/* read and allocate a DVB string preceeded by its length */
+static char *getstr8(const uint8_t **pp, const uint8_t *p_end)
+{
+ int len;
+ const uint8_t *p;
+ char *str;
+
+ p = *pp;
+ len = get8(&p, p_end);
+ if (len < 0)
+ return NULL;
+ if ((p + len) > p_end)
+ return NULL;
+ str = av_malloc(len + 1);
+ if (!str)
+ return NULL;
+ memcpy(str, p, len);
+ str[len] = '\0';
+ p += len;
+ *pp = p;
+ return str;
+}
+
+static int parse_section_header(SectionHeader *h,
+ const uint8_t **pp, const uint8_t *p_end)
+{
+ int val;
+
+ val = get8(pp, p_end);
+ if (val < 0)
+ return -1;
+ h->tid = val;
+ *pp += 2;
+ val = get16(pp, p_end);
+ if (val < 0)
+ return -1;
+ h->id = val;
+ val = get8(pp, p_end);
+ if (val < 0)
+ return -1;
+ h->version = (val >> 1) & 0x1f;
+ val = get8(pp, p_end);
+ if (val < 0)
+ return -1;
+ h->sec_num = val;
+ val = get8(pp, p_end);
+ if (val < 0)
+ return -1;
+ h->last_sec_num = val;
+ return 0;
+}
+
+static MpegTSService *new_service(MpegTSContext *ts, int sid,
+ char *provider_name, char *name)
+{
+ MpegTSService *service;
+
+#ifdef DEBUG_SI
+ printf("new_service: sid=0x%04x provider='%s' name='%s'\n",
+ sid, provider_name, name);
+#endif
+
+ service = av_mallocz(sizeof(MpegTSService));
+ if (!service)
+ return NULL;
+ service->sid = sid;
+ service->provider_name = provider_name;
+ service->name = name;
+ dynarray_add(&ts->services, &ts->nb_services, service);
+ return service;
+}
+
+static void pmt_cb(void *opaque, const uint8_t *section, int section_len)
+{
+ MpegTSContext *ts = opaque;
+ SectionHeader h1, *h = &h1;
+ PESContext *pes;
+ AVStream *st;
+ const uint8_t *p, *p_end, *desc_list_end, *desc_end;
+ int program_info_length, pcr_pid, pid, stream_type;
+ int desc_list_len, desc_len, desc_tag;
+ int comp_page = 0, anc_page = 0; /* initialize to kill warnings */
+ char language[4];
+
+#ifdef DEBUG_SI
+ printf("PMT:\n");
+ av_hex_dump(stdout, (uint8_t *)section, section_len);
+#endif
+ p_end = section + section_len - 4;
+ p = section;
+ if (parse_section_header(h, &p, p_end) < 0)
+ return;
+#ifdef DEBUG_SI
+ printf("sid=0x%x sec_num=%d/%d\n", h->id, h->sec_num, h->last_sec_num);
+#endif
+ if (h->tid != PMT_TID || (ts->req_sid >= 0 && h->id != ts->req_sid) )
+ return;
+
+ pcr_pid = get16(&p, p_end) & 0x1fff;
+ if (pcr_pid < 0)
+ return;
+ ts->pcr_pid = pcr_pid;
+#ifdef DEBUG_SI
+ printf("pcr_pid=0x%x\n", pcr_pid);
+#endif
+ program_info_length = get16(&p, p_end) & 0xfff;
+ if (program_info_length < 0)
+ return;
+ p += program_info_length;
+ if (p >= p_end)
+ return;
+ for(;;) {
+ language[0] = 0;
+ st = 0;
+ stream_type = get8(&p, p_end);
+ if (stream_type < 0)
+ break;
+ pid = get16(&p, p_end) & 0x1fff;
+ if (pid < 0)
+ break;
+ desc_list_len = get16(&p, p_end) & 0xfff;
+ if (desc_list_len < 0)
+ break;
+ desc_list_end = p + desc_list_len;
+ if (desc_list_end > p_end)
+ break;
+ for(;;) {
+ desc_tag = get8(&p, desc_list_end);
+ if (desc_tag < 0)
+ break;
+ if (stream_type == STREAM_TYPE_PRIVATE_DATA) {
+ if((desc_tag == 0x6A) || (desc_tag == 0x7A)) {
+ /*assume DVB AC-3 Audio*/
+ stream_type = STREAM_TYPE_AUDIO_AC3;
+ } else if(desc_tag == 0x7B) {
+ /* DVB DTS audio */
+ stream_type = STREAM_TYPE_AUDIO_DTS;
+ }
+ }
+ desc_len = get8(&p, desc_list_end);
+ desc_end = p + desc_len;
+ if (desc_end > desc_list_end)
+ break;
+#ifdef DEBUG_SI
+ printf("tag: 0x%02x len=%d\n", desc_tag, desc_len);
+#endif
+ switch(desc_tag) {
+ case DVB_SUBT_DESCID:
+ if (stream_type == STREAM_TYPE_PRIVATE_DATA)
+ stream_type = STREAM_TYPE_SUBTITLE_DVB;
+
+ language[0] = get8(&p, desc_end);
+ language[1] = get8(&p, desc_end);
+ language[2] = get8(&p, desc_end);
+ language[3] = 0;
+ get8(&p, desc_end);
+ comp_page = get16(&p, desc_end);
+ anc_page = get16(&p, desc_end);
+
+ break;
+ case 0x0a: /* ISO 639 language descriptor */
+ language[0] = get8(&p, desc_end);
+ language[1] = get8(&p, desc_end);
+ language[2] = get8(&p, desc_end);
+ language[3] = 0;
+ break;
+ default:
+ break;
+ }
+ p = desc_end;
+ }
+ p = desc_list_end;
+
+#ifdef DEBUG_SI
+ printf("stream_type=%d pid=0x%x\n", stream_type, pid);
+#endif
+
+ /* now create ffmpeg stream */
+ switch(stream_type) {
+ case STREAM_TYPE_AUDIO_MPEG1:
+ case STREAM_TYPE_AUDIO_MPEG2:
+ case STREAM_TYPE_VIDEO_MPEG1:
+ case STREAM_TYPE_VIDEO_MPEG2:
+ case STREAM_TYPE_VIDEO_MPEG4:
+ case STREAM_TYPE_VIDEO_H264:
+ case STREAM_TYPE_AUDIO_AAC:
+ case STREAM_TYPE_AUDIO_AC3:
+ case STREAM_TYPE_AUDIO_DTS:
+ case STREAM_TYPE_SUBTITLE_DVB:
+ pes = add_pes_stream(ts, pid, stream_type);
+ if (pes)
+ st = new_pes_av_stream(pes, 0);
+ break;
+ default:
+ /* we ignore the other streams */
+ break;
+ }
+
+ if (st) {
+ if (language[0] != 0) {
+ st->language[0] = language[0];
+ st->language[1] = language[1];
+ st->language[2] = language[2];
+ st->language[3] = language[3];
+ }
+
+ if (stream_type == STREAM_TYPE_SUBTITLE_DVB) {
+ st->codec->sub_id = (anc_page << 16) | comp_page;
+ }
+ }
+ }
+ /* all parameters are there */
+ ts->set_service_cb(ts->set_service_opaque, 0);
+ mpegts_close_filter(ts, ts->pmt_filter);
+ ts->pmt_filter = NULL;
+}
+
+static void pat_cb(void *opaque, const uint8_t *section, int section_len)
+{
+ MpegTSContext *ts = opaque;
+ SectionHeader h1, *h = &h1;
+ const uint8_t *p, *p_end;
+ int sid, pmt_pid;
+
+#ifdef DEBUG_SI
+ printf("PAT:\n");
+ av_hex_dump(stdout, (uint8_t *)section, section_len);
+#endif
+ p_end = section + section_len - 4;
+ p = section;
+ if (parse_section_header(h, &p, p_end) < 0)
+ return;
+ if (h->tid != PAT_TID)
+ return;
+
+ for(;;) {
+ sid = get16(&p, p_end);
+ if (sid < 0)
+ break;
+ pmt_pid = get16(&p, p_end) & 0x1fff;
+ if (pmt_pid < 0)
+ break;
+#ifdef DEBUG_SI
+ printf("sid=0x%x pid=0x%x\n", sid, pmt_pid);
+#endif
+ if (sid == 0x0000) {
+ /* NIT info */
+ } else {
+ if (ts->req_sid == sid) {
+ ts->pmt_filter = mpegts_open_section_filter(ts, pmt_pid,
+ pmt_cb, ts, 1);
+ goto found;
+ }
+ }
+ }
+ /* not found */
+ ts->set_service_cb(ts->set_service_opaque, -1);
+
+ found:
+ mpegts_close_filter(ts, ts->pat_filter);
+ ts->pat_filter = NULL;
+}
+
+/* add all services found in the PAT */
+static void pat_scan_cb(void *opaque, const uint8_t *section, int section_len)
+{
+ MpegTSContext *ts = opaque;
+ SectionHeader h1, *h = &h1;
+ const uint8_t *p, *p_end;
+ int sid, pmt_pid;
+ char *provider_name, *name;
+ char buf[256];
+
+#ifdef DEBUG_SI
+ printf("PAT:\n");
+ av_hex_dump(stdout, (uint8_t *)section, section_len);
+#endif
+ p_end = section + section_len - 4;
+ p = section;
+ if (parse_section_header(h, &p, p_end) < 0)
+ return;
+ if (h->tid != PAT_TID)
+ return;
+
+ for(;;) {
+ sid = get16(&p, p_end);
+ if (sid < 0)
+ break;
+ pmt_pid = get16(&p, p_end) & 0x1fff;
+ if (pmt_pid < 0)
+ break;
+#ifdef DEBUG_SI
+ printf("sid=0x%x pid=0x%x\n", sid, pmt_pid);
+#endif
+ if (sid == 0x0000) {
+ /* NIT info */
+ } else {
+ /* add the service with a dummy name */
+ snprintf(buf, sizeof(buf), "Service %x\n", sid);
+ name = av_strdup(buf);
+ provider_name = av_strdup("");
+ if (name && provider_name) {
+ new_service(ts, sid, provider_name, name);
+ } else {
+ av_freep(&name);
+ av_freep(&provider_name);
+ }
+ }
+ }
+ ts->stop_parse = 1;
+
+ /* remove filter */
+ mpegts_close_filter(ts, ts->pat_filter);
+ ts->pat_filter = NULL;
+}
+
+static void mpegts_set_service(MpegTSContext *ts, int sid,
+ SetServiceCallback *set_service_cb, void *opaque)
+{
+ ts->set_service_cb = set_service_cb;
+ ts->set_service_opaque = opaque;
+ ts->req_sid = sid;
+ ts->pat_filter = mpegts_open_section_filter(ts, PAT_PID,
+ pat_cb, ts, 1);
+}
+
+static void sdt_cb(void *opaque, const uint8_t *section, int section_len)
+{
+ MpegTSContext *ts = opaque;
+ SectionHeader h1, *h = &h1;
+ const uint8_t *p, *p_end, *desc_list_end, *desc_end;
+ int onid, val, sid, desc_list_len, desc_tag, desc_len, service_type;
+ char *name, *provider_name;
+
+#ifdef DEBUG_SI
+ printf("SDT:\n");
+ av_hex_dump(stdout, (uint8_t *)section, section_len);
+#endif
+
+ p_end = section + section_len - 4;
+ p = section;
+ if (parse_section_header(h, &p, p_end) < 0)
+ return;
+ if (h->tid != SDT_TID)
+ return;
+ onid = get16(&p, p_end);
+ if (onid < 0)
+ return;
+ val = get8(&p, p_end);
+ if (val < 0)
+ return;
+ for(;;) {
+ sid = get16(&p, p_end);
+ if (sid < 0)
+ break;
+ val = get8(&p, p_end);
+ if (val < 0)
+ break;
+ desc_list_len = get16(&p, p_end) & 0xfff;
+ if (desc_list_len < 0)
+ break;
+ desc_list_end = p + desc_list_len;
+ if (desc_list_end > p_end)
+ break;
+ for(;;) {
+ desc_tag = get8(&p, desc_list_end);
+ if (desc_tag < 0)
+ break;
+ desc_len = get8(&p, desc_list_end);
+ desc_end = p + desc_len;
+ if (desc_end > desc_list_end)
+ break;
+#ifdef DEBUG_SI
+ printf("tag: 0x%02x len=%d\n", desc_tag, desc_len);
+#endif
+ switch(desc_tag) {
+ case 0x48:
+ service_type = get8(&p, p_end);
+ if (service_type < 0)
+ break;
+ provider_name = getstr8(&p, p_end);
+ if (!provider_name)
+ break;
+ name = getstr8(&p, p_end);
+ if (!name)
+ break;
+ new_service(ts, sid, provider_name, name);
+ break;
+ default:
+ break;
+ }
+ p = desc_end;
+ }
+ p = desc_list_end;
+ }
+ ts->stop_parse = 1;
+
+ /* remove filter */
+ mpegts_close_filter(ts, ts->sdt_filter);
+ ts->sdt_filter = NULL;
+}
+
+/* scan services in a transport stream by looking at the SDT */
+static void mpegts_scan_sdt(MpegTSContext *ts)
+{
+ ts->sdt_filter = mpegts_open_section_filter(ts, SDT_PID,
+ sdt_cb, ts, 1);
+}
+
+/* scan services in a transport stream by looking at the PAT (better
+ than nothing !) */
+static void mpegts_scan_pat(MpegTSContext *ts)
+{
+ ts->pat_filter = mpegts_open_section_filter(ts, PAT_PID,
+ pat_scan_cb, ts, 1);
+}
+
+/* TS stream handling */
+
+enum MpegTSState {
+ MPEGTS_HEADER = 0,
+ MPEGTS_PESHEADER_FILL,
+ MPEGTS_PAYLOAD,
+ MPEGTS_SKIP,
+};
+
+/* enough for PES header + length */
+#define PES_START_SIZE 9
+#define MAX_PES_HEADER_SIZE (9 + 255)
+
+struct PESContext {
+ int pid;
+ int stream_type;
+ MpegTSContext *ts;
+ AVFormatContext *stream;
+ AVStream *st;
+ enum MpegTSState state;
+ /* used to get the format */
+ int data_index;
+ int total_size;
+ int pes_header_size;
+ int64_t pts, dts;
+ uint8_t header[MAX_PES_HEADER_SIZE];
+};
+
+static int64_t get_pts(const uint8_t *p)
+{
+ int64_t pts;
+ int val;
+
+ pts = (int64_t)((p[0] >> 1) & 0x07) << 30;
+ val = (p[1] << 8) | p[2];
+ pts |= (int64_t)(val >> 1) << 15;
+ val = (p[3] << 8) | p[4];
+ pts |= (int64_t)(val >> 1);
+ return pts;
+}
+
+/* return non zero if a packet could be constructed */
+static void mpegts_push_data(void *opaque,
+ const uint8_t *buf, int buf_size, int is_start)
+{
+ PESContext *pes = opaque;
+ MpegTSContext *ts = pes->ts;
+ const uint8_t *p;
+ int len, code;
+
+ if (is_start) {
+ pes->state = MPEGTS_HEADER;
+ pes->data_index = 0;
+ }
+ p = buf;
+ while (buf_size > 0) {
+ switch(pes->state) {
+ case MPEGTS_HEADER:
+ len = PES_START_SIZE - pes->data_index;
+ if (len > buf_size)
+ len = buf_size;
+ memcpy(pes->header + pes->data_index, p, len);
+ pes->data_index += len;
+ p += len;
+ buf_size -= len;
+ if (pes->data_index == PES_START_SIZE) {
+ /* we got all the PES or section header. We can now
+ decide */
+#if 0
+ av_hex_dump(pes->header, pes->data_index);
+#endif
+ if (pes->header[0] == 0x00 && pes->header[1] == 0x00 &&
+ pes->header[2] == 0x01) {
+ /* it must be an mpeg2 PES stream */
+ code = pes->header[3] | 0x100;
+ if (!((code >= 0x1c0 && code <= 0x1df) ||
+ (code >= 0x1e0 && code <= 0x1ef) ||
+ (code == 0x1bd)))
+ goto skip;
+ if (!pes->st) {
+ /* allocate stream */
+ new_pes_av_stream(pes, code);
+ }
+ pes->state = MPEGTS_PESHEADER_FILL;
+ pes->total_size = (pes->header[4] << 8) | pes->header[5];
+ /* NOTE: a zero total size means the PES size is
+ unbounded */
+ if (pes->total_size)
+ pes->total_size += 6;
+ pes->pes_header_size = pes->header[8] + 9;
+ } else {
+ /* otherwise, it should be a table */
+ /* skip packet */
+ skip:
+ pes->state = MPEGTS_SKIP;
+ continue;
+ }
+ }
+ break;
+ /**********************************************/
+ /* PES packing parsing */
+ case MPEGTS_PESHEADER_FILL:
+ len = pes->pes_header_size - pes->data_index;
+ if (len > buf_size)
+ len = buf_size;
+ memcpy(pes->header + pes->data_index, p, len);
+ pes->data_index += len;
+ p += len;
+ buf_size -= len;
+ if (pes->data_index == pes->pes_header_size) {
+ const uint8_t *r;
+ unsigned int flags;
+
+ flags = pes->header[7];
+ r = pes->header + 9;
+ pes->pts = AV_NOPTS_VALUE;
+ pes->dts = AV_NOPTS_VALUE;
+ if ((flags & 0xc0) == 0x80) {
+ pes->pts = get_pts(r);
+ r += 5;
+ } else if ((flags & 0xc0) == 0xc0) {
+ pes->pts = get_pts(r);
+ r += 5;
+ pes->dts = get_pts(r);
+ r += 5;
+ }
+ /* we got the full header. We parse it and get the payload */
+ pes->state = MPEGTS_PAYLOAD;
+ }
+ break;
+ case MPEGTS_PAYLOAD:
+ if (pes->total_size) {
+ len = pes->total_size - pes->data_index;
+ if (len > buf_size)
+ len = buf_size;
+ } else {
+ len = buf_size;
+ }
+ if (len > 0) {
+ AVPacket *pkt = ts->pkt;
+ if (pes->st && av_new_packet(pkt, len) == 0) {
+ memcpy(pkt->data, p, len);
+ pkt->stream_index = pes->st->index;
+ pkt->pts = pes->pts;
+ pkt->dts = pes->dts;
+ /* reset pts values */
+ pes->pts = AV_NOPTS_VALUE;
+ pes->dts = AV_NOPTS_VALUE;
+ ts->stop_parse = 1;
+ return;
+ }
+ }
+ buf_size = 0;
+ break;
+ case MPEGTS_SKIP:
+ buf_size = 0;
+ break;
+ }
+ }
+}
+
+static AVStream* new_pes_av_stream(PESContext *pes, uint32_t code)
+{
+ AVStream *st;
+ int codec_type, codec_id;
+
+ switch(pes->stream_type){
+ case STREAM_TYPE_AUDIO_MPEG1:
+ case STREAM_TYPE_AUDIO_MPEG2:
+ codec_type = CODEC_TYPE_AUDIO;
+ codec_id = CODEC_ID_MP3;
+ break;
+ case STREAM_TYPE_VIDEO_MPEG1:
+ case STREAM_TYPE_VIDEO_MPEG2:
+ codec_type = CODEC_TYPE_VIDEO;
+ codec_id = CODEC_ID_MPEG2VIDEO;
+ break;
+ case STREAM_TYPE_VIDEO_MPEG4:
+ codec_type = CODEC_TYPE_VIDEO;
+ codec_id = CODEC_ID_MPEG4;
+ break;
+ case STREAM_TYPE_VIDEO_H264:
+ codec_type = CODEC_TYPE_VIDEO;
+ codec_id = CODEC_ID_H264;
+ break;
+ case STREAM_TYPE_AUDIO_AAC:
+ codec_type = CODEC_TYPE_AUDIO;
+ codec_id = CODEC_ID_AAC;
+ break;
+ case STREAM_TYPE_AUDIO_AC3:
+ codec_type = CODEC_TYPE_AUDIO;
+ codec_id = CODEC_ID_AC3;
+ break;
+ case STREAM_TYPE_AUDIO_DTS:
+ codec_type = CODEC_TYPE_AUDIO;
+ codec_id = CODEC_ID_DTS;
+ break;
+ case STREAM_TYPE_SUBTITLE_DVB:
+ codec_type = CODEC_TYPE_SUBTITLE;
+ codec_id = CODEC_ID_DVB_SUBTITLE;
+ break;
+ default:
+ if (code >= 0x1c0 && code <= 0x1df) {
+ codec_type = CODEC_TYPE_AUDIO;
+ codec_id = CODEC_ID_MP2;
+ } else if (code == 0x1bd) {
+ codec_type = CODEC_TYPE_AUDIO;
+ codec_id = CODEC_ID_AC3;
+ } else {
+ codec_type = CODEC_TYPE_VIDEO;
+ codec_id = CODEC_ID_MPEG1VIDEO;
+ }
+ break;
+ }
+ st = av_new_stream(pes->stream, pes->pid);
+ if (st) {
+ av_set_pts_info(st, 33, 1, 90000);
+ st->priv_data = pes;
+ st->codec->codec_type = codec_type;
+ st->codec->codec_id = codec_id;
+ st->need_parsing = 1;
+ pes->st = st;
+ }
+ return st;
+}
+
+
+static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int stream_type)
+{
+ MpegTSFilter *tss;
+ PESContext *pes;
+
+ /* if no pid found, then add a pid context */
+ pes = av_mallocz(sizeof(PESContext));
+ if (!pes)
+ return 0;
+ pes->ts = ts;
+ pes->stream = ts->stream;
+ pes->pid = pid;
+ pes->stream_type = stream_type;
+ tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes);
+ if (!tss) {
+ av_free(pes);
+ return 0;
+ }
+ return pes;
+}
+
+/* handle one TS packet */
+static void handle_packet(MpegTSContext *ts, const uint8_t *packet)
+{
+ AVFormatContext *s = ts->stream;
+ MpegTSFilter *tss;
+ int len, pid, cc, cc_ok, afc, is_start;
+ const uint8_t *p, *p_end;
+
+ pid = ((packet[1] & 0x1f) << 8) | packet[2];
+ is_start = packet[1] & 0x40;
+ tss = ts->pids[pid];
+ if (ts->auto_guess && tss == NULL && is_start) {
+ add_pes_stream(ts, pid, 0);
+ tss = ts->pids[pid];
+ }
+ if (!tss)
+ return;
+
+ /* continuity check (currently not used) */
+ cc = (packet[3] & 0xf);
+ cc_ok = (tss->last_cc < 0) || ((((tss->last_cc + 1) & 0x0f) == cc));
+ tss->last_cc = cc;
+
+ /* skip adaptation field */
+ afc = (packet[3] >> 4) & 3;
+ p = packet + 4;
+ if (afc == 0) /* reserved value */
+ return;
+ if (afc == 2) /* adaptation field only */
+ return;
+ if (afc == 3) {
+ /* skip adapation field */
+ p += p[0] + 1;
+ }
+ /* if past the end of packet, ignore */
+ p_end = packet + TS_PACKET_SIZE;
+ if (p >= p_end)
+ return;
+
+ if (tss->type == MPEGTS_SECTION) {
+ if (is_start) {
+ /* pointer field present */
+ len = *p++;
+ if (p + len > p_end)
+ return;
+ if (len && cc_ok) {
+ /* write remaining section bytes */
+ write_section_data(s, tss,
+ p, len, 0);
+ /* check whether filter has been closed */
+ if (!ts->pids[pid])
+ return;
+ }
+ p += len;
+ if (p < p_end) {
+ write_section_data(s, tss,
+ p, p_end - p, 1);
+ }
+ } else {
+ if (cc_ok) {
+ write_section_data(s, tss,
+ p, p_end - p, 0);
+ }
+ }
+ } else {
+ tss->u.pes_filter.pes_cb(tss->u.pes_filter.opaque,
+ p, p_end - p, is_start);
+ }
+}
+
+/* XXX: try to find a better synchro over several packets (use
+ get_packet_size() ?) */
+static int mpegts_resync(ByteIOContext *pb)
+{
+ int c, i;
+
+ for(i = 0;i < MAX_RESYNC_SIZE; i++) {
+ c = url_fgetc(pb);
+ if (c < 0)
+ return -1;
+ if (c == 0x47) {
+ url_fseek(pb, -1, SEEK_CUR);
+ return 0;
+ }
+ }
+ /* no sync found */
+ return -1;
+}
+
+/* return -1 if error or EOF. Return 0 if OK. */
+static int read_packet(ByteIOContext *pb, uint8_t *buf, int raw_packet_size)
+{
+ int skip, len;
+
+ for(;;) {
+ len = get_buffer(pb, buf, TS_PACKET_SIZE);
+ if (len != TS_PACKET_SIZE)
+ return AVERROR_IO;
+ /* check paquet sync byte */
+ if (buf[0] != 0x47) {
+ /* find a new packet start */
+ url_fseek(pb, -TS_PACKET_SIZE, SEEK_CUR);
+ if (mpegts_resync(pb) < 0)
+ return AVERROR_INVALIDDATA;
+ else
+ continue;
+ } else {
+ skip = raw_packet_size - TS_PACKET_SIZE;
+ if (skip > 0)
+ url_fskip(pb, skip);
+ break;
+ }
+ }
+ return 0;
+}
+
+static int handle_packets(MpegTSContext *ts, int nb_packets)
+{
+ AVFormatContext *s = ts->stream;
+ ByteIOContext *pb = &s->pb;
+ uint8_t packet[TS_PACKET_SIZE];
+ int packet_num, ret;
+
+ ts->stop_parse = 0;
+ packet_num = 0;
+ for(;;) {
+ if (ts->stop_parse)
+ break;
+ packet_num++;
+ if (nb_packets != 0 && packet_num >= nb_packets)
+ break;
+ ret = read_packet(pb, packet, ts->raw_packet_size);
+ if (ret != 0)
+ return ret;
+ handle_packet(ts, packet);
+ }
+ return 0;
+}
+
+static int mpegts_probe(AVProbeData *p)
+{
+#if 1
+ const int size= p->buf_size;
+ int score, fec_score, dvhs_score;
+#define CHECK_COUNT 10
+
+ if (size < (TS_FEC_PACKET_SIZE * CHECK_COUNT))
+ return -1;
+
+ score = analyze(p->buf, TS_PACKET_SIZE *CHECK_COUNT, TS_PACKET_SIZE, NULL);
+ dvhs_score = analyze(p->buf, TS_DVHS_PACKET_SIZE *CHECK_COUNT, TS_DVHS_PACKET_SIZE, NULL);
+ fec_score= analyze(p->buf, TS_FEC_PACKET_SIZE*CHECK_COUNT, TS_FEC_PACKET_SIZE, NULL);
+// av_log(NULL, AV_LOG_DEBUG, "score: %d, dvhs_score: %d, fec_score: %d \n", score, dvhs_score, fec_score);
+
+// we need a clear definition for the returned score otherwise things will become messy sooner or later
+ if (score > fec_score && score > dvhs_score && score > 6) return AVPROBE_SCORE_MAX + score - CHECK_COUNT;
+ else if(dvhs_score > score && dvhs_score > fec_score && dvhs_score > 6) return AVPROBE_SCORE_MAX + dvhs_score - CHECK_COUNT;
+ else if( fec_score > 6) return AVPROBE_SCORE_MAX + fec_score - CHECK_COUNT;
+ else return -1;
+#else
+ /* only use the extension for safer guess */
+ if (match_ext(p->filename, "ts"))
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+#endif
+}
+
+static void set_service_cb(void *opaque, int ret)
+{
+ MpegTSContext *ts = opaque;
+ ts->set_service_ret = ret;
+ ts->stop_parse = 1;
+}
+
+/* return the 90 kHz PCR and the extension for the 27 MHz PCR. return
+ (-1) if not available */
+static int parse_pcr(int64_t *ppcr_high, int *ppcr_low,
+ const uint8_t *packet)
+{
+ int afc, len, flags;
+ const uint8_t *p;
+ unsigned int v;
+
+ afc = (packet[3] >> 4) & 3;
+ if (afc <= 1)
+ return -1;
+ p = packet + 4;
+ len = p[0];
+ p++;
+ if (len == 0)
+ return -1;
+ flags = *p++;
+ len--;
+ if (!(flags & 0x10))
+ return -1;
+ if (len < 6)
+ return -1;
+ v = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ *ppcr_high = ((int64_t)v << 1) | (p[4] >> 7);
+ *ppcr_low = ((p[4] & 1) << 8) | p[5];
+ return 0;
+}
+
+static int mpegts_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ MpegTSContext *ts = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ uint8_t buf[1024];
+ int len, sid, i;
+ int64_t pos;
+ MpegTSService *service;
+
+ if (ap) {
+ ts->mpeg2ts_raw = ap->mpeg2ts_raw;
+ ts->mpeg2ts_compute_pcr = ap->mpeg2ts_compute_pcr;
+ }
+
+ /* read the first 1024 bytes to get packet size */
+ pos = url_ftell(pb);
+ len = get_buffer(pb, buf, sizeof(buf));
+ if (len != sizeof(buf))
+ goto fail;
+ ts->raw_packet_size = get_packet_size(buf, sizeof(buf));
+ if (ts->raw_packet_size <= 0)
+ goto fail;
+ ts->stream = s;
+ ts->auto_guess = 0;
+
+goto_auto_guess:
+ if (!ts->mpeg2ts_raw) {
+ /* normal demux */
+
+ if (!ts->auto_guess) {
+ ts->set_service_ret = -1;
+
+ /* first do a scaning to get all the services */
+ url_fseek(pb, pos, SEEK_SET);
+ mpegts_scan_sdt(ts);
+
+ handle_packets(ts, s->probesize);
+
+ if (ts->nb_services <= 0) {
+ /* no SDT found, we try to look at the PAT */
+
+ /* First remove the SDT filters from each PID */
+ int i;
+ for (i=0; i < NB_PID_MAX; i++) {
+ if (ts->pids[i])
+ mpegts_close_filter(ts, ts->pids[i]);
+ }
+ url_fseek(pb, pos, SEEK_SET);
+ mpegts_scan_pat(ts);
+
+ handle_packets(ts, s->probesize);
+ }
+
+ if (ts->nb_services <= 0) {
+ /* raw transport stream */
+ ts->auto_guess = 1;
+ s->ctx_flags |= AVFMTCTX_NOHEADER;
+ goto do_pcr;
+ }
+
+ /* tune to first service found */
+ for(i=0; i<ts->nb_services && ts->set_service_ret; i++){
+ service = ts->services[i];
+ sid = service->sid;
+#ifdef DEBUG_SI
+ printf("tuning to '%s'\n", service->name);
+#endif
+
+ /* now find the info for the first service if we found any,
+ otherwise try to filter all PATs */
+
+ url_fseek(pb, pos, SEEK_SET);
+ mpegts_set_service(ts, sid, set_service_cb, ts);
+
+ handle_packets(ts, s->probesize);
+ }
+ /* if could not find service, exit */
+
+ if (ts->set_service_ret != 0) {
+ if(ts->auto_guess)
+ return -1;
+ else {
+ //let's retry with auto_guess set
+ ts->auto_guess = 1;
+ goto goto_auto_guess;
+ }
+ }
+
+#ifdef DEBUG_SI
+ printf("tuning done\n");
+#endif
+ }
+ s->ctx_flags |= AVFMTCTX_NOHEADER;
+ } else {
+ AVStream *st;
+ int pcr_pid, pid, nb_packets, nb_pcrs, ret, pcr_l;
+ int64_t pcrs[2], pcr_h;
+ int packet_count[2];
+ uint8_t packet[TS_PACKET_SIZE];
+
+ /* only read packets */
+
+ do_pcr:
+ st = av_new_stream(s, 0);
+ if (!st)
+ goto fail;
+ av_set_pts_info(st, 60, 1, 27000000);
+ st->codec->codec_type = CODEC_TYPE_DATA;
+ st->codec->codec_id = CODEC_ID_MPEG2TS;
+
+ /* we iterate until we find two PCRs to estimate the bitrate */
+ pcr_pid = -1;
+ nb_pcrs = 0;
+ nb_packets = 0;
+ for(;;) {
+ ret = read_packet(&s->pb, packet, ts->raw_packet_size);
+ if (ret < 0)
+ return -1;
+ pid = ((packet[1] & 0x1f) << 8) | packet[2];
+ if ((pcr_pid == -1 || pcr_pid == pid) &&
+ parse_pcr(&pcr_h, &pcr_l, packet) == 0) {
+ pcr_pid = pid;
+ packet_count[nb_pcrs] = nb_packets;
+ pcrs[nb_pcrs] = pcr_h * 300 + pcr_l;
+ nb_pcrs++;
+ if (nb_pcrs >= 2)
+ break;
+ }
+ nb_packets++;
+ }
+ ts->pcr_pid = pcr_pid;
+
+ /* NOTE1: the bitrate is computed without the FEC */
+ /* NOTE2: it is only the bitrate of the start of the stream */
+ ts->pcr_incr = (pcrs[1] - pcrs[0]) / (packet_count[1] - packet_count[0]);
+ ts->cur_pcr = pcrs[0] - ts->pcr_incr * packet_count[0];
+ s->bit_rate = (TS_PACKET_SIZE * 8) * 27e6 / ts->pcr_incr;
+ st->codec->bit_rate = s->bit_rate;
+ st->start_time = ts->cur_pcr;
+#if 0
+ printf("start=%0.3f pcr=%0.3f incr=%d\n",
+ st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr);
+#endif
+ }
+
+ url_fseek(pb, pos, SEEK_SET);
+ return 0;
+ fail:
+ return -1;
+}
+
+#define MAX_PACKET_READAHEAD ((128 * 1024) / 188)
+
+static int mpegts_raw_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ MpegTSContext *ts = s->priv_data;
+ int ret, i;
+ int64_t pcr_h, next_pcr_h, pos;
+ int pcr_l, next_pcr_l;
+ uint8_t pcr_buf[12];
+
+ if (av_new_packet(pkt, TS_PACKET_SIZE) < 0)
+ return -ENOMEM;
+ pkt->pos= url_ftell(&s->pb);
+ ret = read_packet(&s->pb, pkt->data, ts->raw_packet_size);
+ if (ret < 0) {
+ av_free_packet(pkt);
+ return ret;
+ }
+ if (ts->mpeg2ts_compute_pcr) {
+ /* compute exact PCR for each packet */
+ if (parse_pcr(&pcr_h, &pcr_l, pkt->data) == 0) {
+ /* we read the next PCR (XXX: optimize it by using a bigger buffer */
+ pos = url_ftell(&s->pb);
+ for(i = 0; i < MAX_PACKET_READAHEAD; i++) {
+ url_fseek(&s->pb, pos + i * ts->raw_packet_size, SEEK_SET);
+ get_buffer(&s->pb, pcr_buf, 12);
+ if (parse_pcr(&next_pcr_h, &next_pcr_l, pcr_buf) == 0) {
+ /* XXX: not precise enough */
+ ts->pcr_incr = ((next_pcr_h - pcr_h) * 300 + (next_pcr_l - pcr_l)) /
+ (i + 1);
+ break;
+ }
+ }
+ url_fseek(&s->pb, pos, SEEK_SET);
+ /* no next PCR found: we use previous increment */
+ ts->cur_pcr = pcr_h * 300 + pcr_l;
+ }
+ pkt->pts = ts->cur_pcr;
+ pkt->duration = ts->pcr_incr;
+ ts->cur_pcr += ts->pcr_incr;
+ }
+ pkt->stream_index = 0;
+ return 0;
+}
+
+static int mpegts_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ MpegTSContext *ts = s->priv_data;
+
+ if (!ts->mpeg2ts_raw) {
+ ts->pkt = pkt;
+ return handle_packets(ts, 0);
+ } else {
+ return mpegts_raw_read_packet(s, pkt);
+ }
+}
+
+static int mpegts_read_close(AVFormatContext *s)
+{
+ MpegTSContext *ts = s->priv_data;
+ int i;
+ for(i=0;i<NB_PID_MAX;i++)
+ if (ts->pids[i]) mpegts_close_filter(ts, ts->pids[i]);
+
+ for(i = 0; i < ts->nb_services; i++){
+ av_free(ts->services[i]->provider_name);
+ av_free(ts->services[i]->name);
+ av_free(ts->services[i]);
+ }
+ av_freep(&ts->services);
+
+ return 0;
+}
+
+static int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index,
+ int64_t *ppos, int64_t pos_limit)
+{
+ MpegTSContext *ts = s->priv_data;
+ int64_t pos, timestamp;
+ uint8_t buf[TS_PACKET_SIZE];
+ int pcr_l, pid;
+ const int find_next= 1;
+ pos = ((*ppos + ts->raw_packet_size - 1) / ts->raw_packet_size) * ts->raw_packet_size;
+ if (find_next) {
+ for(;;) {
+ url_fseek(&s->pb, pos, SEEK_SET);
+ if (get_buffer(&s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
+ return AV_NOPTS_VALUE;
+ pid = ((buf[1] & 0x1f) << 8) | buf[2];
+ if (pid == ts->pcr_pid &&
+ parse_pcr(&timestamp, &pcr_l, buf) == 0) {
+ break;
+ }
+ pos += ts->raw_packet_size;
+ }
+ } else {
+ for(;;) {
+ pos -= ts->raw_packet_size;
+ if (pos < 0)
+ return AV_NOPTS_VALUE;
+ url_fseek(&s->pb, pos, SEEK_SET);
+ if (get_buffer(&s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
+ return AV_NOPTS_VALUE;
+ pid = ((buf[1] & 0x1f) << 8) | buf[2];
+ if (pid == ts->pcr_pid &&
+ parse_pcr(&timestamp, &pcr_l, buf) == 0) {
+ break;
+ }
+ }
+ }
+ *ppos = pos;
+
+ return timestamp;
+}
+
+static int read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, int flags){
+ MpegTSContext *ts = s->priv_data;
+ uint8_t buf[TS_PACKET_SIZE];
+ int64_t pos;
+
+ if(av_seek_frame_binary(s, stream_index, target_ts, flags) < 0)
+ return -1;
+
+ pos= url_ftell(&s->pb);
+
+ for(;;) {
+ url_fseek(&s->pb, pos, SEEK_SET);
+ if (get_buffer(&s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
+ return -1;
+// pid = ((buf[1] & 0x1f) << 8) | buf[2];
+ if(buf[1] & 0x40) break;
+ pos += ts->raw_packet_size;
+ }
+ url_fseek(&s->pb, pos, SEEK_SET);
+
+ return 0;
+}
+
+/**************************************************************/
+/* parsing functions - called from other demuxers such as RTP */
+
+MpegTSContext *mpegts_parse_open(AVFormatContext *s)
+{
+ MpegTSContext *ts;
+
+ ts = av_mallocz(sizeof(MpegTSContext));
+ if (!ts)
+ return NULL;
+ /* no stream case, currently used by RTP */
+ ts->raw_packet_size = TS_PACKET_SIZE;
+ ts->stream = s;
+ ts->auto_guess = 1;
+ return ts;
+}
+
+/* return the consumed length if a packet was output, or -1 if no
+ packet is output */
+int mpegts_parse_packet(MpegTSContext *ts, AVPacket *pkt,
+ const uint8_t *buf, int len)
+{
+ int len1;
+
+ len1 = len;
+ ts->pkt = pkt;
+ ts->stop_parse = 0;
+ for(;;) {
+ if (ts->stop_parse)
+ break;
+ if (len < TS_PACKET_SIZE)
+ return -1;
+ if (buf[0] != 0x47) {
+ buf++;
+ len--;
+ } else {
+ handle_packet(ts, buf);
+ buf += TS_PACKET_SIZE;
+ len -= TS_PACKET_SIZE;
+ }
+ }
+ return len1 - len;
+}
+
+void mpegts_parse_close(MpegTSContext *ts)
+{
+ int i;
+
+ for(i=0;i<NB_PID_MAX;i++)
+ av_free(ts->pids[i]);
+ av_free(ts);
+}
+
+AVInputFormat mpegts_demuxer = {
+ "mpegts",
+ "MPEG2 transport stream format",
+ sizeof(MpegTSContext),
+ mpegts_probe,
+ mpegts_read_header,
+ mpegts_read_packet,
+ mpegts_read_close,
+ read_seek,
+ mpegts_get_pcr,
+ .flags = AVFMT_SHOW_IDS,
+};
diff --git a/contrib/ffmpeg/libavformat/mpegts.h b/contrib/ffmpeg/libavformat/mpegts.h
new file mode 100644
index 000000000..b3eb3cda7
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/mpegts.h
@@ -0,0 +1,63 @@
+/*
+ * MPEG2 transport stream defines
+ * 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 TS_FEC_PACKET_SIZE 204
+#define TS_DVHS_PACKET_SIZE 192
+#define TS_PACKET_SIZE 188
+#define NB_PID_MAX 8192
+#define MAX_SECTION_SIZE 4096
+
+/* pids */
+#define PAT_PID 0x0000
+#define SDT_PID 0x0011
+
+/* table ids */
+#define PAT_TID 0x00
+#define PMT_TID 0x02
+#define SDT_TID 0x42
+
+/* descriptor ids */
+#define DVB_SUBT_DESCID 0x59
+
+#define STREAM_TYPE_VIDEO_MPEG1 0x01
+#define STREAM_TYPE_VIDEO_MPEG2 0x02
+#define STREAM_TYPE_AUDIO_MPEG1 0x03
+#define STREAM_TYPE_AUDIO_MPEG2 0x04
+#define STREAM_TYPE_PRIVATE_SECTION 0x05
+#define STREAM_TYPE_PRIVATE_DATA 0x06
+#define STREAM_TYPE_AUDIO_AAC 0x0f
+#define STREAM_TYPE_VIDEO_MPEG4 0x10
+#define STREAM_TYPE_VIDEO_H264 0x1b
+
+#define STREAM_TYPE_AUDIO_AC3 0x81
+#define STREAM_TYPE_AUDIO_DTS 0x8a
+
+#define STREAM_TYPE_SUBTITLE_DVB 0x100
+
+unsigned int mpegts_crc32(const uint8_t *data, int len);
+extern AVOutputFormat mpegts_muxer;
+
+typedef struct MpegTSContext MpegTSContext;
+
+MpegTSContext *mpegts_parse_open(AVFormatContext *s);
+int mpegts_parse_packet(MpegTSContext *ts, AVPacket *pkt,
+ const uint8_t *buf, int len);
+void mpegts_parse_close(MpegTSContext *ts);
diff --git a/contrib/ffmpeg/libavformat/mpegtsenc.c b/contrib/ffmpeg/libavformat/mpegtsenc.c
new file mode 100644
index 000000000..39868bea4
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/mpegtsenc.c
@@ -0,0 +1,676 @@
+/*
+ * MPEG2 transport stream (aka DVB) muxer
+ * 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 "avformat.h"
+#include "crc.h"
+#include "mpegts.h"
+
+/* write DVB SI sections */
+
+/*********************************************/
+/* mpegts section writer */
+
+typedef struct MpegTSSection {
+ int pid;
+ int cc;
+ void (*write_packet)(struct MpegTSSection *s, const uint8_t *packet);
+ void *opaque;
+} MpegTSSection;
+
+/* NOTE: 4 bytes must be left at the end for the crc32 */
+static void mpegts_write_section(MpegTSSection *s, uint8_t *buf, int len)
+{
+ unsigned int crc;
+ unsigned char packet[TS_PACKET_SIZE];
+ const unsigned char *buf_ptr;
+ unsigned char *q;
+ int first, b, len1, left;
+
+ crc = bswap_32(av_crc(av_crc04C11DB7, -1, buf, len - 4));
+ buf[len - 4] = (crc >> 24) & 0xff;
+ buf[len - 3] = (crc >> 16) & 0xff;
+ buf[len - 2] = (crc >> 8) & 0xff;
+ buf[len - 1] = (crc) & 0xff;
+
+ /* send each packet */
+ buf_ptr = buf;
+ while (len > 0) {
+ first = (buf == buf_ptr);
+ q = packet;
+ *q++ = 0x47;
+ b = (s->pid >> 8);
+ if (first)
+ b |= 0x40;
+ *q++ = b;
+ *q++ = s->pid;
+ s->cc = (s->cc + 1) & 0xf;
+ *q++ = 0x10 | s->cc;
+ if (first)
+ *q++ = 0; /* 0 offset */
+ len1 = TS_PACKET_SIZE - (q - packet);
+ if (len1 > len)
+ len1 = len;
+ memcpy(q, buf_ptr, len1);
+ q += len1;
+ /* add known padding data */
+ left = TS_PACKET_SIZE - (q - packet);
+ if (left > 0)
+ memset(q, 0xff, left);
+
+ s->write_packet(s, packet);
+
+ buf_ptr += len1;
+ len -= len1;
+ }
+}
+
+static inline void put16(uint8_t **q_ptr, int val)
+{
+ uint8_t *q;
+ q = *q_ptr;
+ *q++ = val >> 8;
+ *q++ = val;
+ *q_ptr = q;
+}
+
+static int mpegts_write_section1(MpegTSSection *s, int tid, int id,
+ int version, int sec_num, int last_sec_num,
+ uint8_t *buf, int len)
+{
+ uint8_t section[1024], *q;
+ unsigned int tot_len;
+
+ tot_len = 3 + 5 + len + 4;
+ /* check if not too big */
+ if (tot_len > 1024)
+ return -1;
+
+ q = section;
+ *q++ = tid;
+ put16(&q, 0xb000 | (len + 5 + 4)); /* 5 byte header + 4 byte CRC */
+ put16(&q, id);
+ *q++ = 0xc1 | (version << 1); /* current_next_indicator = 1 */
+ *q++ = sec_num;
+ *q++ = last_sec_num;
+ memcpy(q, buf, len);
+
+ mpegts_write_section(s, section, tot_len);
+ return 0;
+}
+
+/*********************************************/
+/* mpegts writer */
+
+#define DEFAULT_PMT_START_PID 0x1000
+#define DEFAULT_START_PID 0x0100
+#define DEFAULT_PROVIDER_NAME "FFmpeg"
+#define DEFAULT_SERVICE_NAME "Service01"
+
+/* default network id, transport stream and service identifiers */
+#define DEFAULT_ONID 0x0001
+#define DEFAULT_TSID 0x0001
+#define DEFAULT_SID 0x0001
+
+/* a PES packet header is generated every DEFAULT_PES_HEADER_FREQ packets */
+#define DEFAULT_PES_HEADER_FREQ 16
+#define DEFAULT_PES_PAYLOAD_SIZE ((DEFAULT_PES_HEADER_FREQ - 1) * 184 + 170)
+
+/* we retransmit the SI info at this rate */
+#define SDT_RETRANS_TIME 500
+#define PAT_RETRANS_TIME 100
+#define PCR_RETRANS_TIME 20
+
+typedef struct MpegTSWriteStream {
+ struct MpegTSService *service;
+ int pid; /* stream associated pid */
+ int cc;
+ int payload_index;
+ int64_t payload_pts;
+ uint8_t payload[DEFAULT_PES_PAYLOAD_SIZE];
+} MpegTSWriteStream;
+
+typedef struct MpegTSService {
+ MpegTSSection pmt; /* MPEG2 pmt table context */
+ int sid; /* service ID */
+ char *name;
+ char *provider_name;
+ int pcr_pid;
+ int pcr_packet_count;
+ int pcr_packet_freq;
+} MpegTSService;
+
+typedef struct MpegTSWrite {
+ MpegTSSection pat; /* MPEG2 pat table */
+ MpegTSSection sdt; /* MPEG2 sdt table context */
+ MpegTSService **services;
+ int sdt_packet_count;
+ int sdt_packet_freq;
+ int pat_packet_count;
+ int pat_packet_freq;
+ int nb_services;
+ int onid;
+ int tsid;
+} MpegTSWrite;
+
+static void mpegts_write_pat(AVFormatContext *s)
+{
+ MpegTSWrite *ts = s->priv_data;
+ MpegTSService *service;
+ uint8_t data[1012], *q;
+ int i;
+
+ q = data;
+ for(i = 0; i < ts->nb_services; i++) {
+ service = ts->services[i];
+ put16(&q, service->sid);
+ put16(&q, 0xe000 | service->pmt.pid);
+ }
+ mpegts_write_section1(&ts->pat, PAT_TID, ts->tsid, 0, 0, 0,
+ data, q - data);
+}
+
+static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
+{
+ // MpegTSWrite *ts = s->priv_data;
+ uint8_t data[1012], *q, *desc_length_ptr, *program_info_length_ptr;
+ int val, stream_type, i;
+
+ q = data;
+ put16(&q, 0xe000 | service->pcr_pid);
+
+ program_info_length_ptr = q;
+ q += 2; /* patched after */
+
+ /* put program info here */
+
+ val = 0xf000 | (q - program_info_length_ptr - 2);
+ program_info_length_ptr[0] = val >> 8;
+ program_info_length_ptr[1] = val;
+
+ for(i = 0; i < s->nb_streams; i++) {
+ AVStream *st = s->streams[i];
+ MpegTSWriteStream *ts_st = st->priv_data;
+ switch(st->codec->codec_id) {
+ case CODEC_ID_MPEG1VIDEO:
+ case CODEC_ID_MPEG2VIDEO:
+ stream_type = STREAM_TYPE_VIDEO_MPEG2;
+ break;
+ case CODEC_ID_MPEG4:
+ stream_type = STREAM_TYPE_VIDEO_MPEG4;
+ break;
+ case CODEC_ID_H264:
+ stream_type = STREAM_TYPE_VIDEO_H264;
+ break;
+ case CODEC_ID_MP2:
+ case CODEC_ID_MP3:
+ stream_type = STREAM_TYPE_AUDIO_MPEG1;
+ break;
+ case CODEC_ID_AAC:
+ stream_type = STREAM_TYPE_AUDIO_AAC;
+ break;
+ case CODEC_ID_AC3:
+ stream_type = STREAM_TYPE_AUDIO_AC3;
+ break;
+ default:
+ stream_type = STREAM_TYPE_PRIVATE_DATA;
+ break;
+ }
+ *q++ = stream_type;
+ put16(&q, 0xe000 | ts_st->pid);
+ desc_length_ptr = q;
+ q += 2; /* patched after */
+
+ /* write optional descriptors here */
+ switch(st->codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ if (strlen(st->language) == 3) {
+ *q++ = 0x0a; /* ISO 639 language descriptor */
+ *q++ = 4;
+ *q++ = st->language[0];
+ *q++ = st->language[1];
+ *q++ = st->language[2];
+ *q++ = 0; /* undefined type */
+ }
+ break;
+ case CODEC_TYPE_SUBTITLE:
+ {
+ const char *language;
+ language = st->language;
+ if (strlen(language) != 3)
+ language = "eng";
+ *q++ = 0x59;
+ *q++ = 8;
+ *q++ = language[0];
+ *q++ = language[1];
+ *q++ = language[2];
+ *q++ = 0x10; /* normal subtitles (0x20 = if hearing pb) */
+ put16(&q, 1); /* page id */
+ put16(&q, 1); /* ancillary page id */
+ }
+ break;
+ }
+
+ val = 0xf000 | (q - desc_length_ptr - 2);
+ desc_length_ptr[0] = val >> 8;
+ desc_length_ptr[1] = val;
+ }
+ mpegts_write_section1(&service->pmt, PMT_TID, service->sid, 0, 0, 0,
+ data, q - data);
+}
+
+/* NOTE: str == NULL is accepted for an empty string */
+static void putstr8(uint8_t **q_ptr, const char *str)
+{
+ uint8_t *q;
+ int len;
+
+ q = *q_ptr;
+ if (!str)
+ len = 0;
+ else
+ len = strlen(str);
+ *q++ = len;
+ memcpy(q, str, len);
+ q += len;
+ *q_ptr = q;
+}
+
+static void mpegts_write_sdt(AVFormatContext *s)
+{
+ MpegTSWrite *ts = s->priv_data;
+ MpegTSService *service;
+ uint8_t data[1012], *q, *desc_list_len_ptr, *desc_len_ptr;
+ int i, running_status, free_ca_mode, val;
+
+ q = data;
+ put16(&q, ts->onid);
+ *q++ = 0xff;
+ for(i = 0; i < ts->nb_services; i++) {
+ service = ts->services[i];
+ put16(&q, service->sid);
+ *q++ = 0xfc | 0x00; /* currently no EIT info */
+ desc_list_len_ptr = q;
+ q += 2;
+ running_status = 4; /* running */
+ free_ca_mode = 0;
+
+ /* write only one descriptor for the service name and provider */
+ *q++ = 0x48;
+ desc_len_ptr = q;
+ q++;
+ *q++ = 0x01; /* digital television service */
+ putstr8(&q, service->provider_name);
+ putstr8(&q, service->name);
+ desc_len_ptr[0] = q - desc_len_ptr - 1;
+
+ /* fill descriptor length */
+ val = (running_status << 13) | (free_ca_mode << 12) |
+ (q - desc_list_len_ptr - 2);
+ desc_list_len_ptr[0] = val >> 8;
+ desc_list_len_ptr[1] = val;
+ }
+ mpegts_write_section1(&ts->sdt, SDT_TID, ts->tsid, 0, 0, 0,
+ data, q - data);
+}
+
+static MpegTSService *mpegts_add_service(MpegTSWrite *ts,
+ int sid,
+ const char *provider_name,
+ const char *name)
+{
+ MpegTSService *service;
+
+ service = av_mallocz(sizeof(MpegTSService));
+ if (!service)
+ return NULL;
+ service->pmt.pid = DEFAULT_PMT_START_PID + ts->nb_services - 1;
+ service->sid = sid;
+ service->provider_name = av_strdup(provider_name);
+ service->name = av_strdup(name);
+ service->pcr_pid = 0x1fff;
+ dynarray_add(&ts->services, &ts->nb_services, service);
+ return service;
+}
+
+static void section_write_packet(MpegTSSection *s, const uint8_t *packet)
+{
+ AVFormatContext *ctx = s->opaque;
+ put_buffer(&ctx->pb, packet, TS_PACKET_SIZE);
+}
+
+static int mpegts_write_header(AVFormatContext *s)
+{
+ MpegTSWrite *ts = s->priv_data;
+ MpegTSWriteStream *ts_st;
+ MpegTSService *service;
+ AVStream *st;
+ int i, total_bit_rate;
+ const char *service_name;
+
+ ts->tsid = DEFAULT_TSID;
+ ts->onid = DEFAULT_ONID;
+ /* allocate a single DVB service */
+ service_name = s->title;
+ if (service_name[0] == '\0')
+ service_name = DEFAULT_SERVICE_NAME;
+ service = mpegts_add_service(ts, DEFAULT_SID,
+ DEFAULT_PROVIDER_NAME, service_name);
+ service->pmt.write_packet = section_write_packet;
+ service->pmt.opaque = s;
+
+ ts->pat.pid = PAT_PID;
+ ts->pat.cc = 0;
+ ts->pat.write_packet = section_write_packet;
+ ts->pat.opaque = s;
+
+ ts->sdt.pid = SDT_PID;
+ ts->sdt.cc = 0;
+ ts->sdt.write_packet = section_write_packet;
+ ts->sdt.opaque = s;
+
+ /* assign pids to each stream */
+ total_bit_rate = 0;
+ for(i = 0;i < s->nb_streams; i++) {
+ st = s->streams[i];
+ ts_st = av_mallocz(sizeof(MpegTSWriteStream));
+ if (!ts_st)
+ goto fail;
+ st->priv_data = ts_st;
+ ts_st->service = service;
+ ts_st->pid = DEFAULT_START_PID + i;
+ ts_st->payload_pts = AV_NOPTS_VALUE;
+ /* update PCR pid by using the first video stream */
+ if (st->codec->codec_type == CODEC_TYPE_VIDEO &&
+ service->pcr_pid == 0x1fff)
+ service->pcr_pid = ts_st->pid;
+ total_bit_rate += st->codec->bit_rate;
+ }
+
+ /* if no video stream, use the first stream as PCR */
+ if (service->pcr_pid == 0x1fff && s->nb_streams > 0) {
+ ts_st = s->streams[0]->priv_data;
+ service->pcr_pid = ts_st->pid;
+ }
+
+ if (total_bit_rate <= 8 * 1024)
+ total_bit_rate = 8 * 1024;
+ service->pcr_packet_freq = (total_bit_rate * PCR_RETRANS_TIME) /
+ (TS_PACKET_SIZE * 8 * 1000);
+ ts->sdt_packet_freq = (total_bit_rate * SDT_RETRANS_TIME) /
+ (TS_PACKET_SIZE * 8 * 1000);
+ ts->pat_packet_freq = (total_bit_rate * PAT_RETRANS_TIME) /
+ (TS_PACKET_SIZE * 8 * 1000);
+#if 0
+ printf("%d %d %d\n",
+ total_bit_rate, ts->sdt_packet_freq, ts->pat_packet_freq);
+#endif
+
+ /* write info at the start of the file, so that it will be fast to
+ find them */
+ mpegts_write_sdt(s);
+ mpegts_write_pat(s);
+ for(i = 0; i < ts->nb_services; i++) {
+ mpegts_write_pmt(s, ts->services[i]);
+ }
+ put_flush_packet(&s->pb);
+
+ return 0;
+
+ fail:
+ for(i = 0;i < s->nb_streams; i++) {
+ st = s->streams[i];
+ av_free(st->priv_data);
+ }
+ return -1;
+}
+
+/* send SDT, PAT and PMT tables regulary */
+static void retransmit_si_info(AVFormatContext *s)
+{
+ MpegTSWrite *ts = s->priv_data;
+ int i;
+
+ if (++ts->sdt_packet_count == ts->sdt_packet_freq) {
+ ts->sdt_packet_count = 0;
+ mpegts_write_sdt(s);
+ }
+ if (++ts->pat_packet_count == ts->pat_packet_freq) {
+ ts->pat_packet_count = 0;
+ mpegts_write_pat(s);
+ for(i = 0; i < ts->nb_services; i++) {
+ mpegts_write_pmt(s, ts->services[i]);
+ }
+ }
+}
+
+/* NOTE: pes_data contains all the PES packet */
+static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
+ const uint8_t *payload, int payload_size,
+ int64_t pts)
+{
+ MpegTSWriteStream *ts_st = st->priv_data;
+ uint8_t buf[TS_PACKET_SIZE];
+ uint8_t *q;
+ int val, is_start, len, header_len, write_pcr, private_code;
+ int afc_len, stuffing_len;
+ int64_t pcr = -1; /* avoid warning */
+
+ is_start = 1;
+ while (payload_size > 0) {
+ retransmit_si_info(s);
+
+ write_pcr = 0;
+ if (ts_st->pid == ts_st->service->pcr_pid) {
+ ts_st->service->pcr_packet_count++;
+ if (ts_st->service->pcr_packet_count >=
+ ts_st->service->pcr_packet_freq) {
+ ts_st->service->pcr_packet_count = 0;
+ write_pcr = 1;
+ /* XXX: this is incorrect, but at least we have a PCR
+ value */
+ pcr = pts;
+ }
+ }
+
+ /* prepare packet header */
+ q = buf;
+ *q++ = 0x47;
+ val = (ts_st->pid >> 8);
+ if (is_start)
+ val |= 0x40;
+ *q++ = val;
+ *q++ = ts_st->pid;
+ *q++ = 0x10 | ts_st->cc | (write_pcr ? 0x20 : 0);
+ ts_st->cc = (ts_st->cc + 1) & 0xf;
+ if (write_pcr) {
+ *q++ = 7; /* AFC length */
+ *q++ = 0x10; /* flags: PCR present */
+ *q++ = pcr >> 25;
+ *q++ = pcr >> 17;
+ *q++ = pcr >> 9;
+ *q++ = pcr >> 1;
+ *q++ = (pcr & 1) << 7;
+ *q++ = 0;
+ }
+ if (is_start) {
+ /* write PES header */
+ *q++ = 0x00;
+ *q++ = 0x00;
+ *q++ = 0x01;
+ private_code = 0;
+ if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ *q++ = 0xe0;
+ } else if (st->codec->codec_type == CODEC_TYPE_AUDIO &&
+ (st->codec->codec_id == CODEC_ID_MP2 ||
+ st->codec->codec_id == CODEC_ID_MP3)) {
+ *q++ = 0xc0;
+ } else {
+ *q++ = 0xbd;
+ if (st->codec->codec_type == CODEC_TYPE_SUBTITLE) {
+ private_code = 0x20;
+ }
+ }
+ if (pts != AV_NOPTS_VALUE)
+ header_len = 8;
+ else
+ header_len = 3;
+ if (private_code != 0)
+ header_len++;
+ len = payload_size + header_len;
+ *q++ = len >> 8;
+ *q++ = len;
+ val = 0x80;
+ /* data alignment indicator is required for subtitle data */
+ if (st->codec->codec_type == CODEC_TYPE_SUBTITLE)
+ val |= 0x04;
+ *q++ = val;
+ if (pts != AV_NOPTS_VALUE) {
+ *q++ = 0x80; /* PTS only */
+ *q++ = 0x05; /* header len */
+ val = (0x02 << 4) |
+ (((pts >> 30) & 0x07) << 1) | 1;
+ *q++ = val;
+ val = (((pts >> 15) & 0x7fff) << 1) | 1;
+ *q++ = val >> 8;
+ *q++ = val;
+ val = (((pts) & 0x7fff) << 1) | 1;
+ *q++ = val >> 8;
+ *q++ = val;
+ } else {
+ *q++ = 0x00;
+ *q++ = 0x00;
+ }
+ if (private_code != 0)
+ *q++ = private_code;
+ is_start = 0;
+ }
+ /* header size */
+ header_len = q - buf;
+ /* data len */
+ len = TS_PACKET_SIZE - header_len;
+ if (len > payload_size)
+ len = payload_size;
+ stuffing_len = TS_PACKET_SIZE - header_len - len;
+ if (stuffing_len > 0) {
+ /* add stuffing with AFC */
+ if (buf[3] & 0x20) {
+ /* stuffing already present: increase its size */
+ afc_len = buf[4] + 1;
+ memmove(buf + 4 + afc_len + stuffing_len,
+ buf + 4 + afc_len,
+ header_len - (4 + afc_len));
+ buf[4] += stuffing_len;
+ memset(buf + 4 + afc_len, 0xff, stuffing_len);
+ } else {
+ /* add stuffing */
+ memmove(buf + 4 + stuffing_len, buf + 4, header_len - 4);
+ buf[3] |= 0x20;
+ buf[4] = stuffing_len - 1;
+ if (stuffing_len >= 2) {
+ buf[5] = 0x00;
+ memset(buf + 6, 0xff, stuffing_len - 2);
+ }
+ }
+ }
+ memcpy(buf + TS_PACKET_SIZE - len, payload, len);
+ payload += len;
+ payload_size -= len;
+ put_buffer(&s->pb, buf, TS_PACKET_SIZE);
+ }
+ put_flush_packet(&s->pb);
+}
+
+static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ AVStream *st = s->streams[pkt->stream_index];
+ int size= pkt->size;
+ uint8_t *buf= pkt->data;
+ MpegTSWriteStream *ts_st = st->priv_data;
+ int len, max_payload_size;
+
+ if (st->codec->codec_type == CODEC_TYPE_SUBTITLE) {
+ /* for subtitle, a single PES packet must be generated */
+ mpegts_write_pes(s, st, buf, size, pkt->pts);
+ return 0;
+ }
+
+ max_payload_size = DEFAULT_PES_PAYLOAD_SIZE;
+ while (size > 0) {
+ len = max_payload_size - ts_st->payload_index;
+ if (len > size)
+ len = size;
+ memcpy(ts_st->payload + ts_st->payload_index, buf, len);
+ buf += len;
+ size -= len;
+ ts_st->payload_index += len;
+ if (ts_st->payload_pts == AV_NOPTS_VALUE)
+ ts_st->payload_pts = pkt->pts;
+ if (ts_st->payload_index >= max_payload_size) {
+ mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index,
+ ts_st->payload_pts);
+ ts_st->payload_pts = AV_NOPTS_VALUE;
+ ts_st->payload_index = 0;
+ }
+ }
+ return 0;
+}
+
+static int mpegts_write_end(AVFormatContext *s)
+{
+ MpegTSWrite *ts = s->priv_data;
+ MpegTSWriteStream *ts_st;
+ MpegTSService *service;
+ AVStream *st;
+ int i;
+
+ /* flush current packets */
+ for(i = 0; i < s->nb_streams; i++) {
+ st = s->streams[i];
+ ts_st = st->priv_data;
+ if (ts_st->payload_index > 0) {
+ mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index,
+ ts_st->payload_pts);
+ }
+ }
+ put_flush_packet(&s->pb);
+
+ for(i = 0; i < ts->nb_services; i++) {
+ service = ts->services[i];
+ av_freep(&service->provider_name);
+ av_freep(&service->name);
+ av_free(service);
+ }
+ av_free(ts->services);
+
+ return 0;
+}
+
+AVOutputFormat mpegts_muxer = {
+ "mpegts",
+ "MPEG2 transport stream format",
+ "video/x-mpegts",
+ "ts",
+ sizeof(MpegTSWrite),
+ CODEC_ID_MP2,
+ CODEC_ID_MPEG2VIDEO,
+ mpegts_write_header,
+ mpegts_write_packet,
+ mpegts_write_end,
+};
diff --git a/contrib/ffmpeg/libavformat/mpjpeg.c b/contrib/ffmpeg/libavformat/mpjpeg.c
new file mode 100644
index 000000000..937917313
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/mpjpeg.c
@@ -0,0 +1,67 @@
+/*
+ * Multipart JPEG format
+ * Copyright (c) 2000, 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
+ */
+#include "avformat.h"
+
+/* Multipart JPEG */
+
+#define BOUNDARY_TAG "ffserver"
+
+static int mpjpeg_write_header(AVFormatContext *s)
+{
+ uint8_t buf1[256];
+
+ snprintf(buf1, sizeof(buf1), "--%s\n", BOUNDARY_TAG);
+ put_buffer(&s->pb, buf1, strlen(buf1));
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+static int mpjpeg_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ uint8_t buf1[256];
+
+ snprintf(buf1, sizeof(buf1), "Content-type: image/jpeg\n\n");
+ put_buffer(&s->pb, buf1, strlen(buf1));
+ put_buffer(&s->pb, pkt->data, pkt->size);
+
+ snprintf(buf1, sizeof(buf1), "\n--%s\n", BOUNDARY_TAG);
+ put_buffer(&s->pb, buf1, strlen(buf1));
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+static int mpjpeg_write_trailer(AVFormatContext *s)
+{
+ return 0;
+}
+
+AVOutputFormat mpjpeg_muxer = {
+ "mpjpeg",
+ "Mime multipart JPEG format",
+ "multipart/x-mixed-replace;boundary=" BOUNDARY_TAG,
+ "mjpg",
+ 0,
+ CODEC_ID_NONE,
+ CODEC_ID_MJPEG,
+ mpjpeg_write_header,
+ mpjpeg_write_packet,
+ mpjpeg_write_trailer,
+};
diff --git a/contrib/ffmpeg/libavformat/mtv.c b/contrib/ffmpeg/libavformat/mtv.c
new file mode 100644
index 000000000..7a68ea97f
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/mtv.c
@@ -0,0 +1,187 @@
+/*
+ * mtv demuxer
+ * Copyright (c) 2006 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 mtv.c
+ * MTV demuxer.
+ */
+
+#include "avformat.h"
+#include "bswap.h"
+
+#define MTV_ASUBCHUNK_DATA_SIZE 500
+#define MTV_HEADER_SIZE 512
+#define MTV_AUDIO_PADDING_SIZE 12
+#define AUDIO_SAMPLING_RATE 44100
+#define VIDEO_SID 0
+#define AUDIO_SID 1
+
+typedef struct MTVDemuxContext {
+
+ unsigned int file_size; ///< filesize, not always right
+ unsigned int segments; ///< number of 512 byte segments
+ unsigned int audio_identifier; ///< 'MP3' on all files I have seen
+ unsigned int audio_br; ///< bitrate of audio chanel (mp3)
+ unsigned int img_colorfmt; ///< frame colorfmt rgb 565/555
+ unsigned int img_bpp; ///< frame bits per pixel
+ unsigned int img_width; //
+ unsigned int img_height; //
+ unsigned int img_segment_size; ///< size of image segment
+ unsigned int video_fps; //
+ unsigned int audio_subsegments; ///< audio subsegments on one segment
+
+ uint8_t audio_packet_count;
+
+} MTVDemuxContext;
+
+static int mtv_probe(AVProbeData *p)
+{
+ if(p->buf_size < 3)
+ return 0;
+
+ /* Magic is 'AMV' */
+
+ if(*(p->buf) != 'A' || *(p->buf+1) != 'M' || *(p->buf+2) != 'V')
+ return 0;
+
+ return AVPROBE_SCORE_MAX;
+}
+
+static int mtv_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ MTVDemuxContext *mtv = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVStream *st;
+
+
+ url_fskip(pb, 3);
+ mtv->file_size = get_le32(pb);
+ mtv->segments = get_le32(pb);
+ url_fskip(pb, 32);
+ mtv->audio_identifier = get_le24(pb);
+ mtv->audio_br = get_le16(pb);
+ mtv->img_colorfmt = get_le24(pb);
+ mtv->img_bpp = get_byte(pb);
+ mtv->img_width = get_le16(pb);
+ mtv->img_height = get_le16(pb);
+ mtv->img_segment_size = get_le16(pb);
+ url_fskip(pb, 4);
+ mtv->audio_subsegments = get_le16(pb);
+ mtv->video_fps = (mtv->audio_br / 4) / mtv->audio_subsegments;
+
+ /* FIXME Add sanity check here */
+
+ /* first packet is allways audio*/
+
+ mtv->audio_packet_count = 1;
+
+ /* all systems go! init decoders */
+
+ /* video - raw rgb565 */
+
+ st = av_new_stream(s, VIDEO_SID);
+ if(!st)
+ return AVERROR_NOMEM;
+
+ av_set_pts_info(st, 64, 1, mtv->video_fps);
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_RAWVIDEO;
+ st->codec->codec_tag = MKTAG('R', 'G', 'B', mtv->img_bpp);
+ st->codec->width = mtv->img_width;
+ st->codec->height = mtv->img_height;
+ st->codec->bits_per_sample = mtv->img_bpp;
+ st->codec->sample_rate = mtv->video_fps;
+
+ /* audio - mp3 */
+
+ st = av_new_stream(s, AUDIO_SID);
+ if(!st)
+ return AVERROR_NOMEM;
+
+ av_set_pts_info(st, 64, 1, AUDIO_SAMPLING_RATE);
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_MP3;
+ st->codec->bit_rate = mtv->audio_br;
+ st->need_parsing=1;
+
+ /* Jump over header */
+
+ if(url_fseek(pb, MTV_HEADER_SIZE, SEEK_SET) != MTV_HEADER_SIZE)
+ return AVERROR_IO;
+
+ return(0);
+
+}
+
+static int mtv_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ MTVDemuxContext *mtv = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int ret;
+#ifndef WORDS_BIGENDIAN
+ int i;
+#endif
+
+ ret = 0;
+
+ if(mtv->audio_subsegments >= mtv->audio_packet_count)
+ {
+ url_fskip(pb, MTV_AUDIO_PADDING_SIZE);
+
+ ret = av_get_packet(pb, pkt, MTV_ASUBCHUNK_DATA_SIZE);
+ if(ret != MTV_ASUBCHUNK_DATA_SIZE)
+ return AVERROR_IO;
+
+ mtv->audio_packet_count++;
+ pkt->stream_index = AUDIO_SID;
+
+ }else
+ {
+ ret = av_get_packet(pb, pkt, mtv->img_segment_size);
+ if(ret != mtv->img_segment_size)
+ return AVERROR_IO;
+
+#ifndef WORDS_BIGENDIAN
+
+ /* pkt->data is GGGRRRR BBBBBGGG
+ * and we need RRRRRGGG GGGBBBBB
+ * for PIX_FMT_RGB565 so here we
+ * just swap bytes as they come
+ */
+
+ for(i=0;i<mtv->img_segment_size/2;i++)
+ *((uint16_t *)pkt->data+i) = bswap_16(*((uint16_t *)pkt->data+i));
+#endif
+ mtv->audio_packet_count = 1;
+ pkt->stream_index = VIDEO_SID;
+ }
+
+ return(ret);
+}
+
+AVInputFormat mtv_demuxer = {
+ "MTV",
+ "MTV format",
+ sizeof(MTVDemuxContext),
+ mtv_probe,
+ mtv_read_header,
+ mtv_read_packet,
+};
diff --git a/contrib/ffmpeg/libavformat/mxf.c b/contrib/ffmpeg/libavformat/mxf.c
new file mode 100644
index 000000000..b20679943
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/mxf.c
@@ -0,0 +1,1082 @@
+/*
+ * MXF demuxer.
+ * Copyright (c) 2006 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot 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
+ */
+
+/*
+ * References
+ * SMPTE 336M KLV Data Encoding Protocol Using Key-Length-Value
+ * SMPTE 377M MXF File Format Specifications
+ * SMPTE 378M Operational Pattern 1a
+ * SMPTE 379M MXF Generic Container
+ * SMPTE 381M Mapping MPEG Streams into the MXF Generic Container
+ * SMPTE 382M Mapping AES3 and Broadcast Wave Audio into the MXF Generic Container
+ * SMPTE 383M Mapping DV-DIF Data to the MXF Generic Container
+ *
+ * Principle
+ * Search for Track numbers which will identify essence element KLV packets.
+ * Search for SourcePackage which define tracks which contains Track numbers.
+ * Material Package contains tracks with reference to SourcePackage tracks.
+ * Search for Descriptors (Picture, Sound) which contains codec info and parameters.
+ * Assign Descriptors to correct Tracks.
+ *
+ * Metadata reading functions read Local Tags, get InstanceUID(0x3C0A) then add MetaDataSet to MXFContext.
+ * Metadata parsing resolves Strong References to objects.
+ *
+ * Simple demuxer, only OP1A supported and some files might not work at all.
+ * Only tracks with associated descriptors will be decoded. "Highly Desirable" SMPTE 377M D.1
+ */
+
+//#define DEBUG
+
+#include "avformat.h"
+
+typedef uint8_t UID[16];
+
+enum MXFMetadataSetType {
+ MaterialPackage,
+ SourcePackage,
+ SourceClip,
+ TimecodeComponent,
+ Sequence,
+ MultipleDescriptor,
+ Descriptor,
+ Track,
+ EssenceContainerData,
+};
+
+typedef struct MXFStructuralComponent {
+ UID uid;
+ enum MXFMetadataSetType type;
+ UID source_package_uid;
+ UID data_definition_ul;
+ int64_t duration;
+ int64_t start_position;
+ int source_track_id;
+} MXFStructuralComponent;
+
+typedef struct MXFSequence {
+ UID uid;
+ enum MXFMetadataSetType type;
+ UID data_definition_ul;
+ UID *structural_components_refs;
+ int structural_components_count;
+ int64_t duration;
+} MXFSequence;
+
+typedef struct MXFTrack {
+ UID uid;
+ enum MXFMetadataSetType type;
+ MXFSequence *sequence; /* mandatory, and only one */
+ UID sequence_ref;
+ int track_id;
+ uint8_t track_number[4];
+ AVRational edit_rate;
+} MXFTrack;
+
+typedef struct MXFDescriptor {
+ UID uid;
+ enum MXFMetadataSetType type;
+ UID essence_container_ul;
+ UID essence_codec_ul;
+ AVRational sample_rate;
+ AVRational aspect_ratio;
+ int width;
+ int height;
+ int channels;
+ int bits_per_sample;
+ UID *sub_descriptors_refs;
+ int sub_descriptors_count;
+ int linked_track_id;
+ uint8_t *extradata;
+ int extradata_size;
+} MXFDescriptor;
+
+typedef struct MXFPackage {
+ UID uid;
+ enum MXFMetadataSetType type;
+ UID package_uid;
+ UID *tracks_refs;
+ int tracks_count;
+ MXFDescriptor *descriptor; /* only one */
+ UID descriptor_ref;
+} MXFPackage;
+
+typedef struct MXFEssenceContainerData {
+ UID uid;
+ enum MXFMetadataSetType type;
+ UID linked_package_uid;
+} MXFEssenceContainerData;
+
+typedef struct {
+ UID uid;
+ enum MXFMetadataSetType type;
+} MXFMetadataSet;
+
+typedef struct MXFContext {
+ UID *packages_refs;
+ int packages_count;
+ UID *essence_container_data_sets_refs;
+ int essence_container_data_sets_count;
+ UID *essence_containers_uls; /* Universal Labels SMPTE RP224 */
+ int essence_containers_uls_count;
+ UID operational_pattern_ul;
+ UID content_storage_uid;
+ MXFMetadataSet **metadata_sets;
+ int metadata_sets_count;
+ AVFormatContext *fc;
+} MXFContext;
+
+typedef struct KLVPacket {
+ UID key;
+ offset_t offset;
+ uint64_t length;
+} KLVPacket;
+
+enum MXFWrappingScheme {
+ Frame,
+ Clip,
+};
+
+typedef struct MXFCodecUL {
+ UID uid;
+ enum CodecID id;
+ enum MXFWrappingScheme wrapping;
+} MXFCodecUL;
+
+typedef struct MXFDataDefinitionUL {
+ UID uid;
+ enum CodecType type;
+} MXFDataDefinitionUL;
+
+typedef struct MXFMetadataReadTableEntry {
+ const UID key;
+ int (*read)(MXFContext *mxf, KLVPacket *klv);
+} MXFMetadataReadTableEntry;
+
+/* partial keys to match */
+static const uint8_t mxf_header_partition_pack_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02 };
+static const uint8_t mxf_essence_element_key[] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01 };
+
+#define IS_KLV_KEY(x, y) (!memcmp(x, y, sizeof(y)))
+
+#define PRINT_KEY(s, x) dprintf("%s %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", s, \
+ (x)[0], (x)[1], (x)[2], (x)[3], (x)[4], (x)[5], (x)[6], (x)[7], (x)[8], (x)[9], (x)[10], (x)[11], (x)[12], (x)[13], (x)[14], (x)[15])
+
+static int64_t klv_decode_ber_length(ByteIOContext *pb)
+{
+ int64_t size = 0;
+ uint8_t length = get_byte(pb);
+ int type = length >> 7;
+
+ if (type) { /* long form */
+ int bytes_num = length & 0x7f;
+ /* SMPTE 379M 5.3.4 guarantee that bytes_num must not exceed 8 bytes */
+ if (bytes_num > 8)
+ return -1;
+ while (bytes_num--)
+ size = size << 8 | get_byte(pb);
+ } else {
+ size = length & 0x7f;
+ }
+ return size;
+}
+
+static int klv_read_packet(KLVPacket *klv, ByteIOContext *pb)
+{
+ klv->offset = url_ftell(pb);
+ get_buffer(pb, klv->key, 16);
+ klv->length = klv_decode_ber_length(pb);
+ return klv->length == -1 ? -1 : 0;
+}
+
+static int mxf_get_stream_index(AVFormatContext *s, KLVPacket *klv)
+{
+ int i;
+
+ for (i = 0; i < s->nb_streams; i++) {
+ MXFTrack *track = s->streams[i]->priv_data;
+ /* SMPTE 379M 7.3 */
+ if (!memcmp(klv->key + sizeof(mxf_essence_element_key), track->track_number, sizeof(track->track_number)))
+ return i;
+ }
+ /* return 0 if only one stream, for OP Atom files with 0 as track number */
+ return s->nb_streams == 1 ? 0 : -1;
+}
+
+/* XXX: use AVBitStreamFilter */
+static int mxf_get_d10_aes3_packet(ByteIOContext *pb, AVStream *st, AVPacket *pkt, int64_t length)
+{
+ uint8_t buffer[61444];
+ uint8_t *buf_ptr, *end_ptr, *data_ptr;
+
+ if (length > 61444) /* worst case PAL 1920 samples 8 channels */
+ return -1;
+ get_buffer(pb, buffer, length);
+ av_new_packet(pkt, length);
+ data_ptr = pkt->data;
+ end_ptr = buffer + length;
+ buf_ptr = buffer + 4; /* skip SMPTE 331M header */
+ for (; buf_ptr < end_ptr; buf_ptr += 4) {
+ if (st->codec->bits_per_sample == 24) {
+ data_ptr[0] = (buf_ptr[2] >> 4) | ((buf_ptr[3] & 0x0f) << 4);
+ data_ptr[1] = (buf_ptr[1] >> 4) | ((buf_ptr[2] & 0x0f) << 4);
+ data_ptr[2] = (buf_ptr[0] >> 4) | ((buf_ptr[1] & 0x0f) << 4);
+ data_ptr += 3;
+ } else {
+ data_ptr[0] = (buf_ptr[2] >> 4) | ((buf_ptr[3] & 0x0f) << 4);
+ data_ptr[1] = (buf_ptr[1] >> 4) | ((buf_ptr[2] & 0x0f) << 4);
+ data_ptr += 2;
+ }
+ }
+ pkt->size = data_ptr - pkt->data;
+ return 0;
+}
+
+static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ KLVPacket klv;
+
+ while (!url_feof(&s->pb)) {
+ if (klv_read_packet(&klv, &s->pb) < 0) {
+ av_log(s, AV_LOG_ERROR, "error reading KLV packet\n");
+ return -1;
+ }
+#ifdef DEBUG
+ PRINT_KEY("read packet", klv.key);
+#endif
+ if (IS_KLV_KEY(klv.key, mxf_essence_element_key)) {
+ int index = mxf_get_stream_index(s, &klv);
+ if (index < 0) {
+ av_log(s, AV_LOG_ERROR, "error getting stream index\n");
+ url_fskip(&s->pb, klv.length);
+ return -1;
+ }
+ /* check for 8 channels AES3 element */
+ if (klv.key[12] == 0x06 && klv.key[13] == 0x01 && klv.key[14] == 0x10) {
+ if (mxf_get_d10_aes3_packet(&s->pb, s->streams[index], pkt, klv.length) < 0) {
+ av_log(s, AV_LOG_ERROR, "error reading D-10 aes3 frame\n");
+ return -1;
+ }
+ } else
+ av_get_packet(&s->pb, pkt, klv.length);
+ pkt->stream_index = index;
+ return 0;
+ } else
+ url_fskip(&s->pb, klv.length);
+ }
+ return AVERROR_IO;
+}
+
+static int mxf_add_metadata_set(MXFContext *mxf, void *metadata_set)
+{
+ mxf->metadata_sets = av_realloc(mxf->metadata_sets, (mxf->metadata_sets_count + 1) * sizeof(*mxf->metadata_sets));
+ mxf->metadata_sets[mxf->metadata_sets_count] = metadata_set;
+ mxf->metadata_sets_count++;
+ return 0;
+}
+
+static int mxf_read_metadata_preface(MXFContext *mxf, KLVPacket *klv)
+{
+ ByteIOContext *pb = &mxf->fc->pb;
+ int bytes_read = 0;
+
+ while (bytes_read < klv->length) {
+ int tag = get_be16(pb);
+ int size = get_be16(pb); /* SMPTE 336M Table 8 KLV specified length, 0x53 */
+
+ switch (tag) {
+ case 0x3B03:
+ get_buffer(pb, mxf->content_storage_uid, 16);
+ break;
+ case 0x3B09:
+ get_buffer(pb, mxf->operational_pattern_ul, 16);
+ break;
+ case 0x3B0A:
+ mxf->essence_containers_uls_count = get_be32(pb);
+ if (mxf->essence_containers_uls_count >= UINT_MAX / sizeof(UID))
+ return -1;
+ mxf->essence_containers_uls = av_malloc(mxf->essence_containers_uls_count * sizeof(UID));
+ url_fskip(pb, 4); /* useless size of objects, always 16 according to specs */
+ get_buffer(pb, (uint8_t *)mxf->essence_containers_uls, mxf->essence_containers_uls_count * sizeof(UID));
+ break;
+ default:
+ url_fskip(pb, size);
+ }
+ bytes_read += size + 4;
+ }
+ return 0;
+}
+
+static int mxf_read_metadata_content_storage(MXFContext *mxf, KLVPacket *klv)
+{
+ ByteIOContext *pb = &mxf->fc->pb;
+ int bytes_read = 0;
+
+ while (bytes_read < klv->length) {
+ int tag = get_be16(pb);
+ int size = get_be16(pb); /* SMPTE 336M Table 8 KLV specified length, 0x53 */
+
+ dprintf("tag 0x%04X, size %d\n", tag, size);
+ switch (tag) {
+ case 0x1901:
+ mxf->packages_count = get_be32(pb);
+ if (mxf->packages_count >= UINT_MAX / sizeof(UID))
+ return -1;
+ mxf->packages_refs = av_malloc(mxf->packages_count * sizeof(UID));
+ url_fskip(pb, 4); /* useless size of objects, always 16 according to specs */
+ get_buffer(pb, (uint8_t *)mxf->packages_refs, mxf->packages_count * sizeof(UID));
+ break;
+ case 0x1902:
+ mxf->essence_container_data_sets_count = get_be32(pb);
+ if (mxf->essence_container_data_sets_count >= UINT_MAX / sizeof(UID))
+ return -1;
+ mxf->essence_container_data_sets_refs = av_malloc(mxf->essence_container_data_sets_count * sizeof(UID));
+ url_fskip(pb, 4); /* useless size of objects, always 16 according to specs */
+ get_buffer(pb, (uint8_t *)mxf->essence_container_data_sets_refs, mxf->essence_container_data_sets_count * sizeof(UID));
+ break;
+ default:
+ url_fskip(pb, size);
+ }
+ bytes_read += size + 4;
+ }
+ return 0;
+}
+
+static int mxf_read_metadata_source_clip(MXFContext *mxf, KLVPacket *klv)
+{
+ ByteIOContext *pb = &mxf->fc->pb;
+ MXFStructuralComponent *source_clip = av_mallocz(sizeof(*source_clip));
+ int bytes_read = 0;
+
+ while (bytes_read < klv->length) {
+ int tag = get_be16(pb);
+ int size = get_be16(pb); /* SMPTE 336M Table 8 KLV specified length, 0x53 */
+
+ bytes_read += size + 4;
+ dprintf("tag 0x%04X, size %d\n", tag, size);
+ if (!size) { /* ignore empty tag, needed for some files with empty UMID tag */
+ av_log(mxf->fc, AV_LOG_ERROR, "local tag 0x%04X with 0 size\n", tag);
+ continue;
+ }
+ switch (tag) {
+ case 0x3C0A:
+ get_buffer(pb, source_clip->uid, 16);
+ break;
+ case 0x0202:
+ source_clip->duration = get_be64(pb);
+ break;
+ case 0x1201:
+ source_clip->start_position = get_be64(pb);
+ break;
+ case 0x1101:
+ /* UMID, only get last 16 bytes */
+ url_fskip(pb, 16);
+ get_buffer(pb, source_clip->source_package_uid, 16);
+ break;
+ case 0x1102:
+ source_clip->source_track_id = get_be32(pb);
+ break;
+ default:
+ url_fskip(pb, size);
+ }
+ }
+ source_clip->type = SourceClip;
+ return mxf_add_metadata_set(mxf, source_clip);
+}
+
+static int mxf_read_metadata_material_package(MXFContext *mxf, KLVPacket *klv)
+{
+ ByteIOContext *pb = &mxf->fc->pb;
+ MXFPackage *package = av_mallocz(sizeof(*package));
+ int bytes_read = 0;
+
+ while (bytes_read < klv->length) {
+ int tag = get_be16(pb);
+ int size = get_be16(pb); /* KLV specified by 0x53 */
+
+ switch (tag) {
+ case 0x3C0A:
+ get_buffer(pb, package->uid, 16);
+ break;
+ case 0x4403:
+ package->tracks_count = get_be32(pb);
+ if (package->tracks_count >= UINT_MAX / sizeof(UID))
+ return -1;
+ package->tracks_refs = av_malloc(package->tracks_count * sizeof(UID));
+ url_fskip(pb, 4); /* useless size of objects, always 16 according to specs */
+ get_buffer(pb, (uint8_t *)package->tracks_refs, package->tracks_count * sizeof(UID));
+ break;
+ default:
+ url_fskip(pb, size);
+ }
+ bytes_read += size + 4;
+ }
+ package->type = MaterialPackage;
+ return mxf_add_metadata_set(mxf, package);
+}
+
+static int mxf_read_metadata_track(MXFContext *mxf, KLVPacket *klv)
+{
+ ByteIOContext *pb = &mxf->fc->pb;
+ MXFTrack *track = av_mallocz(sizeof(*track));
+ int bytes_read = 0;
+
+ while (bytes_read < klv->length) {
+ int tag = get_be16(pb);
+ int size = get_be16(pb); /* KLV specified by 0x53 */
+
+ dprintf("tag 0x%04X, size %d\n", tag, size);
+ switch (tag) {
+ case 0x3C0A:
+ get_buffer(pb, track->uid, 16);
+ break;
+ case 0x4801:
+ track->track_id = get_be32(pb);
+ break;
+ case 0x4804:
+ get_buffer(pb, track->track_number, 4);
+ break;
+ case 0x4B01:
+ track->edit_rate.den = get_be32(pb);
+ track->edit_rate.num = get_be32(pb);
+ break;
+ case 0x4803:
+ get_buffer(pb, track->sequence_ref, 16);
+ break;
+ default:
+ url_fskip(pb, size);
+ }
+ bytes_read += size + 4;
+ }
+ track->type = Track;
+ return mxf_add_metadata_set(mxf, track);
+}
+
+static int mxf_read_metadata_sequence(MXFContext *mxf, KLVPacket *klv)
+{
+ ByteIOContext *pb = &mxf->fc->pb;
+ MXFSequence *sequence = av_mallocz(sizeof(*sequence));
+ int bytes_read = 0;
+
+ while (bytes_read < klv->length) {
+ int tag = get_be16(pb);
+ int size = get_be16(pb); /* KLV specified by 0x53 */
+
+ dprintf("tag 0x%04X, size %d\n", tag, size);
+ switch (tag) {
+ case 0x3C0A:
+ get_buffer(pb, sequence->uid, 16);
+ break;
+ case 0x0202:
+ sequence->duration = get_be64(pb);
+ break;
+ case 0x0201:
+ get_buffer(pb, sequence->data_definition_ul, 16);
+ break;
+ case 0x1001:
+ sequence->structural_components_count = get_be32(pb);
+ if (sequence->structural_components_count >= UINT_MAX / sizeof(UID))
+ return -1;
+ sequence->structural_components_refs = av_malloc(sequence->structural_components_count * sizeof(UID));
+ url_fskip(pb, 4); /* useless size of objects, always 16 according to specs */
+ get_buffer(pb, (uint8_t *)sequence->structural_components_refs, sequence->structural_components_count * sizeof(UID));
+ break;
+ default:
+ url_fskip(pb, size);
+ }
+ bytes_read += size + 4;
+ }
+ sequence->type = Sequence;
+ return mxf_add_metadata_set(mxf, sequence);
+}
+
+static int mxf_read_metadata_source_package(MXFContext *mxf, KLVPacket *klv)
+{
+ ByteIOContext *pb = &mxf->fc->pb;
+ MXFPackage *package = av_mallocz(sizeof(*package));
+ int bytes_read = 0;
+
+ while (bytes_read < klv->length) {
+ int tag = get_be16(pb);
+ int size = get_be16(pb); /* KLV specified by 0x53 */
+
+ dprintf("tag 0x%04X, size %d\n", tag, size);
+ switch (tag) {
+ case 0x3C0A:
+ get_buffer(pb, package->uid, 16);
+ break;
+ case 0x4403:
+ package->tracks_count = get_be32(pb);
+ if (package->tracks_count >= UINT_MAX / sizeof(UID))
+ return -1;
+ package->tracks_refs = av_malloc(package->tracks_count * sizeof(UID));
+ url_fskip(pb, 4); /* useless size of objects, always 16 according to specs */
+ get_buffer(pb, (uint8_t *)package->tracks_refs, package->tracks_count * sizeof(UID));
+ break;
+ case 0x4401:
+ /* UMID, only get last 16 bytes */
+ url_fskip(pb, 16);
+ get_buffer(pb, package->package_uid, 16);
+ break;
+ case 0x4701:
+ get_buffer(pb, package->descriptor_ref, 16);
+ break;
+ default:
+ url_fskip(pb, size);
+ }
+ bytes_read += size + 4;
+ }
+ package->type = SourcePackage;
+ return mxf_add_metadata_set(mxf, package);
+}
+
+static int mxf_read_metadata_multiple_descriptor(MXFContext *mxf, KLVPacket *klv)
+{
+ ByteIOContext *pb = &mxf->fc->pb;
+ MXFDescriptor *descriptor = av_mallocz(sizeof(*descriptor));
+ int bytes_read = 0;
+
+ while (bytes_read < klv->length) {
+ int tag = get_be16(pb);
+ int size = get_be16(pb); /* KLV specified by 0x53 */
+
+ dprintf("tag 0x%04X, size %d\n", tag, size);
+ switch (tag) {
+ case 0x3C0A:
+ get_buffer(pb, descriptor->uid, 16);
+ break;
+ case 0x3F01:
+ descriptor->sub_descriptors_count = get_be32(pb);
+ if (descriptor->sub_descriptors_count >= UINT_MAX / sizeof(UID))
+ return -1;
+ descriptor->sub_descriptors_refs = av_malloc(descriptor->sub_descriptors_count * sizeof(UID));
+ url_fskip(pb, 4); /* useless size of objects, always 16 according to specs */
+ get_buffer(pb, (uint8_t *)descriptor->sub_descriptors_refs, descriptor->sub_descriptors_count * sizeof(UID));
+ break;
+ default:
+ url_fskip(pb, size);
+ }
+ bytes_read += size + 4;
+ }
+ descriptor->type = MultipleDescriptor;
+ return mxf_add_metadata_set(mxf, descriptor);
+}
+
+static void mxf_read_metadata_pixel_layout(ByteIOContext *pb, MXFDescriptor *descriptor)
+{
+ int code;
+
+ do {
+ code = get_byte(pb);
+ dprintf("pixel layout: code 0x%x\n", code);
+ switch (code) {
+ case 0x52: /* R */
+ descriptor->bits_per_sample += get_byte(pb);
+ break;
+ case 0x47: /* G */
+ descriptor->bits_per_sample += get_byte(pb);
+ break;
+ case 0x42: /* B */
+ descriptor->bits_per_sample += get_byte(pb);
+ break;
+ default:
+ get_byte(pb);
+ }
+ } while (code != 0); /* SMPTE 377M E.2.46 */
+}
+
+static int mxf_read_metadata_generic_descriptor(MXFContext *mxf, KLVPacket *klv)
+{
+ ByteIOContext *pb = &mxf->fc->pb;
+ MXFDescriptor *descriptor = av_mallocz(sizeof(*descriptor));
+ int bytes_read = 0;
+
+ while (bytes_read < klv->length) {
+ int tag = get_be16(pb);
+ int size = get_be16(pb); /* KLV specified by 0x53 */
+
+ dprintf("tag 0x%04X, size %d\n", tag, size);
+ switch (tag) {
+ case 0x3C0A:
+ get_buffer(pb, descriptor->uid, 16);
+ break;
+ case 0x3004:
+ get_buffer(pb, descriptor->essence_container_ul, 16);
+ break;
+ case 0x3006:
+ descriptor->linked_track_id = get_be32(pb);
+ break;
+ case 0x3201: /* PictureEssenceCoding */
+ get_buffer(pb, descriptor->essence_codec_ul, 16);
+ break;
+ case 0x3203:
+ descriptor->width = get_be32(pb);
+ break;
+ case 0x3202:
+ descriptor->height = get_be32(pb);
+ break;
+ case 0x320E:
+ descriptor->aspect_ratio.num = get_be32(pb);
+ descriptor->aspect_ratio.den = get_be32(pb);
+ break;
+ case 0x3D03:
+ descriptor->sample_rate.num = get_be32(pb);
+ descriptor->sample_rate.den = get_be32(pb);
+ break;
+ case 0x3D06: /* SoundEssenceCompression */
+ get_buffer(pb, descriptor->essence_codec_ul, 16);
+ break;
+ case 0x3D07:
+ descriptor->channels = get_be32(pb);
+ break;
+ case 0x3D01:
+ descriptor->bits_per_sample = get_be32(pb);
+ break;
+ case 0x3401:
+ mxf_read_metadata_pixel_layout(pb, descriptor);
+ break;
+ case 0x8201: /* Private tag used by SONY C0023S01.mxf */
+ descriptor->extradata = av_malloc(size);
+ descriptor->extradata_size = size;
+ get_buffer(pb, descriptor->extradata, size);
+ break;
+ default:
+ url_fskip(pb, size);
+ }
+ bytes_read += size + 4;
+ }
+ descriptor->type = Descriptor;
+ return mxf_add_metadata_set(mxf, descriptor);
+}
+
+/* SMPTE RP224 http://www.smpte-ra.org/mdd/index.html */
+static const MXFDataDefinitionUL mxf_data_definition_uls[] = {
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x01,0x03,0x02,0x02,0x01,0x00,0x00,0x00 }, CODEC_TYPE_VIDEO },
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x01,0x03,0x02,0x02,0x02,0x00,0x00,0x00 }, CODEC_TYPE_AUDIO },
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x05,0x01,0x03,0x02,0x02,0x02,0x02,0x00,0x00 }, CODEC_TYPE_AUDIO },
+ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, CODEC_TYPE_DATA },
+};
+
+static const MXFCodecUL mxf_codec_uls[] = {
+ /* PictureEssenceCoding */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x02,0x02,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@ML I-Frame */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x02,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@HL I-Frame */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x03,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@HL Long GoP */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x11,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* MP@ML Long GoP */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x02,0x03,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@ML Long GoP */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x03,0x03,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* MP@HL Long GoP */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x20,0x02,0x03 }, CODEC_ID_MPEG4, Frame }, /* XDCAM proxy_pal030926.mxf */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x20,0x02,0x04 }, CODEC_ID_MPEG4, Frame }, /* XDCAM Proxy C0023S01.mxf */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x05 }, CODEC_ID_MPEG2VIDEO, Frame }, /* D-10 30Mbps PAL */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x01 }, CODEC_ID_MPEG2VIDEO, Frame }, /* D-10 50Mbps PAL */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x04,0x00 }, CODEC_ID_DVVIDEO, Frame }, /* DVCPRO50 PAL */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x02,0x00 }, CODEC_ID_DVVIDEO, Frame }, /* DVCPRO25 PAL */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x01,0x02,0x00 }, CODEC_ID_DVVIDEO, Frame }, /* DV25 IEC PAL */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, CODEC_ID_JPEG2000, Frame }, /* JPEG2000 Codestream */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x01,0x7F,0x00,0x00,0x00 }, CODEC_ID_RAWVIDEO, Frame }, /* Uncompressed */
+ /* SoundEssenceCompression */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, CODEC_ID_PCM_S16LE, Frame }, /* Uncompressed */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x7F,0x00,0x00,0x00 }, CODEC_ID_PCM_S16LE, Frame },
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x02,0x02,0x01,0x7E,0x00,0x00,0x00 }, CODEC_ID_PCM_S16BE, Frame }, /* From Omneon MXF file */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x01,0x01,0x00 }, CODEC_ID_PCM_ALAW, Frame },
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x04,0x04,0x02,0x02,0x02,0x03,0x01,0x01,0x00 }, CODEC_ID_PCM_ALAW, Frame }, /* XDCAM Proxy C0023S01.mxf */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x01,0x00 }, CODEC_ID_AC3, Frame },
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x05,0x00 }, CODEC_ID_MP2, Frame }, /* MP2 or MP3 */
+ //{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x1C,0x00 }, CODEC_ID_DOLBY_E, Frame }, /* Dolby-E */
+ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, CODEC_ID_NONE, Frame },
+};
+
+static const MXFCodecUL mxf_picture_essence_container_uls[] = {
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, CODEC_ID_MPEG2VIDEO, Frame }, /* MPEG-ES Frame wrapped */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0xe0,0x02 }, CODEC_ID_MPEG2VIDEO, Clip }, /* MPEG-ES Clip wrapped, 0xe0 MPV stream id */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x04,0x61,0x07 }, CODEC_ID_MPEG2VIDEO, Clip }, /* MPEG-ES Custom wrapped, 0x61 ??? stream id */
+ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, CODEC_ID_NONE, Frame },
+};
+
+static const MXFCodecUL mxf_sound_essence_container_uls[] = {
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x06,0x01,0x00 }, CODEC_ID_PCM_S16LE, Frame }, /* BWF Frame wrapped */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x06,0x03,0x00 }, CODEC_ID_PCM_S16LE, Frame }, /* AES Frame wrapped */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x40,0x01 }, CODEC_ID_MP2, Frame }, /* MPEG-ES Frame wrapped, 0x40 ??? stream id */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0xc0,0x01 }, CODEC_ID_MP2, Frame }, /* MPEG-ES Frame wrapped, 0xc0 MPA stream id */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0xc0,0x02 }, CODEC_ID_MP2, Clip }, /* MPEG-ES Clip wrapped, 0xc0 MPA stream id */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x05,0x01 }, CODEC_ID_PCM_S16BE, Frame }, /* D-10 Mapping 30Mbps PAL Extended Template */
+ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }, CODEC_ID_PCM_S16BE, Frame }, /* D-10 Mapping 50Mbps PAL Extended Template */
+ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, CODEC_ID_NONE, Frame },
+};
+
+static const MXFCodecUL *mxf_get_codec_ul(const MXFCodecUL *uls, UID *uid)
+{
+ while (uls->id != CODEC_ID_NONE) {
+ if(!memcmp(uls->uid, *uid, 16))
+ break;
+ uls++;
+ }
+ return uls;
+}
+
+static enum CodecType mxf_get_codec_type(const MXFDataDefinitionUL *uls, UID *uid)
+{
+ while (uls->type != CODEC_TYPE_DATA) {
+ if(!memcmp(uls->uid, *uid, 16))
+ break;
+ uls++;
+ }
+ return uls->type;
+}
+
+static void *mxf_resolve_strong_ref(MXFContext *mxf, UID *strong_ref)
+{
+ int i;
+
+ if (!strong_ref)
+ return NULL;
+ for (i = 0; i < mxf->metadata_sets_count; i++) {
+ if (!memcmp(*strong_ref, mxf->metadata_sets[i]->uid, 16)) {
+ return mxf->metadata_sets[i];
+ }
+ }
+ return NULL;
+}
+
+static int mxf_parse_structural_metadata(MXFContext *mxf)
+{
+ MXFPackage *material_package = NULL;
+ MXFPackage *temp_package = NULL;
+ int i, j, k;
+
+ dprintf("metadata sets count %d\n", mxf->metadata_sets_count);
+ /* TODO: handle multiple material packages (OP3x) */
+ for (i = 0; i < mxf->packages_count; i++) {
+ if (!(temp_package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[i]))) {
+ av_log(mxf->fc, AV_LOG_ERROR, "could not resolve package strong ref\n");
+ return -1;
+ }
+ if (temp_package->type == MaterialPackage) {
+ material_package = temp_package;
+ break;
+ }
+ }
+ if (!material_package) {
+ av_log(mxf->fc, AV_LOG_ERROR, "no material package found\n");
+ return -1;
+ }
+
+ for (i = 0; i < material_package->tracks_count; i++) {
+ MXFPackage *source_package = NULL;
+ MXFTrack *material_track = NULL;
+ MXFTrack *source_track = NULL;
+ MXFTrack *temp_track = NULL;
+ MXFDescriptor *descriptor = NULL;
+ MXFStructuralComponent *component = NULL;
+ const MXFCodecUL *codec_ul = NULL;
+ const MXFCodecUL *container_ul = NULL;
+ AVStream *st;
+
+ if (!(material_track = mxf_resolve_strong_ref(mxf, &material_package->tracks_refs[i]))) {
+ av_log(mxf->fc, AV_LOG_ERROR, "could not resolve material track strong ref\n");
+ continue;
+ }
+
+ if (!(material_track->sequence = mxf_resolve_strong_ref(mxf, &material_track->sequence_ref))) {
+ av_log(mxf->fc, AV_LOG_ERROR, "could not resolve material track sequence strong ref\n");
+ return -1;
+ }
+
+ /* TODO: handle multiple source clips */
+ for (j = 0; j < material_track->sequence->structural_components_count; j++) {
+ /* TODO: handle timecode component */
+ component = mxf_resolve_strong_ref(mxf, &material_track->sequence->structural_components_refs[j]);
+ if (!component || component->type != SourceClip)
+ continue;
+
+ for (k = 0; k < mxf->packages_count; k++) {
+ if (!(temp_package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[k]))) {
+ av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track strong ref\n");
+ return -1;
+ }
+ if (!memcmp(temp_package->package_uid, component->source_package_uid, 16)) {
+ source_package = temp_package;
+ break;
+ }
+ }
+ if (!source_package) {
+ av_log(mxf->fc, AV_LOG_ERROR, "material track %d: no corresponding source package found\n", material_track->track_id);
+ break;
+ }
+ for (k = 0; k < source_package->tracks_count; k++) {
+ if (!(temp_track = mxf_resolve_strong_ref(mxf, &source_package->tracks_refs[k]))) {
+ av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track strong ref\n");
+ return -1;
+ }
+ if (temp_track->track_id == component->source_track_id) {
+ source_track = temp_track;
+ break;
+ }
+ }
+ if (!source_track) {
+ av_log(mxf->fc, AV_LOG_ERROR, "material track %d: no corresponding source track found\n", material_track->track_id);
+ break;
+ }
+ }
+ if (!source_track)
+ continue;
+
+ st = av_new_stream(mxf->fc, source_track->track_id);
+ st->priv_data = source_track;
+ st->duration = component->duration;
+ if (st->duration == -1)
+ st->duration = AV_NOPTS_VALUE;
+ st->start_time = component->start_position;
+ av_set_pts_info(st, 64, material_track->edit_rate.num, material_track->edit_rate.den);
+
+ if (!(source_track->sequence = mxf_resolve_strong_ref(mxf, &source_track->sequence_ref))) {
+ av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track sequence strong ref\n");
+ return -1;
+ }
+
+#ifdef DEBUG
+ PRINT_KEY("data definition ul", source_track->sequence->data_definition_ul);
+#endif
+ st->codec->codec_type = mxf_get_codec_type(mxf_data_definition_uls, &source_track->sequence->data_definition_ul);
+
+ source_package->descriptor = mxf_resolve_strong_ref(mxf, &source_package->descriptor_ref);
+ if (source_package->descriptor) {
+ if (source_package->descriptor->type == MultipleDescriptor) {
+ for (j = 0; j < source_package->descriptor->sub_descriptors_count; j++) {
+ MXFDescriptor *sub_descriptor = mxf_resolve_strong_ref(mxf, &source_package->descriptor->sub_descriptors_refs[j]);
+
+ if (!sub_descriptor) {
+ av_log(mxf->fc, AV_LOG_ERROR, "could not resolve sub descriptor strong ref\n");
+ continue;
+ }
+ if (sub_descriptor->linked_track_id == source_track->track_id) {
+ descriptor = sub_descriptor;
+ break;
+ }
+ }
+ } else
+ descriptor = source_package->descriptor;
+ }
+ if (!descriptor) {
+ av_log(mxf->fc, AV_LOG_INFO, "source track %d: stream %d, no descriptor found\n", source_track->track_id, st->index);
+ continue;
+ }
+#ifdef DEBUG
+ PRINT_KEY("essence codec ul", descriptor->essence_codec_ul);
+ PRINT_KEY("essence container ul", descriptor->essence_container_ul);
+#endif
+ /* TODO: drop PictureEssenceCoding and SoundEssenceCompression, only check EssenceContainer */
+ codec_ul = mxf_get_codec_ul(mxf_codec_uls, &descriptor->essence_codec_ul);
+ st->codec->codec_id = codec_ul->id;
+ if (descriptor->extradata) {
+ st->codec->extradata = descriptor->extradata;
+ st->codec->extradata_size = descriptor->extradata_size;
+ }
+ if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ container_ul = mxf_get_codec_ul(mxf_picture_essence_container_uls, &descriptor->essence_container_ul);
+ if (st->codec->codec_id == CODEC_ID_NONE)
+ st->codec->codec_id = container_ul->id;
+ st->codec->width = descriptor->width;
+ st->codec->height = descriptor->height;
+ st->codec->bits_per_sample = descriptor->bits_per_sample; /* Uncompressed */
+ st->need_parsing = 2; /* only parse headers */
+ } else if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
+ container_ul = mxf_get_codec_ul(mxf_sound_essence_container_uls, &descriptor->essence_container_ul);
+ if (st->codec->codec_id == CODEC_ID_NONE)
+ st->codec->codec_id = container_ul->id;
+ st->codec->channels = descriptor->channels;
+ st->codec->bits_per_sample = descriptor->bits_per_sample;
+ st->codec->sample_rate = descriptor->sample_rate.num / descriptor->sample_rate.den;
+ /* TODO: implement CODEC_ID_RAWAUDIO */
+ if (st->codec->codec_id == CODEC_ID_PCM_S16LE) {
+ if (descriptor->bits_per_sample == 24)
+ st->codec->codec_id = CODEC_ID_PCM_S24LE;
+ else if (descriptor->bits_per_sample == 32)
+ st->codec->codec_id = CODEC_ID_PCM_S32LE;
+ } else if (st->codec->codec_id == CODEC_ID_PCM_S16BE) {
+ if (descriptor->bits_per_sample == 24)
+ st->codec->codec_id = CODEC_ID_PCM_S24BE;
+ else if (descriptor->bits_per_sample == 32)
+ st->codec->codec_id = CODEC_ID_PCM_S32BE;
+ if (descriptor->essence_container_ul[13] == 0x01) /* D-10 Mapping */
+ st->codec->channels = 8; /* force channels to 8 */
+ } else if (st->codec->codec_id == CODEC_ID_MP2) {
+ st->need_parsing = 1;
+ }
+ }
+ if (container_ul && container_ul->wrapping == Clip) {
+ dprintf("stream %d: clip wrapped essence\n", st->index);
+ st->need_parsing = 1;
+ }
+ }
+ return 0;
+}
+
+static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = {
+ { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x2F,0x00 }, mxf_read_metadata_preface },
+ { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x18,0x00 }, mxf_read_metadata_content_storage },
+ { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x37,0x00 }, mxf_read_metadata_source_package },
+ { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x36,0x00 }, mxf_read_metadata_material_package },
+ { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0F,0x00 }, mxf_read_metadata_sequence },
+ { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x11,0x00 }, mxf_read_metadata_source_clip },
+ { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x44,0x00 }, mxf_read_metadata_multiple_descriptor },
+ { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x42,0x00 }, mxf_read_metadata_generic_descriptor }, /* Generic Sound */
+ { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x28,0x00 }, mxf_read_metadata_generic_descriptor }, /* CDCI */
+ { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x29,0x00 }, mxf_read_metadata_generic_descriptor }, /* RGBA */
+ { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x51,0x00 }, mxf_read_metadata_generic_descriptor }, /* MPEG 2 Video */
+ { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x48,0x00 }, mxf_read_metadata_generic_descriptor }, /* Wave */
+ { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x47,0x00 }, mxf_read_metadata_generic_descriptor }, /* AES3 */
+ { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3A,0x00 }, mxf_read_metadata_track }, /* Static Track */
+ { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3B,0x00 }, mxf_read_metadata_track }, /* Generic Track */
+ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, NULL },
+};
+
+static int mxf_read_sync(ByteIOContext *pb, const uint8_t *key, unsigned size)
+{
+ int i, b;
+ for (i = 0; i < size && !url_feof(pb); i++) {
+ b = get_byte(pb);
+ if (b == key[0])
+ i = 0;
+ else if (b != key[i])
+ i = -1;
+ }
+ return i == size;
+}
+
+static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ MXFContext *mxf = s->priv_data;
+ KLVPacket klv;
+
+ if (!mxf_read_sync(&s->pb, mxf_header_partition_pack_key, 14)) {
+ av_log(s, AV_LOG_ERROR, "could not find header partition pack key\n");
+ return -1;
+ }
+ url_fseek(&s->pb, -14, SEEK_CUR);
+ mxf->fc = s;
+ while (!url_feof(&s->pb)) {
+ const MXFMetadataReadTableEntry *function;
+
+ if (klv_read_packet(&klv, &s->pb) < 0) {
+ av_log(s, AV_LOG_ERROR, "error reading KLV packet\n");
+ return -1;
+ }
+#ifdef DEBUG
+ PRINT_KEY("read header", klv.key);
+#endif
+ if (IS_KLV_KEY(klv.key, mxf_essence_element_key)) {
+ /* FIXME avoid seek */
+ url_fseek(&s->pb, klv.offset, SEEK_SET);
+ break;
+ }
+
+ for (function = mxf_metadata_read_table; function->read; function++) {
+ if (IS_KLV_KEY(klv.key, function->key)) {
+ if (function->read(mxf, &klv) < 0) {
+ av_log(s, AV_LOG_ERROR, "error reading header metadata\n");
+ return -1;
+ }
+ break;
+ }
+ }
+ if (!function->read)
+ url_fskip(&s->pb, klv.length);
+ }
+ return mxf_parse_structural_metadata(mxf);
+}
+
+static int mxf_read_close(AVFormatContext *s)
+{
+ MXFContext *mxf = s->priv_data;
+ int i;
+
+ av_freep(&mxf->packages_refs);
+ av_freep(&mxf->essence_container_data_sets_refs);
+ av_freep(&mxf->essence_containers_uls);
+ for (i = 0; i < mxf->metadata_sets_count; i++) {
+ switch (mxf->metadata_sets[i]->type) {
+ case MultipleDescriptor:
+ av_freep(&((MXFDescriptor *)mxf->metadata_sets[i])->sub_descriptors_refs);
+ break;
+ case Sequence:
+ av_freep(&((MXFSequence *)mxf->metadata_sets[i])->structural_components_refs);
+ break;
+ case SourcePackage:
+ case MaterialPackage:
+ av_freep(&((MXFPackage *)mxf->metadata_sets[i])->tracks_refs);
+ break;
+ default:
+ break;
+ }
+ av_freep(&mxf->metadata_sets[i]);
+ }
+ av_freep(&mxf->metadata_sets);
+ return 0;
+}
+
+static int mxf_probe(AVProbeData *p) {
+ uint8_t *bufp = p->buf;
+ uint8_t *end = p->buf + p->buf_size;
+
+ if (p->buf_size < sizeof(mxf_header_partition_pack_key))
+ return 0;
+
+ /* Must skip Run-In Sequence and search for MXF header partition pack key SMPTE 377M 5.5 */
+ end -= sizeof(mxf_header_partition_pack_key);
+ for (; bufp < end; bufp++) {
+ if (IS_KLV_KEY(bufp, mxf_header_partition_pack_key))
+ return AVPROBE_SCORE_MAX;
+ }
+ return 0;
+}
+
+/* rudimentary binary seek */
+/* XXX: use MXF Index */
+static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
+{
+ AVStream *st = s->streams[stream_index];
+ int64_t seconds;
+
+ if (!s->bit_rate)
+ return -1;
+ if (sample_time < 0)
+ sample_time = 0;
+ seconds = av_rescale(sample_time, st->time_base.num, st->time_base.den);
+ url_fseek(&s->pb, (s->bit_rate * seconds) >> 3, SEEK_SET);
+ if (!mxf_read_sync(&s->pb, mxf_essence_element_key, 12))
+ return -1;
+
+ /* found KLV key */
+ url_fseek(&s->pb, -12, SEEK_CUR);
+ av_update_cur_dts(s, st, sample_time);
+ return 0;
+}
+
+AVInputFormat mxf_demuxer = {
+ "mxf",
+ "MXF format",
+ sizeof(MXFContext),
+ mxf_probe,
+ mxf_read_header,
+ mxf_read_packet,
+ mxf_read_close,
+ mxf_read_seek,
+};
diff --git a/contrib/ffmpeg/libavformat/nsvdec.c b/contrib/ffmpeg/libavformat/nsvdec.c
new file mode 100644
index 000000000..9a5fe97f8
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/nsvdec.c
@@ -0,0 +1,763 @@
+/*
+ * NSV demuxer
+ * 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
+ */
+#include "avformat.h"
+#include "riff.h"
+
+//#define DEBUG
+//#define DEBUG_DUMP_INDEX // XXX dumbdriving-271.nsv breaks with it commented!!
+//#define DEBUG_SEEK
+#define CHECK_SUBSEQUENT_NSVS
+//#define DISABLE_AUDIO
+
+/* max bytes to crawl for trying to resync
+ * stupid streaming servers don't start at chunk boundaries...
+ */
+#define NSV_MAX_RESYNC (500*1024)
+#define NSV_MAX_RESYNC_TRIES 300
+
+/*
+ * First version by Francois Revol - revol@free.fr
+ * References:
+ * (1) http://www.multimedia.cx/nsv-format.txt
+ * seems someone came to the same conclusions as me, and updated it:
+ * (2) http://www.stud.ktu.lt/~vitslav/nsv/nsv-format.txt
+ * http://www.stud.ktu.lt/~vitslav/nsv/
+ * official docs
+ * (3) http://ultravox.aol.com/NSVFormat.rtf
+ * Sample files:
+ * (S1) http://www.nullsoft.com/nsv/samples/
+ * http://www.nullsoft.com/nsv/samples/faster.nsv
+ * http://streamripper.sourceforge.net/openbb/read.php?TID=492&page=4
+ */
+
+/*
+ * notes on the header (Francois Revol):
+ *
+ * It is followed by strings, then a table, but nothing tells
+ * where the table begins according to (1). After checking faster.nsv,
+ * I believe NVSf[16-19] gives the size of the strings data
+ * (that is the offset of the data table after the header).
+ * After checking all samples from (S1) all confirms this.
+ *
+ * Then, about NSVf[12-15], faster.nsf has 179700. When veiwing it in VLC,
+ * I noticed there was about 1 NVSs chunk/s, so I ran
+ * strings faster.nsv | grep NSVs | wc -l
+ * which gave me 180. That leads me to think that NSVf[12-15] might be the
+ * file length in milliseconds.
+ * Let's try that:
+ * for f in *.nsv; do HTIME="$(od -t x4 "$f" | head -1 | sed 's/.* //')"; echo "'$f' $((0x$HTIME))s = $((0x$HTIME/1000/60)):$((0x$HTIME/1000%60))"; done
+ * except for nstrailer (which doesn't have an NSVf header), it repports correct time.
+ *
+ * nsvtrailer.nsv (S1) does not have any NSVf header, only NSVs chunks,
+ * so the header seems to not be mandatory. (for streaming).
+ *
+ * index slice duration check (excepts nsvtrailer.nsv):
+ * for f in [^n]*.nsv; do DUR="$(ffmpeg -i "$f" 2>/dev/null | grep 'NSVf duration' | cut -d ' ' -f 4)"; IC="$(ffmpeg -i "$f" 2>/dev/null | grep 'INDEX ENTRIES' | cut -d ' ' -f 2)"; echo "duration $DUR, slite time $(($DUR/$IC))"; done
+ */
+
+/*
+ * TODO:
+ * - handle timestamps !!!
+ * - use index
+ * - mime-type in probe()
+ * - seek
+ */
+
+#ifdef DEBUG
+#define PRINT(_v) printf _v
+#else
+#define PRINT(_v)
+#endif
+
+#if 0
+struct NSVf_header {
+ uint32_t chunk_tag; /* 'NSVf' */
+ uint32_t chunk_size;
+ uint32_t file_size; /* max 4GB ??? noone learns anything it seems :^) */
+ uint32_t file_length; //unknown1; /* what about MSB of file_size ? */
+ uint32_t info_strings_size; /* size of the info strings */ //unknown2;
+ uint32_t table_entries;
+ uint32_t table_entries_used; /* the left ones should be -1 */
+};
+
+struct NSVs_header {
+ uint32_t chunk_tag; /* 'NSVs' */
+ uint32_t v4cc; /* or 'NONE' */
+ uint32_t a4cc; /* or 'NONE' */
+ uint16_t vwidth; /* assert(vwidth%16==0) */
+ uint16_t vheight; /* assert(vheight%16==0) */
+ uint8_t framerate; /* value = (framerate&0x80)?frtable[frameratex0x7f]:framerate */
+ uint16_t unknown;
+};
+
+struct nsv_avchunk_header {
+ uint8_t vchunk_size_lsb;
+ uint16_t vchunk_size_msb; /* value = (vchunk_size_msb << 4) | (vchunk_size_lsb >> 4) */
+ uint16_t achunk_size;
+};
+
+struct nsv_pcm_header {
+ uint8_t bits_per_sample;
+ uint8_t channel_count;
+ uint16_t sample_rate;
+};
+#endif
+
+/* variation from avi.h */
+/*typedef struct CodecTag {
+ int id;
+ unsigned int tag;
+} CodecTag;*/
+
+/* tags */
+
+#define T_NSVF MKTAG('N', 'S', 'V', 'f') /* file header */
+#define T_NSVS MKTAG('N', 'S', 'V', 's') /* chunk header */
+#define T_TOC2 MKTAG('T', 'O', 'C', '2') /* extra index marker */
+#define T_NONE MKTAG('N', 'O', 'N', 'E') /* null a/v 4CC */
+#define T_SUBT MKTAG('S', 'U', 'B', 'T') /* subtitle aux data */
+#define T_ASYN MKTAG('A', 'S', 'Y', 'N') /* async a/v aux marker */
+#define T_KEYF MKTAG('K', 'E', 'Y', 'F') /* video keyframe aux marker (addition) */
+
+#define TB_NSVF MKBETAG('N', 'S', 'V', 'f')
+#define TB_NSVS MKBETAG('N', 'S', 'V', 's')
+
+/* hardcoded stream indices */
+#define NSV_ST_VIDEO 0
+#define NSV_ST_AUDIO 1
+#define NSV_ST_SUBT 2
+
+enum NSVStatus {
+ NSV_UNSYNC,
+ NSV_FOUND_NSVF,
+ NSV_HAS_READ_NSVF,
+ NSV_FOUND_NSVS,
+ NSV_HAS_READ_NSVS,
+ NSV_FOUND_BEEF,
+ NSV_GOT_VIDEO,
+ NSV_GOT_AUDIO,
+};
+
+typedef struct NSVStream {
+ int frame_offset; /* current frame (video) or byte (audio) counter
+ (used to compute the pts) */
+ int scale;
+ int rate;
+ int sample_size; /* audio only data */
+ int start;
+
+ int new_frame_offset; /* temporary storage (used during seek) */
+ int cum_len; /* temporary storage (used during seek) */
+} NSVStream;
+
+typedef struct {
+ int base_offset;
+ int NSVf_end;
+ uint32_t *nsvf_index_data;
+ int index_entries;
+ enum NSVStatus state;
+ AVPacket ahead[2]; /* [v, a] if .data is !NULL there is something */
+ /* cached */
+ int64_t duration;
+ uint32_t vtag, atag;
+ uint16_t vwidth, vheight;
+ int16_t avsync;
+ //DVDemuxContext* dv_demux;
+} NSVContext;
+
+static const CodecTag nsv_codec_video_tags[] = {
+ { CODEC_ID_VP3, MKTAG('V', 'P', '3', ' ') },
+ { CODEC_ID_VP3, MKTAG('V', 'P', '3', '0') },
+ { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') },
+ { CODEC_ID_VP5, MKTAG('V', 'P', '5', ' ') },
+ { CODEC_ID_VP5, MKTAG('V', 'P', '5', '0') },
+ { CODEC_ID_VP6, MKTAG('V', 'P', '6', '2') },
+/*
+ { CODEC_ID_VP4, MKTAG('V', 'P', '4', ' ') },
+ { CODEC_ID_VP4, MKTAG('V', 'P', '4', '0') },
+ { CODEC_ID_VP6, MKTAG('V', 'P', '6', ' ') },
+ { CODEC_ID_VP6, MKTAG('V', 'P', '6', '0') },
+ { CODEC_ID_VP6, MKTAG('V', 'P', '6', '1') },
+*/
+ { CODEC_ID_XVID, MKTAG('X', 'V', 'I', 'D') }, /* cf sample xvid decoder from nsv_codec_sdk.zip */
+ { CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', '3') },
+ { 0, 0 },
+};
+
+static const CodecTag nsv_codec_audio_tags[] = {
+ { CODEC_ID_MP3, MKTAG('M', 'P', '3', ' ') },
+ { CODEC_ID_AAC, MKTAG('A', 'A', 'C', ' ') },
+ { CODEC_ID_AAC, MKTAG('A', 'A', 'C', 'P') }, /* _CUTTED__MUXED_2 Heads - Out Of The City.nsv */
+ { CODEC_ID_PCM_U16LE, MKTAG('P', 'C', 'M', ' ') },
+ { 0, 0 },
+};
+
+//static int nsv_load_index(AVFormatContext *s);
+static int nsv_read_chunk(AVFormatContext *s, int fill_header);
+
+#ifdef DEBUG
+static void print_tag(const char *str, unsigned int tag, int size)
+{
+ printf("%s: tag=%c%c%c%c\n",
+ str, tag & 0xff,
+ (tag >> 8) & 0xff,
+ (tag >> 16) & 0xff,
+ (tag >> 24) & 0xff);
+}
+#endif
+
+/* try to find something we recognize, and set the state accordingly */
+static int nsv_resync(AVFormatContext *s)
+{
+ NSVContext *nsv = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ uint32_t v = 0;
+ int i;
+
+ PRINT(("%s(), offset = %"PRId64", state = %d\n", __FUNCTION__, url_ftell(pb), nsv->state));
+
+ //nsv->state = NSV_UNSYNC;
+
+ for (i = 0; i < NSV_MAX_RESYNC; i++) {
+ if (url_feof(pb)) {
+ PRINT(("NSV EOF\n"));
+ nsv->state = NSV_UNSYNC;
+ return -1;
+ }
+ v <<= 8;
+ v |= get_byte(pb);
+/*
+ if (i < 8) {
+ PRINT(("NSV resync: [%d] = %02x\n", i, v & 0x0FF));
+ }
+*/
+
+ if ((v & 0x0000ffff) == 0xefbe) { /* BEEF */
+ PRINT(("NSV resynced on BEEF after %d bytes\n", i+1));
+ nsv->state = NSV_FOUND_BEEF;
+ return 0;
+ }
+ /* we read as big endian, thus the MK*BE* */
+ if (v == TB_NSVF) { /* NSVf */
+ PRINT(("NSV resynced on NSVf after %d bytes\n", i+1));
+ nsv->state = NSV_FOUND_NSVF;
+ return 0;
+ }
+ if (v == MKBETAG('N', 'S', 'V', 's')) { /* NSVs */
+ PRINT(("NSV resynced on NSVs after %d bytes\n", i+1));
+ nsv->state = NSV_FOUND_NSVS;
+ return 0;
+ }
+
+ }
+ PRINT(("NSV sync lost\n"));
+ return -1;
+}
+
+static int nsv_parse_NSVf_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ NSVContext *nsv = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ unsigned int file_size, size;
+ int64_t duration;
+ int strings_size;
+ int table_entries;
+ int table_entries_used;
+
+ PRINT(("%s()\n", __FUNCTION__));
+
+ nsv->state = NSV_UNSYNC; /* in case we fail */
+
+ size = get_le32(pb);
+ if (size < 28)
+ return -1;
+ nsv->NSVf_end = size;
+
+ //s->file_size = (uint32_t)get_le32(pb);
+ file_size = (uint32_t)get_le32(pb);
+ PRINT(("NSV NSVf chunk_size %u\n", size));
+ PRINT(("NSV NSVf file_size %u\n", file_size));
+
+ nsv->duration = duration = get_le32(pb); /* in ms */
+ PRINT(("NSV NSVf duration %"PRId64" ms\n", duration));
+ // XXX: store it in AVStreams
+
+ strings_size = get_le32(pb);
+ table_entries = get_le32(pb);
+ table_entries_used = get_le32(pb);
+ PRINT(("NSV NSVf info-strings size: %d, table entries: %d, bis %d\n",
+ strings_size, table_entries, table_entries_used));
+ if (url_feof(pb))
+ return -1;
+
+ PRINT(("NSV got header; filepos %"PRId64"\n", url_ftell(pb)));
+
+ if (strings_size > 0) {
+ char *strings; /* last byte will be '\0' to play safe with str*() */
+ char *p, *endp;
+ char *token, *value;
+ char quote;
+
+ p = strings = av_mallocz(strings_size + 1);
+ endp = strings + strings_size;
+ get_buffer(pb, strings, strings_size);
+ while (p < endp) {
+ while (*p == ' ')
+ p++; /* strip out spaces */
+ if (p >= endp-2)
+ break;
+ token = p;
+ p = strchr(p, '=');
+ if (!p || p >= endp-2)
+ break;
+ *p++ = '\0';
+ quote = *p++;
+ value = p;
+ p = strchr(p, quote);
+ if (!p || p >= endp)
+ break;
+ *p++ = '\0';
+ PRINT(("NSV NSVf INFO: %s='%s'\n", token, value));
+ if (!strcmp(token, "ASPECT")) {
+ /* don't care */
+ } else if (!strcmp(token, "CREATOR") || !strcmp(token, "Author")) {
+ strncpy(s->author, value, 512-1);
+ } else if (!strcmp(token, "Copyright")) {
+ strncpy(s->copyright, value, 512-1);
+ } else if (!strcmp(token, "TITLE") || !strcmp(token, "Title")) {
+ strncpy(s->title, value, 512-1);
+ }
+ }
+ av_free(strings);
+ }
+ if (url_feof(pb))
+ return -1;
+
+ PRINT(("NSV got infos; filepos %"PRId64"\n", url_ftell(pb)));
+
+ if (table_entries_used > 0) {
+ nsv->index_entries = table_entries_used;
+ if((unsigned)table_entries >= UINT_MAX / sizeof(uint32_t))
+ return -1;
+ nsv->nsvf_index_data = av_malloc(table_entries * sizeof(uint32_t));
+#warning "FIXME: Byteswap buffer as needed"
+ get_buffer(pb, (unsigned char *)nsv->nsvf_index_data, table_entries * sizeof(uint32_t));
+ }
+
+ PRINT(("NSV got index; filepos %"PRId64"\n", url_ftell(pb)));
+
+#ifdef DEBUG_DUMP_INDEX
+#define V(v) ((v<0x20 || v > 127)?'.':v)
+ /* dump index */
+ PRINT(("NSV %d INDEX ENTRIES:\n", table_entries));
+ PRINT(("NSV [dataoffset][fileoffset]\n", table_entries));
+ for (i = 0; i < table_entries; i++) {
+ unsigned char b[8];
+ url_fseek(pb, size + nsv->nsvf_index_data[i], SEEK_SET);
+ get_buffer(pb, b, 8);
+ PRINT(("NSV [0x%08lx][0x%08lx]: %02x %02x %02x %02x %02x %02x %02x %02x"
+ "%c%c%c%c%c%c%c%c\n",
+ nsv->nsvf_index_data[i], size + nsv->nsvf_index_data[i],
+ b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
+ V(b[0]), V(b[1]), V(b[2]), V(b[3]), V(b[4]), V(b[5]), V(b[6]), V(b[7]) ));
+ }
+ //url_fseek(pb, size, SEEK_SET); /* go back to end of header */
+#undef V
+#endif
+
+ url_fseek(pb, nsv->base_offset + size, SEEK_SET); /* required for dumbdriving-271.nsv (2 extra bytes) */
+
+ if (url_feof(pb))
+ return -1;
+ nsv->state = NSV_HAS_READ_NSVF;
+ return 0;
+}
+
+static int nsv_parse_NSVs_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ NSVContext *nsv = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ uint32_t vtag, atag;
+ uint16_t vwidth, vheight;
+ AVRational framerate;
+ int i;
+ AVStream *st;
+ NSVStream *nst;
+ PRINT(("%s()\n", __FUNCTION__));
+
+ vtag = get_le32(pb);
+ atag = get_le32(pb);
+ vwidth = get_le16(pb);
+ vheight = get_le16(pb);
+ i = get_byte(pb);
+
+ PRINT(("NSV NSVs framerate code %2x\n", i));
+ if(i&0x80) { /* odd way of giving native framerates from docs */
+ int t=(i & 0x7F)>>2;
+ if(t<16) framerate = (AVRational){1, t+1};
+ else framerate = (AVRational){t-15, 1};
+
+ if(i&1){
+ framerate.num *= 1000;
+ framerate.den *= 1001;
+ }
+
+ if((i&3)==3) framerate.num *= 24;
+ else if((i&3)==2) framerate.num *= 25;
+ else framerate.num *= 30;
+ }
+ else
+ framerate= (AVRational){i, 1};
+
+ nsv->avsync = get_le16(pb);
+#ifdef DEBUG
+ print_tag("NSV NSVs vtag", vtag, 0);
+ print_tag("NSV NSVs atag", atag, 0);
+ PRINT(("NSV NSVs vsize %dx%d\n", vwidth, vheight));
+#endif
+
+ /* XXX change to ap != NULL ? */
+ if (s->nb_streams == 0) { /* streams not yet published, let's do that */
+ nsv->vtag = vtag;
+ nsv->atag = atag;
+ nsv->vwidth = vwidth;
+ nsv->vheight = vwidth;
+ if (vtag != T_NONE) {
+ st = av_new_stream(s, NSV_ST_VIDEO);
+ if (!st)
+ goto fail;
+
+ nst = av_mallocz(sizeof(NSVStream));
+ if (!nst)
+ goto fail;
+ st->priv_data = nst;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_tag = vtag;
+ st->codec->codec_id = codec_get_id(nsv_codec_video_tags, vtag);
+ st->codec->width = vwidth;
+ st->codec->height = vheight;
+ st->codec->bits_per_sample = 24; /* depth XXX */
+
+ av_set_pts_info(st, 64, framerate.den, framerate.num);
+ st->start_time = 0;
+ st->duration = av_rescale(nsv->duration, framerate.num, 1000*framerate.den);
+ }
+ if (atag != T_NONE) {
+#ifndef DISABLE_AUDIO
+ st = av_new_stream(s, NSV_ST_AUDIO);
+ if (!st)
+ goto fail;
+
+ nst = av_mallocz(sizeof(NSVStream));
+ if (!nst)
+ goto fail;
+ st->priv_data = nst;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_tag = atag;
+ st->codec->codec_id = codec_get_id(nsv_codec_audio_tags, atag);
+
+ st->need_parsing = 1; /* for PCM we will read a chunk later and put correct info */
+
+ /* set timebase to common denominator of ms and framerate */
+ av_set_pts_info(st, 64, 1, framerate.num*1000);
+ st->start_time = 0;
+ st->duration = (int64_t)nsv->duration * framerate.num;
+#endif
+ }
+#ifdef CHECK_SUBSEQUENT_NSVS
+ } else {
+ if (nsv->vtag != vtag || nsv->atag != atag || nsv->vwidth != vwidth || nsv->vheight != vwidth) {
+ PRINT(("NSV NSVs header values differ from the first one!!!\n"));
+ //return -1;
+ }
+#endif /* CHECK_SUBSEQUENT_NSVS */
+ }
+
+ nsv->state = NSV_HAS_READ_NSVS;
+ return 0;
+fail:
+ /* XXX */
+ nsv->state = NSV_UNSYNC;
+ return -1;
+}
+
+static int nsv_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ NSVContext *nsv = s->priv_data;
+ int i, err;
+
+ PRINT(("%s()\n", __FUNCTION__));
+ PRINT(("filename '%s'\n", s->filename));
+
+ nsv->state = NSV_UNSYNC;
+ nsv->ahead[0].data = nsv->ahead[1].data = NULL;
+
+ for (i = 0; i < NSV_MAX_RESYNC_TRIES; i++) {
+ if (nsv_resync(s) < 0)
+ return -1;
+ if (nsv->state == NSV_FOUND_NSVF)
+ err = nsv_parse_NSVf_header(s, ap);
+ /* we need the first NSVs also... */
+ if (nsv->state == NSV_FOUND_NSVS) {
+ err = nsv_parse_NSVs_header(s, ap);
+ break; /* we just want the first one */
+ }
+ }
+ if (s->nb_streams < 1) /* no luck so far */
+ return -1;
+ /* now read the first chunk, so we can attempt to decode more info */
+ err = nsv_read_chunk(s, 1);
+
+ PRINT(("parsed header\n"));
+ return 0;
+}
+
+static int nsv_read_chunk(AVFormatContext *s, int fill_header)
+{
+ NSVContext *nsv = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVStream *st[2] = {NULL, NULL};
+ NSVStream *nst;
+ AVPacket *pkt;
+ int i, err = 0;
+ uint8_t auxcount; /* number of aux metadata, also 4 bits of vsize */
+ uint32_t vsize;
+ uint16_t asize;
+ uint16_t auxsize;
+ uint32_t auxtag;
+
+ PRINT(("%s(%d)\n", __FUNCTION__, fill_header));
+
+ if (nsv->ahead[0].data || nsv->ahead[1].data)
+ return 0; //-1; /* hey! eat what you've in your plate first! */
+
+null_chunk_retry:
+ if (url_feof(pb))
+ return -1;
+
+ for (i = 0; i < NSV_MAX_RESYNC_TRIES && nsv->state < NSV_FOUND_NSVS && !err; i++)
+ err = nsv_resync(s);
+ if (err < 0)
+ return err;
+ if (nsv->state == NSV_FOUND_NSVS)
+ err = nsv_parse_NSVs_header(s, NULL);
+ if (err < 0)
+ return err;
+ if (nsv->state != NSV_HAS_READ_NSVS && nsv->state != NSV_FOUND_BEEF)
+ return -1;
+
+ auxcount = get_byte(pb);
+ vsize = get_le16(pb);
+ asize = get_le16(pb);
+ vsize = (vsize << 4) | (auxcount >> 4);
+ auxcount &= 0x0f;
+ PRINT(("NSV CHUNK %d aux, %u bytes video, %d bytes audio\n", auxcount, vsize, asize));
+ /* skip aux stuff */
+ for (i = 0; i < auxcount; i++) {
+ auxsize = get_le16(pb);
+ auxtag = get_le32(pb);
+ PRINT(("NSV aux data: '%c%c%c%c', %d bytes\n",
+ (auxtag & 0x0ff),
+ ((auxtag >> 8) & 0x0ff),
+ ((auxtag >> 16) & 0x0ff),
+ ((auxtag >> 24) & 0x0ff),
+ auxsize));
+ url_fskip(pb, auxsize);
+ vsize -= auxsize + sizeof(uint16_t) + sizeof(uint32_t); /* that's becoming braindead */
+ }
+
+ if (url_feof(pb))
+ return -1;
+ if (!vsize && !asize) {
+ nsv->state = NSV_UNSYNC;
+ goto null_chunk_retry;
+ }
+
+ /* map back streams to v,a */
+ if (s->streams[0])
+ st[s->streams[0]->id] = s->streams[0];
+ if (s->streams[1])
+ st[s->streams[1]->id] = s->streams[1];
+
+ if (vsize/* && st[NSV_ST_VIDEO]*/) {
+ nst = st[NSV_ST_VIDEO]->priv_data;
+ pkt = &nsv->ahead[NSV_ST_VIDEO];
+ av_get_packet(pb, pkt, vsize);
+ pkt->stream_index = st[NSV_ST_VIDEO]->index;//NSV_ST_VIDEO;
+ pkt->dts = nst->frame_offset++;
+ pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */
+/*
+ for (i = 0; i < MIN(8, vsize); i++)
+ PRINT(("NSV video: [%d] = %02x\n", i, pkt->data[i]));
+*/
+ }
+ if (asize/*st[NSV_ST_AUDIO]*/) {
+ nst = st[NSV_ST_AUDIO]->priv_data;
+ pkt = &nsv->ahead[NSV_ST_AUDIO];
+ /* read raw audio specific header on the first audio chunk... */
+ /* on ALL audio chunks ?? seems so! */
+ if (asize && st[NSV_ST_AUDIO]->codec->codec_tag == MKTAG('P', 'C', 'M', ' ')/* && fill_header*/) {
+ uint8_t bps;
+ uint8_t channels;
+ uint16_t samplerate;
+ bps = get_byte(pb);
+ channels = get_byte(pb);
+ samplerate = get_le16(pb);
+ asize-=4;
+ PRINT(("NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate));
+ if (fill_header) {
+ st[NSV_ST_AUDIO]->need_parsing = 0; /* we know everything */
+ if (bps != 16) {
+ PRINT(("NSV AUDIO bit/sample != 16 (%d)!!!\n", bps));
+ }
+ bps /= channels; // ???
+ if (bps == 8)
+ st[NSV_ST_AUDIO]->codec->codec_id = CODEC_ID_PCM_U8;
+ samplerate /= 4;/* UGH ??? XXX */
+ channels = 1;
+ st[NSV_ST_AUDIO]->codec->channels = channels;
+ st[NSV_ST_AUDIO]->codec->sample_rate = samplerate;
+ PRINT(("NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate));
+ }
+ }
+ av_get_packet(pb, pkt, asize);
+ pkt->stream_index = st[NSV_ST_AUDIO]->index;//NSV_ST_AUDIO;
+ pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */
+ if( nsv->state == NSV_HAS_READ_NSVS && st[NSV_ST_VIDEO] ) {
+ /* on a nsvs frame we have new information on a/v sync */
+ pkt->dts = (((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset-1);
+ pkt->dts *= (int64_t)1000 * st[NSV_ST_VIDEO]->time_base.num;
+ pkt->dts += (int64_t)nsv->avsync * st[NSV_ST_VIDEO]->time_base.den;
+ PRINT(("NSV AUDIO: sync:%d, dts:%"PRId64, nsv->avsync, pkt->dts));
+ }
+ nst->frame_offset++;
+ }
+
+ nsv->state = NSV_UNSYNC;
+ return 0;
+}
+
+
+static int nsv_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ NSVContext *nsv = s->priv_data;
+ int i, err = 0;
+
+ PRINT(("%s()\n", __FUNCTION__));
+
+ /* in case we don't already have something to eat ... */
+ if (nsv->ahead[0].data == NULL && nsv->ahead[1].data == NULL)
+ err = nsv_read_chunk(s, 0);
+ if (err < 0)
+ return err;
+
+ /* now pick one of the plates */
+ for (i = 0; i < 2; i++) {
+ if (nsv->ahead[i].data) {
+ PRINT(("%s: using cached packet[%d]\n", __FUNCTION__, i));
+ /* avoid the cost of new_packet + memcpy(->data) */
+ memcpy(pkt, &nsv->ahead[i], sizeof(AVPacket));
+ nsv->ahead[i].data = NULL; /* we ate that one */
+ return pkt->size;
+ }
+ }
+
+ /* this restaurant is not approvisionned :^] */
+ return -1;
+}
+
+static int nsv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
+{
+#if 0
+ NSVContext *avi = s->priv_data;
+ AVStream *st;
+ NSVStream *ast;
+ int frame_number, i;
+ int64_t pos;
+#endif
+
+ return -1;
+}
+
+static int nsv_read_close(AVFormatContext *s)
+{
+/* int i; */
+ NSVContext *nsv = s->priv_data;
+
+ if (nsv->index_entries)
+ av_free(nsv->nsvf_index_data);
+
+#if 0
+
+ for(i=0;i<s->nb_streams;i++) {
+ AVStream *st = s->streams[i];
+ NSVStream *ast = st->priv_data;
+ if(ast){
+ av_free(ast->index_entries);
+ av_free(ast);
+ }
+ av_free(st->codec->palctrl);
+ }
+
+#endif
+ return 0;
+}
+
+static int nsv_probe(AVProbeData *p)
+{
+ int i;
+// PRINT(("nsv_probe(), buf_size %d\n", p->buf_size));
+ /* check file header */
+ if (p->buf_size <= 32)
+ return 0;
+ if (p->buf[0] == 'N' && p->buf[1] == 'S' &&
+ p->buf[2] == 'V' && p->buf[3] == 'f')
+ return AVPROBE_SCORE_MAX;
+ /* streamed files might not have any header */
+ if (p->buf[0] == 'N' && p->buf[1] == 'S' &&
+ p->buf[2] == 'V' && p->buf[3] == 's')
+ return AVPROBE_SCORE_MAX;
+ /* XXX: do streamed files always start at chunk boundary ?? */
+ /* or do we need to search NSVs in the byte stream ? */
+ /* seems the servers don't bother starting clean chunks... */
+ /* sometimes even the first header is at 9KB or something :^) */
+ for (i = 1; i < p->buf_size - 3; i++) {
+ if (p->buf[i+0] == 'N' && p->buf[i+1] == 'S' &&
+ p->buf[i+2] == 'V' && p->buf[i+3] == 's')
+ return AVPROBE_SCORE_MAX-20;
+ }
+ /* so we'll have more luck on extension... */
+ if (match_ext(p->filename, "nsv"))
+ return AVPROBE_SCORE_MAX-20;
+ /* FIXME: add mime-type check */
+ return 0;
+}
+
+AVInputFormat nsv_demuxer = {
+ "nsv",
+ "NullSoft Video format",
+ sizeof(NSVContext),
+ nsv_probe,
+ nsv_read_header,
+ nsv_read_packet,
+ nsv_read_close,
+ nsv_read_seek,
+};
diff --git a/contrib/ffmpeg/libavformat/nut.c b/contrib/ffmpeg/libavformat/nut.c
new file mode 100644
index 000000000..df64caf15
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/nut.c
@@ -0,0 +1,1457 @@
+/*
+ * "NUT" Container Format muxer and demuxer (DRAFT-200403??)
+ * Copyright (c) 2003 Alex Beregszaszi
+ * 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
+ *
+ *
+ * Visit the official site at http://www.nut.hu/
+ *
+ */
+
+/*
+ * TODO:
+ * - index writing
+ * - index packet reading support
+*/
+
+//#define DEBUG 1
+
+#include <limits.h>
+#include "avformat.h"
+#include "mpegaudio.h"
+#include "riff.h"
+#include "adler32.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+//#define TRACE
+
+//from /dev/random
+
+#define MAIN_STARTCODE (0x7A561F5F04ADULL + (((uint64_t)('N'<<8) + 'M')<<48))
+#define STREAM_STARTCODE (0x11405BF2F9DBULL + (((uint64_t)('N'<<8) + 'S')<<48))
+#define KEYFRAME_STARTCODE (0xE4ADEECA4569ULL + (((uint64_t)('N'<<8) + 'K')<<48))
+#define INDEX_STARTCODE (0xDD672F23E64EULL + (((uint64_t)('N'<<8) + 'X')<<48))
+#define INFO_STARTCODE (0xAB68B596BA78ULL + (((uint64_t)('N'<<8) + 'I')<<48))
+
+#define ID_STRING "nut/multimedia container\0"
+
+#define MAX_DISTANCE (1024*16-1)
+#define MAX_SHORT_DISTANCE (1024*4-1)
+
+#define FLAG_DATA_SIZE 1
+#define FLAG_KEY_FRAME 2
+#define FLAG_INVALID 4
+
+typedef struct {
+ uint8_t flags;
+ uint8_t stream_id_plus1;
+ uint16_t size_mul;
+ uint16_t size_lsb;
+ int16_t timestamp_delta;
+ uint8_t reserved_count;
+} FrameCode;
+
+typedef struct {
+ int last_key_frame;
+ int msb_timestamp_shift;
+ int rate_num;
+ int rate_den;
+ int64_t last_pts;
+ int64_t last_sync_pos; ///<pos of last 1/2 type frame
+ int decode_delay;
+} StreamContext;
+
+typedef struct {
+ AVFormatContext *avf;
+ int written_packet_size;
+ int64_t packet_start[3]; //0-> startcode less, 1-> short startcode 2-> long startcodes
+ FrameCode frame_code[256];
+ unsigned int stream_count;
+ uint64_t next_startcode; ///< stores the next startcode if it has alraedy been parsed but the stream isnt seekable
+ StreamContext *stream;
+ int max_distance;
+ int max_short_distance;
+ int rate_num;
+ int rate_den;
+ int short_startcode;
+} NUTContext;
+
+static char *info_table[][2]={
+ {NULL , NULL }, // end
+ {NULL , NULL },
+ {NULL , "UTF8"},
+ {NULL , "v"},
+ {NULL , "s"},
+ {"StreamId" , "v"},
+ {"SegmentId" , "v"},
+ {"StartTimestamp" , "v"},
+ {"EndTimestamp" , "v"},
+ {"Author" , "UTF8"},
+ {"Title" , "UTF8"},
+ {"Description" , "UTF8"},
+ {"Copyright" , "UTF8"},
+ {"Encoder" , "UTF8"},
+ {"Keyword" , "UTF8"},
+ {"Cover" , "JPEG"},
+ {"Cover" , "PNG"},
+};
+
+static void update(NUTContext *nut, int stream_index, int64_t frame_start, int frame_type, int frame_code, int key_frame, int size, int64_t pts){
+ StreamContext *stream= &nut->stream[stream_index];
+
+ stream->last_key_frame= key_frame;
+ nut->packet_start[ frame_type ]= frame_start;
+ stream->last_pts= pts;
+}
+
+static void reset(AVFormatContext *s, int64_t global_ts){
+ NUTContext *nut = s->priv_data;
+ int i;
+
+ for(i=0; i<s->nb_streams; i++){
+ StreamContext *stream= &nut->stream[i];
+
+ stream->last_key_frame= 1;
+
+ stream->last_pts= av_rescale(global_ts, stream->rate_num*(int64_t)nut->rate_den, stream->rate_den*(int64_t)nut->rate_num);
+ }
+}
+
+static void build_frame_code(AVFormatContext *s){
+ NUTContext *nut = s->priv_data;
+ int key_frame, index, pred, stream_id;
+ int start=0;
+ int end= 255;
+ int keyframe_0_esc= s->nb_streams > 2;
+ int pred_table[10];
+
+ if(keyframe_0_esc){
+ /* keyframe = 0 escape */
+ FrameCode *ft= &nut->frame_code[start];
+ ft->flags= FLAG_DATA_SIZE;
+ ft->stream_id_plus1= 0;
+ ft->size_mul=1;
+ ft->timestamp_delta=0;
+ start++;
+ }
+
+ for(stream_id= 0; stream_id<s->nb_streams; stream_id++){
+ int start2= start + (end-start)*stream_id / s->nb_streams;
+ int end2 = start + (end-start)*(stream_id+1) / s->nb_streams;
+ AVCodecContext *codec = s->streams[stream_id]->codec;
+ int is_audio= codec->codec_type == CODEC_TYPE_AUDIO;
+ int intra_only= /*codec->intra_only || */is_audio;
+ int pred_count;
+
+ for(key_frame=0; key_frame<2; key_frame++){
+ if(intra_only && keyframe_0_esc && key_frame==0)
+ continue;
+
+ {
+ FrameCode *ft= &nut->frame_code[start2];
+ ft->flags= FLAG_KEY_FRAME*key_frame;
+ ft->flags|= FLAG_DATA_SIZE;
+ ft->stream_id_plus1= stream_id + 1;
+ ft->size_mul=1;
+ ft->timestamp_delta=0;
+ start2++;
+ }
+ }
+
+ key_frame= intra_only;
+#if 1
+ if(is_audio){
+ int frame_bytes= codec->frame_size*(int64_t)codec->bit_rate / (8*codec->sample_rate);
+ int pts;
+ for(pts=0; pts<2; pts++){
+ for(pred=0; pred<2; pred++){
+ FrameCode *ft= &nut->frame_code[start2];
+ ft->flags= FLAG_KEY_FRAME*key_frame;
+ ft->stream_id_plus1= stream_id + 1;
+ ft->size_mul=frame_bytes + 2;
+ ft->size_lsb=frame_bytes + pred;
+ ft->timestamp_delta=pts;
+ start2++;
+ }
+ }
+ }else{
+ FrameCode *ft= &nut->frame_code[start2];
+ ft->flags= FLAG_KEY_FRAME | FLAG_DATA_SIZE;
+ ft->stream_id_plus1= stream_id + 1;
+ ft->size_mul=1;
+ ft->timestamp_delta=1;
+ start2++;
+ }
+#endif
+
+ if(codec->has_b_frames){
+ pred_count=5;
+ pred_table[0]=-2;
+ pred_table[1]=-1;
+ pred_table[2]=1;
+ pred_table[3]=3;
+ pred_table[4]=4;
+ }else if(codec->codec_id == CODEC_ID_VORBIS){
+ pred_count=3;
+ pred_table[0]=2;
+ pred_table[1]=9;
+ pred_table[2]=16;
+ }else{
+ pred_count=1;
+ pred_table[0]=1;
+ }
+
+ for(pred=0; pred<pred_count; pred++){
+ int start3= start2 + (end2-start2)*pred / pred_count;
+ int end3 = start2 + (end2-start2)*(pred+1) / pred_count;
+
+ for(index=start3; index<end3; index++){
+ FrameCode *ft= &nut->frame_code[index];
+ ft->flags= FLAG_KEY_FRAME*key_frame;
+ ft->flags|= FLAG_DATA_SIZE;
+ ft->stream_id_plus1= stream_id + 1;
+//FIXME use single byte size and pred from last
+ ft->size_mul= end3-start3;
+ ft->size_lsb= index - start3;
+ ft->timestamp_delta= pred_table[pred];
+ }
+ }
+ }
+ memmove(&nut->frame_code['N'+1], &nut->frame_code['N'], sizeof(FrameCode)*(255-'N'));
+ nut->frame_code['N'].flags= FLAG_INVALID;
+}
+
+static uint64_t get_v(ByteIOContext *bc)
+{
+ uint64_t val = 0;
+
+ for(;;)
+ {
+ int tmp = get_byte(bc);
+
+ if (tmp&0x80)
+ val= (val<<7) + tmp - 0x80;
+ else{
+//av_log(NULL, AV_LOG_DEBUG, "get_v()= %"PRId64"\n", (val<<7) + tmp);
+ return (val<<7) + tmp;
+ }
+ }
+ return -1;
+}
+
+static int get_str(ByteIOContext *bc, char *string, unsigned int maxlen){
+ unsigned int len= get_v(bc);
+
+ if(len && maxlen)
+ get_buffer(bc, string, FFMIN(len, maxlen));
+ while(len > maxlen){
+ get_byte(bc);
+ len--;
+ }
+
+ if(maxlen)
+ string[FFMIN(len, maxlen-1)]= 0;
+
+ if(maxlen == len)
+ return -1;
+ else
+ return 0;
+}
+
+static int64_t get_s(ByteIOContext *bc){
+ int64_t v = get_v(bc) + 1;
+
+ if (v&1) return -(v>>1);
+ else return (v>>1);
+}
+
+static uint64_t get_vb(ByteIOContext *bc){
+ uint64_t val=0;
+ unsigned int i= get_v(bc);
+
+ if(i>8)
+ return UINT64_MAX;
+
+ while(i--)
+ val = (val<<8) + get_byte(bc);
+
+//av_log(NULL, AV_LOG_DEBUG, "get_vb()= %"PRId64"\n", val);
+ return val;
+}
+
+#ifdef TRACE
+static inline uint64_t get_v_trace(ByteIOContext *bc, char *file, char *func, int line){
+ uint64_t v= get_v(bc);
+
+ printf("get_v %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
+ return v;
+}
+
+static inline int64_t get_s_trace(ByteIOContext *bc, char *file, char *func, int line){
+ int64_t v= get_s(bc);
+
+ printf("get_s %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
+ return v;
+}
+
+static inline uint64_t get_vb_trace(ByteIOContext *bc, char *file, char *func, int line){
+ uint64_t v= get_vb(bc);
+
+ printf("get_vb %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
+ return v;
+}
+#define get_v(bc) get_v_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
+#define get_s(bc) get_s_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
+#define get_vb(bc) get_vb_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
+#endif
+
+
+static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int calculate_checksum)
+{
+ int64_t start, size;
+ start= url_ftell(bc) - 8;
+
+ size= get_v(bc);
+
+ init_checksum(bc, calculate_checksum ? av_adler32_update : NULL, 1);
+
+ nut->packet_start[2] = start;
+ nut->written_packet_size= size;
+
+ return size;
+}
+
+static int check_checksum(ByteIOContext *bc){
+ unsigned long checksum= get_checksum(bc);
+ return checksum != get_be32(bc);
+}
+
+/**
+ *
+ */
+static int get_length(uint64_t val){
+ int i;
+
+ for (i=7; val>>i; i+=7);
+
+ return i;
+}
+
+static uint64_t find_any_startcode(ByteIOContext *bc, int64_t pos){
+ uint64_t state=0;
+
+ if(pos >= 0)
+ url_fseek(bc, pos, SEEK_SET); //note, this may fail if the stream isnt seekable, but that shouldnt matter, as in this case we simply start where we are currently
+
+ while(!url_feof(bc)){
+ state= (state<<8) | get_byte(bc);
+ if((state>>56) != 'N')
+ continue;
+ switch(state){
+ case MAIN_STARTCODE:
+ case STREAM_STARTCODE:
+ case KEYFRAME_STARTCODE:
+ case INFO_STARTCODE:
+ case INDEX_STARTCODE:
+ return state;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * find the given startcode.
+ * @param code the startcode
+ * @param pos the start position of the search, or -1 if the current position
+ * @returns the position of the startcode or -1 if not found
+ */
+static int64_t find_startcode(ByteIOContext *bc, uint64_t code, int64_t pos){
+ for(;;){
+ uint64_t startcode= find_any_startcode(bc, pos);
+ if(startcode == code)
+ return url_ftell(bc) - 8;
+ else if(startcode == 0)
+ return -1;
+ pos=-1;
+ }
+}
+
+static int64_t lsb2full(StreamContext *stream, int64_t lsb){
+ int64_t mask = (1<<stream->msb_timestamp_shift)-1;
+ int64_t delta= stream->last_pts - mask/2;
+ return ((lsb - delta)&mask) + delta;
+}
+
+#ifdef CONFIG_MUXERS
+
+static void put_v(ByteIOContext *bc, uint64_t val)
+{
+ int i;
+
+//av_log(NULL, AV_LOG_DEBUG, "put_v()= %"PRId64"\n", val);
+ val &= 0x7FFFFFFFFFFFFFFFULL; // FIXME can only encode upto 63 bits currently
+ i= get_length(val);
+
+ for (i-=7; i>0; i-=7){
+ put_byte(bc, 0x80 | (val>>i));
+ }
+
+ put_byte(bc, val&0x7f);
+}
+
+/**
+ * stores a string as vb.
+ */
+static void put_str(ByteIOContext *bc, const char *string){
+ int len= strlen(string);
+
+ put_v(bc, len);
+ put_buffer(bc, string, len);
+}
+
+static void put_s(ByteIOContext *bc, int64_t val){
+ if (val<=0) put_v(bc, -2*val );
+ else put_v(bc, 2*val-1);
+}
+
+static void put_vb(ByteIOContext *bc, uint64_t val){
+ int i;
+
+ for (i=8; val>>i; i+=8);
+
+ put_v(bc, i>>3);
+ for(i-=8; i>=0; i-=8)
+ put_byte(bc, (val>>i)&0xFF);
+}
+
+#ifdef TRACE
+static inline void put_v_trace(ByteIOContext *bc, uint64_t v, char *file, char *func, int line){
+ printf("get_v %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
+
+ put_v(bc, v);
+}
+
+static inline void put_s_trace(ByteIOContext *bc, int64_t v, char *file, char *func, int line){
+ printf("get_s %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
+
+ put_s(bc, v);
+}
+
+static inline void put_vb_trace(ByteIOContext *bc, uint64_t v, char *file, char *func, int line){
+ printf("get_vb %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
+
+ put_vb(bc, v);
+}
+#define put_v(bc, v) put_v_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)
+#define put_s(bc, v) put_s_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)
+#define put_vb(bc, v) put_vb_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)
+#endif
+
+static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size, int calculate_checksum)
+{
+ put_flush_packet(bc);
+ nut->packet_start[2]= url_ftell(bc) - 8;
+ nut->written_packet_size = max_size;
+
+ /* packet header */
+ put_v(bc, nut->written_packet_size); /* forward ptr */
+
+ if(calculate_checksum)
+ init_checksum(bc, av_adler32_update, 1);
+
+ return 0;
+}
+
+/**
+ *
+ * must not be called more then once per packet
+ */
+static int update_packetheader(NUTContext *nut, ByteIOContext *bc, int additional_size, int calculate_checksum){
+ int64_t start= nut->packet_start[2];
+ int64_t cur= url_ftell(bc);
+ int size= cur - start - get_length(nut->written_packet_size)/7 - 8;
+
+ if(calculate_checksum)
+ size += 4;
+
+ if(size != nut->written_packet_size){
+ int i;
+
+ assert( size <= nut->written_packet_size );
+
+ url_fseek(bc, start + 8, SEEK_SET);
+ for(i=get_length(size); i < get_length(nut->written_packet_size); i+=7)
+ put_byte(bc, 0x80);
+ put_v(bc, size);
+
+ url_fseek(bc, cur, SEEK_SET);
+ nut->written_packet_size= size; //FIXME may fail if multiple updates with differing sizes, as get_length may differ
+
+ if(calculate_checksum)
+ put_be32(bc, get_checksum(bc));
+ }
+
+ return 0;
+}
+
+static int nut_write_header(AVFormatContext *s)
+{
+ NUTContext *nut = s->priv_data;
+ ByteIOContext *bc = &s->pb;
+ AVCodecContext *codec;
+ int i, j, tmp_time, tmp_flags,tmp_stream, tmp_mul, tmp_size, tmp_fields;
+
+ if (strcmp(s->filename, "./data/b-libav.nut")) {
+ av_log(s, AV_LOG_ERROR, " libavformat NUT is non-compliant and disabled\n");
+ return -1;
+ }
+
+ nut->avf= s;
+
+ nut->stream =
+ av_mallocz(sizeof(StreamContext)*s->nb_streams);
+
+
+ put_buffer(bc, ID_STRING, strlen(ID_STRING));
+ put_byte(bc, 0);
+ nut->packet_start[2]= url_ftell(bc);
+
+ /* main header */
+ put_be64(bc, MAIN_STARTCODE);
+ put_packetheader(nut, bc, 120+5*256, 1);
+ put_v(bc, 2); /* version */
+ put_v(bc, s->nb_streams);
+ put_v(bc, MAX_DISTANCE);
+ put_v(bc, MAX_SHORT_DISTANCE);
+
+ put_v(bc, nut->rate_num=1);
+ put_v(bc, nut->rate_den=2);
+ put_v(bc, nut->short_startcode=0x4EFE79);
+
+ build_frame_code(s);
+ assert(nut->frame_code['N'].flags == FLAG_INVALID);
+
+ tmp_time= tmp_flags= tmp_stream= tmp_mul= tmp_size= /*tmp_res=*/ INT_MAX;
+ for(i=0; i<256;){
+ tmp_fields=0;
+ tmp_size= 0;
+ if(tmp_time != nut->frame_code[i].timestamp_delta) tmp_fields=1;
+ if(tmp_mul != nut->frame_code[i].size_mul ) tmp_fields=2;
+ if(tmp_stream != nut->frame_code[i].stream_id_plus1) tmp_fields=3;
+ if(tmp_size != nut->frame_code[i].size_lsb ) tmp_fields=4;
+// if(tmp_res != nut->frame_code[i].res ) tmp_fields=5;
+
+ tmp_time = nut->frame_code[i].timestamp_delta;
+ tmp_flags = nut->frame_code[i].flags;
+ tmp_stream= nut->frame_code[i].stream_id_plus1;
+ tmp_mul = nut->frame_code[i].size_mul;
+ tmp_size = nut->frame_code[i].size_lsb;
+// tmp_res = nut->frame_code[i].res;
+
+ for(j=0; i<256; j++,i++){
+ if(nut->frame_code[i].timestamp_delta != tmp_time ) break;
+ if(nut->frame_code[i].flags != tmp_flags ) break;
+ if(nut->frame_code[i].stream_id_plus1 != tmp_stream) break;
+ if(nut->frame_code[i].size_mul != tmp_mul ) break;
+ if(nut->frame_code[i].size_lsb != tmp_size+j) break;
+// if(nut->frame_code[i].res != tmp_res ) break;
+ }
+ if(j != tmp_mul - tmp_size) tmp_fields=6;
+
+ put_v(bc, tmp_flags);
+ put_v(bc, tmp_fields);
+ if(tmp_fields>0) put_s(bc, tmp_time);
+ if(tmp_fields>1) put_v(bc, tmp_mul);
+ if(tmp_fields>2) put_v(bc, tmp_stream);
+ if(tmp_fields>3) put_v(bc, tmp_size);
+ if(tmp_fields>4) put_v(bc, 0 /*tmp_res*/);
+ if(tmp_fields>5) put_v(bc, j);
+ }
+
+ update_packetheader(nut, bc, 0, 1);
+
+ /* stream headers */
+ for (i = 0; i < s->nb_streams; i++)
+ {
+ int nom, denom, ssize;
+
+ codec = s->streams[i]->codec;
+
+ put_be64(bc, STREAM_STARTCODE);
+ put_packetheader(nut, bc, 120 + codec->extradata_size, 1);
+ put_v(bc, i /*s->streams[i]->index*/);
+ switch(codec->codec_type){
+ case CODEC_TYPE_VIDEO: put_v(bc, 0); break;
+ case CODEC_TYPE_AUDIO: put_v(bc, 1); break;
+// case CODEC_TYPE_TEXT : put_v(bc, 2); break;
+ case CODEC_TYPE_DATA : put_v(bc, 3); break;
+ default: return -1;
+ }
+ if (codec->codec_tag)
+ put_vb(bc, codec->codec_tag);
+ else if (codec->codec_type == CODEC_TYPE_VIDEO)
+ {
+ put_vb(bc, codec_get_bmp_tag(codec->codec_id));
+ }
+ else if (codec->codec_type == CODEC_TYPE_AUDIO)
+ {
+ put_vb(bc, codec_get_wav_tag(codec->codec_id));
+ }
+ else
+ put_vb(bc, 0);
+
+ ff_parse_specific_params(codec, &nom, &ssize, &denom);
+
+ nut->stream[i].rate_num= nom;
+ nut->stream[i].rate_den= denom;
+ av_set_pts_info(s->streams[i], 60, denom, nom);
+
+ put_v(bc, codec->bit_rate);
+ put_vb(bc, 0); /* no language code */
+ put_v(bc, nom);
+ put_v(bc, denom);
+ if(nom / denom < 1000)
+ nut->stream[i].msb_timestamp_shift = 7;
+ else
+ nut->stream[i].msb_timestamp_shift = 14;
+ put_v(bc, nut->stream[i].msb_timestamp_shift);
+ put_v(bc, codec->has_b_frames);
+ put_byte(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */
+
+ if(codec->extradata_size){
+ put_v(bc, 1);
+ put_v(bc, codec->extradata_size);
+ put_buffer(bc, codec->extradata, codec->extradata_size);
+ }
+ put_v(bc, 0); /* end of codec specific headers */
+
+ switch(codec->codec_type)
+ {
+ case CODEC_TYPE_AUDIO:
+ put_v(bc, codec->sample_rate);
+ put_v(bc, 1);
+ put_v(bc, codec->channels);
+ break;
+ case CODEC_TYPE_VIDEO:
+ put_v(bc, codec->width);
+ put_v(bc, codec->height);
+ put_v(bc, codec->sample_aspect_ratio.num);
+ put_v(bc, codec->sample_aspect_ratio.den);
+ put_v(bc, 0); /* csp type -- unknown */
+ break;
+ default:
+ break;
+ }
+ update_packetheader(nut, bc, 0, 1);
+ }
+
+ /* info header */
+ put_be64(bc, INFO_STARTCODE);
+ put_packetheader(nut, bc, 30+strlen(s->author)+strlen(s->title)+
+ strlen(s->comment)+strlen(s->copyright)+strlen(LIBAVFORMAT_IDENT), 1);
+ if (s->author[0])
+ {
+ put_v(bc, 9); /* type */
+ put_str(bc, s->author);
+ }
+ if (s->title[0])
+ {
+ put_v(bc, 10); /* type */
+ put_str(bc, s->title);
+ }
+ if (s->comment[0])
+ {
+ put_v(bc, 11); /* type */
+ put_str(bc, s->comment);
+ }
+ if (s->copyright[0])
+ {
+ put_v(bc, 12); /* type */
+ put_str(bc, s->copyright);
+ }
+ /* encoder */
+ if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)){
+ put_v(bc, 13); /* type */
+ put_str(bc, LIBAVFORMAT_IDENT);
+ }
+
+ put_v(bc, 0); /* eof info */
+ update_packetheader(nut, bc, 0, 1);
+
+ put_flush_packet(bc);
+
+ return 0;
+}
+
+static int nut_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ NUTContext *nut = s->priv_data;
+ StreamContext *stream= &nut->stream[pkt->stream_index];
+ ByteIOContext *bc = &s->pb;
+ int key_frame = 0, full_pts=0;
+ AVCodecContext *enc;
+ int64_t coded_pts;
+ int frame_type, best_length, frame_code, flags, i, size_mul, size_lsb, time_delta;
+ const int64_t frame_start= url_ftell(bc);
+ int64_t pts= pkt->pts;
+ int size= pkt->size;
+ int stream_index= pkt->stream_index;
+
+ enc = s->streams[stream_index]->codec;
+ key_frame = !!(pkt->flags & PKT_FLAG_KEY);
+
+ frame_type=0;
+ if(frame_start + size + 20 - FFMAX(nut->packet_start[1], nut->packet_start[2]) > MAX_DISTANCE)
+ frame_type=2;
+ if(key_frame && !stream->last_key_frame)
+ frame_type=2;
+
+ if(frame_type>1){
+ int64_t global_ts= av_rescale(pts, stream->rate_den*(int64_t)nut->rate_num, stream->rate_num*(int64_t)nut->rate_den);
+ reset(s, global_ts);
+ put_be64(bc, KEYFRAME_STARTCODE);
+ put_v(bc, global_ts);
+ }
+ assert(stream->last_pts != AV_NOPTS_VALUE);
+ coded_pts = pts & ((1<<stream->msb_timestamp_shift)-1);
+ if(lsb2full(stream, coded_pts) != pts)
+ full_pts=1;
+
+ if(full_pts)
+ coded_pts= pts + (1<<stream->msb_timestamp_shift);
+
+ best_length=INT_MAX;
+ frame_code= -1;
+ for(i=0; i<256; i++){
+ int stream_id_plus1= nut->frame_code[i].stream_id_plus1;
+ int fc_key_frame;
+ int length=0;
+ size_mul= nut->frame_code[i].size_mul;
+ size_lsb= nut->frame_code[i].size_lsb;
+ time_delta= nut->frame_code[i].timestamp_delta;
+ flags= nut->frame_code[i].flags;
+
+ assert(size_mul > size_lsb);
+
+ if(stream_id_plus1 == 0) length+= get_length(stream_index);
+ else if(stream_id_plus1 - 1 != stream_index)
+ continue;
+ fc_key_frame= !!(flags & FLAG_KEY_FRAME);
+
+ assert(key_frame==0 || key_frame==1);
+ if(fc_key_frame != key_frame)
+ continue;
+
+ if(flags & FLAG_DATA_SIZE){
+ if(size % size_mul != size_lsb)
+ continue;
+ length += get_length(size / size_mul);
+ }else if(size != size_lsb)
+ continue;
+
+ if(full_pts && time_delta)
+ continue;
+
+ if(!time_delta){
+ length += get_length(coded_pts);
+ }else{
+ if(time_delta != pts - stream->last_pts)
+ continue;
+ }
+
+ if(length < best_length){
+ best_length= length;
+ frame_code=i;
+ }
+// av_log(s, AV_LOG_DEBUG, "%d %d %d %d %d %d %d %d %d %d\n", key_frame, frame_type, full_pts, size, stream_index, flags, size_mul, size_lsb, stream_id_plus1, length);
+ }
+
+ assert(frame_code != -1);
+ flags= nut->frame_code[frame_code].flags;
+ size_mul= nut->frame_code[frame_code].size_mul;
+ size_lsb= nut->frame_code[frame_code].size_lsb;
+ time_delta= nut->frame_code[frame_code].timestamp_delta;
+#ifdef TRACE
+ best_length /= 7;
+ best_length ++; //frame_code
+ if(frame_type==2){
+ best_length += 8; // startcode
+ }
+ av_log(s, AV_LOG_DEBUG, "kf:%d ft:%d pt:%d fc:%2X len:%2d size:%d stream:%d flag:%d mul:%d lsb:%d s+1:%d pts_delta:%d pts:%"PRId64" fs:%"PRId64"\n", key_frame, frame_type, full_pts ? 1 : 0, frame_code, best_length, size, stream_index, flags, size_mul, size_lsb, nut->frame_code[frame_code].stream_id_plus1,(int)(pts - stream->last_pts), pts, frame_start);
+// av_log(s, AV_LOG_DEBUG, "%d %d %d\n", stream->lru_pts_delta[0], stream->lru_pts_delta[1], stream->lru_pts_delta[2]);
+#endif
+
+ assert(frame_type != 1); //short startcode not implemented yet
+ put_byte(bc, frame_code);
+
+ if(nut->frame_code[frame_code].stream_id_plus1 == 0)
+ put_v(bc, stream_index);
+ if (!time_delta){
+ put_v(bc, coded_pts);
+ }
+ if(flags & FLAG_DATA_SIZE)
+ put_v(bc, size / size_mul);
+ else
+ assert(size == size_lsb);
+ if(size > MAX_DISTANCE){
+ assert(frame_type > 1);
+ }
+
+ put_buffer(bc, pkt->data, size);
+
+ update(nut, stream_index, frame_start, frame_type, frame_code, key_frame, size, pts);
+
+ return 0;
+}
+
+static int nut_write_trailer(AVFormatContext *s)
+{
+ NUTContext *nut = s->priv_data;
+ ByteIOContext *bc = &s->pb;
+
+#if 0
+ int i;
+
+ /* WRITE INDEX */
+
+ for (i = 0; s->nb_streams; i++)
+ {
+ put_be64(bc, INDEX_STARTCODE);
+ put_packetheader(nut, bc, 64, 1);
+ put_v(bc, s->streams[i]->id);
+ put_v(bc, ...);
+ update_packetheader(nut, bc, 0, 1);
+ }
+#endif
+
+ put_flush_packet(bc);
+
+ av_freep(&nut->stream);
+
+ return 0;
+}
+#endif //CONFIG_MUXERS
+
+static int nut_probe(AVProbeData *p)
+{
+ int i;
+ uint64_t code= 0xff;
+
+ for (i = 0; i < p->buf_size; i++) {
+ code = (code << 8) | p->buf[i];
+ if (code == MAIN_STARTCODE)
+ return AVPROBE_SCORE_MAX;
+ }
+ return 0;
+}
+
+static int decode_main_header(NUTContext *nut){
+ AVFormatContext *s= nut->avf;
+ ByteIOContext *bc = &s->pb;
+ uint64_t tmp;
+ int i, j, tmp_stream, tmp_mul, tmp_time, tmp_size, count, tmp_res;
+
+ get_packetheader(nut, bc, 1);
+
+ tmp = get_v(bc);
+ if (tmp != 2){
+ av_log(s, AV_LOG_ERROR, "bad version (%"PRId64")\n", tmp);
+ return -1;
+ }
+
+ nut->stream_count = get_v(bc);
+ if(nut->stream_count > MAX_STREAMS){
+ av_log(s, AV_LOG_ERROR, "too many streams\n");
+ return -1;
+ }
+ nut->max_distance = get_v(bc);
+ nut->max_short_distance = get_v(bc);
+ nut->rate_num= get_v(bc);
+ nut->rate_den= get_v(bc);
+ nut->short_startcode= get_v(bc);
+ if(nut->short_startcode>>16 != 'N'){
+ av_log(s, AV_LOG_ERROR, "invalid short startcode %X\n", nut->short_startcode);
+ return -1;
+ }
+
+ for(i=0; i<256;){
+ int tmp_flags = get_v(bc);
+ int tmp_fields= get_v(bc);
+ if(tmp_fields>0) tmp_time = get_s(bc);
+ if(tmp_fields>1) tmp_mul = get_v(bc);
+ if(tmp_fields>2) tmp_stream= get_v(bc);
+ if(tmp_fields>3) tmp_size = get_v(bc);
+ else tmp_size = 0;
+ if(tmp_fields>4) tmp_res = get_v(bc);
+ else tmp_res = 0;
+ if(tmp_fields>5) count = get_v(bc);
+ else count = tmp_mul - tmp_size;
+
+ while(tmp_fields-- > 6)
+ get_v(bc);
+
+ if(count == 0 || i+count > 256){
+ av_log(s, AV_LOG_ERROR, "illegal count %d at %d\n", count, i);
+ return -1;
+ }
+ if(tmp_stream > nut->stream_count + 1){
+ av_log(s, AV_LOG_ERROR, "illegal stream number\n");
+ return -1;
+ }
+
+ for(j=0; j<count; j++,i++){
+ nut->frame_code[i].flags = tmp_flags ;
+ nut->frame_code[i].timestamp_delta = tmp_time ;
+ nut->frame_code[i].stream_id_plus1 = tmp_stream;
+ nut->frame_code[i].size_mul = tmp_mul ;
+ nut->frame_code[i].size_lsb = tmp_size+j;
+ nut->frame_code[i].reserved_count = tmp_res ;
+ }
+ }
+ if(nut->frame_code['N'].flags != FLAG_INVALID){
+ av_log(s, AV_LOG_ERROR, "illegal frame_code table\n");
+ return -1;
+ }
+
+ if(check_checksum(bc)){
+ av_log(s, AV_LOG_ERROR, "Main header checksum mismatch\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int decode_stream_header(NUTContext *nut){
+ AVFormatContext *s= nut->avf;
+ ByteIOContext *bc = &s->pb;
+ int class, nom, denom, stream_id;
+ uint64_t tmp;
+ AVStream *st;
+
+ get_packetheader(nut, bc, 1);
+ stream_id= get_v(bc);
+ if(stream_id >= nut->stream_count || s->streams[stream_id])
+ return -1;
+
+ st = av_new_stream(s, stream_id);
+ if (!st)
+ return AVERROR_NOMEM;
+
+ class = get_v(bc);
+ tmp = get_vb(bc);
+ st->codec->codec_tag= tmp;
+ switch(class)
+ {
+ case 0:
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = codec_get_bmp_id(tmp);
+ if (st->codec->codec_id == CODEC_ID_NONE)
+ av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");
+ break;
+ case 1:
+ case 32: //compatibility
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = codec_get_wav_id(tmp);
+ if (st->codec->codec_id == CODEC_ID_NONE)
+ av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");
+ break;
+ case 2:
+// st->codec->codec_type = CODEC_TYPE_TEXT;
+// break;
+ case 3:
+ st->codec->codec_type = CODEC_TYPE_DATA;
+ break;
+ default:
+ av_log(s, AV_LOG_ERROR, "Unknown stream class (%d)\n", class);
+ return -1;
+ }
+ s->bit_rate += get_v(bc);
+ get_vb(bc); /* language code */
+ nom = get_v(bc);
+ denom = get_v(bc);
+ nut->stream[stream_id].msb_timestamp_shift = get_v(bc);
+ st->codec->has_b_frames=
+ nut->stream[stream_id].decode_delay= get_v(bc);
+ get_byte(bc); /* flags */
+
+ /* codec specific data headers */
+ while(get_v(bc) != 0){
+ st->codec->extradata_size= get_v(bc);
+ if((unsigned)st->codec->extradata_size > (1<<30))
+ return -1;
+ st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ get_buffer(bc, st->codec->extradata, st->codec->extradata_size);
+// url_fskip(bc, get_v(bc));
+ }
+
+ if (st->codec->codec_type == CODEC_TYPE_VIDEO) /* VIDEO */
+ {
+ st->codec->width = get_v(bc);
+ st->codec->height = get_v(bc);
+ st->codec->sample_aspect_ratio.num= get_v(bc);
+ st->codec->sample_aspect_ratio.den= get_v(bc);
+ get_v(bc); /* csp type */
+ }
+ if (st->codec->codec_type == CODEC_TYPE_AUDIO) /* AUDIO */
+ {
+ st->codec->sample_rate = get_v(bc);
+ get_v(bc); // samplerate_den
+ st->codec->channels = get_v(bc);
+ }
+ if(check_checksum(bc)){
+ av_log(s, AV_LOG_ERROR, "Stream header %d checksum mismatch\n", stream_id);
+ return -1;
+ }
+ av_set_pts_info(s->streams[stream_id], 60, denom, nom);
+ nut->stream[stream_id].rate_num= nom;
+ nut->stream[stream_id].rate_den= denom;
+ return 0;
+}
+
+static int decode_info_header(NUTContext *nut){
+ AVFormatContext *s= nut->avf;
+ ByteIOContext *bc = &s->pb;
+
+ get_packetheader(nut, bc, 1);
+
+ for(;;){
+ int id= get_v(bc);
+ char *name, *type, custom_name[256], custom_type[256];
+
+ if(!id)
+ break;
+ else if(id >= sizeof(info_table)/sizeof(info_table[0])){
+ av_log(s, AV_LOG_ERROR, "info id is too large %d %zd\n", id, sizeof(info_table)/sizeof(info_table[0]));
+ return -1;
+ }
+
+ type= info_table[id][1];
+ name= info_table[id][0];
+//av_log(s, AV_LOG_DEBUG, "%d %s %s\n", id, type, name);
+
+ if(!type){
+ get_str(bc, custom_type, sizeof(custom_type));
+ type= custom_type;
+ }
+ if(!name){
+ get_str(bc, custom_name, sizeof(custom_name));
+ name= custom_name;
+ }
+
+ if(!strcmp(type, "v")){
+ get_v(bc);
+ }else{
+ if(!strcmp(name, "Author"))
+ get_str(bc, s->author, sizeof(s->author));
+ else if(!strcmp(name, "Title"))
+ get_str(bc, s->title, sizeof(s->title));
+ else if(!strcmp(name, "Copyright"))
+ get_str(bc, s->copyright, sizeof(s->copyright));
+ else if(!strcmp(name, "Description"))
+ get_str(bc, s->comment, sizeof(s->comment));
+ else
+ get_str(bc, NULL, 0);
+ }
+ }
+ if(check_checksum(bc)){
+ av_log(s, AV_LOG_ERROR, "Info header checksum mismatch\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ NUTContext *nut = s->priv_data;
+ ByteIOContext *bc = &s->pb;
+ int64_t pos;
+ int inited_stream_count;
+
+ nut->avf= s;
+
+ /* main header */
+ pos=0;
+ for(;;){
+ pos= find_startcode(bc, MAIN_STARTCODE, pos)+1;
+ if (pos<0){
+ av_log(s, AV_LOG_ERROR, "no main startcode found\n");
+ return -1;
+ }
+ if(decode_main_header(nut) >= 0)
+ break;
+ }
+
+
+ s->bit_rate = 0;
+
+ nut->stream = av_malloc(sizeof(StreamContext)*nut->stream_count);
+
+ /* stream headers */
+ pos=0;
+ for(inited_stream_count=0; inited_stream_count < nut->stream_count;){
+ pos= find_startcode(bc, STREAM_STARTCODE, pos)+1;
+ if (pos<0+1){
+ av_log(s, AV_LOG_ERROR, "not all stream headers found\n");
+ return -1;
+ }
+ if(decode_stream_header(nut) >= 0)
+ inited_stream_count++;
+ }
+
+ /* info headers */
+ pos=0;
+ for(;;){
+ uint64_t startcode= find_any_startcode(bc, pos);
+ pos= url_ftell(bc);
+
+ if(startcode==0){
+ av_log(s, AV_LOG_ERROR, "EOF before video frames\n");
+ return -1;
+ }else if(startcode == KEYFRAME_STARTCODE){
+ nut->next_startcode= startcode;
+ break;
+ }else if(startcode != INFO_STARTCODE){
+ continue;
+ }
+
+ decode_info_header(nut);
+ }
+
+ return 0;
+}
+
+static int decode_frame_header(NUTContext *nut, int *key_frame_ret, int64_t *pts_ret, int *stream_id_ret, int frame_code, int frame_type, int64_t frame_start){
+ AVFormatContext *s= nut->avf;
+ StreamContext *stream;
+ ByteIOContext *bc = &s->pb;
+ int size, flags, size_mul, size_lsb, stream_id, time_delta;
+ int64_t pts = 0;
+
+ if(frame_type < 2 && frame_start - nut->packet_start[2] > nut->max_distance){
+ av_log(s, AV_LOG_ERROR, "last frame must have been damaged\n");
+ return -1;
+ }
+
+ if(frame_type)
+ nut->packet_start[ frame_type ]= frame_start; //otherwise 1 goto 1 may happen
+
+ flags= nut->frame_code[frame_code].flags;
+ size_mul= nut->frame_code[frame_code].size_mul;
+ size_lsb= nut->frame_code[frame_code].size_lsb;
+ stream_id= nut->frame_code[frame_code].stream_id_plus1 - 1;
+ time_delta= nut->frame_code[frame_code].timestamp_delta;
+
+ if(stream_id==-1)
+ stream_id= get_v(bc);
+ if(stream_id >= s->nb_streams){
+ av_log(s, AV_LOG_ERROR, "illegal stream_id\n");
+ return -1;
+ }
+ stream= &nut->stream[stream_id];
+
+// av_log(s, AV_LOG_DEBUG, "ft:%d ppts:%d %d %d\n", frame_type, stream->lru_pts_delta[0], stream->lru_pts_delta[1], stream->lru_pts_delta[2]);
+
+ *key_frame_ret= !!(flags & FLAG_KEY_FRAME);
+
+ if(!time_delta){
+ int64_t mask = (1<<stream->msb_timestamp_shift)-1;
+ pts= get_v(bc);
+ if(pts > mask){
+ pts -= mask+1;
+ }else{
+ if(stream->last_pts == AV_NOPTS_VALUE){
+ av_log(s, AV_LOG_ERROR, "no reference pts available\n");
+ return -1;
+ }
+ pts= lsb2full(stream, pts);
+ }
+ }else{
+ if(stream->last_pts == AV_NOPTS_VALUE){
+ av_log(s, AV_LOG_ERROR, "no reference pts available\n");
+ return -1;
+ }
+ pts= stream->last_pts + time_delta;
+ }
+
+ if(*key_frame_ret){
+// av_log(s, AV_LOG_DEBUG, "stream:%d start:%"PRId64" pts:%"PRId64" length:%"PRId64"\n",stream_id, frame_start, av_pts, frame_start - nut->stream[stream_id].last_sync_pos);
+ av_add_index_entry(
+ s->streams[stream_id],
+ frame_start,
+ pts,
+ 0,
+ frame_start - nut->stream[stream_id].last_sync_pos,
+ AVINDEX_KEYFRAME);
+ nut->stream[stream_id].last_sync_pos= frame_start;
+// assert(nut->packet_start == frame_start);
+ }
+
+ assert(size_mul > size_lsb);
+ size= size_lsb;
+ if(flags & FLAG_DATA_SIZE)
+ size+= size_mul*get_v(bc);
+
+#ifdef TRACE
+av_log(s, AV_LOG_DEBUG, "fs:%"PRId64" fc:%d ft:%d kf:%d pts:%"PRId64" size:%d mul:%d lsb:%d flags:%d delta:%d\n", frame_start, frame_code, frame_type, *key_frame_ret, pts, size, size_mul, size_lsb, flags, time_delta);
+#endif
+
+ if(frame_type==0 && url_ftell(bc) - nut->packet_start[2] + size > nut->max_distance){
+ av_log(s, AV_LOG_ERROR, "frame size too large\n");
+ return -1;
+ }
+
+ *stream_id_ret = stream_id;
+ *pts_ret = pts;
+
+ update(nut, stream_id, frame_start, frame_type, frame_code, *key_frame_ret, size, pts);
+
+ return size;
+}
+
+static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code, int frame_type, int64_t frame_start){
+ AVFormatContext *s= nut->avf;
+ ByteIOContext *bc = &s->pb;
+ int size, stream_id, key_frame, discard;
+ int64_t pts, last_IP_pts;
+
+ size= decode_frame_header(nut, &key_frame, &pts, &stream_id, frame_code, frame_type, frame_start);
+ if(size < 0)
+ return -1;
+
+ discard= s->streams[ stream_id ]->discard;
+ last_IP_pts= s->streams[ stream_id ]->last_IP_pts;
+ if( (discard >= AVDISCARD_NONKEY && !key_frame)
+ ||(discard >= AVDISCARD_BIDIR && last_IP_pts != AV_NOPTS_VALUE && last_IP_pts > pts)
+ || discard >= AVDISCARD_ALL){
+ url_fskip(bc, size);
+ return 1;
+ }
+
+ av_get_packet(bc, pkt, size);
+ pkt->stream_index = stream_id;
+ if (key_frame)
+ pkt->flags |= PKT_FLAG_KEY;
+ pkt->pts = pts;
+
+ return 0;
+}
+
+static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ NUTContext *nut = s->priv_data;
+ ByteIOContext *bc = &s->pb;
+ int i, frame_code=0, ret;
+
+ for(;;){
+ int64_t pos= url_ftell(bc);
+ int frame_type= 0;
+ uint64_t tmp= nut->next_startcode;
+ nut->next_startcode=0;
+
+ if (url_feof(bc))
+ return -1;
+
+ if(tmp){
+ pos-=8;
+ }else{
+ frame_code = get_byte(bc);
+ if(frame_code == 'N'){
+ tmp= frame_code;
+ for(i=1; i<8; i++)
+ tmp = (tmp<<8) + get_byte(bc);
+ }
+ }
+ switch(tmp){
+ case MAIN_STARTCODE:
+ case STREAM_STARTCODE:
+ case INDEX_STARTCODE:
+ get_packetheader(nut, bc, 0);
+ assert(nut->packet_start[2] == pos);
+ url_fseek(bc, nut->written_packet_size, SEEK_CUR);
+ break;
+ case INFO_STARTCODE:
+ if(decode_info_header(nut)<0)
+ goto resync;
+ break;
+ case KEYFRAME_STARTCODE:
+ frame_type = 2;
+ reset(s, get_v(bc));
+ frame_code = get_byte(bc);
+ case 0:
+ ret= decode_frame(nut, pkt, frame_code, frame_type, pos);
+ if(ret==0)
+ return 0;
+ else if(ret==1) //ok but discard packet
+ break;
+ default:
+resync:
+av_log(s, AV_LOG_DEBUG, "syncing from %"PRId64"\n", nut->packet_start[2]+1);
+ tmp= find_any_startcode(bc, nut->packet_start[2]+1);
+ if(tmp==0)
+ return -1;
+av_log(s, AV_LOG_DEBUG, "sync\n");
+ nut->next_startcode= tmp;
+ }
+ }
+}
+
+static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index, int64_t *pos_arg, int64_t pos_limit){
+ NUTContext *nut = s->priv_data;
+ StreamContext *stream;
+ ByteIOContext *bc = &s->pb;
+ int64_t pos, pts;
+ uint64_t code;
+ int frame_code,step, stream_id, i,size, key_frame;
+av_log(s, AV_LOG_DEBUG, "read_timestamp(X,%d,%"PRId64",%"PRId64")\n", stream_index, *pos_arg, pos_limit);
+
+ if(*pos_arg < 0)
+ return AV_NOPTS_VALUE;
+
+ pos= *pos_arg;
+ step= FFMIN(16*1024, pos);
+ do{
+ pos-= step;
+ code= find_any_startcode(bc, pos);
+
+ if(code && url_ftell(bc) - 8 <= *pos_arg)
+ break;
+ step= FFMIN(2*step, pos);
+ }while(step);
+
+ if(!code) //nothing found, not even after pos_arg
+ return AV_NOPTS_VALUE;
+
+ url_fseek(bc, -8, SEEK_CUR);
+ for(i=0; i<s->nb_streams; i++)
+ nut->stream[i].last_sync_pos= url_ftell(bc);
+
+ for(;;){
+ int frame_type=0;
+ int64_t pos= url_ftell(bc);
+ uint64_t tmp=0;
+
+ if(pos > pos_limit || url_feof(bc))
+ return AV_NOPTS_VALUE;
+
+ frame_code = get_byte(bc);
+ if(frame_code == 'N'){
+ tmp= frame_code;
+ for(i=1; i<8; i++)
+ tmp = (tmp<<8) + get_byte(bc);
+ }
+//av_log(s, AV_LOG_DEBUG, "before switch %"PRIX64" at=%"PRId64"\n", tmp, pos);
+
+ switch(tmp){
+ case MAIN_STARTCODE:
+ case STREAM_STARTCODE:
+ case INDEX_STARTCODE:
+ case INFO_STARTCODE:
+ get_packetheader(nut, bc, 0);
+ assert(nut->packet_start[2]==pos);
+ url_fseek(bc, nut->written_packet_size, SEEK_CUR);
+ break;
+ case KEYFRAME_STARTCODE:
+ frame_type=2;
+ reset(s, get_v(bc));
+ frame_code = get_byte(bc);
+ case 0:
+ size= decode_frame_header(nut, &key_frame, &pts, &stream_id, frame_code, frame_type, pos);
+ if(size < 0)
+ goto resync;
+
+ stream= &nut->stream[stream_id];
+ if(stream_id != stream_index || !key_frame || pos < *pos_arg){
+ url_fseek(bc, size, SEEK_CUR);
+ break;
+ }
+
+ *pos_arg= pos;
+ return pts;
+ default:
+resync:
+av_log(s, AV_LOG_DEBUG, "syncing from %"PRId64"\n", nut->packet_start[2]+1);
+ if(!find_any_startcode(bc, nut->packet_start[2]+1))
+ return AV_NOPTS_VALUE;
+
+ url_fseek(bc, -8, SEEK_CUR);
+ }
+ }
+ return AV_NOPTS_VALUE;
+}
+
+static int nut_read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, int flags){
+// NUTContext *nut = s->priv_data;
+ int64_t pos;
+
+ if(av_seek_frame_binary(s, stream_index, target_ts, flags) < 0)
+ return -1;
+
+ pos= url_ftell(&s->pb);
+ nut_read_timestamp(s, stream_index, &pos, pos-1);
+
+ return 0;
+}
+
+static int nut_read_close(AVFormatContext *s)
+{
+ NUTContext *nut = s->priv_data;
+
+ av_freep(&nut->stream);
+
+ return 0;
+}
+
+#ifdef CONFIG_NUT_DEMUXER
+AVInputFormat nut_demuxer = {
+ "nut",
+ "nut format",
+ sizeof(NUTContext),
+ nut_probe,
+ nut_read_header,
+ nut_read_packet,
+ nut_read_close,
+ nut_read_seek,
+ nut_read_timestamp,
+ .extensions = "nut",
+};
+#endif
+#ifdef CONFIG_NUT_MUXER
+AVOutputFormat nut_muxer = {
+ "nut",
+ "nut format",
+ "video/x-nut",
+ "nut",
+ sizeof(NUTContext),
+#ifdef CONFIG_LIBVORBIS
+ CODEC_ID_VORBIS,
+#elif defined(CONFIG_MP3LAME)
+ CODEC_ID_MP3,
+#else
+ CODEC_ID_MP2, /* AC3 needs liba52 decoder */
+#endif
+ CODEC_ID_MPEG4,
+ nut_write_header,
+ nut_write_packet,
+ nut_write_trailer,
+ .flags = AVFMT_GLOBALHEADER,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/nut.h b/contrib/ffmpeg/libavformat/nut.h
new file mode 100644
index 000000000..82bbf6f17
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/nut.h
@@ -0,0 +1,97 @@
+/*
+ * "NUT" Container Format (de)muxer
+ * 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 <limits.h>
+#include "avformat.h"
+#include "crc.h"
+//#include "mpegaudio.h"
+#include "riff.h"
+//#include "adler32.h"
+
+#define MAIN_STARTCODE (0x7A561F5F04ADULL + (((uint64_t)('N'<<8) + 'M')<<48))
+#define STREAM_STARTCODE (0x11405BF2F9DBULL + (((uint64_t)('N'<<8) + 'S')<<48))
+#define SYNCPOINT_STARTCODE (0xE4ADEECA4569ULL + (((uint64_t)('N'<<8) + 'K')<<48))
+#define INDEX_STARTCODE (0xDD672F23E64EULL + (((uint64_t)('N'<<8) + 'X')<<48))
+#define INFO_STARTCODE (0xAB68B596BA78ULL + (((uint64_t)('N'<<8) + 'I')<<48))
+
+#define ID_STRING "nut/multimedia container\0"
+
+#define MAX_DISTANCE (1024*32-1)
+
+typedef enum{
+ FLAG_KEY = 1, ///<if set, frame is keyframe
+ FLAG_EOR = 2, ///<if set, stream has no relevance on presentation. (EOR)
+ FLAG_CODED_PTS = 8, ///<if set, coded_pts is in the frame header
+ FLAG_STREAM_ID = 16, ///<if set, stream_id is coded in the frame header
+ FLAG_SIZE_MSB = 32, ///<if set, data_size_msb is at frame header, otherwise data_size_msb is 0
+ FLAG_CHECKSUM = 64, ///<if set then the frame header contains a checksum
+ FLAG_RESERVED = 128, ///<if set, reserved_count is coded in the frame header
+ FLAG_CODED =4096, ///<if set, coded_flags are stored in the frame header.
+ FLAG_INVALID =8192, ///<if set, frame_code is invalid.
+}flag_t;
+
+typedef struct {
+ uint64_t pos;
+ uint64_t back_ptr;
+// uint64_t global_key_pts;
+ int64_t ts;
+} syncpoint_t;
+
+typedef struct {
+ uint16_t flags;
+ uint8_t stream_id;
+ uint16_t size_mul;
+ uint16_t size_lsb;
+ int16_t pts_delta;
+ uint8_t reserved_count;
+} FrameCode; // maybe s/FrameCode/framecode_t/ or change all to java style but dont mix
+
+typedef struct {
+ int last_flags;
+ int skip_until_key_frame;
+ int64_t last_pts;
+ int time_base_id;
+ AVRational time_base;
+ int msb_pts_shift;
+ int max_pts_distance;
+ int decode_delay; //FIXME duplicate of has_b_frames
+} StreamContext;// maybe s/StreamContext/streamcontext_t/
+
+typedef struct {
+ AVFormatContext *avf;
+// int written_packet_size;
+// int64_t packet_start[3]; //0-> startcode less, 1-> short startcode 2-> long startcodes
+ FrameCode frame_code[256];
+ uint64_t next_startcode; ///< stores the next startcode if it has alraedy been parsed but the stream isnt seekable
+ StreamContext *stream;
+ unsigned int max_distance;
+ unsigned int time_base_count;
+ int64_t last_syncpoint_pos;
+ AVRational *time_base;
+ struct AVTreeNode *syncpoints;
+} NUTContext;
+
+
+//FIXME move to a common spot, like crc.c/h
+static unsigned long av_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, unsigned int len){
+ return av_crc(av_crc04C11DB7, checksum, buf, len);
+}
diff --git a/contrib/ffmpeg/libavformat/nutdec.c b/contrib/ffmpeg/libavformat/nutdec.c
new file mode 100644
index 000000000..7e0f8cd93
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/nutdec.c
@@ -0,0 +1,889 @@
+/*
+ * "NUT" Container Format demuxer
+ * Copyright (c) 2004-2006 Michael Niedermayer
+ * 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 "tree.h"
+#include "nut.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+static uint64_t get_v(ByteIOContext *bc){
+ uint64_t val = 0;
+
+ for(;;)
+ {
+ int tmp = get_byte(bc);
+
+ if (tmp&0x80)
+ val= (val<<7) + tmp - 0x80;
+ else{
+ return (val<<7) + tmp;
+ }
+ }
+ return -1;
+}
+
+static int get_str(ByteIOContext *bc, char *string, unsigned int maxlen){
+ unsigned int len= get_v(bc);
+
+ if(len && maxlen)
+ get_buffer(bc, string, FFMIN(len, maxlen));
+ while(len > maxlen){
+ get_byte(bc);
+ len--;
+ }
+
+ if(maxlen)
+ string[FFMIN(len, maxlen-1)]= 0;
+
+ if(maxlen == len)
+ return -1;
+ else
+ return 0;
+}
+
+static int64_t get_s(ByteIOContext *bc){
+ int64_t v = get_v(bc) + 1;
+
+ if (v&1) return -(v>>1);
+ else return (v>>1);
+}
+
+static uint64_t get_fourcc(ByteIOContext *bc){
+ unsigned int len= get_v(bc);
+
+ if (len==2) return get_le16(bc);
+ else if(len==4) return get_le32(bc);
+ else return -1;
+}
+
+#ifdef TRACE
+static inline uint64_t get_v_trace(ByteIOContext *bc, char *file, char *func, int line){
+ uint64_t v= get_v(bc);
+
+ printf("get_v %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
+ return v;
+}
+
+static inline int64_t get_s_trace(ByteIOContext *bc, char *file, char *func, int line){
+ int64_t v= get_s(bc);
+
+ printf("get_s %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
+ return v;
+}
+
+static inline uint64_t get_vb_trace(ByteIOContext *bc, char *file, char *func, int line){
+ uint64_t v= get_vb(bc);
+
+ printf("get_vb %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
+ return v;
+}
+#define get_v(bc) get_v_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
+#define get_s(bc) get_s_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
+#define get_vb(bc) get_vb_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
+#endif
+
+static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int calculate_checksum)
+{
+ int64_t start, size;
+// start= url_ftell(bc) - 8;
+
+ size= get_v(bc);
+
+ init_checksum(bc, calculate_checksum ? av_crc04C11DB7_update : NULL, 0);
+
+// nut->packet_start[2] = start;
+// nut->written_packet_size= size;
+
+ return size;
+}
+
+static uint64_t find_any_startcode(ByteIOContext *bc, int64_t pos){
+ uint64_t state=0;
+
+ if(pos >= 0)
+ url_fseek(bc, pos, SEEK_SET); //note, this may fail if the stream isnt seekable, but that shouldnt matter, as in this case we simply start where we are currently
+
+ while(!url_feof(bc)){
+ state= (state<<8) | get_byte(bc);
+ if((state>>56) != 'N')
+ continue;
+ switch(state){
+ case MAIN_STARTCODE:
+ case STREAM_STARTCODE:
+ case SYNCPOINT_STARTCODE:
+ case INFO_STARTCODE:
+ case INDEX_STARTCODE:
+ return state;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * find the given startcode.
+ * @param code the startcode
+ * @param pos the start position of the search, or -1 if the current position
+ * @returns the position of the startcode or -1 if not found
+ */
+static int64_t find_startcode(ByteIOContext *bc, uint64_t code, int64_t pos){
+ for(;;){
+ uint64_t startcode= find_any_startcode(bc, pos);
+ if(startcode == code)
+ return url_ftell(bc) - 8;
+ else if(startcode == 0)
+ return -1;
+ pos=-1;
+ }
+}
+
+static int64_t lsb2full(StreamContext *stream, int64_t lsb){
+ int64_t mask = (1<<stream->msb_pts_shift)-1;
+ int64_t delta= stream->last_pts - mask/2;
+ return ((lsb - delta)&mask) + delta;
+}
+
+static int nut_probe(AVProbeData *p){
+ int i;
+ uint64_t code= 0;
+
+ for (i = 0; i < p->buf_size; i++) {
+ code = (code << 8) | p->buf[i];
+ if (code == MAIN_STARTCODE)
+ return AVPROBE_SCORE_MAX;
+ }
+ return 0;
+}
+
+#define GET_V(dst, check) \
+ tmp= get_v(bc);\
+ if(!(check)){\
+ av_log(s, AV_LOG_ERROR, "Error " #dst " is (%"PRId64")\n", tmp);\
+ return -1;\
+ }\
+ dst= tmp;
+
+static int skip_reserved(ByteIOContext *bc, int64_t pos){
+ pos -= url_ftell(bc);
+ if(pos<0){
+ url_fseek(bc, pos, SEEK_CUR);
+ return -1;
+ }else{
+ while(pos--)
+ get_byte(bc);
+ return 0;
+ }
+}
+
+static int decode_main_header(NUTContext *nut){
+ AVFormatContext *s= nut->avf;
+ ByteIOContext *bc = &s->pb;
+ uint64_t tmp, end;
+ unsigned int stream_count;
+ int i, j, tmp_stream, tmp_mul, tmp_pts, tmp_size, count, tmp_res;
+
+ end= get_packetheader(nut, bc, 1);
+ end += url_ftell(bc);
+
+ GET_V(tmp , tmp >=2 && tmp <= 3)
+ GET_V(stream_count , tmp > 0 && tmp <=MAX_STREAMS)
+
+ nut->max_distance = get_v(bc);
+ if(nut->max_distance > 65536){
+ av_log(s, AV_LOG_DEBUG, "max_distance %d\n", nut->max_distance);
+ nut->max_distance= 65536;
+ }
+
+ GET_V(nut->time_base_count, tmp>0 && tmp<INT_MAX / sizeof(AVRational))
+ nut->time_base= av_malloc(nut->time_base_count * sizeof(AVRational));
+
+ for(i=0; i<nut->time_base_count; i++){
+ GET_V(nut->time_base[i].num, tmp>0 && tmp<(1ULL<<31))
+ GET_V(nut->time_base[i].den, tmp>0 && tmp<(1ULL<<31))
+ if(ff_gcd(nut->time_base[i].num, nut->time_base[i].den) != 1){
+ av_log(s, AV_LOG_ERROR, "time base invalid\n");
+ return -1;
+ }
+ }
+ tmp_pts=0;
+ tmp_mul=1;
+ tmp_stream=0;
+ for(i=0; i<256;){
+ int tmp_flags = get_v(bc);
+ int tmp_fields= get_v(bc);
+ if(tmp_fields>0) tmp_pts = get_s(bc);
+ if(tmp_fields>1) tmp_mul = get_v(bc);
+ if(tmp_fields>2) tmp_stream= get_v(bc);
+ if(tmp_fields>3) tmp_size = get_v(bc);
+ else tmp_size = 0;
+ if(tmp_fields>4) tmp_res = get_v(bc);
+ else tmp_res = 0;
+ if(tmp_fields>5) count = get_v(bc);
+ else count = tmp_mul - tmp_size;
+
+ while(tmp_fields-- > 6)
+ get_v(bc);
+
+ if(count == 0 || i+count > 256){
+ av_log(s, AV_LOG_ERROR, "illegal count %d at %d\n", count, i);
+ return -1;
+ }
+ if(tmp_stream >= stream_count){
+ av_log(s, AV_LOG_ERROR, "illegal stream number\n");
+ return -1;
+ }
+
+ for(j=0; j<count; j++,i++){
+ if (i == 'N') {
+ nut->frame_code[i].flags= FLAG_INVALID;
+ j--;
+ continue;
+ }
+ nut->frame_code[i].flags = tmp_flags ;
+ nut->frame_code[i].pts_delta = tmp_pts ;
+ nut->frame_code[i].stream_id = tmp_stream;
+ nut->frame_code[i].size_mul = tmp_mul ;
+ nut->frame_code[i].size_lsb = tmp_size+j;
+ nut->frame_code[i].reserved_count = tmp_res ;
+ }
+ }
+ assert(nut->frame_code['N'].flags == FLAG_INVALID);
+
+ if(skip_reserved(bc, end) || get_checksum(bc)){
+ av_log(s, AV_LOG_ERROR, "Main header checksum mismatch\n");
+ return -1;
+ }
+
+ nut->stream = av_mallocz(sizeof(StreamContext)*stream_count);
+ for(i=0; i<stream_count; i++){
+ av_new_stream(s, i);
+ }
+
+ return 0;
+}
+
+static int decode_stream_header(NUTContext *nut){
+ AVFormatContext *s= nut->avf;
+ ByteIOContext *bc = &s->pb;
+ StreamContext *stc;
+ int class, stream_id;
+ uint64_t tmp, end;
+ AVStream *st;
+
+ end= get_packetheader(nut, bc, 1);
+ end += url_ftell(bc);
+
+ GET_V(stream_id, tmp < s->nb_streams && !nut->stream[tmp].time_base.num);
+ stc= &nut->stream[stream_id];
+
+ st = s->streams[stream_id];
+ if (!st)
+ return AVERROR_NOMEM;
+
+ class = get_v(bc);
+ tmp = get_fourcc(bc);
+ st->codec->codec_tag= tmp;
+ switch(class)
+ {
+ case 0:
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = codec_get_bmp_id(tmp);
+ if (st->codec->codec_id == CODEC_ID_NONE)
+ av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");
+ break;
+ case 1:
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = codec_get_wav_id(tmp);
+ if (st->codec->codec_id == CODEC_ID_NONE)
+ av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");
+ break;
+ case 2:
+// st->codec->codec_type = CODEC_TYPE_TEXT;
+// break;
+ case 3:
+ st->codec->codec_type = CODEC_TYPE_DATA;
+ break;
+ default:
+ av_log(s, AV_LOG_ERROR, "Unknown stream class (%d)\n", class);
+ return -1;
+ }
+ GET_V(stc->time_base_id , tmp < nut->time_base_count);
+ GET_V(stc->msb_pts_shift , tmp < 16);
+ stc->max_pts_distance= get_v(bc);
+ GET_V(stc->decode_delay , tmp < 1000); //sanity limit, raise this if moors law is true
+ st->codec->has_b_frames= stc->decode_delay;
+ get_v(bc); //stream flags
+
+ GET_V(st->codec->extradata_size, tmp < (1<<30));
+ if(st->codec->extradata_size){
+ st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ get_buffer(bc, st->codec->extradata, st->codec->extradata_size);
+ }
+
+ if (st->codec->codec_type == CODEC_TYPE_VIDEO){
+ GET_V(st->codec->width , tmp > 0)
+ GET_V(st->codec->height, tmp > 0)
+ st->codec->sample_aspect_ratio.num= get_v(bc);
+ st->codec->sample_aspect_ratio.den= get_v(bc);
+ if((!st->codec->sample_aspect_ratio.num) != (!st->codec->sample_aspect_ratio.den)){
+ av_log(s, AV_LOG_ERROR, "invalid aspect ratio\n");
+ return -1;
+ }
+ get_v(bc); /* csp type */
+ }else if (st->codec->codec_type == CODEC_TYPE_AUDIO){
+ GET_V(st->codec->sample_rate , tmp > 0)
+ tmp= get_v(bc); // samplerate_den
+ if(tmp > st->codec->sample_rate){
+ av_log(s, AV_LOG_ERROR, "bleh, libnut muxed this ;)\n");
+ st->codec->sample_rate= tmp;
+ }
+ GET_V(st->codec->channels, tmp > 0)
+ }
+ if(skip_reserved(bc, end) || get_checksum(bc)){
+ av_log(s, AV_LOG_ERROR, "Stream header %d checksum mismatch\n", stream_id);
+ return -1;
+ }
+ stc->time_base= nut->time_base[stc->time_base_id];
+ av_set_pts_info(s->streams[stream_id], 63, stc->time_base.num, stc->time_base.den);
+ return 0;
+}
+
+static int decode_info_header(NUTContext *nut){
+ AVFormatContext *s= nut->avf;
+ ByteIOContext *bc = &s->pb;
+ uint64_t tmp;
+ unsigned int stream_id_plus1, chapter_start, chapter_len, count;
+ int chapter_id, i;
+ int64_t value, end;
+ char name[256], str_value[1024], type_str[256], *type= type_str;
+
+ end= get_packetheader(nut, bc, 1);
+ end += url_ftell(bc);
+
+ GET_V(stream_id_plus1, tmp <= s->nb_streams)
+ chapter_id = get_s(bc);
+ chapter_start= get_v(bc);
+ chapter_len = get_v(bc);
+ count = get_v(bc);
+ for(i=0; i<count; i++){
+ get_str(bc, name, sizeof(name));
+ value= get_s(bc);
+ if(value == -1){
+ type= "UTF-8";
+ get_str(bc, str_value, sizeof(str_value));
+ }else if(value == -2){
+ get_str(bc, type, sizeof(type));
+ get_str(bc, str_value, sizeof(str_value));
+ }else if(value == -3){
+ type= "s";
+ value= get_s(bc);
+ }else if(value == -4){
+ type= "t";
+ value= get_v(bc);
+ }else if(value < -4){
+ type= "r";
+ get_s(bc);
+ }else{
+ type= "v";
+ }
+
+ if(chapter_id==0 && !strcmp(type, "UTF-8")){
+ if (!strcmp(name, "Author"))
+ pstrcpy(s->author , sizeof(s->author) , str_value);
+ else if(!strcmp(name, "Title"))
+ pstrcpy(s->title , sizeof(s->title) , str_value);
+ else if(!strcmp(name, "Copyright"))
+ pstrcpy(s->copyright, sizeof(s->copyright), str_value);
+ else if(!strcmp(name, "Description"))
+ pstrcpy(s->comment , sizeof(s->comment) , str_value);
+ }
+ }
+
+ if(skip_reserved(bc, end) || get_checksum(bc)){
+ av_log(s, AV_LOG_ERROR, "Info header checksum mismatch\n");
+ return -1;
+ }
+ return 0;
+}
+
+int sp_pos_cmp(syncpoint_t *a, syncpoint_t *b){
+ return (a->pos - b->pos>>32) - (b->pos - a->pos>>32);
+}
+
+int sp_pts_cmp(syncpoint_t *a, syncpoint_t *b){
+ return (a->ts - b->ts>>32) - (b->ts - a->ts>>32);
+}
+
+static void add_sp(NUTContext *nut, int64_t pos, int64_t back_ptr, int64_t ts){
+ syncpoint_t *sp2, *sp= av_mallocz(sizeof(syncpoint_t));
+
+ sp->pos= pos;
+ sp->back_ptr= back_ptr;
+ sp->ts= ts;
+ sp2= av_tree_insert(&nut->syncpoints, sp, sp_pos_cmp);
+ if(sp2 && sp2 != sp)
+ av_free(sp);
+}
+
+static int decode_syncpoint(NUTContext *nut, int64_t *ts, int64_t *back_ptr){
+ AVFormatContext *s= nut->avf;
+ ByteIOContext *bc = &s->pb;
+ int64_t end, tmp;
+ int i;
+ AVRational time_base;
+
+ nut->last_syncpoint_pos= url_ftell(bc)-8;
+
+ end= get_packetheader(nut, bc, 1);
+ end += url_ftell(bc);
+
+ tmp= get_v(bc);
+ *back_ptr= nut->last_syncpoint_pos - 16*get_v(bc);
+ if(*back_ptr < 0)
+ return -1;
+
+ time_base= nut->time_base[tmp % nut->time_base_count];
+ for(i=0; i<s->nb_streams; i++){
+ nut->stream[i].last_pts= av_rescale_rnd(
+ tmp / nut->time_base_count,
+ time_base.num * (int64_t)nut->stream[i].time_base.den,
+ time_base.den * (int64_t)nut->stream[i].time_base.num,
+ AV_ROUND_DOWN);
+ //last_key_frame ?
+ }
+ //FIXME put this in a reset func maybe
+
+ if(skip_reserved(bc, end) || get_checksum(bc)){
+ av_log(s, AV_LOG_ERROR, "sync point checksum mismatch\n");
+ return -1;
+ }
+
+ *ts= tmp / s->nb_streams * av_q2d(nut->time_base[tmp % s->nb_streams])*AV_TIME_BASE;
+ add_sp(nut, nut->last_syncpoint_pos, *back_ptr, *ts);
+
+ return 0;
+}
+
+static int find_and_decode_index(NUTContext *nut){
+ AVFormatContext *s= nut->avf;
+ ByteIOContext *bc = &s->pb;
+ uint64_t tmp, end;
+ int i, j, syncpoint_count;
+ int64_t filesize= url_fsize(bc);
+ int64_t *syncpoints;
+ int8_t *has_keyframe;
+
+ url_fseek(bc, filesize-12, SEEK_SET);
+ url_fseek(bc, filesize-get_be64(bc), SEEK_SET);
+ if(get_be64(bc) != INDEX_STARTCODE){
+ av_log(s, AV_LOG_ERROR, "no index at the end\n");
+ return -1;
+ }
+
+ end= get_packetheader(nut, bc, 1);
+ end += url_ftell(bc);
+
+ get_v(bc); //max_pts
+ GET_V(syncpoint_count, tmp < INT_MAX/8 && tmp > 0)
+ syncpoints= av_malloc(sizeof(int64_t)*syncpoint_count);
+ has_keyframe= av_malloc(sizeof(int8_t)*(syncpoint_count+1));
+ for(i=0; i<syncpoint_count; i++){
+ GET_V(syncpoints[i], tmp>0)
+ if(i)
+ syncpoints[i] += syncpoints[i-1];
+ }
+
+ for(i=0; i<s->nb_streams; i++){
+ int64_t last_pts= -1;
+ for(j=0; j<syncpoint_count;){
+ uint64_t x= get_v(bc);
+ int type= x&1;
+ int n= j;
+ x>>=1;
+ if(type){
+ int flag= x&1;
+ x>>=1;
+ if(n+x >= syncpoint_count + 1){
+ av_log(s, AV_LOG_ERROR, "index overflow A\n");
+ return -1;
+ }
+ while(x--)
+ has_keyframe[n++]= flag;
+ has_keyframe[n++]= !flag;
+ }else{
+ while(x != 1){
+ if(n>=syncpoint_count + 1){
+ av_log(s, AV_LOG_ERROR, "index overflow B\n");
+ return -1;
+ }
+ has_keyframe[n++]= x&1;
+ x>>=1;
+ }
+ }
+ if(has_keyframe[0]){
+ av_log(s, AV_LOG_ERROR, "keyframe before first syncpoint in index\n");
+ return -1;
+ }
+ assert(n<=syncpoint_count+1);
+ for(; j<n; j++){
+ if(has_keyframe[j]){
+ uint64_t B, A= get_v(bc);
+ if(!A){
+ A= get_v(bc);
+ B= get_v(bc);
+ //eor_pts[j][i] = last_pts + A + B
+ }else
+ B= 0;
+ av_add_index_entry(
+ s->streams[i],
+ 16*syncpoints[j-1],
+ last_pts + A,
+ 0,
+ 0,
+ AVINDEX_KEYFRAME);
+ last_pts += A + B;
+ }
+ }
+ }
+ }
+
+ if(skip_reserved(bc, end) || get_checksum(bc)){
+ av_log(s, AV_LOG_ERROR, "Index checksum mismatch\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ NUTContext *nut = s->priv_data;
+ ByteIOContext *bc = &s->pb;
+ int64_t pos;
+ int inited_stream_count;
+
+ nut->avf= s;
+
+ /* main header */
+ pos=0;
+ do{
+ pos= find_startcode(bc, MAIN_STARTCODE, pos)+1;
+ if (pos<0+1){
+ av_log(s, AV_LOG_ERROR, "no main startcode found\n");
+ return -1;
+ }
+ }while(decode_main_header(nut) < 0);
+
+ /* stream headers */
+ pos=0;
+ for(inited_stream_count=0; inited_stream_count < s->nb_streams;){
+ pos= find_startcode(bc, STREAM_STARTCODE, pos)+1;
+ if (pos<0+1){
+ av_log(s, AV_LOG_ERROR, "not all stream headers found\n");
+ return -1;
+ }
+ if(decode_stream_header(nut) >= 0)
+ inited_stream_count++;
+ }
+
+ /* info headers */
+ pos=0;
+ for(;;){
+ uint64_t startcode= find_any_startcode(bc, pos);
+ pos= url_ftell(bc);
+
+ if(startcode==0){
+ av_log(s, AV_LOG_ERROR, "EOF before video frames\n");
+ return -1;
+ }else if(startcode == SYNCPOINT_STARTCODE){
+ nut->next_startcode= startcode;
+ break;
+ }else if(startcode != INFO_STARTCODE){
+ continue;
+ }
+
+ decode_info_header(nut);
+ }
+
+ s->data_offset= pos-8;
+
+ if(!url_is_streamed(bc)){
+ int64_t orig_pos= url_ftell(bc);
+ find_and_decode_index(nut);
+ url_fseek(bc, orig_pos, SEEK_SET);
+ }
+ assert(nut->next_startcode == SYNCPOINT_STARTCODE);
+
+ return 0;
+}
+
+static int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id, int frame_code){
+ AVFormatContext *s= nut->avf;
+ ByteIOContext *bc = &s->pb;
+ StreamContext *stc;
+ int size, flags, size_mul, pts_delta, i, reserved_count;
+ uint64_t tmp;
+
+ if(url_ftell(bc) > nut->last_syncpoint_pos + nut->max_distance){
+ av_log(s, AV_LOG_ERROR, "last frame must have been damaged %Ld > %Ld + %d\n", url_ftell(bc), nut->last_syncpoint_pos, nut->max_distance);
+ return -1;
+ }
+
+ flags = nut->frame_code[frame_code].flags;
+ size_mul = nut->frame_code[frame_code].size_mul;
+ size = nut->frame_code[frame_code].size_lsb;
+ *stream_id = nut->frame_code[frame_code].stream_id;
+ pts_delta = nut->frame_code[frame_code].pts_delta;
+ reserved_count = nut->frame_code[frame_code].reserved_count;
+
+ if(flags & FLAG_INVALID)
+ return -1;
+ if(flags & FLAG_CODED)
+ flags ^= get_v(bc);
+ if(flags & FLAG_STREAM_ID){
+ GET_V(*stream_id, tmp < s->nb_streams)
+ }
+ stc= &nut->stream[*stream_id];
+ if(flags&FLAG_CODED_PTS){
+ int coded_pts= get_v(bc);
+//FIXME check last_pts validity?
+ if(coded_pts < (1<<stc->msb_pts_shift)){
+ *pts=lsb2full(stc, coded_pts);
+ }else
+ *pts=coded_pts - (1<<stc->msb_pts_shift);
+ }else
+ *pts= stc->last_pts + pts_delta;
+ if(flags&FLAG_SIZE_MSB){
+ size += size_mul*get_v(bc);
+ }
+ if(flags&FLAG_RESERVED)
+ reserved_count= get_v(bc);
+ for(i=0; i<reserved_count; i++)
+ get_v(bc);
+ if(flags&FLAG_CHECKSUM){
+ get_be32(bc); //FIXME check this
+ }else if(size > 2*nut->max_distance || FFABS(stc->last_pts - *pts) > stc->max_pts_distance){
+ av_log(s, AV_LOG_ERROR, "frame size > 2max_distance and no checksum\n");
+ return -1;
+ }
+
+ stc->last_pts= *pts;
+ stc->last_flags= flags;
+
+ return size;
+}
+
+static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code){
+ AVFormatContext *s= nut->avf;
+ ByteIOContext *bc = &s->pb;
+ int size, stream_id, discard;
+ int64_t pts, last_IP_pts;
+ StreamContext *stc;
+
+ size= decode_frame_header(nut, &pts, &stream_id, frame_code);
+ if(size < 0)
+ return -1;
+
+ stc= &nut->stream[stream_id];
+
+ if (stc->last_flags & FLAG_KEY)
+ stc->skip_until_key_frame=0;
+
+ discard= s->streams[ stream_id ]->discard;
+ last_IP_pts= s->streams[ stream_id ]->last_IP_pts;
+ if( (discard >= AVDISCARD_NONKEY && !(stc->last_flags & FLAG_KEY))
+ ||(discard >= AVDISCARD_BIDIR && last_IP_pts != AV_NOPTS_VALUE && last_IP_pts > pts)
+ || discard >= AVDISCARD_ALL
+ || stc->skip_until_key_frame){
+ url_fskip(bc, size);
+ return 1;
+ }
+
+ av_get_packet(bc, pkt, size);
+ pkt->stream_index = stream_id;
+ if (stc->last_flags & FLAG_KEY)
+ pkt->flags |= PKT_FLAG_KEY;
+ pkt->pts = pts;
+
+ return 0;
+}
+
+static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ NUTContext *nut = s->priv_data;
+ ByteIOContext *bc = &s->pb;
+ int i, frame_code=0, ret, skip;
+ int64_t ts, back_ptr;
+
+ for(;;){
+ int64_t pos= url_ftell(bc);
+ uint64_t tmp= nut->next_startcode;
+ nut->next_startcode=0;
+
+ if (url_feof(bc))
+ return -1;
+
+ if(tmp){
+ pos-=8;
+ }else{
+ frame_code = get_byte(bc);
+ if(frame_code == 'N'){
+ tmp= frame_code;
+ for(i=1; i<8; i++)
+ tmp = (tmp<<8) + get_byte(bc);
+ }
+ }
+ switch(tmp){
+ case MAIN_STARTCODE:
+ case STREAM_STARTCODE:
+ case INDEX_STARTCODE:
+ skip= get_packetheader(nut, bc, 0);
+ url_fseek(bc, skip, SEEK_CUR);
+ break;
+ case INFO_STARTCODE:
+ if(decode_info_header(nut)<0)
+ goto resync;
+ break;
+ case SYNCPOINT_STARTCODE:
+ if(decode_syncpoint(nut, &ts, &back_ptr)<0)
+ goto resync;
+ frame_code = get_byte(bc);
+ case 0:
+ ret= decode_frame(nut, pkt, frame_code);
+ if(ret==0)
+ return 0;
+ else if(ret==1) //ok but discard packet
+ break;
+ default:
+resync:
+av_log(s, AV_LOG_DEBUG, "syncing from %"PRId64"\n", pos);
+ tmp= find_any_startcode(bc, nut->last_syncpoint_pos+1);
+ if(tmp==0)
+ return -1;
+av_log(s, AV_LOG_DEBUG, "sync\n");
+ nut->next_startcode= tmp;
+ }
+ }
+}
+
+static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index, int64_t *pos_arg, int64_t pos_limit){
+ NUTContext *nut = s->priv_data;
+ ByteIOContext *bc = &s->pb;
+ int64_t pos, pts, back_ptr;
+av_log(s, AV_LOG_DEBUG, "read_timestamp(X,%d,%"PRId64",%"PRId64")\n", stream_index, *pos_arg, pos_limit);
+
+ pos= *pos_arg;
+resync:
+ do{
+ pos= find_startcode(bc, SYNCPOINT_STARTCODE, pos)+1;
+ if(pos < 1){
+ assert(nut->next_startcode == 0);
+ av_log(s, AV_LOG_ERROR, "read_timestamp failed\n");
+ return AV_NOPTS_VALUE;
+ }
+ }while(decode_syncpoint(nut, &pts, &back_ptr) < 0);
+ *pos_arg = pos-1;
+ assert(nut->last_syncpoint_pos == *pos_arg);
+
+ av_log(s, AV_LOG_DEBUG, "return %Ld %Ld\n", pts,back_ptr );
+ if (stream_index == -1) return pts;
+ else if(stream_index == -2) return back_ptr;
+
+assert(0);
+}
+
+static int read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags){
+ NUTContext *nut = s->priv_data;
+ AVStream *st= s->streams[stream_index];
+ syncpoint_t dummy={.ts= pts*av_q2d(st->time_base)*AV_TIME_BASE};
+ syncpoint_t nopts_sp= {.ts= AV_NOPTS_VALUE, .back_ptr= AV_NOPTS_VALUE};
+ syncpoint_t *sp, *next_node[2]= {&nopts_sp, &nopts_sp};
+ int64_t pos, pos2, ts;
+ int i;
+
+ if(st->index_entries){
+ int index= av_index_search_timestamp(st, pts, flags);
+ if(index<0)
+ return -1;
+
+ pos2= st->index_entries[index].pos;
+ ts = st->index_entries[index].timestamp;
+ }else{
+ av_tree_find(nut->syncpoints, &dummy, sp_pts_cmp, next_node);
+ av_log(s, AV_LOG_DEBUG, "%Ld-%Ld %Ld-%Ld\n", next_node[0]->pos, next_node[1]->pos,
+ next_node[0]->ts , next_node[1]->ts);
+ pos= av_gen_search(s, -1, dummy.ts, next_node[0]->pos, next_node[1]->pos, next_node[1]->pos,
+ next_node[0]->ts , next_node[1]->ts, AVSEEK_FLAG_BACKWARD, &ts, nut_read_timestamp);
+
+ if(!(flags & AVSEEK_FLAG_BACKWARD)){
+ dummy.pos= pos+16;
+ next_node[1]= &nopts_sp;
+ av_tree_find(nut->syncpoints, &dummy, sp_pos_cmp, next_node);
+ pos2= av_gen_search(s, -2, dummy.pos, next_node[0]->pos , next_node[1]->pos, next_node[1]->pos,
+ next_node[0]->back_ptr, next_node[1]->back_ptr, flags, &ts, nut_read_timestamp);
+ if(pos2>=0)
+ pos= pos2;
+ //FIXME dir but i think it doesnt matter
+ }
+ dummy.pos= pos;
+ sp= av_tree_find(nut->syncpoints, &dummy, sp_pos_cmp, NULL);
+
+ assert(sp);
+ pos2= sp->back_ptr - 15;
+ }
+ av_log(NULL, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos2);
+ pos= find_startcode(&s->pb, SYNCPOINT_STARTCODE, pos2);
+ url_fseek(&s->pb, pos, SEEK_SET);
+ av_log(NULL, AV_LOG_DEBUG, "SP: %"PRId64"\n", pos);
+ if(pos2 > pos || pos2 + 15 < pos){
+ av_log(NULL, AV_LOG_ERROR, "no syncpoint at backptr pos\n");
+ }
+ for(i=0; i<s->nb_streams; i++)
+ nut->stream[i].skip_until_key_frame=1;
+
+ return 0;
+}
+
+static int nut_read_close(AVFormatContext *s)
+{
+ NUTContext *nut = s->priv_data;
+
+ av_freep(&nut->time_base);
+ av_freep(&nut->stream);
+
+ return 0;
+}
+
+#ifdef CONFIG_NUT_DEMUXER
+AVInputFormat nut_demuxer = {
+ "nut",
+ "nut format",
+ sizeof(NUTContext),
+ nut_probe,
+ nut_read_header,
+ nut_read_packet,
+ nut_read_close,
+ read_seek,
+ .extensions = "nut",
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/nuv.c b/contrib/ffmpeg/libavformat/nuv.c
new file mode 100644
index 000000000..3b96eb940
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/nuv.c
@@ -0,0 +1,241 @@
+/*
+ * NuppelVideo demuxer.
+ * 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 "avformat.h"
+#include "riff.h"
+
+typedef struct {
+ int v_id;
+ int a_id;
+} NUVContext;
+
+typedef enum {
+ NUV_VIDEO = 'V',
+ NUV_EXTRADATA = 'D',
+ NUV_AUDIO = 'A',
+ NUV_SEEKP = 'R',
+ NUV_MYTHEXT = 'X'
+} frametype_t;
+
+static int nuv_probe(AVProbeData *p) {
+ if (p->buf_size < 12)
+ return 0;
+ if (!memcmp(p->buf, "NuppelVideo", 12))
+ return AVPROBE_SCORE_MAX;
+ if (!memcmp(p->buf, "MythTVVideo", 12))
+ return AVPROBE_SCORE_MAX;
+ return 0;
+}
+
+//! little macro to sanitize packet size
+#define PKTSIZE(s) (s & 0xffffff)
+
+/**
+ * \brief read until we found all data needed for decoding
+ * \param vst video stream of which to change parameters
+ * \param ast video stream of which to change parameters
+ * \param myth set if this is a MythTVVideo format file
+ * \return 1 if all required codec data was found
+ */
+static int get_codec_data(ByteIOContext *pb, AVStream *vst,
+ AVStream *ast, int myth) {
+ frametype_t frametype;
+ if (!vst && !myth)
+ return 1; // no codec data needed
+ while (!url_feof(pb)) {
+ int size, subtype;
+ frametype = get_byte(pb);
+ switch (frametype) {
+ case NUV_EXTRADATA:
+ subtype = get_byte(pb);
+ url_fskip(pb, 6);
+ size = PKTSIZE(get_le32(pb));
+ if (vst && subtype == 'R') {
+ vst->codec->extradata_size = size;
+ vst->codec->extradata = av_malloc(size);
+ get_buffer(pb, vst->codec->extradata, size);
+ size = 0;
+ if (!myth)
+ return 1;
+ }
+ break;
+ case NUV_MYTHEXT:
+ url_fskip(pb, 7);
+ size = PKTSIZE(get_le32(pb));
+ if (size != 128 * 4)
+ break;
+ get_le32(pb); // version
+ if (vst) {
+ vst->codec->codec_tag = get_le32(pb);
+ vst->codec->codec_id =
+ codec_get_id(codec_bmp_tags, vst->codec->codec_tag);
+ } else
+ url_fskip(pb, 4);
+
+ if (ast) {
+ ast->codec->codec_tag = get_le32(pb);
+ ast->codec->sample_rate = get_le32(pb);
+ ast->codec->bits_per_sample = get_le32(pb);
+ ast->codec->channels = get_le32(pb);
+ ast->codec->codec_id =
+ wav_codec_get_id(ast->codec->codec_tag,
+ ast->codec->bits_per_sample);
+ } else
+ url_fskip(pb, 4 * 4);
+
+ size -= 6 * 4;
+ url_fskip(pb, size);
+ return 1;
+ case NUV_SEEKP:
+ size = 11;
+ break;
+ default:
+ url_fskip(pb, 7);
+ size = PKTSIZE(get_le32(pb));
+ break;
+ }
+ url_fskip(pb, size);
+ }
+ return 0;
+}
+
+static int nuv_header(AVFormatContext *s, AVFormatParameters *ap) {
+ NUVContext *ctx = (NUVContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ char id_string[12], version_string[5];
+ double aspect, fps;
+ int is_mythtv, width, height, v_packs, a_packs;
+ int stream_nr = 0;
+ AVStream *vst = NULL, *ast = NULL;
+ get_buffer(pb, id_string, 12);
+ is_mythtv = !memcmp(id_string, "MythTVVideo", 12);
+ get_buffer(pb, version_string, 5);
+ url_fskip(pb, 3); // padding
+ width = get_le32(pb);
+ height = get_le32(pb);
+ get_le32(pb); // unused, "desiredwidth"
+ get_le32(pb); // unused, "desiredheight"
+ get_byte(pb); // 'P' == progressive, 'I' == interlaced
+ url_fskip(pb, 3); // padding
+ aspect = av_int2dbl(get_le64(pb));
+ fps = av_int2dbl(get_le64(pb));
+
+ // number of packets per stream type, -1 means unknown, e.g. streaming
+ v_packs = get_le32(pb);
+ a_packs = get_le32(pb);
+ get_le32(pb); // text
+
+ get_le32(pb); // keyframe distance (?)
+
+ if (v_packs) {
+ ctx->v_id = stream_nr++;
+ vst = av_new_stream(s, ctx->v_id);
+ vst->codec->codec_type = CODEC_TYPE_VIDEO;
+ vst->codec->codec_id = CODEC_ID_NUV;
+ vst->codec->codec_tag = MKTAG('R', 'J', 'P', 'G');
+ vst->codec->width = width;
+ vst->codec->height = height;
+ vst->codec->bits_per_sample = 10;
+ vst->codec->sample_aspect_ratio = av_d2q(aspect, 10000);
+ vst->r_frame_rate = av_d2q(1.0 / fps, 10000);
+ av_set_pts_info(vst, 32, 1, 1000);
+ } else
+ ctx->v_id = -1;
+
+ if (a_packs) {
+ ctx->a_id = stream_nr++;
+ ast = av_new_stream(s, ctx->a_id);
+ ast->codec->codec_type = CODEC_TYPE_AUDIO;
+ ast->codec->codec_id = CODEC_ID_PCM_S16LE;
+ ast->codec->channels = 2;
+ ast->codec->sample_rate = 44100;
+ ast->codec->bit_rate = 2 * 2 * 44100 * 8;
+ ast->codec->block_align = 2 * 2;
+ ast->codec->bits_per_sample = 16;
+ av_set_pts_info(ast, 32, 1, 1000);
+ } else
+ ctx->a_id = -1;
+
+ get_codec_data(pb, vst, ast, is_mythtv);
+ return 0;
+}
+
+#define HDRSIZE 12
+
+static int nuv_packet(AVFormatContext *s, AVPacket *pkt) {
+ NUVContext *ctx = (NUVContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ uint8_t hdr[HDRSIZE];
+ frametype_t frametype;
+ int ret, size;
+ while (!url_feof(pb)) {
+ ret = get_buffer(pb, hdr, HDRSIZE);
+ if (ret <= 0)
+ return ret ? ret : -1;
+ frametype = hdr[0];
+ size = PKTSIZE(LE_32(&hdr[8]));
+ switch (frametype) {
+ case NUV_VIDEO:
+ case NUV_EXTRADATA:
+ if (ctx->v_id < 0) {
+ av_log(s, AV_LOG_ERROR, "Video packet in file without video stream!\n");
+ url_fskip(pb, size);
+ break;
+ }
+ ret = av_new_packet(pkt, HDRSIZE + size);
+ if (ret < 0)
+ return ret;
+ pkt->pos = url_ftell(pb);
+ pkt->pts = LE_32(&hdr[4]);
+ pkt->stream_index = ctx->v_id;
+ memcpy(pkt->data, hdr, HDRSIZE);
+ ret = get_buffer(pb, pkt->data + HDRSIZE, size);
+ return ret;
+ case NUV_AUDIO:
+ if (ctx->a_id < 0) {
+ av_log(s, AV_LOG_ERROR, "Audio packet in file without audio stream!\n");
+ url_fskip(pb, size);
+ break;
+ }
+ ret = av_get_packet(pb, pkt, size);
+ pkt->pts = LE_32(&hdr[4]);
+ pkt->stream_index = ctx->a_id;
+ return ret;
+ case NUV_SEEKP:
+ // contains no data, size value is invalid
+ break;
+ default:
+ url_fskip(pb, size);
+ break;
+ }
+ }
+ return AVERROR_IO;
+}
+
+AVInputFormat nuv_demuxer = {
+ "nuv",
+ "NuppelVideo format",
+ sizeof(NUVContext),
+ nuv_probe,
+ nuv_header,
+ nuv_packet,
+ NULL,
+ NULL,
+};
diff --git a/contrib/ffmpeg/libavformat/ogg.c b/contrib/ffmpeg/libavformat/ogg.c
new file mode 100644
index 000000000..369fa4639
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/ogg.c
@@ -0,0 +1,283 @@
+/*
+ * Ogg bitstream support
+ * Mark Hills <mark@pogo.org.uk>
+ *
+ * Uses libogg, but requires libvorbisenc to construct correct headers
+ * when containing Vorbis stream -- currently the only format supported
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+
+#include <ogg/ogg.h>
+
+#include "avformat.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+#define DECODER_BUFFER_SIZE 4096
+
+
+typedef struct OggContext {
+ /* output */
+ ogg_stream_state os ;
+ int header_handled ;
+ ogg_packet op;
+
+ /* input */
+ ogg_sync_state oy ;
+} OggContext ;
+
+
+#ifdef CONFIG_MUXERS
+static int ogg_write_header(AVFormatContext *avfcontext)
+{
+ OggContext *context = avfcontext->priv_data;
+ ogg_packet *op= &context->op;
+ int n;
+
+ ogg_stream_init(&context->os, 31415);
+
+ for(n = 0 ; n < avfcontext->nb_streams ; n++) {
+ AVCodecContext *codec = avfcontext->streams[n]->codec;
+ uint8_t *headers = codec->extradata;
+ int headers_len = codec->extradata_size;
+ uint8_t *header_start[3];
+ int header_len[3];
+ int i, j;
+
+ av_set_pts_info(avfcontext->streams[n], 60, 1, AV_TIME_BASE);
+
+ for(j=1,i=0;i<2;++i, ++j) {
+ header_len[i]=0;
+ while(j<headers_len && headers[j]==0xff) {
+ header_len[i]+=0xff;
+ ++j;
+ }
+ header_len[i]+=headers[j];
+ }
+ header_len[2]=headers_len-header_len[0]-header_len[1]-j;
+ headers+=j;
+ header_start[0] = headers;
+ header_start[1] = header_start[0] + header_len[0];
+ header_start[2] = header_start[1] + header_len[1];
+
+ for(i=0; i < 3; ++i){
+ op->bytes = header_len[i];
+
+ op->packet= header_start[i];
+ op->b_o_s= op->packetno==0;
+
+ ogg_stream_packetin(&context->os, op);
+
+ op->packetno++; //FIXME multiple streams
+ }
+
+ context->header_handled = 0 ;
+ }
+
+ return 0 ;
+}
+
+static int ogg_write_packet(AVFormatContext *avfcontext, AVPacket *pkt)
+{
+ OggContext *context = avfcontext->priv_data ;
+ AVCodecContext *avctx= avfcontext->streams[pkt->stream_index]->codec;
+ ogg_packet *op= &context->op;
+ ogg_page og ;
+ int64_t pts;
+
+ pts= av_rescale(pkt->pts, avctx->sample_rate, AV_TIME_BASE);
+
+// av_log(avfcontext, AV_LOG_DEBUG, "M%d\n", size);
+
+ /* flush header packets so audio starts on a new page */
+
+ if(!context->header_handled) {
+ while(ogg_stream_flush(&context->os, &og)) {
+ put_buffer(&avfcontext->pb, og.header, og.header_len) ;
+ put_buffer(&avfcontext->pb, og.body, og.body_len) ;
+ put_flush_packet(&avfcontext->pb);
+ }
+ context->header_handled = 1 ;
+ }
+
+ op->packet = (uint8_t*) pkt->data;
+ op->bytes = pkt->size;
+ op->b_o_s = op->packetno == 0;
+ op->granulepos= pts;
+
+ /* correct the fields in the packet -- essential for streaming */
+
+ ogg_stream_packetin(&context->os, op);
+
+ while(ogg_stream_pageout(&context->os, &og)) {
+ put_buffer(&avfcontext->pb, og.header, og.header_len);
+ put_buffer(&avfcontext->pb, og.body, og.body_len);
+ put_flush_packet(&avfcontext->pb);
+ }
+ op->packetno++;
+
+ return 0;
+}
+
+
+static int ogg_write_trailer(AVFormatContext *avfcontext) {
+ OggContext *context = avfcontext->priv_data ;
+ ogg_page og ;
+
+ while(ogg_stream_flush(&context->os, &og)) {
+ put_buffer(&avfcontext->pb, og.header, og.header_len) ;
+ put_buffer(&avfcontext->pb, og.body, og.body_len) ;
+ put_flush_packet(&avfcontext->pb);
+ }
+
+ ogg_stream_clear(&context->os) ;
+ return 0 ;
+}
+
+
+AVOutputFormat ogg_muxer = {
+ "ogg",
+ "Ogg Vorbis",
+ "audio/x-vorbis",
+ "ogg",
+ sizeof(OggContext),
+ CODEC_ID_VORBIS,
+ 0,
+ ogg_write_header,
+ ogg_write_packet,
+ ogg_write_trailer,
+} ;
+#endif //CONFIG_MUXERS
+
+#if 0
+static int next_packet(AVFormatContext *avfcontext, ogg_packet *op) {
+ OggContext *context = avfcontext->priv_data ;
+ ogg_page og ;
+ char *buf ;
+
+ while(ogg_stream_packetout(&context->os, op) != 1) {
+
+ /* while no pages are available, read in more data to the sync */
+ while(ogg_sync_pageout(&context->oy, &og) != 1) {
+ buf = ogg_sync_buffer(&context->oy, DECODER_BUFFER_SIZE) ;
+ if(get_buffer(&avfcontext->pb, buf, DECODER_BUFFER_SIZE) <= 0)
+ return 1 ;
+ ogg_sync_wrote(&context->oy, DECODER_BUFFER_SIZE) ;
+ }
+
+ /* got a page. Feed it into the stream and get the packet */
+ if(ogg_stream_pagein(&context->os, &og) != 0)
+ return 1 ;
+ }
+
+ return 0 ;
+}
+
+
+static int ogg_read_header(AVFormatContext *avfcontext, AVFormatParameters *ap)
+{
+ OggContext *context = avfcontext->priv_data;
+ ogg_packet op ;
+ char *buf ;
+ ogg_page og ;
+ AVStream *ast ;
+ AVCodecContext *codec;
+ uint8_t *p;
+ int i;
+
+ ogg_sync_init(&context->oy) ;
+ buf = ogg_sync_buffer(&context->oy, DECODER_BUFFER_SIZE) ;
+
+ if(get_buffer(&avfcontext->pb, buf, DECODER_BUFFER_SIZE) <= 0)
+ return AVERROR_IO ;
+
+ ogg_sync_wrote(&context->oy, DECODER_BUFFER_SIZE) ;
+ ogg_sync_pageout(&context->oy, &og) ;
+ ogg_stream_init(&context->os, ogg_page_serialno(&og)) ;
+ ogg_stream_pagein(&context->os, &og) ;
+
+ /* currently only one vorbis stream supported */
+
+ ast = av_new_stream(avfcontext, 0) ;
+ if(!ast)
+ return AVERROR_NOMEM ;
+ av_set_pts_info(ast, 60, 1, AV_TIME_BASE);
+
+ codec= &ast->codec;
+ codec->codec_type = CODEC_TYPE_AUDIO;
+ codec->codec_id = CODEC_ID_VORBIS;
+ for(i=0; i<3; i++){
+ if(next_packet(avfcontext, &op)){
+ return -1;
+ }
+ if(op.bytes >= (1<<16) || op.bytes < 0)
+ return -1;
+ codec->extradata_size+= 2 + op.bytes;
+ codec->extradata= av_realloc(codec->extradata, codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ memset(codec->extradata + codec->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+ p= codec->extradata + codec->extradata_size - 2 - op.bytes;
+ *(p++)= op.bytes>>8;
+ *(p++)= op.bytes&0xFF;
+ memcpy(p, op.packet, op.bytes);
+ }
+
+ return 0 ;
+}
+
+
+static int ogg_read_packet(AVFormatContext *avfcontext, AVPacket *pkt) {
+ ogg_packet op ;
+
+ if(next_packet(avfcontext, &op))
+ return AVERROR_IO ;
+ if(av_new_packet(pkt, op.bytes) < 0)
+ return AVERROR_IO ;
+ pkt->stream_index = 0 ;
+ memcpy(pkt->data, op.packet, op.bytes);
+ if(avfcontext->streams[0]->codec.sample_rate && op.granulepos!=-1)
+ pkt->pts= av_rescale(op.granulepos, AV_TIME_BASE, avfcontext->streams[0]->codec.sample_rate);
+// printf("%"PRId64" %d %d\n", pkt->pts, (int)op.granulepos, avfcontext->streams[0]->codec.sample_rate);
+
+ return op.bytes;
+}
+
+
+static int ogg_read_close(AVFormatContext *avfcontext) {
+ OggContext *context = avfcontext->priv_data ;
+
+ ogg_stream_clear(&context->os) ;
+ ogg_sync_clear(&context->oy) ;
+
+ return 0 ;
+}
+
+
+static AVInputFormat ogg_iformat = {
+ "ogg",
+ "Ogg Vorbis",
+ sizeof(OggContext),
+ NULL,
+ ogg_read_header,
+ ogg_read_packet,
+ ogg_read_close,
+ .extensions = "ogg",
+} ;
+#endif
diff --git a/contrib/ffmpeg/libavformat/ogg2.c b/contrib/ffmpeg/libavformat/ogg2.c
new file mode 100644
index 000000000..1e5d38620
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/ogg2.c
@@ -0,0 +1,697 @@
+/*
+ * Ogg bitstream support
+ * Luca Barbato <lu_zero@gentoo.org>
+ * Based on tcvp implementation
+ *
+ */
+
+/**
+ Copyright (C) 2005 Michael Ahlberg, Måns Rullgård
+
+ 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 <stdio.h>
+#include "ogg2.h"
+#include "avformat.h"
+
+#define MAX_PAGE_SIZE 65307
+#define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
+
+static ogg_codec_t *ogg_codecs[] = {
+ &vorbis_codec,
+ &theora_codec,
+ &flac_codec,
+ &ogm_video_codec,
+ &ogm_audio_codec,
+ &ogm_old_codec,
+ NULL
+};
+
+#if 0 // CONFIG_MUXERS
+static int
+ogg_write_header (AVFormatContext * avfcontext)
+{
+}
+
+static int
+ogg_write_packet (AVFormatContext * avfcontext, AVPacket * pkt)
+{
+}
+
+
+static int
+ogg_write_trailer (AVFormatContext * avfcontext)
+{
+}
+
+
+AVOutputFormat ogg_muxer = {
+ "ogg",
+ "Ogg Vorbis",
+ "audio/x-vorbis",
+ "ogg",
+ sizeof (OggContext),
+ CODEC_ID_VORBIS,
+ 0,
+ ogg_write_header,
+ ogg_write_packet,
+ ogg_write_trailer,
+};
+#endif //CONFIG_MUXERS
+
+//FIXME We could avoid some structure duplication
+static int
+ogg_save (AVFormatContext * s)
+{
+ ogg_t *ogg = s->priv_data;
+ ogg_state_t *ost =
+ av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
+ int i;
+ ost->pos = url_ftell (&s->pb);;
+ ost->curidx = ogg->curidx;
+ ost->next = ogg->state;
+ memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
+
+ for (i = 0; i < ogg->nstreams; i++){
+ ogg_stream_t *os = ogg->streams + i;
+ os->buf = av_malloc (os->bufsize);
+ memset (os->buf, 0, os->bufsize);
+ memcpy (os->buf, ost->streams[i].buf, os->bufpos);
+ }
+
+ ogg->state = ost;
+
+ return 0;
+}
+
+static int
+ogg_restore (AVFormatContext * s, int discard)
+{
+ ogg_t *ogg = s->priv_data;
+ ByteIOContext *bc = &s->pb;
+ ogg_state_t *ost = ogg->state;
+ int i;
+
+ if (!ost)
+ return 0;
+
+ ogg->state = ost->next;
+
+ if (!discard){
+ for (i = 0; i < ogg->nstreams; i++)
+ av_free (ogg->streams[i].buf);
+
+ url_fseek (bc, ost->pos, SEEK_SET);
+ ogg->curidx = ost->curidx;
+ memcpy (ogg->streams, ost->streams,
+ ogg->nstreams * sizeof (*ogg->streams));
+ }
+
+ av_free (ost);
+
+ return 0;
+}
+
+static int
+ogg_reset (ogg_t * ogg)
+{
+ int i;
+
+ for (i = 0; i < ogg->nstreams; i++){
+ ogg_stream_t *os = ogg->streams + i;
+ os->bufpos = 0;
+ os->pstart = 0;
+ os->psize = 0;
+ os->granule = -1;
+ os->lastgp = -1;
+ os->nsegs = 0;
+ os->segp = 0;
+ }
+
+ ogg->curidx = -1;
+
+ return 0;
+}
+
+static ogg_codec_t *
+ogg_find_codec (uint8_t * buf, int size)
+{
+ int i;
+
+ for (i = 0; ogg_codecs[i]; i++)
+ if (size >= ogg_codecs[i]->magicsize &&
+ !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
+ return ogg_codecs[i];
+
+ return NULL;
+}
+
+static int
+ogg_find_stream (ogg_t * ogg, int serial)
+{
+ int i;
+
+ for (i = 0; i < ogg->nstreams; i++)
+ if (ogg->streams[i].serial == serial)
+ return i;
+
+ return -1;
+}
+
+static int
+ogg_new_stream (AVFormatContext * s, uint32_t serial)
+{
+
+ ogg_t *ogg = s->priv_data;
+ int idx = ogg->nstreams++;
+ AVStream *st;
+ ogg_stream_t *os;
+
+ ogg->streams = av_realloc (ogg->streams,
+ ogg->nstreams * sizeof (*ogg->streams));
+ memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
+ os = ogg->streams + idx;
+ os->serial = serial;
+ os->bufsize = DECODER_BUFFER_SIZE;
+ os->buf = av_malloc(os->bufsize);
+ os->header = -1;
+
+ st = av_new_stream (s, idx);
+ if (!st)
+ return AVERROR_NOMEM;
+
+ av_set_pts_info(st, 64, 1, 1000000);
+
+ return idx;
+}
+
+static int
+ogg_new_buf(ogg_t *ogg, int idx)
+{
+ ogg_stream_t *os = ogg->streams + idx;
+ uint8_t *nb = av_malloc(os->bufsize);
+ int size = os->bufpos - os->pstart;
+ if(os->buf){
+ memcpy(nb, os->buf + os->pstart, size);
+ av_free(os->buf);
+ }
+ os->buf = nb;
+ os->bufpos = size;
+ os->pstart = 0;
+
+ return 0;
+}
+
+static int
+ogg_read_page (AVFormatContext * s, int *str)
+{
+ ByteIOContext *bc = &s->pb;
+ ogg_t *ogg = s->priv_data;
+ ogg_stream_t *os;
+ int i = 0;
+ int flags, nsegs;
+ uint64_t gp;
+ uint32_t serial;
+ uint32_t seq;
+ uint32_t crc;
+ int size, idx;
+ uint8_t sync[4];
+ int sp = 0;
+
+ if (get_buffer (bc, sync, 4) < 4)
+ return -1;
+
+ do{
+ int c;
+
+ if (sync[sp & 3] == 'O' &&
+ sync[(sp + 1) & 3] == 'g' &&
+ sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
+ break;
+
+ c = url_fgetc (bc);
+ if (c < 0)
+ return -1;
+ sync[sp++ & 3] = c;
+ }while (i++ < MAX_PAGE_SIZE);
+
+ if (i >= MAX_PAGE_SIZE){
+ av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
+ return -1;
+ }
+
+ if (url_fgetc (bc) != 0) /* version */
+ return -1;
+
+ flags = url_fgetc (bc);
+ gp = get_le64 (bc);
+ serial = get_le32 (bc);
+ seq = get_le32 (bc);
+ crc = get_le32 (bc);
+ nsegs = url_fgetc (bc);
+
+ idx = ogg_find_stream (ogg, serial);
+ if (idx < 0){
+ idx = ogg_new_stream (s, serial);
+ if (idx < 0)
+ return -1;
+ }
+
+ os = ogg->streams + idx;
+
+ if(os->psize > 0)
+ ogg_new_buf(ogg, idx);
+
+ if (get_buffer (bc, os->segments, nsegs) < nsegs)
+ return -1;
+
+ os->nsegs = nsegs;
+ os->segp = 0;
+
+ size = 0;
+ for (i = 0; i < nsegs; i++)
+ size += os->segments[i];
+
+ if (flags & OGG_FLAG_CONT){
+ if (!os->psize){
+ while (os->segp < os->nsegs){
+ int seg = os->segments[os->segp++];
+ os->pstart += seg;
+ if (seg < 255)
+ break;
+ }
+ }
+ }else{
+ os->psize = 0;
+ }
+
+ if (os->bufsize - os->bufpos < size){
+ uint8_t *nb = av_malloc (os->bufsize *= 2);
+ memcpy (nb, os->buf, os->bufpos);
+ av_free (os->buf);
+ os->buf = nb;
+ }
+
+ if (get_buffer (bc, os->buf + os->bufpos, size) < size)
+ return -1;
+
+ os->lastgp = os->granule;
+ os->bufpos += size;
+ os->granule = gp;
+ os->flags = flags;
+
+ if (str)
+ *str = idx;
+
+ return 0;
+}
+
+static int
+ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize)
+{
+ ogg_t *ogg = s->priv_data;
+ int idx;
+ ogg_stream_t *os;
+ int complete = 0;
+ int segp = 0, psize = 0;
+
+#if 0
+ av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
+#endif
+
+ do{
+ idx = ogg->curidx;
+
+ while (idx < 0){
+ if (ogg_read_page (s, &idx) < 0)
+ return -1;
+ }
+
+ os = ogg->streams + idx;
+
+#if 0
+ av_log (s, AV_LOG_DEBUG,
+ "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
+ idx, os->pstart, os->psize, os->segp, os->nsegs);
+#endif
+
+ if (!os->codec){
+ if (os->header < 0){
+ os->codec = ogg_find_codec (os->buf, os->bufpos);
+ if (!os->codec){
+ os->header = 0;
+ return 0;
+ }
+ }else{
+ return 0;
+ }
+ }
+
+ segp = os->segp;
+ psize = os->psize;
+
+ while (os->segp < os->nsegs){
+ int ss = os->segments[os->segp++];
+ os->psize += ss;
+ if (ss < 255){
+ complete = 1;
+ break;
+ }
+ }
+
+ if (!complete && os->segp == os->nsegs){
+ ogg->curidx = -1;
+ }
+ }while (!complete);
+
+#if 0
+ av_log (s, AV_LOG_DEBUG,
+ "ogg_packet: idx %i, frame size %i, start %i\n",
+ idx, os->psize, os->pstart);
+#endif
+
+ ogg->curidx = idx;
+
+ if (os->header < 0){
+ int hdr = os->codec->header (s, idx);
+ if (!hdr){
+ os->header = os->seq;
+ os->segp = segp;
+ os->psize = psize;
+ ogg->headers = 1;
+ }else{
+ os->pstart += os->psize;
+ os->psize = 0;
+ }
+ }
+
+ if (os->header > -1 && os->seq > os->header){
+ if (os->codec && os->codec->packet)
+ os->codec->packet (s, idx);
+ if (str)
+ *str = idx;
+ if (dstart)
+ *dstart = os->pstart;
+ if (dsize)
+ *dsize = os->psize;
+ os->pstart += os->psize;
+ os->psize = 0;
+ }
+
+ os->seq++;
+ if (os->segp == os->nsegs)
+ ogg->curidx = -1;
+
+ return 0;
+}
+
+static int
+ogg_get_headers (AVFormatContext * s)
+{
+ ogg_t *ogg = s->priv_data;
+
+ do{
+ if (ogg_packet (s, NULL, NULL, NULL) < 0)
+ return -1;
+ }while (!ogg->headers);
+
+#if 0
+ av_log (s, AV_LOG_DEBUG, "found headers\n");
+#endif
+
+ return 0;
+}
+
+static uint64_t
+ogg_gptopts (AVFormatContext * s, int i, uint64_t gp)
+{
+ ogg_t *ogg = s->priv_data;
+ ogg_stream_t *os = ogg->streams + i;
+ uint64_t pts = AV_NOPTS_VALUE;
+
+ if(os->codec->gptopts){
+ pts = os->codec->gptopts(s, i, gp);
+ } else {
+ pts = gp;
+ }
+
+ return pts;
+}
+
+
+static int
+ogg_get_length (AVFormatContext * s)
+{
+ ogg_t *ogg = s->priv_data;
+ int idx = -1, i;
+ offset_t size, end;
+
+ if(s->pb.is_streamed)
+ return 0;
+
+// already set
+ if (s->duration != AV_NOPTS_VALUE)
+ return 0;
+
+ size = url_fsize(&s->pb);
+ if(size < 0)
+ return 0;
+ end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: size;
+
+ ogg_save (s);
+ url_fseek (&s->pb, end, SEEK_SET);
+
+ while (!ogg_read_page (s, &i)){
+ if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0)
+ idx = i;
+ }
+
+ if (idx != -1){
+ s->streams[idx]->duration =
+ ogg_gptopts (s, idx, ogg->streams[idx].granule);
+ }
+
+ ogg->size = size;
+ ogg_restore (s, 0);
+ ogg_save (s);
+ while (!ogg_read_page (s, &i)) {
+ if (i == idx && ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0)
+ break;
+ }
+ if (i == idx) {
+ s->streams[idx]->start_time = ogg_gptopts (s, idx, ogg->streams[idx].granule);
+ s->streams[idx]->duration -= s->streams[idx]->start_time;
+ }
+ ogg_restore (s, 0);
+
+ return 0;
+}
+
+
+static int
+ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
+{
+ ogg_t *ogg = s->priv_data;
+ ogg->curidx = -1;
+ //linear headers seek from start
+ if (ogg_get_headers (s) < 0){
+ return -1;
+ }
+
+ //linear granulepos seek from end
+ ogg_get_length (s);
+
+ //fill the extradata in the per codec callbacks
+ return 0;
+}
+
+
+static int
+ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
+{
+ ogg_t *ogg;
+ ogg_stream_t *os;
+ int idx = -1;
+ int pstart, psize;
+
+ //Get an ogg packet
+ do{
+ if (ogg_packet (s, &idx, &pstart, &psize) < 0)
+ return AVERROR_IO;
+ }while (idx < 0 || !s->streams[idx]);
+
+ ogg = s->priv_data;
+ os = ogg->streams + idx;
+
+ //Alloc a pkt
+ if (av_new_packet (pkt, psize) < 0)
+ return AVERROR_IO;
+ pkt->stream_index = idx;
+ memcpy (pkt->data, os->buf + pstart, psize);
+ if (os->lastgp != -1LL){
+ pkt->pts = ogg_gptopts (s, idx, os->lastgp);
+ os->lastgp = -1;
+ }
+
+ return psize;
+}
+
+
+static int
+ogg_read_close (AVFormatContext * s)
+{
+ ogg_t *ogg = s->priv_data;
+ int i;
+
+ for (i = 0; i < ogg->nstreams; i++){
+ av_free (ogg->streams[i].buf);
+ av_free (ogg->streams[i].private);
+ }
+ av_free (ogg->streams);
+ return 0;
+}
+
+
+static int
+ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts,
+ int flags)
+{
+ AVStream *st = s->streams[stream_index];
+ ogg_t *ogg = s->priv_data;
+ ByteIOContext *bc = &s->pb;
+ uint64_t min = 0, max = ogg->size;
+ uint64_t tmin = st->start_time, tmax = st->start_time + st->duration;
+ int64_t pts = AV_NOPTS_VALUE;
+
+ ogg_save (s);
+
+ if ((uint64_t)target_ts < tmin || target_ts < 0)
+ target_ts = tmin;
+ while (min <= max && tmin < tmax){
+ uint64_t p = min + (max - min) * (target_ts - tmin) / (tmax - tmin);
+ int i = -1;
+
+ url_fseek (bc, p, SEEK_SET);
+
+ while (!ogg_read_page (s, &i)){
+ if (i == stream_index && ogg->streams[i].granule != 0 &&
+ ogg->streams[i].granule != -1)
+ break;
+ }
+
+ if (i == -1)
+ break;
+
+ pts = ogg_gptopts (s, i, ogg->streams[i].granule);
+ p = url_ftell (bc);
+
+ if (FFABS (pts - target_ts) * st->time_base.num < st->time_base.den)
+ break;
+
+ if (pts > target_ts){
+ if (max == p && tmax == pts) {
+ // probably our tmin is wrong, causing us to always end up too late in the file
+ tmin = (target_ts + tmin + 1) / 2;
+ if (tmin == target_ts) {
+ url_fseek(bc, min, SEEK_SET);
+ break;
+ }
+ }
+ max = p;
+ tmax = pts;
+ }else{
+ if (min == p && tmin == pts) {
+ // probably our tmax is wrong, causing us to always end up too early in the file
+ tmax = (target_ts + tmax) / 2;
+ if (tmax == target_ts) {
+ url_fseek(bc, max, SEEK_SET);
+ break;
+ }
+ }
+ min = p;
+ tmin = pts;
+ }
+ }
+
+ if (FFABS (pts - target_ts) * st->time_base.num < st->time_base.den){
+ ogg_restore (s, 1);
+ ogg_reset (ogg);
+ }else{
+ ogg_restore (s, 0);
+ pts = AV_NOPTS_VALUE;
+ }
+
+ av_update_cur_dts(s, st, pts);
+ return 0;
+
+#if 0
+ //later...
+ int64_t pos;
+ if (av_seek_frame_binary (s, stream_index, target_ts, flags) < 0)
+ return -1;
+ pos = url_ftell (&s->pb);
+ ogg_read_timestamp (s, stream_index, &pos, pos - 1);
+#endif
+
+}
+
+#if 0
+static int64_t
+ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
+ int64_t pos_limit)
+{
+ ogg_t *ogg = s->priv_data;
+ ByteIOContext *bc = &s->pb;
+ int64_t pos, pts;
+
+ if (*pos_arg < 0)
+ return AV_NOPTS_VALUE;
+
+ pos = *pos_arg;
+}
+#endif
+
+static int ogg_probe(AVProbeData *p)
+{
+ if (p->buf_size < 6)
+ return 0;
+ if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
+ p->buf[2] == 'g' && p->buf[3] == 'S' &&
+ p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+AVInputFormat ogg_demuxer = {
+ "ogg",
+ "Ogg",
+ sizeof (ogg_t),
+ ogg_probe,
+ ogg_read_header,
+ ogg_read_packet,
+ ogg_read_close,
+ ogg_read_seek,
+// ogg_read_timestamp,
+ .extensions = "ogg",
+};
diff --git a/contrib/ffmpeg/libavformat/ogg2.h b/contrib/ffmpeg/libavformat/ogg2.h
new file mode 100644
index 000000000..dd6f24aab
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/ogg2.h
@@ -0,0 +1,85 @@
+/**
+ Copyright (C) 2005 Michael Ahlberg, Måns Rullgård
+
+ 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.
+**/
+
+#ifndef OGG_H
+#define OGG_H
+
+#include "avformat.h"
+
+typedef struct ogg_codec {
+ int8_t *magic;
+ uint8_t magicsize;
+ int8_t *name;
+ int (*header)(AVFormatContext *, int);
+ int (*packet)(AVFormatContext *, int);
+ uint64_t (*gptopts)(AVFormatContext *, int, uint64_t);
+} ogg_codec_t;
+
+typedef struct ogg_stream {
+ uint8_t *buf;
+ unsigned int bufsize;
+ unsigned int bufpos;
+ unsigned int pstart;
+ unsigned int psize;
+ uint32_t serial;
+ uint32_t seq;
+ uint64_t granule, lastgp;
+ int flags;
+ ogg_codec_t *codec;
+ int header;
+ int nsegs, segp;
+ uint8_t segments[255];
+ void *private;
+} ogg_stream_t;
+
+typedef struct ogg_state {
+ uint64_t pos;
+ int curidx;
+ struct ogg_state *next;
+ ogg_stream_t streams[1];
+} ogg_state_t;
+
+typedef struct ogg {
+ ogg_stream_t *streams;
+ int nstreams;
+ int headers;
+ int curidx;
+ uint64_t size;
+ ogg_state_t *state;
+} ogg_t;
+
+#define OGG_FLAG_CONT 1
+#define OGG_FLAG_BOS 2
+#define OGG_FLAG_EOS 4
+
+extern ogg_codec_t vorbis_codec;
+extern ogg_codec_t theora_codec;
+extern ogg_codec_t flac_codec;
+extern ogg_codec_t ogm_video_codec;
+extern ogg_codec_t ogm_audio_codec;
+extern ogg_codec_t ogm_old_codec;
+
+extern int vorbis_comment(AVFormatContext *ms, uint8_t *buf, int size);
+
+#endif
diff --git a/contrib/ffmpeg/libavformat/oggparseflac.c b/contrib/ffmpeg/libavformat/oggparseflac.c
new file mode 100644
index 000000000..8960088d8
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/oggparseflac.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2005 Matthieu CASTET
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include "avformat.h"
+#include "bitstream.h"
+#include "ogg2.h"
+
+#define FLAC_STREAMINFO_SIZE 0x22
+
+static int
+flac_header (AVFormatContext * s, int idx)
+{
+ ogg_t *ogg = s->priv_data;
+ ogg_stream_t *os = ogg->streams + idx;
+ AVStream *st = s->streams[idx];
+ GetBitContext gb;
+ int mdt;
+
+ if (os->buf[os->pstart] == 0xff)
+ return 0;
+
+ init_get_bits(&gb, os->buf + os->pstart, os->psize*8);
+ get_bits(&gb, 1); /* metadata_last */
+ mdt = get_bits(&gb, 7);
+
+ if (mdt == 0x7f) {
+ skip_bits(&gb, 4*8); /* "FLAC" */
+ if(get_bits(&gb, 8) != 1) /* unsupported major version */
+ return -1;
+ skip_bits(&gb, 8 + 16); /* minor version + header count */
+ skip_bits(&gb, 4*8); /* "fLaC" */
+
+ /* METADATA_BLOCK_HEADER */
+ if (get_bits(&gb, 32) != FLAC_STREAMINFO_SIZE)
+ return -1;
+
+ skip_bits(&gb, 16*2+24*2);
+
+ st->codec->sample_rate = get_bits_long(&gb, 20);
+ st->codec->channels = get_bits(&gb, 3) + 1;
+
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_FLAC;
+
+ st->codec->extradata =
+ av_malloc(FLAC_STREAMINFO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
+ memcpy (st->codec->extradata, os->buf + os->pstart + 5 + 4 + 4 + 4,
+ FLAC_STREAMINFO_SIZE);
+ st->codec->extradata_size = FLAC_STREAMINFO_SIZE;
+
+ st->time_base.num = 1;
+ st->time_base.den = st->codec->sample_rate;
+ } else if (mdt == 4) {
+ vorbis_comment (s, os->buf + os->pstart + 4, os->psize - 4);
+ }
+
+ return 1;
+}
+
+ogg_codec_t flac_codec = {
+ .magic = "\177FLAC",
+ .magicsize = 5,
+ .header = flac_header
+};
diff --git a/contrib/ffmpeg/libavformat/oggparseogm.c b/contrib/ffmpeg/libavformat/oggparseogm.c
new file mode 100644
index 000000000..8788e5d41
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/oggparseogm.c
@@ -0,0 +1,166 @@
+/**
+ Copyright (C) 2005 Michael Ahlberg, Måns Rullgård
+
+ 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 <stdlib.h>
+#include "avformat.h"
+#include "bitstream.h"
+#include "bswap.h"
+#include "ogg2.h"
+#include "riff.h"
+
+static int
+ogm_header(AVFormatContext *s, int idx)
+{
+ ogg_t *ogg = s->priv_data;
+ ogg_stream_t *os = ogg->streams + idx;
+ AVStream *st = s->streams[idx];
+ uint8_t *p = os->buf + os->pstart;
+ uint64_t time_unit;
+ uint64_t spu;
+ uint32_t default_len;
+
+ if(!(*p & 1))
+ return 0;
+ if(*p != 1)
+ return 1;
+
+ p++;
+
+ if(*p == 'v'){
+ int tag;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ p += 8;
+ tag = le2me_32(unaligned32(p));
+ st->codec->codec_id = codec_get_bmp_id(tag);
+ st->codec->codec_tag = tag;
+ } else {
+ int cid;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ p += 8;
+ p[4] = 0;
+ cid = strtol(p, NULL, 16);
+ st->codec->codec_id = codec_get_wav_id(cid);
+ }
+
+ p += 4;
+ p += 4; /* useless size field */
+
+ time_unit = le2me_64(unaligned64(p));
+ p += 8;
+ spu = le2me_64(unaligned64(p));
+ p += 8;
+ default_len = le2me_32(unaligned32(p));
+ p += 4;
+
+ p += 8; /* buffersize + bits_per_sample */
+
+ if(st->codec->codec_type == CODEC_TYPE_VIDEO){
+ st->codec->width = le2me_32(unaligned32(p));
+ p += 4;
+ st->codec->height = le2me_32(unaligned32(p));
+ st->codec->time_base.den = spu * 10000000;
+ st->codec->time_base.num = time_unit;
+ st->time_base = st->codec->time_base;
+ } else {
+ st->codec->channels = le2me_16(unaligned16(p));
+ p += 2;
+ p += 2; /* block_align */
+ st->codec->bit_rate = le2me_32(unaligned32(p)) * 8;
+ st->codec->sample_rate = spu * 10000000 / time_unit;
+ st->time_base.num = 1;
+ st->time_base.den = st->codec->sample_rate;
+ }
+
+ return 1;
+}
+
+static int
+ogm_dshow_header(AVFormatContext *s, int idx)
+{
+ ogg_t *ogg = s->priv_data;
+ ogg_stream_t *os = ogg->streams + idx;
+ AVStream *st = s->streams[idx];
+ uint8_t *p = os->buf + os->pstart;
+ uint32_t t;
+
+ if(!(*p & 1))
+ return 0;
+ if(*p != 1)
+ return 1;
+
+ t = le2me_32(unaligned32(p + 96));
+
+ if(t == 0x05589f80){
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = codec_get_bmp_id(le2me_32(unaligned32(p + 68)));
+ st->codec->time_base.den = 10000000;
+ st->codec->time_base.num = le2me_64(unaligned64(p + 164));
+ st->codec->width = le2me_32(unaligned32(p + 176));
+ st->codec->height = le2me_32(unaligned32(p + 180));
+ } else if(t == 0x05589f81){
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = codec_get_wav_id(le2me_16(unaligned16(p+124)));
+ st->codec->channels = le2me_16(unaligned16(p + 126));
+ st->codec->sample_rate = le2me_32(unaligned32(p + 128));
+ st->codec->bit_rate = le2me_32(unaligned32(p + 132)) * 8;
+ }
+
+ return 1;
+}
+
+static int
+ogm_packet(AVFormatContext *s, int idx)
+{
+ ogg_t *ogg = s->priv_data;
+ ogg_stream_t *os = ogg->streams + idx;
+ uint8_t *p = os->buf + os->pstart;
+ int lb;
+
+ lb = ((*p & 2) << 1) | ((*p >> 6) & 3);
+ os->pstart += lb + 1;
+ os->psize -= lb + 1;
+
+ return 0;
+}
+
+ogg_codec_t ogm_video_codec = {
+ .magic = "\001video",
+ .magicsize = 6,
+ .header = ogm_header,
+ .packet = ogm_packet
+};
+
+ogg_codec_t ogm_audio_codec = {
+ .magic = "\001audio",
+ .magicsize = 6,
+ .header = ogm_header,
+ .packet = ogm_packet
+};
+
+ogg_codec_t ogm_old_codec = {
+ .magic = "\001Direct Show Samples embedded in Ogg",
+ .magicsize = 35,
+ .header = ogm_dshow_header,
+ .packet = ogm_packet
+};
diff --git a/contrib/ffmpeg/libavformat/oggparsetheora.c b/contrib/ffmpeg/libavformat/oggparsetheora.c
new file mode 100644
index 000000000..9052bbbea
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/oggparsetheora.c
@@ -0,0 +1,129 @@
+/**
+ Copyright (C) 2005 Matthieu CASTET, Alex Beregszaszi
+
+ 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 <stdlib.h>
+#include "avformat.h"
+#include "bitstream.h"
+#include "bswap.h"
+#include "ogg2.h"
+
+typedef struct theora_params {
+ int gpshift;
+ int gpmask;
+} theora_params_t;
+
+static int
+theora_header (AVFormatContext * s, int idx)
+{
+ ogg_t *ogg = s->priv_data;
+ ogg_stream_t *os = ogg->streams + idx;
+ AVStream *st = s->streams[idx];
+ theora_params_t *thp = os->private;
+ int cds = st->codec->extradata_size + os->psize + 2;
+ uint8_t *cdp;
+
+ if(!(os->buf[os->pstart] & 0x80))
+ return 0;
+
+ if(!thp){
+ thp = av_mallocz(sizeof(*thp));
+ os->private = thp;
+ }
+
+ if (os->buf[os->pstart] == 0x80) {
+ GetBitContext gb;
+ int version;
+
+ init_get_bits(&gb, os->buf + os->pstart, os->psize*8);
+
+ skip_bits(&gb, 7*8); /* 0x80"theora" */
+
+ version = get_bits(&gb, 8) << 16;
+ version |= get_bits(&gb, 8) << 8;
+ version |= get_bits(&gb, 8);
+
+ if (version < 0x030100)
+ {
+ av_log(s, AV_LOG_ERROR,
+ "Too old or unsupported Theora (%x)\n", version);
+ return -1;
+ }
+
+ st->codec->width = get_bits(&gb, 16) << 4;
+ st->codec->height = get_bits(&gb, 16) << 4;
+
+ if (version >= 0x030400)
+ skip_bits(&gb, 164);
+ else if (version >= 0x030200)
+ skip_bits(&gb, 64);
+ st->codec->time_base.den = get_bits(&gb, 32);
+ st->codec->time_base.num = get_bits(&gb, 32);
+ st->time_base = st->codec->time_base;
+
+ st->codec->sample_aspect_ratio.num = get_bits(&gb, 24);
+ st->codec->sample_aspect_ratio.den = get_bits(&gb, 24);
+
+ if (version >= 0x030200)
+ skip_bits(&gb, 38);
+ if (version >= 0x304000)
+ skip_bits(&gb, 2);
+
+ thp->gpshift = get_bits(&gb, 5);
+ thp->gpmask = (1 << thp->gpshift) - 1;
+
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_THEORA;
+
+ } else if (os->buf[os->pstart] == 0x83) {
+ vorbis_comment (s, os->buf + os->pstart + 7, os->psize - 8);
+ }
+
+ st->codec->extradata = av_realloc (st->codec->extradata, cds);
+ cdp = st->codec->extradata + st->codec->extradata_size;
+ *cdp++ = os->psize >> 8;
+ *cdp++ = os->psize & 0xff;
+ memcpy (cdp, os->buf + os->pstart, os->psize);
+ st->codec->extradata_size = cds;
+
+ return 1;
+}
+
+static uint64_t
+theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp)
+{
+ ogg_t *ogg = ctx->priv_data;
+ ogg_stream_t *os = ogg->streams + idx;
+ theora_params_t *thp = os->private;
+ uint64_t iframe = gp >> thp->gpshift;
+ uint64_t pframe = gp & thp->gpmask;
+
+ return iframe + pframe;
+}
+
+ogg_codec_t theora_codec = {
+ .magic = "\200theora",
+ .magicsize = 7,
+ .header = theora_header,
+ .gptopts = theora_gptopts
+};
diff --git a/contrib/ffmpeg/libavformat/oggparsevorbis.c b/contrib/ffmpeg/libavformat/oggparsevorbis.c
new file mode 100644
index 000000000..5de221cb4
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/oggparsevorbis.c
@@ -0,0 +1,205 @@
+/**
+ Copyright (C) 2005 Michael Ahlberg, Måns Rullgård
+
+ 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 <stdlib.h>
+#include "avformat.h"
+#include "bitstream.h"
+#include "bswap.h"
+#include "ogg2.h"
+
+extern int
+vorbis_comment (AVFormatContext * as, uint8_t *buf, int size)
+{
+ char *p = buf;
+ int s, n, j;
+
+ if (size < 4)
+ return -1;
+
+ s = le2me_32 (unaligned32 (p));
+ p += 4;
+ size -= 4;
+
+ if (size < s + 4)
+ return -1;
+
+ p += s;
+ size -= s;
+
+ n = le2me_32 (unaligned32 (p));
+ p += 4;
+ size -= 4;
+
+ while (size >= 4){
+ char *t, *v;
+ int tl, vl;
+
+ s = le2me_32 (unaligned32 (p));
+ p += 4;
+ size -= 4;
+
+ if (size < s)
+ break;
+
+ t = p;
+ p += s;
+ size -= s;
+ n--;
+
+ v = memchr (t, '=', s);
+ if (!v)
+ continue;
+
+ tl = v - t;
+ vl = s - tl - 1;
+ v++;
+
+ if (tl && vl){
+ char tt[tl + 1];
+ char ct[vl + 1];
+
+ for (j = 0; j < tl; j++)
+ tt[j] = toupper (t[j]);
+ tt[tl] = 0;
+
+ memcpy (ct, v, vl);
+ ct[vl] = 0;
+
+ // took from Vorbis_I_spec
+ if (!strcmp (tt, "AUTHOR"))
+ strncpy (as->author, ct, FFMIN(sizeof (as->author), vl));
+ else if (!strcmp (tt, "TITLE"))
+ strncpy (as->title, ct, FFMIN(sizeof (as->title), vl));
+ else if (!strcmp (tt, "COPYRIGHT"))
+ strncpy (as->copyright, ct, FFMIN(sizeof (as->copyright), vl));
+ else if (!strcmp (tt, "DESCRIPTION"))
+ strncpy (as->comment, ct, FFMIN(sizeof (as->comment), vl));
+ else if (!strcmp (tt, "GENRE"))
+ strncpy (as->genre, ct, FFMIN(sizeof (as->genre), vl));
+ else if (!strcmp (tt, "TRACKNUMBER"))
+ as->track = atoi (ct);
+ //Too bored to add others for today
+ }
+ }
+
+ if (size > 0)
+ av_log (as, AV_LOG_INFO, "%i bytes of comment header remain\n", size);
+ if (n > 0)
+ av_log (as, AV_LOG_INFO,
+ "truncated comment header, %i comments not found\n", n);
+
+ return 0;
+}
+
+
+/** Parse the vorbis header
+ * Vorbis Identification header from Vorbis_I_spec.html#vorbis-spec-codec
+ * [vorbis_version] = read 32 bits as unsigned integer | Not used
+ * [audio_channels] = read 8 bit integer as unsigned | Used
+ * [audio_sample_rate] = read 32 bits as unsigned integer | Used
+ * [bitrate_maximum] = read 32 bits as signed integer | Not used yet
+ * [bitrate_nominal] = read 32 bits as signed integer | Not used yet
+ * [bitrate_minimum] = read 32 bits as signed integer | Used as bitrate
+ * [blocksize_0] = read 4 bits as unsigned integer | Not Used
+ * [blocksize_1] = read 4 bits as unsigned integer | Not Used
+ * [framing_flag] = read one bit | Not Used
+ * */
+
+typedef struct {
+ unsigned int len[3];
+ unsigned char *packet[3];
+} oggvorbis_private_t;
+
+
+static unsigned int
+fixup_vorbis_headers(AVFormatContext * as, oggvorbis_private_t *priv,
+ void **buf)
+{
+ int i,offset, len;
+ unsigned char *ptr;
+
+ len = priv->len[0] + priv->len[1] + priv->len[2];
+ ptr = *buf = av_mallocz(len + len/255 + 64);
+
+ ptr[0] = 2;
+ offset = 1;
+ offset += av_xiphlacing(&ptr[offset], priv->len[0]);
+ offset += av_xiphlacing(&ptr[offset], priv->len[1]);
+ for(i = 0; i < 3; i++) {
+ memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
+ offset += priv->len[i];
+ }
+ *buf = av_realloc(*buf, offset);
+ return offset;
+}
+
+
+static int
+vorbis_header (AVFormatContext * s, int idx)
+{
+ ogg_t *ogg = s->priv_data;
+ ogg_stream_t *os = ogg->streams + idx;
+ AVStream *st = s->streams[idx];
+ oggvorbis_private_t *priv;
+
+ if (os->seq > 2)
+ return 0;
+
+ if(os->seq == 0) {
+ os->private = av_mallocz(sizeof(oggvorbis_private_t));
+ if(!os->private)
+ return 0;
+ }
+
+ priv = os->private;
+ priv->len[os->seq] = os->psize;
+ priv->packet[os->seq] = av_mallocz(os->psize);
+ memcpy(priv->packet[os->seq], os->buf + os->pstart, os->psize);
+ if (os->buf[os->pstart] == 1) {
+ uint8_t *p = os->buf + os->pstart + 11; //skip up to the audio channels
+ st->codec->channels = *p++;
+ st->codec->sample_rate = le2me_32 (unaligned32 (p));
+ p += 8; //skip maximum and and nominal bitrate
+ st->codec->bit_rate = le2me_32 (unaligned32 (p)); //Minimum bitrate
+
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_VORBIS;
+
+ st->time_base.num = 1;
+ st->time_base.den = st->codec->sample_rate;
+ } else if (os->buf[os->pstart] == 3) {
+ vorbis_comment (s, os->buf + os->pstart + 7, os->psize - 8);
+ } else {
+ st->codec->extradata_size =
+ fixup_vorbis_headers(s, priv, &st->codec->extradata);
+ }
+
+ return os->seq < 3;
+}
+
+ogg_codec_t vorbis_codec = {
+ .magic = "\001vorbis",
+ .magicsize = 7,
+ .header = vorbis_header
+};
diff --git a/contrib/ffmpeg/libavformat/os_support.c b/contrib/ffmpeg/libavformat/os_support.c
new file mode 100644
index 000000000..a66c867f0
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/os_support.c
@@ -0,0 +1,96 @@
+/*
+ * Various utilities for ffmpeg system
+ * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
+ * copyright (c) 2002 Francois Revol
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * 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 "avformat.h"
+#if defined(CONFIG_WINCE)
+/* Skip includes on WinCE. */
+#elif defined(__MINGW32__)
+#include <sys/types.h>
+#include <sys/timeb.h>
+#elif defined(CONFIG_OS2)
+#include <string.h>
+#include <sys/time.h>
+#else
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#endif
+#include <time.h>
+
+/**
+ * gets the current time in micro seconds.
+ */
+int64_t av_gettime(void)
+{
+#if defined(CONFIG_WINCE)
+ return timeGetTime() * int64_t_C(1000);
+#elif defined(__MINGW32__)
+ struct timeb tb;
+ _ftime(&tb);
+ return ((int64_t)tb.time * int64_t_C(1000) + (int64_t)tb.millitm) * int64_t_C(1000);
+#else
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
+#endif
+}
+
+#if !defined(CONFIG_WINCE) && !defined(HAVE_LOCALTIME_R)
+struct tm *localtime_r(const time_t *t, struct tm *tp)
+{
+ struct tm *l;
+
+ l = localtime(t);
+ if (!l)
+ return 0;
+ *tp = *l;
+ return tp;
+}
+#endif /* !defined(CONFIG_WINCE) && !defined(HAVE_LOCALTIME_R) */
+
+#if !defined(HAVE_INET_ATON) && defined(CONFIG_NETWORK)
+#include <stdlib.h>
+#include <strings.h>
+#include "barpainet.h"
+
+int inet_aton (const char * str, struct in_addr * add)
+{
+ const char * pch = str;
+ unsigned int add1 = 0, add2 = 0, add3 = 0, add4 = 0;
+
+ add1 = atoi(pch);
+ pch = strpbrk(pch,".");
+ if (pch == 0 || ++pch == 0) goto done;
+ add2 = atoi(pch);
+ pch = strpbrk(pch,".");
+ if (pch == 0 || ++pch == 0) goto done;
+ add3 = atoi(pch);
+ pch = strpbrk(pch,".");
+ if (pch == 0 || ++pch == 0) goto done;
+ add4 = atoi(pch);
+
+done:
+ add->s_addr=(add4<<24)+(add3<<16)+(add2<<8)+add1;
+
+ return 1;
+}
+#endif /* !defined(HAVE_INET_ATON) && defined(CONFIG_NETWORK) */
diff --git a/contrib/ffmpeg/libavformat/os_support.h b/contrib/ffmpeg/libavformat/os_support.h
new file mode 100644
index 000000000..e76a9aaaf
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/os_support.h
@@ -0,0 +1,53 @@
+/*
+ * various utilities for ffmpeg system
+ * 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 _OS_SUPPORT_H
+#define _OS_SUPPORT_H
+
+/**
+ * @file os_support.h
+ * miscellaneous OS support macros and functions.
+ *
+ * - usleep() (Win32, BeOS, OS/2)
+ * - floatf() (OS/2)
+ * - strcasecmp() (OS/2)
+ */
+
+#ifdef __MINGW32__
+__declspec(dllimport) void __stdcall Sleep(unsigned long dwMilliseconds);
+// # include <windows.h>
+# define usleep(t) Sleep((t) / 1000)
+#endif
+
+#ifdef __BEOS__
+# ifndef usleep
+# include <OS.h>
+# define usleep(t) snooze((bigtime_t)(t))
+# endif
+#endif
+
+#if defined(CONFIG_OS2)
+#include <stdlib.h>
+static inline int usleep(unsigned int t) { return _sleep2(t / 1000); }
+static inline int strcasecmp(const char* s1, const char* s2) { return stricmp(s1,s2); }
+#endif
+
+#endif /* _OS_SUPPORT_H */
diff --git a/contrib/ffmpeg/libavformat/png.c b/contrib/ffmpeg/libavformat/png.c
new file mode 100644
index 000000000..d62bf540a
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/png.c
@@ -0,0 +1,889 @@
+/*
+ * 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 "avformat.h"
+
+/* TODO:
+ * - add 2, 4 and 16 bit depth support
+ * - use filters when generating a png (better compression)
+ */
+
+#ifdef CONFIG_ZLIB
+#include <zlib.h>
+
+//#define DEBUG
+
+#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_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_IHDR 0x0001
+#define PNG_IDAT 0x0002
+#define PNG_ALLIMAGE 0x0004
+#define PNG_PLTE 0x0008
+
+#define NB_PASSES 7
+
+#define IOBUF_SIZE 4096
+
+typedef struct PNGDecodeState {
+ 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;
+} PNGDecodeState;
+
+static const uint8_t pngsig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
+
+/* Mask to determine which y pixels are valid in a pass */
+static const uint8_t png_pass_ymask[NB_PASSES] = {
+ 0x80, 0x80, 0x08, 0x88, 0x22, 0xaa, 0x55,
+};
+
+/* 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, 0xcc, 0x33, 0xff, 0x55,
+};
+
+/* minimum x value */
+static const uint8_t png_pass_xmin[NB_PASSES] = {
+ 0, 4, 0, 2, 0, 1, 0
+};
+
+/* x shift to get row width */
+static const uint8_t png_pass_xshift[NB_PASSES] = {
+ 3, 3, 2, 2, 1, 1, 0
+};
+
+/* Mask to determine which pixels are valid in a pass */
+static const uint8_t png_pass_mask[NB_PASSES] = {
+ 0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff
+};
+
+/* 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
+};
+
+static int png_probe(AVProbeData *pd)
+{
+ if (pd->buf_size >= 8 &&
+ memcmp(pd->buf, pngsig, 8) == 0)
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+static void *png_zalloc(void *opaque, unsigned int items, unsigned int size)
+{
+ return av_malloc(items * size);
+}
+
+static void png_zfree(void *opaque, void *ptr)
+{
+ av_free(ptr);
+}
+
+static int 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 */
+static int png_pass_row_size(int pass, int bits_per_pixel, int width)
+{
+ int shift, xmin, pass_width;
+
+ xmin = png_pass_xmin[pass];
+ if (width <= xmin)
+ return 0;
+ shift = png_pass_xshift[pass];
+ pass_width = (width - xmin + (1 << shift) - 1) >> shift;
+ return (pass_width * bits_per_pixel + 7) >> 3;
+}
+
+/* NOTE: we try to construct a good looking image at each pass. width
+ is the original image width. We also do pixel format convertion 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:
+ /* we must intialize the line to zero before writing to it */
+ if (pass == 0)
+ memset(dst, 0, (width + 7) >> 3);
+ 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] |= b << (7 - j);
+ }
+ if ((mask << j) & 0x80)
+ src_x++;
+ }
+ break;
+ default:
+ bpp = bits_per_pixel >> 3;
+ d = dst;
+ s = src;
+ if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
+ for(x = 0; x < width; x++) {
+ j = x & 7;
+ if ((dsp_mask << j) & 0x80) {
+ *(uint32_t *)d = (s[3] << 24) | (s[0] << 16) | (s[1] << 8) | s[2];
+ }
+ d += bpp;
+ if ((mask << j) & 0x80)
+ s += bpp;
+ }
+ } else {
+ 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;
+ }
+}
+
+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 = png_pass_mask[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;
+ }
+}
+
+/* XXX: optimize */
+/* NOTE: 'dst' can be equal to 'last' */
+static void png_filter_row(uint8_t *dst, int filter_type,
+ uint8_t *src, uint8_t *last, int size, int bpp)
+{
+ int i, p;
+
+ 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];
+ }
+ for(i = bpp; i < size; i++) {
+ p = dst[i - bpp];
+ dst[i] = p + src[i];
+ }
+ break;
+ case PNG_FILTER_VALUE_UP:
+ for(i = 0; i < size; i++) {
+ p = last[i];
+ dst[i] = p + src[i];
+ }
+ break;
+ case PNG_FILTER_VALUE_AVG:
+ for(i = 0; i < bpp; i++) {
+ p = (last[i] >> 1);
+ dst[i] = p + src[i];
+ }
+ for(i = bpp; i < size; i++) {
+ p = ((dst[i - bpp] + last[i]) >> 1);
+ dst[i] = p + src[i];
+ }
+ break;
+ case PNG_FILTER_VALUE_PAETH:
+ for(i = 0; i < bpp; i++) {
+ p = last[i];
+ dst[i] = p + src[i];
+ }
+ for(i = bpp; i < size; i++) {
+ int a, b, c, pa, pb, pc;
+
+ a = dst[i - bpp];
+ b = last[i];
+ c = last[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];
+ }
+ break;
+ }
+}
+
+static void convert_from_rgba32(uint8_t *dst, const uint8_t *src, int width)
+{
+ uint8_t *d;
+ int j;
+ unsigned int v;
+
+ d = dst;
+ for(j = 0; j < width; j++) {
+ v = ((const uint32_t *)src)[j];
+ d[0] = v >> 16;
+ d[1] = v >> 8;
+ d[2] = v;
+ d[3] = v >> 24;
+ d += 4;
+ }
+}
+
+static void convert_to_rgba32(uint8_t *dst, const uint8_t *src, int width)
+{
+ int j;
+ unsigned int r, g, b, a;
+
+ for(j = 0;j < width; j++) {
+ r = src[0];
+ g = src[1];
+ b = src[2];
+ a = src[3];
+ *(uint32_t *)dst = (a << 24) | (r << 16) | (g << 8) | b;
+ dst += 4;
+ src += 4;
+ }
+}
+
+/* process exactly one decompressed row */
+static void png_handle_row(PNGDecodeState *s)
+{
+ uint8_t *ptr, *last_row;
+ int got_line;
+
+ if (!s->interlace_type) {
+ ptr = s->image_buf + s->image_linesize * s->y;
+ /* need to swap bytes correctly for RGB_ALPHA */
+ if (s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
+ png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
+ s->last_row, s->row_size, s->bpp);
+ memcpy(s->last_row, s->tmp_row, s->row_size);
+ convert_to_rgba32(ptr, s->tmp_row, s->width);
+ } else {
+ /* in normal case, we avoid one copy */
+ if (s->y == 0)
+ last_row = s->last_row;
+ else
+ last_row = ptr - s->image_linesize;
+
+ png_filter_row(ptr, s->crow_buf[0], s->crow_buf + 1,
+ last_row, s->row_size, s->bpp);
+ }
+ s->y++;
+ if (s->y == s->height) {
+ s->state |= PNG_ALLIMAGE;
+ }
+ } else {
+ got_line = 0;
+ for(;;) {
+ ptr = s->image_buf + s->image_linesize * s->y;
+ if ((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->tmp_row, s->crow_buf[0], s->crow_buf + 1,
+ s->last_row, s->pass_row_size, s->bpp);
+ memcpy(s->last_row, s->tmp_row, s->pass_row_size);
+ got_line = 1;
+ }
+ if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) {
+ /* NOTE: rgba32 is handled directly in png_put_interlaced_row */
+ 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) {
+ for(;;) {
+ if (s->pass == NB_PASSES - 1) {
+ s->state |= PNG_ALLIMAGE;
+ goto the_end;
+ } else {
+ s->pass++;
+ s->y = 0;
+ s->pass_row_size = 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(PNGDecodeState *s, ByteIOContext *f, int length)
+{
+ uint8_t buf[IOBUF_SIZE];
+ int buf_size;
+ int ret;
+ while (length > 0) {
+ /* read the buffer */
+ buf_size = IOBUF_SIZE;
+ if (buf_size > length)
+ buf_size = length;
+ ret = get_buffer(f, buf, buf_size);
+ if (ret != buf_size)
+ return -1;
+ s->zstream.avail_in = buf_size;
+ s->zstream.next_in = buf;
+ /* 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) {
+ 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;
+ }
+ }
+ length -= buf_size;
+ }
+ return 0;
+}
+
+static int png_read(ByteIOContext *f,
+ int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
+{
+ AVImageInfo info1, *info = &info1;
+ PNGDecodeState s1, *s = &s1;
+ uint32_t tag, length;
+ int ret, crc;
+ uint8_t buf[8];
+
+ /* check signature */
+ ret = get_buffer(f, buf, 8);
+ if (ret != 8)
+ return -1;
+ if (memcmp(buf, pngsig, 8) != 0)
+ return -1;
+ memset(s, 0, sizeof(PNGDecodeState));
+ /* init the zlib */
+ s->zstream.zalloc = png_zalloc;
+ s->zstream.zfree = png_zfree;
+ s->zstream.opaque = NULL;
+ ret = inflateInit(&s->zstream);
+ if (ret != Z_OK)
+ return -1;
+ for(;;) {
+ if (url_feof(f))
+ goto fail;
+ length = get_be32(f);
+ if (length > 0x7fffffff)
+ goto fail;
+ tag = get_le32(f);
+#ifdef DEBUG
+ printf("png: tag=%c%c%c%c length=%u\n",
+ (tag & 0xff),
+ ((tag >> 8) & 0xff),
+ ((tag >> 16) & 0xff),
+ ((tag >> 24) & 0xff), length);
+#endif
+ switch(tag) {
+ case MKTAG('I', 'H', 'D', 'R'):
+ if (length != 13)
+ goto fail;
+ s->width = get_be32(f);
+ s->height = get_be32(f);
+ s->bit_depth = get_byte(f);
+ s->color_type = get_byte(f);
+ s->compression_type = get_byte(f);
+ s->filter_type = get_byte(f);
+ s->interlace_type = get_byte(f);
+ crc = get_be32(f);
+ s->state |= PNG_IHDR;
+#ifdef DEBUG
+ printf("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);
+#endif
+ break;
+ case MKTAG('I', 'D', 'A', 'T'):
+ if (!(s->state & PNG_IHDR))
+ goto fail;
+ if (!(s->state & PNG_IDAT)) {
+ /* init image info */
+ info->width = s->width;
+ info->height = s->height;
+ info->interleaved = (s->interlace_type != 0);
+
+ s->channels = 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 = (info->width * s->bits_per_pixel + 7) >> 3;
+
+ if (s->bit_depth == 8 &&
+ s->color_type == PNG_COLOR_TYPE_RGB) {
+ info->pix_fmt = PIX_FMT_RGB24;
+ } else if (s->bit_depth == 8 &&
+ s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
+ info->pix_fmt = PIX_FMT_RGBA32;
+ } else if (s->bit_depth == 8 &&
+ s->color_type == PNG_COLOR_TYPE_GRAY) {
+ info->pix_fmt = PIX_FMT_GRAY8;
+ } else if (s->bit_depth == 1 &&
+ s->color_type == PNG_COLOR_TYPE_GRAY) {
+ info->pix_fmt = PIX_FMT_MONOBLACK;
+ } else if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
+ info->pix_fmt = PIX_FMT_PAL8;
+ } else {
+ goto fail;
+ }
+ ret = alloc_cb(opaque, info);
+ if (ret)
+ goto the_end;
+
+ /* compute the compressed row size */
+ if (!s->interlace_type) {
+ s->crow_size = s->row_size + 1;
+ } else {
+ s->pass = 0;
+ s->pass_row_size = png_pass_row_size(s->pass,
+ s->bits_per_pixel,
+ s->width);
+ s->crow_size = s->pass_row_size + 1;
+ }
+#ifdef DEBUG
+ printf("row_size=%d crow_size =%d\n",
+ s->row_size, s->crow_size);
+#endif
+ s->image_buf = info->pict.data[0];
+ s->image_linesize = info->pict.linesize[0];
+ /* copy the palette if needed */
+ if (s->color_type == PNG_COLOR_TYPE_PALETTE)
+ memcpy(info->pict.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 */
+ s->crow_buf = av_malloc(s->row_size + 1);
+ if (!s->crow_buf)
+ goto fail;
+ s->zstream.avail_out = s->crow_size;
+ s->zstream.next_out = s->crow_buf;
+ }
+ s->state |= PNG_IDAT;
+ if (png_decode_idat(s, f, length) < 0)
+ goto fail;
+ /* skip crc */
+ crc = get_be32(f);
+ 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 = get_byte(f);
+ g = get_byte(f);
+ b = get_byte(f);
+ s->palette[i] = (0xff << 24) | (r << 16) | (g << 8) | b;
+ }
+ for(;i<256;i++) {
+ s->palette[i] = (0xff << 24);
+ }
+ s->state |= PNG_PLTE;
+ crc = get_be32(f);
+ }
+ 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 = get_byte(f);
+ s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
+ }
+ crc = get_be32(f);
+ }
+ break;
+ case MKTAG('I', 'E', 'N', 'D'):
+ if (!(s->state & PNG_ALLIMAGE))
+ goto fail;
+ crc = get_be32(f);
+ goto exit_loop;
+ default:
+ /* skip tag */
+ skip_tag:
+ url_fskip(f, length + 4);
+ break;
+ }
+ }
+ exit_loop:
+ ret = 0;
+ the_end:
+ inflateEnd(&s->zstream);
+ av_free(s->crow_buf);
+ av_free(s->last_row);
+ av_free(s->tmp_row);
+ return ret;
+ fail:
+ ret = -1;
+ goto the_end;
+}
+
+static void png_write_chunk(ByteIOContext *f, uint32_t tag,
+ const uint8_t *buf, int length)
+{
+ uint32_t crc;
+ uint8_t tagbuf[4];
+
+ put_be32(f, length);
+ crc = crc32(0, Z_NULL, 0);
+ tagbuf[0] = tag;
+ tagbuf[1] = tag >> 8;
+ tagbuf[2] = tag >> 16;
+ tagbuf[3] = tag >> 24;
+ crc = crc32(crc, tagbuf, 4);
+ put_le32(f, tag);
+ if (length > 0) {
+ crc = crc32(crc, buf, length);
+ put_buffer(f, buf, length);
+ }
+ put_be32(f, crc);
+}
+
+/* XXX: use avcodec generic function ? */
+static void to_be32(uint8_t *p, uint32_t v)
+{
+ p[0] = v >> 24;
+ p[1] = v >> 16;
+ p[2] = v >> 8;
+ p[3] = v;
+}
+
+typedef struct PNGEncodeState {
+ ByteIOContext *f;
+ z_stream zstream;
+ uint8_t buf[IOBUF_SIZE];
+} PNGEncodeState;
+
+
+/* XXX: do filtering */
+static int png_write_row(PNGEncodeState *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) {
+ png_write_chunk(s->f, 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 png_write(ByteIOContext *f, AVImageInfo *info)
+{
+ PNGEncodeState s1, *s = &s1;
+ int bit_depth, color_type, y, len, row_size, ret, is_progressive;
+ int bits_per_pixel, pass_row_size;
+ uint8_t *ptr;
+ uint8_t *crow_buf = NULL;
+ uint8_t *tmp_buf = NULL;
+
+ s->f = f;
+ is_progressive = info->interleaved;
+ switch(info->pix_fmt) {
+ case PIX_FMT_RGBA32:
+ bit_depth = 8;
+ color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ break;
+ case PIX_FMT_RGB24:
+ bit_depth = 8;
+ color_type = PNG_COLOR_TYPE_RGB;
+ break;
+ case PIX_FMT_GRAY8:
+ bit_depth = 8;
+ color_type = PNG_COLOR_TYPE_GRAY;
+ break;
+ case PIX_FMT_MONOBLACK:
+ bit_depth = 1;
+ color_type = PNG_COLOR_TYPE_GRAY;
+ break;
+ case PIX_FMT_PAL8:
+ bit_depth = 8;
+ color_type = PNG_COLOR_TYPE_PALETTE;
+ break;
+ default:
+ return -1;
+ }
+ bits_per_pixel = png_get_nb_channels(color_type) * bit_depth;
+ row_size = (info->width * bits_per_pixel + 7) >> 3;
+
+ s->zstream.zalloc = png_zalloc;
+ s->zstream.zfree = png_zfree;
+ s->zstream.opaque = NULL;
+ ret = deflateInit2(&s->zstream, Z_DEFAULT_COMPRESSION,
+ Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY);
+ if (ret != Z_OK)
+ return -1;
+ crow_buf = av_malloc(row_size + 1);
+ if (!crow_buf)
+ goto fail;
+ if (is_progressive) {
+ tmp_buf = av_malloc(row_size + 1);
+ if (!tmp_buf)
+ goto fail;
+ }
+
+ /* write png header */
+ put_buffer(f, pngsig, 8);
+
+ to_be32(s->buf, info->width);
+ to_be32(s->buf + 4, info->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(f, MKTAG('I', 'H', 'D', 'R'), s->buf, 13);
+
+ /* 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 *)info->pict.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;
+ ptr[0] = v >> 16;
+ ptr[1] = v >> 8;
+ ptr[2] = v;
+ ptr += 3;
+ }
+ png_write_chunk(f, MKTAG('P', 'L', 'T', 'E'), s->buf, 256 * 3);
+ if (has_alpha) {
+ png_write_chunk(f, 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) {
+ uint8_t *ptr1;
+ int pass;
+
+ for(pass = 0; pass < NB_PASSES; pass++) {
+ /* NOTE: a pass is completely omited if no pixels would be
+ output */
+ pass_row_size = png_pass_row_size(pass, bits_per_pixel, info->width);
+ if (pass_row_size > 0) {
+ for(y = 0; y < info->height; y++) {
+ if ((png_pass_ymask[pass] << (y & 7)) & 0x80) {
+ ptr = info->pict.data[0] + y * info->pict.linesize[0];
+ if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
+ convert_from_rgba32(tmp_buf, ptr, info->width);
+ ptr1 = tmp_buf;
+ } else {
+ ptr1 = ptr;
+ }
+ png_get_interlaced_row(crow_buf + 1, pass_row_size,
+ bits_per_pixel, pass,
+ ptr1, info->width);
+ crow_buf[0] = PNG_FILTER_VALUE_NONE;
+ png_write_row(s, crow_buf, pass_row_size + 1);
+ }
+ }
+ }
+ }
+ } else {
+ for(y = 0; y < info->height; y++) {
+ ptr = info->pict.data[0] + y * info->pict.linesize[0];
+ if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ convert_from_rgba32(crow_buf + 1, ptr, info->width);
+ else
+ memcpy(crow_buf + 1, ptr, row_size);
+ crow_buf[0] = PNG_FILTER_VALUE_NONE;
+ png_write_row(s, crow_buf, row_size + 1);
+ }
+ }
+ /* 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) {
+ png_write_chunk(f, 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(f, MKTAG('I', 'E', 'N', 'D'), NULL, 0);
+
+ put_flush_packet(f);
+ ret = 0;
+ the_end:
+ av_free(crow_buf);
+ av_free(tmp_buf);
+ deflateEnd(&s->zstream);
+ return ret;
+ fail:
+ ret = -1;
+ goto the_end;
+}
+
+AVImageFormat png_image_format = {
+ "png",
+ "png",
+ png_probe,
+ png_read,
+ (1 << PIX_FMT_RGBA32) | (1 << PIX_FMT_RGB24) | (1 << PIX_FMT_GRAY8) |
+ (1 << PIX_FMT_MONOBLACK) | (1 << PIX_FMT_PAL8),
+ png_write,
+ AVIMAGE_INTERLEAVED,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/pnm.c b/contrib/ffmpeg/libavformat/pnm.c
new file mode 100644
index 000000000..ade5d7c5d
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/pnm.c
@@ -0,0 +1,478 @@
+/*
+ * 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 "avformat.h"
+
+static inline int pnm_space(int c)
+{
+ return (c == ' ' || c == '\n' || c == '\r' || c == '\t');
+}
+
+static void pnm_get(ByteIOContext *f, char *str, int buf_size)
+{
+ char *s;
+ int c;
+
+ /* skip spaces and comments */
+ for(;;) {
+ c = url_fgetc(f);
+ if (c == '#') {
+ do {
+ c = url_fgetc(f);
+ } while (c != '\n' && c != URL_EOF);
+ } else if (!pnm_space(c)) {
+ break;
+ }
+ }
+
+ s = str;
+ while (c != URL_EOF && !pnm_space(c)) {
+ if ((s - str) < buf_size - 1)
+ *s++ = c;
+ c = url_fgetc(f);
+ }
+ *s = '\0';
+}
+
+static int pnm_read1(ByteIOContext *f,
+ int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque,
+ int allow_yuv)
+{
+ int i, n, linesize, h;
+ char buf1[32];
+ unsigned char *ptr;
+ AVImageInfo info1, *info = &info1;
+ int ret;
+
+ pnm_get(f, buf1, sizeof(buf1));
+ if (!strcmp(buf1, "P4")) {
+ info->pix_fmt = PIX_FMT_MONOWHITE;
+ } else if (!strcmp(buf1, "P5")) {
+ if (allow_yuv)
+ info->pix_fmt = PIX_FMT_YUV420P;
+ else
+ info->pix_fmt = PIX_FMT_GRAY8;
+ } else if (!strcmp(buf1, "P6")) {
+ info->pix_fmt = PIX_FMT_RGB24;
+ } else {
+ return AVERROR_INVALIDDATA;
+ }
+ pnm_get(f, buf1, sizeof(buf1));
+ info->width = atoi(buf1);
+ if (info->width <= 0)
+ return AVERROR_INVALIDDATA;
+ pnm_get(f, buf1, sizeof(buf1));
+ info->height = atoi(buf1);
+ if (info->height <= 0)
+ return AVERROR_INVALIDDATA;
+ if (info->pix_fmt != PIX_FMT_MONOWHITE) {
+ pnm_get(f, buf1, sizeof(buf1));
+ }
+
+ /* more check if YUV420 */
+ if (info->pix_fmt == PIX_FMT_YUV420P) {
+ if ((info->width & 1) != 0)
+ return AVERROR_INVALIDDATA;
+ h = (info->height * 2);
+ if ((h % 3) != 0)
+ return AVERROR_INVALIDDATA;
+ h /= 3;
+ info->height = h;
+ }
+
+ ret = alloc_cb(opaque, info);
+ if (ret)
+ return ret;
+
+ switch(info->pix_fmt) {
+ default:
+ return AVERROR_INVALIDDATA;
+ case PIX_FMT_RGB24:
+ n = info->width * 3;
+ goto do_read;
+ case PIX_FMT_GRAY8:
+ n = info->width;
+ goto do_read;
+ case PIX_FMT_MONOWHITE:
+ n = (info->width + 7) >> 3;
+ do_read:
+ ptr = info->pict.data[0];
+ linesize = info->pict.linesize[0];
+ for(i = 0; i < info->height; i++) {
+ get_buffer(f, ptr, n);
+ ptr += linesize;
+ }
+ break;
+ case PIX_FMT_YUV420P:
+ {
+ unsigned char *ptr1, *ptr2;
+
+ n = info->width;
+ ptr = info->pict.data[0];
+ linesize = info->pict.linesize[0];
+ for(i = 0; i < info->height; i++) {
+ get_buffer(f, ptr, n);
+ ptr += linesize;
+ }
+ ptr1 = info->pict.data[1];
+ ptr2 = info->pict.data[2];
+ n >>= 1;
+ h = info->height >> 1;
+ for(i = 0; i < h; i++) {
+ get_buffer(f, ptr1, n);
+ get_buffer(f, ptr2, n);
+ ptr1 += info->pict.linesize[1];
+ ptr2 += info->pict.linesize[2];
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+static int pnm_read(ByteIOContext *f,
+ int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
+{
+ return pnm_read1(f, alloc_cb, opaque, 0);
+}
+
+static int pgmyuv_read(ByteIOContext *f,
+ int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
+{
+ return pnm_read1(f, alloc_cb, opaque, 1);
+}
+
+static int pnm_write(ByteIOContext *pb, AVImageInfo *info)
+{
+ int i, h, h1, c, n, linesize;
+ char buf[100];
+ uint8_t *ptr, *ptr1, *ptr2;
+
+ h = info->height;
+ h1 = h;
+ switch(info->pix_fmt) {
+ case PIX_FMT_MONOWHITE:
+ c = '4';
+ n = (info->width + 7) >> 3;
+ break;
+ case PIX_FMT_GRAY8:
+ c = '5';
+ n = info->width;
+ break;
+ case PIX_FMT_RGB24:
+ c = '6';
+ n = info->width * 3;
+ break;
+ case PIX_FMT_YUV420P:
+ c = '5';
+ n = info->width;
+ h1 = (h * 3) / 2;
+ break;
+ default:
+ return AVERROR_INVALIDDATA;
+ }
+ snprintf(buf, sizeof(buf),
+ "P%c\n%d %d\n",
+ c, info->width, h1);
+ put_buffer(pb, buf, strlen(buf));
+ if (info->pix_fmt != PIX_FMT_MONOWHITE) {
+ snprintf(buf, sizeof(buf),
+ "%d\n", 255);
+ put_buffer(pb, buf, strlen(buf));
+ }
+
+ ptr = info->pict.data[0];
+ linesize = info->pict.linesize[0];
+ for(i=0;i<h;i++) {
+ put_buffer(pb, ptr, n);
+ ptr += linesize;
+ }
+
+ if (info->pix_fmt == PIX_FMT_YUV420P) {
+ h >>= 1;
+ n >>= 1;
+ ptr1 = info->pict.data[1];
+ ptr2 = info->pict.data[2];
+ for(i=0;i<h;i++) {
+ put_buffer(pb, ptr1, n);
+ put_buffer(pb, ptr2, n);
+ ptr1 += info->pict.linesize[1];
+ ptr2 += info->pict.linesize[2];
+ }
+ }
+ put_flush_packet(pb);
+ return 0;
+}
+
+static int pam_read(ByteIOContext *f,
+ int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
+{
+ int i, n, linesize, h, w, depth, maxval;
+ char buf1[32], tuple_type[32];
+ unsigned char *ptr;
+ AVImageInfo info1, *info = &info1;
+ int ret;
+
+ pnm_get(f, buf1, sizeof(buf1));
+ if (strcmp(buf1, "P7") != 0)
+ return AVERROR_INVALIDDATA;
+ w = -1;
+ h = -1;
+ maxval = -1;
+ depth = -1;
+ tuple_type[0] = '\0';
+ for(;;) {
+ pnm_get(f, buf1, sizeof(buf1));
+ if (!strcmp(buf1, "WIDTH")) {
+ pnm_get(f, buf1, sizeof(buf1));
+ w = strtol(buf1, NULL, 10);
+ } else if (!strcmp(buf1, "HEIGHT")) {
+ pnm_get(f, buf1, sizeof(buf1));
+ h = strtol(buf1, NULL, 10);
+ } else if (!strcmp(buf1, "DEPTH")) {
+ pnm_get(f, buf1, sizeof(buf1));
+ depth = strtol(buf1, NULL, 10);
+ } else if (!strcmp(buf1, "MAXVAL")) {
+ pnm_get(f, buf1, sizeof(buf1));
+ maxval = strtol(buf1, NULL, 10);
+ } else if (!strcmp(buf1, "TUPLETYPE")) {
+ pnm_get(f, buf1, sizeof(buf1));
+ pstrcpy(tuple_type, sizeof(tuple_type), buf1);
+ } 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')
+ return AVERROR_INVALIDDATA;
+ info->width = w;
+ info->height = h;
+ if (depth == 1) {
+ if (maxval == 1)
+ info->pix_fmt = PIX_FMT_MONOWHITE;
+ else
+ info->pix_fmt = PIX_FMT_GRAY8;
+ } else if (depth == 3) {
+ info->pix_fmt = PIX_FMT_RGB24;
+ } else if (depth == 4) {
+ info->pix_fmt = PIX_FMT_RGBA32;
+ } else {
+ return AVERROR_INVALIDDATA;
+ }
+ ret = alloc_cb(opaque, info);
+ if (ret)
+ return ret;
+
+ switch(info->pix_fmt) {
+ default:
+ return AVERROR_INVALIDDATA;
+ case PIX_FMT_RGB24:
+ n = info->width * 3;
+ goto do_read;
+ case PIX_FMT_GRAY8:
+ n = info->width;
+ goto do_read;
+ case PIX_FMT_MONOWHITE:
+ n = (info->width + 7) >> 3;
+ do_read:
+ ptr = info->pict.data[0];
+ linesize = info->pict.linesize[0];
+ for(i = 0; i < info->height; i++) {
+ get_buffer(f, ptr, n);
+ ptr += linesize;
+ }
+ break;
+ case PIX_FMT_RGBA32:
+ ptr = info->pict.data[0];
+ linesize = info->pict.linesize[0];
+ for(i = 0; i < info->height; i++) {
+ int j, r, g, b, a;
+
+ for(j = 0;j < w; j++) {
+ r = get_byte(f);
+ g = get_byte(f);
+ b = get_byte(f);
+ a = get_byte(f);
+ ((uint32_t *)ptr)[j] = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ ptr += linesize;
+ }
+ break;
+ }
+ return 0;
+}
+
+static int pam_write(ByteIOContext *pb, AVImageInfo *info)
+{
+ int i, h, w, n, linesize, depth, maxval;
+ const char *tuple_type;
+ char buf[100];
+ uint8_t *ptr;
+
+ h = info->height;
+ w = info->width;
+ switch(info->pix_fmt) {
+ case PIX_FMT_MONOWHITE:
+ n = (info->width + 7) >> 3;
+ depth = 1;
+ maxval = 1;
+ tuple_type = "BLACKANDWHITE";
+ break;
+ case PIX_FMT_GRAY8:
+ n = info->width;
+ depth = 1;
+ maxval = 255;
+ tuple_type = "GRAYSCALE";
+ break;
+ case PIX_FMT_RGB24:
+ n = info->width * 3;
+ depth = 3;
+ maxval = 255;
+ tuple_type = "RGB";
+ break;
+ case PIX_FMT_RGBA32:
+ n = info->width * 4;
+ depth = 4;
+ maxval = 255;
+ tuple_type = "RGB_ALPHA";
+ break;
+ default:
+ return AVERROR_INVALIDDATA;
+ }
+ snprintf(buf, sizeof(buf),
+ "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLETYPE %s\nENDHDR\n",
+ w, h, depth, maxval, tuple_type);
+ put_buffer(pb, buf, strlen(buf));
+
+ ptr = info->pict.data[0];
+ linesize = info->pict.linesize[0];
+
+ if (info->pix_fmt == PIX_FMT_RGBA32) {
+ int j;
+ unsigned int v;
+
+ for(i=0;i<h;i++) {
+ for(j=0;j<w;j++) {
+ v = ((uint32_t *)ptr)[j];
+ put_byte(pb, (v >> 16) & 0xff);
+ put_byte(pb, (v >> 8) & 0xff);
+ put_byte(pb, (v) & 0xff);
+ put_byte(pb, (v >> 24) & 0xff);
+ }
+ ptr += linesize;
+ }
+ } else {
+ for(i=0;i<h;i++) {
+ put_buffer(pb, ptr, n);
+ ptr += linesize;
+ }
+ }
+ put_flush_packet(pb);
+ return 0;
+}
+
+static int pnm_probe(AVProbeData *pd)
+{
+ const char *p = pd->buf;
+ if (pd->buf_size >= 8 &&
+ p[0] == 'P' &&
+ p[1] >= '4' && p[1] <= '6' &&
+ pnm_space(p[2]) )
+ return AVPROBE_SCORE_MAX - 1; /* to permit pgmyuv probe */
+ else
+ return 0;
+}
+
+static int pgmyuv_probe(AVProbeData *pd)
+{
+ if (match_ext(pd->filename, "pgmyuv"))
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+static int pam_probe(AVProbeData *pd)
+{
+ const char *p = pd->buf;
+ if (pd->buf_size >= 8 &&
+ p[0] == 'P' &&
+ p[1] == '7' &&
+ p[2] == '\n')
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+AVImageFormat pnm_image_format = {
+ "pnm",
+ NULL,
+ pnm_probe,
+ pnm_read,
+ 0,
+ NULL,
+};
+
+AVImageFormat pbm_image_format = {
+ "pbm",
+ "pbm",
+ NULL,
+ NULL,
+ (1 << PIX_FMT_MONOWHITE),
+ pnm_write,
+};
+
+AVImageFormat pgm_image_format = {
+ "pgm",
+ "pgm",
+ NULL,
+ NULL,
+ (1 << PIX_FMT_GRAY8),
+ pnm_write,
+};
+
+AVImageFormat ppm_image_format = {
+ "ppm",
+ "ppm",
+ NULL,
+ NULL,
+ (1 << PIX_FMT_RGB24),
+ pnm_write,
+};
+
+AVImageFormat pam_image_format = {
+ "pam",
+ "pam",
+ pam_probe,
+ pam_read,
+ (1 << PIX_FMT_MONOWHITE) | (1 << PIX_FMT_GRAY8) | (1 << PIX_FMT_RGB24) |
+ (1 << PIX_FMT_RGBA32),
+ pam_write,
+};
+
+AVImageFormat pgmyuv_image_format = {
+ "pgmyuv",
+ "pgmyuv",
+ pgmyuv_probe,
+ pgmyuv_read,
+ (1 << PIX_FMT_YUV420P),
+ pnm_write,
+};
diff --git a/contrib/ffmpeg/libavformat/psxstr.c b/contrib/ffmpeg/libavformat/psxstr.c
new file mode 100644
index 000000000..b03f65750
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/psxstr.c
@@ -0,0 +1,364 @@
+/*
+ * Sony Playstation (PSX) STR File Demuxer
+ * 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 psxstr.c
+ * PSX STR file demuxer
+ * by Mike Melanson (melanson@pcisys.net)
+ * This module handles streams that have been ripped from Sony Playstation
+ * CD games. This demuxer can handle either raw STR files (which are just
+ * concatenations of raw compact disc sectors) or STR files with 0x2C-byte
+ * RIFF headers, followed by CD sectors.
+ */
+
+#include "avformat.h"
+
+//#define PRINTSTUFF
+
+#define RIFF_TAG MKTAG('R', 'I', 'F', 'F')
+#define CDXA_TAG MKTAG('C', 'D', 'X', 'A')
+
+#define RAW_CD_SECTOR_SIZE 2352
+#define RAW_CD_SECTOR_DATA_SIZE 2304
+#define VIDEO_DATA_CHUNK_SIZE 0x7E0
+#define VIDEO_DATA_HEADER_SIZE 0x38
+#define RIFF_HEADER_SIZE 0x2C
+
+#define CDXA_TYPE_MASK 0x0E
+#define CDXA_TYPE_DATA 0x08
+#define CDXA_TYPE_AUDIO 0x04
+#define CDXA_TYPE_VIDEO 0x02
+
+#define STR_MAGIC (0x80010160)
+
+typedef struct StrChannel {
+
+ int type;
+#define STR_AUDIO 0
+#define STR_VIDEO 1
+
+ /* video parameters */
+ int width;
+ int height;
+ int video_stream_index;
+
+ /* audio parameters */
+ int sample_rate;
+ int channels;
+ int bits;
+ int audio_stream_index;
+} StrChannel;
+
+typedef struct StrDemuxContext {
+
+ /* a STR file can contain up to 32 channels of data */
+ StrChannel channels[32];
+
+ /* only decode the first audio and video channels encountered */
+ int video_channel;
+ int audio_channel;
+
+ int64_t pts;
+
+ unsigned char *video_chunk;
+ AVPacket tmp_pkt;
+} StrDemuxContext;
+
+static const char sync_header[12] = {0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00};
+
+static int str_probe(AVProbeData *p)
+{
+ int start;
+
+ /* need at least 0x38 bytes to validate */
+ if (p->buf_size < 0x38)
+ return 0;
+
+ if ((LE_32(&p->buf[0]) == RIFF_TAG) &&
+ (LE_32(&p->buf[8]) == CDXA_TAG)) {
+
+ /* RIFF header seen; skip 0x2C bytes */
+ start = RIFF_HEADER_SIZE;
+ } else
+ start = 0;
+
+ /* look for CD sync header (00, 0xFF x 10, 00) */
+ if (memcmp(p->buf+start,sync_header,sizeof(sync_header)))
+ return 0;
+
+ /* MPEG files (like those ripped from VCDs) can also look like this;
+ * only return half certainty */
+ return 50;
+}
+
+#if 0
+static void dump(unsigned char *buf,size_t len)
+{
+ int i;
+ for(i=0;i<len;i++) {
+ if ((i&15)==0) av_log(NULL, AV_LOG_DEBUG, "%04x ",i);
+ av_log(NULL, AV_LOG_DEBUG, "%02x ",buf[i]);
+ if ((i&15)==15) av_log(NULL, AV_LOG_DEBUG, "\n");
+ }
+ av_log(NULL, AV_LOG_DEBUG, "\n");
+}
+#endif
+
+static int str_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ ByteIOContext *pb = &s->pb;
+ StrDemuxContext *str = (StrDemuxContext *)s->priv_data;
+ AVStream *st;
+ unsigned char sector[RAW_CD_SECTOR_SIZE];
+ int start;
+ int i;
+ int channel;
+
+ /* initialize context members */
+ str->pts = 0;
+ str->audio_channel = -1; /* assume to audio or video */
+ str->video_channel = -1;
+ str->video_chunk = NULL;
+
+
+ /* skip over any RIFF header */
+ if (get_buffer(pb, sector, RIFF_HEADER_SIZE) != RIFF_HEADER_SIZE)
+ return AVERROR_IO;
+ if (LE_32(&sector[0]) == RIFF_TAG)
+ start = RIFF_HEADER_SIZE;
+ else
+ start = 0;
+
+ url_fseek(pb, start, SEEK_SET);
+
+ /* check through the first 32 sectors for individual channels */
+ for (i = 0; i < 32; i++) {
+ if (get_buffer(pb, sector, RAW_CD_SECTOR_SIZE) != RAW_CD_SECTOR_SIZE)
+ return AVERROR_IO;
+
+//printf("%02x %02x %02x %02x\n",sector[0x10],sector[0x11],sector[0x12],sector[0x13]);
+
+ channel = sector[0x11];
+ if (channel >= 32)
+ return AVERROR_INVALIDDATA;
+
+ switch (sector[0x12] & CDXA_TYPE_MASK) {
+
+ case CDXA_TYPE_DATA:
+ case CDXA_TYPE_VIDEO:
+ /* check if this channel gets to be the dominant video channel */
+ if (str->video_channel == -1) {
+ /* qualify the magic number */
+ if (LE_32(&sector[0x18]) != STR_MAGIC)
+ break;
+ str->video_channel = channel;
+ str->channels[channel].type = STR_VIDEO;
+ str->channels[channel].width = LE_16(&sector[0x28]);
+ str->channels[channel].height = LE_16(&sector[0x2A]);
+
+ /* allocate a new AVStream */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ av_set_pts_info(st, 64, 1, 15);
+
+ str->channels[channel].video_stream_index = st->index;
+
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_MDEC;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->width = str->channels[channel].width;
+ st->codec->height = str->channels[channel].height;
+ }
+ break;
+
+ case CDXA_TYPE_AUDIO:
+ /* check if this channel gets to be the dominant audio channel */
+ if (str->audio_channel == -1) {
+ int fmt;
+ str->audio_channel = channel;
+ str->channels[channel].type = STR_AUDIO;
+ str->channels[channel].channels =
+ (sector[0x13] & 0x01) ? 2 : 1;
+ str->channels[channel].sample_rate =
+ (sector[0x13] & 0x04) ? 18900 : 37800;
+ str->channels[channel].bits =
+ (sector[0x13] & 0x10) ? 8 : 4;
+
+ /* allocate a new AVStream */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ av_set_pts_info(st, 64, 128, str->channels[channel].sample_rate);
+
+ str->channels[channel].audio_stream_index = st->index;
+
+ fmt = sector[0x13];
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_ADPCM_XA;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->channels = (fmt&1)?2:1;
+ st->codec->sample_rate = (fmt&4)?18900:37800;
+ // st->codec->bit_rate = 0; //FIXME;
+ st->codec->block_align = 128;
+ }
+ break;
+
+ default:
+ /* ignore */
+ break;
+ }
+ }
+
+if (str->video_channel != -1)
+ av_log (s, AV_LOG_DEBUG, " video channel = %d, %d x %d %d\n", str->video_channel,
+ str->channels[str->video_channel].width,
+ str->channels[str->video_channel].height,str->channels[str->video_channel].video_stream_index);
+if (str->audio_channel != -1)
+ av_log (s, AV_LOG_DEBUG, " audio channel = %d, %d Hz, %d channels, %d bits/sample %d\n",
+ str->audio_channel,
+ str->channels[str->audio_channel].sample_rate,
+ str->channels[str->audio_channel].channels,
+ str->channels[str->audio_channel].bits,str->channels[str->audio_channel].audio_stream_index);
+
+ /* back to the start */
+ url_fseek(pb, start, SEEK_SET);
+
+ return 0;
+}
+
+static int str_read_packet(AVFormatContext *s,
+ AVPacket *ret_pkt)
+{
+ ByteIOContext *pb = &s->pb;
+ StrDemuxContext *str = (StrDemuxContext *)s->priv_data;
+ unsigned char sector[RAW_CD_SECTOR_SIZE];
+ int channel;
+ int packet_read = 0;
+ int ret = 0;
+ AVPacket *pkt;
+
+ while (!packet_read) {
+
+ if (get_buffer(pb, sector, RAW_CD_SECTOR_SIZE) != RAW_CD_SECTOR_SIZE)
+ return AVERROR_IO;
+
+ channel = sector[0x11];
+ if (channel >= 32)
+ return AVERROR_INVALIDDATA;
+
+ switch (sector[0x12] & CDXA_TYPE_MASK) {
+
+ case CDXA_TYPE_DATA:
+ case CDXA_TYPE_VIDEO:
+ /* check if this the video channel we care about */
+ if (channel == str->video_channel) {
+
+ int current_sector = LE_16(&sector[0x1C]);
+ int sector_count = LE_16(&sector[0x1E]);
+ int frame_size = LE_32(&sector[0x24]);
+ int bytes_to_copy;
+// printf("%d %d %d\n",current_sector,sector_count,frame_size);
+ /* if this is the first sector of the frame, allocate a pkt */
+ pkt = &str->tmp_pkt;
+ if (current_sector == 0) {
+ if (av_new_packet(pkt, frame_size))
+ return AVERROR_IO;
+
+ pkt->pos= url_ftell(pb) - RAW_CD_SECTOR_SIZE;
+ pkt->stream_index =
+ str->channels[channel].video_stream_index;
+ // pkt->pts = str->pts;
+
+ /* if there is no audio, adjust the pts after every video
+ * frame; assume 15 fps */
+ if (str->audio_channel != -1)
+ str->pts += (90000 / 15);
+ }
+
+ /* load all the constituent chunks in the video packet */
+ bytes_to_copy = frame_size - current_sector*VIDEO_DATA_CHUNK_SIZE;
+ if (bytes_to_copy>0) {
+ if (bytes_to_copy>VIDEO_DATA_CHUNK_SIZE) bytes_to_copy=VIDEO_DATA_CHUNK_SIZE;
+ memcpy(pkt->data + current_sector*VIDEO_DATA_CHUNK_SIZE,
+ sector + VIDEO_DATA_HEADER_SIZE, bytes_to_copy);
+ }
+ if (current_sector == sector_count-1) {
+ *ret_pkt = *pkt;
+ return 0;
+ }
+
+ }
+ break;
+
+ case CDXA_TYPE_AUDIO:
+#ifdef PRINTSTUFF
+printf (" dropping audio sector\n");
+#endif
+#if 1
+ /* check if this the video channel we care about */
+ if (channel == str->audio_channel) {
+ pkt = ret_pkt;
+ if (av_new_packet(pkt, 2304))
+ return AVERROR_IO;
+ memcpy(pkt->data,sector+24,2304);
+
+ pkt->stream_index =
+ str->channels[channel].audio_stream_index;
+ //pkt->pts = str->pts;
+ return 0;
+ }
+#endif
+ break;
+ default:
+ /* drop the sector and move on */
+#ifdef PRINTSTUFF
+printf (" dropping other sector\n");
+#endif
+ break;
+ }
+
+ if (url_feof(pb))
+ return AVERROR_IO;
+ }
+
+ return ret;
+}
+
+static int str_read_close(AVFormatContext *s)
+{
+ StrDemuxContext *str = (StrDemuxContext *)s->priv_data;
+
+ av_free(str->video_chunk);
+
+ return 0;
+}
+
+AVInputFormat str_demuxer = {
+ "psxstr",
+ "Sony Playstation STR format",
+ sizeof(StrDemuxContext),
+ str_probe,
+ str_read_header,
+ str_read_packet,
+ str_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/qtpalette.h b/contrib/ffmpeg/libavformat/qtpalette.h
new file mode 100644
index 000000000..ef4ccfa91
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/qtpalette.h
@@ -0,0 +1,295 @@
+/*
+ * Default Palettes for Quicktime Files
+ * Automatically generated from a utility derived from XAnim:
+ * http://xanim.va.pubnix.com/home.html
+ */
+
+#ifndef QTPALETTE_H
+#define QTPALETTE_H
+
+unsigned char ff_qt_default_palette_4[4 * 4] = {
+ 0x93, 0x65, 0x5E, 0x00,
+ 0xFF, 0xFF, 0xFF, 0x00,
+ 0xDF, 0xD0, 0xAB, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+};
+
+unsigned char ff_qt_default_palette_16[16 * 4] = {
+ 0xFF, 0xFB, 0xFF, 0x00,
+ 0xEF, 0xD9, 0xBB, 0x00,
+ 0xE8, 0xC9, 0xB1, 0x00,
+ 0x93, 0x65, 0x5E, 0x00,
+ 0xFC, 0xDE, 0xE8, 0x00,
+ 0x9D, 0x88, 0x91, 0x00,
+ 0xFF, 0xFF, 0xFF, 0x00,
+ 0xFF, 0xFF, 0xFF, 0x00,
+ 0xFF, 0xFF, 0xFF, 0x00,
+ 0x47, 0x48, 0x37, 0x00,
+ 0x7A, 0x5E, 0x55, 0x00,
+ 0xDF, 0xD0, 0xAB, 0x00,
+ 0xFF, 0xFB, 0xF9, 0x00,
+ 0xE8, 0xCA, 0xC5, 0x00,
+ 0x8A, 0x7C, 0x77, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+};
+
+unsigned char ff_qt_default_palette_256[256 * 4] = {
+ /* 0, 0x00 */ 0xFF, 0xFF, 0xFF, 0x00,
+ /* 1, 0x01 */ 0xFF, 0xFF, 0xCC, 0x00,
+ /* 2, 0x02 */ 0xFF, 0xFF, 0x99, 0x00,
+ /* 3, 0x03 */ 0xFF, 0xFF, 0x66, 0x00,
+ /* 4, 0x04 */ 0xFF, 0xFF, 0x33, 0x00,
+ /* 5, 0x05 */ 0xFF, 0xFF, 0x00, 0x00,
+ /* 6, 0x06 */ 0xFF, 0xCC, 0xFF, 0x00,
+ /* 7, 0x07 */ 0xFF, 0xCC, 0xCC, 0x00,
+ /* 8, 0x08 */ 0xFF, 0xCC, 0x99, 0x00,
+ /* 9, 0x09 */ 0xFF, 0xCC, 0x66, 0x00,
+ /* 10, 0x0A */ 0xFF, 0xCC, 0x33, 0x00,
+ /* 11, 0x0B */ 0xFF, 0xCC, 0x00, 0x00,
+ /* 12, 0x0C */ 0xFF, 0x99, 0xFF, 0x00,
+ /* 13, 0x0D */ 0xFF, 0x99, 0xCC, 0x00,
+ /* 14, 0x0E */ 0xFF, 0x99, 0x99, 0x00,
+ /* 15, 0x0F */ 0xFF, 0x99, 0x66, 0x00,
+ /* 16, 0x10 */ 0xFF, 0x99, 0x33, 0x00,
+ /* 17, 0x11 */ 0xFF, 0x99, 0x00, 0x00,
+ /* 18, 0x12 */ 0xFF, 0x66, 0xFF, 0x00,
+ /* 19, 0x13 */ 0xFF, 0x66, 0xCC, 0x00,
+ /* 20, 0x14 */ 0xFF, 0x66, 0x99, 0x00,
+ /* 21, 0x15 */ 0xFF, 0x66, 0x66, 0x00,
+ /* 22, 0x16 */ 0xFF, 0x66, 0x33, 0x00,
+ /* 23, 0x17 */ 0xFF, 0x66, 0x00, 0x00,
+ /* 24, 0x18 */ 0xFF, 0x33, 0xFF, 0x00,
+ /* 25, 0x19 */ 0xFF, 0x33, 0xCC, 0x00,
+ /* 26, 0x1A */ 0xFF, 0x33, 0x99, 0x00,
+ /* 27, 0x1B */ 0xFF, 0x33, 0x66, 0x00,
+ /* 28, 0x1C */ 0xFF, 0x33, 0x33, 0x00,
+ /* 29, 0x1D */ 0xFF, 0x33, 0x00, 0x00,
+ /* 30, 0x1E */ 0xFF, 0x00, 0xFF, 0x00,
+ /* 31, 0x1F */ 0xFF, 0x00, 0xCC, 0x00,
+ /* 32, 0x20 */ 0xFF, 0x00, 0x99, 0x00,
+ /* 33, 0x21 */ 0xFF, 0x00, 0x66, 0x00,
+ /* 34, 0x22 */ 0xFF, 0x00, 0x33, 0x00,
+ /* 35, 0x23 */ 0xFF, 0x00, 0x00, 0x00,
+ /* 36, 0x24 */ 0xCC, 0xFF, 0xFF, 0x00,
+ /* 37, 0x25 */ 0xCC, 0xFF, 0xCC, 0x00,
+ /* 38, 0x26 */ 0xCC, 0xFF, 0x99, 0x00,
+ /* 39, 0x27 */ 0xCC, 0xFF, 0x66, 0x00,
+ /* 40, 0x28 */ 0xCC, 0xFF, 0x33, 0x00,
+ /* 41, 0x29 */ 0xCC, 0xFF, 0x00, 0x00,
+ /* 42, 0x2A */ 0xCC, 0xCC, 0xFF, 0x00,
+ /* 43, 0x2B */ 0xCC, 0xCC, 0xCC, 0x00,
+ /* 44, 0x2C */ 0xCC, 0xCC, 0x99, 0x00,
+ /* 45, 0x2D */ 0xCC, 0xCC, 0x66, 0x00,
+ /* 46, 0x2E */ 0xCC, 0xCC, 0x33, 0x00,
+ /* 47, 0x2F */ 0xCC, 0xCC, 0x00, 0x00,
+ /* 48, 0x30 */ 0xCC, 0x99, 0xFF, 0x00,
+ /* 49, 0x31 */ 0xCC, 0x99, 0xCC, 0x00,
+ /* 50, 0x32 */ 0xCC, 0x99, 0x99, 0x00,
+ /* 51, 0x33 */ 0xCC, 0x99, 0x66, 0x00,
+ /* 52, 0x34 */ 0xCC, 0x99, 0x33, 0x00,
+ /* 53, 0x35 */ 0xCC, 0x99, 0x00, 0x00,
+ /* 54, 0x36 */ 0xCC, 0x66, 0xFF, 0x00,
+ /* 55, 0x37 */ 0xCC, 0x66, 0xCC, 0x00,
+ /* 56, 0x38 */ 0xCC, 0x66, 0x99, 0x00,
+ /* 57, 0x39 */ 0xCC, 0x66, 0x66, 0x00,
+ /* 58, 0x3A */ 0xCC, 0x66, 0x33, 0x00,
+ /* 59, 0x3B */ 0xCC, 0x66, 0x00, 0x00,
+ /* 60, 0x3C */ 0xCC, 0x33, 0xFF, 0x00,
+ /* 61, 0x3D */ 0xCC, 0x33, 0xCC, 0x00,
+ /* 62, 0x3E */ 0xCC, 0x33, 0x99, 0x00,
+ /* 63, 0x3F */ 0xCC, 0x33, 0x66, 0x00,
+ /* 64, 0x40 */ 0xCC, 0x33, 0x33, 0x00,
+ /* 65, 0x41 */ 0xCC, 0x33, 0x00, 0x00,
+ /* 66, 0x42 */ 0xCC, 0x00, 0xFF, 0x00,
+ /* 67, 0x43 */ 0xCC, 0x00, 0xCC, 0x00,
+ /* 68, 0x44 */ 0xCC, 0x00, 0x99, 0x00,
+ /* 69, 0x45 */ 0xCC, 0x00, 0x66, 0x00,
+ /* 70, 0x46 */ 0xCC, 0x00, 0x33, 0x00,
+ /* 71, 0x47 */ 0xCC, 0x00, 0x00, 0x00,
+ /* 72, 0x48 */ 0x99, 0xFF, 0xFF, 0x00,
+ /* 73, 0x49 */ 0x99, 0xFF, 0xCC, 0x00,
+ /* 74, 0x4A */ 0x99, 0xFF, 0x99, 0x00,
+ /* 75, 0x4B */ 0x99, 0xFF, 0x66, 0x00,
+ /* 76, 0x4C */ 0x99, 0xFF, 0x33, 0x00,
+ /* 77, 0x4D */ 0x99, 0xFF, 0x00, 0x00,
+ /* 78, 0x4E */ 0x99, 0xCC, 0xFF, 0x00,
+ /* 79, 0x4F */ 0x99, 0xCC, 0xCC, 0x00,
+ /* 80, 0x50 */ 0x99, 0xCC, 0x99, 0x00,
+ /* 81, 0x51 */ 0x99, 0xCC, 0x66, 0x00,
+ /* 82, 0x52 */ 0x99, 0xCC, 0x33, 0x00,
+ /* 83, 0x53 */ 0x99, 0xCC, 0x00, 0x00,
+ /* 84, 0x54 */ 0x99, 0x99, 0xFF, 0x00,
+ /* 85, 0x55 */ 0x99, 0x99, 0xCC, 0x00,
+ /* 86, 0x56 */ 0x99, 0x99, 0x99, 0x00,
+ /* 87, 0x57 */ 0x99, 0x99, 0x66, 0x00,
+ /* 88, 0x58 */ 0x99, 0x99, 0x33, 0x00,
+ /* 89, 0x59 */ 0x99, 0x99, 0x00, 0x00,
+ /* 90, 0x5A */ 0x99, 0x66, 0xFF, 0x00,
+ /* 91, 0x5B */ 0x99, 0x66, 0xCC, 0x00,
+ /* 92, 0x5C */ 0x99, 0x66, 0x99, 0x00,
+ /* 93, 0x5D */ 0x99, 0x66, 0x66, 0x00,
+ /* 94, 0x5E */ 0x99, 0x66, 0x33, 0x00,
+ /* 95, 0x5F */ 0x99, 0x66, 0x00, 0x00,
+ /* 96, 0x60 */ 0x99, 0x33, 0xFF, 0x00,
+ /* 97, 0x61 */ 0x99, 0x33, 0xCC, 0x00,
+ /* 98, 0x62 */ 0x99, 0x33, 0x99, 0x00,
+ /* 99, 0x63 */ 0x99, 0x33, 0x66, 0x00,
+ /* 100, 0x64 */ 0x99, 0x33, 0x33, 0x00,
+ /* 101, 0x65 */ 0x99, 0x33, 0x00, 0x00,
+ /* 102, 0x66 */ 0x99, 0x00, 0xFF, 0x00,
+ /* 103, 0x67 */ 0x99, 0x00, 0xCC, 0x00,
+ /* 104, 0x68 */ 0x99, 0x00, 0x99, 0x00,
+ /* 105, 0x69 */ 0x99, 0x00, 0x66, 0x00,
+ /* 106, 0x6A */ 0x99, 0x00, 0x33, 0x00,
+ /* 107, 0x6B */ 0x99, 0x00, 0x00, 0x00,
+ /* 108, 0x6C */ 0x66, 0xFF, 0xFF, 0x00,
+ /* 109, 0x6D */ 0x66, 0xFF, 0xCC, 0x00,
+ /* 110, 0x6E */ 0x66, 0xFF, 0x99, 0x00,
+ /* 111, 0x6F */ 0x66, 0xFF, 0x66, 0x00,
+ /* 112, 0x70 */ 0x66, 0xFF, 0x33, 0x00,
+ /* 113, 0x71 */ 0x66, 0xFF, 0x00, 0x00,
+ /* 114, 0x72 */ 0x66, 0xCC, 0xFF, 0x00,
+ /* 115, 0x73 */ 0x66, 0xCC, 0xCC, 0x00,
+ /* 116, 0x74 */ 0x66, 0xCC, 0x99, 0x00,
+ /* 117, 0x75 */ 0x66, 0xCC, 0x66, 0x00,
+ /* 118, 0x76 */ 0x66, 0xCC, 0x33, 0x00,
+ /* 119, 0x77 */ 0x66, 0xCC, 0x00, 0x00,
+ /* 120, 0x78 */ 0x66, 0x99, 0xFF, 0x00,
+ /* 121, 0x79 */ 0x66, 0x99, 0xCC, 0x00,
+ /* 122, 0x7A */ 0x66, 0x99, 0x99, 0x00,
+ /* 123, 0x7B */ 0x66, 0x99, 0x66, 0x00,
+ /* 124, 0x7C */ 0x66, 0x99, 0x33, 0x00,
+ /* 125, 0x7D */ 0x66, 0x99, 0x00, 0x00,
+ /* 126, 0x7E */ 0x66, 0x66, 0xFF, 0x00,
+ /* 127, 0x7F */ 0x66, 0x66, 0xCC, 0x00,
+ /* 128, 0x80 */ 0x66, 0x66, 0x99, 0x00,
+ /* 129, 0x81 */ 0x66, 0x66, 0x66, 0x00,
+ /* 130, 0x82 */ 0x66, 0x66, 0x33, 0x00,
+ /* 131, 0x83 */ 0x66, 0x66, 0x00, 0x00,
+ /* 132, 0x84 */ 0x66, 0x33, 0xFF, 0x00,
+ /* 133, 0x85 */ 0x66, 0x33, 0xCC, 0x00,
+ /* 134, 0x86 */ 0x66, 0x33, 0x99, 0x00,
+ /* 135, 0x87 */ 0x66, 0x33, 0x66, 0x00,
+ /* 136, 0x88 */ 0x66, 0x33, 0x33, 0x00,
+ /* 137, 0x89 */ 0x66, 0x33, 0x00, 0x00,
+ /* 138, 0x8A */ 0x66, 0x00, 0xFF, 0x00,
+ /* 139, 0x8B */ 0x66, 0x00, 0xCC, 0x00,
+ /* 140, 0x8C */ 0x66, 0x00, 0x99, 0x00,
+ /* 141, 0x8D */ 0x66, 0x00, 0x66, 0x00,
+ /* 142, 0x8E */ 0x66, 0x00, 0x33, 0x00,
+ /* 143, 0x8F */ 0x66, 0x00, 0x00, 0x00,
+ /* 144, 0x90 */ 0x33, 0xFF, 0xFF, 0x00,
+ /* 145, 0x91 */ 0x33, 0xFF, 0xCC, 0x00,
+ /* 146, 0x92 */ 0x33, 0xFF, 0x99, 0x00,
+ /* 147, 0x93 */ 0x33, 0xFF, 0x66, 0x00,
+ /* 148, 0x94 */ 0x33, 0xFF, 0x33, 0x00,
+ /* 149, 0x95 */ 0x33, 0xFF, 0x00, 0x00,
+ /* 150, 0x96 */ 0x33, 0xCC, 0xFF, 0x00,
+ /* 151, 0x97 */ 0x33, 0xCC, 0xCC, 0x00,
+ /* 152, 0x98 */ 0x33, 0xCC, 0x99, 0x00,
+ /* 153, 0x99 */ 0x33, 0xCC, 0x66, 0x00,
+ /* 154, 0x9A */ 0x33, 0xCC, 0x33, 0x00,
+ /* 155, 0x9B */ 0x33, 0xCC, 0x00, 0x00,
+ /* 156, 0x9C */ 0x33, 0x99, 0xFF, 0x00,
+ /* 157, 0x9D */ 0x33, 0x99, 0xCC, 0x00,
+ /* 158, 0x9E */ 0x33, 0x99, 0x99, 0x00,
+ /* 159, 0x9F */ 0x33, 0x99, 0x66, 0x00,
+ /* 160, 0xA0 */ 0x33, 0x99, 0x33, 0x00,
+ /* 161, 0xA1 */ 0x33, 0x99, 0x00, 0x00,
+ /* 162, 0xA2 */ 0x33, 0x66, 0xFF, 0x00,
+ /* 163, 0xA3 */ 0x33, 0x66, 0xCC, 0x00,
+ /* 164, 0xA4 */ 0x33, 0x66, 0x99, 0x00,
+ /* 165, 0xA5 */ 0x33, 0x66, 0x66, 0x00,
+ /* 166, 0xA6 */ 0x33, 0x66, 0x33, 0x00,
+ /* 167, 0xA7 */ 0x33, 0x66, 0x00, 0x00,
+ /* 168, 0xA8 */ 0x33, 0x33, 0xFF, 0x00,
+ /* 169, 0xA9 */ 0x33, 0x33, 0xCC, 0x00,
+ /* 170, 0xAA */ 0x33, 0x33, 0x99, 0x00,
+ /* 171, 0xAB */ 0x33, 0x33, 0x66, 0x00,
+ /* 172, 0xAC */ 0x33, 0x33, 0x33, 0x00,
+ /* 173, 0xAD */ 0x33, 0x33, 0x00, 0x00,
+ /* 174, 0xAE */ 0x33, 0x00, 0xFF, 0x00,
+ /* 175, 0xAF */ 0x33, 0x00, 0xCC, 0x00,
+ /* 176, 0xB0 */ 0x33, 0x00, 0x99, 0x00,
+ /* 177, 0xB1 */ 0x33, 0x00, 0x66, 0x00,
+ /* 178, 0xB2 */ 0x33, 0x00, 0x33, 0x00,
+ /* 179, 0xB3 */ 0x33, 0x00, 0x00, 0x00,
+ /* 180, 0xB4 */ 0x00, 0xFF, 0xFF, 0x00,
+ /* 181, 0xB5 */ 0x00, 0xFF, 0xCC, 0x00,
+ /* 182, 0xB6 */ 0x00, 0xFF, 0x99, 0x00,
+ /* 183, 0xB7 */ 0x00, 0xFF, 0x66, 0x00,
+ /* 184, 0xB8 */ 0x00, 0xFF, 0x33, 0x00,
+ /* 185, 0xB9 */ 0x00, 0xFF, 0x00, 0x00,
+ /* 186, 0xBA */ 0x00, 0xCC, 0xFF, 0x00,
+ /* 187, 0xBB */ 0x00, 0xCC, 0xCC, 0x00,
+ /* 188, 0xBC */ 0x00, 0xCC, 0x99, 0x00,
+ /* 189, 0xBD */ 0x00, 0xCC, 0x66, 0x00,
+ /* 190, 0xBE */ 0x00, 0xCC, 0x33, 0x00,
+ /* 191, 0xBF */ 0x00, 0xCC, 0x00, 0x00,
+ /* 192, 0xC0 */ 0x00, 0x99, 0xFF, 0x00,
+ /* 193, 0xC1 */ 0x00, 0x99, 0xCC, 0x00,
+ /* 194, 0xC2 */ 0x00, 0x99, 0x99, 0x00,
+ /* 195, 0xC3 */ 0x00, 0x99, 0x66, 0x00,
+ /* 196, 0xC4 */ 0x00, 0x99, 0x33, 0x00,
+ /* 197, 0xC5 */ 0x00, 0x99, 0x00, 0x00,
+ /* 198, 0xC6 */ 0x00, 0x66, 0xFF, 0x00,
+ /* 199, 0xC7 */ 0x00, 0x66, 0xCC, 0x00,
+ /* 200, 0xC8 */ 0x00, 0x66, 0x99, 0x00,
+ /* 201, 0xC9 */ 0x00, 0x66, 0x66, 0x00,
+ /* 202, 0xCA */ 0x00, 0x66, 0x33, 0x00,
+ /* 203, 0xCB */ 0x00, 0x66, 0x00, 0x00,
+ /* 204, 0xCC */ 0x00, 0x33, 0xFF, 0x00,
+ /* 205, 0xCD */ 0x00, 0x33, 0xCC, 0x00,
+ /* 206, 0xCE */ 0x00, 0x33, 0x99, 0x00,
+ /* 207, 0xCF */ 0x00, 0x33, 0x66, 0x00,
+ /* 208, 0xD0 */ 0x00, 0x33, 0x33, 0x00,
+ /* 209, 0xD1 */ 0x00, 0x33, 0x00, 0x00,
+ /* 210, 0xD2 */ 0x00, 0x00, 0xFF, 0x00,
+ /* 211, 0xD3 */ 0x00, 0x00, 0xCC, 0x00,
+ /* 212, 0xD4 */ 0x00, 0x00, 0x99, 0x00,
+ /* 213, 0xD5 */ 0x00, 0x00, 0x66, 0x00,
+ /* 214, 0xD6 */ 0x00, 0x00, 0x33, 0x00,
+ /* 215, 0xD7 */ 0xEE, 0x00, 0x00, 0x00,
+ /* 216, 0xD8 */ 0xDD, 0x00, 0x00, 0x00,
+ /* 217, 0xD9 */ 0xBB, 0x00, 0x00, 0x00,
+ /* 218, 0xDA */ 0xAA, 0x00, 0x00, 0x00,
+ /* 219, 0xDB */ 0x88, 0x00, 0x00, 0x00,
+ /* 220, 0xDC */ 0x77, 0x00, 0x00, 0x00,
+ /* 221, 0xDD */ 0x55, 0x00, 0x00, 0x00,
+ /* 222, 0xDE */ 0x44, 0x00, 0x00, 0x00,
+ /* 223, 0xDF */ 0x22, 0x00, 0x00, 0x00,
+ /* 224, 0xE0 */ 0x11, 0x00, 0x00, 0x00,
+ /* 225, 0xE1 */ 0x00, 0xEE, 0x00, 0x00,
+ /* 226, 0xE2 */ 0x00, 0xDD, 0x00, 0x00,
+ /* 227, 0xE3 */ 0x00, 0xBB, 0x00, 0x00,
+ /* 228, 0xE4 */ 0x00, 0xAA, 0x00, 0x00,
+ /* 229, 0xE5 */ 0x00, 0x88, 0x00, 0x00,
+ /* 230, 0xE6 */ 0x00, 0x77, 0x00, 0x00,
+ /* 231, 0xE7 */ 0x00, 0x55, 0x00, 0x00,
+ /* 232, 0xE8 */ 0x00, 0x44, 0x00, 0x00,
+ /* 233, 0xE9 */ 0x00, 0x22, 0x00, 0x00,
+ /* 234, 0xEA */ 0x00, 0x11, 0x00, 0x00,
+ /* 235, 0xEB */ 0x00, 0x00, 0xEE, 0x00,
+ /* 236, 0xEC */ 0x00, 0x00, 0xDD, 0x00,
+ /* 237, 0xED */ 0x00, 0x00, 0xBB, 0x00,
+ /* 238, 0xEE */ 0x00, 0x00, 0xAA, 0x00,
+ /* 239, 0xEF */ 0x00, 0x00, 0x88, 0x00,
+ /* 240, 0xF0 */ 0x00, 0x00, 0x77, 0x00,
+ /* 241, 0xF1 */ 0x00, 0x00, 0x55, 0x00,
+ /* 242, 0xF2 */ 0x00, 0x00, 0x44, 0x00,
+ /* 243, 0xF3 */ 0x00, 0x00, 0x22, 0x00,
+ /* 244, 0xF4 */ 0x00, 0x00, 0x11, 0x00,
+ /* 245, 0xF5 */ 0xEE, 0xEE, 0xEE, 0x00,
+ /* 246, 0xF6 */ 0xDD, 0xDD, 0xDD, 0x00,
+ /* 247, 0xF7 */ 0xBB, 0xBB, 0xBB, 0x00,
+ /* 248, 0xF8 */ 0xAA, 0xAA, 0xAA, 0x00,
+ /* 249, 0xF9 */ 0x88, 0x88, 0x88, 0x00,
+ /* 250, 0xFA */ 0x77, 0x77, 0x77, 0x00,
+ /* 251, 0xFB */ 0x55, 0x55, 0x55, 0x00,
+ /* 252, 0xFC */ 0x44, 0x44, 0x44, 0x00,
+ /* 253, 0xFD */ 0x22, 0x22, 0x22, 0x00,
+ /* 254, 0xFE */ 0x11, 0x11, 0x11, 0x00,
+ /* 255, 0xFF */ 0x00, 0x00, 0x00, 0x00
+};
+
+#endif
diff --git a/contrib/ffmpeg/libavformat/raw.c b/contrib/ffmpeg/libavformat/raw.c
new file mode 100644
index 000000000..e1ccbcd6d
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/raw.c
@@ -0,0 +1,843 @@
+/*
+ * RAW muxer and demuxer
+ * Copyright (c) 2001 Fabrice Bellard.
+ * Copyright (c) 2005 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 "avformat.h"
+
+#ifdef CONFIG_MUXERS
+/* simple formats */
+static int raw_write_header(struct AVFormatContext *s)
+{
+ return 0;
+}
+
+static int flac_write_header(struct AVFormatContext *s)
+{
+ static const uint8_t header[8] = {
+ 0x66, 0x4C, 0x61, 0x43, 0x80, 0x00, 0x00, 0x22
+ };
+ uint8_t *streaminfo = s->streams[0]->codec->extradata;
+ int len = s->streams[0]->codec->extradata_size;
+ if(streaminfo != NULL && len > 0) {
+ put_buffer(&s->pb, header, 8);
+ put_buffer(&s->pb, streaminfo, len);
+ }
+ return 0;
+}
+
+static int raw_write_packet(struct AVFormatContext *s, AVPacket *pkt)
+{
+ put_buffer(&s->pb, pkt->data, pkt->size);
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+static int raw_write_trailer(struct AVFormatContext *s)
+{
+ return 0;
+}
+#endif //CONFIG_MUXERS
+
+/* raw input */
+static int raw_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ AVStream *st;
+ int id;
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+
+ id = s->iformat->value;
+ if (id == CODEC_ID_RAWVIDEO) {
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ } else {
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ }
+ st->codec->codec_id = id;
+
+ switch(st->codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ st->codec->sample_rate = ap->sample_rate;
+ st->codec->channels = ap->channels;
+ av_set_pts_info(st, 64, 1, st->codec->sample_rate);
+ break;
+ case CODEC_TYPE_VIDEO:
+ av_set_pts_info(st, 64, ap->time_base.num, ap->time_base.den);
+ st->codec->width = ap->width;
+ st->codec->height = ap->height;
+ st->codec->pix_fmt = ap->pix_fmt;
+ if(st->codec->pix_fmt == PIX_FMT_NONE)
+ st->codec->pix_fmt= PIX_FMT_YUV420P;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+#define RAW_PACKET_SIZE 1024
+
+static int raw_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ int ret, size;
+ // AVStream *st = s->streams[0];
+
+ size= RAW_PACKET_SIZE;
+
+ ret= av_get_packet(&s->pb, pkt, size);
+
+ pkt->stream_index = 0;
+ if (ret <= 0) {
+ return AVERROR_IO;
+ }
+ /* note: we need to modify the packet size here to handle the last
+ packet */
+ pkt->size = ret;
+ return ret;
+}
+
+static int raw_read_partial_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ int ret, size;
+
+ size = RAW_PACKET_SIZE;
+
+ if (av_new_packet(pkt, size) < 0)
+ return AVERROR_IO;
+
+ pkt->pos= url_ftell(&s->pb);
+ pkt->stream_index = 0;
+ ret = get_partial_buffer(&s->pb, pkt->data, size);
+ if (ret <= 0) {
+ av_free_packet(pkt);
+ return AVERROR_IO;
+ }
+ pkt->size = ret;
+ return ret;
+}
+
+// http://www.artificis.hu/files/texts/ingenient.txt
+static int ingenient_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ int ret, size, w, h, unk1, unk2;
+
+ if (get_le32(&s->pb) != MKTAG('M', 'J', 'P', 'G'))
+ return AVERROR_IO; // FIXME
+
+ size = get_le32(&s->pb);
+
+ w = get_le16(&s->pb);
+ h = get_le16(&s->pb);
+
+ url_fskip(&s->pb, 8); // zero + size (padded?)
+ url_fskip(&s->pb, 2);
+ unk1 = get_le16(&s->pb);
+ unk2 = get_le16(&s->pb);
+ url_fskip(&s->pb, 22); // ascii timestamp
+
+ av_log(NULL, AV_LOG_DEBUG, "Ingenient packet: size=%d, width=%d, height=%d, unk1=%d unk2=%d\n",
+ size, w, h, unk1, unk2);
+
+ if (av_new_packet(pkt, size) < 0)
+ return AVERROR_IO;
+
+ pkt->pos = url_ftell(&s->pb);
+ pkt->stream_index = 0;
+ ret = get_buffer(&s->pb, pkt->data, size);
+ if (ret <= 0) {
+ av_free_packet(pkt);
+ return AVERROR_IO;
+ }
+ pkt->size = ret;
+ return ret;
+}
+
+static int raw_read_close(AVFormatContext *s)
+{
+ return 0;
+}
+
+int pcm_read_seek(AVFormatContext *s,
+ int stream_index, int64_t timestamp, int flags)
+{
+ AVStream *st;
+ int block_align, byte_rate;
+ int64_t pos;
+
+ st = s->streams[0];
+
+ block_align = st->codec->block_align ? st->codec->block_align :
+ (av_get_bits_per_sample(st->codec->codec_id) * st->codec->channels) >> 3;
+ byte_rate = st->codec->bit_rate ? st->codec->bit_rate >> 3 :
+ block_align * st->codec->sample_rate;
+
+ if (block_align <= 0 || byte_rate <= 0)
+ return -1;
+
+ /* compute the position by aligning it to block_align */
+ pos = av_rescale_rnd(timestamp * byte_rate,
+ st->time_base.num,
+ st->time_base.den * (int64_t)block_align,
+ (flags & AVSEEK_FLAG_BACKWARD) ? AV_ROUND_DOWN : AV_ROUND_UP);
+ pos *= block_align;
+
+ /* recompute exact position */
+ st->cur_dts = av_rescale(pos, st->time_base.den, byte_rate * (int64_t)st->time_base.num);
+ url_fseek(&s->pb, pos + s->data_offset, SEEK_SET);
+ return 0;
+}
+
+/* ac3 read */
+static int ac3_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ AVStream *st;
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_AC3;
+ st->need_parsing = 1;
+ /* the parameters will be extracted from the compressed bitstream */
+ return 0;
+}
+
+static int shorten_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ AVStream *st;
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_SHORTEN;
+ st->need_parsing = 1;
+ /* the parameters will be extracted from the compressed bitstream */
+ return 0;
+}
+
+/* flac read */
+static int flac_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ AVStream *st;
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_FLAC;
+ st->need_parsing = 1;
+ /* the parameters will be extracted from the compressed bitstream */
+ return 0;
+}
+
+/* dts read */
+static int dts_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ AVStream *st;
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_DTS;
+ st->need_parsing = 1;
+ /* the parameters will be extracted from the compressed bitstream */
+ return 0;
+}
+
+/* aac read */
+static int aac_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ AVStream *st;
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_AAC;
+ st->need_parsing = 1;
+ /* the parameters will be extracted from the compressed bitstream */
+ return 0;
+}
+
+/* mpeg1/h263 input */
+static int video_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ AVStream *st;
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = s->iformat->value;
+ st->need_parsing = 1;
+
+ /* for mjpeg, specify frame rate */
+ /* for mpeg4 specify it too (most mpeg4 streams dont have the fixed_vop_rate set ...)*/
+ if (ap->time_base.num) {
+ av_set_pts_info(st, 64, ap->time_base.num, ap->time_base.den);
+ } else if ( st->codec->codec_id == CODEC_ID_MJPEG ||
+ st->codec->codec_id == CODEC_ID_MPEG4 ||
+ st->codec->codec_id == CODEC_ID_H264) {
+ av_set_pts_info(st, 64, 1, 25);
+ }
+
+ return 0;
+}
+
+#define SEQ_START_CODE 0x000001b3
+#define GOP_START_CODE 0x000001b8
+#define PICTURE_START_CODE 0x00000100
+#define SLICE_START_CODE 0x00000101
+#define PACK_START_CODE 0x000001ba
+#define VIDEO_ID 0x000001e0
+#define AUDIO_ID 0x000001c0
+
+static int mpegvideo_probe(AVProbeData *p)
+{
+ uint32_t code= -1;
+ int pic=0, seq=0, slice=0, pspack=0, pes=0;
+ int i;
+
+ for(i=0; i<p->buf_size; i++){
+ code = (code<<8) + p->buf[i];
+ if ((code & 0xffffff00) == 0x100) {
+ switch(code){
+ case SEQ_START_CODE: seq++; break;
+ case PICTURE_START_CODE: pic++; break;
+ case SLICE_START_CODE: slice++; break;
+ case PACK_START_CODE: pspack++; break;
+ case VIDEO_ID:
+ case AUDIO_ID: pes++; break;
+ }
+ }
+ }
+ if(seq && seq*9<=pic*10 && pic*9<=slice*10 && !pspack && !pes)
+ return AVPROBE_SCORE_MAX/2+1; // +1 for .mpg
+ return 0;
+}
+
+#define VIDEO_OBJECT_START_CODE 0x00000100
+#define VIDEO_OBJECT_LAYER_START_CODE 0x00000120
+#define VISUAL_OBJECT_START_CODE 0x000001b5
+#define VOP_START_CODE 0x000001b6
+
+static int mpeg4video_probe(AVProbeData *probe_packet)
+{
+ uint32_t temp_buffer= -1;
+ int VO=0, VOL=0, VOP = 0, VISO = 0;
+ int i;
+
+ for(i=0; i<probe_packet->buf_size; i++){
+ temp_buffer = (temp_buffer<<8) + probe_packet->buf[i];
+ if ((temp_buffer & 0xffffff00) == 0x100) {
+ switch(temp_buffer){
+ case VOP_START_CODE: VOP++; break;
+ case VISUAL_OBJECT_START_CODE: VISO++; break;
+ }
+ switch(temp_buffer & 0xfffffff0){
+ case VIDEO_OBJECT_START_CODE: VO++; break;
+ case VIDEO_OBJECT_LAYER_START_CODE: VOL++; break;
+ }
+ }
+ }
+
+ if ( VOP >= VISO && VOP >= VOL && VO >= VOL && VOL > 0)
+ return AVPROBE_SCORE_MAX/2;
+ return 0;
+}
+
+static int h263_probe(AVProbeData *p)
+{
+ int code;
+ const uint8_t *d;
+
+ if (p->buf_size < 6)
+ return 0;
+ d = p->buf;
+ code = (d[0] << 14) | (d[1] << 6) | (d[2] >> 2);
+ if (code == 0x20) {
+ return 50;
+ }
+ return 0;
+}
+
+static int h261_probe(AVProbeData *p)
+{
+ int code;
+ const uint8_t *d;
+
+ if (p->buf_size < 6)
+ return 0;
+ d = p->buf;
+ code = (d[0] << 12) | (d[1] << 4) | (d[2] >> 4);
+ if (code == 0x10) {
+ return 50;
+ }
+ return 0;
+}
+
+AVInputFormat shorten_demuxer = {
+ "shn",
+ "raw shorten",
+ 0,
+ NULL,
+ shorten_read_header,
+ raw_read_partial_packet,
+ raw_read_close,
+ .extensions = "shn",
+};
+
+AVInputFormat flac_demuxer = {
+ "flac",
+ "raw flac",
+ 0,
+ NULL,
+ flac_read_header,
+ raw_read_partial_packet,
+ raw_read_close,
+ .extensions = "flac",
+};
+
+#ifdef CONFIG_MUXERS
+AVOutputFormat flac_muxer = {
+ "flac",
+ "raw flac",
+ "audio/x-flac",
+ "flac",
+ 0,
+ CODEC_ID_FLAC,
+ 0,
+ flac_write_header,
+ raw_write_packet,
+ raw_write_trailer,
+ .flags= AVFMT_NOTIMESTAMPS,
+};
+#endif //CONFIG_MUXERS
+
+AVInputFormat ac3_demuxer = {
+ "ac3",
+ "raw ac3",
+ 0,
+ NULL,
+ ac3_read_header,
+ raw_read_partial_packet,
+ raw_read_close,
+ .extensions = "ac3",
+};
+
+#ifdef CONFIG_MUXERS
+AVOutputFormat ac3_muxer = {
+ "ac3",
+ "raw ac3",
+ "audio/x-ac3",
+ "ac3",
+ 0,
+ CODEC_ID_AC3,
+ 0,
+ raw_write_header,
+ raw_write_packet,
+ raw_write_trailer,
+ .flags= AVFMT_NOTIMESTAMPS,
+};
+#endif //CONFIG_MUXERS
+
+AVInputFormat dts_demuxer = {
+ "dts",
+ "raw dts",
+ 0,
+ NULL,
+ dts_read_header,
+ raw_read_partial_packet,
+ raw_read_close,
+ .extensions = "dts",
+};
+
+AVInputFormat aac_demuxer = {
+ "aac",
+ "ADTS AAC",
+ 0,
+ NULL,
+ aac_read_header,
+ raw_read_partial_packet,
+ raw_read_close,
+ .extensions = "aac",
+};
+
+AVInputFormat h261_demuxer = {
+ "h261",
+ "raw h261",
+ 0,
+ h261_probe,
+ video_read_header,
+ raw_read_partial_packet,
+ raw_read_close,
+ .extensions = "h261",
+ .value = CODEC_ID_H261,
+};
+
+#ifdef CONFIG_MUXERS
+AVOutputFormat h261_muxer = {
+ "h261",
+ "raw h261",
+ "video/x-h261",
+ "h261",
+ 0,
+ 0,
+ CODEC_ID_H261,
+ raw_write_header,
+ raw_write_packet,
+ raw_write_trailer,
+ .flags= AVFMT_NOTIMESTAMPS,
+};
+#endif //CONFIG_MUXERS
+
+AVInputFormat h263_demuxer = {
+ "h263",
+ "raw h263",
+ 0,
+ h263_probe,
+ video_read_header,
+ raw_read_partial_packet,
+ raw_read_close,
+// .extensions = "h263", //FIXME remove after writing mpeg4_probe
+ .value = CODEC_ID_H263,
+};
+
+#ifdef CONFIG_MUXERS
+AVOutputFormat h263_muxer = {
+ "h263",
+ "raw h263",
+ "video/x-h263",
+ "h263",
+ 0,
+ 0,
+ CODEC_ID_H263,
+ raw_write_header,
+ raw_write_packet,
+ raw_write_trailer,
+ .flags= AVFMT_NOTIMESTAMPS,
+};
+#endif //CONFIG_MUXERS
+
+AVInputFormat m4v_demuxer = {
+ "m4v",
+ "raw MPEG4 video format",
+ 0,
+ mpeg4video_probe, /** probing for mpeg4 data */
+ video_read_header,
+ raw_read_partial_packet,
+ raw_read_close,
+ .extensions = "m4v", //FIXME remove after writing mpeg4_probe
+ .value = CODEC_ID_MPEG4,
+};
+
+#ifdef CONFIG_MUXERS
+AVOutputFormat m4v_muxer = {
+ "m4v",
+ "raw MPEG4 video format",
+ NULL,
+ "m4v",
+ 0,
+ CODEC_ID_NONE,
+ CODEC_ID_MPEG4,
+ raw_write_header,
+ raw_write_packet,
+ raw_write_trailer,
+ .flags= AVFMT_NOTIMESTAMPS,
+};
+#endif //CONFIG_MUXERS
+
+AVInputFormat h264_demuxer = {
+ "h264",
+ "raw H264 video format",
+ 0,
+ NULL /*mpegvideo_probe*/,
+ video_read_header,
+ raw_read_partial_packet,
+ raw_read_close,
+ .extensions = "h26l,h264,264", //FIXME remove after writing mpeg4_probe
+ .value = CODEC_ID_H264,
+};
+
+#ifdef CONFIG_MUXERS
+AVOutputFormat h264_muxer = {
+ "h264",
+ "raw H264 video format",
+ NULL,
+ "h264",
+ 0,
+ CODEC_ID_NONE,
+ CODEC_ID_H264,
+ raw_write_header,
+ raw_write_packet,
+ raw_write_trailer,
+ .flags= AVFMT_NOTIMESTAMPS,
+};
+#endif //CONFIG_MUXERS
+
+AVInputFormat mpegvideo_demuxer = {
+ "mpegvideo",
+ "MPEG video",
+ 0,
+ mpegvideo_probe,
+ video_read_header,
+ raw_read_partial_packet,
+ raw_read_close,
+ .value = CODEC_ID_MPEG1VIDEO,
+};
+
+#ifdef CONFIG_MUXERS
+AVOutputFormat mpeg1video_muxer = {
+ "mpeg1video",
+ "MPEG video",
+ "video/x-mpeg",
+ "mpg,mpeg,m1v",
+ 0,
+ 0,
+ CODEC_ID_MPEG1VIDEO,
+ raw_write_header,
+ raw_write_packet,
+ raw_write_trailer,
+ .flags= AVFMT_NOTIMESTAMPS,
+};
+#endif //CONFIG_MUXERS
+
+#ifdef CONFIG_MUXERS
+AVOutputFormat mpeg2video_muxer = {
+ "mpeg2video",
+ "MPEG2 video",
+ NULL,
+ "m2v",
+ 0,
+ 0,
+ CODEC_ID_MPEG2VIDEO,
+ raw_write_header,
+ raw_write_packet,
+ raw_write_trailer,
+ .flags= AVFMT_NOTIMESTAMPS,
+};
+#endif //CONFIG_MUXERS
+
+AVInputFormat mjpeg_demuxer = {
+ "mjpeg",
+ "MJPEG video",
+ 0,
+ NULL,
+ video_read_header,
+ raw_read_partial_packet,
+ raw_read_close,
+ .extensions = "mjpg,mjpeg",
+ .value = CODEC_ID_MJPEG,
+};
+
+AVInputFormat ingenient_demuxer = {
+ "ingenient",
+ "Ingenient MJPEG",
+ 0,
+ NULL,
+ video_read_header,
+ ingenient_read_packet,
+ raw_read_close,
+ .extensions = "cgi", // FIXME
+ .value = CODEC_ID_MJPEG,
+};
+
+#ifdef CONFIG_MUXERS
+AVOutputFormat mjpeg_muxer = {
+ "mjpeg",
+ "MJPEG video",
+ "video/x-mjpeg",
+ "mjpg,mjpeg",
+ 0,
+ 0,
+ CODEC_ID_MJPEG,
+ raw_write_header,
+ raw_write_packet,
+ raw_write_trailer,
+ .flags= AVFMT_NOTIMESTAMPS,
+};
+#endif //CONFIG_MUXERS
+
+/* pcm formats */
+
+#define PCMINPUTDEF(name, long_name, ext, codec) \
+AVInputFormat pcm_ ## name ## _demuxer = {\
+ #name,\
+ long_name,\
+ 0,\
+ NULL,\
+ raw_read_header,\
+ raw_read_packet,\
+ raw_read_close,\
+ pcm_read_seek,\
+ .extensions = ext,\
+ .value = codec,\
+};
+
+#define PCMOUTPUTDEF(name, long_name, ext, codec) \
+AVOutputFormat pcm_ ## name ## _muxer = {\
+ #name,\
+ long_name,\
+ NULL,\
+ ext,\
+ 0,\
+ codec,\
+ 0,\
+ raw_write_header,\
+ raw_write_packet,\
+ raw_write_trailer,\
+ .flags= AVFMT_NOTIMESTAMPS,\
+};
+
+
+#if !defined(CONFIG_MUXERS) && defined(CONFIG_DEMUXERS)
+#define PCMDEF(name, long_name, ext, codec) \
+ PCMINPUTDEF(name, long_name, ext, codec)
+#elif defined(CONFIG_MUXERS) && !defined(CONFIG_DEMUXERS)
+#define PCMDEF(name, long_name, ext, codec) \
+ PCMOUTPUTDEF(name, long_name, ext, codec)
+#elif defined(CONFIG_MUXERS) && defined(CONFIG_DEMUXERS)
+#define PCMDEF(name, long_name, ext, codec) \
+ PCMINPUTDEF(name, long_name, ext, codec)\
+ PCMOUTPUTDEF(name, long_name, ext, codec)
+#else
+#define PCMDEF(name, long_name, ext, codec)
+#endif
+
+#ifdef WORDS_BIGENDIAN
+#define BE_DEF(s) s
+#define LE_DEF(s) NULL
+#else
+#define BE_DEF(s) NULL
+#define LE_DEF(s) s
+#endif
+
+
+PCMDEF(s16le, "pcm signed 16 bit little endian format",
+ LE_DEF("sw"), CODEC_ID_PCM_S16LE)
+
+PCMDEF(s16be, "pcm signed 16 bit big endian format",
+ BE_DEF("sw"), CODEC_ID_PCM_S16BE)
+
+PCMDEF(u16le, "pcm unsigned 16 bit little endian format",
+ LE_DEF("uw"), CODEC_ID_PCM_U16LE)
+
+PCMDEF(u16be, "pcm unsigned 16 bit big endian format",
+ BE_DEF("uw"), CODEC_ID_PCM_U16BE)
+
+PCMDEF(s8, "pcm signed 8 bit format",
+ "sb", CODEC_ID_PCM_S8)
+
+PCMDEF(u8, "pcm unsigned 8 bit format",
+ "ub", CODEC_ID_PCM_U8)
+
+PCMDEF(mulaw, "pcm mu law format",
+ "ul", CODEC_ID_PCM_MULAW)
+
+PCMDEF(alaw, "pcm A law format",
+ "al", CODEC_ID_PCM_ALAW)
+
+static int rawvideo_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ int packet_size, ret, width, height;
+ AVStream *st = s->streams[0];
+
+ width = st->codec->width;
+ height = st->codec->height;
+
+ packet_size = avpicture_get_size(st->codec->pix_fmt, width, height);
+ if (packet_size < 0)
+ return -1;
+
+ ret= av_get_packet(&s->pb, pkt, packet_size);
+
+ pkt->stream_index = 0;
+ if (ret != packet_size) {
+ return AVERROR_IO;
+ } else {
+ return 0;
+ }
+}
+
+AVInputFormat rawvideo_demuxer = {
+ "rawvideo",
+ "raw video format",
+ 0,
+ NULL,
+ raw_read_header,
+ rawvideo_read_packet,
+ raw_read_close,
+ .extensions = "yuv,cif,qcif",
+ .value = CODEC_ID_RAWVIDEO,
+};
+
+#ifdef CONFIG_MUXERS
+AVOutputFormat rawvideo_muxer = {
+ "rawvideo",
+ "raw video format",
+ NULL,
+ "yuv",
+ 0,
+ CODEC_ID_NONE,
+ CODEC_ID_RAWVIDEO,
+ raw_write_header,
+ raw_write_packet,
+ raw_write_trailer,
+ .flags= AVFMT_NOTIMESTAMPS,
+};
+#endif //CONFIG_MUXERS
+
+#ifdef CONFIG_MUXERS
+static int null_write_packet(struct AVFormatContext *s, AVPacket *pkt)
+{
+ return 0;
+}
+
+AVOutputFormat null_muxer = {
+ "null",
+ "null video format",
+ NULL,
+ NULL,
+ 0,
+#ifdef WORDS_BIGENDIAN
+ CODEC_ID_PCM_S16BE,
+#else
+ CODEC_ID_PCM_S16LE,
+#endif
+ CODEC_ID_RAWVIDEO,
+ raw_write_header,
+ null_write_packet,
+ raw_write_trailer,
+ .flags = AVFMT_NOFILE | AVFMT_RAWPICTURE | AVFMT_NOTIMESTAMPS,
+};
+#endif //CONFIG_MUXERS
diff --git a/contrib/ffmpeg/libavformat/riff.c b/contrib/ffmpeg/libavformat/riff.c
new file mode 100644
index 000000000..d315c66af
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/riff.c
@@ -0,0 +1,468 @@
+/*
+ * RIFF codec tags
+ * 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
+ */
+
+#include "avformat.h"
+#include "avcodec.h"
+#include "riff.h"
+
+/* Note: when encoding, the first matching tag is used, so order is
+ important if multiple tags possible for a given codec. */
+const CodecTag codec_bmp_tags[] = {
+ { CODEC_ID_H264, MKTAG('H', '2', '6', '4') },
+ { CODEC_ID_H264, MKTAG('h', '2', '6', '4') },
+ { CODEC_ID_H264, MKTAG('X', '2', '6', '4') },
+ { CODEC_ID_H264, MKTAG('x', '2', '6', '4') },
+ { CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') },
+ { CODEC_ID_H264, MKTAG('V', 'S', 'S', 'H') },
+
+ { CODEC_ID_H263, MKTAG('H', '2', '6', '3') },
+ { CODEC_ID_H263P, MKTAG('H', '2', '6', '3') },
+ { CODEC_ID_H263I, MKTAG('I', '2', '6', '3') }, /* intel h263 */
+ { CODEC_ID_H261, MKTAG('H', '2', '6', '1') },
+
+ /* added based on MPlayer */
+ { CODEC_ID_H263P, MKTAG('U', '2', '6', '3') },
+ { CODEC_ID_H263P, MKTAG('v', 'i', 'v', '1') },
+
+ { CODEC_ID_MPEG4, MKTAG('F', 'M', 'P', '4')},
+ { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X'), .invalid_asf = 1 },
+ { CODEC_ID_MPEG4, MKTAG('D', 'X', '5', '0'), .invalid_asf = 1 },
+ { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D'), .invalid_asf = 1 },
+ { CODEC_ID_MPEG4, MKTAG('M', 'P', '4', 'S') },
+ { CODEC_ID_MPEG4, MKTAG('M', '4', 'S', '2') },
+ { CODEC_ID_MPEG4, MKTAG(0x04, 0, 0, 0) }, /* some broken avi use this */
+
+ /* added based on MPlayer */
+ { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', '1') },
+ { CODEC_ID_MPEG4, MKTAG('B', 'L', 'Z', '0') },
+ { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
+ { CODEC_ID_MPEG4, MKTAG('U', 'M', 'P', '4') },
+ { CODEC_ID_MPEG4, MKTAG('W', 'V', '1', 'F') },
+ { CODEC_ID_MPEG4, MKTAG('S', 'E', 'D', 'G') },
+
+ { CODEC_ID_MPEG4, MKTAG('R', 'M', 'P', '4') },
+
+ { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '3'), .invalid_asf = 1 }, /* default signature when using MSMPEG4 */
+ { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') },
+
+ /* added based on MPlayer */
+ { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', 'G', '3') },
+ { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '5') },
+ { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '6') },
+ { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '4') },
+ { CODEC_ID_MSMPEG4V3, MKTAG('A', 'P', '4', '1') },
+ { CODEC_ID_MSMPEG4V3, MKTAG('C', 'O', 'L', '1') },
+ { CODEC_ID_MSMPEG4V3, MKTAG('C', 'O', 'L', '0') },
+
+ { CODEC_ID_MSMPEG4V2, MKTAG('M', 'P', '4', '2') },
+
+ /* added based on MPlayer */
+ { CODEC_ID_MSMPEG4V2, MKTAG('D', 'I', 'V', '2') },
+
+ { CODEC_ID_MSMPEG4V1, MKTAG('M', 'P', 'G', '4') },
+
+ { CODEC_ID_WMV1, MKTAG('W', 'M', 'V', '1') },
+
+ /* added based on MPlayer */
+ { CODEC_ID_WMV2, MKTAG('W', 'M', 'V', '2') },
+ { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'd') },
+ { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', 'd') },
+ { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'l') },
+ { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '2', '5') },
+ { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '1') },
+ { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '2') },
+ { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', 'g', '2') },
+ { CODEC_ID_MPEG2VIDEO, MKTAG('M', 'P', 'E', 'G') },
+ { CODEC_ID_MPEG1VIDEO, MKTAG('P', 'I', 'M', '1') },
+ { CODEC_ID_MPEG1VIDEO, MKTAG('V', 'C', 'R', '2') },
+ { CODEC_ID_MPEG1VIDEO, 0x10000001 },
+ { CODEC_ID_MPEG2VIDEO, 0x10000002 },
+ { CODEC_ID_MPEG2VIDEO, MKTAG('D', 'V', 'R', ' ') },
+ { CODEC_ID_MJPEG, MKTAG('M', 'J', 'P', 'G') },
+ { CODEC_ID_MJPEG, MKTAG('L', 'J', 'P', 'G') },
+ { CODEC_ID_LJPEG, MKTAG('L', 'J', 'P', 'G') },
+ { CODEC_ID_MJPEG, MKTAG('J', 'P', 'G', 'L') }, /* Pegasus lossless JPEG */
+ { CODEC_ID_MJPEG, MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - decoder */
+ { CODEC_ID_JPEGLS, MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - encoder */
+ { CODEC_ID_HUFFYUV, MKTAG('H', 'F', 'Y', 'U') },
+ { CODEC_ID_FFVHUFF, MKTAG('F', 'F', 'V', 'H') },
+ { CODEC_ID_CYUV, MKTAG('C', 'Y', 'U', 'V') },
+ { CODEC_ID_RAWVIDEO, 0 },
+ { CODEC_ID_RAWVIDEO, MKTAG('I', '4', '2', '0') },
+ { CODEC_ID_RAWVIDEO, MKTAG('Y', 'U', 'Y', '2') },
+ { CODEC_ID_RAWVIDEO, MKTAG('Y', '4', '2', '2') },
+ { CODEC_ID_RAWVIDEO, MKTAG('Y', 'V', '1', '2') },
+ { CODEC_ID_RAWVIDEO, MKTAG('U', 'Y', 'V', 'Y') },
+ { CODEC_ID_RAWVIDEO, MKTAG('I', 'Y', 'U', 'V') },
+ { CODEC_ID_RAWVIDEO, MKTAG('Y', '8', '0', '0') },
+ { CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '1') },
+ { CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '2') },
+ { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') },
+ { CODEC_ID_VP3, MKTAG('V', 'P', '3', '0') },
+ { CODEC_ID_VP5, MKTAG('V', 'P', '5', '0') },
+ { CODEC_ID_VP6, MKTAG('V', 'P', '6', '2') },
+ { CODEC_ID_ASV1, MKTAG('A', 'S', 'V', '1') },
+ { CODEC_ID_ASV2, MKTAG('A', 'S', 'V', '2') },
+ { CODEC_ID_VCR1, MKTAG('V', 'C', 'R', '1') },
+ { CODEC_ID_FFV1, MKTAG('F', 'F', 'V', '1') },
+ { CODEC_ID_XAN_WC4, MKTAG('X', 'x', 'a', 'n') },
+ { CODEC_ID_MSRLE, MKTAG('m', 'r', 'l', 'e') },
+ { CODEC_ID_MSRLE, MKTAG(0x1, 0x0, 0x0, 0x0) },
+ { CODEC_ID_MSVIDEO1, MKTAG('M', 'S', 'V', 'C') },
+ { CODEC_ID_MSVIDEO1, MKTAG('m', 's', 'v', 'c') },
+ { CODEC_ID_MSVIDEO1, MKTAG('C', 'R', 'A', 'M') },
+ { CODEC_ID_MSVIDEO1, MKTAG('c', 'r', 'a', 'm') },
+ { CODEC_ID_MSVIDEO1, MKTAG('W', 'H', 'A', 'M') },
+ { CODEC_ID_MSVIDEO1, MKTAG('w', 'h', 'a', 'm') },
+ { CODEC_ID_CINEPAK, MKTAG('c', 'v', 'i', 'd') },
+ { CODEC_ID_TRUEMOTION1, MKTAG('D', 'U', 'C', 'K') },
+ { CODEC_ID_MSZH, MKTAG('M', 'S', 'Z', 'H') },
+ { CODEC_ID_ZLIB, MKTAG('Z', 'L', 'I', 'B') },
+ { CODEC_ID_SNOW, MKTAG('S', 'N', 'O', 'W') },
+ { CODEC_ID_4XM, MKTAG('4', 'X', 'M', 'V') },
+ { CODEC_ID_FLV1, MKTAG('F', 'L', 'V', '1') },
+ { CODEC_ID_FLASHSV, MKTAG('F', 'S', 'V', '1') },
+ { CODEC_ID_VP6F, MKTAG('V', 'P', '6', 'F') },
+ { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', '1') },
+ { CODEC_ID_TSCC, MKTAG('t', 's', 'c', 'c') },
+ { CODEC_ID_ULTI, MKTAG('U', 'L', 'T', 'I') },
+ { CODEC_ID_VIXL, MKTAG('V', 'I', 'X', 'L') },
+ { CODEC_ID_QPEG, MKTAG('Q', 'P', 'E', 'G') },
+ { CODEC_ID_QPEG, MKTAG('Q', '1', '.', '0') },
+ { CODEC_ID_QPEG, MKTAG('Q', '1', '.', '1') },
+ { CODEC_ID_WMV3, MKTAG('W', 'M', 'V', '3') },
+ { CODEC_ID_VC1, MKTAG('W', 'V', 'C', '1') },
+ { CODEC_ID_LOCO, MKTAG('L', 'O', 'C', 'O') },
+ { CODEC_ID_WNV1, MKTAG('W', 'N', 'V', '1') },
+ { CODEC_ID_AASC, MKTAG('A', 'A', 'S', 'C') },
+ { CODEC_ID_INDEO2, MKTAG('R', 'T', '2', '1') },
+ { CODEC_ID_FRAPS, MKTAG('F', 'P', 'S', '1') },
+ { CODEC_ID_THEORA, MKTAG('t', 'h', 'e', 'o') },
+ { CODEC_ID_TRUEMOTION2, MKTAG('T', 'M', '2', '0') },
+ { CODEC_ID_CSCD, MKTAG('C', 'S', 'C', 'D') },
+ { CODEC_ID_ZMBV, MKTAG('Z', 'M', 'B', 'V') },
+ { CODEC_ID_KMVC, MKTAG('K', 'M', 'V', 'C') },
+ { CODEC_ID_CAVS, MKTAG('C', 'A', 'V', 'S') },
+ { CODEC_ID_JPEG2000, MKTAG('M', 'J', '2', 'C') },
+ { CODEC_ID_VMNC, MKTAG('V', 'M', 'n', 'c') },
+ { CODEC_ID_NONE, 0 },
+};
+
+const CodecTag codec_wav_tags[] = {
+ { CODEC_ID_MP2, 0x50 },
+ { CODEC_ID_MP3, 0x55 },
+ { CODEC_ID_AC3, 0x2000 },
+ { CODEC_ID_DTS, 0x2001 },
+ { CODEC_ID_PCM_S16LE, 0x01 },
+ { CODEC_ID_PCM_U8, 0x01 }, /* must come after s16le in this list */
+ { CODEC_ID_PCM_S24LE, 0x01 },
+ { CODEC_ID_PCM_S32LE, 0x01 },
+ { CODEC_ID_PCM_ALAW, 0x06 },
+ { CODEC_ID_PCM_MULAW, 0x07 },
+ { CODEC_ID_ADPCM_MS, 0x02 },
+ { CODEC_ID_ADPCM_IMA_WAV, 0x11 },
+ { CODEC_ID_ADPCM_YAMAHA, 0x20 },
+ { CODEC_ID_ADPCM_G726, 0x45 },
+ { CODEC_ID_ADPCM_IMA_DK4, 0x61 }, /* rogue format number */
+ { CODEC_ID_ADPCM_IMA_DK3, 0x62 }, /* rogue format number */
+ { CODEC_ID_WMAV1, 0x160 },
+ { CODEC_ID_WMAV2, 0x161 },
+ { CODEC_ID_AAC, 0x706d },
+ { CODEC_ID_AAC, 0xff },
+ { CODEC_ID_VORBIS, ('V'<<8)+'o' }, //HACK/FIXME, does vorbis in WAV/AVI have an (in)official id?
+ { CODEC_ID_SONIC, 0x2048 },
+ { CODEC_ID_SONIC_LS, 0x2048 },
+ { CODEC_ID_ADPCM_CT, 0x200 },
+ { CODEC_ID_ADPCM_SWF, ('S'<<8)+'F' },
+ { CODEC_ID_TRUESPEECH, 0x22 },
+ { CODEC_ID_FLAC, 0xF1AC },
+ { CODEC_ID_IMC, 0x401 },
+
+ /* FIXME: All of the IDs below are not 16 bit and thus illegal. */
+ // for NuppelVideo (nuv.c)
+ { CODEC_ID_PCM_S16LE, MKTAG('R', 'A', 'W', 'A') },
+ { CODEC_ID_MP3, MKTAG('L', 'A', 'M', 'E') },
+ { CODEC_ID_MP3, MKTAG('M', 'P', '3', ' ') },
+ { 0, 0 },
+};
+
+unsigned int codec_get_tag(const CodecTag *tags, int id)
+{
+ while (tags->id != CODEC_ID_NONE) {
+ if (tags->id == id)
+ return tags->tag;
+ tags++;
+ }
+ return 0;
+}
+
+unsigned int codec_get_asf_tag(const CodecTag *tags, unsigned int id)
+{
+ while (tags->id != CODEC_ID_NONE) {
+ if (!tags->invalid_asf && tags->id == id)
+ return tags->tag;
+ tags++;
+ }
+ return 0;
+}
+
+enum CodecID codec_get_id(const CodecTag *tags, unsigned int tag)
+{
+ while (tags->id != CODEC_ID_NONE) {
+ if( toupper((tag >> 0)&0xFF) == toupper((tags->tag >> 0)&0xFF)
+ && toupper((tag >> 8)&0xFF) == toupper((tags->tag >> 8)&0xFF)
+ && toupper((tag >>16)&0xFF) == toupper((tags->tag >>16)&0xFF)
+ && toupper((tag >>24)&0xFF) == toupper((tags->tag >>24)&0xFF))
+ return tags->id;
+ tags++;
+ }
+ return CODEC_ID_NONE;
+}
+
+unsigned int codec_get_bmp_tag(int id)
+{
+ return codec_get_tag(codec_bmp_tags, id);
+}
+
+unsigned int codec_get_wav_tag(int id)
+{
+ return codec_get_tag(codec_wav_tags, id);
+}
+
+enum CodecID codec_get_bmp_id(unsigned int tag)
+{
+ return codec_get_id(codec_bmp_tags, tag);
+}
+
+enum CodecID codec_get_wav_id(unsigned int tag)
+{
+ return codec_get_id(codec_wav_tags, tag);
+}
+
+#ifdef CONFIG_MUXERS
+offset_t start_tag(ByteIOContext *pb, const char *tag)
+{
+ put_tag(pb, tag);
+ put_le32(pb, 0);
+ return url_ftell(pb);
+}
+
+void end_tag(ByteIOContext *pb, offset_t start)
+{
+ offset_t pos;
+
+ pos = url_ftell(pb);
+ url_fseek(pb, start - 4, SEEK_SET);
+ put_le32(pb, (uint32_t)(pos - start));
+ url_fseek(pb, pos, SEEK_SET);
+}
+
+/* WAVEFORMATEX header */
+/* returns the size or -1 on error */
+int put_wav_header(ByteIOContext *pb, AVCodecContext *enc)
+{
+ int bps, blkalign, bytespersec;
+ int hdrsize = 18;
+
+ if(!enc->codec_tag || enc->codec_tag > 0xffff)
+ enc->codec_tag = codec_get_tag(codec_wav_tags, enc->codec_id);
+ if(!enc->codec_tag || enc->codec_tag > 0xffff)
+ return -1;
+
+ put_le16(pb, enc->codec_tag);
+ put_le16(pb, enc->channels);
+ put_le32(pb, enc->sample_rate);
+ if (enc->codec_id == CODEC_ID_PCM_U8 ||
+ enc->codec_id == CODEC_ID_PCM_ALAW ||
+ enc->codec_id == CODEC_ID_PCM_MULAW) {
+ bps = 8;
+ } else if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3) {
+ bps = 0;
+ } else if (enc->codec_id == CODEC_ID_ADPCM_IMA_WAV || enc->codec_id == CODEC_ID_ADPCM_MS || enc->codec_id == CODEC_ID_ADPCM_G726 || enc->codec_id == CODEC_ID_ADPCM_YAMAHA) { //
+ bps = 4;
+ } else if (enc->codec_id == CODEC_ID_PCM_S24LE) {
+ bps = 24;
+ } else if (enc->codec_id == CODEC_ID_PCM_S32LE) {
+ bps = 32;
+ } else {
+ bps = 16;
+ }
+
+ if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3) {
+ blkalign = enc->frame_size; //this is wrong, but seems many demuxers dont work if this is set correctly
+ //blkalign = 144 * enc->bit_rate/enc->sample_rate;
+ } else if (enc->codec_id == CODEC_ID_ADPCM_G726) { //
+ blkalign = 1;
+ } else if (enc->block_align != 0) { /* specified by the codec */
+ blkalign = enc->block_align;
+ } else
+ blkalign = enc->channels*bps >> 3;
+ if (enc->codec_id == CODEC_ID_PCM_U8 ||
+ enc->codec_id == CODEC_ID_PCM_S24LE ||
+ enc->codec_id == CODEC_ID_PCM_S32LE ||
+ enc->codec_id == CODEC_ID_PCM_S16LE) {
+ bytespersec = enc->sample_rate * blkalign;
+ } else {
+ bytespersec = enc->bit_rate / 8;
+ }
+ put_le32(pb, bytespersec); /* bytes per second */
+ put_le16(pb, blkalign); /* block align */
+ put_le16(pb, bps); /* bits per sample */
+ if (enc->codec_id == CODEC_ID_MP3) {
+ put_le16(pb, 12); /* wav_extra_size */
+ hdrsize += 12;
+ put_le16(pb, 1); /* wID */
+ put_le32(pb, 2); /* fdwFlags */
+ put_le16(pb, 1152); /* nBlockSize */
+ put_le16(pb, 1); /* nFramesPerBlock */
+ put_le16(pb, 1393); /* nCodecDelay */
+ } else if (enc->codec_id == CODEC_ID_MP2) {
+ put_le16(pb, 22); /* wav_extra_size */
+ hdrsize += 22;
+ put_le16(pb, 2); /* fwHeadLayer */
+ put_le32(pb, enc->bit_rate); /* dwHeadBitrate */
+ put_le16(pb, enc->channels == 2 ? 1 : 8); /* fwHeadMode */
+ put_le16(pb, 0); /* fwHeadModeExt */
+ put_le16(pb, 1); /* wHeadEmphasis */
+ put_le16(pb, 16); /* fwHeadFlags */
+ put_le32(pb, 0); /* dwPTSLow */
+ put_le32(pb, 0); /* dwPTSHigh */
+ } else if (enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) {
+ put_le16(pb, 2); /* wav_extra_size */
+ hdrsize += 2;
+ put_le16(pb, ((enc->block_align - 4 * enc->channels) / (4 * enc->channels)) * 8 + 1); /* wSamplesPerBlock */
+ } else if(enc->extradata_size){
+ put_le16(pb, enc->extradata_size);
+ put_buffer(pb, enc->extradata, enc->extradata_size);
+ hdrsize += enc->extradata_size;
+ if(hdrsize&1){
+ hdrsize++;
+ put_byte(pb, 0);
+ }
+ } else {
+ hdrsize -= 2;
+ }
+
+ return hdrsize;
+}
+
+/* BITMAPINFOHEADER header */
+void put_bmp_header(ByteIOContext *pb, AVCodecContext *enc, const CodecTag *tags, int for_asf)
+{
+ put_le32(pb, 40 + enc->extradata_size); /* size */
+ put_le32(pb, enc->width);
+ put_le32(pb, enc->height);
+ put_le16(pb, 1); /* planes */
+
+ put_le16(pb, enc->bits_per_sample ? enc->bits_per_sample : 24); /* depth */
+ /* compression type */
+ put_le32(pb, for_asf ? (enc->codec_tag ? enc->codec_tag : codec_get_asf_tag(tags, enc->codec_id)) : enc->codec_tag); //
+ put_le32(pb, enc->width * enc->height * 3);
+ put_le32(pb, 0);
+ put_le32(pb, 0);
+ put_le32(pb, 0);
+ put_le32(pb, 0);
+
+ put_buffer(pb, enc->extradata, enc->extradata_size);
+
+ if (enc->extradata_size & 1)
+ put_byte(pb, 0);
+}
+#endif //CONFIG_MUXERS
+
+#ifdef CONFIG_DEMUXERS
+/* We could be given one of the three possible structures here:
+ * WAVEFORMAT, PCMWAVEFORMAT or WAVEFORMATEX. Each structure
+ * is an expansion of the previous one with the fields added
+ * at the bottom. PCMWAVEFORMAT adds 'WORD wBitsPerSample' and
+ * WAVEFORMATEX adds 'WORD cbSize' and basically makes itself
+ * an openended structure.
+ */
+void get_wav_header(ByteIOContext *pb, AVCodecContext *codec, int size)
+{
+ int id;
+
+ id = get_le16(pb);
+ codec->codec_type = CODEC_TYPE_AUDIO;
+ codec->codec_tag = id;
+ codec->channels = get_le16(pb);
+ codec->sample_rate = get_le32(pb);
+ codec->bit_rate = get_le32(pb) * 8;
+ codec->block_align = get_le16(pb);
+ if (size == 14) { /* We're dealing with plain vanilla WAVEFORMAT */
+ codec->bits_per_sample = 8;
+ }else
+ codec->bits_per_sample = get_le16(pb);
+ codec->codec_id = wav_codec_get_id(id, codec->bits_per_sample);
+
+ if (size > 16) { /* We're obviously dealing with WAVEFORMATEX */
+ codec->extradata_size = get_le16(pb);
+ if (codec->extradata_size > 0) {
+ if (codec->extradata_size > size - 18)
+ codec->extradata_size = size - 18;
+ codec->extradata = av_mallocz(codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ get_buffer(pb, codec->extradata, codec->extradata_size);
+ } else
+ codec->extradata_size = 0;
+
+ /* It is possible for the chunk to contain garbage at the end */
+ if (size - codec->extradata_size - 18 > 0)
+ url_fskip(pb, size - codec->extradata_size - 18);
+ }
+}
+
+
+int wav_codec_get_id(unsigned int tag, int bps)
+{
+ int id;
+ id = codec_get_id(codec_wav_tags, tag);
+ if (id <= 0)
+ return id;
+ /* handle specific u8 codec */
+ if (id == CODEC_ID_PCM_S16LE && bps == 8)
+ id = CODEC_ID_PCM_U8;
+ if (id == CODEC_ID_PCM_S16LE && bps == 24)
+ id = CODEC_ID_PCM_S24LE;
+ if (id == CODEC_ID_PCM_S16LE && bps == 32)
+ id = CODEC_ID_PCM_S32LE;
+ return id;
+}
+#endif // CONFIG_DEMUXERS
+
+void ff_parse_specific_params(AVCodecContext *stream, int *au_rate, int *au_ssize, int *au_scale)
+{
+ int gcd;
+
+ *au_ssize= stream->block_align;
+ if(stream->frame_size && stream->sample_rate){
+ *au_scale=stream->frame_size;
+ *au_rate= stream->sample_rate;
+ }else if(stream->codec_type == CODEC_TYPE_VIDEO){
+ *au_scale= stream->time_base.num;
+ *au_rate = stream->time_base.den;
+ }else{
+ *au_scale= stream->block_align ? stream->block_align*8 : 8;
+ *au_rate = stream->bit_rate;
+ }
+ gcd= ff_gcd(*au_scale, *au_rate);
+ *au_scale /= gcd;
+ *au_rate /= gcd;
+}
diff --git a/contrib/ffmpeg/libavformat/riff.h b/contrib/ffmpeg/libavformat/riff.h
new file mode 100644
index 000000000..240855a8b
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/riff.h
@@ -0,0 +1,51 @@
+/*
+ * RIFF codec tags
+ * 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
+ */
+
+#ifndef FF_RIFF_H
+#define FF_RIFF_H
+
+offset_t start_tag(ByteIOContext *pb, const char *tag);
+void end_tag(ByteIOContext *pb, offset_t start);
+
+typedef struct CodecTag {
+ int id;
+ unsigned int tag;
+ unsigned int invalid_asf : 1;
+} CodecTag;
+
+void put_bmp_header(ByteIOContext *pb, AVCodecContext *enc, const CodecTag *tags, int for_asf);
+int put_wav_header(ByteIOContext *pb, AVCodecContext *enc);
+int wav_codec_get_id(unsigned int tag, int bps);
+void get_wav_header(ByteIOContext *pb, AVCodecContext *codec, int size);
+
+extern const CodecTag codec_bmp_tags[];
+extern const CodecTag codec_wav_tags[];
+
+unsigned int codec_get_tag(const CodecTag *tags, int id);
+enum CodecID codec_get_id(const CodecTag *tags, unsigned int tag);
+unsigned int codec_get_bmp_tag(int id);
+unsigned int codec_get_wav_tag(int id);
+enum CodecID codec_get_bmp_id(unsigned int tag);
+enum CodecID codec_get_wav_id(unsigned int tag);
+unsigned int codec_get_asf_tag(const CodecTag *tags, unsigned int id);
+void ff_parse_specific_params(AVCodecContext *stream, int *au_rate, int *au_ssize, int *au_scale);
+
+#endif
diff --git a/contrib/ffmpeg/libavformat/rm.c b/contrib/ffmpeg/libavformat/rm.c
new file mode 100644
index 000000000..b4ddf1b02
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rm.c
@@ -0,0 +1,1146 @@
+/*
+ * "Real" compatible muxer and demuxer.
+ * 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 "avformat.h"
+
+/* in ms */
+#define BUFFER_DURATION 0
+
+typedef struct {
+ int nb_packets;
+ int packet_total_size;
+ int packet_max_size;
+ /* codec related output */
+ int bit_rate;
+ float frame_rate;
+ int nb_frames; /* current frame number */
+ int total_frames; /* total number of frames */
+ int num;
+ AVCodecContext *enc;
+} StreamInfo;
+
+typedef struct {
+ StreamInfo streams[2];
+ StreamInfo *audio_stream, *video_stream;
+ int data_pos; /* position of the data after the header */
+ int nb_packets;
+ int old_format;
+ int current_stream;
+ int remaining_len;
+ /// Audio descrambling matrix parameters
+ uint8_t *audiobuf; ///< place to store reordered audio data
+ int64_t audiotimestamp; ///< Audio packet timestamp
+ int sub_packet_cnt; // Subpacket counter, used while reading
+ int sub_packet_size, sub_packet_h, coded_framesize; ///< Descrambling parameters from container
+ int audio_stream_num; ///< Stream number for audio packets
+ int audio_pkt_cnt; ///< Output packet counter
+ int audio_framesize; /// Audio frame size from container
+ int sub_packet_lengths[16]; /// Length of each aac subpacket
+} RMContext;
+
+#ifdef CONFIG_MUXERS
+static void put_str(ByteIOContext *s, const char *tag)
+{
+ put_be16(s,strlen(tag));
+ while (*tag) {
+ put_byte(s, *tag++);
+ }
+}
+
+static void put_str8(ByteIOContext *s, const char *tag)
+{
+ put_byte(s, strlen(tag));
+ while (*tag) {
+ put_byte(s, *tag++);
+ }
+}
+
+static void rv10_write_header(AVFormatContext *ctx,
+ int data_size, int index_pos)
+{
+ RMContext *rm = ctx->priv_data;
+ ByteIOContext *s = &ctx->pb;
+ StreamInfo *stream;
+ unsigned char *data_offset_ptr, *start_ptr;
+ const char *desc, *mimetype;
+ int nb_packets, packet_total_size, packet_max_size, size, packet_avg_size, i;
+ int bit_rate, v, duration, flags, data_pos;
+
+ start_ptr = s->buf_ptr;
+
+ put_tag(s, ".RMF");
+ put_be32(s,18); /* header size */
+ put_be16(s,0);
+ put_be32(s,0);
+ put_be32(s,4 + ctx->nb_streams); /* num headers */
+
+ put_tag(s,"PROP");
+ put_be32(s, 50);
+ put_be16(s, 0);
+ packet_max_size = 0;
+ packet_total_size = 0;
+ nb_packets = 0;
+ bit_rate = 0;
+ duration = 0;
+ for(i=0;i<ctx->nb_streams;i++) {
+ StreamInfo *stream = &rm->streams[i];
+ bit_rate += stream->bit_rate;
+ if (stream->packet_max_size > packet_max_size)
+ packet_max_size = stream->packet_max_size;
+ nb_packets += stream->nb_packets;
+ packet_total_size += stream->packet_total_size;
+ /* select maximum duration */
+ v = (int) (1000.0 * (float)stream->total_frames / stream->frame_rate);
+ if (v > duration)
+ duration = v;
+ }
+ put_be32(s, bit_rate); /* max bit rate */
+ put_be32(s, bit_rate); /* avg bit rate */
+ put_be32(s, packet_max_size); /* max packet size */
+ if (nb_packets > 0)
+ packet_avg_size = packet_total_size / nb_packets;
+ else
+ packet_avg_size = 0;
+ put_be32(s, packet_avg_size); /* avg packet size */
+ put_be32(s, nb_packets); /* num packets */
+ put_be32(s, duration); /* duration */
+ put_be32(s, BUFFER_DURATION); /* preroll */
+ put_be32(s, index_pos); /* index offset */
+ /* computation of data the data offset */
+ data_offset_ptr = s->buf_ptr;
+ put_be32(s, 0); /* data offset : will be patched after */
+ put_be16(s, ctx->nb_streams); /* num streams */
+ flags = 1 | 2; /* save allowed & perfect play */
+ if (url_is_streamed(s))
+ flags |= 4; /* live broadcast */
+ put_be16(s, flags);
+
+ /* comments */
+
+ put_tag(s,"CONT");
+ size = strlen(ctx->title) + strlen(ctx->author) + strlen(ctx->copyright) +
+ strlen(ctx->comment) + 4 * 2 + 10;
+ put_be32(s,size);
+ put_be16(s,0);
+ put_str(s, ctx->title);
+ put_str(s, ctx->author);
+ put_str(s, ctx->copyright);
+ put_str(s, ctx->comment);
+
+ for(i=0;i<ctx->nb_streams;i++) {
+ int codec_data_size;
+
+ stream = &rm->streams[i];
+
+ if (stream->enc->codec_type == CODEC_TYPE_AUDIO) {
+ desc = "The Audio Stream";
+ mimetype = "audio/x-pn-realaudio";
+ codec_data_size = 73;
+ } else {
+ desc = "The Video Stream";
+ mimetype = "video/x-pn-realvideo";
+ codec_data_size = 34;
+ }
+
+ put_tag(s,"MDPR");
+ size = 10 + 9 * 4 + strlen(desc) + strlen(mimetype) + codec_data_size;
+ put_be32(s, size);
+ put_be16(s, 0);
+
+ put_be16(s, i); /* stream number */
+ put_be32(s, stream->bit_rate); /* max bit rate */
+ put_be32(s, stream->bit_rate); /* avg bit rate */
+ put_be32(s, stream->packet_max_size); /* max packet size */
+ if (stream->nb_packets > 0)
+ packet_avg_size = stream->packet_total_size /
+ stream->nb_packets;
+ else
+ packet_avg_size = 0;
+ put_be32(s, packet_avg_size); /* avg packet size */
+ put_be32(s, 0); /* start time */
+ put_be32(s, BUFFER_DURATION); /* preroll */
+ /* duration */
+ if (url_is_streamed(s) || !stream->total_frames)
+ put_be32(s, (int)(3600 * 1000));
+ else
+ put_be32(s, (int)(stream->total_frames * 1000 / stream->frame_rate));
+ put_str8(s, desc);
+ put_str8(s, mimetype);
+ put_be32(s, codec_data_size);
+
+ if (stream->enc->codec_type == CODEC_TYPE_AUDIO) {
+ int coded_frame_size, fscode, sample_rate;
+ sample_rate = stream->enc->sample_rate;
+ coded_frame_size = (stream->enc->bit_rate *
+ stream->enc->frame_size) / (8 * sample_rate);
+ /* audio codec info */
+ put_tag(s, ".ra");
+ put_byte(s, 0xfd);
+ put_be32(s, 0x00040000); /* version */
+ put_tag(s, ".ra4");
+ put_be32(s, 0x01b53530); /* stream length */
+ put_be16(s, 4); /* unknown */
+ put_be32(s, 0x39); /* header size */
+
+ switch(sample_rate) {
+ case 48000:
+ case 24000:
+ case 12000:
+ fscode = 1;
+ break;
+ default:
+ case 44100:
+ case 22050:
+ case 11025:
+ fscode = 2;
+ break;
+ case 32000:
+ case 16000:
+ case 8000:
+ fscode = 3;
+ }
+ put_be16(s, fscode); /* codec additional info, for AC3, seems
+ to be a frequency code */
+ /* special hack to compensate rounding errors... */
+ if (coded_frame_size == 557)
+ coded_frame_size--;
+ put_be32(s, coded_frame_size); /* frame length */
+ put_be32(s, 0x51540); /* unknown */
+ put_be32(s, 0x249f0); /* unknown */
+ put_be32(s, 0x249f0); /* unknown */
+ put_be16(s, 0x01);
+ /* frame length : seems to be very important */
+ put_be16(s, coded_frame_size);
+ put_be32(s, 0); /* unknown */
+ put_be16(s, stream->enc->sample_rate); /* sample rate */
+ put_be32(s, 0x10); /* unknown */
+ put_be16(s, stream->enc->channels);
+ put_str8(s, "Int0"); /* codec name */
+ put_str8(s, "dnet"); /* codec name */
+ put_be16(s, 0); /* title length */
+ put_be16(s, 0); /* author length */
+ put_be16(s, 0); /* copyright length */
+ put_byte(s, 0); /* end of header */
+ } else {
+ /* video codec info */
+ put_be32(s,34); /* size */
+ if(stream->enc->codec_id == CODEC_ID_RV10)
+ put_tag(s,"VIDORV10");
+ else
+ put_tag(s,"VIDORV20");
+ put_be16(s, stream->enc->width);
+ put_be16(s, stream->enc->height);
+ put_be16(s, (int) stream->frame_rate); /* frames per seconds ? */
+ put_be32(s,0); /* unknown meaning */
+ put_be16(s, (int) stream->frame_rate); /* unknown meaning */
+ put_be32(s,0); /* unknown meaning */
+ put_be16(s, 8); /* unknown meaning */
+ /* Seems to be the codec version: only use basic H263. The next
+ versions seems to add a diffential DC coding as in
+ MPEG... nothing new under the sun */
+ if(stream->enc->codec_id == CODEC_ID_RV10)
+ put_be32(s,0x10000000);
+ else
+ put_be32(s,0x20103001);
+ //put_be32(s,0x10003000);
+ }
+ }
+
+ /* patch data offset field */
+ data_pos = s->buf_ptr - start_ptr;
+ rm->data_pos = data_pos;
+ data_offset_ptr[0] = data_pos >> 24;
+ data_offset_ptr[1] = data_pos >> 16;
+ data_offset_ptr[2] = data_pos >> 8;
+ data_offset_ptr[3] = data_pos;
+
+ /* data stream */
+ put_tag(s,"DATA");
+ put_be32(s,data_size + 10 + 8);
+ put_be16(s,0);
+
+ put_be32(s, nb_packets); /* number of packets */
+ put_be32(s,0); /* next data header */
+}
+
+static void write_packet_header(AVFormatContext *ctx, StreamInfo *stream,
+ int length, int key_frame)
+{
+ int timestamp;
+ ByteIOContext *s = &ctx->pb;
+
+ stream->nb_packets++;
+ stream->packet_total_size += length;
+ if (length > stream->packet_max_size)
+ stream->packet_max_size = length;
+
+ put_be16(s,0); /* version */
+ put_be16(s,length + 12);
+ put_be16(s, stream->num); /* stream number */
+ timestamp = (1000 * (float)stream->nb_frames) / stream->frame_rate;
+ put_be32(s, timestamp); /* timestamp */
+ put_byte(s, 0); /* reserved */
+ put_byte(s, key_frame ? 2 : 0); /* flags */
+}
+
+static int rm_write_header(AVFormatContext *s)
+{
+ RMContext *rm = s->priv_data;
+ StreamInfo *stream;
+ int n;
+ AVCodecContext *codec;
+
+ for(n=0;n<s->nb_streams;n++) {
+ s->streams[n]->id = n;
+ codec = s->streams[n]->codec;
+ stream = &rm->streams[n];
+ memset(stream, 0, sizeof(StreamInfo));
+ stream->num = n;
+ stream->bit_rate = codec->bit_rate;
+ stream->enc = codec;
+
+ switch(codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ rm->audio_stream = stream;
+ stream->frame_rate = (float)codec->sample_rate / (float)codec->frame_size;
+ /* XXX: dummy values */
+ stream->packet_max_size = 1024;
+ stream->nb_packets = 0;
+ stream->total_frames = stream->nb_packets;
+ break;
+ case CODEC_TYPE_VIDEO:
+ rm->video_stream = stream;
+ stream->frame_rate = (float)codec->time_base.den / (float)codec->time_base.num;
+ /* XXX: dummy values */
+ stream->packet_max_size = 4096;
+ stream->nb_packets = 0;
+ stream->total_frames = stream->nb_packets;
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ rv10_write_header(s, 0, 0);
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+static int rm_write_audio(AVFormatContext *s, const uint8_t *buf, int size, int flags)
+{
+ uint8_t *buf1;
+ RMContext *rm = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ StreamInfo *stream = rm->audio_stream;
+ int i;
+
+ /* XXX: suppress this malloc */
+ buf1= (uint8_t*) av_malloc( size * sizeof(uint8_t) );
+
+ write_packet_header(s, stream, size, !!(flags & PKT_FLAG_KEY));
+
+ /* for AC3, the words seems to be reversed */
+ for(i=0;i<size;i+=2) {
+ buf1[i] = buf[i+1];
+ buf1[i+1] = buf[i];
+ }
+ put_buffer(pb, buf1, size);
+ put_flush_packet(pb);
+ stream->nb_frames++;
+ av_free(buf1);
+ return 0;
+}
+
+static int rm_write_video(AVFormatContext *s, const uint8_t *buf, int size, int flags)
+{
+ RMContext *rm = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ StreamInfo *stream = rm->video_stream;
+ int key_frame = !!(flags & PKT_FLAG_KEY);
+
+ /* XXX: this is incorrect: should be a parameter */
+
+ /* Well, I spent some time finding the meaning of these bits. I am
+ not sure I understood everything, but it works !! */
+#if 1
+ write_packet_header(s, stream, size + 7, key_frame);
+ /* bit 7: '1' if final packet of a frame converted in several packets */
+ put_byte(pb, 0x81);
+ /* bit 7: '1' if I frame. bits 6..0 : sequence number in current
+ frame starting from 1 */
+ if (key_frame) {
+ put_byte(pb, 0x81);
+ } else {
+ put_byte(pb, 0x01);
+ }
+ put_be16(pb, 0x4000 + (size)); /* total frame size */
+ put_be16(pb, 0x4000 + (size)); /* offset from the start or the end */
+#else
+ /* full frame */
+ write_packet_header(s, size + 6);
+ put_byte(pb, 0xc0);
+ put_be16(pb, 0x4000 + size); /* total frame size */
+ put_be16(pb, 0x4000 + packet_number * 126); /* position in stream */
+#endif
+ put_byte(pb, stream->nb_frames & 0xff);
+
+ put_buffer(pb, buf, size);
+ put_flush_packet(pb);
+
+ stream->nb_frames++;
+ return 0;
+}
+
+static int rm_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ if (s->streams[pkt->stream_index]->codec->codec_type ==
+ CODEC_TYPE_AUDIO)
+ return rm_write_audio(s, pkt->data, pkt->size, pkt->flags);
+ else
+ return rm_write_video(s, pkt->data, pkt->size, pkt->flags);
+}
+
+static int rm_write_trailer(AVFormatContext *s)
+{
+ RMContext *rm = s->priv_data;
+ int data_size, index_pos, i;
+ ByteIOContext *pb = &s->pb;
+
+ if (!url_is_streamed(&s->pb)) {
+ /* end of file: finish to write header */
+ index_pos = url_fseek(pb, 0, SEEK_CUR);
+ data_size = index_pos - rm->data_pos;
+
+ /* index */
+ put_tag(pb, "INDX");
+ put_be32(pb, 10 + 10 * s->nb_streams);
+ put_be16(pb, 0);
+
+ for(i=0;i<s->nb_streams;i++) {
+ put_be32(pb, 0); /* zero indices */
+ put_be16(pb, i); /* stream number */
+ put_be32(pb, 0); /* next index */
+ }
+ /* undocumented end header */
+ put_be32(pb, 0);
+ put_be32(pb, 0);
+
+ url_fseek(pb, 0, SEEK_SET);
+ for(i=0;i<s->nb_streams;i++)
+ rm->streams[i].total_frames = rm->streams[i].nb_frames;
+ rv10_write_header(s, data_size, index_pos);
+ } else {
+ /* undocumented end header */
+ put_be32(pb, 0);
+ put_be32(pb, 0);
+ }
+ put_flush_packet(pb);
+ return 0;
+}
+#endif //CONFIG_MUXERS
+
+/***************************************************/
+
+static void get_str(ByteIOContext *pb, char *buf, int buf_size)
+{
+ int len, i;
+ char *q;
+
+ len = get_be16(pb);
+ q = buf;
+ for(i=0;i<len;i++) {
+ if (i < buf_size - 1)
+ *q++ = get_byte(pb);
+ }
+ *q = '\0';
+}
+
+static void get_str8(ByteIOContext *pb, char *buf, int buf_size)
+{
+ int len, i;
+ char *q;
+
+ len = get_byte(pb);
+ q = buf;
+ for(i=0;i<len;i++) {
+ if (i < buf_size - 1)
+ *q++ = get_byte(pb);
+ }
+ *q = '\0';
+}
+
+static int rm_read_audio_stream_info(AVFormatContext *s, AVStream *st,
+ int read_all)
+{
+ RMContext *rm = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ char buf[256];
+ uint32_t version;
+ int i;
+
+ /* ra type header */
+ version = get_be32(pb); /* version */
+ if (((version >> 16) & 0xff) == 3) {
+ int64_t startpos = url_ftell(pb);
+ /* very old version */
+ for(i = 0; i < 14; i++)
+ get_byte(pb);
+ get_str8(pb, s->title, sizeof(s->title));
+ get_str8(pb, s->author, sizeof(s->author));
+ get_str8(pb, s->copyright, sizeof(s->copyright));
+ get_str8(pb, s->comment, sizeof(s->comment));
+ if ((startpos + (version & 0xffff)) >= url_ftell(pb) + 2) {
+ // fourcc (should always be "lpcJ")
+ get_byte(pb);
+ get_str8(pb, buf, sizeof(buf));
+ }
+ // Skip extra header crap (this should never happen)
+ if ((startpos + (version & 0xffff)) > url_ftell(pb))
+ url_fskip(pb, (version & 0xffff) + startpos - url_ftell(pb));
+ st->codec->sample_rate = 8000;
+ st->codec->channels = 1;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_RA_144;
+ } else {
+ int flavor, sub_packet_h, coded_framesize, sub_packet_size;
+ /* old version (4) */
+ get_be32(pb); /* .ra4 */
+ get_be32(pb); /* data size */
+ get_be16(pb); /* version2 */
+ get_be32(pb); /* header size */
+ flavor= get_be16(pb); /* add codec info / flavor */
+ rm->coded_framesize = coded_framesize = get_be32(pb); /* coded frame size */
+ get_be32(pb); /* ??? */
+ get_be32(pb); /* ??? */
+ get_be32(pb); /* ??? */
+ rm->sub_packet_h = sub_packet_h = get_be16(pb); /* 1 */
+ st->codec->block_align= get_be16(pb); /* frame size */
+ rm->sub_packet_size = sub_packet_size = get_be16(pb); /* sub packet size */
+ get_be16(pb); /* ??? */
+ if (((version >> 16) & 0xff) == 5) {
+ get_be16(pb); get_be16(pb); get_be16(pb); }
+ st->codec->sample_rate = get_be16(pb);
+ get_be32(pb);
+ st->codec->channels = get_be16(pb);
+ if (((version >> 16) & 0xff) == 5) {
+ get_be32(pb);
+ buf[0] = get_byte(pb);
+ buf[1] = get_byte(pb);
+ buf[2] = get_byte(pb);
+ buf[3] = get_byte(pb);
+ buf[4] = 0;
+ } else {
+ get_str8(pb, buf, sizeof(buf)); /* desc */
+ get_str8(pb, buf, sizeof(buf)); /* desc */
+ }
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ if (!strcmp(buf, "dnet")) {
+ st->codec->codec_id = CODEC_ID_AC3;
+ } else if (!strcmp(buf, "28_8")) {
+ st->codec->codec_id = CODEC_ID_RA_288;
+ st->codec->extradata_size= 0;
+ rm->audio_framesize = st->codec->block_align;
+ st->codec->block_align = coded_framesize;
+
+ if(rm->audio_framesize >= UINT_MAX / sub_packet_h){
+ av_log(s, AV_LOG_ERROR, "rm->audio_framesize * sub_packet_h too large\n");
+ return -1;
+ }
+
+ rm->audiobuf = av_malloc(rm->audio_framesize * sub_packet_h);
+ } else if (!strcmp(buf, "cook")) {
+ int codecdata_length, i;
+ get_be16(pb); get_byte(pb);
+ if (((version >> 16) & 0xff) == 5)
+ get_byte(pb);
+ codecdata_length = get_be32(pb);
+ if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){
+ av_log(s, AV_LOG_ERROR, "codecdata_length too large\n");
+ return -1;
+ }
+
+ st->codec->codec_id = CODEC_ID_COOK;
+ st->codec->extradata_size= codecdata_length;
+ st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ for(i = 0; i < codecdata_length; i++)
+ ((uint8_t*)st->codec->extradata)[i] = get_byte(pb);
+ rm->audio_framesize = st->codec->block_align;
+ st->codec->block_align = rm->sub_packet_size;
+
+ if(rm->audio_framesize >= UINT_MAX / sub_packet_h){
+ av_log(s, AV_LOG_ERROR, "rm->audio_framesize * sub_packet_h too large\n");
+ return -1;
+ }
+
+ rm->audiobuf = av_malloc(rm->audio_framesize * sub_packet_h);
+ } else if (!strcmp(buf, "raac") || !strcmp(buf, "racp")) {
+ int codecdata_length, i;
+ get_be16(pb); get_byte(pb);
+ if (((version >> 16) & 0xff) == 5)
+ get_byte(pb);
+ st->codec->codec_id = CODEC_ID_AAC;
+ codecdata_length = get_be32(pb);
+ if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){
+ av_log(s, AV_LOG_ERROR, "codecdata_length too large\n");
+ return -1;
+ }
+ if (codecdata_length >= 1) {
+ st->codec->extradata_size = codecdata_length - 1;
+ st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ get_byte(pb);
+ for(i = 0; i < st->codec->extradata_size; i++)
+ ((uint8_t*)st->codec->extradata)[i] = get_byte(pb);
+ }
+ } else {
+ st->codec->codec_id = CODEC_ID_NONE;
+ pstrcpy(st->codec->codec_name, sizeof(st->codec->codec_name),
+ buf);
+ }
+ if (read_all) {
+ get_byte(pb);
+ get_byte(pb);
+ get_byte(pb);
+
+ get_str8(pb, s->title, sizeof(s->title));
+ get_str8(pb, s->author, sizeof(s->author));
+ get_str8(pb, s->copyright, sizeof(s->copyright));
+ get_str8(pb, s->comment, sizeof(s->comment));
+ }
+ }
+ return 0;
+}
+
+static int rm_read_header_old(AVFormatContext *s, AVFormatParameters *ap)
+{
+ RMContext *rm = s->priv_data;
+ AVStream *st;
+
+ rm->old_format = 1;
+ st = av_new_stream(s, 0);
+ if (!st)
+ return -1;
+ return rm_read_audio_stream_info(s, st, 1);
+}
+
+static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ RMContext *rm = s->priv_data;
+ AVStream *st;
+ ByteIOContext *pb = &s->pb;
+ unsigned int tag, v;
+ int tag_size, size, codec_data_size, i;
+ int64_t codec_pos;
+ unsigned int start_time, duration;
+ char buf[128];
+ int flags = 0;
+
+ tag = get_le32(pb);
+ if (tag == MKTAG('.', 'r', 'a', 0xfd)) {
+ /* very old .ra format */
+ return rm_read_header_old(s, ap);
+ } else if (tag != MKTAG('.', 'R', 'M', 'F')) {
+ return AVERROR_IO;
+ }
+
+ get_be32(pb); /* header size */
+ get_be16(pb);
+ get_be32(pb);
+ get_be32(pb); /* number of headers */
+
+ for(;;) {
+ if (url_feof(pb))
+ goto fail;
+ tag = get_le32(pb);
+ tag_size = get_be32(pb);
+ get_be16(pb);
+#if 0
+ printf("tag=%c%c%c%c (%08x) size=%d\n",
+ (tag) & 0xff,
+ (tag >> 8) & 0xff,
+ (tag >> 16) & 0xff,
+ (tag >> 24) & 0xff,
+ tag,
+ tag_size);
+#endif
+ if (tag_size < 10 && tag != MKTAG('D', 'A', 'T', 'A'))
+ goto fail;
+ switch(tag) {
+ case MKTAG('P', 'R', 'O', 'P'):
+ /* file header */
+ get_be32(pb); /* max bit rate */
+ get_be32(pb); /* avg bit rate */
+ get_be32(pb); /* max packet size */
+ get_be32(pb); /* avg packet size */
+ get_be32(pb); /* nb packets */
+ get_be32(pb); /* duration */
+ get_be32(pb); /* preroll */
+ get_be32(pb); /* index offset */
+ get_be32(pb); /* data offset */
+ get_be16(pb); /* nb streams */
+ flags = get_be16(pb); /* flags */
+ break;
+ case MKTAG('C', 'O', 'N', 'T'):
+ get_str(pb, s->title, sizeof(s->title));
+ get_str(pb, s->author, sizeof(s->author));
+ get_str(pb, s->copyright, sizeof(s->copyright));
+ get_str(pb, s->comment, sizeof(s->comment));
+ break;
+ case MKTAG('M', 'D', 'P', 'R'):
+ st = av_new_stream(s, 0);
+ if (!st)
+ goto fail;
+ st->id = get_be16(pb);
+ get_be32(pb); /* max bit rate */
+ st->codec->bit_rate = get_be32(pb); /* bit rate */
+ get_be32(pb); /* max packet size */
+ get_be32(pb); /* avg packet size */
+ start_time = get_be32(pb); /* start time */
+ get_be32(pb); /* preroll */
+ duration = get_be32(pb); /* duration */
+ st->start_time = start_time;
+ st->duration = duration;
+ get_str8(pb, buf, sizeof(buf)); /* desc */
+ get_str8(pb, buf, sizeof(buf)); /* mimetype */
+ codec_data_size = get_be32(pb);
+ codec_pos = url_ftell(pb);
+ st->codec->codec_type = CODEC_TYPE_DATA;
+ av_set_pts_info(st, 64, 1, 1000);
+
+ v = get_be32(pb);
+ if (v == MKTAG(0xfd, 'a', 'r', '.')) {
+ /* ra type header */
+ if (rm_read_audio_stream_info(s, st, 0))
+ return -1;
+ } else {
+ int fps, fps2;
+ if (get_le32(pb) != MKTAG('V', 'I', 'D', 'O')) {
+ fail1:
+ av_log(st->codec, AV_LOG_ERROR, "Unsupported video codec\n");
+ goto skip;
+ }
+ st->codec->codec_tag = get_le32(pb);
+// av_log(NULL, AV_LOG_DEBUG, "%X %X\n", st->codec->codec_tag, MKTAG('R', 'V', '2', '0'));
+ if ( st->codec->codec_tag != MKTAG('R', 'V', '1', '0')
+ && st->codec->codec_tag != MKTAG('R', 'V', '2', '0')
+ && st->codec->codec_tag != MKTAG('R', 'V', '3', '0')
+ && st->codec->codec_tag != MKTAG('R', 'V', '4', '0'))
+ goto fail1;
+ st->codec->width = get_be16(pb);
+ st->codec->height = get_be16(pb);
+ st->codec->time_base.num= 1;
+ fps= get_be16(pb);
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ get_be32(pb);
+ fps2= get_be16(pb);
+ get_be16(pb);
+
+ st->codec->extradata_size= codec_data_size - (url_ftell(pb) - codec_pos);
+
+ if(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)st->codec->extradata_size){
+ //check is redundant as get_buffer() will catch this
+ av_log(s, AV_LOG_ERROR, "st->codec->extradata_size too large\n");
+ return -1;
+ }
+ st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
+
+// av_log(NULL, AV_LOG_DEBUG, "fps= %d fps2= %d\n", fps, fps2);
+ st->codec->time_base.den = fps * st->codec->time_base.num;
+ switch(((uint8_t*)st->codec->extradata)[4]>>4){
+ case 1: st->codec->codec_id = CODEC_ID_RV10; break;
+ case 2: st->codec->codec_id = CODEC_ID_RV20; break;
+ case 3: st->codec->codec_id = CODEC_ID_RV30; break;
+ case 4: st->codec->codec_id = CODEC_ID_RV40; break;
+ default: goto fail1;
+ }
+ }
+skip:
+ /* skip codec info */
+ size = url_ftell(pb) - codec_pos;
+ url_fskip(pb, codec_data_size - size);
+ break;
+ case MKTAG('D', 'A', 'T', 'A'):
+ goto header_end;
+ default:
+ /* unknown tag: skip it */
+ url_fskip(pb, tag_size - 10);
+ break;
+ }
+ }
+ header_end:
+ rm->nb_packets = get_be32(pb); /* number of packets */
+ if (!rm->nb_packets && (flags & 4))
+ rm->nb_packets = 3600 * 25;
+ get_be32(pb); /* next data header */
+ return 0;
+
+ fail:
+ for(i=0;i<s->nb_streams;i++) {
+ av_free(s->streams[i]);
+ }
+ return AVERROR_IO;
+}
+
+static int get_num(ByteIOContext *pb, int *len)
+{
+ int n, n1;
+
+ n = get_be16(pb);
+ (*len)-=2;
+ if (n >= 0x4000) {
+ return n - 0x4000;
+ } else {
+ n1 = get_be16(pb);
+ (*len)-=2;
+ return (n << 16) | n1;
+ }
+}
+
+/* multiple of 20 bytes for ra144 (ugly) */
+#define RAW_PACKET_SIZE 1000
+
+static int sync(AVFormatContext *s, int64_t *timestamp, int *flags, int *stream_index, int64_t *pos){
+ RMContext *rm = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int len, num, res, i;
+ AVStream *st;
+ uint32_t state=0xFFFFFFFF;
+
+ while(!url_feof(pb)){
+ *pos= url_ftell(pb);
+ if(rm->remaining_len > 0){
+ num= rm->current_stream;
+ len= rm->remaining_len;
+ *timestamp = AV_NOPTS_VALUE;
+ *flags= 0;
+ }else{
+ state= (state<<8) + get_byte(pb);
+
+ if(state == MKBETAG('I', 'N', 'D', 'X')){
+ len = get_be16(pb) - 6;
+ if(len<0)
+ continue;
+ goto skip;
+ }
+
+ if(state > (unsigned)0xFFFF || state < 12)
+ continue;
+ len=state;
+ state= 0xFFFFFFFF;
+
+ num = get_be16(pb);
+ *timestamp = get_be32(pb);
+ res= get_byte(pb); /* reserved */
+ *flags = get_byte(pb); /* flags */
+
+
+ len -= 12;
+ }
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+ if (num == st->id)
+ break;
+ }
+ if (i == s->nb_streams) {
+skip:
+ /* skip packet if unknown number */
+ url_fskip(pb, len);
+ rm->remaining_len -= len;
+ continue;
+ }
+ *stream_index= i;
+
+ return len;
+ }
+ return -1;
+}
+
+static int rm_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ RMContext *rm = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVStream *st;
+ int i, len, tmp, j;
+ int64_t timestamp, pos;
+ uint8_t *ptr;
+ int flags;
+
+ if (rm->audio_pkt_cnt) {
+ // If there are queued audio packet return them first
+ st = s->streams[rm->audio_stream_num];
+ if (st->codec->codec_id == CODEC_ID_AAC)
+ av_get_packet(pb, pkt, rm->sub_packet_lengths[rm->sub_packet_cnt - rm->audio_pkt_cnt]);
+ else {
+ av_new_packet(pkt, st->codec->block_align);
+ memcpy(pkt->data, rm->audiobuf + st->codec->block_align *
+ (rm->sub_packet_h * rm->audio_framesize / st->codec->block_align - rm->audio_pkt_cnt),
+ st->codec->block_align);
+ }
+ rm->audio_pkt_cnt--;
+ pkt->flags = 0;
+ pkt->stream_index = rm->audio_stream_num;
+ } else if (rm->old_format) {
+ st = s->streams[0];
+ if (st->codec->codec_id == CODEC_ID_RA_288) {
+ int x, y;
+
+ for (y = 0; y < rm->sub_packet_h; y++)
+ for (x = 0; x < rm->sub_packet_h/2; x++)
+ if (get_buffer(pb, rm->audiobuf+x*2*rm->audio_framesize+y*rm->coded_framesize, rm->coded_framesize) <= 0)
+ return AVERROR_IO;
+ rm->audio_stream_num = 0;
+ rm->audio_pkt_cnt = rm->sub_packet_h * rm->audio_framesize / st->codec->block_align - 1;
+ // Release first audio packet
+ av_new_packet(pkt, st->codec->block_align);
+ memcpy(pkt->data, rm->audiobuf, st->codec->block_align);
+ pkt->flags |= PKT_FLAG_KEY; // Mark first packet as keyframe
+ pkt->stream_index = 0;
+ } else {
+ /* just read raw bytes */
+ len = RAW_PACKET_SIZE;
+ len= av_get_packet(pb, pkt, len);
+ pkt->stream_index = 0;
+ if (len <= 0) {
+ return AVERROR_IO;
+ }
+ pkt->size = len;
+ }
+ } else {
+ int seq=1;
+resync:
+ len=sync(s, &timestamp, &flags, &i, &pos);
+ if(len<0)
+ return AVERROR_IO;
+ st = s->streams[i];
+
+ if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ int h, pic_num, len2, pos;
+
+ h= get_byte(pb); len--;
+ if(!(h & 0x40)){
+ seq = get_byte(pb); len--;
+ }
+
+ if((h & 0xc0) == 0x40){
+ len2= pos= 0;
+ }else{
+ len2 = get_num(pb, &len);
+ pos = get_num(pb, &len);
+ }
+ /* picture number */
+ pic_num= get_byte(pb); len--;
+ rm->remaining_len= len;
+ rm->current_stream= st->id;
+
+// av_log(NULL, AV_LOG_DEBUG, "%X len:%d pos:%d len2:%d pic_num:%d\n",h, len, pos, len2, pic_num);
+ if(len2 && len2<len)
+ len=len2;
+ rm->remaining_len-= len;
+ av_get_packet(pb, pkt, len);
+ }
+
+ if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
+ if ((st->codec->codec_id == CODEC_ID_RA_288) ||
+ (st->codec->codec_id == CODEC_ID_COOK)) {
+ int x;
+ int sps = rm->sub_packet_size;
+ int cfs = rm->coded_framesize;
+ int h = rm->sub_packet_h;
+ int y = rm->sub_packet_cnt;
+ int w = rm->audio_framesize;
+
+ if (flags & 2)
+ y = rm->sub_packet_cnt = 0;
+ if (!y)
+ rm->audiotimestamp = timestamp;
+
+ switch(st->codec->codec_id) {
+ case CODEC_ID_RA_288:
+ for (x = 0; x < h/2; x++)
+ get_buffer(pb, rm->audiobuf+x*2*w+y*cfs, cfs);
+ break;
+ case CODEC_ID_COOK:
+ for (x = 0; x < w/sps; x++)
+ get_buffer(pb, rm->audiobuf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), sps);
+ break;
+ }
+
+ if (++(rm->sub_packet_cnt) < h)
+ goto resync;
+ else {
+ rm->sub_packet_cnt = 0;
+ rm->audio_stream_num = i;
+ rm->audio_pkt_cnt = h * w / st->codec->block_align - 1;
+ // Release first audio packet
+ av_new_packet(pkt, st->codec->block_align);
+ memcpy(pkt->data, rm->audiobuf, st->codec->block_align);
+ timestamp = rm->audiotimestamp;
+ flags = 2; // Mark first packet as keyframe
+ }
+ } else if (st->codec->codec_id == CODEC_ID_AAC) {
+ int x;
+ rm->audio_stream_num = i;
+ rm->sub_packet_cnt = (get_be16(pb) & 0xf0) >> 4;
+ if (rm->sub_packet_cnt) {
+ for (x = 0; x < rm->sub_packet_cnt; x++)
+ rm->sub_packet_lengths[x] = get_be16(pb);
+ // Release first audio packet
+ rm->audio_pkt_cnt = rm->sub_packet_cnt - 1;
+ av_get_packet(pb, pkt, rm->sub_packet_lengths[0]);
+ flags = 2; // Mark first packet as keyframe
+ }
+ } else
+ av_get_packet(pb, pkt, len);
+ }
+
+ if( (st->discard >= AVDISCARD_NONKEY && !(flags&2))
+ || st->discard >= AVDISCARD_ALL){
+ av_free_packet(pkt);
+ goto resync;
+ }
+
+ pkt->stream_index = i;
+
+#if 0
+ if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ if(st->codec->codec_id == CODEC_ID_RV20){
+ int seq= 128*(pkt->data[2]&0x7F) + (pkt->data[3]>>1);
+ av_log(NULL, AV_LOG_DEBUG, "%d %"PRId64" %d\n", timestamp, timestamp*512LL/25, seq);
+
+ seq |= (timestamp&~0x3FFF);
+ if(seq - timestamp > 0x2000) seq -= 0x4000;
+ if(seq - timestamp < -0x2000) seq += 0x4000;
+ }
+ }
+#endif
+ pkt->pts= timestamp;
+ if(flags&2){
+ pkt->flags |= PKT_FLAG_KEY;
+ if((seq&0x7F) == 1)
+ av_add_index_entry(st, pos, timestamp, 0, 0, AVINDEX_KEYFRAME);
+ }
+ }
+
+ /* for AC3, needs to swap bytes */
+ if (st->codec->codec_id == CODEC_ID_AC3) {
+ ptr = pkt->data;
+ for(j=0;j<len;j+=2) {
+ tmp = ptr[0];
+ ptr[0] = ptr[1];
+ ptr[1] = tmp;
+ ptr += 2;
+ }
+ }
+ return 0;
+}
+
+static int rm_read_close(AVFormatContext *s)
+{
+ RMContext *rm = s->priv_data;
+
+ av_free(rm->audiobuf);
+ return 0;
+}
+
+static int rm_probe(AVProbeData *p)
+{
+ /* check file header */
+ if (p->buf_size <= 32)
+ return 0;
+ if ((p->buf[0] == '.' && p->buf[1] == 'R' &&
+ p->buf[2] == 'M' && p->buf[3] == 'F' &&
+ p->buf[4] == 0 && p->buf[5] == 0) ||
+ (p->buf[0] == '.' && p->buf[1] == 'r' &&
+ p->buf[2] == 'a' && p->buf[3] == 0xfd))
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+static int64_t rm_read_dts(AVFormatContext *s, int stream_index,
+ int64_t *ppos, int64_t pos_limit)
+{
+ RMContext *rm = s->priv_data;
+ int64_t pos, dts;
+ int stream_index2, flags, len, h;
+
+ pos = *ppos;
+
+ if(rm->old_format)
+ return AV_NOPTS_VALUE;
+
+ url_fseek(&s->pb, pos, SEEK_SET);
+ rm->remaining_len=0;
+ for(;;){
+ int seq=1;
+ AVStream *st;
+
+ len=sync(s, &dts, &flags, &stream_index2, &pos);
+ if(len<0)
+ return AV_NOPTS_VALUE;
+
+ st = s->streams[stream_index2];
+ if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ h= get_byte(&s->pb); len--;
+ if(!(h & 0x40)){
+ seq = get_byte(&s->pb); len--;
+ }
+ }
+
+ if((flags&2) && (seq&0x7F) == 1){
+// av_log(s, AV_LOG_DEBUG, "%d %d-%d %"PRId64" %d\n", flags, stream_index2, stream_index, dts, seq);
+ av_add_index_entry(st, pos, dts, 0, 0, AVINDEX_KEYFRAME);
+ if(stream_index2 == stream_index)
+ break;
+ }
+
+ url_fskip(&s->pb, len);
+ }
+ *ppos = pos;
+ return dts;
+}
+
+#ifdef CONFIG_RM_DEMUXER
+AVInputFormat rm_demuxer = {
+ "rm",
+ "rm format",
+ sizeof(RMContext),
+ rm_probe,
+ rm_read_header,
+ rm_read_packet,
+ rm_read_close,
+ NULL,
+ rm_read_dts,
+};
+#endif
+#ifdef CONFIG_RM_MUXER
+AVOutputFormat rm_muxer = {
+ "rm",
+ "rm format",
+ "application/vnd.rn-realmedia",
+ "rm,ra",
+ sizeof(RMContext),
+ CODEC_ID_AC3,
+ CODEC_ID_RV10,
+ rm_write_header,
+ rm_write_packet,
+ rm_write_trailer,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/rtp.c b/contrib/ffmpeg/libavformat/rtp.c
new file mode 100644
index 000000000..37a286289
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rtp.c
@@ -0,0 +1,1099 @@
+/*
+ * RTP input/output format
+ * 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 "avformat.h"
+#include "mpegts.h"
+#include "bitstream.h"
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifndef __BEOS__
+# include <arpa/inet.h>
+#else
+# include "barpainet.h"
+#endif
+#include <netdb.h>
+
+#include "rtp_internal.h"
+#include "rtp_h264.h"
+
+//#define DEBUG
+
+
+/* TODO: - add RTCP statistics reporting (should be optional).
+
+ - add support for h263/mpeg4 packetized output : IDEA: send a
+ buffer to 'rtp_write_packet' contains all the packets for ONE
+ frame. Each packet should have a four byte header containing
+ the length in big endian format (same trick as
+ 'url_open_dyn_packet_buf')
+*/
+
+/* from http://www.iana.org/assignments/rtp-parameters last updated 05 January 2005 */
+AVRtpPayloadType_t AVRtpPayloadTypes[]=
+{
+ {0, "PCMU", CODEC_TYPE_AUDIO, CODEC_ID_PCM_MULAW, 8000, 1},
+ {1, "Reserved", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {2, "Reserved", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {3, "GSM", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1},
+ {4, "G723", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1},
+ {5, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1},
+ {6, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 16000, 1},
+ {7, "LPC", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1},
+ {8, "PCMA", CODEC_TYPE_AUDIO, CODEC_ID_PCM_ALAW, 8000, 1},
+ {9, "G722", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1},
+ {10, "L16", CODEC_TYPE_AUDIO, CODEC_ID_PCM_S16BE, 44100, 2},
+ {11, "L16", CODEC_TYPE_AUDIO, CODEC_ID_PCM_S16BE, 44100, 1},
+ {12, "QCELP", CODEC_TYPE_AUDIO, CODEC_ID_QCELP, 8000, 1},
+ {13, "CN", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1},
+ {14, "MPA", CODEC_TYPE_AUDIO, CODEC_ID_MP2, 90000, -1},
+ {15, "G728", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1},
+ {16, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 11025, 1},
+ {17, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 22050, 1},
+ {18, "G729", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1},
+ {19, "reserved", CODEC_TYPE_AUDIO, CODEC_ID_NONE, -1, -1},
+ {20, "unassigned", CODEC_TYPE_AUDIO, CODEC_ID_NONE, -1, -1},
+ {21, "unassigned", CODEC_TYPE_AUDIO, CODEC_ID_NONE, -1, -1},
+ {22, "unassigned", CODEC_TYPE_AUDIO, CODEC_ID_NONE, -1, -1},
+ {23, "unassigned", CODEC_TYPE_AUDIO, CODEC_ID_NONE, -1, -1},
+ {24, "unassigned", CODEC_TYPE_VIDEO, CODEC_ID_NONE, -1, -1},
+ {25, "CelB", CODEC_TYPE_VIDEO, CODEC_ID_NONE, 90000, -1},
+ {26, "JPEG", CODEC_TYPE_VIDEO, CODEC_ID_MJPEG, 90000, -1},
+ {27, "unassigned", CODEC_TYPE_VIDEO, CODEC_ID_NONE, -1, -1},
+ {28, "nv", CODEC_TYPE_VIDEO, CODEC_ID_NONE, 90000, -1},
+ {29, "unassigned", CODEC_TYPE_VIDEO, CODEC_ID_NONE, -1, -1},
+ {30, "unassigned", CODEC_TYPE_VIDEO, CODEC_ID_NONE, -1, -1},
+ {31, "H261", CODEC_TYPE_VIDEO, CODEC_ID_H261, 90000, -1},
+ {32, "MPV", CODEC_TYPE_VIDEO, CODEC_ID_MPEG1VIDEO, 90000, -1},
+ {33, "MP2T", CODEC_TYPE_DATA, CODEC_ID_MPEG2TS, 90000, -1},
+ {34, "H263", CODEC_TYPE_VIDEO, CODEC_ID_H263, 90000, -1},
+ {35, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {36, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {37, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {38, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {39, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {40, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {41, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {42, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {43, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {44, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {45, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {46, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {47, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {48, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {49, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {50, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {51, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {52, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {53, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {54, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {55, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {56, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {57, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {58, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {59, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {60, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {61, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {62, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {63, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {64, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {65, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {66, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {67, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {68, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {69, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {70, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {71, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {72, "reserved for RTCP conflict avoidance", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {73, "reserved for RTCP conflict avoidance", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {74, "reserved for RTCP conflict avoidance", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {75, "reserved for RTCP conflict avoidance", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {76, "reserved for RTCP conflict avoidance", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {77, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {78, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {79, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {80, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {81, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {82, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {83, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {84, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {85, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {86, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {87, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {88, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {89, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {90, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {91, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {92, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {93, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {94, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {95, "unassigned", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {96, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {97, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {98, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {99, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {100, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {101, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {102, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {103, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {104, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {105, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {106, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {107, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {108, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {109, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {110, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {111, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {112, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {113, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {114, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {115, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {116, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {117, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {118, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {119, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {120, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {121, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {122, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {123, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {124, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {125, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {126, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {127, "dynamic", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1},
+ {-1, "", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1}
+};
+
+/* statistics functions */
+RTPDynamicProtocolHandler *RTPFirstDynamicPayloadHandler= NULL;
+
+static RTPDynamicProtocolHandler mp4v_es_handler= {"MP4V-ES", CODEC_TYPE_VIDEO, CODEC_ID_MPEG4};
+static RTPDynamicProtocolHandler mpeg4_generic_handler= {"mpeg4-generic", CODEC_TYPE_AUDIO, CODEC_ID_AAC};
+
+static void register_dynamic_payload_handler(RTPDynamicProtocolHandler *handler)
+{
+ handler->next= RTPFirstDynamicPayloadHandler;
+ RTPFirstDynamicPayloadHandler= handler;
+}
+
+void av_register_rtp_dynamic_payload_handlers()
+{
+ register_dynamic_payload_handler(&mp4v_es_handler);
+ register_dynamic_payload_handler(&mpeg4_generic_handler);
+ register_dynamic_payload_handler(&ff_h264_dynamic_handler);
+}
+
+int rtp_get_codec_info(AVCodecContext *codec, int payload_type)
+{
+ if (AVRtpPayloadTypes[payload_type].codec_id != CODEC_ID_NONE) {
+ codec->codec_type = AVRtpPayloadTypes[payload_type].codec_type;
+ codec->codec_id = AVRtpPayloadTypes[payload_type].codec_id;
+ if (AVRtpPayloadTypes[payload_type].audio_channels > 0)
+ codec->channels = AVRtpPayloadTypes[payload_type].audio_channels;
+ if (AVRtpPayloadTypes[payload_type].clock_rate > 0)
+ codec->sample_rate = AVRtpPayloadTypes[payload_type].clock_rate;
+ return 0;
+ }
+ return -1;
+}
+
+/* return < 0 if unknown payload type */
+int rtp_get_payload_type(AVCodecContext *codec)
+{
+ int i, payload_type;
+
+ /* compute the payload type */
+ for (payload_type = -1, i = 0; AVRtpPayloadTypes[i].pt >= 0; ++i)
+ if (AVRtpPayloadTypes[i].codec_id == codec->codec_id) {
+ if (codec->codec_id == CODEC_ID_PCM_S16BE)
+ if (codec->channels != AVRtpPayloadTypes[i].audio_channels)
+ continue;
+ payload_type = AVRtpPayloadTypes[i].pt;
+ }
+ return payload_type;
+}
+
+static inline uint32_t decode_be32(const uint8_t *p)
+{
+ return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+}
+
+static inline uint64_t decode_be64(const uint8_t *p)
+{
+ return ((uint64_t)decode_be32(p) << 32) | decode_be32(p + 4);
+}
+
+static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char *buf, int len)
+{
+ if (buf[1] != 200)
+ return -1;
+ s->last_rtcp_ntp_time = decode_be64(buf + 8);
+ if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE)
+ s->first_rtcp_ntp_time = s->last_rtcp_ntp_time;
+ s->last_rtcp_timestamp = decode_be32(buf + 16);
+ return 0;
+}
+
+#define RTP_SEQ_MOD (1<<16)
+
+/**
+* called on parse open packet
+*/
+static void rtp_init_statistics(RTPStatistics *s, uint16_t base_sequence) // called on parse open packet.
+{
+ memset(s, 0, sizeof(RTPStatistics));
+ s->max_seq= base_sequence;
+ s->probation= 1;
+}
+
+/**
+* called whenever there is a large jump in sequence numbers, or when they get out of probation...
+*/
+static void rtp_init_sequence(RTPStatistics *s, uint16_t seq)
+{
+ s->max_seq= seq;
+ s->cycles= 0;
+ s->base_seq= seq -1;
+ s->bad_seq= RTP_SEQ_MOD + 1;
+ s->received= 0;
+ s->expected_prior= 0;
+ s->received_prior= 0;
+ s->jitter= 0;
+ s->transit= 0;
+}
+
+/**
+* returns 1 if we should handle this packet.
+*/
+static int rtp_valid_packet_in_sequence(RTPStatistics *s, uint16_t seq)
+{
+ uint16_t udelta= seq - s->max_seq;
+ const int MAX_DROPOUT= 3000;
+ const int MAX_MISORDER = 100;
+ const int MIN_SEQUENTIAL = 2;
+
+ /* source not valid until MIN_SEQUENTIAL packets with sequence seq. numbers have been received */
+ if(s->probation)
+ {
+ if(seq==s->max_seq + 1) {
+ s->probation--;
+ s->max_seq= seq;
+ if(s->probation==0) {
+ rtp_init_sequence(s, seq);
+ s->received++;
+ return 1;
+ }
+ } else {
+ s->probation= MIN_SEQUENTIAL - 1;
+ s->max_seq = seq;
+ }
+ } else if (udelta < MAX_DROPOUT) {
+ // in order, with permissible gap
+ if(seq < s->max_seq) {
+ //sequence number wrapped; count antother 64k cycles
+ s->cycles += RTP_SEQ_MOD;
+ }
+ s->max_seq= seq;
+ } else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) {
+ // sequence made a large jump...
+ if(seq==s->bad_seq) {
+ // two sequential packets-- assume that the other side restarted without telling us; just resync.
+ rtp_init_sequence(s, seq);
+ } else {
+ s->bad_seq= (seq + 1) & (RTP_SEQ_MOD-1);
+ return 0;
+ }
+ } else {
+ // duplicate or reordered packet...
+ }
+ s->received++;
+ return 1;
+}
+
+#if 0
+/**
+* This function is currently unused; without a valid local ntp time, I don't see how we could calculate the
+* difference between the arrival and sent timestamp. As a result, the jitter and transit statistics values
+* never change. I left this in in case someone else can see a way. (rdm)
+*/
+static void rtcp_update_jitter(RTPStatistics *s, uint32_t sent_timestamp, uint32_t arrival_timestamp)
+{
+ uint32_t transit= arrival_timestamp - sent_timestamp;
+ int d;
+ s->transit= transit;
+ d= FFABS(transit - s->transit);
+ s->jitter += d - ((s->jitter + 8)>>4);
+}
+#endif
+
+/**
+ * some rtp servers assume client is dead if they don't hear from them...
+ * so we send a Receiver Report to the provided ByteIO context
+ * (we don't have access to the rtcp handle from here)
+ */
+int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count)
+{
+ ByteIOContext pb;
+ uint8_t *buf;
+ int len;
+ int rtcp_bytes;
+ RTPStatistics *stats= &s->statistics;
+ uint32_t lost;
+ uint32_t extended_max;
+ uint32_t expected_interval;
+ uint32_t received_interval;
+ uint32_t lost_interval;
+ uint32_t expected;
+ uint32_t fraction;
+ uint64_t ntp_time= s->last_rtcp_ntp_time; // TODO: Get local ntp time?
+
+ if (!s->rtp_ctx || (count < 1))
+ return -1;
+
+ /* TODO: I think this is way too often; RFC 1889 has algorithm for this */
+ /* XXX: mpeg pts hardcoded. RTCP send every 0.5 seconds */
+ s->octet_count += count;
+ rtcp_bytes = ((s->octet_count - s->last_octet_count) * RTCP_TX_RATIO_NUM) /
+ RTCP_TX_RATIO_DEN;
+ rtcp_bytes /= 50; // mmu_man: that's enough for me... VLC sends much less btw !?
+ if (rtcp_bytes < 28)
+ return -1;
+ s->last_octet_count = s->octet_count;
+
+ if (url_open_dyn_buf(&pb) < 0)
+ return -1;
+
+ // Receiver Report
+ put_byte(&pb, (RTP_VERSION << 6) + 1); /* 1 report block */
+ put_byte(&pb, 201);
+ put_be16(&pb, 7); /* length in words - 1 */
+ put_be32(&pb, s->ssrc); // our own SSRC
+ put_be32(&pb, s->ssrc); // XXX: should be the server's here!
+ // some placeholders we should really fill...
+ // RFC 1889/p64
+ extended_max= stats->cycles + stats->max_seq;
+ expected= extended_max - stats->base_seq + 1;
+ lost= expected - stats->received;
+ lost= FFMIN(lost, 0xffffff); // clamp it since it's only 24 bits...
+ expected_interval= expected - stats->expected_prior;
+ stats->expected_prior= expected;
+ received_interval= stats->received - stats->received_prior;
+ stats->received_prior= stats->received;
+ lost_interval= expected_interval - received_interval;
+ if (expected_interval==0 || lost_interval<=0) fraction= 0;
+ else fraction = (lost_interval<<8)/expected_interval;
+
+ fraction= (fraction<<24) | lost;
+
+ put_be32(&pb, fraction); /* 8 bits of fraction, 24 bits of total packets lost */
+ put_be32(&pb, extended_max); /* max sequence received */
+ put_be32(&pb, stats->jitter>>4); /* jitter */
+
+ if(s->last_rtcp_ntp_time==AV_NOPTS_VALUE)
+ {
+ put_be32(&pb, 0); /* last SR timestamp */
+ put_be32(&pb, 0); /* delay since last SR */
+ } else {
+ uint32_t middle_32_bits= s->last_rtcp_ntp_time>>16; // this is valid, right? do we need to handle 64 bit values special?
+ uint32_t delay_since_last= ntp_time - s->last_rtcp_ntp_time;
+
+ put_be32(&pb, middle_32_bits); /* last SR timestamp */
+ put_be32(&pb, delay_since_last); /* delay since last SR */
+ }
+
+ // CNAME
+ put_byte(&pb, (RTP_VERSION << 6) + 1); /* 1 report block */
+ put_byte(&pb, 202);
+ len = strlen(s->hostname);
+ put_be16(&pb, (6 + len + 3) / 4); /* length in words - 1 */
+ put_be32(&pb, s->ssrc);
+ put_byte(&pb, 0x01);
+ put_byte(&pb, len);
+ put_buffer(&pb, s->hostname, len);
+ // padding
+ for (len = (6 + len) % 4; len % 4; len++) {
+ put_byte(&pb, 0);
+ }
+
+ put_flush_packet(&pb);
+ len = url_close_dyn_buf(&pb, &buf);
+ if ((len > 0) && buf) {
+ int result;
+#if defined(DEBUG)
+ printf("sending %d bytes of RR\n", len);
+#endif
+ result= url_write(s->rtp_ctx, buf, len);
+#if defined(DEBUG)
+ printf("result from url_write: %d\n", result);
+#endif
+ av_free(buf);
+ }
+ return 0;
+}
+
+/**
+ * open a new RTP parse context for stream 'st'. 'st' can be NULL for
+ * MPEG2TS streams to indicate that they should be demuxed inside the
+ * rtp demux (otherwise CODEC_ID_MPEG2TS packets are returned)
+ * TODO: change this to not take rtp_payload data, and use the new dynamic payload system.
+ */
+RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext *rtpc, int payload_type, rtp_payload_data_t *rtp_payload_data)
+{
+ RTPDemuxContext *s;
+
+ s = av_mallocz(sizeof(RTPDemuxContext));
+ if (!s)
+ return NULL;
+ s->payload_type = payload_type;
+ s->last_rtcp_ntp_time = AV_NOPTS_VALUE;
+ s->first_rtcp_ntp_time = AV_NOPTS_VALUE;
+ s->ic = s1;
+ s->st = st;
+ s->rtp_payload_data = rtp_payload_data;
+ rtp_init_statistics(&s->statistics, 0); // do we know the initial sequence from sdp?
+ if (!strcmp(AVRtpPayloadTypes[payload_type].enc_name, "MP2T")) {
+ s->ts = mpegts_parse_open(s->ic);
+ if (s->ts == NULL) {
+ av_free(s);
+ return NULL;
+ }
+ } else {
+ switch(st->codec->codec_id) {
+ case CODEC_ID_MPEG1VIDEO:
+ case CODEC_ID_MPEG2VIDEO:
+ case CODEC_ID_MP2:
+ case CODEC_ID_MP3:
+ case CODEC_ID_MPEG4:
+ case CODEC_ID_H264:
+ st->need_parsing = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ // needed to send back RTCP RR in RTSP sessions
+ s->rtp_ctx = rtpc;
+ gethostname(s->hostname, sizeof(s->hostname));
+ return s;
+}
+
+static int rtp_parse_mp4_au(RTPDemuxContext *s, const uint8_t *buf)
+{
+ int au_headers_length, au_header_size, i;
+ GetBitContext getbitcontext;
+ rtp_payload_data_t *infos;
+
+ infos = s->rtp_payload_data;
+
+ if (infos == NULL)
+ return -1;
+
+ /* decode the first 2 bytes where are stored the AUHeader sections
+ length in bits */
+ au_headers_length = BE_16(buf);
+
+ if (au_headers_length > RTP_MAX_PACKET_LENGTH)
+ return -1;
+
+ infos->au_headers_length_bytes = (au_headers_length + 7) / 8;
+
+ /* skip AU headers length section (2 bytes) */
+ buf += 2;
+
+ init_get_bits(&getbitcontext, buf, infos->au_headers_length_bytes * 8);
+
+ /* XXX: Wrong if optionnal additional sections are present (cts, dts etc...) */
+ au_header_size = infos->sizelength + infos->indexlength;
+ if (au_header_size <= 0 || (au_headers_length % au_header_size != 0))
+ return -1;
+
+ infos->nb_au_headers = au_headers_length / au_header_size;
+ infos->au_headers = av_malloc(sizeof(struct AUHeaders) * infos->nb_au_headers);
+
+ /* XXX: We handle multiple AU Section as only one (need to fix this for interleaving)
+ In my test, the faad decoder doesnt behave correctly when sending each AU one by one
+ but does when sending the whole as one big packet... */
+ infos->au_headers[0].size = 0;
+ infos->au_headers[0].index = 0;
+ for (i = 0; i < infos->nb_au_headers; ++i) {
+ infos->au_headers[0].size += get_bits_long(&getbitcontext, infos->sizelength);
+ infos->au_headers[0].index = get_bits_long(&getbitcontext, infos->indexlength);
+ }
+
+ infos->nb_au_headers = 1;
+
+ return 0;
+}
+
+/**
+ * This was the second switch in rtp_parse packet. Normalizes time, if required, sets stream_index, etc.
+ */
+static void finalize_packet(RTPDemuxContext *s, AVPacket *pkt, uint32_t timestamp)
+{
+ switch(s->st->codec->codec_id) {
+ case CODEC_ID_MP2:
+ case CODEC_ID_MPEG1VIDEO:
+ if (s->last_rtcp_ntp_time != AV_NOPTS_VALUE) {
+ int64_t addend;
+
+ int delta_timestamp;
+ /* XXX: is it really necessary to unify the timestamp base ? */
+ /* compute pts from timestamp with received ntp_time */
+ delta_timestamp = timestamp - s->last_rtcp_timestamp;
+ /* convert to 90 kHz without overflow */
+ addend = (s->last_rtcp_ntp_time - s->first_rtcp_ntp_time) >> 14;
+ addend = (addend * 5625) >> 14;
+ pkt->pts = addend + delta_timestamp;
+ }
+ break;
+ case CODEC_ID_AAC:
+ case CODEC_ID_H264:
+ case CODEC_ID_MPEG4:
+ pkt->pts = timestamp;
+ break;
+ default:
+ /* no timestamp info yet */
+ break;
+ }
+ pkt->stream_index = s->st->index;
+}
+
+/**
+ * Parse an RTP or RTCP packet directly sent as a buffer.
+ * @param s RTP parse context.
+ * @param pkt returned packet
+ * @param buf input buffer or NULL to read the next packets
+ * @param len buffer len
+ * @return 0 if a packet is returned, 1 if a packet is returned and more can follow
+ * (use buf as NULL to read the next). -1 if no packet (error or no more packet).
+ */
+int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
+ const uint8_t *buf, int len)
+{
+ unsigned int ssrc, h;
+ int payload_type, seq, ret;
+ AVStream *st;
+ uint32_t timestamp;
+ int rv= 0;
+
+ if (!buf) {
+ /* return the next packets, if any */
+ if(s->st && s->parse_packet) {
+ timestamp= 0; ///< Should not be used if buf is NULL, but should be set to the timestamp of the packet returned....
+ rv= s->parse_packet(s, pkt, &timestamp, NULL, 0);
+ finalize_packet(s, pkt, timestamp);
+ return rv;
+ } else {
+ // TODO: Move to a dynamic packet handler (like above)
+ if (s->read_buf_index >= s->read_buf_size)
+ return -1;
+ ret = mpegts_parse_packet(s->ts, pkt, s->buf + s->read_buf_index,
+ s->read_buf_size - s->read_buf_index);
+ if (ret < 0)
+ return -1;
+ s->read_buf_index += ret;
+ if (s->read_buf_index < s->read_buf_size)
+ return 1;
+ else
+ return 0;
+ }
+ }
+
+ if (len < 12)
+ return -1;
+
+ if ((buf[0] & 0xc0) != (RTP_VERSION << 6))
+ return -1;
+ if (buf[1] >= 200 && buf[1] <= 204) {
+ rtcp_parse_packet(s, buf, len);
+ return -1;
+ }
+ payload_type = buf[1] & 0x7f;
+ seq = (buf[2] << 8) | buf[3];
+ timestamp = decode_be32(buf + 4);
+ ssrc = decode_be32(buf + 8);
+ /* store the ssrc in the RTPDemuxContext */
+ s->ssrc = ssrc;
+
+ /* NOTE: we can handle only one payload type */
+ if (s->payload_type != payload_type)
+ return -1;
+
+ st = s->st;
+ // only do something with this if all the rtp checks pass...
+ if(!rtp_valid_packet_in_sequence(&s->statistics, seq))
+ {
+ av_log(st?st->codec:NULL, AV_LOG_ERROR, "RTP: PT=%02x: bad cseq %04x expected=%04x\n",
+ payload_type, seq, ((s->seq + 1) & 0xffff));
+ return -1;
+ }
+
+ s->seq = seq;
+ len -= 12;
+ buf += 12;
+
+ if (!st) {
+ /* specific MPEG2TS demux support */
+ ret = mpegts_parse_packet(s->ts, pkt, buf, len);
+ if (ret < 0)
+ return -1;
+ if (ret < len) {
+ s->read_buf_size = len - ret;
+ memcpy(s->buf, buf + ret, s->read_buf_size);
+ s->read_buf_index = 0;
+ return 1;
+ }
+ } else {
+ // at this point, the RTP header has been stripped; This is ASSUMING that there is only 1 CSRC, which in't wise.
+ switch(st->codec->codec_id) {
+ case CODEC_ID_MP2:
+ /* better than nothing: skip mpeg audio RTP header */
+ if (len <= 4)
+ return -1;
+ h = decode_be32(buf);
+ len -= 4;
+ buf += 4;
+ av_new_packet(pkt, len);
+ memcpy(pkt->data, buf, len);
+ break;
+ case CODEC_ID_MPEG1VIDEO:
+ /* better than nothing: skip mpeg video RTP header */
+ if (len <= 4)
+ return -1;
+ h = decode_be32(buf);
+ buf += 4;
+ len -= 4;
+ if (h & (1 << 26)) {
+ /* mpeg2 */
+ if (len <= 4)
+ return -1;
+ buf += 4;
+ len -= 4;
+ }
+ av_new_packet(pkt, len);
+ memcpy(pkt->data, buf, len);
+ break;
+ // moved from below, verbatim. this is because this section handles packets, and the lower switch handles
+ // timestamps.
+ // TODO: Put this into a dynamic packet handler...
+ case CODEC_ID_AAC:
+ if (rtp_parse_mp4_au(s, buf))
+ return -1;
+ {
+ rtp_payload_data_t *infos = s->rtp_payload_data;
+ if (infos == NULL)
+ return -1;
+ buf += infos->au_headers_length_bytes + 2;
+ len -= infos->au_headers_length_bytes + 2;
+
+ /* XXX: Fixme we only handle the case where rtp_parse_mp4_au define
+ one au_header */
+ av_new_packet(pkt, infos->au_headers[0].size);
+ memcpy(pkt->data, buf, infos->au_headers[0].size);
+ buf += infos->au_headers[0].size;
+ len -= infos->au_headers[0].size;
+ }
+ s->read_buf_size = len;
+ s->buf_ptr = buf;
+ rv= 0;
+ break;
+ default:
+ if(s->parse_packet) {
+ rv= s->parse_packet(s, pkt, &timestamp, buf, len);
+ } else {
+ av_new_packet(pkt, len);
+ memcpy(pkt->data, buf, len);
+ }
+ break;
+ }
+
+ // now perform timestamp things....
+ finalize_packet(s, pkt, timestamp);
+ }
+ return rv;
+}
+
+void rtp_parse_close(RTPDemuxContext *s)
+{
+ // TODO: fold this into the protocol specific data fields.
+ if (!strcmp(AVRtpPayloadTypes[s->payload_type].enc_name, "MP2T")) {
+ mpegts_parse_close(s->ts);
+ }
+ av_free(s);
+}
+
+/* rtp output */
+
+static int rtp_write_header(AVFormatContext *s1)
+{
+ RTPDemuxContext *s = s1->priv_data;
+ int payload_type, max_packet_size, n;
+ AVStream *st;
+
+ if (s1->nb_streams != 1)
+ return -1;
+ st = s1->streams[0];
+
+ payload_type = rtp_get_payload_type(st->codec);
+ if (payload_type < 0)
+ payload_type = RTP_PT_PRIVATE; /* private payload type */
+ s->payload_type = payload_type;
+
+// following 2 FIXMies could be set based on the current time, theres normaly no info leak, as rtp will likely be transmitted immedeatly
+ s->base_timestamp = 0; /* FIXME: was random(), what should this be? */
+ s->timestamp = s->base_timestamp;
+ s->ssrc = 0; /* FIXME: was random(), what should this be? */
+ s->first_packet = 1;
+
+ max_packet_size = url_fget_max_packet_size(&s1->pb);
+ if (max_packet_size <= 12)
+ return AVERROR_IO;
+ s->max_payload_size = max_packet_size - 12;
+
+ switch(st->codec->codec_id) {
+ case CODEC_ID_MP2:
+ case CODEC_ID_MP3:
+ s->buf_ptr = s->buf + 4;
+ s->cur_timestamp = 0;
+ break;
+ case CODEC_ID_MPEG1VIDEO:
+ s->cur_timestamp = 0;
+ break;
+ case CODEC_ID_MPEG2TS:
+ n = s->max_payload_size / TS_PACKET_SIZE;
+ if (n < 1)
+ n = 1;
+ s->max_payload_size = n * TS_PACKET_SIZE;
+ s->buf_ptr = s->buf;
+ break;
+ default:
+ s->buf_ptr = s->buf;
+ break;
+ }
+
+ return 0;
+}
+
+/* send an rtcp sender report packet */
+static void rtcp_send_sr(AVFormatContext *s1, int64_t ntp_time)
+{
+ RTPDemuxContext *s = s1->priv_data;
+#if defined(DEBUG)
+ printf("RTCP: %02x %"PRIx64" %x\n", s->payload_type, ntp_time, s->timestamp);
+#endif
+ put_byte(&s1->pb, (RTP_VERSION << 6));
+ put_byte(&s1->pb, 200);
+ put_be16(&s1->pb, 6); /* length in words - 1 */
+ put_be32(&s1->pb, s->ssrc);
+ put_be64(&s1->pb, ntp_time);
+ put_be32(&s1->pb, s->timestamp);
+ put_be32(&s1->pb, s->packet_count);
+ put_be32(&s1->pb, s->octet_count);
+ put_flush_packet(&s1->pb);
+}
+
+/* send an rtp packet. sequence number is incremented, but the caller
+ must update the timestamp itself */
+static void rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m)
+{
+ RTPDemuxContext *s = s1->priv_data;
+
+#ifdef DEBUG
+ printf("rtp_send_data size=%d\n", len);
+#endif
+
+ /* build the RTP header */
+ put_byte(&s1->pb, (RTP_VERSION << 6));
+ put_byte(&s1->pb, (s->payload_type & 0x7f) | ((m & 0x01) << 7));
+ put_be16(&s1->pb, s->seq);
+ put_be32(&s1->pb, s->timestamp);
+ put_be32(&s1->pb, s->ssrc);
+
+ put_buffer(&s1->pb, buf1, len);
+ put_flush_packet(&s1->pb);
+
+ s->seq++;
+ s->octet_count += len;
+ s->packet_count++;
+}
+
+/* send an integer number of samples and compute time stamp and fill
+ the rtp send buffer before sending. */
+static void rtp_send_samples(AVFormatContext *s1,
+ const uint8_t *buf1, int size, int sample_size)
+{
+ RTPDemuxContext *s = s1->priv_data;
+ int len, max_packet_size, n;
+
+ max_packet_size = (s->max_payload_size / sample_size) * sample_size;
+ /* not needed, but who nows */
+ if ((size % sample_size) != 0)
+ av_abort();
+ while (size > 0) {
+ len = (max_packet_size - (s->buf_ptr - s->buf));
+ if (len > size)
+ len = size;
+
+ /* copy data */
+ memcpy(s->buf_ptr, buf1, len);
+ s->buf_ptr += len;
+ buf1 += len;
+ size -= len;
+ n = (s->buf_ptr - s->buf);
+ /* if buffer full, then send it */
+ if (n >= max_packet_size) {
+ rtp_send_data(s1, s->buf, n, 0);
+ s->buf_ptr = s->buf;
+ /* update timestamp */
+ s->timestamp += n / sample_size;
+ }
+ }
+}
+
+/* NOTE: we suppose that exactly one frame is given as argument here */
+/* XXX: test it */
+static void rtp_send_mpegaudio(AVFormatContext *s1,
+ const uint8_t *buf1, int size)
+{
+ RTPDemuxContext *s = s1->priv_data;
+ AVStream *st = s1->streams[0];
+ int len, count, max_packet_size;
+
+ max_packet_size = s->max_payload_size;
+
+ /* test if we must flush because not enough space */
+ len = (s->buf_ptr - s->buf);
+ if ((len + size) > max_packet_size) {
+ if (len > 4) {
+ rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 0);
+ s->buf_ptr = s->buf + 4;
+ /* 90 KHz time stamp */
+ s->timestamp = s->base_timestamp +
+ (s->cur_timestamp * 90000LL) / st->codec->sample_rate;
+ }
+ }
+
+ /* add the packet */
+ if (size > max_packet_size) {
+ /* big packet: fragment */
+ count = 0;
+ while (size > 0) {
+ len = max_packet_size - 4;
+ if (len > size)
+ len = size;
+ /* build fragmented packet */
+ s->buf[0] = 0;
+ s->buf[1] = 0;
+ s->buf[2] = count >> 8;
+ s->buf[3] = count;
+ memcpy(s->buf + 4, buf1, len);
+ rtp_send_data(s1, s->buf, len + 4, 0);
+ size -= len;
+ buf1 += len;
+ count += len;
+ }
+ } else {
+ if (s->buf_ptr == s->buf + 4) {
+ /* no fragmentation possible */
+ s->buf[0] = 0;
+ s->buf[1] = 0;
+ s->buf[2] = 0;
+ s->buf[3] = 0;
+ }
+ memcpy(s->buf_ptr, buf1, size);
+ s->buf_ptr += size;
+ }
+ s->cur_timestamp += st->codec->frame_size;
+}
+
+/* NOTE: a single frame must be passed with sequence header if
+ needed. XXX: use slices. */
+static void rtp_send_mpegvideo(AVFormatContext *s1,
+ const uint8_t *buf1, int size)
+{
+ RTPDemuxContext *s = s1->priv_data;
+ AVStream *st = s1->streams[0];
+ int len, h, max_packet_size;
+ uint8_t *q;
+
+ max_packet_size = s->max_payload_size;
+
+ while (size > 0) {
+ /* XXX: more correct headers */
+ h = 0;
+ if (st->codec->sub_id == 2)
+ h |= 1 << 26; /* mpeg 2 indicator */
+ q = s->buf;
+ *q++ = h >> 24;
+ *q++ = h >> 16;
+ *q++ = h >> 8;
+ *q++ = h;
+
+ if (st->codec->sub_id == 2) {
+ h = 0;
+ *q++ = h >> 24;
+ *q++ = h >> 16;
+ *q++ = h >> 8;
+ *q++ = h;
+ }
+
+ len = max_packet_size - (q - s->buf);
+ if (len > size)
+ len = size;
+
+ memcpy(q, buf1, len);
+ q += len;
+
+ /* 90 KHz time stamp */
+ s->timestamp = s->base_timestamp +
+ av_rescale((int64_t)s->cur_timestamp * st->codec->time_base.num, 90000, st->codec->time_base.den); //FIXME pass timestamps
+ rtp_send_data(s1, s->buf, q - s->buf, (len == size));
+
+ buf1 += len;
+ size -= len;
+ }
+ s->cur_timestamp++;
+}
+
+static void rtp_send_raw(AVFormatContext *s1,
+ const uint8_t *buf1, int size)
+{
+ RTPDemuxContext *s = s1->priv_data;
+ AVStream *st = s1->streams[0];
+ int len, max_packet_size;
+
+ max_packet_size = s->max_payload_size;
+
+ while (size > 0) {
+ len = max_packet_size;
+ if (len > size)
+ len = size;
+
+ /* 90 KHz time stamp */
+ s->timestamp = s->base_timestamp +
+ av_rescale((int64_t)s->cur_timestamp * st->codec->time_base.num, 90000, st->codec->time_base.den); //FIXME pass timestamps
+ rtp_send_data(s1, buf1, len, (len == size));
+
+ buf1 += len;
+ size -= len;
+ }
+ s->cur_timestamp++;
+}
+
+/* NOTE: size is assumed to be an integer multiple of TS_PACKET_SIZE */
+static void rtp_send_mpegts_raw(AVFormatContext *s1,
+ const uint8_t *buf1, int size)
+{
+ RTPDemuxContext *s = s1->priv_data;
+ int len, out_len;
+
+ while (size >= TS_PACKET_SIZE) {
+ len = s->max_payload_size - (s->buf_ptr - s->buf);
+ if (len > size)
+ len = size;
+ memcpy(s->buf_ptr, buf1, len);
+ buf1 += len;
+ size -= len;
+ s->buf_ptr += len;
+
+ out_len = s->buf_ptr - s->buf;
+ if (out_len >= s->max_payload_size) {
+ rtp_send_data(s1, s->buf, out_len, 0);
+ s->buf_ptr = s->buf;
+ }
+ }
+}
+
+/* write an RTP packet. 'buf1' must contain a single specific frame. */
+static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
+{
+ RTPDemuxContext *s = s1->priv_data;
+ AVStream *st = s1->streams[0];
+ int rtcp_bytes;
+ int64_t ntp_time;
+ int size= pkt->size;
+ uint8_t *buf1= pkt->data;
+
+#ifdef DEBUG
+ printf("%d: write len=%d\n", pkt->stream_index, size);
+#endif
+
+ /* XXX: mpeg pts hardcoded. RTCP send every 0.5 seconds */
+ rtcp_bytes = ((s->octet_count - s->last_octet_count) * RTCP_TX_RATIO_NUM) /
+ RTCP_TX_RATIO_DEN;
+ if (s->first_packet || rtcp_bytes >= 28) {
+ /* compute NTP time */
+ /* XXX: 90 kHz timestamp hardcoded */
+ ntp_time = (pkt->pts << 28) / 5625;
+ rtcp_send_sr(s1, ntp_time);
+ s->last_octet_count = s->octet_count;
+ s->first_packet = 0;
+ }
+
+ switch(st->codec->codec_id) {
+ case CODEC_ID_PCM_MULAW:
+ case CODEC_ID_PCM_ALAW:
+ case CODEC_ID_PCM_U8:
+ case CODEC_ID_PCM_S8:
+ rtp_send_samples(s1, buf1, size, 1 * st->codec->channels);
+ break;
+ case CODEC_ID_PCM_U16BE:
+ case CODEC_ID_PCM_U16LE:
+ case CODEC_ID_PCM_S16BE:
+ case CODEC_ID_PCM_S16LE:
+ rtp_send_samples(s1, buf1, size, 2 * st->codec->channels);
+ break;
+ case CODEC_ID_MP2:
+ case CODEC_ID_MP3:
+ rtp_send_mpegaudio(s1, buf1, size);
+ break;
+ case CODEC_ID_MPEG1VIDEO:
+ rtp_send_mpegvideo(s1, buf1, size);
+ break;
+ case CODEC_ID_MPEG2TS:
+ rtp_send_mpegts_raw(s1, buf1, size);
+ break;
+ default:
+ /* better than nothing : send the codec raw data */
+ rtp_send_raw(s1, buf1, size);
+ break;
+ }
+ return 0;
+}
+
+static int rtp_write_trailer(AVFormatContext *s1)
+{
+ // RTPDemuxContext *s = s1->priv_data;
+ return 0;
+}
+
+AVOutputFormat rtp_muxer = {
+ "rtp",
+ "RTP output format",
+ NULL,
+ NULL,
+ sizeof(RTPDemuxContext),
+ CODEC_ID_PCM_MULAW,
+ CODEC_ID_NONE,
+ rtp_write_header,
+ rtp_write_packet,
+ rtp_write_trailer,
+};
diff --git a/contrib/ffmpeg/libavformat/rtp.h b/contrib/ffmpeg/libavformat/rtp.h
new file mode 100644
index 000000000..60ccc50ee
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rtp.h
@@ -0,0 +1,118 @@
+/*
+ * RTP definitions
+ * 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
+ */
+#ifndef RTP_H
+#define RTP_H
+
+#define RTP_MIN_PACKET_LENGTH 12
+#define RTP_MAX_PACKET_LENGTH 1500 /* XXX: suppress this define */
+
+int rtp_init(void);
+int rtp_get_codec_info(AVCodecContext *codec, int payload_type);
+int rtp_get_payload_type(AVCodecContext *codec);
+
+typedef struct RTPDemuxContext RTPDemuxContext;
+typedef struct rtp_payload_data_s rtp_payload_data_s;
+RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext *rtpc, int payload_type, rtp_payload_data_s *rtp_payload_data);
+int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
+ const uint8_t *buf, int len);
+void rtp_parse_close(RTPDemuxContext *s);
+
+extern AVOutputFormat rtp_muxer;
+extern AVInputFormat rtp_demuxer;
+
+int rtp_get_local_port(URLContext *h);
+int rtp_set_remote_url(URLContext *h, const char *uri);
+void rtp_get_file_handles(URLContext *h, int *prtp_fd, int *prtcp_fd);
+
+extern URLProtocol rtp_protocol;
+
+#define RTP_PT_PRIVATE 96
+#define RTP_VERSION 2
+#define RTP_MAX_SDES 256 /* maximum text length for SDES */
+
+/* RTCP paquets use 0.5 % of the bandwidth */
+#define RTCP_TX_RATIO_NUM 5
+#define RTCP_TX_RATIO_DEN 1000
+
+/* Structure listing usefull vars to parse RTP packet payload*/
+typedef struct rtp_payload_data_s
+{
+ int sizelength;
+ int indexlength;
+ int indexdeltalength;
+ int profile_level_id;
+ int streamtype;
+ int objecttype;
+ char *mode;
+
+ /* mpeg 4 AU headers */
+ struct AUHeaders {
+ int size;
+ int index;
+ int cts_flag;
+ int cts;
+ int dts_flag;
+ int dts;
+ int rap_flag;
+ int streamstate;
+ } *au_headers;
+ int nb_au_headers;
+ int au_headers_length_bytes;
+ int cur_au_index;
+} rtp_payload_data_t;
+
+typedef struct AVRtpPayloadType_s
+{
+ int pt;
+ const char enc_name[50]; /* XXX: why 50 ? */
+ enum CodecType codec_type;
+ enum CodecID codec_id;
+ int clock_rate;
+ int audio_channels;
+} AVRtpPayloadType_t;
+
+#if 0
+typedef enum {
+ RTCP_SR = 200,
+ RTCP_RR = 201,
+ RTCP_SDES = 202,
+ RTCP_BYE = 203,
+ RTCP_APP = 204
+} rtcp_type_t;
+
+typedef enum {
+ RTCP_SDES_END = 0,
+ RTCP_SDES_CNAME = 1,
+ RTCP_SDES_NAME = 2,
+ RTCP_SDES_EMAIL = 3,
+ RTCP_SDES_PHONE = 4,
+ RTCP_SDES_LOC = 5,
+ RTCP_SDES_TOOL = 6,
+ RTCP_SDES_NOTE = 7,
+ RTCP_SDES_PRIV = 8,
+ RTCP_SDES_IMG = 9,
+ RTCP_SDES_DOOR = 10,
+ RTCP_SDES_SOURCE = 11
+} rtcp_sdes_type_t;
+#endif
+
+extern AVRtpPayloadType_t AVRtpPayloadTypes[];
+#endif /* RTP_H */
diff --git a/contrib/ffmpeg/libavformat/rtp_h264.c b/contrib/ffmpeg/libavformat/rtp_h264.c
new file mode 100644
index 000000000..2568e9ea5
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rtp_h264.c
@@ -0,0 +1,419 @@
+/*
+ * RTP H264 Protocol (RFC3984)
+ * Copyright (c) 2006 Ryan Martell.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+* @file rtp_h264.c
+ * @brief H.264 / RTP Code (RFC3984)
+ * @author Ryan Martell <rdm4@martellventures.com>
+ *
+ * @note Notes:
+ * Notes:
+ * This currently supports packetization mode:
+ * Single Nal Unit Mode (0), or
+ * Non-Interleaved Mode (1). It currently does not support
+ * Interleaved Mode (2). (This requires implementing STAP-B, MTAP16, MTAP24, FU-B packet types)
+ *
+ * @note TODO:
+ * 1) RTCP sender reports for udp streams are required..
+ *
+ */
+
+#include "avformat.h"
+#include "mpegts.h"
+#include "bitstream.h"
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <assert.h>
+#ifndef __BEOS__
+# include <arpa/inet.h>
+#else
+# include "barpainet.h"
+#endif
+#include <netdb.h>
+
+#include "rtp_internal.h"
+#include "rtp_h264.h"
+#include "base64.h"
+
+/**
+ RTP/H264 specific private data.
+*/
+typedef struct h264_rtp_extra_data {
+ unsigned long cookie; ///< sanity check, to make sure we get the pointer we're expecting.
+
+ //sdp setup parameters
+ uint8_t profile_idc; ///< from the sdp setup parameters.
+ uint8_t profile_iop; ///< from the sdp setup parameters.
+ uint8_t level_idc; ///< from the sdp setup parameters.
+ int packetization_mode; ///< from the sdp setup parameters.
+#ifdef DEBUG
+ int packet_types_received[32];
+#endif
+} h264_rtp_extra_data;
+
+#define MAGIC_COOKIE (0xdeadbeef) ///< Cookie for the extradata; to verify we are what we think we are, and that we haven't been freed.
+#define DEAD_COOKIE (0xdeaddead) ///< Cookie for the extradata; once it is freed.
+
+/* ---------------- private code */
+static void sdp_parse_fmtp_config_h264(AVStream * stream,
+ h264_rtp_extra_data * h264_data,
+ char *attr, char *value)
+{
+ AVCodecContext *codec = stream->codec;
+ assert(codec->codec_id == CODEC_ID_H264);
+ assert(h264_data != NULL);
+
+ if (!strcmp(attr, "packetization-mode")) {
+ av_log(NULL, AV_LOG_DEBUG, "H.264/RTP Packetization Mode: %d\n", atoi(attr));
+ h264_data->packetization_mode = atoi(attr);
+ /*
+ Packetization Mode:
+ 0 or not present: Single NAL mode (Only nals from 1-23 are allowed)
+ 1: Non-interleaved Mode: 1-23, 24 (STAP-A), 28 (FU-A) are allowed.
+ 2: Interleaved Mode: 25 (STAP-B), 26 (MTAP16), 27 (MTAP24), 28 (FU-A), and 29 (FU-B) are allowed.
+ */
+ if (h264_data->packetization_mode > 1)
+ av_log(stream, AV_LOG_ERROR,
+ "H.264/RTP Interleaved RTP mode is not supported yet.");
+ } else if (!strcmp(attr, "profile-level-id")) {
+ if (strlen(value) == 6) {
+ char buffer[3];
+ // 6 characters=3 bytes, in hex.
+ uint8_t profile_idc;
+ uint8_t profile_iop;
+ uint8_t level_idc;
+
+ buffer[0] = value[0]; buffer[1] = value[1]; buffer[2] = '\0';
+ profile_idc = strtol(buffer, NULL, 16);
+ buffer[0] = value[2]; buffer[1] = value[3];
+ profile_iop = strtol(buffer, NULL, 16);
+ buffer[0] = value[4]; buffer[1] = value[5];
+ level_idc = strtol(buffer, NULL, 16);
+
+ // set the parameters...
+ av_log(NULL, AV_LOG_DEBUG,
+ "H.264/RTP Profile IDC: %x Profile IOP: %x Level: %x\n",
+ profile_idc, profile_iop, level_idc);
+ h264_data->profile_idc = profile_idc;
+ h264_data->profile_iop = profile_iop;
+ h264_data->level_idc = level_idc;
+ }
+ } else if (!strcmp(attr, "sprop-parameter-sets")) {
+ uint8_t start_sequence[]= { 0, 0, 1 };
+ codec->extradata_size= 0;
+ codec->extradata= NULL;
+
+ while (*value) {
+ char base64packet[1024];
+ uint8_t decoded_packet[1024];
+ uint32_t packet_size;
+ char *dst = base64packet;
+
+ while (*value && *value != ','
+ && (dst - base64packet) < sizeof(base64packet) - 1) {
+ *dst++ = *value++;
+ }
+ *dst++ = '\0';
+
+ if (*value == ',')
+ value++;
+
+ packet_size= av_base64_decode(decoded_packet, base64packet, sizeof(decoded_packet));
+ if (packet_size) {
+ uint8_t *dest= av_malloc(packet_size+sizeof(start_sequence)+codec->extradata_size);
+ if(dest)
+ {
+ if(codec->extradata_size)
+ {
+ // av_realloc?
+ memcpy(dest, codec->extradata, codec->extradata_size);
+ av_free(codec->extradata);
+ }
+
+ memcpy(dest+codec->extradata_size, start_sequence, sizeof(start_sequence));
+ memcpy(dest+codec->extradata_size+sizeof(start_sequence), decoded_packet, packet_size);
+
+ codec->extradata= dest;
+ codec->extradata_size+= sizeof(start_sequence)+packet_size;
+ } else {
+ av_log(NULL, AV_LOG_ERROR, "H.264/RTP Unable to allocate memory for extradata!");
+ }
+ }
+ }
+ av_log(NULL, AV_LOG_DEBUG, "H.264/RTP Extradata set to %p (size: %d)!", codec->extradata, codec->extradata_size);
+ }
+}
+
+// return 0 on packet, no more left, 1 on packet, 1 on partial packet...
+static int h264_handle_packet(RTPDemuxContext * s,
+ AVPacket * pkt,
+ uint32_t * timestamp,
+ const uint8_t * buf,
+ int len)
+{
+// h264_rtp_extra_data *data = s->dynamic_protocol_context;
+ uint8_t nal = buf[0];
+ uint8_t type = (nal & 0x1f);
+ int result= 0;
+ uint8_t start_sequence[]= {0, 0, 1};
+
+ assert(data);
+ assert(data->cookie == MAGIC_COOKIE);
+ assert(buf);
+
+ if (type >= 1 && type <= 23)
+ type = 1; // simplify the case. (these are all the nal types used internally by the h264 codec)
+ switch (type) {
+ case 0: // undefined;
+ result= -1;
+ break;
+
+ case 1:
+ av_new_packet(pkt, len+sizeof(start_sequence));
+ memcpy(pkt->data, start_sequence, sizeof(start_sequence));
+ memcpy(pkt->data+sizeof(start_sequence), buf, len);
+#ifdef DEBUG
+ data->packet_types_received[nal & 0x1f]++;
+#endif
+ break;
+
+ case 24: // STAP-A (one packet, multiple nals)
+ // consume the STAP-A NAL
+ buf++;
+ len--;
+ // first we are going to figure out the total size....
+ {
+ int pass= 0;
+ int total_length= 0;
+ uint8_t *dst= NULL;
+
+ for(pass= 0; pass<2; pass++) {
+ const uint8_t *src= buf;
+ int src_len= len;
+
+ do {
+ uint16_t nal_size = BE_16(src); // this going to be a problem if unaligned (can it be?)
+
+ // consume the length of the aggregate...
+ src += 2;
+ src_len -= 2;
+
+ if (nal_size <= src_len) {
+ if(pass==0) {
+ // counting...
+ total_length+= sizeof(start_sequence)+nal_size;
+ } else {
+ // copying
+ assert(dst);
+ memcpy(dst, start_sequence, sizeof(start_sequence));
+ dst+= sizeof(start_sequence);
+ memcpy(dst, src, nal_size);
+#ifdef DEBUG
+ data->packet_types_received[*src & 0x1f]++;
+#endif
+ dst+= nal_size;
+ }
+ } else {
+ av_log(NULL, AV_LOG_ERROR,
+ "nal size exceeds length: %d %d\n", nal_size, src_len);
+ }
+
+ // eat what we handled...
+ src += nal_size;
+ src_len -= nal_size;
+
+ if (src_len < 0)
+ av_log(NULL, AV_LOG_ERROR,
+ "Consumed more bytes than we got! (%d)\n", src_len);
+ } while (src_len > 2); // because there could be rtp padding..
+
+ if(pass==0) {
+ // now we know the total size of the packet (with the start sequences added)
+ av_new_packet(pkt, total_length);
+ dst= pkt->data;
+ } else {
+ assert(dst-pkt->data==total_length);
+ }
+ }
+ }
+ break;
+
+ case 25: // STAP-B
+ case 26: // MTAP-16
+ case 27: // MTAP-24
+ case 29: // FU-B
+ av_log(NULL, AV_LOG_ERROR,
+ "Unhandled type (%d) (See RFC for implementation details\n",
+ type);
+ result= -1;
+ break;
+
+ case 28: // FU-A (fragmented nal)
+ buf++;
+ len--; // skip the fu_indicator
+ {
+ // these are the same as above, we just redo them here for clarity...
+ uint8_t fu_indicator = nal;
+ uint8_t fu_header = *buf; // read the fu_header.
+ uint8_t start_bit = (fu_header & 0x80) >> 7;
+// uint8_t end_bit = (fu_header & 0x40) >> 6;
+ uint8_t nal_type = (fu_header & 0x1f);
+ uint8_t reconstructed_nal;
+
+ // reconstruct this packet's true nal; only the data follows..
+ reconstructed_nal = fu_indicator & (0xe0); // the original nal forbidden bit and NRI are stored in this packet's nal;
+ reconstructed_nal |= (nal_type & 0x1f);
+
+ // skip the fu_header...
+ buf++;
+ len--;
+
+#ifdef DEBUG
+ if (start_bit)
+ data->packet_types_received[nal_type & 0x1f]++;
+#endif
+ if(start_bit) {
+ // copy in the start sequence, and the reconstructed nal....
+ av_new_packet(pkt, sizeof(start_sequence)+sizeof(nal)+len);
+ memcpy(pkt->data, start_sequence, sizeof(start_sequence));
+ pkt->data[sizeof(start_sequence)]= reconstructed_nal;
+ memcpy(pkt->data+sizeof(start_sequence)+sizeof(nal), buf, len);
+ } else {
+ av_new_packet(pkt, len);
+ memcpy(pkt->data, buf, len);
+ }
+ }
+ break;
+
+ case 30: // undefined
+ case 31: // undefined
+ default:
+ av_log(NULL, AV_LOG_ERROR, "Undefined type (%d)", type);
+ result= -1;
+ break;
+ }
+
+ return result;
+}
+
+/* ---------------- public code */
+static void *h264_new_extradata()
+{
+ h264_rtp_extra_data *data =
+ av_mallocz(sizeof(h264_rtp_extra_data) +
+ FF_INPUT_BUFFER_PADDING_SIZE);
+
+ if (data) {
+ data->cookie = MAGIC_COOKIE;
+ }
+
+ return data;
+}
+
+static void h264_free_extradata(void *d)
+{
+ h264_rtp_extra_data *data = (h264_rtp_extra_data *) d;
+#ifdef DEBUG
+ int ii;
+
+ for (ii = 0; ii < 32; ii++) {
+ if (data->packet_types_received[ii])
+ av_log(NULL, AV_LOG_DEBUG, "Received %d packets of type %d\n",
+ data->packet_types_received[ii], ii);
+ }
+#endif
+
+ assert(data);
+ assert(data->cookie == MAGIC_COOKIE);
+
+ // avoid stale pointers (assert)
+ data->cookie = DEAD_COOKIE;
+
+ // and clear out this...
+ av_free(data);
+}
+
+static int parse_h264_sdp_line(AVStream * stream, void *data,
+ const char *line)
+{
+ AVCodecContext *codec = stream->codec;
+ h264_rtp_extra_data *h264_data = (h264_rtp_extra_data *) data;
+ const char *p = line;
+
+ assert(h264_data->cookie == MAGIC_COOKIE);
+
+ if (strstart(p, "framesize:", &p)) {
+ char buf1[50];
+ char *dst = buf1;
+
+ // remove the protocol identifier..
+ while (*p && *p == ' ') p++; // strip spaces.
+ while (*p && *p != ' ') p++; // eat protocol identifier
+ while (*p && *p == ' ') p++; // strip trailing spaces.
+ while (*p && *p != '-' && (buf1 - dst) < sizeof(buf1) - 1) {
+ *dst++ = *p++;
+ }
+ *dst = '\0';
+
+ // a='framesize:96 320-240'
+ // set our parameters..
+ codec->width = atoi(buf1);
+ codec->height = atoi(p + 1); // skip the -
+ codec->pix_fmt = PIX_FMT_YUV420P;
+ } else if (strstart(p, "fmtp:", &p)) {
+ char attr[256];
+ char value[4096];
+
+ // remove the protocol identifier..
+ while (*p && *p == ' ') p++; // strip spaces.
+ while (*p && *p != ' ') p++; // eat protocol identifier
+ while (*p && *p == ' ') p++; // strip trailing spaces.
+
+ /* loop on each attribute */
+ while (rtsp_next_attr_and_value
+ (&p, attr, sizeof(attr), value, sizeof(value))) {
+ /* grab the codec extra_data from the config parameter of the fmtp line */
+ sdp_parse_fmtp_config_h264(stream, h264_data, attr, value);
+ }
+ } else if (strstart(p, "cliprect:", &p)) {
+ // could use this if we wanted.
+ }
+
+ av_set_pts_info(stream, 33, 1, 90000); // 33 should be right, because the pts is 64 bit? (done elsewhere; this is a one time thing)
+
+ return 0; // keep processing it the normal way...
+}
+
+/**
+This is the structure for expanding on the dynamic rtp protocols (makes everything static. yay!)
+*/
+RTPDynamicProtocolHandler ff_h264_dynamic_handler = {
+ "H264",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_H264,
+ parse_h264_sdp_line,
+ h264_new_extradata,
+ h264_free_extradata,
+ h264_handle_packet
+};
diff --git a/contrib/ffmpeg/libavformat/rtp_h264.h b/contrib/ffmpeg/libavformat/rtp_h264.h
new file mode 100644
index 000000000..19508574d
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rtp_h264.h
@@ -0,0 +1,26 @@
+/*
+ * RTP H264 Protocol (RFC3984)
+ * Copyright (c) 2006 Ryan Martell.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 RTP_H264_H
+#define RTP_H264_H
+
+extern RTPDynamicProtocolHandler ff_h264_dynamic_handler;
+#endif /* RTP_H264_H */
diff --git a/contrib/ffmpeg/libavformat/rtp_internal.h b/contrib/ffmpeg/libavformat/rtp_internal.h
new file mode 100644
index 000000000..3edcf49c8
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rtp_internal.h
@@ -0,0 +1,110 @@
+/*
+ * RTP definitions
+ * Copyright (c) 2006 Ryan Martell <rdm4@martellventures.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
+ */
+
+// this is a bit of a misnomer, because rtp & rtsp internal structures and prototypes are in here.
+#ifndef RTP_INTERNAL_H
+#define RTP_INTERNAL_H
+
+// these statistics are used for rtcp receiver reports...
+typedef struct {
+ uint16_t max_seq; ///< highest sequence number seen
+ uint32_t cycles; ///< shifted count of sequence number cycles
+ uint32_t base_seq; ///< base sequence number
+ uint32_t bad_seq; ///< last bad sequence number + 1
+ int probation; ///< sequence packets till source is valid
+ int received; ///< packets received
+ int expected_prior; ///< packets expected in last interval
+ int received_prior; ///< packets received in last interval
+ uint32_t transit; ///< relative transit time for previous packet
+ uint32_t jitter; ///< estimated jitter.
+} RTPStatistics;
+
+
+typedef int (*DynamicPayloadPacketHandlerProc) (struct RTPDemuxContext * s,
+ AVPacket * pkt,
+ uint32_t *timestamp,
+ const uint8_t * buf,
+ int len);
+
+typedef struct RTPDynamicProtocolHandler_s {
+ // fields from AVRtpDynamicPayloadType_s
+ const char enc_name[50]; /* XXX: still why 50 ? ;-) */
+ enum CodecType codec_type;
+ enum CodecID codec_id;
+
+ // may be null
+ int (*parse_sdp_a_line) (AVStream * stream,
+ void *protocol_data,
+ const char *line); ///< Parse the a= line from the sdp field
+ void *(*open) (); ///< allocate any data needed by the rtp parsing for this dynamic data.
+ void (*close)(void *protocol_data); ///< free any data needed by the rtp parsing for this dynamic data.
+ DynamicPayloadPacketHandlerProc parse_packet; ///< parse handler for this dynamic packet.
+
+ struct RTPDynamicProtocolHandler_s *next;
+} RTPDynamicProtocolHandler;
+
+// moved out of rtp.c, because the h264 decoder needs to know about this structure..
+struct RTPDemuxContext {
+ AVFormatContext *ic;
+ AVStream *st;
+ int payload_type;
+ uint32_t ssrc;
+ uint16_t seq;
+ uint32_t timestamp;
+ uint32_t base_timestamp;
+ uint32_t cur_timestamp;
+ int max_payload_size;
+ struct MpegTSContext *ts; /* only used for MP2T payloads */
+ int read_buf_index;
+ int read_buf_size;
+ /* used to send back RTCP RR */
+ URLContext *rtp_ctx;
+ char hostname[256];
+
+ RTPStatistics statistics; ///< Statistics for this stream (used by RTCP receiver reports)
+
+ /* rtcp sender statistics receive */
+ int64_t last_rtcp_ntp_time; // TODO: move into statistics
+ int64_t first_rtcp_ntp_time; // TODO: move into statistics
+ uint32_t last_rtcp_timestamp; // TODO: move into statistics
+
+ /* rtcp sender statistics */
+ unsigned int packet_count; // TODO: move into statistics (outgoing)
+ unsigned int octet_count; // TODO: move into statistics (outgoing)
+ unsigned int last_octet_count; // TODO: move into statistics (outgoing)
+ int first_packet;
+ /* buffer for output */
+ uint8_t buf[RTP_MAX_PACKET_LENGTH];
+ uint8_t *buf_ptr;
+
+ /* special infos for au headers parsing */
+ rtp_payload_data_t *rtp_payload_data; // TODO: Move into dynamic payload handlers
+
+ /* dynamic payload stuff */
+ DynamicPayloadPacketHandlerProc parse_packet; ///< This is also copied from the dynamic protocol handler structure
+ void *dynamic_protocol_context; ///< This is a copy from the values setup from the sdp parsing, in rtsp.c don't free me.
+};
+
+extern RTPDynamicProtocolHandler *RTPFirstDynamicPayloadHandler;
+
+int rtsp_next_attr_and_value(const char **p, char *attr, int attr_size, char *value, int value_size); ///< from rtsp.c, but used by rtp dynamic protocol handlers.
+#endif /* RTP_INTERNAL_H */
+
diff --git a/contrib/ffmpeg/libavformat/rtpproto.c b/contrib/ffmpeg/libavformat/rtpproto.c
new file mode 100644
index 000000000..d31c509c2
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rtpproto.c
@@ -0,0 +1,303 @@
+/*
+ * RTP network protocol
+ * 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 "avformat.h"
+
+#include <unistd.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifndef __BEOS__
+# include <arpa/inet.h>
+#else
+# include "barpainet.h"
+#endif
+#include <netdb.h>
+#include <fcntl.h>
+
+#define RTP_TX_BUF_SIZE (64 * 1024)
+#define RTP_RX_BUF_SIZE (128 * 1024)
+
+typedef struct RTPContext {
+ URLContext *rtp_hd, *rtcp_hd;
+ int rtp_fd, rtcp_fd;
+} RTPContext;
+
+/**
+ * If no filename is given to av_open_input_file because you want to
+ * get the local port first, then you must call this function to set
+ * the remote server address.
+ *
+ * @param s1 media file context
+ * @param uri of the remote server
+ * @return zero if no error.
+ */
+int rtp_set_remote_url(URLContext *h, const char *uri)
+{
+ RTPContext *s = h->priv_data;
+ char hostname[256];
+ int port;
+
+ char buf[1024];
+ char path[1024];
+
+ url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port,
+ path, sizeof(path), uri);
+
+ snprintf(buf, sizeof(buf), "udp://%s:%d%s", hostname, port, path);
+ udp_set_remote_url(s->rtp_hd, buf);
+
+ snprintf(buf, sizeof(buf), "udp://%s:%d%s", hostname, port + 1, path);
+ udp_set_remote_url(s->rtcp_hd, buf);
+ return 0;
+}
+
+
+/* add option to url of the form:
+ "http://host:port/path?option1=val1&option2=val2... */
+static void url_add_option(char *buf, int buf_size, const char *fmt, ...)
+{
+ char buf1[1024];
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (strchr(buf, '?'))
+ pstrcat(buf, buf_size, "&");
+ else
+ pstrcat(buf, buf_size, "?");
+ vsnprintf(buf1, sizeof(buf1), fmt, ap);
+ pstrcat(buf, buf_size, buf1);
+ va_end(ap);
+}
+
+static void build_udp_url(char *buf, int buf_size,
+ const char *hostname, int port,
+ int local_port, int multicast, int ttl)
+{
+ snprintf(buf, buf_size, "udp://%s:%d", hostname, port);
+ if (local_port >= 0)
+ url_add_option(buf, buf_size, "localport=%d", local_port);
+ if (multicast)
+ url_add_option(buf, buf_size, "multicast=1", multicast);
+ if (ttl >= 0)
+ url_add_option(buf, buf_size, "ttl=%d", ttl);
+}
+
+/*
+ * url syntax: rtp://host:port[?option=val...]
+ * option: 'multicast=1' : enable multicast
+ * 'ttl=n' : set the ttl value (for multicast only)
+ * 'localport=n' : set the local port to n
+ *
+ */
+static int rtp_open(URLContext *h, const char *uri, int flags)
+{
+ RTPContext *s;
+ int port, is_output, is_multicast, ttl, local_port;
+ char hostname[256];
+ char buf[1024];
+ char path[1024];
+ const char *p;
+
+ is_output = (flags & URL_WRONLY);
+
+ s = av_mallocz(sizeof(RTPContext));
+ if (!s)
+ return -ENOMEM;
+ h->priv_data = s;
+
+ url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port,
+ path, sizeof(path), uri);
+ /* extract parameters */
+ is_multicast = 0;
+ ttl = -1;
+ local_port = -1;
+ p = strchr(uri, '?');
+ if (p) {
+ is_multicast = find_info_tag(buf, sizeof(buf), "multicast", p);
+ if (find_info_tag(buf, sizeof(buf), "ttl", p)) {
+ ttl = strtol(buf, NULL, 10);
+ }
+ if (find_info_tag(buf, sizeof(buf), "localport", p)) {
+ local_port = strtol(buf, NULL, 10);
+ }
+ }
+
+ build_udp_url(buf, sizeof(buf),
+ hostname, port, local_port, is_multicast, ttl);
+ if (url_open(&s->rtp_hd, buf, flags) < 0)
+ goto fail;
+ local_port = udp_get_local_port(s->rtp_hd);
+ /* XXX: need to open another connexion if the port is not even */
+
+ /* well, should suppress localport in path */
+
+ build_udp_url(buf, sizeof(buf),
+ hostname, port + 1, local_port + 1, is_multicast, ttl);
+ if (url_open(&s->rtcp_hd, buf, flags) < 0)
+ goto fail;
+
+ /* just to ease handle access. XXX: need to suppress direct handle
+ access */
+ s->rtp_fd = udp_get_file_handle(s->rtp_hd);
+ s->rtcp_fd = udp_get_file_handle(s->rtcp_hd);
+
+ h->max_packet_size = url_get_max_packet_size(s->rtp_hd);
+ h->is_streamed = 1;
+ return 0;
+
+ fail:
+ if (s->rtp_hd)
+ url_close(s->rtp_hd);
+ if (s->rtcp_hd)
+ url_close(s->rtcp_hd);
+ av_free(s);
+ return AVERROR_IO;
+}
+
+static int rtp_read(URLContext *h, uint8_t *buf, int size)
+{
+ RTPContext *s = h->priv_data;
+ struct sockaddr_in from;
+ socklen_t from_len;
+ int len, fd_max, n;
+ fd_set rfds;
+#if 0
+ for(;;) {
+ from_len = sizeof(from);
+ len = recvfrom (s->rtp_fd, buf, size, 0,
+ (struct sockaddr *)&from, &from_len);
+ if (len < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ return AVERROR_IO;
+ }
+ break;
+ }
+#else
+ for(;;) {
+ /* build fdset to listen to RTP and RTCP packets */
+ FD_ZERO(&rfds);
+ fd_max = s->rtp_fd;
+ FD_SET(s->rtp_fd, &rfds);
+ if (s->rtcp_fd > fd_max)
+ fd_max = s->rtcp_fd;
+ FD_SET(s->rtcp_fd, &rfds);
+ n = select(fd_max + 1, &rfds, NULL, NULL, NULL);
+ if (n > 0) {
+ /* first try RTCP */
+ if (FD_ISSET(s->rtcp_fd, &rfds)) {
+ from_len = sizeof(from);
+ len = recvfrom (s->rtcp_fd, buf, size, 0,
+ (struct sockaddr *)&from, &from_len);
+ if (len < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ return AVERROR_IO;
+ }
+ break;
+ }
+ /* then RTP */
+ if (FD_ISSET(s->rtp_fd, &rfds)) {
+ from_len = sizeof(from);
+ len = recvfrom (s->rtp_fd, buf, size, 0,
+ (struct sockaddr *)&from, &from_len);
+ if (len < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ return AVERROR_IO;
+ }
+ break;
+ }
+ }
+ }
+#endif
+ return len;
+}
+
+static int rtp_write(URLContext *h, uint8_t *buf, int size)
+{
+ RTPContext *s = h->priv_data;
+ int ret;
+ URLContext *hd;
+
+ if (buf[1] >= 200 && buf[1] <= 204) {
+ /* RTCP payload type */
+ hd = s->rtcp_hd;
+ } else {
+ /* RTP payload type */
+ hd = s->rtp_hd;
+ }
+
+ ret = url_write(hd, buf, size);
+#if 0
+ {
+ struct timespec ts;
+ ts.tv_sec = 0;
+ ts.tv_nsec = 10 * 1000000;
+ nanosleep(&ts, NULL);
+ }
+#endif
+ return ret;
+}
+
+static int rtp_close(URLContext *h)
+{
+ RTPContext *s = h->priv_data;
+
+ url_close(s->rtp_hd);
+ url_close(s->rtcp_hd);
+ av_free(s);
+ return 0;
+}
+
+/**
+ * Return the local port used by the RTP connexion
+ * @param s1 media file context
+ * @return the local port number
+ */
+int rtp_get_local_port(URLContext *h)
+{
+ RTPContext *s = h->priv_data;
+ return udp_get_local_port(s->rtp_hd);
+}
+
+/**
+ * Return the rtp and rtcp file handles for select() usage to wait for several RTP
+ * streams at the same time.
+ * @param h media file context
+ */
+void rtp_get_file_handles(URLContext *h, int *prtp_fd, int *prtcp_fd)
+{
+ RTPContext *s = h->priv_data;
+
+ *prtp_fd = s->rtp_fd;
+ *prtcp_fd = s->rtcp_fd;
+}
+
+URLProtocol rtp_protocol = {
+ "rtp",
+ rtp_open,
+ rtp_read,
+ rtp_write,
+ NULL, /* seek */
+ rtp_close,
+};
diff --git a/contrib/ffmpeg/libavformat/rtsp.c b/contrib/ffmpeg/libavformat/rtsp.c
new file mode 100644
index 000000000..787cdd685
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rtsp.c
@@ -0,0 +1,1493 @@
+/*
+ * RTSP/SDP client
+ * 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 "avformat.h"
+
+#include <unistd.h> /* for select() prototype */
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#ifndef __BEOS__
+# include <arpa/inet.h>
+#else
+# include "barpainet.h"
+#endif
+
+#include "rtp_internal.h"
+
+//#define DEBUG
+//#define DEBUG_RTP_TCP
+
+enum RTSPClientState {
+ RTSP_STATE_IDLE,
+ RTSP_STATE_PLAYING,
+ RTSP_STATE_PAUSED,
+};
+
+typedef struct RTSPState {
+ URLContext *rtsp_hd; /* RTSP TCP connexion handle */
+ int nb_rtsp_streams;
+ struct RTSPStream **rtsp_streams;
+
+ enum RTSPClientState state;
+ int64_t seek_timestamp;
+
+ /* XXX: currently we use unbuffered input */
+ // ByteIOContext rtsp_gb;
+ int seq; /* RTSP command sequence number */
+ char session_id[512];
+ enum RTSPProtocol protocol;
+ char last_reply[2048]; /* XXX: allocate ? */
+ RTPDemuxContext *cur_rtp;
+} RTSPState;
+
+typedef struct RTSPStream {
+ URLContext *rtp_handle; /* RTP stream handle */
+ RTPDemuxContext *rtp_ctx; /* RTP parse context */
+
+ int stream_index; /* corresponding stream index, if any. -1 if none (MPEG2TS case) */
+ int interleaved_min, interleaved_max; /* interleave ids, if TCP transport */
+ char control_url[1024]; /* url for this stream (from SDP) */
+
+ int sdp_port; /* port (from SDP content - not used in RTSP) */
+ struct in_addr sdp_ip; /* IP address (from SDP content - not used in RTSP) */
+ int sdp_ttl; /* IP TTL (from SDP content - not used in RTSP) */
+ int sdp_payload_type; /* payload type - only used in SDP */
+ rtp_payload_data_t rtp_payload_data; /* rtp payload parsing infos from SDP */
+
+ RTPDynamicProtocolHandler *dynamic_handler; ///< Only valid if it's a dynamic protocol. (This is the handler structure)
+ void *dynamic_protocol_context; ///< Only valid if it's a dynamic protocol. (This is any private data associated with the dynamic protocol)
+} RTSPStream;
+
+static int rtsp_read_play(AVFormatContext *s);
+
+/* XXX: currently, the only way to change the protocols consists in
+ changing this variable */
+
+int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_UDP);
+
+FFRTSPCallback *ff_rtsp_callback = NULL;
+
+static int rtsp_probe(AVProbeData *p)
+{
+ if (strstart(p->filename, "rtsp:", NULL))
+ return AVPROBE_SCORE_MAX;
+ return 0;
+}
+
+static int redir_isspace(int c)
+{
+ return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
+}
+
+static void skip_spaces(const char **pp)
+{
+ const char *p;
+ p = *pp;
+ while (redir_isspace(*p))
+ p++;
+ *pp = p;
+}
+
+static void get_word_sep(char *buf, int buf_size, const char *sep,
+ const char **pp)
+{
+ const char *p;
+ char *q;
+
+ p = *pp;
+ if (*p == '/')
+ p++;
+ skip_spaces(&p);
+ q = buf;
+ while (!strchr(sep, *p) && *p != '\0') {
+ if ((q - buf) < buf_size - 1)
+ *q++ = *p;
+ p++;
+ }
+ if (buf_size > 0)
+ *q = '\0';
+ *pp = p;
+}
+
+static void get_word(char *buf, int buf_size, const char **pp)
+{
+ const char *p;
+ char *q;
+
+ p = *pp;
+ skip_spaces(&p);
+ q = buf;
+ while (!redir_isspace(*p) && *p != '\0') {
+ if ((q - buf) < buf_size - 1)
+ *q++ = *p;
+ p++;
+ }
+ if (buf_size > 0)
+ *q = '\0';
+ *pp = p;
+}
+
+/* parse the rtpmap description: <codec_name>/<clock_rate>[/<other
+ params>] */
+static int sdp_parse_rtpmap(AVCodecContext *codec, RTSPStream *rtsp_st, int payload_type, const char *p)
+{
+ char buf[256];
+ int i;
+ AVCodec *c;
+ const char *c_name;
+
+ /* Loop into AVRtpDynamicPayloadTypes[] and AVRtpPayloadTypes[] and
+ see if we can handle this kind of payload */
+ get_word_sep(buf, sizeof(buf), "/", &p);
+ if (payload_type >= RTP_PT_PRIVATE) {
+ RTPDynamicProtocolHandler *handler= RTPFirstDynamicPayloadHandler;
+ while(handler) {
+ if (!strcmp(buf, handler->enc_name) && (codec->codec_type == handler->codec_type)) {
+ codec->codec_id = handler->codec_id;
+ rtsp_st->dynamic_handler= handler;
+ if(handler->open) {
+ rtsp_st->dynamic_protocol_context= handler->open();
+ }
+ break;
+ }
+ handler= handler->next;
+ }
+ } else {
+ /* We are in a standard case ( from http://www.iana.org/assignments/rtp-parameters) */
+ /* search into AVRtpPayloadTypes[] */
+ for (i = 0; AVRtpPayloadTypes[i].pt >= 0; ++i)
+ if (!strcmp(buf, AVRtpPayloadTypes[i].enc_name) && (codec->codec_type == AVRtpPayloadTypes[i].codec_type)){
+ codec->codec_id = AVRtpPayloadTypes[i].codec_id;
+ break;
+ }
+ }
+
+ c = avcodec_find_decoder(codec->codec_id);
+ if (c && c->name)
+ c_name = c->name;
+ else
+ c_name = (char *)NULL;
+
+ if (c_name) {
+ get_word_sep(buf, sizeof(buf), "/", &p);
+ i = atoi(buf);
+ switch (codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ av_log(codec, AV_LOG_DEBUG, " audio codec set to : %s\n", c_name);
+ codec->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE;
+ codec->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS;
+ if (i > 0) {
+ codec->sample_rate = i;
+ get_word_sep(buf, sizeof(buf), "/", &p);
+ i = atoi(buf);
+ if (i > 0)
+ codec->channels = i;
+ // TODO: there is a bug here; if it is a mono stream, and less than 22000Hz, faad upconverts to stereo and twice the
+ // frequency. No problem, but the sample rate is being set here by the sdp line. Upcoming patch forthcoming. (rdm)
+ }
+ av_log(codec, AV_LOG_DEBUG, " audio samplerate set to : %i\n", codec->sample_rate);
+ av_log(codec, AV_LOG_DEBUG, " audio channels set to : %i\n", codec->channels);
+ break;
+ case CODEC_TYPE_VIDEO:
+ av_log(codec, AV_LOG_DEBUG, " video codec set to : %s\n", c_name);
+ break;
+ default:
+ break;
+ }
+ return 0;
+ }
+
+ return -1;
+}
+
+/* return the length and optionnaly the data */
+static int hex_to_data(uint8_t *data, const char *p)
+{
+ int c, len, v;
+
+ len = 0;
+ v = 1;
+ for(;;) {
+ skip_spaces(&p);
+ if (p == '\0')
+ break;
+ c = toupper((unsigned char)*p++);
+ if (c >= '0' && c <= '9')
+ c = c - '0';
+ else if (c >= 'A' && c <= 'F')
+ c = c - 'A' + 10;
+ else
+ break;
+ v = (v << 4) | c;
+ if (v & 0x100) {
+ if (data)
+ data[len] = v;
+ len++;
+ v = 1;
+ }
+ }
+ return len;
+}
+
+static void sdp_parse_fmtp_config(AVCodecContext *codec, char *attr, char *value)
+{
+ switch (codec->codec_id) {
+ case CODEC_ID_MPEG4:
+ case CODEC_ID_AAC:
+ if (!strcmp(attr, "config")) {
+ /* decode the hexa encoded parameter */
+ int len = hex_to_data(NULL, value);
+ codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
+ if (!codec->extradata)
+ return;
+ codec->extradata_size = len;
+ hex_to_data(codec->extradata, value);
+ }
+ break;
+ default:
+ break;
+ }
+ return;
+}
+
+typedef struct attrname_map
+{
+ const char *str;
+ uint16_t type;
+ uint32_t offset;
+} attrname_map_t;
+
+/* All known fmtp parmeters and the corresping RTPAttrTypeEnum */
+#define ATTR_NAME_TYPE_INT 0
+#define ATTR_NAME_TYPE_STR 1
+static attrname_map_t attr_names[]=
+{
+ {"SizeLength", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, sizelength)},
+ {"IndexLength", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, indexlength)},
+ {"IndexDeltaLength", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, indexdeltalength)},
+ {"profile-level-id", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, profile_level_id)},
+ {"StreamType", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, streamtype)},
+ {"mode", ATTR_NAME_TYPE_STR, offsetof(rtp_payload_data_t, mode)},
+ {NULL, -1, -1},
+};
+
+/** parse the attribute line from the fmtp a line of an sdp resonse. This is broken out as a function
+* because it is used in rtp_h264.c, which is forthcoming.
+*/
+int rtsp_next_attr_and_value(const char **p, char *attr, int attr_size, char *value, int value_size)
+{
+ skip_spaces(p);
+ if(**p)
+ {
+ get_word_sep(attr, attr_size, "=", p);
+ if (**p == '=')
+ (*p)++;
+ get_word_sep(value, value_size, ";", p);
+ if (**p == ';')
+ (*p)++;
+ return 1;
+ }
+ return 0;
+}
+
+/* parse a SDP line and save stream attributes */
+static void sdp_parse_fmtp(AVStream *st, const char *p)
+{
+ char attr[256];
+ char value[4096];
+ int i;
+
+ RTSPStream *rtsp_st = st->priv_data;
+ AVCodecContext *codec = st->codec;
+ rtp_payload_data_t *rtp_payload_data = &rtsp_st->rtp_payload_data;
+
+ /* loop on each attribute */
+ while(rtsp_next_attr_and_value(&p, attr, sizeof(attr), value, sizeof(value)))
+ {
+ /* grab the codec extra_data from the config parameter of the fmtp line */
+ sdp_parse_fmtp_config(codec, attr, value);
+ /* Looking for a known attribute */
+ for (i = 0; attr_names[i].str; ++i) {
+ if (!strcasecmp(attr, attr_names[i].str)) {
+ if (attr_names[i].type == ATTR_NAME_TYPE_INT)
+ *(int *)((char *)rtp_payload_data + attr_names[i].offset) = atoi(value);
+ else if (attr_names[i].type == ATTR_NAME_TYPE_STR)
+ *(char **)((char *)rtp_payload_data + attr_names[i].offset) = av_strdup(value);
+ }
+ }
+ }
+}
+
+/** Parse a string \p in the form of Range:npt=xx-xx, and determine the start
+ * and end time.
+ * Used for seeking in the rtp stream.
+ */
+static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end)
+{
+ char buf[256];
+
+ skip_spaces(&p);
+ if (!stristart(p, "npt=", &p))
+ return;
+
+ *start = AV_NOPTS_VALUE;
+ *end = AV_NOPTS_VALUE;
+
+ get_word_sep(buf, sizeof(buf), "-", &p);
+ *start = parse_date(buf, 1);
+ if (*p == '-') {
+ p++;
+ get_word_sep(buf, sizeof(buf), "-", &p);
+ *end = parse_date(buf, 1);
+ }
+// av_log(NULL, AV_LOG_DEBUG, "Range Start: %lld\n", *start);
+// av_log(NULL, AV_LOG_DEBUG, "Range End: %lld\n", *end);
+}
+
+typedef struct SDPParseState {
+ /* SDP only */
+ struct in_addr default_ip;
+ int default_ttl;
+} SDPParseState;
+
+static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
+ int letter, const char *buf)
+{
+ RTSPState *rt = s->priv_data;
+ char buf1[64], st_type[64];
+ const char *p;
+ int codec_type, payload_type, i;
+ AVStream *st;
+ RTSPStream *rtsp_st;
+ struct in_addr sdp_ip;
+ int ttl;
+
+#ifdef DEBUG
+ printf("sdp: %c='%s'\n", letter, buf);
+#endif
+
+ p = buf;
+ switch(letter) {
+ case 'c':
+ get_word(buf1, sizeof(buf1), &p);
+ if (strcmp(buf1, "IN") != 0)
+ return;
+ get_word(buf1, sizeof(buf1), &p);
+ if (strcmp(buf1, "IP4") != 0)
+ return;
+ get_word_sep(buf1, sizeof(buf1), "/", &p);
+ if (inet_aton(buf1, &sdp_ip) == 0)
+ return;
+ ttl = 16;
+ if (*p == '/') {
+ p++;
+ get_word_sep(buf1, sizeof(buf1), "/", &p);
+ ttl = atoi(buf1);
+ }
+ if (s->nb_streams == 0) {
+ s1->default_ip = sdp_ip;
+ s1->default_ttl = ttl;
+ } else {
+ st = s->streams[s->nb_streams - 1];
+ rtsp_st = st->priv_data;
+ rtsp_st->sdp_ip = sdp_ip;
+ rtsp_st->sdp_ttl = ttl;
+ }
+ break;
+ case 's':
+ pstrcpy(s->title, sizeof(s->title), p);
+ break;
+ case 'i':
+ if (s->nb_streams == 0) {
+ pstrcpy(s->comment, sizeof(s->comment), p);
+ break;
+ }
+ break;
+ case 'm':
+ /* new stream */
+ get_word(st_type, sizeof(st_type), &p);
+ if (!strcmp(st_type, "audio")) {
+ codec_type = CODEC_TYPE_AUDIO;
+ } else if (!strcmp(st_type, "video")) {
+ codec_type = CODEC_TYPE_VIDEO;
+ } else {
+ return;
+ }
+ rtsp_st = av_mallocz(sizeof(RTSPStream));
+ if (!rtsp_st)
+ return;
+ rtsp_st->stream_index = -1;
+ dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st);
+
+ rtsp_st->sdp_ip = s1->default_ip;
+ rtsp_st->sdp_ttl = s1->default_ttl;
+
+ get_word(buf1, sizeof(buf1), &p); /* port */
+ rtsp_st->sdp_port = atoi(buf1);
+
+ get_word(buf1, sizeof(buf1), &p); /* protocol (ignored) */
+
+ /* XXX: handle list of formats */
+ get_word(buf1, sizeof(buf1), &p); /* format list */
+ rtsp_st->sdp_payload_type = atoi(buf1);
+
+ if (!strcmp(AVRtpPayloadTypes[rtsp_st->sdp_payload_type].enc_name, "MP2T")) {
+ /* no corresponding stream */
+ } else {
+ st = av_new_stream(s, 0);
+ if (!st)
+ return;
+ st->priv_data = rtsp_st;
+ rtsp_st->stream_index = st->index;
+ st->codec->codec_type = codec_type;
+ if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) {
+ /* if standard payload type, we can find the codec right now */
+ rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type);
+ }
+ }
+ /* put a default control url */
+ pstrcpy(rtsp_st->control_url, sizeof(rtsp_st->control_url), s->filename);
+ break;
+ case 'a':
+ if (strstart(p, "control:", &p) && s->nb_streams > 0) {
+ char proto[32];
+ /* get the control url */
+ st = s->streams[s->nb_streams - 1];
+ rtsp_st = st->priv_data;
+
+ /* XXX: may need to add full url resolution */
+ url_split(proto, sizeof(proto), NULL, 0, NULL, 0, NULL, NULL, 0, p);
+ if (proto[0] == '\0') {
+ /* relative control URL */
+ pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), "/");
+ pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), p);
+ } else {
+ pstrcpy(rtsp_st->control_url, sizeof(rtsp_st->control_url), p);
+ }
+ } else if (strstart(p, "rtpmap:", &p)) {
+ /* NOTE: rtpmap is only supported AFTER the 'm=' tag */
+ get_word(buf1, sizeof(buf1), &p);
+ payload_type = atoi(buf1);
+ for(i = 0; i < s->nb_streams;i++) {
+ st = s->streams[i];
+ rtsp_st = st->priv_data;
+ if (rtsp_st->sdp_payload_type == payload_type) {
+ sdp_parse_rtpmap(st->codec, rtsp_st, payload_type, p);
+ }
+ }
+ } else if (strstart(p, "fmtp:", &p)) {
+ /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */
+ get_word(buf1, sizeof(buf1), &p);
+ payload_type = atoi(buf1);
+ for(i = 0; i < s->nb_streams;i++) {
+ st = s->streams[i];
+ rtsp_st = st->priv_data;
+ if (rtsp_st->sdp_payload_type == payload_type) {
+ if(rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->parse_sdp_a_line) {
+ if(!rtsp_st->dynamic_handler->parse_sdp_a_line(st, rtsp_st->dynamic_protocol_context, buf)) {
+ sdp_parse_fmtp(st, p);
+ }
+ } else {
+ sdp_parse_fmtp(st, p);
+ }
+ }
+ }
+ } else if(strstart(p, "framesize:", &p)) {
+ // let dynamic protocol handlers have a stab at the line.
+ get_word(buf1, sizeof(buf1), &p);
+ payload_type = atoi(buf1);
+ for(i = 0; i < s->nb_streams;i++) {
+ st = s->streams[i];
+ rtsp_st = st->priv_data;
+ if (rtsp_st->sdp_payload_type == payload_type) {
+ if(rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->parse_sdp_a_line) {
+ rtsp_st->dynamic_handler->parse_sdp_a_line(st, rtsp_st->dynamic_protocol_context, buf);
+ }
+ }
+ }
+ } else if(strstart(p, "range:", &p)) {
+ int64_t start, end;
+
+ // this is so that seeking on a streamed file can work.
+ rtsp_parse_range_npt(p, &start, &end);
+ s->start_time= start;
+ s->duration= (end==AV_NOPTS_VALUE)?AV_NOPTS_VALUE:end-start; // AV_NOPTS_VALUE means live broadcast (and can't seek)
+ }
+ break;
+ }
+}
+
+static int sdp_parse(AVFormatContext *s, const char *content)
+{
+ const char *p;
+ int letter;
+ char buf[1024], *q;
+ SDPParseState sdp_parse_state, *s1 = &sdp_parse_state;
+
+ memset(s1, 0, sizeof(SDPParseState));
+ p = content;
+ for(;;) {
+ skip_spaces(&p);
+ letter = *p;
+ if (letter == '\0')
+ break;
+ p++;
+ if (*p != '=')
+ goto next_line;
+ p++;
+ /* get the content */
+ q = buf;
+ while (*p != '\n' && *p != '\r' && *p != '\0') {
+ if ((q - buf) < sizeof(buf) - 1)
+ *q++ = *p;
+ p++;
+ }
+ *q = '\0';
+ sdp_parse_line(s, s1, letter, buf);
+ next_line:
+ while (*p != '\n' && *p != '\0')
+ p++;
+ if (*p == '\n')
+ p++;
+ }
+ return 0;
+}
+
+static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
+{
+ const char *p;
+ int v;
+
+ p = *pp;
+ skip_spaces(&p);
+ v = strtol(p, (char **)&p, 10);
+ if (*p == '-') {
+ p++;
+ *min_ptr = v;
+ v = strtol(p, (char **)&p, 10);
+ *max_ptr = v;
+ } else {
+ *min_ptr = v;
+ *max_ptr = v;
+ }
+ *pp = p;
+}
+
+/* XXX: only one transport specification is parsed */
+static void rtsp_parse_transport(RTSPHeader *reply, const char *p)
+{
+ char transport_protocol[16];
+ char profile[16];
+ char lower_transport[16];
+ char parameter[16];
+ RTSPTransportField *th;
+ char buf[256];
+
+ reply->nb_transports = 0;
+
+ for(;;) {
+ skip_spaces(&p);
+ if (*p == '\0')
+ break;
+
+ th = &reply->transports[reply->nb_transports];
+
+ get_word_sep(transport_protocol, sizeof(transport_protocol),
+ "/", &p);
+ if (*p == '/')
+ p++;
+ get_word_sep(profile, sizeof(profile), "/;,", &p);
+ lower_transport[0] = '\0';
+ if (*p == '/') {
+ p++;
+ get_word_sep(lower_transport, sizeof(lower_transport),
+ ";,", &p);
+ }
+ if (!strcasecmp(lower_transport, "TCP"))
+ th->protocol = RTSP_PROTOCOL_RTP_TCP;
+ else
+ th->protocol = RTSP_PROTOCOL_RTP_UDP;
+
+ if (*p == ';')
+ p++;
+ /* get each parameter */
+ while (*p != '\0' && *p != ',') {
+ get_word_sep(parameter, sizeof(parameter), "=;,", &p);
+ if (!strcmp(parameter, "port")) {
+ if (*p == '=') {
+ p++;
+ rtsp_parse_range(&th->port_min, &th->port_max, &p);
+ }
+ } else if (!strcmp(parameter, "client_port")) {
+ if (*p == '=') {
+ p++;
+ rtsp_parse_range(&th->client_port_min,
+ &th->client_port_max, &p);
+ }
+ } else if (!strcmp(parameter, "server_port")) {
+ if (*p == '=') {
+ p++;
+ rtsp_parse_range(&th->server_port_min,
+ &th->server_port_max, &p);
+ }
+ } else if (!strcmp(parameter, "interleaved")) {
+ if (*p == '=') {
+ p++;
+ rtsp_parse_range(&th->interleaved_min,
+ &th->interleaved_max, &p);
+ }
+ } else if (!strcmp(parameter, "multicast")) {
+ if (th->protocol == RTSP_PROTOCOL_RTP_UDP)
+ th->protocol = RTSP_PROTOCOL_RTP_UDP_MULTICAST;
+ } else if (!strcmp(parameter, "ttl")) {
+ if (*p == '=') {
+ p++;
+ th->ttl = strtol(p, (char **)&p, 10);
+ }
+ } else if (!strcmp(parameter, "destination")) {
+ struct in_addr ipaddr;
+
+ if (*p == '=') {
+ p++;
+ get_word_sep(buf, sizeof(buf), ";,", &p);
+ if (inet_aton(buf, &ipaddr))
+ th->destination = ntohl(ipaddr.s_addr);
+ }
+ }
+ while (*p != ';' && *p != '\0' && *p != ',')
+ p++;
+ if (*p == ';')
+ p++;
+ }
+ if (*p == ',')
+ p++;
+
+ reply->nb_transports++;
+ }
+}
+
+void rtsp_parse_line(RTSPHeader *reply, const char *buf)
+{
+ const char *p;
+
+ /* NOTE: we do case independent match for broken servers */
+ p = buf;
+ if (stristart(p, "Session:", &p)) {
+ get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
+ } else if (stristart(p, "Content-Length:", &p)) {
+ reply->content_length = strtol(p, NULL, 10);
+ } else if (stristart(p, "Transport:", &p)) {
+ rtsp_parse_transport(reply, p);
+ } else if (stristart(p, "CSeq:", &p)) {
+ reply->seq = strtol(p, NULL, 10);
+ } else if (stristart(p, "Range:", &p)) {
+ rtsp_parse_range_npt(p, &reply->range_start, &reply->range_end);
+ }
+}
+
+static int url_readbuf(URLContext *h, unsigned char *buf, int size)
+{
+ int ret, len;
+
+ len = 0;
+ while (len < size) {
+ ret = url_read(h, buf+len, size-len);
+ if (ret < 1)
+ return ret;
+ len += ret;
+ }
+ return len;
+}
+
+/* skip a RTP/TCP interleaved packet */
+static void rtsp_skip_packet(AVFormatContext *s)
+{
+ RTSPState *rt = s->priv_data;
+ int ret, len, len1;
+ uint8_t buf[1024];
+
+ ret = url_readbuf(rt->rtsp_hd, buf, 3);
+ if (ret != 3)
+ return;
+ len = (buf[1] << 8) | buf[2];
+#ifdef DEBUG
+ printf("skipping RTP packet len=%d\n", len);
+#endif
+ /* skip payload */
+ while (len > 0) {
+ len1 = len;
+ if (len1 > sizeof(buf))
+ len1 = sizeof(buf);
+ ret = url_readbuf(rt->rtsp_hd, buf, len1);
+ if (ret != len1)
+ return;
+ len -= len1;
+ }
+}
+
+static void rtsp_send_cmd(AVFormatContext *s,
+ const char *cmd, RTSPHeader *reply,
+ unsigned char **content_ptr)
+{
+ RTSPState *rt = s->priv_data;
+ char buf[4096], buf1[1024], *q;
+ unsigned char ch;
+ const char *p;
+ int content_length, line_count;
+ unsigned char *content = NULL;
+
+ memset(reply, 0, sizeof(RTSPHeader));
+
+ rt->seq++;
+ pstrcpy(buf, sizeof(buf), cmd);
+ snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq);
+ pstrcat(buf, sizeof(buf), buf1);
+ if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) {
+ snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id);
+ pstrcat(buf, sizeof(buf), buf1);
+ }
+ pstrcat(buf, sizeof(buf), "\r\n");
+#ifdef DEBUG
+ printf("Sending:\n%s--\n", buf);
+#endif
+ url_write(rt->rtsp_hd, buf, strlen(buf));
+
+ /* parse reply (XXX: use buffers) */
+ line_count = 0;
+ rt->last_reply[0] = '\0';
+ for(;;) {
+ q = buf;
+ for(;;) {
+ if (url_readbuf(rt->rtsp_hd, &ch, 1) != 1)
+ break;
+ if (ch == '\n')
+ break;
+ if (ch == '$') {
+ /* XXX: only parse it if first char on line ? */
+ rtsp_skip_packet(s);
+ } else if (ch != '\r') {
+ if ((q - buf) < sizeof(buf) - 1)
+ *q++ = ch;
+ }
+ }
+ *q = '\0';
+#ifdef DEBUG
+ printf("line='%s'\n", buf);
+#endif
+ /* test if last line */
+ if (buf[0] == '\0')
+ break;
+ p = buf;
+ if (line_count == 0) {
+ /* get reply code */
+ get_word(buf1, sizeof(buf1), &p);
+ get_word(buf1, sizeof(buf1), &p);
+ reply->status_code = atoi(buf1);
+ } else {
+ rtsp_parse_line(reply, p);
+ pstrcat(rt->last_reply, sizeof(rt->last_reply), p);
+ pstrcat(rt->last_reply, sizeof(rt->last_reply), "\n");
+ }
+ line_count++;
+ }
+
+ if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
+ pstrcpy(rt->session_id, sizeof(rt->session_id), reply->session_id);
+
+ content_length = reply->content_length;
+ if (content_length > 0) {
+ /* leave some room for a trailing '\0' (useful for simple parsing) */
+ content = av_malloc(content_length + 1);
+ (void)url_readbuf(rt->rtsp_hd, content, content_length);
+ content[content_length] = '\0';
+ }
+ if (content_ptr)
+ *content_ptr = content;
+}
+
+/* useful for modules: set RTSP callback function */
+
+void rtsp_set_callback(FFRTSPCallback *rtsp_cb)
+{
+ ff_rtsp_callback = rtsp_cb;
+}
+
+
+/* close and free RTSP streams */
+static void rtsp_close_streams(RTSPState *rt)
+{
+ int i;
+ RTSPStream *rtsp_st;
+
+ for(i=0;i<rt->nb_rtsp_streams;i++) {
+ rtsp_st = rt->rtsp_streams[i];
+ if (rtsp_st) {
+ if (rtsp_st->rtp_ctx)
+ rtp_parse_close(rtsp_st->rtp_ctx);
+ if (rtsp_st->rtp_handle)
+ url_close(rtsp_st->rtp_handle);
+ if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context)
+ rtsp_st->dynamic_handler->close(rtsp_st->dynamic_protocol_context);
+ }
+ av_free(rtsp_st);
+ }
+ av_free(rt->rtsp_streams);
+}
+
+static int rtsp_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ RTSPState *rt = s->priv_data;
+ char host[1024], path[1024], tcpname[1024], cmd[2048];
+ URLContext *rtsp_hd;
+ int port, i, j, ret, err;
+ RTSPHeader reply1, *reply = &reply1;
+ unsigned char *content = NULL;
+ RTSPStream *rtsp_st;
+ int protocol_mask;
+ AVStream *st;
+
+ /* extract hostname and port */
+ url_split(NULL, 0, NULL, 0,
+ host, sizeof(host), &port, path, sizeof(path), s->filename);
+ if (port < 0)
+ port = RTSP_DEFAULT_PORT;
+
+ /* open the tcp connexion */
+ snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port);
+ if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0)
+ return AVERROR_IO;
+ rt->rtsp_hd = rtsp_hd;
+ rt->seq = 0;
+
+ /* describe the stream */
+ snprintf(cmd, sizeof(cmd),
+ "DESCRIBE %s RTSP/1.0\r\n"
+ "Accept: application/sdp\r\n",
+ s->filename);
+ rtsp_send_cmd(s, cmd, reply, &content);
+ if (!content) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ if (reply->status_code != RTSP_STATUS_OK) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
+ /* now we got the SDP description, we parse it */
+ ret = sdp_parse(s, (const char *)content);
+ av_freep(&content);
+ if (ret < 0) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
+ protocol_mask = rtsp_default_protocols;
+
+ /* for each stream, make the setup request */
+ /* XXX: we assume the same server is used for the control of each
+ RTSP stream */
+
+ for(j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
+ char transport[2048];
+
+ rtsp_st = rt->rtsp_streams[i];
+
+ /* compute available transports */
+ transport[0] = '\0';
+
+ /* RTP/UDP */
+ if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP)) {
+ char buf[256];
+
+ /* first try in specified port range */
+ if (RTSP_RTP_PORT_MIN != 0) {
+ while(j <= RTSP_RTP_PORT_MAX) {
+ snprintf(buf, sizeof(buf), "rtp://?localport=%d", j);
+ if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0) {
+ j += 2; /* we will use two port by rtp stream (rtp and rtcp) */
+ goto rtp_opened;
+ }
+ }
+ }
+
+/* then try on any port
+** if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) {
+** err = AVERROR_INVALIDDATA;
+** goto fail;
+** }
+*/
+
+ rtp_opened:
+ port = rtp_get_local_port(rtsp_st->rtp_handle);
+ if (transport[0] != '\0')
+ pstrcat(transport, sizeof(transport), ",");
+ snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,
+ "RTP/AVP/UDP;unicast;client_port=%d-%d",
+ port, port + 1);
+ }
+
+ /* RTP/TCP */
+ else if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_TCP)) {
+ if (transport[0] != '\0')
+ pstrcat(transport, sizeof(transport), ",");
+ snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,
+ "RTP/AVP/TCP");
+ }
+
+ else if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST)) {
+ if (transport[0] != '\0')
+ pstrcat(transport, sizeof(transport), ",");
+ snprintf(transport + strlen(transport),
+ sizeof(transport) - strlen(transport) - 1,
+ "RTP/AVP/UDP;multicast");
+ }
+ snprintf(cmd, sizeof(cmd),
+ "SETUP %s RTSP/1.0\r\n"
+ "Transport: %s\r\n",
+ rtsp_st->control_url, transport);
+ rtsp_send_cmd(s, cmd, reply, NULL);
+ if (reply->status_code != RTSP_STATUS_OK ||
+ reply->nb_transports != 1) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
+ /* XXX: same protocol for all streams is required */
+ if (i > 0) {
+ if (reply->transports[0].protocol != rt->protocol) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ } else {
+ rt->protocol = reply->transports[0].protocol;
+ }
+
+ /* close RTP connection if not choosen */
+ if (reply->transports[0].protocol != RTSP_PROTOCOL_RTP_UDP &&
+ (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP))) {
+ url_close(rtsp_st->rtp_handle);
+ rtsp_st->rtp_handle = NULL;
+ }
+
+ switch(reply->transports[0].protocol) {
+ case RTSP_PROTOCOL_RTP_TCP:
+ rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
+ rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
+ break;
+
+ case RTSP_PROTOCOL_RTP_UDP:
+ {
+ char url[1024];
+
+ /* XXX: also use address if specified */
+ snprintf(url, sizeof(url), "rtp://%s:%d",
+ host, reply->transports[0].server_port_min);
+ if (rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ }
+ break;
+ case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
+ {
+ char url[1024];
+ int ttl;
+
+ ttl = reply->transports[0].ttl;
+ if (!ttl)
+ ttl = 16;
+ snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d",
+ host,
+ reply->transports[0].server_port_min,
+ ttl);
+ if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ }
+ break;
+ }
+ /* open the RTP context */
+ st = NULL;
+ if (rtsp_st->stream_index >= 0)
+ st = s->streams[rtsp_st->stream_index];
+ if (!st)
+ s->ctx_flags |= AVFMTCTX_NOHEADER;
+ rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->rtp_handle, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data);
+
+ if (!rtsp_st->rtp_ctx) {
+ err = AVERROR_NOMEM;
+ goto fail;
+ } else {
+ if(rtsp_st->dynamic_handler) {
+ rtsp_st->rtp_ctx->dynamic_protocol_context= rtsp_st->dynamic_protocol_context;
+ rtsp_st->rtp_ctx->parse_packet= rtsp_st->dynamic_handler->parse_packet;
+ }
+ }
+ }
+
+ /* use callback if available to extend setup */
+ if (ff_rtsp_callback) {
+ if (ff_rtsp_callback(RTSP_ACTION_CLIENT_SETUP, rt->session_id,
+ NULL, 0, rt->last_reply) < 0) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ }
+
+
+ rt->state = RTSP_STATE_IDLE;
+ rt->seek_timestamp = 0; /* default is to start stream at position
+ zero */
+ if (ap->initial_pause) {
+ /* do not start immediately */
+ } else {
+ if (rtsp_read_play(s) < 0) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ }
+ return 0;
+ fail:
+ rtsp_close_streams(rt);
+ av_freep(&content);
+ url_close(rt->rtsp_hd);
+ return err;
+}
+
+static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
+ uint8_t *buf, int buf_size)
+{
+ RTSPState *rt = s->priv_data;
+ int id, len, i, ret;
+ RTSPStream *rtsp_st;
+
+#ifdef DEBUG_RTP_TCP
+ printf("tcp_read_packet:\n");
+#endif
+ redo:
+ for(;;) {
+ ret = url_readbuf(rt->rtsp_hd, buf, 1);
+#ifdef DEBUG_RTP_TCP
+ printf("ret=%d c=%02x [%c]\n", ret, buf[0], buf[0]);
+#endif
+ if (ret != 1)
+ return -1;
+ if (buf[0] == '$')
+ break;
+ }
+ ret = url_readbuf(rt->rtsp_hd, buf, 3);
+ if (ret != 3)
+ return -1;
+ id = buf[0];
+ len = (buf[1] << 8) | buf[2];
+#ifdef DEBUG_RTP_TCP
+ printf("id=%d len=%d\n", id, len);
+#endif
+ if (len > buf_size || len < 12)
+ goto redo;
+ /* get the data */
+ ret = url_readbuf(rt->rtsp_hd, buf, len);
+ if (ret != len)
+ return -1;
+
+ /* find the matching stream */
+ for(i = 0; i < rt->nb_rtsp_streams; i++) {
+ rtsp_st = rt->rtsp_streams[i];
+ if (id >= rtsp_st->interleaved_min &&
+ id <= rtsp_st->interleaved_max)
+ goto found;
+ }
+ goto redo;
+ found:
+ *prtsp_st = rtsp_st;
+ return len;
+}
+
+static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
+ uint8_t *buf, int buf_size)
+{
+ RTSPState *rt = s->priv_data;
+ RTSPStream *rtsp_st;
+ fd_set rfds;
+ int fd1, fd2, fd_max, n, i, ret;
+ struct timeval tv;
+
+ for(;;) {
+ if (url_interrupt_cb())
+ return -1;
+ FD_ZERO(&rfds);
+ fd_max = -1;
+ for(i = 0; i < rt->nb_rtsp_streams; i++) {
+ rtsp_st = rt->rtsp_streams[i];
+ /* currently, we cannot probe RTCP handle because of blocking restrictions */
+ rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2);
+ if (fd1 > fd_max)
+ fd_max = fd1;
+ FD_SET(fd1, &rfds);
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 100 * 1000;
+ n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
+ if (n > 0) {
+ for(i = 0; i < rt->nb_rtsp_streams; i++) {
+ rtsp_st = rt->rtsp_streams[i];
+ rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2);
+ if (FD_ISSET(fd1, &rfds)) {
+ ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
+ if (ret > 0) {
+ *prtsp_st = rtsp_st;
+ return ret;
+ }
+ }
+ }
+ }
+ }
+}
+
+static int rtsp_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ RTSPState *rt = s->priv_data;
+ RTSPStream *rtsp_st;
+ int ret, len;
+ uint8_t buf[RTP_MAX_PACKET_LENGTH];
+
+ /* get next frames from the same RTP packet */
+ if (rt->cur_rtp) {
+ ret = rtp_parse_packet(rt->cur_rtp, pkt, NULL, 0);
+ if (ret == 0) {
+ rt->cur_rtp = NULL;
+ return 0;
+ } else if (ret == 1) {
+ return 0;
+ } else {
+ rt->cur_rtp = NULL;
+ }
+ }
+
+ /* read next RTP packet */
+ redo:
+ switch(rt->protocol) {
+ default:
+ case RTSP_PROTOCOL_RTP_TCP:
+ len = tcp_read_packet(s, &rtsp_st, buf, sizeof(buf));
+ break;
+ case RTSP_PROTOCOL_RTP_UDP:
+ case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
+ len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf));
+ if (rtsp_st->rtp_ctx)
+ rtp_check_and_send_back_rr(rtsp_st->rtp_ctx, len);
+ break;
+ }
+ if (len < 0)
+ return AVERROR_IO;
+ ret = rtp_parse_packet(rtsp_st->rtp_ctx, pkt, buf, len);
+ if (ret < 0)
+ goto redo;
+ if (ret == 1) {
+ /* more packets may follow, so we save the RTP context */
+ rt->cur_rtp = rtsp_st->rtp_ctx;
+ }
+ return 0;
+}
+
+static int rtsp_read_play(AVFormatContext *s)
+{
+ RTSPState *rt = s->priv_data;
+ RTSPHeader reply1, *reply = &reply1;
+ char cmd[1024];
+
+ av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state);
+
+ if (rt->state == RTSP_STATE_PAUSED) {
+ snprintf(cmd, sizeof(cmd),
+ "PLAY %s RTSP/1.0\r\n",
+ s->filename);
+ } else {
+ snprintf(cmd, sizeof(cmd),
+ "PLAY %s RTSP/1.0\r\n"
+ "Range: npt=%0.3f-\r\n",
+ s->filename,
+ (double)rt->seek_timestamp / AV_TIME_BASE);
+ }
+ rtsp_send_cmd(s, cmd, reply, NULL);
+ if (reply->status_code != RTSP_STATUS_OK) {
+ return -1;
+ } else {
+ rt->state = RTSP_STATE_PLAYING;
+ return 0;
+ }
+}
+
+/* pause the stream */
+static int rtsp_read_pause(AVFormatContext *s)
+{
+ RTSPState *rt = s->priv_data;
+ RTSPHeader reply1, *reply = &reply1;
+ char cmd[1024];
+
+ rt = s->priv_data;
+
+ if (rt->state != RTSP_STATE_PLAYING)
+ return 0;
+
+ snprintf(cmd, sizeof(cmd),
+ "PAUSE %s RTSP/1.0\r\n",
+ s->filename);
+ rtsp_send_cmd(s, cmd, reply, NULL);
+ if (reply->status_code != RTSP_STATUS_OK) {
+ return -1;
+ } else {
+ rt->state = RTSP_STATE_PAUSED;
+ return 0;
+ }
+}
+
+static int rtsp_read_seek(AVFormatContext *s, int stream_index,
+ int64_t timestamp, int flags)
+{
+ RTSPState *rt = s->priv_data;
+
+ rt->seek_timestamp = timestamp;
+ switch(rt->state) {
+ default:
+ case RTSP_STATE_IDLE:
+ break;
+ case RTSP_STATE_PLAYING:
+ if (rtsp_read_play(s) != 0)
+ return -1;
+ break;
+ case RTSP_STATE_PAUSED:
+ rt->state = RTSP_STATE_IDLE;
+ break;
+ }
+ return 0;
+}
+
+static int rtsp_read_close(AVFormatContext *s)
+{
+ RTSPState *rt = s->priv_data;
+ RTSPHeader reply1, *reply = &reply1;
+ char cmd[1024];
+
+#if 0
+ /* NOTE: it is valid to flush the buffer here */
+ if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) {
+ url_fclose(&rt->rtsp_gb);
+ }
+#endif
+ snprintf(cmd, sizeof(cmd),
+ "TEARDOWN %s RTSP/1.0\r\n",
+ s->filename);
+ rtsp_send_cmd(s, cmd, reply, NULL);
+
+ if (ff_rtsp_callback) {
+ ff_rtsp_callback(RTSP_ACTION_CLIENT_TEARDOWN, rt->session_id,
+ NULL, 0, NULL);
+ }
+
+ rtsp_close_streams(rt);
+ url_close(rt->rtsp_hd);
+ return 0;
+}
+
+AVInputFormat rtsp_demuxer = {
+ "rtsp",
+ "RTSP input format",
+ sizeof(RTSPState),
+ rtsp_probe,
+ rtsp_read_header,
+ rtsp_read_packet,
+ rtsp_read_close,
+ rtsp_read_seek,
+ .flags = AVFMT_NOFILE,
+ .read_play = rtsp_read_play,
+ .read_pause = rtsp_read_pause,
+};
+
+static int sdp_probe(AVProbeData *p1)
+{
+ const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;
+
+ /* we look for a line beginning "c=IN IP4" */
+ while (p < p_end && *p != '\0') {
+ if (p + sizeof("c=IN IP4") - 1 < p_end && strstart(p, "c=IN IP4", NULL))
+ return AVPROBE_SCORE_MAX / 2;
+
+ while(p < p_end - 1 && *p != '\n') p++;
+ if (++p >= p_end)
+ break;
+ if (*p == '\r')
+ p++;
+ }
+ return 0;
+}
+
+#define SDP_MAX_SIZE 8192
+
+static int sdp_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ RTSPState *rt = s->priv_data;
+ RTSPStream *rtsp_st;
+ int size, i, err;
+ char *content;
+ char url[1024];
+ AVStream *st;
+
+ /* read the whole sdp file */
+ /* XXX: better loading */
+ content = av_malloc(SDP_MAX_SIZE);
+ size = get_buffer(&s->pb, content, SDP_MAX_SIZE - 1);
+ if (size <= 0) {
+ av_free(content);
+ return AVERROR_INVALIDDATA;
+ }
+ content[size] ='\0';
+
+ sdp_parse(s, content);
+ av_free(content);
+
+ /* open each RTP stream */
+ for(i=0;i<rt->nb_rtsp_streams;i++) {
+ rtsp_st = rt->rtsp_streams[i];
+
+ snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d",
+ inet_ntoa(rtsp_st->sdp_ip),
+ rtsp_st->sdp_port,
+ rtsp_st->sdp_ttl);
+ if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ /* open the RTP context */
+ st = NULL;
+ if (rtsp_st->stream_index >= 0)
+ st = s->streams[rtsp_st->stream_index];
+ if (!st)
+ s->ctx_flags |= AVFMTCTX_NOHEADER;
+ rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->rtp_handle, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data);
+ if (!rtsp_st->rtp_ctx) {
+ err = AVERROR_NOMEM;
+ goto fail;
+ } else {
+ if(rtsp_st->dynamic_handler) {
+ rtsp_st->rtp_ctx->dynamic_protocol_context= rtsp_st->dynamic_protocol_context;
+ rtsp_st->rtp_ctx->parse_packet= rtsp_st->dynamic_handler->parse_packet;
+ }
+ }
+ }
+ return 0;
+ fail:
+ rtsp_close_streams(rt);
+ return err;
+}
+
+static int sdp_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ return rtsp_read_packet(s, pkt);
+}
+
+static int sdp_read_close(AVFormatContext *s)
+{
+ RTSPState *rt = s->priv_data;
+ rtsp_close_streams(rt);
+ return 0;
+}
+
+#ifdef CONFIG_SDP_DEMUXER
+AVInputFormat sdp_demuxer = {
+ "sdp",
+ "SDP",
+ sizeof(RTSPState),
+ sdp_probe,
+ sdp_read_header,
+ sdp_read_packet,
+ sdp_read_close,
+};
+#endif
+
+/* dummy redirector format (used directly in av_open_input_file now) */
+static int redir_probe(AVProbeData *pd)
+{
+ const char *p;
+ p = pd->buf;
+ while (redir_isspace(*p))
+ p++;
+ if (strstart(p, "http://", NULL) ||
+ strstart(p, "rtsp://", NULL))
+ return AVPROBE_SCORE_MAX;
+ return 0;
+}
+
+/* called from utils.c */
+int redir_open(AVFormatContext **ic_ptr, ByteIOContext *f)
+{
+ char buf[4096], *q;
+ int c;
+ AVFormatContext *ic = NULL;
+
+ /* parse each URL and try to open it */
+ c = url_fgetc(f);
+ while (c != URL_EOF) {
+ /* skip spaces */
+ for(;;) {
+ if (!redir_isspace(c))
+ break;
+ c = url_fgetc(f);
+ }
+ if (c == URL_EOF)
+ break;
+ /* record url */
+ q = buf;
+ for(;;) {
+ if (c == URL_EOF || redir_isspace(c))
+ break;
+ if ((q - buf) < sizeof(buf) - 1)
+ *q++ = c;
+ c = url_fgetc(f);
+ }
+ *q = '\0';
+ //printf("URL='%s'\n", buf);
+ /* try to open the media file */
+ if (av_open_input_file(&ic, buf, NULL, 0, NULL) == 0)
+ break;
+ }
+ *ic_ptr = ic;
+ if (!ic)
+ return AVERROR_IO;
+ else
+ return 0;
+}
+
+AVInputFormat redir_demuxer = {
+ "redir",
+ "Redirector format",
+ 0,
+ redir_probe,
+ NULL,
+ NULL,
+ NULL,
+};
diff --git a/contrib/ffmpeg/libavformat/rtsp.h b/contrib/ffmpeg/libavformat/rtsp.h
new file mode 100644
index 000000000..c08aaa6ac
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rtsp.h
@@ -0,0 +1,98 @@
+/*
+ * RTSP definitions
+ * 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
+ */
+#ifndef RTSP_H
+#define RTSP_H
+
+/* RTSP handling */
+enum RTSPStatusCode {
+#define DEF(n, c, s) c = n,
+#include "rtspcodes.h"
+#undef DEF
+};
+
+enum RTSPProtocol {
+ RTSP_PROTOCOL_RTP_UDP = 0,
+ RTSP_PROTOCOL_RTP_TCP = 1,
+ RTSP_PROTOCOL_RTP_UDP_MULTICAST = 2,
+};
+
+#define RTSP_DEFAULT_PORT 554
+#define RTSP_MAX_TRANSPORTS 8
+#define RTSP_TCP_MAX_PACKET_SIZE 1472
+#define RTSP_DEFAULT_NB_AUDIO_CHANNELS 2
+#define RTSP_DEFAULT_AUDIO_SAMPLERATE 44100
+#define RTSP_RTP_PORT_MIN 5000
+#define RTSP_RTP_PORT_MAX 10000
+
+typedef struct RTSPTransportField {
+ int interleaved_min, interleaved_max; /* interleave ids, if TCP transport */
+ int port_min, port_max; /* RTP ports */
+ int client_port_min, client_port_max; /* RTP ports */
+ int server_port_min, server_port_max; /* RTP ports */
+ int ttl; /* ttl value */
+ uint32_t destination; /* destination IP address */
+ enum RTSPProtocol protocol;
+} RTSPTransportField;
+
+typedef struct RTSPHeader {
+ int content_length;
+ enum RTSPStatusCode status_code; /* response code from server */
+ int nb_transports;
+ /* in AV_TIME_BASE unit, AV_NOPTS_VALUE if not used */
+ int64_t range_start, range_end;
+ RTSPTransportField transports[RTSP_MAX_TRANSPORTS];
+ int seq; /* sequence number */
+ char session_id[512];
+} RTSPHeader;
+
+/* the callback can be used to extend the connection setup/teardown step */
+enum RTSPCallbackAction {
+ RTSP_ACTION_SERVER_SETUP,
+ RTSP_ACTION_SERVER_TEARDOWN,
+ RTSP_ACTION_CLIENT_SETUP,
+ RTSP_ACTION_CLIENT_TEARDOWN,
+};
+
+typedef struct RTSPActionServerSetup {
+ uint32_t ipaddr;
+ char transport_option[512];
+} RTSPActionServerSetup;
+
+typedef int FFRTSPCallback(enum RTSPCallbackAction action,
+ const char *session_id,
+ char *buf, int buf_size,
+ void *arg);
+
+void rtsp_set_callback(FFRTSPCallback *rtsp_cb);
+
+int rtsp_init(void);
+void rtsp_parse_line(RTSPHeader *reply, const char *buf);
+
+extern int rtsp_default_protocols;
+extern int rtsp_rtp_port_min;
+extern int rtsp_rtp_port_max;
+extern FFRTSPCallback *ff_rtsp_callback;
+extern AVInputFormat rtsp_demuxer;
+
+int rtsp_pause(AVFormatContext *s);
+int rtsp_resume(AVFormatContext *s);
+
+#endif /* RTSP_H */
diff --git a/contrib/ffmpeg/libavformat/rtspcodes.h b/contrib/ffmpeg/libavformat/rtspcodes.h
new file mode 100644
index 000000000..f7aab31c9
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/rtspcodes.h
@@ -0,0 +1,31 @@
+/*
+ * RTSP definitions
+ * 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
+ */
+DEF(200, RTSP_STATUS_OK, "OK")
+DEF(405, RTSP_STATUS_METHOD, "Method Not Allowed")
+DEF(453, RTSP_STATUS_BANDWIDTH, "Not Enough Bandwidth")
+DEF(454, RTSP_STATUS_SESSION, "Session Not Found")
+DEF(455, RTSP_STATUS_STATE, "Method Not Valid in This State")
+DEF(459, RTSP_STATUS_AGGREGATE, "Aggregate operation not allowed")
+DEF(460, RTSP_STATUS_ONLY_AGGREGATE, "Only aggregate operation allowed")
+DEF(461, RTSP_STATUS_TRANSPORT, "Unsupported transport")
+DEF(500, RTSP_STATUS_INTERNAL, "Internal Server Error")
+DEF(503, RTSP_STATUS_SERVICE, "Service Unavailable")
+DEF(505, RTSP_STATUS_VERSION, "RTSP Version not supported")
diff --git a/contrib/ffmpeg/libavformat/segafilm.c b/contrib/ffmpeg/libavformat/segafilm.c
new file mode 100644
index 000000000..4feb97262
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/segafilm.c
@@ -0,0 +1,310 @@
+/*
+ * Sega FILM Format (CPK) Demuxer
+ * 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 segafilm.c
+ * Sega FILM (.cpk) file demuxer
+ * by Mike Melanson (melanson@pcisys.net)
+ * For more information regarding the Sega FILM file format, visit:
+ * http://www.pcisys.net/~melanson/codecs/
+ */
+
+#include "avformat.h"
+
+#define FILM_TAG MKBETAG('F', 'I', 'L', 'M')
+#define FDSC_TAG MKBETAG('F', 'D', 'S', 'C')
+#define STAB_TAG MKBETAG('S', 'T', 'A', 'B')
+#define CVID_TAG MKBETAG('c', 'v', 'i', 'd')
+
+typedef struct {
+ int stream;
+ offset_t sample_offset;
+ unsigned int sample_size;
+ int64_t pts;
+ int keyframe;
+} film_sample_t;
+
+typedef struct FilmDemuxContext {
+ int video_stream_index;
+ int audio_stream_index;
+
+ unsigned int audio_type;
+ unsigned int audio_samplerate;
+ unsigned int audio_bits;
+ unsigned int audio_channels;
+
+ unsigned int video_type;
+ unsigned int sample_count;
+ film_sample_t *sample_table;
+ unsigned int current_sample;
+
+ unsigned int base_clock;
+ unsigned int version;
+ int cvid_extra_bytes; /* the number of bytes thrown into the Cinepak
+ * chunk header to throw off decoders */
+
+ /* buffer used for interleaving stereo PCM data */
+ unsigned char *stereo_buffer;
+ int stereo_buffer_size;
+} FilmDemuxContext;
+
+static int film_probe(AVProbeData *p)
+{
+ if (p->buf_size < 4)
+ return 0;
+
+ if (BE_32(&p->buf[0]) != FILM_TAG)
+ return 0;
+
+ return AVPROBE_SCORE_MAX;
+}
+
+static int film_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ FilmDemuxContext *film = (FilmDemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVStream *st;
+ unsigned char scratch[256];
+ int i;
+ unsigned int data_offset;
+ unsigned int audio_frame_counter;
+
+ film->sample_table = NULL;
+ film->stereo_buffer = NULL;
+ film->stereo_buffer_size = 0;
+
+ /* load the main FILM header */
+ if (get_buffer(pb, scratch, 16) != 16)
+ return AVERROR_IO;
+ data_offset = BE_32(&scratch[4]);
+ film->version = BE_32(&scratch[8]);
+
+ /* load the FDSC chunk */
+ if (film->version == 0) {
+ /* special case for Lemmings .film files; 20-byte header */
+ if (get_buffer(pb, scratch, 20) != 20)
+ return AVERROR_IO;
+ /* make some assumptions about the audio parameters */
+ film->audio_type = CODEC_ID_PCM_S8;
+ film->audio_samplerate = 22050;
+ film->audio_channels = 1;
+ film->audio_bits = 8;
+ } else {
+ /* normal Saturn .cpk files; 32-byte header */
+ if (get_buffer(pb, scratch, 32) != 32)
+ return AVERROR_IO;
+ film->audio_samplerate = BE_16(&scratch[24]);;
+ film->audio_channels = scratch[21];
+ film->audio_bits = scratch[22];
+ if (film->audio_bits == 8)
+ film->audio_type = CODEC_ID_PCM_S8;
+ else if (film->audio_bits == 16)
+ film->audio_type = CODEC_ID_PCM_S16BE;
+ else
+ film->audio_type = 0;
+ }
+
+ if (BE_32(&scratch[0]) != FDSC_TAG)
+ return AVERROR_INVALIDDATA;
+
+ film->cvid_extra_bytes = 0;
+ if (BE_32(&scratch[8]) == CVID_TAG) {
+ film->video_type = CODEC_ID_CINEPAK;
+ if (film->version)
+ film->cvid_extra_bytes = 2;
+ else
+ film->cvid_extra_bytes = 6; /* Lemmings 3DO case */
+ } else
+ film->video_type = 0;
+
+ /* initialize the decoder streams */
+ if (film->video_type) {
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ film->video_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = film->video_type;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->width = BE_32(&scratch[16]);
+ st->codec->height = BE_32(&scratch[12]);
+ }
+
+ if (film->audio_type) {
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ film->audio_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = film->audio_type;
+ st->codec->codec_tag = 1;
+ st->codec->channels = film->audio_channels;
+ st->codec->bits_per_sample = film->audio_bits;
+ st->codec->sample_rate = film->audio_samplerate;
+ st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
+ st->codec->bits_per_sample;
+ st->codec->block_align = st->codec->channels *
+ st->codec->bits_per_sample / 8;
+ }
+
+ /* load the sample table */
+ if (get_buffer(pb, scratch, 16) != 16)
+ return AVERROR_IO;
+ if (BE_32(&scratch[0]) != STAB_TAG)
+ return AVERROR_INVALIDDATA;
+ film->base_clock = BE_32(&scratch[8]);
+ film->sample_count = BE_32(&scratch[12]);
+ if(film->sample_count >= UINT_MAX / sizeof(film_sample_t))
+ return -1;
+ film->sample_table = av_malloc(film->sample_count * sizeof(film_sample_t));
+
+ for(i=0; i<s->nb_streams; i++)
+ av_set_pts_info(s->streams[i], 33, 1, film->base_clock);
+
+ audio_frame_counter = 0;
+ for (i = 0; i < film->sample_count; i++) {
+ /* load the next sample record and transfer it to an internal struct */
+ if (get_buffer(pb, scratch, 16) != 16) {
+ av_free(film->sample_table);
+ return AVERROR_IO;
+ }
+ film->sample_table[i].sample_offset =
+ data_offset + BE_32(&scratch[0]);
+ film->sample_table[i].sample_size = BE_32(&scratch[4]);
+ if (BE_32(&scratch[8]) == 0xFFFFFFFF) {
+ film->sample_table[i].stream = film->audio_stream_index;
+ film->sample_table[i].pts = audio_frame_counter;
+ film->sample_table[i].pts *= film->base_clock;
+ film->sample_table[i].pts /= film->audio_samplerate;
+
+ audio_frame_counter += (film->sample_table[i].sample_size /
+ (film->audio_channels * film->audio_bits / 8));
+ } else {
+ film->sample_table[i].stream = film->video_stream_index;
+ film->sample_table[i].pts = BE_32(&scratch[8]) & 0x7FFFFFFF;
+ film->sample_table[i].keyframe = (scratch[8] & 0x80) ? 0 : 1;
+ }
+ }
+
+ film->current_sample = 0;
+
+ return 0;
+}
+
+static int film_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ FilmDemuxContext *film = (FilmDemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ film_sample_t *sample;
+ int ret = 0;
+ int i;
+ int left, right;
+
+ if (film->current_sample >= film->sample_count)
+ return AVERROR_IO;
+
+ sample = &film->sample_table[film->current_sample];
+
+ /* position the stream (will probably be there anyway) */
+ url_fseek(pb, sample->sample_offset, SEEK_SET);
+
+ /* do a special song and dance when loading FILM Cinepak chunks */
+ if ((sample->stream == film->video_stream_index) &&
+ (film->video_type == CODEC_ID_CINEPAK)) {
+ if (av_new_packet(pkt, sample->sample_size - film->cvid_extra_bytes))
+ return AVERROR_NOMEM;
+ if(pkt->size < 10)
+ return -1;
+ pkt->pos= url_ftell(pb);
+ ret = get_buffer(pb, pkt->data, 10);
+ /* skip the non-spec CVID bytes */
+ url_fseek(pb, film->cvid_extra_bytes, SEEK_CUR);
+ ret += get_buffer(pb, pkt->data + 10,
+ sample->sample_size - 10 - film->cvid_extra_bytes);
+ if (ret != sample->sample_size - film->cvid_extra_bytes)
+ ret = AVERROR_IO;
+ } else if ((sample->stream == film->audio_stream_index) &&
+ (film->audio_channels == 2)) {
+ /* stereo PCM needs to be interleaved */
+
+ if (av_new_packet(pkt, sample->sample_size))
+ return AVERROR_NOMEM;
+
+ /* make sure the interleave buffer is large enough */
+ if (sample->sample_size > film->stereo_buffer_size) {
+ av_free(film->stereo_buffer);
+ film->stereo_buffer_size = sample->sample_size;
+ film->stereo_buffer = av_malloc(film->stereo_buffer_size);
+ }
+
+ pkt->pos= url_ftell(pb);
+ ret = get_buffer(pb, film->stereo_buffer, sample->sample_size);
+ if (ret != sample->sample_size)
+ ret = AVERROR_IO;
+
+ left = 0;
+ right = sample->sample_size / 2;
+ for (i = 0; i < sample->sample_size; ) {
+ if (film->audio_bits == 8) {
+ pkt->data[i++] = film->stereo_buffer[left++];
+ pkt->data[i++] = film->stereo_buffer[right++];
+ } else {
+ pkt->data[i++] = film->stereo_buffer[left++];
+ pkt->data[i++] = film->stereo_buffer[left++];
+ pkt->data[i++] = film->stereo_buffer[right++];
+ pkt->data[i++] = film->stereo_buffer[right++];
+ }
+ }
+ } else {
+ ret= av_get_packet(pb, pkt, sample->sample_size);
+ if (ret != sample->sample_size)
+ ret = AVERROR_IO;
+ }
+
+ pkt->stream_index = sample->stream;
+ pkt->pts = sample->pts;
+
+ film->current_sample++;
+
+ return ret;
+}
+
+static int film_read_close(AVFormatContext *s)
+{
+ FilmDemuxContext *film = (FilmDemuxContext *)s->priv_data;
+
+ av_free(film->sample_table);
+ av_free(film->stereo_buffer);
+
+ return 0;
+}
+
+AVInputFormat segafilm_demuxer = {
+ "film_cpk",
+ "Sega FILM/CPK format",
+ sizeof(FilmDemuxContext),
+ film_probe,
+ film_read_header,
+ film_read_packet,
+ film_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/sgi.c b/contrib/ffmpeg/libavformat/sgi.c
new file mode 100644
index 000000000..bf0297e81
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/sgi.c
@@ -0,0 +1,460 @@
+/*
+ * SGI image format
+ * Todd Kirby <doubleshot@pacbell.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 "avformat.h"
+#include "avio.h"
+
+/* #define DEBUG */
+
+/* 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
+
+#define SGI_SINGLE_CHAN 2
+#define SGI_MULTI_CHAN 3
+
+typedef struct SGIInfo{
+ short magic;
+ char rle;
+ char bytes_per_channel;
+ unsigned short dimension;
+ unsigned short xsize;
+ unsigned short ysize;
+ unsigned short zsize;
+} SGIInfo;
+
+
+static int sgi_probe(AVProbeData *pd)
+{
+ /* test for sgi magic */
+ if (pd->buf_size >= 2 && BE_16(&pd->buf[0]) == SGI_MAGIC) {
+ return AVPROBE_SCORE_MAX;
+ } else {
+ return 0;
+ }
+}
+
+/* read sgi header fields */
+static void read_sgi_header(ByteIOContext *f, SGIInfo *info)
+{
+ info->magic = (unsigned short) get_be16(f);
+ info->rle = get_byte(f);
+ info->bytes_per_channel = get_byte(f);
+ info->dimension = (unsigned short)get_be16(f);
+ info->xsize = (unsigned short) get_be16(f);
+ info->ysize = (unsigned short) get_be16(f);
+ info->zsize = (unsigned short) get_be16(f);
+
+ if(info->zsize > 4096)
+ info->zsize= 0;
+
+#ifdef DEBUG
+ printf("sgi header fields:\n");
+ printf(" magic: %d\n", info->magic);
+ printf(" rle: %d\n", info->rle);
+ printf(" bpc: %d\n", info->bytes_per_channel);
+ printf(" dim: %d\n", info->dimension);
+ printf(" xsize: %d\n", info->xsize);
+ printf(" ysize: %d\n", info->ysize);
+ printf(" zsize: %d\n", info->zsize);
+#endif
+
+ return;
+}
+
+
+/* read an uncompressed sgi image */
+static int read_uncompressed_sgi(const SGIInfo *si,
+ AVPicture *pict, ByteIOContext *f)
+{
+ int x, y, z, chan_offset, ret = 0;
+ uint8_t *dest_row;
+
+ /* skip header */
+ url_fseek(f, SGI_HEADER_SIZE, SEEK_SET);
+
+ pict->linesize[0] = si->xsize;
+
+ for (z = 0; z < si->zsize; z++) {
+
+#ifndef WORDS_BIGENDIAN
+ /* rgba -> bgra for rgba32 on little endian cpus */
+ if (si->zsize == 4 && z != 3)
+ chan_offset = 2 - z;
+ else
+#endif
+ chan_offset = z;
+
+ for (y = si->ysize - 1; y >= 0; y--) {
+ dest_row = pict->data[0] + (y * si->xsize * si->zsize);
+
+ for (x = 0; x < si->xsize; x++) {
+ dest_row[chan_offset] = get_byte(f);
+ dest_row += si->zsize;
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+/* expand an rle row into a channel */
+static int expand_rle_row(ByteIOContext *f, unsigned char *optr,
+ int chan_offset, int pixelstride)
+{
+ unsigned char pixel, count;
+ int length = 0;
+
+#ifndef WORDS_BIGENDIAN
+ /* rgba -> bgra for rgba32 on little endian cpus */
+ if (pixelstride == 4 && chan_offset != 3) {
+ chan_offset = 2 - chan_offset;
+ }
+#endif
+
+ optr += chan_offset;
+
+ while (1) {
+ pixel = get_byte(f);
+
+ if (!(count = (pixel & 0x7f))) {
+ return length;
+ }
+ if (pixel & 0x80) {
+ while (count--) {
+ *optr = get_byte(f);
+ length++;
+ optr += pixelstride;
+ }
+ } else {
+ pixel = get_byte(f);
+
+ while (count--) {
+ *optr = pixel;
+ length++;
+ optr += pixelstride;
+ }
+ }
+ }
+}
+
+
+/* read a run length encoded sgi image */
+static int read_rle_sgi(const SGIInfo *sgi_info,
+ AVPicture *pict, ByteIOContext *f)
+{
+ uint8_t *dest_row;
+ unsigned long *start_table;
+ int y, z, xsize, ysize, zsize, tablen;
+ long start_offset;
+ int ret = 0;
+
+ xsize = sgi_info->xsize;
+ ysize = sgi_info->ysize;
+ zsize = sgi_info->zsize;
+
+ /* skip header */
+ url_fseek(f, SGI_HEADER_SIZE, SEEK_SET);
+
+ /* size of rle offset and length tables */
+ tablen = ysize * zsize * sizeof(long);
+
+ start_table = (unsigned long *)av_malloc(tablen);
+
+ if (!get_buffer(f, (uint8_t *)start_table, tablen)) {
+ ret = AVERROR_IO;
+ goto fail;
+ }
+
+ /* skip run length table */
+ url_fseek(f, tablen, SEEK_CUR);
+
+ for (z = 0; z < zsize; z++) {
+ for (y = 0; y < ysize; y++) {
+ dest_row = pict->data[0] + (ysize - 1 - y) * (xsize * zsize);
+
+ start_offset = BE_32(&start_table[y + z * ysize]);
+
+ /* don't seek if already at the next rle start offset */
+ if (url_ftell(f) != start_offset) {
+ url_fseek(f, start_offset, SEEK_SET);
+ }
+
+ if (expand_rle_row(f, dest_row, z, zsize) != xsize) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ }
+ }
+
+fail:
+ av_free(start_table);
+
+ return ret;
+}
+
+
+static int sgi_read(ByteIOContext *f,
+ int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
+{
+ SGIInfo sgi_info, *s = &sgi_info;
+ AVImageInfo info1, *info = &info1;
+ int ret;
+
+ read_sgi_header(f, s);
+
+ if (s->bytes_per_channel != 1) {
+ return AVERROR_INVALIDDATA;
+ }
+
+ /* check for supported image dimensions */
+ if (s->dimension != 2 && s->dimension != 3) {
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (s->zsize == SGI_GRAYSCALE) {
+ info->pix_fmt = PIX_FMT_GRAY8;
+ } else if (s->zsize == SGI_RGB) {
+ info->pix_fmt = PIX_FMT_RGB24;
+ } else if (s->zsize == SGI_RGBA) {
+ info->pix_fmt = PIX_FMT_RGBA32;
+ } else {
+ return AVERROR_INVALIDDATA;
+ }
+
+ info->width = s->xsize;
+ info->height = s->ysize;
+
+ ret = alloc_cb(opaque, info);
+ if (ret)
+ return ret;
+
+ if (s->rle) {
+ return read_rle_sgi(s, &info->pict, f);
+ } else {
+ return read_uncompressed_sgi(s, &info->pict, f);
+ }
+
+ return 0; /* not reached */
+}
+
+#ifdef CONFIG_MUXERS
+static void write_sgi_header(ByteIOContext *f, const SGIInfo *info)
+{
+ int i;
+
+ put_be16(f, SGI_MAGIC);
+ put_byte(f, info->rle);
+ put_byte(f, info->bytes_per_channel);
+ put_be16(f, info->dimension);
+ put_be16(f, info->xsize);
+ put_be16(f, info->ysize);
+ put_be16(f, info->zsize);
+
+ /* The rest are constant in this implementation */
+ put_be32(f, 0L); /* pixmin */
+ put_be32(f, 255L); /* pixmax */
+ put_be32(f, 0L); /* dummy */
+
+ /* name */
+ for (i = 0; i < 80; i++) {
+ put_byte(f, 0);
+ }
+
+ put_be32(f, 0L); /* colormap */
+
+ /* The rest of the 512 byte header is unused. */
+ for (i = 0; i < 404; i++) {
+ put_byte(f, 0);
+ }
+}
+
+
+static int rle_row(ByteIOContext *f, char *row, int stride, int rowsize)
+{
+ int length, count, i, x;
+ char *start, repeat = 0;
+
+ for (x = rowsize, length = 0; x > 0;) {
+ start = row;
+ row += (2 * stride);
+ x -= 2;
+
+ while (x > 0 && (row[-2 * stride] != row[-1 * stride] ||
+ row[-1 * stride] != row[0])) {
+ row += stride;
+ x--;
+ };
+
+ row -= (2 * stride);
+ x += 2;
+
+ count = (row - start) / stride;
+ while (count > 0) {
+ i = count > 126 ? 126 : count;
+ count -= i;
+
+ put_byte(f, 0x80 | i);
+ length++;
+
+ while (i > 0) {
+ put_byte(f, *start);
+ start += stride;
+ i--;
+ length++;
+ };
+ };
+
+ if (x <= 0) {
+ break;
+ }
+
+ start = row;
+ repeat = row[0];
+
+ row += stride;
+ x--;
+
+ while (x > 0 && *row == repeat) {
+ row += stride;
+ x--;
+ };
+
+ count = (row - start) / stride;
+ while (count > 0) {
+ i = count > 126 ? 126 : count;
+ count -= i;
+
+ put_byte(f, i);
+ length++;
+
+ put_byte(f, repeat);
+ length++;
+ };
+ };
+
+ length++;
+
+ put_byte(f, 0);
+ return (length);
+}
+
+
+static int sgi_write(ByteIOContext *pb, AVImageInfo *info)
+{
+ SGIInfo sgi_info, *si = &sgi_info;
+ long *offsettab, *lengthtab;
+ int i, y, z;
+ int tablesize, chan_offset;
+ uint8_t *srcrow;
+
+ si->xsize = info->width;
+ si->ysize = info->height;
+ si->rle = 1;
+ si->bytes_per_channel = 1;
+
+ switch(info->pix_fmt) {
+ case PIX_FMT_GRAY8:
+ si->dimension = SGI_SINGLE_CHAN;
+ si->zsize = SGI_GRAYSCALE;
+ break;
+ case PIX_FMT_RGB24:
+ si->dimension = SGI_MULTI_CHAN;
+ si->zsize = SGI_RGB;
+ break;
+ case PIX_FMT_RGBA32:
+ si->dimension = SGI_MULTI_CHAN;
+ si->zsize = SGI_RGBA;
+ break;
+ default:
+ return AVERROR_INVALIDDATA;
+ }
+
+ write_sgi_header(pb, si);
+
+ tablesize = si->zsize * si->ysize * sizeof(long);
+
+ /* skip rle offset and length tables, write them at the end. */
+ url_fseek(pb, tablesize * 2, SEEK_CUR);
+ put_flush_packet(pb);
+
+ lengthtab = av_malloc(tablesize);
+ offsettab = av_malloc(tablesize);
+
+ for (z = 0; z < si->zsize; z++) {
+
+#ifndef WORDS_BIGENDIAN
+ /* rgba -> bgra for rgba32 on little endian cpus */
+ if (si->zsize == 4 && z != 3)
+ chan_offset = 2 - z;
+ else
+#endif
+ chan_offset = z;
+
+ srcrow = info->pict.data[0] + chan_offset;
+
+ for (y = si->ysize -1; y >= 0; y--) {
+ offsettab[(z * si->ysize) + y] = url_ftell(pb);
+ lengthtab[(z * si->ysize) + y] = rle_row(pb, srcrow,
+ si->zsize, si->xsize);
+ srcrow += info->pict.linesize[0];
+ }
+ }
+
+ url_fseek(pb, 512, SEEK_SET);
+
+ /* write offset table */
+ for (i = 0; i < (si->ysize * si->zsize); i++) {
+ put_be32(pb, offsettab[i]);
+ }
+
+ /* write length table */
+ for (i = 0; i < (si->ysize * si->zsize); i++) {
+ put_be32(pb, lengthtab[i]);
+ }
+
+ put_flush_packet(pb);
+
+ av_free(lengthtab);
+ av_free(offsettab);
+
+ return 0;
+}
+#endif // CONFIG_MUXERS
+
+AVImageFormat sgi_image_format = {
+ "sgi",
+ "sgi,rgb,rgba,bw",
+ sgi_probe,
+ sgi_read,
+ (1 << PIX_FMT_GRAY8) | (1 << PIX_FMT_RGB24) | (1 << PIX_FMT_RGBA32),
+#ifdef CONFIG_MUXERS
+ sgi_write,
+#else
+ NULL,
+#endif // CONFIG_MUXERS
+};
diff --git a/contrib/ffmpeg/libavformat/sierravmd.c b/contrib/ffmpeg/libavformat/sierravmd.c
new file mode 100644
index 000000000..92dbce91d
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/sierravmd.c
@@ -0,0 +1,302 @@
+/*
+ * Sierra VMD Format Demuxer
+ * 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 sierravmd.c
+ * Sierra VMD file demuxer
+ * by Vladimir "VAG" Gneushev (vagsoft at mail.ru)
+ * for more information on the Sierra VMD file format, visit:
+ * http://www.pcisys.net/~melanson/codecs/
+ */
+
+#include "avformat.h"
+
+#define VMD_HEADER_SIZE 0x0330
+#define BYTES_PER_FRAME_RECORD 16
+
+typedef struct {
+ int stream_index;
+ offset_t frame_offset;
+ unsigned int frame_size;
+ int64_t pts;
+ int keyframe;
+ unsigned char frame_record[BYTES_PER_FRAME_RECORD];
+} vmd_frame_t;
+
+typedef struct VmdDemuxContext {
+ int video_stream_index;
+ int audio_stream_index;
+
+ unsigned int frame_count;
+ unsigned int frames_per_block;
+ vmd_frame_t *frame_table;
+ unsigned int current_frame;
+
+ int sample_rate;
+ int64_t audio_sample_counter;
+ int skiphdr;
+
+ unsigned char vmd_header[VMD_HEADER_SIZE];
+} VmdDemuxContext;
+
+static int vmd_probe(AVProbeData *p)
+{
+ if (p->buf_size < 2)
+ return 0;
+
+ /* check if the first 2 bytes of the file contain the appropriate size
+ * of a VMD header chunk */
+ if (LE_16(&p->buf[0]) != VMD_HEADER_SIZE - 2)
+ return 0;
+
+ /* only return half certainty since this check is a bit sketchy */
+ return AVPROBE_SCORE_MAX / 2;
+}
+
+static int vmd_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ VmdDemuxContext *vmd = (VmdDemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVStream *st, *vst;
+ unsigned int toc_offset;
+ unsigned char *raw_frame_table;
+ int raw_frame_table_size;
+ offset_t current_offset;
+ int i, j;
+ unsigned int total_frames;
+ int64_t pts_inc = 1;
+ int64_t current_video_pts = 0, current_audio_pts = 0;
+ unsigned char chunk[BYTES_PER_FRAME_RECORD];
+ int num, den;
+ int sound_buffers;
+
+ /* fetch the main header, including the 2 header length bytes */
+ url_fseek(pb, 0, SEEK_SET);
+ if (get_buffer(pb, vmd->vmd_header, VMD_HEADER_SIZE) != VMD_HEADER_SIZE)
+ return AVERROR_IO;
+
+ /* start up the decoders */
+ vst = av_new_stream(s, 0);
+ if (!vst)
+ return AVERROR_NOMEM;
+ av_set_pts_info(vst, 33, 1, 10);
+ vmd->video_stream_index = vst->index;
+ vst->codec->codec_type = CODEC_TYPE_VIDEO;
+ vst->codec->codec_id = CODEC_ID_VMDVIDEO;
+ vst->codec->codec_tag = 0; /* no fourcc */
+ vst->codec->width = LE_16(&vmd->vmd_header[12]);
+ vst->codec->height = LE_16(&vmd->vmd_header[14]);
+ vst->codec->extradata_size = VMD_HEADER_SIZE;
+ vst->codec->extradata = av_mallocz(VMD_HEADER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
+ memcpy(vst->codec->extradata, vmd->vmd_header, VMD_HEADER_SIZE);
+
+ /* if sample rate is 0, assume no audio */
+ vmd->sample_rate = LE_16(&vmd->vmd_header[804]);
+ if (vmd->sample_rate) {
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ vmd->audio_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_VMDAUDIO;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->channels = (vmd->vmd_header[811] & 0x80) ? 2 : 1;
+ st->codec->sample_rate = vmd->sample_rate;
+ st->codec->block_align = LE_16(&vmd->vmd_header[806]);
+ if (st->codec->block_align & 0x8000) {
+ st->codec->bits_per_sample = 16;
+ st->codec->block_align = -(st->codec->block_align - 0x10000);
+ } else {
+ st->codec->bits_per_sample = 8;
+ }
+ st->codec->bit_rate = st->codec->sample_rate *
+ st->codec->bits_per_sample * st->codec->channels;
+
+ /* calculate pts */
+ num = st->codec->block_align;
+ den = st->codec->sample_rate * st->codec->channels;
+ av_reduce(&den, &num, den, num, (1UL<<31)-1);
+ av_set_pts_info(vst, 33, num, den);
+ av_set_pts_info(st, 33, num, den);
+ pts_inc = num;
+ }
+
+ toc_offset = LE_32(&vmd->vmd_header[812]);
+ vmd->frame_count = LE_16(&vmd->vmd_header[6]);
+ vmd->frames_per_block = LE_16(&vmd->vmd_header[18]);
+ url_fseek(pb, toc_offset, SEEK_SET);
+
+ raw_frame_table = NULL;
+ vmd->frame_table = NULL;
+ sound_buffers = LE_16(&vmd->vmd_header[808]);
+ raw_frame_table_size = vmd->frame_count * 6;
+ raw_frame_table = av_malloc(raw_frame_table_size);
+ if(vmd->frame_count * vmd->frames_per_block >= UINT_MAX / sizeof(vmd_frame_t)){
+ av_log(s, AV_LOG_ERROR, "vmd->frame_count * vmd->frames_per_block too large\n");
+ return -1;
+ }
+ vmd->frame_table = av_malloc((vmd->frame_count * vmd->frames_per_block + sound_buffers) * sizeof(vmd_frame_t));
+ if (!raw_frame_table || !vmd->frame_table) {
+ av_free(raw_frame_table);
+ av_free(vmd->frame_table);
+ return AVERROR_NOMEM;
+ }
+ if (get_buffer(pb, raw_frame_table, raw_frame_table_size) !=
+ raw_frame_table_size) {
+ av_free(raw_frame_table);
+ av_free(vmd->frame_table);
+ return AVERROR_IO;
+ }
+
+ total_frames = 0;
+ for (i = 0; i < vmd->frame_count; i++) {
+
+ current_offset = LE_32(&raw_frame_table[6 * i + 2]);
+
+ /* handle each entry in index block */
+ for (j = 0; j < vmd->frames_per_block; j++) {
+ int type;
+ uint32_t size;
+
+ get_buffer(pb, chunk, BYTES_PER_FRAME_RECORD);
+ type = chunk[0];
+ size = LE_32(&chunk[2]);
+ if(!size)
+ continue;
+ switch(type) {
+ case 1: /* Audio Chunk */
+ /* first audio chunk contains several audio buffers */
+ if(current_audio_pts){
+ vmd->frame_table[total_frames].frame_offset = current_offset;
+ vmd->frame_table[total_frames].stream_index = vmd->audio_stream_index;
+ vmd->frame_table[total_frames].frame_size = size;
+ memcpy(vmd->frame_table[total_frames].frame_record, chunk, BYTES_PER_FRAME_RECORD);
+ vmd->frame_table[total_frames].pts = current_audio_pts;
+ total_frames++;
+ current_audio_pts += pts_inc;
+ }else{
+ uint32_t flags;
+ int k;
+ int noff;
+ int64_t pos;
+
+ pos = url_ftell(pb);
+ url_fseek(pb, current_offset, SEEK_SET);
+ flags = get_le32(pb);
+ noff = 4;
+ url_fseek(pb, pos, SEEK_SET);
+ av_log(s, AV_LOG_DEBUG, "Sound mapping = %08X (%i bufs)\n", flags, sound_buffers);
+ for(k = 0; k < sound_buffers - 1; k++){
+ if(flags & 1) { /* silent block */
+ vmd->frame_table[total_frames].frame_size = 0;
+ }else{
+ vmd->frame_table[total_frames].frame_size = st->codec->block_align + (st->codec->block_align & 1);
+ }
+ noff += vmd->frame_table[total_frames].frame_size;
+ vmd->frame_table[total_frames].frame_offset = current_offset + noff;
+ vmd->frame_table[total_frames].stream_index = vmd->audio_stream_index;
+ memcpy(vmd->frame_table[total_frames].frame_record, chunk, BYTES_PER_FRAME_RECORD);
+ vmd->frame_table[total_frames].pts = current_audio_pts;
+ total_frames++;
+ current_audio_pts += pts_inc;
+ flags >>= 1;
+ }
+ }
+ break;
+ case 2: /* Video Chunk */
+ vmd->frame_table[total_frames].frame_offset = current_offset;
+ vmd->frame_table[total_frames].stream_index = vmd->video_stream_index;
+ vmd->frame_table[total_frames].frame_size = size;
+ memcpy(vmd->frame_table[total_frames].frame_record, chunk, BYTES_PER_FRAME_RECORD);
+ vmd->frame_table[total_frames].pts = current_video_pts;
+ total_frames++;
+ break;
+ }
+ current_offset += size;
+ }
+ current_video_pts += pts_inc;
+ }
+
+ av_free(raw_frame_table);
+
+ vmd->current_frame = 0;
+ vmd->frame_count = total_frames;
+
+ return 0;
+}
+
+static int vmd_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ VmdDemuxContext *vmd = (VmdDemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int ret = 0;
+ vmd_frame_t *frame;
+
+ if (vmd->current_frame >= vmd->frame_count)
+ return AVERROR_IO;
+
+ frame = &vmd->frame_table[vmd->current_frame];
+ /* position the stream (will probably be there already) */
+ url_fseek(pb, frame->frame_offset, SEEK_SET);
+
+ if (av_new_packet(pkt, frame->frame_size + BYTES_PER_FRAME_RECORD))
+ return AVERROR_NOMEM;
+ pkt->pos= url_ftell(pb);
+ memcpy(pkt->data, frame->frame_record, BYTES_PER_FRAME_RECORD);
+ ret = get_buffer(pb, pkt->data + BYTES_PER_FRAME_RECORD,
+ frame->frame_size);
+
+ if (ret != frame->frame_size) {
+ av_free_packet(pkt);
+ ret = AVERROR_IO;
+ }
+ pkt->stream_index = frame->stream_index;
+ pkt->pts = frame->pts;
+ av_log(NULL, AV_LOG_INFO, " dispatching %s frame with %d bytes and pts %"PRId64"\n",
+ (frame->frame_record[0] == 0x02) ? "video" : "audio",
+ frame->frame_size + BYTES_PER_FRAME_RECORD,
+ pkt->pts);
+
+ vmd->current_frame++;
+
+ return ret;
+}
+
+static int vmd_read_close(AVFormatContext *s)
+{
+ VmdDemuxContext *vmd = (VmdDemuxContext *)s->priv_data;
+
+ av_free(vmd->frame_table);
+
+ return 0;
+}
+
+AVInputFormat vmd_demuxer = {
+ "vmd",
+ "Sierra VMD format",
+ sizeof(VmdDemuxContext),
+ vmd_probe,
+ vmd_read_header,
+ vmd_read_packet,
+ vmd_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/smacker.c b/contrib/ffmpeg/libavformat/smacker.c
new file mode 100644
index 000000000..a08bd2d9f
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/smacker.c
@@ -0,0 +1,345 @@
+/*
+ * Smacker demuxer
+ * 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
+ */
+
+/*
+ * Based on http://wiki.multimedia.cx/index.php?title=Smacker
+ */
+
+#include "avformat.h"
+#include "riff.h"
+#include "bswap.h"
+
+#define SMACKER_PAL 0x01
+
+enum SAudFlags {
+ SMK_AUD_PACKED = 0x80000000,
+ SMK_AUD_16BITS = 0x20000000,
+ SMK_AUD_STEREO = 0x10000000,
+ SMK_AUD_BINKAUD = 0x08000000,
+ SMK_AUD_USEDCT = 0x04000000
+};
+
+typedef struct SmackerContext {
+ /* Smacker file header */
+ uint32_t magic;
+ uint32_t width, height;
+ uint32_t frames;
+ int pts_inc;
+ uint32_t flags;
+ uint32_t audio[7];
+ uint32_t treesize;
+ uint32_t mmap_size, mclr_size, full_size, type_size;
+ uint32_t rates[7];
+ uint32_t pad;
+ /* frame info */
+ uint32_t *frm_size;
+ uint8_t *frm_flags;
+ /* internal variables */
+ int cur_frame;
+ int is_ver4;
+ int64_t cur_pts;
+ /* current frame for demuxing */
+ uint8_t pal[768];
+ int indexes[7];
+ int videoindex;
+ uint8_t *bufs[7];
+ int buf_sizes[7];
+ int stream_id[7];
+ int curstream;
+ offset_t nextpos;
+ int64_t aud_pts[7];
+} SmackerContext;
+
+typedef struct SmackerFrame {
+ int64_t pts;
+ int stream;
+} SmackerFrame;
+
+/* palette used in Smacker */
+static const uint8_t smk_pal[64] = {
+ 0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C,
+ 0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C,
+ 0x41, 0x45, 0x49, 0x4D, 0x51, 0x55, 0x59, 0x5D,
+ 0x61, 0x65, 0x69, 0x6D, 0x71, 0x75, 0x79, 0x7D,
+ 0x82, 0x86, 0x8A, 0x8E, 0x92, 0x96, 0x9A, 0x9E,
+ 0xA2, 0xA6, 0xAA, 0xAE, 0xB2, 0xB6, 0xBA, 0xBE,
+ 0xC3, 0xC7, 0xCB, 0xCF, 0xD3, 0xD7, 0xDB, 0xDF,
+ 0xE3, 0xE7, 0xEB, 0xEF, 0xF3, 0xF7, 0xFB, 0xFF
+};
+
+
+static int smacker_probe(AVProbeData *p)
+{
+ if (p->buf_size < 4)
+ return 0;
+ if(p->buf[0] == 'S' && p->buf[1] == 'M' && p->buf[2] == 'K'
+ && (p->buf[3] == '2' || p->buf[3] == '4'))
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+static int smacker_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ ByteIOContext *pb = &s->pb;
+ SmackerContext *smk = (SmackerContext *)s->priv_data;
+ AVStream *st, *ast[7];
+ int i, ret;
+ int tbase;
+
+ /* read and check header */
+ smk->magic = get_le32(pb);
+ if (smk->magic != MKTAG('S', 'M', 'K', '2') && smk->magic != MKTAG('S', 'M', 'K', '4'))
+ return -1;
+ smk->width = get_le32(pb);
+ smk->height = get_le32(pb);
+ smk->frames = get_le32(pb);
+ smk->pts_inc = (int32_t)get_le32(pb);
+ smk->flags = get_le32(pb);
+ for(i = 0; i < 7; i++)
+ smk->audio[i] = get_le32(pb);
+ smk->treesize = get_le32(pb);
+
+ if(smk->treesize >= UINT_MAX/4){ // smk->treesize + 16 must not overflow (this check is probably redundant)
+ av_log(s, AV_LOG_ERROR, "treesize too large\n");
+ return -1;
+ }
+
+//FIXME remove extradata "rebuilding"
+ smk->mmap_size = get_le32(pb);
+ smk->mclr_size = get_le32(pb);
+ smk->full_size = get_le32(pb);
+ smk->type_size = get_le32(pb);
+ for(i = 0; i < 7; i++)
+ smk->rates[i] = get_le32(pb);
+ smk->pad = get_le32(pb);
+ /* setup data */
+ if(smk->frames > 0xFFFFFF) {
+ av_log(s, AV_LOG_ERROR, "Too many frames: %i\n", smk->frames);
+ return -1;
+ }
+ smk->frm_size = av_malloc(smk->frames * 4);
+ smk->frm_flags = av_malloc(smk->frames);
+
+ smk->is_ver4 = (smk->magic != MKTAG('S', 'M', 'K', '2'));
+
+ /* read frame info */
+ for(i = 0; i < smk->frames; i++) {
+ smk->frm_size[i] = get_le32(pb);
+ }
+ for(i = 0; i < smk->frames; i++) {
+ smk->frm_flags[i] = get_byte(pb);
+ }
+
+ /* init video codec */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return -1;
+ smk->videoindex = st->index;
+ st->codec->width = smk->width;
+ st->codec->height = smk->height;
+ st->codec->pix_fmt = PIX_FMT_PAL8;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_SMACKVIDEO;
+ st->codec->codec_tag = smk->magic;
+ /* Smacker uses 100000 as internal timebase */
+ if(smk->pts_inc < 0)
+ smk->pts_inc = -smk->pts_inc;
+ else
+ smk->pts_inc *= 100;
+ tbase = 100000;
+ av_reduce(&tbase, &smk->pts_inc, tbase, smk->pts_inc, (1UL<<31)-1);
+ av_set_pts_info(st, 33, smk->pts_inc, tbase);
+ /* handle possible audio streams */
+ for(i = 0; i < 7; i++) {
+ smk->indexes[i] = -1;
+ if((smk->rates[i] & 0xFFFFFF) && !(smk->rates[i] & SMK_AUD_BINKAUD)){
+ ast[i] = av_new_stream(s, 0);
+ smk->indexes[i] = ast[i]->index;
+ ast[i]->codec->codec_type = CODEC_TYPE_AUDIO;
+ ast[i]->codec->codec_id = (smk->rates[i] & SMK_AUD_PACKED) ? CODEC_ID_SMACKAUDIO : CODEC_ID_PCM_U8;
+ ast[i]->codec->codec_tag = MKTAG('S', 'M', 'K', 'A');
+ ast[i]->codec->channels = (smk->rates[i] & SMK_AUD_STEREO) ? 2 : 1;
+ ast[i]->codec->sample_rate = smk->rates[i] & 0xFFFFFF;
+ ast[i]->codec->bits_per_sample = (smk->rates[i] & SMK_AUD_16BITS) ? 16 : 8;
+ if(ast[i]->codec->bits_per_sample == 16 && ast[i]->codec->codec_id == CODEC_ID_PCM_U8)
+ ast[i]->codec->codec_id = CODEC_ID_PCM_S16LE;
+ av_set_pts_info(ast[i], 64, 1, ast[i]->codec->sample_rate
+ * ast[i]->codec->channels * ast[i]->codec->bits_per_sample / 8);
+ }
+ }
+
+
+ /* load trees to extradata, they will be unpacked by decoder */
+ st->codec->extradata = av_malloc(smk->treesize + 16);
+ st->codec->extradata_size = smk->treesize + 16;
+ if(!st->codec->extradata){
+ av_log(s, AV_LOG_ERROR, "Cannot allocate %i bytes of extradata\n", smk->treesize + 16);
+ av_free(smk->frm_size);
+ av_free(smk->frm_flags);
+ return -1;
+ }
+ ret = get_buffer(pb, st->codec->extradata + 16, st->codec->extradata_size - 16);
+ if(ret != st->codec->extradata_size - 16){
+ av_free(smk->frm_size);
+ av_free(smk->frm_flags);
+ return AVERROR_IO;
+ }
+ ((int32_t*)st->codec->extradata)[0] = le2me_32(smk->mmap_size);
+ ((int32_t*)st->codec->extradata)[1] = le2me_32(smk->mclr_size);
+ ((int32_t*)st->codec->extradata)[2] = le2me_32(smk->full_size);
+ ((int32_t*)st->codec->extradata)[3] = le2me_32(smk->type_size);
+
+ smk->curstream = -1;
+ smk->nextpos = url_ftell(pb);
+
+ return 0;
+}
+
+
+static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ SmackerContext *smk = (SmackerContext *)s->priv_data;
+ int flags;
+ int ret;
+ int i;
+ int frame_size = 0;
+ int palchange = 0;
+ int pos;
+
+ if (url_feof(&s->pb) || smk->cur_frame >= smk->frames)
+ return -EIO;
+
+ /* if we demuxed all streams, pass another frame */
+ if(smk->curstream < 0) {
+ url_fseek(&s->pb, smk->nextpos, 0);
+ frame_size = smk->frm_size[smk->cur_frame] & (~3);
+ flags = smk->frm_flags[smk->cur_frame];
+ /* handle palette change event */
+ pos = url_ftell(&s->pb);
+ if(flags & SMACKER_PAL){
+ int size, sz, t, off, j, pos;
+ uint8_t *pal = smk->pal;
+ uint8_t oldpal[768];
+
+ memcpy(oldpal, pal, 768);
+ size = get_byte(&s->pb);
+ size = size * 4 - 1;
+ frame_size -= size;
+ frame_size--;
+ sz = 0;
+ pos = url_ftell(&s->pb) + size;
+ while(sz < 256){
+ t = get_byte(&s->pb);
+ if(t & 0x80){ /* skip palette entries */
+ sz += (t & 0x7F) + 1;
+ pal += ((t & 0x7F) + 1) * 3;
+ } else if(t & 0x40){ /* copy with offset */
+ off = get_byte(&s->pb) * 3;
+ j = (t & 0x3F) + 1;
+ while(j-- && sz < 256) {
+ *pal++ = oldpal[off + 0];
+ *pal++ = oldpal[off + 1];
+ *pal++ = oldpal[off + 2];
+ sz++;
+ off += 3;
+ }
+ } else { /* new entries */
+ *pal++ = smk_pal[t];
+ *pal++ = smk_pal[get_byte(&s->pb) & 0x3F];
+ *pal++ = smk_pal[get_byte(&s->pb) & 0x3F];
+ sz++;
+ }
+ }
+ url_fseek(&s->pb, pos, 0);
+ palchange |= 1;
+ }
+ flags >>= 1;
+ smk->curstream = -1;
+ /* if audio chunks are present, put them to stack and retrieve later */
+ for(i = 0; i < 7; i++) {
+ if(flags & 1) {
+ int size;
+ size = get_le32(&s->pb) - 4;
+ frame_size -= size;
+ frame_size -= 4;
+ smk->curstream++;
+ smk->bufs[smk->curstream] = av_realloc(smk->bufs[smk->curstream], size);
+ smk->buf_sizes[smk->curstream] = size;
+ ret = get_buffer(&s->pb, smk->bufs[smk->curstream], size);
+ if(ret != size)
+ return AVERROR_IO;
+ smk->stream_id[smk->curstream] = smk->indexes[i];
+ }
+ flags >>= 1;
+ }
+ if (av_new_packet(pkt, frame_size + 768))
+ return AVERROR_NOMEM;
+ if(smk->frm_size[smk->cur_frame] & 1)
+ palchange |= 2;
+ pkt->data[0] = palchange;
+ memcpy(pkt->data + 1, smk->pal, 768);
+ ret = get_buffer(&s->pb, pkt->data + 769, frame_size);
+ if(ret != frame_size)
+ return AVERROR_IO;
+ pkt->stream_index = smk->videoindex;
+ pkt->size = ret + 769;
+ smk->cur_frame++;
+ smk->nextpos = url_ftell(&s->pb);
+ } else {
+ if (av_new_packet(pkt, smk->buf_sizes[smk->curstream]))
+ return AVERROR_NOMEM;
+ memcpy(pkt->data, smk->bufs[smk->curstream], smk->buf_sizes[smk->curstream]);
+ pkt->size = smk->buf_sizes[smk->curstream];
+ pkt->stream_index = smk->stream_id[smk->curstream];
+ pkt->pts = smk->aud_pts[smk->curstream];
+ smk->aud_pts[smk->curstream] += LE_32(pkt->data);
+ smk->curstream--;
+ }
+
+ return 0;
+}
+
+static int smacker_read_close(AVFormatContext *s)
+{
+ SmackerContext *smk = (SmackerContext *)s->priv_data;
+ int i;
+
+ for(i = 0; i < 7; i++)
+ if(smk->bufs[i])
+ av_free(smk->bufs[i]);
+ if(smk->frm_size)
+ av_free(smk->frm_size);
+ if(smk->frm_flags)
+ av_free(smk->frm_flags);
+
+ return 0;
+}
+
+AVInputFormat smacker_demuxer = {
+ "smk",
+ "Smacker Video",
+ sizeof(SmackerContext),
+ smacker_probe,
+ smacker_read_header,
+ smacker_read_packet,
+ smacker_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/sol.c b/contrib/ffmpeg/libavformat/sol.c
new file mode 100644
index 000000000..20e45f75d
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/sol.c
@@ -0,0 +1,160 @@
+/*
+ * Sierra SOL demuxer
+ * Copyright 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
+ */
+
+/*
+ * Based on documents from Game Audio Player and own research
+ */
+
+#include "avformat.h"
+#include "allformats.h"
+#include "riff.h"
+#include "bswap.h"
+
+/* if we don't know the size in advance */
+#define AU_UNKOWN_SIZE ((uint32_t)(~0))
+
+static int sol_probe(AVProbeData *p)
+{
+ /* check file header */
+ uint16_t magic;
+ if (p->buf_size <= 14)
+ return 0;
+ magic=le2me_16(*((uint16_t*)p->buf));
+ if ((magic == 0x0B8D || magic == 0x0C0D || magic == 0x0C8D) &&
+ p->buf[2] == 'S' && p->buf[3] == 'O' &&
+ p->buf[4] == 'L' && p->buf[5] == 0)
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+#define SOL_DPCM 1
+#define SOL_16BIT 4
+#define SOL_STEREO 16
+
+static int sol_codec_id(int magic, int type)
+{
+ if (magic == 0x0B8D)
+ {
+ if (type & SOL_DPCM) return CODEC_ID_SOL_DPCM;
+ else return CODEC_ID_PCM_U8;
+ }
+ if (type & SOL_DPCM)
+ {
+ if (type & SOL_16BIT) return CODEC_ID_SOL_DPCM;
+ else if (magic == 0x0C8D) return CODEC_ID_SOL_DPCM;
+ else return CODEC_ID_SOL_DPCM;
+ }
+ if (type & SOL_16BIT) return CODEC_ID_PCM_S16LE;
+ return CODEC_ID_PCM_U8;
+}
+
+static int sol_codec_type(int magic, int type)
+{
+ if (magic == 0x0B8D) return 1;//SOL_DPCM_OLD;
+ if (type & SOL_DPCM)
+ {
+ if (type & SOL_16BIT) return 3;//SOL_DPCM_NEW16;
+ else if (magic == 0x0C8D) return 1;//SOL_DPCM_OLD;
+ else return 2;//SOL_DPCM_NEW8;
+ }
+ return -1;
+}
+
+static int sol_channels(int magic, int type)
+{
+ if (magic == 0x0B8D || !(type & SOL_STEREO)) return 1;
+ return 2;
+}
+
+static int sol_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ int size;
+ unsigned int magic,tag;
+ ByteIOContext *pb = &s->pb;
+ unsigned int id, codec, channels, rate, type;
+ AVStream *st;
+
+ /* check ".snd" header */
+ magic = get_le16(pb);
+ tag = get_le32(pb);
+ if (tag != MKTAG('S', 'O', 'L', 0))
+ return -1;
+ rate = get_le16(pb);
+ type = get_byte(pb);
+ size = get_le32(pb);
+ if (magic != 0x0B8D)
+ get_byte(pb); /* newer SOLs contain padding byte */
+
+ codec = sol_codec_id(magic, type);
+ channels = sol_channels(magic, type);
+
+ if (codec == CODEC_ID_SOL_DPCM)
+ id = sol_codec_type(magic, type);
+ else id = 0;
+
+ /* now we are ready: build format streams */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return -1;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_tag = id;
+ st->codec->codec_id = codec;
+ st->codec->channels = channels;
+ st->codec->sample_rate = rate;
+ av_set_pts_info(st, 64, 1, rate);
+ return 0;
+}
+
+#define MAX_SIZE 4096
+
+static int sol_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ int ret;
+
+ if (url_feof(&s->pb))
+ return -EIO;
+ ret= av_get_packet(&s->pb, pkt, MAX_SIZE);
+ pkt->stream_index = 0;
+
+ /* note: we need to modify the packet size here to handle the last
+ packet */
+ pkt->size = ret;
+ return 0;
+}
+
+static int sol_read_close(AVFormatContext *s)
+{
+ return 0;
+}
+
+AVInputFormat sol_demuxer = {
+ "sol",
+ "Sierra SOL Format",
+ 0,
+ sol_probe,
+ sol_read_header,
+ sol_read_packet,
+ sol_read_close,
+ pcm_read_seek,
+};
diff --git a/contrib/ffmpeg/libavformat/swf.c b/contrib/ffmpeg/libavformat/swf.c
new file mode 100644
index 000000000..6029e3678
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/swf.c
@@ -0,0 +1,944 @@
+/*
+ * Flash Compatible Streaming Format
+ * Copyright (c) 2000 Fabrice Bellard.
+ * Copyright (c) 2003 Tinic Uro.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "avformat.h"
+#include "bitstream.h"
+#include "riff.h" /* for CodecTag */
+
+/* should have a generic way to indicate probable size */
+#define DUMMY_FILE_SIZE (100 * 1024 * 1024)
+#define DUMMY_DURATION 600 /* in seconds */
+
+#define TAG_END 0
+#define TAG_SHOWFRAME 1
+#define TAG_DEFINESHAPE 2
+#define TAG_FREECHARACTER 3
+#define TAG_PLACEOBJECT 4
+#define TAG_REMOVEOBJECT 5
+#define TAG_STREAMHEAD 18
+#define TAG_STREAMBLOCK 19
+#define TAG_JPEG2 21
+#define TAG_PLACEOBJECT2 26
+#define TAG_STREAMHEAD2 45
+#define TAG_VIDEOSTREAM 60
+#define TAG_VIDEOFRAME 61
+
+#define TAG_LONG 0x100
+
+/* flags for shape definition */
+#define FLAG_MOVETO 0x01
+#define FLAG_SETFILL0 0x02
+#define FLAG_SETFILL1 0x04
+
+#define AUDIO_FIFO_SIZE 65536
+
+/* character id used */
+#define BITMAP_ID 0
+#define VIDEO_ID 0
+#define SHAPE_ID 1
+
+#undef NDEBUG
+#include <assert.h>
+
+typedef struct {
+
+ offset_t duration_pos;
+ offset_t tag_pos;
+
+ int samples_per_frame;
+ int sound_samples;
+ int video_samples;
+ int swf_frame_number;
+ int video_frame_number;
+ int ms_per_frame;
+ int ch_id;
+ int tag;
+
+ uint8_t *audio_fifo;
+ int audio_in_pos;
+ int audio_out_pos;
+ int audio_size;
+
+ int video_type;
+ int audio_type;
+} SWFContext;
+
+static const CodecTag swf_codec_tags[] = {
+ {CODEC_ID_FLV1, 0x02},
+ {CODEC_ID_VP6F, 0x04},
+ {0, 0},
+};
+
+static const int sSampleRates[3][4] = {
+ {44100, 48000, 32000, 0},
+ {22050, 24000, 16000, 0},
+ {11025, 12000, 8000, 0},
+};
+
+static const int sBitRates[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}
+ },
+};
+
+static const int sSamplesPerFrame[3][3] =
+{
+ { 384, 1152, 1152 },
+ { 384, 1152, 576 },
+ { 384, 1152, 576 }
+};
+
+static const int sBitsPerSlot[3] = {
+ 32,
+ 8,
+ 8
+};
+
+static int swf_mp3_info(void *data, int *byteSize, int *samplesPerFrame, int *sampleRate, int *isMono )
+{
+ uint8_t *dataTmp = (uint8_t *)data;
+ uint32_t header = ( (uint32_t)dataTmp[0] << 24 ) | ( (uint32_t)dataTmp[1] << 16 ) | ( (uint32_t)dataTmp[2] << 8 ) | (uint32_t)dataTmp[3];
+ int layerID = 3 - ((header >> 17) & 0x03);
+ int bitRateID = ((header >> 12) & 0x0f);
+ int sampleRateID = ((header >> 10) & 0x03);
+ int bitRate = 0;
+ int bitsPerSlot = sBitsPerSlot[layerID];
+ int isPadded = ((header >> 9) & 0x01);
+
+ if ( (( header >> 21 ) & 0x7ff) != 0x7ff ) {
+ return 0;
+ }
+
+ *isMono = ((header >> 6) & 0x03) == 0x03;
+
+ if ( (header >> 19 ) & 0x01 ) {
+ *sampleRate = sSampleRates[0][sampleRateID];
+ bitRate = sBitRates[0][layerID][bitRateID] * 1000;
+ *samplesPerFrame = sSamplesPerFrame[0][layerID];
+ } else {
+ if ( (header >> 20) & 0x01 ) {
+ *sampleRate = sSampleRates[1][sampleRateID];
+ bitRate = sBitRates[1][layerID][bitRateID] * 1000;
+ *samplesPerFrame = sSamplesPerFrame[1][layerID];
+ } else {
+ *sampleRate = sSampleRates[2][sampleRateID];
+ bitRate = sBitRates[1][layerID][bitRateID] * 1000;
+ *samplesPerFrame = sSamplesPerFrame[2][layerID];
+ }
+ }
+
+ *byteSize = ( ( ( ( *samplesPerFrame * (bitRate / bitsPerSlot) ) / *sampleRate ) + isPadded ) );
+
+ return 1;
+}
+
+#ifdef CONFIG_MUXERS
+static void put_swf_tag(AVFormatContext *s, int tag)
+{
+ SWFContext *swf = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+
+ swf->tag_pos = url_ftell(pb);
+ swf->tag = tag;
+ /* reserve some room for the tag */
+ if (tag & TAG_LONG) {
+ put_le16(pb, 0);
+ put_le32(pb, 0);
+ } else {
+ put_le16(pb, 0);
+ }
+}
+
+static void put_swf_end_tag(AVFormatContext *s)
+{
+ SWFContext *swf = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ offset_t pos;
+ int tag_len, tag;
+
+ pos = url_ftell(pb);
+ tag_len = pos - swf->tag_pos - 2;
+ tag = swf->tag;
+ url_fseek(pb, swf->tag_pos, SEEK_SET);
+ if (tag & TAG_LONG) {
+ tag &= ~TAG_LONG;
+ put_le16(pb, (tag << 6) | 0x3f);
+ put_le32(pb, tag_len - 4);
+ } else {
+ assert(tag_len < 0x3f);
+ put_le16(pb, (tag << 6) | tag_len);
+ }
+ url_fseek(pb, pos, SEEK_SET);
+}
+
+static inline void max_nbits(int *nbits_ptr, int val)
+{
+ int n;
+
+ if (val == 0)
+ return;
+ val = abs(val);
+ n = 1;
+ while (val != 0) {
+ n++;
+ val >>= 1;
+ }
+ if (n > *nbits_ptr)
+ *nbits_ptr = n;
+}
+
+static void put_swf_rect(ByteIOContext *pb,
+ int xmin, int xmax, int ymin, int ymax)
+{
+ PutBitContext p;
+ uint8_t buf[256];
+ int nbits, mask;
+
+ init_put_bits(&p, buf, sizeof(buf));
+
+ nbits = 0;
+ max_nbits(&nbits, xmin);
+ max_nbits(&nbits, xmax);
+ max_nbits(&nbits, ymin);
+ max_nbits(&nbits, ymax);
+ mask = (1 << nbits) - 1;
+
+ /* rectangle info */
+ put_bits(&p, 5, nbits);
+ put_bits(&p, nbits, xmin & mask);
+ put_bits(&p, nbits, xmax & mask);
+ put_bits(&p, nbits, ymin & mask);
+ put_bits(&p, nbits, ymax & mask);
+
+ flush_put_bits(&p);
+ put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
+}
+
+static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
+{
+ int nbits, mask;
+
+ put_bits(pb, 1, 1); /* edge */
+ put_bits(pb, 1, 1); /* line select */
+ nbits = 2;
+ max_nbits(&nbits, dx);
+ max_nbits(&nbits, dy);
+
+ mask = (1 << nbits) - 1;
+ put_bits(pb, 4, nbits - 2); /* 16 bits precision */
+ if (dx == 0) {
+ put_bits(pb, 1, 0);
+ put_bits(pb, 1, 1);
+ put_bits(pb, nbits, dy & mask);
+ } else if (dy == 0) {
+ put_bits(pb, 1, 0);
+ put_bits(pb, 1, 0);
+ put_bits(pb, nbits, dx & mask);
+ } else {
+ put_bits(pb, 1, 1);
+ put_bits(pb, nbits, dx & mask);
+ put_bits(pb, nbits, dy & mask);
+ }
+}
+
+#define FRAC_BITS 16
+
+/* put matrix */
+static void put_swf_matrix(ByteIOContext *pb,
+ int a, int b, int c, int d, int tx, int ty)
+{
+ PutBitContext p;
+ uint8_t buf[256];
+ int nbits;
+
+ init_put_bits(&p, buf, sizeof(buf));
+
+ put_bits(&p, 1, 1); /* a, d present */
+ nbits = 1;
+ max_nbits(&nbits, a);
+ max_nbits(&nbits, d);
+ put_bits(&p, 5, nbits); /* nb bits */
+ put_bits(&p, nbits, a);
+ put_bits(&p, nbits, d);
+
+ put_bits(&p, 1, 1); /* b, c present */
+ nbits = 1;
+ max_nbits(&nbits, c);
+ max_nbits(&nbits, b);
+ put_bits(&p, 5, nbits); /* nb bits */
+ put_bits(&p, nbits, c);
+ put_bits(&p, nbits, b);
+
+ nbits = 1;
+ max_nbits(&nbits, tx);
+ max_nbits(&nbits, ty);
+ put_bits(&p, 5, nbits); /* nb bits */
+ put_bits(&p, nbits, tx);
+ put_bits(&p, nbits, ty);
+
+ flush_put_bits(&p);
+ put_buffer(pb, buf, pbBufPtr(&p) - p.buf);
+}
+
+/* */
+static int swf_write_header(AVFormatContext *s)
+{
+ SWFContext *swf;
+ ByteIOContext *pb = &s->pb;
+ AVCodecContext *enc, *audio_enc, *video_enc;
+ PutBitContext p;
+ uint8_t buf1[256];
+ int i, width, height, rate, rate_base;
+
+ swf = av_malloc(sizeof(SWFContext));
+ if (!swf)
+ return -1;
+ s->priv_data = swf;
+
+ swf->ch_id = -1;
+ swf->audio_in_pos = 0;
+ swf->audio_out_pos = 0;
+ swf->audio_size = 0;
+ swf->audio_fifo = av_malloc(AUDIO_FIFO_SIZE);
+ swf->sound_samples = 0;
+ swf->video_samples = 0;
+ swf->swf_frame_number = 0;
+ swf->video_frame_number = 0;
+
+ video_enc = NULL;
+ audio_enc = NULL;
+ for(i=0;i<s->nb_streams;i++) {
+ enc = s->streams[i]->codec;
+ if (enc->codec_type == CODEC_TYPE_AUDIO)
+ audio_enc = enc;
+ else {
+ if ( enc->codec_id == CODEC_ID_VP6F ||
+ enc->codec_id == CODEC_ID_FLV1 ||
+ enc->codec_id == CODEC_ID_MJPEG ) {
+ video_enc = enc;
+ } else {
+ av_log(enc, AV_LOG_ERROR, "SWF only supports VP6, FLV1 and MJPEG\n");
+ return -1;
+ }
+ }
+ }
+
+ if (!video_enc) {
+ /* currenty, cannot work correctly if audio only */
+ swf->video_type = 0;
+ width = 320;
+ height = 200;
+ rate = 10;
+ rate_base= 1;
+ } else {
+ swf->video_type = video_enc->codec_id;
+ width = video_enc->width;
+ height = video_enc->height;
+ rate = video_enc->time_base.den;
+ rate_base = video_enc->time_base.num;
+ }
+
+ if (!audio_enc ) {
+ swf->audio_type = 0;
+ swf->samples_per_frame = ( 44100. * rate_base ) / rate;
+ } else {
+ swf->audio_type = audio_enc->codec_id;
+ swf->samples_per_frame = ( ( audio_enc->sample_rate ) * rate_base ) / rate;
+ }
+
+ put_tag(pb, "FWS");
+ if ( video_enc && video_enc->codec_id == CODEC_ID_VP6F ) {
+ put_byte(pb, 8); /* version (version 8 and above support VP6 codec) */
+ } else if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
+ put_byte(pb, 6); /* version (version 6 and above support FLV1 codec) */
+ } else {
+ put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */
+ }
+ put_le32(pb, DUMMY_FILE_SIZE); /* dummy size
+ (will be patched if not streamed) */
+
+ put_swf_rect(pb, 0, width * 20, 0, height * 20);
+ put_le16(pb, (rate * 256) / rate_base); /* frame rate */
+ swf->duration_pos = url_ftell(pb);
+ put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
+
+ /* define a shape with the jpeg inside */
+ if ( video_enc && (video_enc->codec_id == CODEC_ID_VP6F ||
+ video_enc->codec_id == CODEC_ID_FLV1 )) {
+ } else if ( video_enc && video_enc->codec_id == CODEC_ID_MJPEG ) {
+ put_swf_tag(s, TAG_DEFINESHAPE);
+
+ put_le16(pb, SHAPE_ID); /* ID of shape */
+ /* bounding rectangle */
+ put_swf_rect(pb, 0, width, 0, height);
+ /* style info */
+ put_byte(pb, 1); /* one fill style */
+ put_byte(pb, 0x41); /* clipped bitmap fill */
+ put_le16(pb, BITMAP_ID); /* bitmap ID */
+ /* position of the bitmap */
+ put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
+ 0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
+ put_byte(pb, 0); /* no line style */
+
+ /* shape drawing */
+ init_put_bits(&p, buf1, sizeof(buf1));
+ put_bits(&p, 4, 1); /* one fill bit */
+ put_bits(&p, 4, 0); /* zero line bit */
+
+ put_bits(&p, 1, 0); /* not an edge */
+ put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
+ put_bits(&p, 5, 1); /* nbits */
+ put_bits(&p, 1, 0); /* X */
+ put_bits(&p, 1, 0); /* Y */
+ put_bits(&p, 1, 1); /* set fill style 1 */
+
+ /* draw the rectangle ! */
+ put_swf_line_edge(&p, width, 0);
+ put_swf_line_edge(&p, 0, height);
+ put_swf_line_edge(&p, -width, 0);
+ put_swf_line_edge(&p, 0, -height);
+
+ /* end of shape */
+ put_bits(&p, 1, 0); /* not an edge */
+ put_bits(&p, 5, 0);
+
+ flush_put_bits(&p);
+ put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);
+
+ put_swf_end_tag(s);
+ }
+
+ if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {
+ int v;
+
+ /* start sound */
+ put_swf_tag(s, TAG_STREAMHEAD2);
+
+ v = 0;
+ switch(audio_enc->sample_rate) {
+ case 11025:
+ v |= 1 << 2;
+ break;
+ case 22050:
+ v |= 2 << 2;
+ break;
+ case 44100:
+ v |= 3 << 2;
+ break;
+ default:
+ /* not supported */
+ av_log(s, AV_LOG_ERROR, "swf doesnt support that sample rate, choose from (44100, 22050, 11025)\n");
+ av_free(swf->audio_fifo);
+ av_free(swf);
+ return -1;
+ }
+ v |= 0x02; /* 16 bit playback */
+ if (audio_enc->channels == 2)
+ v |= 0x01; /* stereo playback */
+ put_byte(&s->pb, v);
+ v |= 0x20; /* mp3 compressed */
+ put_byte(&s->pb, v);
+ put_le16(&s->pb, swf->samples_per_frame); /* avg samples per frame */
+ put_le16(&s->pb, 0);
+
+ put_swf_end_tag(s);
+ }
+
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+static int swf_write_video(AVFormatContext *s,
+ AVCodecContext *enc, const uint8_t *buf, int size)
+{
+ SWFContext *swf = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int c = 0;
+ int outSize = 0;
+ int outSamples = 0;
+
+ /* Flash Player limit */
+ if ( swf->swf_frame_number == 16000 ) {
+ av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
+ }
+
+ if ( swf->audio_type ) {
+ /* Prescan audio data for this swf frame */
+retry_swf_audio_packet:
+ if ( ( swf->audio_size-outSize ) >= 4 ) {
+ int mp3FrameSize = 0;
+ int mp3SampleRate = 0;
+ int mp3IsMono = 0;
+ int mp3SamplesPerFrame = 0;
+
+ /* copy out mp3 header from ring buffer */
+ uint8_t header[4];
+ for (c=0; c<4; c++) {
+ header[c] = swf->audio_fifo[(swf->audio_in_pos+outSize+c) % AUDIO_FIFO_SIZE];
+ }
+
+ if ( swf_mp3_info(header,&mp3FrameSize,&mp3SamplesPerFrame,&mp3SampleRate,&mp3IsMono) ) {
+ if ( ( swf->audio_size-outSize ) >= mp3FrameSize ) {
+ outSize += mp3FrameSize;
+ outSamples += mp3SamplesPerFrame;
+ if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
+ goto retry_swf_audio_packet;
+ }
+ }
+ } else {
+ /* invalid mp3 data, skip forward
+ we need to do this since the Flash Player
+ does not like custom headers */
+ swf->audio_in_pos ++;
+ swf->audio_size --;
+ swf->audio_in_pos %= AUDIO_FIFO_SIZE;
+ goto retry_swf_audio_packet;
+ }
+ }
+
+ /* audio stream is behind video stream, bail */
+ if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
+ return 0;
+ }
+ }
+
+ if ( swf->video_type == CODEC_ID_VP6F ||
+ swf->video_type == CODEC_ID_FLV1 ) {
+ if ( swf->video_frame_number == 0 ) {
+ /* create a new video object */
+ put_swf_tag(s, TAG_VIDEOSTREAM);
+ put_le16(pb, VIDEO_ID);
+ put_le16(pb, 15000 ); /* hard flash player limit */
+ put_le16(pb, enc->width);
+ put_le16(pb, enc->height);
+ put_byte(pb, 0);
+ put_byte(pb,codec_get_tag(swf_codec_tags,swf->video_type));
+ put_swf_end_tag(s);
+
+ /* place the video object for the first time */
+ put_swf_tag(s, TAG_PLACEOBJECT2);
+ put_byte(pb, 0x36);
+ put_le16(pb, 1);
+ put_le16(pb, VIDEO_ID);
+ put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
+ put_le16(pb, swf->video_frame_number );
+ put_byte(pb, 'v');
+ put_byte(pb, 'i');
+ put_byte(pb, 'd');
+ put_byte(pb, 'e');
+ put_byte(pb, 'o');
+ put_byte(pb, 0x00);
+ put_swf_end_tag(s);
+ } else {
+ /* mark the character for update */
+ put_swf_tag(s, TAG_PLACEOBJECT2);
+ put_byte(pb, 0x11);
+ put_le16(pb, 1);
+ put_le16(pb, swf->video_frame_number );
+ put_swf_end_tag(s);
+ }
+
+ /* set video frame data */
+ put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
+ put_le16(pb, VIDEO_ID);
+ put_le16(pb, swf->video_frame_number++ );
+ put_buffer(pb, buf, size);
+ put_swf_end_tag(s);
+ } else if ( swf->video_type == CODEC_ID_MJPEG ) {
+ if (swf->swf_frame_number > 0) {
+ /* remove the shape */
+ put_swf_tag(s, TAG_REMOVEOBJECT);
+ put_le16(pb, SHAPE_ID); /* shape ID */
+ put_le16(pb, 1); /* depth */
+ put_swf_end_tag(s);
+
+ /* free the bitmap */
+ put_swf_tag(s, TAG_FREECHARACTER);
+ put_le16(pb, BITMAP_ID);
+ put_swf_end_tag(s);
+ }
+
+ put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
+
+ put_le16(pb, BITMAP_ID); /* ID of the image */
+
+ /* a dummy jpeg header seems to be required */
+ put_byte(pb, 0xff);
+ put_byte(pb, 0xd8);
+ put_byte(pb, 0xff);
+ put_byte(pb, 0xd9);
+ /* write the jpeg image */
+ put_buffer(pb, buf, size);
+
+ put_swf_end_tag(s);
+
+ /* draw the shape */
+
+ put_swf_tag(s, TAG_PLACEOBJECT);
+ put_le16(pb, SHAPE_ID); /* shape ID */
+ put_le16(pb, 1); /* depth */
+ put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
+ put_swf_end_tag(s);
+ } else {
+ /* invalid codec */
+ }
+
+ swf->swf_frame_number ++;
+
+ swf->video_samples += swf->samples_per_frame;
+
+ /* streaming sound always should be placed just before showframe tags */
+ if ( outSize > 0 ) {
+ put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
+ put_le16(pb, outSamples);
+ put_le16(pb, 0);
+ for (c=0; c<outSize; c++) {
+ put_byte(pb,swf->audio_fifo[(swf->audio_in_pos+c) % AUDIO_FIFO_SIZE]);
+ }
+ put_swf_end_tag(s);
+
+ /* update FIFO */
+ swf->sound_samples += outSamples;
+ swf->audio_in_pos += outSize;
+ swf->audio_size -= outSize;
+ swf->audio_in_pos %= AUDIO_FIFO_SIZE;
+ }
+
+ /* output the frame */
+ put_swf_tag(s, TAG_SHOWFRAME);
+ put_swf_end_tag(s);
+
+ put_flush_packet(&s->pb);
+
+ return 0;
+}
+
+static int swf_write_audio(AVFormatContext *s,
+ AVCodecContext *enc, const uint8_t *buf, int size)
+{
+ SWFContext *swf = s->priv_data;
+ int c = 0;
+
+ /* Flash Player limit */
+ if ( swf->swf_frame_number == 16000 ) {
+ av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
+ }
+
+ if (enc->codec_id == CODEC_ID_MP3 ) {
+ for (c=0; c<size; c++) {
+ swf->audio_fifo[(swf->audio_out_pos+c)%AUDIO_FIFO_SIZE] = buf[c];
+ }
+ swf->audio_size += size;
+ swf->audio_out_pos += size;
+ swf->audio_out_pos %= AUDIO_FIFO_SIZE;
+ }
+
+ /* if audio only stream make sure we add swf frames */
+ if ( swf->video_type == 0 ) {
+ swf_write_video(s, enc, 0, 0);
+ }
+
+ return 0;
+}
+
+static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
+ if (codec->codec_type == CODEC_TYPE_AUDIO)
+ return swf_write_audio(s, codec, pkt->data, pkt->size);
+ else
+ return swf_write_video(s, codec, pkt->data, pkt->size);
+}
+
+static int swf_write_trailer(AVFormatContext *s)
+{
+ SWFContext *swf = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVCodecContext *enc, *video_enc;
+ int file_size, i;
+
+ video_enc = NULL;
+ for(i=0;i<s->nb_streams;i++) {
+ enc = s->streams[i]->codec;
+ if (enc->codec_type == CODEC_TYPE_VIDEO)
+ video_enc = enc;
+ }
+
+ put_swf_tag(s, TAG_END);
+ put_swf_end_tag(s);
+
+ put_flush_packet(&s->pb);
+
+ /* patch file size and number of frames if not streamed */
+ if (!url_is_streamed(&s->pb) && video_enc) {
+ file_size = url_ftell(pb);
+ url_fseek(pb, 4, SEEK_SET);
+ put_le32(pb, file_size);
+ url_fseek(pb, swf->duration_pos, SEEK_SET);
+ put_le16(pb, video_enc->frame_number);
+ }
+
+ av_free(swf->audio_fifo);
+
+ return 0;
+}
+#endif //CONFIG_MUXERS
+
+/*********************************************/
+/* Extract FLV encoded frame and MP3 from swf
+ Note that the detection of the real frame
+ is inaccurate at this point as it can be
+ quite tricky to determine, you almost certainly
+ will get a bad audio/video sync */
+
+static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
+{
+ int tag, len;
+
+ if (url_feof(pb))
+ return -1;
+
+ tag = get_le16(pb);
+ len = tag & 0x3f;
+ tag = tag >> 6;
+ if (len == 0x3f) {
+ len = get_le32(pb);
+ }
+// av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
+ *len_ptr = len;
+ return tag;
+}
+
+
+static int swf_probe(AVProbeData *p)
+{
+ /* check file header */
+ if (p->buf_size <= 16)
+ return 0;
+ if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
+ p->buf[2] == 'S')
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ SWFContext *swf = 0;
+ ByteIOContext *pb = &s->pb;
+ int nbits, len, frame_rate, tag, v;
+ offset_t firstTagOff;
+ AVStream *ast = 0;
+ AVStream *vst = 0;
+
+ swf = av_malloc(sizeof(SWFContext));
+ if (!swf)
+ return -1;
+ s->priv_data = swf;
+
+ tag = get_be32(pb) & 0xffffff00;
+
+ if (tag == MKBETAG('C', 'W', 'S', 0))
+ {
+ av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
+ return AVERROR_IO;
+ }
+ if (tag != MKBETAG('F', 'W', 'S', 0))
+ return AVERROR_IO;
+ get_le32(pb);
+ /* skip rectangle size */
+ nbits = get_byte(pb) >> 3;
+ len = (4 * nbits - 3 + 7) / 8;
+ url_fskip(pb, len);
+ frame_rate = get_le16(pb);
+ get_le16(pb); /* frame count */
+
+ /* The Flash Player converts 8.8 frame rates
+ to milliseconds internally. Do the same to get
+ a correct framerate */
+ swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;
+ swf->samples_per_frame = 0;
+ swf->ch_id = -1;
+
+ firstTagOff = url_ftell(pb);
+ for(;;) {
+ tag = get_swf_tag(pb, &len);
+ if (tag < 0) {
+ if ( ast || vst ) {
+ if ( vst && ast ) {
+ vst->codec->time_base.den = ast->codec->sample_rate / swf->samples_per_frame;
+ vst->codec->time_base.num = 1;
+ }
+ break;
+ }
+ av_log(s, AV_LOG_ERROR, "No media found in SWF\n");
+ return AVERROR_IO;
+ }
+ if ( tag == TAG_VIDEOSTREAM && !vst) {
+ int codec_id;
+ swf->ch_id = get_le16(pb);
+ get_le16(pb);
+ get_le16(pb);
+ get_le16(pb);
+ get_byte(pb);
+ /* Check for FLV1 */
+ codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
+ if ( codec_id ) {
+ vst = av_new_stream(s, 0);
+ av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
+
+ vst->codec->codec_type = CODEC_TYPE_VIDEO;
+ vst->codec->codec_id = codec_id;
+ if ( swf->samples_per_frame ) {
+ vst->codec->time_base.den = 1000. / swf->ms_per_frame;
+ vst->codec->time_base.num = 1;
+ }
+ }
+ } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {
+ /* streaming found */
+ get_byte(pb);
+ v = get_byte(pb);
+ swf->samples_per_frame = get_le16(pb);
+ if (len!=4)
+ url_fskip(pb,len-4);
+ /* if mp3 streaming found, OK */
+ if ((v & 0x20) != 0) {
+ if ( tag == TAG_STREAMHEAD2 ) {
+ get_le16(pb);
+ }
+ ast = av_new_stream(s, 1);
+ if (!ast)
+ return -ENOMEM;
+ av_set_pts_info(ast, 24, 1, 1000); /* 24 bit pts in ms */
+
+ if (v & 0x01)
+ ast->codec->channels = 2;
+ else
+ ast->codec->channels = 1;
+
+ switch((v>> 2) & 0x03) {
+ case 1:
+ ast->codec->sample_rate = 11025;
+ break;
+ case 2:
+ ast->codec->sample_rate = 22050;
+ break;
+ case 3:
+ ast->codec->sample_rate = 44100;
+ break;
+ default:
+ av_free(ast);
+ return AVERROR_IO;
+ }
+ ast->codec->codec_type = CODEC_TYPE_AUDIO;
+ ast->codec->codec_id = CODEC_ID_MP3;
+ ast->need_parsing = 1;
+ }
+ } else {
+ url_fskip(pb, len);
+ }
+ }
+ url_fseek(pb, firstTagOff, SEEK_SET);
+
+ return 0;
+}
+
+static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ SWFContext *swf = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVStream *st = 0;
+ int tag, len, i, frame;
+
+ for(;;) {
+ tag = get_swf_tag(pb, &len);
+ if (tag < 0)
+ return AVERROR_IO;
+ if (tag == TAG_VIDEOFRAME) {
+ for( i=0; i<s->nb_streams; i++ ) {
+ st = s->streams[i];
+ if (st->id == 0) {
+ if ( get_le16(pb) == swf->ch_id ) {
+ frame = get_le16(pb);
+ av_get_packet(pb, pkt, len-4);
+ pkt->pts = frame * swf->ms_per_frame;
+ pkt->stream_index = st->index;
+ return pkt->size;
+ } else {
+ url_fskip(pb, len-2);
+ continue;
+ }
+ }
+ }
+ url_fskip(pb, len);
+ } else if (tag == TAG_STREAMBLOCK) {
+ for( i=0; i<s->nb_streams; i++ ) {
+ st = s->streams[i];
+ if (st->id == 1) {
+ url_fskip(pb, 4);
+ av_get_packet(pb, pkt, len-4);
+ pkt->stream_index = st->index;
+ return pkt->size;
+ }
+ }
+ url_fskip(pb, len);
+ } else {
+ url_fskip(pb, len);
+ }
+ }
+ return 0;
+}
+
+static int swf_read_close(AVFormatContext *s)
+{
+ return 0;
+}
+
+#ifdef CONFIG_SWF_DEMUXER
+AVInputFormat swf_demuxer = {
+ "swf",
+ "Flash format",
+ sizeof(SWFContext),
+ swf_probe,
+ swf_read_header,
+ swf_read_packet,
+ swf_read_close,
+};
+#endif
+#ifdef CONFIG_SWF_MUXER
+AVOutputFormat swf_muxer = {
+ "swf",
+ "Flash format",
+ "application/x-shockwave-flash",
+ "swf",
+ sizeof(SWFContext),
+ CODEC_ID_MP3,
+ CODEC_ID_FLV1,
+ swf_write_header,
+ swf_write_packet,
+ swf_write_trailer,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/tcp.c b/contrib/ffmpeg/libavformat/tcp.c
new file mode 100644
index 000000000..93755c497
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/tcp.c
@@ -0,0 +1,232 @@
+/*
+ * TCP protocol
+ * 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 "avformat.h"
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#if defined(__BEOS__) || defined(__INNOTEK_LIBC__)
+typedef int socklen_t;
+#endif
+#ifndef __BEOS__
+# include <arpa/inet.h>
+#else
+# include "barpainet.h"
+#endif
+#include <netdb.h>
+#include <sys/time.h>
+#include <fcntl.h>
+
+typedef struct TCPContext {
+ int fd;
+} TCPContext;
+
+/* resolve host with also IP address parsing */
+int resolve_host(struct in_addr *sin_addr, const char *hostname)
+{
+ struct hostent *hp;
+
+ if ((inet_aton(hostname, sin_addr)) == 0) {
+ hp = gethostbyname(hostname);
+ if (!hp)
+ return -1;
+ memcpy (sin_addr, hp->h_addr, sizeof(struct in_addr));
+ }
+ return 0;
+}
+
+/* return non zero if error */
+static int tcp_open(URLContext *h, const char *uri, int flags)
+{
+ struct sockaddr_in dest_addr;
+ char hostname[1024], *q;
+ int port, fd = -1;
+ TCPContext *s = NULL;
+ fd_set wfds;
+ int fd_max, ret;
+ struct timeval tv;
+ socklen_t optlen;
+ char proto[1024],path[1024],tmp[1024]; // PETR: protocol and path strings
+
+ url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname),
+ &port, path, sizeof(path), uri); // PETR: use url_split
+ if (strcmp(proto,"tcp")) goto fail; // PETR: check protocol
+ if ((q = strchr(hostname,'@'))) { strcpy(tmp,q+1); strcpy(hostname,tmp); } // PETR: take only the part after '@' for tcp protocol
+
+ s = av_malloc(sizeof(TCPContext));
+ if (!s)
+ return -ENOMEM;
+ h->priv_data = s;
+
+ if (port <= 0 || port >= 65536)
+ goto fail;
+
+ dest_addr.sin_family = AF_INET;
+ dest_addr.sin_port = htons(port);
+ if (resolve_host(&dest_addr.sin_addr, hostname) < 0)
+ goto fail;
+
+ fd = socket(PF_INET, SOCK_STREAM, 0);
+ if (fd < 0)
+ goto fail;
+ fcntl(fd, F_SETFL, O_NONBLOCK);
+
+ redo:
+ ret = connect(fd, (struct sockaddr *)&dest_addr,
+ sizeof(dest_addr));
+ if (ret < 0) {
+ if (errno == EINTR)
+ goto redo;
+ if (errno != EINPROGRESS)
+ goto fail;
+
+ /* wait until we are connected or until abort */
+ for(;;) {
+ if (url_interrupt_cb()) {
+ ret = -EINTR;
+ goto fail1;
+ }
+ fd_max = fd;
+ FD_ZERO(&wfds);
+ FD_SET(fd, &wfds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 100 * 1000;
+ ret = select(fd_max + 1, NULL, &wfds, NULL, &tv);
+ if (ret > 0 && FD_ISSET(fd, &wfds))
+ break;
+ }
+
+ /* test error */
+ optlen = sizeof(ret);
+ getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen);
+ if (ret != 0)
+ goto fail;
+ }
+ s->fd = fd;
+ return 0;
+
+ fail:
+ ret = AVERROR_IO;
+ fail1:
+ if (fd >= 0)
+ close(fd);
+ av_free(s);
+ return ret;
+}
+
+static int tcp_read(URLContext *h, uint8_t *buf, int size)
+{
+ TCPContext *s = h->priv_data;
+ int len, fd_max, ret;
+ fd_set rfds;
+ struct timeval tv;
+
+ for (;;) {
+ if (url_interrupt_cb())
+ return -EINTR;
+ fd_max = s->fd;
+ FD_ZERO(&rfds);
+ FD_SET(s->fd, &rfds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 100 * 1000;
+ ret = select(fd_max + 1, &rfds, NULL, NULL, &tv);
+ if (ret > 0 && FD_ISSET(s->fd, &rfds)) {
+#ifdef __BEOS__
+ len = recv(s->fd, buf, size, 0);
+#else
+ len = read(s->fd, buf, size);
+#endif
+ if (len < 0) {
+ if (errno != EINTR && errno != EAGAIN)
+#ifdef __BEOS__
+ return errno;
+#else
+ return -errno;
+#endif
+ } else return len;
+ } else if (ret < 0) {
+ return -1;
+ }
+ }
+}
+
+static int tcp_write(URLContext *h, uint8_t *buf, int size)
+{
+ TCPContext *s = h->priv_data;
+ int ret, size1, fd_max, len;
+ fd_set wfds;
+ struct timeval tv;
+
+ size1 = size;
+ while (size > 0) {
+ if (url_interrupt_cb())
+ return -EINTR;
+ fd_max = s->fd;
+ FD_ZERO(&wfds);
+ FD_SET(s->fd, &wfds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 100 * 1000;
+ ret = select(fd_max + 1, NULL, &wfds, NULL, &tv);
+ if (ret > 0 && FD_ISSET(s->fd, &wfds)) {
+#ifdef __BEOS__
+ len = send(s->fd, buf, size, 0);
+#else
+ len = write(s->fd, buf, size);
+#endif
+ if (len < 0) {
+ if (errno != EINTR && errno != EAGAIN) {
+#ifdef __BEOS__
+ return errno;
+#else
+ return -errno;
+#endif
+ }
+ continue;
+ }
+ size -= len;
+ buf += len;
+ } else if (ret < 0) {
+ return -1;
+ }
+ }
+ return size1 - size;
+}
+
+static int tcp_close(URLContext *h)
+{
+ TCPContext *s = h->priv_data;
+#ifdef CONFIG_BEOS_NETSERVER
+ closesocket(s->fd);
+#else
+ close(s->fd);
+#endif
+ av_free(s);
+ return 0;
+}
+
+URLProtocol tcp_protocol = {
+ "tcp",
+ tcp_open,
+ tcp_read,
+ tcp_write,
+ NULL, /* seek */
+ tcp_close,
+};
diff --git a/contrib/ffmpeg/libavformat/tiertexseq.c b/contrib/ffmpeg/libavformat/tiertexseq.c
new file mode 100644
index 000000000..b1a39bf76
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/tiertexseq.c
@@ -0,0 +1,310 @@
+/*
+ * Tiertex Limited SEQ File Demuxer
+ * 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 tiertexseq.c
+ * Tiertex Limited SEQ file demuxer
+ */
+
+#include "avformat.h"
+
+#define SEQ_FRAME_SIZE 6144
+#define SEQ_FRAME_W 256
+#define SEQ_FRAME_H 128
+#define SEQ_NUM_FRAME_BUFFERS 30
+#define SEQ_AUDIO_BUFFER_SIZE 882
+#define SEQ_SAMPLE_RATE 22050
+#define SEQ_FRAME_RATE 25
+
+
+typedef struct TiertexSeqFrameBuffer {
+ int fill_size;
+ int data_size;
+ unsigned char *data;
+} TiertexSeqFrameBuffer;
+
+typedef struct SeqDemuxContext {
+ int audio_stream_index;
+ int video_stream_index;
+ int current_frame_pts;
+ int current_frame_offs;
+ TiertexSeqFrameBuffer frame_buffers[SEQ_NUM_FRAME_BUFFERS];
+ int frame_buffers_count;
+ unsigned int current_audio_data_size;
+ unsigned int current_audio_data_offs;
+ unsigned int current_pal_data_size;
+ unsigned int current_pal_data_offs;
+ unsigned int current_video_data_size;
+ unsigned char *current_video_data_ptr;
+ int audio_buffer_full;
+} SeqDemuxContext;
+
+
+static int seq_probe(AVProbeData *p)
+{
+ int i;
+
+ if (p->buf_size < 256)
+ return 0;
+
+ /* there's no real header in a .seq file, the only thing they have in common */
+ /* is the first 256 bytes of the file which are always filled with 0 */
+ for (i = 0; i < 256; i++)
+ if (p->buf[i] != 0)
+ return 0;
+
+ /* only one fourth of the score since the previous check is too naive */
+ return AVPROBE_SCORE_MAX / 4;
+}
+
+static int seq_init_frame_buffers(SeqDemuxContext *seq, ByteIOContext *pb)
+{
+ int i, sz;
+ TiertexSeqFrameBuffer *seq_buffer;
+
+ url_fseek(pb, 256, SEEK_SET);
+
+ for (i = 0; i < SEQ_NUM_FRAME_BUFFERS; i++) {
+ sz = get_le16(pb);
+ if (sz == 0)
+ break;
+ else {
+ seq_buffer = &seq->frame_buffers[i];
+ seq_buffer->fill_size = 0;
+ seq_buffer->data_size = sz;
+ seq_buffer->data = av_malloc(sz);
+ if (!seq_buffer->data)
+ return AVERROR_NOMEM;
+ }
+ }
+ seq->frame_buffers_count = i;
+ return 0;
+}
+
+static int seq_fill_buffer(SeqDemuxContext *seq, ByteIOContext *pb, int buffer_num, unsigned int data_offs, int data_size)
+{
+ TiertexSeqFrameBuffer *seq_buffer;
+
+ if (buffer_num >= SEQ_NUM_FRAME_BUFFERS)
+ return AVERROR_INVALIDDATA;
+
+ seq_buffer = &seq->frame_buffers[buffer_num];
+ if (seq_buffer->fill_size + data_size > seq_buffer->data_size)
+ return AVERROR_INVALIDDATA;
+
+ url_fseek(pb, seq->current_frame_offs + data_offs, SEEK_SET);
+ if (get_buffer(pb, seq_buffer->data + seq_buffer->fill_size, data_size) != data_size)
+ return AVERROR_IO;
+
+ seq_buffer->fill_size += data_size;
+ return 0;
+}
+
+static int seq_parse_frame_data(SeqDemuxContext *seq, ByteIOContext *pb)
+{
+ unsigned int offset_table[4], buffer_num[4];
+ TiertexSeqFrameBuffer *seq_buffer;
+ int i, e, err;
+
+ seq->current_frame_offs += SEQ_FRAME_SIZE;
+ url_fseek(pb, seq->current_frame_offs, SEEK_SET);
+
+ /* sound data */
+ seq->current_audio_data_offs = get_le16(pb);
+ if (seq->current_audio_data_offs != 0) {
+ seq->current_audio_data_size = SEQ_AUDIO_BUFFER_SIZE * 2;
+ } else {
+ seq->current_audio_data_size = 0;
+ }
+
+ /* palette data */
+ seq->current_pal_data_offs = get_le16(pb);
+ if (seq->current_pal_data_offs != 0) {
+ seq->current_pal_data_size = 768;
+ } else {
+ seq->current_pal_data_size = 0;
+ }
+
+ /* video data */
+ for (i = 0; i < 4; i++)
+ buffer_num[i] = get_byte(pb);
+
+ for (i = 0; i < 4; i++)
+ offset_table[i] = get_le16(pb);
+
+ for (i = 0; i < 3; i++) {
+ if (offset_table[i] != 0) {
+ for (e = i + 1; e < 4 && offset_table[e] == 0; e++);
+ err = seq_fill_buffer(seq, pb, buffer_num[1 + i],
+ offset_table[i],
+ offset_table[e] - offset_table[i]);
+ if (err != 0)
+ return err;
+ }
+ }
+
+ if (buffer_num[0] != 255) {
+ if (buffer_num[0] >= SEQ_NUM_FRAME_BUFFERS)
+ return AVERROR_INVALIDDATA;
+
+ seq_buffer = &seq->frame_buffers[buffer_num[0]];
+ seq->current_video_data_size = seq_buffer->fill_size;
+ seq->current_video_data_ptr = seq_buffer->data;
+ seq_buffer->fill_size = 0;
+ } else {
+ seq->current_video_data_size = 0;
+ seq->current_video_data_ptr = 0;
+ }
+
+ return 0;
+}
+
+static int seq_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ int i, rc;
+ SeqDemuxContext *seq = (SeqDemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVStream *st;
+
+ /* init internal buffers */
+ rc = seq_init_frame_buffers(seq, pb);
+ if (rc)
+ return rc;
+
+ seq->current_frame_offs = 0;
+
+ /* preload (no audio data, just buffer operations related data) */
+ for (i = 1; i <= 100; i++) {
+ rc = seq_parse_frame_data(seq, pb);
+ if (rc)
+ return rc;
+ }
+
+ seq->current_frame_pts = 0;
+
+ seq->audio_buffer_full = 0;
+
+ /* initialize the video decoder stream */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+
+ av_set_pts_info(st, 32, 1, SEQ_FRAME_RATE);
+ seq->video_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_TIERTEXSEQVIDEO;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->width = SEQ_FRAME_W;
+ st->codec->height = SEQ_FRAME_H;
+
+ /* initialize the audio decoder stream */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+
+ av_set_pts_info(st, 32, 1, SEQ_SAMPLE_RATE);
+ seq->audio_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_PCM_S16BE;
+ st->codec->codec_tag = 0; /* no tag */
+ st->codec->channels = 1;
+ st->codec->sample_rate = SEQ_SAMPLE_RATE;
+ st->codec->bits_per_sample = 16;
+ st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_sample * st->codec->channels;
+ st->codec->block_align = st->codec->channels * st->codec->bits_per_sample;
+
+ return 0;
+}
+
+static int seq_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ int rc;
+ SeqDemuxContext *seq = (SeqDemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+
+ if (!seq->audio_buffer_full) {
+ rc = seq_parse_frame_data(seq, pb);
+ if (rc)
+ return rc;
+
+ /* video packet */
+ if (seq->current_pal_data_size + seq->current_video_data_size != 0) {
+ if (av_new_packet(pkt, 1 + seq->current_pal_data_size + seq->current_video_data_size))
+ return AVERROR_NOMEM;
+
+ pkt->data[0] = 0;
+ if (seq->current_pal_data_size != 0) {
+ pkt->data[0] |= 1;
+ url_fseek(pb, seq->current_frame_offs + seq->current_pal_data_offs, SEEK_SET);
+ if (get_buffer(pb, &pkt->data[1], seq->current_pal_data_size) != seq->current_pal_data_size)
+ return AVERROR_IO;
+ }
+ if (seq->current_video_data_size != 0) {
+ pkt->data[0] |= 2;
+ memcpy(&pkt->data[1 + seq->current_pal_data_size],
+ seq->current_video_data_ptr,
+ seq->current_video_data_size);
+ }
+ pkt->stream_index = seq->video_stream_index;
+ pkt->pts = seq->current_frame_pts;
+
+ /* sound buffer will be processed on next read_packet() call */
+ seq->audio_buffer_full = 1;
+ return 0;
+ }
+ }
+
+ /* audio packet */
+ if (seq->current_audio_data_offs == 0) /* end of data reached */
+ return AVERROR_IO;
+
+ url_fseek(pb, seq->current_frame_offs + seq->current_audio_data_offs, SEEK_SET);
+ rc = av_get_packet(pb, pkt, seq->current_audio_data_size);
+ if (rc < 0)
+ return rc;
+
+ pkt->stream_index = seq->audio_stream_index;
+ pkt->pts = seq->current_frame_pts++;
+
+ seq->audio_buffer_full = 0;
+ return 0;
+}
+
+static int seq_read_close(AVFormatContext *s)
+{
+ int i;
+ SeqDemuxContext *seq = (SeqDemuxContext *)s->priv_data;
+
+ for (i = 0; i < SEQ_NUM_FRAME_BUFFERS; i++)
+ av_free(seq->frame_buffers[i].data);
+
+ return 0;
+}
+
+AVInputFormat tiertexseq_demuxer = {
+ "tiertexseq",
+ "Tiertex Limited SEQ format",
+ sizeof(SeqDemuxContext),
+ seq_probe,
+ seq_read_header,
+ seq_read_packet,
+ seq_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/tta.c b/contrib/ffmpeg/libavformat/tta.c
new file mode 100644
index 000000000..a513d9d38
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/tta.c
@@ -0,0 +1,152 @@
+/*
+ * TTA demuxer
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "avformat.h"
+#include "bitstream.h"
+
+typedef struct {
+ int totalframes, currentframe;
+ uint32_t *seektable;
+} TTAContext;
+
+static int tta_probe(AVProbeData *p)
+{
+ const uint8_t *d = p->buf;
+ if (p->buf_size < 4)
+ return 0;
+ if (d[0] == 'T' && d[1] == 'T' && d[2] == 'A' && d[3] == '1')
+ return 80;
+ return 0;
+}
+
+static int tta_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ TTAContext *c = s->priv_data;
+ AVStream *st;
+ int i, channels, bps, samplerate, datalen, framelen, start;
+
+ start = url_ftell(&s->pb);
+
+ if (get_le32(&s->pb) != ff_get_fourcc("TTA1"))
+ return -1; // not tta file
+
+ url_fskip(&s->pb, 2); // FIXME: flags
+ channels = get_le16(&s->pb);
+ bps = get_le16(&s->pb);
+ samplerate = get_le32(&s->pb);
+ if(samplerate <= 0 || samplerate > 1000000){
+ av_log(s, AV_LOG_ERROR, "nonsense samplerate\n");
+ return -1;
+ }
+
+ datalen = get_le32(&s->pb);
+ if(datalen < 0){
+ av_log(s, AV_LOG_ERROR, "nonsense datalen\n");
+ return -1;
+ }
+
+ url_fskip(&s->pb, 4); // header crc
+
+ framelen = 1.04489795918367346939 * samplerate;
+ c->totalframes = datalen / framelen + ((datalen % framelen) ? 1 : 0);
+ c->currentframe = 0;
+
+ if(c->totalframes >= UINT_MAX/sizeof(uint32_t)){
+ av_log(s, AV_LOG_ERROR, "totalframes too large\n");
+ return -1;
+ }
+ c->seektable = av_mallocz(sizeof(uint32_t)*c->totalframes);
+ if (!c->seektable)
+ return AVERROR_NOMEM;
+
+ for (i = 0; i < c->totalframes; i++)
+ c->seektable[i] = get_le32(&s->pb);
+ url_fskip(&s->pb, 4); // seektable crc
+
+ st = av_new_stream(s, 0);
+// av_set_pts_info(st, 32, 1, 1000);
+ if (!st)
+ return AVERROR_NOMEM;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_TTA;
+ st->codec->channels = channels;
+ st->codec->sample_rate = samplerate;
+ st->codec->bits_per_sample = bps;
+
+ st->codec->extradata_size = url_ftell(&s->pb) - start;
+ if(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)st->codec->extradata_size){
+ //this check is redundant as get_buffer should fail
+ av_log(s, AV_LOG_ERROR, "extradata_size too large\n");
+ return -1;
+ }
+ st->codec->extradata = av_mallocz(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE);
+ url_fseek(&s->pb, start, SEEK_SET); // or SEEK_CUR and -size ? :)
+ get_buffer(&s->pb, st->codec->extradata, st->codec->extradata_size);
+
+ return 0;
+}
+
+static int tta_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ TTAContext *c = s->priv_data;
+ int ret, size;
+
+ // FIXME!
+ if (c->currentframe > c->totalframes)
+ size = 0;
+ else
+ size = c->seektable[c->currentframe];
+
+ c->currentframe++;
+
+ if (av_new_packet(pkt, size) < 0)
+ return AVERROR_IO;
+
+ pkt->pos = url_ftell(&s->pb);
+ pkt->stream_index = 0;
+ ret = get_buffer(&s->pb, pkt->data, size);
+ if (ret <= 0) {
+ av_free_packet(pkt);
+ return AVERROR_IO;
+ }
+ pkt->size = ret;
+// av_log(s, AV_LOG_INFO, "TTA packet #%d desired size: %d read size: %d at pos %d\n",
+// c->currentframe, size, ret, pkt->pos);
+ return 0; //ret;
+}
+
+static int tta_read_close(AVFormatContext *s)
+{
+ TTAContext *c = s->priv_data;
+ if (c->seektable)
+ av_free(c->seektable);
+ return 0;
+}
+
+AVInputFormat tta_demuxer = {
+ "tta",
+ "true-audio",
+ sizeof(TTAContext),
+ tta_probe,
+ tta_read_header,
+ tta_read_packet,
+ tta_read_close,
+ .extensions = "tta",
+};
diff --git a/contrib/ffmpeg/libavformat/udp.c b/contrib/ffmpeg/libavformat/udp.c
new file mode 100644
index 000000000..96fa4e152
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/udp.c
@@ -0,0 +1,512 @@
+/*
+ * UDP prototype streaming system
+ * 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 "avformat.h"
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifndef __BEOS__
+# include <arpa/inet.h>
+#else
+# include "barpainet.h"
+#endif
+#include <netdb.h>
+
+#ifndef IPV6_ADD_MEMBERSHIP
+#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
+#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
+#endif
+
+typedef struct {
+ int udp_fd;
+ int ttl;
+ int is_multicast;
+ int local_port;
+ int reuse_socket;
+#ifndef CONFIG_IPV6
+ struct ip_mreq mreq;
+ struct sockaddr_in dest_addr;
+#else
+ struct sockaddr_storage dest_addr;
+ size_t dest_addr_len;
+#endif
+} UDPContext;
+
+#define UDP_TX_BUF_SIZE 32768
+
+#ifdef CONFIG_IPV6
+
+static int udp_ipv6_is_multicast_address(const struct sockaddr *addr) {
+ if (addr->sa_family == AF_INET)
+ return IN_MULTICAST(ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr));
+ if (addr->sa_family == AF_INET6)
+ return IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)addr)->sin6_addr);
+ return -1;
+}
+
+static int udp_ipv6_set_multicast_ttl(int sockfd, int mcastTTL, struct sockaddr *addr) {
+ if (addr->sa_family == AF_INET) {
+ if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &mcastTTL, sizeof(mcastTTL)) < 0) {
+ perror("setsockopt(IP_MULTICAST_TTL)");
+ return -1;
+ }
+ }
+ if (addr->sa_family == AF_INET6) {
+ if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastTTL, sizeof(mcastTTL)) < 0) {
+ perror("setsockopt(IPV6_MULTICAST_HOPS)");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int udp_ipv6_join_multicast_group(int sockfd, struct sockaddr *addr) {
+ struct ip_mreq mreq;
+ struct ipv6_mreq mreq6;
+ if (addr->sa_family == AF_INET) {
+ mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
+ mreq.imr_interface.s_addr= INADDR_ANY;
+ if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) {
+ perror("setsockopt(IP_ADD_MEMBERSHIP)");
+ return -1;
+ }
+ }
+ if (addr->sa_family == AF_INET6) {
+ memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr));
+ mreq6.ipv6mr_interface= 0;
+ if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) {
+ perror("setsockopt(IPV6_ADD_MEMBERSHIP)");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int udp_ipv6_leave_multicast_group(int sockfd, struct sockaddr *addr) {
+ struct ip_mreq mreq;
+ struct ipv6_mreq mreq6;
+ if (addr->sa_family == AF_INET) {
+ mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
+ mreq.imr_interface.s_addr= INADDR_ANY;
+ if (setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) {
+ perror("setsockopt(IP_DROP_MEMBERSHIP)");
+ return -1;
+ }
+ }
+ if (addr->sa_family == AF_INET6) {
+ memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr));
+ mreq6.ipv6mr_interface= 0;
+ if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) {
+ perror("setsockopt(IPV6_DROP_MEMBERSHIP)");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static struct addrinfo* udp_ipv6_resolve_host(const char *hostname, int port, int type, int family, int flags) {
+ struct addrinfo hints, *res = 0;
+ int error;
+ char sport[16];
+ const char *node = 0, *service = 0;
+
+ if (port > 0) {
+ snprintf(sport, sizeof(sport), "%d", port);
+ service = sport;
+ }
+ if ((hostname) && (hostname[0] != '\0') && (hostname[0] != '?')) {
+ node = hostname;
+ }
+ if ((node) || (service)) {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = type;
+ hints.ai_family = family;
+ hints.ai_flags = flags;
+ if ((error = getaddrinfo(node, service, &hints, &res))) {
+ av_log(NULL, AV_LOG_ERROR, "udp_ipv6_resolve_host: %s\n", gai_strerror(error));
+ }
+ }
+ return res;
+}
+
+static int udp_ipv6_set_remote_url(URLContext *h, const char *uri) {
+ UDPContext *s = h->priv_data;
+ char hostname[256];
+ int port;
+ struct addrinfo *res0;
+ url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);
+ res0 = udp_ipv6_resolve_host(hostname, port, SOCK_DGRAM, AF_UNSPEC, 0);
+ if (res0 == 0) return AVERROR_IO;
+ memcpy(&s->dest_addr, res0->ai_addr, res0->ai_addrlen);
+ s->dest_addr_len = res0->ai_addrlen;
+ freeaddrinfo(res0);
+ return 0;
+}
+
+static int udp_ipv6_set_local(URLContext *h) {
+ UDPContext *s = h->priv_data;
+ int udp_fd = -1;
+ struct sockaddr_storage clientaddr;
+ socklen_t addrlen;
+ char sbuf[NI_MAXSERV];
+ char hbuf[NI_MAXHOST];
+ struct addrinfo *res0 = NULL, *res = NULL;
+
+ if (s->local_port != 0) {
+ res0 = udp_ipv6_resolve_host(0, s->local_port, SOCK_DGRAM, AF_UNSPEC, AI_PASSIVE);
+ if (res0 == 0)
+ goto fail;
+ for (res = res0; res; res=res->ai_next) {
+ udp_fd = socket(res->ai_family, SOCK_DGRAM, 0);
+ if (udp_fd > 0) break;
+ perror("socket");
+ }
+ } else {
+ udp_fd = socket(s->dest_addr.ss_family, SOCK_DGRAM, 0);
+ if (udp_fd < 0)
+ perror("socket");
+ }
+
+ if (udp_fd < 0)
+ goto fail;
+
+ if (s->local_port != 0) {
+ if (bind(udp_fd, res0->ai_addr, res0->ai_addrlen) < 0) {
+ perror("bind");
+ goto fail;
+ }
+ freeaddrinfo(res0);
+ res0 = NULL;
+ }
+
+ addrlen = sizeof(clientaddr);
+ if (getsockname(udp_fd, (struct sockaddr *)&clientaddr, &addrlen) < 0) {
+ perror("getsockname");
+ goto fail;
+ }
+
+ if (getnameinfo((struct sockaddr *)&clientaddr, addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
+ perror("getnameinfo");
+ goto fail;
+ }
+
+ s->local_port = strtol(sbuf, NULL, 10);
+
+ return udp_fd;
+
+ fail:
+ if (udp_fd >= 0)
+#ifdef CONFIG_BEOS_NETSERVER
+ closesocket(udp_fd);
+#else
+ close(udp_fd);
+#endif
+ if(res0)
+ freeaddrinfo(res0);
+ return -1;
+}
+
+#endif
+
+
+/**
+ * If no filename is given to av_open_input_file because you want to
+ * get the local port first, then you must call this function to set
+ * the remote server address.
+ *
+ * url syntax: udp://host:port[?option=val...]
+ * option: 'multicast=1' : enable multicast
+ * 'ttl=n' : set the ttl value (for multicast only)
+ * 'localport=n' : set the local port
+ * 'pkt_size=n' : set max packet size
+ * 'reuse=1' : enable reusing the socket
+ *
+ * @param s1 media file context
+ * @param uri of the remote server
+ * @return zero if no error.
+ */
+int udp_set_remote_url(URLContext *h, const char *uri)
+{
+#ifdef CONFIG_IPV6
+ return udp_ipv6_set_remote_url(h, uri);
+#else
+ UDPContext *s = h->priv_data;
+ char hostname[256];
+ int port;
+
+ url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);
+
+ /* set the destination address */
+ if (resolve_host(&s->dest_addr.sin_addr, hostname) < 0)
+ return AVERROR_IO;
+ s->dest_addr.sin_family = AF_INET;
+ s->dest_addr.sin_port = htons(port);
+ return 0;
+#endif
+}
+
+/**
+ * Return the local port used by the UDP connexion
+ * @param s1 media file context
+ * @return the local port number
+ */
+int udp_get_local_port(URLContext *h)
+{
+ UDPContext *s = h->priv_data;
+ return s->local_port;
+}
+
+/**
+ * Return the udp file handle for select() usage to wait for several RTP
+ * streams at the same time.
+ * @param h media file context
+ */
+int udp_get_file_handle(URLContext *h)
+{
+ UDPContext *s = h->priv_data;
+ return s->udp_fd;
+}
+
+/* put it in UDP context */
+/* return non zero if error */
+static int udp_open(URLContext *h, const char *uri, int flags)
+{
+ char hostname[1024];
+ int port, udp_fd = -1, tmp;
+ UDPContext *s = NULL;
+ int is_output;
+ const char *p;
+ char buf[256];
+#ifndef CONFIG_IPV6
+ struct sockaddr_in my_addr, my_addr1;
+ int len;
+#endif
+
+ h->is_streamed = 1;
+ h->max_packet_size = 1472;
+
+ is_output = (flags & URL_WRONLY);
+
+ s = av_malloc(sizeof(UDPContext));
+ if (!s)
+ return -ENOMEM;
+
+ h->priv_data = s;
+ s->ttl = 16;
+ s->is_multicast = 0;
+ s->local_port = 0;
+ s->reuse_socket = 0;
+ p = strchr(uri, '?');
+ if (p) {
+ s->is_multicast = find_info_tag(buf, sizeof(buf), "multicast", p);
+ s->reuse_socket = find_info_tag(buf, sizeof(buf), "reuse", p);
+ if (find_info_tag(buf, sizeof(buf), "ttl", p)) {
+ s->ttl = strtol(buf, NULL, 10);
+ }
+ if (find_info_tag(buf, sizeof(buf), "localport", p)) {
+ s->local_port = strtol(buf, NULL, 10);
+ }
+ if (find_info_tag(buf, sizeof(buf), "pkt_size", p)) {
+ h->max_packet_size = strtol(buf, NULL, 10);
+ }
+ }
+
+ /* fill the dest addr */
+ url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);
+
+ /* XXX: fix url_split */
+ if (hostname[0] == '\0' || hostname[0] == '?') {
+ /* only accepts null hostname if input */
+ if (s->is_multicast || (flags & URL_WRONLY))
+ goto fail;
+ } else {
+ udp_set_remote_url(h, uri);
+ }
+
+#ifndef CONFIG_IPV6
+ udp_fd = socket(PF_INET, SOCK_DGRAM, 0);
+ if (udp_fd < 0)
+ goto fail;
+
+ my_addr.sin_family = AF_INET;
+ my_addr.sin_addr.s_addr = htonl (INADDR_ANY);
+ if (s->is_multicast && !(h->flags & URL_WRONLY)) {
+ /* special case: the bind must be done on the multicast address port */
+ my_addr.sin_port = s->dest_addr.sin_port;
+ } else {
+ my_addr.sin_port = htons(s->local_port);
+ }
+
+ if (s->reuse_socket)
+ if (setsockopt (udp_fd, SOL_SOCKET, SO_REUSEADDR, &(s->reuse_socket), sizeof(s->reuse_socket)) != 0)
+ goto fail;
+
+ /* the bind is needed to give a port to the socket now */
+ if (bind(udp_fd,(struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
+ goto fail;
+
+ len = sizeof(my_addr1);
+ getsockname(udp_fd, (struct sockaddr *)&my_addr1, &len);
+ s->local_port = ntohs(my_addr1.sin_port);
+
+#ifndef CONFIG_BEOS_NETSERVER
+ if (s->is_multicast) {
+ if (h->flags & URL_WRONLY) {
+ /* output */
+ if (setsockopt(udp_fd, IPPROTO_IP, IP_MULTICAST_TTL,
+ &s->ttl, sizeof(s->ttl)) < 0) {
+ perror("IP_MULTICAST_TTL");
+ goto fail;
+ }
+ } else {
+ /* input */
+ memset(&s->mreq, 0, sizeof(s->mreq));
+ s->mreq.imr_multiaddr = s->dest_addr.sin_addr;
+ s->mreq.imr_interface.s_addr = htonl (INADDR_ANY);
+ if (setsockopt(udp_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ &s->mreq, sizeof(s->mreq)) < 0) {
+ perror("rtp: IP_ADD_MEMBERSHIP");
+ goto fail;
+ }
+ }
+ }
+#endif
+#else
+ if (s->is_multicast && !(h->flags & URL_WRONLY))
+ s->local_port = port;
+ udp_fd = udp_ipv6_set_local(h);
+ if (udp_fd < 0)
+ goto fail;
+#ifndef CONFIG_BEOS_NETSERVER
+ if (s->is_multicast) {
+ if (h->flags & URL_WRONLY) {
+ if (udp_ipv6_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0)
+ goto fail;
+ } else {
+ if (udp_ipv6_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
+ goto fail;
+ }
+ }
+#endif
+#endif
+
+ if (is_output) {
+ /* limit the tx buf size to limit latency */
+ tmp = UDP_TX_BUF_SIZE;
+ if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) {
+ perror("setsockopt sndbuf");
+ goto fail;
+ }
+ }
+
+ s->udp_fd = udp_fd;
+ return 0;
+ fail:
+ if (udp_fd >= 0)
+#ifdef CONFIG_BEOS_NETSERVER
+ closesocket(udp_fd);
+#else
+ close(udp_fd);
+#endif
+ av_free(s);
+ return AVERROR_IO;
+}
+
+static int udp_read(URLContext *h, uint8_t *buf, int size)
+{
+ UDPContext *s = h->priv_data;
+#ifndef CONFIG_IPV6
+ struct sockaddr_in from;
+#else
+ struct sockaddr_storage from;
+#endif
+ socklen_t from_len;
+ int len;
+
+ for(;;) {
+ from_len = sizeof(from);
+ len = recvfrom (s->udp_fd, buf, size, 0,
+ (struct sockaddr *)&from, &from_len);
+ if (len < 0) {
+ if (errno != EAGAIN && errno != EINTR)
+ return AVERROR_IO;
+ } else {
+ break;
+ }
+ }
+ return len;
+}
+
+static int udp_write(URLContext *h, uint8_t *buf, int size)
+{
+ UDPContext *s = h->priv_data;
+ int ret;
+
+ for(;;) {
+ ret = sendto (s->udp_fd, buf, size, 0,
+ (struct sockaddr *) &s->dest_addr,
+#ifndef CONFIG_IPV6
+ sizeof (s->dest_addr));
+#else
+ s->dest_addr_len);
+#endif
+ if (ret < 0) {
+ if (errno != EINTR && errno != EAGAIN)
+ return AVERROR_IO;
+ } else {
+ break;
+ }
+ }
+ return size;
+}
+
+static int udp_close(URLContext *h)
+{
+ UDPContext *s = h->priv_data;
+
+#ifndef CONFIG_BEOS_NETSERVER
+#ifndef CONFIG_IPV6
+ if (s->is_multicast && !(h->flags & URL_WRONLY)) {
+ if (setsockopt(s->udp_fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+ &s->mreq, sizeof(s->mreq)) < 0) {
+ perror("IP_DROP_MEMBERSHIP");
+ }
+ }
+#else
+ if (s->is_multicast && !(h->flags & URL_WRONLY))
+ udp_ipv6_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr);
+#endif
+ close(s->udp_fd);
+#else
+ closesocket(s->udp_fd);
+#endif
+ av_free(s);
+ return 0;
+}
+
+URLProtocol udp_protocol = {
+ "udp",
+ udp_open,
+ udp_read,
+ udp_write,
+ NULL, /* seek */
+ udp_close,
+};
diff --git a/contrib/ffmpeg/libavformat/utils.c b/contrib/ffmpeg/libavformat/utils.c
new file mode 100644
index 000000000..eaeeb7c16
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/utils.c
@@ -0,0 +1,3108 @@
+/*
+ * Various utilities for ffmpeg system
+ * 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 "avformat.h"
+#include "allformats.h"
+#include "opt.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+/**
+ * @file libavformat/utils.c
+ * Various utility functions for using ffmpeg library.
+ */
+
+static void av_frac_init(AVFrac *f, int64_t val, int64_t num, int64_t den);
+static void av_frac_add(AVFrac *f, int64_t incr);
+static void av_frac_set(AVFrac *f, int64_t val);
+
+/** head of registered input format linked list. */
+AVInputFormat *first_iformat = NULL;
+/** head of registered output format linked list. */
+AVOutputFormat *first_oformat = NULL;
+
+void av_register_input_format(AVInputFormat *format)
+{
+ AVInputFormat **p;
+ p = &first_iformat;
+ while (*p != NULL) p = &(*p)->next;
+ *p = format;
+ format->next = NULL;
+}
+
+void av_register_output_format(AVOutputFormat *format)
+{
+ AVOutputFormat **p;
+ p = &first_oformat;
+ while (*p != NULL) p = &(*p)->next;
+ *p = format;
+ format->next = NULL;
+}
+
+int match_ext(const char *filename, const char *extensions)
+{
+ const char *ext, *p;
+ char ext1[32], *q;
+
+ if(!filename)
+ return 0;
+
+ ext = strrchr(filename, '.');
+ if (ext) {
+ ext++;
+ p = extensions;
+ for(;;) {
+ q = ext1;
+ while (*p != '\0' && *p != ',' && q-ext1<sizeof(ext1)-1)
+ *q++ = *p++;
+ *q = '\0';
+ if (!strcasecmp(ext1, ext))
+ return 1;
+ if (*p == '\0')
+ break;
+ p++;
+ }
+ }
+ return 0;
+}
+
+AVOutputFormat *guess_format(const char *short_name, const char *filename,
+ const char *mime_type)
+{
+ AVOutputFormat *fmt, *fmt_found;
+ int score_max, score;
+
+ /* specific test for image sequences */
+#ifdef CONFIG_IMAGE2_MUXER
+ if (!short_name && filename &&
+ av_filename_number_test(filename) &&
+ av_guess_image2_codec(filename) != CODEC_ID_NONE) {
+ return guess_format("image2", NULL, NULL);
+ }
+#endif
+ /* find the proper file type */
+ fmt_found = NULL;
+ score_max = 0;
+ fmt = first_oformat;
+ while (fmt != NULL) {
+ score = 0;
+ if (fmt->name && short_name && !strcmp(fmt->name, short_name))
+ score += 100;
+ if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type))
+ score += 10;
+ if (filename && fmt->extensions &&
+ match_ext(filename, fmt->extensions)) {
+ score += 5;
+ }
+ if (score > score_max) {
+ score_max = score;
+ fmt_found = fmt;
+ }
+ fmt = fmt->next;
+ }
+ return fmt_found;
+}
+
+AVOutputFormat *guess_stream_format(const char *short_name, const char *filename,
+ const char *mime_type)
+{
+ AVOutputFormat *fmt = guess_format(short_name, filename, mime_type);
+
+ if (fmt) {
+ AVOutputFormat *stream_fmt;
+ char stream_format_name[64];
+
+ snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
+ stream_fmt = guess_format(stream_format_name, NULL, NULL);
+
+ if (stream_fmt)
+ fmt = stream_fmt;
+ }
+
+ return fmt;
+}
+
+/**
+ * Guesses the codec id based upon muxer and filename.
+ */
+enum CodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name,
+ const char *filename, const char *mime_type, enum CodecType type){
+ if(type == CODEC_TYPE_VIDEO){
+ enum CodecID codec_id= CODEC_ID_NONE;
+
+#ifdef CONFIG_IMAGE2_MUXER
+ if(!strcmp(fmt->name, "image2") || !strcmp(fmt->name, "image2pipe")){
+ codec_id= av_guess_image2_codec(filename);
+ }
+#endif
+ if(codec_id == CODEC_ID_NONE)
+ codec_id= fmt->video_codec;
+ return codec_id;
+ }else if(type == CODEC_TYPE_AUDIO)
+ return fmt->audio_codec;
+ else
+ return CODEC_ID_NONE;
+}
+
+/**
+ * finds AVInputFormat based on input format's short name.
+ */
+AVInputFormat *av_find_input_format(const char *short_name)
+{
+ AVInputFormat *fmt;
+ for(fmt = first_iformat; fmt != NULL; fmt = fmt->next) {
+ if (!strcmp(fmt->name, short_name))
+ return fmt;
+ }
+ return NULL;
+}
+
+/* memory handling */
+
+/**
+ * Default packet destructor.
+ */
+void av_destruct_packet(AVPacket *pkt)
+{
+ av_free(pkt->data);
+ pkt->data = NULL; pkt->size = 0;
+}
+
+/**
+ * Allocate the payload of a packet and intialized its fields to 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)
+{
+ uint8_t *data;
+ if((unsigned)size > (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE)
+ return AVERROR_NOMEM;
+ data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
+ if (!data)
+ return AVERROR_NOMEM;
+ memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+
+ av_init_packet(pkt);
+ pkt->data = data;
+ pkt->size = size;
+ pkt->destruct = av_destruct_packet;
+ return 0;
+}
+
+/**
+ * Allocate and read the payload of a packet and intialized its fields to default values.
+ *
+ * @param pkt packet
+ * @param size wanted payload size
+ * @return >0 (read size) if OK. AVERROR_xxx otherwise.
+ */
+int av_get_packet(ByteIOContext *s, AVPacket *pkt, int size)
+{
+ int ret= av_new_packet(pkt, size);
+
+ if(ret<0)
+ return ret;
+
+ pkt->pos= url_ftell(s);
+
+ ret= get_buffer(s, pkt->data, size);
+ if(ret<=0)
+ av_free_packet(pkt);
+ else
+ pkt->size= ret;
+
+ return ret;
+}
+
+/* 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)
+{
+ if (pkt->destruct != av_destruct_packet) {
+ uint8_t *data;
+ /* we duplicate the packet and don't forget to put the padding
+ again */
+ if((unsigned)pkt->size > (unsigned)pkt->size + FF_INPUT_BUFFER_PADDING_SIZE)
+ return AVERROR_NOMEM;
+ data = av_malloc(pkt->size + FF_INPUT_BUFFER_PADDING_SIZE);
+ if (!data) {
+ return AVERROR_NOMEM;
+ }
+ memcpy(data, pkt->data, pkt->size);
+ memset(data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+ pkt->data = data;
+ pkt->destruct = av_destruct_packet;
+ }
+ return 0;
+}
+
+/**
+ * Allocate the payload of a packet and intialized its fields to default values.
+ *
+ * @param filename possible numbered sequence string
+ * @return 1 if a valid numbered sequence string, 0 otherwise.
+ */
+int av_filename_number_test(const char *filename)
+{
+ char buf[1024];
+ return filename && (av_get_frame_filename(buf, sizeof(buf), filename, 1)>=0);
+}
+
+/**
+ * Guess file format.
+ */
+AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened)
+{
+ AVInputFormat *fmt1, *fmt;
+ int score, score_max;
+
+ fmt = NULL;
+ score_max = 0;
+ for(fmt1 = first_iformat; fmt1 != NULL; fmt1 = fmt1->next) {
+ if (!is_opened && !(fmt1->flags & AVFMT_NOFILE))
+ continue;
+ score = 0;
+ if (fmt1->read_probe) {
+ score = fmt1->read_probe(pd);
+ } else if (fmt1->extensions) {
+ if (match_ext(pd->filename, fmt1->extensions)) {
+ score = 50;
+ }
+ }
+ if (score > score_max) {
+ score_max = score;
+ fmt = fmt1;
+ }
+ }
+ return fmt;
+}
+
+/************************************************************/
+/* input media file */
+
+/**
+ * Open a media file from an IO stream. 'fmt' must be specified.
+ */
+static const char* format_to_name(void* ptr)
+{
+ AVFormatContext* fc = (AVFormatContext*) ptr;
+ if(fc->iformat) return fc->iformat->name;
+ else if(fc->oformat) return fc->oformat->name;
+ else return "NULL";
+}
+
+#define OFFSET(x) offsetof(AVFormatContext,x)
+#define DEFAULT 0 //should be NAN but it doesnt work as its not a constant in glibc as required by ANSI/ISO C
+//these names are too long to be readable
+#define E AV_OPT_FLAG_ENCODING_PARAM
+#define D AV_OPT_FLAG_DECODING_PARAM
+
+static const AVOption options[]={
+{"probesize", NULL, OFFSET(probesize), FF_OPT_TYPE_INT, 32000, 32, INT_MAX, D}, /* 32000 from mpegts.c: 1.0 second at 24Mbit/s */
+{"muxrate", "set mux rate", OFFSET(mux_rate), FF_OPT_TYPE_INT, DEFAULT, 0, INT_MAX, E},
+{"packetsize", "set packet size", OFFSET(packet_size), FF_OPT_TYPE_INT, DEFAULT, 0, INT_MAX, E},
+{"fflags", NULL, OFFSET(flags), FF_OPT_TYPE_FLAGS, DEFAULT, INT_MIN, INT_MAX, D|E, "fflags"},
+{"ignidx", "ignore index", 0, FF_OPT_TYPE_CONST, AVFMT_FLAG_IGNIDX, INT_MIN, INT_MAX, D, "fflags"},
+{"genpts", "generate pts", 0, FF_OPT_TYPE_CONST, AVFMT_FLAG_GENPTS, INT_MIN, INT_MAX, D, "fflags"},
+{"track", " set the track number", OFFSET(track), FF_OPT_TYPE_INT, DEFAULT, 0, INT_MAX, E},
+{"year", "set the year", OFFSET(year), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, E},
+{NULL},
+};
+
+#undef E
+#undef D
+#undef DEFAULT
+
+static const AVClass av_format_context_class = { "AVFormatContext", format_to_name, options };
+
+#if LIBAVFORMAT_VERSION_INT >= ((51<<16)+(0<<8)+0)
+static
+#endif
+void avformat_get_context_defaults(AVFormatContext *s){
+ memset(s, 0, sizeof(AVFormatContext));
+
+ s->av_class = &av_format_context_class;
+
+ av_opt_set_defaults(s);
+}
+
+AVFormatContext *av_alloc_format_context(void)
+{
+ AVFormatContext *ic;
+ ic = av_malloc(sizeof(AVFormatContext));
+ if (!ic) return ic;
+ avformat_get_context_defaults(ic);
+ ic->av_class = &av_format_context_class;
+ return ic;
+}
+
+/**
+ * Allocates all the structures needed to read an input stream.
+ * This does not open the needed codecs for decoding the stream[s].
+ */
+int av_open_input_stream(AVFormatContext **ic_ptr,
+ ByteIOContext *pb, const char *filename,
+ AVInputFormat *fmt, AVFormatParameters *ap)
+{
+ int err;
+ AVFormatContext *ic;
+ AVFormatParameters default_ap;
+
+ if(!ap){
+ ap=&default_ap;
+ memset(ap, 0, sizeof(default_ap));
+ }
+
+ if(!ap->prealloced_context)
+ ic = av_alloc_format_context();
+ else
+ ic = *ic_ptr;
+ if (!ic) {
+ err = AVERROR_NOMEM;
+ goto fail;
+ }
+ ic->iformat = fmt;
+ if (pb)
+ ic->pb = *pb;
+ ic->duration = AV_NOPTS_VALUE;
+ ic->start_time = AV_NOPTS_VALUE;
+ pstrcpy(ic->filename, sizeof(ic->filename), filename);
+
+ /* allocate private data */
+ if (fmt->priv_data_size > 0) {
+ ic->priv_data = av_mallocz(fmt->priv_data_size);
+ if (!ic->priv_data) {
+ err = AVERROR_NOMEM;
+ goto fail;
+ }
+ } else {
+ ic->priv_data = NULL;
+ }
+
+ err = ic->iformat->read_header(ic, ap);
+ if (err < 0)
+ goto fail;
+
+ if (pb && !ic->data_offset)
+ ic->data_offset = url_ftell(&ic->pb);
+
+ *ic_ptr = ic;
+ return 0;
+ fail:
+ if (ic) {
+ av_freep(&ic->priv_data);
+ }
+ av_free(ic);
+ *ic_ptr = NULL;
+ return err;
+}
+
+/** Size of probe buffer, for guessing file type from file contents. */
+#define PROBE_BUF_MIN 2048
+#define PROBE_BUF_MAX (1<<20)
+
+/**
+ * Open a media file as input. The codec are not opened. Only the file
+ * header (if present) is read.
+ *
+ * @param ic_ptr the opened media file handle is put here
+ * @param filename filename to open.
+ * @param fmt if non NULL, force the file format to use
+ * @param buf_size optional buffer size (zero if default is OK)
+ * @param ap additionnal parameters needed when opening the file (NULL if default)
+ * @return 0 if OK. AVERROR_xxx otherwise.
+ */
+int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
+ AVInputFormat *fmt,
+ int buf_size,
+ AVFormatParameters *ap)
+{
+ int err, must_open_file, file_opened, probe_size;
+ AVProbeData probe_data, *pd = &probe_data;
+ ByteIOContext pb1, *pb = &pb1;
+
+ file_opened = 0;
+ pd->filename = "";
+ if (filename)
+ pd->filename = filename;
+ pd->buf = NULL;
+ pd->buf_size = 0;
+
+ if (!fmt) {
+ /* guess format if no file can be opened */
+ fmt = av_probe_input_format(pd, 0);
+ }
+
+ /* do not open file if the format does not need it. XXX: specific
+ hack needed to handle RTSP/TCP */
+ must_open_file = 1;
+ if (fmt && (fmt->flags & AVFMT_NOFILE)) {
+ must_open_file = 0;
+ pb= NULL; //FIXME this or memset(pb, 0, sizeof(ByteIOContext)); otherwise its uninitalized
+ }
+
+ if (!fmt || must_open_file) {
+ /* if no file needed do not try to open one */
+ if (url_fopen(pb, filename, URL_RDONLY) < 0) {
+ err = AVERROR_IO;
+ goto fail;
+ }
+ file_opened = 1;
+ if (buf_size > 0) {
+ url_setbufsize(pb, buf_size);
+ }
+
+ for(probe_size= PROBE_BUF_MIN; probe_size<=PROBE_BUF_MAX && !fmt; probe_size<<=1){
+ /* read probe data */
+ pd->buf= av_realloc(pd->buf, probe_size);
+ pd->buf_size = get_buffer(pb, pd->buf, probe_size);
+ if (url_fseek(pb, 0, SEEK_SET) == (offset_t)-EPIPE) {
+ url_fclose(pb);
+ if (url_fopen(pb, filename, URL_RDONLY) < 0) {
+ file_opened = 0;
+ err = AVERROR_IO;
+ goto fail;
+ }
+ }
+ /* guess file format */
+ fmt = av_probe_input_format(pd, 1);
+ }
+ av_freep(&pd->buf);
+ }
+
+ /* if still no format found, error */
+ if (!fmt) {
+ err = AVERROR_NOFMT;
+ goto fail;
+ }
+
+ /* XXX: suppress this hack for redirectors */
+#ifdef CONFIG_NETWORK
+ if (fmt == &redir_demuxer) {
+ err = redir_open(ic_ptr, pb);
+ url_fclose(pb);
+ return err;
+ }
+#endif
+
+ /* check filename in case of an image number is expected */
+ if (fmt->flags & AVFMT_NEEDNUMBER) {
+ if (!av_filename_number_test(filename)) {
+ err = AVERROR_NUMEXPECTED;
+ goto fail;
+ }
+ }
+ err = av_open_input_stream(ic_ptr, pb, filename, fmt, ap);
+ if (err)
+ goto fail;
+ return 0;
+ fail:
+ av_freep(&pd->buf);
+ if (file_opened)
+ url_fclose(pb);
+ *ic_ptr = NULL;
+ return err;
+
+}
+
+/*******************************************************/
+
+/**
+ * Read a transport packet from a media file.
+ *
+ * This function is absolete and should never be used.
+ * Use av_read_frame() instead.
+ *
+ * @param s media file handle
+ * @param pkt is filled
+ * @return 0 if OK. AVERROR_xxx if error.
+ */
+int av_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ return s->iformat->read_packet(s, pkt);
+}
+
+/**********************************************************/
+
+/**
+ * Get the number of samples of an audio frame. Return (-1) if error.
+ */
+static int get_audio_frame_size(AVCodecContext *enc, int size)
+{
+ int frame_size;
+
+ if (enc->frame_size <= 1) {
+ int bits_per_sample = av_get_bits_per_sample(enc->codec_id);
+
+ if (bits_per_sample) {
+ if (enc->channels == 0)
+ return -1;
+ frame_size = (size << 3) / (bits_per_sample * enc->channels);
+ } else {
+ /* used for example by ADPCM codecs */
+ if (enc->bit_rate == 0)
+ return -1;
+ frame_size = (size * 8 * enc->sample_rate) / enc->bit_rate;
+ }
+ } else {
+ frame_size = enc->frame_size;
+ }
+ return frame_size;
+}
+
+
+/**
+ * Return the frame duration in seconds, return 0 if not available.
+ */
+static void compute_frame_duration(int *pnum, int *pden, AVStream *st,
+ AVCodecParserContext *pc, AVPacket *pkt)
+{
+ int frame_size;
+
+ *pnum = 0;
+ *pden = 0;
+ switch(st->codec->codec_type) {
+ case CODEC_TYPE_VIDEO:
+ if(st->time_base.num*1000LL > st->time_base.den){
+ *pnum = st->time_base.num;
+ *pden = st->time_base.den;
+ }else if(st->codec->time_base.num*1000LL > st->codec->time_base.den){
+ *pnum = st->codec->time_base.num;
+ *pden = st->codec->time_base.den;
+ if (pc && pc->repeat_pict) {
+ *pden *= 2;
+ *pnum = (*pnum) * (2 + pc->repeat_pict);
+ }
+ }
+ break;
+ case CODEC_TYPE_AUDIO:
+ frame_size = get_audio_frame_size(st->codec, pkt->size);
+ if (frame_size < 0)
+ break;
+ *pnum = frame_size;
+ *pden = st->codec->sample_rate;
+ break;
+ default:
+ break;
+ }
+}
+
+static int is_intra_only(AVCodecContext *enc){
+ if(enc->codec_type == CODEC_TYPE_AUDIO){
+ return 1;
+ }else if(enc->codec_type == CODEC_TYPE_VIDEO){
+ switch(enc->codec_id){
+ case CODEC_ID_MJPEG:
+ case CODEC_ID_MJPEGB:
+ case CODEC_ID_LJPEG:
+ case CODEC_ID_RAWVIDEO:
+ case CODEC_ID_DVVIDEO:
+ case CODEC_ID_HUFFYUV:
+ case CODEC_ID_FFVHUFF:
+ case CODEC_ID_ASV1:
+ case CODEC_ID_ASV2:
+ case CODEC_ID_VCR1:
+ return 1;
+ default: break;
+ }
+ }
+ return 0;
+}
+
+static int64_t lsb2full(int64_t lsb, int64_t last_ts, int lsb_bits){
+ int64_t mask = lsb_bits < 64 ? (1LL<<lsb_bits)-1 : -1LL;
+ int64_t delta= last_ts - mask/2;
+ return ((lsb - delta)&mask) + delta;
+}
+
+static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
+ AVCodecParserContext *pc, AVPacket *pkt)
+{
+ int num, den, presentation_delayed;
+ /* handle wrapping */
+ if(st->cur_dts != AV_NOPTS_VALUE){
+ if(pkt->pts != AV_NOPTS_VALUE)
+ pkt->pts= lsb2full(pkt->pts, st->cur_dts, st->pts_wrap_bits);
+ if(pkt->dts != AV_NOPTS_VALUE)
+ pkt->dts= lsb2full(pkt->dts, st->cur_dts, st->pts_wrap_bits);
+ }
+
+ if (pkt->duration == 0) {
+ compute_frame_duration(&num, &den, st, pc, pkt);
+ if (den && num) {
+ pkt->duration = av_rescale(1, num * (int64_t)st->time_base.den, den * (int64_t)st->time_base.num);
+ }
+ }
+
+ if(is_intra_only(st->codec))
+ pkt->flags |= PKT_FLAG_KEY;
+
+ /* do we have a video B frame ? */
+ presentation_delayed = 0;
+ if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ /* XXX: need has_b_frame, but cannot get it if the codec is
+ not initialized */
+ if (( st->codec->codec_id == CODEC_ID_H264
+ || st->codec->has_b_frames) &&
+ pc && pc->pict_type != FF_B_TYPE)
+ presentation_delayed = 1;
+ /* this may be redundant, but it shouldnt hurt */
+ if(pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts > pkt->dts)
+ presentation_delayed = 1;
+ }
+
+ if(st->cur_dts == AV_NOPTS_VALUE){
+ if(presentation_delayed) st->cur_dts = -pkt->duration;
+ else st->cur_dts = 0;
+ }
+
+// av_log(NULL, AV_LOG_DEBUG, "IN delayed:%d pts:%"PRId64", dts:%"PRId64" cur_dts:%"PRId64" st:%d pc:%p\n", presentation_delayed, pkt->pts, pkt->dts, st->cur_dts, pkt->stream_index, pc);
+ /* interpolate PTS and DTS if they are not present */
+ if (presentation_delayed) {
+ /* DTS = decompression time stamp */
+ /* PTS = presentation time stamp */
+ if (pkt->dts == AV_NOPTS_VALUE) {
+ /* if we know the last pts, use it */
+ if(st->last_IP_pts != AV_NOPTS_VALUE)
+ st->cur_dts = pkt->dts = st->last_IP_pts;
+ else
+ pkt->dts = st->cur_dts;
+ } else {
+ st->cur_dts = pkt->dts;
+ }
+ /* this is tricky: the dts must be incremented by the duration
+ of the frame we are displaying, i.e. the last I or P frame */
+ if (st->last_IP_duration == 0)
+ st->cur_dts += pkt->duration;
+ else
+ st->cur_dts += st->last_IP_duration;
+ st->last_IP_duration = pkt->duration;
+ st->last_IP_pts= pkt->pts;
+ /* cannot compute PTS if not present (we can compute it only
+ by knowing the futur */
+ } else if(pkt->pts != AV_NOPTS_VALUE || pkt->dts != AV_NOPTS_VALUE || pkt->duration){
+ if(pkt->pts != AV_NOPTS_VALUE && pkt->duration){
+ int64_t old_diff= FFABS(st->cur_dts - pkt->duration - pkt->pts);
+ int64_t new_diff= FFABS(st->cur_dts - pkt->pts);
+ if(old_diff < new_diff && old_diff < (pkt->duration>>3)){
+ pkt->pts += pkt->duration;
+// av_log(NULL, AV_LOG_DEBUG, "id:%d old:%"PRId64" new:%"PRId64" dur:%d cur:%"PRId64" size:%d\n", pkt->stream_index, old_diff, new_diff, pkt->duration, st->cur_dts, pkt->size);
+ }
+ }
+
+ /* presentation is not delayed : PTS and DTS are the same */
+ if (pkt->pts == AV_NOPTS_VALUE) {
+ if (pkt->dts == AV_NOPTS_VALUE) {
+ pkt->pts = st->cur_dts;
+ pkt->dts = st->cur_dts;
+ }
+ else {
+ st->cur_dts = pkt->dts;
+ pkt->pts = pkt->dts;
+ }
+ } else {
+ st->cur_dts = pkt->pts;
+ pkt->dts = pkt->pts;
+ }
+ st->cur_dts += pkt->duration;
+ }
+// av_log(NULL, AV_LOG_DEBUG, "OUTdelayed:%d pts:%"PRId64", dts:%"PRId64" cur_dts:%"PRId64"\n", presentation_delayed, pkt->pts, pkt->dts, st->cur_dts);
+
+ /* update flags */
+ if (pc) {
+ pkt->flags = 0;
+ /* key frame computation */
+ switch(st->codec->codec_type) {
+ case CODEC_TYPE_VIDEO:
+ if (pc->pict_type == FF_I_TYPE)
+ pkt->flags |= PKT_FLAG_KEY;
+ break;
+ case CODEC_TYPE_AUDIO:
+ pkt->flags |= PKT_FLAG_KEY;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void av_destruct_packet_nofree(AVPacket *pkt)
+{
+ pkt->data = NULL; pkt->size = 0;
+}
+
+static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
+{
+ AVStream *st;
+ int len, ret, i;
+
+ for(;;) {
+ /* select current input stream component */
+ st = s->cur_st;
+ if (st) {
+ if (!st->need_parsing || !st->parser) {
+ /* no parsing needed: we just output the packet as is */
+ /* raw data support */
+ *pkt = s->cur_pkt;
+ compute_pkt_fields(s, st, NULL, pkt);
+ s->cur_st = NULL;
+ break;
+ } else if (s->cur_len > 0 && st->discard < AVDISCARD_ALL) {
+ len = av_parser_parse(st->parser, st->codec, &pkt->data, &pkt->size,
+ s->cur_ptr, s->cur_len,
+ s->cur_pkt.pts, s->cur_pkt.dts);
+ s->cur_pkt.pts = AV_NOPTS_VALUE;
+ s->cur_pkt.dts = AV_NOPTS_VALUE;
+ /* increment read pointer */
+ s->cur_ptr += len;
+ s->cur_len -= len;
+
+ /* return packet if any */
+ if (pkt->size) {
+ got_packet:
+ pkt->duration = 0;
+ pkt->stream_index = st->index;
+ pkt->pts = st->parser->pts;
+ pkt->dts = st->parser->dts;
+ pkt->destruct = av_destruct_packet_nofree;
+ compute_pkt_fields(s, st, st->parser, pkt);
+ break;
+ }
+ } else {
+ /* free packet */
+ av_free_packet(&s->cur_pkt);
+ s->cur_st = NULL;
+ }
+ } else {
+ /* read next packet */
+ ret = av_read_packet(s, &s->cur_pkt);
+ if (ret < 0) {
+ if (ret == -EAGAIN)
+ return ret;
+ /* return the last frames, if any */
+ for(i = 0; i < s->nb_streams; i++) {
+ st = s->streams[i];
+ if (st->parser && st->need_parsing) {
+ av_parser_parse(st->parser, st->codec,
+ &pkt->data, &pkt->size,
+ NULL, 0,
+ AV_NOPTS_VALUE, AV_NOPTS_VALUE);
+ if (pkt->size)
+ goto got_packet;
+ }
+ }
+ /* no more packets: really terminates parsing */
+ return ret;
+ }
+
+ st = s->streams[s->cur_pkt.stream_index];
+ if(st->codec->debug & FF_DEBUG_PTS)
+ av_log(s, AV_LOG_DEBUG, "av_read_packet stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d\n",
+ s->cur_pkt.stream_index,
+ s->cur_pkt.pts,
+ s->cur_pkt.dts,
+ s->cur_pkt.size);
+
+ s->cur_st = st;
+ s->cur_ptr = s->cur_pkt.data;
+ s->cur_len = s->cur_pkt.size;
+ if (st->need_parsing && !st->parser) {
+ st->parser = av_parser_init(st->codec->codec_id);
+ if (!st->parser) {
+ /* no parser available : just output the raw packets */
+ st->need_parsing = 0;
+ }else if(st->need_parsing == 2){
+ st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
+ }
+ }
+ }
+ }
+ if(st->codec->debug & FF_DEBUG_PTS)
+ av_log(s, AV_LOG_DEBUG, "av_read_frame_internal stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d\n",
+ pkt->stream_index,
+ pkt->pts,
+ pkt->dts,
+ pkt->size);
+
+ return 0;
+}
+
+/**
+ * Return the next frame of a stream.
+ *
+ * The returned packet is valid
+ * until the next av_read_frame() or until av_close_input_file() and
+ * must be freed with av_free_packet. For video, the packet contains
+ * exactly one frame. For audio, it contains an integer number of
+ * frames if each frame has a known fixed size (e.g. PCM or ADPCM
+ * data). If the audio frames have a variable size (e.g. MPEG audio),
+ * then it contains one frame.
+ *
+ * pkt->pts, pkt->dts and pkt->duration are always set to correct
+ * values in AV_TIME_BASE unit (and guessed if the format cannot
+ * provided them). pkt->pts can be AV_NOPTS_VALUE if the video format
+ * has B frames, so it is better to rely on pkt->dts if you do not
+ * decompress the payload.
+ *
+ * @return 0 if OK, < 0 if error or end of file.
+ */
+int av_read_frame(AVFormatContext *s, AVPacket *pkt)
+{
+ AVPacketList *pktl;
+ int eof=0;
+ const int genpts= s->flags & AVFMT_FLAG_GENPTS;
+
+ for(;;){
+ pktl = s->packet_buffer;
+ if (pktl) {
+ AVPacket *next_pkt= &pktl->pkt;
+
+ if(genpts && next_pkt->dts != AV_NOPTS_VALUE){
+ while(pktl && next_pkt->pts == AV_NOPTS_VALUE){
+ if( pktl->pkt.stream_index == next_pkt->stream_index
+ && next_pkt->dts < pktl->pkt.dts
+ && pktl->pkt.pts != pktl->pkt.dts //not b frame
+ /*&& pktl->pkt.dts != AV_NOPTS_VALUE*/){
+ next_pkt->pts= pktl->pkt.dts;
+ }
+ pktl= pktl->next;
+ }
+ pktl = s->packet_buffer;
+ }
+
+ if( next_pkt->pts != AV_NOPTS_VALUE
+ || next_pkt->dts == AV_NOPTS_VALUE
+ || !genpts || eof){
+ /* read packet from packet buffer, if there is data */
+ *pkt = *next_pkt;
+ s->packet_buffer = pktl->next;
+ av_free(pktl);
+ return 0;
+ }
+ }
+ if(genpts){
+ AVPacketList **plast_pktl= &s->packet_buffer;
+ int ret= av_read_frame_internal(s, pkt);
+ if(ret<0){
+ if(pktl && ret != -EAGAIN){
+ eof=1;
+ continue;
+ }else
+ return ret;
+ }
+
+ /* duplicate the packet */
+ if (av_dup_packet(pkt) < 0)
+ return AVERROR_NOMEM;
+
+ while(*plast_pktl) plast_pktl= &(*plast_pktl)->next; //FIXME maybe maintain pointer to the last?
+
+ pktl = av_mallocz(sizeof(AVPacketList));
+ if (!pktl)
+ return AVERROR_NOMEM;
+
+ /* add the packet in the buffered packet list */
+ *plast_pktl = pktl;
+ pktl->pkt= *pkt;
+ }else{
+ assert(!s->packet_buffer);
+ return av_read_frame_internal(s, pkt);
+ }
+ }
+}
+
+/* XXX: suppress the packet queue */
+static void flush_packet_queue(AVFormatContext *s)
+{
+ AVPacketList *pktl;
+
+ for(;;) {
+ pktl = s->packet_buffer;
+ if (!pktl)
+ break;
+ s->packet_buffer = pktl->next;
+ av_free_packet(&pktl->pkt);
+ av_free(pktl);
+ }
+}
+
+/*******************************************************/
+/* seek support */
+
+int av_find_default_stream_index(AVFormatContext *s)
+{
+ int i;
+ AVStream *st;
+
+ if (s->nb_streams <= 0)
+ return -1;
+ for(i = 0; i < s->nb_streams; i++) {
+ st = s->streams[i];
+ if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ return i;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Flush the frame reader.
+ */
+static void av_read_frame_flush(AVFormatContext *s)
+{
+ AVStream *st;
+ int i;
+
+ flush_packet_queue(s);
+
+ /* free previous packet */
+ if (s->cur_st) {
+ if (s->cur_st->parser)
+ av_free_packet(&s->cur_pkt);
+ s->cur_st = NULL;
+ }
+ /* fail safe */
+ s->cur_ptr = NULL;
+ s->cur_len = 0;
+
+ /* for each stream, reset read state */
+ for(i = 0; i < s->nb_streams; i++) {
+ st = s->streams[i];
+
+ if (st->parser) {
+ av_parser_close(st->parser);
+ st->parser = NULL;
+ }
+ st->last_IP_pts = AV_NOPTS_VALUE;
+ st->cur_dts = 0; /* we set the current DTS to an unspecified origin */
+ }
+}
+
+/**
+ * Updates cur_dts of all streams based on given timestamp and AVStream.
+ *
+ * Stream ref_st unchanged, others set cur_dts in their native timebase
+ * only needed for timestamp wrapping or if (dts not set and pts!=dts)
+ * @param timestamp new dts expressed in time_base of param ref_st
+ * @param ref_st reference stream giving time_base of param timestamp
+ */
+void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp){
+ int i;
+
+ for(i = 0; i < s->nb_streams; i++) {
+ AVStream *st = s->streams[i];
+
+ st->cur_dts = av_rescale(timestamp,
+ st->time_base.den * (int64_t)ref_st->time_base.num,
+ st->time_base.num * (int64_t)ref_st->time_base.den);
+ }
+}
+
+/**
+ * Add a index entry into a sorted list updateing if it is already there.
+ *
+ * @param timestamp timestamp in the timebase of the given stream
+ */
+int av_add_index_entry(AVStream *st,
+ int64_t pos, int64_t timestamp, int size, int distance, int flags)
+{
+ AVIndexEntry *entries, *ie;
+ int index;
+
+ if((unsigned)st->nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry))
+ return -1;
+
+ entries = av_fast_realloc(st->index_entries,
+ &st->index_entries_allocated_size,
+ (st->nb_index_entries + 1) *
+ sizeof(AVIndexEntry));
+ if(!entries)
+ return -1;
+
+ st->index_entries= entries;
+
+ index= av_index_search_timestamp(st, timestamp, AVSEEK_FLAG_ANY);
+
+ if(index<0){
+ index= st->nb_index_entries++;
+ ie= &entries[index];
+ assert(index==0 || ie[-1].timestamp < timestamp);
+ }else{
+ ie= &entries[index];
+ if(ie->timestamp != timestamp){
+ if(ie->timestamp <= timestamp)
+ return -1;
+ memmove(entries + index + 1, entries + index, sizeof(AVIndexEntry)*(st->nb_index_entries - index));
+ st->nb_index_entries++;
+ }else if(ie->pos == pos && distance < ie->min_distance) //dont reduce the distance
+ distance= ie->min_distance;
+ }
+
+ ie->pos = pos;
+ ie->timestamp = timestamp;
+ ie->min_distance= distance;
+ ie->size= size;
+ ie->flags = flags;
+
+ return index;
+}
+
+/**
+ * build an index for raw streams using a parser.
+ */
+static void av_build_index_raw(AVFormatContext *s)
+{
+ AVPacket pkt1, *pkt = &pkt1;
+ int ret;
+ AVStream *st;
+
+ st = s->streams[0];
+ av_read_frame_flush(s);
+ url_fseek(&s->pb, s->data_offset, SEEK_SET);
+
+ for(;;) {
+ ret = av_read_frame(s, pkt);
+ if (ret < 0)
+ break;
+ if (pkt->stream_index == 0 && st->parser &&
+ (pkt->flags & PKT_FLAG_KEY)) {
+ av_add_index_entry(st, st->parser->frame_offset, pkt->dts,
+ 0, 0, AVINDEX_KEYFRAME);
+ }
+ av_free_packet(pkt);
+ }
+}
+
+/**
+ * Returns TRUE if we deal with a raw stream.
+ *
+ * Raw codec data and parsing needed.
+ */
+static int is_raw_stream(AVFormatContext *s)
+{
+ AVStream *st;
+
+ if (s->nb_streams != 1)
+ return 0;
+ st = s->streams[0];
+ if (!st->need_parsing)
+ return 0;
+ return 1;
+}
+
+/**
+ * Gets the index for a specific timestamp.
+ * @param flags if AVSEEK_FLAG_BACKWARD then the returned index will correspond to
+ * the timestamp which is <= the requested one, if backward is 0
+ * then it will be >=
+ * if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise
+ * @return < 0 if no such timestamp could be found
+ */
+int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp,
+ int flags)
+{
+ AVIndexEntry *entries= st->index_entries;
+ int nb_entries= st->nb_index_entries;
+ int a, b, m;
+ int64_t timestamp;
+
+ a = - 1;
+ b = nb_entries;
+
+ while (b - a > 1) {
+ m = (a + b) >> 1;
+ timestamp = entries[m].timestamp;
+ if(timestamp >= wanted_timestamp)
+ b = m;
+ if(timestamp <= wanted_timestamp)
+ a = m;
+ }
+ m= (flags & AVSEEK_FLAG_BACKWARD) ? a : b;
+
+ if(!(flags & AVSEEK_FLAG_ANY)){
+ while(m>=0 && m<nb_entries && !(entries[m].flags & AVINDEX_KEYFRAME)){
+ m += (flags & AVSEEK_FLAG_BACKWARD) ? -1 : 1;
+ }
+ }
+
+ if(m == nb_entries)
+ return -1;
+ return m;
+}
+
+#define DEBUG_SEEK
+
+/**
+ * Does a binary search using av_index_search_timestamp() and AVCodec.read_timestamp().
+ * this isnt supposed to be called directly by a user application, but by demuxers
+ * @param target_ts target timestamp in the time base of the given stream
+ * @param stream_index stream number
+ */
+int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags){
+ AVInputFormat *avif= s->iformat;
+ int64_t pos_min, pos_max, pos, pos_limit;
+ int64_t ts_min, ts_max, ts;
+ int index;
+ AVStream *st;
+
+ if (stream_index < 0)
+ return -1;
+
+#ifdef DEBUG_SEEK
+ av_log(s, AV_LOG_DEBUG, "read_seek: %d %"PRId64"\n", stream_index, target_ts);
+#endif
+
+ ts_max=
+ ts_min= AV_NOPTS_VALUE;
+ pos_limit= -1; //gcc falsely says it may be uninitalized
+
+ st= s->streams[stream_index];
+ if(st->index_entries){
+ AVIndexEntry *e;
+
+ index= av_index_search_timestamp(st, target_ts, flags | AVSEEK_FLAG_BACKWARD); //FIXME whole func must be checked for non keyframe entries in index case, especially read_timestamp()
+ index= FFMAX(index, 0);
+ e= &st->index_entries[index];
+
+ if(e->timestamp <= target_ts || e->pos == e->min_distance){
+ pos_min= e->pos;
+ ts_min= e->timestamp;
+#ifdef DEBUG_SEEK
+ av_log(s, AV_LOG_DEBUG, "using cached pos_min=0x%"PRIx64" dts_min=%"PRId64"\n",
+ pos_min,ts_min);
+#endif
+ }else{
+ assert(index==0);
+ }
+
+ index= av_index_search_timestamp(st, target_ts, flags & ~AVSEEK_FLAG_BACKWARD);
+ assert(index < st->nb_index_entries);
+ if(index >= 0){
+ e= &st->index_entries[index];
+ assert(e->timestamp >= target_ts);
+ pos_max= e->pos;
+ ts_max= e->timestamp;
+ pos_limit= pos_max - e->min_distance;
+#ifdef DEBUG_SEEK
+ av_log(s, AV_LOG_DEBUG, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64" dts_max=%"PRId64"\n",
+ pos_max,pos_limit, ts_max);
+#endif
+ }
+ }
+
+ pos= av_gen_search(s, stream_index, target_ts, pos_min, pos_max, pos_limit, ts_min, ts_max, flags, &ts, avif->read_timestamp);
+ if(pos<0)
+ return -1;
+
+ /* do the seek */
+ url_fseek(&s->pb, pos, SEEK_SET);
+
+ av_update_cur_dts(s, st, ts);
+
+ return 0;
+}
+
+/**
+ * Does a binary search using read_timestamp().
+ * this isnt supposed to be called directly by a user application, but by demuxers
+ * @param target_ts target timestamp in the time base of the given stream
+ * @param stream_index stream number
+ */
+int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, int64_t pos_min, int64_t pos_max, int64_t pos_limit, int64_t ts_min, int64_t ts_max, int flags, int64_t *ts_ret, int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t )){
+ int64_t pos, ts;
+ int64_t start_pos, filesize;
+ int no_change;
+
+#ifdef DEBUG_SEEK
+ av_log(s, AV_LOG_DEBUG, "gen_seek: %d %"PRId64"\n", stream_index, target_ts);
+#endif
+
+ if(ts_min == AV_NOPTS_VALUE){
+ pos_min = s->data_offset;
+ ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX);
+ if (ts_min == AV_NOPTS_VALUE)
+ return -1;
+ }
+
+ if(ts_max == AV_NOPTS_VALUE){
+ int step= 1024;
+ filesize = url_fsize(&s->pb);
+ pos_max = filesize - 1;
+ do{
+ pos_max -= step;
+ ts_max = read_timestamp(s, stream_index, &pos_max, pos_max + step);
+ step += step;
+ }while(ts_max == AV_NOPTS_VALUE && pos_max >= step);
+ if (ts_max == AV_NOPTS_VALUE)
+ return -1;
+
+ for(;;){
+ int64_t tmp_pos= pos_max + 1;
+ int64_t tmp_ts= read_timestamp(s, stream_index, &tmp_pos, INT64_MAX);
+ if(tmp_ts == AV_NOPTS_VALUE)
+ break;
+ ts_max= tmp_ts;
+ pos_max= tmp_pos;
+ if(tmp_pos >= filesize)
+ break;
+ }
+ pos_limit= pos_max;
+ }
+
+ if(ts_min > ts_max){
+ return -1;
+ }else if(ts_min == ts_max){
+ pos_limit= pos_min;
+ }
+
+ no_change=0;
+ while (pos_min < pos_limit) {
+#ifdef DEBUG_SEEK
+ av_log(s, AV_LOG_DEBUG, "pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%"PRId64" dts_max=%"PRId64"\n",
+ pos_min, pos_max,
+ ts_min, ts_max);
+#endif
+ assert(pos_limit <= pos_max);
+
+ if(no_change==0){
+ int64_t approximate_keyframe_distance= pos_max - pos_limit;
+ // interpolate position (better than dichotomy)
+ pos = av_rescale(target_ts - ts_min, pos_max - pos_min, ts_max - ts_min)
+ + pos_min - approximate_keyframe_distance;
+ }else if(no_change==1){
+ // bisection, if interpolation failed to change min or max pos last time
+ pos = (pos_min + pos_limit)>>1;
+ }else{
+ // linear search if bisection failed, can only happen if there are very few or no keframes between min/max
+ pos=pos_min;
+ }
+ if(pos <= pos_min)
+ pos= pos_min + 1;
+ else if(pos > pos_limit)
+ pos= pos_limit;
+ start_pos= pos;
+
+ ts = read_timestamp(s, stream_index, &pos, INT64_MAX); //may pass pos_limit instead of -1
+ if(pos == pos_max)
+ no_change++;
+ else
+ no_change=0;
+#ifdef DEBUG_SEEK
+av_log(s, AV_LOG_DEBUG, "%"PRId64" %"PRId64" %"PRId64" / %"PRId64" %"PRId64" %"PRId64" target:%"PRId64" limit:%"PRId64" start:%"PRId64" noc:%d\n", pos_min, pos, pos_max, ts_min, ts, ts_max, target_ts, pos_limit, start_pos, no_change);
+#endif
+ assert(ts != AV_NOPTS_VALUE);
+ if (target_ts <= ts) {
+ pos_limit = start_pos - 1;
+ pos_max = pos;
+ ts_max = ts;
+ }
+ if (target_ts >= ts) {
+ pos_min = pos;
+ ts_min = ts;
+ }
+ }
+
+ pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max;
+ ts = (flags & AVSEEK_FLAG_BACKWARD) ? ts_min : ts_max;
+#ifdef DEBUG_SEEK
+ pos_min = pos;
+ ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX);
+ pos_min++;
+ ts_max = read_timestamp(s, stream_index, &pos_min, INT64_MAX);
+ av_log(s, AV_LOG_DEBUG, "pos=0x%"PRIx64" %"PRId64"<=%"PRId64"<=%"PRId64"\n",
+ pos, ts_min, target_ts, ts_max);
+#endif
+ *ts_ret= ts;
+ return pos;
+}
+
+static int av_seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, int flags){
+ int64_t pos_min, pos_max;
+#if 0
+ AVStream *st;
+
+ if (stream_index < 0)
+ return -1;
+
+ st= s->streams[stream_index];
+#endif
+
+ pos_min = s->data_offset;
+ pos_max = url_fsize(&s->pb) - 1;
+
+ if (pos < pos_min) pos= pos_min;
+ else if(pos > pos_max) pos= pos_max;
+
+ url_fseek(&s->pb, pos, SEEK_SET);
+
+#if 0
+ av_update_cur_dts(s, st, ts);
+#endif
+ return 0;
+}
+
+static int av_seek_frame_generic(AVFormatContext *s,
+ int stream_index, int64_t timestamp, int flags)
+{
+ int index;
+ AVStream *st;
+ AVIndexEntry *ie;
+
+ if (!s->index_built) {
+ if (is_raw_stream(s)) {
+ av_build_index_raw(s);
+ } else {
+ return -1;
+ }
+ s->index_built = 1;
+ }
+
+ st = s->streams[stream_index];
+ index = av_index_search_timestamp(st, timestamp, flags);
+ if (index < 0)
+ return -1;
+
+ /* now we have found the index, we can seek */
+ ie = &st->index_entries[index];
+ av_read_frame_flush(s);
+ url_fseek(&s->pb, ie->pos, SEEK_SET);
+
+ av_update_cur_dts(s, st, ie->timestamp);
+
+ return 0;
+}
+
+/**
+ * Seek to the key frame at timestamp.
+ * 'timestamp' in 'stream_index'.
+ * @param stream_index If stream_index is (-1), a default
+ * stream is selected, and timestamp is automatically converted
+ * from AV_TIME_BASE units to the stream specific time_base.
+ * @param timestamp timestamp in AVStream.time_base units
+ * or if there is no stream specified then in AV_TIME_BASE units
+ * @param flags flags which select direction and seeking mode
+ * @return >= 0 on success
+ */
+int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
+{
+ int ret;
+ AVStream *st;
+
+ av_read_frame_flush(s);
+
+ if(flags & AVSEEK_FLAG_BYTE)
+ return av_seek_frame_byte(s, stream_index, timestamp, flags);
+
+ if(stream_index < 0){
+ stream_index= av_find_default_stream_index(s);
+ if(stream_index < 0)
+ return -1;
+
+ st= s->streams[stream_index];
+ /* timestamp for default must be expressed in AV_TIME_BASE units */
+ timestamp = av_rescale(timestamp, st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num);
+ }
+ st= s->streams[stream_index];
+
+ /* first, we try the format specific seek */
+ if (s->iformat->read_seek)
+ ret = s->iformat->read_seek(s, stream_index, timestamp, flags);
+ else
+ ret = -1;
+ if (ret >= 0) {
+ return 0;
+ }
+
+ if(s->iformat->read_timestamp)
+ return av_seek_frame_binary(s, stream_index, timestamp, flags);
+ else
+ return av_seek_frame_generic(s, stream_index, timestamp, flags);
+}
+
+/*******************************************************/
+
+/**
+ * Returns TRUE if the stream has accurate timings in any stream.
+ *
+ * @return TRUE if the stream has accurate timings for at least one component.
+ */
+static int av_has_timings(AVFormatContext *ic)
+{
+ int i;
+ AVStream *st;
+
+ for(i = 0;i < ic->nb_streams; i++) {
+ st = ic->streams[i];
+ if (st->start_time != AV_NOPTS_VALUE &&
+ st->duration != AV_NOPTS_VALUE)
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * Estimate the stream timings from the one of each components.
+ *
+ * Also computes the global bitrate if possible.
+ */
+static void av_update_stream_timings(AVFormatContext *ic)
+{
+ int64_t start_time, start_time1, end_time, end_time1;
+ int i;
+ AVStream *st;
+
+ start_time = MAXINT64;
+ end_time = MININT64;
+ for(i = 0;i < ic->nb_streams; i++) {
+ st = ic->streams[i];
+ if (st->start_time != AV_NOPTS_VALUE) {
+ start_time1= av_rescale_q(st->start_time, st->time_base, AV_TIME_BASE_Q);
+ if (start_time1 < start_time)
+ start_time = start_time1;
+ if (st->duration != AV_NOPTS_VALUE) {
+ end_time1 = start_time1
+ + av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);
+ if (end_time1 > end_time)
+ end_time = end_time1;
+ }
+ }
+ }
+ if (start_time != MAXINT64) {
+ ic->start_time = start_time;
+ if (end_time != MININT64) {
+ ic->duration = end_time - start_time;
+ if (ic->file_size > 0) {
+ /* compute the bit rate */
+ ic->bit_rate = (double)ic->file_size * 8.0 * AV_TIME_BASE /
+ (double)ic->duration;
+ }
+ }
+ }
+
+}
+
+static void fill_all_stream_timings(AVFormatContext *ic)
+{
+ int i;
+ AVStream *st;
+
+ av_update_stream_timings(ic);
+ for(i = 0;i < ic->nb_streams; i++) {
+ st = ic->streams[i];
+ if (st->start_time == AV_NOPTS_VALUE) {
+ if(ic->start_time != AV_NOPTS_VALUE)
+ st->start_time = av_rescale_q(ic->start_time, AV_TIME_BASE_Q, st->time_base);
+ if(ic->duration != AV_NOPTS_VALUE)
+ st->duration = av_rescale_q(ic->duration, AV_TIME_BASE_Q, st->time_base);
+ }
+ }
+}
+
+static void av_estimate_timings_from_bit_rate(AVFormatContext *ic)
+{
+ int64_t filesize, duration;
+ int bit_rate, i;
+ AVStream *st;
+
+ /* if bit_rate is already set, we believe it */
+ if (ic->bit_rate == 0) {
+ bit_rate = 0;
+ for(i=0;i<ic->nb_streams;i++) {
+ st = ic->streams[i];
+ bit_rate += st->codec->bit_rate;
+ }
+ ic->bit_rate = bit_rate;
+ }
+
+ /* if duration is already set, we believe it */
+ if (ic->duration == AV_NOPTS_VALUE &&
+ ic->bit_rate != 0 &&
+ ic->file_size != 0) {
+ filesize = ic->file_size;
+ if (filesize > 0) {
+ for(i = 0; i < ic->nb_streams; i++) {
+ st = ic->streams[i];
+ duration= av_rescale(8*filesize, st->time_base.den, ic->bit_rate*(int64_t)st->time_base.num);
+ if (st->start_time == AV_NOPTS_VALUE ||
+ st->duration == AV_NOPTS_VALUE) {
+ st->start_time = 0;
+ st->duration = duration;
+ }
+ }
+ }
+ }
+}
+
+#define DURATION_MAX_READ_SIZE 250000
+
+/* only usable for MPEG-PS streams */
+static void av_estimate_timings_from_pts(AVFormatContext *ic)
+{
+ AVPacket pkt1, *pkt = &pkt1;
+ AVStream *st;
+ int read_size, i, ret;
+ int64_t end_time;
+ int64_t filesize, offset, duration;
+
+ /* free previous packet */
+ if (ic->cur_st && ic->cur_st->parser)
+ av_free_packet(&ic->cur_pkt);
+ ic->cur_st = NULL;
+
+ /* flush packet queue */
+ flush_packet_queue(ic);
+
+ for(i=0;i<ic->nb_streams;i++) {
+ st = ic->streams[i];
+ if (st->parser) {
+ av_parser_close(st->parser);
+ st->parser= NULL;
+ }
+ }
+
+ /* we read the first packets to get the first PTS (not fully
+ accurate, but it is enough now) */
+ url_fseek(&ic->pb, 0, SEEK_SET);
+ read_size = 0;
+ for(;;) {
+ if (read_size >= DURATION_MAX_READ_SIZE)
+ break;
+ /* if all info is available, we can stop */
+ for(i = 0;i < ic->nb_streams; i++) {
+ st = ic->streams[i];
+ if (st->start_time == AV_NOPTS_VALUE)
+ break;
+ }
+ if (i == ic->nb_streams)
+ break;
+
+ ret = av_read_packet(ic, pkt);
+ if (ret != 0)
+ break;
+ read_size += pkt->size;
+ st = ic->streams[pkt->stream_index];
+ if (pkt->pts != AV_NOPTS_VALUE) {
+ if (st->start_time == AV_NOPTS_VALUE)
+ st->start_time = pkt->pts;
+ }
+ av_free_packet(pkt);
+ }
+
+ /* estimate the end time (duration) */
+ /* XXX: may need to support wrapping */
+ filesize = ic->file_size;
+ offset = filesize - DURATION_MAX_READ_SIZE;
+ if (offset < 0)
+ offset = 0;
+
+ url_fseek(&ic->pb, offset, SEEK_SET);
+ read_size = 0;
+ for(;;) {
+ if (read_size >= DURATION_MAX_READ_SIZE)
+ break;
+ /* if all info is available, we can stop */
+ for(i = 0;i < ic->nb_streams; i++) {
+ st = ic->streams[i];
+ if (st->duration == AV_NOPTS_VALUE)
+ break;
+ }
+ if (i == ic->nb_streams)
+ break;
+
+ ret = av_read_packet(ic, pkt);
+ if (ret != 0)
+ break;
+ read_size += pkt->size;
+ st = ic->streams[pkt->stream_index];
+ if (pkt->pts != AV_NOPTS_VALUE) {
+ end_time = pkt->pts;
+ duration = end_time - st->start_time;
+ if (duration > 0) {
+ if (st->duration == AV_NOPTS_VALUE ||
+ st->duration < duration)
+ st->duration = duration;
+ }
+ }
+ av_free_packet(pkt);
+ }
+
+ fill_all_stream_timings(ic);
+
+ url_fseek(&ic->pb, 0, SEEK_SET);
+}
+
+static void av_estimate_timings(AVFormatContext *ic)
+{
+ int64_t file_size;
+
+ /* get the file size, if possible */
+ if (ic->iformat->flags & AVFMT_NOFILE) {
+ file_size = 0;
+ } else {
+ file_size = url_fsize(&ic->pb);
+ if (file_size < 0)
+ file_size = 0;
+ }
+ ic->file_size = file_size;
+
+ if ((!strcmp(ic->iformat->name, "mpeg") ||
+ !strcmp(ic->iformat->name, "mpegts")) &&
+ file_size && !ic->pb.is_streamed) {
+ /* get accurate estimate from the PTSes */
+ av_estimate_timings_from_pts(ic);
+ } else if (av_has_timings(ic)) {
+ /* at least one components has timings - we use them for all
+ the components */
+ fill_all_stream_timings(ic);
+ } else {
+ /* less precise: use bit rate info */
+ av_estimate_timings_from_bit_rate(ic);
+ }
+ av_update_stream_timings(ic);
+
+#if 0
+ {
+ int i;
+ AVStream *st;
+ for(i = 0;i < ic->nb_streams; i++) {
+ st = ic->streams[i];
+ printf("%d: start_time: %0.3f duration: %0.3f\n",
+ i, (double)st->start_time / AV_TIME_BASE,
+ (double)st->duration / AV_TIME_BASE);
+ }
+ printf("stream: start_time: %0.3f duration: %0.3f bitrate=%d kb/s\n",
+ (double)ic->start_time / AV_TIME_BASE,
+ (double)ic->duration / AV_TIME_BASE,
+ ic->bit_rate / 1000);
+ }
+#endif
+}
+
+static int has_codec_parameters(AVCodecContext *enc)
+{
+ int val;
+ switch(enc->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ val = enc->sample_rate;
+ break;
+ case CODEC_TYPE_VIDEO:
+ val = enc->width && enc->pix_fmt != PIX_FMT_NONE;
+ break;
+ default:
+ val = 1;
+ break;
+ }
+ return (val != 0);
+}
+
+static int try_decode_frame(AVStream *st, const uint8_t *data, int size)
+{
+ int16_t *samples;
+ AVCodec *codec;
+ int got_picture, ret=0;
+ AVFrame picture;
+
+ if(!st->codec->codec){
+ codec = avcodec_find_decoder(st->codec->codec_id);
+ if (!codec)
+ return -1;
+ ret = avcodec_open(st->codec, codec);
+ if (ret < 0)
+ return ret;
+ }
+
+ if(!has_codec_parameters(st->codec)){
+ switch(st->codec->codec_type) {
+ case CODEC_TYPE_VIDEO:
+ ret = avcodec_decode_video(st->codec, &picture,
+ &got_picture, (uint8_t *)data, size);
+ break;
+ case CODEC_TYPE_AUDIO:
+ samples = av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
+ if (!samples)
+ goto fail;
+ ret = avcodec_decode_audio(st->codec, samples,
+ &got_picture, (uint8_t *)data, size);
+ av_free(samples);
+ break;
+ default:
+ break;
+ }
+ }
+ fail:
+ return ret;
+}
+
+/* absolute maximum size we read until we abort */
+#define MAX_READ_SIZE 5000000
+
+/* maximum duration until we stop analysing the stream */
+#define MAX_STREAM_DURATION ((int)(AV_TIME_BASE * 3.0))
+
+/**
+ * Read the beginning of a media file to get stream information. This
+ * is useful for file formats with no headers such as MPEG. This
+ * function also compute the real frame rate in case of mpeg2 repeat
+ * frame mode.
+ *
+ * @param ic media file handle
+ * @return >=0 if OK. AVERROR_xxx if error.
+ * @todo let user decide somehow what information is needed so we dont waste time geting stuff the user doesnt need
+ */
+int av_find_stream_info(AVFormatContext *ic)
+{
+ int i, count, ret, read_size, j;
+ AVStream *st;
+ AVPacket pkt1, *pkt;
+ AVPacketList *pktl=NULL, **ppktl;
+ int64_t last_dts[MAX_STREAMS];
+ int64_t duration_sum[MAX_STREAMS];
+ int duration_count[MAX_STREAMS]={0};
+
+ for(i=0;i<ic->nb_streams;i++) {
+ st = ic->streams[i];
+ if(st->codec->codec_type == CODEC_TYPE_VIDEO){
+/* if(!st->time_base.num)
+ st->time_base= */
+ if(!st->codec->time_base.num)
+ st->codec->time_base= st->time_base;
+ }
+ //only for the split stuff
+ if (!st->parser) {
+ st->parser = av_parser_init(st->codec->codec_id);
+ if(st->need_parsing == 2 && st->parser){
+ st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
+ }
+ }
+ }
+
+ for(i=0;i<MAX_STREAMS;i++){
+ last_dts[i]= AV_NOPTS_VALUE;
+ duration_sum[i]= INT64_MAX;
+ }
+
+ count = 0;
+ read_size = 0;
+ ppktl = &ic->packet_buffer;
+ for(;;) {
+ /* check if one codec still needs to be handled */
+ for(i=0;i<ic->nb_streams;i++) {
+ st = ic->streams[i];
+ if (!has_codec_parameters(st->codec))
+ break;
+ /* variable fps and no guess at the real fps */
+ if( st->codec->time_base.den >= 101LL*st->codec->time_base.num
+ && duration_count[i]<20 && st->codec->codec_type == CODEC_TYPE_VIDEO)
+ break;
+ if(st->parser && st->parser->parser->split && !st->codec->extradata)
+ break;
+ }
+ if (i == ic->nb_streams) {
+ /* NOTE: if the format has no header, then we need to read
+ some packets to get most of the streams, so we cannot
+ stop here */
+ if (!(ic->ctx_flags & AVFMTCTX_NOHEADER)) {
+ /* if we found the info for all the codecs, we can stop */
+ ret = count;
+ break;
+ }
+ }
+ /* we did not get all the codec info, but we read too much data */
+ if (read_size >= MAX_READ_SIZE) {
+ ret = count;
+ break;
+ }
+
+ /* NOTE: a new stream can be added there if no header in file
+ (AVFMTCTX_NOHEADER) */
+ ret = av_read_frame_internal(ic, &pkt1);
+ if (ret < 0) {
+ /* EOF or error */
+ ret = -1; /* we could not have all the codec parameters before EOF */
+ for(i=0;i<ic->nb_streams;i++) {
+ st = ic->streams[i];
+ if (!has_codec_parameters(st->codec)){
+ char buf[256];
+ avcodec_string(buf, sizeof(buf), st->codec, 0);
+ av_log(ic, AV_LOG_INFO, "Could not find codec parameters (%s)\n", buf);
+ } else {
+ ret = 0;
+ }
+ }
+ break;
+ }
+
+ pktl = av_mallocz(sizeof(AVPacketList));
+ if (!pktl) {
+ ret = AVERROR_NOMEM;
+ break;
+ }
+
+ /* add the packet in the buffered packet list */
+ *ppktl = pktl;
+ ppktl = &pktl->next;
+
+ pkt = &pktl->pkt;
+ *pkt = pkt1;
+
+ /* duplicate the packet */
+ if (av_dup_packet(pkt) < 0) {
+ ret = AVERROR_NOMEM;
+ break;
+ }
+
+ read_size += pkt->size;
+
+ st = ic->streams[pkt->stream_index];
+ st->codec_info_duration += pkt->duration;
+ if (pkt->duration != 0)
+ st->codec_info_nb_frames++;
+
+ {
+ int index= pkt->stream_index;
+ int64_t last= last_dts[index];
+ int64_t duration= pkt->dts - last;
+
+ if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && duration>0){
+ if(duration*duration_count[index]*10/9 < duration_sum[index]){
+ duration_sum[index]= duration;
+ duration_count[index]=1;
+ }else{
+ int factor= av_rescale(2*duration, duration_count[index], duration_sum[index]);
+ if(factor==3)
+ duration_count[index] *= 2;
+ factor= av_rescale(duration, duration_count[index], duration_sum[index]);
+ duration_sum[index] += duration;
+ duration_count[index]+= factor;
+ }
+ if(st->codec_info_nb_frames == 0 && 0)
+ st->codec_info_duration += duration;
+ }
+ last_dts[pkt->stream_index]= pkt->dts;
+ }
+ if(st->parser && st->parser->parser->split && !st->codec->extradata){
+ int i= st->parser->parser->split(st->codec, pkt->data, pkt->size);
+ if(i){
+ st->codec->extradata_size= i;
+ st->codec->extradata= av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ memcpy(st->codec->extradata, pkt->data, st->codec->extradata_size);
+ memset(st->codec->extradata + i, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+ }
+ }
+
+ /* if still no information, we try to open the codec and to
+ decompress the frame. We try to avoid that in most cases as
+ it takes longer and uses more memory. For MPEG4, we need to
+ decompress for Quicktime. */
+ if (!has_codec_parameters(st->codec) /*&&
+ (st->codec->codec_id == CODEC_ID_FLV1 ||
+ st->codec->codec_id == CODEC_ID_H264 ||
+ st->codec->codec_id == CODEC_ID_H263 ||
+ st->codec->codec_id == CODEC_ID_H261 ||
+ st->codec->codec_id == CODEC_ID_VORBIS ||
+ st->codec->codec_id == CODEC_ID_MJPEG ||
+ st->codec->codec_id == CODEC_ID_PNG ||
+ st->codec->codec_id == CODEC_ID_PAM ||
+ st->codec->codec_id == CODEC_ID_PGM ||
+ st->codec->codec_id == CODEC_ID_PGMYUV ||
+ st->codec->codec_id == CODEC_ID_PBM ||
+ st->codec->codec_id == CODEC_ID_PPM ||
+ st->codec->codec_id == CODEC_ID_SHORTEN ||
+ (st->codec->codec_id == CODEC_ID_MPEG4 && !st->need_parsing))*/)
+ try_decode_frame(st, pkt->data, pkt->size);
+
+ if (av_rescale_q(st->codec_info_duration, st->time_base, AV_TIME_BASE_Q) >= MAX_STREAM_DURATION) {
+ break;
+ }
+ count++;
+ }
+
+ // close codecs which where opened in try_decode_frame()
+ for(i=0;i<ic->nb_streams;i++) {
+ st = ic->streams[i];
+ if(st->codec->codec)
+ avcodec_close(st->codec);
+ }
+ for(i=0;i<ic->nb_streams;i++) {
+ st = ic->streams[i];
+ if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ if(st->codec->codec_id == CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_sample)
+ st->codec->codec_tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);
+
+ if(duration_count[i]
+ && (st->codec->time_base.num*101LL <= st->codec->time_base.den || st->codec->codec_id == CODEC_ID_MPEG2VIDEO) &&
+ //FIXME we should not special case mpeg2, but this needs testing with non mpeg2 ...
+ st->time_base.num*duration_sum[i]/duration_count[i]*101LL > st->time_base.den){
+ int64_t num, den, error, best_error;
+
+ num= st->time_base.den*duration_count[i];
+ den= st->time_base.num*duration_sum[i];
+
+ best_error= INT64_MAX;
+ for(j=1; j<60*12; j++){
+ error= FFABS(1001*12*num - 1001*j*den);
+ if(error < best_error){
+ best_error= error;
+ av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, j, 12, INT_MAX);
+ }
+ }
+ for(j=0; j<3; j++){
+ static const int ticks[]= {24,30,60};
+ error= FFABS(1001*12*num - 1000*12*den * ticks[j]);
+ if(error < best_error){
+ best_error= error;
+ av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, ticks[j]*1000, 1001, INT_MAX);
+ }
+ }
+ }
+
+ if (!st->r_frame_rate.num){
+ if( st->codec->time_base.den * (int64_t)st->time_base.num
+ <= st->codec->time_base.num * (int64_t)st->time_base.den){
+ st->r_frame_rate.num = st->codec->time_base.den;
+ st->r_frame_rate.den = st->codec->time_base.num;
+ }else{
+ st->r_frame_rate.num = st->time_base.den;
+ st->r_frame_rate.den = st->time_base.num;
+ }
+ }
+ }
+ }
+
+ av_estimate_timings(ic);
+#if 0
+ /* correct DTS for b frame streams with no timestamps */
+ for(i=0;i<ic->nb_streams;i++) {
+ st = ic->streams[i];
+ if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ if(b-frames){
+ ppktl = &ic->packet_buffer;
+ while(ppkt1){
+ if(ppkt1->stream_index != i)
+ continue;
+ if(ppkt1->pkt->dts < 0)
+ break;
+ if(ppkt1->pkt->pts != AV_NOPTS_VALUE)
+ break;
+ ppkt1->pkt->dts -= delta;
+ ppkt1= ppkt1->next;
+ }
+ if(ppkt1)
+ continue;
+ st->cur_dts -= delta;
+ }
+ }
+ }
+#endif
+ return ret;
+}
+
+/*******************************************************/
+
+/**
+ * start playing a network based stream (e.g. RTSP stream) at the
+ * current position
+ */
+int av_read_play(AVFormatContext *s)
+{
+ if (!s->iformat->read_play)
+ return AVERROR_NOTSUPP;
+ return s->iformat->read_play(s);
+}
+
+/**
+ * Pause a network based stream (e.g. RTSP stream).
+ *
+ * Use av_read_play() to resume it.
+ */
+int av_read_pause(AVFormatContext *s)
+{
+ if (!s->iformat->read_pause)
+ return AVERROR_NOTSUPP;
+ return s->iformat->read_pause(s);
+}
+
+/**
+ * Close a media file (but not its codecs).
+ *
+ * @param s media file handle
+ */
+void av_close_input_file(AVFormatContext *s)
+{
+ int i, must_open_file;
+ AVStream *st;
+
+ /* free previous packet */
+ if (s->cur_st && s->cur_st->parser)
+ av_free_packet(&s->cur_pkt);
+
+ if (s->iformat->read_close)
+ s->iformat->read_close(s);
+ for(i=0;i<s->nb_streams;i++) {
+ /* free all data in a stream component */
+ st = s->streams[i];
+ if (st->parser) {
+ av_parser_close(st->parser);
+ }
+ av_free(st->index_entries);
+ av_free(st->codec->extradata);
+ av_free(st->codec);
+ av_free(st);
+ }
+ flush_packet_queue(s);
+ must_open_file = 1;
+ if (s->iformat->flags & AVFMT_NOFILE) {
+ must_open_file = 0;
+ }
+ if (must_open_file) {
+ url_fclose(&s->pb);
+ }
+ av_freep(&s->priv_data);
+ av_free(s);
+}
+
+/**
+ * Add a new stream to a media file.
+ *
+ * Can only be called in the read_header() function. If the flag
+ * AVFMTCTX_NOHEADER is in the format context, then new streams
+ * can be added in read_packet too.
+ *
+ * @param s media file handle
+ * @param id file format dependent stream id
+ */
+AVStream *av_new_stream(AVFormatContext *s, int id)
+{
+ AVStream *st;
+ int i;
+
+ if (s->nb_streams >= MAX_STREAMS)
+ return NULL;
+
+ st = av_mallocz(sizeof(AVStream));
+ if (!st)
+ return NULL;
+
+ st->codec= avcodec_alloc_context();
+ if (s->iformat) {
+ /* no default bitrate if decoding */
+ st->codec->bit_rate = 0;
+ }
+ st->index = s->nb_streams;
+ st->id = id;
+ st->start_time = AV_NOPTS_VALUE;
+ st->duration = AV_NOPTS_VALUE;
+ st->cur_dts = AV_NOPTS_VALUE;
+
+ /* default pts settings is MPEG like */
+ av_set_pts_info(st, 33, 1, 90000);
+ st->last_IP_pts = AV_NOPTS_VALUE;
+ for(i=0; i<MAX_REORDER_DELAY+1; i++)
+ st->pts_buffer[i]= AV_NOPTS_VALUE;
+
+ s->streams[s->nb_streams++] = st;
+ return st;
+}
+
+/************************************************************/
+/* output media file */
+
+int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap)
+{
+ int ret;
+
+ if (s->oformat->priv_data_size > 0) {
+ s->priv_data = av_mallocz(s->oformat->priv_data_size);
+ if (!s->priv_data)
+ return AVERROR_NOMEM;
+ } else
+ s->priv_data = NULL;
+
+ if (s->oformat->set_parameters) {
+ ret = s->oformat->set_parameters(s, ap);
+ if (ret < 0)
+ return ret;
+ }
+ return 0;
+}
+
+/**
+ * allocate the stream private data and write the stream header to an
+ * output media file
+ *
+ * @param s media file handle
+ * @return 0 if OK. AVERROR_xxx if error.
+ */
+int av_write_header(AVFormatContext *s)
+{
+ int ret, i;
+ AVStream *st;
+
+ // some sanity checks
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+
+ switch (st->codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ if(st->codec->sample_rate<=0){
+ av_log(s, AV_LOG_ERROR, "sample rate not set\n");
+ return -1;
+ }
+ break;
+ case CODEC_TYPE_VIDEO:
+ if(st->codec->time_base.num<=0 || st->codec->time_base.den<=0){ //FIXME audio too?
+ av_log(s, AV_LOG_ERROR, "time base not set\n");
+ return -1;
+ }
+ if(st->codec->width<=0 || st->codec->height<=0){
+ av_log(s, AV_LOG_ERROR, "dimensions not set\n");
+ return -1;
+ }
+ break;
+ }
+ }
+
+ if(s->oformat->write_header){
+ ret = s->oformat->write_header(s);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* init PTS generation */
+ for(i=0;i<s->nb_streams;i++) {
+ int64_t den = AV_NOPTS_VALUE;
+ st = s->streams[i];
+
+ switch (st->codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ den = (int64_t)st->time_base.num * st->codec->sample_rate;
+ break;
+ case CODEC_TYPE_VIDEO:
+ den = (int64_t)st->time_base.num * st->codec->time_base.den;
+ break;
+ default:
+ break;
+ }
+ if (den != AV_NOPTS_VALUE) {
+ if (den <= 0)
+ return AVERROR_INVALIDDATA;
+ av_frac_init(&st->pts, 0, 0, den);
+ }
+ }
+ return 0;
+}
+
+//FIXME merge with compute_pkt_fields
+static int compute_pkt_fields2(AVStream *st, AVPacket *pkt){
+ int delay = FFMAX(st->codec->has_b_frames, !!st->codec->max_b_frames);
+ int num, den, frame_size, i;
+
+// av_log(st->codec, AV_LOG_DEBUG, "av_write_frame: pts:%"PRId64" dts:%"PRId64" cur_dts:%"PRId64" b:%d size:%d st:%d\n", pkt->pts, pkt->dts, st->cur_dts, delay, pkt->size, pkt->stream_index);
+
+/* if(pkt->pts == AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE)
+ return -1;*/
+
+ /* duration field */
+ if (pkt->duration == 0) {
+ compute_frame_duration(&num, &den, st, NULL, pkt);
+ if (den && num) {
+ pkt->duration = av_rescale(1, num * (int64_t)st->time_base.den, den * (int64_t)st->time_base.num);
+ }
+ }
+
+ //XXX/FIXME this is a temporary hack until all encoders output pts
+ if((pkt->pts == 0 || pkt->pts == AV_NOPTS_VALUE) && pkt->dts == AV_NOPTS_VALUE && !delay){
+ pkt->dts=
+// pkt->pts= st->cur_dts;
+ pkt->pts= st->pts.val;
+ }
+
+ //calculate dts from pts
+ if(pkt->pts != AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE){
+ st->pts_buffer[0]= pkt->pts;
+ for(i=1; i<delay+1 && st->pts_buffer[i] == AV_NOPTS_VALUE; i++)
+ st->pts_buffer[i]= (i-delay-1) * pkt->duration;
+ for(i=0; i<delay && st->pts_buffer[i] > st->pts_buffer[i+1]; i++)
+ FFSWAP(int64_t, st->pts_buffer[i], st->pts_buffer[i+1]);
+
+ pkt->dts= st->pts_buffer[0];
+ }
+
+ if(st->cur_dts && st->cur_dts != AV_NOPTS_VALUE && st->cur_dts >= pkt->dts){
+ av_log(NULL, AV_LOG_ERROR, "error, non monotone timestamps %"PRId64" >= %"PRId64"\n", st->cur_dts, pkt->dts);
+ return -1;
+ }
+ if(pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts < pkt->dts){
+ av_log(NULL, AV_LOG_ERROR, "error, pts < dts\n");
+ return -1;
+ }
+
+// av_log(NULL, AV_LOG_DEBUG, "av_write_frame: pts2:%"PRId64" dts2:%"PRId64"\n", pkt->pts, pkt->dts);
+ st->cur_dts= pkt->dts;
+ st->pts.val= pkt->dts;
+
+ /* update pts */
+ switch (st->codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ frame_size = get_audio_frame_size(st->codec, pkt->size);
+
+ /* HACK/FIXME, we skip the initial 0-size packets as they are most likely equal to the encoder delay,
+ but it would be better if we had the real timestamps from the encoder */
+ if (frame_size >= 0 && (pkt->size || st->pts.num!=st->pts.den>>1 || st->pts.val)) {
+ av_frac_add(&st->pts, (int64_t)st->time_base.den * frame_size);
+ }
+ break;
+ case CODEC_TYPE_VIDEO:
+ av_frac_add(&st->pts, (int64_t)st->time_base.den * st->codec->time_base.num);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static void truncate_ts(AVStream *st, AVPacket *pkt){
+ int64_t pts_mask = (2LL << (st->pts_wrap_bits-1)) - 1;
+
+// if(pkt->dts < 0)
+// pkt->dts= 0; //this happens for low_delay=0 and b frames, FIXME, needs further invstigation about what we should do here
+
+ pkt->pts &= pts_mask;
+ pkt->dts &= pts_mask;
+}
+
+/**
+ * Write a packet to an output media file.
+ *
+ * The packet shall contain one audio or video frame.
+ *
+ * @param s media file handle
+ * @param pkt the packet, which contains the stream_index, buf/buf_size, dts/pts, ...
+ * @return < 0 if error, = 0 if OK, 1 if end of stream wanted.
+ */
+int av_write_frame(AVFormatContext *s, AVPacket *pkt)
+{
+ int ret;
+
+ ret=compute_pkt_fields2(s->streams[pkt->stream_index], pkt);
+ if(ret<0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
+ return ret;
+
+ truncate_ts(s->streams[pkt->stream_index], pkt);
+
+ ret= s->oformat->write_packet(s, pkt);
+ if(!ret)
+ ret= url_ferror(&s->pb);
+ return ret;
+}
+
+/**
+ * Interleave a packet per DTS in an output media file.
+ *
+ * Packets with pkt->destruct == av_destruct_packet will be freed inside this function,
+ * so they cannot be used after it, note calling av_free_packet() on them is still safe.
+ *
+ * @param s media file handle
+ * @param out the interleaved packet will be output here
+ * @param in the input packet
+ * @param flush 1 if no further packets are available as input and all
+ * remaining packets should be output
+ * @return 1 if a packet was output, 0 if no packet could be output,
+ * < 0 if an error occured
+ */
+int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush){
+ AVPacketList *pktl, **next_point, *this_pktl;
+ int stream_count=0;
+ int streams[MAX_STREAMS];
+
+ if(pkt){
+ AVStream *st= s->streams[ pkt->stream_index];
+
+// assert(pkt->destruct != av_destruct_packet); //FIXME
+
+ this_pktl = av_mallocz(sizeof(AVPacketList));
+ this_pktl->pkt= *pkt;
+ if(pkt->destruct == av_destruct_packet)
+ pkt->destruct= NULL; // non shared -> must keep original from being freed
+ else
+ av_dup_packet(&this_pktl->pkt); //shared -> must dup
+
+ next_point = &s->packet_buffer;
+ while(*next_point){
+ AVStream *st2= s->streams[ (*next_point)->pkt.stream_index];
+ int64_t left= st2->time_base.num * (int64_t)st ->time_base.den;
+ int64_t right= st ->time_base.num * (int64_t)st2->time_base.den;
+ if((*next_point)->pkt.dts * left > pkt->dts * right) //FIXME this can overflow
+ break;
+ next_point= &(*next_point)->next;
+ }
+ this_pktl->next= *next_point;
+ *next_point= this_pktl;
+ }
+
+ memset(streams, 0, sizeof(streams));
+ pktl= s->packet_buffer;
+ while(pktl){
+//av_log(s, AV_LOG_DEBUG, "show st:%d dts:%"PRId64"\n", pktl->pkt.stream_index, pktl->pkt.dts);
+ if(streams[ pktl->pkt.stream_index ] == 0)
+ stream_count++;
+ streams[ pktl->pkt.stream_index ]++;
+ pktl= pktl->next;
+ }
+
+ if(s->nb_streams == stream_count || (flush && stream_count)){
+ pktl= s->packet_buffer;
+ *out= pktl->pkt;
+
+ s->packet_buffer= pktl->next;
+ av_freep(&pktl);
+ return 1;
+ }else{
+ av_init_packet(out);
+ return 0;
+ }
+}
+
+/**
+ * Interleaves a AVPacket correctly so it can be muxed.
+ * @param out the interleaved packet will be output here
+ * @param in the input packet
+ * @param flush 1 if no further packets are available as input and all
+ * remaining packets should be output
+ * @return 1 if a packet was output, 0 if no packet could be output,
+ * < 0 if an error occured
+ */
+static int av_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, int flush){
+ if(s->oformat->interleave_packet)
+ return s->oformat->interleave_packet(s, out, in, flush);
+ else
+ return av_interleave_packet_per_dts(s, out, in, flush);
+}
+
+/**
+ * Writes a packet to an output media file ensuring correct interleaving.
+ *
+ * The packet must contain one audio or video frame.
+ * If the packets are already correctly interleaved the application should
+ * call av_write_frame() instead as its slightly faster, its also important
+ * to keep in mind that completly non interleaved input will need huge amounts
+ * of memory to interleave with this, so its prefereable to interleave at the
+ * demuxer level
+ *
+ * @param s media file handle
+ * @param pkt the packet, which contains the stream_index, buf/buf_size, dts/pts, ...
+ * @return < 0 if error, = 0 if OK, 1 if end of stream wanted.
+ */
+int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){
+ AVStream *st= s->streams[ pkt->stream_index];
+
+ //FIXME/XXX/HACK drop zero sized packets
+ if(st->codec->codec_type == CODEC_TYPE_AUDIO && pkt->size==0)
+ return 0;
+
+//av_log(NULL, AV_LOG_DEBUG, "av_interleaved_write_frame %d %"PRId64" %"PRId64"\n", pkt->size, pkt->dts, pkt->pts);
+ if(compute_pkt_fields2(st, pkt) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
+ return -1;
+
+ if(pkt->dts == AV_NOPTS_VALUE)
+ return -1;
+
+ for(;;){
+ AVPacket opkt;
+ int ret= av_interleave_packet(s, &opkt, pkt, 0);
+ if(ret<=0) //FIXME cleanup needed for ret<0 ?
+ return ret;
+
+ truncate_ts(s->streams[opkt.stream_index], &opkt);
+ ret= s->oformat->write_packet(s, &opkt);
+
+ av_free_packet(&opkt);
+ pkt= NULL;
+
+ if(ret<0)
+ return ret;
+ if(url_ferror(&s->pb))
+ return url_ferror(&s->pb);
+ }
+}
+
+/**
+ * @brief Write the stream trailer to an output media file and
+ * free the file private data.
+ *
+ * @param s media file handle
+ * @return 0 if OK. AVERROR_xxx if error.
+ */
+int av_write_trailer(AVFormatContext *s)
+{
+ int ret, i;
+
+ for(;;){
+ AVPacket pkt;
+ ret= av_interleave_packet(s, &pkt, NULL, 1);
+ if(ret<0) //FIXME cleanup needed for ret<0 ?
+ goto fail;
+ if(!ret)
+ break;
+
+ truncate_ts(s->streams[pkt.stream_index], &pkt);
+ ret= s->oformat->write_packet(s, &pkt);
+
+ av_free_packet(&pkt);
+
+ if(ret<0)
+ goto fail;
+ if(url_ferror(&s->pb))
+ goto fail;
+ }
+
+ if(s->oformat->write_trailer)
+ ret = s->oformat->write_trailer(s);
+fail:
+ if(ret == 0)
+ ret=url_ferror(&s->pb);
+ for(i=0;i<s->nb_streams;i++)
+ av_freep(&s->streams[i]->priv_data);
+ av_freep(&s->priv_data);
+ return ret;
+}
+
+/* "user interface" functions */
+
+void dump_format(AVFormatContext *ic,
+ int index,
+ const char *url,
+ int is_output)
+{
+ int i, flags;
+ char buf[256];
+
+ av_log(NULL, AV_LOG_INFO, "%s #%d, %s, %s '%s':\n",
+ is_output ? "Output" : "Input",
+ index,
+ is_output ? ic->oformat->name : ic->iformat->name,
+ is_output ? "to" : "from", url);
+ if (!is_output) {
+ av_log(NULL, AV_LOG_INFO, " Duration: ");
+ if (ic->duration != AV_NOPTS_VALUE) {
+ int hours, mins, secs, us;
+ secs = ic->duration / AV_TIME_BASE;
+ us = ic->duration % AV_TIME_BASE;
+ mins = secs / 60;
+ secs %= 60;
+ hours = mins / 60;
+ mins %= 60;
+ av_log(NULL, AV_LOG_INFO, "%02d:%02d:%02d.%01d", hours, mins, secs,
+ (10 * us) / AV_TIME_BASE);
+ } else {
+ av_log(NULL, AV_LOG_INFO, "N/A");
+ }
+ if (ic->start_time != AV_NOPTS_VALUE) {
+ int secs, us;
+ av_log(NULL, AV_LOG_INFO, ", start: ");
+ secs = ic->start_time / AV_TIME_BASE;
+ us = ic->start_time % AV_TIME_BASE;
+ av_log(NULL, AV_LOG_INFO, "%d.%06d",
+ secs, (int)av_rescale(us, 1000000, AV_TIME_BASE));
+ }
+ av_log(NULL, AV_LOG_INFO, ", bitrate: ");
+ if (ic->bit_rate) {
+ av_log(NULL, AV_LOG_INFO,"%d kb/s", ic->bit_rate / 1000);
+ } else {
+ av_log(NULL, AV_LOG_INFO, "N/A");
+ }
+ av_log(NULL, AV_LOG_INFO, "\n");
+ }
+ for(i=0;i<ic->nb_streams;i++) {
+ AVStream *st = ic->streams[i];
+ int g= ff_gcd(st->time_base.num, st->time_base.den);
+ avcodec_string(buf, sizeof(buf), st->codec, is_output);
+ av_log(NULL, AV_LOG_INFO, " Stream #%d.%d", index, i);
+ /* the pid is an important information, so we display it */
+ /* XXX: add a generic system */
+ if (is_output)
+ flags = ic->oformat->flags;
+ else
+ flags = ic->iformat->flags;
+ if (flags & AVFMT_SHOW_IDS) {
+ av_log(NULL, AV_LOG_INFO, "[0x%x]", st->id);
+ }
+ if (strlen(st->language) > 0) {
+ av_log(NULL, AV_LOG_INFO, "(%s)", st->language);
+ }
+ av_log(NULL, AV_LOG_DEBUG, ", %d/%d", st->time_base.num/g, st->time_base.den/g);
+ av_log(NULL, AV_LOG_INFO, ": %s", buf);
+ if(st->codec->codec_type == CODEC_TYPE_VIDEO){
+ if(st->r_frame_rate.den && st->r_frame_rate.num)
+ av_log(NULL, AV_LOG_INFO, ", %5.2f fps(r)", av_q2d(st->r_frame_rate));
+/* else if(st->time_base.den && st->time_base.num)
+ av_log(NULL, AV_LOG_INFO, ", %5.2f fps(m)", 1/av_q2d(st->time_base));*/
+ else
+ av_log(NULL, AV_LOG_INFO, ", %5.2f fps(c)", 1/av_q2d(st->codec->time_base));
+ }
+ av_log(NULL, AV_LOG_INFO, "\n");
+ }
+}
+
+typedef struct {
+ const char *abv;
+ int width, height;
+ int frame_rate, frame_rate_base;
+} AbvEntry;
+
+static AbvEntry frame_abvs[] = {
+ { "ntsc", 720, 480, 30000, 1001 },
+ { "pal", 720, 576, 25, 1 },
+ { "qntsc", 352, 240, 30000, 1001 }, /* VCD compliant ntsc */
+ { "qpal", 352, 288, 25, 1 }, /* VCD compliant pal */
+ { "sntsc", 640, 480, 30000, 1001 }, /* square pixel ntsc */
+ { "spal", 768, 576, 25, 1 }, /* square pixel pal */
+ { "film", 352, 240, 24, 1 },
+ { "ntsc-film", 352, 240, 24000, 1001 },
+ { "sqcif", 128, 96, 0, 0 },
+ { "qcif", 176, 144, 0, 0 },
+ { "cif", 352, 288, 0, 0 },
+ { "4cif", 704, 576, 0, 0 },
+};
+
+/**
+ * parses width and height out of string str.
+ */
+int parse_image_size(int *width_ptr, int *height_ptr, const char *str)
+{
+ int i;
+ int n = sizeof(frame_abvs) / sizeof(AbvEntry);
+ const char *p;
+ int frame_width = 0, frame_height = 0;
+
+ for(i=0;i<n;i++) {
+ if (!strcmp(frame_abvs[i].abv, str)) {
+ frame_width = frame_abvs[i].width;
+ frame_height = frame_abvs[i].height;
+ break;
+ }
+ }
+ if (i == n) {
+ p = str;
+ frame_width = strtol(p, (char **)&p, 10);
+ if (*p)
+ p++;
+ frame_height = strtol(p, (char **)&p, 10);
+ }
+ if (frame_width <= 0 || frame_height <= 0)
+ return -1;
+ *width_ptr = frame_width;
+ *height_ptr = frame_height;
+ return 0;
+}
+
+/**
+ * Converts frame rate from string to a fraction.
+ *
+ * First we try to get an exact integer or fractional frame rate.
+ * If this fails we convert the frame rate to a double and return
+ * an approximate fraction using the DEFAULT_FRAME_RATE_BASE.
+ */
+int parse_frame_rate(int *frame_rate, int *frame_rate_base, const char *arg)
+{
+ int i;
+ char* cp;
+
+ /* First, we check our abbreviation table */
+ for (i = 0; i < sizeof(frame_abvs)/sizeof(*frame_abvs); ++i)
+ if (!strcmp(frame_abvs[i].abv, arg)) {
+ *frame_rate = frame_abvs[i].frame_rate;
+ *frame_rate_base = frame_abvs[i].frame_rate_base;
+ return 0;
+ }
+
+ /* Then, we try to parse it as fraction */
+ cp = strchr(arg, '/');
+ if (!cp)
+ cp = strchr(arg, ':');
+ if (cp) {
+ char* cpp;
+ *frame_rate = strtol(arg, &cpp, 10);
+ if (cpp != arg || cpp == cp)
+ *frame_rate_base = strtol(cp+1, &cpp, 10);
+ else
+ *frame_rate = 0;
+ }
+ else {
+ /* Finally we give up and parse it as double */
+ AVRational time_base = av_d2q(strtod(arg, 0), DEFAULT_FRAME_RATE_BASE);
+ *frame_rate_base = time_base.den;
+ *frame_rate = time_base.num;
+ }
+ if (!*frame_rate || !*frame_rate_base)
+ return -1;
+ else
+ return 0;
+}
+
+/**
+ * Converts date string to number of seconds since Jan 1st, 1970.
+ *
+ * @code
+ * Syntax:
+ * - If not a duration:
+ * [{YYYY-MM-DD|YYYYMMDD}]{T| }{HH[:MM[:SS[.m...]]][Z]|HH[MM[SS[.m...]]][Z]}
+ * Time is localtime unless Z is suffixed to the end. In this case GMT
+ * Return the date in micro seconds since 1970
+ *
+ * - If a duration:
+ * HH[:MM[:SS[.m...]]]
+ * S+[.m...]
+ * @endcode
+ */
+#ifndef CONFIG_WINCE
+int64_t parse_date(const char *datestr, int duration)
+{
+ const char *p;
+ int64_t t;
+ struct tm dt;
+ int i;
+ static const char *date_fmt[] = {
+ "%Y-%m-%d",
+ "%Y%m%d",
+ };
+ static const char *time_fmt[] = {
+ "%H:%M:%S",
+ "%H%M%S",
+ };
+ const char *q;
+ int is_utc, len;
+ char lastch;
+ int negative = 0;
+
+#undef time
+ time_t now = time(0);
+
+ len = strlen(datestr);
+ if (len > 0)
+ lastch = datestr[len - 1];
+ else
+ lastch = '\0';
+ is_utc = (lastch == 'z' || lastch == 'Z');
+
+ memset(&dt, 0, sizeof(dt));
+
+ p = datestr;
+ q = NULL;
+ if (!duration) {
+ for (i = 0; i < sizeof(date_fmt) / sizeof(date_fmt[0]); i++) {
+ q = small_strptime(p, date_fmt[i], &dt);
+ if (q) {
+ break;
+ }
+ }
+
+ if (!q) {
+ if (is_utc) {
+ dt = *gmtime(&now);
+ } else {
+ dt = *localtime(&now);
+ }
+ dt.tm_hour = dt.tm_min = dt.tm_sec = 0;
+ } else {
+ p = q;
+ }
+
+ if (*p == 'T' || *p == 't' || *p == ' ')
+ p++;
+
+ for (i = 0; i < sizeof(time_fmt) / sizeof(time_fmt[0]); i++) {
+ q = small_strptime(p, time_fmt[i], &dt);
+ if (q) {
+ break;
+ }
+ }
+ } else {
+ if (p[0] == '-') {
+ negative = 1;
+ ++p;
+ }
+ q = small_strptime(p, time_fmt[0], &dt);
+ if (!q) {
+ dt.tm_sec = strtol(p, (char **)&q, 10);
+ dt.tm_min = 0;
+ dt.tm_hour = 0;
+ }
+ }
+
+ /* Now we have all the fields that we can get */
+ if (!q) {
+ if (duration)
+ return 0;
+ else
+ return now * int64_t_C(1000000);
+ }
+
+ if (duration) {
+ t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
+ } else {
+ dt.tm_isdst = -1; /* unknown */
+ if (is_utc) {
+ t = mktimegm(&dt);
+ } else {
+ t = mktime(&dt);
+ }
+ }
+
+ t *= 1000000;
+
+ if (*q == '.') {
+ int val, n;
+ q++;
+ for (val = 0, n = 100000; n >= 1; n /= 10, q++) {
+ if (!isdigit(*q))
+ break;
+ val += n * (*q - '0');
+ }
+ t += val;
+ }
+ return negative ? -t : t;
+}
+#endif /* CONFIG_WINCE */
+
+/**
+ * Attempts to find a specific tag in a URL.
+ *
+ * syntax: '?tag1=val1&tag2=val2...'. Little URL decoding is done.
+ * Return 1 if found.
+ */
+int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
+{
+ const char *p;
+ char tag[128], *q;
+
+ p = info;
+ if (*p == '?')
+ p++;
+ for(;;) {
+ q = tag;
+ while (*p != '\0' && *p != '=' && *p != '&') {
+ if ((q - tag) < sizeof(tag) - 1)
+ *q++ = *p;
+ p++;
+ }
+ *q = '\0';
+ q = arg;
+ if (*p == '=') {
+ p++;
+ while (*p != '&' && *p != '\0') {
+ if ((q - arg) < arg_size - 1) {
+ if (*p == '+')
+ *q++ = ' ';
+ else
+ *q++ = *p;
+ }
+ p++;
+ }
+ *q = '\0';
+ }
+ if (!strcmp(tag, tag1))
+ return 1;
+ if (*p != '&')
+ break;
+ p++;
+ }
+ return 0;
+}
+
+/**
+ * Returns in 'buf' the path with '%d' replaced by number.
+
+ * Also handles the '%0nd' format where 'n' is the total number
+ * of digits and '%%'.
+ *
+ * @param buf destination buffer
+ * @param buf_size destination buffer size
+ * @param path numbered sequence string
+ * @number frame number
+ * @return 0 if OK, -1 if format error.
+ */
+int av_get_frame_filename(char *buf, int buf_size,
+ const char *path, int number)
+{
+ const char *p;
+ char *q, buf1[20], c;
+ int nd, len, percentd_found;
+
+ q = buf;
+ p = path;
+ percentd_found = 0;
+ for(;;) {
+ c = *p++;
+ if (c == '\0')
+ break;
+ if (c == '%') {
+ do {
+ nd = 0;
+ while (isdigit(*p)) {
+ nd = nd * 10 + *p++ - '0';
+ }
+ c = *p++;
+ } while (isdigit(c));
+
+ switch(c) {
+ case '%':
+ goto addchar;
+ case 'd':
+ if (percentd_found)
+ goto fail;
+ percentd_found = 1;
+ snprintf(buf1, sizeof(buf1), "%0*d", nd, number);
+ len = strlen(buf1);
+ if ((q - buf + len) > buf_size - 1)
+ goto fail;
+ memcpy(q, buf1, len);
+ q += len;
+ break;
+ default:
+ goto fail;
+ }
+ } else {
+ addchar:
+ if ((q - buf) < buf_size - 1)
+ *q++ = c;
+ }
+ }
+ if (!percentd_found)
+ goto fail;
+ *q = '\0';
+ return 0;
+ fail:
+ *q = '\0';
+ return -1;
+}
+
+/**
+ * Print nice hexa dump of a buffer
+ * @param f stream for output
+ * @param buf buffer
+ * @param size buffer size
+ */
+void av_hex_dump(FILE *f, uint8_t *buf, int size)
+{
+ int len, i, j, c;
+
+ for(i=0;i<size;i+=16) {
+ len = size - i;
+ if (len > 16)
+ len = 16;
+ fprintf(f, "%08x ", i);
+ for(j=0;j<16;j++) {
+ if (j < len)
+ fprintf(f, " %02x", buf[i+j]);
+ else
+ fprintf(f, " ");
+ }
+ fprintf(f, " ");
+ for(j=0;j<len;j++) {
+ c = buf[i+j];
+ if (c < ' ' || c > '~')
+ c = '.';
+ fprintf(f, "%c", c);
+ }
+ fprintf(f, "\n");
+ }
+}
+
+/**
+ * Print on 'f' a nice dump of a packet
+ * @param f stream for output
+ * @param pkt packet to dump
+ * @param dump_payload true if the payload must be displayed too
+ */
+ //FIXME needs to know the time_base
+void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload)
+{
+ fprintf(f, "stream #%d:\n", pkt->stream_index);
+ fprintf(f, " keyframe=%d\n", ((pkt->flags & PKT_FLAG_KEY) != 0));
+ fprintf(f, " duration=%0.3f\n", (double)pkt->duration / AV_TIME_BASE);
+ /* DTS is _always_ valid after av_read_frame() */
+ fprintf(f, " dts=");
+ if (pkt->dts == AV_NOPTS_VALUE)
+ fprintf(f, "N/A");
+ else
+ fprintf(f, "%0.3f", (double)pkt->dts / AV_TIME_BASE);
+ /* PTS may be not known if B frames are present */
+ fprintf(f, " pts=");
+ if (pkt->pts == AV_NOPTS_VALUE)
+ fprintf(f, "N/A");
+ else
+ fprintf(f, "%0.3f", (double)pkt->pts / AV_TIME_BASE);
+ fprintf(f, "\n");
+ fprintf(f, " size=%d\n", pkt->size);
+ if (dump_payload)
+ av_hex_dump(f, pkt->data, pkt->size);
+}
+
+void url_split(char *proto, int proto_size,
+ char *authorization, int authorization_size,
+ char *hostname, int hostname_size,
+ int *port_ptr,
+ char *path, int path_size,
+ const char *url)
+{
+ const char *p;
+ char *q;
+ int port;
+
+ port = -1;
+
+ p = url;
+ q = proto;
+ while (*p != ':' && *p != '\0') {
+ if ((q - proto) < proto_size - 1)
+ *q++ = *p;
+ p++;
+ }
+ if (proto_size > 0)
+ *q = '\0';
+ if (authorization_size > 0)
+ authorization[0] = '\0';
+ if (*p == '\0') {
+ if (proto_size > 0)
+ proto[0] = '\0';
+ if (hostname_size > 0)
+ hostname[0] = '\0';
+ p = url;
+ } else {
+ char *at,*slash; // PETR: position of '@' character and '/' character
+
+ p++;
+ if (*p == '/')
+ p++;
+ if (*p == '/')
+ p++;
+ at = strchr(p,'@'); // PETR: get the position of '@'
+ slash = strchr(p,'/'); // PETR: get position of '/' - end of hostname
+ if (at && slash && at > slash) at = NULL; // PETR: not interested in '@' behind '/'
+
+ q = at ? authorization : hostname; // PETR: if '@' exists starting with auth.
+
+ while ((at || *p != ':') && *p != '/' && *p != '?' && *p != '\0') { // PETR:
+ if (*p == '@') { // PETR: passed '@'
+ if (authorization_size > 0)
+ *q = '\0';
+ q = hostname;
+ at = NULL;
+ } else if (!at) { // PETR: hostname
+ if ((q - hostname) < hostname_size - 1)
+ *q++ = *p;
+ } else {
+ if ((q - authorization) < authorization_size - 1)
+ *q++ = *p;
+ }
+ p++;
+ }
+ if (hostname_size > 0)
+ *q = '\0';
+ if (*p == ':') {
+ p++;
+ port = strtoul(p, (char **)&p, 10);
+ }
+ }
+ if (port_ptr)
+ *port_ptr = port;
+ pstrcpy(path, path_size, p);
+}
+
+/**
+ * Set the pts for a given stream.
+ *
+ * @param s stream
+ * @param pts_wrap_bits number of bits effectively used by the pts
+ * (used for wrap control, 33 is the value for MPEG)
+ * @param pts_num numerator to convert to seconds (MPEG: 1)
+ * @param pts_den denominator to convert to seconds (MPEG: 90000)
+ */
+void av_set_pts_info(AVStream *s, int pts_wrap_bits,
+ int pts_num, int pts_den)
+{
+ s->pts_wrap_bits = pts_wrap_bits;
+ s->time_base.num = pts_num;
+ s->time_base.den = pts_den;
+}
+
+/* fraction handling */
+
+/**
+ * f = val + (num / den) + 0.5.
+ *
+ * 'num' is normalized so that it is such as 0 <= num < den.
+ *
+ * @param f fractional number
+ * @param val integer value
+ * @param num must be >= 0
+ * @param den must be >= 1
+ */
+static void av_frac_init(AVFrac *f, int64_t val, int64_t num, int64_t den)
+{
+ num += (den >> 1);
+ if (num >= den) {
+ val += num / den;
+ num = num % den;
+ }
+ f->val = val;
+ f->num = num;
+ f->den = den;
+}
+
+/**
+ * Set f to (val + 0.5).
+ */
+static void av_frac_set(AVFrac *f, int64_t val)
+{
+ f->val = val;
+ f->num = f->den >> 1;
+}
+
+/**
+ * Fractionnal addition to f: f = f + (incr / f->den).
+ *
+ * @param f fractional number
+ * @param incr increment, can be positive or negative
+ */
+static void av_frac_add(AVFrac *f, int64_t incr)
+{
+ int64_t num, den;
+
+ num = f->num + incr;
+ den = f->den;
+ if (num < 0) {
+ f->val += num / den;
+ num = num % den;
+ if (num < 0) {
+ num += den;
+ f->val--;
+ }
+ } else if (num >= den) {
+ f->val += num / den;
+ num = num % den;
+ }
+ f->num = num;
+}
diff --git a/contrib/ffmpeg/libavformat/v4l2.c b/contrib/ffmpeg/libavformat/v4l2.c
new file mode 100644
index 000000000..00adccaa8
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/v4l2.c
@@ -0,0 +1,541 @@
+/*
+ * Video4Linux2 grab interface
+ * Copyright (c) 2000,2001 Fabrice Bellard.
+ * Copyright (c) 2006 Luca Abeni.
+ *
+ * Part of this file is based on the V4L2 video capture example
+ * (http://v4l2spec.bytesex.org/v4l2spec/capture.c)
+ *
+ * Thanks to Michael Niedermayer for providing the mapping between
+ * V4L2_PIX_FMT_* and PIX_FMT_*
+ *
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "avformat.h"
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <asm/types.h>
+#include <linux/videodev2.h>
+#include <time.h>
+
+static const int desired_video_buffers = 256;
+
+enum io_method {
+ io_read,
+ io_mmap,
+ io_userptr
+};
+
+struct video_data {
+ int fd;
+ int frame_format; /* V4L2_PIX_FMT_* */
+ enum io_method io_method;
+ int width, height;
+ int frame_rate;
+ int frame_rate_base;
+ int frame_size;
+ int top_field_first;
+
+ int buffers;
+ void **buf_start;
+ unsigned int *buf_len;
+};
+
+struct fmt_map {
+ enum PixelFormat ff_fmt;
+ int32_t v4l2_fmt;
+};
+
+static struct fmt_map fmt_conversion_table[] = {
+ {
+ .ff_fmt = PIX_FMT_YUV420P,
+ .v4l2_fmt = V4L2_PIX_FMT_YUV420,
+ },
+ {
+ .ff_fmt = PIX_FMT_YUV422P,
+ .v4l2_fmt = V4L2_PIX_FMT_YUV422P,
+ },
+ {
+ .ff_fmt = PIX_FMT_YUV422,
+ .v4l2_fmt = V4L2_PIX_FMT_YUYV,
+ },
+ {
+ .ff_fmt = PIX_FMT_UYVY422,
+ .v4l2_fmt = V4L2_PIX_FMT_UYVY,
+ },
+ {
+ .ff_fmt = PIX_FMT_YUV411P,
+ .v4l2_fmt = V4L2_PIX_FMT_YUV411P,
+ },
+ {
+ .ff_fmt = PIX_FMT_YUV410P,
+ .v4l2_fmt = V4L2_PIX_FMT_YUV410,
+ },
+ {
+ .ff_fmt = PIX_FMT_BGR24,
+ .v4l2_fmt = V4L2_PIX_FMT_BGR24,
+ },
+ {
+ .ff_fmt = PIX_FMT_RGB24,
+ .v4l2_fmt = V4L2_PIX_FMT_RGB24,
+ },
+ /*
+ {
+ .ff_fmt = PIX_FMT_RGBA32,
+ .v4l2_fmt = V4L2_PIX_FMT_BGR32,
+ },
+ */
+ {
+ .ff_fmt = PIX_FMT_GRAY8,
+ .v4l2_fmt = V4L2_PIX_FMT_GREY,
+ },
+};
+
+static int device_open(const char *devname, uint32_t *capabilities)
+{
+ struct v4l2_capability cap;
+ int fd;
+ int res;
+
+ fd = open(devname, O_RDWR /*| O_NONBLOCK*/, 0);
+ if (fd < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Cannot open video device %s : %s\n",
+ devname, strerror(errno));
+
+ return -1;
+ }
+
+ res = ioctl(fd, VIDIOC_QUERYCAP, &cap);
+ // ENOIOCTLCMD definition only availble on __KERNEL__
+ if (res < 0 && errno == 515)
+ {
+ av_log(NULL, AV_LOG_ERROR, "QUERYCAP not implemented, probably V4L device but not supporting V4L2\n");
+ close(fd);
+
+ return -1;
+ }
+ if (res < 0) {
+ av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n",
+ strerror(errno));
+ close(fd);
+
+ return -1;
+ }
+ if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
+ av_log(NULL, AV_LOG_ERROR, "Not a video capture device\n");
+ close(fd);
+
+ return -1;
+ }
+ *capabilities = cap.capabilities;
+
+ return fd;
+}
+
+static int device_init(int fd, int *width, int *height, int pix_fmt)
+{
+ struct v4l2_format fmt;
+ int res;
+
+ memset(&fmt, 0, sizeof(struct v4l2_format));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt.fmt.pix.width = *width;
+ fmt.fmt.pix.height = *height;
+ fmt.fmt.pix.pixelformat = pix_fmt;
+ fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
+ res = ioctl(fd, VIDIOC_S_FMT, &fmt);
+ if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) {
+ av_log(NULL, AV_LOG_INFO, "The V4L2 driver changed the video from %dx%d to %dx%d\n", *width, *height, fmt.fmt.pix.width, fmt.fmt.pix.height);
+ *width = fmt.fmt.pix.width;
+ *height = fmt.fmt.pix.height;
+ }
+
+ return res;
+}
+
+static int first_field(int fd)
+{
+ int res;
+ v4l2_std_id std;
+
+ res = ioctl(fd, VIDIOC_G_STD, &std);
+ if (res < 0) {
+ return 0;
+ }
+ if (std & V4L2_STD_NTSC) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static uint32_t fmt_ff2v4l(enum PixelFormat pix_fmt)
+{
+ int i;
+
+ for (i = 0; i < sizeof(fmt_conversion_table) / sizeof(struct fmt_map); i++) {
+ if (fmt_conversion_table[i].ff_fmt == pix_fmt) {
+ return fmt_conversion_table[i].v4l2_fmt;
+ }
+ }
+
+ return 0;
+}
+
+static enum PixelFormat fmt_v4l2ff(uint32_t pix_fmt)
+{
+ int i;
+
+ for (i = 0; i < sizeof(fmt_conversion_table) / sizeof(struct fmt_map); i++) {
+ if (fmt_conversion_table[i].v4l2_fmt == pix_fmt) {
+ return fmt_conversion_table[i].ff_fmt;
+ }
+ }
+
+ return -1;
+}
+
+static int mmap_init(struct video_data *s)
+{
+ struct v4l2_requestbuffers req;
+ int i, res;
+
+ memset(&req, 0, sizeof(struct v4l2_requestbuffers));
+ req.count = desired_video_buffers;
+ req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ req.memory = V4L2_MEMORY_MMAP;
+ res = ioctl (s->fd, VIDIOC_REQBUFS, &req);
+ if (res < 0) {
+ if (errno == EINVAL) {
+ av_log(NULL, AV_LOG_ERROR, "Device does not support mmap\n");
+ } else {
+ av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_REQBUFS)\n");
+ }
+
+ return -1;
+ }
+
+ if (req.count < 2) {
+ av_log(NULL, AV_LOG_ERROR, "Insufficient buffer memory\n");
+
+ return -1;
+ }
+ s->buffers = req.count;
+ s->buf_start = av_malloc(sizeof(void *) * s->buffers);
+ if (s->buf_start == NULL) {
+ av_log(NULL, AV_LOG_ERROR, "Cannot allocate buffer pointers\n");
+
+ return -1;
+ }
+ s->buf_len = av_malloc(sizeof(unsigned int) * s->buffers);
+ if (s->buf_len == NULL) {
+ av_log(NULL, AV_LOG_ERROR, "Cannot allocate buffer sizes\n");
+ av_free(s->buf_start);
+
+ return -1;
+ }
+
+ for (i = 0; i < req.count; i++) {
+ struct v4l2_buffer buf;
+
+ memset(&buf, 0, sizeof(struct v4l2_buffer));
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = i;
+ res = ioctl (s->fd, VIDIOC_QUERYBUF, &buf);
+ if (res < 0) {
+ av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF)\n");
+
+ return -1;
+ }
+
+ s->buf_len[i] = buf.length;
+ if (s->buf_len[i] < s->frame_size) {
+ av_log(NULL, AV_LOG_ERROR, "Buffer len [%d] = %d != %d\n", i, s->buf_len[i], s->frame_size);
+
+ return -1;
+ }
+ s->buf_start[i] = mmap (NULL, buf.length,
+ PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf.m.offset);
+ if (s->buf_start[i] == MAP_FAILED) {
+ av_log(NULL, AV_LOG_ERROR, "mmap: %s\n", strerror(errno));
+
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int read_init(struct video_data *s)
+{
+ return -1;
+}
+
+static int mmap_read_frame(struct video_data *s, void *frame, int64_t *ts)
+{
+ struct v4l2_buffer buf;
+ int res;
+
+ memset(&buf, 0, sizeof(struct v4l2_buffer));
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+
+ /* FIXME: Some special treatment might be needed in case of loss of signal... */
+ while ((res = ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 &&
+ ((errno == EAGAIN) || (errno == EINTR)));
+ if (res < 0) {
+ av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", strerror(errno));
+
+ return -1;
+ }
+ assert (buf.index < s->buffers);
+ if (buf.bytesused != s->frame_size) {
+ av_log(NULL, AV_LOG_ERROR, "The v4l2 frame is %d bytes, but %d bytes are expected\n", buf.bytesused, s->frame_size);
+
+ return -1;
+ }
+
+ /* Image is at s->buff_start[buf.index] */
+ memcpy(frame, s->buf_start[buf.index], buf.bytesused);
+ *ts = buf.timestamp.tv_sec * int64_t_C(1000000) + buf.timestamp.tv_usec;
+
+ res = ioctl (s->fd, VIDIOC_QBUF, &buf);
+ if (res < 0) {
+ av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF)\n");
+
+ return -1;
+ }
+
+ return s->buf_len[buf.index];
+}
+
+static int read_frame(struct video_data *s, void *frame, int64_t *ts)
+{
+ return -1;
+}
+
+static int mmap_start(struct video_data *s)
+{
+ enum v4l2_buf_type type;
+ int i, res;
+
+ for (i = 0; i < s->buffers; i++) {
+ struct v4l2_buffer buf;
+
+ memset(&buf, 0, sizeof(struct v4l2_buffer));
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = i;
+
+ res = ioctl (s->fd, VIDIOC_QBUF, &buf);
+ if (res < 0) {
+ av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno));
+
+ return -1;
+ }
+ }
+
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ res = ioctl (s->fd, VIDIOC_STREAMON, &type);
+ if (res < 0) {
+ av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n", strerror(errno));
+
+ return -1;
+ }
+
+ return 0;
+}
+
+static void mmap_close(struct video_data *s)
+{
+ enum v4l2_buf_type type;
+ int i;
+
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ /* We do not check for the result, because we could
+ * not do anything about it anyway...
+ */
+ ioctl(s->fd, VIDIOC_STREAMOFF, &type);
+ for (i = 0; i < s->buffers; i++) {
+ munmap(s->buf_start[i], s->buf_len[i]);
+ }
+ av_free(s->buf_start);
+ av_free(s->buf_len);
+}
+
+static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
+{
+ struct video_data *s = s1->priv_data;
+ AVStream *st;
+ int width, height;
+ int res, frame_rate, frame_rate_base;
+ uint32_t desired_format, capabilities;
+ const char *video_device;
+
+ if (ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) {
+ av_log(s1, AV_LOG_ERROR, "Missing/Wrong parameters\n");
+
+ return -1;
+ }
+
+ width = ap->width;
+ height = ap->height;
+ frame_rate = ap->time_base.den;
+ frame_rate_base = ap->time_base.num;
+
+ if((unsigned)width > 32767 || (unsigned)height > 32767) {
+ av_log(s1, AV_LOG_ERROR, "Wrong size %dx%d\n", width, height);
+
+ return -1;
+ }
+
+ st = av_new_stream(s1, 0);
+ if (!st) {
+ return -ENOMEM;
+ }
+ av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
+
+ s->width = width;
+ s->height = height;
+ s->frame_rate = frame_rate;
+ s->frame_rate_base = frame_rate_base;
+
+ video_device = ap->device;
+ if (!video_device) {
+ video_device = "/dev/video";
+ }
+ capabilities = 0;
+ s->fd = device_open(video_device, &capabilities);
+ if (s->fd < 0) {
+ av_free(st);
+
+ return AVERROR_IO;
+ }
+ av_log(s1, AV_LOG_INFO, "[%d]Capabilities: %x\n", s->fd, capabilities);
+
+ desired_format = fmt_ff2v4l(ap->pix_fmt);
+ if (desired_format == 0 || (device_init(s->fd, &width, &height, desired_format) < 0)) {
+ int i, done;
+
+ done = 0; i = 0;
+ while (!done) {
+ desired_format = fmt_conversion_table[i].v4l2_fmt;
+ if (device_init(s->fd, &width, &height, desired_format) < 0) {
+ desired_format = 0;
+ i++;
+ } else {
+ done = 1;
+ }
+ if (i == sizeof(fmt_conversion_table) / sizeof(struct fmt_map)) {
+ done = 1;
+ }
+ }
+ }
+ if (desired_format == 0) {
+ av_log(s1, AV_LOG_ERROR, "Cannot find a proper format.\n");
+ close(s->fd);
+ av_free(st);
+
+ return AVERROR_IO;
+ }
+ s->frame_format = desired_format;
+
+ st->codec->pix_fmt = fmt_v4l2ff(desired_format);
+ s->frame_size = avpicture_get_size(st->codec->pix_fmt, width, height);
+ if (capabilities & V4L2_CAP_STREAMING) {
+ s->io_method = io_mmap;
+ res = mmap_init(s);
+ if (res == 0) {
+ res = mmap_start(s);
+ }
+ } else {
+ s->io_method = io_read;
+ res = read_init(s);
+ }
+ if (res < 0) {
+ close(s->fd);
+ av_free(st);
+
+ return AVERROR_IO;
+ }
+ s->top_field_first = first_field(s->fd);
+
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_RAWVIDEO;
+ st->codec->width = width;
+ st->codec->height = height;
+ st->codec->time_base.den = frame_rate;
+ st->codec->time_base.num = frame_rate_base;
+ st->codec->bit_rate = s->frame_size * 1/av_q2d(st->codec->time_base) * 8;
+
+ return 0;
+}
+
+static int v4l2_read_packet(AVFormatContext *s1, AVPacket *pkt)
+{
+ struct video_data *s = s1->priv_data;
+ int res;
+
+ if (av_new_packet(pkt, s->frame_size) < 0)
+ return AVERROR_IO;
+
+ if (s->io_method == io_mmap) {
+ res = mmap_read_frame(s, pkt->data, &pkt->pts);
+ } else if (s->io_method == io_read) {
+ res = read_frame(s, pkt->data, &pkt->pts);
+ } else {
+ return AVERROR_IO;
+ }
+ if (res < 0) {
+ return AVERROR_IO;
+ }
+
+ if (s1->streams[0]->codec->coded_frame) {
+ s1->streams[0]->codec->coded_frame->interlaced_frame = 1;
+ s1->streams[0]->codec->coded_frame->top_field_first = s->top_field_first;
+ }
+
+ return s->frame_size;
+}
+
+static int v4l2_read_close(AVFormatContext *s1)
+{
+ struct video_data *s = s1->priv_data;
+
+ if (s->io_method == io_mmap) {
+ mmap_close(s);
+ }
+
+ close(s->fd);
+ return 0;
+}
+
+AVInputFormat v4l2_demuxer = {
+ "video4linux2",
+ "video grab",
+ sizeof(struct video_data),
+ NULL,
+ v4l2_read_header,
+ v4l2_read_packet,
+ v4l2_read_close,
+ .flags = AVFMT_NOFILE,
+};
diff --git a/contrib/ffmpeg/libavformat/voc.c b/contrib/ffmpeg/libavformat/voc.c
new file mode 100644
index 000000000..329f07739
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/voc.c
@@ -0,0 +1,36 @@
+/*
+ * Creative Voice File common data.
+ * Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "voc.h"
+
+const unsigned char voc_magic[21] = "Creative Voice File\x1A";
+
+const CodecTag voc_codec_tags[] = {
+ {CODEC_ID_PCM_U8, 0x00},
+ {CODEC_ID_ADPCM_SBPRO_4, 0x01},
+ {CODEC_ID_ADPCM_SBPRO_3, 0x02},
+ {CODEC_ID_ADPCM_SBPRO_2, 0x03},
+ {CODEC_ID_PCM_S16LE, 0x04},
+ {CODEC_ID_PCM_ALAW, 0x06},
+ {CODEC_ID_PCM_MULAW, 0x07},
+ {CODEC_ID_ADPCM_CT, 0x0200},
+ {0, 0},
+};
diff --git a/contrib/ffmpeg/libavformat/voc.h b/contrib/ffmpeg/libavformat/voc.h
new file mode 100644
index 000000000..16adb0078
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/voc.h
@@ -0,0 +1,51 @@
+/*
+ * Creative Voice File demuxer.
+ * Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef VOC_H
+#define VOC_H
+
+#include "avformat.h"
+#include "riff.h" /* for CodecTag */
+
+typedef struct voc_dec_context {
+ int remaining_size;
+} voc_dec_context_t;
+
+typedef enum voc_type {
+ VOC_TYPE_EOF = 0x00,
+ VOC_TYPE_VOICE_DATA = 0x01,
+ VOC_TYPE_VOICE_DATA_CONT = 0x02,
+ VOC_TYPE_SILENCE = 0x03,
+ VOC_TYPE_MARKER = 0x04,
+ VOC_TYPE_ASCII = 0x05,
+ VOC_TYPE_REPETITION_START = 0x06,
+ VOC_TYPE_REPETITION_END = 0x07,
+ VOC_TYPE_EXTENDED = 0x08,
+ VOC_TYPE_NEW_VOICE_DATA = 0x09,
+} voc_type_t;
+
+extern const unsigned char voc_magic[21];
+extern const CodecTag voc_codec_tags[];
+
+int voc_get_packet(AVFormatContext *s, AVPacket *pkt,
+ AVStream *st, int max_size);
+
+#endif
diff --git a/contrib/ffmpeg/libavformat/vocdec.c b/contrib/ffmpeg/libavformat/vocdec.c
new file mode 100644
index 000000000..6a7869227
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/vocdec.c
@@ -0,0 +1,155 @@
+/*
+ * Creative Voice File demuxer.
+ * Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "voc.h"
+
+
+static const int voc_max_pkt_size = 2048;
+
+
+static int voc_probe(AVProbeData *p)
+{
+ int version, check;
+
+ if (p->buf_size < 26)
+ return 0;
+ if (memcmp(p->buf, voc_magic, sizeof(voc_magic) - 1))
+ return 0;
+ version = p->buf[22] | (p->buf[23] << 8);
+ check = p->buf[24] | (p->buf[25] << 8);
+ if (~version + 0x1234 != check)
+ return 10;
+
+ return AVPROBE_SCORE_MAX;
+}
+
+static int voc_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ voc_dec_context_t *voc = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int header_size;
+ AVStream *st;
+
+ url_fskip(pb, 20);
+ header_size = get_le16(pb) - 22;
+ if (header_size != 4) {
+ av_log(s, AV_LOG_ERROR, "unkown header size: %d\n", header_size);
+ return AVERROR_NOTSUPP;
+ }
+ url_fskip(pb, header_size);
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+
+ voc->remaining_size = 0;
+ return 0;
+}
+
+int
+voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size)
+{
+ voc_dec_context_t *voc = s->priv_data;
+ AVCodecContext *dec = st->codec;
+ ByteIOContext *pb = &s->pb;
+ voc_type_t type;
+ int size;
+ int sample_rate = 0;
+ int channels = 1;
+
+ while (!voc->remaining_size) {
+ type = get_byte(pb);
+ if (type == VOC_TYPE_EOF)
+ return AVERROR_IO;
+ voc->remaining_size = get_le24(pb);
+ max_size -= 4;
+
+ switch (type) {
+ case VOC_TYPE_VOICE_DATA:
+ dec->sample_rate = 1000000 / (256 - get_byte(pb));
+ if (sample_rate)
+ dec->sample_rate = sample_rate;
+ dec->channels = channels;
+ dec->codec_id = codec_get_id(voc_codec_tags, get_byte(pb));
+ dec->bits_per_sample = av_get_bits_per_sample(dec->codec_id);
+ voc->remaining_size -= 2;
+ max_size -= 2;
+ channels = 1;
+ break;
+
+ case VOC_TYPE_VOICE_DATA_CONT:
+ break;
+
+ case VOC_TYPE_EXTENDED:
+ sample_rate = get_le16(pb);
+ get_byte(pb);
+ channels = get_byte(pb) + 1;
+ sample_rate = 256000000 / (channels * (65536 - sample_rate));
+ voc->remaining_size = 0;
+ max_size -= 4;
+ break;
+
+ case VOC_TYPE_NEW_VOICE_DATA:
+ dec->sample_rate = get_le32(pb);
+ dec->bits_per_sample = get_byte(pb);
+ dec->channels = get_byte(pb);
+ dec->codec_id = codec_get_id(voc_codec_tags, get_le16(pb));
+ url_fskip(pb, 4);
+ voc->remaining_size -= 12;
+ max_size -= 12;
+ break;
+
+ default:
+ url_fskip(pb, voc->remaining_size);
+ max_size -= voc->remaining_size;
+ voc->remaining_size = 0;
+ break;
+ }
+ }
+
+ dec->bit_rate = dec->sample_rate * dec->bits_per_sample;
+
+ if (max_size <= 0)
+ max_size = voc_max_pkt_size;
+ size = FFMIN(voc->remaining_size, max_size);
+ voc->remaining_size -= size;
+ return av_get_packet(pb, pkt, size);
+}
+
+static int voc_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ return voc_get_packet(s, pkt, s->streams[0], 0);
+}
+
+static int voc_read_close(AVFormatContext *s)
+{
+ return 0;
+}
+
+AVInputFormat voc_demuxer = {
+ "voc",
+ "Creative Voice File format",
+ sizeof(voc_dec_context_t),
+ voc_probe,
+ voc_read_header,
+ voc_read_packet,
+ voc_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/vocenc.c b/contrib/ffmpeg/libavformat/vocenc.c
new file mode 100644
index 000000000..ed304883d
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/vocenc.c
@@ -0,0 +1,104 @@
+/*
+ * Creative Voice File muxer.
+ * Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "voc.h"
+
+
+typedef struct voc_enc_context {
+ int param_written;
+} voc_enc_context_t;
+
+static int voc_write_header(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+ const int header_size = 26;
+ const int version = 0x0114;
+
+ if (s->nb_streams != 1
+ || s->streams[0]->codec->codec_type != CODEC_TYPE_AUDIO)
+ return AVERROR_NOTSUPP;
+
+ put_buffer(pb, voc_magic, sizeof(voc_magic) - 1);
+ put_le16(pb, header_size);
+ put_le16(pb, version);
+ put_le16(pb, ~version + 0x1234);
+
+ return 0;
+}
+
+static int voc_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ voc_enc_context_t *voc = s->priv_data;
+ AVCodecContext *enc = s->streams[0]->codec;
+ ByteIOContext *pb = &s->pb;
+
+ if (!voc->param_written) {
+ int format = codec_get_tag(voc_codec_tags, enc->codec_id);
+
+ if (format > 0xFF) {
+ put_byte(pb, VOC_TYPE_NEW_VOICE_DATA);
+ put_le24(pb, pkt->size + 12);
+ put_le32(pb, enc->sample_rate);
+ put_byte(pb, enc->bits_per_sample);
+ put_byte(pb, enc->channels);
+ put_le16(pb, format);
+ put_le32(pb, 0);
+ } else {
+ if (s->streams[0]->codec->channels > 1) {
+ put_byte(pb, VOC_TYPE_EXTENDED);
+ put_le24(pb, 4);
+ put_le16(pb, 65536-256000000/(enc->sample_rate*enc->channels));
+ put_byte(pb, format);
+ put_byte(pb, enc->channels - 1);
+ }
+ put_byte(pb, VOC_TYPE_VOICE_DATA);
+ put_le24(pb, pkt->size + 2);
+ put_byte(pb, 256 - 1000000 / enc->sample_rate);
+ put_byte(pb, format);
+ }
+ voc->param_written = 1;
+ } else {
+ put_byte(pb, VOC_TYPE_VOICE_DATA_CONT);
+ put_le24(pb, pkt->size);
+ }
+
+ put_buffer(pb, pkt->data, pkt->size);
+ return 0;
+}
+
+static int voc_write_trailer(AVFormatContext *s)
+{
+ put_byte(&s->pb, 0);
+ return 0;
+}
+
+AVOutputFormat voc_muxer = {
+ "voc",
+ "Creative Voice File format",
+ "audio/x-voc",
+ "voc",
+ sizeof(voc_enc_context_t),
+ CODEC_ID_PCM_U8,
+ CODEC_ID_NONE,
+ voc_write_header,
+ voc_write_packet,
+ voc_write_trailer,
+};
diff --git a/contrib/ffmpeg/libavformat/wav.c b/contrib/ffmpeg/libavformat/wav.c
new file mode 100644
index 000000000..7fb982349
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/wav.c
@@ -0,0 +1,253 @@
+/*
+ * WAV muxer and demuxer
+ * 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 "avformat.h"
+#include "allformats.h"
+#include "riff.h"
+
+typedef struct {
+ offset_t data;
+ offset_t data_end;
+} WAVContext;
+
+#ifdef CONFIG_MUXERS
+static int wav_write_header(AVFormatContext *s)
+{
+ WAVContext *wav = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ offset_t fmt;
+
+ put_tag(pb, "RIFF");
+ put_le32(pb, 0); /* file length */
+ put_tag(pb, "WAVE");
+
+ /* format header */
+ fmt = start_tag(pb, "fmt ");
+ if (put_wav_header(pb, s->streams[0]->codec) < 0) {
+ av_free(wav);
+ return -1;
+ }
+ end_tag(pb, fmt);
+
+ av_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate);
+
+ /* data header */
+ wav->data = start_tag(pb, "data");
+
+ put_flush_packet(pb);
+
+ return 0;
+}
+
+static int wav_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ ByteIOContext *pb = &s->pb;
+ put_buffer(pb, pkt->data, pkt->size);
+ return 0;
+}
+
+static int wav_write_trailer(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+ WAVContext *wav = s->priv_data;
+ offset_t file_size;
+
+ if (!url_is_streamed(&s->pb)) {
+ end_tag(pb, wav->data);
+
+ /* update file size */
+ file_size = url_ftell(pb);
+ url_fseek(pb, 4, SEEK_SET);
+ put_le32(pb, (uint32_t)(file_size - 8));
+ url_fseek(pb, file_size, SEEK_SET);
+
+ put_flush_packet(pb);
+ }
+ return 0;
+}
+#endif //CONFIG_MUXERS
+
+/* return the size of the found tag */
+/* XXX: > 2GB ? */
+static int find_tag(ByteIOContext *pb, uint32_t tag1)
+{
+ unsigned int tag;
+ int size;
+
+ for(;;) {
+ if (url_feof(pb))
+ return -1;
+ tag = get_le32(pb);
+ size = get_le32(pb);
+ if (tag == tag1)
+ break;
+ url_fseek(pb, size, SEEK_CUR);
+ }
+ if (size < 0)
+ size = 0x7fffffff;
+ return size;
+}
+
+static int wav_probe(AVProbeData *p)
+{
+ /* check file header */
+ if (p->buf_size <= 32)
+ return 0;
+ if (p->buf[0] == 'R' && p->buf[1] == 'I' &&
+ p->buf[2] == 'F' && p->buf[3] == 'F' &&
+ p->buf[8] == 'W' && p->buf[9] == 'A' &&
+ p->buf[10] == 'V' && p->buf[11] == 'E')
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+/* wav input */
+static int wav_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ int size;
+ unsigned int tag;
+ ByteIOContext *pb = &s->pb;
+ AVStream *st;
+ WAVContext *wav = s->priv_data;
+
+ /* check RIFF header */
+ tag = get_le32(pb);
+
+ if (tag != MKTAG('R', 'I', 'F', 'F'))
+ return -1;
+ get_le32(pb); /* file size */
+ tag = get_le32(pb);
+ if (tag != MKTAG('W', 'A', 'V', 'E'))
+ return -1;
+
+ /* parse fmt header */
+ size = find_tag(pb, MKTAG('f', 'm', 't', ' '));
+ if (size < 0)
+ return -1;
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+
+ get_wav_header(pb, st->codec, size);
+ st->need_parsing = 1;
+
+ av_set_pts_info(st, 64, 1, st->codec->sample_rate);
+
+ size = find_tag(pb, MKTAG('d', 'a', 't', 'a'));
+ if (size < 0)
+ return -1;
+ wav->data_end= url_ftell(pb) + size;
+ return 0;
+}
+
+#define MAX_SIZE 4096
+
+static int wav_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ int ret, size, left;
+ AVStream *st;
+ WAVContext *wav = s->priv_data;
+
+ if (url_feof(&s->pb))
+ return AVERROR_IO;
+ st = s->streams[0];
+
+ left= wav->data_end - url_ftell(&s->pb);
+ if(left <= 0){
+ left = find_tag(&(s->pb), MKTAG('d', 'a', 't', 'a'));
+ if (left < 0) {
+ return AVERROR_IO;
+ }
+ wav->data_end= url_ftell(&s->pb) + left;
+ }
+
+ size = MAX_SIZE;
+ if (st->codec->block_align > 1) {
+ if (size < st->codec->block_align)
+ size = st->codec->block_align;
+ size = (size / st->codec->block_align) * st->codec->block_align;
+ }
+ size= FFMIN(size, left);
+ if (av_new_packet(pkt, size))
+ return AVERROR_IO;
+ pkt->stream_index = 0;
+
+ ret = get_buffer(&s->pb, pkt->data, pkt->size);
+ if (ret < 0)
+ av_free_packet(pkt);
+ /* note: we need to modify the packet size here to handle the last
+ packet */
+ pkt->size = ret;
+ return ret;
+}
+
+static int wav_read_close(AVFormatContext *s)
+{
+ return 0;
+}
+
+static int wav_read_seek(AVFormatContext *s,
+ int stream_index, int64_t timestamp, int flags)
+{
+ AVStream *st;
+
+ st = s->streams[0];
+ switch(st->codec->codec_id) {
+ case CODEC_ID_MP2:
+ case CODEC_ID_MP3:
+ case CODEC_ID_AC3:
+ case CODEC_ID_DTS:
+ /* use generic seeking with dynamically generated indexes */
+ return -1;
+ default:
+ break;
+ }
+ return pcm_read_seek(s, stream_index, timestamp, flags);
+}
+
+#ifdef CONFIG_WAV_DEMUXER
+AVInputFormat wav_demuxer = {
+ "wav",
+ "wav format",
+ sizeof(WAVContext),
+ wav_probe,
+ wav_read_header,
+ wav_read_packet,
+ wav_read_close,
+ wav_read_seek,
+};
+#endif
+#ifdef CONFIG_WAV_MUXER
+AVOutputFormat wav_muxer = {
+ "wav",
+ "wav format",
+ "audio/x-wav",
+ "wav",
+ sizeof(WAVContext),
+ CODEC_ID_PCM_S16LE,
+ CODEC_ID_NONE,
+ wav_write_header,
+ wav_write_packet,
+ wav_write_trailer,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/wc3movie.c b/contrib/ffmpeg/libavformat/wc3movie.c
new file mode 100644
index 000000000..6b3242797
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/wc3movie.c
@@ -0,0 +1,394 @@
+/*
+ * Wing Commander III Movie (.mve) File Demuxer
+ * 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 wc3movie.c
+ * Wing Commander III Movie file demuxer
+ * by Mike Melanson (melanson@pcisys.net)
+ * for more information on the WC3 .mve file format, visit:
+ * http://www.pcisys.net/~melanson/codecs/
+ */
+
+#include "avformat.h"
+
+#define WC3_PREAMBLE_SIZE 8
+
+#define FORM_TAG MKTAG('F', 'O', 'R', 'M')
+#define MOVE_TAG MKTAG('M', 'O', 'V', 'E')
+#define _PC__TAG MKTAG('_', 'P', 'C', '_')
+#define SOND_TAG MKTAG('S', 'O', 'N', 'D')
+#define BNAM_TAG MKTAG('B', 'N', 'A', 'M')
+#define SIZE_TAG MKTAG('S', 'I', 'Z', 'E')
+#define PALT_TAG MKTAG('P', 'A', 'L', 'T')
+#define INDX_TAG MKTAG('I', 'N', 'D', 'X')
+#define BRCH_TAG MKTAG('B', 'R', 'C', 'H')
+#define SHOT_TAG MKTAG('S', 'H', 'O', 'T')
+#define VGA__TAG MKTAG('V', 'G', 'A', ' ')
+#define TEXT_TAG MKTAG('T', 'E', 'X', 'T')
+#define AUDI_TAG MKTAG('A', 'U', 'D', 'I')
+
+/* video resolution unless otherwise specified */
+#define WC3_DEFAULT_WIDTH 320
+#define WC3_DEFAULT_HEIGHT 165
+
+/* always use the same PCM audio parameters */
+#define WC3_SAMPLE_RATE 22050
+#define WC3_AUDIO_CHANNELS 1
+#define WC3_AUDIO_BITS 16
+
+/* nice, constant framerate */
+#define WC3_FRAME_PTS_INC (90000 / 15)
+
+#define PALETTE_SIZE (256 * 3)
+#define PALETTE_COUNT 256
+
+typedef struct Wc3DemuxContext {
+ int width;
+ int height;
+ unsigned char *palettes;
+ int palette_count;
+ int64_t pts;
+ int video_stream_index;
+ int audio_stream_index;
+
+ AVPaletteControl palette_control;
+
+} Wc3DemuxContext;
+
+/* bizarre palette lookup table */
+static const unsigned char wc3_pal_lookup[] = {
+ 0x00, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0E,
+ 0x10, 0x12, 0x13, 0x15, 0x16, 0x18, 0x19, 0x1A,
+ 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x23, 0x24, 0x25,
+ 0x27, 0x28, 0x29, 0x2A, 0x2C, 0x2D, 0x2E, 0x2F,
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38, 0x39,
+ 0x3A, 0x3B, 0x3C, 0x3D, 0x3F, 0x40, 0x41, 0x42,
+ 0x43, 0x44, 0x45, 0x46, 0x48, 0x49, 0x4A, 0x4B,
+ 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53,
+ 0x54, 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, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83,
+ 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B,
+ 0x8C, 0x8D, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
+ 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x99,
+ 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1,
+ 0xA2, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
+ 0xA9, 0xAA, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
+ 0xB0, 0xB1, 0xB2, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
+ 0xB7, 0xB8, 0xB9, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD,
+ 0xBE, 0xBF, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4,
+ 0xC5, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB,
+ 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD0, 0xD1,
+ 0xD2, 0xD3, 0xD4, 0xD5, 0xD5, 0xD6, 0xD7, 0xD8,
+ 0xD9, 0xDA, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
+ 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE4, 0xE5,
+ 0xE6, 0xE7, 0xE8, 0xE9, 0xE9, 0xEA, 0xEB, 0xEC,
+ 0xED, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF1, 0xF2,
+ 0xF3, 0xF4, 0xF5, 0xF6, 0xF6, 0xF7, 0xF8, 0xF9,
+ 0xFA, 0xFA, 0xFB, 0xFC, 0xFD, 0xFD, 0xFD, 0xFD
+};
+
+
+static int wc3_probe(AVProbeData *p)
+{
+ if (p->buf_size < 12)
+ return 0;
+
+ if ((LE_32(&p->buf[0]) != FORM_TAG) ||
+ (LE_32(&p->buf[8]) != MOVE_TAG))
+ return 0;
+
+ return AVPROBE_SCORE_MAX;
+}
+
+static int wc3_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ unsigned int fourcc_tag;
+ unsigned int size;
+ AVStream *st;
+ unsigned char preamble[WC3_PREAMBLE_SIZE];
+ int ret = 0;
+ int current_palette = 0;
+ int bytes_to_read;
+ int i;
+ unsigned char rotate;
+
+ /* default context members */
+ wc3->width = WC3_DEFAULT_WIDTH;
+ wc3->height = WC3_DEFAULT_HEIGHT;
+ wc3->palettes = NULL;
+ wc3->palette_count = 0;
+ wc3->pts = 0;
+ wc3->video_stream_index = wc3->audio_stream_index = 0;
+
+ /* skip the first 3 32-bit numbers */
+ url_fseek(pb, 12, SEEK_CUR);
+
+ /* traverse through the chunks and load the header information before
+ * the first BRCH tag */
+ if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
+ WC3_PREAMBLE_SIZE)
+ return AVERROR_IO;
+ fourcc_tag = LE_32(&preamble[0]);
+ size = (BE_32(&preamble[4]) + 1) & (~1);
+
+ do {
+ switch (fourcc_tag) {
+
+ case SOND_TAG:
+ case INDX_TAG:
+ /* SOND unknown, INDX unnecessary; ignore both */
+ url_fseek(pb, size, SEEK_CUR);
+ break;
+
+ case _PC__TAG:
+ /* need the number of palettes */
+ url_fseek(pb, 8, SEEK_CUR);
+ if ((ret = get_buffer(pb, preamble, 4)) != 4)
+ return AVERROR_IO;
+ wc3->palette_count = LE_32(&preamble[0]);
+ if((unsigned)wc3->palette_count >= UINT_MAX / PALETTE_SIZE){
+ wc3->palette_count= 0;
+ return -1;
+ }
+ wc3->palettes = av_malloc(wc3->palette_count * PALETTE_SIZE);
+ break;
+
+ case BNAM_TAG:
+ /* load up the name */
+ if ((unsigned)size < 512)
+ bytes_to_read = size;
+ else
+ bytes_to_read = 512;
+ if ((ret = get_buffer(pb, s->title, bytes_to_read)) != bytes_to_read)
+ return AVERROR_IO;
+ break;
+
+ case SIZE_TAG:
+ /* video resolution override */
+ if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
+ WC3_PREAMBLE_SIZE)
+ return AVERROR_IO;
+ wc3->width = LE_32(&preamble[0]);
+ wc3->height = LE_32(&preamble[4]);
+ break;
+
+ case PALT_TAG:
+ /* one of several palettes */
+ if ((unsigned)current_palette >= wc3->palette_count)
+ return AVERROR_INVALIDDATA;
+ if ((ret = get_buffer(pb,
+ &wc3->palettes[current_palette * PALETTE_SIZE],
+ PALETTE_SIZE)) != PALETTE_SIZE)
+ return AVERROR_IO;
+
+ /* transform the current palette in place */
+ for (i = current_palette * PALETTE_SIZE;
+ i < (current_palette + 1) * PALETTE_SIZE; i++) {
+ /* rotate each palette component left by 2 and use the result
+ * as an index into the color component table */
+ rotate = ((wc3->palettes[i] << 2) & 0xFF) |
+ ((wc3->palettes[i] >> 6) & 0xFF);
+ wc3->palettes[i] = wc3_pal_lookup[rotate];
+ }
+ current_palette++;
+ break;
+
+ default:
+ av_log(s, AV_LOG_ERROR, " unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
+ preamble[0], preamble[1], preamble[2], preamble[3],
+ preamble[0], preamble[1], preamble[2], preamble[3]);
+ return AVERROR_INVALIDDATA;
+ break;
+ }
+
+ if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
+ WC3_PREAMBLE_SIZE)
+ return AVERROR_IO;
+ fourcc_tag = LE_32(&preamble[0]);
+ /* chunk sizes are 16-bit aligned */
+ size = (BE_32(&preamble[4]) + 1) & (~1);
+
+ } while (fourcc_tag != BRCH_TAG);
+
+ /* initialize the decoder streams */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ av_set_pts_info(st, 33, 1, 90000);
+ wc3->video_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_XAN_WC3;
+ st->codec->codec_tag = 0; /* no fourcc */
+ st->codec->width = wc3->width;
+ st->codec->height = wc3->height;
+
+ /* palette considerations */
+ st->codec->palctrl = &wc3->palette_control;
+
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ av_set_pts_info(st, 33, 1, 90000);
+ wc3->audio_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_PCM_S16LE;
+ st->codec->codec_tag = 1;
+ st->codec->channels = WC3_AUDIO_CHANNELS;
+ st->codec->bits_per_sample = WC3_AUDIO_BITS;
+ st->codec->sample_rate = WC3_SAMPLE_RATE;
+ st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
+ st->codec->bits_per_sample;
+ st->codec->block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS;
+
+ return 0;
+}
+
+static int wc3_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ unsigned int fourcc_tag;
+ unsigned int size;
+ int packet_read = 0;
+ int ret = 0;
+ unsigned char preamble[WC3_PREAMBLE_SIZE];
+ unsigned char text[1024];
+ unsigned int palette_number;
+ int i;
+ unsigned char r, g, b;
+ int base_palette_index;
+
+ while (!packet_read) {
+
+ /* get the next chunk preamble */
+ if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
+ WC3_PREAMBLE_SIZE)
+ ret = AVERROR_IO;
+
+ fourcc_tag = LE_32(&preamble[0]);
+ /* chunk sizes are 16-bit aligned */
+ size = (BE_32(&preamble[4]) + 1) & (~1);
+
+ switch (fourcc_tag) {
+
+ case BRCH_TAG:
+ /* no-op */
+ break;
+
+ case SHOT_TAG:
+ /* load up new palette */
+ if ((ret = get_buffer(pb, preamble, 4)) != 4)
+ return AVERROR_IO;
+ palette_number = LE_32(&preamble[0]);
+ if (palette_number >= wc3->palette_count)
+ return AVERROR_INVALIDDATA;
+ base_palette_index = palette_number * PALETTE_COUNT * 3;
+ for (i = 0; i < PALETTE_COUNT; i++) {
+ r = wc3->palettes[base_palette_index + i * 3 + 0];
+ g = wc3->palettes[base_palette_index + i * 3 + 1];
+ b = wc3->palettes[base_palette_index + i * 3 + 2];
+ wc3->palette_control.palette[i] = (r << 16) | (g << 8) | (b);
+ }
+ wc3->palette_control.palette_changed = 1;
+ break;
+
+ case VGA__TAG:
+ /* send out video chunk */
+ ret= av_get_packet(pb, pkt, size);
+ pkt->stream_index = wc3->video_stream_index;
+ pkt->pts = wc3->pts;
+ if (ret != size)
+ ret = AVERROR_IO;
+ packet_read = 1;
+ break;
+
+ case TEXT_TAG:
+ /* subtitle chunk */
+#if 0
+ url_fseek(pb, size, SEEK_CUR);
+#else
+ if ((unsigned)size > sizeof(text) || (ret = get_buffer(pb, text, size)) != size)
+ ret = AVERROR_IO;
+ else {
+ int i = 0;
+ av_log (s, AV_LOG_DEBUG, "Subtitle time!\n");
+ av_log (s, AV_LOG_DEBUG, " inglish: %s\n", &text[i + 1]);
+ i += text[i] + 1;
+ av_log (s, AV_LOG_DEBUG, " doytsch: %s\n", &text[i + 1]);
+ i += text[i] + 1;
+ av_log (s, AV_LOG_DEBUG, " fronsay: %s\n", &text[i + 1]);
+ }
+#endif
+ break;
+
+ case AUDI_TAG:
+ /* send out audio chunk */
+ ret= av_get_packet(pb, pkt, size);
+ pkt->stream_index = wc3->audio_stream_index;
+ pkt->pts = wc3->pts;
+ if (ret != size)
+ ret = AVERROR_IO;
+
+ /* time to advance pts */
+ wc3->pts += WC3_FRAME_PTS_INC;
+
+ packet_read = 1;
+ break;
+
+ default:
+ av_log (s, AV_LOG_ERROR, " unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
+ preamble[0], preamble[1], preamble[2], preamble[3],
+ preamble[0], preamble[1], preamble[2], preamble[3]);
+ ret = AVERROR_INVALIDDATA;
+ packet_read = 1;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int wc3_read_close(AVFormatContext *s)
+{
+ Wc3DemuxContext *wc3 = (Wc3DemuxContext *)s->priv_data;
+
+ av_free(wc3->palettes);
+
+ return 0;
+}
+
+AVInputFormat wc3_demuxer = {
+ "wc3movie",
+ "Wing Commander III movie format",
+ sizeof(Wc3DemuxContext),
+ wc3_probe,
+ wc3_read_header,
+ wc3_read_packet,
+ wc3_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/westwood.c b/contrib/ffmpeg/libavformat/westwood.c
new file mode 100644
index 000000000..5c42e3b55
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/westwood.c
@@ -0,0 +1,414 @@
+/*
+ * Westwood Studios Multimedia Formats Demuxer (VQA, AUD)
+ * 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 westwood.c
+ * Westwood Studios VQA & AUD file demuxers
+ * by Mike Melanson (melanson@pcisys.net)
+ * for more information on the Westwood file formats, visit:
+ * http://www.pcisys.net/~melanson/codecs/
+ * http://www.geocities.com/SiliconValley/8682/aud3.txt
+ *
+ * Implementation note: There is no definite file signature for AUD files.
+ * The demuxer uses a probabilistic strategy for content detection. This
+ * entails performing sanity checks on certain header values in order to
+ * qualify a file. Refer to wsaud_probe() for the precise parameters.
+ */
+
+#include "avformat.h"
+
+#define AUD_HEADER_SIZE 12
+#define AUD_CHUNK_PREAMBLE_SIZE 8
+#define AUD_CHUNK_SIGNATURE 0x0000DEAF
+
+#define FORM_TAG MKBETAG('F', 'O', 'R', 'M')
+#define WVQA_TAG MKBETAG('W', 'V', 'Q', 'A')
+#define VQHD_TAG MKBETAG('V', 'Q', 'H', 'D')
+#define FINF_TAG MKBETAG('F', 'I', 'N', 'F')
+#define SND0_TAG MKBETAG('S', 'N', 'D', '0')
+#define SND1_TAG MKBETAG('S', 'N', 'D', '1')
+#define SND2_TAG MKBETAG('S', 'N', 'D', '2')
+#define VQFR_TAG MKBETAG('V', 'Q', 'F', 'R')
+
+/* don't know what these tags are for, but acknowledge their existence */
+#define CINF_TAG MKBETAG('C', 'I', 'N', 'F')
+#define CINH_TAG MKBETAG('C', 'I', 'N', 'H')
+#define CIND_TAG MKBETAG('C', 'I', 'N', 'D')
+#define PINF_TAG MKBETAG('P', 'I', 'N', 'F')
+#define PINH_TAG MKBETAG('P', 'I', 'N', 'H')
+#define PIND_TAG MKBETAG('P', 'I', 'N', 'D')
+#define CMDS_TAG MKBETAG('C', 'M', 'D', 'S')
+
+#define VQA_HEADER_SIZE 0x2A
+#define VQA_FRAMERATE 15
+#define VQA_VIDEO_PTS_INC (90000 / VQA_FRAMERATE)
+#define VQA_PREAMBLE_SIZE 8
+
+typedef struct WsAudDemuxContext {
+ int audio_samplerate;
+ int audio_channels;
+ int audio_bits;
+ int audio_type;
+ int audio_stream_index;
+ int64_t audio_frame_counter;
+} WsAudDemuxContext;
+
+typedef struct WsVqaDemuxContext {
+ int audio_samplerate;
+ int audio_channels;
+ int audio_bits;
+
+ int audio_stream_index;
+ int video_stream_index;
+
+ int64_t audio_frame_counter;
+ int64_t video_pts;
+} WsVqaDemuxContext;
+
+static int wsaud_probe(AVProbeData *p)
+{
+ int field;
+
+ /* Probabilistic content detection strategy: There is no file signature
+ * so perform sanity checks on various header parameters:
+ * 8000 <= sample rate (16 bits) <= 48000 ==> 40001 acceptable numbers
+ * compression type (8 bits) = 1 or 99 ==> 2 acceptable numbers
+ * There is a total of 24 bits. The number space contains 2^24 =
+ * 16777216 numbers. There are 40001 * 2 = 80002 acceptable combinations
+ * of numbers. There is a 80002/16777216 = 0.48% chance of a false
+ * positive.
+ */
+
+ if (p->buf_size < AUD_HEADER_SIZE)
+ return 0;
+
+ /* check sample rate */
+ field = LE_16(&p->buf[0]);
+ if ((field < 8000) || (field > 48000))
+ return 0;
+
+ /* note: only check for WS IMA (type 99) right now since there is no
+ * support for type 1 */
+ if (p->buf[11] != 99)
+ return 0;
+
+ /* return 1/2 certainty since this file check is a little sketchy */
+ return AVPROBE_SCORE_MAX / 2;
+}
+
+static int wsaud_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ WsAudDemuxContext *wsaud = (WsAudDemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVStream *st;
+ unsigned char header[AUD_HEADER_SIZE];
+
+ if (get_buffer(pb, header, AUD_HEADER_SIZE) != AUD_HEADER_SIZE)
+ return AVERROR_IO;
+ wsaud->audio_samplerate = LE_16(&header[0]);
+ if (header[11] == 99)
+ wsaud->audio_type = CODEC_ID_ADPCM_IMA_WS;
+ else
+ return AVERROR_INVALIDDATA;
+
+ /* flag 0 indicates stereo */
+ wsaud->audio_channels = (header[10] & 0x1) + 1;
+ /* flag 1 indicates 16 bit audio */
+ wsaud->audio_bits = (((header[10] & 0x2) >> 1) + 1) * 8;
+
+ /* initialize the audio decoder stream */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ av_set_pts_info(st, 33, 1, wsaud->audio_samplerate);
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = wsaud->audio_type;
+ st->codec->codec_tag = 0; /* no tag */
+ st->codec->channels = wsaud->audio_channels;
+ st->codec->sample_rate = wsaud->audio_samplerate;
+ st->codec->bits_per_sample = wsaud->audio_bits;
+ st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
+ st->codec->bits_per_sample / 4;
+ st->codec->block_align = st->codec->channels * st->codec->bits_per_sample;
+
+ wsaud->audio_stream_index = st->index;
+ wsaud->audio_frame_counter = 0;
+
+ return 0;
+}
+
+static int wsaud_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ WsAudDemuxContext *wsaud = (WsAudDemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ unsigned char preamble[AUD_CHUNK_PREAMBLE_SIZE];
+ unsigned int chunk_size;
+ int ret = 0;
+
+ if (get_buffer(pb, preamble, AUD_CHUNK_PREAMBLE_SIZE) !=
+ AUD_CHUNK_PREAMBLE_SIZE)
+ return AVERROR_IO;
+
+ /* validate the chunk */
+ if (LE_32(&preamble[4]) != AUD_CHUNK_SIGNATURE)
+ return AVERROR_INVALIDDATA;
+
+ chunk_size = LE_16(&preamble[0]);
+ ret= av_get_packet(pb, pkt, chunk_size);
+ if (ret != chunk_size)
+ return AVERROR_IO;
+ pkt->stream_index = wsaud->audio_stream_index;
+ pkt->pts = wsaud->audio_frame_counter;
+ pkt->pts /= wsaud->audio_samplerate;
+
+ /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */
+ wsaud->audio_frame_counter += (chunk_size * 2) / wsaud->audio_channels;
+
+ return ret;
+}
+
+static int wsaud_read_close(AVFormatContext *s)
+{
+// WsAudDemuxContext *wsaud = (WsAudDemuxContext *)s->priv_data;
+
+ return 0;
+}
+
+
+static int wsvqa_probe(AVProbeData *p)
+{
+ /* need 12 bytes to qualify */
+ if (p->buf_size < 12)
+ return 0;
+
+ /* check for the VQA signatures */
+ if ((BE_32(&p->buf[0]) != FORM_TAG) ||
+ (BE_32(&p->buf[8]) != WVQA_TAG))
+ return 0;
+
+ return AVPROBE_SCORE_MAX;
+}
+
+static int wsvqa_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ WsVqaDemuxContext *wsvqa = (WsVqaDemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVStream *st;
+ unsigned char *header;
+ unsigned char scratch[VQA_PREAMBLE_SIZE];
+ unsigned int chunk_tag;
+ unsigned int chunk_size;
+
+ /* initialize the video decoder stream */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ av_set_pts_info(st, 33, 1, 90000);
+ wsvqa->video_stream_index = st->index;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_WS_VQA;
+ st->codec->codec_tag = 0; /* no fourcc */
+
+ /* skip to the start of the VQA header */
+ url_fseek(pb, 20, SEEK_SET);
+
+ /* the VQA header needs to go to the decoder */
+ st->codec->extradata_size = VQA_HEADER_SIZE;
+ st->codec->extradata = av_mallocz(VQA_HEADER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
+ header = (unsigned char *)st->codec->extradata;
+ if (get_buffer(pb, st->codec->extradata, VQA_HEADER_SIZE) !=
+ VQA_HEADER_SIZE) {
+ av_free(st->codec->extradata);
+ return AVERROR_IO;
+ }
+ st->codec->width = LE_16(&header[6]);
+ st->codec->height = LE_16(&header[8]);
+
+ st->codec->time_base.num = 1;
+ st->codec->time_base.den = VQA_FRAMERATE;
+
+ /* initialize the audio decoder stream for VQA v1 or nonzero samplerate */
+ if (LE_16(&header[24]) || (LE_16(&header[0]) == 1)) {
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ av_set_pts_info(st, 33, 1, 90000);
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ if (LE_16(&header[0]) == 1)
+ st->codec->codec_id = CODEC_ID_WESTWOOD_SND1;
+ else
+ st->codec->codec_id = CODEC_ID_ADPCM_IMA_WS;
+ st->codec->codec_tag = 0; /* no tag */
+ st->codec->sample_rate = LE_16(&header[24]);
+ if (!st->codec->sample_rate)
+ st->codec->sample_rate = 22050;
+ st->codec->channels = header[26];
+ if (!st->codec->channels)
+ st->codec->channels = 1;
+ st->codec->bits_per_sample = 16;
+ st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
+ st->codec->bits_per_sample / 4;
+ st->codec->block_align = st->codec->channels * st->codec->bits_per_sample;
+
+ wsvqa->audio_stream_index = st->index;
+ wsvqa->audio_samplerate = st->codec->sample_rate;
+ wsvqa->audio_channels = st->codec->channels;
+ wsvqa->audio_frame_counter = 0;
+ }
+
+ /* there are 0 or more chunks before the FINF chunk; iterate until
+ * FINF has been skipped and the file will be ready to be demuxed */
+ do {
+ if (get_buffer(pb, scratch, VQA_PREAMBLE_SIZE) != VQA_PREAMBLE_SIZE) {
+ av_free(st->codec->extradata);
+ return AVERROR_IO;
+ }
+ chunk_tag = BE_32(&scratch[0]);
+ chunk_size = BE_32(&scratch[4]);
+
+ /* catch any unknown header tags, for curiousity */
+ switch (chunk_tag) {
+ case CINF_TAG:
+ case CINH_TAG:
+ case CIND_TAG:
+ case PINF_TAG:
+ case PINH_TAG:
+ case PIND_TAG:
+ case FINF_TAG:
+ case CMDS_TAG:
+ break;
+
+ default:
+ av_log (s, AV_LOG_ERROR, " note: unknown chunk seen (%c%c%c%c)\n",
+ scratch[0], scratch[1],
+ scratch[2], scratch[3]);
+ break;
+ }
+
+ url_fseek(pb, chunk_size, SEEK_CUR);
+ } while (chunk_tag != FINF_TAG);
+
+ wsvqa->video_pts = wsvqa->audio_frame_counter = 0;
+
+ return 0;
+}
+
+static int wsvqa_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ WsVqaDemuxContext *wsvqa = (WsVqaDemuxContext *)s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int ret = -1;
+ unsigned char preamble[VQA_PREAMBLE_SIZE];
+ unsigned int chunk_type;
+ unsigned int chunk_size;
+ int skip_byte;
+
+ while (get_buffer(pb, preamble, VQA_PREAMBLE_SIZE) == VQA_PREAMBLE_SIZE) {
+ chunk_type = BE_32(&preamble[0]);
+ chunk_size = BE_32(&preamble[4]);
+ skip_byte = chunk_size & 0x01;
+
+ if ((chunk_type == SND1_TAG) || (chunk_type == SND2_TAG) || (chunk_type == VQFR_TAG)) {
+
+ if (av_new_packet(pkt, chunk_size))
+ return AVERROR_IO;
+ ret = get_buffer(pb, pkt->data, chunk_size);
+ if (ret != chunk_size) {
+ av_free_packet(pkt);
+ return AVERROR_IO;
+ }
+
+ if (chunk_type == SND2_TAG) {
+ pkt->stream_index = wsvqa->audio_stream_index;
+
+ pkt->pts = 90000;
+ pkt->pts *= wsvqa->audio_frame_counter;
+ pkt->pts /= wsvqa->audio_samplerate;
+
+ /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */
+ wsvqa->audio_frame_counter += (chunk_size * 2) / wsvqa->audio_channels;
+ } else if(chunk_type == SND1_TAG) {
+ pkt->stream_index = wsvqa->audio_stream_index;
+
+ pkt->pts = 90000;
+ pkt->pts *= wsvqa->audio_frame_counter;
+ pkt->pts /= wsvqa->audio_samplerate;
+
+ /* unpacked size is stored in header */
+ wsvqa->audio_frame_counter += LE_16(pkt->data) / wsvqa->audio_channels;
+ } else {
+ pkt->stream_index = wsvqa->video_stream_index;
+ pkt->pts = wsvqa->video_pts;
+ wsvqa->video_pts += VQA_VIDEO_PTS_INC;
+ }
+ /* stay on 16-bit alignment */
+ if (skip_byte)
+ url_fseek(pb, 1, SEEK_CUR);
+
+ return ret;
+ } else {
+ switch(chunk_type){
+ case CMDS_TAG:
+ case SND0_TAG:
+ break;
+ default:
+ av_log(s, AV_LOG_INFO, "Skipping unknown chunk 0x%08X\n", chunk_type);
+ }
+ url_fseek(pb, chunk_size + skip_byte, SEEK_CUR);
+ }
+ }
+
+ return ret;
+}
+
+static int wsvqa_read_close(AVFormatContext *s)
+{
+// WsVqaDemuxContext *wsvqa = (WsVqaDemuxContext *)s->priv_data;
+
+ return 0;
+}
+
+#ifdef CONFIG_WSAUD_DEMUXER
+AVInputFormat wsaud_demuxer = {
+ "wsaud",
+ "Westwood Studios audio format",
+ sizeof(WsAudDemuxContext),
+ wsaud_probe,
+ wsaud_read_header,
+ wsaud_read_packet,
+ wsaud_read_close,
+};
+#endif
+#ifdef CONFIG_WSVQA_DEMUXER
+AVInputFormat wsvqa_demuxer = {
+ "wsvqa",
+ "Westwood Studios VQA format",
+ sizeof(WsVqaDemuxContext),
+ wsvqa_probe,
+ wsvqa_read_header,
+ wsvqa_read_packet,
+ wsvqa_read_close,
+};
+#endif
diff --git a/contrib/ffmpeg/libavformat/wv.c b/contrib/ffmpeg/libavformat/wv.c
new file mode 100644
index 000000000..2de07fe3f
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/wv.c
@@ -0,0 +1,202 @@
+/*
+ * WavPack demuxer
+ * 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 "avformat.h"
+#include "allformats.h"
+#include "bswap.h"
+
+// specs say that maximum block size is 1Mb
+#define WV_BLOCK_LIMIT 1047576
+
+#define WV_EXTRA_SIZE 12
+
+enum WV_FLAGS{
+ WV_MONO = 0x0004,
+ WV_HYBRID = 0x0008,
+ WV_JOINT = 0x0010,
+ WV_CROSSD = 0x0020,
+ WV_HSHAPE = 0x0040,
+ WV_FLOAT = 0x0080,
+ WV_INT32 = 0x0100,
+ WV_HBR = 0x0200,
+ WV_HBAL = 0x0400,
+ WV_MCINIT = 0x0800,
+ WV_MCEND = 0x1000,
+};
+
+static const int wv_rates[16] = {
+ 6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000,
+ 32000, 44100, 48000, 64000, 88200, 96000, 192000, -1
+};
+
+typedef struct{
+ uint32_t blksize, flags;
+ int rate, chan, bpp;
+ int block_parsed;
+ uint8_t extra[WV_EXTRA_SIZE];
+}WVContext;
+
+static int wv_probe(AVProbeData *p)
+{
+ /* check file header */
+ if (p->buf_size <= 32)
+ return 0;
+ if (p->buf[0] == 'w' && p->buf[1] == 'v' &&
+ p->buf[2] == 'p' && p->buf[3] == 'k')
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+static int wv_read_block_header(AVFormatContext *ctx, ByteIOContext *pb)
+{
+ WVContext *wc = ctx->priv_data;
+ uint32_t tag, ver;
+ int size;
+ int rate, bpp, chan;
+
+ tag = get_le32(pb);
+ if (tag != MKTAG('w', 'v', 'p', 'k'))
+ return -1;
+ size = get_le32(pb);
+ if(size < 24 || size > WV_BLOCK_LIMIT){
+ av_log(ctx, AV_LOG_ERROR, "Incorrect block size %i\n", size);
+ return -1;
+ }
+ wc->blksize = size;
+ ver = get_le16(pb);
+ if(ver < 0x402 || ver > 0x40F){
+ av_log(ctx, AV_LOG_ERROR, "Unsupported version %03X\n", ver);
+ return -1;
+ }
+ get_byte(pb); // track no
+ get_byte(pb); // track sub index
+ get_le32(pb); // total samples in file
+ get_le32(pb); // offset in samples of current block
+ get_buffer(pb, wc->extra, WV_EXTRA_SIZE);
+ wc->flags = LE_32(wc->extra + 4);
+ //parse flags
+ if(wc->flags & WV_FLOAT){
+ av_log(ctx, AV_LOG_ERROR, "Floating point data is not supported\n");
+ return -1;
+ }
+ if(wc->flags & WV_HYBRID){
+ av_log(ctx, AV_LOG_ERROR, "Hybrid coding mode is not supported\n");
+ return -1;
+ }
+ if(wc->flags & WV_INT32){
+ av_log(ctx, AV_LOG_ERROR, "Integer point data is not supported\n");
+ return -1;
+ }
+
+ bpp = ((wc->flags & 3) + 1) << 3;
+ chan = 1 + !(wc->flags & WV_MONO);
+ rate = wv_rates[(wc->flags >> 23) & 0xF];
+ if(rate == -1){
+ av_log(ctx, AV_LOG_ERROR, "Unknown sampling rate\n");
+ return -1;
+ }
+ if(!wc->bpp) wc->bpp = bpp;
+ if(!wc->chan) wc->chan = chan;
+ if(!wc->rate) wc->rate = rate;
+
+ if(wc->flags && bpp != wc->bpp){
+ av_log(ctx, AV_LOG_ERROR, "Bits per sample differ, this block: %i, header block: %i\n", bpp, wc->bpp);
+ return -1;
+ }
+ if(wc->flags && chan != wc->chan){
+ av_log(ctx, AV_LOG_ERROR, "Channels differ, this block: %i, header block: %i\n", chan, wc->chan);
+ return -1;
+ }
+ if(wc->flags && rate != wc->rate){
+ av_log(ctx, AV_LOG_ERROR, "Sampling rate differ, this block: %i, header block: %i\n", rate, wc->rate);
+ return -1;
+ }
+ wc->blksize = size - 24;
+ return 0;
+}
+
+static int wv_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ ByteIOContext *pb = &s->pb;
+ WVContext *wc = s->priv_data;
+ AVStream *st;
+
+ if(wv_read_block_header(s, pb) < 0)
+ return -1;
+
+ wc->block_parsed = 0;
+ /* now we are ready: build format streams */
+ st = av_new_stream(s, 0);
+ if (!st)
+ return -1;
+ st->codec->codec_type = CODEC_TYPE_AUDIO;
+ st->codec->codec_id = CODEC_ID_WAVPACK;
+ st->codec->channels = wc->chan;
+ st->codec->sample_rate = wc->rate;
+ st->codec->bits_per_sample = wc->bpp;
+ av_set_pts_info(st, 64, 1, wc->rate);
+ return 0;
+}
+
+static int wv_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ WVContext *wc = s->priv_data;
+ int ret;
+
+ if (url_feof(&s->pb))
+ return -EIO;
+ if(wc->block_parsed){
+ if(wv_read_block_header(s, &s->pb) < 0)
+ return -1;
+ }
+
+ if(av_new_packet(pkt, wc->blksize + WV_EXTRA_SIZE) < 0)
+ return AVERROR_NOMEM;
+ memcpy(pkt->data, wc->extra, WV_EXTRA_SIZE);
+ ret = get_buffer(&s->pb, pkt->data + WV_EXTRA_SIZE, wc->blksize);
+ if(ret != wc->blksize){
+ av_free_packet(pkt);
+ return AVERROR_IO;
+ }
+ pkt->stream_index = 0;
+ wc->block_parsed = 1;
+ pkt->size = ret + WV_EXTRA_SIZE;
+
+ return 0;
+}
+
+static int wv_read_close(AVFormatContext *s)
+{
+ return 0;
+}
+
+AVInputFormat wv_demuxer = {
+ "wv",
+ "WavPack",
+ sizeof(WVContext),
+ wv_probe,
+ wv_read_header,
+ wv_read_packet,
+ wv_read_close,
+};
diff --git a/contrib/ffmpeg/libavformat/yuv.c b/contrib/ffmpeg/libavformat/yuv.c
new file mode 100644
index 000000000..fe52cdea5
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/yuv.c
@@ -0,0 +1,161 @@
+/*
+ * .Y.U.V 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 "avformat.h"
+
+static int sizes[][2] = {
+ { 640, 480 },
+ { 720, 480 },
+ { 720, 576 },
+ { 352, 288 },
+ { 352, 240 },
+ { 160, 128 },
+ { 512, 384 },
+ { 640, 352 },
+ { 640, 240 },
+};
+
+static int infer_size(int *width_ptr, int *height_ptr, int size)
+{
+ int i;
+
+ for(i=0;i<sizeof(sizes)/sizeof(sizes[0]);i++) {
+ if ((sizes[i][0] * sizes[i][1]) == size) {
+ *width_ptr = sizes[i][0];
+ *height_ptr = sizes[i][1];
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static int yuv_read(ByteIOContext *f,
+ int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
+{
+ ByteIOContext pb1, *pb = &pb1;
+ int img_size, ret;
+ char fname[1024], *p;
+ int size;
+ URLContext *h;
+ AVImageInfo info1, *info = &info1;
+
+ img_size = url_fsize(f);
+
+ /* XXX: hack hack */
+ h = url_fileno(f);
+ url_get_filename(h, fname, sizeof(fname));
+
+ if (infer_size(&info->width, &info->height, img_size) < 0) {
+ return AVERROR_IO;
+ }
+ info->pix_fmt = PIX_FMT_YUV420P;
+
+ ret = alloc_cb(opaque, info);
+ if (ret)
+ return ret;
+
+ size = info->width * info->height;
+
+ p = strrchr(fname, '.');
+ if (!p || p[1] != 'Y')
+ return AVERROR_IO;
+
+ get_buffer(f, info->pict.data[0], size);
+
+ p[1] = 'U';
+ if (url_fopen(pb, fname, URL_RDONLY) < 0)
+ return AVERROR_IO;
+
+ get_buffer(pb, info->pict.data[1], size / 4);
+ url_fclose(pb);
+
+ p[1] = 'V';
+ if (url_fopen(pb, fname, URL_RDONLY) < 0)
+ return AVERROR_IO;
+
+ get_buffer(pb, info->pict.data[2], size / 4);
+ url_fclose(pb);
+ return 0;
+}
+
+static int yuv_write(ByteIOContext *pb2, AVImageInfo *info)
+{
+ ByteIOContext pb1, *pb;
+ char fname[1024], *p;
+ int i, j, width, height;
+ uint8_t *ptr;
+ URLContext *h;
+ static const char *ext = "YUV";
+
+ /* XXX: hack hack */
+ h = url_fileno(pb2);
+ url_get_filename(h, fname, sizeof(fname));
+
+ p = strrchr(fname, '.');
+ if (!p || p[1] != 'Y')
+ return AVERROR_IO;
+
+ width = info->width;
+ height = info->height;
+
+ for(i=0;i<3;i++) {
+ if (i == 1) {
+ width >>= 1;
+ height >>= 1;
+ }
+
+ if (i >= 1) {
+ pb = &pb1;
+ p[1] = ext[i];
+ if (url_fopen(pb, fname, URL_WRONLY) < 0)
+ return AVERROR_IO;
+ } else {
+ pb = pb2;
+ }
+
+ ptr = info->pict.data[i];
+ for(j=0;j<height;j++) {
+ put_buffer(pb, ptr, width);
+ ptr += info->pict.linesize[i];
+ }
+ put_flush_packet(pb);
+ if (i >= 1) {
+ url_fclose(pb);
+ }
+ }
+ return 0;
+}
+
+static int yuv_probe(AVProbeData *pd)
+{
+ if (match_ext(pd->filename, "Y"))
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+AVImageFormat yuv_image_format = {
+ "yuv",
+ "Y",
+ yuv_probe,
+ yuv_read,
+ (1 << PIX_FMT_YUV420P),
+ yuv_write,
+};
diff --git a/contrib/ffmpeg/libavformat/yuv4mpeg.c b/contrib/ffmpeg/libavformat/yuv4mpeg.c
new file mode 100644
index 000000000..70214ae00
--- /dev/null
+++ b/contrib/ffmpeg/libavformat/yuv4mpeg.c
@@ -0,0 +1,408 @@
+/*
+ * YUV4MPEG format
+ * 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
+ */
+#include "avformat.h"
+
+#define Y4M_MAGIC "YUV4MPEG2"
+#define Y4M_FRAME_MAGIC "FRAME"
+#define Y4M_LINE_MAX 256
+
+struct frame_attributes {
+ int interlaced_frame;
+ int top_field_first;
+};
+
+static int yuv4_generate_header(AVFormatContext *s, char* buf)
+{
+ AVStream *st;
+ int width, height;
+ int raten, rated, aspectn, aspectd, n;
+ char inter;
+ const char *colorspace = "";
+
+ st = s->streams[0];
+ width = st->codec->width;
+ height = st->codec->height;
+
+ av_reduce(&raten, &rated, st->codec->time_base.den, st->codec->time_base.num, (1UL<<31)-1);
+
+ aspectn = st->codec->sample_aspect_ratio.num;
+ aspectd = st->codec->sample_aspect_ratio.den;
+
+ if ( aspectn == 0 && aspectd == 1 ) aspectd = 0; // 0:0 means unknown
+
+ inter = 'p'; /* progressive is the default */
+ if (st->codec->coded_frame && st->codec->coded_frame->interlaced_frame) {
+ inter = st->codec->coded_frame->top_field_first ? 't' : 'b';
+ }
+
+ switch(st->codec->pix_fmt) {
+ case PIX_FMT_GRAY8:
+ colorspace = " Cmono";
+ break;
+ case PIX_FMT_YUV411P:
+ colorspace = " C411 XYSCSS=411";
+ break;
+ case PIX_FMT_YUV420P:
+ colorspace = (st->codec->codec_id == CODEC_ID_DVVIDEO)?" C420paldv XYSCSS=420PALDV":" C420mpeg2 XYSCSS=420MPEG2";
+ break;
+ case PIX_FMT_YUV422P:
+ colorspace = " C422 XYSCSS=422";
+ break;
+ case PIX_FMT_YUV444P:
+ colorspace = " C444 XYSCSS=444";
+ break;
+ }
+
+ /* construct stream header, if this is the first frame */
+ n = snprintf(buf, Y4M_LINE_MAX, "%s W%d H%d F%d:%d I%c A%d:%d%s\n",
+ Y4M_MAGIC,
+ width,
+ height,
+ raten, rated,
+ inter,
+ aspectn, aspectd,
+ colorspace);
+
+ return n;
+}
+
+static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ AVStream *st = s->streams[pkt->stream_index];
+ ByteIOContext *pb = &s->pb;
+ AVPicture *picture;
+ int* first_pkt = s->priv_data;
+ int width, height, h_chroma_shift, v_chroma_shift;
+ int i, m;
+ char buf2[Y4M_LINE_MAX+1];
+ char buf1[20];
+ uint8_t *ptr, *ptr1, *ptr2;
+
+ picture = (AVPicture *)pkt->data;
+
+ /* for the first packet we have to output the header as well */
+ if (*first_pkt) {
+ *first_pkt = 0;
+ if (yuv4_generate_header(s, buf2) < 0) {
+ av_log(s, AV_LOG_ERROR, "Error. YUV4MPEG stream header write failed.\n");
+ return AVERROR_IO;
+ } else {
+ put_buffer(pb, buf2, strlen(buf2));
+ }
+ }
+
+ /* construct frame header */
+
+ m = snprintf(buf1, sizeof(buf1), "%s\n", Y4M_FRAME_MAGIC);
+ put_buffer(pb, buf1, strlen(buf1));
+
+ width = st->codec->width;
+ height = st->codec->height;
+
+ ptr = picture->data[0];
+ for(i=0;i<height;i++) {
+ put_buffer(pb, ptr, width);
+ ptr += picture->linesize[0];
+ }
+
+ if (st->codec->pix_fmt != PIX_FMT_GRAY8){
+ // Adjust for smaller Cb and Cr planes
+ avcodec_get_chroma_sub_sample(st->codec->pix_fmt, &h_chroma_shift, &v_chroma_shift);
+ width >>= h_chroma_shift;
+ height >>= v_chroma_shift;
+
+ ptr1 = picture->data[1];
+ ptr2 = picture->data[2];
+ for(i=0;i<height;i++) { /* Cb */
+ put_buffer(pb, ptr1, width);
+ ptr1 += picture->linesize[1];
+ }
+ for(i=0;i<height;i++) { /* Cr */
+ put_buffer(pb, ptr2, width);
+ ptr2 += picture->linesize[2];
+ }
+ }
+ put_flush_packet(pb);
+ return 0;
+}
+
+static int yuv4_write_header(AVFormatContext *s)
+{
+ int* first_pkt = s->priv_data;
+
+ if (s->nb_streams != 1)
+ return AVERROR_IO;
+
+ if (s->streams[0]->codec->pix_fmt == PIX_FMT_YUV411P) {
+ av_log(s, AV_LOG_ERROR, "Warning: generating rarely used 4:1:1 YUV stream, some mjpegtools might not work.\n");
+ }
+ else if ((s->streams[0]->codec->pix_fmt != PIX_FMT_YUV420P) &&
+ (s->streams[0]->codec->pix_fmt != PIX_FMT_YUV422P) &&
+ (s->streams[0]->codec->pix_fmt != PIX_FMT_GRAY8) &&
+ (s->streams[0]->codec->pix_fmt != PIX_FMT_YUV444P)) {
+ av_log(s, AV_LOG_ERROR, "ERROR: yuv4mpeg only handles yuv444p, yuv422p, yuv420p, yuv411p and gray pixel formats. Use -pix_fmt to select one.\n");
+ return AVERROR_IO;
+ }
+
+ *first_pkt = 1;
+ return 0;
+}
+
+static int yuv4_write_trailer(AVFormatContext *s)
+{
+ return 0;
+}
+
+#ifdef CONFIG_YUV4MPEGPIPE_MUXER
+AVOutputFormat yuv4mpegpipe_muxer = {
+ "yuv4mpegpipe",
+ "YUV4MPEG pipe format",
+ "",
+ "y4m",
+ sizeof(int),
+ CODEC_ID_NONE,
+ CODEC_ID_RAWVIDEO,
+ yuv4_write_header,
+ yuv4_write_packet,
+ yuv4_write_trailer,
+ .flags = AVFMT_RAWPICTURE,
+};
+#endif
+
+/* Header size increased to allow room for optional flags */
+#define MAX_YUV4_HEADER 80
+#define MAX_FRAME_HEADER 80
+
+static int yuv4_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ char header[MAX_YUV4_HEADER+10]; // Include headroom for the longest option
+ char *tokstart,*tokend,*header_end;
+ int i;
+ ByteIOContext *pb = &s->pb;
+ int width=-1, height=-1, raten=0, rated=0, aspectn=0, aspectd=0;
+ enum PixelFormat pix_fmt=PIX_FMT_NONE,alt_pix_fmt=PIX_FMT_NONE;
+ AVStream *st;
+ struct frame_attributes *s1 = s->priv_data;
+
+ for (i=0; i<MAX_YUV4_HEADER; i++) {
+ header[i] = get_byte(pb);
+ if (header[i] == '\n') {
+ header[i+1] = 0x20; // Add a space after last option. Makes parsing "444" vs "444alpha" easier.
+ header[i+2] = 0;
+ break;
+ }
+ }
+ if (i == MAX_YUV4_HEADER) return -1;
+ if (strncmp(header, Y4M_MAGIC, strlen(Y4M_MAGIC))) return -1;
+
+ s1->interlaced_frame = 0;
+ s1->top_field_first = 0;
+ header_end = &header[i+1]; // Include space
+ for(tokstart = &header[strlen(Y4M_MAGIC) + 1]; tokstart < header_end; tokstart++) {
+ if (*tokstart==0x20) continue;
+ switch (*tokstart++) {
+ case 'W': // Width. Required.
+ width = strtol(tokstart, &tokend, 10);
+ tokstart=tokend;
+ break;
+ case 'H': // Height. Required.
+ height = strtol(tokstart, &tokend, 10);
+ tokstart=tokend;
+ break;
+ case 'C': // Color space
+ if (strncmp("420jpeg",tokstart,7)==0)
+ pix_fmt = PIX_FMT_YUV420P;
+ else if (strncmp("420mpeg2",tokstart,8)==0)
+ pix_fmt = PIX_FMT_YUV420P;
+ else if (strncmp("420paldv", tokstart, 8)==0)
+ pix_fmt = PIX_FMT_YUV420P;
+ else if (strncmp("411", tokstart, 3)==0)
+ pix_fmt = PIX_FMT_YUV411P;
+ else if (strncmp("422", tokstart, 3)==0)
+ pix_fmt = PIX_FMT_YUV422P;
+ else if (strncmp("444alpha", tokstart, 8)==0) {
+ av_log(s, AV_LOG_ERROR, "Cannot handle 4:4:4:4 YUV4MPEG stream.\n");
+ return -1;
+ } else if (strncmp("444", tokstart, 3)==0)
+ pix_fmt = PIX_FMT_YUV444P;
+ else if (strncmp("mono",tokstart, 4)==0) {
+ pix_fmt = PIX_FMT_GRAY8;
+ } else {
+ av_log(s, AV_LOG_ERROR, "YUV4MPEG stream contains an unknown pixel format.\n");
+ return -1;
+ }
+ while(tokstart<header_end&&*tokstart!=0x20) tokstart++;
+ break;
+ case 'I': // Interlace type
+ switch (*tokstart++){
+ case '?':
+ break;
+ case 'p':
+ s1->interlaced_frame=0;
+ break;
+ case 't':
+ s1->interlaced_frame=1;
+ s1->top_field_first=1;
+ break;
+ case 'b':
+ s1->interlaced_frame=1;
+ s1->top_field_first=0;
+ break;
+ case 'm':
+ av_log(s, AV_LOG_ERROR, "YUV4MPEG stream contains mixed interlaced and non-interlaced frames.\n");
+ return -1;
+ default:
+ av_log(s, AV_LOG_ERROR, "YUV4MPEG has invalid header.\n");
+ return -1;
+ }
+ break;
+ case 'F': // Frame rate
+ sscanf(tokstart,"%d:%d",&raten,&rated); // 0:0 if unknown
+ while(tokstart<header_end&&*tokstart!=0x20) tokstart++;
+ break;
+ case 'A': // Pixel aspect
+ sscanf(tokstart,"%d:%d",&aspectn,&aspectd); // 0:0 if unknown
+ while(tokstart<header_end&&*tokstart!=0x20) tokstart++;
+ break;
+ case 'X': // Vendor extensions
+ if (strncmp("YSCSS=",tokstart,6)==0) {
+ // Older nonstandard pixel format representation
+ tokstart+=6;
+ if (strncmp("420JPEG",tokstart,7)==0)
+ alt_pix_fmt=PIX_FMT_YUV420P;
+ else if (strncmp("420MPEG2",tokstart,8)==0)
+ alt_pix_fmt=PIX_FMT_YUV420P;
+ else if (strncmp("420PALDV",tokstart,8)==0)
+ alt_pix_fmt=PIX_FMT_YUV420P;
+ else if (strncmp("411",tokstart,3)==0)
+ alt_pix_fmt=PIX_FMT_YUV411P;
+ else if (strncmp("422",tokstart,3)==0)
+ alt_pix_fmt=PIX_FMT_YUV422P;
+ else if (strncmp("444",tokstart,3)==0)
+ alt_pix_fmt=PIX_FMT_YUV444P;
+ }
+ while(tokstart<header_end&&*tokstart!=0x20) tokstart++;
+ break;
+ }
+ }
+
+ if ((width == -1) || (height == -1)) {
+ av_log(s, AV_LOG_ERROR, "YUV4MPEG has invalid header.\n");
+ return -1;
+ }
+
+ if (pix_fmt == PIX_FMT_NONE) {
+ if (alt_pix_fmt == PIX_FMT_NONE)
+ pix_fmt = PIX_FMT_YUV420P;
+ else
+ pix_fmt = alt_pix_fmt;
+ }
+
+ if (raten == 0 && rated == 0) {
+ // Frame rate unknown
+ raten = 25;
+ rated = 1;
+ }
+
+ if (aspectn == 0 && aspectd == 0) {
+ // Pixel aspect unknown
+ aspectd = 1;
+ }
+
+ st = av_new_stream(s, 0);
+ st = s->streams[0];
+ st->codec->width = width;
+ st->codec->height = height;
+ av_reduce(&raten, &rated, raten, rated, (1UL<<31)-1);
+ av_set_pts_info(st, 64, rated, raten);
+ st->codec->pix_fmt = pix_fmt;
+ st->codec->codec_type = CODEC_TYPE_VIDEO;
+ st->codec->codec_id = CODEC_ID_RAWVIDEO;
+ st->codec->sample_aspect_ratio= (AVRational){aspectn, aspectd};
+
+ return 0;
+}
+
+static int yuv4_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ int i;
+ char header[MAX_FRAME_HEADER+1];
+ int packet_size, width, height;
+ AVStream *st = s->streams[0];
+ struct frame_attributes *s1 = s->priv_data;
+
+ for (i=0; i<MAX_FRAME_HEADER; i++) {
+ header[i] = get_byte(&s->pb);
+ if (header[i] == '\n') {
+ header[i+1] = 0;
+ break;
+ }
+ }
+ if (i == MAX_FRAME_HEADER) return -1;
+ if (strncmp(header, Y4M_FRAME_MAGIC, strlen(Y4M_FRAME_MAGIC))) return -1;
+
+ width = st->codec->width;
+ height = st->codec->height;
+
+ packet_size = avpicture_get_size(st->codec->pix_fmt, width, height);
+ if (packet_size < 0)
+ return -1;
+
+ if (av_get_packet(&s->pb, pkt, packet_size) != packet_size)
+ return AVERROR_IO;
+
+ if (s->streams[0]->codec->coded_frame) {
+ s->streams[0]->codec->coded_frame->interlaced_frame = s1->interlaced_frame;
+ s->streams[0]->codec->coded_frame->top_field_first = s1->top_field_first;
+ }
+
+ pkt->stream_index = 0;
+ return 0;
+}
+
+static int yuv4_read_close(AVFormatContext *s)
+{
+ return 0;
+}
+
+static int yuv4_probe(AVProbeData *pd)
+{
+ /* check file header */
+ if (pd->buf_size <= sizeof(Y4M_MAGIC))
+ return 0;
+ if (strncmp(pd->buf, Y4M_MAGIC, sizeof(Y4M_MAGIC)-1)==0)
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+#ifdef CONFIG_YUV4MPEGPIPE_DEMUXER
+AVInputFormat yuv4mpegpipe_demuxer = {
+ "yuv4mpegpipe",
+ "YUV4MPEG pipe format",
+ sizeof(struct frame_attributes),
+ yuv4_probe,
+ yuv4_read_header,
+ yuv4_read_packet,
+ yuv4_read_close,
+ .extensions = "y4m"
+};
+#endif
diff --git a/contrib/ffmpeg/libavutil/Makefile b/contrib/ffmpeg/libavutil/Makefile
new file mode 100644
index 000000000..ab0db8f9b
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/Makefile
@@ -0,0 +1,29 @@
+#
+# libavutil Makefile
+#
+include ../config.mak
+
+CFLAGS+=-DBUILD_AVUTIL
+
+OBJS= mathematics.o \
+ rational.o \
+ intfloat_readwrite.o \
+ crc.o \
+ md5.o \
+ lls.o \
+ adler32.o \
+ log.o \
+ mem.o \
+ fifo.o \
+ tree.o \
+
+HEADERS = avutil.h common.h mathematics.h integer.h rational.h \
+ intfloat_readwrite.h md5.h adler32.h log.h fifo.h
+
+NAME=avutil
+ifeq ($(BUILD_SHARED),yes)
+LIBVERSION=$(LAVUVERSION)
+LIBMAJOR=$(LAVUMAJOR)
+endif
+
+include ../common.mak
diff --git a/contrib/ffmpeg/libavutil/adler32.c b/contrib/ffmpeg/libavutil/adler32.c
new file mode 100644
index 000000000..50d57470b
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/adler32.c
@@ -0,0 +1,71 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * This is a modified version based on adler32.c from the zlib library.
+ *
+ * Copyright (C) 1995 Mark Adler
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ */
+
+#include "common.h"
+#include "adler32.h"
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+
+#define DO1(buf) {s1 += *buf++; s2 += s1;}
+#define DO4(buf) DO1(buf); DO1(buf); DO1(buf); DO1(buf);
+#define DO16(buf) DO4(buf); DO4(buf); DO4(buf); DO4(buf);
+
+unsigned long av_adler32_update(unsigned long adler, const uint8_t *buf, unsigned int len)
+{
+ unsigned long s1 = adler & 0xffff;
+ unsigned long s2 = adler >> 16;
+
+ while (len>0) {
+#ifdef CONFIG_SMALL
+ while(len>4 && s2 < (1U<<31)){
+ DO4(buf); len-=4;
+#else
+ while(len>16 && s2 < (1U<<31)){
+ DO16(buf); len-=16;
+#endif
+ }
+ DO1(buf); len--;
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+}
+
+#ifdef TEST
+#include "log.h"
+#define LEN 7001
+volatile int checksum;
+int main(){
+ int i;
+ char data[LEN];
+ av_log_level = AV_LOG_DEBUG;
+ for(i=0; i<LEN; i++)
+ data[i]= ((i*i)>>3) + 123*i;
+ for(i=0; i<1000; i++){
+ START_TIMER
+ checksum= av_adler32_update(1, data, LEN);
+ STOP_TIMER("adler")
+ }
+ av_log(NULL, AV_LOG_DEBUG, "%X == 50E6E508\n", checksum);
+}
+#endif
diff --git a/contrib/ffmpeg/libavutil/adler32.h b/contrib/ffmpeg/libavutil/adler32.h
new file mode 100644
index 000000000..f56d416fb
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/adler32.h
@@ -0,0 +1,27 @@
+/*
+ * 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
+ */
+
+#ifndef ADLER32_H
+#define ADLER32_H
+
+unsigned long av_adler32_update(unsigned long adler, const uint8_t *buf,
+ unsigned int len);
+
+#endif
diff --git a/contrib/ffmpeg/libavutil/avutil.h b/contrib/ffmpeg/libavutil/avutil.h
new file mode 100644
index 000000000..08cc61567
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/avutil.h
@@ -0,0 +1,137 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 AVUTIL_H
+#define AVUTIL_H
+
+/**
+ * @file avutil.h
+ * external api header.
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AV_STRINGIFY(s) AV_TOSTRING(s)
+#define AV_TOSTRING(s) #s
+
+#define LIBAVUTIL_VERSION_INT ((49<<16)+(1<<8)+0)
+#define LIBAVUTIL_VERSION 49.1.0
+#define LIBAVUTIL_BUILD LIBAVUTIL_VERSION_INT
+
+#define LIBAVUTIL_IDENT "Lavu" AV_STRINGIFY(LIBAVUTIL_VERSION)
+
+
+#include "common.h"
+#include "mathematics.h"
+#include "rational.h"
+#include "integer.h"
+#include "intfloat_readwrite.h"
+#include "log.h"
+
+/**
+ * Pixel format. Notes:
+ *
+ * PIX_FMT_RGB32 is handled in an endian-specific manner. A RGBA
+ * color is put together as:
+ * (A << 24) | (R << 16) | (G << 8) | B
+ * This is stored as BGRA on little endian CPU architectures and ARGB on
+ * big endian CPUs.
+ *
+ * When the pixel format is palettized RGB (PIX_FMT_PAL8), the palettized
+ * image data is stored in AVFrame.data[0]. The palette is transported in
+ * AVFrame.data[1] and, is 1024 bytes long (256 4-byte entries) and is
+ * formatted the same as in PIX_FMT_RGB32 described above (i.e., it is
+ * also endian-specific). Note also that the individual RGB palette
+ * components stored in AVFrame.data[1] should be in the range 0..255.
+ * This is important as many custom PAL8 video codecs that were designed
+ * to run on the IBM VGA graphics adapter use 6-bit palette components.
+ */
+enum PixelFormat {
+ PIX_FMT_NONE= -1,
+ PIX_FMT_YUV420P, ///< Planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
+ PIX_FMT_YUYV422, ///< Packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
+ PIX_FMT_RGB24, ///< Packed RGB 8:8:8, 24bpp, RGBRGB...
+ PIX_FMT_BGR24, ///< Packed RGB 8:8:8, 24bpp, BGRBGR...
+ PIX_FMT_YUV422P, ///< Planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
+ PIX_FMT_YUV444P, ///< Planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
+ PIX_FMT_RGB32, ///< Packed RGB 8:8:8, 32bpp, (msb)8A 8R 8G 8B(lsb), in cpu endianness
+ PIX_FMT_YUV410P, ///< Planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
+ PIX_FMT_YUV411P, ///< Planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
+ PIX_FMT_RGB565, ///< Packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), in cpu endianness
+ PIX_FMT_RGB555, ///< Packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), in cpu endianness most significant bit to 0
+ PIX_FMT_GRAY8, ///< Y , 8bpp
+ PIX_FMT_MONOWHITE, ///< Y , 1bpp, 1 is white
+ PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black
+ PIX_FMT_PAL8, ///< 8 bit with PIX_FMT_RGB32 palette
+ PIX_FMT_YUVJ420P, ///< Planar YUV 4:2:0, 12bpp, full scale (jpeg)
+ PIX_FMT_YUVJ422P, ///< Planar YUV 4:2:2, 16bpp, full scale (jpeg)
+ PIX_FMT_YUVJ444P, ///< Planar YUV 4:4:4, 24bpp, full scale (jpeg)
+ PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing(xvmc_render.h)
+ PIX_FMT_XVMC_MPEG2_IDCT,
+ PIX_FMT_UYVY422, ///< Packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
+ PIX_FMT_UYYVYY411, ///< Packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
+ PIX_FMT_BGR32, ///< Packed RGB 8:8:8, 32bpp, (msb)8A 8B 8G 8R(lsb), in cpu endianness
+ PIX_FMT_BGR565, ///< Packed RGB 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), in cpu endianness
+ PIX_FMT_BGR555, ///< Packed RGB 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), in cpu endianness most significant bit to 1
+ PIX_FMT_BGR8, ///< Packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
+ PIX_FMT_BGR4, ///< Packed RGB 1:2:1, 4bpp, (msb)1B 2G 1R(lsb)
+ PIX_FMT_BGR4_BYTE, ///< Packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb)
+ PIX_FMT_RGB8, ///< Packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
+ PIX_FMT_RGB4, ///< Packed RGB 1:2:1, 4bpp, (msb)2R 3G 3B(lsb)
+ PIX_FMT_RGB4_BYTE, ///< Packed RGB 1:2:1, 8bpp, (msb)2R 3G 3B(lsb)
+ PIX_FMT_NV12, ///< Planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 for UV
+ PIX_FMT_NV21, ///< as above, but U and V bytes are swapped
+
+ PIX_FMT_RGB32_1, ///< Packed RGB 8:8:8, 32bpp, (msb)8R 8G 8B 8A(lsb), in cpu endianness
+ PIX_FMT_BGR32_1, ///< Packed RGB 8:8:8, 32bpp, (msb)8B 8G 8R 8A(lsb), in cpu endianness
+
+ PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian
+ PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian
+ PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
+};
+
+#ifdef WORDS_BIGENDIAN
+#define PIX_FMT_RGBA PIX_FMT_RGB32_1
+#define PIX_FMT_BGRA PIX_FMT_BGR32_1
+#define PIX_FMT_ARGB PIX_FMT_RGB32
+#define PIX_FMT_ABGR PIX_FMT_BGR32
+#define PIX_FMT_GRAY16 PIX_FMT_GRAY16BE
+#else
+#define PIX_FMT_RGBA PIX_FMT_BGR32
+#define PIX_FMT_BGRA PIX_FMT_RGB32
+#define PIX_FMT_ARGB PIX_FMT_BGR32_1
+#define PIX_FMT_ABGR PIX_FMT_RGB32_1
+#define PIX_FMT_GRAY16 PIX_FMT_GRAY16LE
+#endif
+
+#if LIBAVUTIL_VERSION_INT < (50<<16)
+#define PIX_FMT_UYVY411 PIX_FMT_UYYVYY411
+#define PIX_FMT_RGBA32 PIX_FMT_RGB32
+#define PIX_FMT_YUV422 PIX_FMT_YUYV422
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVUTIL_H */
diff --git a/contrib/ffmpeg/libavutil/bswap.h b/contrib/ffmpeg/libavutil/bswap.h
new file mode 100644
index 000000000..4614c9045
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/bswap.h
@@ -0,0 +1,175 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file bswap.h
+ * byte swap.
+ */
+
+#ifndef __BSWAP_H__
+#define __BSWAP_H__
+
+#ifdef HAVE_BYTESWAP_H
+#include <byteswap.h>
+#else
+
+#ifdef ARCH_X86_64
+# define LEGACY_REGS "=Q"
+#else
+# define LEGACY_REGS "=q"
+#endif
+
+#if defined(ARCH_X86)
+static always_inline uint16_t bswap_16(uint16_t x)
+{
+ __asm("rorw $8, %0" :
+ LEGACY_REGS (x) :
+ "0" (x));
+ return x;
+}
+
+static always_inline uint32_t bswap_32(uint32_t x)
+{
+#if __CPU__ != 386
+ __asm("bswap %0":
+ "=r" (x) :
+#else
+ __asm("xchgb %b0,%h0\n"
+ " rorl $16,%0\n"
+ " xchgb %b0,%h0":
+ LEGACY_REGS (x) :
+#endif
+ "0" (x));
+ return x;
+}
+
+static inline uint64_t bswap_64(uint64_t x)
+{
+#ifdef ARCH_X86_64
+ __asm("bswap %0":
+ "=r" (x) :
+ "0" (x));
+ return x;
+#else
+ union {
+ uint64_t ll;
+ struct {
+ uint32_t l,h;
+ } l;
+ } r;
+ r.l.l = bswap_32 (x);
+ r.l.h = bswap_32 (x>>32);
+ return r.ll;
+#endif
+}
+
+#elif defined(ARCH_SH4)
+
+static always_inline uint16_t bswap_16(uint16_t x) {
+ __asm__("swap.b %0,%0":"=r"(x):"0"(x));
+ return x;
+}
+
+static always_inline uint32_t bswap_32(uint32_t x) {
+ __asm__(
+ "swap.b %0,%0\n"
+ "swap.w %0,%0\n"
+ "swap.b %0,%0\n"
+ :"=r"(x):"0"(x));
+ return x;
+}
+
+static inline uint64_t bswap_64(uint64_t x)
+{
+ union {
+ uint64_t ll;
+ struct {
+ uint32_t l,h;
+ } l;
+ } r;
+ r.l.l = bswap_32 (x);
+ r.l.h = bswap_32 (x>>32);
+ return r.ll;
+}
+#else
+
+static always_inline uint16_t bswap_16(uint16_t x){
+ return (x>>8) | (x<<8);
+}
+
+#ifdef ARCH_ARM
+static always_inline uint32_t bswap_32(uint32_t x){
+ uint32_t t;
+ __asm__ (
+ "eor %1, %0, %0, ror #16 \n\t"
+ "bic %1, %1, #0xFF0000 \n\t"
+ "mov %0, %0, ror #8 \n\t"
+ "eor %0, %0, %1, lsr #8 \n\t"
+ : "+r"(x), "+r"(t));
+ return x;
+}
+#else
+static always_inline uint32_t bswap_32(uint32_t x){
+ x= ((x<<8)&0xFF00FF00) | ((x>>8)&0x00FF00FF);
+ return (x>>16) | (x<<16);
+}
+#endif
+
+static inline uint64_t bswap_64(uint64_t x)
+{
+#if 0
+ x= ((x<< 8)&0xFF00FF00FF00FF00ULL) | ((x>> 8)&0x00FF00FF00FF00FFULL);
+ x= ((x<<16)&0xFFFF0000FFFF0000ULL) | ((x>>16)&0x0000FFFF0000FFFFULL);
+ return (x>>32) | (x<<32);
+#else
+ union {
+ uint64_t ll;
+ uint32_t l[2];
+ } w, r;
+ w.ll = x;
+ r.l[0] = bswap_32 (w.l[1]);
+ r.l[1] = bswap_32 (w.l[0]);
+ return r.ll;
+#endif
+}
+#endif /* defined(ARCH_X86) */
+
+#endif /* !HAVE_BYTESWAP_H */
+
+// be2me ... BigEndian to MachineEndian
+// le2me ... LittleEndian to MachineEndian
+
+#ifdef WORDS_BIGENDIAN
+#define be2me_16(x) (x)
+#define be2me_32(x) (x)
+#define be2me_64(x) (x)
+#define le2me_16(x) bswap_16(x)
+#define le2me_32(x) bswap_32(x)
+#define le2me_64(x) bswap_64(x)
+#else
+#define be2me_16(x) bswap_16(x)
+#define be2me_32(x) bswap_32(x)
+#define be2me_64(x) bswap_64(x)
+#define le2me_16(x) (x)
+#define le2me_32(x) (x)
+#define le2me_64(x) (x)
+#endif
+
+#endif /* __BSWAP_H__ */
diff --git a/contrib/ffmpeg/libavutil/common.h b/contrib/ffmpeg/libavutil/common.h
new file mode 100644
index 000000000..41bbe8f63
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/common.h
@@ -0,0 +1,449 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * 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.h
+ * common internal and external api header.
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#ifdef HAVE_AV_CONFIG_H
+/* only include the following when compiling package */
+# include "config.h"
+
+# include <stdlib.h>
+# include <stdio.h>
+# include <string.h>
+# include <ctype.h>
+# include <limits.h>
+# ifndef __BEOS__
+# include <errno.h>
+# else
+# include "berrno.h"
+# endif
+# include <math.h>
+#endif /* HAVE_AV_CONFIG_H */
+
+/* Suppress restrict if it was not defined in config.h. */
+#ifndef restrict
+# define restrict
+#endif
+
+#ifndef always_inline
+#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)
+# define always_inline __attribute__((always_inline)) inline
+#else
+# define always_inline inline
+#endif
+#endif
+
+#ifndef attribute_used
+#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)
+# define attribute_used __attribute__((used))
+#else
+# define attribute_used
+#endif
+#endif
+
+#ifndef attribute_unused
+#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)
+# define attribute_unused __attribute__((unused))
+#else
+# define attribute_unused
+#endif
+#endif
+
+#ifndef attribute_deprecated
+#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)
+# define attribute_deprecated __attribute__((deprecated))
+#else
+# define attribute_deprecated
+#endif
+#endif
+
+# include <inttypes.h>
+
+#ifndef PRId64
+#define PRId64 "lld"
+#endif
+
+#ifndef PRIu64
+#define PRIu64 "llu"
+#endif
+
+#ifndef PRIx64
+#define PRIx64 "llx"
+#endif
+
+#ifndef PRIX64
+#define PRIX64 "llX"
+#endif
+
+#ifndef PRId32
+#define PRId32 "d"
+#endif
+
+#ifndef PRIdFAST16
+#define PRIdFAST16 PRId32
+#endif
+
+#ifndef PRIdFAST32
+#define PRIdFAST32 PRId32
+#endif
+
+#ifndef INT16_MIN
+#define INT16_MIN (-0x7fff-1)
+#endif
+
+#ifndef INT16_MAX
+#define INT16_MAX 0x7fff
+#endif
+
+#ifndef INT32_MIN
+#define INT32_MIN (-0x7fffffff-1)
+#endif
+
+#ifndef INT32_MAX
+#define INT32_MAX 0x7fffffff
+#endif
+
+#ifndef UINT32_MAX
+#define UINT32_MAX 0xffffffff
+#endif
+
+#ifndef INT64_MIN
+#define INT64_MIN (-0x7fffffffffffffffLL-1)
+#endif
+
+#ifndef INT64_MAX
+#define INT64_MAX int64_t_C(9223372036854775807)
+#endif
+
+#ifndef UINT64_MAX
+#define UINT64_MAX uint64_t_C(0xFFFFFFFFFFFFFFFF)
+#endif
+
+#ifndef INT_BIT
+# if INT_MAX != 2147483647
+# define INT_BIT 64
+# else
+# define INT_BIT 32
+# endif
+#endif
+
+#ifndef int64_t_C
+#define int64_t_C(c) (c ## LL)
+#define uint64_t_C(c) (c ## ULL)
+#endif
+
+#if defined(__MINGW32__) && !defined(BUILD_AVUTIL) && defined(BUILD_SHARED_AV)
+# define FF_IMPORT_ATTR __declspec(dllimport)
+#else
+# define FF_IMPORT_ATTR
+#endif
+
+
+#ifdef HAVE_AV_CONFIG_H
+/* only include the following when compiling package */
+# include "internal.h"
+#endif
+
+//rounded divison & shift
+#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b))
+/* assume b>0 */
+#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b))
+#define FFABS(a) ((a) >= 0 ? (a) : (-(a)))
+#define FFSIGN(a) ((a) > 0 ? 1 : -1)
+
+#define FFMAX(a,b) ((a) > (b) ? (a) : (b))
+#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
+
+#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0)
+
+/* misc math functions */
+extern FF_IMPORT_ATTR const uint8_t ff_log2_tab[256];
+
+static inline int av_log2(unsigned int v)
+{
+ int n;
+
+ n = 0;
+ if (v & 0xffff0000) {
+ v >>= 16;
+ n += 16;
+ }
+ if (v & 0xff00) {
+ v >>= 8;
+ n += 8;
+ }
+ n += ff_log2_tab[v];
+
+ return n;
+}
+
+static inline int av_log2_16bit(unsigned int v)
+{
+ int n;
+
+ n = 0;
+ if (v & 0xff00) {
+ v >>= 8;
+ n += 8;
+ }
+ n += ff_log2_tab[v];
+
+ return n;
+}
+
+/* median of 3 */
+static inline int mid_pred(int a, int b, int c)
+{
+#if HAVE_CMOV
+ 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;
+#elif 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
+}
+
+/**
+ * clip a signed integer value into the amin-amax range
+ * @param a value to clip
+ * @param amin minimum value of the clip range
+ * @param amax maximum value of the clip range
+ * @return cliped value
+ */
+static inline int clip(int a, int amin, int amax)
+{
+ if (a < amin) return amin;
+ else if (a > amax) return amax;
+ else return a;
+}
+
+/**
+ * clip a signed integer value into the 0-255 range
+ * @param a value to clip
+ * @return cliped value
+ */
+static inline uint8_t clip_uint8(int a)
+{
+ if (a&(~255)) return (-a)>>31;
+ else return a;
+}
+
+/* math */
+int64_t ff_gcd(int64_t a, int64_t b);
+
+/**
+ * converts fourcc string to int
+ */
+static inline int ff_get_fourcc(const char *s){
+#ifdef HAVE_AV_CONFIG_H
+ assert( strlen(s)==4 );
+#endif
+
+ return (s[0]) + (s[1]<<8) + (s[2]<<16) + (s[3]<<24);
+}
+
+#define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
+#define MKBETAG(a,b,c,d) (d | (c << 8) | (b << 16) | (a << 24))
+
+/*!
+ * \def GET_UTF8(val, GET_BYTE, ERROR)
+ * converts a utf-8 character (up to 4 bytes long) to its 32-bit ucs-4 encoded form
+ * \param val is the output and should be of type uint32_t. It holds the converted
+ * ucs-4 character and should be a left value.
+ * \param GET_BYTE gets utf-8 encoded bytes from any proper source. It can be
+ * a function or a statement whose return value or evaluated value is of type
+ * uint8_t. It will be executed up to 4 times for values in the valid utf-8 range,
+ * and up to 7 times in the general case.
+ * \param ERROR action that should be taken when an invalid utf-8 byte is returned
+ * from GET_BYTE. It should be a statement that jumps out of the macro,
+ * like exit(), goto, return, break, or continue.
+ */
+#define GET_UTF8(val, GET_BYTE, ERROR)\
+ val= GET_BYTE;\
+ {\
+ int ones= 7 - av_log2(val ^ 255);\
+ if(ones==1)\
+ ERROR\
+ val&= 127>>ones;\
+ while(--ones > 0){\
+ int tmp= GET_BYTE - 128;\
+ if(tmp>>6)\
+ ERROR\
+ val= (val<<6) + tmp;\
+ }\
+ }
+
+/*!
+ * \def PUT_UTF8(val, tmp, PUT_BYTE)
+ * converts a 32-bit unicode character to its utf-8 encoded form (up to 4 bytes long).
+ * \param val is an input only argument and should be of type uint32_t. It holds
+ * a ucs4 encoded unicode character that is to be converted to utf-8. If
+ * val is given as a function it's executed only once.
+ * \param tmp is a temporary variable and should be of type uint8_t. It
+ * represents an intermediate value during conversion that is to be
+ * outputted by PUT_BYTE.
+ * \param PUT_BYTE writes the converted utf-8 bytes to any proper destination.
+ * It could be a function or a statement, and uses tmp as the input byte.
+ * For example, PUT_BYTE could be "*output++ = tmp;" PUT_BYTE will be
+ * executed up to 4 times for values in the valid utf-8 range and up to
+ * 7 times in the general case, depending on the length of the converted
+ * unicode character.
+ */
+#define PUT_UTF8(val, tmp, PUT_BYTE)\
+ {\
+ int bytes, shift;\
+ uint32_t in = val;\
+ if (in < 0x80) {\
+ tmp = in;\
+ PUT_BYTE\
+ } else {\
+ bytes = (av_log2(in) + 4) / 5;\
+ shift = (bytes - 1) * 6;\
+ tmp = (256 - (256 >> bytes)) | (in >> shift);\
+ PUT_BYTE\
+ while (shift >= 6) {\
+ shift -= 6;\
+ tmp = 0x80 | ((in >> shift) & 0x3f);\
+ PUT_BYTE\
+ }\
+ }\
+ }
+
+#if defined(ARCH_X86) || defined(ARCH_POWERPC)
+#if defined(ARCH_X86_64)
+static inline uint64_t read_time(void)
+{
+ uint64_t a, d;
+ asm volatile( "rdtsc\n\t"
+ : "=a" (a), "=d" (d)
+ );
+ return (d << 32) | (a & 0xffffffff);
+}
+#elif defined(ARCH_X86_32)
+static inline long long read_time(void)
+{
+ long long l;
+ asm volatile( "rdtsc\n\t"
+ : "=A" (l)
+ );
+ return l;
+}
+#else //FIXME check ppc64
+static inline uint64_t read_time(void)
+{
+ uint32_t tbu, tbl, temp;
+
+ /* from section 2.2.1 of the 32-bit PowerPC PEM */
+ __asm__ __volatile__(
+ "1:\n"
+ "mftbu %2\n"
+ "mftb %0\n"
+ "mftbu %1\n"
+ "cmpw %2,%1\n"
+ "bne 1b\n"
+ : "=r"(tbl), "=r"(tbu), "=r"(temp)
+ :
+ : "cc");
+
+ return (((uint64_t)tbu)<<32) | (uint64_t)tbl;
+}
+#endif
+
+#define START_TIMER \
+uint64_t tend;\
+uint64_t tstart= read_time();\
+
+#define STOP_TIMER(id) \
+tend= read_time();\
+{\
+ static uint64_t tsum=0;\
+ static int tcount=0;\
+ static int tskip_count=0;\
+ if(tcount<2 || tend - tstart < 8*tsum/tcount){\
+ tsum+= tend - tstart;\
+ tcount++;\
+ }else\
+ tskip_count++;\
+ if(((tcount+tskip_count)&(tcount+tskip_count-1))==0){\
+ av_log(NULL, AV_LOG_DEBUG, "%"PRIu64" dezicycles in %s, %d runs, %d skips\n", tsum*10/tcount, id, tcount, tskip_count);\
+ }\
+}
+#else
+#define START_TIMER
+#define STOP_TIMER(id) {}
+#endif
+
+/* memory */
+
+#ifdef __GNUC__
+ #define DECLARE_ALIGNED(n,t,v) t v __attribute__ ((aligned (n)))
+#else
+ #define DECLARE_ALIGNED(n,t,v) __declspec(align(n)) t v
+#endif
+
+/* memory */
+void *av_malloc(unsigned int size);
+void *av_realloc(void *ptr, unsigned int size);
+void av_free(void *ptr);
+
+void *av_mallocz(unsigned int size);
+char *av_strdup(const char *s);
+void av_freep(void *ptr);
+
+#endif /* COMMON_H */
diff --git a/contrib/ffmpeg/libavutil/crc.c b/contrib/ffmpeg/libavutil/crc.c
new file mode 100644
index 000000000..baa605d32
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/crc.c
@@ -0,0 +1,104 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "common.h"
+#include "crc.h"
+
+AVCRC *av_crcEDB88320;
+AVCRC *av_crc04C11DB7;
+AVCRC *av_crc8005 ;
+AVCRC *av_crc07 ;
+
+/**
+ * Inits a crc table.
+ * @param ctx must be an array of sizeof(AVCRC)*257 or sizeof(AVCRC)*1024
+ * @param cts_size size of ctx in bytes
+ * @return <0 on failure
+ */
+int av_crc_init(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size){
+ int i, j;
+ uint32_t c;
+
+ if (bits < 8 || bits > 32 || poly >= (1LL<<bits))
+ return -1;
+ if (ctx_size != sizeof(AVCRC)*257 && ctx_size != sizeof(AVCRC)*1024)
+ return -1;
+
+ for (i = 0; i < 256; i++) {
+ if (le) {
+ for (c = i, j = 0; j < 8; j++)
+ c = (c>>1)^(poly & (-(c&1)));
+ ctx[i] = c;
+ } else {
+ for (c = i << 24, j = 0; j < 8; j++)
+ c = (c<<1) ^ ((poly<<(32-bits)) & (((int32_t)c)>>31) );
+ ctx[i] = bswap_32(c);
+ }
+ }
+ ctx[256]=1;
+#ifndef CONFIG_SMALL
+ if(ctx_size >= sizeof(AVCRC)*1024)
+ for (i = 0; i < 256; i++)
+ for(j=0; j<3; j++)
+ ctx[256*(j+1) + i]= (ctx[256*j + i]>>8) ^ ctx[ ctx[256*j + i]&0xFF ];
+#endif
+
+ return 0;
+}
+
+uint32_t av_crc(const AVCRC *ctx, uint32_t crc, const uint8_t *buffer, size_t length){
+ const uint8_t *end= buffer+length;
+
+#ifndef CONFIG_SMALL
+ if(!ctx[256])
+ while(buffer<end-3){
+ crc ^= le2me_32(*(uint32_t*)buffer); buffer+=4;
+ crc = ctx[3*256 + ( crc &0xFF)]
+ ^ctx[2*256 + ((crc>>8 )&0xFF)]
+ ^ctx[1*256 + ((crc>>16)&0xFF)]
+ ^ctx[0*256 + ((crc>>24) )];
+ }
+#endif
+ while(buffer<end)
+ crc = ctx[((uint8_t)crc) ^ *buffer++] ^ (crc >> 8);
+
+ return crc;
+}
+
+#ifdef TEST
+#undef printf
+main(){
+ uint8_t buf[1999];
+ int i;
+ int p[4][4]={{1, 32, 0xedb88320L, 0x3D5CDD04},
+ {0, 32, 0x04c11db7L, 0xC0F5BAE0},
+ {0, 16, 0x8005 , 0x1FBB },
+ {0, 8, 0x07 , 0xE3 },};
+ AVCRC ctx[1 ? 1024:257];
+
+ for(i=0; i<sizeof(buf); i++)
+ buf[i]= i+i*i;
+
+ for(i=0; i<4; i++){
+ av_crc_init(ctx, p[i][0], p[i][1], p[i][2], sizeof(ctx));
+ printf("crc %08X =%X\n", p[i][2], av_crc(ctx, 0, buf, sizeof(buf)));
+ }
+}
+#endif
diff --git a/contrib/ffmpeg/libavutil/crc.h b/contrib/ffmpeg/libavutil/crc.h
new file mode 100644
index 000000000..e739c309b
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/crc.h
@@ -0,0 +1,35 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 CRC_H
+#define CRC_H
+
+typedef uint32_t AVCRC;
+
+extern AVCRC *av_crcEDB88320;
+extern AVCRC *av_crc04C11DB7;
+extern AVCRC *av_crc8005 ;
+extern AVCRC *av_crc07 ;
+
+int av_crc_init(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size);
+uint32_t av_crc(const AVCRC *ctx, uint32_t start_crc, const uint8_t *buffer, size_t length);
+
+#endif /* CRC_H */
+
diff --git a/contrib/ffmpeg/libavutil/fifo.c b/contrib/ffmpeg/libavutil/fifo.c
new file mode 100644
index 000000000..550f13de5
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/fifo.c
@@ -0,0 +1,137 @@
+/*
+ * A very simple circular buffer FIFO implementation
+ * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
+ * Copyright (c) 2006 Roman Shaposhnik
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "common.h"
+#include "fifo.h"
+
+int av_fifo_init(AVFifoBuffer *f, int size)
+{
+ f->buffer = av_malloc(size);
+ if (!f->buffer)
+ return -1;
+ f->end = f->buffer + size;
+ f->wptr = f->rptr = f->buffer;
+ return 0;
+}
+
+void av_fifo_free(AVFifoBuffer *f)
+{
+ av_free(f->buffer);
+}
+
+int av_fifo_size(AVFifoBuffer *f)
+{
+ int size = f->wptr - f->rptr;
+ if (size < 0)
+ size += f->end - f->buffer;
+ return size;
+}
+
+/**
+ * Get data from the fifo (returns -1 if not enough data).
+ */
+int av_fifo_read(AVFifoBuffer *f, uint8_t *buf, int buf_size)
+{
+ int len;
+ int size = f->wptr - f->rptr;
+ if (size < 0)
+ size += f->end - f->buffer;
+
+ if (size < buf_size)
+ return -1;
+ while (buf_size > 0) {
+ len = FFMIN(f->end - f->rptr, buf_size);
+ memcpy(buf, f->rptr, len);
+ buf += len;
+ f->rptr += len;
+ if (f->rptr >= f->end)
+ f->rptr = f->buffer;
+ buf_size -= len;
+ }
+ return 0;
+}
+
+/**
+ * Resizes a FIFO.
+ */
+void av_fifo_realloc(AVFifoBuffer *f, unsigned int new_size) {
+ unsigned int old_size= f->end - f->buffer;
+
+ if(old_size < new_size){
+ uint8_t *old= f->buffer;
+
+ f->buffer= av_realloc(f->buffer, new_size);
+
+ f->rptr += f->buffer - old;
+ f->wptr += f->buffer - old;
+
+ if(f->wptr < f->rptr){
+ memmove(f->rptr + new_size - old_size, f->rptr, f->buffer + old_size - f->rptr);
+ f->rptr += new_size - old_size;
+ }
+ f->end= f->buffer + new_size;
+ }
+}
+
+void av_fifo_write(AVFifoBuffer *f, const uint8_t *buf, int size)
+{
+ int len;
+
+ while (size > 0) {
+ len = FFMIN(f->end - f->wptr, size);
+ memcpy(f->wptr, buf, len);
+ f->wptr += len;
+ if (f->wptr >= f->end)
+ f->wptr = f->buffer;
+ buf += len;
+ size -= len;
+ }
+}
+
+
+/* get data from the fifo (return -1 if not enough data) */
+int av_fifo_generic_read(AVFifoBuffer *f, int buf_size, void (*func)(void*, void*, int), void* dest)
+{
+ int len;
+ int size = f->wptr - f->rptr;
+ if (size < 0)
+ size += f->end - f->buffer;
+
+ if (size < buf_size)
+ return -1;
+ while (buf_size > 0) {
+ len = FFMIN(f->end - f->rptr, buf_size);
+ func(dest, f->rptr, len);
+ f->rptr += len;
+ if (f->rptr >= f->end)
+ f->rptr = f->buffer;
+ buf_size -= len;
+ }
+ return 0;
+}
+
+/* discard data from the fifo */
+void av_fifo_drain(AVFifoBuffer *f, int size)
+{
+ f->rptr += size;
+ if (f->rptr >= f->end)
+ f->rptr -= f->end - f->buffer;
+}
diff --git a/contrib/ffmpeg/libavutil/fifo.h b/contrib/ffmpeg/libavutil/fifo.h
new file mode 100644
index 000000000..9dec0e62d
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/fifo.h
@@ -0,0 +1,25 @@
+#ifndef FIFO_H
+#define FIFO_H
+
+typedef struct AVFifoBuffer {
+ uint8_t *buffer;
+ uint8_t *rptr, *wptr, *end;
+} AVFifoBuffer;
+
+int av_fifo_init(AVFifoBuffer *f, int size);
+void av_fifo_free(AVFifoBuffer *f);
+int av_fifo_size(AVFifoBuffer *f);
+int av_fifo_read(AVFifoBuffer *f, uint8_t *buf, int buf_size);
+int av_fifo_generic_read(AVFifoBuffer *f, int buf_size, void (*func)(void*, void*, int), void* dest);
+void av_fifo_write(AVFifoBuffer *f, const uint8_t *buf, int size);
+void av_fifo_realloc(AVFifoBuffer *f, unsigned int size);
+void av_fifo_drain(AVFifoBuffer *f, int size);
+
+static inline uint8_t av_fifo_peek(AVFifoBuffer *f, int offs)
+{
+ uint8_t *ptr = f->rptr + offs;
+ if (ptr >= f->end)
+ ptr -= f->end - f->buffer;
+ return *ptr;
+}
+#endif /* FIFO_H */
diff --git a/contrib/ffmpeg/libavutil/integer.c b/contrib/ffmpeg/libavutil/integer.c
new file mode 100644
index 000000000..09cd756e2
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/integer.c
@@ -0,0 +1,223 @@
+/*
+ * arbitrary precision integers
+ * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * 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.c
+ * arbitrary precision integers.
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#include "common.h"
+#include "integer.h"
+
+AVInteger av_add_i(AVInteger a, AVInteger b){
+ int i, carry=0;
+
+ for(i=0; i<AV_INTEGER_SIZE; i++){
+ carry= (carry>>16) + a.v[i] + b.v[i];
+ a.v[i]= carry;
+ }
+ return a;
+}
+
+AVInteger av_sub_i(AVInteger a, AVInteger b){
+ int i, carry=0;
+
+ for(i=0; i<AV_INTEGER_SIZE; i++){
+ carry= (carry>>16) + a.v[i] - b.v[i];
+ a.v[i]= carry;
+ }
+ return a;
+}
+
+/**
+ * returns the rounded down value of the logarithm of base 2 of the given AVInteger.
+ * this is simply the index of the most significant bit which is 1. Or 0 of all bits are 0
+ */
+int av_log2_i(AVInteger a){
+ int i;
+
+ for(i=AV_INTEGER_SIZE-1; i>=0; i--){
+ if(a.v[i])
+ return av_log2_16bit(a.v[i]) + 16*i;
+ }
+ return -1;
+}
+
+AVInteger av_mul_i(AVInteger a, AVInteger b){
+ AVInteger out;
+ int i, j;
+ int na= (av_log2_i(a)+16) >> 4;
+ int nb= (av_log2_i(b)+16) >> 4;
+
+ memset(&out, 0, sizeof(out));
+
+ for(i=0; i<na; i++){
+ unsigned int carry=0;
+
+ if(a.v[i])
+ for(j=i; j<AV_INTEGER_SIZE && j-i<=nb; j++){
+ carry= (carry>>16) + out.v[j] + a.v[i]*b.v[j-i];
+ out.v[j]= carry;
+ }
+ }
+
+ return out;
+}
+
+/**
+ * returns 0 if a==b, 1 if a>b and -1 if a<b.
+ */
+int av_cmp_i(AVInteger a, AVInteger b){
+ int i;
+ int v= (int16_t)a.v[AV_INTEGER_SIZE-1] - (int16_t)b.v[AV_INTEGER_SIZE-1];
+ if(v) return (v>>16)|1;
+
+ for(i=AV_INTEGER_SIZE-2; i>=0; i--){
+ int v= a.v[i] - b.v[i];
+ if(v) return (v>>16)|1;
+ }
+ return 0;
+}
+
+/**
+ * bitwise shift.
+ * @param s the number of bits by which the value should be shifted right, may be negative for shifting left
+ */
+AVInteger av_shr_i(AVInteger a, int s){
+ AVInteger out;
+ int i;
+
+ for(i=0; i<AV_INTEGER_SIZE; i++){
+ int index= i + (s>>4);
+ unsigned int v=0;
+ if(index+1<AV_INTEGER_SIZE && index+1>=0) v = a.v[index+1]<<16;
+ if(index <AV_INTEGER_SIZE && index >=0) v+= a.v[index ];
+ out.v[i]= v >> (s&15);
+ }
+ return out;
+}
+
+/**
+ * returns a % b.
+ * @param quot a/b will be stored here
+ */
+AVInteger av_mod_i(AVInteger *quot, AVInteger a, AVInteger b){
+ int i= av_log2_i(a) - av_log2_i(b);
+ AVInteger quot_temp;
+ if(!quot) quot = &quot_temp;
+
+ assert((int16_t)a[AV_INTEGER_SIZE-1] >= 0 && (int16_t)b[AV_INTEGER_SIZE-1] >= 0);
+ assert(av_log2(b)>=0);
+
+ if(i > 0)
+ b= av_shr_i(b, -i);
+
+ memset(quot, 0, sizeof(AVInteger));
+
+ while(i-- >= 0){
+ *quot= av_shr_i(*quot, -1);
+ if(av_cmp_i(a, b) >= 0){
+ a= av_sub_i(a, b);
+ quot->v[0] += 1;
+ }
+ b= av_shr_i(b, 1);
+ }
+ return a;
+}
+
+/**
+ * returns a/b.
+ */
+AVInteger av_div_i(AVInteger a, AVInteger b){
+ AVInteger quot;
+ av_mod_i(&quot, a, b);
+ return quot;
+}
+
+/**
+ * converts the given int64_t to an AVInteger.
+ */
+AVInteger av_int2i(int64_t a){
+ AVInteger out;
+ int i;
+
+ for(i=0; i<AV_INTEGER_SIZE; i++){
+ out.v[i]= a;
+ a>>=16;
+ }
+ return out;
+}
+
+/**
+ * converts the given AVInteger to an int64_t.
+ * if the AVInteger is too large to fit into an int64_t,
+ * then only the least significant 64bit will be used
+ */
+int64_t av_i2int(AVInteger a){
+ int i;
+ int64_t out=(int8_t)a.v[AV_INTEGER_SIZE-1];
+
+ for(i= AV_INTEGER_SIZE-2; i>=0; i--){
+ out = (out<<16) + a.v[i];
+ }
+ return out;
+}
+
+#if 0
+#undef NDEBUG
+#include <assert.h>
+
+const uint8_t ff_log2_tab[256]={
+ 0,0,1,1,2,2,2,2,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,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,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,
+ 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,
+ 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,
+ 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,
+ 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
+};
+
+main(){
+ int64_t a,b;
+
+ for(a=7; a<256*256*256; a+=13215){
+ for(b=3; b<256*256*256; b+=27118){
+ AVInteger ai= av_int2i(a);
+ AVInteger bi= av_int2i(b);
+
+ assert(av_i2int(ai) == a);
+ assert(av_i2int(bi) == b);
+ assert(av_i2int(av_add_i(ai,bi)) == a+b);
+ assert(av_i2int(av_sub_i(ai,bi)) == a-b);
+ assert(av_i2int(av_mul_i(ai,bi)) == a*b);
+ assert(av_i2int(av_shr_i(ai, 9)) == a>>9);
+ assert(av_i2int(av_shr_i(ai,-9)) == a<<9);
+ assert(av_i2int(av_shr_i(ai, 17)) == a>>17);
+ assert(av_i2int(av_shr_i(ai,-17)) == a<<17);
+ assert(av_log2_i(ai) == av_log2(a));
+ assert(av_i2int(av_div_i(ai,bi)) == a/b);
+ }
+ }
+}
+#endif
diff --git a/contrib/ffmpeg/libavutil/integer.h b/contrib/ffmpeg/libavutil/integer.h
new file mode 100644
index 000000000..a50ad9bae
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/integer.h
@@ -0,0 +1,49 @@
+/*
+ * arbitrary precision integers
+ * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * 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.h
+ * arbitrary precision integers
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#ifndef INTEGER_H
+#define INTEGER_H
+
+#define AV_INTEGER_SIZE 8
+
+typedef struct AVInteger{
+ uint16_t v[AV_INTEGER_SIZE];
+} AVInteger;
+
+AVInteger av_add_i(AVInteger a, AVInteger b);
+AVInteger av_sub_i(AVInteger a, AVInteger b);
+int av_log2_i(AVInteger a);
+AVInteger av_mul_i(AVInteger a, AVInteger b);
+int av_cmp_i(AVInteger a, AVInteger b);
+AVInteger av_shr_i(AVInteger a, int s);
+AVInteger av_mod_i(AVInteger *quot, AVInteger a, AVInteger b);
+AVInteger av_div_i(AVInteger a, AVInteger b);
+AVInteger av_int2i(int64_t a);
+int64_t av_i2int(AVInteger a);
+
+#endif // INTEGER_H
diff --git a/contrib/ffmpeg/libavutil/internal.h b/contrib/ffmpeg/libavutil/internal.h
new file mode 100644
index 000000000..4cb0d2a7e
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/internal.h
@@ -0,0 +1,235 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file internal.h
+ * common internal api header.
+ */
+
+#ifndef INTERNAL_H
+#define INTERNAL_H
+
+#if ( defined(__PIC__) || defined(__pic__) ) && ! defined(PIC)
+# define PIC
+#endif
+
+#ifndef ENODATA
+# define ENODATA 61
+#endif
+
+#include "bswap.h"
+
+#include <stddef.h>
+#ifndef offsetof
+# define offsetof(T,F) ((unsigned int)((char *)&((T *)0)->F))
+#endif
+
+#ifdef __MINGW32__
+# ifdef _DEBUG
+# define DEBUG
+# endif
+
+# define snprintf _snprintf
+# define vsnprintf _vsnprintf
+
+# ifdef CONFIG_WINCE
+# define perror(a)
+# define abort()
+# endif
+
+/* __MINGW32__ end */
+#elif defined (CONFIG_OS2)
+/* OS/2 EMX */
+
+# include <float.h>
+
+#endif /* !__MINGW32__ && CONFIG_OS2 */
+
+#ifdef USE_FASTMEMCPY
+# include "libvo/fastmemcpy.h"
+#endif
+
+// Use rip-relative addressing if compiling PIC code on x86-64.
+#if defined(__MINGW32__) || defined(__CYGWIN__) || \
+ defined(__OS2__) || (defined (__OpenBSD__) && !defined(__ELF__))
+# if defined(ARCH_X86_64) && defined(PIC)
+# define MANGLE(a) "_" #a"(%%rip)"
+# else
+# define MANGLE(a) "_" #a
+# endif
+#else
+# if defined(ARCH_X86_64) && defined(PIC)
+# define MANGLE(a) #a"(%%rip)"
+# elif defined(CONFIG_DARWIN)
+# define MANGLE(a) "_" #a
+# else
+# define MANGLE(a) #a
+# endif
+#endif
+
+/* debug stuff */
+
+#if !defined(DEBUG) && !defined(NDEBUG)
+# define NDEBUG
+#endif
+#include <assert.h>
+
+/* dprintf macros */
+#ifdef DEBUG
+# define dprintf(fmt,...) av_log(NULL, AV_LOG_DEBUG, fmt, __VA_ARGS__)
+#else
+# define dprintf(fmt,...)
+#endif
+
+#define av_abort() do { av_log(NULL, AV_LOG_ERROR, "Abort at %s:%d\n", __FILE__, __LINE__); abort(); } while (0)
+
+/* math */
+
+extern const uint32_t ff_inverse[256];
+
+#if defined(ARCH_X86)
+# define FASTDIV(a,b) \
+ ({\
+ int ret,dmy;\
+ asm volatile(\
+ "mull %3"\
+ :"=d"(ret),"=a"(dmy)\
+ :"1"(a),"g"(ff_inverse[b])\
+ );\
+ ret;\
+ })
+#elif defined(ARCH_ARMV4L)
+# define FASTDIV(a,b) \
+ ({\
+ int ret,dmy;\
+ asm volatile(\
+ "umull %1, %0, %2, %3"\
+ :"=&r"(ret),"=&r"(dmy)\
+ :"r"(a),"r"(ff_inverse[b])\
+ );\
+ ret;\
+ })
+#elif defined(CONFIG_FASTDIV)
+# define FASTDIV(a,b) ((uint32_t)((((uint64_t)a)*ff_inverse[b])>>32))
+#else
+# define FASTDIV(a,b) ((a)/(b))
+#endif
+
+extern FF_IMPORT_ATTR const uint8_t ff_sqrt_tab[128];
+
+static inline int ff_sqrt(int a)
+{
+ int ret=0;
+ int s;
+ int ret_sq=0;
+
+ if(a<128) return ff_sqrt_tab[a];
+
+ for(s=15; s>=0; s--){
+ int b= ret_sq + (1<<(s*2)) + (ret<<s)*2;
+ if(b<=a){
+ ret_sq=b;
+ ret+= 1<<s;
+ }
+ }
+ return ret;
+}
+
+#if defined(ARCH_X86)
+#define MASK_ABS(mask, level)\
+ asm volatile(\
+ "cdq \n\t"\
+ "xorl %1, %0 \n\t"\
+ "subl %1, %0 \n\t"\
+ : "+a" (level), "=&d" (mask)\
+ );
+#else
+#define MASK_ABS(mask, level)\
+ mask= level>>31;\
+ level= (level^mask)-mask;
+#endif
+
+#ifdef 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)\
+);
+#else
+#define COPY3_IF_LT(x,y,a,b,c,d)\
+if((y)<(x)){\
+ (x)=(y);\
+ (a)=(b);\
+ (c)=(d);\
+}
+#endif
+
+/* avoid usage of various functions */
+#define malloc please_use_av_malloc
+#define free please_use_av_free
+#define realloc please_use_av_realloc
+#define time time_is_forbidden_due_to_security_issues
+#define rand rand_is_forbidden_due_to_state_trashing
+#define srand srand_is_forbidden_due_to_state_trashing
+#define sprintf sprintf_is_forbidden_due_to_security_issues_use_snprintf
+#define strcat strcat_is_forbidden_due_to_security_issues_use_pstrcat
+#if !(defined(LIBAVFORMAT_BUILD) || defined(_FRAMEHOOK_H))
+#define printf please_use_av_log
+#define fprintf please_use_av_log
+#endif
+
+#define CHECKED_ALLOCZ(p, size)\
+{\
+ p= av_mallocz(size);\
+ if(p==NULL && (size)!=0){\
+ perror("malloc");\
+ goto fail;\
+ }\
+}
+
+#ifndef HAVE_LRINTF
+/* XXX: add ISOC specific test to avoid specific BSD testing. */
+/* better than nothing implementation. */
+/* btw, rintf() is existing on fbsd too -- alex */
+static always_inline long int lrintf(float x)
+{
+#ifdef __MINGW32__
+# ifdef ARCH_X86_32
+ int32_t i;
+ asm volatile(
+ "fistpl %0\n\t"
+ : "=m" (i) : "t" (x) : "st"
+ );
+ return i;
+# else
+ /* XXX: incorrect, but make it compile */
+ return (int)(x + (x < 0 ? -0.5 : 0.5));
+# endif /* ARCH_X86_32 */
+#else
+ return (int)(rint(x));
+#endif /* __MINGW32__ */
+}
+#endif /* HAVE_LRINTF */
+
+#endif /* INTERNAL_H */
diff --git a/contrib/ffmpeg/libavutil/intfloat_readwrite.c b/contrib/ffmpeg/libavutil/intfloat_readwrite.c
new file mode 100644
index 000000000..261cf76c3
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/intfloat_readwrite.c
@@ -0,0 +1,97 @@
+/*
+ * portable IEEE float/double read/write functions
+ *
+ * Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file intfloat_readwrite.c
+ * Portable IEEE float/double read/write functions.
+ */
+
+#include "common.h"
+#include "intfloat_readwrite.h"
+
+double av_int2dbl(int64_t v){
+ if(v+v > 0xFFEULL<<52)
+ return 0.0/0.0;
+ return ldexp(((v&((1LL<<52)-1)) + (1LL<<52)) * (v>>63|1), (v>>52&0x7FF)-1075);
+}
+
+float av_int2flt(int32_t v){
+ if(v+v > 0xFF000000U)
+ return 0.0/0.0;
+ return ldexp(((v&0x7FFFFF) + (1<<23)) * (v>>31|1), (v>>23&0xFF)-150);
+}
+
+double av_ext2dbl(const AVExtFloat ext){
+ uint64_t m = 0;
+ int e, i;
+
+ for (i = 0; i < 8; i++)
+ m = (m<<8) + ext.mantissa[i];
+ e = (((int)ext.exponent[0]&0x7f)<<8) | ext.exponent[1];
+ if (e == 0x7fff && m)
+ return 0.0/0.0;
+ e -= 16383 + 63; /* In IEEE 80 bits, the whole (i.e. 1.xxxx)
+ * mantissa bit is written as opposed to the
+ * single and double precision formats */
+ if (ext.exponent[0]&0x80)
+ m= -m;
+ return ldexp(m, e);
+}
+
+int64_t av_dbl2int(double d){
+ int e;
+ if ( !d) return 0;
+ else if(d-d) return 0x7FF0000000000000LL + ((int64_t)(d<0)<<63) + (d!=d);
+ d= frexp(d, &e);
+ return (int64_t)(d<0)<<63 | (e+1022LL)<<52 | (int64_t)((fabs(d)-0.5)*(1LL<<53));
+}
+
+int32_t av_flt2int(float d){
+ int e;
+ if ( !d) return 0;
+ else if(d-d) return 0x7F800000 + ((d<0)<<31) + (d!=d);
+ d= frexp(d, &e);
+ return (d<0)<<31 | (e+126)<<23 | (int64_t)((fabs(d)-0.5)*(1<<24));
+}
+
+AVExtFloat av_dbl2ext(double d){
+ struct AVExtFloat ext= {{0}};
+ int e, i; double f; uint64_t m;
+
+ f = fabs(frexp(d, &e));
+ if (f >= 0.5 && f < 1) {
+ e += 16382;
+ ext.exponent[0] = e>>8;
+ ext.exponent[1] = e;
+ m = (uint64_t)ldexp(f, 64);
+ for (i=0; i < 8; i++)
+ ext.mantissa[i] = m>>(56-(i<<3));
+ } else if (f != 0.0) {
+ ext.exponent[0] = 0x7f; ext.exponent[1] = 0xff;
+ if (f != 1/0.0)
+ ext.mantissa[0] = ~0;
+ }
+ if (d < 0)
+ ext.exponent[0] |= 0x80;
+ return ext;
+}
+
diff --git a/contrib/ffmpeg/libavutil/intfloat_readwrite.h b/contrib/ffmpeg/libavutil/intfloat_readwrite.h
new file mode 100644
index 000000000..c535b64c8
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/intfloat_readwrite.h
@@ -0,0 +1,39 @@
+/*
+ * copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 INTFLOAT_READWRITE_H
+#define INTFLOAT_READWRITE_H
+
+#include "common.h"
+
+/* IEEE 80 bits extended float */
+typedef struct AVExtFloat {
+ uint8_t exponent[2];
+ uint8_t mantissa[8];
+} AVExtFloat;
+
+double av_int2dbl(int64_t v);
+float av_int2flt(int32_t v);
+double av_ext2dbl(const AVExtFloat ext);
+int64_t av_dbl2int(double d);
+int32_t av_flt2int(float d);
+AVExtFloat av_dbl2ext(double d);
+
+#endif /* INTFLOAT_READWRITE_H */
diff --git a/contrib/ffmpeg/libavutil/lls.c b/contrib/ffmpeg/libavutil/lls.c
new file mode 100644
index 000000000..aa9467dce
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/lls.c
@@ -0,0 +1,151 @@
+/*
+ * linear least squares model
+ *
+ * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have 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 lls.c
+ * linear least squares model
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "lls.h"
+
+#ifdef TEST
+#define av_log(a,b,...) printf(__VA_ARGS__)
+#endif
+
+void av_init_lls(LLSModel *m, int indep_count){
+ memset(m, 0, sizeof(LLSModel));
+
+ m->indep_count= indep_count;
+}
+
+void av_update_lls(LLSModel *m, double *var, double decay){
+ int i,j;
+
+ for(i=0; i<=m->indep_count; i++){
+ for(j=i; j<=m->indep_count; j++){
+ m->covariance[i][j] *= decay;
+ m->covariance[i][j] += var[i]*var[j];
+ }
+ }
+}
+
+void av_solve_lls(LLSModel *m, double threshold, int min_order){
+ int i,j,k;
+ double (*factor)[MAX_VARS+1]= &m->covariance[1][0];
+ double (*covar )[MAX_VARS+1]= &m->covariance[1][1];
+ double *covar_y = m->covariance[0];
+ int count= m->indep_count;
+
+ for(i=0; i<count; i++){
+ for(j=i; j<count; j++){
+ double sum= covar[i][j];
+
+ for(k=i-1; k>=0; k--)
+ sum -= factor[i][k]*factor[j][k];
+
+ if(i==j){
+ if(sum < threshold)
+ sum= 1.0;
+ factor[i][i]= sqrt(sum);
+ }else
+ factor[j][i]= sum / factor[i][i];
+ }
+ }
+ for(i=0; i<count; i++){
+ double sum= covar_y[i+1];
+ for(k=i-1; k>=0; k--)
+ sum -= factor[i][k]*m->coeff[0][k];
+ m->coeff[0][i]= sum / factor[i][i];
+ }
+
+ for(j=count-1; j>=min_order; j--){
+ for(i=j; i>=0; i--){
+ double sum= m->coeff[0][i];
+ for(k=i+1; k<=j; k++)
+ sum -= factor[k][i]*m->coeff[j][k];
+ m->coeff[j][i]= sum / factor[i][i];
+ }
+
+ m->variance[j]= covar_y[0];
+ for(i=0; i<=j; i++){
+ double sum= m->coeff[j][i]*covar[i][i] - 2*covar_y[i+1];
+ for(k=0; k<i; k++)
+ sum += 2*m->coeff[j][k]*covar[k][i];
+ m->variance[j] += m->coeff[j][i]*sum;
+ }
+ }
+}
+
+double av_evaluate_lls(LLSModel *m, double *param, int order){
+ int i;
+ double out= 0;
+
+ for(i=0; i<=order; i++)
+ out+= param[i]*m->coeff[order][i];
+
+ return out;
+}
+
+#ifdef TEST
+
+#include <stdlib.h>
+#include <stdio.h>
+
+int main(){
+ LLSModel m;
+ int i, order;
+
+ av_init_lls(&m, 3);
+
+ for(i=0; i<100; i++){
+ double var[4];
+ double eval, variance;
+#if 0
+ var[1] = rand() / (double)RAND_MAX;
+ var[2] = rand() / (double)RAND_MAX;
+ var[3] = rand() / (double)RAND_MAX;
+
+ var[2]= var[1] + var[3]/2;
+
+ var[0] = var[1] + var[2] + var[3] + var[1]*var[2]/100;
+#else
+ var[0] = (rand() / (double)RAND_MAX - 0.5)*2;
+ var[1] = var[0] + rand() / (double)RAND_MAX - 0.5;
+ var[2] = var[1] + rand() / (double)RAND_MAX - 0.5;
+ var[3] = var[2] + rand() / (double)RAND_MAX - 0.5;
+#endif
+ av_update_lls(&m, var, 0.99);
+ av_solve_lls(&m, 0.001, 0);
+ for(order=0; order<3; order++){
+ eval= av_evaluate_lls(&m, var+1, order);
+ av_log(NULL, AV_LOG_DEBUG, "real:%f order:%d pred:%f var:%f coeffs:%f %f %f\n",
+ var[0], order, eval, sqrt(m.variance[order] / (i+1)),
+ m.coeff[order][0], m.coeff[order][1], m.coeff[order][2]);
+ }
+ }
+ return 0;
+}
+
+#endif
diff --git a/contrib/ffmpeg/libavutil/lls.h b/contrib/ffmpeg/libavutil/lls.h
new file mode 100644
index 000000000..59ad2e958
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/lls.h
@@ -0,0 +1,45 @@
+/*
+ * linear least squares model
+ *
+ * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have 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 LLS_H
+#define LLS_H
+
+#define MAX_VARS 32
+
+//FIXME avoid direct access to LLSModel from outside
+
+/**
+ * Linear least squares model.
+ */
+typedef struct LLSModel{
+ double covariance[MAX_VARS+1][MAX_VARS+1];
+ double coeff[MAX_VARS][MAX_VARS];
+ double variance[MAX_VARS];
+ int indep_count;
+}LLSModel;
+
+void av_init_lls(LLSModel *m, int indep_count);
+void av_update_lls(LLSModel *m, double *param, double decay);
+void av_solve_lls(LLSModel *m, double threshold, int min_order);
+double av_evaluate_lls(LLSModel *m, double *param, int order);
+
+#endif
diff --git a/contrib/ffmpeg/libavutil/log.c b/contrib/ffmpeg/libavutil/log.c
new file mode 100644
index 000000000..8b2dc6f6d
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/log.c
@@ -0,0 +1,82 @@
+/*
+ * log functions
+ * Copyright (c) 2003 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 log.c
+ * log.
+ */
+
+#include "avutil.h"
+
+int av_log_level = AV_LOG_INFO;
+
+static void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl)
+{
+ static int print_prefix=1;
+ AVClass* avc= ptr ? *(AVClass**)ptr : NULL;
+ if(level>av_log_level)
+ return;
+#undef fprintf
+ if(print_prefix && avc) {
+ fprintf(stderr, "[%s @ %p]", avc->item_name(ptr), avc);
+ }
+#define fprintf please_use_av_log
+
+ print_prefix= strstr(fmt, "\n") != NULL;
+
+ vfprintf(stderr, fmt, vl);
+}
+
+#if LIBAVUTIL_VERSION_INT < (50<<16)
+static void (*av_log_callback)(void*, int, const char*, va_list) = av_log_default_callback;
+#else
+void (*av_vlog)(void*, int, const char*, va_list) = av_log_default_callback;
+#endif
+
+void av_log(void* avcl, int level, const char *fmt, ...)
+{
+ va_list vl;
+ va_start(vl, fmt);
+ av_vlog(avcl, level, fmt, vl);
+ va_end(vl);
+}
+
+#if LIBAVUTIL_VERSION_INT < (50<<16)
+void av_vlog(void* avcl, int level, const char *fmt, va_list vl)
+{
+ av_log_callback(avcl, level, fmt, vl);
+}
+
+int av_log_get_level(void)
+{
+ return av_log_level;
+}
+
+void av_log_set_level(int level)
+{
+ av_log_level = level;
+}
+
+void av_log_set_callback(void (*callback)(void*, int, const char*, va_list))
+{
+ av_log_callback = callback;
+}
+#endif
diff --git a/contrib/ffmpeg/libavutil/log.h b/contrib/ffmpeg/libavutil/log.h
new file mode 100644
index 000000000..0ff1f9fcf
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/log.h
@@ -0,0 +1,62 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 LOG_H
+#define LOG_H
+
+#include <stdarg.h>
+
+/**
+ * Used by av_log
+ */
+typedef struct AVCLASS AVClass;
+struct AVCLASS {
+ const char* class_name;
+ const char* (*item_name)(void*); /* actually passing a pointer to an AVCodecContext
+ or AVFormatContext, which begin with an AVClass.
+ Needed because av_log is in libavcodec and has no visibility
+ of AVIn/OutputFormat */
+ const struct AVOption *option;
+};
+
+/* av_log API */
+
+#define AV_LOG_QUIET -1
+#define AV_LOG_ERROR 0
+#define AV_LOG_INFO 1
+#define AV_LOG_DEBUG 2
+extern int av_log_level;
+
+#ifdef __GNUC__
+extern void av_log(void*, int level, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 3, 4)));
+#else
+extern void av_log(void*, int level, const char *fmt, ...);
+#endif
+
+#if LIBAVUTIL_VERSION_INT < (50<<16)
+extern void av_vlog(void*, int level, const char *fmt, va_list);
+extern int av_log_get_level(void);
+extern void av_log_set_level(int);
+extern void av_log_set_callback(void (*)(void*, int, const char*, va_list));
+#else
+extern void (*av_vlog)(void*, int, const char*, va_list);
+#endif
+
+#endif /* LOG_H */
diff --git a/contrib/ffmpeg/libavutil/mathematics.c b/contrib/ffmpeg/libavutil/mathematics.c
new file mode 100644
index 000000000..4be027d9d
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/mathematics.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file mathematics.c
+ * Miscellaneous math routines and tables.
+ */
+
+#include "common.h"
+#include "mathematics.h"
+
+const uint8_t ff_sqrt_tab[128]={
+ 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 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, 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, 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,11,11,11,11,11,11,11
+};
+
+const uint8_t ff_log2_tab[256]={
+ 0,0,1,1,2,2,2,2,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,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,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,
+ 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,
+ 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,
+ 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,
+ 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
+};
+
+int64_t ff_gcd(int64_t a, int64_t b){
+ if(b) return ff_gcd(b, a%b);
+ else return a;
+}
+
+int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd){
+ int64_t r=0;
+ assert(c > 0);
+ assert(b >=0);
+ assert(rnd >=0 && rnd<=5 && rnd!=4);
+
+ if(a<0 && a != INT64_MIN) return -av_rescale_rnd(-a, b, c, rnd ^ ((rnd>>1)&1));
+
+ if(rnd==AV_ROUND_NEAR_INF) r= c/2;
+ else if(rnd&1) r= c-1;
+
+ if(b<=INT_MAX && c<=INT_MAX){
+ if(a<=INT_MAX)
+ return (a * b + r)/c;
+ else
+ return a/c*b + (a%c*b + r)/c;
+ }else{
+#if 1
+ uint64_t a0= a&0xFFFFFFFF;
+ uint64_t a1= a>>32;
+ uint64_t b0= b&0xFFFFFFFF;
+ uint64_t b1= b>>32;
+ uint64_t t1= a0*b1 + a1*b0;
+ uint64_t t1a= t1<<32;
+ int i;
+
+ a0 = a0*b0 + t1a;
+ a1 = a1*b1 + (t1>>32) + (a0<t1a);
+ a0 += r;
+ a1 += a0<r;
+
+ for(i=63; i>=0; i--){
+// int o= a1 & 0x8000000000000000ULL;
+ a1+= a1 + ((a0>>i)&1);
+ t1+=t1;
+ if(/*o || */c <= a1){
+ a1 -= c;
+ t1++;
+ }
+ }
+ return t1;
+ }
+#else
+ AVInteger ai;
+ ai= av_mul_i(av_int2i(a), av_int2i(b));
+ ai= av_add_i(ai, av_int2i(r));
+
+ return av_i2int(av_div_i(ai, av_int2i(c)));
+ }
+#endif
+}
+
+int64_t av_rescale(int64_t a, int64_t b, int64_t c){
+ return av_rescale_rnd(a, b, c, AV_ROUND_NEAR_INF);
+}
+
+int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq){
+ int64_t b= bq.num * (int64_t)cq.den;
+ int64_t c= cq.num * (int64_t)bq.den;
+ return av_rescale_rnd(a, b, c, AV_ROUND_NEAR_INF);
+}
+#if 0
+#include "integer.h"
+#undef printf
+main(){
+ int64_t a,b,c,d,e;
+
+ for(a=7; a<(1LL<<62); a+=a/3+1){
+ for(b=3; b<(1LL<<62); b+=b/4+1){
+ for(c=9; c<(1LL<<62); c+=(c*2)/5+3){
+ int64_t r= c/2;
+ AVInteger ai;
+ ai= av_mul_i(av_int2i(a), av_int2i(b));
+ ai= av_add_i(ai, av_int2i(r));
+
+ d= av_i2int(av_div_i(ai, av_int2i(c)));
+
+ e= av_rescale(a,b,c);
+
+ if((double)a * (double)b / (double)c > (1LL<<63))
+ continue;
+
+ if(d!=e) printf("%"PRId64"*%"PRId64"/%"PRId64"= %"PRId64"=%"PRId64"\n", a, b, c, d, e);
+ }
+ }
+ }
+}
+#endif
diff --git a/contrib/ffmpeg/libavutil/mathematics.h b/contrib/ffmpeg/libavutil/mathematics.h
new file mode 100644
index 000000000..0b74b254b
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/mathematics.h
@@ -0,0 +1,51 @@
+/*
+ * copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 MATHEMATICS_H
+#define MATHEMATICS_H
+
+#include "rational.h"
+
+enum AVRounding {
+ AV_ROUND_ZERO = 0, ///< round toward zero
+ AV_ROUND_INF = 1, ///< round away from zero
+ AV_ROUND_DOWN = 2, ///< round toward -infinity
+ AV_ROUND_UP = 3, ///< round toward +infinity
+ AV_ROUND_NEAR_INF = 5, ///< round to nearest and halfway cases away from zero
+};
+
+/**
+ * rescale a 64bit integer with rounding to nearest.
+ * a simple a*b/c isn't possible as it can overflow
+ */
+int64_t av_rescale(int64_t a, int64_t b, int64_t c);
+
+/**
+ * rescale a 64bit integer with specified rounding.
+ * a simple a*b/c isn't possible as it can overflow
+ */
+int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding);
+
+/**
+ * rescale a 64bit integer by 2 rational numbers.
+ */
+int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq);
+
+#endif /* MATHEMATICS_H */
diff --git a/contrib/ffmpeg/libavutil/md5.c b/contrib/ffmpeg/libavutil/md5.c
new file mode 100644
index 000000000..d33ad1483
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/md5.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2006 Michael Niedermayer (michaelni@gmx.at)
+ * Copyright (C) 2003-2005 by Christopher R. Hertel (crh@ubiqx.mn.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
+ *
+ * References:
+ * IETF RFC 1321: The MD5 Message-Digest Algorithm
+ * Ron Rivest. IETF, April, 1992
+ *
+ * based on http://ubiqx.org/libcifs/source/Auth/MD5.c
+ * from Christopher R. Hertel (crh@ubiqx.mn.org)
+ * simplified, cleaned and IMO redundant comments removed by michael
+ *
+ * if you use gcc, then version 4.1 or later and -fomit-frame-pointer is
+ * strongly recommended
+ */
+
+#include "common.h"
+#include <string.h>
+#include "md5.h"
+
+typedef struct AVMD5{
+ uint8_t block[64];
+ uint32_t ABCD[4];
+ uint64_t len;
+ int b_used;
+} AVMD5;
+
+const int av_md5_size= sizeof(AVMD5);
+
+static const uint8_t S[4][4] = {
+ { 7, 12, 17, 22 }, /* Round 1 */
+ { 5, 9, 14, 20 }, /* Round 2 */
+ { 4, 11, 16, 23 }, /* Round 3 */
+ { 6, 10, 15, 21 } /* Round 4 */
+};
+
+static const uint32_t T[64] = {
+ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, /* Round 1 */
+ 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+ 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+ 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+
+ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, /* Round 2 */
+ 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+ 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+ 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+
+ 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, /* Round 3 */
+ 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+ 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
+ 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+
+ 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, /* Round 4 */
+ 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+ 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
+};
+
+#define CORE(i, a, b, c, d) \
+ t = S[i>>4][i&3];\
+ a += T[i];\
+\
+ switch(i>>4){\
+ case 0: a += (d ^ (b&(c^d))) + X[ i &15 ]; break;\
+ case 1: a += (c ^ (d&(c^b))) + X[ (1+5*i)&15 ]; break;\
+ case 2: a += (b^c^d) + X[ (5+3*i)&15 ]; break;\
+ case 3: a += (c^(b|~d)) + X[ ( 7*i)&15 ]; break;\
+ }\
+ a = b + (( a << t ) | ( a >> (32 - t) ));
+
+static void body(uint32_t ABCD[4], uint32_t X[16]){
+
+ int t;
+ int i attribute_unused;
+ unsigned int a= ABCD[3];
+ unsigned int b= ABCD[2];
+ unsigned int c= ABCD[1];
+ unsigned int d= ABCD[0];
+
+#ifdef WORDS_BIGENDIAN
+ for(i=0; i<16; i++)
+ X[i]= bswap_32(X[i]);
+#endif
+
+#ifdef CONFIG_SMALL
+ for( i = 0; i < 64; i++ ){
+ CORE(i,a,b,c,d)
+ t=d; d=c; c=b; b=a; a=t;
+ }
+#else
+#define CORE2(i) CORE(i,a,b,c,d) CORE((i+1),d,a,b,c) CORE((i+2),c,d,a,b) CORE((i+3),b,c,d,a)
+#define CORE4(i) CORE2(i) CORE2((i+4)) CORE2((i+8)) CORE2((i+12))
+CORE4(0) CORE4(16) CORE4(32) CORE4(48)
+#endif
+
+ ABCD[0] += d;
+ ABCD[1] += c;
+ ABCD[2] += b;
+ ABCD[3] += a;
+}
+
+void av_md5_init(AVMD5 *ctx){
+ ctx->len = 0;
+ ctx->b_used = 0;
+
+ ctx->ABCD[0] = 0x10325476;
+ ctx->ABCD[1] = 0x98badcfe;
+ ctx->ABCD[2] = 0xefcdab89;
+ ctx->ABCD[3] = 0x67452301;
+}
+
+void av_md5_update(AVMD5 *ctx, const uint8_t *src, const int len){
+ int i;
+
+ ctx->len += len;
+
+ for( i = 0; i < len; i++ ){
+ ctx->block[ ctx->b_used++ ] = src[i];
+ if( 64 == ctx->b_used ){
+ body(ctx->ABCD, (uint32_t*) ctx->block);
+ ctx->b_used = 0;
+ }
+ }
+}
+
+void av_md5_final(AVMD5 *ctx, uint8_t *dst){
+ int i;
+
+ ctx->block[ctx->b_used++] = 0x80;
+
+ memset(&ctx->block[ctx->b_used], 0, 64 - ctx->b_used);
+
+ if( 56 < ctx->b_used ){
+ body( ctx->ABCD, (uint32_t*) ctx->block );
+ memset(ctx->block, 0, 64);
+ }
+
+ for(i=0; i<8; i++)
+ ctx->block[56+i] = (ctx->len << 3) >> (i<<3);
+
+ body(ctx->ABCD, (uint32_t*) ctx->block);
+
+ for(i=0; i<4; i++)
+ ((uint32_t*)dst)[i]= le2me_32(ctx->ABCD[3-i]);
+}
+
+void av_md5_sum(uint8_t *dst, const uint8_t *src, const int len){
+ AVMD5 ctx[1];
+
+ av_md5_init(ctx);
+ av_md5_update(ctx, src, len);
+ av_md5_final(ctx, dst);
+}
+
+#ifdef TEST
+#include <stdio.h>
+main(){
+ uint64_t md5val;
+ int i;
+ uint8_t in[1000];
+
+ for(i=0; i<1000; i++) in[i]= i*i;
+ av_md5_sum( (uint8_t*)&md5val, in, 1000); printf("%"PRId64"\n", md5val);
+ av_md5_sum( (uint8_t*)&md5val, in, 63); printf("%"PRId64"\n", md5val);
+ av_md5_sum( (uint8_t*)&md5val, in, 64); printf("%"PRId64"\n", md5val);
+ av_md5_sum( (uint8_t*)&md5val, in, 65); printf("%"PRId64"\n", md5val);
+ for(i=0; i<1000; i++) in[i]= i % 127;
+ av_md5_sum( (uint8_t*)&md5val, in, 999); printf("%"PRId64"\n", md5val);
+}
+#endif
diff --git a/contrib/ffmpeg/libavutil/md5.h b/contrib/ffmpeg/libavutil/md5.h
new file mode 100644
index 000000000..8d1b4b5fe
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/md5.h
@@ -0,0 +1,34 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 MD5_H
+#define MD5_H
+
+extern const int av_md5_size;
+
+struct AVMD5;
+
+void av_md5_init(struct AVMD5 *ctx);
+void av_md5_update(struct AVMD5 *ctx, const uint8_t *src, const int len);
+void av_md5_final(struct AVMD5 *ctx, uint8_t *dst);
+void av_md5_sum(uint8_t *dst, const uint8_t *src, const int len);
+
+#endif /* MD5_H */
+
diff --git a/contrib/ffmpeg/libavutil/mem.c b/contrib/ffmpeg/libavutil/mem.c
new file mode 100644
index 000000000..f43fb5420
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/mem.c
@@ -0,0 +1,171 @@
+/*
+ * default memory allocator for libavutil
+ * 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 mem.c
+ * default memory allocator for libavutil.
+ */
+
+#include "common.h"
+
+/* here we can use OS dependant allocation functions */
+#undef malloc
+#undef free
+#undef realloc
+
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+/* you can redefine av_malloc and av_free in your project to use your
+ memory allocator. You do not need to suppress this file because the
+ linker will do it automatically */
+
+/**
+ * Memory allocation of size byte with alignment suitable for all
+ * memory accesses (including vectors if available on the
+ * CPU). av_malloc(0) must return a non NULL pointer.
+ */
+void *av_malloc(unsigned int size)
+{
+ void *ptr;
+#ifdef CONFIG_MEMALIGN_HACK
+ long diff;
+#endif
+
+ /* let's disallow possible ambiguous cases */
+ if(size > (INT_MAX-16) )
+ return NULL;
+
+#ifdef CONFIG_MEMALIGN_HACK
+ ptr = malloc(size+16);
+ if(!ptr)
+ return ptr;
+ diff= ((-(long)ptr - 1)&15) + 1;
+ ptr += diff;
+ ((char*)ptr)[-1]= diff;
+#elif defined (HAVE_MEMALIGN)
+ ptr = memalign(16,size);
+ /* Why 64?
+ Indeed, we should align it:
+ on 4 for 386
+ on 16 for 486
+ on 32 for 586, PPro - k6-III
+ on 64 for K7 (maybe for P3 too).
+ Because L1 and L2 caches are aligned on those values.
+ But I don't want to code such logic here!
+ */
+ /* Why 16?
+ because some cpus need alignment, for example SSE2 on P4, & most RISC cpus
+ it will just trigger an exception and the unaligned load will be done in the
+ exception handler or it will just segfault (SSE2 on P4)
+ Why not larger? because i didnt see a difference in benchmarks ...
+ */
+ /* benchmarks with p3
+ memalign(64)+1 3071,3051,3032
+ memalign(64)+2 3051,3032,3041
+ memalign(64)+4 2911,2896,2915
+ memalign(64)+8 2545,2554,2550
+ memalign(64)+16 2543,2572,2563
+ memalign(64)+32 2546,2545,2571
+ memalign(64)+64 2570,2533,2558
+
+ btw, malloc seems to do 8 byte alignment by default here
+ */
+#else
+ ptr = malloc(size);
+#endif
+ return ptr;
+}
+
+/**
+ * av_realloc semantics (same as glibc): if ptr is NULL and size > 0,
+ * identical to malloc(size). If size is zero, it is identical to
+ * free(ptr) and NULL is returned.
+ */
+void *av_realloc(void *ptr, unsigned int size)
+{
+#ifdef CONFIG_MEMALIGN_HACK
+ int diff;
+#endif
+
+ /* let's disallow possible ambiguous cases */
+ if(size > (INT_MAX-16) )
+ return NULL;
+
+#ifdef CONFIG_MEMALIGN_HACK
+ //FIXME this isn't aligned correctly, though it probably isn't needed
+ if(!ptr) return av_malloc(size);
+ diff= ((char*)ptr)[-1];
+ return realloc(ptr - diff, size + diff) + diff;
+#else
+ return realloc(ptr, size);
+#endif
+}
+
+/**
+ * Free memory which has been allocated with av_malloc(z)() or av_realloc().
+ * NOTE: ptr = NULL is explicetly allowed
+ * Note2: it is recommended that you use av_freep() instead
+ */
+void av_free(void *ptr)
+{
+ /* XXX: this test should not be needed on most libcs */
+ if (ptr)
+#ifdef CONFIG_MEMALIGN_HACK
+ free(ptr - ((char*)ptr)[-1]);
+#else
+ free(ptr);
+#endif
+}
+
+/**
+ * Frees memory and sets the pointer to NULL.
+ * @param arg pointer to the pointer which should be freed
+ */
+void av_freep(void *arg)
+{
+ void **ptr= (void**)arg;
+ av_free(*ptr);
+ *ptr = NULL;
+}
+
+void *av_mallocz(unsigned int size)
+{
+ void *ptr;
+
+ ptr = av_malloc(size);
+ if (ptr)
+ memset(ptr, 0, size);
+ return ptr;
+}
+
+char *av_strdup(const char *s)
+{
+ char *ptr;
+ int len;
+ len = strlen(s) + 1;
+ ptr = av_malloc(len);
+ if (ptr)
+ memcpy(ptr, s, len);
+ return ptr;
+}
+
diff --git a/contrib/ffmpeg/libavutil/rational.c b/contrib/ffmpeg/libavutil/rational.c
new file mode 100644
index 000000000..0e018c41b
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/rational.c
@@ -0,0 +1,118 @@
+/*
+ * Rational numbers
+ * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/**
+ * @file rational.c
+ * Rational numbers
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+//#include <math.h>
+#include <limits.h>
+
+#include "common.h"
+#include "mathematics.h"
+#include "rational.h"
+
+int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max){
+ AVRational a0={0,1}, a1={1,0};
+ int sign= (nom<0) ^ (den<0);
+ int64_t gcd= ff_gcd(FFABS(nom), FFABS(den));
+
+ nom = FFABS(nom)/gcd;
+ den = FFABS(den)/gcd;
+ if(nom<=max && den<=max){
+ a1= (AVRational){nom, den};
+ den=0;
+ }
+
+ while(den){
+ uint64_t x = nom / den;
+ int64_t next_den= nom - den*x;
+ int64_t a2n= x*a1.num + a0.num;
+ int64_t a2d= x*a1.den + a0.den;
+
+ if(a2n > max || a2d > max){
+ if(a1.num) x= (max - a0.num) / a1.num;
+ if(a1.den) x= FFMIN(x, (max - a0.den) / a1.den);
+
+ if (den*(2*x*a1.den + a0.den) > nom*a1.den)
+ a1 = (AVRational){x*a1.num + a0.num, x*a1.den + a0.den};
+ break;
+ }
+
+ a0= a1;
+ a1= (AVRational){a2n, a2d};
+ nom= den;
+ den= next_den;
+ }
+ assert(ff_gcd(a1.num, a1.den) == 1);
+
+ *dst_nom = sign ? -a1.num : a1.num;
+ *dst_den = a1.den;
+
+ return den==0;
+}
+
+/**
+ * returns b*c.
+ */
+AVRational av_mul_q(AVRational b, AVRational c){
+ av_reduce(&b.num, &b.den, b.num * (int64_t)c.num, b.den * (int64_t)c.den, INT_MAX);
+ return b;
+}
+
+/**
+ * returns b/c.
+ */
+AVRational av_div_q(AVRational b, AVRational c){
+ return av_mul_q(b, (AVRational){c.den, c.num});
+}
+
+/**
+ * returns b+c.
+ */
+AVRational av_add_q(AVRational b, AVRational c){
+ av_reduce(&b.num, &b.den, b.num * (int64_t)c.den + c.num * (int64_t)b.den, b.den * (int64_t)c.den, INT_MAX);
+ return b;
+}
+
+/**
+ * returns b-c.
+ */
+AVRational av_sub_q(AVRational b, AVRational c){
+ return av_add_q(b, (AVRational){-c.num, c.den});
+}
+
+/**
+ * Converts a double precission floating point number to a AVRational.
+ * @param max the maximum allowed numerator and denominator
+ */
+AVRational av_d2q(double d, int max){
+ AVRational a;
+#define LOG2 0.69314718055994530941723212145817656807550013436025
+ int exponent= FFMAX( (int)(log(fabs(d) + 1e-20)/LOG2), 0);
+ int64_t den= 1LL << (61 - exponent);
+ av_reduce(&a.num, &a.den, (int64_t)(d * den + 0.5), den, max);
+
+ return a;
+}
diff --git a/contrib/ffmpeg/libavutil/rational.h b/contrib/ffmpeg/libavutil/rational.h
new file mode 100644
index 000000000..43fc22114
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/rational.h
@@ -0,0 +1,71 @@
+/*
+ * Rational numbers
+ * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/**
+ * @file rational.h
+ * Rational numbers.
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#ifndef RATIONAL_H
+#define RATIONAL_H
+
+/**
+ * Rational number num/den.
+ */
+typedef struct AVRational{
+ int num; ///< numerator
+ int den; ///< denominator
+} AVRational;
+
+/**
+ * returns 0 if a==b, 1 if a>b and -1 if a<b.
+ */
+static inline int av_cmp_q(AVRational a, AVRational b){
+ const int64_t tmp= a.num * (int64_t)b.den - b.num * (int64_t)a.den;
+
+ if(tmp) return (tmp>>63)|1;
+ else return 0;
+}
+
+/**
+ * converts the given AVRational to a double.
+ */
+static inline double av_q2d(AVRational a){
+ return a.num / (double) a.den;
+}
+
+/**
+ * reduce a fraction.
+ * this is usefull for framerate calculations
+ * @param max the maximum allowed for dst_nom & dst_den
+ * @return 1 if exact, 0 otherwise
+ */
+int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max);
+
+AVRational av_mul_q(AVRational b, AVRational c);
+AVRational av_div_q(AVRational b, AVRational c);
+AVRational av_add_q(AVRational b, AVRational c);
+AVRational av_sub_q(AVRational b, AVRational c);
+AVRational av_d2q(double d, int max);
+
+#endif // RATIONAL_H
diff --git a/contrib/ffmpeg/libavutil/softfloat.c b/contrib/ffmpeg/libavutil/softfloat.c
new file mode 100644
index 000000000..f12fd17a0
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/softfloat.c
@@ -0,0 +1,72 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <assert.h>
+#include "softfloat.h"
+#include "common.h"
+#include "log.h"
+
+#undef printf
+
+int main(){
+ SoftFloat one= av_int2sf(1, 0);
+ SoftFloat sf1, sf2;
+ double d1, d2;
+ int i, j;
+av_log_level = AV_LOG_DEBUG;
+
+ d1= 1;
+ for(i= 0; i<10; i++){
+ d1= 1/(d1+1);
+ }
+ printf("test1 double=%d\n", (int)(d1 * (1<<24)));
+
+ sf1= one;
+ for(i= 0; i<10; i++){
+ sf1= av_div_sf(one, av_normalize_sf(av_add_sf(one, sf1)));
+ }
+ printf("test1 sf =%d\n", av_sf2int(sf1, 24));
+
+
+ for(i= 0; i<100; i++){
+ START_TIMER
+ d1= i;
+ d2= i/100.0;
+ for(j= 0; j<1000; j++){
+ d1= (d1+1)*d2;
+ }
+ STOP_TIMER("float add mul")
+ }
+ printf("test2 double=%d\n", (int)(d1 * (1<<24)));
+
+ for(i= 0; i<100; i++){
+ START_TIMER
+ sf1= av_int2sf(i, 0);
+ sf2= av_div_sf(av_int2sf(i, 2), av_int2sf(200, 3));
+ for(j= 0; j<1000; j++){
+ sf1= av_mul_sf(av_add_sf(sf1, one),sf2);
+ }
+ STOP_TIMER("softfloat add mul")
+ }
+ printf("test2 sf =%d (%d %d)\n", av_sf2int(sf1, 24), sf1.exp, sf1.mant);
+ return 0;
+}
diff --git a/contrib/ffmpeg/libavutil/softfloat.h b/contrib/ffmpeg/libavutil/softfloat.h
new file mode 100644
index 000000000..5bb2c1cbc
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/softfloat.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 MIN_EXP -126
+#define MAX_EXP 126
+#define ONE_BITS 29
+
+typedef struct SoftFloat{
+ int32_t exp;
+ int32_t mant;
+}SoftFloat;
+
+static SoftFloat av_normalize_sf(SoftFloat a){
+ if(a.mant){
+#if 1
+ while((a.mant + 0x20000000U)<0x40000000U){
+ a.mant += a.mant;
+ a.exp -= 1;
+ }
+#else
+ int s=ONE_BITS + 1 - av_log2(a.mant ^ (a.mant<<1));
+ a.exp -= s;
+ a.mant <<= s;
+#endif
+ if(a.exp < MIN_EXP){
+ a.exp = MIN_EXP;
+ a.mant= 0;
+ }
+ }else{
+ a.exp= MIN_EXP;
+ }
+ return a;
+}
+
+static inline SoftFloat av_normalize1_sf(SoftFloat a){
+#if 1
+ if(a.mant + 0x40000000 < 0){
+ a.exp++;
+ a.mant>>=1;
+ }
+ return a;
+#elif 1
+ int t= a.mant + 0x40000000 < 0;
+ return (SoftFloat){a.exp+t, a.mant>>t};
+#else
+ int t= (a.mant + 0x40000000U)>>31;
+ return (SoftFloat){a.exp+t, a.mant>>t};
+#endif
+}
+
+/**
+ *
+ * @return will not be more denormalized then a+b, so if either input is
+ * normalized then the output wont be worse then the other input
+ * if both are normalized then the output will be normalized
+ */
+static inline SoftFloat av_mul_sf(SoftFloat a, SoftFloat b){
+ a.exp += b.exp;
+ a.mant = (a.mant * (int64_t)b.mant) >> ONE_BITS;
+ return av_normalize1_sf(a);
+}
+
+/**
+ *
+ * b has to be normalized and not zero
+ * @return will not be more denormalized then a
+ */
+static SoftFloat av_div_sf(SoftFloat a, SoftFloat b){
+ a.exp -= b.exp+1;
+ a.mant = ((int64_t)a.mant<<(ONE_BITS+1)) / b.mant;
+ return av_normalize1_sf(a);
+}
+
+static inline int av_cmp_sf(SoftFloat a, SoftFloat b){
+ int t= a.exp - b.exp;
+ if(t<0) return (a.mant >> (-t)) - b.mant ;
+ else return a.mant - (b.mant >> t);
+}
+
+static inline SoftFloat av_add_sf(SoftFloat a, SoftFloat b){
+ int t= a.exp - b.exp;
+ if(t<0) return av_normalize1_sf((SoftFloat){b.exp, b.mant + (a.mant >> (-t))});
+ else return av_normalize1_sf((SoftFloat){a.exp, a.mant + (b.mant >> t )});
+}
+
+static inline SoftFloat av_sub_sf(SoftFloat a, SoftFloat b){
+ return av_add_sf(a, (SoftFloat){b.exp, -b.mant});
+}
+
+//FIXME sqrt, log, exp, pow, sin, cos
+
+static inline SoftFloat av_int2sf(int v, int frac_bits){
+ return av_normalize_sf((SoftFloat){ONE_BITS-frac_bits, v});
+}
+
+/**
+ *
+ * rounding is to -inf
+ */
+static inline int av_sf2int(SoftFloat v, int frac_bits){
+ v.exp += frac_bits - ONE_BITS;
+ if(v.exp >= 0) return v.mant << v.exp ;
+ else return v.mant >>(-v.exp);
+}
diff --git a/contrib/ffmpeg/libavutil/tree.c b/contrib/ffmpeg/libavutil/tree.c
new file mode 100644
index 000000000..c929e4819
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/tree.c
@@ -0,0 +1,151 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "common.h"
+#include "log.h"
+#include "tree.h"
+
+typedef struct AVTreeNode{
+ struct AVTreeNode *child[2];
+ void *elem;
+ int state;
+}AVTreeNode;
+
+void *av_tree_find(const AVTreeNode *t, void *key, int (*cmp)(void *key, const void *b), void *next[2]){
+ if(t){
+ unsigned int v= cmp(t->elem, key);
+ if(v){
+ if(next) next[(v>>31)^1]= t->elem;
+ return av_tree_find(t->child[v>>31], key, cmp, next);
+ }else{
+ return t->elem;
+ }
+ }
+ return NULL;
+}
+
+void *av_tree_insert(AVTreeNode **tp, void *key, int (*cmp)(void *key, const void *b)){
+ AVTreeNode *t= *tp;
+ if(t){
+ unsigned int v= cmp(t->elem, key);
+ if(v){
+ int i= v>>31;
+ AVTreeNode **child= &t->child[i];
+ void *ret= av_tree_insert(child, key, cmp);
+ if(!ret){
+ t->state -= ((int)v>>31)|1;
+ if(!(t->state&1)){
+ if(t->state){
+ if((*child)->state*2 == t->state){
+ *tp= *child;
+ *child= (*child)->child[i^1];
+ (*tp)->child[i^1]= t;
+ t->state= 0;
+ }else{
+ *tp= (*child)->child[i^1];
+ (*child)->child[i^1]= (*tp)->child[i];
+ (*tp)->child[i]= *child;
+ *child= (*tp)->child[i^1];
+ (*tp)->child[i^1]= t;
+
+ i= (*tp)->state > 0;
+ (*tp)->child[i ]->state= 0;
+ (*tp)->child[i^1]->state= -(*tp)->state;
+ }
+ (*tp)->state=0;
+ }
+ return key;
+ }
+ }
+ return ret;
+ }else{
+ return t->elem;
+ }
+ }else{
+ *tp= av_mallocz(sizeof(AVTreeNode));
+ (*tp)->elem= key;
+ return NULL;
+ }
+}
+
+void av_tree_destroy(AVTreeNode *t){
+ av_tree_destroy(t->child[0]);
+ av_tree_destroy(t->child[1]);
+ av_free(t);
+}
+
+#if 0
+void av_tree_enumerate(AVTreeNode *t, void *opaque, int (*f)(void *opaque, void *elem)){
+ int v= f(opaque, t->elem);
+ if(v>=0) av_tree_enumerate(t->child[0], opaque, f);
+ if(v<=0) av_tree_enumerate(t->child[1], opaque, f);
+}
+#endif
+
+#ifdef TEST
+
+static int check(AVTreeNode *t){
+ if(t){
+ int left= check(t->child[0]);
+ int right= check(t->child[1]);
+
+ if(left>999 || right>999)
+ return 1000;
+ if(right - left != t->state)
+ return 1000;
+ if(t->state>1 || t->state<-1)
+ return 1000;
+ return FFMAX(left, right)+1;
+ }
+ return 0;
+}
+
+static void print(AVTreeNode *t, int depth){
+ int i;
+ for(i=0; i<depth*4; i++) av_log(NULL, AV_LOG_ERROR, " ");
+ if(t){
+ av_log(NULL, AV_LOG_ERROR, "Node %p %2d %4d\n", t, t->state, t->elem);
+ print(t->child[0], depth+1);
+ print(t->child[1], depth+1);
+ }else
+ av_log(NULL, AV_LOG_ERROR, "NULL\n");
+}
+
+int cmp(const void *a, const void *b){
+ return a-b;
+}
+
+int main(){
+ int i,j,k;
+ AVTreeNode *root= NULL;
+
+ for(i=0; i<10000; i++){
+ int j= (random()%863294);
+ if(check(root) > 999){
+ av_log(NULL, AV_LOG_ERROR, "FATAL error %d\n", i);
+ print(root, 0);
+ return -1;
+ }
+ av_log(NULL, AV_LOG_ERROR, "inserting %4d\n", j);
+ av_tree_insert(&root, (void*)(j+1), cmp);
+ }
+ return 0;
+}
+#endif
diff --git a/contrib/ffmpeg/libavutil/tree.h b/contrib/ffmpeg/libavutil/tree.h
new file mode 100644
index 000000000..36897ef46
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/tree.h
@@ -0,0 +1,52 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 TREE_H
+#define TREE_H
+
+struct AVTreeNode;
+
+/**
+ * Finds an element.
+ * @param root a pointer to the root node of the tree
+ * @param next if next is not NULL then next[0] will contain the previous element and
+ * next[1] the next element if either doesnt exist then the corresponding
+ * entry in next is unchanged
+ * @return an element with cmp(key, elem)==0 or NULL if no such element exists in
+ * the tree
+ */
+void *av_tree_find(const struct AVTreeNode *root, void *key, int (*cmp)(void *key, const void *b), void *next[2]);
+
+/**
+ * Finds a element for which cmp(key, elem)==0, if no such element is found key
+ * is inserted into the tree.
+ * @param rootp a pointer to a pointer to the root node of the tree note the
+ * root node can change during insertions, this is required to
+ * keep the tree balanced
+ *
+ * @return if no insertion happened, the found element
+ * if a insertion happened, then either key or NULL is returned (which it is
+ * depends on the tree state and the implemenattion, you should make no
+ * asumtations that its one or the other in code)
+ */
+void *av_tree_insert(struct AVTreeNode **rootp, void *key, int (*cmp)(void *key, const void *b));
+void av_tree_destroy(struct AVTreeNode *t);
+
+#endif /* TREE_H */
diff --git a/contrib/ffmpeg/libavutil/x86_cpu.h b/contrib/ffmpeg/libavutil/x86_cpu.h
new file mode 100644
index 000000000..3d54b2a60
--- /dev/null
+++ b/contrib/ffmpeg/libavutil/x86_cpu.h
@@ -0,0 +1,60 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 AVUTIL_X86CPU_H
+#define AVUTIL_X86CPU_H
+
+#ifdef ARCH_X86_64
+# define REG_a "rax"
+# define REG_b "rbx"
+# define REG_c "rcx"
+# define REG_d "rdx"
+# define REG_D "rdi"
+# define REG_S "rsi"
+# define PTR_SIZE "8"
+
+# define REG_SP "rsp"
+# define REG_BP "rbp"
+# define REGBP rbp
+# define REGa rax
+# define REGb rbx
+# define REGc rcx
+# define REGSP rsp
+
+#else
+
+# define REG_a "eax"
+# define REG_b "ebx"
+# define REG_c "ecx"
+# define REG_d "edx"
+# define REG_D "edi"
+# define REG_S "esi"
+# define PTR_SIZE "4"
+
+# define REG_SP "esp"
+# define REG_BP "ebp"
+# define REGBP ebp
+# define REGa eax
+# define REGb ebx
+# define REGc ecx
+# define REGSP esp
+#endif
+
+#endif /* AVUTIL_X86CPU_H */
diff --git a/contrib/ffmpeg/libpostproc/Makefile b/contrib/ffmpeg/libpostproc/Makefile
new file mode 100644
index 000000000..a6765365d
--- /dev/null
+++ b/contrib/ffmpeg/libpostproc/Makefile
@@ -0,0 +1,26 @@
+
+include ../config.mak
+
+# Overload incdir, postproc include files go in a different directory.
+incdir=$(prefix)/include/postproc
+
+EXTRALIBS := -L$(BUILD_ROOT)/libavutil -lavutil$(BUILDSUF) $(EXTRALIBS)
+
+NAME=postproc
+ifeq ($(BUILD_SHARED),yes)
+LIBVERSION=$(SPPVERSION)
+LIBMAJOR=$(SPPMAJOR)
+endif
+
+STATIC_OBJS=postprocess.o
+SHARED_OBJS=postprocess_pic.o
+
+HEADERS = postprocess.h
+
+include ../common.mak
+
+depend dep: postprocess.c
+
+postprocess_pic.o: postprocess.c
+ $(CC) -c $(CFLAGS) -fomit-frame-pointer -fPIC -DPIC -o $@ $<
+
diff --git a/contrib/ffmpeg/libpostproc/mangle.h b/contrib/ffmpeg/libpostproc/mangle.h
new file mode 100644
index 000000000..3521fa9bb
--- /dev/null
+++ b/contrib/ffmpeg/libpostproc/mangle.h
@@ -0,0 +1,47 @@
+/*
+ * mangle.h - This file has some CPP macros to deal with different symbol
+ * mangling across binary formats.
+ *
+ * (c)2002 by Felix Buenemann <atmosfear at 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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that 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
+ */
+
+#ifndef __MANGLE_H
+#define __MANGLE_H
+
+/* Feel free to add more to the list, eg. a.out IMO */
+/* Use rip-relative addressing if compiling PIC code on x86-64. */
+#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__OS2__) || \
+ (defined(__OpenBSD__) && !defined(__ELF__))
+#if defined(ARCH_X86_64) && defined(PIC)
+#define MANGLE(a) "_" #a"(%%rip)"
+#else
+#define MANGLE(a) "_" #a
+#endif
+#else
+#if defined(ARCH_X86_64) && defined(PIC)
+#define MANGLE(a) #a"(%%rip)"
+#elif defined(CONFIG_DARWIN)
+#define MANGLE(a) "_" #a
+#else
+#define MANGLE(a) #a
+#endif
+#endif
+
+#endif /* !__MANGLE_H */
+
diff --git a/contrib/ffmpeg/libpostproc/postprocess.c b/contrib/ffmpeg/libpostproc/postprocess.c
new file mode 100644
index 000000000..c9f2893e3
--- /dev/null
+++ b/contrib/ffmpeg/libpostproc/postprocess.c
@@ -0,0 +1,1144 @@
+/*
+ * Copyright (C) 2001-2003 Michael Niedermayer (michaelni@gmx.at)
+ *
+ * AltiVec optimizations (C) 2004 Romain Dolbeau <romain@dolbeau.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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that 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 postprocess.c
+ * postprocessing.
+ */
+
+/*
+ C MMX MMX2 3DNow AltiVec
+isVertDC Ec Ec Ec
+isVertMinMaxOk Ec Ec Ec
+doVertLowPass E e e Ec
+doVertDefFilter Ec Ec e e Ec
+isHorizDC Ec Ec Ec
+isHorizMinMaxOk a E Ec
+doHorizLowPass E e e Ec
+doHorizDefFilter Ec Ec e e Ec
+do_a_deblock Ec E Ec E
+deRing E e e* Ecp
+Vertical RKAlgo1 E a a
+Horizontal RKAlgo1 a a
+Vertical X1# a E E
+Horizontal X1# a E E
+LinIpolDeinterlace e E E*
+CubicIpolDeinterlace a e e*
+LinBlendDeinterlace e E E*
+MedianDeinterlace# E Ec Ec
+TempDeNoiser# E e e Ec
+
+* i dont have a 3dnow CPU -> its untested, but noone said it doesnt work so it seems to work
+# more or less selfinvented filters so the exactness isnt too meaningfull
+E = Exact implementation
+e = allmost exact implementation (slightly different rounding,...)
+a = alternative / approximate impl
+c = checked against the other implementations (-vo md5)
+p = partially optimized, still some work to do
+*/
+
+/*
+TODO:
+reduce the time wasted on the mem transfer
+unroll stuff if instructions depend too much on the prior one
+move YScale thing to the end instead of fixing QP
+write a faster and higher quality deblocking filter :)
+make the mainloop more flexible (variable number of blocks at once
+ (the if/else stuff per block is slowing things down)
+compare the quality & speed of all filters
+split this huge file
+optimize c versions
+try to unroll inner for(x=0 ... loop to avoid these damn if(x ... checks
+...
+*/
+
+//Changelog: use the Subversion log
+
+#include "config.h"
+#include "avutil.h"
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+//#undef HAVE_MMX2
+//#define HAVE_3DNOW
+//#undef HAVE_MMX
+//#undef ARCH_X86
+//#define DEBUG_BRIGHTNESS
+#ifdef USE_FASTMEMCPY
+#include "libvo/fastmemcpy.h"
+#endif
+#include "postprocess.h"
+#include "postprocess_internal.h"
+
+#include "mangle.h" //FIXME should be supressed
+
+#ifdef HAVE_ALTIVEC_H
+#include <altivec.h>
+#endif
+
+#define GET_MODE_BUFFER_SIZE 500
+#define OPTIONS_ARRAY_SIZE 10
+#define BLOCK_SIZE 8
+#define TEMP_STRIDE 8
+//#define NUM_BLOCKS_AT_ONCE 16 //not used yet
+
+#if defined(ARCH_X86)
+static uint64_t __attribute__((aligned(8))) attribute_used w05= 0x0005000500050005LL;
+static uint64_t __attribute__((aligned(8))) attribute_used w04= 0x0004000400040004LL;
+static uint64_t __attribute__((aligned(8))) attribute_used w20= 0x0020002000200020LL;
+static uint64_t __attribute__((aligned(8))) attribute_used b00= 0x0000000000000000LL;
+static uint64_t __attribute__((aligned(8))) attribute_used b01= 0x0101010101010101LL;
+static uint64_t __attribute__((aligned(8))) attribute_used b02= 0x0202020202020202LL;
+static uint64_t __attribute__((aligned(8))) attribute_used b08= 0x0808080808080808LL;
+static uint64_t __attribute__((aligned(8))) attribute_used b80= 0x8080808080808080LL;
+#endif
+
+static uint8_t clip_table[3*256];
+static uint8_t * const clip_tab= clip_table + 256;
+
+static const int attribute_used deringThreshold= 20;
+
+
+static struct PPFilter filters[]=
+{
+ {"hb", "hdeblock", 1, 1, 3, H_DEBLOCK},
+ {"vb", "vdeblock", 1, 2, 4, V_DEBLOCK},
+/* {"hr", "rkhdeblock", 1, 1, 3, H_RK1_FILTER},
+ {"vr", "rkvdeblock", 1, 2, 4, V_RK1_FILTER},*/
+ {"h1", "x1hdeblock", 1, 1, 3, H_X1_FILTER},
+ {"v1", "x1vdeblock", 1, 2, 4, V_X1_FILTER},
+ {"ha", "ahdeblock", 1, 1, 3, H_A_DEBLOCK},
+ {"va", "avdeblock", 1, 2, 4, V_A_DEBLOCK},
+ {"dr", "dering", 1, 5, 6, DERING},
+ {"al", "autolevels", 0, 1, 2, LEVEL_FIX},
+ {"lb", "linblenddeint", 1, 1, 4, LINEAR_BLEND_DEINT_FILTER},
+ {"li", "linipoldeint", 1, 1, 4, LINEAR_IPOL_DEINT_FILTER},
+ {"ci", "cubicipoldeint", 1, 1, 4, CUBIC_IPOL_DEINT_FILTER},
+ {"md", "mediandeint", 1, 1, 4, MEDIAN_DEINT_FILTER},
+ {"fd", "ffmpegdeint", 1, 1, 4, FFMPEG_DEINT_FILTER},
+ {"l5", "lowpass5", 1, 1, 4, LOWPASS5_DEINT_FILTER},
+ {"tn", "tmpnoise", 1, 7, 8, TEMP_NOISE_FILTER},
+ {"fq", "forcequant", 1, 0, 0, FORCE_QUANT},
+ {NULL, NULL,0,0,0,0} //End Marker
+};
+
+static const char *replaceTable[]=
+{
+ "default", "hdeblock:a,vdeblock:a,dering:a",
+ "de", "hdeblock:a,vdeblock:a,dering:a",
+ "fast", "x1hdeblock:a,x1vdeblock:a,dering:a",
+ "fa", "x1hdeblock:a,x1vdeblock:a,dering:a",
+ "ac", "ha:a:128:7,va:a,dering:a",
+ NULL //End Marker
+};
+
+
+#if defined(ARCH_X86)
+static inline void prefetchnta(void *p)
+{
+ asm volatile( "prefetchnta (%0)\n\t"
+ : : "r" (p)
+ );
+}
+
+static inline void prefetcht0(void *p)
+{
+ asm volatile( "prefetcht0 (%0)\n\t"
+ : : "r" (p)
+ );
+}
+
+static inline void prefetcht1(void *p)
+{
+ asm volatile( "prefetcht1 (%0)\n\t"
+ : : "r" (p)
+ );
+}
+
+static inline void prefetcht2(void *p)
+{
+ asm volatile( "prefetcht2 (%0)\n\t"
+ : : "r" (p)
+ );
+}
+#endif
+
+// The horizontal Functions exist only in C cuz the MMX code is faster with vertical filters and transposing
+
+/**
+ * Check if the given 8x8 Block is mostly "flat"
+ */
+static inline int isHorizDC_C(uint8_t src[], int stride, PPContext *c)
+{
+ int numEq= 0;
+ int y;
+ const int dcOffset= ((c->nonBQP*c->ppMode.baseDcDiff)>>8) + 1;
+ const int dcThreshold= dcOffset*2 + 1;
+
+ for(y=0; y<BLOCK_SIZE; y++)
+ {
+ if(((unsigned)(src[0] - src[1] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[1] - src[2] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[2] - src[3] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[3] - src[4] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[4] - src[5] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[5] - src[6] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[6] - src[7] + dcOffset)) < dcThreshold) numEq++;
+ src+= stride;
+ }
+ return numEq > c->ppMode.flatnessThreshold;
+}
+
+/**
+ * Check if the middle 8x8 Block in the given 8x16 block is flat
+ */
+static inline int isVertDC_C(uint8_t src[], int stride, PPContext *c){
+ int numEq= 0;
+ int y;
+ const int dcOffset= ((c->nonBQP*c->ppMode.baseDcDiff)>>8) + 1;
+ const int dcThreshold= dcOffset*2 + 1;
+
+ src+= stride*4; // src points to begin of the 8x8 Block
+ for(y=0; y<BLOCK_SIZE-1; y++)
+ {
+ if(((unsigned)(src[0] - src[0+stride] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[1] - src[1+stride] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[2] - src[2+stride] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[3] - src[3+stride] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[4] - src[4+stride] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[5] - src[5+stride] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[6] - src[6+stride] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[7] - src[7+stride] + dcOffset)) < dcThreshold) numEq++;
+ src+= stride;
+ }
+ return numEq > c->ppMode.flatnessThreshold;
+}
+
+static inline int isHorizMinMaxOk_C(uint8_t src[], int stride, int QP)
+{
+ int i;
+#if 1
+ for(i=0; i<2; i++){
+ if((unsigned)(src[0] - src[5] + 2*QP) > 4*QP) return 0;
+ src += stride;
+ if((unsigned)(src[2] - src[7] + 2*QP) > 4*QP) return 0;
+ src += stride;
+ if((unsigned)(src[4] - src[1] + 2*QP) > 4*QP) return 0;
+ src += stride;
+ if((unsigned)(src[6] - src[3] + 2*QP) > 4*QP) return 0;
+ src += stride;
+ }
+#else
+ for(i=0; i<8; i++){
+ if((unsigned)(src[0] - src[7] + 2*QP) > 4*QP) return 0;
+ src += stride;
+ }
+#endif
+ return 1;
+}
+
+static inline int isVertMinMaxOk_C(uint8_t src[], int stride, int QP)
+{
+#if 1
+#if 1
+ int x;
+ src+= stride*4;
+ for(x=0; x<BLOCK_SIZE; x+=4)
+ {
+ if((unsigned)(src[ x + 0*stride] - src[ x + 5*stride] + 2*QP) > 4*QP) return 0;
+ if((unsigned)(src[1+x + 2*stride] - src[1+x + 7*stride] + 2*QP) > 4*QP) return 0;
+ if((unsigned)(src[2+x + 4*stride] - src[2+x + 1*stride] + 2*QP) > 4*QP) return 0;
+ if((unsigned)(src[3+x + 6*stride] - src[3+x + 3*stride] + 2*QP) > 4*QP) return 0;
+ }
+#else
+ int x;
+ src+= stride*3;
+ for(x=0; x<BLOCK_SIZE; x++)
+ {
+ if((unsigned)(src[x + stride] - src[x + (stride<<3)] + 2*QP) > 4*QP) return 0;
+ }
+#endif
+ return 1;
+#else
+ int x;
+ src+= stride*4;
+ for(x=0; x<BLOCK_SIZE; x++)
+ {
+ int min=255;
+ int max=0;
+ int y;
+ for(y=0; y<8; y++){
+ int v= src[x + y*stride];
+ if(v>max) max=v;
+ if(v<min) min=v;
+ }
+ if(max-min > 2*QP) return 0;
+ }
+ return 1;
+#endif
+}
+
+static inline int horizClassify_C(uint8_t src[], int stride, PPContext *c){
+ if( isHorizDC_C(src, stride, c) ){
+ if( isHorizMinMaxOk_C(src, stride, c->QP) )
+ return 1;
+ else
+ return 0;
+ }else{
+ return 2;
+ }
+}
+
+static inline int vertClassify_C(uint8_t src[], int stride, PPContext *c){
+ if( isVertDC_C(src, stride, c) ){
+ if( isVertMinMaxOk_C(src, stride, c->QP) )
+ return 1;
+ else
+ return 0;
+ }else{
+ return 2;
+ }
+}
+
+static inline void doHorizDefFilter_C(uint8_t dst[], int stride, PPContext *c)
+{
+ int y;
+ for(y=0; y<BLOCK_SIZE; y++)
+ {
+ const int middleEnergy= 5*(dst[4] - dst[3]) + 2*(dst[2] - dst[5]);
+
+ if(FFABS(middleEnergy) < 8*c->QP)
+ {
+ const int q=(dst[3] - dst[4])/2;
+ const int leftEnergy= 5*(dst[2] - dst[1]) + 2*(dst[0] - dst[3]);
+ const int rightEnergy= 5*(dst[6] - dst[5]) + 2*(dst[4] - dst[7]);
+
+ int d= FFABS(middleEnergy) - FFMIN( FFABS(leftEnergy), FFABS(rightEnergy) );
+ d= FFMAX(d, 0);
+
+ d= (5*d + 32) >> 6;
+ d*= FFSIGN(-middleEnergy);
+
+ if(q>0)
+ {
+ d= d<0 ? 0 : d;
+ d= d>q ? q : d;
+ }
+ else
+ {
+ d= d>0 ? 0 : d;
+ d= d<q ? q : d;
+ }
+
+ dst[3]-= d;
+ dst[4]+= d;
+ }
+ dst+= stride;
+ }
+}
+
+/**
+ * Do a horizontal low pass filter on the 10x8 block (dst points to middle 8x8 Block)
+ * using the 9-Tap Filter (1,1,2,2,4,2,2,1,1)/16 (C version)
+ */
+static inline void doHorizLowPass_C(uint8_t dst[], int stride, PPContext *c)
+{
+ int y;
+ for(y=0; y<BLOCK_SIZE; y++)
+ {
+ const int first= FFABS(dst[-1] - dst[0]) < c->QP ? dst[-1] : dst[0];
+ const int last= FFABS(dst[8] - dst[7]) < c->QP ? dst[8] : dst[7];
+
+ int sums[10];
+ sums[0] = 4*first + dst[0] + dst[1] + dst[2] + 4;
+ sums[1] = sums[0] - first + dst[3];
+ sums[2] = sums[1] - first + dst[4];
+ sums[3] = sums[2] - first + dst[5];
+ sums[4] = sums[3] - first + dst[6];
+ sums[5] = sums[4] - dst[0] + dst[7];
+ sums[6] = sums[5] - dst[1] + last;
+ sums[7] = sums[6] - dst[2] + last;
+ sums[8] = sums[7] - dst[3] + last;
+ sums[9] = sums[8] - dst[4] + last;
+
+ dst[0]= (sums[0] + sums[2] + 2*dst[0])>>4;
+ dst[1]= (sums[1] + sums[3] + 2*dst[1])>>4;
+ dst[2]= (sums[2] + sums[4] + 2*dst[2])>>4;
+ dst[3]= (sums[3] + sums[5] + 2*dst[3])>>4;
+ dst[4]= (sums[4] + sums[6] + 2*dst[4])>>4;
+ dst[5]= (sums[5] + sums[7] + 2*dst[5])>>4;
+ dst[6]= (sums[6] + sums[8] + 2*dst[6])>>4;
+ dst[7]= (sums[7] + sums[9] + 2*dst[7])>>4;
+
+ dst+= stride;
+ }
+}
+
+/**
+ * Experimental Filter 1 (Horizontal)
+ * will not damage linear gradients
+ * Flat blocks should look like they where passed through the (1,1,2,2,4,2,2,1,1) 9-Tap filter
+ * can only smooth blocks at the expected locations (it cant smooth them if they did move)
+ * MMX2 version does correct clipping C version doesnt
+ * not identical with the vertical one
+ */
+static inline void horizX1Filter(uint8_t *src, int stride, int QP)
+{
+ int y;
+ static uint64_t *lut= NULL;
+ if(lut==NULL)
+ {
+ int i;
+ lut = av_malloc(256*8);
+ for(i=0; i<256; i++)
+ {
+ int v= i < 128 ? 2*i : 2*(i-256);
+/*
+//Simulate 112242211 9-Tap filter
+ uint64_t a= (v/16) & 0xFF;
+ uint64_t b= (v/8) & 0xFF;
+ uint64_t c= (v/4) & 0xFF;
+ uint64_t d= (3*v/8) & 0xFF;
+*/
+//Simulate piecewise linear interpolation
+ uint64_t a= (v/16) & 0xFF;
+ uint64_t b= (v*3/16) & 0xFF;
+ uint64_t c= (v*5/16) & 0xFF;
+ uint64_t d= (7*v/16) & 0xFF;
+ uint64_t A= (0x100 - a)&0xFF;
+ uint64_t B= (0x100 - b)&0xFF;
+ uint64_t C= (0x100 - c)&0xFF;
+ uint64_t D= (0x100 - c)&0xFF;
+
+ lut[i] = (a<<56) | (b<<48) | (c<<40) | (d<<32) |
+ (D<<24) | (C<<16) | (B<<8) | (A);
+ //lut[i] = (v<<32) | (v<<24);
+ }
+ }
+
+ for(y=0; y<BLOCK_SIZE; y++)
+ {
+ int a= src[1] - src[2];
+ int b= src[3] - src[4];
+ int c= src[5] - src[6];
+
+ int d= FFMAX(FFABS(b) - (FFABS(a) + FFABS(c))/2, 0);
+
+ if(d < QP)
+ {
+ int v = d * FFSIGN(-b);
+
+ src[1] +=v/8;
+ src[2] +=v/4;
+ src[3] +=3*v/8;
+ src[4] -=3*v/8;
+ src[5] -=v/4;
+ src[6] -=v/8;
+
+ }
+ src+=stride;
+ }
+}
+
+/**
+ * accurate deblock filter
+ */
+static always_inline void do_a_deblock_C(uint8_t *src, int step, int stride, PPContext *c){
+ int y;
+ const int QP= c->QP;
+ const int dcOffset= ((c->nonBQP*c->ppMode.baseDcDiff)>>8) + 1;
+ const int dcThreshold= dcOffset*2 + 1;
+//START_TIMER
+ src+= step*4; // src points to begin of the 8x8 Block
+ for(y=0; y<8; y++){
+ int numEq= 0;
+
+ if(((unsigned)(src[-1*step] - src[0*step] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[ 0*step] - src[1*step] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[ 1*step] - src[2*step] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[ 2*step] - src[3*step] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[ 3*step] - src[4*step] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[ 4*step] - src[5*step] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[ 5*step] - src[6*step] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[ 6*step] - src[7*step] + dcOffset)) < dcThreshold) numEq++;
+ if(((unsigned)(src[ 7*step] - src[8*step] + dcOffset)) < dcThreshold) numEq++;
+ if(numEq > c->ppMode.flatnessThreshold){
+ int min, max, x;
+
+ if(src[0] > src[step]){
+ max= src[0];
+ min= src[step];
+ }else{
+ max= src[step];
+ min= src[0];
+ }
+ for(x=2; x<8; x+=2){
+ if(src[x*step] > src[(x+1)*step]){
+ if(src[x *step] > max) max= src[ x *step];
+ if(src[(x+1)*step] < min) min= src[(x+1)*step];
+ }else{
+ if(src[(x+1)*step] > max) max= src[(x+1)*step];
+ if(src[ x *step] < min) min= src[ x *step];
+ }
+ }
+ if(max-min < 2*QP){
+ const int first= FFABS(src[-1*step] - src[0]) < QP ? src[-1*step] : src[0];
+ const int last= FFABS(src[8*step] - src[7*step]) < QP ? src[8*step] : src[7*step];
+
+ int sums[10];
+ sums[0] = 4*first + src[0*step] + src[1*step] + src[2*step] + 4;
+ sums[1] = sums[0] - first + src[3*step];
+ sums[2] = sums[1] - first + src[4*step];
+ sums[3] = sums[2] - first + src[5*step];
+ sums[4] = sums[3] - first + src[6*step];
+ sums[5] = sums[4] - src[0*step] + src[7*step];
+ sums[6] = sums[5] - src[1*step] + last;
+ sums[7] = sums[6] - src[2*step] + last;
+ sums[8] = sums[7] - src[3*step] + last;
+ sums[9] = sums[8] - src[4*step] + last;
+
+ src[0*step]= (sums[0] + sums[2] + 2*src[0*step])>>4;
+ src[1*step]= (sums[1] + sums[3] + 2*src[1*step])>>4;
+ src[2*step]= (sums[2] + sums[4] + 2*src[2*step])>>4;
+ src[3*step]= (sums[3] + sums[5] + 2*src[3*step])>>4;
+ src[4*step]= (sums[4] + sums[6] + 2*src[4*step])>>4;
+ src[5*step]= (sums[5] + sums[7] + 2*src[5*step])>>4;
+ src[6*step]= (sums[6] + sums[8] + 2*src[6*step])>>4;
+ src[7*step]= (sums[7] + sums[9] + 2*src[7*step])>>4;
+ }
+ }else{
+ const int middleEnergy= 5*(src[4*step] - src[3*step]) + 2*(src[2*step] - src[5*step]);
+
+ if(FFABS(middleEnergy) < 8*QP)
+ {
+ const int q=(src[3*step] - src[4*step])/2;
+ const int leftEnergy= 5*(src[2*step] - src[1*step]) + 2*(src[0*step] - src[3*step]);
+ const int rightEnergy= 5*(src[6*step] - src[5*step]) + 2*(src[4*step] - src[7*step]);
+
+ int d= FFABS(middleEnergy) - FFMIN( FFABS(leftEnergy), FFABS(rightEnergy) );
+ d= FFMAX(d, 0);
+
+ d= (5*d + 32) >> 6;
+ d*= FFSIGN(-middleEnergy);
+
+ if(q>0)
+ {
+ d= d<0 ? 0 : d;
+ d= d>q ? q : d;
+ }
+ else
+ {
+ d= d>0 ? 0 : d;
+ d= d<q ? q : d;
+ }
+
+ src[3*step]-= d;
+ src[4*step]+= d;
+ }
+ }
+
+ src += stride;
+ }
+/*if(step==16){
+ STOP_TIMER("step16")
+}else{
+ STOP_TIMER("stepX")
+}*/
+}
+
+//Note: we have C, MMX, MMX2, 3DNOW version there is no 3DNOW+MMX2 one
+//Plain C versions
+#if !defined (HAVE_MMX) || defined (RUNTIME_CPUDETECT)
+#define COMPILE_C
+#endif
+
+#ifdef ARCH_POWERPC
+#ifdef HAVE_ALTIVEC
+#define COMPILE_ALTIVEC
+#endif //HAVE_ALTIVEC
+#endif //ARCH_POWERPC
+
+#if defined(ARCH_X86)
+
+#if (defined (HAVE_MMX) && !defined (HAVE_3DNOW) && !defined (HAVE_MMX2)) || defined (RUNTIME_CPUDETECT)
+#define COMPILE_MMX
+#endif
+
+#if defined (HAVE_MMX2) || defined (RUNTIME_CPUDETECT)
+#define COMPILE_MMX2
+#endif
+
+#if (defined (HAVE_3DNOW) && !defined (HAVE_MMX2)) || defined (RUNTIME_CPUDETECT)
+#define COMPILE_3DNOW
+#endif
+#endif /* defined(ARCH_X86) */
+
+#undef HAVE_MMX
+#undef HAVE_MMX2
+#undef HAVE_3DNOW
+#undef HAVE_ALTIVEC
+
+#ifdef COMPILE_C
+#undef HAVE_MMX
+#undef HAVE_MMX2
+#undef HAVE_3DNOW
+#define RENAME(a) a ## _C
+#include "postprocess_template.c"
+#endif
+
+#ifdef ARCH_POWERPC
+#ifdef COMPILE_ALTIVEC
+#undef RENAME
+#define HAVE_ALTIVEC
+#define RENAME(a) a ## _altivec
+#include "postprocess_altivec_template.c"
+#include "postprocess_template.c"
+#endif
+#endif //ARCH_POWERPC
+
+//MMX versions
+#ifdef COMPILE_MMX
+#undef RENAME
+#define HAVE_MMX
+#undef HAVE_MMX2
+#undef HAVE_3DNOW
+#define RENAME(a) a ## _MMX
+#include "postprocess_template.c"
+#endif
+
+//MMX2 versions
+#ifdef COMPILE_MMX2
+#undef RENAME
+#define HAVE_MMX
+#define HAVE_MMX2
+#undef HAVE_3DNOW
+#define RENAME(a) a ## _MMX2
+#include "postprocess_template.c"
+#endif
+
+//3DNOW versions
+#ifdef COMPILE_3DNOW
+#undef RENAME
+#define HAVE_MMX
+#undef HAVE_MMX2
+#define HAVE_3DNOW
+#define RENAME(a) a ## _3DNow
+#include "postprocess_template.c"
+#endif
+
+// minor note: the HAVE_xyz is messed up after that line so dont use it
+
+static inline void postProcess(uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height,
+ QP_STORE_T QPs[], int QPStride, int isColor, pp_mode_t *vm, pp_context_t *vc)
+{
+ PPContext *c= (PPContext *)vc;
+ PPMode *ppMode= (PPMode *)vm;
+ c->ppMode= *ppMode; //FIXME
+
+ // useing ifs here as they are faster than function pointers allthough the
+ // difference wouldnt be messureable here but its much better because
+ // someone might exchange the cpu whithout restarting mplayer ;)
+#ifdef RUNTIME_CPUDETECT
+#if defined(ARCH_X86)
+ // ordered per speed fasterst first
+ if(c->cpuCaps & PP_CPU_CAPS_MMX2)
+ postProcess_MMX2(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
+ else if(c->cpuCaps & PP_CPU_CAPS_3DNOW)
+ postProcess_3DNow(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
+ else if(c->cpuCaps & PP_CPU_CAPS_MMX)
+ postProcess_MMX(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
+ else
+ postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
+#else
+#ifdef ARCH_POWERPC
+#ifdef HAVE_ALTIVEC
+ if(c->cpuCaps & PP_CPU_CAPS_ALTIVEC)
+ postProcess_altivec(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
+ else
+#endif
+#endif
+ postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
+#endif
+#else //RUNTIME_CPUDETECT
+#ifdef HAVE_MMX2
+ postProcess_MMX2(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
+#elif defined (HAVE_3DNOW)
+ postProcess_3DNow(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
+#elif defined (HAVE_MMX)
+ postProcess_MMX(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
+#elif defined (HAVE_ALTIVEC)
+ postProcess_altivec(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
+#else
+ postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
+#endif
+#endif //!RUNTIME_CPUDETECT
+}
+
+//static void postProcess(uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height,
+// QP_STORE_T QPs[], int QPStride, int isColor, struct PPMode *ppMode);
+
+/* -pp Command line Help
+*/
+char *pp_help=
+"Available postprocessing filters:\n"
+"Filters Options\n"
+"short long name short long option Description\n"
+"* * a autoq CPU power dependent enabler\n"
+" c chrom chrominance filtering enabled\n"
+" y nochrom chrominance filtering disabled\n"
+" n noluma luma filtering disabled\n"
+"hb hdeblock (2 threshold) horizontal deblocking filter\n"
+" 1. difference factor: default=32, higher -> more deblocking\n"
+" 2. flatness threshold: default=39, lower -> more deblocking\n"
+" the h & v deblocking filters share these\n"
+" so you can't set different thresholds for h / v\n"
+"vb vdeblock (2 threshold) vertical deblocking filter\n"
+"ha hadeblock (2 threshold) horizontal deblocking filter\n"
+"va vadeblock (2 threshold) vertical deblocking filter\n"
+"h1 x1hdeblock experimental h deblock filter 1\n"
+"v1 x1vdeblock experimental v deblock filter 1\n"
+"dr dering deringing filter\n"
+"al autolevels automatic brightness / contrast\n"
+" f fullyrange stretch luminance to (0..255)\n"
+"lb linblenddeint linear blend deinterlacer\n"
+"li linipoldeint linear interpolating deinterlace\n"
+"ci cubicipoldeint cubic interpolating deinterlacer\n"
+"md mediandeint median deinterlacer\n"
+"fd ffmpegdeint ffmpeg deinterlacer\n"
+"l5 lowpass5 FIR lowpass deinterlacer\n"
+"de default hb:a,vb:a,dr:a\n"
+"fa fast h1:a,v1:a,dr:a\n"
+"ac ha:a:128:7,va:a,dr:a\n"
+"tn tmpnoise (3 threshold) temporal noise reducer\n"
+" 1. <= 2. <= 3. larger -> stronger filtering\n"
+"fq forceQuant <quantizer> force quantizer\n"
+"Usage:\n"
+"<filterName>[:<option>[:<option>...]][[,|/][-]<filterName>[:<option>...]]...\n"
+"long form example:\n"
+"vdeblock:autoq/hdeblock:autoq/linblenddeint default,-vdeblock\n"
+"short form example:\n"
+"vb:a/hb:a/lb de,-vb\n"
+"more examples:\n"
+"tn:64:128:256\n"
+"\n"
+;
+
+pp_mode_t *pp_get_mode_by_name_and_quality(char *name, int quality)
+{
+ char temp[GET_MODE_BUFFER_SIZE];
+ char *p= temp;
+ const char *filterDelimiters= ",/";
+ const char *optionDelimiters= ":";
+ struct PPMode *ppMode;
+ char *filterToken;
+
+ ppMode= av_malloc(sizeof(PPMode));
+
+ ppMode->lumMode= 0;
+ ppMode->chromMode= 0;
+ ppMode->maxTmpNoise[0]= 700;
+ ppMode->maxTmpNoise[1]= 1500;
+ ppMode->maxTmpNoise[2]= 3000;
+ ppMode->maxAllowedY= 234;
+ ppMode->minAllowedY= 16;
+ ppMode->baseDcDiff= 256/8;
+ ppMode->flatnessThreshold= 56-16-1;
+ ppMode->maxClippedThreshold= 0.01;
+ ppMode->error=0;
+
+ strncpy(temp, name, GET_MODE_BUFFER_SIZE);
+
+ av_log(NULL, AV_LOG_DEBUG, "pp: %s\n", name);
+
+ for(;;){
+ char *filterName;
+ int q= 1000000; //PP_QUALITY_MAX;
+ int chrom=-1;
+ int luma=-1;
+ char *option;
+ char *options[OPTIONS_ARRAY_SIZE];
+ int i;
+ int filterNameOk=0;
+ int numOfUnknownOptions=0;
+ int enable=1; //does the user want us to enabled or disabled the filter
+
+ filterToken= strtok(p, filterDelimiters);
+ if(filterToken == NULL) break;
+ p+= strlen(filterToken) + 1; // p points to next filterToken
+ filterName= strtok(filterToken, optionDelimiters);
+ av_log(NULL, AV_LOG_DEBUG, "pp: %s::%s\n", filterToken, filterName);
+
+ if(*filterName == '-')
+ {
+ enable=0;
+ filterName++;
+ }
+
+ for(;;){ //for all options
+ option= strtok(NULL, optionDelimiters);
+ if(option == NULL) break;
+
+ av_log(NULL, AV_LOG_DEBUG, "pp: option: %s\n", option);
+ if(!strcmp("autoq", option) || !strcmp("a", option)) q= quality;
+ else if(!strcmp("nochrom", option) || !strcmp("y", option)) chrom=0;
+ else if(!strcmp("chrom", option) || !strcmp("c", option)) chrom=1;
+ else if(!strcmp("noluma", option) || !strcmp("n", option)) luma=0;
+ else
+ {
+ options[numOfUnknownOptions] = option;
+ numOfUnknownOptions++;
+ }
+ if(numOfUnknownOptions >= OPTIONS_ARRAY_SIZE-1) break;
+ }
+ options[numOfUnknownOptions] = NULL;
+
+ /* replace stuff from the replace Table */
+ for(i=0; replaceTable[2*i]!=NULL; i++)
+ {
+ if(!strcmp(replaceTable[2*i], filterName))
+ {
+ int newlen= strlen(replaceTable[2*i + 1]);
+ int plen;
+ int spaceLeft;
+
+ if(p==NULL) p= temp, *p=0; //last filter
+ else p--, *p=','; //not last filter
+
+ plen= strlen(p);
+ spaceLeft= p - temp + plen;
+ if(spaceLeft + newlen >= GET_MODE_BUFFER_SIZE)
+ {
+ ppMode->error++;
+ break;
+ }
+ memmove(p + newlen, p, plen+1);
+ memcpy(p, replaceTable[2*i + 1], newlen);
+ filterNameOk=1;
+ }
+ }
+
+ for(i=0; filters[i].shortName!=NULL; i++)
+ {
+ if( !strcmp(filters[i].longName, filterName)
+ || !strcmp(filters[i].shortName, filterName))
+ {
+ ppMode->lumMode &= ~filters[i].mask;
+ ppMode->chromMode &= ~filters[i].mask;
+
+ filterNameOk=1;
+ if(!enable) break; // user wants to disable it
+
+ if(q >= filters[i].minLumQuality && luma)
+ ppMode->lumMode|= filters[i].mask;
+ if(chrom==1 || (chrom==-1 && filters[i].chromDefault))
+ if(q >= filters[i].minChromQuality)
+ ppMode->chromMode|= filters[i].mask;
+
+ if(filters[i].mask == LEVEL_FIX)
+ {
+ int o;
+ ppMode->minAllowedY= 16;
+ ppMode->maxAllowedY= 234;
+ for(o=0; options[o]!=NULL; o++)
+ {
+ if( !strcmp(options[o],"fullyrange")
+ ||!strcmp(options[o],"f"))
+ {
+ ppMode->minAllowedY= 0;
+ ppMode->maxAllowedY= 255;
+ numOfUnknownOptions--;
+ }
+ }
+ }
+ else if(filters[i].mask == TEMP_NOISE_FILTER)
+ {
+ int o;
+ int numOfNoises=0;
+
+ for(o=0; options[o]!=NULL; o++)
+ {
+ char *tail;
+ ppMode->maxTmpNoise[numOfNoises]=
+ strtol(options[o], &tail, 0);
+ if(tail!=options[o])
+ {
+ numOfNoises++;
+ numOfUnknownOptions--;
+ if(numOfNoises >= 3) break;
+ }
+ }
+ }
+ else if(filters[i].mask == V_DEBLOCK || filters[i].mask == H_DEBLOCK
+ || filters[i].mask == V_A_DEBLOCK || filters[i].mask == H_A_DEBLOCK)
+ {
+ int o;
+
+ for(o=0; options[o]!=NULL && o<2; o++)
+ {
+ char *tail;
+ int val= strtol(options[o], &tail, 0);
+ if(tail==options[o]) break;
+
+ numOfUnknownOptions--;
+ if(o==0) ppMode->baseDcDiff= val;
+ else ppMode->flatnessThreshold= val;
+ }
+ }
+ else if(filters[i].mask == FORCE_QUANT)
+ {
+ int o;
+ ppMode->forcedQuant= 15;
+
+ for(o=0; options[o]!=NULL && o<1; o++)
+ {
+ char *tail;
+ int val= strtol(options[o], &tail, 0);
+ if(tail==options[o]) break;
+
+ numOfUnknownOptions--;
+ ppMode->forcedQuant= val;
+ }
+ }
+ }
+ }
+ if(!filterNameOk) ppMode->error++;
+ ppMode->error += numOfUnknownOptions;
+ }
+
+ av_log(NULL, AV_LOG_DEBUG, "pp: lumMode=%X, chromMode=%X\n", ppMode->lumMode, ppMode->chromMode);
+ if(ppMode->error)
+ {
+ av_log(NULL, AV_LOG_ERROR, "%d errors in postprocess string \"%s\"\n", ppMode->error, name);
+ av_free(ppMode);
+ return NULL;
+ }
+ return ppMode;
+}
+
+void pp_free_mode(pp_mode_t *mode){
+ av_free(mode);
+}
+
+static void reallocAlign(void **p, int alignment, int size){
+ av_free(*p);
+ *p= av_mallocz(size);
+}
+
+static void reallocBuffers(PPContext *c, int width, int height, int stride, int qpStride){
+ int mbWidth = (width+15)>>4;
+ int mbHeight= (height+15)>>4;
+ int i;
+
+ c->stride= stride;
+ c->qpStride= qpStride;
+
+ reallocAlign((void **)&c->tempDst, 8, stride*24);
+ reallocAlign((void **)&c->tempSrc, 8, stride*24);
+ reallocAlign((void **)&c->tempBlocks, 8, 2*16*8);
+ reallocAlign((void **)&c->yHistogram, 8, 256*sizeof(uint64_t));
+ for(i=0; i<256; i++)
+ c->yHistogram[i]= width*height/64*15/256;
+
+ for(i=0; i<3; i++)
+ {
+ //Note:the +17*1024 is just there so i dont have to worry about r/w over te end
+ reallocAlign((void **)&c->tempBlured[i], 8, stride*mbHeight*16 + 17*1024);
+ reallocAlign((void **)&c->tempBluredPast[i], 8, 256*((height+7)&(~7))/2 + 17*1024);//FIXME size
+ }
+
+ reallocAlign((void **)&c->deintTemp, 8, 2*width+32);
+ reallocAlign((void **)&c->nonBQPTable, 8, qpStride*mbHeight*sizeof(QP_STORE_T));
+ reallocAlign((void **)&c->stdQPTable, 8, qpStride*mbHeight*sizeof(QP_STORE_T));
+ reallocAlign((void **)&c->forcedQPTable, 8, mbWidth*sizeof(QP_STORE_T));
+}
+
+static void global_init(void){
+ int i;
+ memset(clip_table, 0, 256);
+ for(i=256; i<512; i++)
+ clip_table[i]= i;
+ memset(clip_table+512, 0, 256);
+}
+
+static const char * context_to_name(void * ptr) {
+ return "postproc";
+}
+
+static AVClass av_codec_context_class = { "Postproc", context_to_name, NULL };
+
+pp_context_t *pp_get_context(int width, int height, int cpuCaps){
+ PPContext *c= av_malloc(sizeof(PPContext));
+ int stride= (width+15)&(~15); //assumed / will realloc if needed
+ int qpStride= (width+15)/16 + 2; //assumed / will realloc if needed
+
+ global_init();
+
+ memset(c, 0, sizeof(PPContext));
+ c->av_class = &av_codec_context_class;
+ c->cpuCaps= cpuCaps;
+ if(cpuCaps&PP_FORMAT){
+ c->hChromaSubSample= cpuCaps&0x3;
+ c->vChromaSubSample= (cpuCaps>>4)&0x3;
+ }else{
+ c->hChromaSubSample= 1;
+ c->vChromaSubSample= 1;
+ }
+
+ reallocBuffers(c, width, height, stride, qpStride);
+
+ c->frameNum=-1;
+
+ return c;
+}
+
+void pp_free_context(void *vc){
+ PPContext *c = (PPContext*)vc;
+ int i;
+
+ for(i=0; i<3; i++) av_free(c->tempBlured[i]);
+ for(i=0; i<3; i++) av_free(c->tempBluredPast[i]);
+
+ av_free(c->tempBlocks);
+ av_free(c->yHistogram);
+ av_free(c->tempDst);
+ av_free(c->tempSrc);
+ av_free(c->deintTemp);
+ av_free(c->stdQPTable);
+ av_free(c->nonBQPTable);
+ av_free(c->forcedQPTable);
+
+ memset(c, 0, sizeof(PPContext));
+
+ av_free(c);
+}
+
+void pp_postprocess(uint8_t * src[3], int srcStride[3],
+ uint8_t * dst[3], int dstStride[3],
+ int width, int height,
+ QP_STORE_T *QP_store, int QPStride,
+ pp_mode_t *vm, void *vc, int pict_type)
+{
+ int mbWidth = (width+15)>>4;
+ int mbHeight= (height+15)>>4;
+ PPMode *mode = (PPMode*)vm;
+ PPContext *c = (PPContext*)vc;
+ int minStride= FFMAX(FFABS(srcStride[0]), FFABS(dstStride[0]));
+ int absQPStride = FFABS(QPStride);
+
+ // c->stride and c->QPStride are always positive
+ if(c->stride < minStride || c->qpStride < absQPStride)
+ reallocBuffers(c, width, height,
+ FFMAX(minStride, c->stride),
+ FFMAX(c->qpStride, absQPStride));
+
+ if(QP_store==NULL || (mode->lumMode & FORCE_QUANT))
+ {
+ int i;
+ QP_store= c->forcedQPTable;
+ absQPStride = QPStride = 0;
+ if(mode->lumMode & FORCE_QUANT)
+ for(i=0; i<mbWidth; i++) QP_store[i]= mode->forcedQuant;
+ else
+ for(i=0; i<mbWidth; i++) QP_store[i]= 1;
+ }
+
+ if(pict_type & PP_PICT_TYPE_QP2){
+ int i;
+ const int count= mbHeight * absQPStride;
+ for(i=0; i<(count>>2); i++){
+ ((uint32_t*)c->stdQPTable)[i] = (((uint32_t*)QP_store)[i]>>1) & 0x7F7F7F7F;
+ }
+ for(i<<=2; i<count; i++){
+ c->stdQPTable[i] = QP_store[i]>>1;
+ }
+ QP_store= c->stdQPTable;
+ QPStride= absQPStride;
+ }
+
+if(0){
+int x,y;
+for(y=0; y<mbHeight; y++){
+ for(x=0; x<mbWidth; x++){
+ av_log(c, AV_LOG_INFO, "%2d ", QP_store[x + y*QPStride]);
+ }
+ av_log(c, AV_LOG_INFO, "\n");
+}
+ av_log(c, AV_LOG_INFO, "\n");
+}
+
+ if((pict_type&7)!=3)
+ {
+ if (QPStride >= 0) {
+ int i;
+ const int count= mbHeight * QPStride;
+ for(i=0; i<(count>>2); i++){
+ ((uint32_t*)c->nonBQPTable)[i] = ((uint32_t*)QP_store)[i] & 0x3F3F3F3F;
+ }
+ for(i<<=2; i<count; i++){
+ c->nonBQPTable[i] = QP_store[i] & 0x3F;
+ }
+ } else {
+ int i,j;
+ for(i=0; i<mbHeight; i++) {
+ for(j=0; j<absQPStride; j++) {
+ c->nonBQPTable[i*absQPStride+j] = QP_store[i*QPStride+j] & 0x3F;
+ }
+ }
+ }
+ }
+
+ av_log(c, AV_LOG_DEBUG, "using npp filters 0x%X/0x%X\n",
+ mode->lumMode, mode->chromMode);
+
+ postProcess(src[0], srcStride[0], dst[0], dstStride[0],
+ width, height, QP_store, QPStride, 0, mode, c);
+
+ width = (width )>>c->hChromaSubSample;
+ height = (height)>>c->vChromaSubSample;
+
+ if(mode->chromMode)
+ {
+ postProcess(src[1], srcStride[1], dst[1], dstStride[1],
+ width, height, QP_store, QPStride, 1, mode, c);
+ postProcess(src[2], srcStride[2], dst[2], dstStride[2],
+ width, height, QP_store, QPStride, 2, mode, c);
+ }
+ else if(srcStride[1] == dstStride[1] && srcStride[2] == dstStride[2])
+ {
+ linecpy(dst[1], src[1], height, srcStride[1]);
+ linecpy(dst[2], src[2], height, srcStride[2]);
+ }
+ else
+ {
+ int y;
+ for(y=0; y<height; y++)
+ {
+ memcpy(&(dst[1][y*dstStride[1]]), &(src[1][y*srcStride[1]]), width);
+ memcpy(&(dst[2][y*dstStride[2]]), &(src[2][y*srcStride[2]]), width);
+ }
+ }
+}
+
diff --git a/contrib/ffmpeg/libpostproc/postprocess.h b/contrib/ffmpeg/libpostproc/postprocess.h
new file mode 100644
index 000000000..eed92ba6d
--- /dev/null
+++ b/contrib/ffmpeg/libpostproc/postprocess.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2001-2003 Michael Niedermayer (michaelni@gmx.at)
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that 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
+ */
+
+#ifndef NEWPOSTPROCESS_H
+#define NEWPOSTPROCESS_H
+
+/**
+ * @file postprocess.h
+ * @brief
+ * external api for the pp stuff
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LIBPOSTPROC_VERSION_INT ((51<<16)+(1<<8)+0)
+#define LIBPOSTPROC_VERSION 51.1.0
+#define LIBPOSTPROC_BUILD LIBPOSTPROC_VERSION_INT
+
+#define LIBPOSTPROC_IDENT "postproc" AV_STRINGIFY(LIBPOSTPROC_VERSION)
+
+#define PP_QUALITY_MAX 6
+
+#define QP_STORE_T int8_t
+
+typedef void pp_context_t;
+typedef void pp_mode_t;
+
+extern char *pp_help; ///< a simple help text
+
+void pp_postprocess(uint8_t * src[3], int srcStride[3],
+ uint8_t * dst[3], int dstStride[3],
+ int horizontalSize, int verticalSize,
+ QP_STORE_T *QP_store, int QP_stride,
+ pp_mode_t *mode, pp_context_t *ppContext, int pict_type);
+
+
+/**
+ * returns a pp_mode_t or NULL if an error occured
+ * name is the string after "-pp" on the command line
+ * quality is a number from 0 to PP_QUALITY_MAX
+ */
+pp_mode_t *pp_get_mode_by_name_and_quality(char *name, int quality);
+void pp_free_mode(pp_mode_t *mode);
+
+pp_context_t *pp_get_context(int width, int height, int flags);
+void pp_free_context(pp_context_t *ppContext);
+
+#define PP_CPU_CAPS_MMX 0x80000000
+#define PP_CPU_CAPS_MMX2 0x20000000
+#define PP_CPU_CAPS_3DNOW 0x40000000
+#define PP_CPU_CAPS_ALTIVEC 0x10000000
+
+#define PP_FORMAT 0x00000008
+#define PP_FORMAT_420 (0x00000011|PP_FORMAT)
+#define PP_FORMAT_422 (0x00000001|PP_FORMAT)
+#define PP_FORMAT_411 (0x00000002|PP_FORMAT)
+#define PP_FORMAT_444 (0x00000000|PP_FORMAT)
+
+#define PP_PICT_TYPE_QP2 0x00000010 ///< MPEG2 style QScale
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/ffmpeg/libpostproc/postprocess_altivec_template.c b/contrib/ffmpeg/libpostproc/postprocess_altivec_template.c
new file mode 100644
index 000000000..3a33a5885
--- /dev/null
+++ b/contrib/ffmpeg/libpostproc/postprocess_altivec_template.c
@@ -0,0 +1,1191 @@
+/*
+ * AltiVec optimizations (C) 2004 Romain Dolbeau <romain@dolbeau.org>
+ *
+ * based on code by Copyright (C) 2001-2003 Michael Niedermayer (michaelni@gmx.at)
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that 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
+ */
+
+
+#ifdef CONFIG_DARWIN
+#define AVV(x...) (x)
+#else
+#define AVV(x...) {x}
+#endif
+
+#define ALTIVEC_TRANSPOSE_8x8_SHORT(src_a,src_b,src_c,src_d,src_e,src_f,src_g,src_h) \
+ do { \
+ __typeof__(src_a) tempA1, tempB1, tempC1, tempD1; \
+ __typeof__(src_a) tempE1, tempF1, tempG1, tempH1; \
+ __typeof__(src_a) tempA2, tempB2, tempC2, tempD2; \
+ __typeof__(src_a) tempE2, tempF2, tempG2, tempH2; \
+ tempA1 = vec_mergeh (src_a, src_e); \
+ tempB1 = vec_mergel (src_a, src_e); \
+ tempC1 = vec_mergeh (src_b, src_f); \
+ tempD1 = vec_mergel (src_b, src_f); \
+ tempE1 = vec_mergeh (src_c, src_g); \
+ tempF1 = vec_mergel (src_c, src_g); \
+ tempG1 = vec_mergeh (src_d, src_h); \
+ tempH1 = vec_mergel (src_d, src_h); \
+ tempA2 = vec_mergeh (tempA1, tempE1); \
+ tempB2 = vec_mergel (tempA1, tempE1); \
+ tempC2 = vec_mergeh (tempB1, tempF1); \
+ tempD2 = vec_mergel (tempB1, tempF1); \
+ tempE2 = vec_mergeh (tempC1, tempG1); \
+ tempF2 = vec_mergel (tempC1, tempG1); \
+ tempG2 = vec_mergeh (tempD1, tempH1); \
+ tempH2 = vec_mergel (tempD1, tempH1); \
+ src_a = vec_mergeh (tempA2, tempE2); \
+ src_b = vec_mergel (tempA2, tempE2); \
+ src_c = vec_mergeh (tempB2, tempF2); \
+ src_d = vec_mergel (tempB2, tempF2); \
+ src_e = vec_mergeh (tempC2, tempG2); \
+ src_f = vec_mergel (tempC2, tempG2); \
+ src_g = vec_mergeh (tempD2, tempH2); \
+ src_h = vec_mergel (tempD2, tempH2); \
+ } while (0)
+
+
+static inline int vertClassify_altivec(uint8_t src[], int stride, PPContext *c) {
+ /*
+ this code makes no assumption on src or stride.
+ One could remove the recomputation of the perm
+ vector by assuming (stride % 16) == 0, unfortunately
+ this is not always true.
+ */
+ short __attribute__ ((aligned(16))) data[8];
+ int numEq;
+ uint8_t *src2 = src;
+ vector signed short v_dcOffset;
+ vector signed short v2QP;
+ vector unsigned short v4QP;
+ vector unsigned short v_dcThreshold;
+ const int properStride = (stride % 16);
+ const int srcAlign = ((unsigned long)src2 % 16);
+ const int two_vectors = ((srcAlign > 8) || properStride) ? 1 : 0;
+ const vector signed int zero = vec_splat_s32(0);
+ const vector signed short mask = vec_splat_s16(1);
+ vector signed int v_numEq = vec_splat_s32(0);
+
+ data[0] = ((c->nonBQP*c->ppMode.baseDcDiff)>>8) + 1;
+ data[1] = data[0] * 2 + 1;
+ data[2] = c->QP * 2;
+ data[3] = c->QP * 4;
+ vector signed short v_data = vec_ld(0, data);
+ v_dcOffset = vec_splat(v_data, 0);
+ v_dcThreshold = (vector unsigned short)vec_splat(v_data, 1);
+ v2QP = vec_splat(v_data, 2);
+ v4QP = (vector unsigned short)vec_splat(v_data, 3);
+
+ src2 += stride * 4;
+
+ vector signed short v_srcAss0, v_srcAss1, v_srcAss2, v_srcAss3, v_srcAss4, v_srcAss5, v_srcAss6, v_srcAss7;
+
+#define LOAD_LINE(i) \
+ register int j##i = i * stride; \
+ vector unsigned char perm##i = vec_lvsl(j##i, src2); \
+ const vector unsigned char v_srcA1##i = vec_ld(j##i, src2); \
+ vector unsigned char v_srcA2##i; \
+ if (two_vectors) \
+ v_srcA2##i = vec_ld(j##i + 16, src2); \
+ const vector unsigned char v_srcA##i = \
+ vec_perm(v_srcA1##i, v_srcA2##i, perm##i); \
+ v_srcAss##i = \
+ (vector signed short)vec_mergeh((vector signed char)zero, \
+ (vector signed char)v_srcA##i)
+
+#define LOAD_LINE_ALIGNED(i) \
+ register int j##i = i * stride; \
+ const vector unsigned char v_srcA##i = vec_ld(j##i, src2); \
+ v_srcAss##i = \
+ (vector signed short)vec_mergeh((vector signed char)zero, \
+ (vector signed char)v_srcA##i)
+
+ // special casing the aligned case is worthwhile, as all call from
+ // the (transposed) horizontable deblocks will be aligned, i naddition
+ // to the naturraly aligned vertical deblocks.
+ if (properStride && srcAlign) {
+ LOAD_LINE_ALIGNED(0);
+ LOAD_LINE_ALIGNED(1);
+ LOAD_LINE_ALIGNED(2);
+ LOAD_LINE_ALIGNED(3);
+ LOAD_LINE_ALIGNED(4);
+ LOAD_LINE_ALIGNED(5);
+ LOAD_LINE_ALIGNED(6);
+ LOAD_LINE_ALIGNED(7);
+ } else {
+ LOAD_LINE(0);
+ LOAD_LINE(1);
+ LOAD_LINE(2);
+ LOAD_LINE(3);
+ LOAD_LINE(4);
+ LOAD_LINE(5);
+ LOAD_LINE(6);
+ LOAD_LINE(7);
+ }
+#undef LOAD_LINE
+#undef LOAD_LINE_ALIGNED
+
+#define ITER(i, j) \
+ const vector signed short v_diff##i = \
+ vec_sub(v_srcAss##i, v_srcAss##j); \
+ const vector signed short v_sum##i = \
+ vec_add(v_diff##i, v_dcOffset); \
+ const vector signed short v_comp##i = \
+ (vector signed short)vec_cmplt((vector unsigned short)v_sum##i, \
+ v_dcThreshold); \
+ const vector signed short v_part##i = vec_and(mask, v_comp##i); \
+ v_numEq = vec_sum4s(v_part##i, v_numEq);
+
+ ITER(0, 1);
+ ITER(1, 2);
+ ITER(2, 3);
+ ITER(3, 4);
+ ITER(4, 5);
+ ITER(5, 6);
+ ITER(6, 7);
+#undef ITER
+
+ v_numEq = vec_sums(v_numEq, zero);
+
+ v_numEq = vec_splat(v_numEq, 3);
+ vec_ste(v_numEq, 0, &numEq);
+
+ if (numEq > c->ppMode.flatnessThreshold)
+ {
+ const vector unsigned char mmoP1 = (const vector unsigned char)
+ AVV(0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+ 0x00, 0x01, 0x12, 0x13, 0x08, 0x09, 0x1A, 0x1B);
+ const vector unsigned char mmoP2 = (const vector unsigned char)
+ AVV(0x04, 0x05, 0x16, 0x17, 0x0C, 0x0D, 0x1E, 0x1F,
+ 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
+ const vector unsigned char mmoP = (const vector unsigned char)
+ vec_lvsl(8, (unsigned char*)0);
+
+ vector signed short mmoL1 = vec_perm(v_srcAss0, v_srcAss2, mmoP1);
+ vector signed short mmoL2 = vec_perm(v_srcAss4, v_srcAss6, mmoP2);
+ vector signed short mmoL = vec_perm(mmoL1, mmoL2, mmoP);
+ vector signed short mmoR1 = vec_perm(v_srcAss5, v_srcAss7, mmoP1);
+ vector signed short mmoR2 = vec_perm(v_srcAss1, v_srcAss3, mmoP2);
+ vector signed short mmoR = vec_perm(mmoR1, mmoR2, mmoP);
+ vector signed short mmoDiff = vec_sub(mmoL, mmoR);
+ vector unsigned short mmoSum = (vector unsigned short)vec_add(mmoDiff, v2QP);
+
+ if (vec_any_gt(mmoSum, v4QP))
+ return 0;
+ else
+ return 1;
+ }
+ else return 2;
+}
+
+static inline void doVertLowPass_altivec(uint8_t *src, int stride, PPContext *c) {
+ /*
+ this code makes no assumption on src or stride.
+ One could remove the recomputation of the perm
+ vector by assuming (stride % 16) == 0, unfortunately
+ this is not always true. Quite a lot of load/stores
+ can be removed by assuming proper alignement of
+ src & stride :-(
+ */
+ uint8_t *src2 = src;
+ const vector signed int zero = vec_splat_s32(0);
+ const int properStride = (stride % 16);
+ const int srcAlign = ((unsigned long)src2 % 16);
+ short __attribute__ ((aligned(16))) qp[8];
+ qp[0] = c->QP;
+ vector signed short vqp = vec_ld(0, qp);
+ vqp = vec_splat(vqp, 0);
+
+ src2 += stride*3;
+
+ vector signed short vb0, vb1, vb2, vb3, vb4, vb5, vb6, vb7, vb8, vb9;
+ vector unsigned char vbA0, vbA1, vbA2, vbA3, vbA4, vbA5, vbA6, vbA7, vbA8, vbA9;
+ vector unsigned char vbB0, vbB1, vbB2, vbB3, vbB4, vbB5, vbB6, vbB7, vbB8, vbB9;
+ vector unsigned char vbT0, vbT1, vbT2, vbT3, vbT4, vbT5, vbT6, vbT7, vbT8, vbT9;
+
+#define LOAD_LINE(i) \
+ const vector unsigned char perml##i = \
+ vec_lvsl(i * stride, src2); \
+ vbA##i = vec_ld(i * stride, src2); \
+ vbB##i = vec_ld(i * stride + 16, src2); \
+ vbT##i = vec_perm(vbA##i, vbB##i, perml##i); \
+ vb##i = \
+ (vector signed short)vec_mergeh((vector unsigned char)zero, \
+ (vector unsigned char)vbT##i)
+
+#define LOAD_LINE_ALIGNED(i) \
+ register int j##i = i * stride; \
+ vbT##i = vec_ld(j##i, src2); \
+ vb##i = \
+ (vector signed short)vec_mergeh((vector signed char)zero, \
+ (vector signed char)vbT##i)
+
+ // special casing the aligned case is worthwhile, as all call from
+ // the (transposed) horizontable deblocks will be aligned, in addition
+ // to the naturraly aligned vertical deblocks.
+ if (properStride && srcAlign) {
+ LOAD_LINE_ALIGNED(0);
+ LOAD_LINE_ALIGNED(1);
+ LOAD_LINE_ALIGNED(2);
+ LOAD_LINE_ALIGNED(3);
+ LOAD_LINE_ALIGNED(4);
+ LOAD_LINE_ALIGNED(5);
+ LOAD_LINE_ALIGNED(6);
+ LOAD_LINE_ALIGNED(7);
+ LOAD_LINE_ALIGNED(8);
+ LOAD_LINE_ALIGNED(9);
+ } else {
+ LOAD_LINE(0);
+ LOAD_LINE(1);
+ LOAD_LINE(2);
+ LOAD_LINE(3);
+ LOAD_LINE(4);
+ LOAD_LINE(5);
+ LOAD_LINE(6);
+ LOAD_LINE(7);
+ LOAD_LINE(8);
+ LOAD_LINE(9);
+ }
+#undef LOAD_LINE
+#undef LOAD_LINE_ALIGNED
+
+ const vector unsigned short v_2 = vec_splat_u16(2);
+ const vector unsigned short v_4 = vec_splat_u16(4);
+
+ const vector signed short v_diff01 = vec_sub(vb0, vb1);
+ const vector unsigned short v_cmp01 =
+ (const vector unsigned short) vec_cmplt(vec_abs(v_diff01), vqp);
+ const vector signed short v_first = vec_sel(vb1, vb0, v_cmp01);
+ const vector signed short v_diff89 = vec_sub(vb8, vb9);
+ const vector unsigned short v_cmp89 =
+ (const vector unsigned short) vec_cmplt(vec_abs(v_diff89), vqp);
+ const vector signed short v_last = vec_sel(vb8, vb9, v_cmp89);
+
+ const vector signed short temp01 = vec_mladd(v_first, (vector signed short)v_4, vb1);
+ const vector signed short temp02 = vec_add(vb2, vb3);
+ const vector signed short temp03 = vec_add(temp01, (vector signed short)v_4);
+ const vector signed short v_sumsB0 = vec_add(temp02, temp03);
+
+ const vector signed short temp11 = vec_sub(v_sumsB0, v_first);
+ const vector signed short v_sumsB1 = vec_add(temp11, vb4);
+
+ const vector signed short temp21 = vec_sub(v_sumsB1, v_first);
+ const vector signed short v_sumsB2 = vec_add(temp21, vb5);
+
+ const vector signed short temp31 = vec_sub(v_sumsB2, v_first);
+ const vector signed short v_sumsB3 = vec_add(temp31, vb6);
+
+ const vector signed short temp41 = vec_sub(v_sumsB3, v_first);
+ const vector signed short v_sumsB4 = vec_add(temp41, vb7);
+
+ const vector signed short temp51 = vec_sub(v_sumsB4, vb1);
+ const vector signed short v_sumsB5 = vec_add(temp51, vb8);
+
+ const vector signed short temp61 = vec_sub(v_sumsB5, vb2);
+ const vector signed short v_sumsB6 = vec_add(temp61, v_last);
+
+ const vector signed short temp71 = vec_sub(v_sumsB6, vb3);
+ const vector signed short v_sumsB7 = vec_add(temp71, v_last);
+
+ const vector signed short temp81 = vec_sub(v_sumsB7, vb4);
+ const vector signed short v_sumsB8 = vec_add(temp81, v_last);
+
+ const vector signed short temp91 = vec_sub(v_sumsB8, vb5);
+ const vector signed short v_sumsB9 = vec_add(temp91, v_last);
+
+#define COMPUTE_VR(i, j, k) \
+ const vector signed short temps1##i = \
+ vec_add(v_sumsB##i, v_sumsB##k); \
+ const vector signed short temps2##i = \
+ vec_mladd(vb##j, (vector signed short)v_2, temps1##i); \
+ const vector signed short vr##j = vec_sra(temps2##i, v_4)
+
+ COMPUTE_VR(0, 1, 2);
+ COMPUTE_VR(1, 2, 3);
+ COMPUTE_VR(2, 3, 4);
+ COMPUTE_VR(3, 4, 5);
+ COMPUTE_VR(4, 5, 6);
+ COMPUTE_VR(5, 6, 7);
+ COMPUTE_VR(6, 7, 8);
+ COMPUTE_VR(7, 8, 9);
+
+ const vector signed char neg1 = vec_splat_s8(-1);
+ const vector unsigned char permHH = (const vector unsigned char)AVV(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F);
+
+#define PACK_AND_STORE(i) \
+ const vector unsigned char perms##i = \
+ vec_lvsr(i * stride, src2); \
+ const vector unsigned char vf##i = \
+ vec_packsu(vr##i, (vector signed short)zero); \
+ const vector unsigned char vg##i = \
+ vec_perm(vf##i, vbT##i, permHH); \
+ const vector unsigned char mask##i = \
+ vec_perm((vector unsigned char)zero, (vector unsigned char)neg1, perms##i); \
+ const vector unsigned char vg2##i = \
+ vec_perm(vg##i, vg##i, perms##i); \
+ const vector unsigned char svA##i = \
+ vec_sel(vbA##i, vg2##i, mask##i); \
+ const vector unsigned char svB##i = \
+ vec_sel(vg2##i, vbB##i, mask##i); \
+ vec_st(svA##i, i * stride, src2); \
+ vec_st(svB##i, i * stride + 16, src2)
+
+#define PACK_AND_STORE_ALIGNED(i) \
+ const vector unsigned char vf##i = \
+ vec_packsu(vr##i, (vector signed short)zero); \
+ const vector unsigned char vg##i = \
+ vec_perm(vf##i, vbT##i, permHH); \
+ vec_st(vg##i, i * stride, src2)
+
+ // special casing the aligned case is worthwhile, as all call from
+ // the (transposed) horizontable deblocks will be aligned, in addition
+ // to the naturraly aligned vertical deblocks.
+ if (properStride && srcAlign) {
+ PACK_AND_STORE_ALIGNED(1);
+ PACK_AND_STORE_ALIGNED(2);
+ PACK_AND_STORE_ALIGNED(3);
+ PACK_AND_STORE_ALIGNED(4);
+ PACK_AND_STORE_ALIGNED(5);
+ PACK_AND_STORE_ALIGNED(6);
+ PACK_AND_STORE_ALIGNED(7);
+ PACK_AND_STORE_ALIGNED(8);
+ } else {
+ PACK_AND_STORE(1);
+ PACK_AND_STORE(2);
+ PACK_AND_STORE(3);
+ PACK_AND_STORE(4);
+ PACK_AND_STORE(5);
+ PACK_AND_STORE(6);
+ PACK_AND_STORE(7);
+ PACK_AND_STORE(8);
+ }
+#undef PACK_AND_STORE
+#undef PACK_AND_STORE_ALIGNED
+}
+
+
+
+static inline void doVertDefFilter_altivec(uint8_t src[], int stride, PPContext *c) {
+ /*
+ this code makes no assumption on src or stride.
+ One could remove the recomputation of the perm
+ vector by assuming (stride % 16) == 0, unfortunately
+ this is not always true. Quite a lot of load/stores
+ can be removed by assuming proper alignement of
+ src & stride :-(
+ */
+ uint8_t *src2 = src;
+ const vector signed int zero = vec_splat_s32(0);
+ short __attribute__ ((aligned(16))) qp[8];
+ qp[0] = 8*c->QP;
+ vector signed short vqp = vec_ld(0, qp);
+ vqp = vec_splat(vqp, 0);
+
+#define LOAD_LINE(i) \
+ const vector unsigned char perm##i = \
+ vec_lvsl(i * stride, src2); \
+ const vector unsigned char vbA##i = \
+ vec_ld(i * stride, src2); \
+ const vector unsigned char vbB##i = \
+ vec_ld(i * stride + 16, src2); \
+ const vector unsigned char vbT##i = \
+ vec_perm(vbA##i, vbB##i, perm##i); \
+ const vector signed short vb##i = \
+ (vector signed short)vec_mergeh((vector unsigned char)zero, \
+ (vector unsigned char)vbT##i)
+
+ src2 += stride*3;
+
+ LOAD_LINE(1);
+ LOAD_LINE(2);
+ LOAD_LINE(3);
+ LOAD_LINE(4);
+ LOAD_LINE(5);
+ LOAD_LINE(6);
+ LOAD_LINE(7);
+ LOAD_LINE(8);
+#undef LOAD_LINE
+
+ const vector signed short v_1 = vec_splat_s16(1);
+ const vector signed short v_2 = vec_splat_s16(2);
+ const vector signed short v_5 = vec_splat_s16(5);
+ const vector signed short v_32 = vec_sl(v_1,
+ (vector unsigned short)v_5);
+ /* middle energy */
+ const vector signed short l3minusl6 = vec_sub(vb3, vb6);
+ const vector signed short l5minusl4 = vec_sub(vb5, vb4);
+ const vector signed short twotimes_l3minusl6 = vec_mladd(v_2, l3minusl6, (vector signed short)zero);
+ const vector signed short mE = vec_mladd(v_5, l5minusl4, twotimes_l3minusl6);
+ const vector signed short absmE = vec_abs(mE);
+ /* left & right energy */
+ const vector signed short l1minusl4 = vec_sub(vb1, vb4);
+ const vector signed short l3minusl2 = vec_sub(vb3, vb2);
+ const vector signed short l5minusl8 = vec_sub(vb5, vb8);
+ const vector signed short l7minusl6 = vec_sub(vb7, vb6);
+ const vector signed short twotimes_l1minusl4 = vec_mladd(v_2, l1minusl4, (vector signed short)zero);
+ const vector signed short twotimes_l5minusl8 = vec_mladd(v_2, l5minusl8, (vector signed short)zero);
+ const vector signed short lE = vec_mladd(v_5, l3minusl2, twotimes_l1minusl4);
+ const vector signed short rE = vec_mladd(v_5, l7minusl6, twotimes_l5minusl8);
+ /* d */
+ const vector signed short ddiff = vec_sub(absmE,
+ vec_min(vec_abs(lE),
+ vec_abs(rE)));
+ const vector signed short ddiffclamp = vec_max(ddiff, (vector signed short)zero);
+ const vector signed short dtimes64 = vec_mladd(v_5, ddiffclamp, v_32);
+ const vector signed short d = vec_sra(dtimes64, vec_splat_u16(6));
+ const vector signed short minusd = vec_sub((vector signed short)zero, d);
+ const vector signed short finald = vec_sel(minusd,
+ d,
+ vec_cmpgt(vec_sub((vector signed short)zero, mE),
+ (vector signed short)zero));
+ /* q */
+ const vector signed short qtimes2 = vec_sub(vb4, vb5);
+ /* for a shift right to behave like /2, we need to add one
+ to all negative integer */
+ const vector signed short rounddown = vec_sel((vector signed short)zero,
+ v_1,
+ vec_cmplt(qtimes2, (vector signed short)zero));
+ const vector signed short q = vec_sra(vec_add(qtimes2, rounddown), vec_splat_u16(1));
+ /* clamp */
+ const vector signed short dclamp_P1 = vec_max((vector signed short)zero, finald);
+ const vector signed short dclamp_P = vec_min(dclamp_P1, q);
+ const vector signed short dclamp_N1 = vec_min((vector signed short)zero, finald);
+ const vector signed short dclamp_N = vec_max(dclamp_N1, q);
+
+ const vector signed short dclampedfinal = vec_sel(dclamp_N,
+ dclamp_P,
+ vec_cmpgt(q, (vector signed short)zero));
+ const vector signed short dornotd = vec_sel((vector signed short)zero,
+ dclampedfinal,
+ vec_cmplt(absmE, vqp));
+ /* add/substract to l4 and l5 */
+ const vector signed short vb4minusd = vec_sub(vb4, dornotd);
+ const vector signed short vb5plusd = vec_add(vb5, dornotd);
+ /* finally, stores */
+ const vector unsigned char st4 = vec_packsu(vb4minusd, (vector signed short)zero);
+ const vector unsigned char st5 = vec_packsu(vb5plusd, (vector signed short)zero);
+
+ const vector signed char neg1 = vec_splat_s8(-1);
+ const vector unsigned char permHH = (const vector unsigned char)AVV(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F);
+
+#define STORE(i) \
+ const vector unsigned char perms##i = \
+ vec_lvsr(i * stride, src2); \
+ const vector unsigned char vg##i = \
+ vec_perm(st##i, vbT##i, permHH); \
+ const vector unsigned char mask##i = \
+ vec_perm((vector unsigned char)zero, (vector unsigned char)neg1, perms##i); \
+ const vector unsigned char vg2##i = \
+ vec_perm(vg##i, vg##i, perms##i); \
+ const vector unsigned char svA##i = \
+ vec_sel(vbA##i, vg2##i, mask##i); \
+ const vector unsigned char svB##i = \
+ vec_sel(vg2##i, vbB##i, mask##i); \
+ vec_st(svA##i, i * stride, src2); \
+ vec_st(svB##i, i * stride + 16, src2)
+
+ STORE(4);
+ STORE(5);
+}
+
+static inline void dering_altivec(uint8_t src[], int stride, PPContext *c) {
+ /*
+ this code makes no assumption on src or stride.
+ One could remove the recomputation of the perm
+ vector by assuming (stride % 16) == 0, unfortunately
+ this is not always true. Quite a lot of load/stores
+ can be removed by assuming proper alignement of
+ src & stride :-(
+ */
+ uint8_t *srcCopy = src;
+ uint8_t __attribute__((aligned(16))) dt[16];
+ const vector signed int zero = vec_splat_s32(0);
+ vector unsigned char v_dt;
+ dt[0] = deringThreshold;
+ v_dt = vec_splat(vec_ld(0, dt), 0);
+
+#define LOAD_LINE(i) \
+ const vector unsigned char perm##i = \
+ vec_lvsl(i * stride, srcCopy); \
+ vector unsigned char sA##i = vec_ld(i * stride, srcCopy); \
+ vector unsigned char sB##i = vec_ld(i * stride + 16, srcCopy); \
+ vector unsigned char src##i = vec_perm(sA##i, sB##i, perm##i)
+
+ LOAD_LINE(0);
+ LOAD_LINE(1);
+ LOAD_LINE(2);
+ LOAD_LINE(3);
+ LOAD_LINE(4);
+ LOAD_LINE(5);
+ LOAD_LINE(6);
+ LOAD_LINE(7);
+ LOAD_LINE(8);
+ LOAD_LINE(9);
+#undef LOAD_LINE
+
+ vector unsigned char v_avg;
+ {
+ const vector unsigned char trunc_perm = (vector unsigned char)
+ AVV(0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18);
+ const vector unsigned char trunc_src12 = vec_perm(src1, src2, trunc_perm);
+ const vector unsigned char trunc_src34 = vec_perm(src3, src4, trunc_perm);
+ const vector unsigned char trunc_src56 = vec_perm(src5, src6, trunc_perm);
+ const vector unsigned char trunc_src78 = vec_perm(src7, src8, trunc_perm);
+
+#define EXTRACT(op) do { \
+ const vector unsigned char s##op##_1 = vec_##op(trunc_src12, trunc_src34); \
+ const vector unsigned char s##op##_2 = vec_##op(trunc_src56, trunc_src78); \
+ const vector unsigned char s##op##_6 = vec_##op(s##op##_1, s##op##_2); \
+ const vector unsigned char s##op##_8h = vec_mergeh(s##op##_6, s##op##_6); \
+ const vector unsigned char s##op##_8l = vec_mergel(s##op##_6, s##op##_6); \
+ const vector unsigned char s##op##_9 = vec_##op(s##op##_8h, s##op##_8l); \
+ const vector unsigned char s##op##_9h = vec_mergeh(s##op##_9, s##op##_9); \
+ const vector unsigned char s##op##_9l = vec_mergel(s##op##_9, s##op##_9); \
+ const vector unsigned char s##op##_10 = vec_##op(s##op##_9h, s##op##_9l); \
+ const vector unsigned char s##op##_10h = vec_mergeh(s##op##_10, s##op##_10); \
+ const vector unsigned char s##op##_10l = vec_mergel(s##op##_10, s##op##_10); \
+ const vector unsigned char s##op##_11 = vec_##op(s##op##_10h, s##op##_10l); \
+ const vector unsigned char s##op##_11h = vec_mergeh(s##op##_11, s##op##_11); \
+ const vector unsigned char s##op##_11l = vec_mergel(s##op##_11, s##op##_11); \
+ v_##op = vec_##op(s##op##_11h, s##op##_11l); } while (0)
+
+ vector unsigned char v_min;
+ vector unsigned char v_max;
+ EXTRACT(min);
+ EXTRACT(max);
+#undef EXTRACT
+
+ if (vec_all_lt(vec_sub(v_max, v_min), v_dt))
+ return;
+
+ v_avg = vec_avg(v_min, v_max);
+ }
+
+ signed int __attribute__((aligned(16))) S[8];
+ {
+ const vector unsigned short mask1 = (vector unsigned short)
+ AVV(0x0001, 0x0002, 0x0004, 0x0008,
+ 0x0010, 0x0020, 0x0040, 0x0080);
+ const vector unsigned short mask2 = (vector unsigned short)
+ AVV(0x0100, 0x0200, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000);
+
+ const vector unsigned int vuint32_16 = vec_sl(vec_splat_u32(1), vec_splat_u32(4));
+ const vector unsigned int vuint32_1 = vec_splat_u32(1);
+
+#define COMPARE(i) \
+ vector signed int sum##i; \
+ do { \
+ const vector unsigned char cmp##i = \
+ (vector unsigned char)vec_cmpgt(src##i, v_avg); \
+ const vector unsigned short cmpHi##i = \
+ (vector unsigned short)vec_mergeh(cmp##i, cmp##i); \
+ const vector unsigned short cmpLi##i = \
+ (vector unsigned short)vec_mergel(cmp##i, cmp##i); \
+ const vector signed short cmpHf##i = \
+ (vector signed short)vec_and(cmpHi##i, mask1); \
+ const vector signed short cmpLf##i = \
+ (vector signed short)vec_and(cmpLi##i, mask2); \
+ const vector signed int sump##i = vec_sum4s(cmpHf##i, zero); \
+ const vector signed int sumq##i = vec_sum4s(cmpLf##i, sump##i); \
+ sum##i = vec_sums(sumq##i, zero); } while (0)
+
+ COMPARE(0);
+ COMPARE(1);
+ COMPARE(2);
+ COMPARE(3);
+ COMPARE(4);
+ COMPARE(5);
+ COMPARE(6);
+ COMPARE(7);
+ COMPARE(8);
+ COMPARE(9);
+#undef COMPARE
+
+ vector signed int sumA2;
+ vector signed int sumB2;
+ {
+ const vector signed int sump02 = vec_mergel(sum0, sum2);
+ const vector signed int sump13 = vec_mergel(sum1, sum3);
+ const vector signed int sumA = vec_mergel(sump02, sump13);
+
+ const vector signed int sump46 = vec_mergel(sum4, sum6);
+ const vector signed int sump57 = vec_mergel(sum5, sum7);
+ const vector signed int sumB = vec_mergel(sump46, sump57);
+
+ const vector signed int sump8A = vec_mergel(sum8, zero);
+ const vector signed int sump9B = vec_mergel(sum9, zero);
+ const vector signed int sumC = vec_mergel(sump8A, sump9B);
+
+ const vector signed int tA = vec_sl(vec_nor(zero, sumA), vuint32_16);
+ const vector signed int tB = vec_sl(vec_nor(zero, sumB), vuint32_16);
+ const vector signed int tC = vec_sl(vec_nor(zero, sumC), vuint32_16);
+ const vector signed int t2A = vec_or(sumA, tA);
+ const vector signed int t2B = vec_or(sumB, tB);
+ const vector signed int t2C = vec_or(sumC, tC);
+ const vector signed int t3A = vec_and(vec_sra(t2A, vuint32_1),
+ vec_sl(t2A, vuint32_1));
+ const vector signed int t3B = vec_and(vec_sra(t2B, vuint32_1),
+ vec_sl(t2B, vuint32_1));
+ const vector signed int t3C = vec_and(vec_sra(t2C, vuint32_1),
+ vec_sl(t2C, vuint32_1));
+ const vector signed int yA = vec_and(t2A, t3A);
+ const vector signed int yB = vec_and(t2B, t3B);
+ const vector signed int yC = vec_and(t2C, t3C);
+
+ const vector unsigned char strangeperm1 = vec_lvsl(4, (unsigned char*)0);
+ const vector unsigned char strangeperm2 = vec_lvsl(8, (unsigned char*)0);
+ const vector signed int sumAd4 = vec_perm(yA, yB, strangeperm1);
+ const vector signed int sumAd8 = vec_perm(yA, yB, strangeperm2);
+ const vector signed int sumBd4 = vec_perm(yB, yC, strangeperm1);
+ const vector signed int sumBd8 = vec_perm(yB, yC, strangeperm2);
+ const vector signed int sumAp = vec_and(yA,
+ vec_and(sumAd4,sumAd8));
+ const vector signed int sumBp = vec_and(yB,
+ vec_and(sumBd4,sumBd8));
+ sumA2 = vec_or(sumAp,
+ vec_sra(sumAp,
+ vuint32_16));
+ sumB2 = vec_or(sumBp,
+ vec_sra(sumBp,
+ vuint32_16));
+ }
+ vec_st(sumA2, 0, S);
+ vec_st(sumB2, 16, S);
+ }
+
+ /* I'm not sure the following is actually faster
+ than straight, unvectorized C code :-( */
+
+ int __attribute__((aligned(16))) tQP2[4];
+ tQP2[0]= c->QP/2 + 1;
+ vector signed int vQP2 = vec_ld(0, tQP2);
+ vQP2 = vec_splat(vQP2, 0);
+ const vector signed int vsint32_8 = vec_splat_s32(8);
+ const vector unsigned int vuint32_4 = vec_splat_u32(4);
+
+ const vector unsigned char permA1 = (vector unsigned char)
+ AVV(0x00, 0x01, 0x02, 0x10, 0x11, 0x12, 0x1F, 0x1F,
+ 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F);
+ const vector unsigned char permA2 = (vector unsigned char)
+ AVV(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x10, 0x11,
+ 0x12, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F);
+ const vector unsigned char permA1inc = (vector unsigned char)
+ AVV(0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ const vector unsigned char permA2inc = (vector unsigned char)
+ AVV(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ const vector unsigned char magic = (vector unsigned char)
+ AVV(0x01, 0x02, 0x01, 0x02, 0x04, 0x02, 0x01, 0x02,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ const vector unsigned char extractPerm = (vector unsigned char)
+ AVV(0x10, 0x10, 0x10, 0x01, 0x10, 0x10, 0x10, 0x01,
+ 0x10, 0x10, 0x10, 0x01, 0x10, 0x10, 0x10, 0x01);
+ const vector unsigned char extractPermInc = (vector unsigned char)
+ AVV(0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01);
+ const vector unsigned char identity = vec_lvsl(0,(unsigned char *)0);
+ const vector unsigned char tenRight = (vector unsigned char)
+ AVV(0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ const vector unsigned char eightLeft = (vector unsigned char)
+ AVV(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08);
+
+
+#define F_INIT(i) \
+ vector unsigned char tenRightM##i = tenRight; \
+ vector unsigned char permA1M##i = permA1; \
+ vector unsigned char permA2M##i = permA2; \
+ vector unsigned char extractPermM##i = extractPerm
+
+#define F2(i, j, k, l) \
+ if (S[i] & (1 << (l+1))) { \
+ const vector unsigned char a_##j##_A##l = \
+ vec_perm(src##i, src##j, permA1M##i); \
+ const vector unsigned char a_##j##_B##l = \
+ vec_perm(a_##j##_A##l, src##k, permA2M##i); \
+ const vector signed int a_##j##_sump##l = \
+ (vector signed int)vec_msum(a_##j##_B##l, magic, \
+ (vector unsigned int)zero); \
+ vector signed int F_##j##_##l = \
+ vec_sr(vec_sums(a_##j##_sump##l, vsint32_8), vuint32_4); \
+ F_##j##_##l = vec_splat(F_##j##_##l, 3); \
+ const vector signed int p_##j##_##l = \
+ (vector signed int)vec_perm(src##j, \
+ (vector unsigned char)zero, \
+ extractPermM##i); \
+ const vector signed int sum_##j##_##l = vec_add( p_##j##_##l, vQP2);\
+ const vector signed int diff_##j##_##l = vec_sub( p_##j##_##l, vQP2);\
+ vector signed int newpm_##j##_##l; \
+ if (vec_all_lt(sum_##j##_##l, F_##j##_##l)) \
+ newpm_##j##_##l = sum_##j##_##l; \
+ else if (vec_all_gt(diff_##j##_##l, F_##j##_##l)) \
+ newpm_##j##_##l = diff_##j##_##l; \
+ else newpm_##j##_##l = F_##j##_##l; \
+ const vector unsigned char newpm2_##j##_##l = \
+ vec_splat((vector unsigned char)newpm_##j##_##l, 15); \
+ const vector unsigned char mask##j##l = vec_add(identity, \
+ tenRightM##i); \
+ src##j = vec_perm(src##j, newpm2_##j##_##l, mask##j##l); \
+ } \
+ permA1M##i = vec_add(permA1M##i, permA1inc); \
+ permA2M##i = vec_add(permA2M##i, permA2inc); \
+ tenRightM##i = vec_sro(tenRightM##i, eightLeft); \
+ extractPermM##i = vec_add(extractPermM##i, extractPermInc)
+
+#define ITER(i, j, k) \
+ F_INIT(i); \
+ F2(i, j, k, 0); \
+ F2(i, j, k, 1); \
+ F2(i, j, k, 2); \
+ F2(i, j, k, 3); \
+ F2(i, j, k, 4); \
+ F2(i, j, k, 5); \
+ F2(i, j, k, 6); \
+ F2(i, j, k, 7)
+
+ ITER(0, 1, 2);
+ ITER(1, 2, 3);
+ ITER(2, 3, 4);
+ ITER(3, 4, 5);
+ ITER(4, 5, 6);
+ ITER(5, 6, 7);
+ ITER(6, 7, 8);
+ ITER(7, 8, 9);
+
+ const vector signed char neg1 = vec_splat_s8(-1);
+
+#define STORE_LINE(i) \
+ const vector unsigned char permST##i = \
+ vec_lvsr(i * stride, srcCopy); \
+ const vector unsigned char maskST##i = \
+ vec_perm((vector unsigned char)zero, \
+ (vector unsigned char)neg1, permST##i); \
+ src##i = vec_perm(src##i ,src##i, permST##i); \
+ sA##i= vec_sel(sA##i, src##i, maskST##i); \
+ sB##i= vec_sel(src##i, sB##i, maskST##i); \
+ vec_st(sA##i, i * stride, srcCopy); \
+ vec_st(sB##i, i * stride + 16, srcCopy)
+
+ STORE_LINE(1);
+ STORE_LINE(2);
+ STORE_LINE(3);
+ STORE_LINE(4);
+ STORE_LINE(5);
+ STORE_LINE(6);
+ STORE_LINE(7);
+ STORE_LINE(8);
+
+#undef STORE_LINE
+#undef ITER
+#undef F2
+}
+
+#define doHorizLowPass_altivec(a...) doHorizLowPass_C(a)
+#define doHorizDefFilter_altivec(a...) doHorizDefFilter_C(a)
+#define do_a_deblock_altivec(a...) do_a_deblock_C(a)
+
+static inline void RENAME(tempNoiseReducer)(uint8_t *src, int stride,
+ uint8_t *tempBlured, uint32_t *tempBluredPast, int *maxNoise)
+{
+ const vector signed int zero = vec_splat_s32(0);
+ const vector signed short vsint16_1 = vec_splat_s16(1);
+ vector signed int v_dp = zero;
+ vector signed int v_sysdp = zero;
+ int d, sysd, i;
+
+ tempBluredPast[127]= maxNoise[0];
+ tempBluredPast[128]= maxNoise[1];
+ tempBluredPast[129]= maxNoise[2];
+
+#define LOAD_LINE(src, i) \
+ register int j##src##i = i * stride; \
+ vector unsigned char perm##src##i = vec_lvsl(j##src##i, src); \
+ const vector unsigned char v_##src##A1##i = vec_ld(j##src##i, src); \
+ const vector unsigned char v_##src##A2##i = vec_ld(j##src##i + 16, src); \
+ const vector unsigned char v_##src##A##i = \
+ vec_perm(v_##src##A1##i, v_##src##A2##i, perm##src##i); \
+ vector signed short v_##src##Ass##i = \
+ (vector signed short)vec_mergeh((vector signed char)zero, \
+ (vector signed char)v_##src##A##i)
+
+ LOAD_LINE(src, 0);
+ LOAD_LINE(src, 1);
+ LOAD_LINE(src, 2);
+ LOAD_LINE(src, 3);
+ LOAD_LINE(src, 4);
+ LOAD_LINE(src, 5);
+ LOAD_LINE(src, 6);
+ LOAD_LINE(src, 7);
+
+ LOAD_LINE(tempBlured, 0);
+ LOAD_LINE(tempBlured, 1);
+ LOAD_LINE(tempBlured, 2);
+ LOAD_LINE(tempBlured, 3);
+ LOAD_LINE(tempBlured, 4);
+ LOAD_LINE(tempBlured, 5);
+ LOAD_LINE(tempBlured, 6);
+ LOAD_LINE(tempBlured, 7);
+#undef LOAD_LINE
+
+#define ACCUMULATE_DIFFS(i) \
+ vector signed short v_d##i = vec_sub(v_tempBluredAss##i, \
+ v_srcAss##i); \
+ v_dp = vec_msums(v_d##i, v_d##i, v_dp); \
+ v_sysdp = vec_msums(v_d##i, vsint16_1, v_sysdp)
+
+ ACCUMULATE_DIFFS(0);
+ ACCUMULATE_DIFFS(1);
+ ACCUMULATE_DIFFS(2);
+ ACCUMULATE_DIFFS(3);
+ ACCUMULATE_DIFFS(4);
+ ACCUMULATE_DIFFS(5);
+ ACCUMULATE_DIFFS(6);
+ ACCUMULATE_DIFFS(7);
+#undef ACCUMULATE_DIFFS
+
+ v_dp = vec_sums(v_dp, zero);
+ v_sysdp = vec_sums(v_sysdp, zero);
+
+ v_dp = vec_splat(v_dp, 3);
+ v_sysdp = vec_splat(v_sysdp, 3);
+
+ vec_ste(v_dp, 0, &d);
+ vec_ste(v_sysdp, 0, &sysd);
+
+ i = d;
+ d = (4*d
+ +(*(tempBluredPast-256))
+ +(*(tempBluredPast-1))+ (*(tempBluredPast+1))
+ +(*(tempBluredPast+256))
+ +4)>>3;
+
+ *tempBluredPast=i;
+
+ if (d > maxNoise[1]) {
+ if (d < maxNoise[2]) {
+#define OP(i) v_tempBluredAss##i = vec_avg(v_tempBluredAss##i, v_srcAss##i);
+
+ OP(0);
+ OP(1);
+ OP(2);
+ OP(3);
+ OP(4);
+ OP(5);
+ OP(6);
+ OP(7);
+#undef OP
+ } else {
+#define OP(i) v_tempBluredAss##i = v_srcAss##i;
+
+ OP(0);
+ OP(1);
+ OP(2);
+ OP(3);
+ OP(4);
+ OP(5);
+ OP(6);
+ OP(7);
+#undef OP
+ }
+ } else {
+ if (d < maxNoise[0]) {
+ const vector signed short vsint16_7 = vec_splat_s16(7);
+ const vector signed short vsint16_4 = vec_splat_s16(4);
+ const vector unsigned short vuint16_3 = vec_splat_u16(3);
+
+#define OP(i) \
+ const vector signed short v_temp##i = \
+ vec_mladd(v_tempBluredAss##i, \
+ vsint16_7, v_srcAss##i); \
+ const vector signed short v_temp2##i = \
+ vec_add(v_temp##i, vsint16_4); \
+ v_tempBluredAss##i = vec_sr(v_temp2##i, vuint16_3)
+
+ OP(0);
+ OP(1);
+ OP(2);
+ OP(3);
+ OP(4);
+ OP(5);
+ OP(6);
+ OP(7);
+#undef OP
+ } else {
+ const vector signed short vsint16_3 = vec_splat_s16(3);
+ const vector signed short vsint16_2 = vec_splat_s16(2);
+
+#define OP(i) \
+ const vector signed short v_temp##i = \
+ vec_mladd(v_tempBluredAss##i, \
+ vsint16_3, v_srcAss##i); \
+ const vector signed short v_temp2##i = \
+ vec_add(v_temp##i, vsint16_2); \
+ v_tempBluredAss##i = vec_sr(v_temp2##i, (vector unsigned short)vsint16_2)
+
+ OP(0);
+ OP(1);
+ OP(2);
+ OP(3);
+ OP(4);
+ OP(5);
+ OP(6);
+ OP(7);
+#undef OP
+ }
+ }
+
+ const vector signed char neg1 = vec_splat_s8(-1);
+ const vector unsigned char permHH = (const vector unsigned char)AVV(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F);
+
+#define PACK_AND_STORE(src, i) \
+ const vector unsigned char perms##src##i = \
+ vec_lvsr(i * stride, src); \
+ const vector unsigned char vf##src##i = \
+ vec_packsu(v_tempBluredAss##i, (vector signed short)zero); \
+ const vector unsigned char vg##src##i = \
+ vec_perm(vf##src##i, v_##src##A##i, permHH); \
+ const vector unsigned char mask##src##i = \
+ vec_perm((vector unsigned char)zero, (vector unsigned char)neg1, perms##src##i); \
+ const vector unsigned char vg2##src##i = \
+ vec_perm(vg##src##i, vg##src##i, perms##src##i); \
+ const vector unsigned char svA##src##i = \
+ vec_sel(v_##src##A1##i, vg2##src##i, mask##src##i); \
+ const vector unsigned char svB##src##i = \
+ vec_sel(vg2##src##i, v_##src##A2##i, mask##src##i); \
+ vec_st(svA##src##i, i * stride, src); \
+ vec_st(svB##src##i, i * stride + 16, src)
+
+ PACK_AND_STORE(src, 0);
+ PACK_AND_STORE(src, 1);
+ PACK_AND_STORE(src, 2);
+ PACK_AND_STORE(src, 3);
+ PACK_AND_STORE(src, 4);
+ PACK_AND_STORE(src, 5);
+ PACK_AND_STORE(src, 6);
+ PACK_AND_STORE(src, 7);
+ PACK_AND_STORE(tempBlured, 0);
+ PACK_AND_STORE(tempBlured, 1);
+ PACK_AND_STORE(tempBlured, 2);
+ PACK_AND_STORE(tempBlured, 3);
+ PACK_AND_STORE(tempBlured, 4);
+ PACK_AND_STORE(tempBlured, 5);
+ PACK_AND_STORE(tempBlured, 6);
+ PACK_AND_STORE(tempBlured, 7);
+#undef PACK_AND_STORE
+}
+
+static inline void transpose_16x8_char_toPackedAlign_altivec(unsigned char* dst, unsigned char* src, int stride) {
+ const vector unsigned char zero = vec_splat_u8(0);
+
+#define LOAD_DOUBLE_LINE(i, j) \
+ vector unsigned char perm1##i = vec_lvsl(i * stride, src); \
+ vector unsigned char perm2##i = vec_lvsl(j * stride, src); \
+ vector unsigned char srcA##i = vec_ld(i * stride, src); \
+ vector unsigned char srcB##i = vec_ld(i * stride + 16, src); \
+ vector unsigned char srcC##i = vec_ld(j * stride, src); \
+ vector unsigned char srcD##i = vec_ld(j * stride+ 16, src); \
+ vector unsigned char src##i = vec_perm(srcA##i, srcB##i, perm1##i); \
+ vector unsigned char src##j = vec_perm(srcC##i, srcD##i, perm2##i)
+
+ LOAD_DOUBLE_LINE(0, 1);
+ LOAD_DOUBLE_LINE(2, 3);
+ LOAD_DOUBLE_LINE(4, 5);
+ LOAD_DOUBLE_LINE(6, 7);
+#undef LOAD_DOUBLE_LINE
+
+ vector unsigned char tempA = vec_mergeh(src0, zero);
+ vector unsigned char tempB = vec_mergel(src0, zero);
+ vector unsigned char tempC = vec_mergeh(src1, zero);
+ vector unsigned char tempD = vec_mergel(src1, zero);
+ vector unsigned char tempE = vec_mergeh(src2, zero);
+ vector unsigned char tempF = vec_mergel(src2, zero);
+ vector unsigned char tempG = vec_mergeh(src3, zero);
+ vector unsigned char tempH = vec_mergel(src3, zero);
+ vector unsigned char tempI = vec_mergeh(src4, zero);
+ vector unsigned char tempJ = vec_mergel(src4, zero);
+ vector unsigned char tempK = vec_mergeh(src5, zero);
+ vector unsigned char tempL = vec_mergel(src5, zero);
+ vector unsigned char tempM = vec_mergeh(src6, zero);
+ vector unsigned char tempN = vec_mergel(src6, zero);
+ vector unsigned char tempO = vec_mergeh(src7, zero);
+ vector unsigned char tempP = vec_mergel(src7, zero);
+
+ vector unsigned char temp0 = vec_mergeh(tempA, tempI);
+ vector unsigned char temp1 = vec_mergel(tempA, tempI);
+ vector unsigned char temp2 = vec_mergeh(tempB, tempJ);
+ vector unsigned char temp3 = vec_mergel(tempB, tempJ);
+ vector unsigned char temp4 = vec_mergeh(tempC, tempK);
+ vector unsigned char temp5 = vec_mergel(tempC, tempK);
+ vector unsigned char temp6 = vec_mergeh(tempD, tempL);
+ vector unsigned char temp7 = vec_mergel(tempD, tempL);
+ vector unsigned char temp8 = vec_mergeh(tempE, tempM);
+ vector unsigned char temp9 = vec_mergel(tempE, tempM);
+ vector unsigned char temp10 = vec_mergeh(tempF, tempN);
+ vector unsigned char temp11 = vec_mergel(tempF, tempN);
+ vector unsigned char temp12 = vec_mergeh(tempG, tempO);
+ vector unsigned char temp13 = vec_mergel(tempG, tempO);
+ vector unsigned char temp14 = vec_mergeh(tempH, tempP);
+ vector unsigned char temp15 = vec_mergel(tempH, tempP);
+
+ tempA = vec_mergeh(temp0, temp8);
+ tempB = vec_mergel(temp0, temp8);
+ tempC = vec_mergeh(temp1, temp9);
+ tempD = vec_mergel(temp1, temp9);
+ tempE = vec_mergeh(temp2, temp10);
+ tempF = vec_mergel(temp2, temp10);
+ tempG = vec_mergeh(temp3, temp11);
+ tempH = vec_mergel(temp3, temp11);
+ tempI = vec_mergeh(temp4, temp12);
+ tempJ = vec_mergel(temp4, temp12);
+ tempK = vec_mergeh(temp5, temp13);
+ tempL = vec_mergel(temp5, temp13);
+ tempM = vec_mergeh(temp6, temp14);
+ tempN = vec_mergel(temp6, temp14);
+ tempO = vec_mergeh(temp7, temp15);
+ tempP = vec_mergel(temp7, temp15);
+
+ temp0 = vec_mergeh(tempA, tempI);
+ temp1 = vec_mergel(tempA, tempI);
+ temp2 = vec_mergeh(tempB, tempJ);
+ temp3 = vec_mergel(tempB, tempJ);
+ temp4 = vec_mergeh(tempC, tempK);
+ temp5 = vec_mergel(tempC, tempK);
+ temp6 = vec_mergeh(tempD, tempL);
+ temp7 = vec_mergel(tempD, tempL);
+ temp8 = vec_mergeh(tempE, tempM);
+ temp9 = vec_mergel(tempE, tempM);
+ temp10 = vec_mergeh(tempF, tempN);
+ temp11 = vec_mergel(tempF, tempN);
+ temp12 = vec_mergeh(tempG, tempO);
+ temp13 = vec_mergel(tempG, tempO);
+ temp14 = vec_mergeh(tempH, tempP);
+ temp15 = vec_mergel(tempH, tempP);
+
+ vec_st(temp0, 0, dst);
+ vec_st(temp1, 16, dst);
+ vec_st(temp2, 32, dst);
+ vec_st(temp3, 48, dst);
+ vec_st(temp4, 64, dst);
+ vec_st(temp5, 80, dst);
+ vec_st(temp6, 96, dst);
+ vec_st(temp7, 112, dst);
+ vec_st(temp8, 128, dst);
+ vec_st(temp9, 144, dst);
+ vec_st(temp10, 160, dst);
+ vec_st(temp11, 176, dst);
+ vec_st(temp12, 192, dst);
+ vec_st(temp13, 208, dst);
+ vec_st(temp14, 224, dst);
+ vec_st(temp15, 240, dst);
+}
+
+static inline void transpose_8x16_char_fromPackedAlign_altivec(unsigned char* dst, unsigned char* src, int stride) {
+ const vector unsigned char zero = vec_splat_u8(0);
+
+#define LOAD_DOUBLE_LINE(i, j) \
+ vector unsigned char src##i = vec_ld(i * 16, src); \
+ vector unsigned char src##j = vec_ld(j * 16, src)
+
+ LOAD_DOUBLE_LINE(0, 1);
+ LOAD_DOUBLE_LINE(2, 3);
+ LOAD_DOUBLE_LINE(4, 5);
+ LOAD_DOUBLE_LINE(6, 7);
+ LOAD_DOUBLE_LINE(8, 9);
+ LOAD_DOUBLE_LINE(10, 11);
+ LOAD_DOUBLE_LINE(12, 13);
+ LOAD_DOUBLE_LINE(14, 15);
+#undef LOAD_DOUBLE_LINE
+
+ vector unsigned char tempA = vec_mergeh(src0, src8);
+ vector unsigned char tempB;
+ vector unsigned char tempC = vec_mergeh(src1, src9);
+ vector unsigned char tempD;
+ vector unsigned char tempE = vec_mergeh(src2, src10);
+ vector unsigned char tempG = vec_mergeh(src3, src11);
+ vector unsigned char tempI = vec_mergeh(src4, src12);
+ vector unsigned char tempJ;
+ vector unsigned char tempK = vec_mergeh(src5, src13);
+ vector unsigned char tempL;
+ vector unsigned char tempM = vec_mergeh(src6, src14);
+ vector unsigned char tempO = vec_mergeh(src7, src15);
+
+ vector unsigned char temp0 = vec_mergeh(tempA, tempI);
+ vector unsigned char temp1 = vec_mergel(tempA, tempI);
+ vector unsigned char temp2;
+ vector unsigned char temp3;
+ vector unsigned char temp4 = vec_mergeh(tempC, tempK);
+ vector unsigned char temp5 = vec_mergel(tempC, tempK);
+ vector unsigned char temp6;
+ vector unsigned char temp7;
+ vector unsigned char temp8 = vec_mergeh(tempE, tempM);
+ vector unsigned char temp9 = vec_mergel(tempE, tempM);
+ vector unsigned char temp12 = vec_mergeh(tempG, tempO);
+ vector unsigned char temp13 = vec_mergel(tempG, tempO);
+
+ tempA = vec_mergeh(temp0, temp8);
+ tempB = vec_mergel(temp0, temp8);
+ tempC = vec_mergeh(temp1, temp9);
+ tempD = vec_mergel(temp1, temp9);
+ tempI = vec_mergeh(temp4, temp12);
+ tempJ = vec_mergel(temp4, temp12);
+ tempK = vec_mergeh(temp5, temp13);
+ tempL = vec_mergel(temp5, temp13);
+
+ temp0 = vec_mergeh(tempA, tempI);
+ temp1 = vec_mergel(tempA, tempI);
+ temp2 = vec_mergeh(tempB, tempJ);
+ temp3 = vec_mergel(tempB, tempJ);
+ temp4 = vec_mergeh(tempC, tempK);
+ temp5 = vec_mergel(tempC, tempK);
+ temp6 = vec_mergeh(tempD, tempL);
+ temp7 = vec_mergel(tempD, tempL);
+
+
+ const vector signed char neg1 = vec_splat_s8(-1);
+#define STORE_DOUBLE_LINE(i, j) \
+ vector unsigned char dstA##i = vec_ld(i * stride, dst); \
+ vector unsigned char dstB##i = vec_ld(i * stride + 16, dst); \
+ vector unsigned char dstA##j = vec_ld(j * stride, dst); \
+ vector unsigned char dstB##j = vec_ld(j * stride+ 16, dst); \
+ vector unsigned char align##i = vec_lvsr(i * stride, dst); \
+ vector unsigned char align##j = vec_lvsr(j * stride, dst); \
+ vector unsigned char mask##i = vec_perm(zero, (vector unsigned char)neg1, align##i); \
+ vector unsigned char mask##j = vec_perm(zero, (vector unsigned char)neg1, align##j); \
+ vector unsigned char dstR##i = vec_perm(temp##i, temp##i, align##i); \
+ vector unsigned char dstR##j = vec_perm(temp##j, temp##j, align##j); \
+ vector unsigned char dstAF##i = vec_sel(dstA##i, dstR##i, mask##i); \
+ vector unsigned char dstBF##i = vec_sel(dstR##i, dstB##i, mask##i); \
+ vector unsigned char dstAF##j = vec_sel(dstA##j, dstR##j, mask##j); \
+ vector unsigned char dstBF##j = vec_sel(dstR##j, dstB##j, mask##j); \
+ vec_st(dstAF##i, i * stride, dst); \
+ vec_st(dstBF##i, i * stride + 16, dst); \
+ vec_st(dstAF##j, j * stride, dst); \
+ vec_st(dstBF##j, j * stride + 16, dst)
+
+ STORE_DOUBLE_LINE(0,1);
+ STORE_DOUBLE_LINE(2,3);
+ STORE_DOUBLE_LINE(4,5);
+ STORE_DOUBLE_LINE(6,7);
+}
diff --git a/contrib/ffmpeg/libpostproc/postprocess_internal.h b/contrib/ffmpeg/libpostproc/postprocess_internal.h
new file mode 100644
index 000000000..537d728c0
--- /dev/null
+++ b/contrib/ffmpeg/libpostproc/postprocess_internal.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2001-2002 Michael Niedermayer (michaelni@gmx.at)
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that 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 postprocess_internal.h
+ * internal api header.
+ */
+
+#include "avutil.h"
+
+#define V_DEBLOCK 0x01
+#define H_DEBLOCK 0x02
+#define DERING 0x04
+#define LEVEL_FIX 0x08 ///< Brightness & Contrast
+
+#define LUM_V_DEBLOCK V_DEBLOCK // 1
+#define LUM_H_DEBLOCK H_DEBLOCK // 2
+#define CHROM_V_DEBLOCK (V_DEBLOCK<<4) // 16
+#define CHROM_H_DEBLOCK (H_DEBLOCK<<4) // 32
+#define LUM_DERING DERING // 4
+#define CHROM_DERING (DERING<<4) // 64
+#define LUM_LEVEL_FIX LEVEL_FIX // 8
+#define CHROM_LEVEL_FIX (LEVEL_FIX<<4) // 128 (not implemented yet)
+
+// Experimental vertical filters
+#define V_X1_FILTER 0x0200 // 512
+#define V_A_DEBLOCK 0x0400
+
+// Experimental horizontal filters
+#define H_X1_FILTER 0x2000 // 8192
+#define H_A_DEBLOCK 0x4000
+
+/// select between full y range (255-0) or standart one (234-16)
+#define FULL_Y_RANGE 0x8000 // 32768
+
+//Deinterlacing Filters
+#define LINEAR_IPOL_DEINT_FILTER 0x10000 // 65536
+#define LINEAR_BLEND_DEINT_FILTER 0x20000 // 131072
+#define CUBIC_BLEND_DEINT_FILTER 0x8000 // (not implemented yet)
+#define CUBIC_IPOL_DEINT_FILTER 0x40000 // 262144
+#define MEDIAN_DEINT_FILTER 0x80000 // 524288
+#define FFMPEG_DEINT_FILTER 0x400000
+#define LOWPASS5_DEINT_FILTER 0x800000
+
+#define TEMP_NOISE_FILTER 0x100000
+#define FORCE_QUANT 0x200000
+
+#if ( defined(__PIC__) || defined(__pic__) ) && ! defined(PIC)
+# define PIC
+#endif
+
+//use if u want a faster postprocessing code
+//cant differentiate between chroma & luma filters (both on or both off)
+//obviosly the -pp option at the commandline has no effect except turning the here selected
+//filters on
+//#define COMPILE_TIME_MODE 0x77
+
+#if 1
+static inline int CLIP(int a){
+ if(a&256) return ((a)>>31)^(-1);
+ else return a;
+}
+//#define CLIP(a) (((a)&256) ? ((a)>>31)^(-1) : (a))
+#elif 0
+#define CLIP(a) clip_tab[a]
+#else
+#define CLIP(a) (a)
+#endif
+/**
+ * Postprocessng filter.
+ */
+struct PPFilter{
+ const char *shortName;
+ const char *longName;
+ int chromDefault; ///< is chrominance filtering on by default if this filter is manually activated
+ int minLumQuality; ///< minimum quality to turn luminance filtering on
+ int minChromQuality; ///< minimum quality to turn chrominance filtering on
+ int mask; ///< Bitmask to turn this filter on
+};
+
+/**
+ * Postprocessng mode.
+ */
+typedef struct PPMode{
+ int lumMode; ///< acivates filters for luminance
+ int chromMode; ///< acivates filters for chrominance
+ int error; ///< non zero on error
+
+ int minAllowedY; ///< for brigtness correction
+ int maxAllowedY; ///< for brihtness correction
+ float maxClippedThreshold; ///< amount of "black" u r willing to loose to get a brightness corrected picture
+
+ int maxTmpNoise[3]; ///< for Temporal Noise Reducing filter (Maximal sum of abs differences)
+
+ int baseDcDiff;
+ int flatnessThreshold;
+
+ int forcedQuant; ///< quantizer if FORCE_QUANT is used
+} PPMode;
+
+/**
+ * postprocess context.
+ */
+typedef struct PPContext{
+ /**
+ * info on struct for av_log
+ */
+ AVClass *av_class;
+
+ uint8_t *tempBlocks; ///<used for the horizontal code
+
+ /**
+ * luma histogram.
+ * we need 64bit here otherwise we'll going to have a problem
+ * after watching a black picture for 5 hours
+ */
+ uint64_t *yHistogram;
+
+ DECLARE_ALIGNED(8, uint64_t, packedYOffset);
+ DECLARE_ALIGNED(8, uint64_t, packedYScale);
+
+ /** Temporal noise reducing buffers */
+ uint8_t *tempBlured[3];
+ int32_t *tempBluredPast[3];
+
+ /** Temporary buffers for handling the last row(s) */
+ uint8_t *tempDst;
+ uint8_t *tempSrc;
+
+ uint8_t *deintTemp;
+
+ DECLARE_ALIGNED(8, uint64_t, pQPb);
+ DECLARE_ALIGNED(8, uint64_t, pQPb2);
+
+ DECLARE_ALIGNED(8, uint64_t, mmxDcOffset[64]);
+ DECLARE_ALIGNED(8, uint64_t, mmxDcThreshold[64]);
+
+ QP_STORE_T *stdQPTable; ///< used to fix MPEG2 style qscale
+ QP_STORE_T *nonBQPTable;
+ QP_STORE_T *forcedQPTable;
+
+ int QP;
+ int nonBQP;
+
+ int frameNum;
+
+ int cpuCaps;
+
+ int qpStride; ///<size of qp buffers (needed to realloc them if needed)
+ int stride; ///<size of some buffers (needed to realloc them if needed)
+
+ int hChromaSubSample;
+ int vChromaSubSample;
+
+ PPMode ppMode;
+} PPContext;
+
+
+static inline void linecpy(void *dest, void *src, int lines, int stride)
+{
+ if (stride > 0) {
+ memcpy(dest, src, lines*stride);
+ } else {
+ memcpy(dest+(lines-1)*stride, src+(lines-1)*stride, -lines*stride);
+ }
+}
diff --git a/contrib/ffmpeg/libpostproc/postprocess_template.c b/contrib/ffmpeg/libpostproc/postprocess_template.c
new file mode 100644
index 000000000..c22d5d1b6
--- /dev/null
+++ b/contrib/ffmpeg/libpostproc/postprocess_template.c
@@ -0,0 +1,3843 @@
+/*
+ * Copyright (C) 2001-2002 Michael Niedermayer (michaelni@gmx.at)
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that 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 postprocess_template.c
+ * mmx/mmx2/3dnow postprocess code.
+ */
+
+
+#ifdef ARCH_X86_64
+# define REGa rax
+# define REGc rcx
+# define REGd rdx
+# define REG_a "rax"
+# define REG_c "rcx"
+# define REG_d "rdx"
+# define REG_SP "rsp"
+# define ALIGN_MASK "$0xFFFFFFFFFFFFFFF8"
+#else
+# define REGa eax
+# define REGc ecx
+# define REGd edx
+# define REG_a "eax"
+# define REG_c "ecx"
+# define REG_d "edx"
+# define REG_SP "esp"
+# define ALIGN_MASK "$0xFFFFFFF8"
+#endif
+
+
+#undef PAVGB
+#undef PMINUB
+#undef PMAXUB
+
+#ifdef HAVE_MMX2
+#define REAL_PAVGB(a,b) "pavgb " #a ", " #b " \n\t"
+#elif defined (HAVE_3DNOW)
+#define REAL_PAVGB(a,b) "pavgusb " #a ", " #b " \n\t"
+#endif
+#define PAVGB(a,b) REAL_PAVGB(a,b)
+
+#ifdef HAVE_MMX2
+#define PMINUB(a,b,t) "pminub " #a ", " #b " \n\t"
+#elif defined (HAVE_MMX)
+#define PMINUB(b,a,t) \
+ "movq " #a ", " #t " \n\t"\
+ "psubusb " #b ", " #t " \n\t"\
+ "psubb " #t ", " #a " \n\t"
+#endif
+
+#ifdef HAVE_MMX2
+#define PMAXUB(a,b) "pmaxub " #a ", " #b " \n\t"
+#elif defined (HAVE_MMX)
+#define PMAXUB(a,b) \
+ "psubusb " #a ", " #b " \n\t"\
+ "paddb " #a ", " #b " \n\t"
+#endif
+
+//FIXME? |255-0| = 1 (shouldnt be a problem ...)
+#ifdef HAVE_MMX
+/**
+ * Check if the middle 8x8 Block in the given 8x16 block is flat
+ */
+static inline int RENAME(vertClassify)(uint8_t src[], int stride, PPContext *c){
+ int numEq= 0, dcOk;
+ src+= stride*4; // src points to begin of the 8x8 Block
+asm volatile(
+ "movq %0, %%mm7 \n\t"
+ "movq %1, %%mm6 \n\t"
+ : : "m" (c->mmxDcOffset[c->nonBQP]), "m" (c->mmxDcThreshold[c->nonBQP])
+ );
+
+asm volatile(
+ "lea (%2, %3), %%"REG_a" \n\t"
+// 0 1 2 3 4 5 6 7 8 9
+// %1 eax eax+%2 eax+2%2 %1+4%2 ecx ecx+%2 ecx+2%2 %1+8%2 ecx+4%2
+
+ "movq (%2), %%mm0 \n\t"
+ "movq (%%"REG_a"), %%mm1 \n\t"
+ "movq %%mm0, %%mm3 \n\t"
+ "movq %%mm0, %%mm4 \n\t"
+ PMAXUB(%%mm1, %%mm4)
+ PMINUB(%%mm1, %%mm3, %%mm5)
+ "psubb %%mm1, %%mm0 \n\t" // mm0 = differnece
+ "paddb %%mm7, %%mm0 \n\t"
+ "pcmpgtb %%mm6, %%mm0 \n\t"
+
+ "movq (%%"REG_a",%3), %%mm2 \n\t"
+ PMAXUB(%%mm2, %%mm4)
+ PMINUB(%%mm2, %%mm3, %%mm5)
+ "psubb %%mm2, %%mm1 \n\t"
+ "paddb %%mm7, %%mm1 \n\t"
+ "pcmpgtb %%mm6, %%mm1 \n\t"
+ "paddb %%mm1, %%mm0 \n\t"
+
+ "movq (%%"REG_a", %3, 2), %%mm1 \n\t"
+ PMAXUB(%%mm1, %%mm4)
+ PMINUB(%%mm1, %%mm3, %%mm5)
+ "psubb %%mm1, %%mm2 \n\t"
+ "paddb %%mm7, %%mm2 \n\t"
+ "pcmpgtb %%mm6, %%mm2 \n\t"
+ "paddb %%mm2, %%mm0 \n\t"
+
+ "lea (%%"REG_a", %3, 4), %%"REG_a" \n\t"
+
+ "movq (%2, %3, 4), %%mm2 \n\t"
+ PMAXUB(%%mm2, %%mm4)
+ PMINUB(%%mm2, %%mm3, %%mm5)
+ "psubb %%mm2, %%mm1 \n\t"
+ "paddb %%mm7, %%mm1 \n\t"
+ "pcmpgtb %%mm6, %%mm1 \n\t"
+ "paddb %%mm1, %%mm0 \n\t"
+
+ "movq (%%"REG_a"), %%mm1 \n\t"
+ PMAXUB(%%mm1, %%mm4)
+ PMINUB(%%mm1, %%mm3, %%mm5)
+ "psubb %%mm1, %%mm2 \n\t"
+ "paddb %%mm7, %%mm2 \n\t"
+ "pcmpgtb %%mm6, %%mm2 \n\t"
+ "paddb %%mm2, %%mm0 \n\t"
+
+ "movq (%%"REG_a", %3), %%mm2 \n\t"
+ PMAXUB(%%mm2, %%mm4)
+ PMINUB(%%mm2, %%mm3, %%mm5)
+ "psubb %%mm2, %%mm1 \n\t"
+ "paddb %%mm7, %%mm1 \n\t"
+ "pcmpgtb %%mm6, %%mm1 \n\t"
+ "paddb %%mm1, %%mm0 \n\t"
+
+ "movq (%%"REG_a", %3, 2), %%mm1 \n\t"
+ PMAXUB(%%mm1, %%mm4)
+ PMINUB(%%mm1, %%mm3, %%mm5)
+ "psubb %%mm1, %%mm2 \n\t"
+ "paddb %%mm7, %%mm2 \n\t"
+ "pcmpgtb %%mm6, %%mm2 \n\t"
+ "paddb %%mm2, %%mm0 \n\t"
+ "psubusb %%mm3, %%mm4 \n\t"
+
+ " \n\t"
+#ifdef HAVE_MMX2
+ "pxor %%mm7, %%mm7 \n\t"
+ "psadbw %%mm7, %%mm0 \n\t"
+#else
+ "movq %%mm0, %%mm1 \n\t"
+ "psrlw $8, %%mm0 \n\t"
+ "paddb %%mm1, %%mm0 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "psrlq $16, %%mm0 \n\t"
+ "paddb %%mm1, %%mm0 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "psrlq $32, %%mm0 \n\t"
+ "paddb %%mm1, %%mm0 \n\t"
+#endif
+ "movq %4, %%mm7 \n\t" // QP,..., QP
+ "paddusb %%mm7, %%mm7 \n\t" // 2QP ... 2QP
+ "psubusb %%mm7, %%mm4 \n\t" // Diff <= 2QP -> 0
+ "packssdw %%mm4, %%mm4 \n\t"
+ "movd %%mm0, %0 \n\t"
+ "movd %%mm4, %1 \n\t"
+
+ : "=r" (numEq), "=r" (dcOk)
+ : "r" (src), "r" ((long)stride), "m" (c->pQPb)
+ : "%"REG_a
+ );
+
+ numEq= (-numEq) &0xFF;
+ if(numEq > c->ppMode.flatnessThreshold){
+ if(dcOk) return 0;
+ else return 1;
+ }else{
+ return 2;
+ }
+}
+#endif //HAVE_MMX
+
+/**
+ * Do a vertical low pass filter on the 8x16 block (only write to the 8x8 block in the middle)
+ * using the 9-Tap Filter (1,1,2,2,4,2,2,1,1)/16
+ */
+#ifndef HAVE_ALTIVEC
+static inline void RENAME(doVertLowPass)(uint8_t *src, int stride, PPContext *c)
+{
+#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ src+= stride*3;
+ asm volatile( //"movv %0 %1 %2\n\t"
+ "movq %2, %%mm0 \n\t" // QP,..., QP
+ "pxor %%mm4, %%mm4 \n\t"
+
+ "movq (%0), %%mm6 \n\t"
+ "movq (%0, %1), %%mm5 \n\t"
+ "movq %%mm5, %%mm1 \n\t"
+ "movq %%mm6, %%mm2 \n\t"
+ "psubusb %%mm6, %%mm5 \n\t"
+ "psubusb %%mm1, %%mm2 \n\t"
+ "por %%mm5, %%mm2 \n\t" // ABS Diff of lines
+ "psubusb %%mm0, %%mm2 \n\t" // diff <= QP -> 0
+ "pcmpeqb %%mm4, %%mm2 \n\t" // diff <= QP -> FF
+
+ "pand %%mm2, %%mm6 \n\t"
+ "pandn %%mm1, %%mm2 \n\t"
+ "por %%mm2, %%mm6 \n\t"// First Line to Filter
+
+ "movq (%0, %1, 8), %%mm5 \n\t"
+ "lea (%0, %1, 4), %%"REG_a" \n\t"
+ "lea (%0, %1, 8), %%"REG_c" \n\t"
+ "sub %1, %%"REG_c" \n\t"
+ "add %1, %0 \n\t" // %0 points to line 1 not 0
+ "movq (%0, %1, 8), %%mm7 \n\t"
+ "movq %%mm5, %%mm1 \n\t"
+ "movq %%mm7, %%mm2 \n\t"
+ "psubusb %%mm7, %%mm5 \n\t"
+ "psubusb %%mm1, %%mm2 \n\t"
+ "por %%mm5, %%mm2 \n\t" // ABS Diff of lines
+ "psubusb %%mm0, %%mm2 \n\t" // diff <= QP -> 0
+ "pcmpeqb %%mm4, %%mm2 \n\t" // diff <= QP -> FF
+
+ "pand %%mm2, %%mm7 \n\t"
+ "pandn %%mm1, %%mm2 \n\t"
+ "por %%mm2, %%mm7 \n\t" // First Line to Filter
+
+
+ // 1 2 3 4 5 6 7 8
+ // %0 %0+%1 %0+2%1 eax %0+4%1 eax+2%1 ecx eax+4%1
+ // 6 4 2 2 1 1
+ // 6 4 4 2
+ // 6 8 2
+
+ "movq (%0, %1), %%mm0 \n\t" // 1
+ "movq %%mm0, %%mm1 \n\t" // 1
+ PAVGB(%%mm6, %%mm0) //1 1 /2
+ PAVGB(%%mm6, %%mm0) //3 1 /4
+
+ "movq (%0, %1, 4), %%mm2 \n\t" // 1
+ "movq %%mm2, %%mm5 \n\t" // 1
+ PAVGB((%%REGa), %%mm2) // 11 /2
+ PAVGB((%0, %1, 2), %%mm2) // 211 /4
+ "movq %%mm2, %%mm3 \n\t" // 211 /4
+ "movq (%0), %%mm4 \n\t" // 1
+ PAVGB(%%mm4, %%mm3) // 4 211 /8
+ PAVGB(%%mm0, %%mm3) //642211 /16
+ "movq %%mm3, (%0) \n\t" // X
+ // mm1=2 mm2=3(211) mm4=1 mm5=5 mm6=0 mm7=9
+ "movq %%mm1, %%mm0 \n\t" // 1
+ PAVGB(%%mm6, %%mm0) //1 1 /2
+ "movq %%mm4, %%mm3 \n\t" // 1
+ PAVGB((%0,%1,2), %%mm3) // 1 1 /2
+ PAVGB((%%REGa,%1,2), %%mm5) // 11 /2
+ PAVGB((%%REGa), %%mm5) // 211 /4
+ PAVGB(%%mm5, %%mm3) // 2 2211 /8
+ PAVGB(%%mm0, %%mm3) //4242211 /16
+ "movq %%mm3, (%0,%1) \n\t" // X
+ // mm1=2 mm2=3(211) mm4=1 mm5=4(211) mm6=0 mm7=9
+ PAVGB(%%mm4, %%mm6) //11 /2
+ "movq (%%"REG_c"), %%mm0 \n\t" // 1
+ PAVGB((%%REGa, %1, 2), %%mm0) // 11/2
+ "movq %%mm0, %%mm3 \n\t" // 11/2
+ PAVGB(%%mm1, %%mm0) // 2 11/4
+ PAVGB(%%mm6, %%mm0) //222 11/8
+ PAVGB(%%mm2, %%mm0) //22242211/16
+ "movq (%0, %1, 2), %%mm2 \n\t" // 1
+ "movq %%mm0, (%0, %1, 2) \n\t" // X
+ // mm1=2 mm2=3 mm3=6(11) mm4=1 mm5=4(211) mm6=0(11) mm7=9
+ "movq (%%"REG_a", %1, 4), %%mm0 \n\t" // 1
+ PAVGB((%%REGc), %%mm0) // 11 /2
+ PAVGB(%%mm0, %%mm6) //11 11 /4
+ PAVGB(%%mm1, %%mm4) // 11 /2
+ PAVGB(%%mm2, %%mm1) // 11 /2
+ PAVGB(%%mm1, %%mm6) //1122 11 /8
+ PAVGB(%%mm5, %%mm6) //112242211 /16
+ "movq (%%"REG_a"), %%mm5 \n\t" // 1
+ "movq %%mm6, (%%"REG_a") \n\t" // X
+ // mm0=7(11) mm1=2(11) mm2=3 mm3=6(11) mm4=1(11) mm5=4 mm7=9
+ "movq (%%"REG_a", %1, 4), %%mm6 \n\t" // 1
+ PAVGB(%%mm7, %%mm6) // 11 /2
+ PAVGB(%%mm4, %%mm6) // 11 11 /4
+ PAVGB(%%mm3, %%mm6) // 11 2211 /8
+ PAVGB(%%mm5, %%mm2) // 11 /2
+ "movq (%0, %1, 4), %%mm4 \n\t" // 1
+ PAVGB(%%mm4, %%mm2) // 112 /4
+ PAVGB(%%mm2, %%mm6) // 112242211 /16
+ "movq %%mm6, (%0, %1, 4) \n\t" // X
+ // mm0=7(11) mm1=2(11) mm2=3(112) mm3=6(11) mm4=5 mm5=4 mm7=9
+ PAVGB(%%mm7, %%mm1) // 11 2 /4
+ PAVGB(%%mm4, %%mm5) // 11 /2
+ PAVGB(%%mm5, %%mm0) // 11 11 /4
+ "movq (%%"REG_a", %1, 2), %%mm6 \n\t" // 1
+ PAVGB(%%mm6, %%mm1) // 11 4 2 /8
+ PAVGB(%%mm0, %%mm1) // 11224222 /16
+ "movq %%mm1, (%%"REG_a", %1, 2) \n\t" // X
+ // mm2=3(112) mm3=6(11) mm4=5 mm5=4(11) mm6=6 mm7=9
+ PAVGB((%%REGc), %%mm2) // 112 4 /8
+ "movq (%%"REG_a", %1, 4), %%mm0 \n\t" // 1
+ PAVGB(%%mm0, %%mm6) // 1 1 /2
+ PAVGB(%%mm7, %%mm6) // 1 12 /4
+ PAVGB(%%mm2, %%mm6) // 1122424 /4
+ "movq %%mm6, (%%"REG_c") \n\t" // X
+ // mm0=8 mm3=6(11) mm4=5 mm5=4(11) mm7=9
+ PAVGB(%%mm7, %%mm5) // 11 2 /4
+ PAVGB(%%mm7, %%mm5) // 11 6 /8
+
+ PAVGB(%%mm3, %%mm0) // 112 /4
+ PAVGB(%%mm0, %%mm5) // 112246 /16
+ "movq %%mm5, (%%"REG_a", %1, 4) \n\t" // X
+ "sub %1, %0 \n\t"
+
+ :
+ : "r" (src), "r" ((long)stride), "m" (c->pQPb)
+ : "%"REG_a, "%"REG_c
+ );
+#else //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ const int l1= stride;
+ const int l2= stride + l1;
+ const int l3= stride + l2;
+ const int l4= stride + l3;
+ const int l5= stride + l4;
+ const int l6= stride + l5;
+ const int l7= stride + l6;
+ const int l8= stride + l7;
+ const int l9= stride + l8;
+ int x;
+ src+= stride*3;
+ for(x=0; x<BLOCK_SIZE; x++)
+ {
+ const int first= FFABS(src[0] - src[l1]) < c->QP ? src[0] : src[l1];
+ const int last= FFABS(src[l8] - src[l9]) < c->QP ? src[l9] : src[l8];
+
+ int sums[10];
+ sums[0] = 4*first + src[l1] + src[l2] + src[l3] + 4;
+ sums[1] = sums[0] - first + src[l4];
+ sums[2] = sums[1] - first + src[l5];
+ sums[3] = sums[2] - first + src[l6];
+ sums[4] = sums[3] - first + src[l7];
+ sums[5] = sums[4] - src[l1] + src[l8];
+ sums[6] = sums[5] - src[l2] + last;
+ sums[7] = sums[6] - src[l3] + last;
+ sums[8] = sums[7] - src[l4] + last;
+ sums[9] = sums[8] - src[l5] + last;
+
+ src[l1]= (sums[0] + sums[2] + 2*src[l1])>>4;
+ src[l2]= (sums[1] + sums[3] + 2*src[l2])>>4;
+ src[l3]= (sums[2] + sums[4] + 2*src[l3])>>4;
+ src[l4]= (sums[3] + sums[5] + 2*src[l4])>>4;
+ src[l5]= (sums[4] + sums[6] + 2*src[l5])>>4;
+ src[l6]= (sums[5] + sums[7] + 2*src[l6])>>4;
+ src[l7]= (sums[6] + sums[8] + 2*src[l7])>>4;
+ src[l8]= (sums[7] + sums[9] + 2*src[l8])>>4;
+
+ src++;
+ }
+#endif //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+}
+#endif //HAVE_ALTIVEC
+
+#if 0
+/**
+ * Experimental implementation of the filter (Algorithm 1) described in a paper from Ramkishor & Karandikar
+ * values are correctly clipped (MMX2)
+ * values are wraparound (C)
+ * conclusion: its fast, but introduces ugly horizontal patterns if there is a continious gradient
+ 0 8 16 24
+ x = 8
+ x/2 = 4
+ x/8 = 1
+ 1 12 12 23
+ */
+static inline void RENAME(vertRK1Filter)(uint8_t *src, int stride, int QP)
+{
+#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ src+= stride*3;
+// FIXME rounding
+ asm volatile(
+ "pxor %%mm7, %%mm7 \n\t" // 0
+ "movq "MANGLE(b80)", %%mm6 \n\t" // MIN_SIGNED_BYTE
+ "leal (%0, %1), %%"REG_a" \n\t"
+ "leal (%%"REG_a", %1, 4), %%"REG_c" \n\t"
+// 0 1 2 3 4 5 6 7 8 9
+// %0 eax eax+%1 eax+2%1 %0+4%1 ecx ecx+%1 ecx+2%1 %0+8%1 ecx+4%1
+ "movq "MANGLE(pQPb)", %%mm0 \n\t" // QP,..., QP
+ "movq %%mm0, %%mm1 \n\t" // QP,..., QP
+ "paddusb "MANGLE(b02)", %%mm0 \n\t"
+ "psrlw $2, %%mm0 \n\t"
+ "pand "MANGLE(b3F)", %%mm0 \n\t" // QP/4,..., QP/4
+ "paddusb %%mm1, %%mm0 \n\t" // QP*1.25 ...
+ "movq (%0, %1, 4), %%mm2 \n\t" // line 4
+ "movq (%%"REG_c"), %%mm3 \n\t" // line 5
+ "movq %%mm2, %%mm4 \n\t" // line 4
+ "pcmpeqb %%mm5, %%mm5 \n\t" // -1
+ "pxor %%mm2, %%mm5 \n\t" // -line 4 - 1
+ PAVGB(%%mm3, %%mm5)
+ "paddb %%mm6, %%mm5 \n\t" // (l5-l4)/2
+ "psubusb %%mm3, %%mm4 \n\t"
+ "psubusb %%mm2, %%mm3 \n\t"
+ "por %%mm3, %%mm4 \n\t" // |l4 - l5|
+ "psubusb %%mm0, %%mm4 \n\t"
+ "pcmpeqb %%mm7, %%mm4 \n\t"
+ "pand %%mm4, %%mm5 \n\t" // d/2
+
+// "paddb %%mm6, %%mm2 \n\t" // line 4 + 0x80
+ "paddb %%mm5, %%mm2 \n\t"
+// "psubb %%mm6, %%mm2 \n\t"
+ "movq %%mm2, (%0,%1, 4) \n\t"
+
+ "movq (%%"REG_c"), %%mm2 \n\t"
+// "paddb %%mm6, %%mm2 \n\t" // line 5 + 0x80
+ "psubb %%mm5, %%mm2 \n\t"
+// "psubb %%mm6, %%mm2 \n\t"
+ "movq %%mm2, (%%"REG_c") \n\t"
+
+ "paddb %%mm6, %%mm5 \n\t"
+ "psrlw $2, %%mm5 \n\t"
+ "pand "MANGLE(b3F)", %%mm5 \n\t"
+ "psubb "MANGLE(b20)", %%mm5 \n\t" // (l5-l4)/8
+
+ "movq (%%"REG_a", %1, 2), %%mm2 \n\t"
+ "paddb %%mm6, %%mm2 \n\t" // line 3 + 0x80
+ "paddsb %%mm5, %%mm2 \n\t"
+ "psubb %%mm6, %%mm2 \n\t"
+ "movq %%mm2, (%%"REG_a", %1, 2) \n\t"
+
+ "movq (%%"REG_c", %1), %%mm2 \n\t"
+ "paddb %%mm6, %%mm2 \n\t" // line 6 + 0x80
+ "psubsb %%mm5, %%mm2 \n\t"
+ "psubb %%mm6, %%mm2 \n\t"
+ "movq %%mm2, (%%"REG_c", %1) \n\t"
+
+ :
+ : "r" (src), "r" ((long)stride)
+ : "%"REG_a, "%"REG_c
+ );
+#else //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ const int l1= stride;
+ const int l2= stride + l1;
+ const int l3= stride + l2;
+ const int l4= stride + l3;
+ const int l5= stride + l4;
+ const int l6= stride + l5;
+// const int l7= stride + l6;
+// const int l8= stride + l7;
+// const int l9= stride + l8;
+ int x;
+ const int QP15= QP + (QP>>2);
+ src+= stride*3;
+ for(x=0; x<BLOCK_SIZE; x++)
+ {
+ const int v = (src[x+l5] - src[x+l4]);
+ if(FFABS(v) < QP15)
+ {
+ src[x+l3] +=v>>3;
+ src[x+l4] +=v>>1;
+ src[x+l5] -=v>>1;
+ src[x+l6] -=v>>3;
+
+ }
+ }
+
+#endif //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+}
+#endif //0
+
+/**
+ * Experimental Filter 1
+ * will not damage linear gradients
+ * Flat blocks should look like they where passed through the (1,1,2,2,4,2,2,1,1) 9-Tap filter
+ * can only smooth blocks at the expected locations (it cant smooth them if they did move)
+ * MMX2 version does correct clipping C version doesnt
+ */
+static inline void RENAME(vertX1Filter)(uint8_t *src, int stride, PPContext *co)
+{
+#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ src+= stride*3;
+
+ asm volatile(
+ "pxor %%mm7, %%mm7 \n\t" // 0
+ "lea (%0, %1), %%"REG_a" \n\t"
+ "lea (%%"REG_a", %1, 4), %%"REG_c" \n\t"
+// 0 1 2 3 4 5 6 7 8 9
+// %0 eax eax+%1 eax+2%1 %0+4%1 ecx ecx+%1 ecx+2%1 %0+8%1 ecx+4%1
+ "movq (%%"REG_a", %1, 2), %%mm0 \n\t" // line 3
+ "movq (%0, %1, 4), %%mm1 \n\t" // line 4
+ "movq %%mm1, %%mm2 \n\t" // line 4
+ "psubusb %%mm0, %%mm1 \n\t"
+ "psubusb %%mm2, %%mm0 \n\t"
+ "por %%mm1, %%mm0 \n\t" // |l2 - l3|
+ "movq (%%"REG_c"), %%mm3 \n\t" // line 5
+ "movq (%%"REG_c", %1), %%mm4 \n\t" // line 6
+ "movq %%mm3, %%mm5 \n\t" // line 5
+ "psubusb %%mm4, %%mm3 \n\t"
+ "psubusb %%mm5, %%mm4 \n\t"
+ "por %%mm4, %%mm3 \n\t" // |l5 - l6|
+ PAVGB(%%mm3, %%mm0) // (|l2 - l3| + |l5 - l6|)/2
+ "movq %%mm2, %%mm1 \n\t" // line 4
+ "psubusb %%mm5, %%mm2 \n\t"
+ "movq %%mm2, %%mm4 \n\t"
+ "pcmpeqb %%mm7, %%mm2 \n\t" // (l4 - l5) <= 0 ? -1 : 0
+ "psubusb %%mm1, %%mm5 \n\t"
+ "por %%mm5, %%mm4 \n\t" // |l4 - l5|
+ "psubusb %%mm0, %%mm4 \n\t" //d = MAX(0, |l4-l5| - (|l2-l3| + |l5-l6|)/2)
+ "movq %%mm4, %%mm3 \n\t" // d
+ "movq %2, %%mm0 \n\t"
+ "paddusb %%mm0, %%mm0 \n\t"
+ "psubusb %%mm0, %%mm4 \n\t"
+ "pcmpeqb %%mm7, %%mm4 \n\t" // d <= QP ? -1 : 0
+ "psubusb "MANGLE(b01)", %%mm3 \n\t"
+ "pand %%mm4, %%mm3 \n\t" // d <= QP ? d : 0
+
+ PAVGB(%%mm7, %%mm3) // d/2
+ "movq %%mm3, %%mm1 \n\t" // d/2
+ PAVGB(%%mm7, %%mm3) // d/4
+ PAVGB(%%mm1, %%mm3) // 3*d/8
+
+ "movq (%0, %1, 4), %%mm0 \n\t" // line 4
+ "pxor %%mm2, %%mm0 \n\t" //(l4 - l5) <= 0 ? -l4-1 : l4
+ "psubusb %%mm3, %%mm0 \n\t"
+ "pxor %%mm2, %%mm0 \n\t"
+ "movq %%mm0, (%0, %1, 4) \n\t" // line 4
+
+ "movq (%%"REG_c"), %%mm0 \n\t" // line 5
+ "pxor %%mm2, %%mm0 \n\t" //(l4 - l5) <= 0 ? -l5-1 : l5
+ "paddusb %%mm3, %%mm0 \n\t"
+ "pxor %%mm2, %%mm0 \n\t"
+ "movq %%mm0, (%%"REG_c") \n\t" // line 5
+
+ PAVGB(%%mm7, %%mm1) // d/4
+
+ "movq (%%"REG_a", %1, 2), %%mm0 \n\t" // line 3
+ "pxor %%mm2, %%mm0 \n\t" //(l4 - l5) <= 0 ? -l4-1 : l4
+ "psubusb %%mm1, %%mm0 \n\t"
+ "pxor %%mm2, %%mm0 \n\t"
+ "movq %%mm0, (%%"REG_a", %1, 2) \n\t" // line 3
+
+ "movq (%%"REG_c", %1), %%mm0 \n\t" // line 6
+ "pxor %%mm2, %%mm0 \n\t" //(l4 - l5) <= 0 ? -l5-1 : l5
+ "paddusb %%mm1, %%mm0 \n\t"
+ "pxor %%mm2, %%mm0 \n\t"
+ "movq %%mm0, (%%"REG_c", %1) \n\t" // line 6
+
+ PAVGB(%%mm7, %%mm1) // d/8
+
+ "movq (%%"REG_a", %1), %%mm0 \n\t" // line 2
+ "pxor %%mm2, %%mm0 \n\t" //(l4 - l5) <= 0 ? -l2-1 : l2
+ "psubusb %%mm1, %%mm0 \n\t"
+ "pxor %%mm2, %%mm0 \n\t"
+ "movq %%mm0, (%%"REG_a", %1) \n\t" // line 2
+
+ "movq (%%"REG_c", %1, 2), %%mm0 \n\t" // line 7
+ "pxor %%mm2, %%mm0 \n\t" //(l4 - l5) <= 0 ? -l7-1 : l7
+ "paddusb %%mm1, %%mm0 \n\t"
+ "pxor %%mm2, %%mm0 \n\t"
+ "movq %%mm0, (%%"REG_c", %1, 2) \n\t" // line 7
+
+ :
+ : "r" (src), "r" ((long)stride), "m" (co->pQPb)
+ : "%"REG_a, "%"REG_c
+ );
+#else //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+
+ const int l1= stride;
+ const int l2= stride + l1;
+ const int l3= stride + l2;
+ const int l4= stride + l3;
+ const int l5= stride + l4;
+ const int l6= stride + l5;
+ const int l7= stride + l6;
+// const int l8= stride + l7;
+// const int l9= stride + l8;
+ int x;
+
+ src+= stride*3;
+ for(x=0; x<BLOCK_SIZE; x++)
+ {
+ int a= src[l3] - src[l4];
+ int b= src[l4] - src[l5];
+ int c= src[l5] - src[l6];
+
+ int d= FFABS(b) - ((FFABS(a) + FFABS(c))>>1);
+ d= FFMAX(d, 0);
+
+ if(d < co->QP*2)
+ {
+ int v = d * FFSIGN(-b);
+
+ src[l2] +=v>>3;
+ src[l3] +=v>>2;
+ src[l4] +=(3*v)>>3;
+ src[l5] -=(3*v)>>3;
+ src[l6] -=v>>2;
+ src[l7] -=v>>3;
+
+ }
+ src++;
+ }
+#endif //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+}
+
+#ifndef HAVE_ALTIVEC
+static inline void RENAME(doVertDefFilter)(uint8_t src[], int stride, PPContext *c)
+{
+#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+/*
+ uint8_t tmp[16];
+ const int l1= stride;
+ const int l2= stride + l1;
+ const int l3= stride + l2;
+ const int l4= (int)tmp - (int)src - stride*3;
+ const int l5= (int)tmp - (int)src - stride*3 + 8;
+ const int l6= stride*3 + l3;
+ const int l7= stride + l6;
+ const int l8= stride + l7;
+
+ memcpy(tmp, src+stride*7, 8);
+ memcpy(tmp+8, src+stride*8, 8);
+*/
+ src+= stride*4;
+ asm volatile(
+
+#if 0 //sligtly more accurate and slightly slower
+ "pxor %%mm7, %%mm7 \n\t" // 0
+ "lea (%0, %1), %%"REG_a" \n\t"
+ "lea (%%"REG_a", %1, 4), %%"REG_c" \n\t"
+// 0 1 2 3 4 5 6 7
+// %0 %0+%1 %0+2%1 eax+2%1 %0+4%1 eax+4%1 ecx+%1 ecx+2%1
+// %0 eax eax+%1 eax+2%1 %0+4%1 ecx ecx+%1 ecx+2%1
+
+
+ "movq (%0, %1, 2), %%mm0 \n\t" // l2
+ "movq (%0), %%mm1 \n\t" // l0
+ "movq %%mm0, %%mm2 \n\t" // l2
+ PAVGB(%%mm7, %%mm0) // ~l2/2
+ PAVGB(%%mm1, %%mm0) // ~(l2 + 2l0)/4
+ PAVGB(%%mm2, %%mm0) // ~(5l2 + 2l0)/8
+
+ "movq (%%"REG_a"), %%mm1 \n\t" // l1
+ "movq (%%"REG_a", %1, 2), %%mm3 \n\t" // l3
+ "movq %%mm1, %%mm4 \n\t" // l1
+ PAVGB(%%mm7, %%mm1) // ~l1/2
+ PAVGB(%%mm3, %%mm1) // ~(l1 + 2l3)/4
+ PAVGB(%%mm4, %%mm1) // ~(5l1 + 2l3)/8
+
+ "movq %%mm0, %%mm4 \n\t" // ~(5l2 + 2l0)/8
+ "psubusb %%mm1, %%mm0 \n\t"
+ "psubusb %%mm4, %%mm1 \n\t"
+ "por %%mm0, %%mm1 \n\t" // ~|2l0 - 5l1 + 5l2 - 2l3|/8
+// mm1= |lenergy|, mm2= l2, mm3= l3, mm7=0
+
+ "movq (%0, %1, 4), %%mm0 \n\t" // l4
+ "movq %%mm0, %%mm4 \n\t" // l4
+ PAVGB(%%mm7, %%mm0) // ~l4/2
+ PAVGB(%%mm2, %%mm0) // ~(l4 + 2l2)/4
+ PAVGB(%%mm4, %%mm0) // ~(5l4 + 2l2)/8
+
+ "movq (%%"REG_c"), %%mm2 \n\t" // l5
+ "movq %%mm3, %%mm5 \n\t" // l3
+ PAVGB(%%mm7, %%mm3) // ~l3/2
+ PAVGB(%%mm2, %%mm3) // ~(l3 + 2l5)/4
+ PAVGB(%%mm5, %%mm3) // ~(5l3 + 2l5)/8
+
+ "movq %%mm0, %%mm6 \n\t" // ~(5l4 + 2l2)/8
+ "psubusb %%mm3, %%mm0 \n\t"
+ "psubusb %%mm6, %%mm3 \n\t"
+ "por %%mm0, %%mm3 \n\t" // ~|2l2 - 5l3 + 5l4 - 2l5|/8
+ "pcmpeqb %%mm7, %%mm0 \n\t" // SIGN(2l2 - 5l3 + 5l4 - 2l5)
+// mm0= SIGN(menergy), mm1= |lenergy|, mm2= l5, mm3= |menergy|, mm4=l4, mm5= l3, mm7=0
+
+ "movq (%%"REG_c", %1), %%mm6 \n\t" // l6
+ "movq %%mm6, %%mm5 \n\t" // l6
+ PAVGB(%%mm7, %%mm6) // ~l6/2
+ PAVGB(%%mm4, %%mm6) // ~(l6 + 2l4)/4
+ PAVGB(%%mm5, %%mm6) // ~(5l6 + 2l4)/8
+
+ "movq (%%"REG_c", %1, 2), %%mm5 \n\t" // l7
+ "movq %%mm2, %%mm4 \n\t" // l5
+ PAVGB(%%mm7, %%mm2) // ~l5/2
+ PAVGB(%%mm5, %%mm2) // ~(l5 + 2l7)/4
+ PAVGB(%%mm4, %%mm2) // ~(5l5 + 2l7)/8
+
+ "movq %%mm6, %%mm4 \n\t" // ~(5l6 + 2l4)/8
+ "psubusb %%mm2, %%mm6 \n\t"
+ "psubusb %%mm4, %%mm2 \n\t"
+ "por %%mm6, %%mm2 \n\t" // ~|2l4 - 5l5 + 5l6 - 2l7|/8
+// mm0= SIGN(menergy), mm1= |lenergy|/8, mm2= |renergy|/8, mm3= |menergy|/8, mm7=0
+
+
+ PMINUB(%%mm2, %%mm1, %%mm4) // MIN(|lenergy|,|renergy|)/8
+ "movq %2, %%mm4 \n\t" // QP //FIXME QP+1 ?
+ "paddusb "MANGLE(b01)", %%mm4 \n\t"
+ "pcmpgtb %%mm3, %%mm4 \n\t" // |menergy|/8 < QP
+ "psubusb %%mm1, %%mm3 \n\t" // d=|menergy|/8-MIN(|lenergy|,|renergy|)/8
+ "pand %%mm4, %%mm3 \n\t"
+
+ "movq %%mm3, %%mm1 \n\t"
+// "psubusb "MANGLE(b01)", %%mm3 \n\t"
+ PAVGB(%%mm7, %%mm3)
+ PAVGB(%%mm7, %%mm3)
+ "paddusb %%mm1, %%mm3 \n\t"
+// "paddusb "MANGLE(b01)", %%mm3 \n\t"
+
+ "movq (%%"REG_a", %1, 2), %%mm6 \n\t" //l3
+ "movq (%0, %1, 4), %%mm5 \n\t" //l4
+ "movq (%0, %1, 4), %%mm4 \n\t" //l4
+ "psubusb %%mm6, %%mm5 \n\t"
+ "psubusb %%mm4, %%mm6 \n\t"
+ "por %%mm6, %%mm5 \n\t" // |l3-l4|
+ "pcmpeqb %%mm7, %%mm6 \n\t" // SIGN(l3-l4)
+ "pxor %%mm6, %%mm0 \n\t"
+ "pand %%mm0, %%mm3 \n\t"
+ PMINUB(%%mm5, %%mm3, %%mm0)
+
+ "psubusb "MANGLE(b01)", %%mm3 \n\t"
+ PAVGB(%%mm7, %%mm3)
+
+ "movq (%%"REG_a", %1, 2), %%mm0 \n\t"
+ "movq (%0, %1, 4), %%mm2 \n\t"
+ "pxor %%mm6, %%mm0 \n\t"
+ "pxor %%mm6, %%mm2 \n\t"
+ "psubb %%mm3, %%mm0 \n\t"
+ "paddb %%mm3, %%mm2 \n\t"
+ "pxor %%mm6, %%mm0 \n\t"
+ "pxor %%mm6, %%mm2 \n\t"
+ "movq %%mm0, (%%"REG_a", %1, 2) \n\t"
+ "movq %%mm2, (%0, %1, 4) \n\t"
+#endif //0
+
+ "lea (%0, %1), %%"REG_a" \n\t"
+ "pcmpeqb %%mm6, %%mm6 \n\t" // -1
+// 0 1 2 3 4 5 6 7
+// %0 %0+%1 %0+2%1 eax+2%1 %0+4%1 eax+4%1 ecx+%1 ecx+2%1
+// %0 eax eax+%1 eax+2%1 %0+4%1 ecx ecx+%1 ecx+2%1
+
+
+ "movq (%%"REG_a", %1, 2), %%mm1 \n\t" // l3
+ "movq (%0, %1, 4), %%mm0 \n\t" // l4
+ "pxor %%mm6, %%mm1 \n\t" // -l3-1
+ PAVGB(%%mm1, %%mm0) // -q+128 = (l4-l3+256)/2
+// mm1=-l3-1, mm0=128-q
+
+ "movq (%%"REG_a", %1, 4), %%mm2 \n\t" // l5
+ "movq (%%"REG_a", %1), %%mm3 \n\t" // l2
+ "pxor %%mm6, %%mm2 \n\t" // -l5-1
+ "movq %%mm2, %%mm5 \n\t" // -l5-1
+ "movq "MANGLE(b80)", %%mm4 \n\t" // 128
+ "lea (%%"REG_a", %1, 4), %%"REG_c" \n\t"
+ PAVGB(%%mm3, %%mm2) // (l2-l5+256)/2
+ PAVGB(%%mm0, %%mm4) // ~(l4-l3)/4 + 128
+ PAVGB(%%mm2, %%mm4) // ~(l2-l5)/4 +(l4-l3)/8 + 128
+ PAVGB(%%mm0, %%mm4) // ~(l2-l5)/8 +5(l4-l3)/16 + 128
+// mm1=-l3-1, mm0=128-q, mm3=l2, mm4=menergy/16 + 128, mm5= -l5-1
+
+ "movq (%%"REG_a"), %%mm2 \n\t" // l1
+ "pxor %%mm6, %%mm2 \n\t" // -l1-1
+ PAVGB(%%mm3, %%mm2) // (l2-l1+256)/2
+ PAVGB((%0), %%mm1) // (l0-l3+256)/2
+ "movq "MANGLE(b80)", %%mm3 \n\t" // 128
+ PAVGB(%%mm2, %%mm3) // ~(l2-l1)/4 + 128
+ PAVGB(%%mm1, %%mm3) // ~(l0-l3)/4 +(l2-l1)/8 + 128
+ PAVGB(%%mm2, %%mm3) // ~(l0-l3)/8 +5(l2-l1)/16 + 128
+// mm0=128-q, mm3=lenergy/16 + 128, mm4= menergy/16 + 128, mm5= -l5-1
+
+ PAVGB((%%REGc, %1), %%mm5) // (l6-l5+256)/2
+ "movq (%%"REG_c", %1, 2), %%mm1 \n\t" // l7
+ "pxor %%mm6, %%mm1 \n\t" // -l7-1
+ PAVGB((%0, %1, 4), %%mm1) // (l4-l7+256)/2
+ "movq "MANGLE(b80)", %%mm2 \n\t" // 128
+ PAVGB(%%mm5, %%mm2) // ~(l6-l5)/4 + 128
+ PAVGB(%%mm1, %%mm2) // ~(l4-l7)/4 +(l6-l5)/8 + 128
+ PAVGB(%%mm5, %%mm2) // ~(l4-l7)/8 +5(l6-l5)/16 + 128
+// mm0=128-q, mm2=renergy/16 + 128, mm3=lenergy/16 + 128, mm4= menergy/16 + 128
+
+ "movq "MANGLE(b00)", %%mm1 \n\t" // 0
+ "movq "MANGLE(b00)", %%mm5 \n\t" // 0
+ "psubb %%mm2, %%mm1 \n\t" // 128 - renergy/16
+ "psubb %%mm3, %%mm5 \n\t" // 128 - lenergy/16
+ PMAXUB(%%mm1, %%mm2) // 128 + |renergy/16|
+ PMAXUB(%%mm5, %%mm3) // 128 + |lenergy/16|
+ PMINUB(%%mm2, %%mm3, %%mm1) // 128 + MIN(|lenergy|,|renergy|)/16
+
+// mm0=128-q, mm3=128 + MIN(|lenergy|,|renergy|)/16, mm4= menergy/16 + 128
+
+ "movq "MANGLE(b00)", %%mm7 \n\t" // 0
+ "movq %2, %%mm2 \n\t" // QP
+ PAVGB(%%mm6, %%mm2) // 128 + QP/2
+ "psubb %%mm6, %%mm2 \n\t"
+
+ "movq %%mm4, %%mm1 \n\t"
+ "pcmpgtb %%mm7, %%mm1 \n\t" // SIGN(menergy)
+ "pxor %%mm1, %%mm4 \n\t"
+ "psubb %%mm1, %%mm4 \n\t" // 128 + |menergy|/16
+ "pcmpgtb %%mm4, %%mm2 \n\t" // |menergy|/16 < QP/2
+ "psubusb %%mm3, %%mm4 \n\t" //d=|menergy|/16 - MIN(|lenergy|,|renergy|)/16
+// mm0=128-q, mm1= SIGN(menergy), mm2= |menergy|/16 < QP/2, mm4= d/16
+
+ "movq %%mm4, %%mm3 \n\t" // d
+ "psubusb "MANGLE(b01)", %%mm4 \n\t"
+ PAVGB(%%mm7, %%mm4) // d/32
+ PAVGB(%%mm7, %%mm4) // (d + 32)/64
+ "paddb %%mm3, %%mm4 \n\t" // 5d/64
+ "pand %%mm2, %%mm4 \n\t"
+
+ "movq "MANGLE(b80)", %%mm5 \n\t" // 128
+ "psubb %%mm0, %%mm5 \n\t" // q
+ "paddsb %%mm6, %%mm5 \n\t" // fix bad rounding
+ "pcmpgtb %%mm5, %%mm7 \n\t" // SIGN(q)
+ "pxor %%mm7, %%mm5 \n\t"
+
+ PMINUB(%%mm5, %%mm4, %%mm3) // MIN(|q|, 5d/64)
+ "pxor %%mm1, %%mm7 \n\t" // SIGN(d*q)
+
+ "pand %%mm7, %%mm4 \n\t"
+ "movq (%%"REG_a", %1, 2), %%mm0 \n\t"
+ "movq (%0, %1, 4), %%mm2 \n\t"
+ "pxor %%mm1, %%mm0 \n\t"
+ "pxor %%mm1, %%mm2 \n\t"
+ "paddb %%mm4, %%mm0 \n\t"
+ "psubb %%mm4, %%mm2 \n\t"
+ "pxor %%mm1, %%mm0 \n\t"
+ "pxor %%mm1, %%mm2 \n\t"
+ "movq %%mm0, (%%"REG_a", %1, 2) \n\t"
+ "movq %%mm2, (%0, %1, 4) \n\t"
+
+ :
+ : "r" (src), "r" ((long)stride), "m" (c->pQPb)
+ : "%"REG_a, "%"REG_c
+ );
+
+/*
+ {
+ int x;
+ src-= stride;
+ for(x=0; x<BLOCK_SIZE; x++)
+ {
+ const int middleEnergy= 5*(src[l5] - src[l4]) + 2*(src[l3] - src[l6]);
+ if(FFABS(middleEnergy)< 8*QP)
+ {
+ const int q=(src[l4] - src[l5])/2;
+ const int leftEnergy= 5*(src[l3] - src[l2]) + 2*(src[l1] - src[l4]);
+ const int rightEnergy= 5*(src[l7] - src[l6]) + 2*(src[l5] - src[l8]);
+
+ int d= FFABS(middleEnergy) - FFMIN( FFABS(leftEnergy), FFABS(rightEnergy) );
+ d= FFMAX(d, 0);
+
+ d= (5*d + 32) >> 6;
+ d*= FFSIGN(-middleEnergy);
+
+ if(q>0)
+ {
+ d= d<0 ? 0 : d;
+ d= d>q ? q : d;
+ }
+ else
+ {
+ d= d>0 ? 0 : d;
+ d= d<q ? q : d;
+ }
+
+ src[l4]-= d;
+ src[l5]+= d;
+ }
+ src++;
+ }
+src-=8;
+ for(x=0; x<8; x++)
+ {
+ int y;
+ for(y=4; y<6; y++)
+ {
+ int d= src[x+y*stride] - tmp[x+(y-4)*8];
+ int ad= FFABS(d);
+ static int max=0;
+ static int sum=0;
+ static int num=0;
+ static int bias=0;
+
+ if(max<ad) max=ad;
+ sum+= ad>3 ? 1 : 0;
+ if(ad>3)
+ {
+ src[0] = src[7] = src[stride*7] = src[(stride+1)*7]=255;
+ }
+ if(y==4) bias+=d;
+ num++;
+ if(num%1000000 == 0)
+ {
+ av_log(c, AV_LOG_INFO, " %d %d %d %d\n", num, sum, max, bias);
+ }
+ }
+ }
+}
+*/
+#elif defined (HAVE_MMX)
+ src+= stride*4;
+ asm volatile(
+ "pxor %%mm7, %%mm7 \n\t"
+ "lea -40(%%"REG_SP"), %%"REG_c" \n\t" // make space for 4 8-byte vars
+ "and "ALIGN_MASK", %%"REG_c" \n\t" // align
+// 0 1 2 3 4 5 6 7
+// %0 %0+%1 %0+2%1 eax+2%1 %0+4%1 eax+4%1 edx+%1 edx+2%1
+// %0 eax eax+%1 eax+2%1 %0+4%1 edx edx+%1 edx+2%1
+
+ "movq (%0), %%mm0 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t" // low part of line 0
+ "punpckhbw %%mm7, %%mm1 \n\t" // high part of line 0
+
+ "movq (%0, %1), %%mm2 \n\t"
+ "lea (%0, %1, 2), %%"REG_a" \n\t"
+ "movq %%mm2, %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t" // low part of line 1
+ "punpckhbw %%mm7, %%mm3 \n\t" // high part of line 1
+
+ "movq (%%"REG_a"), %%mm4 \n\t"
+ "movq %%mm4, %%mm5 \n\t"
+ "punpcklbw %%mm7, %%mm4 \n\t" // low part of line 2
+ "punpckhbw %%mm7, %%mm5 \n\t" // high part of line 2
+
+ "paddw %%mm0, %%mm0 \n\t" // 2L0
+ "paddw %%mm1, %%mm1 \n\t" // 2H0
+ "psubw %%mm4, %%mm2 \n\t" // L1 - L2
+ "psubw %%mm5, %%mm3 \n\t" // H1 - H2
+ "psubw %%mm2, %%mm0 \n\t" // 2L0 - L1 + L2
+ "psubw %%mm3, %%mm1 \n\t" // 2H0 - H1 + H2
+
+ "psllw $2, %%mm2 \n\t" // 4L1 - 4L2
+ "psllw $2, %%mm3 \n\t" // 4H1 - 4H2
+ "psubw %%mm2, %%mm0 \n\t" // 2L0 - 5L1 + 5L2
+ "psubw %%mm3, %%mm1 \n\t" // 2H0 - 5H1 + 5H2
+
+ "movq (%%"REG_a", %1), %%mm2 \n\t"
+ "movq %%mm2, %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t" // L3
+ "punpckhbw %%mm7, %%mm3 \n\t" // H3
+
+ "psubw %%mm2, %%mm0 \n\t" // 2L0 - 5L1 + 5L2 - L3
+ "psubw %%mm3, %%mm1 \n\t" // 2H0 - 5H1 + 5H2 - H3
+ "psubw %%mm2, %%mm0 \n\t" // 2L0 - 5L1 + 5L2 - 2L3
+ "psubw %%mm3, %%mm1 \n\t" // 2H0 - 5H1 + 5H2 - 2H3
+ "movq %%mm0, (%%"REG_c") \n\t" // 2L0 - 5L1 + 5L2 - 2L3
+ "movq %%mm1, 8(%%"REG_c") \n\t" // 2H0 - 5H1 + 5H2 - 2H3
+
+ "movq (%%"REG_a", %1, 2), %%mm0 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t" // L4
+ "punpckhbw %%mm7, %%mm1 \n\t" // H4
+
+ "psubw %%mm0, %%mm2 \n\t" // L3 - L4
+ "psubw %%mm1, %%mm3 \n\t" // H3 - H4
+ "movq %%mm2, 16(%%"REG_c") \n\t" // L3 - L4
+ "movq %%mm3, 24(%%"REG_c") \n\t" // H3 - H4
+ "paddw %%mm4, %%mm4 \n\t" // 2L2
+ "paddw %%mm5, %%mm5 \n\t" // 2H2
+ "psubw %%mm2, %%mm4 \n\t" // 2L2 - L3 + L4
+ "psubw %%mm3, %%mm5 \n\t" // 2H2 - H3 + H4
+
+ "lea (%%"REG_a", %1), %0 \n\t"
+ "psllw $2, %%mm2 \n\t" // 4L3 - 4L4
+ "psllw $2, %%mm3 \n\t" // 4H3 - 4H4
+ "psubw %%mm2, %%mm4 \n\t" // 2L2 - 5L3 + 5L4
+ "psubw %%mm3, %%mm5 \n\t" // 2H2 - 5H3 + 5H4
+//50 opcodes so far
+ "movq (%0, %1, 2), %%mm2 \n\t"
+ "movq %%mm2, %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t" // L5
+ "punpckhbw %%mm7, %%mm3 \n\t" // H5
+ "psubw %%mm2, %%mm4 \n\t" // 2L2 - 5L3 + 5L4 - L5
+ "psubw %%mm3, %%mm5 \n\t" // 2H2 - 5H3 + 5H4 - H5
+ "psubw %%mm2, %%mm4 \n\t" // 2L2 - 5L3 + 5L4 - 2L5
+ "psubw %%mm3, %%mm5 \n\t" // 2H2 - 5H3 + 5H4 - 2H5
+
+ "movq (%%"REG_a", %1, 4), %%mm6 \n\t"
+ "punpcklbw %%mm7, %%mm6 \n\t" // L6
+ "psubw %%mm6, %%mm2 \n\t" // L5 - L6
+ "movq (%%"REG_a", %1, 4), %%mm6 \n\t"
+ "punpckhbw %%mm7, %%mm6 \n\t" // H6
+ "psubw %%mm6, %%mm3 \n\t" // H5 - H6
+
+ "paddw %%mm0, %%mm0 \n\t" // 2L4
+ "paddw %%mm1, %%mm1 \n\t" // 2H4
+ "psubw %%mm2, %%mm0 \n\t" // 2L4 - L5 + L6
+ "psubw %%mm3, %%mm1 \n\t" // 2H4 - H5 + H6
+
+ "psllw $2, %%mm2 \n\t" // 4L5 - 4L6
+ "psllw $2, %%mm3 \n\t" // 4H5 - 4H6
+ "psubw %%mm2, %%mm0 \n\t" // 2L4 - 5L5 + 5L6
+ "psubw %%mm3, %%mm1 \n\t" // 2H4 - 5H5 + 5H6
+
+ "movq (%0, %1, 4), %%mm2 \n\t"
+ "movq %%mm2, %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t" // L7
+ "punpckhbw %%mm7, %%mm3 \n\t" // H7
+
+ "paddw %%mm2, %%mm2 \n\t" // 2L7
+ "paddw %%mm3, %%mm3 \n\t" // 2H7
+ "psubw %%mm2, %%mm0 \n\t" // 2L4 - 5L5 + 5L6 - 2L7
+ "psubw %%mm3, %%mm1 \n\t" // 2H4 - 5H5 + 5H6 - 2H7
+
+ "movq (%%"REG_c"), %%mm2 \n\t" // 2L0 - 5L1 + 5L2 - 2L3
+ "movq 8(%%"REG_c"), %%mm3 \n\t" // 2H0 - 5H1 + 5H2 - 2H3
+
+#ifdef HAVE_MMX2
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "psubw %%mm0, %%mm6 \n\t"
+ "pmaxsw %%mm6, %%mm0 \n\t" // |2L4 - 5L5 + 5L6 - 2L7|
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "psubw %%mm1, %%mm6 \n\t"
+ "pmaxsw %%mm6, %%mm1 \n\t" // |2H4 - 5H5 + 5H6 - 2H7|
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "psubw %%mm2, %%mm6 \n\t"
+ "pmaxsw %%mm6, %%mm2 \n\t" // |2L0 - 5L1 + 5L2 - 2L3|
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "psubw %%mm3, %%mm6 \n\t"
+ "pmaxsw %%mm6, %%mm3 \n\t" // |2H0 - 5H1 + 5H2 - 2H3|
+#else
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "pcmpgtw %%mm0, %%mm6 \n\t"
+ "pxor %%mm6, %%mm0 \n\t"
+ "psubw %%mm6, %%mm0 \n\t" // |2L4 - 5L5 + 5L6 - 2L7|
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "pcmpgtw %%mm1, %%mm6 \n\t"
+ "pxor %%mm6, %%mm1 \n\t"
+ "psubw %%mm6, %%mm1 \n\t" // |2H4 - 5H5 + 5H6 - 2H7|
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "pcmpgtw %%mm2, %%mm6 \n\t"
+ "pxor %%mm6, %%mm2 \n\t"
+ "psubw %%mm6, %%mm2 \n\t" // |2L0 - 5L1 + 5L2 - 2L3|
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "pcmpgtw %%mm3, %%mm6 \n\t"
+ "pxor %%mm6, %%mm3 \n\t"
+ "psubw %%mm6, %%mm3 \n\t" // |2H0 - 5H1 + 5H2 - 2H3|
+#endif
+
+#ifdef HAVE_MMX2
+ "pminsw %%mm2, %%mm0 \n\t"
+ "pminsw %%mm3, %%mm1 \n\t"
+#else
+ "movq %%mm0, %%mm6 \n\t"
+ "psubusw %%mm2, %%mm6 \n\t"
+ "psubw %%mm6, %%mm0 \n\t"
+ "movq %%mm1, %%mm6 \n\t"
+ "psubusw %%mm3, %%mm6 \n\t"
+ "psubw %%mm6, %%mm1 \n\t"
+#endif
+
+ "movd %2, %%mm2 \n\t" // QP
+ "punpcklbw %%mm7, %%mm2 \n\t"
+
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "pcmpgtw %%mm4, %%mm6 \n\t" // sign(2L2 - 5L3 + 5L4 - 2L5)
+ "pxor %%mm6, %%mm4 \n\t"
+ "psubw %%mm6, %%mm4 \n\t" // |2L2 - 5L3 + 5L4 - 2L5|
+ "pcmpgtw %%mm5, %%mm7 \n\t" // sign(2H2 - 5H3 + 5H4 - 2H5)
+ "pxor %%mm7, %%mm5 \n\t"
+ "psubw %%mm7, %%mm5 \n\t" // |2H2 - 5H3 + 5H4 - 2H5|
+// 100 opcodes
+ "psllw $3, %%mm2 \n\t" // 8QP
+ "movq %%mm2, %%mm3 \n\t" // 8QP
+ "pcmpgtw %%mm4, %%mm2 \n\t"
+ "pcmpgtw %%mm5, %%mm3 \n\t"
+ "pand %%mm2, %%mm4 \n\t"
+ "pand %%mm3, %%mm5 \n\t"
+
+
+ "psubusw %%mm0, %%mm4 \n\t" // hd
+ "psubusw %%mm1, %%mm5 \n\t" // ld
+
+
+ "movq "MANGLE(w05)", %%mm2 \n\t" // 5
+ "pmullw %%mm2, %%mm4 \n\t"
+ "pmullw %%mm2, %%mm5 \n\t"
+ "movq "MANGLE(w20)", %%mm2 \n\t" // 32
+ "paddw %%mm2, %%mm4 \n\t"
+ "paddw %%mm2, %%mm5 \n\t"
+ "psrlw $6, %%mm4 \n\t"
+ "psrlw $6, %%mm5 \n\t"
+
+ "movq 16(%%"REG_c"), %%mm0 \n\t" // L3 - L4
+ "movq 24(%%"REG_c"), %%mm1 \n\t" // H3 - H4
+
+ "pxor %%mm2, %%mm2 \n\t"
+ "pxor %%mm3, %%mm3 \n\t"
+
+ "pcmpgtw %%mm0, %%mm2 \n\t" // sign (L3-L4)
+ "pcmpgtw %%mm1, %%mm3 \n\t" // sign (H3-H4)
+ "pxor %%mm2, %%mm0 \n\t"
+ "pxor %%mm3, %%mm1 \n\t"
+ "psubw %%mm2, %%mm0 \n\t" // |L3-L4|
+ "psubw %%mm3, %%mm1 \n\t" // |H3-H4|
+ "psrlw $1, %%mm0 \n\t" // |L3 - L4|/2
+ "psrlw $1, %%mm1 \n\t" // |H3 - H4|/2
+
+ "pxor %%mm6, %%mm2 \n\t"
+ "pxor %%mm7, %%mm3 \n\t"
+ "pand %%mm2, %%mm4 \n\t"
+ "pand %%mm3, %%mm5 \n\t"
+
+#ifdef HAVE_MMX2
+ "pminsw %%mm0, %%mm4 \n\t"
+ "pminsw %%mm1, %%mm5 \n\t"
+#else
+ "movq %%mm4, %%mm2 \n\t"
+ "psubusw %%mm0, %%mm2 \n\t"
+ "psubw %%mm2, %%mm4 \n\t"
+ "movq %%mm5, %%mm2 \n\t"
+ "psubusw %%mm1, %%mm2 \n\t"
+ "psubw %%mm2, %%mm5 \n\t"
+#endif
+ "pxor %%mm6, %%mm4 \n\t"
+ "pxor %%mm7, %%mm5 \n\t"
+ "psubw %%mm6, %%mm4 \n\t"
+ "psubw %%mm7, %%mm5 \n\t"
+ "packsswb %%mm5, %%mm4 \n\t"
+ "movq (%0), %%mm0 \n\t"
+ "paddb %%mm4, %%mm0 \n\t"
+ "movq %%mm0, (%0) \n\t"
+ "movq (%0, %1), %%mm0 \n\t"
+ "psubb %%mm4, %%mm0 \n\t"
+ "movq %%mm0, (%0, %1) \n\t"
+
+ : "+r" (src)
+ : "r" ((long)stride), "m" (c->pQPb)
+ : "%"REG_a, "%"REG_c
+ );
+#else //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ const int l1= stride;
+ const int l2= stride + l1;
+ const int l3= stride + l2;
+ const int l4= stride + l3;
+ const int l5= stride + l4;
+ const int l6= stride + l5;
+ const int l7= stride + l6;
+ const int l8= stride + l7;
+// const int l9= stride + l8;
+ int x;
+ src+= stride*3;
+ for(x=0; x<BLOCK_SIZE; x++)
+ {
+ const int middleEnergy= 5*(src[l5] - src[l4]) + 2*(src[l3] - src[l6]);
+ if(FFABS(middleEnergy) < 8*c->QP)
+ {
+ const int q=(src[l4] - src[l5])/2;
+ const int leftEnergy= 5*(src[l3] - src[l2]) + 2*(src[l1] - src[l4]);
+ const int rightEnergy= 5*(src[l7] - src[l6]) + 2*(src[l5] - src[l8]);
+
+ int d= FFABS(middleEnergy) - FFMIN( FFABS(leftEnergy), FFABS(rightEnergy) );
+ d= FFMAX(d, 0);
+
+ d= (5*d + 32) >> 6;
+ d*= FFSIGN(-middleEnergy);
+
+ if(q>0)
+ {
+ d= d<0 ? 0 : d;
+ d= d>q ? q : d;
+ }
+ else
+ {
+ d= d>0 ? 0 : d;
+ d= d<q ? q : d;
+ }
+
+ src[l4]-= d;
+ src[l5]+= d;
+ }
+ src++;
+ }
+#endif //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+}
+#endif //HAVE_ALTIVEC
+
+#ifndef HAVE_ALTIVEC
+static inline void RENAME(dering)(uint8_t src[], int stride, PPContext *c)
+{
+#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ asm volatile(
+ "pxor %%mm6, %%mm6 \n\t"
+ "pcmpeqb %%mm7, %%mm7 \n\t"
+ "movq %2, %%mm0 \n\t"
+ "punpcklbw %%mm6, %%mm0 \n\t"
+ "psrlw $1, %%mm0 \n\t"
+ "psubw %%mm7, %%mm0 \n\t"
+ "packuswb %%mm0, %%mm0 \n\t"
+ "movq %%mm0, %3 \n\t"
+
+ "lea (%0, %1), %%"REG_a" \n\t"
+ "lea (%%"REG_a", %1, 4), %%"REG_d" \n\t"
+
+// 0 1 2 3 4 5 6 7 8 9
+// %0 eax eax+%1 eax+2%1 %0+4%1 edx edx+%1 edx+2%1 %0+8%1 edx+4%1
+
+#undef FIND_MIN_MAX
+#ifdef HAVE_MMX2
+#define REAL_FIND_MIN_MAX(addr)\
+ "movq " #addr ", %%mm0 \n\t"\
+ "pminub %%mm0, %%mm7 \n\t"\
+ "pmaxub %%mm0, %%mm6 \n\t"
+#else
+#define REAL_FIND_MIN_MAX(addr)\
+ "movq " #addr ", %%mm0 \n\t"\
+ "movq %%mm7, %%mm1 \n\t"\
+ "psubusb %%mm0, %%mm6 \n\t"\
+ "paddb %%mm0, %%mm6 \n\t"\
+ "psubusb %%mm0, %%mm1 \n\t"\
+ "psubb %%mm1, %%mm7 \n\t"
+#endif
+#define FIND_MIN_MAX(addr) REAL_FIND_MIN_MAX(addr)
+
+FIND_MIN_MAX((%%REGa))
+FIND_MIN_MAX((%%REGa, %1))
+FIND_MIN_MAX((%%REGa, %1, 2))
+FIND_MIN_MAX((%0, %1, 4))
+FIND_MIN_MAX((%%REGd))
+FIND_MIN_MAX((%%REGd, %1))
+FIND_MIN_MAX((%%REGd, %1, 2))
+FIND_MIN_MAX((%0, %1, 8))
+
+ "movq %%mm7, %%mm4 \n\t"
+ "psrlq $8, %%mm7 \n\t"
+#ifdef HAVE_MMX2
+ "pminub %%mm4, %%mm7 \n\t" // min of pixels
+ "pshufw $0xF9, %%mm7, %%mm4 \n\t"
+ "pminub %%mm4, %%mm7 \n\t" // min of pixels
+ "pshufw $0xFE, %%mm7, %%mm4 \n\t"
+ "pminub %%mm4, %%mm7 \n\t"
+#else
+ "movq %%mm7, %%mm1 \n\t"
+ "psubusb %%mm4, %%mm1 \n\t"
+ "psubb %%mm1, %%mm7 \n\t"
+ "movq %%mm7, %%mm4 \n\t"
+ "psrlq $16, %%mm7 \n\t"
+ "movq %%mm7, %%mm1 \n\t"
+ "psubusb %%mm4, %%mm1 \n\t"
+ "psubb %%mm1, %%mm7 \n\t"
+ "movq %%mm7, %%mm4 \n\t"
+ "psrlq $32, %%mm7 \n\t"
+ "movq %%mm7, %%mm1 \n\t"
+ "psubusb %%mm4, %%mm1 \n\t"
+ "psubb %%mm1, %%mm7 \n\t"
+#endif
+
+
+ "movq %%mm6, %%mm4 \n\t"
+ "psrlq $8, %%mm6 \n\t"
+#ifdef HAVE_MMX2
+ "pmaxub %%mm4, %%mm6 \n\t" // max of pixels
+ "pshufw $0xF9, %%mm6, %%mm4 \n\t"
+ "pmaxub %%mm4, %%mm6 \n\t"
+ "pshufw $0xFE, %%mm6, %%mm4 \n\t"
+ "pmaxub %%mm4, %%mm6 \n\t"
+#else
+ "psubusb %%mm4, %%mm6 \n\t"
+ "paddb %%mm4, %%mm6 \n\t"
+ "movq %%mm6, %%mm4 \n\t"
+ "psrlq $16, %%mm6 \n\t"
+ "psubusb %%mm4, %%mm6 \n\t"
+ "paddb %%mm4, %%mm6 \n\t"
+ "movq %%mm6, %%mm4 \n\t"
+ "psrlq $32, %%mm6 \n\t"
+ "psubusb %%mm4, %%mm6 \n\t"
+ "paddb %%mm4, %%mm6 \n\t"
+#endif
+ "movq %%mm6, %%mm0 \n\t" // max
+ "psubb %%mm7, %%mm6 \n\t" // max - min
+ "movd %%mm6, %%ecx \n\t"
+ "cmpb "MANGLE(deringThreshold)", %%cl \n\t"
+ " jb 1f \n\t"
+ "lea -24(%%"REG_SP"), %%"REG_c" \n\t"
+ "and "ALIGN_MASK", %%"REG_c" \n\t"
+ PAVGB(%%mm0, %%mm7) // a=(max + min)/2
+ "punpcklbw %%mm7, %%mm7 \n\t"
+ "punpcklbw %%mm7, %%mm7 \n\t"
+ "punpcklbw %%mm7, %%mm7 \n\t"
+ "movq %%mm7, (%%"REG_c") \n\t"
+
+ "movq (%0), %%mm0 \n\t" // L10
+ "movq %%mm0, %%mm1 \n\t" // L10
+ "movq %%mm0, %%mm2 \n\t" // L10
+ "psllq $8, %%mm1 \n\t"
+ "psrlq $8, %%mm2 \n\t"
+ "movd -4(%0), %%mm3 \n\t"
+ "movd 8(%0), %%mm4 \n\t"
+ "psrlq $24, %%mm3 \n\t"
+ "psllq $56, %%mm4 \n\t"
+ "por %%mm3, %%mm1 \n\t" // L00
+ "por %%mm4, %%mm2 \n\t" // L20
+ "movq %%mm1, %%mm3 \n\t" // L00
+ PAVGB(%%mm2, %%mm1) // (L20 + L00)/2
+ PAVGB(%%mm0, %%mm1) // (L20 + L00 + 2L10)/4
+ "psubusb %%mm7, %%mm0 \n\t"
+ "psubusb %%mm7, %%mm2 \n\t"
+ "psubusb %%mm7, %%mm3 \n\t"
+ "pcmpeqb "MANGLE(b00)", %%mm0 \n\t" // L10 > a ? 0 : -1
+ "pcmpeqb "MANGLE(b00)", %%mm2 \n\t" // L20 > a ? 0 : -1
+ "pcmpeqb "MANGLE(b00)", %%mm3 \n\t" // L00 > a ? 0 : -1
+ "paddb %%mm2, %%mm0 \n\t"
+ "paddb %%mm3, %%mm0 \n\t"
+
+ "movq (%%"REG_a"), %%mm2 \n\t" // L11
+ "movq %%mm2, %%mm3 \n\t" // L11
+ "movq %%mm2, %%mm4 \n\t" // L11
+ "psllq $8, %%mm3 \n\t"
+ "psrlq $8, %%mm4 \n\t"
+ "movd -4(%%"REG_a"), %%mm5 \n\t"
+ "movd 8(%%"REG_a"), %%mm6 \n\t"
+ "psrlq $24, %%mm5 \n\t"
+ "psllq $56, %%mm6 \n\t"
+ "por %%mm5, %%mm3 \n\t" // L01
+ "por %%mm6, %%mm4 \n\t" // L21
+ "movq %%mm3, %%mm5 \n\t" // L01
+ PAVGB(%%mm4, %%mm3) // (L21 + L01)/2
+ PAVGB(%%mm2, %%mm3) // (L21 + L01 + 2L11)/4
+ "psubusb %%mm7, %%mm2 \n\t"
+ "psubusb %%mm7, %%mm4 \n\t"
+ "psubusb %%mm7, %%mm5 \n\t"
+ "pcmpeqb "MANGLE(b00)", %%mm2 \n\t" // L11 > a ? 0 : -1
+ "pcmpeqb "MANGLE(b00)", %%mm4 \n\t" // L21 > a ? 0 : -1
+ "pcmpeqb "MANGLE(b00)", %%mm5 \n\t" // L01 > a ? 0 : -1
+ "paddb %%mm4, %%mm2 \n\t"
+ "paddb %%mm5, %%mm2 \n\t"
+// 0, 2, 3, 1
+#define REAL_DERING_CORE(dst,src,ppsx,psx,sx,pplx,plx,lx,t0,t1) \
+ "movq " #src ", " #sx " \n\t" /* src[0] */\
+ "movq " #sx ", " #lx " \n\t" /* src[0] */\
+ "movq " #sx ", " #t0 " \n\t" /* src[0] */\
+ "psllq $8, " #lx " \n\t"\
+ "psrlq $8, " #t0 " \n\t"\
+ "movd -4" #src ", " #t1 " \n\t"\
+ "psrlq $24, " #t1 " \n\t"\
+ "por " #t1 ", " #lx " \n\t" /* src[-1] */\
+ "movd 8" #src ", " #t1 " \n\t"\
+ "psllq $56, " #t1 " \n\t"\
+ "por " #t1 ", " #t0 " \n\t" /* src[+1] */\
+ "movq " #lx ", " #t1 " \n\t" /* src[-1] */\
+ PAVGB(t0, lx) /* (src[-1] + src[+1])/2 */\
+ PAVGB(sx, lx) /* (src[-1] + 2src[0] + src[+1])/4 */\
+ PAVGB(lx, pplx) \
+ "movq " #lx ", 8(%%"REG_c") \n\t"\
+ "movq (%%"REG_c"), " #lx " \n\t"\
+ "psubusb " #lx ", " #t1 " \n\t"\
+ "psubusb " #lx ", " #t0 " \n\t"\
+ "psubusb " #lx ", " #sx " \n\t"\
+ "movq "MANGLE(b00)", " #lx " \n\t"\
+ "pcmpeqb " #lx ", " #t1 " \n\t" /* src[-1] > a ? 0 : -1*/\
+ "pcmpeqb " #lx ", " #t0 " \n\t" /* src[+1] > a ? 0 : -1*/\
+ "pcmpeqb " #lx ", " #sx " \n\t" /* src[0] > a ? 0 : -1*/\
+ "paddb " #t1 ", " #t0 " \n\t"\
+ "paddb " #t0 ", " #sx " \n\t"\
+\
+ PAVGB(plx, pplx) /* filtered */\
+ "movq " #dst ", " #t0 " \n\t" /* dst */\
+ "movq " #t0 ", " #t1 " \n\t" /* dst */\
+ "psubusb %3, " #t0 " \n\t"\
+ "paddusb %3, " #t1 " \n\t"\
+ PMAXUB(t0, pplx)\
+ PMINUB(t1, pplx, t0)\
+ "paddb " #sx ", " #ppsx " \n\t"\
+ "paddb " #psx ", " #ppsx " \n\t"\
+ "#paddb "MANGLE(b02)", " #ppsx " \n\t"\
+ "pand "MANGLE(b08)", " #ppsx " \n\t"\
+ "pcmpeqb " #lx ", " #ppsx " \n\t"\
+ "pand " #ppsx ", " #pplx " \n\t"\
+ "pandn " #dst ", " #ppsx " \n\t"\
+ "por " #pplx ", " #ppsx " \n\t"\
+ "movq " #ppsx ", " #dst " \n\t"\
+ "movq 8(%%"REG_c"), " #lx " \n\t"
+
+#define DERING_CORE(dst,src,ppsx,psx,sx,pplx,plx,lx,t0,t1) \
+ REAL_DERING_CORE(dst,src,ppsx,psx,sx,pplx,plx,lx,t0,t1)
+/*
+0000000
+1111111
+
+1111110
+1111101
+1111100
+1111011
+1111010
+1111001
+
+1111000
+1110111
+
+*/
+//DERING_CORE(dst ,src ,ppsx ,psx ,sx ,pplx ,plx ,lx ,t0 ,t1)
+DERING_CORE((%%REGa) ,(%%REGa, %1) ,%%mm0,%%mm2,%%mm4,%%mm1,%%mm3,%%mm5,%%mm6,%%mm7)
+DERING_CORE((%%REGa, %1) ,(%%REGa, %1, 2),%%mm2,%%mm4,%%mm0,%%mm3,%%mm5,%%mm1,%%mm6,%%mm7)
+DERING_CORE((%%REGa, %1, 2),(%0, %1, 4) ,%%mm4,%%mm0,%%mm2,%%mm5,%%mm1,%%mm3,%%mm6,%%mm7)
+DERING_CORE((%0, %1, 4) ,(%%REGd) ,%%mm0,%%mm2,%%mm4,%%mm1,%%mm3,%%mm5,%%mm6,%%mm7)
+DERING_CORE((%%REGd) ,(%%REGd, %1) ,%%mm2,%%mm4,%%mm0,%%mm3,%%mm5,%%mm1,%%mm6,%%mm7)
+DERING_CORE((%%REGd, %1) ,(%%REGd, %1, 2),%%mm4,%%mm0,%%mm2,%%mm5,%%mm1,%%mm3,%%mm6,%%mm7)
+DERING_CORE((%%REGd, %1, 2),(%0, %1, 8) ,%%mm0,%%mm2,%%mm4,%%mm1,%%mm3,%%mm5,%%mm6,%%mm7)
+DERING_CORE((%0, %1, 8) ,(%%REGd, %1, 4),%%mm2,%%mm4,%%mm0,%%mm3,%%mm5,%%mm1,%%mm6,%%mm7)
+
+ "1: \n\t"
+ : : "r" (src), "r" ((long)stride), "m" (c->pQPb), "m"(c->pQPb2)
+ : "%"REG_a, "%"REG_d, "%"REG_c
+ );
+#else //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ int y;
+ int min=255;
+ int max=0;
+ int avg;
+ uint8_t *p;
+ int s[10];
+ const int QP2= c->QP/2 + 1;
+
+ for(y=1; y<9; y++)
+ {
+ int x;
+ p= src + stride*y;
+ for(x=1; x<9; x++)
+ {
+ p++;
+ if(*p > max) max= *p;
+ if(*p < min) min= *p;
+ }
+ }
+ avg= (min + max + 1)>>1;
+
+ if(max - min <deringThreshold) return;
+
+ for(y=0; y<10; y++)
+ {
+ int t = 0;
+
+ if(src[stride*y + 0] > avg) t+= 1;
+ if(src[stride*y + 1] > avg) t+= 2;
+ if(src[stride*y + 2] > avg) t+= 4;
+ if(src[stride*y + 3] > avg) t+= 8;
+ if(src[stride*y + 4] > avg) t+= 16;
+ if(src[stride*y + 5] > avg) t+= 32;
+ if(src[stride*y + 6] > avg) t+= 64;
+ if(src[stride*y + 7] > avg) t+= 128;
+ if(src[stride*y + 8] > avg) t+= 256;
+ if(src[stride*y + 9] > avg) t+= 512;
+
+ t |= (~t)<<16;
+ t &= (t<<1) & (t>>1);
+ s[y] = t;
+ }
+
+ for(y=1; y<9; y++)
+ {
+ int t = s[y-1] & s[y] & s[y+1];
+ t|= t>>16;
+ s[y-1]= t;
+ }
+
+ for(y=1; y<9; y++)
+ {
+ int x;
+ int t = s[y-1];
+
+ p= src + stride*y;
+ for(x=1; x<9; x++)
+ {
+ p++;
+ if(t & (1<<x))
+ {
+ int f= (*(p-stride-1)) + 2*(*(p-stride)) + (*(p-stride+1))
+ +2*(*(p -1)) + 4*(*p ) + 2*(*(p +1))
+ +(*(p+stride-1)) + 2*(*(p+stride)) + (*(p+stride+1));
+ f= (f + 8)>>4;
+
+#ifdef DEBUG_DERING_THRESHOLD
+ asm volatile("emms\n\t":);
+ {
+ static long long numPixels=0;
+ if(x!=1 && x!=8 && y!=1 && y!=8) numPixels++;
+// if((max-min)<20 || (max-min)*QP<200)
+// if((max-min)*QP < 500)
+// if(max-min<QP/2)
+ if(max-min < 20)
+ {
+ static int numSkiped=0;
+ static int errorSum=0;
+ static int worstQP=0;
+ static int worstRange=0;
+ static int worstDiff=0;
+ int diff= (f - *p);
+ int absDiff= FFABS(diff);
+ int error= diff*diff;
+
+ if(x==1 || x==8 || y==1 || y==8) continue;
+
+ numSkiped++;
+ if(absDiff > worstDiff)
+ {
+ worstDiff= absDiff;
+ worstQP= QP;
+ worstRange= max-min;
+ }
+ errorSum+= error;
+
+ if(1024LL*1024LL*1024LL % numSkiped == 0)
+ {
+ av_log(c, AV_LOG_INFO, "sum:%1.3f, skip:%d, wQP:%d, "
+ "wRange:%d, wDiff:%d, relSkip:%1.3f\n",
+ (float)errorSum/numSkiped, numSkiped, worstQP, worstRange,
+ worstDiff, (float)numSkiped/numPixels);
+ }
+ }
+ }
+#endif
+ if (*p + QP2 < f) *p= *p + QP2;
+ else if(*p - QP2 > f) *p= *p - QP2;
+ else *p=f;
+ }
+ }
+ }
+#ifdef DEBUG_DERING_THRESHOLD
+ if(max-min < 20)
+ {
+ for(y=1; y<9; y++)
+ {
+ int x;
+ int t = 0;
+ p= src + stride*y;
+ for(x=1; x<9; x++)
+ {
+ p++;
+ *p = FFMIN(*p + 20, 255);
+ }
+ }
+// src[0] = src[7]=src[stride*7]=src[stride*7 + 7]=255;
+ }
+#endif
+#endif //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+}
+#endif //HAVE_ALTIVEC
+
+/**
+ * Deinterlaces the given block by linearly interpolating every second line.
+ * will be called for every 8x8 block and can read & write from line 4-15
+ * lines 0-3 have been passed through the deblock / dering filters allready, but can be read too
+ * lines 4-12 will be read into the deblocking filter and should be deinterlaced
+ */
+static inline void RENAME(deInterlaceInterpolateLinear)(uint8_t src[], int stride)
+{
+#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ src+= 4*stride;
+ asm volatile(
+ "lea (%0, %1), %%"REG_a" \n\t"
+ "lea (%%"REG_a", %1, 4), %%"REG_c" \n\t"
+// 0 1 2 3 4 5 6 7 8 9
+// %0 eax eax+%1 eax+2%1 %0+4%1 ecx ecx+%1 ecx+2%1 %0+8%1 ecx+4%1
+
+ "movq (%0), %%mm0 \n\t"
+ "movq (%%"REG_a", %1), %%mm1 \n\t"
+ PAVGB(%%mm1, %%mm0)
+ "movq %%mm0, (%%"REG_a") \n\t"
+ "movq (%0, %1, 4), %%mm0 \n\t"
+ PAVGB(%%mm0, %%mm1)
+ "movq %%mm1, (%%"REG_a", %1, 2) \n\t"
+ "movq (%%"REG_c", %1), %%mm1 \n\t"
+ PAVGB(%%mm1, %%mm0)
+ "movq %%mm0, (%%"REG_c") \n\t"
+ "movq (%0, %1, 8), %%mm0 \n\t"
+ PAVGB(%%mm0, %%mm1)
+ "movq %%mm1, (%%"REG_c", %1, 2) \n\t"
+
+ : : "r" (src), "r" ((long)stride)
+ : "%"REG_a, "%"REG_c
+ );
+#else
+ int a, b, x;
+ src+= 4*stride;
+
+ for(x=0; x<2; x++){
+ a= *(uint32_t*)&src[stride*0];
+ b= *(uint32_t*)&src[stride*2];
+ *(uint32_t*)&src[stride*1]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
+ a= *(uint32_t*)&src[stride*4];
+ *(uint32_t*)&src[stride*3]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
+ b= *(uint32_t*)&src[stride*6];
+ *(uint32_t*)&src[stride*5]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
+ a= *(uint32_t*)&src[stride*8];
+ *(uint32_t*)&src[stride*7]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
+ src += 4;
+ }
+#endif
+}
+
+/**
+ * Deinterlaces the given block by cubic interpolating every second line.
+ * will be called for every 8x8 block and can read & write from line 4-15
+ * lines 0-3 have been passed through the deblock / dering filters allready, but can be read too
+ * lines 4-12 will be read into the deblocking filter and should be deinterlaced
+ * this filter will read lines 3-15 and write 7-13
+ */
+static inline void RENAME(deInterlaceInterpolateCubic)(uint8_t src[], int stride)
+{
+#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ src+= stride*3;
+ asm volatile(
+ "lea (%0, %1), %%"REG_a" \n\t"
+ "lea (%%"REG_a", %1, 4), %%"REG_d" \n\t"
+ "lea (%%"REG_d", %1, 4), %%"REG_c" \n\t"
+ "add %1, %%"REG_c" \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+// 0 1 2 3 4 5 6 7 8 9 10
+// %0 eax eax+%1 eax+2%1 %0+4%1 edx edx+%1 edx+2%1 %0+8%1 edx+4%1 ecx
+
+#define REAL_DEINT_CUBIC(a,b,c,d,e)\
+ "movq " #a ", %%mm0 \n\t"\
+ "movq " #b ", %%mm1 \n\t"\
+ "movq " #d ", %%mm2 \n\t"\
+ "movq " #e ", %%mm3 \n\t"\
+ PAVGB(%%mm2, %%mm1) /* (b+d) /2 */\
+ PAVGB(%%mm3, %%mm0) /* a(a+e) /2 */\
+ "movq %%mm0, %%mm2 \n\t"\
+ "punpcklbw %%mm7, %%mm0 \n\t"\
+ "punpckhbw %%mm7, %%mm2 \n\t"\
+ "movq %%mm1, %%mm3 \n\t"\
+ "punpcklbw %%mm7, %%mm1 \n\t"\
+ "punpckhbw %%mm7, %%mm3 \n\t"\
+ "psubw %%mm1, %%mm0 \n\t" /* L(a+e - (b+d))/2 */\
+ "psubw %%mm3, %%mm2 \n\t" /* H(a+e - (b+d))/2 */\
+ "psraw $3, %%mm0 \n\t" /* L(a+e - (b+d))/16 */\
+ "psraw $3, %%mm2 \n\t" /* H(a+e - (b+d))/16 */\
+ "psubw %%mm0, %%mm1 \n\t" /* L(9b + 9d - a - e)/16 */\
+ "psubw %%mm2, %%mm3 \n\t" /* H(9b + 9d - a - e)/16 */\
+ "packuswb %%mm3, %%mm1 \n\t"\
+ "movq %%mm1, " #c " \n\t"
+#define DEINT_CUBIC(a,b,c,d,e) REAL_DEINT_CUBIC(a,b,c,d,e)
+
+DEINT_CUBIC((%0) , (%%REGa, %1), (%%REGa, %1, 2), (%0, %1, 4) , (%%REGd, %1))
+DEINT_CUBIC((%%REGa, %1), (%0, %1, 4) , (%%REGd) , (%%REGd, %1), (%0, %1, 8))
+DEINT_CUBIC((%0, %1, 4) , (%%REGd, %1), (%%REGd, %1, 2), (%0, %1, 8) , (%%REGc))
+DEINT_CUBIC((%%REGd, %1), (%0, %1, 8) , (%%REGd, %1, 4), (%%REGc) , (%%REGc, %1, 2))
+
+ : : "r" (src), "r" ((long)stride)
+ : "%"REG_a, "%"REG_d, "%"REG_c
+ );
+#else //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ int x;
+ src+= stride*3;
+ for(x=0; x<8; x++)
+ {
+ src[stride*3] = CLIP((-src[0] + 9*src[stride*2] + 9*src[stride*4] - src[stride*6])>>4);
+ src[stride*5] = CLIP((-src[stride*2] + 9*src[stride*4] + 9*src[stride*6] - src[stride*8])>>4);
+ src[stride*7] = CLIP((-src[stride*4] + 9*src[stride*6] + 9*src[stride*8] - src[stride*10])>>4);
+ src[stride*9] = CLIP((-src[stride*6] + 9*src[stride*8] + 9*src[stride*10] - src[stride*12])>>4);
+ src++;
+ }
+#endif //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+}
+
+/**
+ * Deinterlaces the given block by filtering every second line with a (-1 4 2 4 -1) filter.
+ * will be called for every 8x8 block and can read & write from line 4-15
+ * lines 0-3 have been passed through the deblock / dering filters allready, but can be read too
+ * lines 4-12 will be read into the deblocking filter and should be deinterlaced
+ * this filter will read lines 4-13 and write 5-11
+ */
+static inline void RENAME(deInterlaceFF)(uint8_t src[], int stride, uint8_t *tmp)
+{
+#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ src+= stride*4;
+ asm volatile(
+ "lea (%0, %1), %%"REG_a" \n\t"
+ "lea (%%"REG_a", %1, 4), %%"REG_d" \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+ "movq (%2), %%mm0 \n\t"
+// 0 1 2 3 4 5 6 7 8 9 10
+// %0 eax eax+%1 eax+2%1 %0+4%1 edx edx+%1 edx+2%1 %0+8%1 edx+4%1 ecx
+
+#define REAL_DEINT_FF(a,b,c,d)\
+ "movq " #a ", %%mm1 \n\t"\
+ "movq " #b ", %%mm2 \n\t"\
+ "movq " #c ", %%mm3 \n\t"\
+ "movq " #d ", %%mm4 \n\t"\
+ PAVGB(%%mm3, %%mm1) \
+ PAVGB(%%mm4, %%mm0) \
+ "movq %%mm0, %%mm3 \n\t"\
+ "punpcklbw %%mm7, %%mm0 \n\t"\
+ "punpckhbw %%mm7, %%mm3 \n\t"\
+ "movq %%mm1, %%mm4 \n\t"\
+ "punpcklbw %%mm7, %%mm1 \n\t"\
+ "punpckhbw %%mm7, %%mm4 \n\t"\
+ "psllw $2, %%mm1 \n\t"\
+ "psllw $2, %%mm4 \n\t"\
+ "psubw %%mm0, %%mm1 \n\t"\
+ "psubw %%mm3, %%mm4 \n\t"\
+ "movq %%mm2, %%mm5 \n\t"\
+ "movq %%mm2, %%mm0 \n\t"\
+ "punpcklbw %%mm7, %%mm2 \n\t"\
+ "punpckhbw %%mm7, %%mm5 \n\t"\
+ "paddw %%mm2, %%mm1 \n\t"\
+ "paddw %%mm5, %%mm4 \n\t"\
+ "psraw $2, %%mm1 \n\t"\
+ "psraw $2, %%mm4 \n\t"\
+ "packuswb %%mm4, %%mm1 \n\t"\
+ "movq %%mm1, " #b " \n\t"\
+
+#define DEINT_FF(a,b,c,d) REAL_DEINT_FF(a,b,c,d)
+
+DEINT_FF((%0) , (%%REGa) , (%%REGa, %1), (%%REGa, %1, 2))
+DEINT_FF((%%REGa, %1), (%%REGa, %1, 2), (%0, %1, 4) , (%%REGd) )
+DEINT_FF((%0, %1, 4) , (%%REGd) , (%%REGd, %1), (%%REGd, %1, 2))
+DEINT_FF((%%REGd, %1), (%%REGd, %1, 2), (%0, %1, 8) , (%%REGd, %1, 4))
+
+ "movq %%mm0, (%2) \n\t"
+ : : "r" (src), "r" ((long)stride), "r"(tmp)
+ : "%"REG_a, "%"REG_d
+ );
+#else //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ int x;
+ src+= stride*4;
+ for(x=0; x<8; x++)
+ {
+ int t1= tmp[x];
+ int t2= src[stride*1];
+
+ src[stride*1]= CLIP((-t1 + 4*src[stride*0] + 2*t2 + 4*src[stride*2] - src[stride*3] + 4)>>3);
+ t1= src[stride*4];
+ src[stride*3]= CLIP((-t2 + 4*src[stride*2] + 2*t1 + 4*src[stride*4] - src[stride*5] + 4)>>3);
+ t2= src[stride*6];
+ src[stride*5]= CLIP((-t1 + 4*src[stride*4] + 2*t2 + 4*src[stride*6] - src[stride*7] + 4)>>3);
+ t1= src[stride*8];
+ src[stride*7]= CLIP((-t2 + 4*src[stride*6] + 2*t1 + 4*src[stride*8] - src[stride*9] + 4)>>3);
+ tmp[x]= t1;
+
+ src++;
+ }
+#endif //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+}
+
+/**
+ * Deinterlaces the given block by filtering every line with a (-1 2 6 2 -1) filter.
+ * will be called for every 8x8 block and can read & write from line 4-15
+ * lines 0-3 have been passed through the deblock / dering filters allready, but can be read too
+ * lines 4-12 will be read into the deblocking filter and should be deinterlaced
+ * this filter will read lines 4-13 and write 4-11
+ */
+static inline void RENAME(deInterlaceL5)(uint8_t src[], int stride, uint8_t *tmp, uint8_t *tmp2)
+{
+#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ src+= stride*4;
+ asm volatile(
+ "lea (%0, %1), %%"REG_a" \n\t"
+ "lea (%%"REG_a", %1, 4), %%"REG_d" \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+ "movq (%2), %%mm0 \n\t"
+ "movq (%3), %%mm1 \n\t"
+// 0 1 2 3 4 5 6 7 8 9 10
+// %0 eax eax+%1 eax+2%1 %0+4%1 edx edx+%1 edx+2%1 %0+8%1 edx+4%1 ecx
+
+#define REAL_DEINT_L5(t1,t2,a,b,c)\
+ "movq " #a ", %%mm2 \n\t"\
+ "movq " #b ", %%mm3 \n\t"\
+ "movq " #c ", %%mm4 \n\t"\
+ PAVGB(t2, %%mm3) \
+ PAVGB(t1, %%mm4) \
+ "movq %%mm2, %%mm5 \n\t"\
+ "movq %%mm2, " #t1 " \n\t"\
+ "punpcklbw %%mm7, %%mm2 \n\t"\
+ "punpckhbw %%mm7, %%mm5 \n\t"\
+ "movq %%mm2, %%mm6 \n\t"\
+ "paddw %%mm2, %%mm2 \n\t"\
+ "paddw %%mm6, %%mm2 \n\t"\
+ "movq %%mm5, %%mm6 \n\t"\
+ "paddw %%mm5, %%mm5 \n\t"\
+ "paddw %%mm6, %%mm5 \n\t"\
+ "movq %%mm3, %%mm6 \n\t"\
+ "punpcklbw %%mm7, %%mm3 \n\t"\
+ "punpckhbw %%mm7, %%mm6 \n\t"\
+ "paddw %%mm3, %%mm3 \n\t"\
+ "paddw %%mm6, %%mm6 \n\t"\
+ "paddw %%mm3, %%mm2 \n\t"\
+ "paddw %%mm6, %%mm5 \n\t"\
+ "movq %%mm4, %%mm6 \n\t"\
+ "punpcklbw %%mm7, %%mm4 \n\t"\
+ "punpckhbw %%mm7, %%mm6 \n\t"\
+ "psubw %%mm4, %%mm2 \n\t"\
+ "psubw %%mm6, %%mm5 \n\t"\
+ "psraw $2, %%mm2 \n\t"\
+ "psraw $2, %%mm5 \n\t"\
+ "packuswb %%mm5, %%mm2 \n\t"\
+ "movq %%mm2, " #a " \n\t"\
+
+#define DEINT_L5(t1,t2,a,b,c) REAL_DEINT_L5(t1,t2,a,b,c)
+
+DEINT_L5(%%mm0, %%mm1, (%0) , (%%REGa) , (%%REGa, %1) )
+DEINT_L5(%%mm1, %%mm0, (%%REGa) , (%%REGa, %1) , (%%REGa, %1, 2))
+DEINT_L5(%%mm0, %%mm1, (%%REGa, %1) , (%%REGa, %1, 2), (%0, %1, 4) )
+DEINT_L5(%%mm1, %%mm0, (%%REGa, %1, 2), (%0, %1, 4) , (%%REGd) )
+DEINT_L5(%%mm0, %%mm1, (%0, %1, 4) , (%%REGd) , (%%REGd, %1) )
+DEINT_L5(%%mm1, %%mm0, (%%REGd) , (%%REGd, %1) , (%%REGd, %1, 2))
+DEINT_L5(%%mm0, %%mm1, (%%REGd, %1) , (%%REGd, %1, 2), (%0, %1, 8) )
+DEINT_L5(%%mm1, %%mm0, (%%REGd, %1, 2), (%0, %1, 8) , (%%REGd, %1, 4))
+
+ "movq %%mm0, (%2) \n\t"
+ "movq %%mm1, (%3) \n\t"
+ : : "r" (src), "r" ((long)stride), "r"(tmp), "r"(tmp2)
+ : "%"REG_a, "%"REG_d
+ );
+#else //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ int x;
+ src+= stride*4;
+ for(x=0; x<8; x++)
+ {
+ int t1= tmp[x];
+ int t2= tmp2[x];
+ int t3= src[0];
+
+ src[stride*0]= CLIP((-(t1 + src[stride*2]) + 2*(t2 + src[stride*1]) + 6*t3 + 4)>>3);
+ t1= src[stride*1];
+ src[stride*1]= CLIP((-(t2 + src[stride*3]) + 2*(t3 + src[stride*2]) + 6*t1 + 4)>>3);
+ t2= src[stride*2];
+ src[stride*2]= CLIP((-(t3 + src[stride*4]) + 2*(t1 + src[stride*3]) + 6*t2 + 4)>>3);
+ t3= src[stride*3];
+ src[stride*3]= CLIP((-(t1 + src[stride*5]) + 2*(t2 + src[stride*4]) + 6*t3 + 4)>>3);
+ t1= src[stride*4];
+ src[stride*4]= CLIP((-(t2 + src[stride*6]) + 2*(t3 + src[stride*5]) + 6*t1 + 4)>>3);
+ t2= src[stride*5];
+ src[stride*5]= CLIP((-(t3 + src[stride*7]) + 2*(t1 + src[stride*6]) + 6*t2 + 4)>>3);
+ t3= src[stride*6];
+ src[stride*6]= CLIP((-(t1 + src[stride*8]) + 2*(t2 + src[stride*7]) + 6*t3 + 4)>>3);
+ t1= src[stride*7];
+ src[stride*7]= CLIP((-(t2 + src[stride*9]) + 2*(t3 + src[stride*8]) + 6*t1 + 4)>>3);
+
+ tmp[x]= t3;
+ tmp2[x]= t1;
+
+ src++;
+ }
+#endif //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+}
+
+/**
+ * Deinterlaces the given block by filtering all lines with a (1 2 1) filter.
+ * will be called for every 8x8 block and can read & write from line 4-15
+ * lines 0-3 have been passed through the deblock / dering filters allready, but can be read too
+ * lines 4-12 will be read into the deblocking filter and should be deinterlaced
+ * this filter will read lines 4-13 and write 4-11
+ */
+static inline void RENAME(deInterlaceBlendLinear)(uint8_t src[], int stride, uint8_t *tmp)
+{
+#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ src+= 4*stride;
+ asm volatile(
+ "lea (%0, %1), %%"REG_a" \n\t"
+ "lea (%%"REG_a", %1, 4), %%"REG_d" \n\t"
+// 0 1 2 3 4 5 6 7 8 9
+// %0 eax eax+%1 eax+2%1 %0+4%1 edx edx+%1 edx+2%1 %0+8%1 edx+4%1
+
+ "movq (%2), %%mm0 \n\t" // L0
+ "movq (%%"REG_a"), %%mm1 \n\t" // L2
+ PAVGB(%%mm1, %%mm0) // L0+L2
+ "movq (%0), %%mm2 \n\t" // L1
+ PAVGB(%%mm2, %%mm0)
+ "movq %%mm0, (%0) \n\t"
+ "movq (%%"REG_a", %1), %%mm0 \n\t" // L3
+ PAVGB(%%mm0, %%mm2) // L1+L3
+ PAVGB(%%mm1, %%mm2) // 2L2 + L1 + L3
+ "movq %%mm2, (%%"REG_a") \n\t"
+ "movq (%%"REG_a", %1, 2), %%mm2 \n\t" // L4
+ PAVGB(%%mm2, %%mm1) // L2+L4
+ PAVGB(%%mm0, %%mm1) // 2L3 + L2 + L4
+ "movq %%mm1, (%%"REG_a", %1) \n\t"
+ "movq (%0, %1, 4), %%mm1 \n\t" // L5
+ PAVGB(%%mm1, %%mm0) // L3+L5
+ PAVGB(%%mm2, %%mm0) // 2L4 + L3 + L5
+ "movq %%mm0, (%%"REG_a", %1, 2) \n\t"
+ "movq (%%"REG_d"), %%mm0 \n\t" // L6
+ PAVGB(%%mm0, %%mm2) // L4+L6
+ PAVGB(%%mm1, %%mm2) // 2L5 + L4 + L6
+ "movq %%mm2, (%0, %1, 4) \n\t"
+ "movq (%%"REG_d", %1), %%mm2 \n\t" // L7
+ PAVGB(%%mm2, %%mm1) // L5+L7
+ PAVGB(%%mm0, %%mm1) // 2L6 + L5 + L7
+ "movq %%mm1, (%%"REG_d") \n\t"
+ "movq (%%"REG_d", %1, 2), %%mm1 \n\t" // L8
+ PAVGB(%%mm1, %%mm0) // L6+L8
+ PAVGB(%%mm2, %%mm0) // 2L7 + L6 + L8
+ "movq %%mm0, (%%"REG_d", %1) \n\t"
+ "movq (%0, %1, 8), %%mm0 \n\t" // L9
+ PAVGB(%%mm0, %%mm2) // L7+L9
+ PAVGB(%%mm1, %%mm2) // 2L8 + L7 + L9
+ "movq %%mm2, (%%"REG_d", %1, 2) \n\t"
+ "movq %%mm1, (%2) \n\t"
+
+ : : "r" (src), "r" ((long)stride), "r" (tmp)
+ : "%"REG_a, "%"REG_d
+ );
+#else //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ int a, b, c, x;
+ src+= 4*stride;
+
+ for(x=0; x<2; x++){
+ a= *(uint32_t*)&tmp[stride*0];
+ b= *(uint32_t*)&src[stride*0];
+ c= *(uint32_t*)&src[stride*1];
+ a= (a&c) + (((a^c)&0xFEFEFEFEUL)>>1);
+ *(uint32_t*)&src[stride*0]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
+
+ a= *(uint32_t*)&src[stride*2];
+ b= (a&b) + (((a^b)&0xFEFEFEFEUL)>>1);
+ *(uint32_t*)&src[stride*1]= (c|b) - (((c^b)&0xFEFEFEFEUL)>>1);
+
+ b= *(uint32_t*)&src[stride*3];
+ c= (b&c) + (((b^c)&0xFEFEFEFEUL)>>1);
+ *(uint32_t*)&src[stride*2]= (c|a) - (((c^a)&0xFEFEFEFEUL)>>1);
+
+ c= *(uint32_t*)&src[stride*4];
+ a= (a&c) + (((a^c)&0xFEFEFEFEUL)>>1);
+ *(uint32_t*)&src[stride*3]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
+
+ a= *(uint32_t*)&src[stride*5];
+ b= (a&b) + (((a^b)&0xFEFEFEFEUL)>>1);
+ *(uint32_t*)&src[stride*4]= (c|b) - (((c^b)&0xFEFEFEFEUL)>>1);
+
+ b= *(uint32_t*)&src[stride*6];
+ c= (b&c) + (((b^c)&0xFEFEFEFEUL)>>1);
+ *(uint32_t*)&src[stride*5]= (c|a) - (((c^a)&0xFEFEFEFEUL)>>1);
+
+ c= *(uint32_t*)&src[stride*7];
+ a= (a&c) + (((a^c)&0xFEFEFEFEUL)>>1);
+ *(uint32_t*)&src[stride*6]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
+
+ a= *(uint32_t*)&src[stride*8];
+ b= (a&b) + (((a^b)&0xFEFEFEFEUL)>>1);
+ *(uint32_t*)&src[stride*7]= (c|b) - (((c^b)&0xFEFEFEFEUL)>>1);
+
+ *(uint32_t*)&tmp[stride*0]= c;
+ src += 4;
+ tmp += 4;
+ }
+#endif //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+}
+
+/**
+ * Deinterlaces the given block by applying a median filter to every second line.
+ * will be called for every 8x8 block and can read & write from line 4-15,
+ * lines 0-3 have been passed through the deblock / dering filters allready, but can be read too
+ * lines 4-12 will be read into the deblocking filter and should be deinterlaced
+ */
+static inline void RENAME(deInterlaceMedian)(uint8_t src[], int stride)
+{
+#ifdef HAVE_MMX
+ src+= 4*stride;
+#ifdef HAVE_MMX2
+ asm volatile(
+ "lea (%0, %1), %%"REG_a" \n\t"
+ "lea (%%"REG_a", %1, 4), %%"REG_d" \n\t"
+// 0 1 2 3 4 5 6 7 8 9
+// %0 eax eax+%1 eax+2%1 %0+4%1 edx edx+%1 edx+2%1 %0+8%1 edx+4%1
+
+ "movq (%0), %%mm0 \n\t" //
+ "movq (%%"REG_a", %1), %%mm2 \n\t" //
+ "movq (%%"REG_a"), %%mm1 \n\t" //
+ "movq %%mm0, %%mm3 \n\t"
+ "pmaxub %%mm1, %%mm0 \n\t" //
+ "pminub %%mm3, %%mm1 \n\t" //
+ "pmaxub %%mm2, %%mm1 \n\t" //
+ "pminub %%mm1, %%mm0 \n\t"
+ "movq %%mm0, (%%"REG_a") \n\t"
+
+ "movq (%0, %1, 4), %%mm0 \n\t" //
+ "movq (%%"REG_a", %1, 2), %%mm1 \n\t" //
+ "movq %%mm2, %%mm3 \n\t"
+ "pmaxub %%mm1, %%mm2 \n\t" //
+ "pminub %%mm3, %%mm1 \n\t" //
+ "pmaxub %%mm0, %%mm1 \n\t" //
+ "pminub %%mm1, %%mm2 \n\t"
+ "movq %%mm2, (%%"REG_a", %1, 2) \n\t"
+
+ "movq (%%"REG_d"), %%mm2 \n\t" //
+ "movq (%%"REG_d", %1), %%mm1 \n\t" //
+ "movq %%mm2, %%mm3 \n\t"
+ "pmaxub %%mm0, %%mm2 \n\t" //
+ "pminub %%mm3, %%mm0 \n\t" //
+ "pmaxub %%mm1, %%mm0 \n\t" //
+ "pminub %%mm0, %%mm2 \n\t"
+ "movq %%mm2, (%%"REG_d") \n\t"
+
+ "movq (%%"REG_d", %1, 2), %%mm2 \n\t" //
+ "movq (%0, %1, 8), %%mm0 \n\t" //
+ "movq %%mm2, %%mm3 \n\t"
+ "pmaxub %%mm0, %%mm2 \n\t" //
+ "pminub %%mm3, %%mm0 \n\t" //
+ "pmaxub %%mm1, %%mm0 \n\t" //
+ "pminub %%mm0, %%mm2 \n\t"
+ "movq %%mm2, (%%"REG_d", %1, 2) \n\t"
+
+
+ : : "r" (src), "r" ((long)stride)
+ : "%"REG_a, "%"REG_d
+ );
+
+#else // MMX without MMX2
+ asm volatile(
+ "lea (%0, %1), %%"REG_a" \n\t"
+ "lea (%%"REG_a", %1, 4), %%"REG_d" \n\t"
+// 0 1 2 3 4 5 6 7 8 9
+// %0 eax eax+%1 eax+2%1 %0+4%1 edx edx+%1 edx+2%1 %0+8%1 edx+4%1
+ "pxor %%mm7, %%mm7 \n\t"
+
+#define REAL_MEDIAN(a,b,c)\
+ "movq " #a ", %%mm0 \n\t"\
+ "movq " #b ", %%mm2 \n\t"\
+ "movq " #c ", %%mm1 \n\t"\
+ "movq %%mm0, %%mm3 \n\t"\
+ "movq %%mm1, %%mm4 \n\t"\
+ "movq %%mm2, %%mm5 \n\t"\
+ "psubusb %%mm1, %%mm3 \n\t"\
+ "psubusb %%mm2, %%mm4 \n\t"\
+ "psubusb %%mm0, %%mm5 \n\t"\
+ "pcmpeqb %%mm7, %%mm3 \n\t"\
+ "pcmpeqb %%mm7, %%mm4 \n\t"\
+ "pcmpeqb %%mm7, %%mm5 \n\t"\
+ "movq %%mm3, %%mm6 \n\t"\
+ "pxor %%mm4, %%mm3 \n\t"\
+ "pxor %%mm5, %%mm4 \n\t"\
+ "pxor %%mm6, %%mm5 \n\t"\
+ "por %%mm3, %%mm1 \n\t"\
+ "por %%mm4, %%mm2 \n\t"\
+ "por %%mm5, %%mm0 \n\t"\
+ "pand %%mm2, %%mm0 \n\t"\
+ "pand %%mm1, %%mm0 \n\t"\
+ "movq %%mm0, " #b " \n\t"
+#define MEDIAN(a,b,c) REAL_MEDIAN(a,b,c)
+
+MEDIAN((%0) , (%%REGa) , (%%REGa, %1))
+MEDIAN((%%REGa, %1), (%%REGa, %1, 2), (%0, %1, 4))
+MEDIAN((%0, %1, 4) , (%%REGd) , (%%REGd, %1))
+MEDIAN((%%REGd, %1), (%%REGd, %1, 2), (%0, %1, 8))
+
+ : : "r" (src), "r" ((long)stride)
+ : "%"REG_a, "%"REG_d
+ );
+#endif //HAVE_MMX2
+#else //HAVE_MMX
+ int x, y;
+ src+= 4*stride;
+ // FIXME - there should be a way to do a few columns in parallel like w/mmx
+ for(x=0; x<8; x++)
+ {
+ uint8_t *colsrc = src;
+ for (y=0; y<4; y++)
+ {
+ int a, b, c, d, e, f;
+ a = colsrc[0 ];
+ b = colsrc[stride ];
+ c = colsrc[stride*2];
+ d = (a-b)>>31;
+ e = (b-c)>>31;
+ f = (c-a)>>31;
+ colsrc[stride ] = (a|(d^f)) & (b|(d^e)) & (c|(e^f));
+ colsrc += stride*2;
+ }
+ src++;
+ }
+#endif //HAVE_MMX
+}
+
+#ifdef HAVE_MMX
+/**
+ * transposes and shift the given 8x8 Block into dst1 and dst2
+ */
+static inline void RENAME(transpose1)(uint8_t *dst1, uint8_t *dst2, uint8_t *src, int srcStride)
+{
+ asm(
+ "lea (%0, %1), %%"REG_a" \n\t"
+// 0 1 2 3 4 5 6 7 8 9
+// %0 eax eax+%1 eax+2%1 %0+4%1 edx edx+%1 edx+2%1 %0+8%1 edx+4%1
+ "movq (%0), %%mm0 \n\t" // 12345678
+ "movq (%%"REG_a"), %%mm1 \n\t" // abcdefgh
+ "movq %%mm0, %%mm2 \n\t" // 12345678
+ "punpcklbw %%mm1, %%mm0 \n\t" // 1a2b3c4d
+ "punpckhbw %%mm1, %%mm2 \n\t" // 5e6f7g8h
+
+ "movq (%%"REG_a", %1), %%mm1 \n\t"
+ "movq (%%"REG_a", %1, 2), %%mm3 \n\t"
+ "movq %%mm1, %%mm4 \n\t"
+ "punpcklbw %%mm3, %%mm1 \n\t"
+ "punpckhbw %%mm3, %%mm4 \n\t"
+
+ "movq %%mm0, %%mm3 \n\t"
+ "punpcklwd %%mm1, %%mm0 \n\t"
+ "punpckhwd %%mm1, %%mm3 \n\t"
+ "movq %%mm2, %%mm1 \n\t"
+ "punpcklwd %%mm4, %%mm2 \n\t"
+ "punpckhwd %%mm4, %%mm1 \n\t"
+
+ "movd %%mm0, 128(%2) \n\t"
+ "psrlq $32, %%mm0 \n\t"
+ "movd %%mm0, 144(%2) \n\t"
+ "movd %%mm3, 160(%2) \n\t"
+ "psrlq $32, %%mm3 \n\t"
+ "movd %%mm3, 176(%2) \n\t"
+ "movd %%mm3, 48(%3) \n\t"
+ "movd %%mm2, 192(%2) \n\t"
+ "movd %%mm2, 64(%3) \n\t"
+ "psrlq $32, %%mm2 \n\t"
+ "movd %%mm2, 80(%3) \n\t"
+ "movd %%mm1, 96(%3) \n\t"
+ "psrlq $32, %%mm1 \n\t"
+ "movd %%mm1, 112(%3) \n\t"
+
+ "lea (%%"REG_a", %1, 4), %%"REG_a" \n\t"
+
+ "movq (%0, %1, 4), %%mm0 \n\t" // 12345678
+ "movq (%%"REG_a"), %%mm1 \n\t" // abcdefgh
+ "movq %%mm0, %%mm2 \n\t" // 12345678
+ "punpcklbw %%mm1, %%mm0 \n\t" // 1a2b3c4d
+ "punpckhbw %%mm1, %%mm2 \n\t" // 5e6f7g8h
+
+ "movq (%%"REG_a", %1), %%mm1 \n\t"
+ "movq (%%"REG_a", %1, 2), %%mm3 \n\t"
+ "movq %%mm1, %%mm4 \n\t"
+ "punpcklbw %%mm3, %%mm1 \n\t"
+ "punpckhbw %%mm3, %%mm4 \n\t"
+
+ "movq %%mm0, %%mm3 \n\t"
+ "punpcklwd %%mm1, %%mm0 \n\t"
+ "punpckhwd %%mm1, %%mm3 \n\t"
+ "movq %%mm2, %%mm1 \n\t"
+ "punpcklwd %%mm4, %%mm2 \n\t"
+ "punpckhwd %%mm4, %%mm1 \n\t"
+
+ "movd %%mm0, 132(%2) \n\t"
+ "psrlq $32, %%mm0 \n\t"
+ "movd %%mm0, 148(%2) \n\t"
+ "movd %%mm3, 164(%2) \n\t"
+ "psrlq $32, %%mm3 \n\t"
+ "movd %%mm3, 180(%2) \n\t"
+ "movd %%mm3, 52(%3) \n\t"
+ "movd %%mm2, 196(%2) \n\t"
+ "movd %%mm2, 68(%3) \n\t"
+ "psrlq $32, %%mm2 \n\t"
+ "movd %%mm2, 84(%3) \n\t"
+ "movd %%mm1, 100(%3) \n\t"
+ "psrlq $32, %%mm1 \n\t"
+ "movd %%mm1, 116(%3) \n\t"
+
+
+ :: "r" (src), "r" ((long)srcStride), "r" (dst1), "r" (dst2)
+ : "%"REG_a
+ );
+}
+
+/**
+ * transposes the given 8x8 block
+ */
+static inline void RENAME(transpose2)(uint8_t *dst, int dstStride, uint8_t *src)
+{
+ asm(
+ "lea (%0, %1), %%"REG_a" \n\t"
+ "lea (%%"REG_a",%1,4), %%"REG_d" \n\t"
+// 0 1 2 3 4 5 6 7 8 9
+// %0 eax eax+%1 eax+2%1 %0+4%1 edx edx+%1 edx+2%1 %0+8%1 edx+4%1
+ "movq (%2), %%mm0 \n\t" // 12345678
+ "movq 16(%2), %%mm1 \n\t" // abcdefgh
+ "movq %%mm0, %%mm2 \n\t" // 12345678
+ "punpcklbw %%mm1, %%mm0 \n\t" // 1a2b3c4d
+ "punpckhbw %%mm1, %%mm2 \n\t" // 5e6f7g8h
+
+ "movq 32(%2), %%mm1 \n\t"
+ "movq 48(%2), %%mm3 \n\t"
+ "movq %%mm1, %%mm4 \n\t"
+ "punpcklbw %%mm3, %%mm1 \n\t"
+ "punpckhbw %%mm3, %%mm4 \n\t"
+
+ "movq %%mm0, %%mm3 \n\t"
+ "punpcklwd %%mm1, %%mm0 \n\t"
+ "punpckhwd %%mm1, %%mm3 \n\t"
+ "movq %%mm2, %%mm1 \n\t"
+ "punpcklwd %%mm4, %%mm2 \n\t"
+ "punpckhwd %%mm4, %%mm1 \n\t"
+
+ "movd %%mm0, (%0) \n\t"
+ "psrlq $32, %%mm0 \n\t"
+ "movd %%mm0, (%%"REG_a") \n\t"
+ "movd %%mm3, (%%"REG_a", %1) \n\t"
+ "psrlq $32, %%mm3 \n\t"
+ "movd %%mm3, (%%"REG_a", %1, 2) \n\t"
+ "movd %%mm2, (%0, %1, 4) \n\t"
+ "psrlq $32, %%mm2 \n\t"
+ "movd %%mm2, (%%"REG_d") \n\t"
+ "movd %%mm1, (%%"REG_d", %1) \n\t"
+ "psrlq $32, %%mm1 \n\t"
+ "movd %%mm1, (%%"REG_d", %1, 2) \n\t"
+
+
+ "movq 64(%2), %%mm0 \n\t" // 12345678
+ "movq 80(%2), %%mm1 \n\t" // abcdefgh
+ "movq %%mm0, %%mm2 \n\t" // 12345678
+ "punpcklbw %%mm1, %%mm0 \n\t" // 1a2b3c4d
+ "punpckhbw %%mm1, %%mm2 \n\t" // 5e6f7g8h
+
+ "movq 96(%2), %%mm1 \n\t"
+ "movq 112(%2), %%mm3 \n\t"
+ "movq %%mm1, %%mm4 \n\t"
+ "punpcklbw %%mm3, %%mm1 \n\t"
+ "punpckhbw %%mm3, %%mm4 \n\t"
+
+ "movq %%mm0, %%mm3 \n\t"
+ "punpcklwd %%mm1, %%mm0 \n\t"
+ "punpckhwd %%mm1, %%mm3 \n\t"
+ "movq %%mm2, %%mm1 \n\t"
+ "punpcklwd %%mm4, %%mm2 \n\t"
+ "punpckhwd %%mm4, %%mm1 \n\t"
+
+ "movd %%mm0, 4(%0) \n\t"
+ "psrlq $32, %%mm0 \n\t"
+ "movd %%mm0, 4(%%"REG_a") \n\t"
+ "movd %%mm3, 4(%%"REG_a", %1) \n\t"
+ "psrlq $32, %%mm3 \n\t"
+ "movd %%mm3, 4(%%"REG_a", %1, 2) \n\t"
+ "movd %%mm2, 4(%0, %1, 4) \n\t"
+ "psrlq $32, %%mm2 \n\t"
+ "movd %%mm2, 4(%%"REG_d") \n\t"
+ "movd %%mm1, 4(%%"REG_d", %1) \n\t"
+ "psrlq $32, %%mm1 \n\t"
+ "movd %%mm1, 4(%%"REG_d", %1, 2) \n\t"
+
+ :: "r" (dst), "r" ((long)dstStride), "r" (src)
+ : "%"REG_a, "%"REG_d
+ );
+}
+#endif //HAVE_MMX
+//static long test=0;
+
+#ifndef HAVE_ALTIVEC
+static inline void RENAME(tempNoiseReducer)(uint8_t *src, int stride,
+ uint8_t *tempBlured, uint32_t *tempBluredPast, int *maxNoise)
+{
+ // to save a register (FIXME do this outside of the loops)
+ tempBluredPast[127]= maxNoise[0];
+ tempBluredPast[128]= maxNoise[1];
+ tempBluredPast[129]= maxNoise[2];
+
+#define FAST_L2_DIFF
+//#define L1_DIFF //u should change the thresholds too if u try that one
+#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ asm volatile(
+ "lea (%2, %2, 2), %%"REG_a" \n\t" // 3*stride
+ "lea (%2, %2, 4), %%"REG_d" \n\t" // 5*stride
+ "lea (%%"REG_d", %2, 2), %%"REG_c" \n\t" // 7*stride
+// 0 1 2 3 4 5 6 7 8 9
+// %x %x+%2 %x+2%2 %x+eax %x+4%2 %x+edx %x+2eax %x+ecx %x+8%2
+//FIXME reorder?
+#ifdef L1_DIFF //needs mmx2
+ "movq (%0), %%mm0 \n\t" // L0
+ "psadbw (%1), %%mm0 \n\t" // |L0-R0|
+ "movq (%0, %2), %%mm1 \n\t" // L1
+ "psadbw (%1, %2), %%mm1 \n\t" // |L1-R1|
+ "movq (%0, %2, 2), %%mm2 \n\t" // L2
+ "psadbw (%1, %2, 2), %%mm2 \n\t" // |L2-R2|
+ "movq (%0, %%"REG_a"), %%mm3 \n\t" // L3
+ "psadbw (%1, %%"REG_a"), %%mm3 \n\t" // |L3-R3|
+
+ "movq (%0, %2, 4), %%mm4 \n\t" // L4
+ "paddw %%mm1, %%mm0 \n\t"
+ "psadbw (%1, %2, 4), %%mm4 \n\t" // |L4-R4|
+ "movq (%0, %%"REG_d"), %%mm5 \n\t" // L5
+ "paddw %%mm2, %%mm0 \n\t"
+ "psadbw (%1, %%"REG_d"), %%mm5 \n\t" // |L5-R5|
+ "movq (%0, %%"REG_a", 2), %%mm6 \n\t" // L6
+ "paddw %%mm3, %%mm0 \n\t"
+ "psadbw (%1, %%"REG_a", 2), %%mm6 \n\t" // |L6-R6|
+ "movq (%0, %%"REG_c"), %%mm7 \n\t" // L7
+ "paddw %%mm4, %%mm0 \n\t"
+ "psadbw (%1, %%"REG_c"), %%mm7 \n\t" // |L7-R7|
+ "paddw %%mm5, %%mm6 \n\t"
+ "paddw %%mm7, %%mm6 \n\t"
+ "paddw %%mm6, %%mm0 \n\t"
+#else //L1_DIFF
+#if defined (FAST_L2_DIFF)
+ "pcmpeqb %%mm7, %%mm7 \n\t"
+ "movq "MANGLE(b80)", %%mm6 \n\t"
+ "pxor %%mm0, %%mm0 \n\t"
+#define REAL_L2_DIFF_CORE(a, b)\
+ "movq " #a ", %%mm5 \n\t"\
+ "movq " #b ", %%mm2 \n\t"\
+ "pxor %%mm7, %%mm2 \n\t"\
+ PAVGB(%%mm2, %%mm5)\
+ "paddb %%mm6, %%mm5 \n\t"\
+ "movq %%mm5, %%mm2 \n\t"\
+ "psllw $8, %%mm5 \n\t"\
+ "pmaddwd %%mm5, %%mm5 \n\t"\
+ "pmaddwd %%mm2, %%mm2 \n\t"\
+ "paddd %%mm2, %%mm5 \n\t"\
+ "psrld $14, %%mm5 \n\t"\
+ "paddd %%mm5, %%mm0 \n\t"
+
+#else //defined (FAST_L2_DIFF)
+ "pxor %%mm7, %%mm7 \n\t"
+ "pxor %%mm0, %%mm0 \n\t"
+#define REAL_L2_DIFF_CORE(a, b)\
+ "movq " #a ", %%mm5 \n\t"\
+ "movq " #b ", %%mm2 \n\t"\
+ "movq %%mm5, %%mm1 \n\t"\
+ "movq %%mm2, %%mm3 \n\t"\
+ "punpcklbw %%mm7, %%mm5 \n\t"\
+ "punpckhbw %%mm7, %%mm1 \n\t"\
+ "punpcklbw %%mm7, %%mm2 \n\t"\
+ "punpckhbw %%mm7, %%mm3 \n\t"\
+ "psubw %%mm2, %%mm5 \n\t"\
+ "psubw %%mm3, %%mm1 \n\t"\
+ "pmaddwd %%mm5, %%mm5 \n\t"\
+ "pmaddwd %%mm1, %%mm1 \n\t"\
+ "paddd %%mm1, %%mm5 \n\t"\
+ "paddd %%mm5, %%mm0 \n\t"
+
+#endif //defined (FAST_L2_DIFF)
+
+#define L2_DIFF_CORE(a, b) REAL_L2_DIFF_CORE(a, b)
+
+L2_DIFF_CORE((%0) , (%1))
+L2_DIFF_CORE((%0, %2) , (%1, %2))
+L2_DIFF_CORE((%0, %2, 2) , (%1, %2, 2))
+L2_DIFF_CORE((%0, %%REGa) , (%1, %%REGa))
+L2_DIFF_CORE((%0, %2, 4) , (%1, %2, 4))
+L2_DIFF_CORE((%0, %%REGd) , (%1, %%REGd))
+L2_DIFF_CORE((%0, %%REGa,2), (%1, %%REGa,2))
+L2_DIFF_CORE((%0, %%REGc) , (%1, %%REGc))
+
+#endif //L1_DIFF
+
+ "movq %%mm0, %%mm4 \n\t"
+ "psrlq $32, %%mm0 \n\t"
+ "paddd %%mm0, %%mm4 \n\t"
+ "movd %%mm4, %%ecx \n\t"
+ "shll $2, %%ecx \n\t"
+ "mov %3, %%"REG_d" \n\t"
+ "addl -4(%%"REG_d"), %%ecx \n\t"
+ "addl 4(%%"REG_d"), %%ecx \n\t"
+ "addl -1024(%%"REG_d"), %%ecx \n\t"
+ "addl $4, %%ecx \n\t"
+ "addl 1024(%%"REG_d"), %%ecx \n\t"
+ "shrl $3, %%ecx \n\t"
+ "movl %%ecx, (%%"REG_d") \n\t"
+
+// "mov %3, %%"REG_c" \n\t"
+// "mov %%"REG_c", test \n\t"
+// "jmp 4f \n\t"
+ "cmpl 512(%%"REG_d"), %%ecx \n\t"
+ " jb 2f \n\t"
+ "cmpl 516(%%"REG_d"), %%ecx \n\t"
+ " jb 1f \n\t"
+
+ "lea (%%"REG_a", %2, 2), %%"REG_d" \n\t" // 5*stride
+ "lea (%%"REG_d", %2, 2), %%"REG_c" \n\t" // 7*stride
+ "movq (%0), %%mm0 \n\t" // L0
+ "movq (%0, %2), %%mm1 \n\t" // L1
+ "movq (%0, %2, 2), %%mm2 \n\t" // L2
+ "movq (%0, %%"REG_a"), %%mm3 \n\t" // L3
+ "movq (%0, %2, 4), %%mm4 \n\t" // L4
+ "movq (%0, %%"REG_d"), %%mm5 \n\t" // L5
+ "movq (%0, %%"REG_a", 2), %%mm6 \n\t" // L6
+ "movq (%0, %%"REG_c"), %%mm7 \n\t" // L7
+ "movq %%mm0, (%1) \n\t" // L0
+ "movq %%mm1, (%1, %2) \n\t" // L1
+ "movq %%mm2, (%1, %2, 2) \n\t" // L2
+ "movq %%mm3, (%1, %%"REG_a") \n\t" // L3
+ "movq %%mm4, (%1, %2, 4) \n\t" // L4
+ "movq %%mm5, (%1, %%"REG_d") \n\t" // L5
+ "movq %%mm6, (%1, %%"REG_a", 2) \n\t" // L6
+ "movq %%mm7, (%1, %%"REG_c") \n\t" // L7
+ "jmp 4f \n\t"
+
+ "1: \n\t"
+ "lea (%%"REG_a", %2, 2), %%"REG_d" \n\t" // 5*stride
+ "lea (%%"REG_d", %2, 2), %%"REG_c" \n\t" // 7*stride
+ "movq (%0), %%mm0 \n\t" // L0
+ PAVGB((%1), %%mm0) // L0
+ "movq (%0, %2), %%mm1 \n\t" // L1
+ PAVGB((%1, %2), %%mm1) // L1
+ "movq (%0, %2, 2), %%mm2 \n\t" // L2
+ PAVGB((%1, %2, 2), %%mm2) // L2
+ "movq (%0, %%"REG_a"), %%mm3 \n\t" // L3
+ PAVGB((%1, %%REGa), %%mm3) // L3
+ "movq (%0, %2, 4), %%mm4 \n\t" // L4
+ PAVGB((%1, %2, 4), %%mm4) // L4
+ "movq (%0, %%"REG_d"), %%mm5 \n\t" // L5
+ PAVGB((%1, %%REGd), %%mm5) // L5
+ "movq (%0, %%"REG_a", 2), %%mm6 \n\t" // L6
+ PAVGB((%1, %%REGa, 2), %%mm6) // L6
+ "movq (%0, %%"REG_c"), %%mm7 \n\t" // L7
+ PAVGB((%1, %%REGc), %%mm7) // L7
+ "movq %%mm0, (%1) \n\t" // R0
+ "movq %%mm1, (%1, %2) \n\t" // R1
+ "movq %%mm2, (%1, %2, 2) \n\t" // R2
+ "movq %%mm3, (%1, %%"REG_a") \n\t" // R3
+ "movq %%mm4, (%1, %2, 4) \n\t" // R4
+ "movq %%mm5, (%1, %%"REG_d") \n\t" // R5
+ "movq %%mm6, (%1, %%"REG_a", 2) \n\t" // R6
+ "movq %%mm7, (%1, %%"REG_c") \n\t" // R7
+ "movq %%mm0, (%0) \n\t" // L0
+ "movq %%mm1, (%0, %2) \n\t" // L1
+ "movq %%mm2, (%0, %2, 2) \n\t" // L2
+ "movq %%mm3, (%0, %%"REG_a") \n\t" // L3
+ "movq %%mm4, (%0, %2, 4) \n\t" // L4
+ "movq %%mm5, (%0, %%"REG_d") \n\t" // L5
+ "movq %%mm6, (%0, %%"REG_a", 2) \n\t" // L6
+ "movq %%mm7, (%0, %%"REG_c") \n\t" // L7
+ "jmp 4f \n\t"
+
+ "2: \n\t"
+ "cmpl 508(%%"REG_d"), %%ecx \n\t"
+ " jb 3f \n\t"
+
+ "lea (%%"REG_a", %2, 2), %%"REG_d" \n\t" // 5*stride
+ "lea (%%"REG_d", %2, 2), %%"REG_c" \n\t" // 7*stride
+ "movq (%0), %%mm0 \n\t" // L0
+ "movq (%0, %2), %%mm1 \n\t" // L1
+ "movq (%0, %2, 2), %%mm2 \n\t" // L2
+ "movq (%0, %%"REG_a"), %%mm3 \n\t" // L3
+ "movq (%1), %%mm4 \n\t" // R0
+ "movq (%1, %2), %%mm5 \n\t" // R1
+ "movq (%1, %2, 2), %%mm6 \n\t" // R2
+ "movq (%1, %%"REG_a"), %%mm7 \n\t" // R3
+ PAVGB(%%mm4, %%mm0)
+ PAVGB(%%mm5, %%mm1)
+ PAVGB(%%mm6, %%mm2)
+ PAVGB(%%mm7, %%mm3)
+ PAVGB(%%mm4, %%mm0)
+ PAVGB(%%mm5, %%mm1)
+ PAVGB(%%mm6, %%mm2)
+ PAVGB(%%mm7, %%mm3)
+ "movq %%mm0, (%1) \n\t" // R0
+ "movq %%mm1, (%1, %2) \n\t" // R1
+ "movq %%mm2, (%1, %2, 2) \n\t" // R2
+ "movq %%mm3, (%1, %%"REG_a") \n\t" // R3
+ "movq %%mm0, (%0) \n\t" // L0
+ "movq %%mm1, (%0, %2) \n\t" // L1
+ "movq %%mm2, (%0, %2, 2) \n\t" // L2
+ "movq %%mm3, (%0, %%"REG_a") \n\t" // L3
+
+ "movq (%0, %2, 4), %%mm0 \n\t" // L4
+ "movq (%0, %%"REG_d"), %%mm1 \n\t" // L5
+ "movq (%0, %%"REG_a", 2), %%mm2 \n\t" // L6
+ "movq (%0, %%"REG_c"), %%mm3 \n\t" // L7
+ "movq (%1, %2, 4), %%mm4 \n\t" // R4
+ "movq (%1, %%"REG_d"), %%mm5 \n\t" // R5
+ "movq (%1, %%"REG_a", 2), %%mm6 \n\t" // R6
+ "movq (%1, %%"REG_c"), %%mm7 \n\t" // R7
+ PAVGB(%%mm4, %%mm0)
+ PAVGB(%%mm5, %%mm1)
+ PAVGB(%%mm6, %%mm2)
+ PAVGB(%%mm7, %%mm3)
+ PAVGB(%%mm4, %%mm0)
+ PAVGB(%%mm5, %%mm1)
+ PAVGB(%%mm6, %%mm2)
+ PAVGB(%%mm7, %%mm3)
+ "movq %%mm0, (%1, %2, 4) \n\t" // R4
+ "movq %%mm1, (%1, %%"REG_d") \n\t" // R5
+ "movq %%mm2, (%1, %%"REG_a", 2) \n\t" // R6
+ "movq %%mm3, (%1, %%"REG_c") \n\t" // R7
+ "movq %%mm0, (%0, %2, 4) \n\t" // L4
+ "movq %%mm1, (%0, %%"REG_d") \n\t" // L5
+ "movq %%mm2, (%0, %%"REG_a", 2) \n\t" // L6
+ "movq %%mm3, (%0, %%"REG_c") \n\t" // L7
+ "jmp 4f \n\t"
+
+ "3: \n\t"
+ "lea (%%"REG_a", %2, 2), %%"REG_d" \n\t" // 5*stride
+ "lea (%%"REG_d", %2, 2), %%"REG_c" \n\t" // 7*stride
+ "movq (%0), %%mm0 \n\t" // L0
+ "movq (%0, %2), %%mm1 \n\t" // L1
+ "movq (%0, %2, 2), %%mm2 \n\t" // L2
+ "movq (%0, %%"REG_a"), %%mm3 \n\t" // L3
+ "movq (%1), %%mm4 \n\t" // R0
+ "movq (%1, %2), %%mm5 \n\t" // R1
+ "movq (%1, %2, 2), %%mm6 \n\t" // R2
+ "movq (%1, %%"REG_a"), %%mm7 \n\t" // R3
+ PAVGB(%%mm4, %%mm0)
+ PAVGB(%%mm5, %%mm1)
+ PAVGB(%%mm6, %%mm2)
+ PAVGB(%%mm7, %%mm3)
+ PAVGB(%%mm4, %%mm0)
+ PAVGB(%%mm5, %%mm1)
+ PAVGB(%%mm6, %%mm2)
+ PAVGB(%%mm7, %%mm3)
+ PAVGB(%%mm4, %%mm0)
+ PAVGB(%%mm5, %%mm1)
+ PAVGB(%%mm6, %%mm2)
+ PAVGB(%%mm7, %%mm3)
+ "movq %%mm0, (%1) \n\t" // R0
+ "movq %%mm1, (%1, %2) \n\t" // R1
+ "movq %%mm2, (%1, %2, 2) \n\t" // R2
+ "movq %%mm3, (%1, %%"REG_a") \n\t" // R3
+ "movq %%mm0, (%0) \n\t" // L0
+ "movq %%mm1, (%0, %2) \n\t" // L1
+ "movq %%mm2, (%0, %2, 2) \n\t" // L2
+ "movq %%mm3, (%0, %%"REG_a") \n\t" // L3
+
+ "movq (%0, %2, 4), %%mm0 \n\t" // L4
+ "movq (%0, %%"REG_d"), %%mm1 \n\t" // L5
+ "movq (%0, %%"REG_a", 2), %%mm2 \n\t" // L6
+ "movq (%0, %%"REG_c"), %%mm3 \n\t" // L7
+ "movq (%1, %2, 4), %%mm4 \n\t" // R4
+ "movq (%1, %%"REG_d"), %%mm5 \n\t" // R5
+ "movq (%1, %%"REG_a", 2), %%mm6 \n\t" // R6
+ "movq (%1, %%"REG_c"), %%mm7 \n\t" // R7
+ PAVGB(%%mm4, %%mm0)
+ PAVGB(%%mm5, %%mm1)
+ PAVGB(%%mm6, %%mm2)
+ PAVGB(%%mm7, %%mm3)
+ PAVGB(%%mm4, %%mm0)
+ PAVGB(%%mm5, %%mm1)
+ PAVGB(%%mm6, %%mm2)
+ PAVGB(%%mm7, %%mm3)
+ PAVGB(%%mm4, %%mm0)
+ PAVGB(%%mm5, %%mm1)
+ PAVGB(%%mm6, %%mm2)
+ PAVGB(%%mm7, %%mm3)
+ "movq %%mm0, (%1, %2, 4) \n\t" // R4
+ "movq %%mm1, (%1, %%"REG_d") \n\t" // R5
+ "movq %%mm2, (%1, %%"REG_a", 2) \n\t" // R6
+ "movq %%mm3, (%1, %%"REG_c") \n\t" // R7
+ "movq %%mm0, (%0, %2, 4) \n\t" // L4
+ "movq %%mm1, (%0, %%"REG_d") \n\t" // L5
+ "movq %%mm2, (%0, %%"REG_a", 2) \n\t" // L6
+ "movq %%mm3, (%0, %%"REG_c") \n\t" // L7
+
+ "4: \n\t"
+
+ :: "r" (src), "r" (tempBlured), "r"((long)stride), "m" (tempBluredPast)
+ : "%"REG_a, "%"REG_d, "%"REG_c, "memory"
+ );
+#else //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+{
+ int y;
+ int d=0;
+// int sysd=0;
+ int i;
+
+ for(y=0; y<8; y++)
+ {
+ int x;
+ for(x=0; x<8; x++)
+ {
+ int ref= tempBlured[ x + y*stride ];
+ int cur= src[ x + y*stride ];
+ int d1=ref - cur;
+// if(x==0 || x==7) d1+= d1>>1;
+// if(y==0 || y==7) d1+= d1>>1;
+// d+= FFABS(d1);
+ d+= d1*d1;
+// sysd+= d1;
+ }
+ }
+ i=d;
+ d= (
+ 4*d
+ +(*(tempBluredPast-256))
+ +(*(tempBluredPast-1))+ (*(tempBluredPast+1))
+ +(*(tempBluredPast+256))
+ +4)>>3;
+ *tempBluredPast=i;
+// ((*tempBluredPast)*3 + d + 2)>>2;
+
+/*
+Switch between
+ 1 0 0 0 0 0 0 (0)
+64 32 16 8 4 2 1 (1)
+64 48 36 27 20 15 11 (33) (approx)
+64 56 49 43 37 33 29 (200) (approx)
+*/
+ if(d > maxNoise[1])
+ {
+ if(d < maxNoise[2])
+ {
+ for(y=0; y<8; y++)
+ {
+ int x;
+ for(x=0; x<8; x++)
+ {
+ int ref= tempBlured[ x + y*stride ];
+ int cur= src[ x + y*stride ];
+ tempBlured[ x + y*stride ]=
+ src[ x + y*stride ]=
+ (ref + cur + 1)>>1;
+ }
+ }
+ }
+ else
+ {
+ for(y=0; y<8; y++)
+ {
+ int x;
+ for(x=0; x<8; x++)
+ {
+ tempBlured[ x + y*stride ]= src[ x + y*stride ];
+ }
+ }
+ }
+ }
+ else
+ {
+ if(d < maxNoise[0])
+ {
+ for(y=0; y<8; y++)
+ {
+ int x;
+ for(x=0; x<8; x++)
+ {
+ int ref= tempBlured[ x + y*stride ];
+ int cur= src[ x + y*stride ];
+ tempBlured[ x + y*stride ]=
+ src[ x + y*stride ]=
+ (ref*7 + cur + 4)>>3;
+ }
+ }
+ }
+ else
+ {
+ for(y=0; y<8; y++)
+ {
+ int x;
+ for(x=0; x<8; x++)
+ {
+ int ref= tempBlured[ x + y*stride ];
+ int cur= src[ x + y*stride ];
+ tempBlured[ x + y*stride ]=
+ src[ x + y*stride ]=
+ (ref*3 + cur + 2)>>2;
+ }
+ }
+ }
+ }
+}
+#endif //defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+}
+#endif //HAVE_ALTIVEC
+
+#ifdef HAVE_MMX
+/**
+ * accurate deblock filter
+ */
+static always_inline void RENAME(do_a_deblock)(uint8_t *src, int step, int stride, PPContext *c){
+ int64_t dc_mask, eq_mask, both_masks;
+ int64_t sums[10*8*2];
+ src+= step*3; // src points to begin of the 8x8 Block
+//START_TIMER
+asm volatile(
+ "movq %0, %%mm7 \n\t"
+ "movq %1, %%mm6 \n\t"
+ : : "m" (c->mmxDcOffset[c->nonBQP]), "m" (c->mmxDcThreshold[c->nonBQP])
+ );
+
+asm volatile(
+ "lea (%2, %3), %%"REG_a" \n\t"
+// 0 1 2 3 4 5 6 7 8 9
+// %1 eax eax+%2 eax+2%2 %1+4%2 ecx ecx+%2 ecx+2%2 %1+8%2 ecx+4%2
+
+ "movq (%2), %%mm0 \n\t"
+ "movq (%%"REG_a"), %%mm1 \n\t"
+ "movq %%mm1, %%mm3 \n\t"
+ "movq %%mm1, %%mm4 \n\t"
+ "psubb %%mm1, %%mm0 \n\t" // mm0 = differnece
+ "paddb %%mm7, %%mm0 \n\t"
+ "pcmpgtb %%mm6, %%mm0 \n\t"
+
+ "movq (%%"REG_a",%3), %%mm2 \n\t"
+ PMAXUB(%%mm2, %%mm4)
+ PMINUB(%%mm2, %%mm3, %%mm5)
+ "psubb %%mm2, %%mm1 \n\t"
+ "paddb %%mm7, %%mm1 \n\t"
+ "pcmpgtb %%mm6, %%mm1 \n\t"
+ "paddb %%mm1, %%mm0 \n\t"
+
+ "movq (%%"REG_a", %3, 2), %%mm1 \n\t"
+ PMAXUB(%%mm1, %%mm4)
+ PMINUB(%%mm1, %%mm3, %%mm5)
+ "psubb %%mm1, %%mm2 \n\t"
+ "paddb %%mm7, %%mm2 \n\t"
+ "pcmpgtb %%mm6, %%mm2 \n\t"
+ "paddb %%mm2, %%mm0 \n\t"
+
+ "lea (%%"REG_a", %3, 4), %%"REG_a" \n\t"
+
+ "movq (%2, %3, 4), %%mm2 \n\t"
+ PMAXUB(%%mm2, %%mm4)
+ PMINUB(%%mm2, %%mm3, %%mm5)
+ "psubb %%mm2, %%mm1 \n\t"
+ "paddb %%mm7, %%mm1 \n\t"
+ "pcmpgtb %%mm6, %%mm1 \n\t"
+ "paddb %%mm1, %%mm0 \n\t"
+
+ "movq (%%"REG_a"), %%mm1 \n\t"
+ PMAXUB(%%mm1, %%mm4)
+ PMINUB(%%mm1, %%mm3, %%mm5)
+ "psubb %%mm1, %%mm2 \n\t"
+ "paddb %%mm7, %%mm2 \n\t"
+ "pcmpgtb %%mm6, %%mm2 \n\t"
+ "paddb %%mm2, %%mm0 \n\t"
+
+ "movq (%%"REG_a", %3), %%mm2 \n\t"
+ PMAXUB(%%mm2, %%mm4)
+ PMINUB(%%mm2, %%mm3, %%mm5)
+ "psubb %%mm2, %%mm1 \n\t"
+ "paddb %%mm7, %%mm1 \n\t"
+ "pcmpgtb %%mm6, %%mm1 \n\t"
+ "paddb %%mm1, %%mm0 \n\t"
+
+ "movq (%%"REG_a", %3, 2), %%mm1 \n\t"
+ PMAXUB(%%mm1, %%mm4)
+ PMINUB(%%mm1, %%mm3, %%mm5)
+ "psubb %%mm1, %%mm2 \n\t"
+ "paddb %%mm7, %%mm2 \n\t"
+ "pcmpgtb %%mm6, %%mm2 \n\t"
+ "paddb %%mm2, %%mm0 \n\t"
+
+ "movq (%2, %3, 8), %%mm2 \n\t"
+ PMAXUB(%%mm2, %%mm4)
+ PMINUB(%%mm2, %%mm3, %%mm5)
+ "psubb %%mm2, %%mm1 \n\t"
+ "paddb %%mm7, %%mm1 \n\t"
+ "pcmpgtb %%mm6, %%mm1 \n\t"
+ "paddb %%mm1, %%mm0 \n\t"
+
+ "movq (%%"REG_a", %3, 4), %%mm1 \n\t"
+ "psubb %%mm1, %%mm2 \n\t"
+ "paddb %%mm7, %%mm2 \n\t"
+ "pcmpgtb %%mm6, %%mm2 \n\t"
+ "paddb %%mm2, %%mm0 \n\t"
+ "psubusb %%mm3, %%mm4 \n\t"
+
+ "pxor %%mm6, %%mm6 \n\t"
+ "movq %4, %%mm7 \n\t" // QP,..., QP
+ "paddusb %%mm7, %%mm7 \n\t" // 2QP ... 2QP
+ "psubusb %%mm4, %%mm7 \n\t" // Diff >=2QP -> 0
+ "pcmpeqb %%mm6, %%mm7 \n\t" // Diff < 2QP -> 0
+ "pcmpeqb %%mm6, %%mm7 \n\t" // Diff < 2QP -> 0
+ "movq %%mm7, %1 \n\t"
+
+ "movq %5, %%mm7 \n\t"
+ "punpcklbw %%mm7, %%mm7 \n\t"
+ "punpcklbw %%mm7, %%mm7 \n\t"
+ "punpcklbw %%mm7, %%mm7 \n\t"
+ "psubb %%mm0, %%mm6 \n\t"
+ "pcmpgtb %%mm7, %%mm6 \n\t"
+ "movq %%mm6, %0 \n\t"
+
+ : "=m" (eq_mask), "=m" (dc_mask)
+ : "r" (src), "r" ((long)step), "m" (c->pQPb), "m"(c->ppMode.flatnessThreshold)
+ : "%"REG_a
+ );
+
+ both_masks = dc_mask & eq_mask;
+
+ if(both_masks){
+ long offset= -8*step;
+ int64_t *temp_sums= sums;
+
+ asm volatile(
+ "movq %2, %%mm0 \n\t" // QP,..., QP
+ "pxor %%mm4, %%mm4 \n\t"
+
+ "movq (%0), %%mm6 \n\t"
+ "movq (%0, %1), %%mm5 \n\t"
+ "movq %%mm5, %%mm1 \n\t"
+ "movq %%mm6, %%mm2 \n\t"
+ "psubusb %%mm6, %%mm5 \n\t"
+ "psubusb %%mm1, %%mm2 \n\t"
+ "por %%mm5, %%mm2 \n\t" // ABS Diff of lines
+ "psubusb %%mm2, %%mm0 \n\t" // diff >= QP -> 0
+ "pcmpeqb %%mm4, %%mm0 \n\t" // diff >= QP -> FF
+
+ "pxor %%mm6, %%mm1 \n\t"
+ "pand %%mm0, %%mm1 \n\t"
+ "pxor %%mm1, %%mm6 \n\t"
+ // 0:QP 6:First
+
+ "movq (%0, %1, 8), %%mm5 \n\t"
+ "add %1, %0 \n\t" // %0 points to line 1 not 0
+ "movq (%0, %1, 8), %%mm7 \n\t"
+ "movq %%mm5, %%mm1 \n\t"
+ "movq %%mm7, %%mm2 \n\t"
+ "psubusb %%mm7, %%mm5 \n\t"
+ "psubusb %%mm1, %%mm2 \n\t"
+ "por %%mm5, %%mm2 \n\t" // ABS Diff of lines
+ "movq %2, %%mm0 \n\t" // QP,..., QP
+ "psubusb %%mm2, %%mm0 \n\t" // diff >= QP -> 0
+ "pcmpeqb %%mm4, %%mm0 \n\t" // diff >= QP -> FF
+
+ "pxor %%mm7, %%mm1 \n\t"
+ "pand %%mm0, %%mm1 \n\t"
+ "pxor %%mm1, %%mm7 \n\t"
+
+ "movq %%mm6, %%mm5 \n\t"
+ "punpckhbw %%mm4, %%mm6 \n\t"
+ "punpcklbw %%mm4, %%mm5 \n\t"
+ // 4:0 5/6:First 7:Last
+
+ "movq %%mm5, %%mm0 \n\t"
+ "movq %%mm6, %%mm1 \n\t"
+ "psllw $2, %%mm0 \n\t"
+ "psllw $2, %%mm1 \n\t"
+ "paddw "MANGLE(w04)", %%mm0 \n\t"
+ "paddw "MANGLE(w04)", %%mm1 \n\t"
+
+#define NEXT\
+ "movq (%0), %%mm2 \n\t"\
+ "movq (%0), %%mm3 \n\t"\
+ "add %1, %0 \n\t"\
+ "punpcklbw %%mm4, %%mm2 \n\t"\
+ "punpckhbw %%mm4, %%mm3 \n\t"\
+ "paddw %%mm2, %%mm0 \n\t"\
+ "paddw %%mm3, %%mm1 \n\t"
+
+#define PREV\
+ "movq (%0), %%mm2 \n\t"\
+ "movq (%0), %%mm3 \n\t"\
+ "add %1, %0 \n\t"\
+ "punpcklbw %%mm4, %%mm2 \n\t"\
+ "punpckhbw %%mm4, %%mm3 \n\t"\
+ "psubw %%mm2, %%mm0 \n\t"\
+ "psubw %%mm3, %%mm1 \n\t"
+
+
+ NEXT //0
+ NEXT //1
+ NEXT //2
+ "movq %%mm0, (%3) \n\t"
+ "movq %%mm1, 8(%3) \n\t"
+
+ NEXT //3
+ "psubw %%mm5, %%mm0 \n\t"
+ "psubw %%mm6, %%mm1 \n\t"
+ "movq %%mm0, 16(%3) \n\t"
+ "movq %%mm1, 24(%3) \n\t"
+
+ NEXT //4
+ "psubw %%mm5, %%mm0 \n\t"
+ "psubw %%mm6, %%mm1 \n\t"
+ "movq %%mm0, 32(%3) \n\t"
+ "movq %%mm1, 40(%3) \n\t"
+
+ NEXT //5
+ "psubw %%mm5, %%mm0 \n\t"
+ "psubw %%mm6, %%mm1 \n\t"
+ "movq %%mm0, 48(%3) \n\t"
+ "movq %%mm1, 56(%3) \n\t"
+
+ NEXT //6
+ "psubw %%mm5, %%mm0 \n\t"
+ "psubw %%mm6, %%mm1 \n\t"
+ "movq %%mm0, 64(%3) \n\t"
+ "movq %%mm1, 72(%3) \n\t"
+
+ "movq %%mm7, %%mm6 \n\t"
+ "punpckhbw %%mm4, %%mm7 \n\t"
+ "punpcklbw %%mm4, %%mm6 \n\t"
+
+ NEXT //7
+ "mov %4, %0 \n\t"
+ "add %1, %0 \n\t"
+ PREV //0
+ "movq %%mm0, 80(%3) \n\t"
+ "movq %%mm1, 88(%3) \n\t"
+
+ PREV //1
+ "paddw %%mm6, %%mm0 \n\t"
+ "paddw %%mm7, %%mm1 \n\t"
+ "movq %%mm0, 96(%3) \n\t"
+ "movq %%mm1, 104(%3) \n\t"
+
+ PREV //2
+ "paddw %%mm6, %%mm0 \n\t"
+ "paddw %%mm7, %%mm1 \n\t"
+ "movq %%mm0, 112(%3) \n\t"
+ "movq %%mm1, 120(%3) \n\t"
+
+ PREV //3
+ "paddw %%mm6, %%mm0 \n\t"
+ "paddw %%mm7, %%mm1 \n\t"
+ "movq %%mm0, 128(%3) \n\t"
+ "movq %%mm1, 136(%3) \n\t"
+
+ PREV //4
+ "paddw %%mm6, %%mm0 \n\t"
+ "paddw %%mm7, %%mm1 \n\t"
+ "movq %%mm0, 144(%3) \n\t"
+ "movq %%mm1, 152(%3) \n\t"
+
+ "mov %4, %0 \n\t" //FIXME
+
+ : "+&r"(src)
+ : "r" ((long)step), "m" (c->pQPb), "r"(sums), "g"(src)
+ );
+
+ src+= step; // src points to begin of the 8x8 Block
+
+ asm volatile(
+ "movq %4, %%mm6 \n\t"
+ "pcmpeqb %%mm5, %%mm5 \n\t"
+ "pxor %%mm6, %%mm5 \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+
+ "1: \n\t"
+ "movq (%1), %%mm0 \n\t"
+ "movq 8(%1), %%mm1 \n\t"
+ "paddw 32(%1), %%mm0 \n\t"
+ "paddw 40(%1), %%mm1 \n\t"
+ "movq (%0, %3), %%mm2 \n\t"
+ "movq %%mm2, %%mm3 \n\t"
+ "movq %%mm2, %%mm4 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "punpckhbw %%mm7, %%mm3 \n\t"
+ "paddw %%mm2, %%mm0 \n\t"
+ "paddw %%mm3, %%mm1 \n\t"
+ "paddw %%mm2, %%mm0 \n\t"
+ "paddw %%mm3, %%mm1 \n\t"
+ "psrlw $4, %%mm0 \n\t"
+ "psrlw $4, %%mm1 \n\t"
+ "packuswb %%mm1, %%mm0 \n\t"
+ "pand %%mm6, %%mm0 \n\t"
+ "pand %%mm5, %%mm4 \n\t"
+ "por %%mm4, %%mm0 \n\t"
+ "movq %%mm0, (%0, %3) \n\t"
+ "add $16, %1 \n\t"
+ "add %2, %0 \n\t"
+ " js 1b \n\t"
+
+ : "+r"(offset), "+r"(temp_sums)
+ : "r" ((long)step), "r"(src - offset), "m"(both_masks)
+ );
+ }else
+ src+= step; // src points to begin of the 8x8 Block
+
+ if(eq_mask != -1LL){
+ uint8_t *temp_src= src;
+ asm volatile(
+ "pxor %%mm7, %%mm7 \n\t"
+ "lea -40(%%"REG_SP"), %%"REG_c" \n\t" // make space for 4 8-byte vars
+ "and "ALIGN_MASK", %%"REG_c" \n\t" // align
+// 0 1 2 3 4 5 6 7 8 9
+// %0 eax eax+%1 eax+2%1 %0+4%1 ecx ecx+%1 ecx+2%1 %1+8%1 ecx+4%1
+
+ "movq (%0), %%mm0 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t" // low part of line 0
+ "punpckhbw %%mm7, %%mm1 \n\t" // high part of line 0
+
+ "movq (%0, %1), %%mm2 \n\t"
+ "lea (%0, %1, 2), %%"REG_a" \n\t"
+ "movq %%mm2, %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t" // low part of line 1
+ "punpckhbw %%mm7, %%mm3 \n\t" // high part of line 1
+
+ "movq (%%"REG_a"), %%mm4 \n\t"
+ "movq %%mm4, %%mm5 \n\t"
+ "punpcklbw %%mm7, %%mm4 \n\t" // low part of line 2
+ "punpckhbw %%mm7, %%mm5 \n\t" // high part of line 2
+
+ "paddw %%mm0, %%mm0 \n\t" // 2L0
+ "paddw %%mm1, %%mm1 \n\t" // 2H0
+ "psubw %%mm4, %%mm2 \n\t" // L1 - L2
+ "psubw %%mm5, %%mm3 \n\t" // H1 - H2
+ "psubw %%mm2, %%mm0 \n\t" // 2L0 - L1 + L2
+ "psubw %%mm3, %%mm1 \n\t" // 2H0 - H1 + H2
+
+ "psllw $2, %%mm2 \n\t" // 4L1 - 4L2
+ "psllw $2, %%mm3 \n\t" // 4H1 - 4H2
+ "psubw %%mm2, %%mm0 \n\t" // 2L0 - 5L1 + 5L2
+ "psubw %%mm3, %%mm1 \n\t" // 2H0 - 5H1 + 5H2
+
+ "movq (%%"REG_a", %1), %%mm2 \n\t"
+ "movq %%mm2, %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t" // L3
+ "punpckhbw %%mm7, %%mm3 \n\t" // H3
+
+ "psubw %%mm2, %%mm0 \n\t" // 2L0 - 5L1 + 5L2 - L3
+ "psubw %%mm3, %%mm1 \n\t" // 2H0 - 5H1 + 5H2 - H3
+ "psubw %%mm2, %%mm0 \n\t" // 2L0 - 5L1 + 5L2 - 2L3
+ "psubw %%mm3, %%mm1 \n\t" // 2H0 - 5H1 + 5H2 - 2H3
+ "movq %%mm0, (%%"REG_c") \n\t" // 2L0 - 5L1 + 5L2 - 2L3
+ "movq %%mm1, 8(%%"REG_c") \n\t" // 2H0 - 5H1 + 5H2 - 2H3
+
+ "movq (%%"REG_a", %1, 2), %%mm0 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t" // L4
+ "punpckhbw %%mm7, %%mm1 \n\t" // H4
+
+ "psubw %%mm0, %%mm2 \n\t" // L3 - L4
+ "psubw %%mm1, %%mm3 \n\t" // H3 - H4
+ "movq %%mm2, 16(%%"REG_c") \n\t" // L3 - L4
+ "movq %%mm3, 24(%%"REG_c") \n\t" // H3 - H4
+ "paddw %%mm4, %%mm4 \n\t" // 2L2
+ "paddw %%mm5, %%mm5 \n\t" // 2H2
+ "psubw %%mm2, %%mm4 \n\t" // 2L2 - L3 + L4
+ "psubw %%mm3, %%mm5 \n\t" // 2H2 - H3 + H4
+
+ "lea (%%"REG_a", %1), %0 \n\t"
+ "psllw $2, %%mm2 \n\t" // 4L3 - 4L4
+ "psllw $2, %%mm3 \n\t" // 4H3 - 4H4
+ "psubw %%mm2, %%mm4 \n\t" // 2L2 - 5L3 + 5L4
+ "psubw %%mm3, %%mm5 \n\t" // 2H2 - 5H3 + 5H4
+//50 opcodes so far
+ "movq (%0, %1, 2), %%mm2 \n\t"
+ "movq %%mm2, %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t" // L5
+ "punpckhbw %%mm7, %%mm3 \n\t" // H5
+ "psubw %%mm2, %%mm4 \n\t" // 2L2 - 5L3 + 5L4 - L5
+ "psubw %%mm3, %%mm5 \n\t" // 2H2 - 5H3 + 5H4 - H5
+ "psubw %%mm2, %%mm4 \n\t" // 2L2 - 5L3 + 5L4 - 2L5
+ "psubw %%mm3, %%mm5 \n\t" // 2H2 - 5H3 + 5H4 - 2H5
+
+ "movq (%%"REG_a", %1, 4), %%mm6 \n\t"
+ "punpcklbw %%mm7, %%mm6 \n\t" // L6
+ "psubw %%mm6, %%mm2 \n\t" // L5 - L6
+ "movq (%%"REG_a", %1, 4), %%mm6 \n\t"
+ "punpckhbw %%mm7, %%mm6 \n\t" // H6
+ "psubw %%mm6, %%mm3 \n\t" // H5 - H6
+
+ "paddw %%mm0, %%mm0 \n\t" // 2L4
+ "paddw %%mm1, %%mm1 \n\t" // 2H4
+ "psubw %%mm2, %%mm0 \n\t" // 2L4 - L5 + L6
+ "psubw %%mm3, %%mm1 \n\t" // 2H4 - H5 + H6
+
+ "psllw $2, %%mm2 \n\t" // 4L5 - 4L6
+ "psllw $2, %%mm3 \n\t" // 4H5 - 4H6
+ "psubw %%mm2, %%mm0 \n\t" // 2L4 - 5L5 + 5L6
+ "psubw %%mm3, %%mm1 \n\t" // 2H4 - 5H5 + 5H6
+
+ "movq (%0, %1, 4), %%mm2 \n\t"
+ "movq %%mm2, %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t" // L7
+ "punpckhbw %%mm7, %%mm3 \n\t" // H7
+
+ "paddw %%mm2, %%mm2 \n\t" // 2L7
+ "paddw %%mm3, %%mm3 \n\t" // 2H7
+ "psubw %%mm2, %%mm0 \n\t" // 2L4 - 5L5 + 5L6 - 2L7
+ "psubw %%mm3, %%mm1 \n\t" // 2H4 - 5H5 + 5H6 - 2H7
+
+ "movq (%%"REG_c"), %%mm2 \n\t" // 2L0 - 5L1 + 5L2 - 2L3
+ "movq 8(%%"REG_c"), %%mm3 \n\t" // 2H0 - 5H1 + 5H2 - 2H3
+
+#ifdef HAVE_MMX2
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "psubw %%mm0, %%mm6 \n\t"
+ "pmaxsw %%mm6, %%mm0 \n\t" // |2L4 - 5L5 + 5L6 - 2L7|
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "psubw %%mm1, %%mm6 \n\t"
+ "pmaxsw %%mm6, %%mm1 \n\t" // |2H4 - 5H5 + 5H6 - 2H7|
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "psubw %%mm2, %%mm6 \n\t"
+ "pmaxsw %%mm6, %%mm2 \n\t" // |2L0 - 5L1 + 5L2 - 2L3|
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "psubw %%mm3, %%mm6 \n\t"
+ "pmaxsw %%mm6, %%mm3 \n\t" // |2H0 - 5H1 + 5H2 - 2H3|
+#else
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "pcmpgtw %%mm0, %%mm6 \n\t"
+ "pxor %%mm6, %%mm0 \n\t"
+ "psubw %%mm6, %%mm0 \n\t" // |2L4 - 5L5 + 5L6 - 2L7|
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "pcmpgtw %%mm1, %%mm6 \n\t"
+ "pxor %%mm6, %%mm1 \n\t"
+ "psubw %%mm6, %%mm1 \n\t" // |2H4 - 5H5 + 5H6 - 2H7|
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "pcmpgtw %%mm2, %%mm6 \n\t"
+ "pxor %%mm6, %%mm2 \n\t"
+ "psubw %%mm6, %%mm2 \n\t" // |2L0 - 5L1 + 5L2 - 2L3|
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "pcmpgtw %%mm3, %%mm6 \n\t"
+ "pxor %%mm6, %%mm3 \n\t"
+ "psubw %%mm6, %%mm3 \n\t" // |2H0 - 5H1 + 5H2 - 2H3|
+#endif
+
+#ifdef HAVE_MMX2
+ "pminsw %%mm2, %%mm0 \n\t"
+ "pminsw %%mm3, %%mm1 \n\t"
+#else
+ "movq %%mm0, %%mm6 \n\t"
+ "psubusw %%mm2, %%mm6 \n\t"
+ "psubw %%mm6, %%mm0 \n\t"
+ "movq %%mm1, %%mm6 \n\t"
+ "psubusw %%mm3, %%mm6 \n\t"
+ "psubw %%mm6, %%mm1 \n\t"
+#endif
+
+ "movd %2, %%mm2 \n\t" // QP
+ "punpcklbw %%mm7, %%mm2 \n\t"
+
+ "movq %%mm7, %%mm6 \n\t" // 0
+ "pcmpgtw %%mm4, %%mm6 \n\t" // sign(2L2 - 5L3 + 5L4 - 2L5)
+ "pxor %%mm6, %%mm4 \n\t"
+ "psubw %%mm6, %%mm4 \n\t" // |2L2 - 5L3 + 5L4 - 2L5|
+ "pcmpgtw %%mm5, %%mm7 \n\t" // sign(2H2 - 5H3 + 5H4 - 2H5)
+ "pxor %%mm7, %%mm5 \n\t"
+ "psubw %%mm7, %%mm5 \n\t" // |2H2 - 5H3 + 5H4 - 2H5|
+// 100 opcodes
+ "psllw $3, %%mm2 \n\t" // 8QP
+ "movq %%mm2, %%mm3 \n\t" // 8QP
+ "pcmpgtw %%mm4, %%mm2 \n\t"
+ "pcmpgtw %%mm5, %%mm3 \n\t"
+ "pand %%mm2, %%mm4 \n\t"
+ "pand %%mm3, %%mm5 \n\t"
+
+
+ "psubusw %%mm0, %%mm4 \n\t" // hd
+ "psubusw %%mm1, %%mm5 \n\t" // ld
+
+
+ "movq "MANGLE(w05)", %%mm2 \n\t" // 5
+ "pmullw %%mm2, %%mm4 \n\t"
+ "pmullw %%mm2, %%mm5 \n\t"
+ "movq "MANGLE(w20)", %%mm2 \n\t" // 32
+ "paddw %%mm2, %%mm4 \n\t"
+ "paddw %%mm2, %%mm5 \n\t"
+ "psrlw $6, %%mm4 \n\t"
+ "psrlw $6, %%mm5 \n\t"
+
+ "movq 16(%%"REG_c"), %%mm0 \n\t" // L3 - L4
+ "movq 24(%%"REG_c"), %%mm1 \n\t" // H3 - H4
+
+ "pxor %%mm2, %%mm2 \n\t"
+ "pxor %%mm3, %%mm3 \n\t"
+
+ "pcmpgtw %%mm0, %%mm2 \n\t" // sign (L3-L4)
+ "pcmpgtw %%mm1, %%mm3 \n\t" // sign (H3-H4)
+ "pxor %%mm2, %%mm0 \n\t"
+ "pxor %%mm3, %%mm1 \n\t"
+ "psubw %%mm2, %%mm0 \n\t" // |L3-L4|
+ "psubw %%mm3, %%mm1 \n\t" // |H3-H4|
+ "psrlw $1, %%mm0 \n\t" // |L3 - L4|/2
+ "psrlw $1, %%mm1 \n\t" // |H3 - H4|/2
+
+ "pxor %%mm6, %%mm2 \n\t"
+ "pxor %%mm7, %%mm3 \n\t"
+ "pand %%mm2, %%mm4 \n\t"
+ "pand %%mm3, %%mm5 \n\t"
+
+#ifdef HAVE_MMX2
+ "pminsw %%mm0, %%mm4 \n\t"
+ "pminsw %%mm1, %%mm5 \n\t"
+#else
+ "movq %%mm4, %%mm2 \n\t"
+ "psubusw %%mm0, %%mm2 \n\t"
+ "psubw %%mm2, %%mm4 \n\t"
+ "movq %%mm5, %%mm2 \n\t"
+ "psubusw %%mm1, %%mm2 \n\t"
+ "psubw %%mm2, %%mm5 \n\t"
+#endif
+ "pxor %%mm6, %%mm4 \n\t"
+ "pxor %%mm7, %%mm5 \n\t"
+ "psubw %%mm6, %%mm4 \n\t"
+ "psubw %%mm7, %%mm5 \n\t"
+ "packsswb %%mm5, %%mm4 \n\t"
+ "movq %3, %%mm1 \n\t"
+ "pandn %%mm4, %%mm1 \n\t"
+ "movq (%0), %%mm0 \n\t"
+ "paddb %%mm1, %%mm0 \n\t"
+ "movq %%mm0, (%0) \n\t"
+ "movq (%0, %1), %%mm0 \n\t"
+ "psubb %%mm1, %%mm0 \n\t"
+ "movq %%mm0, (%0, %1) \n\t"
+
+ : "+r" (temp_src)
+ : "r" ((long)step), "m" (c->pQPb), "m"(eq_mask)
+ : "%"REG_a, "%"REG_c
+ );
+ }
+/*if(step==16){
+ STOP_TIMER("step16")
+}else{
+ STOP_TIMER("stepX")
+}*/
+}
+#endif //HAVE_MMX
+
+static void RENAME(postProcess)(uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height,
+ QP_STORE_T QPs[], int QPStride, int isColor, PPContext *c);
+
+/**
+ * Copies a block from src to dst and fixes the blacklevel
+ * levelFix == 0 -> dont touch the brighness & contrast
+ */
+#undef SCALED_CPY
+
+static inline void RENAME(blockCopy)(uint8_t dst[], int dstStride, uint8_t src[], int srcStride,
+ int levelFix, int64_t *packedOffsetAndScale)
+{
+#ifndef HAVE_MMX
+ int i;
+#endif
+ if(levelFix)
+ {
+#ifdef HAVE_MMX
+ asm volatile(
+ "movq (%%"REG_a"), %%mm2 \n\t" // packedYOffset
+ "movq 8(%%"REG_a"), %%mm3 \n\t" // packedYScale
+ "lea (%2,%4), %%"REG_a" \n\t"
+ "lea (%3,%5), %%"REG_d" \n\t"
+ "pxor %%mm4, %%mm4 \n\t"
+#ifdef HAVE_MMX2
+#define REAL_SCALED_CPY(src1, src2, dst1, dst2) \
+ "movq " #src1 ", %%mm0 \n\t"\
+ "movq " #src1 ", %%mm5 \n\t"\
+ "movq " #src2 ", %%mm1 \n\t"\
+ "movq " #src2 ", %%mm6 \n\t"\
+ "punpcklbw %%mm0, %%mm0 \n\t"\
+ "punpckhbw %%mm5, %%mm5 \n\t"\
+ "punpcklbw %%mm1, %%mm1 \n\t"\
+ "punpckhbw %%mm6, %%mm6 \n\t"\
+ "pmulhuw %%mm3, %%mm0 \n\t"\
+ "pmulhuw %%mm3, %%mm5 \n\t"\
+ "pmulhuw %%mm3, %%mm1 \n\t"\
+ "pmulhuw %%mm3, %%mm6 \n\t"\
+ "psubw %%mm2, %%mm0 \n\t"\
+ "psubw %%mm2, %%mm5 \n\t"\
+ "psubw %%mm2, %%mm1 \n\t"\
+ "psubw %%mm2, %%mm6 \n\t"\
+ "packuswb %%mm5, %%mm0 \n\t"\
+ "packuswb %%mm6, %%mm1 \n\t"\
+ "movq %%mm0, " #dst1 " \n\t"\
+ "movq %%mm1, " #dst2 " \n\t"\
+
+#else //HAVE_MMX2
+#define REAL_SCALED_CPY(src1, src2, dst1, dst2) \
+ "movq " #src1 ", %%mm0 \n\t"\
+ "movq " #src1 ", %%mm5 \n\t"\
+ "punpcklbw %%mm4, %%mm0 \n\t"\
+ "punpckhbw %%mm4, %%mm5 \n\t"\
+ "psubw %%mm2, %%mm0 \n\t"\
+ "psubw %%mm2, %%mm5 \n\t"\
+ "movq " #src2 ", %%mm1 \n\t"\
+ "psllw $6, %%mm0 \n\t"\
+ "psllw $6, %%mm5 \n\t"\
+ "pmulhw %%mm3, %%mm0 \n\t"\
+ "movq " #src2 ", %%mm6 \n\t"\
+ "pmulhw %%mm3, %%mm5 \n\t"\
+ "punpcklbw %%mm4, %%mm1 \n\t"\
+ "punpckhbw %%mm4, %%mm6 \n\t"\
+ "psubw %%mm2, %%mm1 \n\t"\
+ "psubw %%mm2, %%mm6 \n\t"\
+ "psllw $6, %%mm1 \n\t"\
+ "psllw $6, %%mm6 \n\t"\
+ "pmulhw %%mm3, %%mm1 \n\t"\
+ "pmulhw %%mm3, %%mm6 \n\t"\
+ "packuswb %%mm5, %%mm0 \n\t"\
+ "packuswb %%mm6, %%mm1 \n\t"\
+ "movq %%mm0, " #dst1 " \n\t"\
+ "movq %%mm1, " #dst2 " \n\t"\
+
+#endif //HAVE_MMX2
+#define SCALED_CPY(src1, src2, dst1, dst2)\
+ REAL_SCALED_CPY(src1, src2, dst1, dst2)
+
+SCALED_CPY((%2) , (%2, %4) , (%3) , (%3, %5))
+SCALED_CPY((%2, %4, 2), (%%REGa, %4, 2), (%3, %5, 2), (%%REGd, %5, 2))
+SCALED_CPY((%2, %4, 4), (%%REGa, %4, 4), (%3, %5, 4), (%%REGd, %5, 4))
+ "lea (%%"REG_a",%4,4), %%"REG_a" \n\t"
+ "lea (%%"REG_d",%5,4), %%"REG_d" \n\t"
+SCALED_CPY((%%REGa, %4), (%%REGa, %4, 2), (%%REGd, %5), (%%REGd, %5, 2))
+
+
+ : "=&a" (packedOffsetAndScale)
+ : "0" (packedOffsetAndScale),
+ "r"(src),
+ "r"(dst),
+ "r" ((long)srcStride),
+ "r" ((long)dstStride)
+ : "%"REG_d
+ );
+#else //HAVE_MMX
+ for(i=0; i<8; i++)
+ memcpy( &(dst[dstStride*i]),
+ &(src[srcStride*i]), BLOCK_SIZE);
+#endif //HAVE_MMX
+ }
+ else
+ {
+#ifdef HAVE_MMX
+ asm volatile(
+ "lea (%0,%2), %%"REG_a" \n\t"
+ "lea (%1,%3), %%"REG_d" \n\t"
+
+#define REAL_SIMPLE_CPY(src1, src2, dst1, dst2) \
+ "movq " #src1 ", %%mm0 \n\t"\
+ "movq " #src2 ", %%mm1 \n\t"\
+ "movq %%mm0, " #dst1 " \n\t"\
+ "movq %%mm1, " #dst2 " \n\t"\
+
+#define SIMPLE_CPY(src1, src2, dst1, dst2)\
+ REAL_SIMPLE_CPY(src1, src2, dst1, dst2)
+
+SIMPLE_CPY((%0) , (%0, %2) , (%1) , (%1, %3))
+SIMPLE_CPY((%0, %2, 2), (%%REGa, %2, 2), (%1, %3, 2), (%%REGd, %3, 2))
+SIMPLE_CPY((%0, %2, 4), (%%REGa, %2, 4), (%1, %3, 4), (%%REGd, %3, 4))
+ "lea (%%"REG_a",%2,4), %%"REG_a" \n\t"
+ "lea (%%"REG_d",%3,4), %%"REG_d" \n\t"
+SIMPLE_CPY((%%REGa, %2), (%%REGa, %2, 2), (%%REGd, %3), (%%REGd, %3, 2))
+
+ : : "r" (src),
+ "r" (dst),
+ "r" ((long)srcStride),
+ "r" ((long)dstStride)
+ : "%"REG_a, "%"REG_d
+ );
+#else //HAVE_MMX
+ for(i=0; i<8; i++)
+ memcpy( &(dst[dstStride*i]),
+ &(src[srcStride*i]), BLOCK_SIZE);
+#endif //HAVE_MMX
+ }
+}
+
+/**
+ * Duplicates the given 8 src pixels ? times upward
+ */
+static inline void RENAME(duplicate)(uint8_t src[], int stride)
+{
+#ifdef HAVE_MMX
+ asm volatile(
+ "movq (%0), %%mm0 \n\t"
+ "add %1, %0 \n\t"
+ "movq %%mm0, (%0) \n\t"
+ "movq %%mm0, (%0, %1) \n\t"
+ "movq %%mm0, (%0, %1, 2) \n\t"
+ : "+r" (src)
+ : "r" ((long)-stride)
+ );
+#else
+ int i;
+ uint8_t *p=src;
+ for(i=0; i<3; i++)
+ {
+ p-= stride;
+ memcpy(p, src, 8);
+ }
+#endif
+}
+
+/**
+ * Filters array of bytes (Y or U or V values)
+ */
+static void RENAME(postProcess)(uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height,
+ QP_STORE_T QPs[], int QPStride, int isColor, PPContext *c2)
+{
+ PPContext __attribute__((aligned(8))) c= *c2; //copy to stack for faster access
+ int x,y;
+#ifdef COMPILE_TIME_MODE
+ const int mode= COMPILE_TIME_MODE;
+#else
+ const int mode= isColor ? c.ppMode.chromMode : c.ppMode.lumMode;
+#endif
+ int black=0, white=255; // blackest black and whitest white in the picture
+ int QPCorrecture= 256*256;
+
+ int copyAhead;
+#ifdef HAVE_MMX
+ int i;
+#endif
+
+ const int qpHShift= isColor ? 4-c.hChromaSubSample : 4;
+ const int qpVShift= isColor ? 4-c.vChromaSubSample : 4;
+
+ //FIXME remove
+ uint64_t * const yHistogram= c.yHistogram;
+ uint8_t * const tempSrc= srcStride > 0 ? c.tempSrc : c.tempSrc - 23*srcStride;
+ uint8_t * const tempDst= dstStride > 0 ? c.tempDst : c.tempDst - 23*dstStride;
+ //const int mbWidth= isColor ? (width+7)>>3 : (width+15)>>4;
+
+#ifdef HAVE_MMX
+ for(i=0; i<57; i++){
+ int offset= ((i*c.ppMode.baseDcDiff)>>8) + 1;
+ int threshold= offset*2 + 1;
+ c.mmxDcOffset[i]= 0x7F - offset;
+ c.mmxDcThreshold[i]= 0x7F - threshold;
+ c.mmxDcOffset[i]*= 0x0101010101010101LL;
+ c.mmxDcThreshold[i]*= 0x0101010101010101LL;
+ }
+#endif
+
+ if(mode & CUBIC_IPOL_DEINT_FILTER) copyAhead=16;
+ else if( (mode & LINEAR_BLEND_DEINT_FILTER)
+ || (mode & FFMPEG_DEINT_FILTER)
+ || (mode & LOWPASS5_DEINT_FILTER)) copyAhead=14;
+ else if( (mode & V_DEBLOCK)
+ || (mode & LINEAR_IPOL_DEINT_FILTER)
+ || (mode & MEDIAN_DEINT_FILTER)
+ || (mode & V_A_DEBLOCK)) copyAhead=13;
+ else if(mode & V_X1_FILTER) copyAhead=11;
+// else if(mode & V_RK1_FILTER) copyAhead=10;
+ else if(mode & DERING) copyAhead=9;
+ else copyAhead=8;
+
+ copyAhead-= 8;
+
+ if(!isColor)
+ {
+ uint64_t sum= 0;
+ int i;
+ uint64_t maxClipped;
+ uint64_t clipped;
+ double scale;
+
+ c.frameNum++;
+ // first frame is fscked so we ignore it
+ if(c.frameNum == 1) yHistogram[0]= width*height/64*15/256;
+
+ for(i=0; i<256; i++)
+ {
+ sum+= yHistogram[i];
+ }
+
+ /* we allways get a completly black picture first */
+ maxClipped= (uint64_t)(sum * c.ppMode.maxClippedThreshold);
+
+ clipped= sum;
+ for(black=255; black>0; black--)
+ {
+ if(clipped < maxClipped) break;
+ clipped-= yHistogram[black];
+ }
+
+ clipped= sum;
+ for(white=0; white<256; white++)
+ {
+ if(clipped < maxClipped) break;
+ clipped-= yHistogram[white];
+ }
+
+ scale= (double)(c.ppMode.maxAllowedY - c.ppMode.minAllowedY) / (double)(white-black);
+
+#ifdef HAVE_MMX2
+ c.packedYScale= (uint16_t)(scale*256.0 + 0.5);
+ c.packedYOffset= (((black*c.packedYScale)>>8) - c.ppMode.minAllowedY) & 0xFFFF;
+#else
+ c.packedYScale= (uint16_t)(scale*1024.0 + 0.5);
+ c.packedYOffset= (black - c.ppMode.minAllowedY) & 0xFFFF;
+#endif
+
+ c.packedYOffset|= c.packedYOffset<<32;
+ c.packedYOffset|= c.packedYOffset<<16;
+
+ c.packedYScale|= c.packedYScale<<32;
+ c.packedYScale|= c.packedYScale<<16;
+
+ if(mode & LEVEL_FIX) QPCorrecture= (int)(scale*256*256 + 0.5);
+ else QPCorrecture= 256*256;
+ }
+ else
+ {
+ c.packedYScale= 0x0100010001000100LL;
+ c.packedYOffset= 0;
+ QPCorrecture= 256*256;
+ }
+
+ /* copy & deinterlace first row of blocks */
+ y=-BLOCK_SIZE;
+ {
+ uint8_t *srcBlock= &(src[y*srcStride]);
+ uint8_t *dstBlock= tempDst + dstStride;
+
+ // From this point on it is guranteed that we can read and write 16 lines downward
+ // finish 1 block before the next otherwise we might have a problem
+ // with the L1 Cache of the P4 ... or only a few blocks at a time or soemthing
+ for(x=0; x<width; x+=BLOCK_SIZE)
+ {
+
+#ifdef HAVE_MMX2
+/*
+ prefetchnta(srcBlock + (((x>>2)&6) + 5)*srcStride + 32);
+ prefetchnta(srcBlock + (((x>>2)&6) + 6)*srcStride + 32);
+ prefetcht0(dstBlock + (((x>>2)&6) + 5)*dstStride + 32);
+ prefetcht0(dstBlock + (((x>>2)&6) + 6)*dstStride + 32);
+*/
+
+ asm(
+ "mov %4, %%"REG_a" \n\t"
+ "shr $2, %%"REG_a" \n\t"
+ "and $6, %%"REG_a" \n\t"
+ "add %5, %%"REG_a" \n\t"
+ "mov %%"REG_a", %%"REG_d" \n\t"
+ "imul %1, %%"REG_a" \n\t"
+ "imul %3, %%"REG_d" \n\t"
+ "prefetchnta 32(%%"REG_a", %0) \n\t"
+ "prefetcht0 32(%%"REG_d", %2) \n\t"
+ "add %1, %%"REG_a" \n\t"
+ "add %3, %%"REG_d" \n\t"
+ "prefetchnta 32(%%"REG_a", %0) \n\t"
+ "prefetcht0 32(%%"REG_d", %2) \n\t"
+ :: "r" (srcBlock), "r" ((long)srcStride), "r" (dstBlock), "r" ((long)dstStride),
+ "g" ((long)x), "g" ((long)copyAhead)
+ : "%"REG_a, "%"REG_d
+ );
+
+#elif defined(HAVE_3DNOW)
+//FIXME check if this is faster on an 3dnow chip or if its faster without the prefetch or ...
+/* prefetch(srcBlock + (((x>>3)&3) + 5)*srcStride + 32);
+ prefetch(srcBlock + (((x>>3)&3) + 9)*srcStride + 32);
+ prefetchw(dstBlock + (((x>>3)&3) + 5)*dstStride + 32);
+ prefetchw(dstBlock + (((x>>3)&3) + 9)*dstStride + 32);
+*/
+#endif
+
+ RENAME(blockCopy)(dstBlock + dstStride*8, dstStride,
+ srcBlock + srcStride*8, srcStride, mode & LEVEL_FIX, &c.packedYOffset);
+
+ RENAME(duplicate)(dstBlock + dstStride*8, dstStride);
+
+ if(mode & LINEAR_IPOL_DEINT_FILTER)
+ RENAME(deInterlaceInterpolateLinear)(dstBlock, dstStride);
+ else if(mode & LINEAR_BLEND_DEINT_FILTER)
+ RENAME(deInterlaceBlendLinear)(dstBlock, dstStride, c.deintTemp + x);
+ else if(mode & MEDIAN_DEINT_FILTER)
+ RENAME(deInterlaceMedian)(dstBlock, dstStride);
+ else if(mode & CUBIC_IPOL_DEINT_FILTER)
+ RENAME(deInterlaceInterpolateCubic)(dstBlock, dstStride);
+ else if(mode & FFMPEG_DEINT_FILTER)
+ RENAME(deInterlaceFF)(dstBlock, dstStride, c.deintTemp + x);
+ else if(mode & LOWPASS5_DEINT_FILTER)
+ RENAME(deInterlaceL5)(dstBlock, dstStride, c.deintTemp + x, c.deintTemp + width + x);
+/* else if(mode & CUBIC_BLEND_DEINT_FILTER)
+ RENAME(deInterlaceBlendCubic)(dstBlock, dstStride);
+*/
+ dstBlock+=8;
+ srcBlock+=8;
+ }
+ if(width==FFABS(dstStride))
+ linecpy(dst, tempDst + 9*dstStride, copyAhead, dstStride);
+ else
+ {
+ int i;
+ for(i=0; i<copyAhead; i++)
+ {
+ memcpy(dst + i*dstStride, tempDst + (9+i)*dstStride, width);
+ }
+ }
+ }
+
+ for(y=0; y<height; y+=BLOCK_SIZE)
+ {
+ //1% speedup if these are here instead of the inner loop
+ uint8_t *srcBlock= &(src[y*srcStride]);
+ uint8_t *dstBlock= &(dst[y*dstStride]);
+#ifdef HAVE_MMX
+ uint8_t *tempBlock1= c.tempBlocks;
+ uint8_t *tempBlock2= c.tempBlocks + 8;
+#endif
+ int8_t *QPptr= &QPs[(y>>qpVShift)*QPStride];
+ int8_t *nonBQPptr= &c.nonBQPTable[(y>>qpVShift)*FFABS(QPStride)];
+ int QP=0;
+ /* can we mess with a 8x16 block from srcBlock/dstBlock downwards and 1 line upwards
+ if not than use a temporary buffer */
+ if(y+15 >= height)
+ {
+ int i;
+ /* copy from line (copyAhead) to (copyAhead+7) of src, these will be copied with
+ blockcopy to dst later */
+ linecpy(tempSrc + srcStride*copyAhead, srcBlock + srcStride*copyAhead,
+ FFMAX(height-y-copyAhead, 0), srcStride);
+
+ /* duplicate last line of src to fill the void upto line (copyAhead+7) */
+ for(i=FFMAX(height-y, 8); i<copyAhead+8; i++)
+ memcpy(tempSrc + srcStride*i, src + srcStride*(height-1), FFABS(srcStride));
+
+ /* copy up to (copyAhead+1) lines of dst (line -1 to (copyAhead-1))*/
+ linecpy(tempDst, dstBlock - dstStride, FFMIN(height-y+1, copyAhead+1), dstStride);
+
+ /* duplicate last line of dst to fill the void upto line (copyAhead) */
+ for(i=height-y+1; i<=copyAhead; i++)
+ memcpy(tempDst + dstStride*i, dst + dstStride*(height-1), FFABS(dstStride));
+
+ dstBlock= tempDst + dstStride;
+ srcBlock= tempSrc;
+ }
+
+ // From this point on it is guranteed that we can read and write 16 lines downward
+ // finish 1 block before the next otherwise we might have a problem
+ // with the L1 Cache of the P4 ... or only a few blocks at a time or soemthing
+ for(x=0; x<width; x+=BLOCK_SIZE)
+ {
+ const int stride= dstStride;
+#ifdef HAVE_MMX
+ uint8_t *tmpXchg;
+#endif
+ if(isColor)
+ {
+ QP= QPptr[x>>qpHShift];
+ c.nonBQP= nonBQPptr[x>>qpHShift];
+ }
+ else
+ {
+ QP= QPptr[x>>4];
+ QP= (QP* QPCorrecture + 256*128)>>16;
+ c.nonBQP= nonBQPptr[x>>4];
+ c.nonBQP= (c.nonBQP* QPCorrecture + 256*128)>>16;
+ yHistogram[ srcBlock[srcStride*12 + 4] ]++;
+ }
+ c.QP= QP;
+#ifdef HAVE_MMX
+ asm volatile(
+ "movd %1, %%mm7 \n\t"
+ "packuswb %%mm7, %%mm7 \n\t" // 0, 0, 0, QP, 0, 0, 0, QP
+ "packuswb %%mm7, %%mm7 \n\t" // 0,QP, 0, QP, 0,QP, 0, QP
+ "packuswb %%mm7, %%mm7 \n\t" // QP,..., QP
+ "movq %%mm7, %0 \n\t"
+ : "=m" (c.pQPb)
+ : "r" (QP)
+ );
+#endif
+
+
+#ifdef HAVE_MMX2
+/*
+ prefetchnta(srcBlock + (((x>>2)&6) + 5)*srcStride + 32);
+ prefetchnta(srcBlock + (((x>>2)&6) + 6)*srcStride + 32);
+ prefetcht0(dstBlock + (((x>>2)&6) + 5)*dstStride + 32);
+ prefetcht0(dstBlock + (((x>>2)&6) + 6)*dstStride + 32);
+*/
+
+ asm(
+ "mov %4, %%"REG_a" \n\t"
+ "shr $2, %%"REG_a" \n\t"
+ "and $6, %%"REG_a" \n\t"
+ "add %5, %%"REG_a" \n\t"
+ "mov %%"REG_a", %%"REG_d" \n\t"
+ "imul %1, %%"REG_a" \n\t"
+ "imul %3, %%"REG_d" \n\t"
+ "prefetchnta 32(%%"REG_a", %0) \n\t"
+ "prefetcht0 32(%%"REG_d", %2) \n\t"
+ "add %1, %%"REG_a" \n\t"
+ "add %3, %%"REG_d" \n\t"
+ "prefetchnta 32(%%"REG_a", %0) \n\t"
+ "prefetcht0 32(%%"REG_d", %2) \n\t"
+ :: "r" (srcBlock), "r" ((long)srcStride), "r" (dstBlock), "r" ((long)dstStride),
+ "g" ((long)x), "g" ((long)copyAhead)
+ : "%"REG_a, "%"REG_d
+ );
+
+#elif defined(HAVE_3DNOW)
+//FIXME check if this is faster on an 3dnow chip or if its faster without the prefetch or ...
+/* prefetch(srcBlock + (((x>>3)&3) + 5)*srcStride + 32);
+ prefetch(srcBlock + (((x>>3)&3) + 9)*srcStride + 32);
+ prefetchw(dstBlock + (((x>>3)&3) + 5)*dstStride + 32);
+ prefetchw(dstBlock + (((x>>3)&3) + 9)*dstStride + 32);
+*/
+#endif
+
+ RENAME(blockCopy)(dstBlock + dstStride*copyAhead, dstStride,
+ srcBlock + srcStride*copyAhead, srcStride, mode & LEVEL_FIX, &c.packedYOffset);
+
+ if(mode & LINEAR_IPOL_DEINT_FILTER)
+ RENAME(deInterlaceInterpolateLinear)(dstBlock, dstStride);
+ else if(mode & LINEAR_BLEND_DEINT_FILTER)
+ RENAME(deInterlaceBlendLinear)(dstBlock, dstStride, c.deintTemp + x);
+ else if(mode & MEDIAN_DEINT_FILTER)
+ RENAME(deInterlaceMedian)(dstBlock, dstStride);
+ else if(mode & CUBIC_IPOL_DEINT_FILTER)
+ RENAME(deInterlaceInterpolateCubic)(dstBlock, dstStride);
+ else if(mode & FFMPEG_DEINT_FILTER)
+ RENAME(deInterlaceFF)(dstBlock, dstStride, c.deintTemp + x);
+ else if(mode & LOWPASS5_DEINT_FILTER)
+ RENAME(deInterlaceL5)(dstBlock, dstStride, c.deintTemp + x, c.deintTemp + width + x);
+/* else if(mode & CUBIC_BLEND_DEINT_FILTER)
+ RENAME(deInterlaceBlendCubic)(dstBlock, dstStride);
+*/
+
+ /* only deblock if we have 2 blocks */
+ if(y + 8 < height)
+ {
+ if(mode & V_X1_FILTER)
+ RENAME(vertX1Filter)(dstBlock, stride, &c);
+ else if(mode & V_DEBLOCK)
+ {
+ const int t= RENAME(vertClassify)(dstBlock, stride, &c);
+
+ if(t==1)
+ RENAME(doVertLowPass)(dstBlock, stride, &c);
+ else if(t==2)
+ RENAME(doVertDefFilter)(dstBlock, stride, &c);
+ }else if(mode & V_A_DEBLOCK){
+ RENAME(do_a_deblock)(dstBlock, stride, 1, &c);
+ }
+ }
+
+#ifdef HAVE_MMX
+ RENAME(transpose1)(tempBlock1, tempBlock2, dstBlock, dstStride);
+#endif
+ /* check if we have a previous block to deblock it with dstBlock */
+ if(x - 8 >= 0)
+ {
+#ifdef HAVE_MMX
+ if(mode & H_X1_FILTER)
+ RENAME(vertX1Filter)(tempBlock1, 16, &c);
+ else if(mode & H_DEBLOCK)
+ {
+//START_TIMER
+ const int t= RENAME(vertClassify)(tempBlock1, 16, &c);
+//STOP_TIMER("dc & minmax")
+ if(t==1)
+ RENAME(doVertLowPass)(tempBlock1, 16, &c);
+ else if(t==2)
+ RENAME(doVertDefFilter)(tempBlock1, 16, &c);
+ }else if(mode & H_A_DEBLOCK){
+ RENAME(do_a_deblock)(tempBlock1, 16, 1, &c);
+ }
+
+ RENAME(transpose2)(dstBlock-4, dstStride, tempBlock1 + 4*16);
+
+#else
+ if(mode & H_X1_FILTER)
+ horizX1Filter(dstBlock-4, stride, QP);
+ else if(mode & H_DEBLOCK)
+ {
+#ifdef HAVE_ALTIVEC
+ unsigned char __attribute__ ((aligned(16))) tempBlock[272];
+ transpose_16x8_char_toPackedAlign_altivec(tempBlock, dstBlock - (4 + 1), stride);
+
+ const int t=vertClassify_altivec(tempBlock-48, 16, &c);
+ if(t==1) {
+ doVertLowPass_altivec(tempBlock-48, 16, &c);
+ transpose_8x16_char_fromPackedAlign_altivec(dstBlock - (4 + 1), tempBlock, stride);
+ }
+ else if(t==2) {
+ doVertDefFilter_altivec(tempBlock-48, 16, &c);
+ transpose_8x16_char_fromPackedAlign_altivec(dstBlock - (4 + 1), tempBlock, stride);
+ }
+#else
+ const int t= RENAME(horizClassify)(dstBlock-4, stride, &c);
+
+ if(t==1)
+ RENAME(doHorizLowPass)(dstBlock-4, stride, &c);
+ else if(t==2)
+ RENAME(doHorizDefFilter)(dstBlock-4, stride, &c);
+#endif
+ }else if(mode & H_A_DEBLOCK){
+ RENAME(do_a_deblock)(dstBlock-8, 1, stride, &c);
+ }
+#endif //HAVE_MMX
+ if(mode & DERING)
+ {
+ //FIXME filter first line
+ if(y>0) RENAME(dering)(dstBlock - stride - 8, stride, &c);
+ }
+
+ if(mode & TEMP_NOISE_FILTER)
+ {
+ RENAME(tempNoiseReducer)(dstBlock-8, stride,
+ c.tempBlured[isColor] + y*dstStride + x,
+ c.tempBluredPast[isColor] + (y>>3)*256 + (x>>3),
+ c.ppMode.maxTmpNoise);
+ }
+ }
+
+ dstBlock+=8;
+ srcBlock+=8;
+
+#ifdef HAVE_MMX
+ tmpXchg= tempBlock1;
+ tempBlock1= tempBlock2;
+ tempBlock2 = tmpXchg;
+#endif
+ }
+
+ if(mode & DERING)
+ {
+ if(y > 0) RENAME(dering)(dstBlock - dstStride - 8, dstStride, &c);
+ }
+
+ if((mode & TEMP_NOISE_FILTER))
+ {
+ RENAME(tempNoiseReducer)(dstBlock-8, dstStride,
+ c.tempBlured[isColor] + y*dstStride + x,
+ c.tempBluredPast[isColor] + (y>>3)*256 + (x>>3),
+ c.ppMode.maxTmpNoise);
+ }
+
+ /* did we use a tmp buffer for the last lines*/
+ if(y+15 >= height)
+ {
+ uint8_t *dstBlock= &(dst[y*dstStride]);
+ if(width==FFABS(dstStride))
+ linecpy(dstBlock, tempDst + dstStride, height-y, dstStride);
+ else
+ {
+ int i;
+ for(i=0; i<height-y; i++)
+ {
+ memcpy(dstBlock + i*dstStride, tempDst + (i+1)*dstStride, width);
+ }
+ }
+ }
+/*
+ for(x=0; x<width; x+=32)
+ {
+ volatile int i;
+ i+= + dstBlock[x + 7*dstStride] + dstBlock[x + 8*dstStride]
+ + dstBlock[x + 9*dstStride] + dstBlock[x +10*dstStride]
+ + dstBlock[x +11*dstStride] + dstBlock[x +12*dstStride];
+// + dstBlock[x +13*dstStride]
+// + dstBlock[x +14*dstStride] + dstBlock[x +15*dstStride];
+ }*/
+ }
+#ifdef HAVE_3DNOW
+ asm volatile("femms");
+#elif defined (HAVE_MMX)
+ asm volatile("emms");
+#endif
+
+#ifdef DEBUG_BRIGHTNESS
+ if(!isColor)
+ {
+ int max=1;
+ int i;
+ for(i=0; i<256; i++)
+ if(yHistogram[i] > max) max=yHistogram[i];
+
+ for(i=1; i<256; i++)
+ {
+ int x;
+ int start=yHistogram[i-1]/(max/256+1);
+ int end=yHistogram[i]/(max/256+1);
+ int inc= end > start ? 1 : -1;
+ for(x=start; x!=end+inc; x+=inc)
+ dst[ i*dstStride + x]+=128;
+ }
+
+ for(i=0; i<100; i+=2)
+ {
+ dst[ (white)*dstStride + i]+=128;
+ dst[ (black)*dstStride + i]+=128;
+ }
+
+ }
+#endif
+
+ *c2= c; //copy local context back
+
+}
diff --git a/contrib/ffmpeg/libswscale/Makefile b/contrib/ffmpeg/libswscale/Makefile
new file mode 100644
index 000000000..82e9bfc02
--- /dev/null
+++ b/contrib/ffmpeg/libswscale/Makefile
@@ -0,0 +1,26 @@
+
+include ../config.mak
+
+NAME=swscale
+ifeq ($(BUILD_SHARED),yes)
+LIBVERSION=$(SWSVERSION)
+LIBMAJOR=$(SWSMAJOR)
+endif
+
+EXTRALIBS := -L$(BUILD_ROOT)/libavutil -lavutil$(BUILDSUF) $(EXTRALIBS)
+
+OBJS= swscale.o rgb2rgb.o yuv2rgb.o
+ifeq ($(TARGET_ALTIVEC),yes)
+OBJS+= yuv2rgb_altivec.o
+endif
+
+HEADERS = swscale.h rgb2rgb.h
+
+include ../common.mak
+
+cs_test: cs_test.c $(LIB)
+
+swscale-example: swscale-example.o $(LIB)
+
+clean::
+ rm -f cs_test swscale-example
diff --git a/contrib/ffmpeg/libswscale/cs_test.c b/contrib/ffmpeg/libswscale/cs_test.c
new file mode 100644
index 000000000..6b2deab3e
--- /dev/null
+++ b/contrib/ffmpeg/libswscale/cs_test.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <string.h> /* for memset() */
+#include <unistd.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <malloc.h>
+
+#include "swscale.h"
+#include "rgb2rgb.h"
+
+#define SIZE 1000
+#define srcByte 0x55
+#define dstByte 0xBB
+
+#ifdef __APPLE_CC__
+#define memalign(x,y) malloc(y)
+#endif
+
+static int cpu_caps;
+
+static char *args_parse(int argc, char *argv[])
+{
+ int o;
+
+ while ((o = getopt(argc, argv, "m23")) != -1) {
+ switch (o) {
+ case 'm':
+ cpu_caps |= SWS_CPU_CAPS_MMX;
+ break;
+ case '2':
+ cpu_caps |= SWS_CPU_CAPS_MMX2;
+ break;
+ case '3':
+ cpu_caps |= SWS_CPU_CAPS_3DNOW;
+ break;
+ default:
+ fprintf(stderr, "Unknown option %c\n", o);
+ }
+ }
+
+ return argv[optind];
+}
+
+int main(int argc, char **argv)
+{
+ int i, funcNum;
+ uint8_t *srcBuffer= (uint8_t*)memalign(128, SIZE);
+ uint8_t *dstBuffer= (uint8_t*)memalign(128, SIZE);
+ int failedNum=0;
+ int passedNum=0;
+
+ printf("memory corruption test ...\n");
+ args_parse(argc, argv);
+ fprintf(stderr, "CPU capabilities forced to %x\n", cpu_caps);
+ sws_rgb2rgb_init(cpu_caps);
+
+ for(funcNum=0; funcNum<100; funcNum++){
+ int width;
+ int failed=0;
+ int srcBpp=0;
+ int dstBpp=0;
+
+ printf("."); fflush(stdout);
+ memset(srcBuffer, srcByte, SIZE);
+
+ for(width=32; width<64; width++){
+ int dstOffset;
+ for(dstOffset=128; dstOffset<196; dstOffset++){
+ int srcOffset;
+ memset(dstBuffer, dstByte, SIZE);
+
+ for(srcOffset=128; srcOffset<196; srcOffset++){
+ uint8_t *src= srcBuffer+srcOffset;
+ uint8_t *dst= dstBuffer+dstOffset;
+ char *name=NULL;
+
+ if(failed) break; //don't fill the screen with shit ...
+
+ switch(funcNum){
+ case 0:
+ srcBpp=2;
+ dstBpp=2;
+ name="rgb15to16";
+ rgb15to16(src, dst, width*srcBpp);
+ break;
+ case 1:
+ srcBpp=2;
+ dstBpp=3;
+ name="rgb15to24";
+ rgb15to24(src, dst, width*srcBpp);
+ break;
+ case 2:
+ srcBpp=2;
+ dstBpp=4;
+ name="rgb15to32";
+ rgb15to32(src, dst, width*srcBpp);
+ break;
+ case 3:
+ srcBpp=2;
+ dstBpp=3;
+ name="rgb16to24";
+ rgb16to24(src, dst, width*srcBpp);
+ break;
+ case 4:
+ srcBpp=2;
+ dstBpp=4;
+ name="rgb16to32";
+ rgb16to32(src, dst, width*srcBpp);
+ break;
+ case 5:
+ srcBpp=3;
+ dstBpp=2;
+ name="rgb24to15";
+ rgb24to15(src, dst, width*srcBpp);
+ break;
+ case 6:
+ srcBpp=3;
+ dstBpp=2;
+ name="rgb24to16";
+ rgb24to16(src, dst, width*srcBpp);
+ break;
+ case 7:
+ srcBpp=3;
+ dstBpp=4;
+ name="rgb24to32";
+ rgb24to32(src, dst, width*srcBpp);
+ break;
+ case 8:
+ srcBpp=4;
+ dstBpp=2;
+ name="rgb32to15";
+ rgb32to15(src, dst, width*srcBpp);
+ break;
+ case 9:
+ srcBpp=4;
+ dstBpp=2;
+ name="rgb32to16";
+ rgb32to16(src, dst, width*srcBpp);
+ break;
+ case 10:
+ srcBpp=4;
+ dstBpp=3;
+ name="rgb32to24";
+ rgb32to24(src, dst, width*srcBpp);
+ break;
+ case 11:
+ srcBpp=2;
+ dstBpp=2;
+ name="rgb16to15";
+ rgb16to15(src, dst, width*srcBpp);
+ break;
+
+ case 14:
+ srcBpp=2;
+ dstBpp=2;
+ name="rgb15tobgr15";
+ rgb15tobgr15(src, dst, width*srcBpp);
+ break;
+ case 15:
+ srcBpp=2;
+ dstBpp=2;
+ name="rgb15tobgr16";
+ rgb15tobgr16(src, dst, width*srcBpp);
+ break;
+ case 16:
+ srcBpp=2;
+ dstBpp=3;
+ name="rgb15tobgr24";
+ rgb15tobgr24(src, dst, width*srcBpp);
+ break;
+ case 17:
+ srcBpp=2;
+ dstBpp=4;
+ name="rgb15tobgr32";
+ rgb15tobgr32(src, dst, width*srcBpp);
+ break;
+ case 18:
+ srcBpp=2;
+ dstBpp=2;
+ name="rgb16tobgr15";
+ rgb16tobgr15(src, dst, width*srcBpp);
+ break;
+ case 19:
+ srcBpp=2;
+ dstBpp=2;
+ name="rgb16tobgr16";
+ rgb16tobgr16(src, dst, width*srcBpp);
+ break;
+ case 20:
+ srcBpp=2;
+ dstBpp=3;
+ name="rgb16tobgr24";
+ rgb16tobgr24(src, dst, width*srcBpp);
+ break;
+ case 21:
+ srcBpp=2;
+ dstBpp=4;
+ name="rgb16tobgr32";
+ rgb16tobgr32(src, dst, width*srcBpp);
+ break;
+ case 22:
+ srcBpp=3;
+ dstBpp=2;
+ name="rgb24tobgr15";
+ rgb24tobgr15(src, dst, width*srcBpp);
+ break;
+ case 23:
+ srcBpp=3;
+ dstBpp=2;
+ name="rgb24tobgr16";
+ rgb24tobgr16(src, dst, width*srcBpp);
+ break;
+ case 24:
+ srcBpp=3;
+ dstBpp=3;
+ name="rgb24tobgr24";
+ rgb24tobgr24(src, dst, width*srcBpp);
+ break;
+ case 25:
+ srcBpp=3;
+ dstBpp=4;
+ name="rgb24tobgr32";
+ rgb24tobgr32(src, dst, width*srcBpp);
+ break;
+ case 26:
+ srcBpp=4;
+ dstBpp=2;
+ name="rgb32tobgr15";
+ rgb32tobgr15(src, dst, width*srcBpp);
+ break;
+ case 27:
+ srcBpp=4;
+ dstBpp=2;
+ name="rgb32tobgr16";
+ rgb32tobgr16(src, dst, width*srcBpp);
+ break;
+ case 28:
+ srcBpp=4;
+ dstBpp=3;
+ name="rgb32tobgr24";
+ rgb32tobgr24(src, dst, width*srcBpp);
+ break;
+ case 29:
+ srcBpp=4;
+ dstBpp=4;
+ name="rgb32tobgr32";
+ rgb32tobgr32(src, dst, width*srcBpp);
+ break;
+
+ }
+ if(!srcBpp) break;
+
+ for(i=0; i<SIZE; i++){
+ if(srcBuffer[i]!=srcByte){
+ printf("src damaged at %d w:%d src:%d dst:%d %s\n",
+ i, width, srcOffset, dstOffset, name);
+ failed=1;
+ break;
+ }
+ }
+ for(i=0; i<dstOffset; i++){
+ if(dstBuffer[i]!=dstByte){
+ printf("dst damaged at %d w:%d src:%d dst:%d %s\n",
+ i, width, srcOffset, dstOffset, name);
+ failed=1;
+ break;
+ }
+ }
+ for(i=dstOffset + width*dstBpp; i<SIZE; i++){
+ if(dstBuffer[i]!=dstByte){
+ printf("dst damaged at %d w:%d src:%d dst:%d %s\n",
+ i, width, srcOffset, dstOffset, name);
+ failed=1;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if(failed) failedNum++;
+ else if(srcBpp) passedNum++;
+ }
+
+ printf("%d converters passed, %d converters randomly overwrote memory\n", passedNum, failedNum);
+ return failedNum;
+}
diff --git a/contrib/ffmpeg/libswscale/rgb2rgb.c b/contrib/ffmpeg/libswscale/rgb2rgb.c
new file mode 100644
index 000000000..2bb5d3355
--- /dev/null
+++ b/contrib/ffmpeg/libswscale/rgb2rgb.c
@@ -0,0 +1,665 @@
+/*
+ *
+ * rgb2rgb.c, Software RGB to RGB convertor
+ * pluralize by Software PAL8 to RGB convertor
+ * Software YUV to YUV convertor
+ * Software YUV to RGB convertor
+ * Written by Nick Kurshev.
+ * palette & YUV & runtime CPU stuff by Michael (michaelni@gmx.at)
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * the C code (not assembly, mmx, ...) of this file can be used
+ * under the LGPL license too
+ */
+#include <inttypes.h>
+#include "config.h"
+#include "rgb2rgb.h"
+#include "swscale.h"
+#include "swscale_internal.h"
+#include "x86_cpu.h"
+#include "bswap.h"
+#ifdef USE_FASTMEMCPY
+#include "libvo/fastmemcpy.h"
+#endif
+
+#define FAST_BGR2YV12 // use 7 bit coeffs instead of 15bit
+
+void (*rgb24to32)(const uint8_t *src,uint8_t *dst,long src_size);
+void (*rgb24to16)(const uint8_t *src,uint8_t *dst,long src_size);
+void (*rgb24to15)(const uint8_t *src,uint8_t *dst,long src_size);
+void (*rgb32to24)(const uint8_t *src,uint8_t *dst,long src_size);
+void (*rgb32to16)(const uint8_t *src,uint8_t *dst,long src_size);
+void (*rgb32to15)(const uint8_t *src,uint8_t *dst,long src_size);
+void (*rgb15to16)(const uint8_t *src,uint8_t *dst,long src_size);
+void (*rgb15to24)(const uint8_t *src,uint8_t *dst,long src_size);
+void (*rgb15to32)(const uint8_t *src,uint8_t *dst,long src_size);
+void (*rgb16to15)(const uint8_t *src,uint8_t *dst,long src_size);
+void (*rgb16to24)(const uint8_t *src,uint8_t *dst,long src_size);
+void (*rgb16to32)(const uint8_t *src,uint8_t *dst,long src_size);
+//void (*rgb24tobgr32)(const uint8_t *src, uint8_t *dst, long src_size);
+void (*rgb24tobgr24)(const uint8_t *src, uint8_t *dst, long src_size);
+void (*rgb24tobgr16)(const uint8_t *src, uint8_t *dst, long src_size);
+void (*rgb24tobgr15)(const uint8_t *src, uint8_t *dst, long src_size);
+void (*rgb32tobgr32)(const uint8_t *src, uint8_t *dst, long src_size);
+//void (*rgb32tobgr24)(const uint8_t *src, uint8_t *dst, long src_size);
+void (*rgb32tobgr16)(const uint8_t *src, uint8_t *dst, long src_size);
+void (*rgb32tobgr15)(const uint8_t *src, uint8_t *dst, long src_size);
+
+void (*yv12toyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
+ long width, long height,
+ long lumStride, long chromStride, long dstStride);
+void (*yv12touyvy)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
+ long width, long height,
+ long lumStride, long chromStride, long dstStride);
+void (*yuv422ptoyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
+ long width, long height,
+ long lumStride, long chromStride, long dstStride);
+void (*yuy2toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
+ long width, long height,
+ long lumStride, long chromStride, long srcStride);
+void (*rgb24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
+ long width, long height,
+ long lumStride, long chromStride, long srcStride);
+void (*planar2x)(const uint8_t *src, uint8_t *dst, long width, long height,
+ long srcStride, long dstStride);
+void (*interleaveBytes)(uint8_t *src1, uint8_t *src2, uint8_t *dst,
+ long width, long height, long src1Stride,
+ long src2Stride, long dstStride);
+void (*vu9_to_vu12)(const uint8_t *src1, const uint8_t *src2,
+ uint8_t *dst1, uint8_t *dst2,
+ long width, long height,
+ long srcStride1, long srcStride2,
+ long dstStride1, long dstStride2);
+void (*yvu9_to_yuy2)(const uint8_t *src1, const uint8_t *src2, const uint8_t *src3,
+ uint8_t *dst,
+ long width, long height,
+ long srcStride1, long srcStride2,
+ long srcStride3, long dstStride);
+
+#if defined(ARCH_X86)
+static const uint64_t mmx_null __attribute__((aligned(8))) = 0x0000000000000000ULL;
+static const uint64_t mmx_one __attribute__((aligned(8))) = 0xFFFFFFFFFFFFFFFFULL;
+static const uint64_t mask32b attribute_used __attribute__((aligned(8))) = 0x000000FF000000FFULL;
+static const uint64_t mask32g attribute_used __attribute__((aligned(8))) = 0x0000FF000000FF00ULL;
+static const uint64_t mask32r attribute_used __attribute__((aligned(8))) = 0x00FF000000FF0000ULL;
+static const uint64_t mask32 __attribute__((aligned(8))) = 0x00FFFFFF00FFFFFFULL;
+static const uint64_t mask3216br __attribute__((aligned(8)))=0x00F800F800F800F8ULL;
+static const uint64_t mask3216g __attribute__((aligned(8)))=0x0000FC000000FC00ULL;
+static const uint64_t mask3215g __attribute__((aligned(8)))=0x0000F8000000F800ULL;
+static const uint64_t mul3216 __attribute__((aligned(8))) = 0x2000000420000004ULL;
+static const uint64_t mul3215 __attribute__((aligned(8))) = 0x2000000820000008ULL;
+static const uint64_t mask24b attribute_used __attribute__((aligned(8))) = 0x00FF0000FF0000FFULL;
+static const uint64_t mask24g attribute_used __attribute__((aligned(8))) = 0xFF0000FF0000FF00ULL;
+static const uint64_t mask24r attribute_used __attribute__((aligned(8))) = 0x0000FF0000FF0000ULL;
+static const uint64_t mask24l __attribute__((aligned(8))) = 0x0000000000FFFFFFULL;
+static const uint64_t mask24h __attribute__((aligned(8))) = 0x0000FFFFFF000000ULL;
+static const uint64_t mask24hh __attribute__((aligned(8))) = 0xffff000000000000ULL;
+static const uint64_t mask24hhh __attribute__((aligned(8))) = 0xffffffff00000000ULL;
+static const uint64_t mask24hhhh __attribute__((aligned(8))) = 0xffffffffffff0000ULL;
+static const uint64_t mask15b __attribute__((aligned(8))) = 0x001F001F001F001FULL; /* 00000000 00011111 xxB */
+static const uint64_t mask15rg __attribute__((aligned(8))) = 0x7FE07FE07FE07FE0ULL; /* 01111111 11100000 RGx */
+static const uint64_t mask15s __attribute__((aligned(8))) = 0xFFE0FFE0FFE0FFE0ULL;
+static const uint64_t mask15g __attribute__((aligned(8))) = 0x03E003E003E003E0ULL;
+static const uint64_t mask15r __attribute__((aligned(8))) = 0x7C007C007C007C00ULL;
+#define mask16b mask15b
+static const uint64_t mask16g __attribute__((aligned(8))) = 0x07E007E007E007E0ULL;
+static const uint64_t mask16r __attribute__((aligned(8))) = 0xF800F800F800F800ULL;
+static const uint64_t red_16mask __attribute__((aligned(8))) = 0x0000f8000000f800ULL;
+static const uint64_t green_16mask __attribute__((aligned(8)))= 0x000007e0000007e0ULL;
+static const uint64_t blue_16mask __attribute__((aligned(8))) = 0x0000001f0000001fULL;
+static const uint64_t red_15mask __attribute__((aligned(8))) = 0x00007c000000f800ULL;
+static const uint64_t green_15mask __attribute__((aligned(8)))= 0x000003e0000007e0ULL;
+static const uint64_t blue_15mask __attribute__((aligned(8))) = 0x0000001f0000001fULL;
+
+#ifdef FAST_BGR2YV12
+static const uint64_t bgr2YCoeff attribute_used __attribute__((aligned(8))) = 0x000000210041000DULL;
+static const uint64_t bgr2UCoeff attribute_used __attribute__((aligned(8))) = 0x0000FFEEFFDC0038ULL;
+static const uint64_t bgr2VCoeff attribute_used __attribute__((aligned(8))) = 0x00000038FFD2FFF8ULL;
+#else
+static const uint64_t bgr2YCoeff attribute_used __attribute__((aligned(8))) = 0x000020E540830C8BULL;
+static const uint64_t bgr2UCoeff attribute_used __attribute__((aligned(8))) = 0x0000ED0FDAC23831ULL;
+static const uint64_t bgr2VCoeff attribute_used __attribute__((aligned(8))) = 0x00003831D0E6F6EAULL;
+#endif
+static const uint64_t bgr2YOffset attribute_used __attribute__((aligned(8))) = 0x1010101010101010ULL;
+static const uint64_t bgr2UVOffset attribute_used __attribute__((aligned(8)))= 0x8080808080808080ULL;
+static const uint64_t w1111 attribute_used __attribute__((aligned(8))) = 0x0001000100010001ULL;
+
+#if 0
+static volatile uint64_t __attribute__((aligned(8))) b5Dither;
+static volatile uint64_t __attribute__((aligned(8))) g5Dither;
+static volatile uint64_t __attribute__((aligned(8))) g6Dither;
+static volatile uint64_t __attribute__((aligned(8))) r5Dither;
+
+static uint64_t __attribute__((aligned(8))) dither4[2]={
+ 0x0103010301030103LL,
+ 0x0200020002000200LL,};
+
+static uint64_t __attribute__((aligned(8))) dither8[2]={
+ 0x0602060206020602LL,
+ 0x0004000400040004LL,};
+#endif
+#endif /* defined(ARCH_X86) */
+
+#define RGB2YUV_SHIFT 8
+#define BY ((int)( 0.098*(1<<RGB2YUV_SHIFT)+0.5))
+#define BV ((int)(-0.071*(1<<RGB2YUV_SHIFT)+0.5))
+#define BU ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5))
+#define GY ((int)( 0.504*(1<<RGB2YUV_SHIFT)+0.5))
+#define GV ((int)(-0.368*(1<<RGB2YUV_SHIFT)+0.5))
+#define GU ((int)(-0.291*(1<<RGB2YUV_SHIFT)+0.5))
+#define RY ((int)( 0.257*(1<<RGB2YUV_SHIFT)+0.5))
+#define RV ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5))
+#define RU ((int)(-0.148*(1<<RGB2YUV_SHIFT)+0.5))
+
+//Note: we have C, MMX, MMX2, 3DNOW version therse no 3DNOW+MMX2 one
+//Plain C versions
+#undef HAVE_MMX
+#undef HAVE_MMX2
+#undef HAVE_3DNOW
+#undef HAVE_SSE2
+#define RENAME(a) a ## _C
+#include "rgb2rgb_template.c"
+
+#if defined(ARCH_X86)
+
+//MMX versions
+#undef RENAME
+#define HAVE_MMX
+#undef HAVE_MMX2
+#undef HAVE_3DNOW
+#undef HAVE_SSE2
+#define RENAME(a) a ## _MMX
+#include "rgb2rgb_template.c"
+
+//MMX2 versions
+#undef RENAME
+#define HAVE_MMX
+#define HAVE_MMX2
+#undef HAVE_3DNOW
+#undef HAVE_SSE2
+#define RENAME(a) a ## _MMX2
+#include "rgb2rgb_template.c"
+
+//3DNOW versions
+#undef RENAME
+#define HAVE_MMX
+#undef HAVE_MMX2
+#define HAVE_3DNOW
+#undef HAVE_SSE2
+#define RENAME(a) a ## _3DNOW
+#include "rgb2rgb_template.c"
+
+#endif //ARCH_X86 || ARCH_X86_64
+
+/*
+ rgb15->rgb16 Original by Strepto/Astral
+ ported to gcc & bugfixed : A'rpi
+ MMX2, 3DNOW optimization by Nick Kurshev
+ 32bit c version, and and&add trick by Michael Niedermayer
+*/
+
+void sws_rgb2rgb_init(int flags){
+#if defined(HAVE_MMX2) || defined(HAVE_3DNOW) || defined(HAVE_MMX)
+ if(flags & SWS_CPU_CAPS_MMX2){
+ rgb15to16= rgb15to16_MMX2;
+ rgb15to24= rgb15to24_MMX2;
+ rgb15to32= rgb15to32_MMX2;
+ rgb16to24= rgb16to24_MMX2;
+ rgb16to32= rgb16to32_MMX2;
+ rgb16to15= rgb16to15_MMX2;
+ rgb24to16= rgb24to16_MMX2;
+ rgb24to15= rgb24to15_MMX2;
+ rgb24to32= rgb24to32_MMX2;
+ rgb32to16= rgb32to16_MMX2;
+ rgb32to15= rgb32to15_MMX2;
+ rgb32to24= rgb32to24_MMX2;
+ rgb24tobgr15= rgb24tobgr15_MMX2;
+ rgb24tobgr16= rgb24tobgr16_MMX2;
+ rgb24tobgr24= rgb24tobgr24_MMX2;
+ rgb32tobgr32= rgb32tobgr32_MMX2;
+ rgb32tobgr16= rgb32tobgr16_MMX2;
+ rgb32tobgr15= rgb32tobgr15_MMX2;
+ yv12toyuy2= yv12toyuy2_MMX2;
+ yv12touyvy= yv12touyvy_MMX2;
+ yuv422ptoyuy2= yuv422ptoyuy2_MMX2;
+ yuy2toyv12= yuy2toyv12_MMX2;
+// uyvytoyv12= uyvytoyv12_MMX2;
+// yvu9toyv12= yvu9toyv12_MMX2;
+ planar2x= planar2x_MMX2;
+ rgb24toyv12= rgb24toyv12_MMX2;
+ interleaveBytes= interleaveBytes_MMX2;
+ vu9_to_vu12= vu9_to_vu12_MMX2;
+ yvu9_to_yuy2= yvu9_to_yuy2_MMX2;
+ }else if(flags & SWS_CPU_CAPS_3DNOW){
+ rgb15to16= rgb15to16_3DNOW;
+ rgb15to24= rgb15to24_3DNOW;
+ rgb15to32= rgb15to32_3DNOW;
+ rgb16to24= rgb16to24_3DNOW;
+ rgb16to32= rgb16to32_3DNOW;
+ rgb16to15= rgb16to15_3DNOW;
+ rgb24to16= rgb24to16_3DNOW;
+ rgb24to15= rgb24to15_3DNOW;
+ rgb24to32= rgb24to32_3DNOW;
+ rgb32to16= rgb32to16_3DNOW;
+ rgb32to15= rgb32to15_3DNOW;
+ rgb32to24= rgb32to24_3DNOW;
+ rgb24tobgr15= rgb24tobgr15_3DNOW;
+ rgb24tobgr16= rgb24tobgr16_3DNOW;
+ rgb24tobgr24= rgb24tobgr24_3DNOW;
+ rgb32tobgr32= rgb32tobgr32_3DNOW;
+ rgb32tobgr16= rgb32tobgr16_3DNOW;
+ rgb32tobgr15= rgb32tobgr15_3DNOW;
+ yv12toyuy2= yv12toyuy2_3DNOW;
+ yv12touyvy= yv12touyvy_3DNOW;
+ yuv422ptoyuy2= yuv422ptoyuy2_3DNOW;
+ yuy2toyv12= yuy2toyv12_3DNOW;
+// uyvytoyv12= uyvytoyv12_3DNOW;
+// yvu9toyv12= yvu9toyv12_3DNOW;
+ planar2x= planar2x_3DNOW;
+ rgb24toyv12= rgb24toyv12_3DNOW;
+ interleaveBytes= interleaveBytes_3DNOW;
+ vu9_to_vu12= vu9_to_vu12_3DNOW;
+ yvu9_to_yuy2= yvu9_to_yuy2_3DNOW;
+ }else if(flags & SWS_CPU_CAPS_MMX){
+ rgb15to16= rgb15to16_MMX;
+ rgb15to24= rgb15to24_MMX;
+ rgb15to32= rgb15to32_MMX;
+ rgb16to24= rgb16to24_MMX;
+ rgb16to32= rgb16to32_MMX;
+ rgb16to15= rgb16to15_MMX;
+ rgb24to16= rgb24to16_MMX;
+ rgb24to15= rgb24to15_MMX;
+ rgb24to32= rgb24to32_MMX;
+ rgb32to16= rgb32to16_MMX;
+ rgb32to15= rgb32to15_MMX;
+ rgb32to24= rgb32to24_MMX;
+ rgb24tobgr15= rgb24tobgr15_MMX;
+ rgb24tobgr16= rgb24tobgr16_MMX;
+ rgb24tobgr24= rgb24tobgr24_MMX;
+ rgb32tobgr32= rgb32tobgr32_MMX;
+ rgb32tobgr16= rgb32tobgr16_MMX;
+ rgb32tobgr15= rgb32tobgr15_MMX;
+ yv12toyuy2= yv12toyuy2_MMX;
+ yv12touyvy= yv12touyvy_MMX;
+ yuv422ptoyuy2= yuv422ptoyuy2_MMX;
+ yuy2toyv12= yuy2toyv12_MMX;
+// uyvytoyv12= uyvytoyv12_MMX;
+// yvu9toyv12= yvu9toyv12_MMX;
+ planar2x= planar2x_MMX;
+ rgb24toyv12= rgb24toyv12_MMX;
+ interleaveBytes= interleaveBytes_MMX;
+ vu9_to_vu12= vu9_to_vu12_MMX;
+ yvu9_to_yuy2= yvu9_to_yuy2_MMX;
+ }else
+#endif /* defined(HAVE_MMX2) || defined(HAVE_3DNOW) || defined(HAVE_MMX) */
+ {
+ rgb15to16= rgb15to16_C;
+ rgb15to24= rgb15to24_C;
+ rgb15to32= rgb15to32_C;
+ rgb16to24= rgb16to24_C;
+ rgb16to32= rgb16to32_C;
+ rgb16to15= rgb16to15_C;
+ rgb24to16= rgb24to16_C;
+ rgb24to15= rgb24to15_C;
+ rgb24to32= rgb24to32_C;
+ rgb32to16= rgb32to16_C;
+ rgb32to15= rgb32to15_C;
+ rgb32to24= rgb32to24_C;
+ rgb24tobgr15= rgb24tobgr15_C;
+ rgb24tobgr16= rgb24tobgr16_C;
+ rgb24tobgr24= rgb24tobgr24_C;
+ rgb32tobgr32= rgb32tobgr32_C;
+ rgb32tobgr16= rgb32tobgr16_C;
+ rgb32tobgr15= rgb32tobgr15_C;
+ yv12toyuy2= yv12toyuy2_C;
+ yv12touyvy= yv12touyvy_C;
+ yuv422ptoyuy2= yuv422ptoyuy2_C;
+ yuy2toyv12= yuy2toyv12_C;
+// uyvytoyv12= uyvytoyv12_C;
+// yvu9toyv12= yvu9toyv12_C;
+ planar2x= planar2x_C;
+ rgb24toyv12= rgb24toyv12_C;
+ interleaveBytes= interleaveBytes_C;
+ vu9_to_vu12= vu9_to_vu12_C;
+ yvu9_to_yuy2= yvu9_to_yuy2_C;
+ }
+}
+
+/**
+ * Pallete is assumed to contain bgr32
+ */
+void palette8torgb32(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette)
+{
+ long i;
+
+/*
+ for(i=0; i<num_pixels; i++)
+ ((unsigned *)dst)[i] = ((unsigned *)palette)[ src[i] ];
+*/
+
+ for(i=0; i<num_pixels; i++)
+ {
+ #ifdef WORDS_BIGENDIAN
+ dst[3]= palette[ src[i]*4+2 ];
+ dst[2]= palette[ src[i]*4+1 ];
+ dst[1]= palette[ src[i]*4+0 ];
+ #else
+ //FIXME slow?
+ dst[0]= palette[ src[i]*4+2 ];
+ dst[1]= palette[ src[i]*4+1 ];
+ dst[2]= palette[ src[i]*4+0 ];
+ //dst[3]= 0; /* do we need this cleansing? */
+ #endif
+ dst+= 4;
+ }
+}
+
+void palette8tobgr32(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette)
+{
+ long i;
+ for(i=0; i<num_pixels; i++)
+ {
+ #ifdef WORDS_BIGENDIAN
+ dst[3]= palette[ src[i]*4+0 ];
+ dst[2]= palette[ src[i]*4+1 ];
+ dst[1]= palette[ src[i]*4+2 ];
+ #else
+ //FIXME slow?
+ dst[0]= palette[ src[i]*4+0 ];
+ dst[1]= palette[ src[i]*4+1 ];
+ dst[2]= palette[ src[i]*4+2 ];
+ //dst[3]= 0; /* do we need this cleansing? */
+ #endif
+
+ dst+= 4;
+ }
+}
+
+/**
+ * Pallete is assumed to contain bgr32
+ */
+void palette8torgb24(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette)
+{
+ long i;
+/*
+ writes 1 byte o much and might cause alignment issues on some architectures?
+ for(i=0; i<num_pixels; i++)
+ ((unsigned *)(&dst[i*3])) = ((unsigned *)palette)[ src[i] ];
+*/
+ for(i=0; i<num_pixels; i++)
+ {
+ //FIXME slow?
+ dst[0]= palette[ src[i]*4+2 ];
+ dst[1]= palette[ src[i]*4+1 ];
+ dst[2]= palette[ src[i]*4+0 ];
+ dst+= 3;
+ }
+}
+
+void palette8tobgr24(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette)
+{
+ long i;
+/*
+ writes 1 byte o much and might cause alignment issues on some architectures?
+ for(i=0; i<num_pixels; i++)
+ ((unsigned *)(&dst[i*3])) = ((unsigned *)palette)[ src[i] ];
+*/
+ for(i=0; i<num_pixels; i++)
+ {
+ //FIXME slow?
+ dst[0]= palette[ src[i]*4+0 ];
+ dst[1]= palette[ src[i]*4+1 ];
+ dst[2]= palette[ src[i]*4+2 ];
+ dst+= 3;
+ }
+}
+
+/**
+ * Palette is assumed to contain bgr16, see rgb32to16 to convert the palette
+ */
+void palette8torgb16(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette)
+{
+ long i;
+ for(i=0; i<num_pixels; i++)
+ ((uint16_t *)dst)[i] = ((uint16_t *)palette)[ src[i] ];
+}
+void palette8tobgr16(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette)
+{
+ long i;
+ for(i=0; i<num_pixels; i++)
+ ((uint16_t *)dst)[i] = bswap_16(((uint16_t *)palette)[ src[i] ]);
+}
+
+/**
+ * Pallete is assumed to contain bgr15, see rgb32to15 to convert the palette
+ */
+void palette8torgb15(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette)
+{
+ long i;
+ for(i=0; i<num_pixels; i++)
+ ((uint16_t *)dst)[i] = ((uint16_t *)palette)[ src[i] ];
+}
+void palette8tobgr15(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette)
+{
+ long i;
+ for(i=0; i<num_pixels; i++)
+ ((uint16_t *)dst)[i] = bswap_16(((uint16_t *)palette)[ src[i] ]);
+}
+
+void rgb32tobgr24(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ long i;
+ long num_pixels = src_size >> 2;
+ for(i=0; i<num_pixels; i++)
+ {
+ #ifdef WORDS_BIGENDIAN
+ /* RGB32 (= A,B,G,R) -> BGR24 (= B,G,R) */
+ dst[3*i + 0] = src[4*i + 1];
+ dst[3*i + 1] = src[4*i + 2];
+ dst[3*i + 2] = src[4*i + 3];
+ #else
+ dst[3*i + 0] = src[4*i + 2];
+ dst[3*i + 1] = src[4*i + 1];
+ dst[3*i + 2] = src[4*i + 0];
+ #endif
+ }
+}
+
+void rgb24tobgr32(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ long i;
+ for(i=0; 3*i<src_size; i++)
+ {
+ #ifdef WORDS_BIGENDIAN
+ /* RGB24 (= R,G,B) -> BGR32 (= A,R,G,B) */
+ dst[4*i + 0] = 0;
+ dst[4*i + 1] = src[3*i + 0];
+ dst[4*i + 2] = src[3*i + 1];
+ dst[4*i + 3] = src[3*i + 2];
+ #else
+ dst[4*i + 0] = src[3*i + 2];
+ dst[4*i + 1] = src[3*i + 1];
+ dst[4*i + 2] = src[3*i + 0];
+ dst[4*i + 3] = 0;
+ #endif
+ }
+}
+
+void rgb16tobgr32(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ const uint16_t *end;
+ uint8_t *d = (uint8_t *)dst;
+ const uint16_t *s = (uint16_t *)src;
+ end = s + src_size/2;
+ while(s < end)
+ {
+ register uint16_t bgr;
+ bgr = *s++;
+ #ifdef WORDS_BIGENDIAN
+ *d++ = 0;
+ *d++ = (bgr&0x1F)<<3;
+ *d++ = (bgr&0x7E0)>>3;
+ *d++ = (bgr&0xF800)>>8;
+ #else
+ *d++ = (bgr&0xF800)>>8;
+ *d++ = (bgr&0x7E0)>>3;
+ *d++ = (bgr&0x1F)<<3;
+ *d++ = 0;
+ #endif
+ }
+}
+
+void rgb16tobgr24(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ const uint16_t *end;
+ uint8_t *d = (uint8_t *)dst;
+ const uint16_t *s = (const uint16_t *)src;
+ end = s + src_size/2;
+ while(s < end)
+ {
+ register uint16_t bgr;
+ bgr = *s++;
+ *d++ = (bgr&0xF800)>>8;
+ *d++ = (bgr&0x7E0)>>3;
+ *d++ = (bgr&0x1F)<<3;
+ }
+}
+
+void rgb16tobgr16(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ long i;
+ long num_pixels = src_size >> 1;
+
+ for(i=0; i<num_pixels; i++)
+ {
+ unsigned b,g,r;
+ register uint16_t rgb;
+ rgb = src[2*i];
+ r = rgb&0x1F;
+ g = (rgb&0x7E0)>>5;
+ b = (rgb&0xF800)>>11;
+ dst[2*i] = (b&0x1F) | ((g&0x3F)<<5) | ((r&0x1F)<<11);
+ }
+}
+
+void rgb16tobgr15(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ long i;
+ long num_pixels = src_size >> 1;
+
+ for(i=0; i<num_pixels; i++)
+ {
+ unsigned b,g,r;
+ register uint16_t rgb;
+ rgb = src[2*i];
+ r = rgb&0x1F;
+ g = (rgb&0x7E0)>>5;
+ b = (rgb&0xF800)>>11;
+ dst[2*i] = (b&0x1F) | ((g&0x1F)<<5) | ((r&0x1F)<<10);
+ }
+}
+
+void rgb15tobgr32(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ const uint16_t *end;
+ uint8_t *d = (uint8_t *)dst;
+ const uint16_t *s = (const uint16_t *)src;
+ end = s + src_size/2;
+ while(s < end)
+ {
+ register uint16_t bgr;
+ bgr = *s++;
+ #ifdef WORDS_BIGENDIAN
+ *d++ = 0;
+ *d++ = (bgr&0x1F)<<3;
+ *d++ = (bgr&0x3E0)>>2;
+ *d++ = (bgr&0x7C00)>>7;
+ #else
+ *d++ = (bgr&0x7C00)>>7;
+ *d++ = (bgr&0x3E0)>>2;
+ *d++ = (bgr&0x1F)<<3;
+ *d++ = 0;
+ #endif
+ }
+}
+
+void rgb15tobgr24(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ const uint16_t *end;
+ uint8_t *d = (uint8_t *)dst;
+ const uint16_t *s = (uint16_t *)src;
+ end = s + src_size/2;
+ while(s < end)
+ {
+ register uint16_t bgr;
+ bgr = *s++;
+ *d++ = (bgr&0x7C00)>>7;
+ *d++ = (bgr&0x3E0)>>2;
+ *d++ = (bgr&0x1F)<<3;
+ }
+}
+
+void rgb15tobgr16(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ long i;
+ long num_pixels = src_size >> 1;
+
+ for(i=0; i<num_pixels; i++)
+ {
+ unsigned b,g,r;
+ register uint16_t rgb;
+ rgb = src[2*i];
+ r = rgb&0x1F;
+ g = (rgb&0x3E0)>>5;
+ b = (rgb&0x7C00)>>10;
+ dst[2*i] = (b&0x1F) | ((g&0x3F)<<5) | ((r&0x1F)<<11);
+ }
+}
+
+void rgb15tobgr15(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ long i;
+ long num_pixels = src_size >> 1;
+
+ for(i=0; i<num_pixels; i++)
+ {
+ unsigned b,g,r;
+ register uint16_t rgb;
+ rgb = src[2*i];
+ r = rgb&0x1F;
+ g = (rgb&0x3E0)>>5;
+ b = (rgb&0x7C00)>>10;
+ dst[2*i] = (b&0x1F) | ((g&0x1F)<<5) | ((r&0x1F)<<10);
+ }
+}
+
+void rgb8tobgr8(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ long i;
+ long num_pixels = src_size;
+ for(i=0; i<num_pixels; i++)
+ {
+ unsigned b,g,r;
+ register uint8_t rgb;
+ rgb = src[i];
+ r = (rgb&0x07);
+ g = (rgb&0x38)>>3;
+ b = (rgb&0xC0)>>6;
+ dst[i] = ((b<<1)&0x07) | ((g&0x07)<<3) | ((r&0x03)<<6);
+ }
+}
diff --git a/contrib/ffmpeg/libswscale/rgb2rgb.h b/contrib/ffmpeg/libswscale/rgb2rgb.h
new file mode 100644
index 000000000..4b5cc0a69
--- /dev/null
+++ b/contrib/ffmpeg/libswscale/rgb2rgb.h
@@ -0,0 +1,147 @@
+/*
+ *
+ * rgb2rgb.h, Software RGB to RGB convertor
+ * pluralize by Software PAL8 to RGB convertor
+ * Software YUV to YUV convertor
+ * Software YUV to RGB convertor
+ * Written by Nick Kurshev.
+ * palette & YUV & runtime CPU stuff by Michael (michaelni@gmx.at)
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have 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 RGB2RGB_INCLUDED
+#define RGB2RGB_INCLUDED
+
+// Note: do not fix the dependence on stdio.h
+
+/* A full collection of rgb to rgb(bgr) convertors */
+extern void (*rgb24to32)(const uint8_t *src,uint8_t *dst,long src_size);
+extern void (*rgb24to16)(const uint8_t *src,uint8_t *dst,long src_size);
+extern void (*rgb24to15)(const uint8_t *src,uint8_t *dst,long src_size);
+extern void (*rgb32to24)(const uint8_t *src,uint8_t *dst,long src_size);
+extern void (*rgb32to16)(const uint8_t *src,uint8_t *dst,long src_size);
+extern void (*rgb32to15)(const uint8_t *src,uint8_t *dst,long src_size);
+extern void (*rgb15to16)(const uint8_t *src,uint8_t *dst,long src_size);
+extern void (*rgb15to24)(const uint8_t *src,uint8_t *dst,long src_size);
+extern void (*rgb15to32)(const uint8_t *src,uint8_t *dst,long src_size);
+extern void (*rgb16to15)(const uint8_t *src,uint8_t *dst,long src_size);
+extern void (*rgb16to24)(const uint8_t *src,uint8_t *dst,long src_size);
+extern void (*rgb16to32)(const uint8_t *src,uint8_t *dst,long src_size);
+extern void (*rgb24tobgr24)(const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb24tobgr16)(const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb24tobgr15)(const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb32tobgr32)(const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb32tobgr16)(const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb32tobgr15)(const uint8_t *src, uint8_t *dst, long src_size);
+
+extern void rgb24tobgr32(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb32tobgr24(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb16tobgr32(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb16tobgr24(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb16tobgr16(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb16tobgr15(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb15tobgr32(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb15tobgr24(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb15tobgr16(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb15tobgr15(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb8tobgr8(const uint8_t *src, uint8_t *dst, long src_size);
+
+
+extern void palette8torgb32(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
+extern void palette8tobgr32(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
+extern void palette8torgb24(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
+extern void palette8tobgr24(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
+extern void palette8torgb16(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
+extern void palette8tobgr16(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
+extern void palette8torgb15(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
+extern void palette8tobgr15(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
+
+/**
+ *
+ * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
+ * problem for anyone then tell me, and ill fix it)
+ * chrominance data is only taken from every secound line others are ignored FIXME write HQ version
+ */
+//void uyvytoyv12(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
+
+/**
+ *
+ * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
+ * problem for anyone then tell me, and ill fix it)
+ */
+extern void (*yv12toyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
+ long width, long height,
+ long lumStride, long chromStride, long dstStride);
+
+/**
+ *
+ * width should be a multiple of 16
+ */
+extern void (*yuv422ptoyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
+ long width, long height,
+ long lumStride, long chromStride, long dstStride);
+
+/**
+ *
+ * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
+ * problem for anyone then tell me, and ill fix it)
+ */
+extern void (*yuy2toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
+ long width, long height,
+ long lumStride, long chromStride, long srcStride);
+
+/**
+ *
+ * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
+ * problem for anyone then tell me, and ill fix it)
+ */
+extern void (*yv12touyvy)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
+ long width, long height,
+ long lumStride, long chromStride, long dstStride);
+
+/**
+ *
+ * height should be a multiple of 2 and width should be a multiple of 2 (if this is a
+ * problem for anyone then tell me, and ill fix it)
+ * chrominance data is only taken from every secound line others are ignored FIXME write HQ version
+ */
+extern void (*rgb24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
+ long width, long height,
+ long lumStride, long chromStride, long srcStride);
+extern void (*planar2x)(const uint8_t *src, uint8_t *dst, long width, long height,
+ long srcStride, long dstStride);
+
+extern void (*interleaveBytes)(uint8_t *src1, uint8_t *src2, uint8_t *dst,
+ long width, long height, long src1Stride,
+ long src2Stride, long dstStride);
+
+extern void (*vu9_to_vu12)(const uint8_t *src1, const uint8_t *src2,
+ uint8_t *dst1, uint8_t *dst2,
+ long width, long height,
+ long srcStride1, long srcStride2,
+ long dstStride1, long dstStride2);
+
+extern void (*yvu9_to_yuy2)(const uint8_t *src1, const uint8_t *src2, const uint8_t *src3,
+ uint8_t *dst,
+ long width, long height,
+ long srcStride1, long srcStride2,
+ long srcStride3, long dstStride);
+
+void sws_rgb2rgb_init(int flags);
+
+#endif
diff --git a/contrib/ffmpeg/libswscale/rgb2rgb_template.c b/contrib/ffmpeg/libswscale/rgb2rgb_template.c
new file mode 100644
index 000000000..d9511c955
--- /dev/null
+++ b/contrib/ffmpeg/libswscale/rgb2rgb_template.c
@@ -0,0 +1,2688 @@
+/*
+ *
+ * rgb2rgb.c, Software RGB to RGB convertor
+ * pluralize by Software PAL8 to RGB convertor
+ * Software YUV to YUV convertor
+ * Software YUV to RGB convertor
+ * Written by Nick Kurshev.
+ * palette & YUV & runtime CPU stuff by Michael (michaelni@gmx.at)
+ * lot of big-endian byteorder fixes 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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * the C code (not assembly, mmx, ...) of this file can be used
+ * under the LGPL license too
+ */
+
+#include <stddef.h>
+#include <inttypes.h> /* for __WORDSIZE */
+
+#ifndef __WORDSIZE
+// #warning You have misconfigured system and probably will lose performance!
+#define __WORDSIZE MP_WORDSIZE
+#endif
+
+#undef PREFETCH
+#undef MOVNTQ
+#undef EMMS
+#undef SFENCE
+#undef MMREG_SIZE
+#undef PREFETCHW
+#undef PAVGB
+
+#ifdef HAVE_SSE2
+#define MMREG_SIZE 16
+#else
+#define MMREG_SIZE 8
+#endif
+
+#ifdef HAVE_3DNOW
+#define PREFETCH "prefetch"
+#define PREFETCHW "prefetchw"
+#define PAVGB "pavgusb"
+#elif defined ( HAVE_MMX2 )
+#define PREFETCH "prefetchnta"
+#define PREFETCHW "prefetcht0"
+#define PAVGB "pavgb"
+#else
+#ifdef __APPLE__
+#define PREFETCH "#"
+#define PREFETCHW "#"
+#else
+#define PREFETCH " # nop"
+#define PREFETCHW " # nop"
+#endif
+#endif
+
+#ifdef HAVE_3DNOW
+/* On K6 femms is faster of emms. On K7 femms is directly mapped on emms. */
+#define EMMS "femms"
+#else
+#define EMMS "emms"
+#endif
+
+#ifdef HAVE_MMX2
+#define MOVNTQ "movntq"
+#define SFENCE "sfence"
+#else
+#define MOVNTQ "movq"
+#define SFENCE " # nop"
+#endif
+
+static inline void RENAME(rgb24to32)(const uint8_t *src,uint8_t *dst,long src_size)
+{
+ uint8_t *dest = dst;
+ const uint8_t *s = src;
+ const uint8_t *end;
+#ifdef HAVE_MMX
+ const uint8_t *mm_end;
+#endif
+ end = s + src_size;
+#ifdef HAVE_MMX
+ __asm __volatile(PREFETCH" %0"::"m"(*s):"memory");
+ mm_end = end - 23;
+ __asm __volatile("movq %0, %%mm7"::"m"(mask32):"memory");
+ while(s < mm_end)
+ {
+ __asm __volatile(
+ PREFETCH" 32%1\n\t"
+ "movd %1, %%mm0\n\t"
+ "punpckldq 3%1, %%mm0\n\t"
+ "movd 6%1, %%mm1\n\t"
+ "punpckldq 9%1, %%mm1\n\t"
+ "movd 12%1, %%mm2\n\t"
+ "punpckldq 15%1, %%mm2\n\t"
+ "movd 18%1, %%mm3\n\t"
+ "punpckldq 21%1, %%mm3\n\t"
+ "pand %%mm7, %%mm0\n\t"
+ "pand %%mm7, %%mm1\n\t"
+ "pand %%mm7, %%mm2\n\t"
+ "pand %%mm7, %%mm3\n\t"
+ MOVNTQ" %%mm0, %0\n\t"
+ MOVNTQ" %%mm1, 8%0\n\t"
+ MOVNTQ" %%mm2, 16%0\n\t"
+ MOVNTQ" %%mm3, 24%0"
+ :"=m"(*dest)
+ :"m"(*s)
+ :"memory");
+ dest += 32;
+ s += 24;
+ }
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#endif
+ while(s < end)
+ {
+#ifdef WORDS_BIGENDIAN
+ /* RGB24 (= R,G,B) -> RGB32 (= A,B,G,R) */
+ *dest++ = 0;
+ *dest++ = s[2];
+ *dest++ = s[1];
+ *dest++ = s[0];
+ s+=3;
+#else
+ *dest++ = *s++;
+ *dest++ = *s++;
+ *dest++ = *s++;
+ *dest++ = 0;
+#endif
+ }
+}
+
+static inline void RENAME(rgb32to24)(const uint8_t *src,uint8_t *dst,long src_size)
+{
+ uint8_t *dest = dst;
+ const uint8_t *s = src;
+ const uint8_t *end;
+#ifdef HAVE_MMX
+ const uint8_t *mm_end;
+#endif
+ end = s + src_size;
+#ifdef HAVE_MMX
+ __asm __volatile(PREFETCH" %0"::"m"(*s):"memory");
+ mm_end = end - 31;
+ while(s < mm_end)
+ {
+ __asm __volatile(
+ PREFETCH" 32%1\n\t"
+ "movq %1, %%mm0\n\t"
+ "movq 8%1, %%mm1\n\t"
+ "movq 16%1, %%mm4\n\t"
+ "movq 24%1, %%mm5\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "movq %%mm4, %%mm6\n\t"
+ "movq %%mm5, %%mm7\n\t"
+ "psrlq $8, %%mm2\n\t"
+ "psrlq $8, %%mm3\n\t"
+ "psrlq $8, %%mm6\n\t"
+ "psrlq $8, %%mm7\n\t"
+ "pand %2, %%mm0\n\t"
+ "pand %2, %%mm1\n\t"
+ "pand %2, %%mm4\n\t"
+ "pand %2, %%mm5\n\t"
+ "pand %3, %%mm2\n\t"
+ "pand %3, %%mm3\n\t"
+ "pand %3, %%mm6\n\t"
+ "pand %3, %%mm7\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "por %%mm3, %%mm1\n\t"
+ "por %%mm6, %%mm4\n\t"
+ "por %%mm7, %%mm5\n\t"
+
+ "movq %%mm1, %%mm2\n\t"
+ "movq %%mm4, %%mm3\n\t"
+ "psllq $48, %%mm2\n\t"
+ "psllq $32, %%mm3\n\t"
+ "pand %4, %%mm2\n\t"
+ "pand %5, %%mm3\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "psrlq $16, %%mm1\n\t"
+ "psrlq $32, %%mm4\n\t"
+ "psllq $16, %%mm5\n\t"
+ "por %%mm3, %%mm1\n\t"
+ "pand %6, %%mm5\n\t"
+ "por %%mm5, %%mm4\n\t"
+
+ MOVNTQ" %%mm0, %0\n\t"
+ MOVNTQ" %%mm1, 8%0\n\t"
+ MOVNTQ" %%mm4, 16%0"
+ :"=m"(*dest)
+ :"m"(*s),"m"(mask24l),
+ "m"(mask24h),"m"(mask24hh),"m"(mask24hhh),"m"(mask24hhhh)
+ :"memory");
+ dest += 24;
+ s += 32;
+ }
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#endif
+ while(s < end)
+ {
+#ifdef WORDS_BIGENDIAN
+ /* RGB32 (= A,B,G,R) -> RGB24 (= R,G,B) */
+ s++;
+ dest[2] = *s++;
+ dest[1] = *s++;
+ dest[0] = *s++;
+ dest += 3;
+#else
+ *dest++ = *s++;
+ *dest++ = *s++;
+ *dest++ = *s++;
+ s++;
+#endif
+ }
+}
+
+/*
+ Original by Strepto/Astral
+ ported to gcc & bugfixed : A'rpi
+ MMX2, 3DNOW optimization by Nick Kurshev
+ 32bit c version, and and&add trick by Michael Niedermayer
+*/
+static inline void RENAME(rgb15to16)(const uint8_t *src,uint8_t *dst,long src_size)
+{
+ register const uint8_t* s=src;
+ register uint8_t* d=dst;
+ register const uint8_t *end;
+ const uint8_t *mm_end;
+ end = s + src_size;
+#ifdef HAVE_MMX
+ __asm __volatile(PREFETCH" %0"::"m"(*s));
+ __asm __volatile("movq %0, %%mm4"::"m"(mask15s));
+ mm_end = end - 15;
+ while(s<mm_end)
+ {
+ __asm __volatile(
+ PREFETCH" 32%1\n\t"
+ "movq %1, %%mm0\n\t"
+ "movq 8%1, %%mm2\n\t"
+ "movq %%mm0, %%mm1\n\t"
+ "movq %%mm2, %%mm3\n\t"
+ "pand %%mm4, %%mm0\n\t"
+ "pand %%mm4, %%mm2\n\t"
+ "paddw %%mm1, %%mm0\n\t"
+ "paddw %%mm3, %%mm2\n\t"
+ MOVNTQ" %%mm0, %0\n\t"
+ MOVNTQ" %%mm2, 8%0"
+ :"=m"(*d)
+ :"m"(*s)
+ );
+ d+=16;
+ s+=16;
+ }
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#endif
+ mm_end = end - 3;
+ while(s < mm_end)
+ {
+ register unsigned x= *((uint32_t *)s);
+ *((uint32_t *)d) = (x&0x7FFF7FFF) + (x&0x7FE07FE0);
+ d+=4;
+ s+=4;
+ }
+ if(s < end)
+ {
+ register unsigned short x= *((uint16_t *)s);
+ *((uint16_t *)d) = (x&0x7FFF) + (x&0x7FE0);
+ }
+}
+
+static inline void RENAME(rgb16to15)(const uint8_t *src,uint8_t *dst,long src_size)
+{
+ register const uint8_t* s=src;
+ register uint8_t* d=dst;
+ register const uint8_t *end;
+ const uint8_t *mm_end;
+ end = s + src_size;
+#ifdef HAVE_MMX
+ __asm __volatile(PREFETCH" %0"::"m"(*s));
+ __asm __volatile("movq %0, %%mm7"::"m"(mask15rg));
+ __asm __volatile("movq %0, %%mm6"::"m"(mask15b));
+ mm_end = end - 15;
+ while(s<mm_end)
+ {
+ __asm __volatile(
+ PREFETCH" 32%1\n\t"
+ "movq %1, %%mm0\n\t"
+ "movq 8%1, %%mm2\n\t"
+ "movq %%mm0, %%mm1\n\t"
+ "movq %%mm2, %%mm3\n\t"
+ "psrlq $1, %%mm0\n\t"
+ "psrlq $1, %%mm2\n\t"
+ "pand %%mm7, %%mm0\n\t"
+ "pand %%mm7, %%mm2\n\t"
+ "pand %%mm6, %%mm1\n\t"
+ "pand %%mm6, %%mm3\n\t"
+ "por %%mm1, %%mm0\n\t"
+ "por %%mm3, %%mm2\n\t"
+ MOVNTQ" %%mm0, %0\n\t"
+ MOVNTQ" %%mm2, 8%0"
+ :"=m"(*d)
+ :"m"(*s)
+ );
+ d+=16;
+ s+=16;
+ }
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#endif
+ mm_end = end - 3;
+ while(s < mm_end)
+ {
+ register uint32_t x= *((uint32_t *)s);
+ *((uint32_t *)d) = ((x>>1)&0x7FE07FE0) | (x&0x001F001F);
+ s+=4;
+ d+=4;
+ }
+ if(s < end)
+ {
+ register uint16_t x= *((uint16_t *)s);
+ *((uint16_t *)d) = ((x>>1)&0x7FE0) | (x&0x001F);
+ s+=2;
+ d+=2;
+ }
+}
+
+static inline void RENAME(rgb32to16)(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ const uint8_t *s = src;
+ const uint8_t *end;
+#ifdef HAVE_MMX
+ const uint8_t *mm_end;
+#endif
+ uint16_t *d = (uint16_t *)dst;
+ end = s + src_size;
+#ifdef HAVE_MMX
+ mm_end = end - 15;
+#if 1 //is faster only if multiplies are reasonable fast (FIXME figure out on which cpus this is faster, on Athlon its slightly faster)
+ asm volatile(
+ "movq %3, %%mm5 \n\t"
+ "movq %4, %%mm6 \n\t"
+ "movq %5, %%mm7 \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ PREFETCH" 32(%1) \n\t"
+ "movd (%1), %%mm0 \n\t"
+ "movd 4(%1), %%mm3 \n\t"
+ "punpckldq 8(%1), %%mm0 \n\t"
+ "punpckldq 12(%1), %%mm3 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "movq %%mm3, %%mm4 \n\t"
+ "pand %%mm6, %%mm0 \n\t"
+ "pand %%mm6, %%mm3 \n\t"
+ "pmaddwd %%mm7, %%mm0 \n\t"
+ "pmaddwd %%mm7, %%mm3 \n\t"
+ "pand %%mm5, %%mm1 \n\t"
+ "pand %%mm5, %%mm4 \n\t"
+ "por %%mm1, %%mm0 \n\t"
+ "por %%mm4, %%mm3 \n\t"
+ "psrld $5, %%mm0 \n\t"
+ "pslld $11, %%mm3 \n\t"
+ "por %%mm3, %%mm0 \n\t"
+ MOVNTQ" %%mm0, (%0) \n\t"
+ "add $16, %1 \n\t"
+ "add $8, %0 \n\t"
+ "cmp %2, %1 \n\t"
+ " jb 1b \n\t"
+ : "+r" (d), "+r"(s)
+ : "r" (mm_end), "m" (mask3216g), "m" (mask3216br), "m" (mul3216)
+ );
+#else
+ __asm __volatile(PREFETCH" %0"::"m"(*src):"memory");
+ __asm __volatile(
+ "movq %0, %%mm7\n\t"
+ "movq %1, %%mm6\n\t"
+ ::"m"(red_16mask),"m"(green_16mask));
+ while(s < mm_end)
+ {
+ __asm __volatile(
+ PREFETCH" 32%1\n\t"
+ "movd %1, %%mm0\n\t"
+ "movd 4%1, %%mm3\n\t"
+ "punpckldq 8%1, %%mm0\n\t"
+ "punpckldq 12%1, %%mm3\n\t"
+ "movq %%mm0, %%mm1\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm3, %%mm4\n\t"
+ "movq %%mm3, %%mm5\n\t"
+ "psrlq $3, %%mm0\n\t"
+ "psrlq $3, %%mm3\n\t"
+ "pand %2, %%mm0\n\t"
+ "pand %2, %%mm3\n\t"
+ "psrlq $5, %%mm1\n\t"
+ "psrlq $5, %%mm4\n\t"
+ "pand %%mm6, %%mm1\n\t"
+ "pand %%mm6, %%mm4\n\t"
+ "psrlq $8, %%mm2\n\t"
+ "psrlq $8, %%mm5\n\t"
+ "pand %%mm7, %%mm2\n\t"
+ "pand %%mm7, %%mm5\n\t"
+ "por %%mm1, %%mm0\n\t"
+ "por %%mm4, %%mm3\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "por %%mm5, %%mm3\n\t"
+ "psllq $16, %%mm3\n\t"
+ "por %%mm3, %%mm0\n\t"
+ MOVNTQ" %%mm0, %0\n\t"
+ :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
+ d += 4;
+ s += 16;
+ }
+#endif
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#endif
+ while(s < end)
+ {
+ register int rgb = *(uint32_t*)s; s += 4;
+ *d++ = ((rgb&0xFF)>>3) + ((rgb&0xFC00)>>5) + ((rgb&0xF80000)>>8);
+ }
+}
+
+static inline void RENAME(rgb32tobgr16)(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ const uint8_t *s = src;
+ const uint8_t *end;
+#ifdef HAVE_MMX
+ const uint8_t *mm_end;
+#endif
+ uint16_t *d = (uint16_t *)dst;
+ end = s + src_size;
+#ifdef HAVE_MMX
+ __asm __volatile(PREFETCH" %0"::"m"(*src):"memory");
+ __asm __volatile(
+ "movq %0, %%mm7\n\t"
+ "movq %1, %%mm6\n\t"
+ ::"m"(red_16mask),"m"(green_16mask));
+ mm_end = end - 15;
+ while(s < mm_end)
+ {
+ __asm __volatile(
+ PREFETCH" 32%1\n\t"
+ "movd %1, %%mm0\n\t"
+ "movd 4%1, %%mm3\n\t"
+ "punpckldq 8%1, %%mm0\n\t"
+ "punpckldq 12%1, %%mm3\n\t"
+ "movq %%mm0, %%mm1\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm3, %%mm4\n\t"
+ "movq %%mm3, %%mm5\n\t"
+ "psllq $8, %%mm0\n\t"
+ "psllq $8, %%mm3\n\t"
+ "pand %%mm7, %%mm0\n\t"
+ "pand %%mm7, %%mm3\n\t"
+ "psrlq $5, %%mm1\n\t"
+ "psrlq $5, %%mm4\n\t"
+ "pand %%mm6, %%mm1\n\t"
+ "pand %%mm6, %%mm4\n\t"
+ "psrlq $19, %%mm2\n\t"
+ "psrlq $19, %%mm5\n\t"
+ "pand %2, %%mm2\n\t"
+ "pand %2, %%mm5\n\t"
+ "por %%mm1, %%mm0\n\t"
+ "por %%mm4, %%mm3\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "por %%mm5, %%mm3\n\t"
+ "psllq $16, %%mm3\n\t"
+ "por %%mm3, %%mm0\n\t"
+ MOVNTQ" %%mm0, %0\n\t"
+ :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
+ d += 4;
+ s += 16;
+ }
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#endif
+ while(s < end)
+ {
+ register int rgb = *(uint32_t*)s; s += 4;
+ *d++ = ((rgb&0xF8)<<8) + ((rgb&0xFC00)>>5) + ((rgb&0xF80000)>>19);
+ }
+}
+
+static inline void RENAME(rgb32to15)(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ const uint8_t *s = src;
+ const uint8_t *end;
+#ifdef HAVE_MMX
+ const uint8_t *mm_end;
+#endif
+ uint16_t *d = (uint16_t *)dst;
+ end = s + src_size;
+#ifdef HAVE_MMX
+ mm_end = end - 15;
+#if 1 //is faster only if multiplies are reasonable fast (FIXME figure out on which cpus this is faster, on Athlon its slightly faster)
+ asm volatile(
+ "movq %3, %%mm5 \n\t"
+ "movq %4, %%mm6 \n\t"
+ "movq %5, %%mm7 \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ PREFETCH" 32(%1) \n\t"
+ "movd (%1), %%mm0 \n\t"
+ "movd 4(%1), %%mm3 \n\t"
+ "punpckldq 8(%1), %%mm0 \n\t"
+ "punpckldq 12(%1), %%mm3 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "movq %%mm3, %%mm4 \n\t"
+ "pand %%mm6, %%mm0 \n\t"
+ "pand %%mm6, %%mm3 \n\t"
+ "pmaddwd %%mm7, %%mm0 \n\t"
+ "pmaddwd %%mm7, %%mm3 \n\t"
+ "pand %%mm5, %%mm1 \n\t"
+ "pand %%mm5, %%mm4 \n\t"
+ "por %%mm1, %%mm0 \n\t"
+ "por %%mm4, %%mm3 \n\t"
+ "psrld $6, %%mm0 \n\t"
+ "pslld $10, %%mm3 \n\t"
+ "por %%mm3, %%mm0 \n\t"
+ MOVNTQ" %%mm0, (%0) \n\t"
+ "add $16, %1 \n\t"
+ "add $8, %0 \n\t"
+ "cmp %2, %1 \n\t"
+ " jb 1b \n\t"
+ : "+r" (d), "+r"(s)
+ : "r" (mm_end), "m" (mask3215g), "m" (mask3216br), "m" (mul3215)
+ );
+#else
+ __asm __volatile(PREFETCH" %0"::"m"(*src):"memory");
+ __asm __volatile(
+ "movq %0, %%mm7\n\t"
+ "movq %1, %%mm6\n\t"
+ ::"m"(red_15mask),"m"(green_15mask));
+ while(s < mm_end)
+ {
+ __asm __volatile(
+ PREFETCH" 32%1\n\t"
+ "movd %1, %%mm0\n\t"
+ "movd 4%1, %%mm3\n\t"
+ "punpckldq 8%1, %%mm0\n\t"
+ "punpckldq 12%1, %%mm3\n\t"
+ "movq %%mm0, %%mm1\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm3, %%mm4\n\t"
+ "movq %%mm3, %%mm5\n\t"
+ "psrlq $3, %%mm0\n\t"
+ "psrlq $3, %%mm3\n\t"
+ "pand %2, %%mm0\n\t"
+ "pand %2, %%mm3\n\t"
+ "psrlq $6, %%mm1\n\t"
+ "psrlq $6, %%mm4\n\t"
+ "pand %%mm6, %%mm1\n\t"
+ "pand %%mm6, %%mm4\n\t"
+ "psrlq $9, %%mm2\n\t"
+ "psrlq $9, %%mm5\n\t"
+ "pand %%mm7, %%mm2\n\t"
+ "pand %%mm7, %%mm5\n\t"
+ "por %%mm1, %%mm0\n\t"
+ "por %%mm4, %%mm3\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "por %%mm5, %%mm3\n\t"
+ "psllq $16, %%mm3\n\t"
+ "por %%mm3, %%mm0\n\t"
+ MOVNTQ" %%mm0, %0\n\t"
+ :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
+ d += 4;
+ s += 16;
+ }
+#endif
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#endif
+ while(s < end)
+ {
+ register int rgb = *(uint32_t*)s; s += 4;
+ *d++ = ((rgb&0xFF)>>3) + ((rgb&0xF800)>>6) + ((rgb&0xF80000)>>9);
+ }
+}
+
+static inline void RENAME(rgb32tobgr15)(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ const uint8_t *s = src;
+ const uint8_t *end;
+#ifdef HAVE_MMX
+ const uint8_t *mm_end;
+#endif
+ uint16_t *d = (uint16_t *)dst;
+ end = s + src_size;
+#ifdef HAVE_MMX
+ __asm __volatile(PREFETCH" %0"::"m"(*src):"memory");
+ __asm __volatile(
+ "movq %0, %%mm7\n\t"
+ "movq %1, %%mm6\n\t"
+ ::"m"(red_15mask),"m"(green_15mask));
+ mm_end = end - 15;
+ while(s < mm_end)
+ {
+ __asm __volatile(
+ PREFETCH" 32%1\n\t"
+ "movd %1, %%mm0\n\t"
+ "movd 4%1, %%mm3\n\t"
+ "punpckldq 8%1, %%mm0\n\t"
+ "punpckldq 12%1, %%mm3\n\t"
+ "movq %%mm0, %%mm1\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm3, %%mm4\n\t"
+ "movq %%mm3, %%mm5\n\t"
+ "psllq $7, %%mm0\n\t"
+ "psllq $7, %%mm3\n\t"
+ "pand %%mm7, %%mm0\n\t"
+ "pand %%mm7, %%mm3\n\t"
+ "psrlq $6, %%mm1\n\t"
+ "psrlq $6, %%mm4\n\t"
+ "pand %%mm6, %%mm1\n\t"
+ "pand %%mm6, %%mm4\n\t"
+ "psrlq $19, %%mm2\n\t"
+ "psrlq $19, %%mm5\n\t"
+ "pand %2, %%mm2\n\t"
+ "pand %2, %%mm5\n\t"
+ "por %%mm1, %%mm0\n\t"
+ "por %%mm4, %%mm3\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "por %%mm5, %%mm3\n\t"
+ "psllq $16, %%mm3\n\t"
+ "por %%mm3, %%mm0\n\t"
+ MOVNTQ" %%mm0, %0\n\t"
+ :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
+ d += 4;
+ s += 16;
+ }
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#endif
+ while(s < end)
+ {
+ register int rgb = *(uint32_t*)s; s += 4;
+ *d++ = ((rgb&0xF8)<<7) + ((rgb&0xF800)>>6) + ((rgb&0xF80000)>>19);
+ }
+}
+
+static inline void RENAME(rgb24to16)(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ const uint8_t *s = src;
+ const uint8_t *end;
+#ifdef HAVE_MMX
+ const uint8_t *mm_end;
+#endif
+ uint16_t *d = (uint16_t *)dst;
+ end = s + src_size;
+#ifdef HAVE_MMX
+ __asm __volatile(PREFETCH" %0"::"m"(*src):"memory");
+ __asm __volatile(
+ "movq %0, %%mm7\n\t"
+ "movq %1, %%mm6\n\t"
+ ::"m"(red_16mask),"m"(green_16mask));
+ mm_end = end - 11;
+ while(s < mm_end)
+ {
+ __asm __volatile(
+ PREFETCH" 32%1\n\t"
+ "movd %1, %%mm0\n\t"
+ "movd 3%1, %%mm3\n\t"
+ "punpckldq 6%1, %%mm0\n\t"
+ "punpckldq 9%1, %%mm3\n\t"
+ "movq %%mm0, %%mm1\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm3, %%mm4\n\t"
+ "movq %%mm3, %%mm5\n\t"
+ "psrlq $3, %%mm0\n\t"
+ "psrlq $3, %%mm3\n\t"
+ "pand %2, %%mm0\n\t"
+ "pand %2, %%mm3\n\t"
+ "psrlq $5, %%mm1\n\t"
+ "psrlq $5, %%mm4\n\t"
+ "pand %%mm6, %%mm1\n\t"
+ "pand %%mm6, %%mm4\n\t"
+ "psrlq $8, %%mm2\n\t"
+ "psrlq $8, %%mm5\n\t"
+ "pand %%mm7, %%mm2\n\t"
+ "pand %%mm7, %%mm5\n\t"
+ "por %%mm1, %%mm0\n\t"
+ "por %%mm4, %%mm3\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "por %%mm5, %%mm3\n\t"
+ "psllq $16, %%mm3\n\t"
+ "por %%mm3, %%mm0\n\t"
+ MOVNTQ" %%mm0, %0\n\t"
+ :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
+ d += 4;
+ s += 12;
+ }
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#endif
+ while(s < end)
+ {
+ const int b= *s++;
+ const int g= *s++;
+ const int r= *s++;
+ *d++ = (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8);
+ }
+}
+
+static inline void RENAME(rgb24tobgr16)(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ const uint8_t *s = src;
+ const uint8_t *end;
+#ifdef HAVE_MMX
+ const uint8_t *mm_end;
+#endif
+ uint16_t *d = (uint16_t *)dst;
+ end = s + src_size;
+#ifdef HAVE_MMX
+ __asm __volatile(PREFETCH" %0"::"m"(*src):"memory");
+ __asm __volatile(
+ "movq %0, %%mm7\n\t"
+ "movq %1, %%mm6\n\t"
+ ::"m"(red_16mask),"m"(green_16mask));
+ mm_end = end - 15;
+ while(s < mm_end)
+ {
+ __asm __volatile(
+ PREFETCH" 32%1\n\t"
+ "movd %1, %%mm0\n\t"
+ "movd 3%1, %%mm3\n\t"
+ "punpckldq 6%1, %%mm0\n\t"
+ "punpckldq 9%1, %%mm3\n\t"
+ "movq %%mm0, %%mm1\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm3, %%mm4\n\t"
+ "movq %%mm3, %%mm5\n\t"
+ "psllq $8, %%mm0\n\t"
+ "psllq $8, %%mm3\n\t"
+ "pand %%mm7, %%mm0\n\t"
+ "pand %%mm7, %%mm3\n\t"
+ "psrlq $5, %%mm1\n\t"
+ "psrlq $5, %%mm4\n\t"
+ "pand %%mm6, %%mm1\n\t"
+ "pand %%mm6, %%mm4\n\t"
+ "psrlq $19, %%mm2\n\t"
+ "psrlq $19, %%mm5\n\t"
+ "pand %2, %%mm2\n\t"
+ "pand %2, %%mm5\n\t"
+ "por %%mm1, %%mm0\n\t"
+ "por %%mm4, %%mm3\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "por %%mm5, %%mm3\n\t"
+ "psllq $16, %%mm3\n\t"
+ "por %%mm3, %%mm0\n\t"
+ MOVNTQ" %%mm0, %0\n\t"
+ :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
+ d += 4;
+ s += 12;
+ }
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#endif
+ while(s < end)
+ {
+ const int r= *s++;
+ const int g= *s++;
+ const int b= *s++;
+ *d++ = (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8);
+ }
+}
+
+static inline void RENAME(rgb24to15)(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ const uint8_t *s = src;
+ const uint8_t *end;
+#ifdef HAVE_MMX
+ const uint8_t *mm_end;
+#endif
+ uint16_t *d = (uint16_t *)dst;
+ end = s + src_size;
+#ifdef HAVE_MMX
+ __asm __volatile(PREFETCH" %0"::"m"(*src):"memory");
+ __asm __volatile(
+ "movq %0, %%mm7\n\t"
+ "movq %1, %%mm6\n\t"
+ ::"m"(red_15mask),"m"(green_15mask));
+ mm_end = end - 11;
+ while(s < mm_end)
+ {
+ __asm __volatile(
+ PREFETCH" 32%1\n\t"
+ "movd %1, %%mm0\n\t"
+ "movd 3%1, %%mm3\n\t"
+ "punpckldq 6%1, %%mm0\n\t"
+ "punpckldq 9%1, %%mm3\n\t"
+ "movq %%mm0, %%mm1\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm3, %%mm4\n\t"
+ "movq %%mm3, %%mm5\n\t"
+ "psrlq $3, %%mm0\n\t"
+ "psrlq $3, %%mm3\n\t"
+ "pand %2, %%mm0\n\t"
+ "pand %2, %%mm3\n\t"
+ "psrlq $6, %%mm1\n\t"
+ "psrlq $6, %%mm4\n\t"
+ "pand %%mm6, %%mm1\n\t"
+ "pand %%mm6, %%mm4\n\t"
+ "psrlq $9, %%mm2\n\t"
+ "psrlq $9, %%mm5\n\t"
+ "pand %%mm7, %%mm2\n\t"
+ "pand %%mm7, %%mm5\n\t"
+ "por %%mm1, %%mm0\n\t"
+ "por %%mm4, %%mm3\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "por %%mm5, %%mm3\n\t"
+ "psllq $16, %%mm3\n\t"
+ "por %%mm3, %%mm0\n\t"
+ MOVNTQ" %%mm0, %0\n\t"
+ :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
+ d += 4;
+ s += 12;
+ }
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#endif
+ while(s < end)
+ {
+ const int b= *s++;
+ const int g= *s++;
+ const int r= *s++;
+ *d++ = (b>>3) | ((g&0xF8)<<2) | ((r&0xF8)<<7);
+ }
+}
+
+static inline void RENAME(rgb24tobgr15)(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ const uint8_t *s = src;
+ const uint8_t *end;
+#ifdef HAVE_MMX
+ const uint8_t *mm_end;
+#endif
+ uint16_t *d = (uint16_t *)dst;
+ end = s + src_size;
+#ifdef HAVE_MMX
+ __asm __volatile(PREFETCH" %0"::"m"(*src):"memory");
+ __asm __volatile(
+ "movq %0, %%mm7\n\t"
+ "movq %1, %%mm6\n\t"
+ ::"m"(red_15mask),"m"(green_15mask));
+ mm_end = end - 15;
+ while(s < mm_end)
+ {
+ __asm __volatile(
+ PREFETCH" 32%1\n\t"
+ "movd %1, %%mm0\n\t"
+ "movd 3%1, %%mm3\n\t"
+ "punpckldq 6%1, %%mm0\n\t"
+ "punpckldq 9%1, %%mm3\n\t"
+ "movq %%mm0, %%mm1\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm3, %%mm4\n\t"
+ "movq %%mm3, %%mm5\n\t"
+ "psllq $7, %%mm0\n\t"
+ "psllq $7, %%mm3\n\t"
+ "pand %%mm7, %%mm0\n\t"
+ "pand %%mm7, %%mm3\n\t"
+ "psrlq $6, %%mm1\n\t"
+ "psrlq $6, %%mm4\n\t"
+ "pand %%mm6, %%mm1\n\t"
+ "pand %%mm6, %%mm4\n\t"
+ "psrlq $19, %%mm2\n\t"
+ "psrlq $19, %%mm5\n\t"
+ "pand %2, %%mm2\n\t"
+ "pand %2, %%mm5\n\t"
+ "por %%mm1, %%mm0\n\t"
+ "por %%mm4, %%mm3\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "por %%mm5, %%mm3\n\t"
+ "psllq $16, %%mm3\n\t"
+ "por %%mm3, %%mm0\n\t"
+ MOVNTQ" %%mm0, %0\n\t"
+ :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
+ d += 4;
+ s += 12;
+ }
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#endif
+ while(s < end)
+ {
+ const int r= *s++;
+ const int g= *s++;
+ const int b= *s++;
+ *d++ = (b>>3) | ((g&0xF8)<<2) | ((r&0xF8)<<7);
+ }
+}
+
+/*
+ I use here less accurate approximation by simply
+ left-shifting the input
+ value and filling the low order bits with
+ zeroes. This method improves png's
+ compression but this scheme cannot reproduce white exactly, since it does not
+ generate an all-ones maximum value; the net effect is to darken the
+ image slightly.
+
+ The better method should be "left bit replication":
+
+ 4 3 2 1 0
+ ---------
+ 1 1 0 1 1
+
+ 7 6 5 4 3 2 1 0
+ ----------------
+ 1 1 0 1 1 1 1 0
+ |=======| |===|
+ | Leftmost Bits Repeated to Fill Open Bits
+ |
+ Original Bits
+*/
+static inline void RENAME(rgb15to24)(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ const uint16_t *end;
+#ifdef HAVE_MMX
+ const uint16_t *mm_end;
+#endif
+ uint8_t *d = (uint8_t *)dst;
+ const uint16_t *s = (uint16_t *)src;
+ end = s + src_size/2;
+#ifdef HAVE_MMX
+ __asm __volatile(PREFETCH" %0"::"m"(*s):"memory");
+ mm_end = end - 7;
+ while(s < mm_end)
+ {
+ __asm __volatile(
+ PREFETCH" 32%1\n\t"
+ "movq %1, %%mm0\n\t"
+ "movq %1, %%mm1\n\t"
+ "movq %1, %%mm2\n\t"
+ "pand %2, %%mm0\n\t"
+ "pand %3, %%mm1\n\t"
+ "pand %4, %%mm2\n\t"
+ "psllq $3, %%mm0\n\t"
+ "psrlq $2, %%mm1\n\t"
+ "psrlq $7, %%mm2\n\t"
+ "movq %%mm0, %%mm3\n\t"
+ "movq %%mm1, %%mm4\n\t"
+ "movq %%mm2, %%mm5\n\t"
+ "punpcklwd %5, %%mm0\n\t"
+ "punpcklwd %5, %%mm1\n\t"
+ "punpcklwd %5, %%mm2\n\t"
+ "punpckhwd %5, %%mm3\n\t"
+ "punpckhwd %5, %%mm4\n\t"
+ "punpckhwd %5, %%mm5\n\t"
+ "psllq $8, %%mm1\n\t"
+ "psllq $16, %%mm2\n\t"
+ "por %%mm1, %%mm0\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "psllq $8, %%mm4\n\t"
+ "psllq $16, %%mm5\n\t"
+ "por %%mm4, %%mm3\n\t"
+ "por %%mm5, %%mm3\n\t"
+
+ "movq %%mm0, %%mm6\n\t"
+ "movq %%mm3, %%mm7\n\t"
+
+ "movq 8%1, %%mm0\n\t"
+ "movq 8%1, %%mm1\n\t"
+ "movq 8%1, %%mm2\n\t"
+ "pand %2, %%mm0\n\t"
+ "pand %3, %%mm1\n\t"
+ "pand %4, %%mm2\n\t"
+ "psllq $3, %%mm0\n\t"
+ "psrlq $2, %%mm1\n\t"
+ "psrlq $7, %%mm2\n\t"
+ "movq %%mm0, %%mm3\n\t"
+ "movq %%mm1, %%mm4\n\t"
+ "movq %%mm2, %%mm5\n\t"
+ "punpcklwd %5, %%mm0\n\t"
+ "punpcklwd %5, %%mm1\n\t"
+ "punpcklwd %5, %%mm2\n\t"
+ "punpckhwd %5, %%mm3\n\t"
+ "punpckhwd %5, %%mm4\n\t"
+ "punpckhwd %5, %%mm5\n\t"
+ "psllq $8, %%mm1\n\t"
+ "psllq $16, %%mm2\n\t"
+ "por %%mm1, %%mm0\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "psllq $8, %%mm4\n\t"
+ "psllq $16, %%mm5\n\t"
+ "por %%mm4, %%mm3\n\t"
+ "por %%mm5, %%mm3\n\t"
+
+ :"=m"(*d)
+ :"m"(*s),"m"(mask15b),"m"(mask15g),"m"(mask15r), "m"(mmx_null)
+ :"memory");
+ /* Borrowed 32 to 24 */
+ __asm __volatile(
+ "movq %%mm0, %%mm4\n\t"
+ "movq %%mm3, %%mm5\n\t"
+ "movq %%mm6, %%mm0\n\t"
+ "movq %%mm7, %%mm1\n\t"
+
+ "movq %%mm4, %%mm6\n\t"
+ "movq %%mm5, %%mm7\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+
+ "psrlq $8, %%mm2\n\t"
+ "psrlq $8, %%mm3\n\t"
+ "psrlq $8, %%mm6\n\t"
+ "psrlq $8, %%mm7\n\t"
+ "pand %2, %%mm0\n\t"
+ "pand %2, %%mm1\n\t"
+ "pand %2, %%mm4\n\t"
+ "pand %2, %%mm5\n\t"
+ "pand %3, %%mm2\n\t"
+ "pand %3, %%mm3\n\t"
+ "pand %3, %%mm6\n\t"
+ "pand %3, %%mm7\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "por %%mm3, %%mm1\n\t"
+ "por %%mm6, %%mm4\n\t"
+ "por %%mm7, %%mm5\n\t"
+
+ "movq %%mm1, %%mm2\n\t"
+ "movq %%mm4, %%mm3\n\t"
+ "psllq $48, %%mm2\n\t"
+ "psllq $32, %%mm3\n\t"
+ "pand %4, %%mm2\n\t"
+ "pand %5, %%mm3\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "psrlq $16, %%mm1\n\t"
+ "psrlq $32, %%mm4\n\t"
+ "psllq $16, %%mm5\n\t"
+ "por %%mm3, %%mm1\n\t"
+ "pand %6, %%mm5\n\t"
+ "por %%mm5, %%mm4\n\t"
+
+ MOVNTQ" %%mm0, %0\n\t"
+ MOVNTQ" %%mm1, 8%0\n\t"
+ MOVNTQ" %%mm4, 16%0"
+
+ :"=m"(*d)
+ :"m"(*s),"m"(mask24l),"m"(mask24h),"m"(mask24hh),"m"(mask24hhh),"m"(mask24hhhh)
+ :"memory");
+ d += 24;
+ s += 8;
+ }
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#endif
+ while(s < end)
+ {
+ register uint16_t bgr;
+ bgr = *s++;
+ *d++ = (bgr&0x1F)<<3;
+ *d++ = (bgr&0x3E0)>>2;
+ *d++ = (bgr&0x7C00)>>7;
+ }
+}
+
+static inline void RENAME(rgb16to24)(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ const uint16_t *end;
+#ifdef HAVE_MMX
+ const uint16_t *mm_end;
+#endif
+ uint8_t *d = (uint8_t *)dst;
+ const uint16_t *s = (const uint16_t *)src;
+ end = s + src_size/2;
+#ifdef HAVE_MMX
+ __asm __volatile(PREFETCH" %0"::"m"(*s):"memory");
+ mm_end = end - 7;
+ while(s < mm_end)
+ {
+ __asm __volatile(
+ PREFETCH" 32%1\n\t"
+ "movq %1, %%mm0\n\t"
+ "movq %1, %%mm1\n\t"
+ "movq %1, %%mm2\n\t"
+ "pand %2, %%mm0\n\t"
+ "pand %3, %%mm1\n\t"
+ "pand %4, %%mm2\n\t"
+ "psllq $3, %%mm0\n\t"
+ "psrlq $3, %%mm1\n\t"
+ "psrlq $8, %%mm2\n\t"
+ "movq %%mm0, %%mm3\n\t"
+ "movq %%mm1, %%mm4\n\t"
+ "movq %%mm2, %%mm5\n\t"
+ "punpcklwd %5, %%mm0\n\t"
+ "punpcklwd %5, %%mm1\n\t"
+ "punpcklwd %5, %%mm2\n\t"
+ "punpckhwd %5, %%mm3\n\t"
+ "punpckhwd %5, %%mm4\n\t"
+ "punpckhwd %5, %%mm5\n\t"
+ "psllq $8, %%mm1\n\t"
+ "psllq $16, %%mm2\n\t"
+ "por %%mm1, %%mm0\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "psllq $8, %%mm4\n\t"
+ "psllq $16, %%mm5\n\t"
+ "por %%mm4, %%mm3\n\t"
+ "por %%mm5, %%mm3\n\t"
+
+ "movq %%mm0, %%mm6\n\t"
+ "movq %%mm3, %%mm7\n\t"
+
+ "movq 8%1, %%mm0\n\t"
+ "movq 8%1, %%mm1\n\t"
+ "movq 8%1, %%mm2\n\t"
+ "pand %2, %%mm0\n\t"
+ "pand %3, %%mm1\n\t"
+ "pand %4, %%mm2\n\t"
+ "psllq $3, %%mm0\n\t"
+ "psrlq $3, %%mm1\n\t"
+ "psrlq $8, %%mm2\n\t"
+ "movq %%mm0, %%mm3\n\t"
+ "movq %%mm1, %%mm4\n\t"
+ "movq %%mm2, %%mm5\n\t"
+ "punpcklwd %5, %%mm0\n\t"
+ "punpcklwd %5, %%mm1\n\t"
+ "punpcklwd %5, %%mm2\n\t"
+ "punpckhwd %5, %%mm3\n\t"
+ "punpckhwd %5, %%mm4\n\t"
+ "punpckhwd %5, %%mm5\n\t"
+ "psllq $8, %%mm1\n\t"
+ "psllq $16, %%mm2\n\t"
+ "por %%mm1, %%mm0\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "psllq $8, %%mm4\n\t"
+ "psllq $16, %%mm5\n\t"
+ "por %%mm4, %%mm3\n\t"
+ "por %%mm5, %%mm3\n\t"
+ :"=m"(*d)
+ :"m"(*s),"m"(mask16b),"m"(mask16g),"m"(mask16r),"m"(mmx_null)
+ :"memory");
+ /* Borrowed 32 to 24 */
+ __asm __volatile(
+ "movq %%mm0, %%mm4\n\t"
+ "movq %%mm3, %%mm5\n\t"
+ "movq %%mm6, %%mm0\n\t"
+ "movq %%mm7, %%mm1\n\t"
+
+ "movq %%mm4, %%mm6\n\t"
+ "movq %%mm5, %%mm7\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+
+ "psrlq $8, %%mm2\n\t"
+ "psrlq $8, %%mm3\n\t"
+ "psrlq $8, %%mm6\n\t"
+ "psrlq $8, %%mm7\n\t"
+ "pand %2, %%mm0\n\t"
+ "pand %2, %%mm1\n\t"
+ "pand %2, %%mm4\n\t"
+ "pand %2, %%mm5\n\t"
+ "pand %3, %%mm2\n\t"
+ "pand %3, %%mm3\n\t"
+ "pand %3, %%mm6\n\t"
+ "pand %3, %%mm7\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "por %%mm3, %%mm1\n\t"
+ "por %%mm6, %%mm4\n\t"
+ "por %%mm7, %%mm5\n\t"
+
+ "movq %%mm1, %%mm2\n\t"
+ "movq %%mm4, %%mm3\n\t"
+ "psllq $48, %%mm2\n\t"
+ "psllq $32, %%mm3\n\t"
+ "pand %4, %%mm2\n\t"
+ "pand %5, %%mm3\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "psrlq $16, %%mm1\n\t"
+ "psrlq $32, %%mm4\n\t"
+ "psllq $16, %%mm5\n\t"
+ "por %%mm3, %%mm1\n\t"
+ "pand %6, %%mm5\n\t"
+ "por %%mm5, %%mm4\n\t"
+
+ MOVNTQ" %%mm0, %0\n\t"
+ MOVNTQ" %%mm1, 8%0\n\t"
+ MOVNTQ" %%mm4, 16%0"
+
+ :"=m"(*d)
+ :"m"(*s),"m"(mask24l),"m"(mask24h),"m"(mask24hh),"m"(mask24hhh),"m"(mask24hhhh)
+ :"memory");
+ d += 24;
+ s += 8;
+ }
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#endif
+ while(s < end)
+ {
+ register uint16_t bgr;
+ bgr = *s++;
+ *d++ = (bgr&0x1F)<<3;
+ *d++ = (bgr&0x7E0)>>3;
+ *d++ = (bgr&0xF800)>>8;
+ }
+}
+
+static inline void RENAME(rgb15to32)(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ const uint16_t *end;
+#ifdef HAVE_MMX
+ const uint16_t *mm_end;
+#endif
+ uint8_t *d = (uint8_t *)dst;
+ const uint16_t *s = (const uint16_t *)src;
+ end = s + src_size/2;
+#ifdef HAVE_MMX
+ __asm __volatile(PREFETCH" %0"::"m"(*s):"memory");
+ __asm __volatile("pxor %%mm7,%%mm7\n\t":::"memory");
+ mm_end = end - 3;
+ while(s < mm_end)
+ {
+ __asm __volatile(
+ PREFETCH" 32%1\n\t"
+ "movq %1, %%mm0\n\t"
+ "movq %1, %%mm1\n\t"
+ "movq %1, %%mm2\n\t"
+ "pand %2, %%mm0\n\t"
+ "pand %3, %%mm1\n\t"
+ "pand %4, %%mm2\n\t"
+ "psllq $3, %%mm0\n\t"
+ "psrlq $2, %%mm1\n\t"
+ "psrlq $7, %%mm2\n\t"
+ "movq %%mm0, %%mm3\n\t"
+ "movq %%mm1, %%mm4\n\t"
+ "movq %%mm2, %%mm5\n\t"
+ "punpcklwd %%mm7, %%mm0\n\t"
+ "punpcklwd %%mm7, %%mm1\n\t"
+ "punpcklwd %%mm7, %%mm2\n\t"
+ "punpckhwd %%mm7, %%mm3\n\t"
+ "punpckhwd %%mm7, %%mm4\n\t"
+ "punpckhwd %%mm7, %%mm5\n\t"
+ "psllq $8, %%mm1\n\t"
+ "psllq $16, %%mm2\n\t"
+ "por %%mm1, %%mm0\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "psllq $8, %%mm4\n\t"
+ "psllq $16, %%mm5\n\t"
+ "por %%mm4, %%mm3\n\t"
+ "por %%mm5, %%mm3\n\t"
+ MOVNTQ" %%mm0, %0\n\t"
+ MOVNTQ" %%mm3, 8%0\n\t"
+ :"=m"(*d)
+ :"m"(*s),"m"(mask15b),"m"(mask15g),"m"(mask15r)
+ :"memory");
+ d += 16;
+ s += 4;
+ }
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#endif
+ while(s < end)
+ {
+#if 0 //slightly slower on athlon
+ int bgr= *s++;
+ *((uint32_t*)d)++ = ((bgr&0x1F)<<3) + ((bgr&0x3E0)<<6) + ((bgr&0x7C00)<<9);
+#else
+ register uint16_t bgr;
+ bgr = *s++;
+#ifdef WORDS_BIGENDIAN
+ *d++ = 0;
+ *d++ = (bgr&0x7C00)>>7;
+ *d++ = (bgr&0x3E0)>>2;
+ *d++ = (bgr&0x1F)<<3;
+#else
+ *d++ = (bgr&0x1F)<<3;
+ *d++ = (bgr&0x3E0)>>2;
+ *d++ = (bgr&0x7C00)>>7;
+ *d++ = 0;
+#endif
+
+#endif
+ }
+}
+
+static inline void RENAME(rgb16to32)(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ const uint16_t *end;
+#ifdef HAVE_MMX
+ const uint16_t *mm_end;
+#endif
+ uint8_t *d = (uint8_t *)dst;
+ const uint16_t *s = (uint16_t *)src;
+ end = s + src_size/2;
+#ifdef HAVE_MMX
+ __asm __volatile(PREFETCH" %0"::"m"(*s):"memory");
+ __asm __volatile("pxor %%mm7,%%mm7\n\t":::"memory");
+ mm_end = end - 3;
+ while(s < mm_end)
+ {
+ __asm __volatile(
+ PREFETCH" 32%1\n\t"
+ "movq %1, %%mm0\n\t"
+ "movq %1, %%mm1\n\t"
+ "movq %1, %%mm2\n\t"
+ "pand %2, %%mm0\n\t"
+ "pand %3, %%mm1\n\t"
+ "pand %4, %%mm2\n\t"
+ "psllq $3, %%mm0\n\t"
+ "psrlq $3, %%mm1\n\t"
+ "psrlq $8, %%mm2\n\t"
+ "movq %%mm0, %%mm3\n\t"
+ "movq %%mm1, %%mm4\n\t"
+ "movq %%mm2, %%mm5\n\t"
+ "punpcklwd %%mm7, %%mm0\n\t"
+ "punpcklwd %%mm7, %%mm1\n\t"
+ "punpcklwd %%mm7, %%mm2\n\t"
+ "punpckhwd %%mm7, %%mm3\n\t"
+ "punpckhwd %%mm7, %%mm4\n\t"
+ "punpckhwd %%mm7, %%mm5\n\t"
+ "psllq $8, %%mm1\n\t"
+ "psllq $16, %%mm2\n\t"
+ "por %%mm1, %%mm0\n\t"
+ "por %%mm2, %%mm0\n\t"
+ "psllq $8, %%mm4\n\t"
+ "psllq $16, %%mm5\n\t"
+ "por %%mm4, %%mm3\n\t"
+ "por %%mm5, %%mm3\n\t"
+ MOVNTQ" %%mm0, %0\n\t"
+ MOVNTQ" %%mm3, 8%0\n\t"
+ :"=m"(*d)
+ :"m"(*s),"m"(mask16b),"m"(mask16g),"m"(mask16r)
+ :"memory");
+ d += 16;
+ s += 4;
+ }
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#endif
+ while(s < end)
+ {
+ register uint16_t bgr;
+ bgr = *s++;
+#ifdef WORDS_BIGENDIAN
+ *d++ = 0;
+ *d++ = (bgr&0xF800)>>8;
+ *d++ = (bgr&0x7E0)>>3;
+ *d++ = (bgr&0x1F)<<3;
+#else
+ *d++ = (bgr&0x1F)<<3;
+ *d++ = (bgr&0x7E0)>>3;
+ *d++ = (bgr&0xF800)>>8;
+ *d++ = 0;
+#endif
+ }
+}
+
+static inline void RENAME(rgb32tobgr32)(const uint8_t *src, uint8_t *dst, long src_size)
+{
+#ifdef HAVE_MMX
+/* TODO: unroll this loop */
+ asm volatile (
+ "xor %%"REG_a", %%"REG_a" \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ PREFETCH" 32(%0, %%"REG_a") \n\t"
+ "movq (%0, %%"REG_a"), %%mm0 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "movq %%mm0, %%mm2 \n\t"
+ "pslld $16, %%mm0 \n\t"
+ "psrld $16, %%mm1 \n\t"
+ "pand "MANGLE(mask32r)", %%mm0 \n\t"
+ "pand "MANGLE(mask32g)", %%mm2 \n\t"
+ "pand "MANGLE(mask32b)", %%mm1 \n\t"
+ "por %%mm0, %%mm2 \n\t"
+ "por %%mm1, %%mm2 \n\t"
+ MOVNTQ" %%mm2, (%1, %%"REG_a") \n\t"
+ "add $8, %%"REG_a" \n\t"
+ "cmp %2, %%"REG_a" \n\t"
+ " jb 1b \n\t"
+ :: "r" (src), "r"(dst), "r" (src_size-7)
+ : "%"REG_a
+ );
+
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#else
+ unsigned i;
+ unsigned num_pixels = src_size >> 2;
+ for(i=0; i<num_pixels; i++)
+ {
+#ifdef WORDS_BIGENDIAN
+ dst[4*i + 1] = src[4*i + 3];
+ dst[4*i + 2] = src[4*i + 2];
+ dst[4*i + 3] = src[4*i + 1];
+#else
+ dst[4*i + 0] = src[4*i + 2];
+ dst[4*i + 1] = src[4*i + 1];
+ dst[4*i + 2] = src[4*i + 0];
+#endif
+ }
+#endif
+}
+
+static inline void RENAME(rgb24tobgr24)(const uint8_t *src, uint8_t *dst, long src_size)
+{
+ unsigned i;
+#ifdef HAVE_MMX
+ long mmx_size= 23 - src_size;
+ asm volatile (
+ "movq "MANGLE(mask24r)", %%mm5 \n\t"
+ "movq "MANGLE(mask24g)", %%mm6 \n\t"
+ "movq "MANGLE(mask24b)", %%mm7 \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ PREFETCH" 32(%1, %%"REG_a") \n\t"
+ "movq (%1, %%"REG_a"), %%mm0 \n\t" // BGR BGR BG
+ "movq (%1, %%"REG_a"), %%mm1 \n\t" // BGR BGR BG
+ "movq 2(%1, %%"REG_a"), %%mm2 \n\t" // R BGR BGR B
+ "psllq $16, %%mm0 \n\t" // 00 BGR BGR
+ "pand %%mm5, %%mm0 \n\t"
+ "pand %%mm6, %%mm1 \n\t"
+ "pand %%mm7, %%mm2 \n\t"
+ "por %%mm0, %%mm1 \n\t"
+ "por %%mm2, %%mm1 \n\t"
+ "movq 6(%1, %%"REG_a"), %%mm0 \n\t" // BGR BGR BG
+ MOVNTQ" %%mm1, (%2, %%"REG_a")\n\t" // RGB RGB RG
+ "movq 8(%1, %%"REG_a"), %%mm1 \n\t" // R BGR BGR B
+ "movq 10(%1, %%"REG_a"), %%mm2 \n\t" // GR BGR BGR
+ "pand %%mm7, %%mm0 \n\t"
+ "pand %%mm5, %%mm1 \n\t"
+ "pand %%mm6, %%mm2 \n\t"
+ "por %%mm0, %%mm1 \n\t"
+ "por %%mm2, %%mm1 \n\t"
+ "movq 14(%1, %%"REG_a"), %%mm0 \n\t" // R BGR BGR B
+ MOVNTQ" %%mm1, 8(%2, %%"REG_a")\n\t" // B RGB RGB R
+ "movq 16(%1, %%"REG_a"), %%mm1 \n\t" // GR BGR BGR
+ "movq 18(%1, %%"REG_a"), %%mm2 \n\t" // BGR BGR BG
+ "pand %%mm6, %%mm0 \n\t"
+ "pand %%mm7, %%mm1 \n\t"
+ "pand %%mm5, %%mm2 \n\t"
+ "por %%mm0, %%mm1 \n\t"
+ "por %%mm2, %%mm1 \n\t"
+ MOVNTQ" %%mm1, 16(%2, %%"REG_a")\n\t"
+ "add $24, %%"REG_a" \n\t"
+ " js 1b \n\t"
+ : "+a" (mmx_size)
+ : "r" (src-mmx_size), "r"(dst-mmx_size)
+ );
+
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+
+ if(mmx_size==23) return; //finihsed, was multiple of 8
+
+ src+= src_size;
+ dst+= src_size;
+ src_size= 23-mmx_size;
+ src-= src_size;
+ dst-= src_size;
+#endif
+ for(i=0; i<src_size; i+=3)
+ {
+ register uint8_t x;
+ x = src[i + 2];
+ dst[i + 1] = src[i + 1];
+ dst[i + 2] = src[i + 0];
+ dst[i + 0] = x;
+ }
+}
+
+static inline void RENAME(yuvPlanartoyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
+ long width, long height,
+ long lumStride, long chromStride, long dstStride, long vertLumPerChroma)
+{
+ long y;
+ const long chromWidth= width>>1;
+ for(y=0; y<height; y++)
+ {
+#ifdef HAVE_MMX
+//FIXME handle 2 lines a once (fewer prefetch, reuse some chrom, but very likely limited by mem anyway)
+ asm volatile(
+ "xor %%"REG_a", %%"REG_a" \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ PREFETCH" 32(%1, %%"REG_a", 2) \n\t"
+ PREFETCH" 32(%2, %%"REG_a") \n\t"
+ PREFETCH" 32(%3, %%"REG_a") \n\t"
+ "movq (%2, %%"REG_a"), %%mm0 \n\t" // U(0)
+ "movq %%mm0, %%mm2 \n\t" // U(0)
+ "movq (%3, %%"REG_a"), %%mm1 \n\t" // V(0)
+ "punpcklbw %%mm1, %%mm0 \n\t" // UVUV UVUV(0)
+ "punpckhbw %%mm1, %%mm2 \n\t" // UVUV UVUV(8)
+
+ "movq (%1, %%"REG_a",2), %%mm3 \n\t" // Y(0)
+ "movq 8(%1, %%"REG_a",2), %%mm5 \n\t" // Y(8)
+ "movq %%mm3, %%mm4 \n\t" // Y(0)
+ "movq %%mm5, %%mm6 \n\t" // Y(8)
+ "punpcklbw %%mm0, %%mm3 \n\t" // YUYV YUYV(0)
+ "punpckhbw %%mm0, %%mm4 \n\t" // YUYV YUYV(4)
+ "punpcklbw %%mm2, %%mm5 \n\t" // YUYV YUYV(8)
+ "punpckhbw %%mm2, %%mm6 \n\t" // YUYV YUYV(12)
+
+ MOVNTQ" %%mm3, (%0, %%"REG_a", 4)\n\t"
+ MOVNTQ" %%mm4, 8(%0, %%"REG_a", 4)\n\t"
+ MOVNTQ" %%mm5, 16(%0, %%"REG_a", 4)\n\t"
+ MOVNTQ" %%mm6, 24(%0, %%"REG_a", 4)\n\t"
+
+ "add $8, %%"REG_a" \n\t"
+ "cmp %4, %%"REG_a" \n\t"
+ " jb 1b \n\t"
+ ::"r"(dst), "r"(ysrc), "r"(usrc), "r"(vsrc), "g" (chromWidth)
+ : "%"REG_a
+ );
+#else
+
+#if defined ARCH_ALPHA && defined HAVE_MVI
+#define pl2yuy2(n) \
+ y1 = yc[n]; \
+ y2 = yc2[n]; \
+ u = uc[n]; \
+ v = vc[n]; \
+ asm("unpkbw %1, %0" : "=r"(y1) : "r"(y1)); \
+ asm("unpkbw %1, %0" : "=r"(y2) : "r"(y2)); \
+ asm("unpkbl %1, %0" : "=r"(u) : "r"(u)); \
+ asm("unpkbl %1, %0" : "=r"(v) : "r"(v)); \
+ yuv1 = (u << 8) + (v << 24); \
+ yuv2 = yuv1 + y2; \
+ yuv1 += y1; \
+ qdst[n] = yuv1; \
+ qdst2[n] = yuv2;
+
+ int i;
+ uint64_t *qdst = (uint64_t *) dst;
+ uint64_t *qdst2 = (uint64_t *) (dst + dstStride);
+ const uint32_t *yc = (uint32_t *) ysrc;
+ const uint32_t *yc2 = (uint32_t *) (ysrc + lumStride);
+ const uint16_t *uc = (uint16_t*) usrc, *vc = (uint16_t*) vsrc;
+ for(i = 0; i < chromWidth; i += 8){
+ uint64_t y1, y2, yuv1, yuv2;
+ uint64_t u, v;
+ /* Prefetch */
+ asm("ldq $31,64(%0)" :: "r"(yc));
+ asm("ldq $31,64(%0)" :: "r"(yc2));
+ asm("ldq $31,64(%0)" :: "r"(uc));
+ asm("ldq $31,64(%0)" :: "r"(vc));
+
+ pl2yuy2(0);
+ pl2yuy2(1);
+ pl2yuy2(2);
+ pl2yuy2(3);
+
+ yc += 4;
+ yc2 += 4;
+ uc += 4;
+ vc += 4;
+ qdst += 4;
+ qdst2 += 4;
+ }
+ y++;
+ ysrc += lumStride;
+ dst += dstStride;
+
+#elif __WORDSIZE >= 64
+ int i;
+ uint64_t *ldst = (uint64_t *) dst;
+ const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
+ for(i = 0; i < chromWidth; i += 2){
+ uint64_t k, l;
+ k = yc[0] + (uc[0] << 8) +
+ (yc[1] << 16) + (vc[0] << 24);
+ l = yc[2] + (uc[1] << 8) +
+ (yc[3] << 16) + (vc[1] << 24);
+ *ldst++ = k + (l << 32);
+ yc += 4;
+ uc += 2;
+ vc += 2;
+ }
+
+#else
+ int i, *idst = (int32_t *) dst;
+ const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
+ for(i = 0; i < chromWidth; i++){
+#ifdef WORDS_BIGENDIAN
+ *idst++ = (yc[0] << 24)+ (uc[0] << 16) +
+ (yc[1] << 8) + (vc[0] << 0);
+#else
+ *idst++ = yc[0] + (uc[0] << 8) +
+ (yc[1] << 16) + (vc[0] << 24);
+#endif
+ yc += 2;
+ uc++;
+ vc++;
+ }
+#endif
+#endif
+ if((y&(vertLumPerChroma-1))==(vertLumPerChroma-1) )
+ {
+ usrc += chromStride;
+ vsrc += chromStride;
+ }
+ ysrc += lumStride;
+ dst += dstStride;
+ }
+#ifdef HAVE_MMX
+asm( EMMS" \n\t"
+ SFENCE" \n\t"
+ :::"memory");
+#endif
+}
+
+/**
+ *
+ * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
+ * problem for anyone then tell me, and ill fix it)
+ */
+static inline void RENAME(yv12toyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
+ long width, long height,
+ long lumStride, long chromStride, long dstStride)
+{
+ //FIXME interpolate chroma
+ RENAME(yuvPlanartoyuy2)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 2);
+}
+
+static inline void RENAME(yuvPlanartouyvy)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
+ long width, long height,
+ long lumStride, long chromStride, long dstStride, long vertLumPerChroma)
+{
+ long y;
+ const long chromWidth= width>>1;
+ for(y=0; y<height; y++)
+ {
+#ifdef HAVE_MMX
+//FIXME handle 2 lines a once (fewer prefetch, reuse some chrom, but very likely limited by mem anyway)
+ asm volatile(
+ "xor %%"REG_a", %%"REG_a" \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ PREFETCH" 32(%1, %%"REG_a", 2) \n\t"
+ PREFETCH" 32(%2, %%"REG_a") \n\t"
+ PREFETCH" 32(%3, %%"REG_a") \n\t"
+ "movq (%2, %%"REG_a"), %%mm0 \n\t" // U(0)
+ "movq %%mm0, %%mm2 \n\t" // U(0)
+ "movq (%3, %%"REG_a"), %%mm1 \n\t" // V(0)
+ "punpcklbw %%mm1, %%mm0 \n\t" // UVUV UVUV(0)
+ "punpckhbw %%mm1, %%mm2 \n\t" // UVUV UVUV(8)
+
+ "movq (%1, %%"REG_a",2), %%mm3 \n\t" // Y(0)
+ "movq 8(%1, %%"REG_a",2), %%mm5 \n\t" // Y(8)
+ "movq %%mm0, %%mm4 \n\t" // Y(0)
+ "movq %%mm2, %%mm6 \n\t" // Y(8)
+ "punpcklbw %%mm3, %%mm0 \n\t" // YUYV YUYV(0)
+ "punpckhbw %%mm3, %%mm4 \n\t" // YUYV YUYV(4)
+ "punpcklbw %%mm5, %%mm2 \n\t" // YUYV YUYV(8)
+ "punpckhbw %%mm5, %%mm6 \n\t" // YUYV YUYV(12)
+
+ MOVNTQ" %%mm0, (%0, %%"REG_a", 4)\n\t"
+ MOVNTQ" %%mm4, 8(%0, %%"REG_a", 4)\n\t"
+ MOVNTQ" %%mm2, 16(%0, %%"REG_a", 4)\n\t"
+ MOVNTQ" %%mm6, 24(%0, %%"REG_a", 4)\n\t"
+
+ "add $8, %%"REG_a" \n\t"
+ "cmp %4, %%"REG_a" \n\t"
+ " jb 1b \n\t"
+ ::"r"(dst), "r"(ysrc), "r"(usrc), "r"(vsrc), "g" (chromWidth)
+ : "%"REG_a
+ );
+#else
+//FIXME adapt the alpha asm code from yv12->yuy2
+
+#if __WORDSIZE >= 64
+ int i;
+ uint64_t *ldst = (uint64_t *) dst;
+ const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
+ for(i = 0; i < chromWidth; i += 2){
+ uint64_t k, l;
+ k = uc[0] + (yc[0] << 8) +
+ (vc[0] << 16) + (yc[1] << 24);
+ l = uc[1] + (yc[2] << 8) +
+ (vc[1] << 16) + (yc[3] << 24);
+ *ldst++ = k + (l << 32);
+ yc += 4;
+ uc += 2;
+ vc += 2;
+ }
+
+#else
+ int i, *idst = (int32_t *) dst;
+ const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
+ for(i = 0; i < chromWidth; i++){
+#ifdef WORDS_BIGENDIAN
+ *idst++ = (uc[0] << 24)+ (yc[0] << 16) +
+ (vc[0] << 8) + (yc[1] << 0);
+#else
+ *idst++ = uc[0] + (yc[0] << 8) +
+ (vc[0] << 16) + (yc[1] << 24);
+#endif
+ yc += 2;
+ uc++;
+ vc++;
+ }
+#endif
+#endif
+ if((y&(vertLumPerChroma-1))==(vertLumPerChroma-1) )
+ {
+ usrc += chromStride;
+ vsrc += chromStride;
+ }
+ ysrc += lumStride;
+ dst += dstStride;
+ }
+#ifdef HAVE_MMX
+asm( EMMS" \n\t"
+ SFENCE" \n\t"
+ :::"memory");
+#endif
+}
+
+/**
+ *
+ * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
+ * problem for anyone then tell me, and ill fix it)
+ */
+static inline void RENAME(yv12touyvy)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
+ long width, long height,
+ long lumStride, long chromStride, long dstStride)
+{
+ //FIXME interpolate chroma
+ RENAME(yuvPlanartouyvy)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 2);
+}
+
+/**
+ *
+ * width should be a multiple of 16
+ */
+static inline void RENAME(yuv422ptoyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
+ long width, long height,
+ long lumStride, long chromStride, long dstStride)
+{
+ RENAME(yuvPlanartoyuy2)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 1);
+}
+
+/**
+ *
+ * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
+ * problem for anyone then tell me, and ill fix it)
+ */
+static inline void RENAME(yuy2toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
+ long width, long height,
+ long lumStride, long chromStride, long srcStride)
+{
+ long y;
+ const long chromWidth= width>>1;
+ for(y=0; y<height; y+=2)
+ {
+#ifdef HAVE_MMX
+ asm volatile(
+ "xor %%"REG_a", %%"REG_a" \n\t"
+ "pcmpeqw %%mm7, %%mm7 \n\t"
+ "psrlw $8, %%mm7 \n\t" // FF,00,FF,00...
+ ASMALIGN(4)
+ "1: \n\t"
+ PREFETCH" 64(%0, %%"REG_a", 4) \n\t"
+ "movq (%0, %%"REG_a", 4), %%mm0 \n\t" // YUYV YUYV(0)
+ "movq 8(%0, %%"REG_a", 4), %%mm1\n\t" // YUYV YUYV(4)
+ "movq %%mm0, %%mm2 \n\t" // YUYV YUYV(0)
+ "movq %%mm1, %%mm3 \n\t" // YUYV YUYV(4)
+ "psrlw $8, %%mm0 \n\t" // U0V0 U0V0(0)
+ "psrlw $8, %%mm1 \n\t" // U0V0 U0V0(4)
+ "pand %%mm7, %%mm2 \n\t" // Y0Y0 Y0Y0(0)
+ "pand %%mm7, %%mm3 \n\t" // Y0Y0 Y0Y0(4)
+ "packuswb %%mm1, %%mm0 \n\t" // UVUV UVUV(0)
+ "packuswb %%mm3, %%mm2 \n\t" // YYYY YYYY(0)
+
+ MOVNTQ" %%mm2, (%1, %%"REG_a", 2)\n\t"
+
+ "movq 16(%0, %%"REG_a", 4), %%mm1\n\t" // YUYV YUYV(8)
+ "movq 24(%0, %%"REG_a", 4), %%mm2\n\t" // YUYV YUYV(12)
+ "movq %%mm1, %%mm3 \n\t" // YUYV YUYV(8)
+ "movq %%mm2, %%mm4 \n\t" // YUYV YUYV(12)
+ "psrlw $8, %%mm1 \n\t" // U0V0 U0V0(8)
+ "psrlw $8, %%mm2 \n\t" // U0V0 U0V0(12)
+ "pand %%mm7, %%mm3 \n\t" // Y0Y0 Y0Y0(8)
+ "pand %%mm7, %%mm4 \n\t" // Y0Y0 Y0Y0(12)
+ "packuswb %%mm2, %%mm1 \n\t" // UVUV UVUV(8)
+ "packuswb %%mm4, %%mm3 \n\t" // YYYY YYYY(8)
+
+ MOVNTQ" %%mm3, 8(%1, %%"REG_a", 2)\n\t"
+
+ "movq %%mm0, %%mm2 \n\t" // UVUV UVUV(0)
+ "movq %%mm1, %%mm3 \n\t" // UVUV UVUV(8)
+ "psrlw $8, %%mm0 \n\t" // V0V0 V0V0(0)
+ "psrlw $8, %%mm1 \n\t" // V0V0 V0V0(8)
+ "pand %%mm7, %%mm2 \n\t" // U0U0 U0U0(0)
+ "pand %%mm7, %%mm3 \n\t" // U0U0 U0U0(8)
+ "packuswb %%mm1, %%mm0 \n\t" // VVVV VVVV(0)
+ "packuswb %%mm3, %%mm2 \n\t" // UUUU UUUU(0)
+
+ MOVNTQ" %%mm0, (%3, %%"REG_a") \n\t"
+ MOVNTQ" %%mm2, (%2, %%"REG_a") \n\t"
+
+ "add $8, %%"REG_a" \n\t"
+ "cmp %4, %%"REG_a" \n\t"
+ " jb 1b \n\t"
+ ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
+ : "memory", "%"REG_a
+ );
+
+ ydst += lumStride;
+ src += srcStride;
+
+ asm volatile(
+ "xor %%"REG_a", %%"REG_a" \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ PREFETCH" 64(%0, %%"REG_a", 4) \n\t"
+ "movq (%0, %%"REG_a", 4), %%mm0 \n\t" // YUYV YUYV(0)
+ "movq 8(%0, %%"REG_a", 4), %%mm1\n\t" // YUYV YUYV(4)
+ "movq 16(%0, %%"REG_a", 4), %%mm2\n\t" // YUYV YUYV(8)
+ "movq 24(%0, %%"REG_a", 4), %%mm3\n\t" // YUYV YUYV(12)
+ "pand %%mm7, %%mm0 \n\t" // Y0Y0 Y0Y0(0)
+ "pand %%mm7, %%mm1 \n\t" // Y0Y0 Y0Y0(4)
+ "pand %%mm7, %%mm2 \n\t" // Y0Y0 Y0Y0(8)
+ "pand %%mm7, %%mm3 \n\t" // Y0Y0 Y0Y0(12)
+ "packuswb %%mm1, %%mm0 \n\t" // YYYY YYYY(0)
+ "packuswb %%mm3, %%mm2 \n\t" // YYYY YYYY(8)
+
+ MOVNTQ" %%mm0, (%1, %%"REG_a", 2)\n\t"
+ MOVNTQ" %%mm2, 8(%1, %%"REG_a", 2)\n\t"
+
+ "add $8, %%"REG_a" \n\t"
+ "cmp %4, %%"REG_a" \n\t"
+ " jb 1b \n\t"
+
+ ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
+ : "memory", "%"REG_a
+ );
+#else
+ long i;
+ for(i=0; i<chromWidth; i++)
+ {
+ ydst[2*i+0] = src[4*i+0];
+ udst[i] = src[4*i+1];
+ ydst[2*i+1] = src[4*i+2];
+ vdst[i] = src[4*i+3];
+ }
+ ydst += lumStride;
+ src += srcStride;
+
+ for(i=0; i<chromWidth; i++)
+ {
+ ydst[2*i+0] = src[4*i+0];
+ ydst[2*i+1] = src[4*i+2];
+ }
+#endif
+ udst += chromStride;
+ vdst += chromStride;
+ ydst += lumStride;
+ src += srcStride;
+ }
+#ifdef HAVE_MMX
+asm volatile( EMMS" \n\t"
+ SFENCE" \n\t"
+ :::"memory");
+#endif
+}
+
+static inline void RENAME(yvu9toyv12)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc,
+ uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
+ long width, long height, long lumStride, long chromStride)
+{
+ /* Y Plane */
+ memcpy(ydst, ysrc, width*height);
+
+ /* XXX: implement upscaling for U,V */
+}
+
+static inline void RENAME(planar2x)(const uint8_t *src, uint8_t *dst, long srcWidth, long srcHeight, long srcStride, long dstStride)
+{
+ long x,y;
+
+ dst[0]= src[0];
+
+ // first line
+ for(x=0; x<srcWidth-1; x++){
+ dst[2*x+1]= (3*src[x] + src[x+1])>>2;
+ dst[2*x+2]= ( src[x] + 3*src[x+1])>>2;
+ }
+ dst[2*srcWidth-1]= src[srcWidth-1];
+
+ dst+= dstStride;
+
+ for(y=1; y<srcHeight; y++){
+#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ const long mmxSize= srcWidth&~15;
+ asm volatile(
+ "mov %4, %%"REG_a" \n\t"
+ "1: \n\t"
+ "movq (%0, %%"REG_a"), %%mm0 \n\t"
+ "movq (%1, %%"REG_a"), %%mm1 \n\t"
+ "movq 1(%0, %%"REG_a"), %%mm2 \n\t"
+ "movq 1(%1, %%"REG_a"), %%mm3 \n\t"
+ "movq -1(%0, %%"REG_a"), %%mm4 \n\t"
+ "movq -1(%1, %%"REG_a"), %%mm5 \n\t"
+ PAVGB" %%mm0, %%mm5 \n\t"
+ PAVGB" %%mm0, %%mm3 \n\t"
+ PAVGB" %%mm0, %%mm5 \n\t"
+ PAVGB" %%mm0, %%mm3 \n\t"
+ PAVGB" %%mm1, %%mm4 \n\t"
+ PAVGB" %%mm1, %%mm2 \n\t"
+ PAVGB" %%mm1, %%mm4 \n\t"
+ PAVGB" %%mm1, %%mm2 \n\t"
+ "movq %%mm5, %%mm7 \n\t"
+ "movq %%mm4, %%mm6 \n\t"
+ "punpcklbw %%mm3, %%mm5 \n\t"
+ "punpckhbw %%mm3, %%mm7 \n\t"
+ "punpcklbw %%mm2, %%mm4 \n\t"
+ "punpckhbw %%mm2, %%mm6 \n\t"
+#if 1
+ MOVNTQ" %%mm5, (%2, %%"REG_a", 2)\n\t"
+ MOVNTQ" %%mm7, 8(%2, %%"REG_a", 2)\n\t"
+ MOVNTQ" %%mm4, (%3, %%"REG_a", 2)\n\t"
+ MOVNTQ" %%mm6, 8(%3, %%"REG_a", 2)\n\t"
+#else
+ "movq %%mm5, (%2, %%"REG_a", 2) \n\t"
+ "movq %%mm7, 8(%2, %%"REG_a", 2)\n\t"
+ "movq %%mm4, (%3, %%"REG_a", 2) \n\t"
+ "movq %%mm6, 8(%3, %%"REG_a", 2)\n\t"
+#endif
+ "add $8, %%"REG_a" \n\t"
+ " js 1b \n\t"
+ :: "r" (src + mmxSize ), "r" (src + srcStride + mmxSize ),
+ "r" (dst + mmxSize*2), "r" (dst + dstStride + mmxSize*2),
+ "g" (-mmxSize)
+ : "%"REG_a
+
+ );
+#else
+ const long mmxSize=1;
+#endif
+ dst[0 ]= (3*src[0] + src[srcStride])>>2;
+ dst[dstStride]= ( src[0] + 3*src[srcStride])>>2;
+
+ for(x=mmxSize-1; x<srcWidth-1; x++){
+ dst[2*x +1]= (3*src[x+0] + src[x+srcStride+1])>>2;
+ dst[2*x+dstStride+2]= ( src[x+0] + 3*src[x+srcStride+1])>>2;
+ dst[2*x+dstStride+1]= ( src[x+1] + 3*src[x+srcStride ])>>2;
+ dst[2*x +2]= (3*src[x+1] + src[x+srcStride ])>>2;
+ }
+ dst[srcWidth*2 -1 ]= (3*src[srcWidth-1] + src[srcWidth-1 + srcStride])>>2;
+ dst[srcWidth*2 -1 + dstStride]= ( src[srcWidth-1] + 3*src[srcWidth-1 + srcStride])>>2;
+
+ dst+=dstStride*2;
+ src+=srcStride;
+ }
+
+ // last line
+#if 1
+ dst[0]= src[0];
+
+ for(x=0; x<srcWidth-1; x++){
+ dst[2*x+1]= (3*src[x] + src[x+1])>>2;
+ dst[2*x+2]= ( src[x] + 3*src[x+1])>>2;
+ }
+ dst[2*srcWidth-1]= src[srcWidth-1];
+#else
+ for(x=0; x<srcWidth; x++){
+ dst[2*x+0]=
+ dst[2*x+1]= src[x];
+ }
+#endif
+
+#ifdef HAVE_MMX
+asm volatile( EMMS" \n\t"
+ SFENCE" \n\t"
+ :::"memory");
+#endif
+}
+
+/**
+ *
+ * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
+ * problem for anyone then tell me, and ill fix it)
+ * chrominance data is only taken from every secound line others are ignored FIXME write HQ version
+ */
+static inline void RENAME(uyvytoyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
+ long width, long height,
+ long lumStride, long chromStride, long srcStride)
+{
+ long y;
+ const long chromWidth= width>>1;
+ for(y=0; y<height; y+=2)
+ {
+#ifdef HAVE_MMX
+ asm volatile(
+ "xorl %%eax, %%eax \n\t"
+ "pcmpeqw %%mm7, %%mm7 \n\t"
+ "psrlw $8, %%mm7 \n\t" // FF,00,FF,00...
+ ASMALIGN(4)
+ "1: \n\t"
+ PREFETCH" 64(%0, %%eax, 4) \n\t"
+ "movq (%0, %%eax, 4), %%mm0 \n\t" // UYVY UYVY(0)
+ "movq 8(%0, %%eax, 4), %%mm1 \n\t" // UYVY UYVY(4)
+ "movq %%mm0, %%mm2 \n\t" // UYVY UYVY(0)
+ "movq %%mm1, %%mm3 \n\t" // UYVY UYVY(4)
+ "pand %%mm7, %%mm0 \n\t" // U0V0 U0V0(0)
+ "pand %%mm7, %%mm1 \n\t" // U0V0 U0V0(4)
+ "psrlw $8, %%mm2 \n\t" // Y0Y0 Y0Y0(0)
+ "psrlw $8, %%mm3 \n\t" // Y0Y0 Y0Y0(4)
+ "packuswb %%mm1, %%mm0 \n\t" // UVUV UVUV(0)
+ "packuswb %%mm3, %%mm2 \n\t" // YYYY YYYY(0)
+
+ MOVNTQ" %%mm2, (%1, %%eax, 2) \n\t"
+
+ "movq 16(%0, %%eax, 4), %%mm1 \n\t" // UYVY UYVY(8)
+ "movq 24(%0, %%eax, 4), %%mm2 \n\t" // UYVY UYVY(12)
+ "movq %%mm1, %%mm3 \n\t" // UYVY UYVY(8)
+ "movq %%mm2, %%mm4 \n\t" // UYVY UYVY(12)
+ "pand %%mm7, %%mm1 \n\t" // U0V0 U0V0(8)
+ "pand %%mm7, %%mm2 \n\t" // U0V0 U0V0(12)
+ "psrlw $8, %%mm3 \n\t" // Y0Y0 Y0Y0(8)
+ "psrlw $8, %%mm4 \n\t" // Y0Y0 Y0Y0(12)
+ "packuswb %%mm2, %%mm1 \n\t" // UVUV UVUV(8)
+ "packuswb %%mm4, %%mm3 \n\t" // YYYY YYYY(8)
+
+ MOVNTQ" %%mm3, 8(%1, %%eax, 2) \n\t"
+
+ "movq %%mm0, %%mm2 \n\t" // UVUV UVUV(0)
+ "movq %%mm1, %%mm3 \n\t" // UVUV UVUV(8)
+ "psrlw $8, %%mm0 \n\t" // V0V0 V0V0(0)
+ "psrlw $8, %%mm1 \n\t" // V0V0 V0V0(8)
+ "pand %%mm7, %%mm2 \n\t" // U0U0 U0U0(0)
+ "pand %%mm7, %%mm3 \n\t" // U0U0 U0U0(8)
+ "packuswb %%mm1, %%mm0 \n\t" // VVVV VVVV(0)
+ "packuswb %%mm3, %%mm2 \n\t" // UUUU UUUU(0)
+
+ MOVNTQ" %%mm0, (%3, %%eax) \n\t"
+ MOVNTQ" %%mm2, (%2, %%eax) \n\t"
+
+ "addl $8, %%eax \n\t"
+ "cmpl %4, %%eax \n\t"
+ " jb 1b \n\t"
+ ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
+ : "memory", "%eax"
+ );
+
+ ydst += lumStride;
+ src += srcStride;
+
+ asm volatile(
+ "xorl %%eax, %%eax \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ PREFETCH" 64(%0, %%eax, 4) \n\t"
+ "movq (%0, %%eax, 4), %%mm0 \n\t" // YUYV YUYV(0)
+ "movq 8(%0, %%eax, 4), %%mm1 \n\t" // YUYV YUYV(4)
+ "movq 16(%0, %%eax, 4), %%mm2 \n\t" // YUYV YUYV(8)
+ "movq 24(%0, %%eax, 4), %%mm3 \n\t" // YUYV YUYV(12)
+ "psrlw $8, %%mm0 \n\t" // Y0Y0 Y0Y0(0)
+ "psrlw $8, %%mm1 \n\t" // Y0Y0 Y0Y0(4)
+ "psrlw $8, %%mm2 \n\t" // Y0Y0 Y0Y0(8)
+ "psrlw $8, %%mm3 \n\t" // Y0Y0 Y0Y0(12)
+ "packuswb %%mm1, %%mm0 \n\t" // YYYY YYYY(0)
+ "packuswb %%mm3, %%mm2 \n\t" // YYYY YYYY(8)
+
+ MOVNTQ" %%mm0, (%1, %%eax, 2) \n\t"
+ MOVNTQ" %%mm2, 8(%1, %%eax, 2) \n\t"
+
+ "addl $8, %%eax \n\t"
+ "cmpl %4, %%eax \n\t"
+ " jb 1b \n\t"
+
+ ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
+ : "memory", "%eax"
+ );
+#else
+ long i;
+ for(i=0; i<chromWidth; i++)
+ {
+ udst[i] = src[4*i+0];
+ ydst[2*i+0] = src[4*i+1];
+ vdst[i] = src[4*i+2];
+ ydst[2*i+1] = src[4*i+3];
+ }
+ ydst += lumStride;
+ src += srcStride;
+
+ for(i=0; i<chromWidth; i++)
+ {
+ ydst[2*i+0] = src[4*i+1];
+ ydst[2*i+1] = src[4*i+3];
+ }
+#endif
+ udst += chromStride;
+ vdst += chromStride;
+ ydst += lumStride;
+ src += srcStride;
+ }
+#ifdef HAVE_MMX
+asm volatile( EMMS" \n\t"
+ SFENCE" \n\t"
+ :::"memory");
+#endif
+}
+
+/**
+ *
+ * height should be a multiple of 2 and width should be a multiple of 2 (if this is a
+ * problem for anyone then tell me, and ill fix it)
+ * chrominance data is only taken from every secound line others are ignored in the C version FIXME write HQ version
+ */
+static inline void RENAME(rgb24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
+ long width, long height,
+ long lumStride, long chromStride, long srcStride)
+{
+ long y;
+ const long chromWidth= width>>1;
+#ifdef HAVE_MMX
+ for(y=0; y<height-2; y+=2)
+ {
+ long i;
+ for(i=0; i<2; i++)
+ {
+ asm volatile(
+ "mov %2, %%"REG_a" \n\t"
+ "movq "MANGLE(bgr2YCoeff)", %%mm6 \n\t"
+ "movq "MANGLE(w1111)", %%mm5 \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+ "lea (%%"REG_a", %%"REG_a", 2), %%"REG_d"\n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ PREFETCH" 64(%0, %%"REG_d") \n\t"
+ "movd (%0, %%"REG_d"), %%mm0 \n\t"
+ "movd 3(%0, %%"REG_d"), %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "movd 6(%0, %%"REG_d"), %%mm2 \n\t"
+ "movd 9(%0, %%"REG_d"), %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm3 \n\t"
+ "pmaddwd %%mm6, %%mm0 \n\t"
+ "pmaddwd %%mm6, %%mm1 \n\t"
+ "pmaddwd %%mm6, %%mm2 \n\t"
+ "pmaddwd %%mm6, %%mm3 \n\t"
+#ifndef FAST_BGR2YV12
+ "psrad $8, %%mm0 \n\t"
+ "psrad $8, %%mm1 \n\t"
+ "psrad $8, %%mm2 \n\t"
+ "psrad $8, %%mm3 \n\t"
+#endif
+ "packssdw %%mm1, %%mm0 \n\t"
+ "packssdw %%mm3, %%mm2 \n\t"
+ "pmaddwd %%mm5, %%mm0 \n\t"
+ "pmaddwd %%mm5, %%mm2 \n\t"
+ "packssdw %%mm2, %%mm0 \n\t"
+ "psraw $7, %%mm0 \n\t"
+
+ "movd 12(%0, %%"REG_d"), %%mm4 \n\t"
+ "movd 15(%0, %%"REG_d"), %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm4 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "movd 18(%0, %%"REG_d"), %%mm2 \n\t"
+ "movd 21(%0, %%"REG_d"), %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm3 \n\t"
+ "pmaddwd %%mm6, %%mm4 \n\t"
+ "pmaddwd %%mm6, %%mm1 \n\t"
+ "pmaddwd %%mm6, %%mm2 \n\t"
+ "pmaddwd %%mm6, %%mm3 \n\t"
+#ifndef FAST_BGR2YV12
+ "psrad $8, %%mm4 \n\t"
+ "psrad $8, %%mm1 \n\t"
+ "psrad $8, %%mm2 \n\t"
+ "psrad $8, %%mm3 \n\t"
+#endif
+ "packssdw %%mm1, %%mm4 \n\t"
+ "packssdw %%mm3, %%mm2 \n\t"
+ "pmaddwd %%mm5, %%mm4 \n\t"
+ "pmaddwd %%mm5, %%mm2 \n\t"
+ "add $24, %%"REG_d" \n\t"
+ "packssdw %%mm2, %%mm4 \n\t"
+ "psraw $7, %%mm4 \n\t"
+
+ "packuswb %%mm4, %%mm0 \n\t"
+ "paddusb "MANGLE(bgr2YOffset)", %%mm0 \n\t"
+
+ MOVNTQ" %%mm0, (%1, %%"REG_a") \n\t"
+ "add $8, %%"REG_a" \n\t"
+ " js 1b \n\t"
+ : : "r" (src+width*3), "r" (ydst+width), "g" (-width)
+ : "%"REG_a, "%"REG_d
+ );
+ ydst += lumStride;
+ src += srcStride;
+ }
+ src -= srcStride*2;
+ asm volatile(
+ "mov %4, %%"REG_a" \n\t"
+ "movq "MANGLE(w1111)", %%mm5 \n\t"
+ "movq "MANGLE(bgr2UCoeff)", %%mm6 \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+ "lea (%%"REG_a", %%"REG_a", 2), %%"REG_d"\n\t"
+ "add %%"REG_d", %%"REG_d" \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ PREFETCH" 64(%0, %%"REG_d") \n\t"
+ PREFETCH" 64(%1, %%"REG_d") \n\t"
+#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ "movq (%0, %%"REG_d"), %%mm0 \n\t"
+ "movq (%1, %%"REG_d"), %%mm1 \n\t"
+ "movq 6(%0, %%"REG_d"), %%mm2 \n\t"
+ "movq 6(%1, %%"REG_d"), %%mm3 \n\t"
+ PAVGB" %%mm1, %%mm0 \n\t"
+ PAVGB" %%mm3, %%mm2 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "movq %%mm2, %%mm3 \n\t"
+ "psrlq $24, %%mm0 \n\t"
+ "psrlq $24, %%mm2 \n\t"
+ PAVGB" %%mm1, %%mm0 \n\t"
+ PAVGB" %%mm3, %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+#else
+ "movd (%0, %%"REG_d"), %%mm0 \n\t"
+ "movd (%1, %%"REG_d"), %%mm1 \n\t"
+ "movd 3(%0, %%"REG_d"), %%mm2 \n\t"
+ "movd 3(%1, %%"REG_d"), %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm3 \n\t"
+ "paddw %%mm1, %%mm0 \n\t"
+ "paddw %%mm3, %%mm2 \n\t"
+ "paddw %%mm2, %%mm0 \n\t"
+ "movd 6(%0, %%"REG_d"), %%mm4 \n\t"
+ "movd 6(%1, %%"REG_d"), %%mm1 \n\t"
+ "movd 9(%0, %%"REG_d"), %%mm2 \n\t"
+ "movd 9(%1, %%"REG_d"), %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm4 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm3 \n\t"
+ "paddw %%mm1, %%mm4 \n\t"
+ "paddw %%mm3, %%mm2 \n\t"
+ "paddw %%mm4, %%mm2 \n\t"
+ "psrlw $2, %%mm0 \n\t"
+ "psrlw $2, %%mm2 \n\t"
+#endif
+ "movq "MANGLE(bgr2VCoeff)", %%mm1 \n\t"
+ "movq "MANGLE(bgr2VCoeff)", %%mm3 \n\t"
+
+ "pmaddwd %%mm0, %%mm1 \n\t"
+ "pmaddwd %%mm2, %%mm3 \n\t"
+ "pmaddwd %%mm6, %%mm0 \n\t"
+ "pmaddwd %%mm6, %%mm2 \n\t"
+#ifndef FAST_BGR2YV12
+ "psrad $8, %%mm0 \n\t"
+ "psrad $8, %%mm1 \n\t"
+ "psrad $8, %%mm2 \n\t"
+ "psrad $8, %%mm3 \n\t"
+#endif
+ "packssdw %%mm2, %%mm0 \n\t"
+ "packssdw %%mm3, %%mm1 \n\t"
+ "pmaddwd %%mm5, %%mm0 \n\t"
+ "pmaddwd %%mm5, %%mm1 \n\t"
+ "packssdw %%mm1, %%mm0 \n\t" // V1 V0 U1 U0
+ "psraw $7, %%mm0 \n\t"
+
+#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ "movq 12(%0, %%"REG_d"), %%mm4 \n\t"
+ "movq 12(%1, %%"REG_d"), %%mm1 \n\t"
+ "movq 18(%0, %%"REG_d"), %%mm2 \n\t"
+ "movq 18(%1, %%"REG_d"), %%mm3 \n\t"
+ PAVGB" %%mm1, %%mm4 \n\t"
+ PAVGB" %%mm3, %%mm2 \n\t"
+ "movq %%mm4, %%mm1 \n\t"
+ "movq %%mm2, %%mm3 \n\t"
+ "psrlq $24, %%mm4 \n\t"
+ "psrlq $24, %%mm2 \n\t"
+ PAVGB" %%mm1, %%mm4 \n\t"
+ PAVGB" %%mm3, %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm4 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+#else
+ "movd 12(%0, %%"REG_d"), %%mm4 \n\t"
+ "movd 12(%1, %%"REG_d"), %%mm1 \n\t"
+ "movd 15(%0, %%"REG_d"), %%mm2 \n\t"
+ "movd 15(%1, %%"REG_d"), %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm4 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm3 \n\t"
+ "paddw %%mm1, %%mm4 \n\t"
+ "paddw %%mm3, %%mm2 \n\t"
+ "paddw %%mm2, %%mm4 \n\t"
+ "movd 18(%0, %%"REG_d"), %%mm5 \n\t"
+ "movd 18(%1, %%"REG_d"), %%mm1 \n\t"
+ "movd 21(%0, %%"REG_d"), %%mm2 \n\t"
+ "movd 21(%1, %%"REG_d"), %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm5 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm3 \n\t"
+ "paddw %%mm1, %%mm5 \n\t"
+ "paddw %%mm3, %%mm2 \n\t"
+ "paddw %%mm5, %%mm2 \n\t"
+ "movq "MANGLE(w1111)", %%mm5 \n\t"
+ "psrlw $2, %%mm4 \n\t"
+ "psrlw $2, %%mm2 \n\t"
+#endif
+ "movq "MANGLE(bgr2VCoeff)", %%mm1 \n\t"
+ "movq "MANGLE(bgr2VCoeff)", %%mm3 \n\t"
+
+ "pmaddwd %%mm4, %%mm1 \n\t"
+ "pmaddwd %%mm2, %%mm3 \n\t"
+ "pmaddwd %%mm6, %%mm4 \n\t"
+ "pmaddwd %%mm6, %%mm2 \n\t"
+#ifndef FAST_BGR2YV12
+ "psrad $8, %%mm4 \n\t"
+ "psrad $8, %%mm1 \n\t"
+ "psrad $8, %%mm2 \n\t"
+ "psrad $8, %%mm3 \n\t"
+#endif
+ "packssdw %%mm2, %%mm4 \n\t"
+ "packssdw %%mm3, %%mm1 \n\t"
+ "pmaddwd %%mm5, %%mm4 \n\t"
+ "pmaddwd %%mm5, %%mm1 \n\t"
+ "add $24, %%"REG_d" \n\t"
+ "packssdw %%mm1, %%mm4 \n\t" // V3 V2 U3 U2
+ "psraw $7, %%mm4 \n\t"
+
+ "movq %%mm0, %%mm1 \n\t"
+ "punpckldq %%mm4, %%mm0 \n\t"
+ "punpckhdq %%mm4, %%mm1 \n\t"
+ "packsswb %%mm1, %%mm0 \n\t"
+ "paddb "MANGLE(bgr2UVOffset)", %%mm0 \n\t"
+ "movd %%mm0, (%2, %%"REG_a") \n\t"
+ "punpckhdq %%mm0, %%mm0 \n\t"
+ "movd %%mm0, (%3, %%"REG_a") \n\t"
+ "add $4, %%"REG_a" \n\t"
+ " js 1b \n\t"
+ : : "r" (src+chromWidth*6), "r" (src+srcStride+chromWidth*6), "r" (udst+chromWidth), "r" (vdst+chromWidth), "g" (-chromWidth)
+ : "%"REG_a, "%"REG_d
+ );
+
+ udst += chromStride;
+ vdst += chromStride;
+ src += srcStride*2;
+ }
+
+ asm volatile( EMMS" \n\t"
+ SFENCE" \n\t"
+ :::"memory");
+#else
+ y=0;
+#endif
+ for(; y<height; y+=2)
+ {
+ long i;
+ for(i=0; i<chromWidth; i++)
+ {
+ unsigned int b= src[6*i+0];
+ unsigned int g= src[6*i+1];
+ unsigned int r= src[6*i+2];
+
+ unsigned int Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
+ unsigned int V = ((RV*r + GV*g + BV*b)>>RGB2YUV_SHIFT) + 128;
+ unsigned int U = ((RU*r + GU*g + BU*b)>>RGB2YUV_SHIFT) + 128;
+
+ udst[i] = U;
+ vdst[i] = V;
+ ydst[2*i] = Y;
+
+ b= src[6*i+3];
+ g= src[6*i+4];
+ r= src[6*i+5];
+
+ Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
+ ydst[2*i+1] = Y;
+ }
+ ydst += lumStride;
+ src += srcStride;
+
+ for(i=0; i<chromWidth; i++)
+ {
+ unsigned int b= src[6*i+0];
+ unsigned int g= src[6*i+1];
+ unsigned int r= src[6*i+2];
+
+ unsigned int Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
+
+ ydst[2*i] = Y;
+
+ b= src[6*i+3];
+ g= src[6*i+4];
+ r= src[6*i+5];
+
+ Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
+ ydst[2*i+1] = Y;
+ }
+ udst += chromStride;
+ vdst += chromStride;
+ ydst += lumStride;
+ src += srcStride;
+ }
+}
+
+void RENAME(interleaveBytes)(uint8_t *src1, uint8_t *src2, uint8_t *dest,
+ long width, long height, long src1Stride,
+ long src2Stride, long dstStride){
+ long h;
+
+ for(h=0; h < height; h++)
+ {
+ long w;
+
+#ifdef HAVE_MMX
+#ifdef HAVE_SSE2
+ asm(
+ "xor %%"REG_a", %%"REG_a" \n\t"
+ "1: \n\t"
+ PREFETCH" 64(%1, %%"REG_a") \n\t"
+ PREFETCH" 64(%2, %%"REG_a") \n\t"
+ "movdqa (%1, %%"REG_a"), %%xmm0 \n\t"
+ "movdqa (%1, %%"REG_a"), %%xmm1 \n\t"
+ "movdqa (%2, %%"REG_a"), %%xmm2 \n\t"
+ "punpcklbw %%xmm2, %%xmm0 \n\t"
+ "punpckhbw %%xmm2, %%xmm1 \n\t"
+ "movntdq %%xmm0, (%0, %%"REG_a", 2)\n\t"
+ "movntdq %%xmm1, 16(%0, %%"REG_a", 2)\n\t"
+ "add $16, %%"REG_a" \n\t"
+ "cmp %3, %%"REG_a" \n\t"
+ " jb 1b \n\t"
+ ::"r"(dest), "r"(src1), "r"(src2), "r" (width-15)
+ : "memory", "%"REG_a""
+ );
+#else
+ asm(
+ "xor %%"REG_a", %%"REG_a" \n\t"
+ "1: \n\t"
+ PREFETCH" 64(%1, %%"REG_a") \n\t"
+ PREFETCH" 64(%2, %%"REG_a") \n\t"
+ "movq (%1, %%"REG_a"), %%mm0 \n\t"
+ "movq 8(%1, %%"REG_a"), %%mm2 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "movq %%mm2, %%mm3 \n\t"
+ "movq (%2, %%"REG_a"), %%mm4 \n\t"
+ "movq 8(%2, %%"REG_a"), %%mm5 \n\t"
+ "punpcklbw %%mm4, %%mm0 \n\t"
+ "punpckhbw %%mm4, %%mm1 \n\t"
+ "punpcklbw %%mm5, %%mm2 \n\t"
+ "punpckhbw %%mm5, %%mm3 \n\t"
+ MOVNTQ" %%mm0, (%0, %%"REG_a", 2)\n\t"
+ MOVNTQ" %%mm1, 8(%0, %%"REG_a", 2)\n\t"
+ MOVNTQ" %%mm2, 16(%0, %%"REG_a", 2)\n\t"
+ MOVNTQ" %%mm3, 24(%0, %%"REG_a", 2)\n\t"
+ "add $16, %%"REG_a" \n\t"
+ "cmp %3, %%"REG_a" \n\t"
+ " jb 1b \n\t"
+ ::"r"(dest), "r"(src1), "r"(src2), "r" (width-15)
+ : "memory", "%"REG_a
+ );
+#endif
+ for(w= (width&(~15)); w < width; w++)
+ {
+ dest[2*w+0] = src1[w];
+ dest[2*w+1] = src2[w];
+ }
+#else
+ for(w=0; w < width; w++)
+ {
+ dest[2*w+0] = src1[w];
+ dest[2*w+1] = src2[w];
+ }
+#endif
+ dest += dstStride;
+ src1 += src1Stride;
+ src2 += src2Stride;
+ }
+#ifdef HAVE_MMX
+ asm(
+ EMMS" \n\t"
+ SFENCE" \n\t"
+ ::: "memory"
+ );
+#endif
+}
+
+static inline void RENAME(vu9_to_vu12)(const uint8_t *src1, const uint8_t *src2,
+ uint8_t *dst1, uint8_t *dst2,
+ long width, long height,
+ long srcStride1, long srcStride2,
+ long dstStride1, long dstStride2)
+{
+ long y,x,w,h;
+ w=width/2; h=height/2;
+#ifdef HAVE_MMX
+ asm volatile(
+ PREFETCH" %0\n\t"
+ PREFETCH" %1\n\t"
+ ::"m"(*(src1+srcStride1)),"m"(*(src2+srcStride2)):"memory");
+#endif
+ for(y=0;y<h;y++){
+ const uint8_t* s1=src1+srcStride1*(y>>1);
+ uint8_t* d=dst1+dstStride1*y;
+ x=0;
+#ifdef HAVE_MMX
+ for(;x<w-31;x+=32)
+ {
+ asm volatile(
+ PREFETCH" 32%1\n\t"
+ "movq %1, %%mm0\n\t"
+ "movq 8%1, %%mm2\n\t"
+ "movq 16%1, %%mm4\n\t"
+ "movq 24%1, %%mm6\n\t"
+ "movq %%mm0, %%mm1\n\t"
+ "movq %%mm2, %%mm3\n\t"
+ "movq %%mm4, %%mm5\n\t"
+ "movq %%mm6, %%mm7\n\t"
+ "punpcklbw %%mm0, %%mm0\n\t"
+ "punpckhbw %%mm1, %%mm1\n\t"
+ "punpcklbw %%mm2, %%mm2\n\t"
+ "punpckhbw %%mm3, %%mm3\n\t"
+ "punpcklbw %%mm4, %%mm4\n\t"
+ "punpckhbw %%mm5, %%mm5\n\t"
+ "punpcklbw %%mm6, %%mm6\n\t"
+ "punpckhbw %%mm7, %%mm7\n\t"
+ MOVNTQ" %%mm0, %0\n\t"
+ MOVNTQ" %%mm1, 8%0\n\t"
+ MOVNTQ" %%mm2, 16%0\n\t"
+ MOVNTQ" %%mm3, 24%0\n\t"
+ MOVNTQ" %%mm4, 32%0\n\t"
+ MOVNTQ" %%mm5, 40%0\n\t"
+ MOVNTQ" %%mm6, 48%0\n\t"
+ MOVNTQ" %%mm7, 56%0"
+ :"=m"(d[2*x])
+ :"m"(s1[x])
+ :"memory");
+ }
+#endif
+ for(;x<w;x++) d[2*x]=d[2*x+1]=s1[x];
+ }
+ for(y=0;y<h;y++){
+ const uint8_t* s2=src2+srcStride2*(y>>1);
+ uint8_t* d=dst2+dstStride2*y;
+ x=0;
+#ifdef HAVE_MMX
+ for(;x<w-31;x+=32)
+ {
+ asm volatile(
+ PREFETCH" 32%1\n\t"
+ "movq %1, %%mm0\n\t"
+ "movq 8%1, %%mm2\n\t"
+ "movq 16%1, %%mm4\n\t"
+ "movq 24%1, %%mm6\n\t"
+ "movq %%mm0, %%mm1\n\t"
+ "movq %%mm2, %%mm3\n\t"
+ "movq %%mm4, %%mm5\n\t"
+ "movq %%mm6, %%mm7\n\t"
+ "punpcklbw %%mm0, %%mm0\n\t"
+ "punpckhbw %%mm1, %%mm1\n\t"
+ "punpcklbw %%mm2, %%mm2\n\t"
+ "punpckhbw %%mm3, %%mm3\n\t"
+ "punpcklbw %%mm4, %%mm4\n\t"
+ "punpckhbw %%mm5, %%mm5\n\t"
+ "punpcklbw %%mm6, %%mm6\n\t"
+ "punpckhbw %%mm7, %%mm7\n\t"
+ MOVNTQ" %%mm0, %0\n\t"
+ MOVNTQ" %%mm1, 8%0\n\t"
+ MOVNTQ" %%mm2, 16%0\n\t"
+ MOVNTQ" %%mm3, 24%0\n\t"
+ MOVNTQ" %%mm4, 32%0\n\t"
+ MOVNTQ" %%mm5, 40%0\n\t"
+ MOVNTQ" %%mm6, 48%0\n\t"
+ MOVNTQ" %%mm7, 56%0"
+ :"=m"(d[2*x])
+ :"m"(s2[x])
+ :"memory");
+ }
+#endif
+ for(;x<w;x++) d[2*x]=d[2*x+1]=s2[x];
+ }
+#ifdef HAVE_MMX
+ asm(
+ EMMS" \n\t"
+ SFENCE" \n\t"
+ ::: "memory"
+ );
+#endif
+}
+
+static inline void RENAME(yvu9_to_yuy2)(const uint8_t *src1, const uint8_t *src2, const uint8_t *src3,
+ uint8_t *dst,
+ long width, long height,
+ long srcStride1, long srcStride2,
+ long srcStride3, long dstStride)
+{
+ long y,x,w,h;
+ w=width/2; h=height;
+ for(y=0;y<h;y++){
+ const uint8_t* yp=src1+srcStride1*y;
+ const uint8_t* up=src2+srcStride2*(y>>2);
+ const uint8_t* vp=src3+srcStride3*(y>>2);
+ uint8_t* d=dst+dstStride*y;
+ x=0;
+#ifdef HAVE_MMX
+ for(;x<w-7;x+=8)
+ {
+ asm volatile(
+ PREFETCH" 32(%1, %0)\n\t"
+ PREFETCH" 32(%2, %0)\n\t"
+ PREFETCH" 32(%3, %0)\n\t"
+ "movq (%1, %0, 4), %%mm0\n\t" /* Y0Y1Y2Y3Y4Y5Y6Y7 */
+ "movq (%2, %0), %%mm1\n\t" /* U0U1U2U3U4U5U6U7 */
+ "movq (%3, %0), %%mm2\n\t" /* V0V1V2V3V4V5V6V7 */
+ "movq %%mm0, %%mm3\n\t" /* Y0Y1Y2Y3Y4Y5Y6Y7 */
+ "movq %%mm1, %%mm4\n\t" /* U0U1U2U3U4U5U6U7 */
+ "movq %%mm2, %%mm5\n\t" /* V0V1V2V3V4V5V6V7 */
+ "punpcklbw %%mm1, %%mm1\n\t" /* U0U0 U1U1 U2U2 U3U3 */
+ "punpcklbw %%mm2, %%mm2\n\t" /* V0V0 V1V1 V2V2 V3V3 */
+ "punpckhbw %%mm4, %%mm4\n\t" /* U4U4 U5U5 U6U6 U7U7 */
+ "punpckhbw %%mm5, %%mm5\n\t" /* V4V4 V5V5 V6V6 V7V7 */
+
+ "movq %%mm1, %%mm6\n\t"
+ "punpcklbw %%mm2, %%mm1\n\t" /* U0V0 U0V0 U1V1 U1V1*/
+ "punpcklbw %%mm1, %%mm0\n\t" /* Y0U0 Y1V0 Y2U0 Y3V0*/
+ "punpckhbw %%mm1, %%mm3\n\t" /* Y4U1 Y5V1 Y6U1 Y7V1*/
+ MOVNTQ" %%mm0, (%4, %0, 8)\n\t"
+ MOVNTQ" %%mm3, 8(%4, %0, 8)\n\t"
+
+ "punpckhbw %%mm2, %%mm6\n\t" /* U2V2 U2V2 U3V3 U3V3*/
+ "movq 8(%1, %0, 4), %%mm0\n\t"
+ "movq %%mm0, %%mm3\n\t"
+ "punpcklbw %%mm6, %%mm0\n\t" /* Y U2 Y V2 Y U2 Y V2*/
+ "punpckhbw %%mm6, %%mm3\n\t" /* Y U3 Y V3 Y U3 Y V3*/
+ MOVNTQ" %%mm0, 16(%4, %0, 8)\n\t"
+ MOVNTQ" %%mm3, 24(%4, %0, 8)\n\t"
+
+ "movq %%mm4, %%mm6\n\t"
+ "movq 16(%1, %0, 4), %%mm0\n\t"
+ "movq %%mm0, %%mm3\n\t"
+ "punpcklbw %%mm5, %%mm4\n\t"
+ "punpcklbw %%mm4, %%mm0\n\t" /* Y U4 Y V4 Y U4 Y V4*/
+ "punpckhbw %%mm4, %%mm3\n\t" /* Y U5 Y V5 Y U5 Y V5*/
+ MOVNTQ" %%mm0, 32(%4, %0, 8)\n\t"
+ MOVNTQ" %%mm3, 40(%4, %0, 8)\n\t"
+
+ "punpckhbw %%mm5, %%mm6\n\t"
+ "movq 24(%1, %0, 4), %%mm0\n\t"
+ "movq %%mm0, %%mm3\n\t"
+ "punpcklbw %%mm6, %%mm0\n\t" /* Y U6 Y V6 Y U6 Y V6*/
+ "punpckhbw %%mm6, %%mm3\n\t" /* Y U7 Y V7 Y U7 Y V7*/
+ MOVNTQ" %%mm0, 48(%4, %0, 8)\n\t"
+ MOVNTQ" %%mm3, 56(%4, %0, 8)\n\t"
+
+ : "+r" (x)
+ : "r"(yp), "r" (up), "r"(vp), "r"(d)
+ :"memory");
+ }
+#endif
+ for(; x<w; x++)
+ {
+ const long x2= x<<2;
+ d[8*x+0]=yp[x2];
+ d[8*x+1]=up[x];
+ d[8*x+2]=yp[x2+1];
+ d[8*x+3]=vp[x];
+ d[8*x+4]=yp[x2+2];
+ d[8*x+5]=up[x];
+ d[8*x+6]=yp[x2+3];
+ d[8*x+7]=vp[x];
+ }
+ }
+#ifdef HAVE_MMX
+ asm(
+ EMMS" \n\t"
+ SFENCE" \n\t"
+ ::: "memory"
+ );
+#endif
+}
diff --git a/contrib/ffmpeg/libswscale/swscale-example.c b/contrib/ffmpeg/libswscale/swscale-example.c
new file mode 100644
index 000000000..40f04c7d0
--- /dev/null
+++ b/contrib/ffmpeg/libswscale/swscale-example.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdarg.h>
+
+#undef HAVE_AV_CONFIG_H
+#include "avutil.h"
+#include "swscale.h"
+#include "swscale_internal.h"
+#include "rgb2rgb.h"
+
+static uint64_t getSSD(uint8_t *src1, uint8_t *src2, int stride1, int stride2, int w, int h){
+ int x,y;
+ uint64_t ssd=0;
+
+//printf("%d %d\n", w, h);
+
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ int d= src1[x + y*stride1] - src2[x + y*stride2];
+ ssd+= d*d;
+//printf("%d", abs(src1[x + y*stride1] - src2[x + y*stride2])/26 );
+ }
+//printf("\n");
+ }
+ return ssd;
+}
+
+// test by ref -> src -> dst -> out & compare out against ref
+// ref & out are YV12
+static int doTest(uint8_t *ref[3], int refStride[3], int w, int h, int srcFormat, int dstFormat,
+ int srcW, int srcH, int dstW, int dstH, int flags){
+ uint8_t *src[3];
+ uint8_t *dst[3];
+ uint8_t *out[3];
+ int srcStride[3], dstStride[3];
+ int i;
+ uint64_t ssdY, ssdU, ssdV;
+ struct SwsContext *srcContext, *dstContext, *outContext;
+ int res;
+
+ res = 0;
+ for(i=0; i<3; i++){
+ // avoid stride % bpp != 0
+ if(srcFormat==PIX_FMT_RGB24 || srcFormat==PIX_FMT_BGR24)
+ srcStride[i]= srcW*3;
+ else
+ srcStride[i]= srcW*4;
+
+ if(dstFormat==PIX_FMT_RGB24 || dstFormat==PIX_FMT_BGR24)
+ dstStride[i]= dstW*3;
+ else
+ dstStride[i]= dstW*4;
+
+ src[i]= (uint8_t*) malloc(srcStride[i]*srcH);
+ dst[i]= (uint8_t*) malloc(dstStride[i]*dstH);
+ out[i]= (uint8_t*) malloc(refStride[i]*h);
+ if ((src[i] == NULL) || (dst[i] == NULL) || (out[i] == NULL)) {
+ perror("Malloc");
+ res = -1;
+
+ goto end;
+ }
+ }
+
+ dstContext = outContext = NULL;
+ srcContext= sws_getContext(w, h, PIX_FMT_YUV420P, srcW, srcH, srcFormat, flags, NULL, NULL, NULL);
+ if (srcContext == NULL) {
+ fprintf(stderr, "Failed to get %s ---> %s\n",
+ sws_format_name(PIX_FMT_YUV420P),
+ sws_format_name(srcFormat));
+ res = -1;
+
+ goto end;
+ }
+ dstContext= sws_getContext(srcW, srcH, srcFormat, dstW, dstH, dstFormat, flags, NULL, NULL, NULL);
+ if (dstContext == NULL) {
+ fprintf(stderr, "Failed to get %s ---> %s\n",
+ sws_format_name(srcFormat),
+ sws_format_name(dstFormat));
+ res = -1;
+
+ goto end;
+ }
+ outContext= sws_getContext(dstW, dstH, dstFormat, w, h, PIX_FMT_YUV420P, flags, NULL, NULL, NULL);
+ if (outContext == NULL) {
+ fprintf(stderr, "Failed to get %s ---> %s\n",
+ sws_format_name(dstFormat),
+ sws_format_name(PIX_FMT_YUV420P));
+ res = -1;
+
+ goto end;
+ }
+// printf("test %X %X %X -> %X %X %X\n", (int)ref[0], (int)ref[1], (int)ref[2],
+// (int)src[0], (int)src[1], (int)src[2]);
+
+ sws_scale(srcContext, ref, refStride, 0, h , src, srcStride);
+ sws_scale(dstContext, src, srcStride, 0, srcH, dst, dstStride);
+ sws_scale(outContext, dst, dstStride, 0, dstH, out, refStride);
+
+#if defined(ARCH_X86)
+ asm volatile ("emms\n\t");
+#endif
+
+ ssdY= getSSD(ref[0], out[0], refStride[0], refStride[0], w, h);
+ ssdU= getSSD(ref[1], out[1], refStride[1], refStride[1], (w+1)>>1, (h+1)>>1);
+ ssdV= getSSD(ref[2], out[2], refStride[2], refStride[2], (w+1)>>1, (h+1)>>1);
+
+ if(srcFormat == PIX_FMT_GRAY8 || dstFormat==PIX_FMT_GRAY8) ssdU=ssdV=0; //FIXME check that output is really gray
+
+ ssdY/= w*h;
+ ssdU/= w*h/4;
+ ssdV/= w*h/4;
+
+ if(ssdY>100 || ssdU>100 || ssdV>100){
+ printf(" %s %dx%d -> %s %4dx%4d flags=%2d SSD=%5lld,%5lld,%5lld\n",
+ sws_format_name(srcFormat), srcW, srcH,
+ sws_format_name(dstFormat), dstW, dstH,
+ flags,
+ ssdY, ssdU, ssdV);
+ }
+
+ end:
+
+ sws_freeContext(srcContext);
+ sws_freeContext(dstContext);
+ sws_freeContext(outContext);
+
+ for(i=0; i<3; i++){
+ free(src[i]);
+ free(dst[i]);
+ free(out[i]);
+ }
+
+ return res;
+}
+
+void fast_memcpy(void *a, void *b, int s){ //FIXME
+ memcpy(a, b, s);
+}
+
+static void selfTest(uint8_t *src[3], int stride[3], int w, int h){
+ enum PixelFormat srcFormat, dstFormat;
+ int srcW, srcH, dstW, dstH;
+ int flags;
+
+ for(srcFormat = 0; srcFormat < PIX_FMT_NB; srcFormat++) {
+ for(dstFormat = 0; dstFormat < PIX_FMT_NB; dstFormat++) {
+ printf("%s -> %s\n",
+ sws_format_name(srcFormat),
+ sws_format_name(dstFormat));
+
+ srcW= w;
+ srcH= h;
+ for(dstW=w - w/3; dstW<= 4*w/3; dstW+= w/3){
+ for(dstH=h - h/3; dstH<= 4*h/3; dstH+= h/3){
+ for(flags=1; flags<33; flags*=2) {
+ int res;
+
+ res = doTest(src, stride, w, h, srcFormat, dstFormat,
+ srcW, srcH, dstW, dstH, flags);
+ if (res < 0) {
+ dstW = 4 * w / 3;
+ dstH = 4 * h / 3;
+ flags = 33;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+#define W 96
+#define H 96
+
+int main(int argc, char **argv){
+ uint8_t rgb_data[W*H*4];
+ uint8_t *rgb_src[3]= {rgb_data, NULL, NULL};
+ int rgb_stride[3]={4*W, 0, 0};
+ uint8_t data[3][W*H];
+ uint8_t *src[3]= {data[0], data[1], data[2]};
+ int stride[3]={W, W, W};
+ int x, y;
+ struct SwsContext *sws;
+
+ sws= sws_getContext(W/12, H/12, PIX_FMT_RGB32, W, H, PIX_FMT_YUV420P, 2, NULL, NULL, NULL);
+
+ for(y=0; y<H; y++){
+ for(x=0; x<W*4; x++){
+ rgb_data[ x + y*4*W]= random();
+ }
+ }
+#if defined(ARCH_X86)
+ sws_rgb2rgb_init(SWS_CPU_CAPS_MMX*0);
+#else
+ sws_rgb2rgb_init(0);
+#endif
+ sws_scale(sws, rgb_src, rgb_stride, 0, H , src, stride);
+
+#if defined(ARCH_X86)
+ asm volatile ("emms\n\t");
+#endif
+
+ selfTest(src, stride, W, H);
+
+ return 123;
+}
diff --git a/contrib/ffmpeg/libswscale/swscale.c b/contrib/ffmpeg/libswscale/swscale.c
new file mode 100644
index 000000000..eb9092c19
--- /dev/null
+++ b/contrib/ffmpeg/libswscale/swscale.c
@@ -0,0 +1,2864 @@
+/*
+ * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * the C code (not assembly, mmx, ...) of this file can be used
+ * under the LGPL license too
+ */
+
+/*
+ supported Input formats: YV12, I420/IYUV, YUY2, UYVY, BGR32, BGR24, BGR16, BGR15, RGB32, RGB24, Y8/Y800, YVU9/IF09
+ supported output formats: YV12, I420/IYUV, YUY2, UYVY, {BGR,RGB}{1,4,8,15,16,24,32}, Y8/Y800, YVU9/IF09
+ {BGR,RGB}{1,4,8,15,16} support dithering
+
+ unscaled special converters (YV12=I420=IYUV, Y800=Y8)
+ YV12 -> {BGR,RGB}{1,4,8,15,16,24,32}
+ x -> x
+ YUV9 -> YV12
+ YUV9/YV12 -> Y800
+ Y800 -> YUV9/YV12
+ BGR24 -> BGR32 & RGB24 -> RGB32
+ BGR32 -> BGR24 & RGB32 -> RGB24
+ BGR15 -> BGR16
+*/
+
+/*
+tested special converters (most are tested actually but i didnt write it down ...)
+ YV12 -> BGR16
+ YV12 -> YV12
+ BGR15 -> BGR16
+ BGR16 -> BGR16
+ YVU9 -> YV12
+
+untested special converters
+ YV12/I420 -> BGR15/BGR24/BGR32 (its the yuv2rgb stuff, so it should be ok)
+ YV12/I420 -> YV12/I420
+ YUY2/BGR15/BGR24/BGR32/RGB24/RGB32 -> same format
+ BGR24 -> BGR32 & RGB24 -> RGB32
+ BGR32 -> BGR24 & RGB32 -> RGB24
+ BGR24 -> YV12
+*/
+
+#include <inttypes.h>
+#include <string.h>
+#include <math.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "config.h"
+#include <assert.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#else
+#include <stdlib.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+#endif
+#include "swscale.h"
+#include "swscale_internal.h"
+#include "x86_cpu.h"
+#include "bswap.h"
+#include "rgb2rgb.h"
+#ifdef USE_FASTMEMCPY
+#include "libvo/fastmemcpy.h"
+#endif
+
+#undef MOVNTQ
+#undef PAVGB
+
+//#undef HAVE_MMX2
+//#define HAVE_3DNOW
+//#undef HAVE_MMX
+//#undef ARCH_X86
+//#define WORDS_BIGENDIAN
+#define DITHER1XBPP
+
+#define FAST_BGR2YV12 // use 7 bit coeffs instead of 15bit
+
+#define RET 0xC3 //near return opcode for X86
+
+#ifdef MP_DEBUG
+#define ASSERT(x) assert(x);
+#else
+#define ASSERT(x) ;
+#endif
+
+#ifdef M_PI
+#define PI M_PI
+#else
+#define PI 3.14159265358979323846
+#endif
+
+#define isSupportedIn(x) ((x)==PIX_FMT_YUV420P || (x)==PIX_FMT_YUYV422 || (x)==PIX_FMT_UYVY422\
+ || (x)==PIX_FMT_RGB32|| (x)==PIX_FMT_BGR24|| (x)==PIX_FMT_BGR565|| (x)==PIX_FMT_BGR555\
+ || (x)==PIX_FMT_BGR32|| (x)==PIX_FMT_RGB24|| (x)==PIX_FMT_RGB565|| (x)==PIX_FMT_RGB555\
+ || (x)==PIX_FMT_GRAY8 || (x)==PIX_FMT_YUV410P\
+ || (x)==PIX_FMT_GRAY16BE || (x)==PIX_FMT_GRAY16LE\
+ || (x)==PIX_FMT_YUV444P || (x)==PIX_FMT_YUV422P || (x)==PIX_FMT_YUV411P)
+#define isSupportedOut(x) ((x)==PIX_FMT_YUV420P || (x)==PIX_FMT_YUYV422 || (x)==PIX_FMT_UYVY422\
+ || (x)==PIX_FMT_YUV444P || (x)==PIX_FMT_YUV422P || (x)==PIX_FMT_YUV411P\
+ || isRGB(x) || isBGR(x)\
+ || (x)==PIX_FMT_NV12 || (x)==PIX_FMT_NV21\
+ || (x)==PIX_FMT_GRAY16BE || (x)==PIX_FMT_GRAY16LE\
+ || (x)==PIX_FMT_GRAY8 || (x)==PIX_FMT_YUV410P)
+#define isPacked(x) ((x)==PIX_FMT_YUYV422 || (x)==PIX_FMT_UYVY422 ||isRGB(x) || isBGR(x))
+
+#define RGB2YUV_SHIFT 16
+#define BY ((int)( 0.098*(1<<RGB2YUV_SHIFT)+0.5))
+#define BV ((int)(-0.071*(1<<RGB2YUV_SHIFT)+0.5))
+#define BU ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5))
+#define GY ((int)( 0.504*(1<<RGB2YUV_SHIFT)+0.5))
+#define GV ((int)(-0.368*(1<<RGB2YUV_SHIFT)+0.5))
+#define GU ((int)(-0.291*(1<<RGB2YUV_SHIFT)+0.5))
+#define RY ((int)( 0.257*(1<<RGB2YUV_SHIFT)+0.5))
+#define RV ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5))
+#define RU ((int)(-0.148*(1<<RGB2YUV_SHIFT)+0.5))
+
+extern const int32_t Inverse_Table_6_9[8][4];
+
+/*
+NOTES
+Special versions: fast Y 1:1 scaling (no interpolation in y direction)
+
+TODO
+more intelligent missalignment avoidance for the horizontal scaler
+write special vertical cubic upscale version
+Optimize C code (yv12 / minmax)
+add support for packed pixel yuv input & output
+add support for Y8 output
+optimize bgr24 & bgr32
+add BGR4 output support
+write special BGR->BGR scaler
+*/
+
+#if defined(ARCH_X86)
+static uint64_t attribute_used __attribute__((aligned(8))) bF8= 0xF8F8F8F8F8F8F8F8LL;
+static uint64_t attribute_used __attribute__((aligned(8))) bFC= 0xFCFCFCFCFCFCFCFCLL;
+static uint64_t __attribute__((aligned(8))) w10= 0x0010001000100010LL;
+static uint64_t attribute_used __attribute__((aligned(8))) w02= 0x0002000200020002LL;
+static uint64_t attribute_used __attribute__((aligned(8))) bm00001111=0x00000000FFFFFFFFLL;
+static uint64_t attribute_used __attribute__((aligned(8))) bm00000111=0x0000000000FFFFFFLL;
+static uint64_t attribute_used __attribute__((aligned(8))) bm11111000=0xFFFFFFFFFF000000LL;
+static uint64_t attribute_used __attribute__((aligned(8))) bm01010101=0x00FF00FF00FF00FFLL;
+
+static volatile uint64_t attribute_used __attribute__((aligned(8))) b5Dither;
+static volatile uint64_t attribute_used __attribute__((aligned(8))) g5Dither;
+static volatile uint64_t attribute_used __attribute__((aligned(8))) g6Dither;
+static volatile uint64_t attribute_used __attribute__((aligned(8))) r5Dither;
+
+static uint64_t __attribute__((aligned(8))) dither4[2]={
+ 0x0103010301030103LL,
+ 0x0200020002000200LL,};
+
+static uint64_t __attribute__((aligned(8))) dither8[2]={
+ 0x0602060206020602LL,
+ 0x0004000400040004LL,};
+
+static uint64_t __attribute__((aligned(8))) b16Mask= 0x001F001F001F001FLL;
+static uint64_t attribute_used __attribute__((aligned(8))) g16Mask= 0x07E007E007E007E0LL;
+static uint64_t attribute_used __attribute__((aligned(8))) r16Mask= 0xF800F800F800F800LL;
+static uint64_t __attribute__((aligned(8))) b15Mask= 0x001F001F001F001FLL;
+static uint64_t attribute_used __attribute__((aligned(8))) g15Mask= 0x03E003E003E003E0LL;
+static uint64_t attribute_used __attribute__((aligned(8))) r15Mask= 0x7C007C007C007C00LL;
+
+static uint64_t attribute_used __attribute__((aligned(8))) M24A= 0x00FF0000FF0000FFLL;
+static uint64_t attribute_used __attribute__((aligned(8))) M24B= 0xFF0000FF0000FF00LL;
+static uint64_t attribute_used __attribute__((aligned(8))) M24C= 0x0000FF0000FF0000LL;
+
+#ifdef FAST_BGR2YV12
+static const uint64_t bgr2YCoeff attribute_used __attribute__((aligned(8))) = 0x000000210041000DULL;
+static const uint64_t bgr2UCoeff attribute_used __attribute__((aligned(8))) = 0x0000FFEEFFDC0038ULL;
+static const uint64_t bgr2VCoeff attribute_used __attribute__((aligned(8))) = 0x00000038FFD2FFF8ULL;
+#else
+static const uint64_t bgr2YCoeff attribute_used __attribute__((aligned(8))) = 0x000020E540830C8BULL;
+static const uint64_t bgr2UCoeff attribute_used __attribute__((aligned(8))) = 0x0000ED0FDAC23831ULL;
+static const uint64_t bgr2VCoeff attribute_used __attribute__((aligned(8))) = 0x00003831D0E6F6EAULL;
+#endif /* FAST_BGR2YV12 */
+static const uint64_t bgr2YOffset attribute_used __attribute__((aligned(8))) = 0x1010101010101010ULL;
+static const uint64_t bgr2UVOffset attribute_used __attribute__((aligned(8)))= 0x8080808080808080ULL;
+static const uint64_t w1111 attribute_used __attribute__((aligned(8))) = 0x0001000100010001ULL;
+#endif /* defined(ARCH_X86) */
+
+// clipping helper table for C implementations:
+static unsigned char clip_table[768];
+
+static SwsVector *sws_getConvVec(SwsVector *a, SwsVector *b);
+
+extern const uint8_t dither_2x2_4[2][8];
+extern const uint8_t dither_2x2_8[2][8];
+extern const uint8_t dither_8x8_32[8][8];
+extern const uint8_t dither_8x8_73[8][8];
+extern const uint8_t dither_8x8_220[8][8];
+
+char *sws_format_name(enum PixelFormat format)
+{
+ switch (format) {
+ case PIX_FMT_YUV420P:
+ return "yuv420p";
+ case PIX_FMT_YUYV422:
+ return "yuyv422";
+ case PIX_FMT_RGB24:
+ return "rgb24";
+ case PIX_FMT_BGR24:
+ return "bgr24";
+ case PIX_FMT_YUV422P:
+ return "yuv422p";
+ case PIX_FMT_YUV444P:
+ return "yuv444p";
+ case PIX_FMT_RGB32:
+ return "rgb32";
+ case PIX_FMT_YUV410P:
+ return "yuv410p";
+ case PIX_FMT_YUV411P:
+ return "yuv411p";
+ case PIX_FMT_RGB565:
+ return "rgb565";
+ case PIX_FMT_RGB555:
+ return "rgb555";
+ case PIX_FMT_GRAY16BE:
+ return "gray16be";
+ case PIX_FMT_GRAY16LE:
+ return "gray16le";
+ case PIX_FMT_GRAY8:
+ return "gray8";
+ case PIX_FMT_MONOWHITE:
+ return "mono white";
+ case PIX_FMT_MONOBLACK:
+ return "mono black";
+ case PIX_FMT_PAL8:
+ return "Palette";
+ case PIX_FMT_YUVJ420P:
+ return "yuvj420p";
+ case PIX_FMT_YUVJ422P:
+ return "yuvj422p";
+ case PIX_FMT_YUVJ444P:
+ return "yuvj444p";
+ case PIX_FMT_XVMC_MPEG2_MC:
+ return "xvmc_mpeg2_mc";
+ case PIX_FMT_XVMC_MPEG2_IDCT:
+ return "xvmc_mpeg2_idct";
+ case PIX_FMT_UYVY422:
+ return "uyvy422";
+ case PIX_FMT_UYYVYY411:
+ return "uyyvyy411";
+ case PIX_FMT_RGB32_1:
+ return "rgb32x";
+ case PIX_FMT_BGR32_1:
+ return "bgr32x";
+ case PIX_FMT_BGR32:
+ return "bgr32";
+ case PIX_FMT_BGR565:
+ return "bgr565";
+ case PIX_FMT_BGR555:
+ return "bgr555";
+ case PIX_FMT_BGR8:
+ return "bgr8";
+ case PIX_FMT_BGR4:
+ return "bgr4";
+ case PIX_FMT_BGR4_BYTE:
+ return "bgr4 byte";
+ case PIX_FMT_RGB8:
+ return "rgb8";
+ case PIX_FMT_RGB4:
+ return "rgb4";
+ case PIX_FMT_RGB4_BYTE:
+ return "rgb4 byte";
+ case PIX_FMT_NV12:
+ return "nv12";
+ case PIX_FMT_NV21:
+ return "nv21";
+ default:
+ return "Unknown format";
+ }
+}
+
+#if defined(ARCH_X86)
+void in_asm_used_var_warning_killer()
+{
+ volatile int i= bF8+bFC+w10+
+ bm00001111+bm00000111+bm11111000+b16Mask+g16Mask+r16Mask+b15Mask+g15Mask+r15Mask+
+ M24A+M24B+M24C+w02 + b5Dither+g5Dither+r5Dither+g6Dither+dither4[0]+dither8[0]+bm01010101;
+ if(i) i=0;
+}
+#endif
+
+static inline void yuv2yuvXinC(int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
+ int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
+ uint8_t *dest, uint8_t *uDest, uint8_t *vDest, int dstW, int chrDstW)
+{
+ //FIXME Optimize (just quickly writen not opti..)
+ int i;
+ for(i=0; i<dstW; i++)
+ {
+ int val=1<<18;
+ int j;
+ for(j=0; j<lumFilterSize; j++)
+ val += lumSrc[j][i] * lumFilter[j];
+
+ dest[i]= FFMIN(FFMAX(val>>19, 0), 255);
+ }
+
+ if(uDest != NULL)
+ for(i=0; i<chrDstW; i++)
+ {
+ int u=1<<18;
+ int v=1<<18;
+ int j;
+ for(j=0; j<chrFilterSize; j++)
+ {
+ u += chrSrc[j][i] * chrFilter[j];
+ v += chrSrc[j][i + 2048] * chrFilter[j];
+ }
+
+ uDest[i]= FFMIN(FFMAX(u>>19, 0), 255);
+ vDest[i]= FFMIN(FFMAX(v>>19, 0), 255);
+ }
+}
+
+static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
+ int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
+ uint8_t *dest, uint8_t *uDest, int dstW, int chrDstW, int dstFormat)
+{
+ //FIXME Optimize (just quickly writen not opti..)
+ int i;
+ for(i=0; i<dstW; i++)
+ {
+ int val=1<<18;
+ int j;
+ for(j=0; j<lumFilterSize; j++)
+ val += lumSrc[j][i] * lumFilter[j];
+
+ dest[i]= FFMIN(FFMAX(val>>19, 0), 255);
+ }
+
+ if(uDest == NULL)
+ return;
+
+ if(dstFormat == PIX_FMT_NV12)
+ for(i=0; i<chrDstW; i++)
+ {
+ int u=1<<18;
+ int v=1<<18;
+ int j;
+ for(j=0; j<chrFilterSize; j++)
+ {
+ u += chrSrc[j][i] * chrFilter[j];
+ v += chrSrc[j][i + 2048] * chrFilter[j];
+ }
+
+ uDest[2*i]= FFMIN(FFMAX(u>>19, 0), 255);
+ uDest[2*i+1]= FFMIN(FFMAX(v>>19, 0), 255);
+ }
+ else
+ for(i=0; i<chrDstW; i++)
+ {
+ int u=1<<18;
+ int v=1<<18;
+ int j;
+ for(j=0; j<chrFilterSize; j++)
+ {
+ u += chrSrc[j][i] * chrFilter[j];
+ v += chrSrc[j][i + 2048] * chrFilter[j];
+ }
+
+ uDest[2*i]= FFMIN(FFMAX(v>>19, 0), 255);
+ uDest[2*i+1]= FFMIN(FFMAX(u>>19, 0), 255);
+ }
+}
+
+#define YSCALE_YUV_2_PACKEDX_C(type) \
+ for(i=0; i<(dstW>>1); i++){\
+ int j;\
+ int Y1=1<<18;\
+ int Y2=1<<18;\
+ int U=1<<18;\
+ int V=1<<18;\
+ type *r, *b, *g;\
+ const int i2= 2*i;\
+ \
+ for(j=0; j<lumFilterSize; j++)\
+ {\
+ Y1 += lumSrc[j][i2] * lumFilter[j];\
+ Y2 += lumSrc[j][i2+1] * lumFilter[j];\
+ }\
+ for(j=0; j<chrFilterSize; j++)\
+ {\
+ U += chrSrc[j][i] * chrFilter[j];\
+ V += chrSrc[j][i+2048] * chrFilter[j];\
+ }\
+ Y1>>=19;\
+ Y2>>=19;\
+ U >>=19;\
+ V >>=19;\
+ if((Y1|Y2|U|V)&256)\
+ {\
+ if(Y1>255) Y1=255;\
+ else if(Y1<0)Y1=0;\
+ if(Y2>255) Y2=255;\
+ else if(Y2<0)Y2=0;\
+ if(U>255) U=255;\
+ else if(U<0) U=0;\
+ if(V>255) V=255;\
+ else if(V<0) V=0;\
+ }
+
+#define YSCALE_YUV_2_RGBX_C(type) \
+ YSCALE_YUV_2_PACKEDX_C(type)\
+ r = c->table_rV[V];\
+ g = c->table_gU[U] + c->table_gV[V];\
+ b = c->table_bU[U];\
+
+#define YSCALE_YUV_2_PACKED2_C \
+ for(i=0; i<(dstW>>1); i++){\
+ const int i2= 2*i;\
+ int Y1= (buf0[i2 ]*yalpha1+buf1[i2 ]*yalpha)>>19;\
+ int Y2= (buf0[i2+1]*yalpha1+buf1[i2+1]*yalpha)>>19;\
+ int U= (uvbuf0[i ]*uvalpha1+uvbuf1[i ]*uvalpha)>>19;\
+ int V= (uvbuf0[i+2048]*uvalpha1+uvbuf1[i+2048]*uvalpha)>>19;\
+
+#define YSCALE_YUV_2_RGB2_C(type) \
+ YSCALE_YUV_2_PACKED2_C\
+ type *r, *b, *g;\
+ r = c->table_rV[V];\
+ g = c->table_gU[U] + c->table_gV[V];\
+ b = c->table_bU[U];\
+
+#define YSCALE_YUV_2_PACKED1_C \
+ for(i=0; i<(dstW>>1); i++){\
+ const int i2= 2*i;\
+ int Y1= buf0[i2 ]>>7;\
+ int Y2= buf0[i2+1]>>7;\
+ int U= (uvbuf1[i ])>>7;\
+ int V= (uvbuf1[i+2048])>>7;\
+
+#define YSCALE_YUV_2_RGB1_C(type) \
+ YSCALE_YUV_2_PACKED1_C\
+ type *r, *b, *g;\
+ r = c->table_rV[V];\
+ g = c->table_gU[U] + c->table_gV[V];\
+ b = c->table_bU[U];\
+
+#define YSCALE_YUV_2_PACKED1B_C \
+ for(i=0; i<(dstW>>1); i++){\
+ const int i2= 2*i;\
+ int Y1= buf0[i2 ]>>7;\
+ int Y2= buf0[i2+1]>>7;\
+ int U= (uvbuf0[i ] + uvbuf1[i ])>>8;\
+ int V= (uvbuf0[i+2048] + uvbuf1[i+2048])>>8;\
+
+#define YSCALE_YUV_2_RGB1B_C(type) \
+ YSCALE_YUV_2_PACKED1B_C\
+ type *r, *b, *g;\
+ r = c->table_rV[V];\
+ g = c->table_gU[U] + c->table_gV[V];\
+ b = c->table_bU[U];\
+
+#define YSCALE_YUV_2_ANYRGB_C(func, func2)\
+ switch(c->dstFormat)\
+ {\
+ case PIX_FMT_RGB32:\
+ case PIX_FMT_BGR32:\
+ func(uint32_t)\
+ ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1];\
+ ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2];\
+ } \
+ break;\
+ case PIX_FMT_RGB24:\
+ func(uint8_t)\
+ ((uint8_t*)dest)[0]= r[Y1];\
+ ((uint8_t*)dest)[1]= g[Y1];\
+ ((uint8_t*)dest)[2]= b[Y1];\
+ ((uint8_t*)dest)[3]= r[Y2];\
+ ((uint8_t*)dest)[4]= g[Y2];\
+ ((uint8_t*)dest)[5]= b[Y2];\
+ dest+=6;\
+ }\
+ break;\
+ case PIX_FMT_BGR24:\
+ func(uint8_t)\
+ ((uint8_t*)dest)[0]= b[Y1];\
+ ((uint8_t*)dest)[1]= g[Y1];\
+ ((uint8_t*)dest)[2]= r[Y1];\
+ ((uint8_t*)dest)[3]= b[Y2];\
+ ((uint8_t*)dest)[4]= g[Y2];\
+ ((uint8_t*)dest)[5]= r[Y2];\
+ dest+=6;\
+ }\
+ break;\
+ case PIX_FMT_RGB565:\
+ case PIX_FMT_BGR565:\
+ {\
+ const int dr1= dither_2x2_8[y&1 ][0];\
+ const int dg1= dither_2x2_4[y&1 ][0];\
+ const int db1= dither_2x2_8[(y&1)^1][0];\
+ const int dr2= dither_2x2_8[y&1 ][1];\
+ const int dg2= dither_2x2_4[y&1 ][1];\
+ const int db2= dither_2x2_8[(y&1)^1][1];\
+ func(uint16_t)\
+ ((uint16_t*)dest)[i2+0]= r[Y1+dr1] + g[Y1+dg1] + b[Y1+db1];\
+ ((uint16_t*)dest)[i2+1]= r[Y2+dr2] + g[Y2+dg2] + b[Y2+db2];\
+ }\
+ }\
+ break;\
+ case PIX_FMT_RGB555:\
+ case PIX_FMT_BGR555:\
+ {\
+ const int dr1= dither_2x2_8[y&1 ][0];\
+ const int dg1= dither_2x2_8[y&1 ][1];\
+ const int db1= dither_2x2_8[(y&1)^1][0];\
+ const int dr2= dither_2x2_8[y&1 ][1];\
+ const int dg2= dither_2x2_8[y&1 ][0];\
+ const int db2= dither_2x2_8[(y&1)^1][1];\
+ func(uint16_t)\
+ ((uint16_t*)dest)[i2+0]= r[Y1+dr1] + g[Y1+dg1] + b[Y1+db1];\
+ ((uint16_t*)dest)[i2+1]= r[Y2+dr2] + g[Y2+dg2] + b[Y2+db2];\
+ }\
+ }\
+ break;\
+ case PIX_FMT_RGB8:\
+ case PIX_FMT_BGR8:\
+ {\
+ const uint8_t * const d64= dither_8x8_73[y&7];\
+ const uint8_t * const d32= dither_8x8_32[y&7];\
+ func(uint8_t)\
+ ((uint8_t*)dest)[i2+0]= r[Y1+d32[(i2+0)&7]] + g[Y1+d32[(i2+0)&7]] + b[Y1+d64[(i2+0)&7]];\
+ ((uint8_t*)dest)[i2+1]= r[Y2+d32[(i2+1)&7]] + g[Y2+d32[(i2+1)&7]] + b[Y2+d64[(i2+1)&7]];\
+ }\
+ }\
+ break;\
+ case PIX_FMT_RGB4:\
+ case PIX_FMT_BGR4:\
+ {\
+ const uint8_t * const d64= dither_8x8_73 [y&7];\
+ const uint8_t * const d128=dither_8x8_220[y&7];\
+ func(uint8_t)\
+ ((uint8_t*)dest)[i]= r[Y1+d128[(i2+0)&7]] + g[Y1+d64[(i2+0)&7]] + b[Y1+d128[(i2+0)&7]]\
+ + ((r[Y2+d128[(i2+1)&7]] + g[Y2+d64[(i2+1)&7]] + b[Y2+d128[(i2+1)&7]])<<4);\
+ }\
+ }\
+ break;\
+ case PIX_FMT_RGB4_BYTE:\
+ case PIX_FMT_BGR4_BYTE:\
+ {\
+ const uint8_t * const d64= dither_8x8_73 [y&7];\
+ const uint8_t * const d128=dither_8x8_220[y&7];\
+ func(uint8_t)\
+ ((uint8_t*)dest)[i2+0]= r[Y1+d128[(i2+0)&7]] + g[Y1+d64[(i2+0)&7]] + b[Y1+d128[(i2+0)&7]];\
+ ((uint8_t*)dest)[i2+1]= r[Y2+d128[(i2+1)&7]] + g[Y2+d64[(i2+1)&7]] + b[Y2+d128[(i2+1)&7]];\
+ }\
+ }\
+ break;\
+ case PIX_FMT_MONOBLACK:\
+ {\
+ const uint8_t * const d128=dither_8x8_220[y&7];\
+ uint8_t *g= c->table_gU[128] + c->table_gV[128];\
+ for(i=0; i<dstW-7; i+=8){\
+ int acc;\
+ acc = g[((buf0[i ]*yalpha1+buf1[i ]*yalpha)>>19) + d128[0]];\
+ acc+= acc + g[((buf0[i+1]*yalpha1+buf1[i+1]*yalpha)>>19) + d128[1]];\
+ acc+= acc + g[((buf0[i+2]*yalpha1+buf1[i+2]*yalpha)>>19) + d128[2]];\
+ acc+= acc + g[((buf0[i+3]*yalpha1+buf1[i+3]*yalpha)>>19) + d128[3]];\
+ acc+= acc + g[((buf0[i+4]*yalpha1+buf1[i+4]*yalpha)>>19) + d128[4]];\
+ acc+= acc + g[((buf0[i+5]*yalpha1+buf1[i+5]*yalpha)>>19) + d128[5]];\
+ acc+= acc + g[((buf0[i+6]*yalpha1+buf1[i+6]*yalpha)>>19) + d128[6]];\
+ acc+= acc + g[((buf0[i+7]*yalpha1+buf1[i+7]*yalpha)>>19) + d128[7]];\
+ ((uint8_t*)dest)[0]= acc;\
+ dest++;\
+ }\
+\
+/*\
+((uint8_t*)dest)-= dstW>>4;\
+{\
+ int acc=0;\
+ int left=0;\
+ static int top[1024];\
+ static int last_new[1024][1024];\
+ static int last_in3[1024][1024];\
+ static int drift[1024][1024];\
+ int topLeft=0;\
+ int shift=0;\
+ int count=0;\
+ const uint8_t * const d128=dither_8x8_220[y&7];\
+ int error_new=0;\
+ int error_in3=0;\
+ int f=0;\
+ \
+ for(i=dstW>>1; i<dstW; i++){\
+ int in= ((buf0[i ]*yalpha1+buf1[i ]*yalpha)>>19);\
+ int in2 = (76309 * (in - 16) + 32768) >> 16;\
+ int in3 = (in2 < 0) ? 0 : ((in2 > 255) ? 255 : in2);\
+ int old= (left*7 + topLeft + top[i]*5 + top[i+1]*3)/20 + in3\
+ + (last_new[y][i] - in3)*f/256;\
+ int new= old> 128 ? 255 : 0;\
+\
+ error_new+= FFABS(last_new[y][i] - new);\
+ error_in3+= FFABS(last_in3[y][i] - in3);\
+ f= error_new - error_in3*4;\
+ if(f<0) f=0;\
+ if(f>256) f=256;\
+\
+ topLeft= top[i];\
+ left= top[i]= old - new;\
+ last_new[y][i]= new;\
+ last_in3[y][i]= in3;\
+\
+ acc+= acc + (new&1);\
+ if((i&7)==6){\
+ ((uint8_t*)dest)[0]= acc;\
+ ((uint8_t*)dest)++;\
+ }\
+ }\
+}\
+*/\
+ }\
+ break;\
+ case PIX_FMT_YUYV422:\
+ func2\
+ ((uint8_t*)dest)[2*i2+0]= Y1;\
+ ((uint8_t*)dest)[2*i2+1]= U;\
+ ((uint8_t*)dest)[2*i2+2]= Y2;\
+ ((uint8_t*)dest)[2*i2+3]= V;\
+ } \
+ break;\
+ case PIX_FMT_UYVY422:\
+ func2\
+ ((uint8_t*)dest)[2*i2+0]= U;\
+ ((uint8_t*)dest)[2*i2+1]= Y1;\
+ ((uint8_t*)dest)[2*i2+2]= V;\
+ ((uint8_t*)dest)[2*i2+3]= Y2;\
+ } \
+ break;\
+ }\
+
+
+static inline void yuv2packedXinC(SwsContext *c, int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
+ int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
+ uint8_t *dest, int dstW, int y)
+{
+ int i;
+ switch(c->dstFormat)
+ {
+ case PIX_FMT_BGR32:
+ case PIX_FMT_RGB32:
+ YSCALE_YUV_2_RGBX_C(uint32_t)
+ ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1];
+ ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2];
+ }
+ break;
+ case PIX_FMT_RGB24:
+ YSCALE_YUV_2_RGBX_C(uint8_t)
+ ((uint8_t*)dest)[0]= r[Y1];
+ ((uint8_t*)dest)[1]= g[Y1];
+ ((uint8_t*)dest)[2]= b[Y1];
+ ((uint8_t*)dest)[3]= r[Y2];
+ ((uint8_t*)dest)[4]= g[Y2];
+ ((uint8_t*)dest)[5]= b[Y2];
+ dest+=6;
+ }
+ break;
+ case PIX_FMT_BGR24:
+ YSCALE_YUV_2_RGBX_C(uint8_t)
+ ((uint8_t*)dest)[0]= b[Y1];
+ ((uint8_t*)dest)[1]= g[Y1];
+ ((uint8_t*)dest)[2]= r[Y1];
+ ((uint8_t*)dest)[3]= b[Y2];
+ ((uint8_t*)dest)[4]= g[Y2];
+ ((uint8_t*)dest)[5]= r[Y2];
+ dest+=6;
+ }
+ break;
+ case PIX_FMT_RGB565:
+ case PIX_FMT_BGR565:
+ {
+ const int dr1= dither_2x2_8[y&1 ][0];
+ const int dg1= dither_2x2_4[y&1 ][0];
+ const int db1= dither_2x2_8[(y&1)^1][0];
+ const int dr2= dither_2x2_8[y&1 ][1];
+ const int dg2= dither_2x2_4[y&1 ][1];
+ const int db2= dither_2x2_8[(y&1)^1][1];
+ YSCALE_YUV_2_RGBX_C(uint16_t)
+ ((uint16_t*)dest)[i2+0]= r[Y1+dr1] + g[Y1+dg1] + b[Y1+db1];
+ ((uint16_t*)dest)[i2+1]= r[Y2+dr2] + g[Y2+dg2] + b[Y2+db2];
+ }
+ }
+ break;
+ case PIX_FMT_RGB555:
+ case PIX_FMT_BGR555:
+ {
+ const int dr1= dither_2x2_8[y&1 ][0];
+ const int dg1= dither_2x2_8[y&1 ][1];
+ const int db1= dither_2x2_8[(y&1)^1][0];
+ const int dr2= dither_2x2_8[y&1 ][1];
+ const int dg2= dither_2x2_8[y&1 ][0];
+ const int db2= dither_2x2_8[(y&1)^1][1];
+ YSCALE_YUV_2_RGBX_C(uint16_t)
+ ((uint16_t*)dest)[i2+0]= r[Y1+dr1] + g[Y1+dg1] + b[Y1+db1];
+ ((uint16_t*)dest)[i2+1]= r[Y2+dr2] + g[Y2+dg2] + b[Y2+db2];
+ }
+ }
+ break;
+ case PIX_FMT_RGB8:
+ case PIX_FMT_BGR8:
+ {
+ const uint8_t * const d64= dither_8x8_73[y&7];
+ const uint8_t * const d32= dither_8x8_32[y&7];
+ YSCALE_YUV_2_RGBX_C(uint8_t)
+ ((uint8_t*)dest)[i2+0]= r[Y1+d32[(i2+0)&7]] + g[Y1+d32[(i2+0)&7]] + b[Y1+d64[(i2+0)&7]];
+ ((uint8_t*)dest)[i2+1]= r[Y2+d32[(i2+1)&7]] + g[Y2+d32[(i2+1)&7]] + b[Y2+d64[(i2+1)&7]];
+ }
+ }
+ break;
+ case PIX_FMT_RGB4:
+ case PIX_FMT_BGR4:
+ {
+ const uint8_t * const d64= dither_8x8_73 [y&7];
+ const uint8_t * const d128=dither_8x8_220[y&7];
+ YSCALE_YUV_2_RGBX_C(uint8_t)
+ ((uint8_t*)dest)[i]= r[Y1+d128[(i2+0)&7]] + g[Y1+d64[(i2+0)&7]] + b[Y1+d128[(i2+0)&7]]
+ +((r[Y2+d128[(i2+1)&7]] + g[Y2+d64[(i2+1)&7]] + b[Y2+d128[(i2+1)&7]])<<4);
+ }
+ }
+ break;
+ case PIX_FMT_RGB4_BYTE:
+ case PIX_FMT_BGR4_BYTE:
+ {
+ const uint8_t * const d64= dither_8x8_73 [y&7];
+ const uint8_t * const d128=dither_8x8_220[y&7];
+ YSCALE_YUV_2_RGBX_C(uint8_t)
+ ((uint8_t*)dest)[i2+0]= r[Y1+d128[(i2+0)&7]] + g[Y1+d64[(i2+0)&7]] + b[Y1+d128[(i2+0)&7]];
+ ((uint8_t*)dest)[i2+1]= r[Y2+d128[(i2+1)&7]] + g[Y2+d64[(i2+1)&7]] + b[Y2+d128[(i2+1)&7]];
+ }
+ }
+ break;
+ case PIX_FMT_MONOBLACK:
+ {
+ const uint8_t * const d128=dither_8x8_220[y&7];
+ uint8_t *g= c->table_gU[128] + c->table_gV[128];
+ int acc=0;
+ for(i=0; i<dstW-1; i+=2){
+ int j;
+ int Y1=1<<18;
+ int Y2=1<<18;
+
+ for(j=0; j<lumFilterSize; j++)
+ {
+ Y1 += lumSrc[j][i] * lumFilter[j];
+ Y2 += lumSrc[j][i+1] * lumFilter[j];
+ }
+ Y1>>=19;
+ Y2>>=19;
+ if((Y1|Y2)&256)
+ {
+ if(Y1>255) Y1=255;
+ else if(Y1<0)Y1=0;
+ if(Y2>255) Y2=255;
+ else if(Y2<0)Y2=0;
+ }
+ acc+= acc + g[Y1+d128[(i+0)&7]];
+ acc+= acc + g[Y2+d128[(i+1)&7]];
+ if((i&7)==6){
+ ((uint8_t*)dest)[0]= acc;
+ dest++;
+ }
+ }
+ }
+ break;
+ case PIX_FMT_YUYV422:
+ YSCALE_YUV_2_PACKEDX_C(void)
+ ((uint8_t*)dest)[2*i2+0]= Y1;
+ ((uint8_t*)dest)[2*i2+1]= U;
+ ((uint8_t*)dest)[2*i2+2]= Y2;
+ ((uint8_t*)dest)[2*i2+3]= V;
+ }
+ break;
+ case PIX_FMT_UYVY422:
+ YSCALE_YUV_2_PACKEDX_C(void)
+ ((uint8_t*)dest)[2*i2+0]= U;
+ ((uint8_t*)dest)[2*i2+1]= Y1;
+ ((uint8_t*)dest)[2*i2+2]= V;
+ ((uint8_t*)dest)[2*i2+3]= Y2;
+ }
+ break;
+ }
+}
+
+
+//Note: we have C, X86, MMX, MMX2, 3DNOW version therse no 3DNOW+MMX2 one
+//Plain C versions
+#if !defined (HAVE_MMX) || defined (RUNTIME_CPUDETECT)
+#define COMPILE_C
+#endif
+
+#ifdef ARCH_POWERPC
+#if defined (HAVE_ALTIVEC) || defined (RUNTIME_CPUDETECT)
+#define COMPILE_ALTIVEC
+#endif //HAVE_ALTIVEC
+#endif //ARCH_POWERPC
+
+#if defined(ARCH_X86)
+
+#if (defined (HAVE_MMX) && !defined (HAVE_3DNOW) && !defined (HAVE_MMX2)) || defined (RUNTIME_CPUDETECT)
+#define COMPILE_MMX
+#endif
+
+#if defined (HAVE_MMX2) || defined (RUNTIME_CPUDETECT)
+#define COMPILE_MMX2
+#endif
+
+#if (defined (HAVE_3DNOW) && !defined (HAVE_MMX2)) || defined (RUNTIME_CPUDETECT)
+#define COMPILE_3DNOW
+#endif
+#endif //ARCH_X86 || ARCH_X86_64
+
+#undef HAVE_MMX
+#undef HAVE_MMX2
+#undef HAVE_3DNOW
+
+#ifdef COMPILE_C
+#undef HAVE_MMX
+#undef HAVE_MMX2
+#undef HAVE_3DNOW
+#undef HAVE_ALTIVEC
+#define RENAME(a) a ## _C
+#include "swscale_template.c"
+#endif
+
+#ifdef ARCH_POWERPC
+#ifdef COMPILE_ALTIVEC
+#undef RENAME
+#define HAVE_ALTIVEC
+#define RENAME(a) a ## _altivec
+#include "swscale_template.c"
+#endif
+#endif //ARCH_POWERPC
+
+#if defined(ARCH_X86)
+
+//X86 versions
+/*
+#undef RENAME
+#undef HAVE_MMX
+#undef HAVE_MMX2
+#undef HAVE_3DNOW
+#define ARCH_X86
+#define RENAME(a) a ## _X86
+#include "swscale_template.c"
+*/
+//MMX versions
+#ifdef COMPILE_MMX
+#undef RENAME
+#define HAVE_MMX
+#undef HAVE_MMX2
+#undef HAVE_3DNOW
+#define RENAME(a) a ## _MMX
+#include "swscale_template.c"
+#endif
+
+//MMX2 versions
+#ifdef COMPILE_MMX2
+#undef RENAME
+#define HAVE_MMX
+#define HAVE_MMX2
+#undef HAVE_3DNOW
+#define RENAME(a) a ## _MMX2
+#include "swscale_template.c"
+#endif
+
+//3DNOW versions
+#ifdef COMPILE_3DNOW
+#undef RENAME
+#define HAVE_MMX
+#undef HAVE_MMX2
+#define HAVE_3DNOW
+#define RENAME(a) a ## _3DNow
+#include "swscale_template.c"
+#endif
+
+#endif //ARCH_X86 || ARCH_X86_64
+
+// minor note: the HAVE_xyz is messed up after that line so don't use it
+
+static double getSplineCoeff(double a, double b, double c, double d, double dist)
+{
+// printf("%f %f %f %f %f\n", a,b,c,d,dist);
+ if(dist<=1.0) return ((d*dist + c)*dist + b)*dist +a;
+ else return getSplineCoeff( 0.0,
+ b+ 2.0*c + 3.0*d,
+ c + 3.0*d,
+ -b- 3.0*c - 6.0*d,
+ dist-1.0);
+}
+
+static inline int initFilter(int16_t **outFilter, int16_t **filterPos, int *outFilterSize, int xInc,
+ int srcW, int dstW, int filterAlign, int one, int flags,
+ SwsVector *srcFilter, SwsVector *dstFilter, double param[2])
+{
+ int i;
+ int filterSize;
+ int filter2Size;
+ int minFilterSize;
+ double *filter=NULL;
+ double *filter2=NULL;
+#if defined(ARCH_X86)
+ if(flags & SWS_CPU_CAPS_MMX)
+ asm volatile("emms\n\t"::: "memory"); //FIXME this shouldnt be required but it IS (even for non mmx versions)
+#endif
+
+ // Note the +1 is for the MMXscaler which reads over the end
+ *filterPos = av_malloc((dstW+1)*sizeof(int16_t));
+
+ if(FFABS(xInc - 0x10000) <10) // unscaled
+ {
+ int i;
+ filterSize= 1;
+ filter= av_malloc(dstW*sizeof(double)*filterSize);
+ for(i=0; i<dstW*filterSize; i++) filter[i]=0;
+
+ for(i=0; i<dstW; i++)
+ {
+ filter[i*filterSize]=1;
+ (*filterPos)[i]=i;
+ }
+
+ }
+ else if(flags&SWS_POINT) // lame looking point sampling mode
+ {
+ int i;
+ int xDstInSrc;
+ filterSize= 1;
+ filter= av_malloc(dstW*sizeof(double)*filterSize);
+
+ xDstInSrc= xInc/2 - 0x8000;
+ for(i=0; i<dstW; i++)
+ {
+ int xx= (xDstInSrc - ((filterSize-1)<<15) + (1<<15))>>16;
+
+ (*filterPos)[i]= xx;
+ filter[i]= 1.0;
+ xDstInSrc+= xInc;
+ }
+ }
+ else if((xInc <= (1<<16) && (flags&SWS_AREA)) || (flags&SWS_FAST_BILINEAR)) // bilinear upscale
+ {
+ int i;
+ int xDstInSrc;
+ if (flags&SWS_BICUBIC) filterSize= 4;
+ else if(flags&SWS_X ) filterSize= 4;
+ else filterSize= 2; // SWS_BILINEAR / SWS_AREA
+ filter= av_malloc(dstW*sizeof(double)*filterSize);
+
+ xDstInSrc= xInc/2 - 0x8000;
+ for(i=0; i<dstW; i++)
+ {
+ int xx= (xDstInSrc - ((filterSize-1)<<15) + (1<<15))>>16;
+ int j;
+
+ (*filterPos)[i]= xx;
+ //Bilinear upscale / linear interpolate / Area averaging
+ for(j=0; j<filterSize; j++)
+ {
+ double d= FFABS((xx<<16) - xDstInSrc)/(double)(1<<16);
+ double coeff= 1.0 - d;
+ if(coeff<0) coeff=0;
+ filter[i*filterSize + j]= coeff;
+ xx++;
+ }
+ xDstInSrc+= xInc;
+ }
+ }
+ else
+ {
+ double xDstInSrc;
+ double sizeFactor, filterSizeInSrc;
+ const double xInc1= (double)xInc / (double)(1<<16);
+
+ if (flags&SWS_BICUBIC) sizeFactor= 4.0;
+ else if(flags&SWS_X) sizeFactor= 8.0;
+ else if(flags&SWS_AREA) sizeFactor= 1.0; //downscale only, for upscale it is bilinear
+ else if(flags&SWS_GAUSS) sizeFactor= 8.0; // infinite ;)
+ else if(flags&SWS_LANCZOS) sizeFactor= param[0] != SWS_PARAM_DEFAULT ? 2.0*param[0] : 6.0;
+ else if(flags&SWS_SINC) sizeFactor= 20.0; // infinite ;)
+ else if(flags&SWS_SPLINE) sizeFactor= 20.0; // infinite ;)
+ else if(flags&SWS_BILINEAR) sizeFactor= 2.0;
+ else {
+ sizeFactor= 0.0; //GCC warning killer
+ ASSERT(0)
+ }
+
+ if(xInc1 <= 1.0) filterSizeInSrc= sizeFactor; // upscale
+ else filterSizeInSrc= sizeFactor*srcW / (double)dstW;
+
+ filterSize= (int)ceil(1 + filterSizeInSrc); // will be reduced later if possible
+ if(filterSize > srcW-2) filterSize=srcW-2;
+
+ filter= av_malloc(dstW*sizeof(double)*filterSize);
+
+ xDstInSrc= xInc1 / 2.0 - 0.5;
+ for(i=0; i<dstW; i++)
+ {
+ int xx= (int)(xDstInSrc - (filterSize-1)*0.5 + 0.5);
+ int j;
+ (*filterPos)[i]= xx;
+ for(j=0; j<filterSize; j++)
+ {
+ double d= FFABS(xx - xDstInSrc)/filterSizeInSrc*sizeFactor;
+ double coeff;
+ if(flags & SWS_BICUBIC)
+ {
+ double B= param[0] != SWS_PARAM_DEFAULT ? param[0] : 0.0;
+ double C= param[1] != SWS_PARAM_DEFAULT ? param[1] : 0.6;
+
+ if(d<1.0)
+ coeff = (12-9*B-6*C)*d*d*d + (-18+12*B+6*C)*d*d + 6-2*B;
+ else if(d<2.0)
+ coeff = (-B-6*C)*d*d*d + (6*B+30*C)*d*d + (-12*B-48*C)*d +8*B+24*C;
+ else
+ coeff=0.0;
+ }
+/* else if(flags & SWS_X)
+ {
+ double p= param ? param*0.01 : 0.3;
+ coeff = d ? sin(d*PI)/(d*PI) : 1.0;
+ coeff*= pow(2.0, - p*d*d);
+ }*/
+ else if(flags & SWS_X)
+ {
+ double A= param[0] != SWS_PARAM_DEFAULT ? param[0] : 1.0;
+
+ if(d<1.0)
+ coeff = cos(d*PI);
+ else
+ coeff=-1.0;
+ if(coeff<0.0) coeff= -pow(-coeff, A);
+ else coeff= pow( coeff, A);
+ coeff= coeff*0.5 + 0.5;
+ }
+ else if(flags & SWS_AREA)
+ {
+ double srcPixelSize= 1.0/xInc1;
+ if(d + srcPixelSize/2 < 0.5) coeff= 1.0;
+ else if(d - srcPixelSize/2 < 0.5) coeff= (0.5-d)/srcPixelSize + 0.5;
+ else coeff=0.0;
+ }
+ else if(flags & SWS_GAUSS)
+ {
+ double p= param[0] != SWS_PARAM_DEFAULT ? param[0] : 3.0;
+ coeff = pow(2.0, - p*d*d);
+ }
+ else if(flags & SWS_SINC)
+ {
+ coeff = d ? sin(d*PI)/(d*PI) : 1.0;
+ }
+ else if(flags & SWS_LANCZOS)
+ {
+ double p= param[0] != SWS_PARAM_DEFAULT ? param[0] : 3.0;
+ coeff = d ? sin(d*PI)*sin(d*PI/p)/(d*d*PI*PI/p) : 1.0;
+ if(d>p) coeff=0;
+ }
+ else if(flags & SWS_BILINEAR)
+ {
+ coeff= 1.0 - d;
+ if(coeff<0) coeff=0;
+ }
+ else if(flags & SWS_SPLINE)
+ {
+ double p=-2.196152422706632;
+ coeff = getSplineCoeff(1.0, 0.0, p, -p-1.0, d);
+ }
+ else {
+ coeff= 0.0; //GCC warning killer
+ ASSERT(0)
+ }
+
+ filter[i*filterSize + j]= coeff;
+ xx++;
+ }
+ xDstInSrc+= xInc1;
+ }
+ }
+
+ /* apply src & dst Filter to filter -> filter2
+ av_free(filter);
+ */
+ ASSERT(filterSize>0)
+ filter2Size= filterSize;
+ if(srcFilter) filter2Size+= srcFilter->length - 1;
+ if(dstFilter) filter2Size+= dstFilter->length - 1;
+ ASSERT(filter2Size>0)
+ filter2= av_malloc(filter2Size*dstW*sizeof(double));
+
+ for(i=0; i<dstW; i++)
+ {
+ int j;
+ SwsVector scaleFilter;
+ SwsVector *outVec;
+
+ scaleFilter.coeff= filter + i*filterSize;
+ scaleFilter.length= filterSize;
+
+ if(srcFilter) outVec= sws_getConvVec(srcFilter, &scaleFilter);
+ else outVec= &scaleFilter;
+
+ ASSERT(outVec->length == filter2Size)
+ //FIXME dstFilter
+
+ for(j=0; j<outVec->length; j++)
+ {
+ filter2[i*filter2Size + j]= outVec->coeff[j];
+ }
+
+ (*filterPos)[i]+= (filterSize-1)/2 - (filter2Size-1)/2;
+
+ if(outVec != &scaleFilter) sws_freeVec(outVec);
+ }
+ av_free(filter); filter=NULL;
+
+ /* try to reduce the filter-size (step1 find size and shift left) */
+ // Assume its near normalized (*0.5 or *2.0 is ok but * 0.001 is not)
+ minFilterSize= 0;
+ for(i=dstW-1; i>=0; i--)
+ {
+ int min= filter2Size;
+ int j;
+ double cutOff=0.0;
+
+ /* get rid off near zero elements on the left by shifting left */
+ for(j=0; j<filter2Size; j++)
+ {
+ int k;
+ cutOff += FFABS(filter2[i*filter2Size]);
+
+ if(cutOff > SWS_MAX_REDUCE_CUTOFF) break;
+
+ /* preserve Monotonicity because the core can't handle the filter otherwise */
+ if(i<dstW-1 && (*filterPos)[i] >= (*filterPos)[i+1]) break;
+
+ // Move filter coeffs left
+ for(k=1; k<filter2Size; k++)
+ filter2[i*filter2Size + k - 1]= filter2[i*filter2Size + k];
+ filter2[i*filter2Size + k - 1]= 0.0;
+ (*filterPos)[i]++;
+ }
+
+ cutOff=0.0;
+ /* count near zeros on the right */
+ for(j=filter2Size-1; j>0; j--)
+ {
+ cutOff += FFABS(filter2[i*filter2Size + j]);
+
+ if(cutOff > SWS_MAX_REDUCE_CUTOFF) break;
+ min--;
+ }
+
+ if(min>minFilterSize) minFilterSize= min;
+ }
+
+ if (flags & SWS_CPU_CAPS_ALTIVEC) {
+ // we can handle the special case 4,
+ // so we don't want to go to the full 8
+ if (minFilterSize < 5)
+ filterAlign = 4;
+
+ // we really don't want to waste our time
+ // doing useless computation, so fall-back on
+ // the scalar C code for very small filter.
+ // vectorizing is worth it only if you have
+ // decent-sized vector.
+ if (minFilterSize < 3)
+ filterAlign = 1;
+ }
+
+ if (flags & SWS_CPU_CAPS_MMX) {
+ // special case for unscaled vertical filtering
+ if(minFilterSize == 1 && filterAlign == 2)
+ filterAlign= 1;
+ }
+
+ ASSERT(minFilterSize > 0)
+ filterSize= (minFilterSize +(filterAlign-1)) & (~(filterAlign-1));
+ ASSERT(filterSize > 0)
+ filter= av_malloc(filterSize*dstW*sizeof(double));
+ if(filterSize >= MAX_FILTER_SIZE)
+ return -1;
+ *outFilterSize= filterSize;
+
+ if(flags&SWS_PRINT_INFO)
+ MSG_V("SwScaler: reducing / aligning filtersize %d -> %d\n", filter2Size, filterSize);
+ /* try to reduce the filter-size (step2 reduce it) */
+ for(i=0; i<dstW; i++)
+ {
+ int j;
+
+ for(j=0; j<filterSize; j++)
+ {
+ if(j>=filter2Size) filter[i*filterSize + j]= 0.0;
+ else filter[i*filterSize + j]= filter2[i*filter2Size + j];
+ }
+ }
+ av_free(filter2); filter2=NULL;
+
+
+ //FIXME try to align filterpos if possible
+
+ //fix borders
+ for(i=0; i<dstW; i++)
+ {
+ int j;
+ if((*filterPos)[i] < 0)
+ {
+ // Move filter coeffs left to compensate for filterPos
+ for(j=1; j<filterSize; j++)
+ {
+ int left= FFMAX(j + (*filterPos)[i], 0);
+ filter[i*filterSize + left] += filter[i*filterSize + j];
+ filter[i*filterSize + j]=0;
+ }
+ (*filterPos)[i]= 0;
+ }
+
+ if((*filterPos)[i] + filterSize > srcW)
+ {
+ int shift= (*filterPos)[i] + filterSize - srcW;
+ // Move filter coeffs right to compensate for filterPos
+ for(j=filterSize-2; j>=0; j--)
+ {
+ int right= FFMIN(j + shift, filterSize-1);
+ filter[i*filterSize +right] += filter[i*filterSize +j];
+ filter[i*filterSize +j]=0;
+ }
+ (*filterPos)[i]= srcW - filterSize;
+ }
+ }
+
+ // Note the +1 is for the MMXscaler which reads over the end
+ /* align at 16 for AltiVec (needed by hScale_altivec_real) */
+ *outFilter= av_malloc(*outFilterSize*(dstW+1)*sizeof(int16_t));
+ memset(*outFilter, 0, *outFilterSize*(dstW+1)*sizeof(int16_t));
+
+ /* Normalize & Store in outFilter */
+ for(i=0; i<dstW; i++)
+ {
+ int j;
+ double error=0;
+ double sum=0;
+ double scale= one;
+
+ for(j=0; j<filterSize; j++)
+ {
+ sum+= filter[i*filterSize + j];
+ }
+ scale/= sum;
+ for(j=0; j<*outFilterSize; j++)
+ {
+ double v= filter[i*filterSize + j]*scale + error;
+ int intV= floor(v + 0.5);
+ (*outFilter)[i*(*outFilterSize) + j]= intV;
+ error = v - intV;
+ }
+ }
+
+ (*filterPos)[dstW]= (*filterPos)[dstW-1]; // the MMX scaler will read over the end
+ for(i=0; i<*outFilterSize; i++)
+ {
+ int j= dstW*(*outFilterSize);
+ (*outFilter)[j + i]= (*outFilter)[j + i - (*outFilterSize)];
+ }
+
+ av_free(filter);
+ return 0;
+}
+
+#ifdef COMPILE_MMX2
+static void initMMX2HScaler(int dstW, int xInc, uint8_t *funnyCode, int16_t *filter, int32_t *filterPos, int numSplits)
+{
+ uint8_t *fragmentA;
+ long imm8OfPShufW1A;
+ long imm8OfPShufW2A;
+ long fragmentLengthA;
+ uint8_t *fragmentB;
+ long imm8OfPShufW1B;
+ long imm8OfPShufW2B;
+ long fragmentLengthB;
+ int fragmentPos;
+
+ int xpos, i;
+
+ // create an optimized horizontal scaling routine
+
+ //code fragment
+
+ asm volatile(
+ "jmp 9f \n\t"
+ // Begin
+ "0: \n\t"
+ "movq (%%"REG_d", %%"REG_a"), %%mm3\n\t"
+ "movd (%%"REG_c", %%"REG_S"), %%mm0\n\t"
+ "movd 1(%%"REG_c", %%"REG_S"), %%mm1\n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "pshufw $0xFF, %%mm1, %%mm1 \n\t"
+ "1: \n\t"
+ "pshufw $0xFF, %%mm0, %%mm0 \n\t"
+ "2: \n\t"
+ "psubw %%mm1, %%mm0 \n\t"
+ "movl 8(%%"REG_b", %%"REG_a"), %%esi\n\t"
+ "pmullw %%mm3, %%mm0 \n\t"
+ "psllw $7, %%mm1 \n\t"
+ "paddw %%mm1, %%mm0 \n\t"
+
+ "movq %%mm0, (%%"REG_D", %%"REG_a")\n\t"
+
+ "add $8, %%"REG_a" \n\t"
+ // End
+ "9: \n\t"
+// "int $3\n\t"
+ "lea 0b, %0 \n\t"
+ "lea 1b, %1 \n\t"
+ "lea 2b, %2 \n\t"
+ "dec %1 \n\t"
+ "dec %2 \n\t"
+ "sub %0, %1 \n\t"
+ "sub %0, %2 \n\t"
+ "lea 9b, %3 \n\t"
+ "sub %0, %3 \n\t"
+
+
+ :"=r" (fragmentA), "=r" (imm8OfPShufW1A), "=r" (imm8OfPShufW2A),
+ "=r" (fragmentLengthA)
+ );
+
+ asm volatile(
+ "jmp 9f \n\t"
+ // Begin
+ "0: \n\t"
+ "movq (%%"REG_d", %%"REG_a"), %%mm3\n\t"
+ "movd (%%"REG_c", %%"REG_S"), %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "pshufw $0xFF, %%mm0, %%mm1 \n\t"
+ "1: \n\t"
+ "pshufw $0xFF, %%mm0, %%mm0 \n\t"
+ "2: \n\t"
+ "psubw %%mm1, %%mm0 \n\t"
+ "movl 8(%%"REG_b", %%"REG_a"), %%esi\n\t"
+ "pmullw %%mm3, %%mm0 \n\t"
+ "psllw $7, %%mm1 \n\t"
+ "paddw %%mm1, %%mm0 \n\t"
+
+ "movq %%mm0, (%%"REG_D", %%"REG_a")\n\t"
+
+ "add $8, %%"REG_a" \n\t"
+ // End
+ "9: \n\t"
+// "int $3\n\t"
+ "lea 0b, %0 \n\t"
+ "lea 1b, %1 \n\t"
+ "lea 2b, %2 \n\t"
+ "dec %1 \n\t"
+ "dec %2 \n\t"
+ "sub %0, %1 \n\t"
+ "sub %0, %2 \n\t"
+ "lea 9b, %3 \n\t"
+ "sub %0, %3 \n\t"
+
+
+ :"=r" (fragmentB), "=r" (imm8OfPShufW1B), "=r" (imm8OfPShufW2B),
+ "=r" (fragmentLengthB)
+ );
+
+ xpos= 0; //lumXInc/2 - 0x8000; // difference between pixel centers
+ fragmentPos=0;
+
+ for(i=0; i<dstW/numSplits; i++)
+ {
+ int xx=xpos>>16;
+
+ if((i&3) == 0)
+ {
+ int a=0;
+ int b=((xpos+xInc)>>16) - xx;
+ int c=((xpos+xInc*2)>>16) - xx;
+ int d=((xpos+xInc*3)>>16) - xx;
+
+ filter[i ] = (( xpos & 0xFFFF) ^ 0xFFFF)>>9;
+ filter[i+1] = (((xpos+xInc ) & 0xFFFF) ^ 0xFFFF)>>9;
+ filter[i+2] = (((xpos+xInc*2) & 0xFFFF) ^ 0xFFFF)>>9;
+ filter[i+3] = (((xpos+xInc*3) & 0xFFFF) ^ 0xFFFF)>>9;
+ filterPos[i/2]= xx;
+
+ if(d+1<4)
+ {
+ int maxShift= 3-(d+1);
+ int shift=0;
+
+ memcpy(funnyCode + fragmentPos, fragmentB, fragmentLengthB);
+
+ funnyCode[fragmentPos + imm8OfPShufW1B]=
+ (a+1) | ((b+1)<<2) | ((c+1)<<4) | ((d+1)<<6);
+ funnyCode[fragmentPos + imm8OfPShufW2B]=
+ a | (b<<2) | (c<<4) | (d<<6);
+
+ if(i+3>=dstW) shift=maxShift; //avoid overread
+ else if((filterPos[i/2]&3) <= maxShift) shift=filterPos[i/2]&3; //Align
+
+ if(shift && i>=shift)
+ {
+ funnyCode[fragmentPos + imm8OfPShufW1B]+= 0x55*shift;
+ funnyCode[fragmentPos + imm8OfPShufW2B]+= 0x55*shift;
+ filterPos[i/2]-=shift;
+ }
+
+ fragmentPos+= fragmentLengthB;
+ }
+ else
+ {
+ int maxShift= 3-d;
+ int shift=0;
+
+ memcpy(funnyCode + fragmentPos, fragmentA, fragmentLengthA);
+
+ funnyCode[fragmentPos + imm8OfPShufW1A]=
+ funnyCode[fragmentPos + imm8OfPShufW2A]=
+ a | (b<<2) | (c<<4) | (d<<6);
+
+ if(i+4>=dstW) shift=maxShift; //avoid overread
+ else if((filterPos[i/2]&3) <= maxShift) shift=filterPos[i/2]&3; //partial align
+
+ if(shift && i>=shift)
+ {
+ funnyCode[fragmentPos + imm8OfPShufW1A]+= 0x55*shift;
+ funnyCode[fragmentPos + imm8OfPShufW2A]+= 0x55*shift;
+ filterPos[i/2]-=shift;
+ }
+
+ fragmentPos+= fragmentLengthA;
+ }
+
+ funnyCode[fragmentPos]= RET;
+ }
+ xpos+=xInc;
+ }
+ filterPos[i/2]= xpos>>16; // needed to jump to the next part
+}
+#endif /* COMPILE_MMX2 */
+
+static void globalInit(void){
+ // generating tables:
+ int i;
+ for(i=0; i<768; i++){
+ int c= FFMIN(FFMAX(i-256, 0), 255);
+ clip_table[i]=c;
+ }
+}
+
+static SwsFunc getSwsFunc(int flags){
+
+#ifdef RUNTIME_CPUDETECT
+#if defined(ARCH_X86)
+ // ordered per speed fasterst first
+ if(flags & SWS_CPU_CAPS_MMX2)
+ return swScale_MMX2;
+ else if(flags & SWS_CPU_CAPS_3DNOW)
+ return swScale_3DNow;
+ else if(flags & SWS_CPU_CAPS_MMX)
+ return swScale_MMX;
+ else
+ return swScale_C;
+
+#else
+#ifdef ARCH_POWERPC
+ if(flags & SWS_CPU_CAPS_ALTIVEC)
+ return swScale_altivec;
+ else
+ return swScale_C;
+#endif
+ return swScale_C;
+#endif /* defined(ARCH_X86) */
+#else //RUNTIME_CPUDETECT
+#ifdef HAVE_MMX2
+ return swScale_MMX2;
+#elif defined (HAVE_3DNOW)
+ return swScale_3DNow;
+#elif defined (HAVE_MMX)
+ return swScale_MMX;
+#elif defined (HAVE_ALTIVEC)
+ return swScale_altivec;
+#else
+ return swScale_C;
+#endif
+#endif //!RUNTIME_CPUDETECT
+}
+
+static int PlanarToNV12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dstParam[], int dstStride[]){
+ uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
+ /* Copy Y plane */
+ if(dstStride[0]==srcStride[0] && srcStride[0] > 0)
+ memcpy(dst, src[0], srcSliceH*dstStride[0]);
+ else
+ {
+ int i;
+ uint8_t *srcPtr= src[0];
+ uint8_t *dstPtr= dst;
+ for(i=0; i<srcSliceH; i++)
+ {
+ memcpy(dstPtr, srcPtr, c->srcW);
+ srcPtr+= srcStride[0];
+ dstPtr+= dstStride[0];
+ }
+ }
+ dst = dstParam[1] + dstStride[1]*srcSliceY/2;
+ if (c->dstFormat == PIX_FMT_NV12)
+ interleaveBytes( src[1],src[2],dst,c->srcW/2,srcSliceH/2,srcStride[1],srcStride[2],dstStride[0] );
+ else
+ interleaveBytes( src[2],src[1],dst,c->srcW/2,srcSliceH/2,srcStride[2],srcStride[1],dstStride[0] );
+
+ return srcSliceH;
+}
+
+static int PlanarToYuy2Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dstParam[], int dstStride[]){
+ uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
+
+ yv12toyuy2( src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0] );
+
+ return srcSliceH;
+}
+
+static int PlanarToUyvyWrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dstParam[], int dstStride[]){
+ uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
+
+ yv12touyvy( src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0] );
+
+ return srcSliceH;
+}
+
+/* {RGB,BGR}{15,16,24,32} -> {RGB,BGR}{15,16,24,32} */
+static int rgb2rgbWrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+ const int srcFormat= c->srcFormat;
+ const int dstFormat= c->dstFormat;
+ const int srcBpp= (fmt_depth(srcFormat) + 7) >> 3;
+ const int dstBpp= (fmt_depth(dstFormat) + 7) >> 3;
+ const int srcId= fmt_depth(srcFormat) >> 2; /* 1:0, 4:1, 8:2, 15:3, 16:4, 24:6, 32:8 */
+ const int dstId= fmt_depth(dstFormat) >> 2;
+ void (*conv)(const uint8_t *src, uint8_t *dst, long src_size)=NULL;
+
+ /* BGR -> BGR */
+ if( (isBGR(srcFormat) && isBGR(dstFormat))
+ || (isRGB(srcFormat) && isRGB(dstFormat))){
+ switch(srcId | (dstId<<4)){
+ case 0x34: conv= rgb16to15; break;
+ case 0x36: conv= rgb24to15; break;
+ case 0x38: conv= rgb32to15; break;
+ case 0x43: conv= rgb15to16; break;
+ case 0x46: conv= rgb24to16; break;
+ case 0x48: conv= rgb32to16; break;
+ case 0x63: conv= rgb15to24; break;
+ case 0x64: conv= rgb16to24; break;
+ case 0x68: conv= rgb32to24; break;
+ case 0x83: conv= rgb15to32; break;
+ case 0x84: conv= rgb16to32; break;
+ case 0x86: conv= rgb24to32; break;
+ default: MSG_ERR("swScaler: internal error %s -> %s converter\n",
+ sws_format_name(srcFormat), sws_format_name(dstFormat)); break;
+ }
+ }else if( (isBGR(srcFormat) && isRGB(dstFormat))
+ || (isRGB(srcFormat) && isBGR(dstFormat))){
+ switch(srcId | (dstId<<4)){
+ case 0x33: conv= rgb15tobgr15; break;
+ case 0x34: conv= rgb16tobgr15; break;
+ case 0x36: conv= rgb24tobgr15; break;
+ case 0x38: conv= rgb32tobgr15; break;
+ case 0x43: conv= rgb15tobgr16; break;
+ case 0x44: conv= rgb16tobgr16; break;
+ case 0x46: conv= rgb24tobgr16; break;
+ case 0x48: conv= rgb32tobgr16; break;
+ case 0x63: conv= rgb15tobgr24; break;
+ case 0x64: conv= rgb16tobgr24; break;
+ case 0x66: conv= rgb24tobgr24; break;
+ case 0x68: conv= rgb32tobgr24; break;
+ case 0x83: conv= rgb15tobgr32; break;
+ case 0x84: conv= rgb16tobgr32; break;
+ case 0x86: conv= rgb24tobgr32; break;
+ case 0x88: conv= rgb32tobgr32; break;
+ default: MSG_ERR("swScaler: internal error %s -> %s converter\n",
+ sws_format_name(srcFormat), sws_format_name(dstFormat)); break;
+ }
+ }else{
+ MSG_ERR("swScaler: internal error %s -> %s converter\n",
+ sws_format_name(srcFormat), sws_format_name(dstFormat));
+ }
+
+ if(dstStride[0]*srcBpp == srcStride[0]*dstBpp)
+ conv(src[0], dst[0] + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
+ else
+ {
+ int i;
+ uint8_t *srcPtr= src[0];
+ uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
+
+ for(i=0; i<srcSliceH; i++)
+ {
+ conv(srcPtr, dstPtr, c->srcW*srcBpp);
+ srcPtr+= srcStride[0];
+ dstPtr+= dstStride[0];
+ }
+ }
+ return srcSliceH;
+}
+
+static int bgr24toyv12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+
+ rgb24toyv12(
+ src[0],
+ dst[0]+ srcSliceY *dstStride[0],
+ dst[1]+(srcSliceY>>1)*dstStride[1],
+ dst[2]+(srcSliceY>>1)*dstStride[2],
+ c->srcW, srcSliceH,
+ dstStride[0], dstStride[1], srcStride[0]);
+ return srcSliceH;
+}
+
+static int yvu9toyv12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+ int i;
+
+ /* copy Y */
+ if(srcStride[0]==dstStride[0] && srcStride[0] > 0)
+ memcpy(dst[0]+ srcSliceY*dstStride[0], src[0], srcStride[0]*srcSliceH);
+ else{
+ uint8_t *srcPtr= src[0];
+ uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
+
+ for(i=0; i<srcSliceH; i++)
+ {
+ memcpy(dstPtr, srcPtr, c->srcW);
+ srcPtr+= srcStride[0];
+ dstPtr+= dstStride[0];
+ }
+ }
+
+ if(c->dstFormat==PIX_FMT_YUV420P){
+ planar2x(src[1], dst[1], c->chrSrcW, c->chrSrcH, srcStride[1], dstStride[1]);
+ planar2x(src[2], dst[2], c->chrSrcW, c->chrSrcH, srcStride[2], dstStride[2]);
+ }else{
+ planar2x(src[1], dst[2], c->chrSrcW, c->chrSrcH, srcStride[1], dstStride[2]);
+ planar2x(src[2], dst[1], c->chrSrcW, c->chrSrcH, srcStride[2], dstStride[1]);
+ }
+ return srcSliceH;
+}
+
+/* unscaled copy like stuff (assumes nearly identical formats) */
+static int simpleCopy(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+
+ if(isPacked(c->srcFormat))
+ {
+ if(dstStride[0]==srcStride[0] && srcStride[0] > 0)
+ memcpy(dst[0] + dstStride[0]*srcSliceY, src[0], srcSliceH*dstStride[0]);
+ else
+ {
+ int i;
+ uint8_t *srcPtr= src[0];
+ uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
+ int length=0;
+
+ /* universal length finder */
+ while(length+c->srcW <= FFABS(dstStride[0])
+ && length+c->srcW <= FFABS(srcStride[0])) length+= c->srcW;
+ ASSERT(length!=0);
+
+ for(i=0; i<srcSliceH; i++)
+ {
+ memcpy(dstPtr, srcPtr, length);
+ srcPtr+= srcStride[0];
+ dstPtr+= dstStride[0];
+ }
+ }
+ }
+ else
+ { /* Planar YUV or gray */
+ int plane;
+ for(plane=0; plane<3; plane++)
+ {
+ int length= plane==0 ? c->srcW : -((-c->srcW )>>c->chrDstHSubSample);
+ int y= plane==0 ? srcSliceY: -((-srcSliceY)>>c->chrDstVSubSample);
+ int height= plane==0 ? srcSliceH: -((-srcSliceH)>>c->chrDstVSubSample);
+
+ if((isGray(c->srcFormat) || isGray(c->dstFormat)) && plane>0)
+ {
+ if(!isGray(c->dstFormat))
+ memset(dst[plane], 128, dstStride[plane]*height);
+ }
+ else
+ {
+ if(dstStride[plane]==srcStride[plane] && srcStride[plane] > 0)
+ memcpy(dst[plane] + dstStride[plane]*y, src[plane], height*dstStride[plane]);
+ else
+ {
+ int i;
+ uint8_t *srcPtr= src[plane];
+ uint8_t *dstPtr= dst[plane] + dstStride[plane]*y;
+ for(i=0; i<height; i++)
+ {
+ memcpy(dstPtr, srcPtr, length);
+ srcPtr+= srcStride[plane];
+ dstPtr+= dstStride[plane];
+ }
+ }
+ }
+ }
+ }
+ return srcSliceH;
+}
+
+static int gray16togray(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+
+ int length= c->srcW;
+ int y= srcSliceY;
+ int height= srcSliceH;
+ int i, j;
+ uint8_t *srcPtr= src[0];
+ uint8_t *dstPtr= dst[0] + dstStride[0]*y;
+
+ if(!isGray(c->dstFormat)){
+ int height= -((-srcSliceH)>>c->chrDstVSubSample);
+ memset(dst[1], 128, dstStride[1]*height);
+ memset(dst[2], 128, dstStride[2]*height);
+ }
+ if(c->srcFormat == PIX_FMT_GRAY16LE) srcPtr++;
+ for(i=0; i<height; i++)
+ {
+ for(j=0; j<length; j++) dstPtr[j] = srcPtr[j<<1];
+ srcPtr+= srcStride[0];
+ dstPtr+= dstStride[0];
+ }
+ return srcSliceH;
+}
+
+static int graytogray16(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+
+ int length= c->srcW;
+ int y= srcSliceY;
+ int height= srcSliceH;
+ int i, j;
+ uint8_t *srcPtr= src[0];
+ uint8_t *dstPtr= dst[0] + dstStride[0]*y;
+ for(i=0; i<height; i++)
+ {
+ for(j=0; j<length; j++)
+ {
+ dstPtr[j<<1] = srcPtr[j];
+ dstPtr[(j<<1)+1] = srcPtr[j];
+ }
+ srcPtr+= srcStride[0];
+ dstPtr+= dstStride[0];
+ }
+ return srcSliceH;
+}
+
+static int gray16swap(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+
+ int length= c->srcW;
+ int y= srcSliceY;
+ int height= srcSliceH;
+ int i, j;
+ uint16_t *srcPtr= src[0];
+ uint16_t *dstPtr= dst[0] + dstStride[0]*y/2;
+ for(i=0; i<height; i++)
+ {
+ for(j=0; j<length; j++) dstPtr[j] = bswap_16(srcPtr[j]);
+ srcPtr+= srcStride[0]/2;
+ dstPtr+= dstStride[0]/2;
+ }
+ return srcSliceH;
+}
+
+
+static void getSubSampleFactors(int *h, int *v, int format){
+ switch(format){
+ case PIX_FMT_UYVY422:
+ case PIX_FMT_YUYV422:
+ *h=1;
+ *v=0;
+ break;
+ case PIX_FMT_YUV420P:
+ case PIX_FMT_GRAY16BE:
+ case PIX_FMT_GRAY16LE:
+ case PIX_FMT_GRAY8: //FIXME remove after different subsamplings are fully implemented
+ case PIX_FMT_NV12:
+ case PIX_FMT_NV21:
+ *h=1;
+ *v=1;
+ break;
+ case PIX_FMT_YUV410P:
+ *h=2;
+ *v=2;
+ break;
+ case PIX_FMT_YUV444P:
+ *h=0;
+ *v=0;
+ break;
+ case PIX_FMT_YUV422P:
+ *h=1;
+ *v=0;
+ break;
+ case PIX_FMT_YUV411P:
+ *h=2;
+ *v=0;
+ break;
+ default:
+ *h=0;
+ *v=0;
+ break;
+ }
+}
+
+static uint16_t roundToInt16(int64_t f){
+ int r= (f + (1<<15))>>16;
+ if(r<-0x7FFF) return 0x8000;
+ else if(r> 0x7FFF) return 0x7FFF;
+ else return r;
+}
+
+/**
+ * @param inv_table the yuv2rgb coeffs, normally Inverse_Table_6_9[x]
+ * @param fullRange if 1 then the luma range is 0..255 if 0 its 16..235
+ * @return -1 if not supported
+ */
+int sws_setColorspaceDetails(SwsContext *c, const int inv_table[4], int srcRange, const int table[4], int dstRange, int brightness, int contrast, int saturation){
+ int64_t crv = inv_table[0];
+ int64_t cbu = inv_table[1];
+ int64_t cgu = -inv_table[2];
+ int64_t cgv = -inv_table[3];
+ int64_t cy = 1<<16;
+ int64_t oy = 0;
+
+ if(isYUV(c->dstFormat) || isGray(c->dstFormat)) return -1;
+ memcpy(c->srcColorspaceTable, inv_table, sizeof(int)*4);
+ memcpy(c->dstColorspaceTable, table, sizeof(int)*4);
+
+ c->brightness= brightness;
+ c->contrast = contrast;
+ c->saturation= saturation;
+ c->srcRange = srcRange;
+ c->dstRange = dstRange;
+
+ c->uOffset= 0x0400040004000400LL;
+ c->vOffset= 0x0400040004000400LL;
+
+ if(!srcRange){
+ cy= (cy*255) / 219;
+ oy= 16<<16;
+ }
+
+ cy = (cy *contrast )>>16;
+ crv= (crv*contrast * saturation)>>32;
+ cbu= (cbu*contrast * saturation)>>32;
+ cgu= (cgu*contrast * saturation)>>32;
+ cgv= (cgv*contrast * saturation)>>32;
+
+ oy -= 256*brightness;
+
+ c->yCoeff= roundToInt16(cy *8192) * 0x0001000100010001ULL;
+ c->vrCoeff= roundToInt16(crv*8192) * 0x0001000100010001ULL;
+ c->ubCoeff= roundToInt16(cbu*8192) * 0x0001000100010001ULL;
+ c->vgCoeff= roundToInt16(cgv*8192) * 0x0001000100010001ULL;
+ c->ugCoeff= roundToInt16(cgu*8192) * 0x0001000100010001ULL;
+ c->yOffset= roundToInt16(oy * 8) * 0x0001000100010001ULL;
+
+ yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness, contrast, saturation);
+ //FIXME factorize
+
+#ifdef COMPILE_ALTIVEC
+ if (c->flags & SWS_CPU_CAPS_ALTIVEC)
+ yuv2rgb_altivec_init_tables (c, inv_table, brightness, contrast, saturation);
+#endif
+ return 0;
+}
+
+/**
+ * @return -1 if not supported
+ */
+int sws_getColorspaceDetails(SwsContext *c, int **inv_table, int *srcRange, int **table, int *dstRange, int *brightness, int *contrast, int *saturation){
+ if(isYUV(c->dstFormat) || isGray(c->dstFormat)) return -1;
+
+ *inv_table = c->srcColorspaceTable;
+ *table = c->dstColorspaceTable;
+ *srcRange = c->srcRange;
+ *dstRange = c->dstRange;
+ *brightness= c->brightness;
+ *contrast = c->contrast;
+ *saturation= c->saturation;
+
+ return 0;
+}
+
+static int handle_jpeg(int *format)
+{
+ switch (*format) {
+ case PIX_FMT_YUVJ420P:
+ *format = PIX_FMT_YUV420P;
+ return 1;
+ case PIX_FMT_YUVJ422P:
+ *format = PIX_FMT_YUV422P;
+ return 1;
+ case PIX_FMT_YUVJ444P:
+ *format = PIX_FMT_YUV444P;
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+SwsContext *sws_getContext(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat, int flags,
+ SwsFilter *srcFilter, SwsFilter *dstFilter, double *param){
+
+ SwsContext *c;
+ int i;
+ int usesVFilter, usesHFilter;
+ int unscaled, needsDither;
+ int srcRange, dstRange;
+ SwsFilter dummyFilter= {NULL, NULL, NULL, NULL};
+#if defined(ARCH_X86)
+ if(flags & SWS_CPU_CAPS_MMX)
+ asm volatile("emms\n\t"::: "memory");
+#endif
+
+#ifndef RUNTIME_CPUDETECT //ensure that the flags match the compiled variant if cpudetect is off
+ flags &= ~(SWS_CPU_CAPS_MMX|SWS_CPU_CAPS_MMX2|SWS_CPU_CAPS_3DNOW|SWS_CPU_CAPS_ALTIVEC);
+#ifdef HAVE_MMX2
+ flags |= SWS_CPU_CAPS_MMX|SWS_CPU_CAPS_MMX2;
+#elif defined (HAVE_3DNOW)
+ flags |= SWS_CPU_CAPS_MMX|SWS_CPU_CAPS_3DNOW;
+#elif defined (HAVE_MMX)
+ flags |= SWS_CPU_CAPS_MMX;
+#elif defined (HAVE_ALTIVEC)
+ flags |= SWS_CPU_CAPS_ALTIVEC;
+#endif
+#endif /* RUNTIME_CPUDETECT */
+ if(clip_table[512] != 255) globalInit();
+ if(rgb15to16 == NULL) sws_rgb2rgb_init(flags);
+
+ unscaled = (srcW == dstW && srcH == dstH);
+ needsDither= (isBGR(dstFormat) || isRGB(dstFormat))
+ && (fmt_depth(dstFormat))<24
+ && ((fmt_depth(dstFormat))<(fmt_depth(srcFormat)) || (!(isRGB(srcFormat) || isBGR(srcFormat))));
+
+ srcRange = handle_jpeg(&srcFormat);
+ dstRange = handle_jpeg(&dstFormat);
+
+ if(!isSupportedIn(srcFormat))
+ {
+ MSG_ERR("swScaler: %s is not supported as input format\n", sws_format_name(srcFormat));
+ return NULL;
+ }
+ if(!isSupportedOut(dstFormat))
+ {
+ MSG_ERR("swScaler: %s is not supported as output format\n", sws_format_name(dstFormat));
+ return NULL;
+ }
+
+ /* sanity check */
+ if(srcW<4 || srcH<1 || dstW<8 || dstH<1) //FIXME check if these are enough and try to lowwer them after fixing the relevant parts of the code
+ {
+ MSG_ERR("swScaler: %dx%d -> %dx%d is invalid scaling dimension\n",
+ srcW, srcH, dstW, dstH);
+ return NULL;
+ }
+
+ if(!dstFilter) dstFilter= &dummyFilter;
+ if(!srcFilter) srcFilter= &dummyFilter;
+
+ c= av_malloc(sizeof(SwsContext));
+ memset(c, 0, sizeof(SwsContext));
+
+ c->srcW= srcW;
+ c->srcH= srcH;
+ c->dstW= dstW;
+ c->dstH= dstH;
+ c->lumXInc= ((srcW<<16) + (dstW>>1))/dstW;
+ c->lumYInc= ((srcH<<16) + (dstH>>1))/dstH;
+ c->flags= flags;
+ c->dstFormat= dstFormat;
+ c->srcFormat= srcFormat;
+ c->vRounder= 4* 0x0001000100010001ULL;
+
+ usesHFilter= usesVFilter= 0;
+ if(dstFilter->lumV!=NULL && dstFilter->lumV->length>1) usesVFilter=1;
+ if(dstFilter->lumH!=NULL && dstFilter->lumH->length>1) usesHFilter=1;
+ if(dstFilter->chrV!=NULL && dstFilter->chrV->length>1) usesVFilter=1;
+ if(dstFilter->chrH!=NULL && dstFilter->chrH->length>1) usesHFilter=1;
+ if(srcFilter->lumV!=NULL && srcFilter->lumV->length>1) usesVFilter=1;
+ if(srcFilter->lumH!=NULL && srcFilter->lumH->length>1) usesHFilter=1;
+ if(srcFilter->chrV!=NULL && srcFilter->chrV->length>1) usesVFilter=1;
+ if(srcFilter->chrH!=NULL && srcFilter->chrH->length>1) usesHFilter=1;
+
+ getSubSampleFactors(&c->chrSrcHSubSample, &c->chrSrcVSubSample, srcFormat);
+ getSubSampleFactors(&c->chrDstHSubSample, &c->chrDstVSubSample, dstFormat);
+
+ // reuse chroma for 2 pixles rgb/bgr unless user wants full chroma interpolation
+ if((isBGR(dstFormat) || isRGB(dstFormat)) && !(flags&SWS_FULL_CHR_H_INT)) c->chrDstHSubSample=1;
+
+ // drop some chroma lines if the user wants it
+ c->vChrDrop= (flags&SWS_SRC_V_CHR_DROP_MASK)>>SWS_SRC_V_CHR_DROP_SHIFT;
+ c->chrSrcVSubSample+= c->vChrDrop;
+
+ // drop every 2. pixel for chroma calculation unless user wants full chroma
+ if((isBGR(srcFormat) || isRGB(srcFormat)) && !(flags&SWS_FULL_CHR_H_INP))
+ c->chrSrcHSubSample=1;
+
+ if(param){
+ c->param[0] = param[0];
+ c->param[1] = param[1];
+ }else{
+ c->param[0] =
+ c->param[1] = SWS_PARAM_DEFAULT;
+ }
+
+ c->chrIntHSubSample= c->chrDstHSubSample;
+ c->chrIntVSubSample= c->chrSrcVSubSample;
+
+ // note the -((-x)>>y) is so that we allways round toward +inf
+ c->chrSrcW= -((-srcW) >> c->chrSrcHSubSample);
+ c->chrSrcH= -((-srcH) >> c->chrSrcVSubSample);
+ c->chrDstW= -((-dstW) >> c->chrDstHSubSample);
+ c->chrDstH= -((-dstH) >> c->chrDstVSubSample);
+
+ sws_setColorspaceDetails(c, Inverse_Table_6_9[SWS_CS_DEFAULT], srcRange, Inverse_Table_6_9[SWS_CS_DEFAULT] /* FIXME*/, dstRange, 0, 1<<16, 1<<16);
+
+ /* unscaled special Cases */
+ if(unscaled && !usesHFilter && !usesVFilter)
+ {
+ /* yv12_to_nv12 */
+ if(srcFormat == PIX_FMT_YUV420P && (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21))
+ {
+ c->swScale= PlanarToNV12Wrapper;
+ }
+ /* yuv2bgr */
+ if((srcFormat==PIX_FMT_YUV420P || srcFormat==PIX_FMT_YUV422P) && (isBGR(dstFormat) || isRGB(dstFormat)))
+ {
+ c->swScale= yuv2rgb_get_func_ptr(c);
+ }
+
+ if( srcFormat==PIX_FMT_YUV410P && dstFormat==PIX_FMT_YUV420P )
+ {
+ c->swScale= yvu9toyv12Wrapper;
+ }
+
+ /* bgr24toYV12 */
+ if(srcFormat==PIX_FMT_BGR24 && dstFormat==PIX_FMT_YUV420P)
+ c->swScale= bgr24toyv12Wrapper;
+
+ /* rgb/bgr -> rgb/bgr (no dither needed forms) */
+ if( (isBGR(srcFormat) || isRGB(srcFormat))
+ && (isBGR(dstFormat) || isRGB(dstFormat))
+ && !needsDither)
+ c->swScale= rgb2rgbWrapper;
+
+ /* LQ converters if -sws 0 or -sws 4*/
+ if(c->flags&(SWS_FAST_BILINEAR|SWS_POINT)){
+ /* rgb/bgr -> rgb/bgr (dither needed forms) */
+ if( (isBGR(srcFormat) || isRGB(srcFormat))
+ && (isBGR(dstFormat) || isRGB(dstFormat))
+ && needsDither)
+ c->swScale= rgb2rgbWrapper;
+
+ /* yv12_to_yuy2 */
+ if(srcFormat == PIX_FMT_YUV420P &&
+ (dstFormat == PIX_FMT_YUYV422 || dstFormat == PIX_FMT_UYVY422))
+ {
+ if (dstFormat == PIX_FMT_YUYV422)
+ c->swScale= PlanarToYuy2Wrapper;
+ else
+ c->swScale= PlanarToUyvyWrapper;
+ }
+ }
+
+#ifdef COMPILE_ALTIVEC
+ if ((c->flags & SWS_CPU_CAPS_ALTIVEC) &&
+ ((srcFormat == PIX_FMT_YUV420P &&
+ (dstFormat == PIX_FMT_YUYV422 || dstFormat == PIX_FMT_UYVY422)))) {
+ // unscaled YV12 -> packed YUV, we want speed
+ if (dstFormat == PIX_FMT_YUYV422)
+ c->swScale= yv12toyuy2_unscaled_altivec;
+ else
+ c->swScale= yv12touyvy_unscaled_altivec;
+ }
+#endif
+
+ /* simple copy */
+ if( srcFormat == dstFormat
+ || (isPlanarYUV(srcFormat) && isGray(dstFormat))
+ || (isPlanarYUV(dstFormat) && isGray(srcFormat))
+ )
+ {
+ c->swScale= simpleCopy;
+ }
+
+ /* gray16{le,be} conversions */
+ if(isGray16(srcFormat) && (isPlanarYUV(dstFormat) || (dstFormat == PIX_FMT_GRAY8)))
+ {
+ c->swScale= gray16togray;
+ }
+ if((isPlanarYUV(srcFormat) || (srcFormat == PIX_FMT_GRAY8)) && isGray16(dstFormat))
+ {
+ c->swScale= graytogray16;
+ }
+ if(srcFormat != dstFormat && isGray16(srcFormat) && isGray16(dstFormat))
+ {
+ c->swScale= gray16swap;
+ }
+
+ if(c->swScale){
+ if(flags&SWS_PRINT_INFO)
+ MSG_INFO("SwScaler: using unscaled %s -> %s special converter\n",
+ sws_format_name(srcFormat), sws_format_name(dstFormat));
+ return c;
+ }
+ }
+
+ if(flags & SWS_CPU_CAPS_MMX2)
+ {
+ c->canMMX2BeUsed= (dstW >=srcW && (dstW&31)==0 && (srcW&15)==0) ? 1 : 0;
+ if(!c->canMMX2BeUsed && dstW >=srcW && (srcW&15)==0 && (flags&SWS_FAST_BILINEAR))
+ {
+ if(flags&SWS_PRINT_INFO)
+ MSG_INFO("SwScaler: output Width is not a multiple of 32 -> no MMX2 scaler\n");
+ }
+ if(usesHFilter) c->canMMX2BeUsed=0;
+ }
+ else
+ c->canMMX2BeUsed=0;
+
+ c->chrXInc= ((c->chrSrcW<<16) + (c->chrDstW>>1))/c->chrDstW;
+ c->chrYInc= ((c->chrSrcH<<16) + (c->chrDstH>>1))/c->chrDstH;
+
+ // match pixel 0 of the src to pixel 0 of dst and match pixel n-2 of src to pixel n-2 of dst
+ // but only for the FAST_BILINEAR mode otherwise do correct scaling
+ // n-2 is the last chrominance sample available
+ // this is not perfect, but noone shuld notice the difference, the more correct variant
+ // would be like the vertical one, but that would require some special code for the
+ // first and last pixel
+ if(flags&SWS_FAST_BILINEAR)
+ {
+ if(c->canMMX2BeUsed)
+ {
+ c->lumXInc+= 20;
+ c->chrXInc+= 20;
+ }
+ //we don't use the x86asm scaler if mmx is available
+ else if(flags & SWS_CPU_CAPS_MMX)
+ {
+ c->lumXInc = ((srcW-2)<<16)/(dstW-2) - 20;
+ c->chrXInc = ((c->chrSrcW-2)<<16)/(c->chrDstW-2) - 20;
+ }
+ }
+
+ /* precalculate horizontal scaler filter coefficients */
+ {
+ const int filterAlign=
+ (flags & SWS_CPU_CAPS_MMX) ? 4 :
+ (flags & SWS_CPU_CAPS_ALTIVEC) ? 8 :
+ 1;
+
+ initFilter(&c->hLumFilter, &c->hLumFilterPos, &c->hLumFilterSize, c->lumXInc,
+ srcW , dstW, filterAlign, 1<<14,
+ (flags&SWS_BICUBLIN) ? (flags|SWS_BICUBIC) : flags,
+ srcFilter->lumH, dstFilter->lumH, c->param);
+ initFilter(&c->hChrFilter, &c->hChrFilterPos, &c->hChrFilterSize, c->chrXInc,
+ c->chrSrcW, c->chrDstW, filterAlign, 1<<14,
+ (flags&SWS_BICUBLIN) ? (flags|SWS_BILINEAR) : flags,
+ srcFilter->chrH, dstFilter->chrH, c->param);
+
+#define MAX_FUNNY_CODE_SIZE 10000
+#if defined(COMPILE_MMX2)
+// can't downscale !!!
+ if(c->canMMX2BeUsed && (flags & SWS_FAST_BILINEAR))
+ {
+#ifdef MAP_ANONYMOUS
+ c->funnyYCode = (uint8_t*)mmap(NULL, MAX_FUNNY_CODE_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+ c->funnyUVCode = (uint8_t*)mmap(NULL, MAX_FUNNY_CODE_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+#else
+ c->funnyYCode = av_malloc(MAX_FUNNY_CODE_SIZE);
+ c->funnyUVCode = av_malloc(MAX_FUNNY_CODE_SIZE);
+#endif
+
+ c->lumMmx2Filter = av_malloc((dstW /8+8)*sizeof(int16_t));
+ c->chrMmx2Filter = av_malloc((c->chrDstW /4+8)*sizeof(int16_t));
+ c->lumMmx2FilterPos= av_malloc((dstW /2/8+8)*sizeof(int32_t));
+ c->chrMmx2FilterPos= av_malloc((c->chrDstW/2/4+8)*sizeof(int32_t));
+
+ initMMX2HScaler( dstW, c->lumXInc, c->funnyYCode , c->lumMmx2Filter, c->lumMmx2FilterPos, 8);
+ initMMX2HScaler(c->chrDstW, c->chrXInc, c->funnyUVCode, c->chrMmx2Filter, c->chrMmx2FilterPos, 4);
+ }
+#endif /* defined(COMPILE_MMX2) */
+ } // Init Horizontal stuff
+
+
+
+ /* precalculate vertical scaler filter coefficients */
+ {
+ const int filterAlign=
+ (flags & SWS_CPU_CAPS_MMX) && (flags & SWS_ACCURATE_RND) ? 2 :
+ (flags & SWS_CPU_CAPS_ALTIVEC) ? 8 :
+ 1;
+
+ initFilter(&c->vLumFilter, &c->vLumFilterPos, &c->vLumFilterSize, c->lumYInc,
+ srcH , dstH, filterAlign, (1<<12)-4,
+ (flags&SWS_BICUBLIN) ? (flags|SWS_BICUBIC) : flags,
+ srcFilter->lumV, dstFilter->lumV, c->param);
+ initFilter(&c->vChrFilter, &c->vChrFilterPos, &c->vChrFilterSize, c->chrYInc,
+ c->chrSrcH, c->chrDstH, filterAlign, (1<<12)-4,
+ (flags&SWS_BICUBLIN) ? (flags|SWS_BILINEAR) : flags,
+ srcFilter->chrV, dstFilter->chrV, c->param);
+
+#ifdef HAVE_ALTIVEC
+ c->vYCoeffsBank = av_malloc(sizeof (vector signed short)*c->vLumFilterSize*c->dstH);
+ c->vCCoeffsBank = av_malloc(sizeof (vector signed short)*c->vChrFilterSize*c->chrDstH);
+
+ for (i=0;i<c->vLumFilterSize*c->dstH;i++) {
+ int j;
+ short *p = (short *)&c->vYCoeffsBank[i];
+ for (j=0;j<8;j++)
+ p[j] = c->vLumFilter[i];
+ }
+
+ for (i=0;i<c->vChrFilterSize*c->chrDstH;i++) {
+ int j;
+ short *p = (short *)&c->vCCoeffsBank[i];
+ for (j=0;j<8;j++)
+ p[j] = c->vChrFilter[i];
+ }
+#endif
+ }
+
+ // Calculate Buffer Sizes so that they won't run out while handling these damn slices
+ c->vLumBufSize= c->vLumFilterSize;
+ c->vChrBufSize= c->vChrFilterSize;
+ for(i=0; i<dstH; i++)
+ {
+ int chrI= i*c->chrDstH / dstH;
+ int nextSlice= FFMAX(c->vLumFilterPos[i ] + c->vLumFilterSize - 1,
+ ((c->vChrFilterPos[chrI] + c->vChrFilterSize - 1)<<c->chrSrcVSubSample));
+
+ nextSlice>>= c->chrSrcVSubSample;
+ nextSlice<<= c->chrSrcVSubSample;
+ if(c->vLumFilterPos[i ] + c->vLumBufSize < nextSlice)
+ c->vLumBufSize= nextSlice - c->vLumFilterPos[i ];
+ if(c->vChrFilterPos[chrI] + c->vChrBufSize < (nextSlice>>c->chrSrcVSubSample))
+ c->vChrBufSize= (nextSlice>>c->chrSrcVSubSample) - c->vChrFilterPos[chrI];
+ }
+
+ // allocate pixbufs (we use dynamic allocation because otherwise we would need to
+ c->lumPixBuf= av_malloc(c->vLumBufSize*2*sizeof(int16_t*));
+ c->chrPixBuf= av_malloc(c->vChrBufSize*2*sizeof(int16_t*));
+ //Note we need at least one pixel more at the end because of the mmx code (just in case someone wanna replace the 4000/8000)
+ /* align at 16 bytes for AltiVec */
+ for(i=0; i<c->vLumBufSize; i++)
+ c->lumPixBuf[i]= c->lumPixBuf[i+c->vLumBufSize]= av_malloc(4000);
+ for(i=0; i<c->vChrBufSize; i++)
+ c->chrPixBuf[i]= c->chrPixBuf[i+c->vChrBufSize]= av_malloc(8000);
+
+ //try to avoid drawing green stuff between the right end and the stride end
+ for(i=0; i<c->vLumBufSize; i++) memset(c->lumPixBuf[i], 0, 4000);
+ for(i=0; i<c->vChrBufSize; i++) memset(c->chrPixBuf[i], 64, 8000);
+
+ ASSERT(c->chrDstH <= dstH)
+
+ if(flags&SWS_PRINT_INFO)
+ {
+#ifdef DITHER1XBPP
+ char *dither= " dithered";
+#else
+ char *dither= "";
+#endif
+ if(flags&SWS_FAST_BILINEAR)
+ MSG_INFO("SwScaler: FAST_BILINEAR scaler, ");
+ else if(flags&SWS_BILINEAR)
+ MSG_INFO("SwScaler: BILINEAR scaler, ");
+ else if(flags&SWS_BICUBIC)
+ MSG_INFO("SwScaler: BICUBIC scaler, ");
+ else if(flags&SWS_X)
+ MSG_INFO("SwScaler: Experimental scaler, ");
+ else if(flags&SWS_POINT)
+ MSG_INFO("SwScaler: Nearest Neighbor / POINT scaler, ");
+ else if(flags&SWS_AREA)
+ MSG_INFO("SwScaler: Area Averageing scaler, ");
+ else if(flags&SWS_BICUBLIN)
+ MSG_INFO("SwScaler: luma BICUBIC / chroma BILINEAR scaler, ");
+ else if(flags&SWS_GAUSS)
+ MSG_INFO("SwScaler: Gaussian scaler, ");
+ else if(flags&SWS_SINC)
+ MSG_INFO("SwScaler: Sinc scaler, ");
+ else if(flags&SWS_LANCZOS)
+ MSG_INFO("SwScaler: Lanczos scaler, ");
+ else if(flags&SWS_SPLINE)
+ MSG_INFO("SwScaler: Bicubic spline scaler, ");
+ else
+ MSG_INFO("SwScaler: ehh flags invalid?! ");
+
+ if(dstFormat==PIX_FMT_BGR555 || dstFormat==PIX_FMT_BGR565)
+ MSG_INFO("from %s to%s %s ",
+ sws_format_name(srcFormat), dither, sws_format_name(dstFormat));
+ else
+ MSG_INFO("from %s to %s ",
+ sws_format_name(srcFormat), sws_format_name(dstFormat));
+
+ if(flags & SWS_CPU_CAPS_MMX2)
+ MSG_INFO("using MMX2\n");
+ else if(flags & SWS_CPU_CAPS_3DNOW)
+ MSG_INFO("using 3DNOW\n");
+ else if(flags & SWS_CPU_CAPS_MMX)
+ MSG_INFO("using MMX\n");
+ else if(flags & SWS_CPU_CAPS_ALTIVEC)
+ MSG_INFO("using AltiVec\n");
+ else
+ MSG_INFO("using C\n");
+ }
+
+ if(flags & SWS_PRINT_INFO)
+ {
+ if(flags & SWS_CPU_CAPS_MMX)
+ {
+ if(c->canMMX2BeUsed && (flags&SWS_FAST_BILINEAR))
+ MSG_V("SwScaler: using FAST_BILINEAR MMX2 scaler for horizontal scaling\n");
+ else
+ {
+ if(c->hLumFilterSize==4)
+ MSG_V("SwScaler: using 4-tap MMX scaler for horizontal luminance scaling\n");
+ else if(c->hLumFilterSize==8)
+ MSG_V("SwScaler: using 8-tap MMX scaler for horizontal luminance scaling\n");
+ else
+ MSG_V("SwScaler: using n-tap MMX scaler for horizontal luminance scaling\n");
+
+ if(c->hChrFilterSize==4)
+ MSG_V("SwScaler: using 4-tap MMX scaler for horizontal chrominance scaling\n");
+ else if(c->hChrFilterSize==8)
+ MSG_V("SwScaler: using 8-tap MMX scaler for horizontal chrominance scaling\n");
+ else
+ MSG_V("SwScaler: using n-tap MMX scaler for horizontal chrominance scaling\n");
+ }
+ }
+ else
+ {
+#if defined(ARCH_X86)
+ MSG_V("SwScaler: using X86-Asm scaler for horizontal scaling\n");
+#else
+ if(flags & SWS_FAST_BILINEAR)
+ MSG_V("SwScaler: using FAST_BILINEAR C scaler for horizontal scaling\n");
+ else
+ MSG_V("SwScaler: using C scaler for horizontal scaling\n");
+#endif
+ }
+ if(isPlanarYUV(dstFormat))
+ {
+ if(c->vLumFilterSize==1)
+ MSG_V("SwScaler: using 1-tap %s \"scaler\" for vertical scaling (YV12 like)\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C");
+ else
+ MSG_V("SwScaler: using n-tap %s scaler for vertical scaling (YV12 like)\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C");
+ }
+ else
+ {
+ if(c->vLumFilterSize==1 && c->vChrFilterSize==2)
+ MSG_V("SwScaler: using 1-tap %s \"scaler\" for vertical luminance scaling (BGR)\n"
+ "SwScaler: 2-tap scaler for vertical chrominance scaling (BGR)\n",(flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C");
+ else if(c->vLumFilterSize==2 && c->vChrFilterSize==2)
+ MSG_V("SwScaler: using 2-tap linear %s scaler for vertical scaling (BGR)\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C");
+ else
+ MSG_V("SwScaler: using n-tap %s scaler for vertical scaling (BGR)\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C");
+ }
+
+ if(dstFormat==PIX_FMT_BGR24)
+ MSG_V("SwScaler: using %s YV12->BGR24 Converter\n",
+ (flags & SWS_CPU_CAPS_MMX2) ? "MMX2" : ((flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C"));
+ else if(dstFormat==PIX_FMT_RGB32)
+ MSG_V("SwScaler: using %s YV12->BGR32 Converter\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C");
+ else if(dstFormat==PIX_FMT_BGR565)
+ MSG_V("SwScaler: using %s YV12->BGR16 Converter\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C");
+ else if(dstFormat==PIX_FMT_BGR555)
+ MSG_V("SwScaler: using %s YV12->BGR15 Converter\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C");
+
+ MSG_V("SwScaler: %dx%d -> %dx%d\n", srcW, srcH, dstW, dstH);
+ }
+ if(flags & SWS_PRINT_INFO)
+ {
+ MSG_DBG2("SwScaler:Lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
+ c->srcW, c->srcH, c->dstW, c->dstH, c->lumXInc, c->lumYInc);
+ MSG_DBG2("SwScaler:Chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
+ c->chrSrcW, c->chrSrcH, c->chrDstW, c->chrDstH, c->chrXInc, c->chrYInc);
+ }
+
+ c->swScale= getSwsFunc(flags);
+ return c;
+}
+
+/**
+ * swscale warper, so we don't need to export the SwsContext.
+ * assumes planar YUV to be in YUV order instead of YVU
+ */
+int sws_scale_ordered(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+ if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
+ MSG_ERR("swScaler: slices start in the middle!\n");
+ return 0;
+ }
+ if (c->sliceDir == 0) {
+ if (srcSliceY == 0) c->sliceDir = 1; else c->sliceDir = -1;
+ }
+
+ // copy strides, so they can safely be modified
+ if (c->sliceDir == 1) {
+ // slices go from top to bottom
+ int srcStride2[3]= {srcStride[0], srcStride[1], srcStride[2]};
+ int dstStride2[3]= {dstStride[0], dstStride[1], dstStride[2]};
+ return c->swScale(c, src, srcStride2, srcSliceY, srcSliceH, dst, dstStride2);
+ } else {
+ // slices go from bottom to top => we flip the image internally
+ uint8_t* src2[3]= {src[0] + (srcSliceH-1)*srcStride[0],
+ src[1] + ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[1],
+ src[2] + ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[2]
+ };
+ uint8_t* dst2[3]= {dst[0] + (c->dstH-1)*dstStride[0],
+ dst[1] + ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[1],
+ dst[2] + ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[2]};
+ int srcStride2[3]= {-srcStride[0], -srcStride[1], -srcStride[2]};
+ int dstStride2[3]= {-dstStride[0], -dstStride[1], -dstStride[2]};
+
+ return c->swScale(c, src2, srcStride2, c->srcH-srcSliceY-srcSliceH, srcSliceH, dst2, dstStride2);
+ }
+}
+
+/**
+ * swscale warper, so we don't need to export the SwsContext
+ */
+int sws_scale(SwsContext *c, uint8_t* srcParam[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dstParam[], int dstStride[]){
+ uint8_t *src[3];
+ uint8_t *dst[3];
+ src[0] = srcParam[0]; src[1] = srcParam[1]; src[2] = srcParam[2];
+ dst[0] = dstParam[0]; dst[1] = dstParam[1]; dst[2] = dstParam[2];
+//printf("sws: slice %d %d\n", srcSliceY, srcSliceH);
+
+ return c->swScale(c, src, srcStride, srcSliceY, srcSliceH, dst, dstStride);
+}
+
+SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur,
+ float lumaSharpen, float chromaSharpen,
+ float chromaHShift, float chromaVShift,
+ int verbose)
+{
+ SwsFilter *filter= av_malloc(sizeof(SwsFilter));
+
+ if(lumaGBlur!=0.0){
+ filter->lumH= sws_getGaussianVec(lumaGBlur, 3.0);
+ filter->lumV= sws_getGaussianVec(lumaGBlur, 3.0);
+ }else{
+ filter->lumH= sws_getIdentityVec();
+ filter->lumV= sws_getIdentityVec();
+ }
+
+ if(chromaGBlur!=0.0){
+ filter->chrH= sws_getGaussianVec(chromaGBlur, 3.0);
+ filter->chrV= sws_getGaussianVec(chromaGBlur, 3.0);
+ }else{
+ filter->chrH= sws_getIdentityVec();
+ filter->chrV= sws_getIdentityVec();
+ }
+
+ if(chromaSharpen!=0.0){
+ SwsVector *id= sws_getIdentityVec();
+ sws_scaleVec(filter->chrH, -chromaSharpen);
+ sws_scaleVec(filter->chrV, -chromaSharpen);
+ sws_addVec(filter->chrH, id);
+ sws_addVec(filter->chrV, id);
+ sws_freeVec(id);
+ }
+
+ if(lumaSharpen!=0.0){
+ SwsVector *id= sws_getIdentityVec();
+ sws_scaleVec(filter->lumH, -lumaSharpen);
+ sws_scaleVec(filter->lumV, -lumaSharpen);
+ sws_addVec(filter->lumH, id);
+ sws_addVec(filter->lumV, id);
+ sws_freeVec(id);
+ }
+
+ if(chromaHShift != 0.0)
+ sws_shiftVec(filter->chrH, (int)(chromaHShift+0.5));
+
+ if(chromaVShift != 0.0)
+ sws_shiftVec(filter->chrV, (int)(chromaVShift+0.5));
+
+ sws_normalizeVec(filter->chrH, 1.0);
+ sws_normalizeVec(filter->chrV, 1.0);
+ sws_normalizeVec(filter->lumH, 1.0);
+ sws_normalizeVec(filter->lumV, 1.0);
+
+ if(verbose) sws_printVec(filter->chrH);
+ if(verbose) sws_printVec(filter->lumH);
+
+ return filter;
+}
+
+/**
+ * returns a normalized gaussian curve used to filter stuff
+ * quality=3 is high quality, lowwer is lowwer quality
+ */
+SwsVector *sws_getGaussianVec(double variance, double quality){
+ const int length= (int)(variance*quality + 0.5) | 1;
+ int i;
+ double *coeff= av_malloc(length*sizeof(double));
+ double middle= (length-1)*0.5;
+ SwsVector *vec= av_malloc(sizeof(SwsVector));
+
+ vec->coeff= coeff;
+ vec->length= length;
+
+ for(i=0; i<length; i++)
+ {
+ double dist= i-middle;
+ coeff[i]= exp( -dist*dist/(2*variance*variance) ) / sqrt(2*variance*PI);
+ }
+
+ sws_normalizeVec(vec, 1.0);
+
+ return vec;
+}
+
+SwsVector *sws_getConstVec(double c, int length){
+ int i;
+ double *coeff= av_malloc(length*sizeof(double));
+ SwsVector *vec= av_malloc(sizeof(SwsVector));
+
+ vec->coeff= coeff;
+ vec->length= length;
+
+ for(i=0; i<length; i++)
+ coeff[i]= c;
+
+ return vec;
+}
+
+
+SwsVector *sws_getIdentityVec(void){
+ return sws_getConstVec(1.0, 1);
+}
+
+double sws_dcVec(SwsVector *a){
+ int i;
+ double sum=0;
+
+ for(i=0; i<a->length; i++)
+ sum+= a->coeff[i];
+
+ return sum;
+}
+
+void sws_scaleVec(SwsVector *a, double scalar){
+ int i;
+
+ for(i=0; i<a->length; i++)
+ a->coeff[i]*= scalar;
+}
+
+void sws_normalizeVec(SwsVector *a, double height){
+ sws_scaleVec(a, height/sws_dcVec(a));
+}
+
+static SwsVector *sws_getConvVec(SwsVector *a, SwsVector *b){
+ int length= a->length + b->length - 1;
+ double *coeff= av_malloc(length*sizeof(double));
+ int i, j;
+ SwsVector *vec= av_malloc(sizeof(SwsVector));
+
+ vec->coeff= coeff;
+ vec->length= length;
+
+ for(i=0; i<length; i++) coeff[i]= 0.0;
+
+ for(i=0; i<a->length; i++)
+ {
+ for(j=0; j<b->length; j++)
+ {
+ coeff[i+j]+= a->coeff[i]*b->coeff[j];
+ }
+ }
+
+ return vec;
+}
+
+static SwsVector *sws_sumVec(SwsVector *a, SwsVector *b){
+ int length= FFMAX(a->length, b->length);
+ double *coeff= av_malloc(length*sizeof(double));
+ int i;
+ SwsVector *vec= av_malloc(sizeof(SwsVector));
+
+ vec->coeff= coeff;
+ vec->length= length;
+
+ for(i=0; i<length; i++) coeff[i]= 0.0;
+
+ for(i=0; i<a->length; i++) coeff[i + (length-1)/2 - (a->length-1)/2]+= a->coeff[i];
+ for(i=0; i<b->length; i++) coeff[i + (length-1)/2 - (b->length-1)/2]+= b->coeff[i];
+
+ return vec;
+}
+
+static SwsVector *sws_diffVec(SwsVector *a, SwsVector *b){
+ int length= FFMAX(a->length, b->length);
+ double *coeff= av_malloc(length*sizeof(double));
+ int i;
+ SwsVector *vec= av_malloc(sizeof(SwsVector));
+
+ vec->coeff= coeff;
+ vec->length= length;
+
+ for(i=0; i<length; i++) coeff[i]= 0.0;
+
+ for(i=0; i<a->length; i++) coeff[i + (length-1)/2 - (a->length-1)/2]+= a->coeff[i];
+ for(i=0; i<b->length; i++) coeff[i + (length-1)/2 - (b->length-1)/2]-= b->coeff[i];
+
+ return vec;
+}
+
+/* shift left / or right if "shift" is negative */
+static SwsVector *sws_getShiftedVec(SwsVector *a, int shift){
+ int length= a->length + FFABS(shift)*2;
+ double *coeff= av_malloc(length*sizeof(double));
+ int i;
+ SwsVector *vec= av_malloc(sizeof(SwsVector));
+
+ vec->coeff= coeff;
+ vec->length= length;
+
+ for(i=0; i<length; i++) coeff[i]= 0.0;
+
+ for(i=0; i<a->length; i++)
+ {
+ coeff[i + (length-1)/2 - (a->length-1)/2 - shift]= a->coeff[i];
+ }
+
+ return vec;
+}
+
+void sws_shiftVec(SwsVector *a, int shift){
+ SwsVector *shifted= sws_getShiftedVec(a, shift);
+ av_free(a->coeff);
+ a->coeff= shifted->coeff;
+ a->length= shifted->length;
+ av_free(shifted);
+}
+
+void sws_addVec(SwsVector *a, SwsVector *b){
+ SwsVector *sum= sws_sumVec(a, b);
+ av_free(a->coeff);
+ a->coeff= sum->coeff;
+ a->length= sum->length;
+ av_free(sum);
+}
+
+void sws_subVec(SwsVector *a, SwsVector *b){
+ SwsVector *diff= sws_diffVec(a, b);
+ av_free(a->coeff);
+ a->coeff= diff->coeff;
+ a->length= diff->length;
+ av_free(diff);
+}
+
+void sws_convVec(SwsVector *a, SwsVector *b){
+ SwsVector *conv= sws_getConvVec(a, b);
+ av_free(a->coeff);
+ a->coeff= conv->coeff;
+ a->length= conv->length;
+ av_free(conv);
+}
+
+SwsVector *sws_cloneVec(SwsVector *a){
+ double *coeff= av_malloc(a->length*sizeof(double));
+ int i;
+ SwsVector *vec= av_malloc(sizeof(SwsVector));
+
+ vec->coeff= coeff;
+ vec->length= a->length;
+
+ for(i=0; i<a->length; i++) coeff[i]= a->coeff[i];
+
+ return vec;
+}
+
+void sws_printVec(SwsVector *a){
+ int i;
+ double max=0;
+ double min=0;
+ double range;
+
+ for(i=0; i<a->length; i++)
+ if(a->coeff[i]>max) max= a->coeff[i];
+
+ for(i=0; i<a->length; i++)
+ if(a->coeff[i]<min) min= a->coeff[i];
+
+ range= max - min;
+
+ for(i=0; i<a->length; i++)
+ {
+ int x= (int)((a->coeff[i]-min)*60.0/range +0.5);
+ MSG_DBG2("%1.3f ", a->coeff[i]);
+ for(;x>0; x--) MSG_DBG2(" ");
+ MSG_DBG2("|\n");
+ }
+}
+
+void sws_freeVec(SwsVector *a){
+ if(!a) return;
+ av_free(a->coeff);
+ a->coeff=NULL;
+ a->length=0;
+ av_free(a);
+}
+
+void sws_freeFilter(SwsFilter *filter){
+ if(!filter) return;
+
+ if(filter->lumH) sws_freeVec(filter->lumH);
+ if(filter->lumV) sws_freeVec(filter->lumV);
+ if(filter->chrH) sws_freeVec(filter->chrH);
+ if(filter->chrV) sws_freeVec(filter->chrV);
+ av_free(filter);
+}
+
+
+void sws_freeContext(SwsContext *c){
+ int i;
+ if(!c) return;
+
+ if(c->lumPixBuf)
+ {
+ for(i=0; i<c->vLumBufSize; i++)
+ {
+ av_free(c->lumPixBuf[i]);
+ c->lumPixBuf[i]=NULL;
+ }
+ av_free(c->lumPixBuf);
+ c->lumPixBuf=NULL;
+ }
+
+ if(c->chrPixBuf)
+ {
+ for(i=0; i<c->vChrBufSize; i++)
+ {
+ av_free(c->chrPixBuf[i]);
+ c->chrPixBuf[i]=NULL;
+ }
+ av_free(c->chrPixBuf);
+ c->chrPixBuf=NULL;
+ }
+
+ av_free(c->vLumFilter);
+ c->vLumFilter = NULL;
+ av_free(c->vChrFilter);
+ c->vChrFilter = NULL;
+ av_free(c->hLumFilter);
+ c->hLumFilter = NULL;
+ av_free(c->hChrFilter);
+ c->hChrFilter = NULL;
+#ifdef HAVE_ALTIVEC
+ av_free(c->vYCoeffsBank);
+ c->vYCoeffsBank = NULL;
+ av_free(c->vCCoeffsBank);
+ c->vCCoeffsBank = NULL;
+#endif
+
+ av_free(c->vLumFilterPos);
+ c->vLumFilterPos = NULL;
+ av_free(c->vChrFilterPos);
+ c->vChrFilterPos = NULL;
+ av_free(c->hLumFilterPos);
+ c->hLumFilterPos = NULL;
+ av_free(c->hChrFilterPos);
+ c->hChrFilterPos = NULL;
+
+#if defined(ARCH_X86)
+#ifdef MAP_ANONYMOUS
+ if(c->funnyYCode) munmap(c->funnyYCode, MAX_FUNNY_CODE_SIZE);
+ if(c->funnyUVCode) munmap(c->funnyUVCode, MAX_FUNNY_CODE_SIZE);
+#else
+ av_free(c->funnyYCode);
+ av_free(c->funnyUVCode);
+#endif
+ c->funnyYCode=NULL;
+ c->funnyUVCode=NULL;
+#endif /* defined(ARCH_X86) */
+
+ av_free(c->lumMmx2Filter);
+ c->lumMmx2Filter=NULL;
+ av_free(c->chrMmx2Filter);
+ c->chrMmx2Filter=NULL;
+ av_free(c->lumMmx2FilterPos);
+ c->lumMmx2FilterPos=NULL;
+ av_free(c->chrMmx2FilterPos);
+ c->chrMmx2FilterPos=NULL;
+ av_free(c->yuvTable);
+ c->yuvTable=NULL;
+
+ av_free(c);
+}
+
+/**
+ * Checks if context is valid or reallocs a new one instead.
+ * If context is NULL, just calls sws_getContext() to get a new one.
+ * Otherwise, checks if the parameters are the same already saved in context.
+ * If that is the case, returns the current context.
+ * Otherwise, frees context and gets a new one.
+ *
+ * Be warned that srcFilter, dstFilter are not checked, they are
+ * asumed to remain valid.
+ */
+struct SwsContext *sws_getCachedContext(struct SwsContext *context,
+ int srcW, int srcH, int srcFormat,
+ int dstW, int dstH, int dstFormat, int flags,
+ SwsFilter *srcFilter, SwsFilter *dstFilter, double *param)
+{
+ if (context != NULL) {
+ if ((context->srcW != srcW) || (context->srcH != srcH) ||
+ (context->srcFormat != srcFormat) ||
+ (context->dstW != dstW) || (context->dstH != dstH) ||
+ (context->dstFormat != dstFormat) || (context->flags != flags) ||
+ (context->param != param))
+ {
+ sws_freeContext(context);
+ context = NULL;
+ }
+ }
+ if (context == NULL) {
+ return sws_getContext(srcW, srcH, srcFormat,
+ dstW, dstH, dstFormat, flags,
+ srcFilter, dstFilter, param);
+ }
+ return context;
+}
+
diff --git a/contrib/ffmpeg/libswscale/swscale.h b/contrib/ffmpeg/libswscale/swscale.h
new file mode 100644
index 000000000..06088b8e4
--- /dev/null
+++ b/contrib/ffmpeg/libswscale/swscale.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have 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 SWSCALE_H
+#define SWSCALE_H
+
+/**
+ * @file swscale.h
+ * @brief
+ * external api for the swscale stuff
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AV_STRINGIFY(s) AV_TOSTRING(s)
+#define AV_TOSTRING(s) #s
+
+#define LIBSWSCALE_VERSION_INT ((0<<16)+(5<<8)+0)
+#define LIBSWSCALE_VERSION 0.5.0
+#define LIBSWSCALE_BUILD LIBSWSCALE_VERSION_INT
+
+#define LIBSWSCALE_IDENT "SwS" AV_STRINGIFY(LIBSWSCALE_VERSION)
+
+/* values for the flags, the stuff on the command line is different */
+#define SWS_FAST_BILINEAR 1
+#define SWS_BILINEAR 2
+#define SWS_BICUBIC 4
+#define SWS_X 8
+#define SWS_POINT 0x10
+#define SWS_AREA 0x20
+#define SWS_BICUBLIN 0x40
+#define SWS_GAUSS 0x80
+#define SWS_SINC 0x100
+#define SWS_LANCZOS 0x200
+#define SWS_SPLINE 0x400
+
+#define SWS_SRC_V_CHR_DROP_MASK 0x30000
+#define SWS_SRC_V_CHR_DROP_SHIFT 16
+
+#define SWS_PARAM_DEFAULT 123456
+
+#define SWS_PRINT_INFO 0x1000
+
+//the following 3 flags are not completly implemented
+//internal chrominace subsamling info
+#define SWS_FULL_CHR_H_INT 0x2000
+//input subsampling info
+#define SWS_FULL_CHR_H_INP 0x4000
+#define SWS_DIRECT_BGR 0x8000
+#define SWS_ACCURATE_RND 0x40000
+
+#define SWS_CPU_CAPS_MMX 0x80000000
+#define SWS_CPU_CAPS_MMX2 0x20000000
+#define SWS_CPU_CAPS_3DNOW 0x40000000
+#define SWS_CPU_CAPS_ALTIVEC 0x10000000
+
+#define SWS_MAX_REDUCE_CUTOFF 0.002
+
+#define SWS_CS_ITU709 1
+#define SWS_CS_FCC 4
+#define SWS_CS_ITU601 5
+#define SWS_CS_ITU624 5
+#define SWS_CS_SMPTE170M 5
+#define SWS_CS_SMPTE240M 7
+#define SWS_CS_DEFAULT 5
+
+
+
+// when used for filters they must have an odd number of elements
+// coeffs cannot be shared between vectors
+typedef struct {
+ double *coeff;
+ int length;
+} SwsVector;
+
+// vectors can be shared
+typedef struct {
+ SwsVector *lumH;
+ SwsVector *lumV;
+ SwsVector *chrH;
+ SwsVector *chrV;
+} SwsFilter;
+
+struct SwsContext;
+
+void sws_freeContext(struct SwsContext *swsContext);
+
+struct SwsContext *sws_getContext(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat, int flags,
+ SwsFilter *srcFilter, SwsFilter *dstFilter, double *param);
+int sws_scale(struct SwsContext *context, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]);
+int sws_scale_ordered(struct SwsContext *context, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]);
+
+
+int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], int srcRange, const int table[4], int dstRange, int brightness, int contrast, int saturation);
+int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table, int *srcRange, int **table, int *dstRange, int *brightness, int *contrast, int *saturation);
+SwsVector *sws_getGaussianVec(double variance, double quality);
+SwsVector *sws_getConstVec(double c, int length);
+SwsVector *sws_getIdentityVec(void);
+void sws_scaleVec(SwsVector *a, double scalar);
+void sws_normalizeVec(SwsVector *a, double height);
+void sws_convVec(SwsVector *a, SwsVector *b);
+void sws_addVec(SwsVector *a, SwsVector *b);
+void sws_subVec(SwsVector *a, SwsVector *b);
+void sws_shiftVec(SwsVector *a, int shift);
+SwsVector *sws_cloneVec(SwsVector *a);
+
+void sws_printVec(SwsVector *a);
+void sws_freeVec(SwsVector *a);
+
+SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur,
+ float lumaSarpen, float chromaSharpen,
+ float chromaHShift, float chromaVShift,
+ int verbose);
+void sws_freeFilter(SwsFilter *filter);
+
+struct SwsContext *sws_getCachedContext(struct SwsContext *context,
+ int srcW, int srcH, int srcFormat,
+ int dstW, int dstH, int dstFormat, int flags,
+ SwsFilter *srcFilter, SwsFilter *dstFilter, double *param);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/ffmpeg/libswscale/swscale_altivec_template.c b/contrib/ffmpeg/libswscale/swscale_altivec_template.c
new file mode 100644
index 000000000..d65c28538
--- /dev/null
+++ b/contrib/ffmpeg/libswscale/swscale_altivec_template.c
@@ -0,0 +1,548 @@
+/*
+ * AltiVec-enhanced yuv2yuvX
+ *
+ * Copyright (C) 2004 Romain Dolbeau <romain@dolbeau.org>
+ * based on the equivalent C code in "postproc/swscale.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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef CONFIG_DARWIN
+#define AVV(x...) (x)
+#else
+#define AVV(x...) {x}
+#endif
+
+#define vzero vec_splat_s32(0)
+
+static inline void
+altivec_packIntArrayToCharArray(int *val, uint8_t* dest, int dstW) {
+ register int i;
+ vector unsigned int altivec_vectorShiftInt19 =
+ vec_add(vec_splat_u32(10),vec_splat_u32(9));
+ if ((unsigned long)dest % 16) {
+ /* badly aligned store, we force store alignement */
+ /* and will handle load misalignement on val w/ vec_perm */
+ vector unsigned char perm1;
+ vector signed int v1;
+ for (i = 0 ; (i < dstW) &&
+ (((unsigned long)dest + i) % 16) ; i++) {
+ int t = val[i] >> 19;
+ dest[i] = (t < 0) ? 0 : ((t > 255) ? 255 : t);
+ }
+ perm1 = vec_lvsl(i << 2, val);
+ v1 = vec_ld(i << 2, val);
+ for ( ; i < (dstW - 15); i+=16) {
+ int offset = i << 2;
+ vector signed int v2 = vec_ld(offset + 16, val);
+ vector signed int v3 = vec_ld(offset + 32, val);
+ vector signed int v4 = vec_ld(offset + 48, val);
+ vector signed int v5 = vec_ld(offset + 64, val);
+ vector signed int v12 = vec_perm(v1,v2,perm1);
+ vector signed int v23 = vec_perm(v2,v3,perm1);
+ vector signed int v34 = vec_perm(v3,v4,perm1);
+ vector signed int v45 = vec_perm(v4,v5,perm1);
+
+ vector signed int vA = vec_sra(v12, altivec_vectorShiftInt19);
+ vector signed int vB = vec_sra(v23, altivec_vectorShiftInt19);
+ vector signed int vC = vec_sra(v34, altivec_vectorShiftInt19);
+ vector signed int vD = vec_sra(v45, altivec_vectorShiftInt19);
+ vector unsigned short vs1 = vec_packsu(vA, vB);
+ vector unsigned short vs2 = vec_packsu(vC, vD);
+ vector unsigned char vf = vec_packsu(vs1, vs2);
+ vec_st(vf, i, dest);
+ v1 = v5;
+ }
+ } else { // dest is properly aligned, great
+ for (i = 0; i < (dstW - 15); i+=16) {
+ int offset = i << 2;
+ vector signed int v1 = vec_ld(offset, val);
+ vector signed int v2 = vec_ld(offset + 16, val);
+ vector signed int v3 = vec_ld(offset + 32, val);
+ vector signed int v4 = vec_ld(offset + 48, val);
+ vector signed int v5 = vec_sra(v1, altivec_vectorShiftInt19);
+ vector signed int v6 = vec_sra(v2, altivec_vectorShiftInt19);
+ vector signed int v7 = vec_sra(v3, altivec_vectorShiftInt19);
+ vector signed int v8 = vec_sra(v4, altivec_vectorShiftInt19);
+ vector unsigned short vs1 = vec_packsu(v5, v6);
+ vector unsigned short vs2 = vec_packsu(v7, v8);
+ vector unsigned char vf = vec_packsu(vs1, vs2);
+ vec_st(vf, i, dest);
+ }
+ }
+ for ( ; i < dstW ; i++) {
+ int t = val[i] >> 19;
+ dest[i] = (t < 0) ? 0 : ((t > 255) ? 255 : t);
+ }
+}
+
+static inline void
+yuv2yuvX_altivec_real(int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
+ int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
+ uint8_t *dest, uint8_t *uDest, uint8_t *vDest, int dstW, int chrDstW)
+{
+ const vector signed int vini = {(1 << 18), (1 << 18), (1 << 18), (1 << 18)};
+ register int i, j;
+ {
+ int __attribute__ ((aligned (16))) val[dstW];
+
+ for (i = 0; i < (dstW -7); i+=4) {
+ vec_st(vini, i << 2, val);
+ }
+ for (; i < dstW; i++) {
+ val[i] = (1 << 18);
+ }
+
+ for (j = 0; j < lumFilterSize; j++) {
+ vector signed short l1, vLumFilter = vec_ld(j << 1, lumFilter);
+ vector unsigned char perm, perm0 = vec_lvsl(j << 1, lumFilter);
+ vLumFilter = vec_perm(vLumFilter, vLumFilter, perm0);
+ vLumFilter = vec_splat(vLumFilter, 0); // lumFilter[j] is loaded 8 times in vLumFilter
+
+ perm = vec_lvsl(0, lumSrc[j]);
+ l1 = vec_ld(0, lumSrc[j]);
+
+ for (i = 0; i < (dstW - 7); i+=8) {
+ int offset = i << 2;
+ vector signed short l2 = vec_ld((i << 1) + 16, lumSrc[j]);
+
+ vector signed int v1 = vec_ld(offset, val);
+ vector signed int v2 = vec_ld(offset + 16, val);
+
+ vector signed short ls = vec_perm(l1, l2, perm); // lumSrc[j][i] ... lumSrc[j][i+7]
+
+ vector signed int i1 = vec_mule(vLumFilter, ls);
+ vector signed int i2 = vec_mulo(vLumFilter, ls);
+
+ vector signed int vf1 = vec_mergeh(i1, i2);
+ vector signed int vf2 = vec_mergel(i1, i2); // lumSrc[j][i] * lumFilter[j] ... lumSrc[j][i+7] * lumFilter[j]
+
+ vector signed int vo1 = vec_add(v1, vf1);
+ vector signed int vo2 = vec_add(v2, vf2);
+
+ vec_st(vo1, offset, val);
+ vec_st(vo2, offset + 16, val);
+
+ l1 = l2;
+ }
+ for ( ; i < dstW; i++) {
+ val[i] += lumSrc[j][i] * lumFilter[j];
+ }
+ }
+ altivec_packIntArrayToCharArray(val,dest,dstW);
+ }
+ if (uDest != 0) {
+ int __attribute__ ((aligned (16))) u[chrDstW];
+ int __attribute__ ((aligned (16))) v[chrDstW];
+
+ for (i = 0; i < (chrDstW -7); i+=4) {
+ vec_st(vini, i << 2, u);
+ vec_st(vini, i << 2, v);
+ }
+ for (; i < chrDstW; i++) {
+ u[i] = (1 << 18);
+ v[i] = (1 << 18);
+ }
+
+ for (j = 0; j < chrFilterSize; j++) {
+ vector signed short l1, l1_V, vChrFilter = vec_ld(j << 1, chrFilter);
+ vector unsigned char perm, perm0 = vec_lvsl(j << 1, chrFilter);
+ vChrFilter = vec_perm(vChrFilter, vChrFilter, perm0);
+ vChrFilter = vec_splat(vChrFilter, 0); // chrFilter[j] is loaded 8 times in vChrFilter
+
+ perm = vec_lvsl(0, chrSrc[j]);
+ l1 = vec_ld(0, chrSrc[j]);
+ l1_V = vec_ld(2048 << 1, chrSrc[j]);
+
+ for (i = 0; i < (chrDstW - 7); i+=8) {
+ int offset = i << 2;
+ vector signed short l2 = vec_ld((i << 1) + 16, chrSrc[j]);
+ vector signed short l2_V = vec_ld(((i + 2048) << 1) + 16, chrSrc[j]);
+
+ vector signed int v1 = vec_ld(offset, u);
+ vector signed int v2 = vec_ld(offset + 16, u);
+ vector signed int v1_V = vec_ld(offset, v);
+ vector signed int v2_V = vec_ld(offset + 16, v);
+
+ vector signed short ls = vec_perm(l1, l2, perm); // chrSrc[j][i] ... chrSrc[j][i+7]
+ vector signed short ls_V = vec_perm(l1_V, l2_V, perm); // chrSrc[j][i+2048] ... chrSrc[j][i+2055]
+
+ vector signed int i1 = vec_mule(vChrFilter, ls);
+ vector signed int i2 = vec_mulo(vChrFilter, ls);
+ vector signed int i1_V = vec_mule(vChrFilter, ls_V);
+ vector signed int i2_V = vec_mulo(vChrFilter, ls_V);
+
+ vector signed int vf1 = vec_mergeh(i1, i2);
+ vector signed int vf2 = vec_mergel(i1, i2); // chrSrc[j][i] * chrFilter[j] ... chrSrc[j][i+7] * chrFilter[j]
+ vector signed int vf1_V = vec_mergeh(i1_V, i2_V);
+ vector signed int vf2_V = vec_mergel(i1_V, i2_V); // chrSrc[j][i] * chrFilter[j] ... chrSrc[j][i+7] * chrFilter[j]
+
+ vector signed int vo1 = vec_add(v1, vf1);
+ vector signed int vo2 = vec_add(v2, vf2);
+ vector signed int vo1_V = vec_add(v1_V, vf1_V);
+ vector signed int vo2_V = vec_add(v2_V, vf2_V);
+
+ vec_st(vo1, offset, u);
+ vec_st(vo2, offset + 16, u);
+ vec_st(vo1_V, offset, v);
+ vec_st(vo2_V, offset + 16, v);
+
+ l1 = l2;
+ l1_V = l2_V;
+ }
+ for ( ; i < chrDstW; i++) {
+ u[i] += chrSrc[j][i] * chrFilter[j];
+ v[i] += chrSrc[j][i + 2048] * chrFilter[j];
+ }
+ }
+ altivec_packIntArrayToCharArray(u,uDest,chrDstW);
+ altivec_packIntArrayToCharArray(v,vDest,chrDstW);
+ }
+}
+
+static inline void hScale_altivec_real(int16_t *dst, int dstW, uint8_t *src, int srcW, int xInc, int16_t *filter, int16_t *filterPos, int filterSize) {
+ register int i;
+ int __attribute__ ((aligned (16))) tempo[4];
+
+ if (filterSize % 4) {
+ for(i=0; i<dstW; i++) {
+ register int j;
+ register int srcPos = filterPos[i];
+ register int val = 0;
+ for(j=0; j<filterSize; j++) {
+ val += ((int)src[srcPos + j])*filter[filterSize*i + j];
+ }
+ dst[i] = FFMIN(FFMAX(0, val>>7), (1<<15)-1);
+ }
+ }
+ else
+ switch (filterSize) {
+ case 4:
+ {
+ for(i=0; i<dstW; i++) {
+ register int srcPos = filterPos[i];
+
+ vector unsigned char src_v0 = vec_ld(srcPos, src);
+ vector unsigned char src_v1, src_vF;
+ vector signed short src_v, filter_v;
+ vector signed int val_vEven, val_s;
+ if ((((int)src + srcPos)% 16) > 12) {
+ src_v1 = vec_ld(srcPos + 16, src);
+ }
+ src_vF = vec_perm(src_v0, src_v1, vec_lvsl(srcPos, src));
+
+ src_v = // vec_unpackh sign-extends...
+ (vector signed short)(vec_mergeh((vector unsigned char)vzero, src_vF));
+ // now put our elements in the even slots
+ src_v = vec_mergeh(src_v, (vector signed short)vzero);
+
+ filter_v = vec_ld(i << 3, filter);
+ // the 3 above is 2 (filterSize == 4) + 1 (sizeof(short) == 2)
+
+ // the neat trick : we only care for half the elements,
+ // high or low depending on (i<<3)%16 (it's 0 or 8 here),
+ // and we're going to use vec_mule, so we chose
+ // carefully how to "unpack" the elements into the even slots
+ if ((i << 3) % 16)
+ filter_v = vec_mergel(filter_v,(vector signed short)vzero);
+ else
+ filter_v = vec_mergeh(filter_v,(vector signed short)vzero);
+
+ val_vEven = vec_mule(src_v, filter_v);
+ val_s = vec_sums(val_vEven, vzero);
+ vec_st(val_s, 0, tempo);
+ dst[i] = FFMIN(FFMAX(0, tempo[3]>>7), (1<<15)-1);
+ }
+ }
+ break;
+
+ case 8:
+ {
+ for(i=0; i<dstW; i++) {
+ register int srcPos = filterPos[i];
+
+ vector unsigned char src_v0 = vec_ld(srcPos, src);
+ vector unsigned char src_v1, src_vF;
+ vector signed short src_v, filter_v;
+ vector signed int val_v, val_s;
+ if ((((int)src + srcPos)% 16) > 8) {
+ src_v1 = vec_ld(srcPos + 16, src);
+ }
+ src_vF = vec_perm(src_v0, src_v1, vec_lvsl(srcPos, src));
+
+ src_v = // vec_unpackh sign-extends...
+ (vector signed short)(vec_mergeh((vector unsigned char)vzero, src_vF));
+ filter_v = vec_ld(i << 4, filter);
+ // the 4 above is 3 (filterSize == 8) + 1 (sizeof(short) == 2)
+
+ val_v = vec_msums(src_v, filter_v, (vector signed int)vzero);
+ val_s = vec_sums(val_v, vzero);
+ vec_st(val_s, 0, tempo);
+ dst[i] = FFMIN(FFMAX(0, tempo[3]>>7), (1<<15)-1);
+ }
+ }
+ break;
+
+ case 16:
+ {
+ for(i=0; i<dstW; i++) {
+ register int srcPos = filterPos[i];
+
+ vector unsigned char src_v0 = vec_ld(srcPos, src);
+ vector unsigned char src_v1 = vec_ld(srcPos + 16, src);
+ vector unsigned char src_vF = vec_perm(src_v0, src_v1, vec_lvsl(srcPos, src));
+
+ vector signed short src_vA = // vec_unpackh sign-extends...
+ (vector signed short)(vec_mergeh((vector unsigned char)vzero, src_vF));
+ vector signed short src_vB = // vec_unpackh sign-extends...
+ (vector signed short)(vec_mergel((vector unsigned char)vzero, src_vF));
+
+ vector signed short filter_v0 = vec_ld(i << 5, filter);
+ vector signed short filter_v1 = vec_ld((i << 5) + 16, filter);
+ // the 5 above are 4 (filterSize == 16) + 1 (sizeof(short) == 2)
+
+ vector signed int val_acc = vec_msums(src_vA, filter_v0, (vector signed int)vzero);
+ vector signed int val_v = vec_msums(src_vB, filter_v1, val_acc);
+
+ vector signed int val_s = vec_sums(val_v, vzero);
+
+ vec_st(val_s, 0, tempo);
+ dst[i] = FFMIN(FFMAX(0, tempo[3]>>7), (1<<15)-1);
+ }
+ }
+ break;
+
+ default:
+ {
+ for(i=0; i<dstW; i++) {
+ register int j;
+ register int srcPos = filterPos[i];
+
+ vector signed int val_s, val_v = (vector signed int)vzero;
+ vector signed short filter_v0R = vec_ld(i * 2 * filterSize, filter);
+ vector unsigned char permF = vec_lvsl((i * 2 * filterSize), filter);
+
+ vector unsigned char src_v0 = vec_ld(srcPos, src);
+ vector unsigned char permS = vec_lvsl(srcPos, src);
+
+ for (j = 0 ; j < filterSize - 15; j += 16) {
+ vector unsigned char src_v1 = vec_ld(srcPos + j + 16, src);
+ vector unsigned char src_vF = vec_perm(src_v0, src_v1, permS);
+
+ vector signed short src_vA = // vec_unpackh sign-extends...
+ (vector signed short)(vec_mergeh((vector unsigned char)vzero, src_vF));
+ vector signed short src_vB = // vec_unpackh sign-extends...
+ (vector signed short)(vec_mergel((vector unsigned char)vzero, src_vF));
+
+ vector signed short filter_v1R = vec_ld((i * 2 * filterSize) + (j * 2) + 16, filter);
+ vector signed short filter_v2R = vec_ld((i * 2 * filterSize) + (j * 2) + 32, filter);
+ vector signed short filter_v0 = vec_perm(filter_v0R, filter_v1R, permF);
+ vector signed short filter_v1 = vec_perm(filter_v1R, filter_v2R, permF);
+
+ vector signed int val_acc = vec_msums(src_vA, filter_v0, val_v);
+ val_v = vec_msums(src_vB, filter_v1, val_acc);
+
+ filter_v0R = filter_v2R;
+ src_v0 = src_v1;
+ }
+
+ if (j < (filterSize-7)) {
+ // loading src_v0 is useless, it's already done above
+ //vector unsigned char src_v0 = vec_ld(srcPos + j, src);
+ vector unsigned char src_v1, src_vF;
+ vector signed short src_v, filter_v1R, filter_v;
+ if ((((int)src + srcPos)% 16) > 8) {
+ src_v1 = vec_ld(srcPos + j + 16, src);
+ }
+ src_vF = vec_perm(src_v0, src_v1, permS);
+
+ src_v = // vec_unpackh sign-extends...
+ (vector signed short)(vec_mergeh((vector unsigned char)vzero, src_vF));
+ // loading filter_v0R is useless, it's already done above
+ //vector signed short filter_v0R = vec_ld((i * 2 * filterSize) + j, filter);
+ filter_v1R = vec_ld((i * 2 * filterSize) + (j * 2) + 16, filter);
+ filter_v = vec_perm(filter_v0R, filter_v1R, permF);
+
+ val_v = vec_msums(src_v, filter_v, val_v);
+ }
+
+ val_s = vec_sums(val_v, vzero);
+
+ vec_st(val_s, 0, tempo);
+ dst[i] = FFMIN(FFMAX(0, tempo[3]>>7), (1<<15)-1);
+ }
+
+ }
+ }
+}
+
+static inline int yv12toyuy2_unscaled_altivec(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dstParam[], int dstStride_a[]) {
+ uint8_t *dst=dstParam[0] + dstStride_a[0]*srcSliceY;
+ // yv12toyuy2( src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0] );
+ uint8_t *ysrc = src[0];
+ uint8_t *usrc = src[1];
+ uint8_t *vsrc = src[2];
+ const int width = c->srcW;
+ const int height = srcSliceH;
+ const int lumStride = srcStride[0];
+ const int chromStride = srcStride[1];
+ const int dstStride = dstStride_a[0];
+ const vector unsigned char yperm = vec_lvsl(0, ysrc);
+ const int vertLumPerChroma = 2;
+ register unsigned int y;
+
+ if(width&15){
+ yv12toyuy2( ysrc, usrc, vsrc, dst,c->srcW,srcSliceH, lumStride, chromStride, dstStride);
+ return srcSliceH;
+ }
+
+ /* this code assume:
+
+ 1) dst is 16 bytes-aligned
+ 2) dstStride is a multiple of 16
+ 3) width is a multiple of 16
+ 4) lum&chrom stride are multiple of 8
+ */
+
+ for(y=0; y<height; y++)
+ {
+ int i;
+ for (i = 0; i < width - 31; i+= 32) {
+ const unsigned int j = i >> 1;
+ vector unsigned char v_yA = vec_ld(i, ysrc);
+ vector unsigned char v_yB = vec_ld(i + 16, ysrc);
+ vector unsigned char v_yC = vec_ld(i + 32, ysrc);
+ vector unsigned char v_y1 = vec_perm(v_yA, v_yB, yperm);
+ vector unsigned char v_y2 = vec_perm(v_yB, v_yC, yperm);
+ vector unsigned char v_uA = vec_ld(j, usrc);
+ vector unsigned char v_uB = vec_ld(j + 16, usrc);
+ vector unsigned char v_u = vec_perm(v_uA, v_uB, vec_lvsl(j, usrc));
+ vector unsigned char v_vA = vec_ld(j, vsrc);
+ vector unsigned char v_vB = vec_ld(j + 16, vsrc);
+ vector unsigned char v_v = vec_perm(v_vA, v_vB, vec_lvsl(j, vsrc));
+ vector unsigned char v_uv_a = vec_mergeh(v_u, v_v);
+ vector unsigned char v_uv_b = vec_mergel(v_u, v_v);
+ vector unsigned char v_yuy2_0 = vec_mergeh(v_y1, v_uv_a);
+ vector unsigned char v_yuy2_1 = vec_mergel(v_y1, v_uv_a);
+ vector unsigned char v_yuy2_2 = vec_mergeh(v_y2, v_uv_b);
+ vector unsigned char v_yuy2_3 = vec_mergel(v_y2, v_uv_b);
+ vec_st(v_yuy2_0, (i << 1), dst);
+ vec_st(v_yuy2_1, (i << 1) + 16, dst);
+ vec_st(v_yuy2_2, (i << 1) + 32, dst);
+ vec_st(v_yuy2_3, (i << 1) + 48, dst);
+ }
+ if (i < width) {
+ const unsigned int j = i >> 1;
+ vector unsigned char v_y1 = vec_ld(i, ysrc);
+ vector unsigned char v_u = vec_ld(j, usrc);
+ vector unsigned char v_v = vec_ld(j, vsrc);
+ vector unsigned char v_uv_a = vec_mergeh(v_u, v_v);
+ vector unsigned char v_yuy2_0 = vec_mergeh(v_y1, v_uv_a);
+ vector unsigned char v_yuy2_1 = vec_mergel(v_y1, v_uv_a);
+ vec_st(v_yuy2_0, (i << 1), dst);
+ vec_st(v_yuy2_1, (i << 1) + 16, dst);
+ }
+ if((y&(vertLumPerChroma-1))==(vertLumPerChroma-1) )
+ {
+ usrc += chromStride;
+ vsrc += chromStride;
+ }
+ ysrc += lumStride;
+ dst += dstStride;
+ }
+
+ return srcSliceH;
+}
+
+static inline int yv12touyvy_unscaled_altivec(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dstParam[], int dstStride_a[]) {
+ uint8_t *dst=dstParam[0] + dstStride_a[0]*srcSliceY;
+ // yv12toyuy2( src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0] );
+ uint8_t *ysrc = src[0];
+ uint8_t *usrc = src[1];
+ uint8_t *vsrc = src[2];
+ const int width = c->srcW;
+ const int height = srcSliceH;
+ const int lumStride = srcStride[0];
+ const int chromStride = srcStride[1];
+ const int dstStride = dstStride_a[0];
+ const int vertLumPerChroma = 2;
+ const vector unsigned char yperm = vec_lvsl(0, ysrc);
+ register unsigned int y;
+
+ if(width&15){
+ yv12touyvy( ysrc, usrc, vsrc, dst,c->srcW,srcSliceH, lumStride, chromStride, dstStride);
+ return srcSliceH;
+ }
+
+ /* this code assume:
+
+ 1) dst is 16 bytes-aligned
+ 2) dstStride is a multiple of 16
+ 3) width is a multiple of 16
+ 4) lum&chrom stride are multiple of 8
+ */
+
+ for(y=0; y<height; y++)
+ {
+ int i;
+ for (i = 0; i < width - 31; i+= 32) {
+ const unsigned int j = i >> 1;
+ vector unsigned char v_yA = vec_ld(i, ysrc);
+ vector unsigned char v_yB = vec_ld(i + 16, ysrc);
+ vector unsigned char v_yC = vec_ld(i + 32, ysrc);
+ vector unsigned char v_y1 = vec_perm(v_yA, v_yB, yperm);
+ vector unsigned char v_y2 = vec_perm(v_yB, v_yC, yperm);
+ vector unsigned char v_uA = vec_ld(j, usrc);
+ vector unsigned char v_uB = vec_ld(j + 16, usrc);
+ vector unsigned char v_u = vec_perm(v_uA, v_uB, vec_lvsl(j, usrc));
+ vector unsigned char v_vA = vec_ld(j, vsrc);
+ vector unsigned char v_vB = vec_ld(j + 16, vsrc);
+ vector unsigned char v_v = vec_perm(v_vA, v_vB, vec_lvsl(j, vsrc));
+ vector unsigned char v_uv_a = vec_mergeh(v_u, v_v);
+ vector unsigned char v_uv_b = vec_mergel(v_u, v_v);
+ vector unsigned char v_uyvy_0 = vec_mergeh(v_uv_a, v_y1);
+ vector unsigned char v_uyvy_1 = vec_mergel(v_uv_a, v_y1);
+ vector unsigned char v_uyvy_2 = vec_mergeh(v_uv_b, v_y2);
+ vector unsigned char v_uyvy_3 = vec_mergel(v_uv_b, v_y2);
+ vec_st(v_uyvy_0, (i << 1), dst);
+ vec_st(v_uyvy_1, (i << 1) + 16, dst);
+ vec_st(v_uyvy_2, (i << 1) + 32, dst);
+ vec_st(v_uyvy_3, (i << 1) + 48, dst);
+ }
+ if (i < width) {
+ const unsigned int j = i >> 1;
+ vector unsigned char v_y1 = vec_ld(i, ysrc);
+ vector unsigned char v_u = vec_ld(j, usrc);
+ vector unsigned char v_v = vec_ld(j, vsrc);
+ vector unsigned char v_uv_a = vec_mergeh(v_u, v_v);
+ vector unsigned char v_uyvy_0 = vec_mergeh(v_uv_a, v_y1);
+ vector unsigned char v_uyvy_1 = vec_mergel(v_uv_a, v_y1);
+ vec_st(v_uyvy_0, (i << 1), dst);
+ vec_st(v_uyvy_1, (i << 1) + 16, dst);
+ }
+ if((y&(vertLumPerChroma-1))==(vertLumPerChroma-1) )
+ {
+ usrc += chromStride;
+ vsrc += chromStride;
+ }
+ ysrc += lumStride;
+ dst += dstStride;
+ }
+ return srcSliceH;
+}
diff --git a/contrib/ffmpeg/libswscale/swscale_internal.h b/contrib/ffmpeg/libswscale/swscale_internal.h
new file mode 100644
index 000000000..837b6eaf5
--- /dev/null
+++ b/contrib/ffmpeg/libswscale/swscale_internal.h
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have 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 SWSCALE_INTERNAL_H
+#define SWSCALE_INTERNAL_H
+
+#ifdef HAVE_ALTIVEC_H
+#include <altivec.h>
+#endif
+
+#include "avutil.h"
+
+#ifdef CONFIG_DARWIN
+#define AVV(x...) (x)
+#else
+#define AVV(x...) {x}
+#endif
+
+#define MSG_WARN(args...) av_log(NULL, AV_LOG_DEBUG, ##args )
+#define MSG_FATAL(args...) av_log(NULL, AV_LOG_ERROR, ##args )
+#define MSG_ERR(args...) av_log(NULL, AV_LOG_ERROR, ##args )
+#define MSG_V(args...) av_log(NULL, AV_LOG_INFO, ##args )
+#define MSG_DBG2(args...) av_log(NULL, AV_LOG_DEBUG, ##args )
+#define MSG_INFO(args...) av_log(NULL, AV_LOG_INFO, ##args )
+
+#define MAX_FILTER_SIZE 256
+
+typedef int (*SwsFunc)(struct SwsContext *context, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]);
+
+/* this struct should be aligned on at least 32-byte boundary */
+typedef struct SwsContext{
+ /**
+ *
+ * Note the src,dst,srcStride,dstStride will be copied, in the sws_scale() warper so they can freely be modified here
+ */
+ SwsFunc swScale;
+ int srcW, srcH, dstH;
+ int chrSrcW, chrSrcH, chrDstW, chrDstH;
+ int lumXInc, chrXInc;
+ int lumYInc, chrYInc;
+ int dstFormat, srcFormat; ///< format 4:2:0 type is allways YV12
+ int origDstFormat, origSrcFormat; ///< format
+ int chrSrcHSubSample, chrSrcVSubSample;
+ int chrIntHSubSample, chrIntVSubSample;
+ int chrDstHSubSample, chrDstVSubSample;
+ int vChrDrop;
+ int sliceDir;
+ double param[2];
+
+ int16_t **lumPixBuf;
+ int16_t **chrPixBuf;
+ int16_t *hLumFilter;
+ int16_t *hLumFilterPos;
+ int16_t *hChrFilter;
+ int16_t *hChrFilterPos;
+ int16_t *vLumFilter;
+ int16_t *vLumFilterPos;
+ int16_t *vChrFilter;
+ int16_t *vChrFilterPos;
+
+ uint8_t formatConvBuffer[4000]; //FIXME dynamic alloc, but we have to change alot of code for this to be usefull
+
+ int hLumFilterSize;
+ int hChrFilterSize;
+ int vLumFilterSize;
+ int vChrFilterSize;
+ int vLumBufSize;
+ int vChrBufSize;
+
+ uint8_t *funnyYCode;
+ uint8_t *funnyUVCode;
+ int32_t *lumMmx2FilterPos;
+ int32_t *chrMmx2FilterPos;
+ int16_t *lumMmx2Filter;
+ int16_t *chrMmx2Filter;
+
+ int canMMX2BeUsed;
+
+ int lastInLumBuf;
+ int lastInChrBuf;
+ int lumBufIndex;
+ int chrBufIndex;
+ int dstY;
+ int flags;
+ void * yuvTable; // pointer to the yuv->rgb table start so it can be freed()
+ void * table_rV[256];
+ void * table_gU[256];
+ int table_gV[256];
+ void * table_bU[256];
+
+ //Colorspace stuff
+ int contrast, brightness, saturation; // for sws_getColorspaceDetails
+ int srcColorspaceTable[4];
+ int dstColorspaceTable[4];
+ int srcRange, dstRange;
+
+#define RED_DITHER "0*8"
+#define GREEN_DITHER "1*8"
+#define BLUE_DITHER "2*8"
+#define Y_COEFF "3*8"
+#define VR_COEFF "4*8"
+#define UB_COEFF "5*8"
+#define VG_COEFF "6*8"
+#define UG_COEFF "7*8"
+#define Y_OFFSET "8*8"
+#define U_OFFSET "9*8"
+#define V_OFFSET "10*8"
+#define LUM_MMX_FILTER_OFFSET "11*8"
+#define CHR_MMX_FILTER_OFFSET "11*8+4*4*256"
+#define DSTW_OFFSET "11*8+4*4*256*2" //do not change, its hardcoded in the asm
+#define ESP_OFFSET "11*8+4*4*256*2+8"
+#define VROUNDER_OFFSET "11*8+4*4*256*2+16"
+#define U_TEMP "11*8+4*4*256*2+24"
+#define V_TEMP "11*8+4*4*256*2+32"
+
+ uint64_t redDither __attribute__((aligned(8)));
+ uint64_t greenDither __attribute__((aligned(8)));
+ uint64_t blueDither __attribute__((aligned(8)));
+
+ uint64_t yCoeff __attribute__((aligned(8)));
+ uint64_t vrCoeff __attribute__((aligned(8)));
+ uint64_t ubCoeff __attribute__((aligned(8)));
+ uint64_t vgCoeff __attribute__((aligned(8)));
+ uint64_t ugCoeff __attribute__((aligned(8)));
+ uint64_t yOffset __attribute__((aligned(8)));
+ uint64_t uOffset __attribute__((aligned(8)));
+ uint64_t vOffset __attribute__((aligned(8)));
+ int32_t lumMmxFilter[4*MAX_FILTER_SIZE];
+ int32_t chrMmxFilter[4*MAX_FILTER_SIZE];
+ int dstW;
+ uint64_t esp __attribute__((aligned(8)));
+ uint64_t vRounder __attribute__((aligned(8)));
+ uint64_t u_temp __attribute__((aligned(8)));
+ uint64_t v_temp __attribute__((aligned(8)));
+
+#ifdef HAVE_ALTIVEC
+
+ vector signed short CY;
+ vector signed short CRV;
+ vector signed short CBU;
+ vector signed short CGU;
+ vector signed short CGV;
+ vector signed short OY;
+ vector unsigned short CSHIFT;
+ vector signed short *vYCoeffsBank, *vCCoeffsBank;
+
+#endif
+
+} SwsContext;
+//FIXME check init (where 0)
+
+SwsFunc yuv2rgb_get_func_ptr (SwsContext *c);
+int yuv2rgb_c_init_tables (SwsContext *c, const int inv_table[4], int fullRange, int brightness, int contrast, int saturation);
+
+char *sws_format_name(int format);
+
+//FIXME replace this with something faster
+#define isPlanarYUV(x) ((x)==PIX_FMT_YUV410P || (x)==PIX_FMT_YUV420P \
+ || (x)==PIX_FMT_YUV411P || (x)==PIX_FMT_YUV422P \
+ || (x)==PIX_FMT_YUV444P || (x)==PIX_FMT_NV12 \
+ || (x)==PIX_FMT_NV21)
+#define isYUV(x) ((x)==PIX_FMT_UYVY422 || (x)==PIX_FMT_YUYV422 || isPlanarYUV(x))
+#define isGray(x) ((x)==PIX_FMT_GRAY8 || (x)==PIX_FMT_GRAY16BE || (x)==PIX_FMT_GRAY16LE)
+#define isGray16(x) ((x)==PIX_FMT_GRAY16BE || (x)==PIX_FMT_GRAY16LE)
+#define isRGB(x) ((x)==PIX_FMT_BGR32 || (x)==PIX_FMT_RGB24 \
+ || (x)==PIX_FMT_RGB565 || (x)==PIX_FMT_RGB555 \
+ || (x)==PIX_FMT_RGB8 || (x)==PIX_FMT_RGB4 \
+ || (x)==PIX_FMT_MONOBLACK)
+#define isBGR(x) ((x)==PIX_FMT_RGB32 || (x)==PIX_FMT_BGR24 \
+ || (x)==PIX_FMT_BGR565 || (x)==PIX_FMT_BGR555 \
+ || (x)==PIX_FMT_BGR8 || (x)==PIX_FMT_BGR4 \
+ || (x)==PIX_FMT_MONOBLACK)
+
+static inline int fmt_depth(int fmt)
+{
+ switch(fmt) {
+ case PIX_FMT_BGRA:
+ case PIX_FMT_ABGR:
+ case PIX_FMT_RGBA:
+ case PIX_FMT_ARGB:
+ return 32;
+ case PIX_FMT_BGR24:
+ case PIX_FMT_RGB24:
+ return 24;
+ case PIX_FMT_BGR565:
+ case PIX_FMT_RGB565:
+ case PIX_FMT_GRAY16BE:
+ case PIX_FMT_GRAY16LE:
+ return 16;
+ case PIX_FMT_BGR555:
+ case PIX_FMT_RGB555:
+ return 15;
+ case PIX_FMT_BGR8:
+ case PIX_FMT_RGB8:
+ return 8;
+ case PIX_FMT_BGR4:
+ case PIX_FMT_RGB4:
+ case PIX_FMT_BGR4_BYTE:
+ case PIX_FMT_RGB4_BYTE:
+ return 4;
+ case PIX_FMT_MONOBLACK:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+#endif
diff --git a/contrib/ffmpeg/libswscale/swscale_template.c b/contrib/ffmpeg/libswscale/swscale_template.c
new file mode 100644
index 000000000..e725a3bb0
--- /dev/null
+++ b/contrib/ffmpeg/libswscale/swscale_template.c
@@ -0,0 +1,3241 @@
+/*
+ * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * the C code (not assembly, mmx, ...) of this file can be used
+ * under the LGPL license too
+ */
+
+#undef REAL_MOVNTQ
+#undef MOVNTQ
+#undef PAVGB
+#undef PREFETCH
+#undef PREFETCHW
+#undef EMMS
+#undef SFENCE
+
+#ifdef HAVE_3DNOW
+/* On K6 femms is faster of emms. On K7 femms is directly mapped on emms. */
+#define EMMS "femms"
+#else
+#define EMMS "emms"
+#endif
+
+#ifdef HAVE_3DNOW
+#define PREFETCH "prefetch"
+#define PREFETCHW "prefetchw"
+#elif defined ( HAVE_MMX2 )
+#define PREFETCH "prefetchnta"
+#define PREFETCHW "prefetcht0"
+#else
+#define PREFETCH " # nop"
+#define PREFETCHW " # nop"
+#endif
+
+#ifdef HAVE_MMX2
+#define SFENCE "sfence"
+#else
+#define SFENCE " # nop"
+#endif
+
+#ifdef HAVE_MMX2
+#define PAVGB(a,b) "pavgb " #a ", " #b " \n\t"
+#elif defined (HAVE_3DNOW)
+#define PAVGB(a,b) "pavgusb " #a ", " #b " \n\t"
+#endif
+
+#ifdef HAVE_MMX2
+#define REAL_MOVNTQ(a,b) "movntq " #a ", " #b " \n\t"
+#else
+#define REAL_MOVNTQ(a,b) "movq " #a ", " #b " \n\t"
+#endif
+#define MOVNTQ(a,b) REAL_MOVNTQ(a,b)
+
+#ifdef HAVE_ALTIVEC
+#include "swscale_altivec_template.c"
+#endif
+
+#define YSCALEYUV2YV12X(x, offset, dest, width) \
+ asm volatile(\
+ "xor %%"REG_a", %%"REG_a" \n\t"\
+ "movq "VROUNDER_OFFSET"(%0), %%mm3\n\t"\
+ "movq %%mm3, %%mm4 \n\t"\
+ "lea " offset "(%0), %%"REG_d" \n\t"\
+ "mov (%%"REG_d"), %%"REG_S" \n\t"\
+ ASMALIGN(4) /* FIXME Unroll? */\
+ "1: \n\t"\
+ "movq 8(%%"REG_d"), %%mm0 \n\t" /* filterCoeff */\
+ "movq " #x "(%%"REG_S", %%"REG_a", 2), %%mm2\n\t" /* srcData */\
+ "movq 8+" #x "(%%"REG_S", %%"REG_a", 2), %%mm5\n\t" /* srcData */\
+ "add $16, %%"REG_d" \n\t"\
+ "mov (%%"REG_d"), %%"REG_S" \n\t"\
+ "test %%"REG_S", %%"REG_S" \n\t"\
+ "pmulhw %%mm0, %%mm2 \n\t"\
+ "pmulhw %%mm0, %%mm5 \n\t"\
+ "paddw %%mm2, %%mm3 \n\t"\
+ "paddw %%mm5, %%mm4 \n\t"\
+ " jnz 1b \n\t"\
+ "psraw $3, %%mm3 \n\t"\
+ "psraw $3, %%mm4 \n\t"\
+ "packuswb %%mm4, %%mm3 \n\t"\
+ MOVNTQ(%%mm3, (%1, %%REGa))\
+ "add $8, %%"REG_a" \n\t"\
+ "cmp %2, %%"REG_a" \n\t"\
+ "movq "VROUNDER_OFFSET"(%0), %%mm3\n\t"\
+ "movq %%mm3, %%mm4 \n\t"\
+ "lea " offset "(%0), %%"REG_d" \n\t"\
+ "mov (%%"REG_d"), %%"REG_S" \n\t"\
+ "jb 1b \n\t"\
+ :: "r" (&c->redDither),\
+ "r" (dest), "g" (width)\
+ : "%"REG_a, "%"REG_d, "%"REG_S\
+ );
+
+#define YSCALEYUV2YV12X_ACCURATE(x, offset, dest, width) \
+ asm volatile(\
+ "lea " offset "(%0), %%"REG_d" \n\t"\
+ "xor %%"REG_a", %%"REG_a" \n\t"\
+ "pxor %%mm4, %%mm4 \n\t"\
+ "pxor %%mm5, %%mm5 \n\t"\
+ "pxor %%mm6, %%mm6 \n\t"\
+ "pxor %%mm7, %%mm7 \n\t"\
+ "mov (%%"REG_d"), %%"REG_S" \n\t"\
+ ASMALIGN(4) \
+ "1: \n\t"\
+ "movq " #x "(%%"REG_S", %%"REG_a", 2), %%mm0\n\t" /* srcData */\
+ "movq 8+" #x "(%%"REG_S", %%"REG_a", 2), %%mm2\n\t" /* srcData */\
+ "mov 4(%%"REG_d"), %%"REG_S" \n\t"\
+ "movq " #x "(%%"REG_S", %%"REG_a", 2), %%mm1\n\t" /* srcData */\
+ "movq %%mm0, %%mm3 \n\t"\
+ "punpcklwd %%mm1, %%mm0 \n\t"\
+ "punpckhwd %%mm1, %%mm3 \n\t"\
+ "movq 8(%%"REG_d"), %%mm1 \n\t" /* filterCoeff */\
+ "pmaddwd %%mm1, %%mm0 \n\t"\
+ "pmaddwd %%mm1, %%mm3 \n\t"\
+ "paddd %%mm0, %%mm4 \n\t"\
+ "paddd %%mm3, %%mm5 \n\t"\
+ "movq 8+" #x "(%%"REG_S", %%"REG_a", 2), %%mm3\n\t" /* srcData */\
+ "mov 16(%%"REG_d"), %%"REG_S" \n\t"\
+ "add $16, %%"REG_d" \n\t"\
+ "test %%"REG_S", %%"REG_S" \n\t"\
+ "movq %%mm2, %%mm0 \n\t"\
+ "punpcklwd %%mm3, %%mm2 \n\t"\
+ "punpckhwd %%mm3, %%mm0 \n\t"\
+ "pmaddwd %%mm1, %%mm2 \n\t"\
+ "pmaddwd %%mm1, %%mm0 \n\t"\
+ "paddd %%mm2, %%mm6 \n\t"\
+ "paddd %%mm0, %%mm7 \n\t"\
+ " jnz 1b \n\t"\
+ "psrad $16, %%mm4 \n\t"\
+ "psrad $16, %%mm5 \n\t"\
+ "psrad $16, %%mm6 \n\t"\
+ "psrad $16, %%mm7 \n\t"\
+ "movq "VROUNDER_OFFSET"(%0), %%mm0\n\t"\
+ "packssdw %%mm5, %%mm4 \n\t"\
+ "packssdw %%mm7, %%mm6 \n\t"\
+ "paddw %%mm0, %%mm4 \n\t"\
+ "paddw %%mm0, %%mm6 \n\t"\
+ "psraw $3, %%mm4 \n\t"\
+ "psraw $3, %%mm6 \n\t"\
+ "packuswb %%mm6, %%mm4 \n\t"\
+ MOVNTQ(%%mm4, (%1, %%REGa))\
+ "add $8, %%"REG_a" \n\t"\
+ "cmp %2, %%"REG_a" \n\t"\
+ "lea " offset "(%0), %%"REG_d" \n\t"\
+ "pxor %%mm4, %%mm4 \n\t"\
+ "pxor %%mm5, %%mm5 \n\t"\
+ "pxor %%mm6, %%mm6 \n\t"\
+ "pxor %%mm7, %%mm7 \n\t"\
+ "mov (%%"REG_d"), %%"REG_S" \n\t"\
+ "jb 1b \n\t"\
+ :: "r" (&c->redDither),\
+ "r" (dest), "g" (width)\
+ : "%"REG_a, "%"REG_d, "%"REG_S\
+ );
+
+#define YSCALEYUV2YV121 \
+ "mov %2, %%"REG_a" \n\t"\
+ ASMALIGN(4) /* FIXME Unroll? */\
+ "1: \n\t"\
+ "movq (%0, %%"REG_a", 2), %%mm0 \n\t"\
+ "movq 8(%0, %%"REG_a", 2), %%mm1\n\t"\
+ "psraw $7, %%mm0 \n\t"\
+ "psraw $7, %%mm1 \n\t"\
+ "packuswb %%mm1, %%mm0 \n\t"\
+ MOVNTQ(%%mm0, (%1, %%REGa))\
+ "add $8, %%"REG_a" \n\t"\
+ "jnc 1b \n\t"
+
+/*
+ :: "m" (-lumFilterSize), "m" (-chrFilterSize),
+ "m" (lumMmxFilter+lumFilterSize*4), "m" (chrMmxFilter+chrFilterSize*4),
+ "r" (dest), "m" (dstW),
+ "m" (lumSrc+lumFilterSize), "m" (chrSrc+chrFilterSize)
+ : "%eax", "%ebx", "%ecx", "%edx", "%esi"
+*/
+#define YSCALEYUV2PACKEDX \
+ asm volatile(\
+ "xor %%"REG_a", %%"REG_a" \n\t"\
+ ASMALIGN(4)\
+ "nop \n\t"\
+ "1: \n\t"\
+ "lea "CHR_MMX_FILTER_OFFSET"(%0), %%"REG_d"\n\t"\
+ "mov (%%"REG_d"), %%"REG_S" \n\t"\
+ "movq "VROUNDER_OFFSET"(%0), %%mm3\n\t"\
+ "movq %%mm3, %%mm4 \n\t"\
+ ASMALIGN(4)\
+ "2: \n\t"\
+ "movq 8(%%"REG_d"), %%mm0 \n\t" /* filterCoeff */\
+ "movq (%%"REG_S", %%"REG_a"), %%mm2 \n\t" /* UsrcData */\
+ "movq 4096(%%"REG_S", %%"REG_a"), %%mm5 \n\t" /* VsrcData */\
+ "add $16, %%"REG_d" \n\t"\
+ "mov (%%"REG_d"), %%"REG_S" \n\t"\
+ "pmulhw %%mm0, %%mm2 \n\t"\
+ "pmulhw %%mm0, %%mm5 \n\t"\
+ "paddw %%mm2, %%mm3 \n\t"\
+ "paddw %%mm5, %%mm4 \n\t"\
+ "test %%"REG_S", %%"REG_S" \n\t"\
+ " jnz 2b \n\t"\
+\
+ "lea "LUM_MMX_FILTER_OFFSET"(%0), %%"REG_d"\n\t"\
+ "mov (%%"REG_d"), %%"REG_S" \n\t"\
+ "movq "VROUNDER_OFFSET"(%0), %%mm1\n\t"\
+ "movq %%mm1, %%mm7 \n\t"\
+ ASMALIGN(4)\
+ "2: \n\t"\
+ "movq 8(%%"REG_d"), %%mm0 \n\t" /* filterCoeff */\
+ "movq (%%"REG_S", %%"REG_a", 2), %%mm2 \n\t" /* Y1srcData */\
+ "movq 8(%%"REG_S", %%"REG_a", 2), %%mm5 \n\t" /* Y2srcData */\
+ "add $16, %%"REG_d" \n\t"\
+ "mov (%%"REG_d"), %%"REG_S" \n\t"\
+ "pmulhw %%mm0, %%mm2 \n\t"\
+ "pmulhw %%mm0, %%mm5 \n\t"\
+ "paddw %%mm2, %%mm1 \n\t"\
+ "paddw %%mm5, %%mm7 \n\t"\
+ "test %%"REG_S", %%"REG_S" \n\t"\
+ " jnz 2b \n\t"\
+
+#define YSCALEYUV2PACKEDX_END\
+ :: "r" (&c->redDither), \
+ "m" (dummy), "m" (dummy), "m" (dummy),\
+ "r" (dest), "m" (dstW)\
+ : "%"REG_a, "%"REG_d, "%"REG_S\
+ );
+
+#define YSCALEYUV2PACKEDX_ACCURATE \
+ asm volatile(\
+ "xor %%"REG_a", %%"REG_a" \n\t"\
+ ASMALIGN(4)\
+ "nop \n\t"\
+ "1: \n\t"\
+ "lea "CHR_MMX_FILTER_OFFSET"(%0), %%"REG_d"\n\t"\
+ "mov (%%"REG_d"), %%"REG_S" \n\t"\
+ "pxor %%mm4, %%mm4 \n\t"\
+ "pxor %%mm5, %%mm5 \n\t"\
+ "pxor %%mm6, %%mm6 \n\t"\
+ "pxor %%mm7, %%mm7 \n\t"\
+ ASMALIGN(4)\
+ "2: \n\t"\
+ "movq (%%"REG_S", %%"REG_a"), %%mm0 \n\t" /* UsrcData */\
+ "movq 4096(%%"REG_S", %%"REG_a"), %%mm2 \n\t" /* VsrcData */\
+ "mov 4(%%"REG_d"), %%"REG_S" \n\t"\
+ "movq (%%"REG_S", %%"REG_a"), %%mm1 \n\t" /* UsrcData */\
+ "movq %%mm0, %%mm3 \n\t"\
+ "punpcklwd %%mm1, %%mm0 \n\t"\
+ "punpckhwd %%mm1, %%mm3 \n\t"\
+ "movq 8(%%"REG_d"), %%mm1 \n\t" /* filterCoeff */\
+ "pmaddwd %%mm1, %%mm0 \n\t"\
+ "pmaddwd %%mm1, %%mm3 \n\t"\
+ "paddd %%mm0, %%mm4 \n\t"\
+ "paddd %%mm3, %%mm5 \n\t"\
+ "movq 4096(%%"REG_S", %%"REG_a"), %%mm3 \n\t" /* VsrcData */\
+ "mov 16(%%"REG_d"), %%"REG_S" \n\t"\
+ "add $16, %%"REG_d" \n\t"\
+ "test %%"REG_S", %%"REG_S" \n\t"\
+ "movq %%mm2, %%mm0 \n\t"\
+ "punpcklwd %%mm3, %%mm2 \n\t"\
+ "punpckhwd %%mm3, %%mm0 \n\t"\
+ "pmaddwd %%mm1, %%mm2 \n\t"\
+ "pmaddwd %%mm1, %%mm0 \n\t"\
+ "paddd %%mm2, %%mm6 \n\t"\
+ "paddd %%mm0, %%mm7 \n\t"\
+ " jnz 2b \n\t"\
+ "psrad $16, %%mm4 \n\t"\
+ "psrad $16, %%mm5 \n\t"\
+ "psrad $16, %%mm6 \n\t"\
+ "psrad $16, %%mm7 \n\t"\
+ "movq "VROUNDER_OFFSET"(%0), %%mm0\n\t"\
+ "packssdw %%mm5, %%mm4 \n\t"\
+ "packssdw %%mm7, %%mm6 \n\t"\
+ "paddw %%mm0, %%mm4 \n\t"\
+ "paddw %%mm0, %%mm6 \n\t"\
+ "movq %%mm4, "U_TEMP"(%0) \n\t"\
+ "movq %%mm6, "V_TEMP"(%0) \n\t"\
+\
+ "lea "LUM_MMX_FILTER_OFFSET"(%0), %%"REG_d"\n\t"\
+ "mov (%%"REG_d"), %%"REG_S" \n\t"\
+ "pxor %%mm1, %%mm1 \n\t"\
+ "pxor %%mm5, %%mm5 \n\t"\
+ "pxor %%mm7, %%mm7 \n\t"\
+ "pxor %%mm6, %%mm6 \n\t"\
+ ASMALIGN(4)\
+ "2: \n\t"\
+ "movq (%%"REG_S", %%"REG_a", 2), %%mm0 \n\t" /* Y1srcData */\
+ "movq 8(%%"REG_S", %%"REG_a", 2), %%mm2 \n\t" /* Y2srcData */\
+ "mov 4(%%"REG_d"), %%"REG_S" \n\t"\
+ "movq (%%"REG_S", %%"REG_a", 2), %%mm4 \n\t" /* Y1srcData */\
+ "movq %%mm0, %%mm3 \n\t"\
+ "punpcklwd %%mm4, %%mm0 \n\t"\
+ "punpckhwd %%mm4, %%mm3 \n\t"\
+ "movq 8(%%"REG_d"), %%mm4 \n\t" /* filterCoeff */\
+ "pmaddwd %%mm4, %%mm0 \n\t"\
+ "pmaddwd %%mm4, %%mm3 \n\t"\
+ "paddd %%mm0, %%mm1 \n\t"\
+ "paddd %%mm3, %%mm5 \n\t"\
+ "movq 8(%%"REG_S", %%"REG_a", 2), %%mm3 \n\t" /* Y2srcData */\
+ "mov 16(%%"REG_d"), %%"REG_S" \n\t"\
+ "add $16, %%"REG_d" \n\t"\
+ "test %%"REG_S", %%"REG_S" \n\t"\
+ "movq %%mm2, %%mm0 \n\t"\
+ "punpcklwd %%mm3, %%mm2 \n\t"\
+ "punpckhwd %%mm3, %%mm0 \n\t"\
+ "pmaddwd %%mm4, %%mm2 \n\t"\
+ "pmaddwd %%mm4, %%mm0 \n\t"\
+ "paddd %%mm2, %%mm7 \n\t"\
+ "paddd %%mm0, %%mm6 \n\t"\
+ " jnz 2b \n\t"\
+ "psrad $16, %%mm1 \n\t"\
+ "psrad $16, %%mm5 \n\t"\
+ "psrad $16, %%mm7 \n\t"\
+ "psrad $16, %%mm6 \n\t"\
+ "movq "VROUNDER_OFFSET"(%0), %%mm0\n\t"\
+ "packssdw %%mm5, %%mm1 \n\t"\
+ "packssdw %%mm6, %%mm7 \n\t"\
+ "paddw %%mm0, %%mm1 \n\t"\
+ "paddw %%mm0, %%mm7 \n\t"\
+ "movq "U_TEMP"(%0), %%mm3 \n\t"\
+ "movq "V_TEMP"(%0), %%mm4 \n\t"\
+
+#define YSCALEYUV2RGBX \
+ "psubw "U_OFFSET"(%0), %%mm3 \n\t" /* (U-128)8*/\
+ "psubw "V_OFFSET"(%0), %%mm4 \n\t" /* (V-128)8*/\
+ "movq %%mm3, %%mm2 \n\t" /* (U-128)8*/\
+ "movq %%mm4, %%mm5 \n\t" /* (V-128)8*/\
+ "pmulhw "UG_COEFF"(%0), %%mm3 \n\t"\
+ "pmulhw "VG_COEFF"(%0), %%mm4 \n\t"\
+ /* mm2=(U-128)8, mm3=ug, mm4=vg mm5=(V-128)8 */\
+ "pmulhw "UB_COEFF"(%0), %%mm2 \n\t"\
+ "pmulhw "VR_COEFF"(%0), %%mm5 \n\t"\
+ "psubw "Y_OFFSET"(%0), %%mm1 \n\t" /* 8(Y-16)*/\
+ "psubw "Y_OFFSET"(%0), %%mm7 \n\t" /* 8(Y-16)*/\
+ "pmulhw "Y_COEFF"(%0), %%mm1 \n\t"\
+ "pmulhw "Y_COEFF"(%0), %%mm7 \n\t"\
+ /* mm1= Y1, mm2=ub, mm3=ug, mm4=vg mm5=vr, mm7=Y2 */\
+ "paddw %%mm3, %%mm4 \n\t"\
+ "movq %%mm2, %%mm0 \n\t"\
+ "movq %%mm5, %%mm6 \n\t"\
+ "movq %%mm4, %%mm3 \n\t"\
+ "punpcklwd %%mm2, %%mm2 \n\t"\
+ "punpcklwd %%mm5, %%mm5 \n\t"\
+ "punpcklwd %%mm4, %%mm4 \n\t"\
+ "paddw %%mm1, %%mm2 \n\t"\
+ "paddw %%mm1, %%mm5 \n\t"\
+ "paddw %%mm1, %%mm4 \n\t"\
+ "punpckhwd %%mm0, %%mm0 \n\t"\
+ "punpckhwd %%mm6, %%mm6 \n\t"\
+ "punpckhwd %%mm3, %%mm3 \n\t"\
+ "paddw %%mm7, %%mm0 \n\t"\
+ "paddw %%mm7, %%mm6 \n\t"\
+ "paddw %%mm7, %%mm3 \n\t"\
+ /* mm0=B1, mm2=B2, mm3=G2, mm4=G1, mm5=R1, mm6=R2 */\
+ "packuswb %%mm0, %%mm2 \n\t"\
+ "packuswb %%mm6, %%mm5 \n\t"\
+ "packuswb %%mm3, %%mm4 \n\t"\
+ "pxor %%mm7, %%mm7 \n\t"
+#if 0
+#define FULL_YSCALEYUV2RGB \
+ "pxor %%mm7, %%mm7 \n\t"\
+ "movd %6, %%mm6 \n\t" /*yalpha1*/\
+ "punpcklwd %%mm6, %%mm6 \n\t"\
+ "punpcklwd %%mm6, %%mm6 \n\t"\
+ "movd %7, %%mm5 \n\t" /*uvalpha1*/\
+ "punpcklwd %%mm5, %%mm5 \n\t"\
+ "punpcklwd %%mm5, %%mm5 \n\t"\
+ "xor %%"REG_a", %%"REG_a" \n\t"\
+ ASMALIGN(4)\
+ "1: \n\t"\
+ "movq (%0, %%"REG_a", 2), %%mm0 \n\t" /*buf0[eax]*/\
+ "movq (%1, %%"REG_a", 2), %%mm1 \n\t" /*buf1[eax]*/\
+ "movq (%2, %%"REG_a",2), %%mm2 \n\t" /* uvbuf0[eax]*/\
+ "movq (%3, %%"REG_a",2), %%mm3 \n\t" /* uvbuf1[eax]*/\
+ "psubw %%mm1, %%mm0 \n\t" /* buf0[eax] - buf1[eax]*/\
+ "psubw %%mm3, %%mm2 \n\t" /* uvbuf0[eax] - uvbuf1[eax]*/\
+ "pmulhw %%mm6, %%mm0 \n\t" /* (buf0[eax] - buf1[eax])yalpha1>>16*/\
+ "pmulhw %%mm5, %%mm2 \n\t" /* (uvbuf0[eax] - uvbuf1[eax])uvalpha1>>16*/\
+ "psraw $4, %%mm1 \n\t" /* buf0[eax] - buf1[eax] >>4*/\
+ "movq 4096(%2, %%"REG_a",2), %%mm4 \n\t" /* uvbuf0[eax+2048]*/\
+ "psraw $4, %%mm3 \n\t" /* uvbuf0[eax] - uvbuf1[eax] >>4*/\
+ "paddw %%mm0, %%mm1 \n\t" /* buf0[eax]yalpha1 + buf1[eax](1-yalpha1) >>16*/\
+ "movq 4096(%3, %%"REG_a",2), %%mm0 \n\t" /* uvbuf1[eax+2048]*/\
+ "paddw %%mm2, %%mm3 \n\t" /* uvbuf0[eax]uvalpha1 - uvbuf1[eax](1-uvalpha1)*/\
+ "psubw %%mm0, %%mm4 \n\t" /* uvbuf0[eax+2048] - uvbuf1[eax+2048]*/\
+ "psubw "MANGLE(w80)", %%mm1 \n\t" /* 8(Y-16)*/\
+ "psubw "MANGLE(w400)", %%mm3 \n\t" /* 8(U-128)*/\
+ "pmulhw "MANGLE(yCoeff)", %%mm1 \n\t"\
+\
+\
+ "pmulhw %%mm5, %%mm4 \n\t" /* (uvbuf0[eax+2048] - uvbuf1[eax+2048])uvalpha1>>16*/\
+ "movq %%mm3, %%mm2 \n\t" /* (U-128)8*/\
+ "pmulhw "MANGLE(ubCoeff)", %%mm3\n\t"\
+ "psraw $4, %%mm0 \n\t" /* uvbuf0[eax+2048] - uvbuf1[eax+2048] >>4*/\
+ "pmulhw "MANGLE(ugCoeff)", %%mm2\n\t"\
+ "paddw %%mm4, %%mm0 \n\t" /* uvbuf0[eax+2048]uvalpha1 - uvbuf1[eax+2048](1-uvalpha1)*/\
+ "psubw "MANGLE(w400)", %%mm0 \n\t" /* (V-128)8*/\
+\
+\
+ "movq %%mm0, %%mm4 \n\t" /* (V-128)8*/\
+ "pmulhw "MANGLE(vrCoeff)", %%mm0\n\t"\
+ "pmulhw "MANGLE(vgCoeff)", %%mm4\n\t"\
+ "paddw %%mm1, %%mm3 \n\t" /* B*/\
+ "paddw %%mm1, %%mm0 \n\t" /* R*/\
+ "packuswb %%mm3, %%mm3 \n\t"\
+\
+ "packuswb %%mm0, %%mm0 \n\t"\
+ "paddw %%mm4, %%mm2 \n\t"\
+ "paddw %%mm2, %%mm1 \n\t" /* G*/\
+\
+ "packuswb %%mm1, %%mm1 \n\t"
+#endif
+
+#define REAL_YSCALEYUV2PACKED(index, c) \
+ "movq "CHR_MMX_FILTER_OFFSET"+8("#c"), %%mm0\n\t"\
+ "movq "LUM_MMX_FILTER_OFFSET"+8("#c"), %%mm1\n\t"\
+ "psraw $3, %%mm0 \n\t"\
+ "psraw $3, %%mm1 \n\t"\
+ "movq %%mm0, "CHR_MMX_FILTER_OFFSET"+8("#c")\n\t"\
+ "movq %%mm1, "LUM_MMX_FILTER_OFFSET"+8("#c")\n\t"\
+ "xor "#index", "#index" \n\t"\
+ ASMALIGN(4)\
+ "1: \n\t"\
+ "movq (%2, "#index"), %%mm2 \n\t" /* uvbuf0[eax]*/\
+ "movq (%3, "#index"), %%mm3 \n\t" /* uvbuf1[eax]*/\
+ "movq 4096(%2, "#index"), %%mm5 \n\t" /* uvbuf0[eax+2048]*/\
+ "movq 4096(%3, "#index"), %%mm4 \n\t" /* uvbuf1[eax+2048]*/\
+ "psubw %%mm3, %%mm2 \n\t" /* uvbuf0[eax] - uvbuf1[eax]*/\
+ "psubw %%mm4, %%mm5 \n\t" /* uvbuf0[eax+2048] - uvbuf1[eax+2048]*/\
+ "movq "CHR_MMX_FILTER_OFFSET"+8("#c"), %%mm0\n\t"\
+ "pmulhw %%mm0, %%mm2 \n\t" /* (uvbuf0[eax] - uvbuf1[eax])uvalpha1>>16*/\
+ "pmulhw %%mm0, %%mm5 \n\t" /* (uvbuf0[eax+2048] - uvbuf1[eax+2048])uvalpha1>>16*/\
+ "psraw $7, %%mm3 \n\t" /* uvbuf0[eax] - uvbuf1[eax] >>4*/\
+ "psraw $7, %%mm4 \n\t" /* uvbuf0[eax+2048] - uvbuf1[eax+2048] >>4*/\
+ "paddw %%mm2, %%mm3 \n\t" /* uvbuf0[eax]uvalpha1 - uvbuf1[eax](1-uvalpha1)*/\
+ "paddw %%mm5, %%mm4 \n\t" /* uvbuf0[eax+2048]uvalpha1 - uvbuf1[eax+2048](1-uvalpha1)*/\
+ "movq (%0, "#index", 2), %%mm0 \n\t" /*buf0[eax]*/\
+ "movq (%1, "#index", 2), %%mm1 \n\t" /*buf1[eax]*/\
+ "movq 8(%0, "#index", 2), %%mm6 \n\t" /*buf0[eax]*/\
+ "movq 8(%1, "#index", 2), %%mm7 \n\t" /*buf1[eax]*/\
+ "psubw %%mm1, %%mm0 \n\t" /* buf0[eax] - buf1[eax]*/\
+ "psubw %%mm7, %%mm6 \n\t" /* buf0[eax] - buf1[eax]*/\
+ "pmulhw "LUM_MMX_FILTER_OFFSET"+8("#c"), %%mm0\n\t" /* (buf0[eax] - buf1[eax])yalpha1>>16*/\
+ "pmulhw "LUM_MMX_FILTER_OFFSET"+8("#c"), %%mm6\n\t" /* (buf0[eax] - buf1[eax])yalpha1>>16*/\
+ "psraw $7, %%mm1 \n\t" /* buf0[eax] - buf1[eax] >>4*/\
+ "psraw $7, %%mm7 \n\t" /* buf0[eax] - buf1[eax] >>4*/\
+ "paddw %%mm0, %%mm1 \n\t" /* buf0[eax]yalpha1 + buf1[eax](1-yalpha1) >>16*/\
+ "paddw %%mm6, %%mm7 \n\t" /* buf0[eax]yalpha1 + buf1[eax](1-yalpha1) >>16*/\
+
+#define YSCALEYUV2PACKED(index, c) REAL_YSCALEYUV2PACKED(index, c)
+
+#define REAL_YSCALEYUV2RGB(index, c) \
+ "xor "#index", "#index" \n\t"\
+ ASMALIGN(4)\
+ "1: \n\t"\
+ "movq (%2, "#index"), %%mm2 \n\t" /* uvbuf0[eax]*/\
+ "movq (%3, "#index"), %%mm3 \n\t" /* uvbuf1[eax]*/\
+ "movq 4096(%2, "#index"), %%mm5\n\t" /* uvbuf0[eax+2048]*/\
+ "movq 4096(%3, "#index"), %%mm4\n\t" /* uvbuf1[eax+2048]*/\
+ "psubw %%mm3, %%mm2 \n\t" /* uvbuf0[eax] - uvbuf1[eax]*/\
+ "psubw %%mm4, %%mm5 \n\t" /* uvbuf0[eax+2048] - uvbuf1[eax+2048]*/\
+ "movq "CHR_MMX_FILTER_OFFSET"+8("#c"), %%mm0\n\t"\
+ "pmulhw %%mm0, %%mm2 \n\t" /* (uvbuf0[eax] - uvbuf1[eax])uvalpha1>>16*/\
+ "pmulhw %%mm0, %%mm5 \n\t" /* (uvbuf0[eax+2048] - uvbuf1[eax+2048])uvalpha1>>16*/\
+ "psraw $4, %%mm3 \n\t" /* uvbuf0[eax] - uvbuf1[eax] >>4*/\
+ "psraw $4, %%mm4 \n\t" /* uvbuf0[eax+2048] - uvbuf1[eax+2048] >>4*/\
+ "paddw %%mm2, %%mm3 \n\t" /* uvbuf0[eax]uvalpha1 - uvbuf1[eax](1-uvalpha1)*/\
+ "paddw %%mm5, %%mm4 \n\t" /* uvbuf0[eax+2048]uvalpha1 - uvbuf1[eax+2048](1-uvalpha1)*/\
+ "psubw "U_OFFSET"("#c"), %%mm3 \n\t" /* (U-128)8*/\
+ "psubw "V_OFFSET"("#c"), %%mm4 \n\t" /* (V-128)8*/\
+ "movq %%mm3, %%mm2 \n\t" /* (U-128)8*/\
+ "movq %%mm4, %%mm5 \n\t" /* (V-128)8*/\
+ "pmulhw "UG_COEFF"("#c"), %%mm3\n\t"\
+ "pmulhw "VG_COEFF"("#c"), %%mm4\n\t"\
+ /* mm2=(U-128)8, mm3=ug, mm4=vg mm5=(V-128)8 */\
+ "movq (%0, "#index", 2), %%mm0 \n\t" /*buf0[eax]*/\
+ "movq (%1, "#index", 2), %%mm1 \n\t" /*buf1[eax]*/\
+ "movq 8(%0, "#index", 2), %%mm6\n\t" /*buf0[eax]*/\
+ "movq 8(%1, "#index", 2), %%mm7\n\t" /*buf1[eax]*/\
+ "psubw %%mm1, %%mm0 \n\t" /* buf0[eax] - buf1[eax]*/\
+ "psubw %%mm7, %%mm6 \n\t" /* buf0[eax] - buf1[eax]*/\
+ "pmulhw "LUM_MMX_FILTER_OFFSET"+8("#c"), %%mm0\n\t" /* (buf0[eax] - buf1[eax])yalpha1>>16*/\
+ "pmulhw "LUM_MMX_FILTER_OFFSET"+8("#c"), %%mm6\n\t" /* (buf0[eax] - buf1[eax])yalpha1>>16*/\
+ "psraw $4, %%mm1 \n\t" /* buf0[eax] - buf1[eax] >>4*/\
+ "psraw $4, %%mm7 \n\t" /* buf0[eax] - buf1[eax] >>4*/\
+ "paddw %%mm0, %%mm1 \n\t" /* buf0[eax]yalpha1 + buf1[eax](1-yalpha1) >>16*/\
+ "paddw %%mm6, %%mm7 \n\t" /* buf0[eax]yalpha1 + buf1[eax](1-yalpha1) >>16*/\
+ "pmulhw "UB_COEFF"("#c"), %%mm2\n\t"\
+ "pmulhw "VR_COEFF"("#c"), %%mm5\n\t"\
+ "psubw "Y_OFFSET"("#c"), %%mm1 \n\t" /* 8(Y-16)*/\
+ "psubw "Y_OFFSET"("#c"), %%mm7 \n\t" /* 8(Y-16)*/\
+ "pmulhw "Y_COEFF"("#c"), %%mm1 \n\t"\
+ "pmulhw "Y_COEFF"("#c"), %%mm7 \n\t"\
+ /* mm1= Y1, mm2=ub, mm3=ug, mm4=vg mm5=vr, mm7=Y2 */\
+ "paddw %%mm3, %%mm4 \n\t"\
+ "movq %%mm2, %%mm0 \n\t"\
+ "movq %%mm5, %%mm6 \n\t"\
+ "movq %%mm4, %%mm3 \n\t"\
+ "punpcklwd %%mm2, %%mm2 \n\t"\
+ "punpcklwd %%mm5, %%mm5 \n\t"\
+ "punpcklwd %%mm4, %%mm4 \n\t"\
+ "paddw %%mm1, %%mm2 \n\t"\
+ "paddw %%mm1, %%mm5 \n\t"\
+ "paddw %%mm1, %%mm4 \n\t"\
+ "punpckhwd %%mm0, %%mm0 \n\t"\
+ "punpckhwd %%mm6, %%mm6 \n\t"\
+ "punpckhwd %%mm3, %%mm3 \n\t"\
+ "paddw %%mm7, %%mm0 \n\t"\
+ "paddw %%mm7, %%mm6 \n\t"\
+ "paddw %%mm7, %%mm3 \n\t"\
+ /* mm0=B1, mm2=B2, mm3=G2, mm4=G1, mm5=R1, mm6=R2 */\
+ "packuswb %%mm0, %%mm2 \n\t"\
+ "packuswb %%mm6, %%mm5 \n\t"\
+ "packuswb %%mm3, %%mm4 \n\t"\
+ "pxor %%mm7, %%mm7 \n\t"
+#define YSCALEYUV2RGB(index, c) REAL_YSCALEYUV2RGB(index, c)
+
+#define REAL_YSCALEYUV2PACKED1(index, c) \
+ "xor "#index", "#index" \n\t"\
+ ASMALIGN(4)\
+ "1: \n\t"\
+ "movq (%2, "#index"), %%mm3 \n\t" /* uvbuf0[eax]*/\
+ "movq 4096(%2, "#index"), %%mm4 \n\t" /* uvbuf0[eax+2048]*/\
+ "psraw $7, %%mm3 \n\t" \
+ "psraw $7, %%mm4 \n\t" \
+ "movq (%0, "#index", 2), %%mm1 \n\t" /*buf0[eax]*/\
+ "movq 8(%0, "#index", 2), %%mm7 \n\t" /*buf0[eax]*/\
+ "psraw $7, %%mm1 \n\t" \
+ "psraw $7, %%mm7 \n\t" \
+
+#define YSCALEYUV2PACKED1(index, c) REAL_YSCALEYUV2PACKED1(index, c)
+
+#define REAL_YSCALEYUV2RGB1(index, c) \
+ "xor "#index", "#index" \n\t"\
+ ASMALIGN(4)\
+ "1: \n\t"\
+ "movq (%2, "#index"), %%mm3 \n\t" /* uvbuf0[eax]*/\
+ "movq 4096(%2, "#index"), %%mm4 \n\t" /* uvbuf0[eax+2048]*/\
+ "psraw $4, %%mm3 \n\t" /* uvbuf0[eax] - uvbuf1[eax] >>4*/\
+ "psraw $4, %%mm4 \n\t" /* uvbuf0[eax+2048] - uvbuf1[eax+2048] >>4*/\
+ "psubw "U_OFFSET"("#c"), %%mm3 \n\t" /* (U-128)8*/\
+ "psubw "V_OFFSET"("#c"), %%mm4 \n\t" /* (V-128)8*/\
+ "movq %%mm3, %%mm2 \n\t" /* (U-128)8*/\
+ "movq %%mm4, %%mm5 \n\t" /* (V-128)8*/\
+ "pmulhw "UG_COEFF"("#c"), %%mm3\n\t"\
+ "pmulhw "VG_COEFF"("#c"), %%mm4\n\t"\
+ /* mm2=(U-128)8, mm3=ug, mm4=vg mm5=(V-128)8 */\
+ "movq (%0, "#index", 2), %%mm1 \n\t" /*buf0[eax]*/\
+ "movq 8(%0, "#index", 2), %%mm7 \n\t" /*buf0[eax]*/\
+ "psraw $4, %%mm1 \n\t" /* buf0[eax] - buf1[eax] >>4*/\
+ "psraw $4, %%mm7 \n\t" /* buf0[eax] - buf1[eax] >>4*/\
+ "pmulhw "UB_COEFF"("#c"), %%mm2\n\t"\
+ "pmulhw "VR_COEFF"("#c"), %%mm5\n\t"\
+ "psubw "Y_OFFSET"("#c"), %%mm1 \n\t" /* 8(Y-16)*/\
+ "psubw "Y_OFFSET"("#c"), %%mm7 \n\t" /* 8(Y-16)*/\
+ "pmulhw "Y_COEFF"("#c"), %%mm1 \n\t"\
+ "pmulhw "Y_COEFF"("#c"), %%mm7 \n\t"\
+ /* mm1= Y1, mm2=ub, mm3=ug, mm4=vg mm5=vr, mm7=Y2 */\
+ "paddw %%mm3, %%mm4 \n\t"\
+ "movq %%mm2, %%mm0 \n\t"\
+ "movq %%mm5, %%mm6 \n\t"\
+ "movq %%mm4, %%mm3 \n\t"\
+ "punpcklwd %%mm2, %%mm2 \n\t"\
+ "punpcklwd %%mm5, %%mm5 \n\t"\
+ "punpcklwd %%mm4, %%mm4 \n\t"\
+ "paddw %%mm1, %%mm2 \n\t"\
+ "paddw %%mm1, %%mm5 \n\t"\
+ "paddw %%mm1, %%mm4 \n\t"\
+ "punpckhwd %%mm0, %%mm0 \n\t"\
+ "punpckhwd %%mm6, %%mm6 \n\t"\
+ "punpckhwd %%mm3, %%mm3 \n\t"\
+ "paddw %%mm7, %%mm0 \n\t"\
+ "paddw %%mm7, %%mm6 \n\t"\
+ "paddw %%mm7, %%mm3 \n\t"\
+ /* mm0=B1, mm2=B2, mm3=G2, mm4=G1, mm5=R1, mm6=R2 */\
+ "packuswb %%mm0, %%mm2 \n\t"\
+ "packuswb %%mm6, %%mm5 \n\t"\
+ "packuswb %%mm3, %%mm4 \n\t"\
+ "pxor %%mm7, %%mm7 \n\t"
+#define YSCALEYUV2RGB1(index, c) REAL_YSCALEYUV2RGB1(index, c)
+
+#define REAL_YSCALEYUV2PACKED1b(index, c) \
+ "xor "#index", "#index" \n\t"\
+ ASMALIGN(4)\
+ "1: \n\t"\
+ "movq (%2, "#index"), %%mm2 \n\t" /* uvbuf0[eax]*/\
+ "movq (%3, "#index"), %%mm3 \n\t" /* uvbuf1[eax]*/\
+ "movq 4096(%2, "#index"), %%mm5 \n\t" /* uvbuf0[eax+2048]*/\
+ "movq 4096(%3, "#index"), %%mm4 \n\t" /* uvbuf1[eax+2048]*/\
+ "paddw %%mm2, %%mm3 \n\t" /* uvbuf0[eax] + uvbuf1[eax]*/\
+ "paddw %%mm5, %%mm4 \n\t" /* uvbuf0[eax+2048] + uvbuf1[eax+2048]*/\
+ "psrlw $8, %%mm3 \n\t" \
+ "psrlw $8, %%mm4 \n\t" \
+ "movq (%0, "#index", 2), %%mm1 \n\t" /*buf0[eax]*/\
+ "movq 8(%0, "#index", 2), %%mm7 \n\t" /*buf0[eax]*/\
+ "psraw $7, %%mm1 \n\t" \
+ "psraw $7, %%mm7 \n\t"
+#define YSCALEYUV2PACKED1b(index, c) REAL_YSCALEYUV2PACKED1b(index, c)
+
+// do vertical chrominance interpolation
+#define REAL_YSCALEYUV2RGB1b(index, c) \
+ "xor "#index", "#index" \n\t"\
+ ASMALIGN(4)\
+ "1: \n\t"\
+ "movq (%2, "#index"), %%mm2 \n\t" /* uvbuf0[eax]*/\
+ "movq (%3, "#index"), %%mm3 \n\t" /* uvbuf1[eax]*/\
+ "movq 4096(%2, "#index"), %%mm5 \n\t" /* uvbuf0[eax+2048]*/\
+ "movq 4096(%3, "#index"), %%mm4 \n\t" /* uvbuf1[eax+2048]*/\
+ "paddw %%mm2, %%mm3 \n\t" /* uvbuf0[eax] + uvbuf1[eax]*/\
+ "paddw %%mm5, %%mm4 \n\t" /* uvbuf0[eax+2048] + uvbuf1[eax+2048]*/\
+ "psrlw $5, %%mm3 \n\t" /*FIXME might overflow*/\
+ "psrlw $5, %%mm4 \n\t" /*FIXME might overflow*/\
+ "psubw "U_OFFSET"("#c"), %%mm3 \n\t" /* (U-128)8*/\
+ "psubw "V_OFFSET"("#c"), %%mm4 \n\t" /* (V-128)8*/\
+ "movq %%mm3, %%mm2 \n\t" /* (U-128)8*/\
+ "movq %%mm4, %%mm5 \n\t" /* (V-128)8*/\
+ "pmulhw "UG_COEFF"("#c"), %%mm3\n\t"\
+ "pmulhw "VG_COEFF"("#c"), %%mm4\n\t"\
+ /* mm2=(U-128)8, mm3=ug, mm4=vg mm5=(V-128)8 */\
+ "movq (%0, "#index", 2), %%mm1 \n\t" /*buf0[eax]*/\
+ "movq 8(%0, "#index", 2), %%mm7 \n\t" /*buf0[eax]*/\
+ "psraw $4, %%mm1 \n\t" /* buf0[eax] - buf1[eax] >>4*/\
+ "psraw $4, %%mm7 \n\t" /* buf0[eax] - buf1[eax] >>4*/\
+ "pmulhw "UB_COEFF"("#c"), %%mm2\n\t"\
+ "pmulhw "VR_COEFF"("#c"), %%mm5\n\t"\
+ "psubw "Y_OFFSET"("#c"), %%mm1 \n\t" /* 8(Y-16)*/\
+ "psubw "Y_OFFSET"("#c"), %%mm7 \n\t" /* 8(Y-16)*/\
+ "pmulhw "Y_COEFF"("#c"), %%mm1 \n\t"\
+ "pmulhw "Y_COEFF"("#c"), %%mm7 \n\t"\
+ /* mm1= Y1, mm2=ub, mm3=ug, mm4=vg mm5=vr, mm7=Y2 */\
+ "paddw %%mm3, %%mm4 \n\t"\
+ "movq %%mm2, %%mm0 \n\t"\
+ "movq %%mm5, %%mm6 \n\t"\
+ "movq %%mm4, %%mm3 \n\t"\
+ "punpcklwd %%mm2, %%mm2 \n\t"\
+ "punpcklwd %%mm5, %%mm5 \n\t"\
+ "punpcklwd %%mm4, %%mm4 \n\t"\
+ "paddw %%mm1, %%mm2 \n\t"\
+ "paddw %%mm1, %%mm5 \n\t"\
+ "paddw %%mm1, %%mm4 \n\t"\
+ "punpckhwd %%mm0, %%mm0 \n\t"\
+ "punpckhwd %%mm6, %%mm6 \n\t"\
+ "punpckhwd %%mm3, %%mm3 \n\t"\
+ "paddw %%mm7, %%mm0 \n\t"\
+ "paddw %%mm7, %%mm6 \n\t"\
+ "paddw %%mm7, %%mm3 \n\t"\
+ /* mm0=B1, mm2=B2, mm3=G2, mm4=G1, mm5=R1, mm6=R2 */\
+ "packuswb %%mm0, %%mm2 \n\t"\
+ "packuswb %%mm6, %%mm5 \n\t"\
+ "packuswb %%mm3, %%mm4 \n\t"\
+ "pxor %%mm7, %%mm7 \n\t"
+#define YSCALEYUV2RGB1b(index, c) REAL_YSCALEYUV2RGB1b(index, c)
+
+#define REAL_WRITEBGR32(dst, dstw, index) \
+ /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */\
+ "movq %%mm2, %%mm1 \n\t" /* B */\
+ "movq %%mm5, %%mm6 \n\t" /* R */\
+ "punpcklbw %%mm4, %%mm2 \n\t" /* GBGBGBGB 0 */\
+ "punpcklbw %%mm7, %%mm5 \n\t" /* 0R0R0R0R 0 */\
+ "punpckhbw %%mm4, %%mm1 \n\t" /* GBGBGBGB 2 */\
+ "punpckhbw %%mm7, %%mm6 \n\t" /* 0R0R0R0R 2 */\
+ "movq %%mm2, %%mm0 \n\t" /* GBGBGBGB 0 */\
+ "movq %%mm1, %%mm3 \n\t" /* GBGBGBGB 2 */\
+ "punpcklwd %%mm5, %%mm0 \n\t" /* 0RGB0RGB 0 */\
+ "punpckhwd %%mm5, %%mm2 \n\t" /* 0RGB0RGB 1 */\
+ "punpcklwd %%mm6, %%mm1 \n\t" /* 0RGB0RGB 2 */\
+ "punpckhwd %%mm6, %%mm3 \n\t" /* 0RGB0RGB 3 */\
+\
+ MOVNTQ(%%mm0, (dst, index, 4))\
+ MOVNTQ(%%mm2, 8(dst, index, 4))\
+ MOVNTQ(%%mm1, 16(dst, index, 4))\
+ MOVNTQ(%%mm3, 24(dst, index, 4))\
+\
+ "add $8, "#index" \n\t"\
+ "cmp "#dstw", "#index" \n\t"\
+ " jb 1b \n\t"
+#define WRITEBGR32(dst, dstw, index) REAL_WRITEBGR32(dst, dstw, index)
+
+#define REAL_WRITEBGR16(dst, dstw, index) \
+ "pand "MANGLE(bF8)", %%mm2 \n\t" /* B */\
+ "pand "MANGLE(bFC)", %%mm4 \n\t" /* G */\
+ "pand "MANGLE(bF8)", %%mm5 \n\t" /* R */\
+ "psrlq $3, %%mm2 \n\t"\
+\
+ "movq %%mm2, %%mm1 \n\t"\
+ "movq %%mm4, %%mm3 \n\t"\
+\
+ "punpcklbw %%mm7, %%mm3 \n\t"\
+ "punpcklbw %%mm5, %%mm2 \n\t"\
+ "punpckhbw %%mm7, %%mm4 \n\t"\
+ "punpckhbw %%mm5, %%mm1 \n\t"\
+\
+ "psllq $3, %%mm3 \n\t"\
+ "psllq $3, %%mm4 \n\t"\
+\
+ "por %%mm3, %%mm2 \n\t"\
+ "por %%mm4, %%mm1 \n\t"\
+\
+ MOVNTQ(%%mm2, (dst, index, 2))\
+ MOVNTQ(%%mm1, 8(dst, index, 2))\
+\
+ "add $8, "#index" \n\t"\
+ "cmp "#dstw", "#index" \n\t"\
+ " jb 1b \n\t"
+#define WRITEBGR16(dst, dstw, index) REAL_WRITEBGR16(dst, dstw, index)
+
+#define REAL_WRITEBGR15(dst, dstw, index) \
+ "pand "MANGLE(bF8)", %%mm2 \n\t" /* B */\
+ "pand "MANGLE(bF8)", %%mm4 \n\t" /* G */\
+ "pand "MANGLE(bF8)", %%mm5 \n\t" /* R */\
+ "psrlq $3, %%mm2 \n\t"\
+ "psrlq $1, %%mm5 \n\t"\
+\
+ "movq %%mm2, %%mm1 \n\t"\
+ "movq %%mm4, %%mm3 \n\t"\
+\
+ "punpcklbw %%mm7, %%mm3 \n\t"\
+ "punpcklbw %%mm5, %%mm2 \n\t"\
+ "punpckhbw %%mm7, %%mm4 \n\t"\
+ "punpckhbw %%mm5, %%mm1 \n\t"\
+\
+ "psllq $2, %%mm3 \n\t"\
+ "psllq $2, %%mm4 \n\t"\
+\
+ "por %%mm3, %%mm2 \n\t"\
+ "por %%mm4, %%mm1 \n\t"\
+\
+ MOVNTQ(%%mm2, (dst, index, 2))\
+ MOVNTQ(%%mm1, 8(dst, index, 2))\
+\
+ "add $8, "#index" \n\t"\
+ "cmp "#dstw", "#index" \n\t"\
+ " jb 1b \n\t"
+#define WRITEBGR15(dst, dstw, index) REAL_WRITEBGR15(dst, dstw, index)
+
+#define WRITEBGR24OLD(dst, dstw, index) \
+ /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */\
+ "movq %%mm2, %%mm1 \n\t" /* B */\
+ "movq %%mm5, %%mm6 \n\t" /* R */\
+ "punpcklbw %%mm4, %%mm2 \n\t" /* GBGBGBGB 0 */\
+ "punpcklbw %%mm7, %%mm5 \n\t" /* 0R0R0R0R 0 */\
+ "punpckhbw %%mm4, %%mm1 \n\t" /* GBGBGBGB 2 */\
+ "punpckhbw %%mm7, %%mm6 \n\t" /* 0R0R0R0R 2 */\
+ "movq %%mm2, %%mm0 \n\t" /* GBGBGBGB 0 */\
+ "movq %%mm1, %%mm3 \n\t" /* GBGBGBGB 2 */\
+ "punpcklwd %%mm5, %%mm0 \n\t" /* 0RGB0RGB 0 */\
+ "punpckhwd %%mm5, %%mm2 \n\t" /* 0RGB0RGB 1 */\
+ "punpcklwd %%mm6, %%mm1 \n\t" /* 0RGB0RGB 2 */\
+ "punpckhwd %%mm6, %%mm3 \n\t" /* 0RGB0RGB 3 */\
+\
+ "movq %%mm0, %%mm4 \n\t" /* 0RGB0RGB 0 */\
+ "psrlq $8, %%mm0 \n\t" /* 00RGB0RG 0 */\
+ "pand "MANGLE(bm00000111)", %%mm4\n\t" /* 00000RGB 0 */\
+ "pand "MANGLE(bm11111000)", %%mm0\n\t" /* 00RGB000 0.5 */\
+ "por %%mm4, %%mm0 \n\t" /* 00RGBRGB 0 */\
+ "movq %%mm2, %%mm4 \n\t" /* 0RGB0RGB 1 */\
+ "psllq $48, %%mm2 \n\t" /* GB000000 1 */\
+ "por %%mm2, %%mm0 \n\t" /* GBRGBRGB 0 */\
+\
+ "movq %%mm4, %%mm2 \n\t" /* 0RGB0RGB 1 */\
+ "psrld $16, %%mm4 \n\t" /* 000R000R 1 */\
+ "psrlq $24, %%mm2 \n\t" /* 0000RGB0 1.5 */\
+ "por %%mm4, %%mm2 \n\t" /* 000RRGBR 1 */\
+ "pand "MANGLE(bm00001111)", %%mm2\n\t" /* 0000RGBR 1 */\
+ "movq %%mm1, %%mm4 \n\t" /* 0RGB0RGB 2 */\
+ "psrlq $8, %%mm1 \n\t" /* 00RGB0RG 2 */\
+ "pand "MANGLE(bm00000111)", %%mm4\n\t" /* 00000RGB 2 */\
+ "pand "MANGLE(bm11111000)", %%mm1\n\t" /* 00RGB000 2.5 */\
+ "por %%mm4, %%mm1 \n\t" /* 00RGBRGB 2 */\
+ "movq %%mm1, %%mm4 \n\t" /* 00RGBRGB 2 */\
+ "psllq $32, %%mm1 \n\t" /* BRGB0000 2 */\
+ "por %%mm1, %%mm2 \n\t" /* BRGBRGBR 1 */\
+\
+ "psrlq $32, %%mm4 \n\t" /* 000000RG 2.5 */\
+ "movq %%mm3, %%mm5 \n\t" /* 0RGB0RGB 3 */\
+ "psrlq $8, %%mm3 \n\t" /* 00RGB0RG 3 */\
+ "pand "MANGLE(bm00000111)", %%mm5\n\t" /* 00000RGB 3 */\
+ "pand "MANGLE(bm11111000)", %%mm3\n\t" /* 00RGB000 3.5 */\
+ "por %%mm5, %%mm3 \n\t" /* 00RGBRGB 3 */\
+ "psllq $16, %%mm3 \n\t" /* RGBRGB00 3 */\
+ "por %%mm4, %%mm3 \n\t" /* RGBRGBRG 2.5 */\
+\
+ MOVNTQ(%%mm0, (dst))\
+ MOVNTQ(%%mm2, 8(dst))\
+ MOVNTQ(%%mm3, 16(dst))\
+ "add $24, "#dst" \n\t"\
+\
+ "add $8, "#index" \n\t"\
+ "cmp "#dstw", "#index" \n\t"\
+ " jb 1b \n\t"
+
+#define WRITEBGR24MMX(dst, dstw, index) \
+ /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */\
+ "movq %%mm2, %%mm1 \n\t" /* B */\
+ "movq %%mm5, %%mm6 \n\t" /* R */\
+ "punpcklbw %%mm4, %%mm2 \n\t" /* GBGBGBGB 0 */\
+ "punpcklbw %%mm7, %%mm5 \n\t" /* 0R0R0R0R 0 */\
+ "punpckhbw %%mm4, %%mm1 \n\t" /* GBGBGBGB 2 */\
+ "punpckhbw %%mm7, %%mm6 \n\t" /* 0R0R0R0R 2 */\
+ "movq %%mm2, %%mm0 \n\t" /* GBGBGBGB 0 */\
+ "movq %%mm1, %%mm3 \n\t" /* GBGBGBGB 2 */\
+ "punpcklwd %%mm5, %%mm0 \n\t" /* 0RGB0RGB 0 */\
+ "punpckhwd %%mm5, %%mm2 \n\t" /* 0RGB0RGB 1 */\
+ "punpcklwd %%mm6, %%mm1 \n\t" /* 0RGB0RGB 2 */\
+ "punpckhwd %%mm6, %%mm3 \n\t" /* 0RGB0RGB 3 */\
+\
+ "movq %%mm0, %%mm4 \n\t" /* 0RGB0RGB 0 */\
+ "movq %%mm2, %%mm6 \n\t" /* 0RGB0RGB 1 */\
+ "movq %%mm1, %%mm5 \n\t" /* 0RGB0RGB 2 */\
+ "movq %%mm3, %%mm7 \n\t" /* 0RGB0RGB 3 */\
+\
+ "psllq $40, %%mm0 \n\t" /* RGB00000 0 */\
+ "psllq $40, %%mm2 \n\t" /* RGB00000 1 */\
+ "psllq $40, %%mm1 \n\t" /* RGB00000 2 */\
+ "psllq $40, %%mm3 \n\t" /* RGB00000 3 */\
+\
+ "punpckhdq %%mm4, %%mm0 \n\t" /* 0RGBRGB0 0 */\
+ "punpckhdq %%mm6, %%mm2 \n\t" /* 0RGBRGB0 1 */\
+ "punpckhdq %%mm5, %%mm1 \n\t" /* 0RGBRGB0 2 */\
+ "punpckhdq %%mm7, %%mm3 \n\t" /* 0RGBRGB0 3 */\
+\
+ "psrlq $8, %%mm0 \n\t" /* 00RGBRGB 0 */\
+ "movq %%mm2, %%mm6 \n\t" /* 0RGBRGB0 1 */\
+ "psllq $40, %%mm2 \n\t" /* GB000000 1 */\
+ "por %%mm2, %%mm0 \n\t" /* GBRGBRGB 0 */\
+ MOVNTQ(%%mm0, (dst))\
+\
+ "psrlq $24, %%mm6 \n\t" /* 0000RGBR 1 */\
+ "movq %%mm1, %%mm5 \n\t" /* 0RGBRGB0 2 */\
+ "psllq $24, %%mm1 \n\t" /* BRGB0000 2 */\
+ "por %%mm1, %%mm6 \n\t" /* BRGBRGBR 1 */\
+ MOVNTQ(%%mm6, 8(dst))\
+\
+ "psrlq $40, %%mm5 \n\t" /* 000000RG 2 */\
+ "psllq $8, %%mm3 \n\t" /* RGBRGB00 3 */\
+ "por %%mm3, %%mm5 \n\t" /* RGBRGBRG 2 */\
+ MOVNTQ(%%mm5, 16(dst))\
+\
+ "add $24, "#dst" \n\t"\
+\
+ "add $8, "#index" \n\t"\
+ "cmp "#dstw", "#index" \n\t"\
+ " jb 1b \n\t"
+
+#define WRITEBGR24MMX2(dst, dstw, index) \
+ /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */\
+ "movq "MANGLE(M24A)", %%mm0 \n\t"\
+ "movq "MANGLE(M24C)", %%mm7 \n\t"\
+ "pshufw $0x50, %%mm2, %%mm1 \n\t" /* B3 B2 B3 B2 B1 B0 B1 B0 */\
+ "pshufw $0x50, %%mm4, %%mm3 \n\t" /* G3 G2 G3 G2 G1 G0 G1 G0 */\
+ "pshufw $0x00, %%mm5, %%mm6 \n\t" /* R1 R0 R1 R0 R1 R0 R1 R0 */\
+\
+ "pand %%mm0, %%mm1 \n\t" /* B2 B1 B0 */\
+ "pand %%mm0, %%mm3 \n\t" /* G2 G1 G0 */\
+ "pand %%mm7, %%mm6 \n\t" /* R1 R0 */\
+\
+ "psllq $8, %%mm3 \n\t" /* G2 G1 G0 */\
+ "por %%mm1, %%mm6 \n\t"\
+ "por %%mm3, %%mm6 \n\t"\
+ MOVNTQ(%%mm6, (dst))\
+\
+ "psrlq $8, %%mm4 \n\t" /* 00 G7 G6 G5 G4 G3 G2 G1 */\
+ "pshufw $0xA5, %%mm2, %%mm1 \n\t" /* B5 B4 B5 B4 B3 B2 B3 B2 */\
+ "pshufw $0x55, %%mm4, %%mm3 \n\t" /* G4 G3 G4 G3 G4 G3 G4 G3 */\
+ "pshufw $0xA5, %%mm5, %%mm6 \n\t" /* R5 R4 R5 R4 R3 R2 R3 R2 */\
+\
+ "pand "MANGLE(M24B)", %%mm1 \n\t" /* B5 B4 B3 */\
+ "pand %%mm7, %%mm3 \n\t" /* G4 G3 */\
+ "pand %%mm0, %%mm6 \n\t" /* R4 R3 R2 */\
+\
+ "por %%mm1, %%mm3 \n\t" /* B5 G4 B4 G3 B3 */\
+ "por %%mm3, %%mm6 \n\t"\
+ MOVNTQ(%%mm6, 8(dst))\
+\
+ "pshufw $0xFF, %%mm2, %%mm1 \n\t" /* B7 B6 B7 B6 B7 B6 B6 B7 */\
+ "pshufw $0xFA, %%mm4, %%mm3 \n\t" /* 00 G7 00 G7 G6 G5 G6 G5 */\
+ "pshufw $0xFA, %%mm5, %%mm6 \n\t" /* R7 R6 R7 R6 R5 R4 R5 R4 */\
+\
+ "pand %%mm7, %%mm1 \n\t" /* B7 B6 */\
+ "pand %%mm0, %%mm3 \n\t" /* G7 G6 G5 */\
+ "pand "MANGLE(M24B)", %%mm6 \n\t" /* R7 R6 R5 */\
+\
+ "por %%mm1, %%mm3 \n\t"\
+ "por %%mm3, %%mm6 \n\t"\
+ MOVNTQ(%%mm6, 16(dst))\
+\
+ "add $24, "#dst" \n\t"\
+\
+ "add $8, "#index" \n\t"\
+ "cmp "#dstw", "#index" \n\t"\
+ " jb 1b \n\t"
+
+#ifdef HAVE_MMX2
+#undef WRITEBGR24
+#define WRITEBGR24(dst, dstw, index) WRITEBGR24MMX2(dst, dstw, index)
+#else
+#undef WRITEBGR24
+#define WRITEBGR24(dst, dstw, index) WRITEBGR24MMX(dst, dstw, index)
+#endif
+
+#define REAL_WRITEYUY2(dst, dstw, index) \
+ "packuswb %%mm3, %%mm3 \n\t"\
+ "packuswb %%mm4, %%mm4 \n\t"\
+ "packuswb %%mm7, %%mm1 \n\t"\
+ "punpcklbw %%mm4, %%mm3 \n\t"\
+ "movq %%mm1, %%mm7 \n\t"\
+ "punpcklbw %%mm3, %%mm1 \n\t"\
+ "punpckhbw %%mm3, %%mm7 \n\t"\
+\
+ MOVNTQ(%%mm1, (dst, index, 2))\
+ MOVNTQ(%%mm7, 8(dst, index, 2))\
+\
+ "add $8, "#index" \n\t"\
+ "cmp "#dstw", "#index" \n\t"\
+ " jb 1b \n\t"
+#define WRITEYUY2(dst, dstw, index) REAL_WRITEYUY2(dst, dstw, index)
+
+
+static inline void RENAME(yuv2yuvX)(SwsContext *c, int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
+ int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
+ uint8_t *dest, uint8_t *uDest, uint8_t *vDest, long dstW, long chrDstW)
+{
+#ifdef HAVE_MMX
+ if(c->flags & SWS_ACCURATE_RND){
+ if(uDest){
+ YSCALEYUV2YV12X_ACCURATE( 0, CHR_MMX_FILTER_OFFSET, uDest, chrDstW)
+ YSCALEYUV2YV12X_ACCURATE(4096, CHR_MMX_FILTER_OFFSET, vDest, chrDstW)
+ }
+
+ YSCALEYUV2YV12X_ACCURATE(0, LUM_MMX_FILTER_OFFSET, dest, dstW)
+ }else{
+ if(uDest){
+ YSCALEYUV2YV12X( 0, CHR_MMX_FILTER_OFFSET, uDest, chrDstW)
+ YSCALEYUV2YV12X(4096, CHR_MMX_FILTER_OFFSET, vDest, chrDstW)
+ }
+
+ YSCALEYUV2YV12X(0, LUM_MMX_FILTER_OFFSET, dest, dstW)
+ }
+#else
+#ifdef HAVE_ALTIVEC
+yuv2yuvX_altivec_real(lumFilter, lumSrc, lumFilterSize,
+ chrFilter, chrSrc, chrFilterSize,
+ dest, uDest, vDest, dstW, chrDstW);
+#else //HAVE_ALTIVEC
+yuv2yuvXinC(lumFilter, lumSrc, lumFilterSize,
+ chrFilter, chrSrc, chrFilterSize,
+ dest, uDest, vDest, dstW, chrDstW);
+#endif //!HAVE_ALTIVEC
+#endif
+}
+
+static inline void RENAME(yuv2nv12X)(SwsContext *c, int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
+ int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
+ uint8_t *dest, uint8_t *uDest, int dstW, int chrDstW, int dstFormat)
+{
+yuv2nv12XinC(lumFilter, lumSrc, lumFilterSize,
+ chrFilter, chrSrc, chrFilterSize,
+ dest, uDest, dstW, chrDstW, dstFormat);
+}
+
+static inline void RENAME(yuv2yuv1)(int16_t *lumSrc, int16_t *chrSrc,
+ uint8_t *dest, uint8_t *uDest, uint8_t *vDest, long dstW, long chrDstW)
+{
+#ifdef HAVE_MMX
+ if(uDest != NULL)
+ {
+ asm volatile(
+ YSCALEYUV2YV121
+ :: "r" (chrSrc + chrDstW), "r" (uDest + chrDstW),
+ "g" (-chrDstW)
+ : "%"REG_a
+ );
+
+ asm volatile(
+ YSCALEYUV2YV121
+ :: "r" (chrSrc + 2048 + chrDstW), "r" (vDest + chrDstW),
+ "g" (-chrDstW)
+ : "%"REG_a
+ );
+ }
+
+ asm volatile(
+ YSCALEYUV2YV121
+ :: "r" (lumSrc + dstW), "r" (dest + dstW),
+ "g" (-dstW)
+ : "%"REG_a
+ );
+#else
+ int i;
+ for(i=0; i<dstW; i++)
+ {
+ int val= lumSrc[i]>>7;
+
+ if(val&256){
+ if(val<0) val=0;
+ else val=255;
+ }
+
+ dest[i]= val;
+ }
+
+ if(uDest != NULL)
+ for(i=0; i<chrDstW; i++)
+ {
+ int u=chrSrc[i]>>7;
+ int v=chrSrc[i + 2048]>>7;
+
+ if((u|v)&256){
+ if(u<0) u=0;
+ else if (u>255) u=255;
+ if(v<0) v=0;
+ else if (v>255) v=255;
+ }
+
+ uDest[i]= u;
+ vDest[i]= v;
+ }
+#endif
+}
+
+
+/**
+ * vertical scale YV12 to RGB
+ */
+static inline void RENAME(yuv2packedX)(SwsContext *c, int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
+ int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
+ uint8_t *dest, long dstW, long dstY)
+{
+#ifdef HAVE_MMX
+ long dummy=0;
+ if(c->flags & SWS_ACCURATE_RND){
+ switch(c->dstFormat){
+ case PIX_FMT_RGB32:
+ YSCALEYUV2PACKEDX_ACCURATE
+ YSCALEYUV2RGBX
+ WRITEBGR32(%4, %5, %%REGa)
+
+ YSCALEYUV2PACKEDX_END
+ return;
+ case PIX_FMT_BGR24:
+ YSCALEYUV2PACKEDX_ACCURATE
+ YSCALEYUV2RGBX
+ "lea (%%"REG_a", %%"REG_a", 2), %%"REG_c"\n\t" //FIXME optimize
+ "add %4, %%"REG_c" \n\t"
+ WRITEBGR24(%%REGc, %5, %%REGa)
+
+
+ :: "r" (&c->redDither),
+ "m" (dummy), "m" (dummy), "m" (dummy),
+ "r" (dest), "m" (dstW)
+ : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S
+ );
+ return;
+ case PIX_FMT_BGR555:
+ YSCALEYUV2PACKEDX_ACCURATE
+ YSCALEYUV2RGBX
+ /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */
+#ifdef DITHER1XBPP
+ "paddusb "MANGLE(b5Dither)", %%mm2\n\t"
+ "paddusb "MANGLE(g5Dither)", %%mm4\n\t"
+ "paddusb "MANGLE(r5Dither)", %%mm5\n\t"
+#endif
+
+ WRITEBGR15(%4, %5, %%REGa)
+ YSCALEYUV2PACKEDX_END
+ return;
+ case PIX_FMT_BGR565:
+ YSCALEYUV2PACKEDX_ACCURATE
+ YSCALEYUV2RGBX
+ /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */
+#ifdef DITHER1XBPP
+ "paddusb "MANGLE(b5Dither)", %%mm2\n\t"
+ "paddusb "MANGLE(g6Dither)", %%mm4\n\t"
+ "paddusb "MANGLE(r5Dither)", %%mm5\n\t"
+#endif
+
+ WRITEBGR16(%4, %5, %%REGa)
+ YSCALEYUV2PACKEDX_END
+ return;
+ case PIX_FMT_YUYV422:
+ YSCALEYUV2PACKEDX_ACCURATE
+ /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */
+
+ "psraw $3, %%mm3 \n\t"
+ "psraw $3, %%mm4 \n\t"
+ "psraw $3, %%mm1 \n\t"
+ "psraw $3, %%mm7 \n\t"
+ WRITEYUY2(%4, %5, %%REGa)
+ YSCALEYUV2PACKEDX_END
+ return;
+ }
+ }else{
+ switch(c->dstFormat)
+ {
+ case PIX_FMT_RGB32:
+ YSCALEYUV2PACKEDX
+ YSCALEYUV2RGBX
+ WRITEBGR32(%4, %5, %%REGa)
+ YSCALEYUV2PACKEDX_END
+ return;
+ case PIX_FMT_BGR24:
+ YSCALEYUV2PACKEDX
+ YSCALEYUV2RGBX
+ "lea (%%"REG_a", %%"REG_a", 2), %%"REG_c"\n\t" //FIXME optimize
+ "add %4, %%"REG_c" \n\t"
+ WRITEBGR24(%%REGc, %5, %%REGa)
+
+ :: "r" (&c->redDither),
+ "m" (dummy), "m" (dummy), "m" (dummy),
+ "r" (dest), "m" (dstW)
+ : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S
+ );
+ return;
+ case PIX_FMT_BGR555:
+ YSCALEYUV2PACKEDX
+ YSCALEYUV2RGBX
+ /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */
+#ifdef DITHER1XBPP
+ "paddusb "MANGLE(b5Dither)", %%mm2\n\t"
+ "paddusb "MANGLE(g5Dither)", %%mm4\n\t"
+ "paddusb "MANGLE(r5Dither)", %%mm5\n\t"
+#endif
+
+ WRITEBGR15(%4, %5, %%REGa)
+ YSCALEYUV2PACKEDX_END
+ return;
+ case PIX_FMT_BGR565:
+ YSCALEYUV2PACKEDX
+ YSCALEYUV2RGBX
+ /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */
+#ifdef DITHER1XBPP
+ "paddusb "MANGLE(b5Dither)", %%mm2\n\t"
+ "paddusb "MANGLE(g6Dither)", %%mm4\n\t"
+ "paddusb "MANGLE(r5Dither)", %%mm5\n\t"
+#endif
+
+ WRITEBGR16(%4, %5, %%REGa)
+ YSCALEYUV2PACKEDX_END
+ return;
+ case PIX_FMT_YUYV422:
+ YSCALEYUV2PACKEDX
+ /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */
+
+ "psraw $3, %%mm3 \n\t"
+ "psraw $3, %%mm4 \n\t"
+ "psraw $3, %%mm1 \n\t"
+ "psraw $3, %%mm7 \n\t"
+ WRITEYUY2(%4, %5, %%REGa)
+ YSCALEYUV2PACKEDX_END
+ return;
+ }
+ }
+#endif
+#ifdef HAVE_ALTIVEC
+ /* The following list of supported dstFormat values should
+ match what's found in the body of altivec_yuv2packedX() */
+ if(c->dstFormat==PIX_FMT_ABGR || c->dstFormat==PIX_FMT_BGRA ||
+ c->dstFormat==PIX_FMT_BGR24 || c->dstFormat==PIX_FMT_RGB24 ||
+ c->dstFormat==PIX_FMT_RGBA || c->dstFormat==PIX_FMT_ARGB)
+ altivec_yuv2packedX (c, lumFilter, lumSrc, lumFilterSize,
+ chrFilter, chrSrc, chrFilterSize,
+ dest, dstW, dstY);
+ else
+#endif
+ yuv2packedXinC(c, lumFilter, lumSrc, lumFilterSize,
+ chrFilter, chrSrc, chrFilterSize,
+ dest, dstW, dstY);
+}
+
+/**
+ * vertical bilinear scale YV12 to RGB
+ */
+static inline void RENAME(yuv2packed2)(SwsContext *c, uint16_t *buf0, uint16_t *buf1, uint16_t *uvbuf0, uint16_t *uvbuf1,
+ uint8_t *dest, int dstW, int yalpha, int uvalpha, int y)
+{
+ int yalpha1=yalpha^4095;
+ int uvalpha1=uvalpha^4095;
+ int i;
+
+#if 0 //isn't used
+ if(flags&SWS_FULL_CHR_H_INT)
+ {
+ switch(dstFormat)
+ {
+#ifdef HAVE_MMX
+ case PIX_FMT_RGB32:
+ asm volatile(
+
+
+FULL_YSCALEYUV2RGB
+ "punpcklbw %%mm1, %%mm3 \n\t" // BGBGBGBG
+ "punpcklbw %%mm7, %%mm0 \n\t" // R0R0R0R0
+
+ "movq %%mm3, %%mm1 \n\t"
+ "punpcklwd %%mm0, %%mm3 \n\t" // BGR0BGR0
+ "punpckhwd %%mm0, %%mm1 \n\t" // BGR0BGR0
+
+ MOVNTQ(%%mm3, (%4, %%REGa, 4))
+ MOVNTQ(%%mm1, 8(%4, %%REGa, 4))
+
+ "add $4, %%"REG_a" \n\t"
+ "cmp %5, %%"REG_a" \n\t"
+ " jb 1b \n\t"
+
+
+ :: "r" (buf0), "r" (buf1), "r" (uvbuf0), "r" (uvbuf1), "r" (dest), "m" ((long)dstW),
+ "m" (yalpha1), "m" (uvalpha1)
+ : "%"REG_a
+ );
+ break;
+ case PIX_FMT_BGR24:
+ asm volatile(
+
+FULL_YSCALEYUV2RGB
+
+ // lsb ... msb
+ "punpcklbw %%mm1, %%mm3 \n\t" // BGBGBGBG
+ "punpcklbw %%mm7, %%mm0 \n\t" // R0R0R0R0
+
+ "movq %%mm3, %%mm1 \n\t"
+ "punpcklwd %%mm0, %%mm3 \n\t" // BGR0BGR0
+ "punpckhwd %%mm0, %%mm1 \n\t" // BGR0BGR0
+
+ "movq %%mm3, %%mm2 \n\t" // BGR0BGR0
+ "psrlq $8, %%mm3 \n\t" // GR0BGR00
+ "pand "MANGLE(bm00000111)", %%mm2\n\t" // BGR00000
+ "pand "MANGLE(bm11111000)", %%mm3\n\t" // 000BGR00
+ "por %%mm2, %%mm3 \n\t" // BGRBGR00
+ "movq %%mm1, %%mm2 \n\t"
+ "psllq $48, %%mm1 \n\t" // 000000BG
+ "por %%mm1, %%mm3 \n\t" // BGRBGRBG
+
+ "movq %%mm2, %%mm1 \n\t" // BGR0BGR0
+ "psrld $16, %%mm2 \n\t" // R000R000
+ "psrlq $24, %%mm1 \n\t" // 0BGR0000
+ "por %%mm2, %%mm1 \n\t" // RBGRR000
+
+ "mov %4, %%"REG_b" \n\t"
+ "add %%"REG_a", %%"REG_b" \n\t"
+
+#ifdef HAVE_MMX2
+ //FIXME Alignment
+ "movntq %%mm3, (%%"REG_b", %%"REG_a", 2)\n\t"
+ "movntq %%mm1, 8(%%"REG_b", %%"REG_a", 2)\n\t"
+#else
+ "movd %%mm3, (%%"REG_b", %%"REG_a", 2) \n\t"
+ "psrlq $32, %%mm3 \n\t"
+ "movd %%mm3, 4(%%"REG_b", %%"REG_a", 2) \n\t"
+ "movd %%mm1, 8(%%"REG_b", %%"REG_a", 2) \n\t"
+#endif
+ "add $4, %%"REG_a" \n\t"
+ "cmp %5, %%"REG_a" \n\t"
+ " jb 1b \n\t"
+
+ :: "r" (buf0), "r" (buf1), "r" (uvbuf0), "r" (uvbuf1), "m" (dest), "m" (dstW),
+ "m" (yalpha1), "m" (uvalpha1)
+ : "%"REG_a, "%"REG_b
+ );
+ break;
+ case PIX_FMT_BGR555:
+ asm volatile(
+
+FULL_YSCALEYUV2RGB
+#ifdef DITHER1XBPP
+ "paddusb "MANGLE(g5Dither)", %%mm1\n\t"
+ "paddusb "MANGLE(r5Dither)", %%mm0\n\t"
+ "paddusb "MANGLE(b5Dither)", %%mm3\n\t"
+#endif
+ "punpcklbw %%mm7, %%mm1 \n\t" // 0G0G0G0G
+ "punpcklbw %%mm7, %%mm3 \n\t" // 0B0B0B0B
+ "punpcklbw %%mm7, %%mm0 \n\t" // 0R0R0R0R
+
+ "psrlw $3, %%mm3 \n\t"
+ "psllw $2, %%mm1 \n\t"
+ "psllw $7, %%mm0 \n\t"
+ "pand "MANGLE(g15Mask)", %%mm1 \n\t"
+ "pand "MANGLE(r15Mask)", %%mm0 \n\t"
+
+ "por %%mm3, %%mm1 \n\t"
+ "por %%mm1, %%mm0 \n\t"
+
+ MOVNTQ(%%mm0, (%4, %%REGa, 2))
+
+ "add $4, %%"REG_a" \n\t"
+ "cmp %5, %%"REG_a" \n\t"
+ " jb 1b \n\t"
+
+ :: "r" (buf0), "r" (buf1), "r" (uvbuf0), "r" (uvbuf1), "r" (dest), "m" (dstW),
+ "m" (yalpha1), "m" (uvalpha1)
+ : "%"REG_a
+ );
+ break;
+ case PIX_FMT_BGR565:
+ asm volatile(
+
+FULL_YSCALEYUV2RGB
+#ifdef DITHER1XBPP
+ "paddusb "MANGLE(g6Dither)", %%mm1\n\t"
+ "paddusb "MANGLE(r5Dither)", %%mm0\n\t"
+ "paddusb "MANGLE(b5Dither)", %%mm3\n\t"
+#endif
+ "punpcklbw %%mm7, %%mm1 \n\t" // 0G0G0G0G
+ "punpcklbw %%mm7, %%mm3 \n\t" // 0B0B0B0B
+ "punpcklbw %%mm7, %%mm0 \n\t" // 0R0R0R0R
+
+ "psrlw $3, %%mm3 \n\t"
+ "psllw $3, %%mm1 \n\t"
+ "psllw $8, %%mm0 \n\t"
+ "pand "MANGLE(g16Mask)", %%mm1 \n\t"
+ "pand "MANGLE(r16Mask)", %%mm0 \n\t"
+
+ "por %%mm3, %%mm1 \n\t"
+ "por %%mm1, %%mm0 \n\t"
+
+ MOVNTQ(%%mm0, (%4, %%REGa, 2))
+
+ "add $4, %%"REG_a" \n\t"
+ "cmp %5, %%"REG_a" \n\t"
+ " jb 1b \n\t"
+
+ :: "r" (buf0), "r" (buf1), "r" (uvbuf0), "r" (uvbuf1), "r" (dest), "m" (dstW),
+ "m" (yalpha1), "m" (uvalpha1)
+ : "%"REG_a
+ );
+ break;
+#endif
+ case PIX_FMT_BGR32:
+#ifndef HAVE_MMX
+ case PIX_FMT_RGB32:
+#endif
+ if(dstFormat==PIX_FMT_RGB32)
+ {
+ int i;
+#ifdef WORDS_BIGENDIAN
+ dest++;
+#endif
+ for(i=0;i<dstW;i++){
+ // vertical linear interpolation && yuv2rgb in a single step:
+ int Y=yuvtab_2568[((buf0[i]*yalpha1+buf1[i]*yalpha)>>19)];
+ int U=((uvbuf0[i]*uvalpha1+uvbuf1[i]*uvalpha)>>19);
+ int V=((uvbuf0[i+2048]*uvalpha1+uvbuf1[i+2048]*uvalpha)>>19);
+ dest[0]=clip_table[((Y + yuvtab_40cf[U]) >>13)];
+ dest[1]=clip_table[((Y + yuvtab_1a1e[V] + yuvtab_0c92[U]) >>13)];
+ dest[2]=clip_table[((Y + yuvtab_3343[V]) >>13)];
+ dest+= 4;
+ }
+ }
+ else if(dstFormat==PIX_FMT_BGR24)
+ {
+ int i;
+ for(i=0;i<dstW;i++){
+ // vertical linear interpolation && yuv2rgb in a single step:
+ int Y=yuvtab_2568[((buf0[i]*yalpha1+buf1[i]*yalpha)>>19)];
+ int U=((uvbuf0[i]*uvalpha1+uvbuf1[i]*uvalpha)>>19);
+ int V=((uvbuf0[i+2048]*uvalpha1+uvbuf1[i+2048]*uvalpha)>>19);
+ dest[0]=clip_table[((Y + yuvtab_40cf[U]) >>13)];
+ dest[1]=clip_table[((Y + yuvtab_1a1e[V] + yuvtab_0c92[U]) >>13)];
+ dest[2]=clip_table[((Y + yuvtab_3343[V]) >>13)];
+ dest+= 3;
+ }
+ }
+ else if(dstFormat==PIX_FMT_BGR565)
+ {
+ int i;
+ for(i=0;i<dstW;i++){
+ // vertical linear interpolation && yuv2rgb in a single step:
+ int Y=yuvtab_2568[((buf0[i]*yalpha1+buf1[i]*yalpha)>>19)];
+ int U=((uvbuf0[i]*uvalpha1+uvbuf1[i]*uvalpha)>>19);
+ int V=((uvbuf0[i+2048]*uvalpha1+uvbuf1[i+2048]*uvalpha)>>19);
+
+ ((uint16_t*)dest)[i] =
+ clip_table16b[(Y + yuvtab_40cf[U]) >>13] |
+ clip_table16g[(Y + yuvtab_1a1e[V] + yuvtab_0c92[U]) >>13] |
+ clip_table16r[(Y + yuvtab_3343[V]) >>13];
+ }
+ }
+ else if(dstFormat==PIX_FMT_BGR555)
+ {
+ int i;
+ for(i=0;i<dstW;i++){
+ // vertical linear interpolation && yuv2rgb in a single step:
+ int Y=yuvtab_2568[((buf0[i]*yalpha1+buf1[i]*yalpha)>>19)];
+ int U=((uvbuf0[i]*uvalpha1+uvbuf1[i]*uvalpha)>>19);
+ int V=((uvbuf0[i+2048]*uvalpha1+uvbuf1[i+2048]*uvalpha)>>19);
+
+ ((uint16_t*)dest)[i] =
+ clip_table15b[(Y + yuvtab_40cf[U]) >>13] |
+ clip_table15g[(Y + yuvtab_1a1e[V] + yuvtab_0c92[U]) >>13] |
+ clip_table15r[(Y + yuvtab_3343[V]) >>13];
+ }
+ }
+ }//FULL_UV_IPOL
+ else
+ {
+#endif // if 0
+#ifdef HAVE_MMX
+ switch(c->dstFormat)
+ {
+//Note 8280 == DSTW_OFFSET but the preprocessor can't handle that there :(
+ case PIX_FMT_RGB32:
+ asm volatile(
+ "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t"
+ "mov %4, %%"REG_b" \n\t"
+ "push %%"REG_BP" \n\t"
+ YSCALEYUV2RGB(%%REGBP, %5)
+ WRITEBGR32(%%REGb, 8280(%5), %%REGBP)
+ "pop %%"REG_BP" \n\t"
+ "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t"
+
+ :: "c" (buf0), "d" (buf1), "S" (uvbuf0), "D" (uvbuf1), "m" (dest),
+ "a" (&c->redDither)
+ );
+ return;
+ case PIX_FMT_BGR24:
+ asm volatile(
+ "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t"
+ "mov %4, %%"REG_b" \n\t"
+ "push %%"REG_BP" \n\t"
+ YSCALEYUV2RGB(%%REGBP, %5)
+ WRITEBGR24(%%REGb, 8280(%5), %%REGBP)
+ "pop %%"REG_BP" \n\t"
+ "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t"
+ :: "c" (buf0), "d" (buf1), "S" (uvbuf0), "D" (uvbuf1), "m" (dest),
+ "a" (&c->redDither)
+ );
+ return;
+ case PIX_FMT_BGR555:
+ asm volatile(
+ "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t"
+ "mov %4, %%"REG_b" \n\t"
+ "push %%"REG_BP" \n\t"
+ YSCALEYUV2RGB(%%REGBP, %5)
+ /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */
+#ifdef DITHER1XBPP
+ "paddusb "MANGLE(b5Dither)", %%mm2\n\t"
+ "paddusb "MANGLE(g5Dither)", %%mm4\n\t"
+ "paddusb "MANGLE(r5Dither)", %%mm5\n\t"
+#endif
+
+ WRITEBGR15(%%REGb, 8280(%5), %%REGBP)
+ "pop %%"REG_BP" \n\t"
+ "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t"
+
+ :: "c" (buf0), "d" (buf1), "S" (uvbuf0), "D" (uvbuf1), "m" (dest),
+ "a" (&c->redDither)
+ );
+ return;
+ case PIX_FMT_BGR565:
+ asm volatile(
+ "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t"
+ "mov %4, %%"REG_b" \n\t"
+ "push %%"REG_BP" \n\t"
+ YSCALEYUV2RGB(%%REGBP, %5)
+ /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */
+#ifdef DITHER1XBPP
+ "paddusb "MANGLE(b5Dither)", %%mm2\n\t"
+ "paddusb "MANGLE(g6Dither)", %%mm4\n\t"
+ "paddusb "MANGLE(r5Dither)", %%mm5\n\t"
+#endif
+
+ WRITEBGR16(%%REGb, 8280(%5), %%REGBP)
+ "pop %%"REG_BP" \n\t"
+ "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t"
+ :: "c" (buf0), "d" (buf1), "S" (uvbuf0), "D" (uvbuf1), "m" (dest),
+ "a" (&c->redDither)
+ );
+ return;
+ case PIX_FMT_YUYV422:
+ asm volatile(
+ "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t"
+ "mov %4, %%"REG_b" \n\t"
+ "push %%"REG_BP" \n\t"
+ YSCALEYUV2PACKED(%%REGBP, %5)
+ WRITEYUY2(%%REGb, 8280(%5), %%REGBP)
+ "pop %%"REG_BP" \n\t"
+ "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t"
+ :: "c" (buf0), "d" (buf1), "S" (uvbuf0), "D" (uvbuf1), "m" (dest),
+ "a" (&c->redDither)
+ );
+ return;
+ default: break;
+ }
+#endif //HAVE_MMX
+YSCALE_YUV_2_ANYRGB_C(YSCALE_YUV_2_RGB2_C, YSCALE_YUV_2_PACKED2_C)
+}
+
+/**
+ * YV12 to RGB without scaling or interpolating
+ */
+static inline void RENAME(yuv2packed1)(SwsContext *c, uint16_t *buf0, uint16_t *uvbuf0, uint16_t *uvbuf1,
+ uint8_t *dest, int dstW, int uvalpha, int dstFormat, int flags, int y)
+{
+ const int yalpha1=0;
+ int i;
+
+ uint16_t *buf1= buf0; //FIXME needed for the rgb1/bgr1
+ const int yalpha= 4096; //FIXME ...
+
+ if(flags&SWS_FULL_CHR_H_INT)
+ {
+ RENAME(yuv2packed2)(c, buf0, buf0, uvbuf0, uvbuf1, dest, dstW, 0, uvalpha, y);
+ return;
+ }
+
+#ifdef HAVE_MMX
+ if( uvalpha < 2048 ) // note this is not correct (shifts chrominance by 0.5 pixels) but its a bit faster
+ {
+ switch(dstFormat)
+ {
+ case PIX_FMT_RGB32:
+ asm volatile(
+ "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t"
+ "mov %4, %%"REG_b" \n\t"
+ "push %%"REG_BP" \n\t"
+ YSCALEYUV2RGB1(%%REGBP, %5)
+ WRITEBGR32(%%REGb, 8280(%5), %%REGBP)
+ "pop %%"REG_BP" \n\t"
+ "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t"
+
+ :: "c" (buf0), "d" (buf1), "S" (uvbuf0), "D" (uvbuf1), "m" (dest),
+ "a" (&c->redDither)
+ );
+ return;
+ case PIX_FMT_BGR24:
+ asm volatile(
+ "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t"
+ "mov %4, %%"REG_b" \n\t"
+ "push %%"REG_BP" \n\t"
+ YSCALEYUV2RGB1(%%REGBP, %5)
+ WRITEBGR24(%%REGb, 8280(%5), %%REGBP)
+ "pop %%"REG_BP" \n\t"
+ "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t"
+
+ :: "c" (buf0), "d" (buf1), "S" (uvbuf0), "D" (uvbuf1), "m" (dest),
+ "a" (&c->redDither)
+ );
+ return;
+ case PIX_FMT_BGR555:
+ asm volatile(
+ "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t"
+ "mov %4, %%"REG_b" \n\t"
+ "push %%"REG_BP" \n\t"
+ YSCALEYUV2RGB1(%%REGBP, %5)
+ /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */
+#ifdef DITHER1XBPP
+ "paddusb "MANGLE(b5Dither)", %%mm2\n\t"
+ "paddusb "MANGLE(g5Dither)", %%mm4\n\t"
+ "paddusb "MANGLE(r5Dither)", %%mm5\n\t"
+#endif
+ WRITEBGR15(%%REGb, 8280(%5), %%REGBP)
+ "pop %%"REG_BP" \n\t"
+ "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t"
+
+ :: "c" (buf0), "d" (buf1), "S" (uvbuf0), "D" (uvbuf1), "m" (dest),
+ "a" (&c->redDither)
+ );
+ return;
+ case PIX_FMT_BGR565:
+ asm volatile(
+ "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t"
+ "mov %4, %%"REG_b" \n\t"
+ "push %%"REG_BP" \n\t"
+ YSCALEYUV2RGB1(%%REGBP, %5)
+ /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */
+#ifdef DITHER1XBPP
+ "paddusb "MANGLE(b5Dither)", %%mm2\n\t"
+ "paddusb "MANGLE(g6Dither)", %%mm4\n\t"
+ "paddusb "MANGLE(r5Dither)", %%mm5\n\t"
+#endif
+
+ WRITEBGR16(%%REGb, 8280(%5), %%REGBP)
+ "pop %%"REG_BP" \n\t"
+ "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t"
+
+ :: "c" (buf0), "d" (buf1), "S" (uvbuf0), "D" (uvbuf1), "m" (dest),
+ "a" (&c->redDither)
+ );
+ return;
+ case PIX_FMT_YUYV422:
+ asm volatile(
+ "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t"
+ "mov %4, %%"REG_b" \n\t"
+ "push %%"REG_BP" \n\t"
+ YSCALEYUV2PACKED1(%%REGBP, %5)
+ WRITEYUY2(%%REGb, 8280(%5), %%REGBP)
+ "pop %%"REG_BP" \n\t"
+ "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t"
+
+ :: "c" (buf0), "d" (buf1), "S" (uvbuf0), "D" (uvbuf1), "m" (dest),
+ "a" (&c->redDither)
+ );
+ return;
+ }
+ }
+ else
+ {
+ switch(dstFormat)
+ {
+ case PIX_FMT_RGB32:
+ asm volatile(
+ "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t"
+ "mov %4, %%"REG_b" \n\t"
+ "push %%"REG_BP" \n\t"
+ YSCALEYUV2RGB1b(%%REGBP, %5)
+ WRITEBGR32(%%REGb, 8280(%5), %%REGBP)
+ "pop %%"REG_BP" \n\t"
+ "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t"
+
+ :: "c" (buf0), "d" (buf1), "S" (uvbuf0), "D" (uvbuf1), "m" (dest),
+ "a" (&c->redDither)
+ );
+ return;
+ case PIX_FMT_BGR24:
+ asm volatile(
+ "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t"
+ "mov %4, %%"REG_b" \n\t"
+ "push %%"REG_BP" \n\t"
+ YSCALEYUV2RGB1b(%%REGBP, %5)
+ WRITEBGR24(%%REGb, 8280(%5), %%REGBP)
+ "pop %%"REG_BP" \n\t"
+ "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t"
+
+ :: "c" (buf0), "d" (buf1), "S" (uvbuf0), "D" (uvbuf1), "m" (dest),
+ "a" (&c->redDither)
+ );
+ return;
+ case PIX_FMT_BGR555:
+ asm volatile(
+ "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t"
+ "mov %4, %%"REG_b" \n\t"
+ "push %%"REG_BP" \n\t"
+ YSCALEYUV2RGB1b(%%REGBP, %5)
+ /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */
+#ifdef DITHER1XBPP
+ "paddusb "MANGLE(b5Dither)", %%mm2\n\t"
+ "paddusb "MANGLE(g5Dither)", %%mm4\n\t"
+ "paddusb "MANGLE(r5Dither)", %%mm5\n\t"
+#endif
+ WRITEBGR15(%%REGb, 8280(%5), %%REGBP)
+ "pop %%"REG_BP" \n\t"
+ "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t"
+
+ :: "c" (buf0), "d" (buf1), "S" (uvbuf0), "D" (uvbuf1), "m" (dest),
+ "a" (&c->redDither)
+ );
+ return;
+ case PIX_FMT_BGR565:
+ asm volatile(
+ "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t"
+ "mov %4, %%"REG_b" \n\t"
+ "push %%"REG_BP" \n\t"
+ YSCALEYUV2RGB1b(%%REGBP, %5)
+ /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */
+#ifdef DITHER1XBPP
+ "paddusb "MANGLE(b5Dither)", %%mm2\n\t"
+ "paddusb "MANGLE(g6Dither)", %%mm4\n\t"
+ "paddusb "MANGLE(r5Dither)", %%mm5\n\t"
+#endif
+
+ WRITEBGR16(%%REGb, 8280(%5), %%REGBP)
+ "pop %%"REG_BP" \n\t"
+ "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t"
+
+ :: "c" (buf0), "d" (buf1), "S" (uvbuf0), "D" (uvbuf1), "m" (dest),
+ "a" (&c->redDither)
+ );
+ return;
+ case PIX_FMT_YUYV422:
+ asm volatile(
+ "mov %%"REG_b", "ESP_OFFSET"(%5) \n\t"
+ "mov %4, %%"REG_b" \n\t"
+ "push %%"REG_BP" \n\t"
+ YSCALEYUV2PACKED1b(%%REGBP, %5)
+ WRITEYUY2(%%REGb, 8280(%5), %%REGBP)
+ "pop %%"REG_BP" \n\t"
+ "mov "ESP_OFFSET"(%5), %%"REG_b" \n\t"
+
+ :: "c" (buf0), "d" (buf1), "S" (uvbuf0), "D" (uvbuf1), "m" (dest),
+ "a" (&c->redDither)
+ );
+ return;
+ }
+ }
+#endif
+ if( uvalpha < 2048 )
+ {
+ YSCALE_YUV_2_ANYRGB_C(YSCALE_YUV_2_RGB1_C, YSCALE_YUV_2_PACKED1_C)
+ }else{
+ YSCALE_YUV_2_ANYRGB_C(YSCALE_YUV_2_RGB1B_C, YSCALE_YUV_2_PACKED1B_C)
+ }
+}
+
+//FIXME yuy2* can read upto 7 samples to much
+
+static inline void RENAME(yuy2ToY)(uint8_t *dst, uint8_t *src, long width)
+{
+#ifdef HAVE_MMX
+ asm volatile(
+ "movq "MANGLE(bm01010101)", %%mm2\n\t"
+ "mov %0, %%"REG_a" \n\t"
+ "1: \n\t"
+ "movq (%1, %%"REG_a",2), %%mm0 \n\t"
+ "movq 8(%1, %%"REG_a",2), %%mm1 \n\t"
+ "pand %%mm2, %%mm0 \n\t"
+ "pand %%mm2, %%mm1 \n\t"
+ "packuswb %%mm1, %%mm0 \n\t"
+ "movq %%mm0, (%2, %%"REG_a") \n\t"
+ "add $8, %%"REG_a" \n\t"
+ " js 1b \n\t"
+ : : "g" (-width), "r" (src+width*2), "r" (dst+width)
+ : "%"REG_a
+ );
+#else
+ int i;
+ for(i=0; i<width; i++)
+ dst[i]= src[2*i];
+#endif
+}
+
+static inline void RENAME(yuy2ToUV)(uint8_t *dstU, uint8_t *dstV, uint8_t *src1, uint8_t *src2, long width)
+{
+ assert(src1 == src2);
+#ifdef HAVE_MMX
+ asm volatile(
+ "movq "MANGLE(bm01010101)", %%mm4\n\t"
+ "mov %0, %%"REG_a" \n\t"
+ "1: \n\t"
+ "movq (%1, %%"REG_a",4), %%mm0 \n\t"
+ "movq 8(%1, %%"REG_a",4), %%mm1 \n\t"
+ "psrlw $8, %%mm0 \n\t"
+ "psrlw $8, %%mm1 \n\t"
+ "packuswb %%mm1, %%mm0 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "psrlw $8, %%mm0 \n\t"
+ "pand %%mm4, %%mm1 \n\t"
+ "packuswb %%mm0, %%mm0 \n\t"
+ "packuswb %%mm1, %%mm1 \n\t"
+ "movd %%mm0, (%3, %%"REG_a") \n\t"
+ "movd %%mm1, (%2, %%"REG_a") \n\t"
+ "add $4, %%"REG_a" \n\t"
+ " js 1b \n\t"
+ : : "g" (-width), "r" (src1+width*4), "r" (dstU+width), "r" (dstV+width)
+ : "%"REG_a
+ );
+#else
+ int i;
+ for(i=0; i<width; i++)
+ {
+ dstU[i]= src1[4*i + 1];
+ dstV[i]= src1[4*i + 3];
+ }
+#endif
+}
+
+//this is allmost identical to the previous, end exists only cuz yuy2ToY/UV)(dst, src+1, ...) would have 100% unaligned accesses
+static inline void RENAME(uyvyToY)(uint8_t *dst, uint8_t *src, long width)
+{
+#ifdef HAVE_MMX
+ asm volatile(
+ "mov %0, %%"REG_a" \n\t"
+ "1: \n\t"
+ "movq (%1, %%"REG_a",2), %%mm0 \n\t"
+ "movq 8(%1, %%"REG_a",2), %%mm1 \n\t"
+ "psrlw $8, %%mm0 \n\t"
+ "psrlw $8, %%mm1 \n\t"
+ "packuswb %%mm1, %%mm0 \n\t"
+ "movq %%mm0, (%2, %%"REG_a") \n\t"
+ "add $8, %%"REG_a" \n\t"
+ " js 1b \n\t"
+ : : "g" (-width), "r" (src+width*2), "r" (dst+width)
+ : "%"REG_a
+ );
+#else
+ int i;
+ for(i=0; i<width; i++)
+ dst[i]= src[2*i+1];
+#endif
+}
+
+static inline void RENAME(uyvyToUV)(uint8_t *dstU, uint8_t *dstV, uint8_t *src1, uint8_t *src2, long width)
+{
+ assert(src1 == src2);
+#ifdef HAVE_MMX
+ asm volatile(
+ "movq "MANGLE(bm01010101)", %%mm4\n\t"
+ "mov %0, %%"REG_a" \n\t"
+ "1: \n\t"
+ "movq (%1, %%"REG_a",4), %%mm0 \n\t"
+ "movq 8(%1, %%"REG_a",4), %%mm1 \n\t"
+ "pand %%mm4, %%mm0 \n\t"
+ "pand %%mm4, %%mm1 \n\t"
+ "packuswb %%mm1, %%mm0 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "psrlw $8, %%mm0 \n\t"
+ "pand %%mm4, %%mm1 \n\t"
+ "packuswb %%mm0, %%mm0 \n\t"
+ "packuswb %%mm1, %%mm1 \n\t"
+ "movd %%mm0, (%3, %%"REG_a") \n\t"
+ "movd %%mm1, (%2, %%"REG_a") \n\t"
+ "add $4, %%"REG_a" \n\t"
+ " js 1b \n\t"
+ : : "g" (-width), "r" (src1+width*4), "r" (dstU+width), "r" (dstV+width)
+ : "%"REG_a
+ );
+#else
+ int i;
+ for(i=0; i<width; i++)
+ {
+ dstU[i]= src1[4*i + 0];
+ dstV[i]= src1[4*i + 2];
+ }
+#endif
+}
+
+static inline void RENAME(bgr32ToY)(uint8_t *dst, uint8_t *src, int width)
+{
+ int i;
+ for(i=0; i<width; i++)
+ {
+ int b= ((uint32_t*)src)[i]&0xFF;
+ int g= (((uint32_t*)src)[i]>>8)&0xFF;
+ int r= (((uint32_t*)src)[i]>>16)&0xFF;
+
+ dst[i]= ((RY*r + GY*g + BY*b + (33<<(RGB2YUV_SHIFT-1)) )>>RGB2YUV_SHIFT);
+ }
+}
+
+static inline void RENAME(bgr32ToUV)(uint8_t *dstU, uint8_t *dstV, uint8_t *src1, uint8_t *src2, int width)
+{
+ int i;
+ assert(src1 == src2);
+ for(i=0; i<width; i++)
+ {
+ const int a= ((uint32_t*)src1)[2*i+0];
+ const int e= ((uint32_t*)src1)[2*i+1];
+ const int l= (a&0xFF00FF) + (e&0xFF00FF);
+ const int h= (a&0x00FF00) + (e&0x00FF00);
+ const int b= l&0x3FF;
+ const int g= h>>8;
+ const int r= l>>16;
+
+ dstU[i]= ((RU*r + GU*g + BU*b)>>(RGB2YUV_SHIFT+1)) + 128;
+ dstV[i]= ((RV*r + GV*g + BV*b)>>(RGB2YUV_SHIFT+1)) + 128;
+ }
+}
+
+static inline void RENAME(bgr24ToY)(uint8_t *dst, uint8_t *src, long width)
+{
+#ifdef HAVE_MMX
+ asm volatile(
+ "mov %2, %%"REG_a" \n\t"
+ "movq "MANGLE(bgr2YCoeff)", %%mm6 \n\t"
+ "movq "MANGLE(w1111)", %%mm5 \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+ "lea (%%"REG_a", %%"REG_a", 2), %%"REG_d"\n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ PREFETCH" 64(%0, %%"REG_d") \n\t"
+ "movd (%0, %%"REG_d"), %%mm0 \n\t"
+ "movd 3(%0, %%"REG_d"), %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "movd 6(%0, %%"REG_d"), %%mm2 \n\t"
+ "movd 9(%0, %%"REG_d"), %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm3 \n\t"
+ "pmaddwd %%mm6, %%mm0 \n\t"
+ "pmaddwd %%mm6, %%mm1 \n\t"
+ "pmaddwd %%mm6, %%mm2 \n\t"
+ "pmaddwd %%mm6, %%mm3 \n\t"
+#ifndef FAST_BGR2YV12
+ "psrad $8, %%mm0 \n\t"
+ "psrad $8, %%mm1 \n\t"
+ "psrad $8, %%mm2 \n\t"
+ "psrad $8, %%mm3 \n\t"
+#endif
+ "packssdw %%mm1, %%mm0 \n\t"
+ "packssdw %%mm3, %%mm2 \n\t"
+ "pmaddwd %%mm5, %%mm0 \n\t"
+ "pmaddwd %%mm5, %%mm2 \n\t"
+ "packssdw %%mm2, %%mm0 \n\t"
+ "psraw $7, %%mm0 \n\t"
+
+ "movd 12(%0, %%"REG_d"), %%mm4 \n\t"
+ "movd 15(%0, %%"REG_d"), %%mm1 \n\t"
+ "punpcklbw %%mm7, %%mm4 \n\t"
+ "punpcklbw %%mm7, %%mm1 \n\t"
+ "movd 18(%0, %%"REG_d"), %%mm2 \n\t"
+ "movd 21(%0, %%"REG_d"), %%mm3 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm3 \n\t"
+ "pmaddwd %%mm6, %%mm4 \n\t"
+ "pmaddwd %%mm6, %%mm1 \n\t"
+ "pmaddwd %%mm6, %%mm2 \n\t"
+ "pmaddwd %%mm6, %%mm3 \n\t"
+#ifndef FAST_BGR2YV12
+ "psrad $8, %%mm4 \n\t"
+ "psrad $8, %%mm1 \n\t"
+ "psrad $8, %%mm2 \n\t"
+ "psrad $8, %%mm3 \n\t"
+#endif
+ "packssdw %%mm1, %%mm4 \n\t"
+ "packssdw %%mm3, %%mm2 \n\t"
+ "pmaddwd %%mm5, %%mm4 \n\t"
+ "pmaddwd %%mm5, %%mm2 \n\t"
+ "add $24, %%"REG_d" \n\t"
+ "packssdw %%mm2, %%mm4 \n\t"
+ "psraw $7, %%mm4 \n\t"
+
+ "packuswb %%mm4, %%mm0 \n\t"
+ "paddusb "MANGLE(bgr2YOffset)", %%mm0 \n\t"
+
+ "movq %%mm0, (%1, %%"REG_a") \n\t"
+ "add $8, %%"REG_a" \n\t"
+ " js 1b \n\t"
+ : : "r" (src+width*3), "r" (dst+width), "g" (-width)
+ : "%"REG_a, "%"REG_d
+ );
+#else
+ int i;
+ for(i=0; i<width; i++)
+ {
+ int b= src[i*3+0];
+ int g= src[i*3+1];
+ int r= src[i*3+2];
+
+ dst[i]= ((RY*r + GY*g + BY*b + (33<<(RGB2YUV_SHIFT-1)) )>>RGB2YUV_SHIFT);
+ }
+#endif
+}
+
+static inline void RENAME(bgr24ToUV)(uint8_t *dstU, uint8_t *dstV, uint8_t *src1, uint8_t *src2, long width)
+{
+ assert(src1 == src2);
+#ifdef HAVE_MMX
+ asm volatile(
+ "mov %3, %%"REG_a" \n\t"
+ "movq "MANGLE(w1111)", %%mm5 \n\t"
+ "movq "MANGLE(bgr2UCoeff)", %%mm6 \n\t"
+ "pxor %%mm7, %%mm7 \n\t"
+ "lea (%%"REG_a", %%"REG_a", 2), %%"REG_d" \n\t"
+ "add %%"REG_d", %%"REG_d" \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ PREFETCH" 64(%0, %%"REG_d") \n\t"
+#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ "movq (%0, %%"REG_d"), %%mm0 \n\t"
+ "movq 6(%0, %%"REG_d"), %%mm2 \n\t"
+ "movq %%mm0, %%mm1 \n\t"
+ "movq %%mm2, %%mm3 \n\t"
+ "psrlq $24, %%mm0 \n\t"
+ "psrlq $24, %%mm2 \n\t"
+ PAVGB(%%mm1, %%mm0)
+ PAVGB(%%mm3, %%mm2)
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+#else
+ "movd (%0, %%"REG_d"), %%mm0 \n\t"
+ "movd 3(%0, %%"REG_d"), %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "paddw %%mm2, %%mm0 \n\t"
+ "movd 6(%0, %%"REG_d"), %%mm4 \n\t"
+ "movd 9(%0, %%"REG_d"), %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm4 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "paddw %%mm4, %%mm2 \n\t"
+ "psrlw $1, %%mm0 \n\t"
+ "psrlw $1, %%mm2 \n\t"
+#endif
+ "movq "MANGLE(bgr2VCoeff)", %%mm1 \n\t"
+ "movq "MANGLE(bgr2VCoeff)", %%mm3 \n\t"
+
+ "pmaddwd %%mm0, %%mm1 \n\t"
+ "pmaddwd %%mm2, %%mm3 \n\t"
+ "pmaddwd %%mm6, %%mm0 \n\t"
+ "pmaddwd %%mm6, %%mm2 \n\t"
+#ifndef FAST_BGR2YV12
+ "psrad $8, %%mm0 \n\t"
+ "psrad $8, %%mm1 \n\t"
+ "psrad $8, %%mm2 \n\t"
+ "psrad $8, %%mm3 \n\t"
+#endif
+ "packssdw %%mm2, %%mm0 \n\t"
+ "packssdw %%mm3, %%mm1 \n\t"
+ "pmaddwd %%mm5, %%mm0 \n\t"
+ "pmaddwd %%mm5, %%mm1 \n\t"
+ "packssdw %%mm1, %%mm0 \n\t" // V1 V0 U1 U0
+ "psraw $7, %%mm0 \n\t"
+
+#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
+ "movq 12(%0, %%"REG_d"), %%mm4 \n\t"
+ "movq 18(%0, %%"REG_d"), %%mm2 \n\t"
+ "movq %%mm4, %%mm1 \n\t"
+ "movq %%mm2, %%mm3 \n\t"
+ "psrlq $24, %%mm4 \n\t"
+ "psrlq $24, %%mm2 \n\t"
+ PAVGB(%%mm1, %%mm4)
+ PAVGB(%%mm3, %%mm2)
+ "punpcklbw %%mm7, %%mm4 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+#else
+ "movd 12(%0, %%"REG_d"), %%mm4 \n\t"
+ "movd 15(%0, %%"REG_d"), %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm4 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "paddw %%mm2, %%mm4 \n\t"
+ "movd 18(%0, %%"REG_d"), %%mm5 \n\t"
+ "movd 21(%0, %%"REG_d"), %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm5 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "paddw %%mm5, %%mm2 \n\t"
+ "movq "MANGLE(w1111)", %%mm5 \n\t"
+ "psrlw $2, %%mm4 \n\t"
+ "psrlw $2, %%mm2 \n\t"
+#endif
+ "movq "MANGLE(bgr2VCoeff)", %%mm1 \n\t"
+ "movq "MANGLE(bgr2VCoeff)", %%mm3 \n\t"
+
+ "pmaddwd %%mm4, %%mm1 \n\t"
+ "pmaddwd %%mm2, %%mm3 \n\t"
+ "pmaddwd %%mm6, %%mm4 \n\t"
+ "pmaddwd %%mm6, %%mm2 \n\t"
+#ifndef FAST_BGR2YV12
+ "psrad $8, %%mm4 \n\t"
+ "psrad $8, %%mm1 \n\t"
+ "psrad $8, %%mm2 \n\t"
+ "psrad $8, %%mm3 \n\t"
+#endif
+ "packssdw %%mm2, %%mm4 \n\t"
+ "packssdw %%mm3, %%mm1 \n\t"
+ "pmaddwd %%mm5, %%mm4 \n\t"
+ "pmaddwd %%mm5, %%mm1 \n\t"
+ "add $24, %%"REG_d" \n\t"
+ "packssdw %%mm1, %%mm4 \n\t" // V3 V2 U3 U2
+ "psraw $7, %%mm4 \n\t"
+
+ "movq %%mm0, %%mm1 \n\t"
+ "punpckldq %%mm4, %%mm0 \n\t"
+ "punpckhdq %%mm4, %%mm1 \n\t"
+ "packsswb %%mm1, %%mm0 \n\t"
+ "paddb "MANGLE(bgr2UVOffset)", %%mm0 \n\t"
+
+ "movd %%mm0, (%1, %%"REG_a") \n\t"
+ "punpckhdq %%mm0, %%mm0 \n\t"
+ "movd %%mm0, (%2, %%"REG_a") \n\t"
+ "add $4, %%"REG_a" \n\t"
+ " js 1b \n\t"
+ : : "r" (src1+width*6), "r" (dstU+width), "r" (dstV+width), "g" (-width)
+ : "%"REG_a, "%"REG_d
+ );
+#else
+ int i;
+ for(i=0; i<width; i++)
+ {
+ int b= src1[6*i + 0] + src1[6*i + 3];
+ int g= src1[6*i + 1] + src1[6*i + 4];
+ int r= src1[6*i + 2] + src1[6*i + 5];
+
+ dstU[i]= ((RU*r + GU*g + BU*b)>>(RGB2YUV_SHIFT+1)) + 128;
+ dstV[i]= ((RV*r + GV*g + BV*b)>>(RGB2YUV_SHIFT+1)) + 128;
+ }
+#endif
+}
+
+static inline void RENAME(bgr16ToY)(uint8_t *dst, uint8_t *src, int width)
+{
+ int i;
+ for(i=0; i<width; i++)
+ {
+ int d= ((uint16_t*)src)[i];
+ int b= d&0x1F;
+ int g= (d>>5)&0x3F;
+ int r= (d>>11)&0x1F;
+
+ dst[i]= ((2*RY*r + GY*g + 2*BY*b)>>(RGB2YUV_SHIFT-2)) + 16;
+ }
+}
+
+static inline void RENAME(bgr16ToUV)(uint8_t *dstU, uint8_t *dstV, uint8_t *src1, uint8_t *src2, int width)
+{
+ int i;
+ assert(src1==src2);
+ for(i=0; i<width; i++)
+ {
+ int d0= ((uint32_t*)src1)[i];
+
+ int dl= (d0&0x07E0F81F);
+ int dh= ((d0>>5)&0x07C0F83F);
+
+ int dh2= (dh>>11) + (dh<<21);
+ int d= dh2 + dl;
+
+ int b= d&0x7F;
+ int r= (d>>11)&0x7F;
+ int g= d>>21;
+ dstU[i]= ((2*RU*r + GU*g + 2*BU*b)>>(RGB2YUV_SHIFT+1-2)) + 128;
+ dstV[i]= ((2*RV*r + GV*g + 2*BV*b)>>(RGB2YUV_SHIFT+1-2)) + 128;
+ }
+}
+
+static inline void RENAME(bgr15ToY)(uint8_t *dst, uint8_t *src, int width)
+{
+ int i;
+ for(i=0; i<width; i++)
+ {
+ int d= ((uint16_t*)src)[i];
+ int b= d&0x1F;
+ int g= (d>>5)&0x1F;
+ int r= (d>>10)&0x1F;
+
+ dst[i]= ((RY*r + GY*g + BY*b)>>(RGB2YUV_SHIFT-3)) + 16;
+ }
+}
+
+static inline void RENAME(bgr15ToUV)(uint8_t *dstU, uint8_t *dstV, uint8_t *src1, uint8_t *src2, int width)
+{
+ int i;
+ assert(src1==src2);
+ for(i=0; i<width; i++)
+ {
+ int d0= ((uint32_t*)src1)[i];
+
+ int dl= (d0&0x03E07C1F);
+ int dh= ((d0>>5)&0x03E0F81F);
+
+ int dh2= (dh>>11) + (dh<<21);
+ int d= dh2 + dl;
+
+ int b= d&0x7F;
+ int r= (d>>10)&0x7F;
+ int g= d>>21;
+ dstU[i]= ((RU*r + GU*g + BU*b)>>(RGB2YUV_SHIFT+1-3)) + 128;
+ dstV[i]= ((RV*r + GV*g + BV*b)>>(RGB2YUV_SHIFT+1-3)) + 128;
+ }
+}
+
+
+static inline void RENAME(rgb32ToY)(uint8_t *dst, uint8_t *src, int width)
+{
+ int i;
+ for(i=0; i<width; i++)
+ {
+ int r= ((uint32_t*)src)[i]&0xFF;
+ int g= (((uint32_t*)src)[i]>>8)&0xFF;
+ int b= (((uint32_t*)src)[i]>>16)&0xFF;
+
+ dst[i]= ((RY*r + GY*g + BY*b + (33<<(RGB2YUV_SHIFT-1)) )>>RGB2YUV_SHIFT);
+ }
+}
+
+static inline void RENAME(rgb32ToUV)(uint8_t *dstU, uint8_t *dstV, uint8_t *src1, uint8_t *src2, int width)
+{
+ int i;
+ assert(src1==src2);
+ for(i=0; i<width; i++)
+ {
+ const int a= ((uint32_t*)src1)[2*i+0];
+ const int e= ((uint32_t*)src1)[2*i+1];
+ const int l= (a&0xFF00FF) + (e&0xFF00FF);
+ const int h= (a&0x00FF00) + (e&0x00FF00);
+ const int r= l&0x3FF;
+ const int g= h>>8;
+ const int b= l>>16;
+
+ dstU[i]= ((RU*r + GU*g + BU*b)>>(RGB2YUV_SHIFT+1)) + 128;
+ dstV[i]= ((RV*r + GV*g + BV*b)>>(RGB2YUV_SHIFT+1)) + 128;
+ }
+}
+
+static inline void RENAME(rgb24ToY)(uint8_t *dst, uint8_t *src, int width)
+{
+ int i;
+ for(i=0; i<width; i++)
+ {
+ int r= src[i*3+0];
+ int g= src[i*3+1];
+ int b= src[i*3+2];
+
+ dst[i]= ((RY*r + GY*g + BY*b + (33<<(RGB2YUV_SHIFT-1)) )>>RGB2YUV_SHIFT);
+ }
+}
+
+static inline void RENAME(rgb24ToUV)(uint8_t *dstU, uint8_t *dstV, uint8_t *src1, uint8_t *src2, int width)
+{
+ int i;
+ assert(src1==src2);
+ for(i=0; i<width; i++)
+ {
+ int r= src1[6*i + 0] + src1[6*i + 3];
+ int g= src1[6*i + 1] + src1[6*i + 4];
+ int b= src1[6*i + 2] + src1[6*i + 5];
+
+ dstU[i]= ((RU*r + GU*g + BU*b)>>(RGB2YUV_SHIFT+1)) + 128;
+ dstV[i]= ((RV*r + GV*g + BV*b)>>(RGB2YUV_SHIFT+1)) + 128;
+ }
+}
+
+static inline void RENAME(rgb16ToY)(uint8_t *dst, uint8_t *src, int width)
+{
+ int i;
+ for(i=0; i<width; i++)
+ {
+ int d= ((uint16_t*)src)[i];
+ int r= d&0x1F;
+ int g= (d>>5)&0x3F;
+ int b= (d>>11)&0x1F;
+
+ dst[i]= ((2*RY*r + GY*g + 2*BY*b)>>(RGB2YUV_SHIFT-2)) + 16;
+ }
+}
+
+static inline void RENAME(rgb16ToUV)(uint8_t *dstU, uint8_t *dstV, uint8_t *src1, uint8_t *src2, int width)
+{
+ int i;
+ assert(src1 == src2);
+ for(i=0; i<width; i++)
+ {
+ int d0= ((uint32_t*)src1)[i];
+
+ int dl= (d0&0x07E0F81F);
+ int dh= ((d0>>5)&0x07C0F83F);
+
+ int dh2= (dh>>11) + (dh<<21);
+ int d= dh2 + dl;
+
+ int r= d&0x7F;
+ int b= (d>>11)&0x7F;
+ int g= d>>21;
+ dstU[i]= ((2*RU*r + GU*g + 2*BU*b)>>(RGB2YUV_SHIFT+1-2)) + 128;
+ dstV[i]= ((2*RV*r + GV*g + 2*BV*b)>>(RGB2YUV_SHIFT+1-2)) + 128;
+ }
+}
+
+static inline void RENAME(rgb15ToY)(uint8_t *dst, uint8_t *src, int width)
+{
+ int i;
+ for(i=0; i<width; i++)
+ {
+ int d= ((uint16_t*)src)[i];
+ int r= d&0x1F;
+ int g= (d>>5)&0x1F;
+ int b= (d>>10)&0x1F;
+
+ dst[i]= ((RY*r + GY*g + BY*b)>>(RGB2YUV_SHIFT-3)) + 16;
+ }
+}
+
+static inline void RENAME(rgb15ToUV)(uint8_t *dstU, uint8_t *dstV, uint8_t *src1, uint8_t *src2, int width)
+{
+ int i;
+ assert(src1 == src2);
+ for(i=0; i<width; i++)
+ {
+ int d0= ((uint32_t*)src1)[i];
+
+ int dl= (d0&0x03E07C1F);
+ int dh= ((d0>>5)&0x03E0F81F);
+
+ int dh2= (dh>>11) + (dh<<21);
+ int d= dh2 + dl;
+
+ int g= d&0x7F;
+ int r= (d>>10)&0x7F;
+ int b= d>>21;
+ dstU[i]= ((RU*r + GU*g + BU*b)>>(RGB2YUV_SHIFT+1-3)) + 128;
+ dstV[i]= ((RV*r + GV*g + BV*b)>>(RGB2YUV_SHIFT+1-3)) + 128;
+ }
+}
+
+// Bilinear / Bicubic scaling
+static inline void RENAME(hScale)(int16_t *dst, int dstW, uint8_t *src, int srcW, int xInc,
+ int16_t *filter, int16_t *filterPos, long filterSize)
+{
+#ifdef HAVE_MMX
+ assert(filterSize % 4 == 0 && filterSize>0);
+ if(filterSize==4) // allways true for upscaling, sometimes for down too
+ {
+ long counter= -2*dstW;
+ filter-= counter*2;
+ filterPos-= counter/2;
+ dst-= counter/2;
+ asm volatile(
+#if defined(PIC)
+ "push %%"REG_b" \n\t"
+#endif
+ "pxor %%mm7, %%mm7 \n\t"
+ "movq "MANGLE(w02)", %%mm6 \n\t"
+ "push %%"REG_BP" \n\t" // we use 7 regs here ...
+ "mov %%"REG_a", %%"REG_BP" \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ "movzwl (%2, %%"REG_BP"), %%eax \n\t"
+ "movzwl 2(%2, %%"REG_BP"), %%ebx\n\t"
+ "movq (%1, %%"REG_BP", 4), %%mm1\n\t"
+ "movq 8(%1, %%"REG_BP", 4), %%mm3\n\t"
+ "movd (%3, %%"REG_a"), %%mm0 \n\t"
+ "movd (%3, %%"REG_b"), %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "pmaddwd %%mm1, %%mm0 \n\t"
+ "pmaddwd %%mm2, %%mm3 \n\t"
+ "psrad $8, %%mm0 \n\t"
+ "psrad $8, %%mm3 \n\t"
+ "packssdw %%mm3, %%mm0 \n\t"
+ "pmaddwd %%mm6, %%mm0 \n\t"
+ "packssdw %%mm0, %%mm0 \n\t"
+ "movd %%mm0, (%4, %%"REG_BP") \n\t"
+ "add $4, %%"REG_BP" \n\t"
+ " jnc 1b \n\t"
+
+ "pop %%"REG_BP" \n\t"
+#if defined(PIC)
+ "pop %%"REG_b" \n\t"
+#endif
+ : "+a" (counter)
+ : "c" (filter), "d" (filterPos), "S" (src), "D" (dst)
+#if !defined(PIC)
+ : "%"REG_b
+#endif
+ );
+ }
+ else if(filterSize==8)
+ {
+ long counter= -2*dstW;
+ filter-= counter*4;
+ filterPos-= counter/2;
+ dst-= counter/2;
+ asm volatile(
+#if defined(PIC)
+ "push %%"REG_b" \n\t"
+#endif
+ "pxor %%mm7, %%mm7 \n\t"
+ "movq "MANGLE(w02)", %%mm6 \n\t"
+ "push %%"REG_BP" \n\t" // we use 7 regs here ...
+ "mov %%"REG_a", %%"REG_BP" \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ "movzwl (%2, %%"REG_BP"), %%eax \n\t"
+ "movzwl 2(%2, %%"REG_BP"), %%ebx\n\t"
+ "movq (%1, %%"REG_BP", 8), %%mm1\n\t"
+ "movq 16(%1, %%"REG_BP", 8), %%mm3\n\t"
+ "movd (%3, %%"REG_a"), %%mm0 \n\t"
+ "movd (%3, %%"REG_b"), %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "pmaddwd %%mm1, %%mm0 \n\t"
+ "pmaddwd %%mm2, %%mm3 \n\t"
+
+ "movq 8(%1, %%"REG_BP", 8), %%mm1\n\t"
+ "movq 24(%1, %%"REG_BP", 8), %%mm5\n\t"
+ "movd 4(%3, %%"REG_a"), %%mm4 \n\t"
+ "movd 4(%3, %%"REG_b"), %%mm2 \n\t"
+ "punpcklbw %%mm7, %%mm4 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "pmaddwd %%mm1, %%mm4 \n\t"
+ "pmaddwd %%mm2, %%mm5 \n\t"
+ "paddd %%mm4, %%mm0 \n\t"
+ "paddd %%mm5, %%mm3 \n\t"
+
+ "psrad $8, %%mm0 \n\t"
+ "psrad $8, %%mm3 \n\t"
+ "packssdw %%mm3, %%mm0 \n\t"
+ "pmaddwd %%mm6, %%mm0 \n\t"
+ "packssdw %%mm0, %%mm0 \n\t"
+ "movd %%mm0, (%4, %%"REG_BP") \n\t"
+ "add $4, %%"REG_BP" \n\t"
+ " jnc 1b \n\t"
+
+ "pop %%"REG_BP" \n\t"
+#if defined(PIC)
+ "pop %%"REG_b" \n\t"
+#endif
+ : "+a" (counter)
+ : "c" (filter), "d" (filterPos), "S" (src), "D" (dst)
+#if !defined(PIC)
+ : "%"REG_b
+#endif
+ );
+ }
+ else
+ {
+ uint8_t *offset = src+filterSize;
+ long counter= -2*dstW;
+// filter-= counter*filterSize/2;
+ filterPos-= counter/2;
+ dst-= counter/2;
+ asm volatile(
+ "pxor %%mm7, %%mm7 \n\t"
+ "movq "MANGLE(w02)", %%mm6 \n\t"
+ ASMALIGN(4)
+ "1: \n\t"
+ "mov %2, %%"REG_c" \n\t"
+ "movzwl (%%"REG_c", %0), %%eax \n\t"
+ "movzwl 2(%%"REG_c", %0), %%edx \n\t"
+ "mov %5, %%"REG_c" \n\t"
+ "pxor %%mm4, %%mm4 \n\t"
+ "pxor %%mm5, %%mm5 \n\t"
+ "2: \n\t"
+ "movq (%1), %%mm1 \n\t"
+ "movq (%1, %6), %%mm3 \n\t"
+ "movd (%%"REG_c", %%"REG_a"), %%mm0\n\t"
+ "movd (%%"REG_c", %%"REG_d"), %%mm2\n\t"
+ "punpcklbw %%mm7, %%mm0 \n\t"
+ "punpcklbw %%mm7, %%mm2 \n\t"
+ "pmaddwd %%mm1, %%mm0 \n\t"
+ "pmaddwd %%mm2, %%mm3 \n\t"
+ "paddd %%mm3, %%mm5 \n\t"
+ "paddd %%mm0, %%mm4 \n\t"
+ "add $8, %1 \n\t"
+ "add $4, %%"REG_c" \n\t"
+ "cmp %4, %%"REG_c" \n\t"
+ " jb 2b \n\t"
+ "add %6, %1 \n\t"
+ "psrad $8, %%mm4 \n\t"
+ "psrad $8, %%mm5 \n\t"
+ "packssdw %%mm5, %%mm4 \n\t"
+ "pmaddwd %%mm6, %%mm4 \n\t"
+ "packssdw %%mm4, %%mm4 \n\t"
+ "mov %3, %%"REG_a" \n\t"
+ "movd %%mm4, (%%"REG_a", %0) \n\t"
+ "add $4, %0 \n\t"
+ " jnc 1b \n\t"
+
+ : "+r" (counter), "+r" (filter)
+ : "m" (filterPos), "m" (dst), "m"(offset),
+ "m" (src), "r" (filterSize*2)
+ : "%"REG_a, "%"REG_c, "%"REG_d
+ );
+ }
+#else
+#ifdef HAVE_ALTIVEC
+ hScale_altivec_real(dst, dstW, src, srcW, xInc, filter, filterPos, filterSize);
+#else
+ int i;
+ for(i=0; i<dstW; i++)
+ {
+ int j;
+ int srcPos= filterPos[i];
+ int val=0;
+// printf("filterPos: %d\n", filterPos[i]);
+ for(j=0; j<filterSize; j++)
+ {
+// printf("filter: %d, src: %d\n", filter[i], src[srcPos + j]);
+ val += ((int)src[srcPos + j])*filter[filterSize*i + j];
+ }
+// filter += hFilterSize;
+ dst[i] = FFMIN(FFMAX(0, val>>7), (1<<15)-1); // the cubic equation does overflow ...
+// dst[i] = val>>7;
+ }
+#endif
+#endif
+}
+ // *** horizontal scale Y line to temp buffer
+static inline void RENAME(hyscale)(uint16_t *dst, long dstWidth, uint8_t *src, int srcW, int xInc,
+ int flags, int canMMX2BeUsed, int16_t *hLumFilter,
+ int16_t *hLumFilterPos, int hLumFilterSize, void *funnyYCode,
+ int srcFormat, uint8_t *formatConvBuffer, int16_t *mmx2Filter,
+ int32_t *mmx2FilterPos)
+{
+ if(srcFormat==PIX_FMT_YUYV422 || srcFormat==PIX_FMT_GRAY16BE)
+ {
+ RENAME(yuy2ToY)(formatConvBuffer, src, srcW);
+ src= formatConvBuffer;
+ }
+ else if(srcFormat==PIX_FMT_UYVY422 || srcFormat==PIX_FMT_GRAY16LE)
+ {
+ RENAME(uyvyToY)(formatConvBuffer, src, srcW);
+ src= formatConvBuffer;
+ }
+ else if(srcFormat==PIX_FMT_RGB32)
+ {
+ RENAME(bgr32ToY)(formatConvBuffer, src, srcW);
+ src= formatConvBuffer;
+ }
+ else if(srcFormat==PIX_FMT_BGR24)
+ {
+ RENAME(bgr24ToY)(formatConvBuffer, src, srcW);
+ src= formatConvBuffer;
+ }
+ else if(srcFormat==PIX_FMT_BGR565)
+ {
+ RENAME(bgr16ToY)(formatConvBuffer, src, srcW);
+ src= formatConvBuffer;
+ }
+ else if(srcFormat==PIX_FMT_BGR555)
+ {
+ RENAME(bgr15ToY)(formatConvBuffer, src, srcW);
+ src= formatConvBuffer;
+ }
+ else if(srcFormat==PIX_FMT_BGR32)
+ {
+ RENAME(rgb32ToY)(formatConvBuffer, src, srcW);
+ src= formatConvBuffer;
+ }
+ else if(srcFormat==PIX_FMT_RGB24)
+ {
+ RENAME(rgb24ToY)(formatConvBuffer, src, srcW);
+ src= formatConvBuffer;
+ }
+ else if(srcFormat==PIX_FMT_RGB565)
+ {
+ RENAME(rgb16ToY)(formatConvBuffer, src, srcW);
+ src= formatConvBuffer;
+ }
+ else if(srcFormat==PIX_FMT_RGB555)
+ {
+ RENAME(rgb15ToY)(formatConvBuffer, src, srcW);
+ src= formatConvBuffer;
+ }
+
+#ifdef HAVE_MMX
+ // use the new MMX scaler if the mmx2 can't be used (its faster than the x86asm one)
+ if(!(flags&SWS_FAST_BILINEAR) || (!canMMX2BeUsed))
+#else
+ if(!(flags&SWS_FAST_BILINEAR))
+#endif
+ {
+ RENAME(hScale)(dst, dstWidth, src, srcW, xInc, hLumFilter, hLumFilterPos, hLumFilterSize);
+ }
+ else // Fast Bilinear upscale / crap downscale
+ {
+#if defined(ARCH_X86)
+#ifdef HAVE_MMX2
+ int i;
+#if defined(PIC)
+ uint64_t ebxsave __attribute__((aligned(8)));
+#endif
+ if(canMMX2BeUsed)
+ {
+ asm volatile(
+#if defined(PIC)
+ "mov %%"REG_b", %5 \n\t"
+#endif
+ "pxor %%mm7, %%mm7 \n\t"
+ "mov %0, %%"REG_c" \n\t"
+ "mov %1, %%"REG_D" \n\t"
+ "mov %2, %%"REG_d" \n\t"
+ "mov %3, %%"REG_b" \n\t"
+ "xor %%"REG_a", %%"REG_a" \n\t" // i
+ PREFETCH" (%%"REG_c") \n\t"
+ PREFETCH" 32(%%"REG_c") \n\t"
+ PREFETCH" 64(%%"REG_c") \n\t"
+
+#ifdef ARCH_X86_64
+
+#define FUNNY_Y_CODE \
+ "movl (%%"REG_b"), %%esi \n\t"\
+ "call *%4 \n\t"\
+ "movl (%%"REG_b", %%"REG_a"), %%esi\n\t"\
+ "add %%"REG_S", %%"REG_c" \n\t"\
+ "add %%"REG_a", %%"REG_D" \n\t"\
+ "xor %%"REG_a", %%"REG_a" \n\t"\
+
+#else
+
+#define FUNNY_Y_CODE \
+ "movl (%%"REG_b"), %%esi \n\t"\
+ "call *%4 \n\t"\
+ "addl (%%"REG_b", %%"REG_a"), %%"REG_c"\n\t"\
+ "add %%"REG_a", %%"REG_D" \n\t"\
+ "xor %%"REG_a", %%"REG_a" \n\t"\
+
+#endif
+
+FUNNY_Y_CODE
+FUNNY_Y_CODE
+FUNNY_Y_CODE
+FUNNY_Y_CODE
+FUNNY_Y_CODE
+FUNNY_Y_CODE
+FUNNY_Y_CODE
+FUNNY_Y_CODE
+
+#if defined(PIC)
+ "mov %5, %%"REG_b" \n\t"
+#endif
+ :: "m" (src), "m" (dst), "m" (mmx2Filter), "m" (mmx2FilterPos),
+ "m" (funnyYCode)
+#if defined(PIC)
+ ,"m" (ebxsave)
+#endif
+ : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S, "%"REG_D
+#if !defined(PIC)
+ ,"%"REG_b
+#endif
+ );
+ for(i=dstWidth-1; (i*xInc)>>16 >=srcW-1; i--) dst[i] = src[srcW-1]*128;
+ }
+ else
+ {
+#endif
+ long xInc_shr16 = xInc >> 16;
+ uint16_t xInc_mask = xInc & 0xffff;
+ //NO MMX just normal asm ...
+ asm volatile(
+ "xor %%"REG_a", %%"REG_a" \n\t" // i
+ "xor %%"REG_d", %%"REG_d" \n\t" // xx
+ "xorl %%ecx, %%ecx \n\t" // 2*xalpha
+ ASMALIGN(4)
+ "1: \n\t"
+ "movzbl (%0, %%"REG_d"), %%edi \n\t" //src[xx]
+ "movzbl 1(%0, %%"REG_d"), %%esi \n\t" //src[xx+1]
+ "subl %%edi, %%esi \n\t" //src[xx+1] - src[xx]
+ "imull %%ecx, %%esi \n\t" //(src[xx+1] - src[xx])*2*xalpha
+ "shll $16, %%edi \n\t"
+ "addl %%edi, %%esi \n\t" //src[xx+1]*2*xalpha + src[xx]*(1-2*xalpha)
+ "mov %1, %%"REG_D" \n\t"
+ "shrl $9, %%esi \n\t"
+ "movw %%si, (%%"REG_D", %%"REG_a", 2)\n\t"
+ "addw %4, %%cx \n\t" //2*xalpha += xInc&0xFF
+ "adc %3, %%"REG_d" \n\t" //xx+= xInc>>8 + carry
+
+ "movzbl (%0, %%"REG_d"), %%edi \n\t" //src[xx]
+ "movzbl 1(%0, %%"REG_d"), %%esi \n\t" //src[xx+1]
+ "subl %%edi, %%esi \n\t" //src[xx+1] - src[xx]
+ "imull %%ecx, %%esi \n\t" //(src[xx+1] - src[xx])*2*xalpha
+ "shll $16, %%edi \n\t"
+ "addl %%edi, %%esi \n\t" //src[xx+1]*2*xalpha + src[xx]*(1-2*xalpha)
+ "mov %1, %%"REG_D" \n\t"
+ "shrl $9, %%esi \n\t"
+ "movw %%si, 2(%%"REG_D", %%"REG_a", 2)\n\t"
+ "addw %4, %%cx \n\t" //2*xalpha += xInc&0xFF
+ "adc %3, %%"REG_d" \n\t" //xx+= xInc>>8 + carry
+
+
+ "add $2, %%"REG_a" \n\t"
+ "cmp %2, %%"REG_a" \n\t"
+ " jb 1b \n\t"
+
+
+ :: "r" (src), "m" (dst), "m" (dstWidth), "m" (xInc_shr16), "m" (xInc_mask)
+ : "%"REG_a, "%"REG_d, "%ecx", "%"REG_D, "%esi"
+ );
+#ifdef HAVE_MMX2
+ } //if MMX2 can't be used
+#endif
+#else
+ int i;
+ unsigned int xpos=0;
+ for(i=0;i<dstWidth;i++)
+ {
+ register unsigned int xx=xpos>>16;
+ register unsigned int xalpha=(xpos&0xFFFF)>>9;
+ dst[i]= (src[xx]<<7) + (src[xx+1] - src[xx])*xalpha;
+ xpos+=xInc;
+ }
+#endif
+ }
+}
+
+inline static void RENAME(hcscale)(uint16_t *dst, long dstWidth, uint8_t *src1, uint8_t *src2,
+ int srcW, int xInc, int flags, int canMMX2BeUsed, int16_t *hChrFilter,
+ int16_t *hChrFilterPos, int hChrFilterSize, void *funnyUVCode,
+ int srcFormat, uint8_t *formatConvBuffer, int16_t *mmx2Filter,
+ int32_t *mmx2FilterPos)
+{
+ if(srcFormat==PIX_FMT_YUYV422)
+ {
+ RENAME(yuy2ToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);
+ src1= formatConvBuffer;
+ src2= formatConvBuffer+2048;
+ }
+ else if(srcFormat==PIX_FMT_UYVY422)
+ {
+ RENAME(uyvyToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);
+ src1= formatConvBuffer;
+ src2= formatConvBuffer+2048;
+ }
+ else if(srcFormat==PIX_FMT_RGB32)
+ {
+ RENAME(bgr32ToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);
+ src1= formatConvBuffer;
+ src2= formatConvBuffer+2048;
+ }
+ else if(srcFormat==PIX_FMT_BGR24)
+ {
+ RENAME(bgr24ToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);
+ src1= formatConvBuffer;
+ src2= formatConvBuffer+2048;
+ }
+ else if(srcFormat==PIX_FMT_BGR565)
+ {
+ RENAME(bgr16ToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);
+ src1= formatConvBuffer;
+ src2= formatConvBuffer+2048;
+ }
+ else if(srcFormat==PIX_FMT_BGR555)
+ {
+ RENAME(bgr15ToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);
+ src1= formatConvBuffer;
+ src2= formatConvBuffer+2048;
+ }
+ else if(srcFormat==PIX_FMT_BGR32)
+ {
+ RENAME(rgb32ToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);
+ src1= formatConvBuffer;
+ src2= formatConvBuffer+2048;
+ }
+ else if(srcFormat==PIX_FMT_RGB24)
+ {
+ RENAME(rgb24ToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);
+ src1= formatConvBuffer;
+ src2= formatConvBuffer+2048;
+ }
+ else if(srcFormat==PIX_FMT_RGB565)
+ {
+ RENAME(rgb16ToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);
+ src1= formatConvBuffer;
+ src2= formatConvBuffer+2048;
+ }
+ else if(srcFormat==PIX_FMT_RGB555)
+ {
+ RENAME(rgb15ToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);
+ src1= formatConvBuffer;
+ src2= formatConvBuffer+2048;
+ }
+ else if(isGray(srcFormat))
+ {
+ return;
+ }
+
+#ifdef HAVE_MMX
+ // use the new MMX scaler if the mmx2 can't be used (its faster than the x86asm one)
+ if(!(flags&SWS_FAST_BILINEAR) || (!canMMX2BeUsed))
+#else
+ if(!(flags&SWS_FAST_BILINEAR))
+#endif
+ {
+ RENAME(hScale)(dst , dstWidth, src1, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize);
+ RENAME(hScale)(dst+2048, dstWidth, src2, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize);
+ }
+ else // Fast Bilinear upscale / crap downscale
+ {
+#if defined(ARCH_X86)
+#ifdef HAVE_MMX2
+ int i;
+#if defined(PIC)
+ uint64_t ebxsave __attribute__((aligned(8)));
+#endif
+ if(canMMX2BeUsed)
+ {
+ asm volatile(
+#if defined(PIC)
+ "mov %%"REG_b", %6 \n\t"
+#endif
+ "pxor %%mm7, %%mm7 \n\t"
+ "mov %0, %%"REG_c" \n\t"
+ "mov %1, %%"REG_D" \n\t"
+ "mov %2, %%"REG_d" \n\t"
+ "mov %3, %%"REG_b" \n\t"
+ "xor %%"REG_a", %%"REG_a" \n\t" // i
+ PREFETCH" (%%"REG_c") \n\t"
+ PREFETCH" 32(%%"REG_c") \n\t"
+ PREFETCH" 64(%%"REG_c") \n\t"
+
+#ifdef ARCH_X86_64
+
+#define FUNNY_UV_CODE \
+ "movl (%%"REG_b"), %%esi \n\t"\
+ "call *%4 \n\t"\
+ "movl (%%"REG_b", %%"REG_a"), %%esi\n\t"\
+ "add %%"REG_S", %%"REG_c" \n\t"\
+ "add %%"REG_a", %%"REG_D" \n\t"\
+ "xor %%"REG_a", %%"REG_a" \n\t"\
+
+#else
+
+#define FUNNY_UV_CODE \
+ "movl (%%"REG_b"), %%esi \n\t"\
+ "call *%4 \n\t"\
+ "addl (%%"REG_b", %%"REG_a"), %%"REG_c"\n\t"\
+ "add %%"REG_a", %%"REG_D" \n\t"\
+ "xor %%"REG_a", %%"REG_a" \n\t"\
+
+#endif
+
+FUNNY_UV_CODE
+FUNNY_UV_CODE
+FUNNY_UV_CODE
+FUNNY_UV_CODE
+ "xor %%"REG_a", %%"REG_a" \n\t" // i
+ "mov %5, %%"REG_c" \n\t" // src
+ "mov %1, %%"REG_D" \n\t" // buf1
+ "add $4096, %%"REG_D" \n\t"
+ PREFETCH" (%%"REG_c") \n\t"
+ PREFETCH" 32(%%"REG_c") \n\t"
+ PREFETCH" 64(%%"REG_c") \n\t"
+
+FUNNY_UV_CODE
+FUNNY_UV_CODE
+FUNNY_UV_CODE
+FUNNY_UV_CODE
+
+#if defined(PIC)
+ "mov %6, %%"REG_b" \n\t"
+#endif
+ :: "m" (src1), "m" (dst), "m" (mmx2Filter), "m" (mmx2FilterPos),
+ "m" (funnyUVCode), "m" (src2)
+#if defined(PIC)
+ ,"m" (ebxsave)
+#endif
+ : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S, "%"REG_D
+#if !defined(PIC)
+ ,"%"REG_b
+#endif
+ );
+ for(i=dstWidth-1; (i*xInc)>>16 >=srcW-1; i--)
+ {
+// printf("%d %d %d\n", dstWidth, i, srcW);
+ dst[i] = src1[srcW-1]*128;
+ dst[i+2048] = src2[srcW-1]*128;
+ }
+ }
+ else
+ {
+#endif
+ long xInc_shr16 = (long) (xInc >> 16);
+ uint16_t xInc_mask = xInc & 0xffff;
+ asm volatile(
+ "xor %%"REG_a", %%"REG_a" \n\t" // i
+ "xor %%"REG_d", %%"REG_d" \n\t" // xx
+ "xorl %%ecx, %%ecx \n\t" // 2*xalpha
+ ASMALIGN(4)
+ "1: \n\t"
+ "mov %0, %%"REG_S" \n\t"
+ "movzbl (%%"REG_S", %%"REG_d"), %%edi \n\t" //src[xx]
+ "movzbl 1(%%"REG_S", %%"REG_d"), %%esi \n\t" //src[xx+1]
+ "subl %%edi, %%esi \n\t" //src[xx+1] - src[xx]
+ "imull %%ecx, %%esi \n\t" //(src[xx+1] - src[xx])*2*xalpha
+ "shll $16, %%edi \n\t"
+ "addl %%edi, %%esi \n\t" //src[xx+1]*2*xalpha + src[xx]*(1-2*xalpha)
+ "mov %1, %%"REG_D" \n\t"
+ "shrl $9, %%esi \n\t"
+ "movw %%si, (%%"REG_D", %%"REG_a", 2)\n\t"
+
+ "movzbl (%5, %%"REG_d"), %%edi \n\t" //src[xx]
+ "movzbl 1(%5, %%"REG_d"), %%esi \n\t" //src[xx+1]
+ "subl %%edi, %%esi \n\t" //src[xx+1] - src[xx]
+ "imull %%ecx, %%esi \n\t" //(src[xx+1] - src[xx])*2*xalpha
+ "shll $16, %%edi \n\t"
+ "addl %%edi, %%esi \n\t" //src[xx+1]*2*xalpha + src[xx]*(1-2*xalpha)
+ "mov %1, %%"REG_D" \n\t"
+ "shrl $9, %%esi \n\t"
+ "movw %%si, 4096(%%"REG_D", %%"REG_a", 2)\n\t"
+
+ "addw %4, %%cx \n\t" //2*xalpha += xInc&0xFF
+ "adc %3, %%"REG_d" \n\t" //xx+= xInc>>8 + carry
+ "add $1, %%"REG_a" \n\t"
+ "cmp %2, %%"REG_a" \n\t"
+ " jb 1b \n\t"
+
+/* GCC-3.3 makes MPlayer crash on IA-32 machines when using "g" operand here,
+ which is needed to support GCC-4.0 */
+#if defined(ARCH_X86_64) && ((__GNUC__ > 3) || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+ :: "m" (src1), "m" (dst), "g" ((long)dstWidth), "m" (xInc_shr16), "m" (xInc_mask),
+#else
+ :: "m" (src1), "m" (dst), "m" ((long)dstWidth), "m" (xInc_shr16), "m" (xInc_mask),
+#endif
+ "r" (src2)
+ : "%"REG_a, "%"REG_d, "%ecx", "%"REG_D, "%esi"
+ );
+#ifdef HAVE_MMX2
+ } //if MMX2 can't be used
+#endif
+#else
+ int i;
+ unsigned int xpos=0;
+ for(i=0;i<dstWidth;i++)
+ {
+ register unsigned int xx=xpos>>16;
+ register unsigned int xalpha=(xpos&0xFFFF)>>9;
+ dst[i]=(src1[xx]*(xalpha^127)+src1[xx+1]*xalpha);
+ dst[i+2048]=(src2[xx]*(xalpha^127)+src2[xx+1]*xalpha);
+/* slower
+ dst[i]= (src1[xx]<<7) + (src1[xx+1] - src1[xx])*xalpha;
+ dst[i+2048]=(src2[xx]<<7) + (src2[xx+1] - src2[xx])*xalpha;
+*/
+ xpos+=xInc;
+ }
+#endif
+ }
+}
+
+static int RENAME(swScale)(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+
+ /* load a few things into local vars to make the code more readable? and faster */
+ const int srcW= c->srcW;
+ const int dstW= c->dstW;
+ const int dstH= c->dstH;
+ const int chrDstW= c->chrDstW;
+ const int chrSrcW= c->chrSrcW;
+ const int lumXInc= c->lumXInc;
+ const int chrXInc= c->chrXInc;
+ const int dstFormat= c->dstFormat;
+ const int srcFormat= c->srcFormat;
+ const int flags= c->flags;
+ const int canMMX2BeUsed= c->canMMX2BeUsed;
+ int16_t *vLumFilterPos= c->vLumFilterPos;
+ int16_t *vChrFilterPos= c->vChrFilterPos;
+ int16_t *hLumFilterPos= c->hLumFilterPos;
+ int16_t *hChrFilterPos= c->hChrFilterPos;
+ int16_t *vLumFilter= c->vLumFilter;
+ int16_t *vChrFilter= c->vChrFilter;
+ int16_t *hLumFilter= c->hLumFilter;
+ int16_t *hChrFilter= c->hChrFilter;
+ int32_t *lumMmxFilter= c->lumMmxFilter;
+ int32_t *chrMmxFilter= c->chrMmxFilter;
+ const int vLumFilterSize= c->vLumFilterSize;
+ const int vChrFilterSize= c->vChrFilterSize;
+ const int hLumFilterSize= c->hLumFilterSize;
+ const int hChrFilterSize= c->hChrFilterSize;
+ int16_t **lumPixBuf= c->lumPixBuf;
+ int16_t **chrPixBuf= c->chrPixBuf;
+ const int vLumBufSize= c->vLumBufSize;
+ const int vChrBufSize= c->vChrBufSize;
+ uint8_t *funnyYCode= c->funnyYCode;
+ uint8_t *funnyUVCode= c->funnyUVCode;
+ uint8_t *formatConvBuffer= c->formatConvBuffer;
+ const int chrSrcSliceY= srcSliceY >> c->chrSrcVSubSample;
+ const int chrSrcSliceH= -((-srcSliceH) >> c->chrSrcVSubSample);
+ int lastDstY;
+
+ /* vars whch will change and which we need to storw back in the context */
+ int dstY= c->dstY;
+ int lumBufIndex= c->lumBufIndex;
+ int chrBufIndex= c->chrBufIndex;
+ int lastInLumBuf= c->lastInLumBuf;
+ int lastInChrBuf= c->lastInChrBuf;
+
+ if(isPacked(c->srcFormat)){
+ src[0]=
+ src[1]=
+ src[2]= src[0];
+ srcStride[0]=
+ srcStride[1]=
+ srcStride[2]= srcStride[0];
+ }
+ srcStride[1]<<= c->vChrDrop;
+ srcStride[2]<<= c->vChrDrop;
+
+// printf("swscale %X %X %X -> %X %X %X\n", (int)src[0], (int)src[1], (int)src[2],
+// (int)dst[0], (int)dst[1], (int)dst[2]);
+
+#if 0 //self test FIXME move to a vfilter or something
+{
+static volatile int i=0;
+i++;
+if(srcFormat==PIX_FMT_YUV420P && i==1 && srcSliceH>= c->srcH)
+ selfTest(src, srcStride, c->srcW, c->srcH);
+i--;
+}
+#endif
+
+//printf("sws Strides:%d %d %d -> %d %d %d\n", srcStride[0],srcStride[1],srcStride[2],
+//dstStride[0],dstStride[1],dstStride[2]);
+
+ if(dstStride[0]%8 !=0 || dstStride[1]%8 !=0 || dstStride[2]%8 !=0)
+ {
+ static int firstTime=1; //FIXME move this into the context perhaps
+ if(flags & SWS_PRINT_INFO && firstTime)
+ {
+ MSG_WARN("SwScaler: Warning: dstStride is not aligned!\n"
+ "SwScaler: ->cannot do aligned memory acesses anymore\n");
+ firstTime=0;
+ }
+ }
+
+ /* Note the user might start scaling the picture in the middle so this will not get executed
+ this is not really intended but works currently, so ppl might do it */
+ if(srcSliceY ==0){
+ lumBufIndex=0;
+ chrBufIndex=0;
+ dstY=0;
+ lastInLumBuf= -1;
+ lastInChrBuf= -1;
+ }
+
+ lastDstY= dstY;
+
+ for(;dstY < dstH; dstY++){
+ unsigned char *dest =dst[0]+dstStride[0]*dstY;
+ const int chrDstY= dstY>>c->chrDstVSubSample;
+ unsigned char *uDest=dst[1]+dstStride[1]*chrDstY;
+ unsigned char *vDest=dst[2]+dstStride[2]*chrDstY;
+
+ const int firstLumSrcY= vLumFilterPos[dstY]; //First line needed as input
+ const int firstChrSrcY= vChrFilterPos[chrDstY]; //First line needed as input
+ const int lastLumSrcY= firstLumSrcY + vLumFilterSize -1; // Last line needed as input
+ const int lastChrSrcY= firstChrSrcY + vChrFilterSize -1; // Last line needed as input
+
+//printf("dstY:%d dstH:%d firstLumSrcY:%d lastInLumBuf:%d vLumBufSize: %d vChrBufSize: %d slice: %d %d vLumFilterSize: %d firstChrSrcY: %d vChrFilterSize: %d c->chrSrcVSubSample: %d\n",
+// dstY, dstH, firstLumSrcY, lastInLumBuf, vLumBufSize, vChrBufSize, srcSliceY, srcSliceH, vLumFilterSize, firstChrSrcY, vChrFilterSize, c->chrSrcVSubSample);
+ //handle holes (FAST_BILINEAR & weird filters)
+ if(firstLumSrcY > lastInLumBuf) lastInLumBuf= firstLumSrcY-1;
+ if(firstChrSrcY > lastInChrBuf) lastInChrBuf= firstChrSrcY-1;
+//printf("%d %d %d\n", firstChrSrcY, lastInChrBuf, vChrBufSize);
+ ASSERT(firstLumSrcY >= lastInLumBuf - vLumBufSize + 1)
+ ASSERT(firstChrSrcY >= lastInChrBuf - vChrBufSize + 1)
+
+ // Do we have enough lines in this slice to output the dstY line
+ if(lastLumSrcY < srcSliceY + srcSliceH && lastChrSrcY < -((-srcSliceY - srcSliceH)>>c->chrSrcVSubSample))
+ {
+ //Do horizontal scaling
+ while(lastInLumBuf < lastLumSrcY)
+ {
+ uint8_t *s= src[0]+(lastInLumBuf + 1 - srcSliceY)*srcStride[0];
+ lumBufIndex++;
+// printf("%d %d %d %d\n", lumBufIndex, vLumBufSize, lastInLumBuf, lastLumSrcY);
+ ASSERT(lumBufIndex < 2*vLumBufSize)
+ ASSERT(lastInLumBuf + 1 - srcSliceY < srcSliceH)
+ ASSERT(lastInLumBuf + 1 - srcSliceY >= 0)
+// printf("%d %d\n", lumBufIndex, vLumBufSize);
+ RENAME(hyscale)(lumPixBuf[ lumBufIndex ], dstW, s, srcW, lumXInc,
+ flags, canMMX2BeUsed, hLumFilter, hLumFilterPos, hLumFilterSize,
+ funnyYCode, c->srcFormat, formatConvBuffer,
+ c->lumMmx2Filter, c->lumMmx2FilterPos);
+ lastInLumBuf++;
+ }
+ while(lastInChrBuf < lastChrSrcY)
+ {
+ uint8_t *src1= src[1]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[1];
+ uint8_t *src2= src[2]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[2];
+ chrBufIndex++;
+ ASSERT(chrBufIndex < 2*vChrBufSize)
+ ASSERT(lastInChrBuf + 1 - chrSrcSliceY < (chrSrcSliceH))
+ ASSERT(lastInChrBuf + 1 - chrSrcSliceY >= 0)
+ //FIXME replace parameters through context struct (some at least)
+
+ if(!(isGray(srcFormat) || isGray(dstFormat)))
+ RENAME(hcscale)(chrPixBuf[ chrBufIndex ], chrDstW, src1, src2, chrSrcW, chrXInc,
+ flags, canMMX2BeUsed, hChrFilter, hChrFilterPos, hChrFilterSize,
+ funnyUVCode, c->srcFormat, formatConvBuffer,
+ c->chrMmx2Filter, c->chrMmx2FilterPos);
+ lastInChrBuf++;
+ }
+ //wrap buf index around to stay inside the ring buffer
+ if(lumBufIndex >= vLumBufSize ) lumBufIndex-= vLumBufSize;
+ if(chrBufIndex >= vChrBufSize ) chrBufIndex-= vChrBufSize;
+ }
+ else // not enough lines left in this slice -> load the rest in the buffer
+ {
+/* printf("%d %d Last:%d %d LastInBuf:%d %d Index:%d %d Y:%d FSize: %d %d BSize: %d %d\n",
+ firstChrSrcY,firstLumSrcY,lastChrSrcY,lastLumSrcY,
+ lastInChrBuf,lastInLumBuf,chrBufIndex,lumBufIndex,dstY,vChrFilterSize,vLumFilterSize,
+ vChrBufSize, vLumBufSize);*/
+
+ //Do horizontal scaling
+ while(lastInLumBuf+1 < srcSliceY + srcSliceH)
+ {
+ uint8_t *s= src[0]+(lastInLumBuf + 1 - srcSliceY)*srcStride[0];
+ lumBufIndex++;
+ ASSERT(lumBufIndex < 2*vLumBufSize)
+ ASSERT(lastInLumBuf + 1 - srcSliceY < srcSliceH)
+ ASSERT(lastInLumBuf + 1 - srcSliceY >= 0)
+ RENAME(hyscale)(lumPixBuf[ lumBufIndex ], dstW, s, srcW, lumXInc,
+ flags, canMMX2BeUsed, hLumFilter, hLumFilterPos, hLumFilterSize,
+ funnyYCode, c->srcFormat, formatConvBuffer,
+ c->lumMmx2Filter, c->lumMmx2FilterPos);
+ lastInLumBuf++;
+ }
+ while(lastInChrBuf+1 < (chrSrcSliceY + chrSrcSliceH))
+ {
+ uint8_t *src1= src[1]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[1];
+ uint8_t *src2= src[2]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[2];
+ chrBufIndex++;
+ ASSERT(chrBufIndex < 2*vChrBufSize)
+ ASSERT(lastInChrBuf + 1 - chrSrcSliceY < chrSrcSliceH)
+ ASSERT(lastInChrBuf + 1 - chrSrcSliceY >= 0)
+
+ if(!(isGray(srcFormat) || isGray(dstFormat)))
+ RENAME(hcscale)(chrPixBuf[ chrBufIndex ], chrDstW, src1, src2, chrSrcW, chrXInc,
+ flags, canMMX2BeUsed, hChrFilter, hChrFilterPos, hChrFilterSize,
+ funnyUVCode, c->srcFormat, formatConvBuffer,
+ c->chrMmx2Filter, c->chrMmx2FilterPos);
+ lastInChrBuf++;
+ }
+ //wrap buf index around to stay inside the ring buffer
+ if(lumBufIndex >= vLumBufSize ) lumBufIndex-= vLumBufSize;
+ if(chrBufIndex >= vChrBufSize ) chrBufIndex-= vChrBufSize;
+ break; //we can't output a dstY line so let's try with the next slice
+ }
+
+#ifdef HAVE_MMX
+ b5Dither= dither8[dstY&1];
+ g6Dither= dither4[dstY&1];
+ g5Dither= dither8[dstY&1];
+ r5Dither= dither8[(dstY+1)&1];
+#endif
+ if(dstY < dstH-2)
+ {
+ int16_t **lumSrcPtr= lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;
+ int16_t **chrSrcPtr= chrPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
+#ifdef HAVE_MMX
+ int i;
+ if(flags & SWS_ACCURATE_RND){
+ for(i=0; i<vLumFilterSize; i+=2){
+ lumMmxFilter[2*i+0]= lumSrcPtr[i ];
+ lumMmxFilter[2*i+1]= lumSrcPtr[i+(vLumFilterSize>1)];
+ lumMmxFilter[2*i+2]=
+ lumMmxFilter[2*i+3]= vLumFilter[dstY*vLumFilterSize + i ]
+ + (vLumFilterSize>1 ? vLumFilter[dstY*vLumFilterSize + i + 1]<<16 : 0);
+ }
+ for(i=0; i<vChrFilterSize; i+=2){
+ chrMmxFilter[2*i+0]= chrSrcPtr[i ];
+ chrMmxFilter[2*i+1]= chrSrcPtr[i+(vChrFilterSize>1)];
+ chrMmxFilter[2*i+2]=
+ chrMmxFilter[2*i+3]= vChrFilter[chrDstY*vChrFilterSize + i ]
+ + (vChrFilterSize>1 ? vChrFilter[chrDstY*vChrFilterSize + i + 1]<<16 : 0);
+ }
+ }else{
+ for(i=0; i<vLumFilterSize; i++)
+ {
+ lumMmxFilter[4*i+0]= (int32_t)lumSrcPtr[i];
+ lumMmxFilter[4*i+2]=
+ lumMmxFilter[4*i+3]=
+ ((uint16_t)vLumFilter[dstY*vLumFilterSize + i])*0x10001;
+ }
+ for(i=0; i<vChrFilterSize; i++)
+ {
+ chrMmxFilter[4*i+0]= (int32_t)chrSrcPtr[i];
+ chrMmxFilter[4*i+2]=
+ chrMmxFilter[4*i+3]=
+ ((uint16_t)vChrFilter[chrDstY*vChrFilterSize + i])*0x10001;
+ }
+ }
+#endif
+ if(dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21){
+ const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
+ if(dstY&chrSkipMask) uDest= NULL; //FIXME split functions in lumi / chromi
+ RENAME(yuv2nv12X)(c,
+ vLumFilter+dstY*vLumFilterSize , lumSrcPtr, vLumFilterSize,
+ vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,
+ dest, uDest, dstW, chrDstW, dstFormat);
+ }
+ else if(isPlanarYUV(dstFormat) || isGray(dstFormat)) //YV12 like
+ {
+ const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
+ if((dstY&chrSkipMask) || isGray(dstFormat)) uDest=vDest= NULL; //FIXME split functions in lumi / chromi
+ if(vLumFilterSize == 1 && vChrFilterSize == 1) // Unscaled YV12
+ {
+ int16_t *lumBuf = lumPixBuf[0];
+ int16_t *chrBuf= chrPixBuf[0];
+ RENAME(yuv2yuv1)(lumBuf, chrBuf, dest, uDest, vDest, dstW, chrDstW);
+ }
+ else //General YV12
+ {
+ RENAME(yuv2yuvX)(c,
+ vLumFilter+dstY*vLumFilterSize , lumSrcPtr, vLumFilterSize,
+ vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,
+ dest, uDest, vDest, dstW, chrDstW);
+ }
+ }
+ else
+ {
+ ASSERT(lumSrcPtr + vLumFilterSize - 1 < lumPixBuf + vLumBufSize*2);
+ ASSERT(chrSrcPtr + vChrFilterSize - 1 < chrPixBuf + vChrBufSize*2);
+ if(vLumFilterSize == 1 && vChrFilterSize == 2) //Unscaled RGB
+ {
+ int chrAlpha= vChrFilter[2*dstY+1];
+ RENAME(yuv2packed1)(c, *lumSrcPtr, *chrSrcPtr, *(chrSrcPtr+1),
+ dest, dstW, chrAlpha, dstFormat, flags, dstY);
+ }
+ else if(vLumFilterSize == 2 && vChrFilterSize == 2) //BiLinear Upscale RGB
+ {
+ int lumAlpha= vLumFilter[2*dstY+1];
+ int chrAlpha= vChrFilter[2*dstY+1];
+ lumMmxFilter[2]=
+ lumMmxFilter[3]= vLumFilter[2*dstY ]*0x10001;
+ chrMmxFilter[2]=
+ chrMmxFilter[3]= vChrFilter[2*chrDstY]*0x10001;
+ RENAME(yuv2packed2)(c, *lumSrcPtr, *(lumSrcPtr+1), *chrSrcPtr, *(chrSrcPtr+1),
+ dest, dstW, lumAlpha, chrAlpha, dstY);
+ }
+ else //General RGB
+ {
+ RENAME(yuv2packedX)(c,
+ vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
+ vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,
+ dest, dstW, dstY);
+ }
+ }
+ }
+ else // hmm looks like we can't use MMX here without overwriting this array's tail
+ {
+ int16_t **lumSrcPtr= lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;
+ int16_t **chrSrcPtr= chrPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
+ if(dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21){
+ const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
+ if(dstY&chrSkipMask) uDest= NULL; //FIXME split functions in lumi / chromi
+ yuv2nv12XinC(
+ vLumFilter+dstY*vLumFilterSize , lumSrcPtr, vLumFilterSize,
+ vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,
+ dest, uDest, dstW, chrDstW, dstFormat);
+ }
+ else if(isPlanarYUV(dstFormat) || isGray(dstFormat)) //YV12
+ {
+ const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
+ if((dstY&chrSkipMask) || isGray(dstFormat)) uDest=vDest= NULL; //FIXME split functions in lumi / chromi
+ yuv2yuvXinC(
+ vLumFilter+dstY*vLumFilterSize , lumSrcPtr, vLumFilterSize,
+ vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,
+ dest, uDest, vDest, dstW, chrDstW);
+ }
+ else
+ {
+ ASSERT(lumSrcPtr + vLumFilterSize - 1 < lumPixBuf + vLumBufSize*2);
+ ASSERT(chrSrcPtr + vChrFilterSize - 1 < chrPixBuf + vChrBufSize*2);
+ yuv2packedXinC(c,
+ vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
+ vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,
+ dest, dstW, dstY);
+ }
+ }
+ }
+
+#ifdef HAVE_MMX
+ __asm __volatile(SFENCE:::"memory");
+ __asm __volatile(EMMS:::"memory");
+#endif
+ /* store changed local vars back in the context */
+ c->dstY= dstY;
+ c->lumBufIndex= lumBufIndex;
+ c->chrBufIndex= chrBufIndex;
+ c->lastInLumBuf= lastInLumBuf;
+ c->lastInChrBuf= lastInChrBuf;
+
+ return dstY - lastDstY;
+}
diff --git a/contrib/ffmpeg/libswscale/yuv2rgb.c b/contrib/ffmpeg/libswscale/yuv2rgb.c
new file mode 100644
index 000000000..9066b68b2
--- /dev/null
+++ b/contrib/ffmpeg/libswscale/yuv2rgb.c
@@ -0,0 +1,844 @@
+/*
+ * yuv2rgb.c, Software YUV to RGB coverter
+ *
+ * Copyright (C) 1999, Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ * All Rights Reserved.
+ *
+ * Functions broken out from display_x11.c and several new modes
+ * added by Håkan Hjort <d95hjort@dtek.chalmers.se>
+ *
+ * 15 & 16 bpp support by Franck Sicard <Franck.Sicard@solsoft.fr>
+ *
+ * This file is part of mpeg2dec, a free MPEG-2 video decoder
+ *
+ * mpeg2dec 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; either version 2, or (at your option)
+ * any later version.
+ *
+ * mpeg2dec is distributed in the hope that 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 GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * MMX/MMX2 Template stuff from Michael Niedermayer (michaelni@gmx.at) (needed for fast movntq support)
+ * 1,4,8bpp support by Michael Niedermayer (michaelni@gmx.at)
+ * context / deglobalize stuff by Michael Niedermayer
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "config.h"
+#include "rgb2rgb.h"
+#include "swscale.h"
+#include "swscale_internal.h"
+
+#ifdef HAVE_MLIB
+#include "yuv2rgb_mlib.c"
+#endif
+
+#define DITHER1XBPP // only for mmx
+
+const uint8_t __attribute__((aligned(8))) dither_2x2_4[2][8]={
+{ 1, 3, 1, 3, 1, 3, 1, 3, },
+{ 2, 0, 2, 0, 2, 0, 2, 0, },
+};
+
+const uint8_t __attribute__((aligned(8))) dither_2x2_8[2][8]={
+{ 6, 2, 6, 2, 6, 2, 6, 2, },
+{ 0, 4, 0, 4, 0, 4, 0, 4, },
+};
+
+const uint8_t __attribute__((aligned(8))) dither_8x8_32[8][8]={
+{ 17, 9, 23, 15, 16, 8, 22, 14, },
+{ 5, 29, 3, 27, 4, 28, 2, 26, },
+{ 21, 13, 19, 11, 20, 12, 18, 10, },
+{ 0, 24, 6, 30, 1, 25, 7, 31, },
+{ 16, 8, 22, 14, 17, 9, 23, 15, },
+{ 4, 28, 2, 26, 5, 29, 3, 27, },
+{ 20, 12, 18, 10, 21, 13, 19, 11, },
+{ 1, 25, 7, 31, 0, 24, 6, 30, },
+};
+
+#if 0
+const uint8_t __attribute__((aligned(8))) dither_8x8_64[8][8]={
+{ 0, 48, 12, 60, 3, 51, 15, 63, },
+{ 32, 16, 44, 28, 35, 19, 47, 31, },
+{ 8, 56, 4, 52, 11, 59, 7, 55, },
+{ 40, 24, 36, 20, 43, 27, 39, 23, },
+{ 2, 50, 14, 62, 1, 49, 13, 61, },
+{ 34, 18, 46, 30, 33, 17, 45, 29, },
+{ 10, 58, 6, 54, 9, 57, 5, 53, },
+{ 42, 26, 38, 22, 41, 25, 37, 21, },
+};
+#endif
+
+const uint8_t __attribute__((aligned(8))) dither_8x8_73[8][8]={
+{ 0, 55, 14, 68, 3, 58, 17, 72, },
+{ 37, 18, 50, 32, 40, 22, 54, 35, },
+{ 9, 64, 5, 59, 13, 67, 8, 63, },
+{ 46, 27, 41, 23, 49, 31, 44, 26, },
+{ 2, 57, 16, 71, 1, 56, 15, 70, },
+{ 39, 21, 52, 34, 38, 19, 51, 33, },
+{ 11, 66, 7, 62, 10, 65, 6, 60, },
+{ 48, 30, 43, 25, 47, 29, 42, 24, },
+};
+
+#if 0
+const uint8_t __attribute__((aligned(8))) dither_8x8_128[8][8]={
+{ 68, 36, 92, 60, 66, 34, 90, 58, },
+{ 20, 116, 12, 108, 18, 114, 10, 106, },
+{ 84, 52, 76, 44, 82, 50, 74, 42, },
+{ 0, 96, 24, 120, 6, 102, 30, 126, },
+{ 64, 32, 88, 56, 70, 38, 94, 62, },
+{ 16, 112, 8, 104, 22, 118, 14, 110, },
+{ 80, 48, 72, 40, 86, 54, 78, 46, },
+{ 4, 100, 28, 124, 2, 98, 26, 122, },
+};
+#endif
+
+#if 1
+const uint8_t __attribute__((aligned(8))) dither_8x8_220[8][8]={
+{117, 62, 158, 103, 113, 58, 155, 100, },
+{ 34, 199, 21, 186, 31, 196, 17, 182, },
+{144, 89, 131, 76, 141, 86, 127, 72, },
+{ 0, 165, 41, 206, 10, 175, 52, 217, },
+{110, 55, 151, 96, 120, 65, 162, 107, },
+{ 28, 193, 14, 179, 38, 203, 24, 189, },
+{138, 83, 124, 69, 148, 93, 134, 79, },
+{ 7, 172, 48, 213, 3, 168, 45, 210, },
+};
+#elif 1
+// tries to correct a gamma of 1.5
+const uint8_t __attribute__((aligned(8))) dither_8x8_220[8][8]={
+{ 0, 143, 18, 200, 2, 156, 25, 215, },
+{ 78, 28, 125, 64, 89, 36, 138, 74, },
+{ 10, 180, 3, 161, 16, 195, 8, 175, },
+{109, 51, 93, 38, 121, 60, 105, 47, },
+{ 1, 152, 23, 210, 0, 147, 20, 205, },
+{ 85, 33, 134, 71, 81, 30, 130, 67, },
+{ 14, 190, 6, 171, 12, 185, 5, 166, },
+{117, 57, 101, 44, 113, 54, 97, 41, },
+};
+#elif 1
+// tries to correct a gamma of 2.0
+const uint8_t __attribute__((aligned(8))) dither_8x8_220[8][8]={
+{ 0, 124, 8, 193, 0, 140, 12, 213, },
+{ 55, 14, 104, 42, 66, 19, 119, 52, },
+{ 3, 168, 1, 145, 6, 187, 3, 162, },
+{ 86, 31, 70, 21, 99, 39, 82, 28, },
+{ 0, 134, 11, 206, 0, 129, 9, 200, },
+{ 62, 17, 114, 48, 58, 16, 109, 45, },
+{ 5, 181, 2, 157, 4, 175, 1, 151, },
+{ 95, 36, 78, 26, 90, 34, 74, 24, },
+};
+#else
+// tries to correct a gamma of 2.5
+const uint8_t __attribute__((aligned(8))) dither_8x8_220[8][8]={
+{ 0, 107, 3, 187, 0, 125, 6, 212, },
+{ 39, 7, 86, 28, 49, 11, 102, 36, },
+{ 1, 158, 0, 131, 3, 180, 1, 151, },
+{ 68, 19, 52, 12, 81, 25, 64, 17, },
+{ 0, 119, 5, 203, 0, 113, 4, 195, },
+{ 45, 9, 96, 33, 42, 8, 91, 30, },
+{ 2, 172, 1, 144, 2, 165, 0, 137, },
+{ 77, 23, 60, 15, 72, 21, 56, 14, },
+};
+#endif
+
+#ifdef HAVE_MMX
+
+/* hope these constant values are cache line aligned */
+static uint64_t attribute_used __attribute__((aligned(8))) mmx_00ffw = 0x00ff00ff00ff00ffULL;
+static uint64_t attribute_used __attribute__((aligned(8))) mmx_redmask = 0xf8f8f8f8f8f8f8f8ULL;
+static uint64_t attribute_used __attribute__((aligned(8))) mmx_grnmask = 0xfcfcfcfcfcfcfcfcULL;
+
+static uint64_t attribute_used __attribute__((aligned(8))) M24A= 0x00FF0000FF0000FFULL;
+static uint64_t attribute_used __attribute__((aligned(8))) M24B= 0xFF0000FF0000FF00ULL;
+static uint64_t attribute_used __attribute__((aligned(8))) M24C= 0x0000FF0000FF0000ULL;
+
+// the volatile is required because gcc otherwise optimizes some writes away not knowing that these
+// are read in the asm block
+static volatile uint64_t attribute_used __attribute__((aligned(8))) b5Dither;
+static volatile uint64_t attribute_used __attribute__((aligned(8))) g5Dither;
+static volatile uint64_t attribute_used __attribute__((aligned(8))) g6Dither;
+static volatile uint64_t attribute_used __attribute__((aligned(8))) r5Dither;
+
+static uint64_t __attribute__((aligned(8))) dither4[2]={
+ 0x0103010301030103LL,
+ 0x0200020002000200LL,};
+
+static uint64_t __attribute__((aligned(8))) dither8[2]={
+ 0x0602060206020602LL,
+ 0x0004000400040004LL,};
+
+#undef HAVE_MMX
+
+//MMX versions
+#undef RENAME
+#define HAVE_MMX
+#undef HAVE_MMX2
+#undef HAVE_3DNOW
+#define RENAME(a) a ## _MMX
+#include "yuv2rgb_template.c"
+
+//MMX2 versions
+#undef RENAME
+#define HAVE_MMX
+#define HAVE_MMX2
+#undef HAVE_3DNOW
+#define RENAME(a) a ## _MMX2
+#include "yuv2rgb_template.c"
+
+#endif /* defined(ARCH_X86) */
+
+const int32_t Inverse_Table_6_9[8][4] = {
+ {117504, 138453, 13954, 34903}, /* no sequence_display_extension */
+ {117504, 138453, 13954, 34903}, /* ITU-R Rec. 709 (1990) */
+ {104597, 132201, 25675, 53279}, /* unspecified */
+ {104597, 132201, 25675, 53279}, /* reserved */
+ {104448, 132798, 24759, 53109}, /* FCC */
+ {104597, 132201, 25675, 53279}, /* ITU-R Rec. 624-4 System B, G */
+ {104597, 132201, 25675, 53279}, /* SMPTE 170M */
+ {117579, 136230, 16907, 35559} /* SMPTE 240M (1987) */
+};
+
+#define RGB(i) \
+ U = pu[i]; \
+ V = pv[i]; \
+ r = c->table_rV[V]; \
+ g = c->table_gU[U] + c->table_gV[V]; \
+ b = c->table_bU[U];
+
+#define DST1(i) \
+ Y = py_1[2*i]; \
+ dst_1[2*i] = r[Y] + g[Y] + b[Y]; \
+ Y = py_1[2*i+1]; \
+ dst_1[2*i+1] = r[Y] + g[Y] + b[Y];
+
+#define DST2(i) \
+ Y = py_2[2*i]; \
+ dst_2[2*i] = r[Y] + g[Y] + b[Y]; \
+ Y = py_2[2*i+1]; \
+ dst_2[2*i+1] = r[Y] + g[Y] + b[Y];
+
+#define DST1RGB(i) \
+ Y = py_1[2*i]; \
+ dst_1[6*i] = r[Y]; dst_1[6*i+1] = g[Y]; dst_1[6*i+2] = b[Y]; \
+ Y = py_1[2*i+1]; \
+ dst_1[6*i+3] = r[Y]; dst_1[6*i+4] = g[Y]; dst_1[6*i+5] = b[Y];
+
+#define DST2RGB(i) \
+ Y = py_2[2*i]; \
+ dst_2[6*i] = r[Y]; dst_2[6*i+1] = g[Y]; dst_2[6*i+2] = b[Y]; \
+ Y = py_2[2*i+1]; \
+ dst_2[6*i+3] = r[Y]; dst_2[6*i+4] = g[Y]; dst_2[6*i+5] = b[Y];
+
+#define DST1BGR(i) \
+ Y = py_1[2*i]; \
+ dst_1[6*i] = b[Y]; dst_1[6*i+1] = g[Y]; dst_1[6*i+2] = r[Y]; \
+ Y = py_1[2*i+1]; \
+ dst_1[6*i+3] = b[Y]; dst_1[6*i+4] = g[Y]; dst_1[6*i+5] = r[Y];
+
+#define DST2BGR(i) \
+ Y = py_2[2*i]; \
+ dst_2[6*i] = b[Y]; dst_2[6*i+1] = g[Y]; dst_2[6*i+2] = r[Y]; \
+ Y = py_2[2*i+1]; \
+ dst_2[6*i+3] = b[Y]; dst_2[6*i+4] = g[Y]; dst_2[6*i+5] = r[Y];
+
+#define PROLOG(func_name, dst_type) \
+static int func_name(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY, \
+ int srcSliceH, uint8_t* dst[], int dstStride[]){\
+ int y;\
+\
+ if(c->srcFormat == PIX_FMT_YUV422P){\
+ srcStride[1] *= 2;\
+ srcStride[2] *= 2;\
+ }\
+ for(y=0; y<srcSliceH; y+=2){\
+ dst_type *dst_1= (dst_type*)(dst[0] + (y+srcSliceY )*dstStride[0]);\
+ dst_type *dst_2= (dst_type*)(dst[0] + (y+srcSliceY+1)*dstStride[0]);\
+ dst_type *r, *g, *b;\
+ uint8_t *py_1= src[0] + y*srcStride[0];\
+ uint8_t *py_2= py_1 + srcStride[0];\
+ uint8_t *pu= src[1] + (y>>1)*srcStride[1];\
+ uint8_t *pv= src[2] + (y>>1)*srcStride[2];\
+ unsigned int h_size= c->dstW>>3;\
+ while (h_size--) {\
+ int U, V, Y;\
+
+#define EPILOG(dst_delta)\
+ pu += 4;\
+ pv += 4;\
+ py_1 += 8;\
+ py_2 += 8;\
+ dst_1 += dst_delta;\
+ dst_2 += dst_delta;\
+ }\
+ }\
+ return srcSliceH;\
+}
+
+PROLOG(yuv2rgb_c_32, uint32_t)
+ RGB(0);
+ DST1(0);
+ DST2(0);
+
+ RGB(1);
+ DST2(1);
+ DST1(1);
+
+ RGB(2);
+ DST1(2);
+ DST2(2);
+
+ RGB(3);
+ DST2(3);
+ DST1(3);
+EPILOG(8)
+
+PROLOG(yuv2rgb_c_24_rgb, uint8_t)
+ RGB(0);
+ DST1RGB(0);
+ DST2RGB(0);
+
+ RGB(1);
+ DST2RGB(1);
+ DST1RGB(1);
+
+ RGB(2);
+ DST1RGB(2);
+ DST2RGB(2);
+
+ RGB(3);
+ DST2RGB(3);
+ DST1RGB(3);
+EPILOG(24)
+
+// only trivial mods from yuv2rgb_c_24_rgb
+PROLOG(yuv2rgb_c_24_bgr, uint8_t)
+ RGB(0);
+ DST1BGR(0);
+ DST2BGR(0);
+
+ RGB(1);
+ DST2BGR(1);
+ DST1BGR(1);
+
+ RGB(2);
+ DST1BGR(2);
+ DST2BGR(2);
+
+ RGB(3);
+ DST2BGR(3);
+ DST1BGR(3);
+EPILOG(24)
+
+// This is exactly the same code as yuv2rgb_c_32 except for the types of
+// r, g, b, dst_1, dst_2
+PROLOG(yuv2rgb_c_16, uint16_t)
+ RGB(0);
+ DST1(0);
+ DST2(0);
+
+ RGB(1);
+ DST2(1);
+ DST1(1);
+
+ RGB(2);
+ DST1(2);
+ DST2(2);
+
+ RGB(3);
+ DST2(3);
+ DST1(3);
+EPILOG(8)
+
+// This is exactly the same code as yuv2rgb_c_32 except for the types of
+// r, g, b, dst_1, dst_2
+PROLOG(yuv2rgb_c_8, uint8_t)
+ RGB(0);
+ DST1(0);
+ DST2(0);
+
+ RGB(1);
+ DST2(1);
+ DST1(1);
+
+ RGB(2);
+ DST1(2);
+ DST2(2);
+
+ RGB(3);
+ DST2(3);
+ DST1(3);
+EPILOG(8)
+
+// r, g, b, dst_1, dst_2
+PROLOG(yuv2rgb_c_8_ordered_dither, uint8_t)
+ const uint8_t *d32= dither_8x8_32[y&7];
+ const uint8_t *d64= dither_8x8_73[y&7];
+#define DST1bpp8(i,o) \
+ Y = py_1[2*i]; \
+ dst_1[2*i] = r[Y+d32[0+o]] + g[Y+d32[0+o]] + b[Y+d64[0+o]]; \
+ Y = py_1[2*i+1]; \
+ dst_1[2*i+1] = r[Y+d32[1+o]] + g[Y+d32[1+o]] + b[Y+d64[1+o]];
+
+#define DST2bpp8(i,o) \
+ Y = py_2[2*i]; \
+ dst_2[2*i] = r[Y+d32[8+o]] + g[Y+d32[8+o]] + b[Y+d64[8+o]]; \
+ Y = py_2[2*i+1]; \
+ dst_2[2*i+1] = r[Y+d32[9+o]] + g[Y+d32[9+o]] + b[Y+d64[9+o]];
+
+
+ RGB(0);
+ DST1bpp8(0,0);
+ DST2bpp8(0,0);
+
+ RGB(1);
+ DST2bpp8(1,2);
+ DST1bpp8(1,2);
+
+ RGB(2);
+ DST1bpp8(2,4);
+ DST2bpp8(2,4);
+
+ RGB(3);
+ DST2bpp8(3,6);
+ DST1bpp8(3,6);
+EPILOG(8)
+
+
+// This is exactly the same code as yuv2rgb_c_32 except for the types of
+// r, g, b, dst_1, dst_2
+PROLOG(yuv2rgb_c_4, uint8_t)
+ int acc;
+#define DST1_4(i) \
+ Y = py_1[2*i]; \
+ acc = r[Y] + g[Y] + b[Y]; \
+ Y = py_1[2*i+1]; \
+ acc |= (r[Y] + g[Y] + b[Y])<<4;\
+ dst_1[i] = acc;
+
+#define DST2_4(i) \
+ Y = py_2[2*i]; \
+ acc = r[Y] + g[Y] + b[Y]; \
+ Y = py_2[2*i+1]; \
+ acc |= (r[Y] + g[Y] + b[Y])<<4;\
+ dst_2[i] = acc;
+
+ RGB(0);
+ DST1_4(0);
+ DST2_4(0);
+
+ RGB(1);
+ DST2_4(1);
+ DST1_4(1);
+
+ RGB(2);
+ DST1_4(2);
+ DST2_4(2);
+
+ RGB(3);
+ DST2_4(3);
+ DST1_4(3);
+EPILOG(4)
+
+PROLOG(yuv2rgb_c_4_ordered_dither, uint8_t)
+ const uint8_t *d64= dither_8x8_73[y&7];
+ const uint8_t *d128=dither_8x8_220[y&7];
+ int acc;
+
+#define DST1bpp4(i,o) \
+ Y = py_1[2*i]; \
+ acc = r[Y+d128[0+o]] + g[Y+d64[0+o]] + b[Y+d128[0+o]]; \
+ Y = py_1[2*i+1]; \
+ acc |= (r[Y+d128[1+o]] + g[Y+d64[1+o]] + b[Y+d128[1+o]])<<4;\
+ dst_1[i]= acc;
+
+#define DST2bpp4(i,o) \
+ Y = py_2[2*i]; \
+ acc = r[Y+d128[8+o]] + g[Y+d64[8+o]] + b[Y+d128[8+o]]; \
+ Y = py_2[2*i+1]; \
+ acc |= (r[Y+d128[9+o]] + g[Y+d64[9+o]] + b[Y+d128[9+o]])<<4;\
+ dst_2[i]= acc;
+
+
+ RGB(0);
+ DST1bpp4(0,0);
+ DST2bpp4(0,0);
+
+ RGB(1);
+ DST2bpp4(1,2);
+ DST1bpp4(1,2);
+
+ RGB(2);
+ DST1bpp4(2,4);
+ DST2bpp4(2,4);
+
+ RGB(3);
+ DST2bpp4(3,6);
+ DST1bpp4(3,6);
+EPILOG(4)
+
+// This is exactly the same code as yuv2rgb_c_32 except for the types of
+// r, g, b, dst_1, dst_2
+PROLOG(yuv2rgb_c_4b, uint8_t)
+ RGB(0);
+ DST1(0);
+ DST2(0);
+
+ RGB(1);
+ DST2(1);
+ DST1(1);
+
+ RGB(2);
+ DST1(2);
+ DST2(2);
+
+ RGB(3);
+ DST2(3);
+ DST1(3);
+EPILOG(8)
+
+PROLOG(yuv2rgb_c_4b_ordered_dither, uint8_t)
+ const uint8_t *d64= dither_8x8_73[y&7];
+ const uint8_t *d128=dither_8x8_220[y&7];
+
+#define DST1bpp4b(i,o) \
+ Y = py_1[2*i]; \
+ dst_1[2*i] = r[Y+d128[0+o]] + g[Y+d64[0+o]] + b[Y+d128[0+o]]; \
+ Y = py_1[2*i+1]; \
+ dst_1[2*i+1] = r[Y+d128[1+o]] + g[Y+d64[1+o]] + b[Y+d128[1+o]];
+
+#define DST2bpp4b(i,o) \
+ Y = py_2[2*i]; \
+ dst_2[2*i] = r[Y+d128[8+o]] + g[Y+d64[8+o]] + b[Y+d128[8+o]]; \
+ Y = py_2[2*i+1]; \
+ dst_2[2*i+1] = r[Y+d128[9+o]] + g[Y+d64[9+o]] + b[Y+d128[9+o]];
+
+
+ RGB(0);
+ DST1bpp4b(0,0);
+ DST2bpp4b(0,0);
+
+ RGB(1);
+ DST2bpp4b(1,2);
+ DST1bpp4b(1,2);
+
+ RGB(2);
+ DST1bpp4b(2,4);
+ DST2bpp4b(2,4);
+
+ RGB(3);
+ DST2bpp4b(3,6);
+ DST1bpp4b(3,6);
+EPILOG(8)
+
+PROLOG(yuv2rgb_c_1_ordered_dither, uint8_t)
+ const uint8_t *d128=dither_8x8_220[y&7];
+ char out_1=0, out_2=0;
+ g= c->table_gU[128] + c->table_gV[128];
+
+#define DST1bpp1(i,o) \
+ Y = py_1[2*i]; \
+ out_1+= out_1 + g[Y+d128[0+o]]; \
+ Y = py_1[2*i+1]; \
+ out_1+= out_1 + g[Y+d128[1+o]];
+
+#define DST2bpp1(i,o) \
+ Y = py_2[2*i]; \
+ out_2+= out_2 + g[Y+d128[8+o]]; \
+ Y = py_2[2*i+1]; \
+ out_2+= out_2 + g[Y+d128[9+o]];
+
+ DST1bpp1(0,0);
+ DST2bpp1(0,0);
+
+ DST2bpp1(1,2);
+ DST1bpp1(1,2);
+
+ DST1bpp1(2,4);
+ DST2bpp1(2,4);
+
+ DST2bpp1(3,6);
+ DST1bpp1(3,6);
+
+ dst_1[0]= out_1;
+ dst_2[0]= out_2;
+EPILOG(1)
+
+SwsFunc yuv2rgb_get_func_ptr (SwsContext *c)
+{
+#if defined(HAVE_MMX2) || defined(HAVE_MMX)
+ if(c->flags & SWS_CPU_CAPS_MMX2){
+ switch(c->dstFormat){
+ case PIX_FMT_RGB32: return yuv420_rgb32_MMX2;
+ case PIX_FMT_BGR24: return yuv420_rgb24_MMX2;
+ case PIX_FMT_BGR565: return yuv420_rgb16_MMX2;
+ case PIX_FMT_BGR555: return yuv420_rgb15_MMX2;
+ }
+ }
+ if(c->flags & SWS_CPU_CAPS_MMX){
+ switch(c->dstFormat){
+ case PIX_FMT_RGB32: return yuv420_rgb32_MMX;
+ case PIX_FMT_BGR24: return yuv420_rgb24_MMX;
+ case PIX_FMT_BGR565: return yuv420_rgb16_MMX;
+ case PIX_FMT_BGR555: return yuv420_rgb15_MMX;
+ }
+ }
+#endif
+#ifdef HAVE_MLIB
+ {
+ SwsFunc t= yuv2rgb_init_mlib(c);
+ if(t) return t;
+ }
+#endif
+#ifdef HAVE_ALTIVEC
+ if (c->flags & SWS_CPU_CAPS_ALTIVEC)
+ {
+ SwsFunc t = yuv2rgb_init_altivec(c);
+ if(t) return t;
+ }
+#endif
+
+ MSG_WARN("No accelerated colorspace conversion found\n");
+
+ switch(c->dstFormat){
+ case PIX_FMT_BGR32:
+ case PIX_FMT_RGB32: return yuv2rgb_c_32;
+ case PIX_FMT_RGB24: return yuv2rgb_c_24_rgb;
+ case PIX_FMT_BGR24: return yuv2rgb_c_24_bgr;
+ case PIX_FMT_RGB565:
+ case PIX_FMT_BGR565:
+ case PIX_FMT_RGB555:
+ case PIX_FMT_BGR555: return yuv2rgb_c_16;
+ case PIX_FMT_RGB8:
+ case PIX_FMT_BGR8: return yuv2rgb_c_8_ordered_dither;
+ case PIX_FMT_RGB4:
+ case PIX_FMT_BGR4: return yuv2rgb_c_4_ordered_dither;
+ case PIX_FMT_RGB4_BYTE:
+ case PIX_FMT_BGR4_BYTE: return yuv2rgb_c_4b_ordered_dither;
+ case PIX_FMT_MONOBLACK: return yuv2rgb_c_1_ordered_dither;
+ default:
+ assert(0);
+ }
+ return NULL;
+}
+
+static int div_round (int dividend, int divisor)
+{
+ if (dividend > 0)
+ return (dividend + (divisor>>1)) / divisor;
+ else
+ return -((-dividend + (divisor>>1)) / divisor);
+}
+
+int yuv2rgb_c_init_tables (SwsContext *c, const int inv_table[4], int fullRange, int brightness, int contrast, int saturation)
+{
+ const int isRgb = isBGR(c->dstFormat);
+ const int bpp = fmt_depth(c->dstFormat);
+ int i;
+ uint8_t table_Y[1024];
+ uint32_t *table_32 = 0;
+ uint16_t *table_16 = 0;
+ uint8_t *table_8 = 0;
+ uint8_t *table_332 = 0;
+ uint8_t *table_121 = 0;
+ uint8_t *table_1 = 0;
+ int entry_size = 0;
+ void *table_r = 0, *table_g = 0, *table_b = 0;
+ void *table_start;
+
+ int64_t crv = inv_table[0];
+ int64_t cbu = inv_table[1];
+ int64_t cgu = -inv_table[2];
+ int64_t cgv = -inv_table[3];
+ int64_t cy = 1<<16;
+ int64_t oy = 0;
+
+//printf("%lld %lld %lld %lld %lld\n", cy, crv, cbu, cgu, cgv);
+ if(!fullRange){
+ cy= (cy*255) / 219;
+ oy= 16<<16;
+ }
+
+ cy = (cy *contrast )>>16;
+ crv= (crv*contrast * saturation)>>32;
+ cbu= (cbu*contrast * saturation)>>32;
+ cgu= (cgu*contrast * saturation)>>32;
+ cgv= (cgv*contrast * saturation)>>32;
+//printf("%lld %lld %lld %lld %lld\n", cy, crv, cbu, cgu, cgv);
+ oy -= 256*brightness;
+
+ for (i = 0; i < 1024; i++) {
+ int j;
+
+ j= (cy*(((i - 384)<<16) - oy) + (1<<31))>>32;
+ j = (j < 0) ? 0 : ((j > 255) ? 255 : j);
+ table_Y[i] = j;
+ }
+
+ switch (bpp) {
+ case 32:
+ table_start= table_32 = av_malloc ((197 + 2*682 + 256 + 132) * sizeof (uint32_t));
+
+ entry_size = sizeof (uint32_t);
+ table_r = table_32 + 197;
+ table_b = table_32 + 197 + 685;
+ table_g = table_32 + 197 + 2*682;
+
+ for (i = -197; i < 256+197; i++)
+ ((uint32_t *)table_r)[i] = table_Y[i+384] << (isRgb ? 16 : 0);
+ for (i = -132; i < 256+132; i++)
+ ((uint32_t *)table_g)[i] = table_Y[i+384] << 8;
+ for (i = -232; i < 256+232; i++)
+ ((uint32_t *)table_b)[i] = table_Y[i+384] << (isRgb ? 0 : 16);
+ break;
+
+ case 24:
+ table_start= table_8 = av_malloc ((256 + 2*232) * sizeof (uint8_t));
+
+ entry_size = sizeof (uint8_t);
+ table_r = table_g = table_b = table_8 + 232;
+
+ for (i = -232; i < 256+232; i++)
+ ((uint8_t * )table_b)[i] = table_Y[i+384];
+ break;
+
+ case 15:
+ case 16:
+ table_start= table_16 = av_malloc ((197 + 2*682 + 256 + 132) * sizeof (uint16_t));
+
+ entry_size = sizeof (uint16_t);
+ table_r = table_16 + 197;
+ table_b = table_16 + 197 + 685;
+ table_g = table_16 + 197 + 2*682;
+
+ for (i = -197; i < 256+197; i++) {
+ int j = table_Y[i+384] >> 3;
+
+ if (isRgb)
+ j <<= ((bpp==16) ? 11 : 10);
+
+ ((uint16_t *)table_r)[i] = j;
+ }
+ for (i = -132; i < 256+132; i++) {
+ int j = table_Y[i+384] >> ((bpp==16) ? 2 : 3);
+
+ ((uint16_t *)table_g)[i] = j << 5;
+ }
+ for (i = -232; i < 256+232; i++) {
+ int j = table_Y[i+384] >> 3;
+
+ if (!isRgb)
+ j <<= ((bpp==16) ? 11 : 10);
+
+ ((uint16_t *)table_b)[i] = j;
+ }
+ break;
+
+ case 8:
+ table_start= table_332 = av_malloc ((197 + 2*682 + 256 + 132) * sizeof (uint8_t));
+
+ entry_size = sizeof (uint8_t);
+ table_r = table_332 + 197;
+ table_b = table_332 + 197 + 685;
+ table_g = table_332 + 197 + 2*682;
+
+ for (i = -197; i < 256+197; i++) {
+ int j = (table_Y[i+384 - 16] + 18)/36;
+
+ if (isRgb)
+ j <<= 5;
+
+ ((uint8_t *)table_r)[i] = j;
+ }
+ for (i = -132; i < 256+132; i++) {
+ int j = (table_Y[i+384 - 16] + 18)/36;
+
+ if (!isRgb)
+ j <<= 1;
+
+ ((uint8_t *)table_g)[i] = j << 2;
+ }
+ for (i = -232; i < 256+232; i++) {
+ int j = (table_Y[i+384 - 37] + 43)/85;
+
+ if (!isRgb)
+ j <<= 6;
+
+ ((uint8_t *)table_b)[i] = j;
+ }
+ break;
+ case 4:
+ case 4|128:
+ table_start= table_121 = av_malloc ((197 + 2*682 + 256 + 132) * sizeof (uint8_t));
+
+ entry_size = sizeof (uint8_t);
+ table_r = table_121 + 197;
+ table_b = table_121 + 197 + 685;
+ table_g = table_121 + 197 + 2*682;
+
+ for (i = -197; i < 256+197; i++) {
+ int j = table_Y[i+384 - 110] >> 7;
+
+ if (isRgb)
+ j <<= 3;
+
+ ((uint8_t *)table_r)[i] = j;
+ }
+ for (i = -132; i < 256+132; i++) {
+ int j = (table_Y[i+384 - 37]+ 43)/85;
+
+ ((uint8_t *)table_g)[i] = j << 1;
+ }
+ for (i = -232; i < 256+232; i++) {
+ int j =table_Y[i+384 - 110] >> 7;
+
+ if (!isRgb)
+ j <<= 3;
+
+ ((uint8_t *)table_b)[i] = j;
+ }
+ break;
+
+ case 1:
+ table_start= table_1 = av_malloc (256*2 * sizeof (uint8_t));
+
+ entry_size = sizeof (uint8_t);
+ table_g = table_1;
+ table_r = table_b = NULL;
+
+ for (i = 0; i < 256+256; i++) {
+ int j = table_Y[i + 384 - 110]>>7;
+
+ ((uint8_t *)table_g)[i] = j;
+ }
+ break;
+
+ default:
+ table_start= NULL;
+ MSG_ERR("%ibpp not supported by yuv2rgb\n", bpp);
+ //free mem?
+ return -1;
+ }
+
+ for (i = 0; i < 256; i++) {
+ c->table_rV[i] = table_r + entry_size * div_round (crv * (i-128), 76309);
+ c->table_gU[i] = table_g + entry_size * div_round (cgu * (i-128), 76309);
+ c->table_gV[i] = entry_size * div_round (cgv * (i-128), 76309);
+ c->table_bU[i] = table_b + entry_size * div_round (cbu * (i-128), 76309);
+ }
+
+ av_free(c->yuvTable);
+ c->yuvTable= table_start;
+ return 0;
+}
diff --git a/contrib/ffmpeg/libswscale/yuv2rgb_altivec.c b/contrib/ffmpeg/libswscale/yuv2rgb_altivec.c
new file mode 100644
index 000000000..ca0680a49
--- /dev/null
+++ b/contrib/ffmpeg/libswscale/yuv2rgb_altivec.c
@@ -0,0 +1,963 @@
+/*
+ marc.hoffman@analog.com March 8, 2004
+
+ Altivec Acceleration for Color Space Conversion revision 0.2
+
+ convert I420 YV12 to RGB in various formats,
+ it rejects images that are not in 420 formats
+ it rejects images that don't have widths of multiples of 16
+ it rejects images that don't have heights of multiples of 2
+ reject defers to C simulation codes.
+
+ lots of optimizations to be done here
+
+ 1. need to fix saturation code, I just couldn't get it to fly with packs and adds.
+ so we currently use max min to clip
+
+ 2. the inefficient use of chroma loading needs a bit of brushing up
+
+ 3. analysis of pipeline stalls needs to be done, use shark to identify pipeline stalls
+
+
+ MODIFIED to calculate coeffs from currently selected color space.
+ MODIFIED core to be a macro which you spec the output format.
+ ADDED UYVY conversion which is never called due to some thing in SWSCALE.
+ CORRECTED algorithim selection to be strict on input formats.
+ ADDED runtime detection of altivec.
+
+ ADDED altivec_yuv2packedX vertical scl + RGB converter
+
+ March 27,2004
+ PERFORMANCE ANALYSIS
+
+ The C version use 25% of the processor or ~250Mips for D1 video rawvideo used as test
+ The ALTIVEC version uses 10% of the processor or ~100Mips for D1 video same sequence
+
+ 720*480*30 ~10MPS
+
+ so we have roughly 10clocks per pixel this is too high something has to be wrong.
+
+ OPTIMIZED clip codes to utilize vec_max and vec_packs removing the need for vec_min.
+
+ OPTIMIZED DST OUTPUT cache/dma controls. we are pretty much
+ guaranteed to have the input video frame it was just decompressed so
+ it probably resides in L1 caches. However we are creating the
+ output video stream this needs to use the DSTST instruction to
+ optimize for the cache. We couple this with the fact that we are
+ not going to be visiting the input buffer again so we mark it Least
+ Recently Used. This shaves 25% of the processor cycles off.
+
+ Now MEMCPY is the largest mips consumer in the system, probably due
+ to the inefficient X11 stuff.
+
+ GL libraries seem to be very slow on this machine 1.33Ghz PB running
+ Jaguar, this is not the case for my 1Ghz PB. I thought it might be
+ a versioning issues, however i have libGL.1.2.dylib for both
+ machines. ((We need to figure this out now))
+
+ GL2 libraries work now with patch for RGB32
+
+ NOTE quartz vo driver ARGB32_to_RGB24 consumes 30% of the processor
+
+ Integrated luma prescaling adjustment for saturation/contrast/brightness adjustment.
+*/
+
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+#include "config.h"
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#include "rgb2rgb.h"
+#include "swscale.h"
+#include "swscale_internal.h"
+
+#undef PROFILE_THE_BEAST
+#undef INC_SCALING
+
+typedef unsigned char ubyte;
+typedef signed char sbyte;
+
+
+/* RGB interleaver, 16 planar pels 8-bit samples per channel in
+ homogeneous vector registers x0,x1,x2 are interleaved with the
+ following technique:
+
+ o0 = vec_mergeh (x0,x1);
+ o1 = vec_perm (o0, x2, perm_rgb_0);
+ o2 = vec_perm (o0, x2, perm_rgb_1);
+ o3 = vec_mergel (x0,x1);
+ o4 = vec_perm (o3,o2,perm_rgb_2);
+ o5 = vec_perm (o3,o2,perm_rgb_3);
+
+ perm_rgb_0: o0(RG).h v1(B) --> o1*
+ 0 1 2 3 4
+ rgbr|gbrg|brgb|rgbr
+ 0010 0100 1001 0010
+ 0102 3145 2673 894A
+
+ perm_rgb_1: o0(RG).h v1(B) --> o2
+ 0 1 2 3 4
+ gbrg|brgb|bbbb|bbbb
+ 0100 1001 1111 1111
+ B5CD 6EF7 89AB CDEF
+
+ perm_rgb_2: o3(RG).l o2(rgbB.l) --> o4*
+ 0 1 2 3 4
+ gbrg|brgb|rgbr|gbrg
+ 1111 1111 0010 0100
+ 89AB CDEF 0182 3945
+
+ perm_rgb_2: o3(RG).l o2(rgbB.l) ---> o5*
+ 0 1 2 3 4
+ brgb|rgbr|gbrg|brgb
+ 1001 0010 0100 1001
+ a67b 89cA BdCD eEFf
+
+*/
+static
+const vector unsigned char
+ perm_rgb_0 = (const vector unsigned char)AVV(0x00,0x01,0x10,0x02,0x03,0x11,0x04,0x05,
+ 0x12,0x06,0x07,0x13,0x08,0x09,0x14,0x0a),
+ perm_rgb_1 = (const vector unsigned char)AVV(0x0b,0x15,0x0c,0x0d,0x16,0x0e,0x0f,0x17,
+ 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f),
+ perm_rgb_2 = (const vector unsigned char)AVV(0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x00,0x01,0x18,0x02,0x03,0x19,0x04,0x05),
+ perm_rgb_3 = (const vector unsigned char)AVV(0x1a,0x06,0x07,0x1b,0x08,0x09,0x1c,0x0a,
+ 0x0b,0x1d,0x0c,0x0d,0x1e,0x0e,0x0f,0x1f);
+
+#define vec_merge3(x2,x1,x0,y0,y1,y2) \
+do { \
+ typeof(x0) o0,o2,o3; \
+ o0 = vec_mergeh (x0,x1); \
+ y0 = vec_perm (o0, x2, perm_rgb_0);\
+ o2 = vec_perm (o0, x2, perm_rgb_1);\
+ o3 = vec_mergel (x0,x1); \
+ y1 = vec_perm (o3,o2,perm_rgb_2); \
+ y2 = vec_perm (o3,o2,perm_rgb_3); \
+} while(0)
+
+#define vec_mstbgr24(x0,x1,x2,ptr) \
+do { \
+ typeof(x0) _0,_1,_2; \
+ vec_merge3 (x0,x1,x2,_0,_1,_2); \
+ vec_st (_0, 0, ptr++); \
+ vec_st (_1, 0, ptr++); \
+ vec_st (_2, 0, ptr++); \
+} while (0);
+
+#define vec_mstrgb24(x0,x1,x2,ptr) \
+do { \
+ typeof(x0) _0,_1,_2; \
+ vec_merge3 (x2,x1,x0,_0,_1,_2); \
+ vec_st (_0, 0, ptr++); \
+ vec_st (_1, 0, ptr++); \
+ vec_st (_2, 0, ptr++); \
+} while (0);
+
+/* pack the pixels in rgb0 format
+ msb R
+ lsb 0
+*/
+#define vec_mstrgb32(T,x0,x1,x2,x3,ptr) \
+do { \
+ T _0,_1,_2,_3; \
+ _0 = vec_mergeh (x0,x1); \
+ _1 = vec_mergeh (x2,x3); \
+ _2 = (T)vec_mergeh ((vector unsigned short)_0,(vector unsigned short)_1); \
+ _3 = (T)vec_mergel ((vector unsigned short)_0,(vector unsigned short)_1); \
+ vec_st (_2, 0*16, (T *)ptr); \
+ vec_st (_3, 1*16, (T *)ptr); \
+ _0 = vec_mergel (x0,x1); \
+ _1 = vec_mergel (x2,x3); \
+ _2 = (T)vec_mergeh ((vector unsigned short)_0,(vector unsigned short)_1); \
+ _3 = (T)vec_mergel ((vector unsigned short)_0,(vector unsigned short)_1); \
+ vec_st (_2, 2*16, (T *)ptr); \
+ vec_st (_3, 3*16, (T *)ptr); \
+ ptr += 4; \
+} while (0);
+
+/*
+
+ | 1 0 1.4021 | | Y |
+ | 1 -0.3441 -0.7142 |x| Cb|
+ | 1 1.7718 0 | | Cr|
+
+
+ Y: [-128 127]
+ Cb/Cr : [-128 127]
+
+ typical yuv conversion work on Y: 0-255 this version has been optimized for jpeg decode.
+
+*/
+
+
+
+
+#define vec_unh(x) \
+ (vector signed short) \
+ vec_perm(x,(typeof(x))AVV(0),\
+ (vector unsigned char)AVV(0x10,0x00,0x10,0x01,0x10,0x02,0x10,0x03,\
+ 0x10,0x04,0x10,0x05,0x10,0x06,0x10,0x07))
+#define vec_unl(x) \
+ (vector signed short) \
+ vec_perm(x,(typeof(x))AVV(0),\
+ (vector unsigned char)AVV(0x10,0x08,0x10,0x09,0x10,0x0A,0x10,0x0B,\
+ 0x10,0x0C,0x10,0x0D,0x10,0x0E,0x10,0x0F))
+
+#define vec_clip_s16(x) \
+ vec_max (vec_min (x, (vector signed short)AVV(235,235,235,235,235,235,235,235)),\
+ (vector signed short)AVV(16, 16, 16, 16, 16, 16, 16, 16 ))
+
+#define vec_packclp(x,y) \
+ (vector unsigned char)vec_packs \
+ ((vector unsigned short)vec_max (x,(vector signed short) AVV(0)), \
+ (vector unsigned short)vec_max (y,(vector signed short) AVV(0)))
+
+//#define out_pixels(a,b,c,ptr) vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),a,a,a,ptr)
+
+
+static inline void cvtyuvtoRGB (SwsContext *c,
+ vector signed short Y, vector signed short U, vector signed short V,
+ vector signed short *R, vector signed short *G, vector signed short *B)
+{
+ vector signed short vx,ux,uvx;
+
+ Y = vec_mradds (Y, c->CY, c->OY);
+ U = vec_sub (U,(vector signed short)
+ vec_splat((vector signed short)AVV(128),0));
+ V = vec_sub (V,(vector signed short)
+ vec_splat((vector signed short)AVV(128),0));
+
+ // ux = (CBU*(u<<c->CSHIFT)+0x4000)>>15;
+ ux = vec_sl (U, c->CSHIFT);
+ *B = vec_mradds (ux, c->CBU, Y);
+
+ // vx = (CRV*(v<<c->CSHIFT)+0x4000)>>15;
+ vx = vec_sl (V, c->CSHIFT);
+ *R = vec_mradds (vx, c->CRV, Y);
+
+ // uvx = ((CGU*u) + (CGV*v))>>15;
+ uvx = vec_mradds (U, c->CGU, Y);
+ *G = vec_mradds (V, c->CGV, uvx);
+}
+
+
+/*
+ ------------------------------------------------------------------------------
+ CS converters
+ ------------------------------------------------------------------------------
+*/
+
+
+#define DEFCSP420_CVT(name,out_pixels) \
+static int altivec_##name (SwsContext *c, \
+ unsigned char **in, int *instrides, \
+ int srcSliceY, int srcSliceH, \
+ unsigned char **oplanes, int *outstrides) \
+{ \
+ int w = c->srcW; \
+ int h = srcSliceH; \
+ int i,j; \
+ int instrides_scl[3]; \
+ vector unsigned char y0,y1; \
+ \
+ vector signed char u,v; \
+ \
+ vector signed short Y0,Y1,Y2,Y3; \
+ vector signed short U,V; \
+ vector signed short vx,ux,uvx; \
+ vector signed short vx0,ux0,uvx0; \
+ vector signed short vx1,ux1,uvx1; \
+ vector signed short R0,G0,B0; \
+ vector signed short R1,G1,B1; \
+ vector unsigned char R,G,B; \
+ \
+ vector unsigned char *y1ivP, *y2ivP, *uivP, *vivP; \
+ vector unsigned char align_perm; \
+ \
+ vector signed short \
+ lCY = c->CY, \
+ lOY = c->OY, \
+ lCRV = c->CRV, \
+ lCBU = c->CBU, \
+ lCGU = c->CGU, \
+ lCGV = c->CGV; \
+ \
+ vector unsigned short lCSHIFT = c->CSHIFT; \
+ \
+ ubyte *y1i = in[0]; \
+ ubyte *y2i = in[0]+instrides[0]; \
+ ubyte *ui = in[1]; \
+ ubyte *vi = in[2]; \
+ \
+ vector unsigned char *oute \
+ = (vector unsigned char *) \
+ (oplanes[0]+srcSliceY*outstrides[0]); \
+ vector unsigned char *outo \
+ = (vector unsigned char *) \
+ (oplanes[0]+srcSliceY*outstrides[0]+outstrides[0]); \
+ \
+ \
+ instrides_scl[0] = instrides[0]*2-w; /* the loop moves y{1,2}i by w */ \
+ instrides_scl[1] = instrides[1]-w/2; /* the loop moves ui by w/2 */ \
+ instrides_scl[2] = instrides[2]-w/2; /* the loop moves vi by w/2 */ \
+ \
+ \
+ for (i=0;i<h/2;i++) { \
+ vec_dstst (outo, (0x02000002|(((w*3+32)/32)<<16)), 0); \
+ vec_dstst (oute, (0x02000002|(((w*3+32)/32)<<16)), 1); \
+ \
+ for (j=0;j<w/16;j++) { \
+ \
+ y1ivP = (vector unsigned char *)y1i; \
+ y2ivP = (vector unsigned char *)y2i; \
+ uivP = (vector unsigned char *)ui; \
+ vivP = (vector unsigned char *)vi; \
+ \
+ align_perm = vec_lvsl (0, y1i); \
+ y0 = (vector unsigned char)vec_perm (y1ivP[0], y1ivP[1], align_perm);\
+ \
+ align_perm = vec_lvsl (0, y2i); \
+ y1 = (vector unsigned char)vec_perm (y2ivP[0], y2ivP[1], align_perm);\
+ \
+ align_perm = vec_lvsl (0, ui); \
+ u = (vector signed char)vec_perm (uivP[0], uivP[1], align_perm); \
+ \
+ align_perm = vec_lvsl (0, vi); \
+ v = (vector signed char)vec_perm (vivP[0], vivP[1], align_perm); \
+ \
+ u = (vector signed char) \
+ vec_sub (u,(vector signed char) \
+ vec_splat((vector signed char)AVV(128),0));\
+ v = (vector signed char) \
+ vec_sub (v,(vector signed char) \
+ vec_splat((vector signed char)AVV(128),0));\
+ \
+ U = vec_unpackh (u); \
+ V = vec_unpackh (v); \
+ \
+ \
+ Y0 = vec_unh (y0); \
+ Y1 = vec_unl (y0); \
+ Y2 = vec_unh (y1); \
+ Y3 = vec_unl (y1); \
+ \
+ Y0 = vec_mradds (Y0, lCY, lOY); \
+ Y1 = vec_mradds (Y1, lCY, lOY); \
+ Y2 = vec_mradds (Y2, lCY, lOY); \
+ Y3 = vec_mradds (Y3, lCY, lOY); \
+ \
+ /* ux = (CBU*(u<<CSHIFT)+0x4000)>>15 */ \
+ ux = vec_sl (U, lCSHIFT); \
+ ux = vec_mradds (ux, lCBU, (vector signed short)AVV(0)); \
+ ux0 = vec_mergeh (ux,ux); \
+ ux1 = vec_mergel (ux,ux); \
+ \
+ /* vx = (CRV*(v<<CSHIFT)+0x4000)>>15; */ \
+ vx = vec_sl (V, lCSHIFT); \
+ vx = vec_mradds (vx, lCRV, (vector signed short)AVV(0)); \
+ vx0 = vec_mergeh (vx,vx); \
+ vx1 = vec_mergel (vx,vx); \
+ \
+ /* uvx = ((CGU*u) + (CGV*v))>>15 */ \
+ uvx = vec_mradds (U, lCGU, (vector signed short)AVV(0)); \
+ uvx = vec_mradds (V, lCGV, uvx); \
+ uvx0 = vec_mergeh (uvx,uvx); \
+ uvx1 = vec_mergel (uvx,uvx); \
+ \
+ R0 = vec_add (Y0,vx0); \
+ G0 = vec_add (Y0,uvx0); \
+ B0 = vec_add (Y0,ux0); \
+ R1 = vec_add (Y1,vx1); \
+ G1 = vec_add (Y1,uvx1); \
+ B1 = vec_add (Y1,ux1); \
+ \
+ R = vec_packclp (R0,R1); \
+ G = vec_packclp (G0,G1); \
+ B = vec_packclp (B0,B1); \
+ \
+ out_pixels(R,G,B,oute); \
+ \
+ R0 = vec_add (Y2,vx0); \
+ G0 = vec_add (Y2,uvx0); \
+ B0 = vec_add (Y2,ux0); \
+ R1 = vec_add (Y3,vx1); \
+ G1 = vec_add (Y3,uvx1); \
+ B1 = vec_add (Y3,ux1); \
+ R = vec_packclp (R0,R1); \
+ G = vec_packclp (G0,G1); \
+ B = vec_packclp (B0,B1); \
+ \
+ \
+ out_pixels(R,G,B,outo); \
+ \
+ y1i += 16; \
+ y2i += 16; \
+ ui += 8; \
+ vi += 8; \
+ \
+ } \
+ \
+ outo += (outstrides[0])>>4; \
+ oute += (outstrides[0])>>4; \
+ \
+ ui += instrides_scl[1]; \
+ vi += instrides_scl[2]; \
+ y1i += instrides_scl[0]; \
+ y2i += instrides_scl[0]; \
+ } \
+ return srcSliceH; \
+}
+
+
+#define out_abgr(a,b,c,ptr) vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),c,b,a,ptr)
+#define out_bgra(a,b,c,ptr) vec_mstrgb32(typeof(a),c,b,a,((typeof (a))AVV(0)),ptr)
+#define out_rgba(a,b,c,ptr) vec_mstrgb32(typeof(a),a,b,c,((typeof (a))AVV(0)),ptr)
+#define out_argb(a,b,c,ptr) vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),a,b,c,ptr)
+#define out_rgb24(a,b,c,ptr) vec_mstrgb24(a,b,c,ptr)
+#define out_bgr24(a,b,c,ptr) vec_mstbgr24(a,b,c,ptr)
+
+DEFCSP420_CVT (yuv2_abgr, out_abgr)
+#if 1
+DEFCSP420_CVT (yuv2_bgra, out_bgra)
+#else
+static int altivec_yuv2_bgra32 (SwsContext *c,
+ unsigned char **in, int *instrides,
+ int srcSliceY, int srcSliceH,
+ unsigned char **oplanes, int *outstrides)
+{
+ int w = c->srcW;
+ int h = srcSliceH;
+ int i,j;
+ int instrides_scl[3];
+ vector unsigned char y0,y1;
+
+ vector signed char u,v;
+
+ vector signed short Y0,Y1,Y2,Y3;
+ vector signed short U,V;
+ vector signed short vx,ux,uvx;
+ vector signed short vx0,ux0,uvx0;
+ vector signed short vx1,ux1,uvx1;
+ vector signed short R0,G0,B0;
+ vector signed short R1,G1,B1;
+ vector unsigned char R,G,B;
+
+ vector unsigned char *uivP, *vivP;
+ vector unsigned char align_perm;
+
+ vector signed short
+ lCY = c->CY,
+ lOY = c->OY,
+ lCRV = c->CRV,
+ lCBU = c->CBU,
+ lCGU = c->CGU,
+ lCGV = c->CGV;
+
+ vector unsigned short lCSHIFT = c->CSHIFT;
+
+ ubyte *y1i = in[0];
+ ubyte *y2i = in[0]+w;
+ ubyte *ui = in[1];
+ ubyte *vi = in[2];
+
+ vector unsigned char *oute
+ = (vector unsigned char *)
+ (oplanes[0]+srcSliceY*outstrides[0]);
+ vector unsigned char *outo
+ = (vector unsigned char *)
+ (oplanes[0]+srcSliceY*outstrides[0]+outstrides[0]);
+
+
+ instrides_scl[0] = instrides[0];
+ instrides_scl[1] = instrides[1]-w/2; /* the loop moves ui by w/2 */
+ instrides_scl[2] = instrides[2]-w/2; /* the loop moves vi by w/2 */
+
+
+ for (i=0;i<h/2;i++) {
+ vec_dstst (outo, (0x02000002|(((w*3+32)/32)<<16)), 0);
+ vec_dstst (oute, (0x02000002|(((w*3+32)/32)<<16)), 1);
+
+ for (j=0;j<w/16;j++) {
+
+ y0 = vec_ldl (0,y1i);
+ y1 = vec_ldl (0,y2i);
+ uivP = (vector unsigned char *)ui;
+ vivP = (vector unsigned char *)vi;
+
+ align_perm = vec_lvsl (0, ui);
+ u = (vector signed char)vec_perm (uivP[0], uivP[1], align_perm);
+
+ align_perm = vec_lvsl (0, vi);
+ v = (vector signed char)vec_perm (vivP[0], vivP[1], align_perm);
+ u = (vector signed char)
+ vec_sub (u,(vector signed char)
+ vec_splat((vector signed char)AVV(128),0));
+
+ v = (vector signed char)
+ vec_sub (v, (vector signed char)
+ vec_splat((vector signed char)AVV(128),0));
+
+ U = vec_unpackh (u);
+ V = vec_unpackh (v);
+
+
+ Y0 = vec_unh (y0);
+ Y1 = vec_unl (y0);
+ Y2 = vec_unh (y1);
+ Y3 = vec_unl (y1);
+
+ Y0 = vec_mradds (Y0, lCY, lOY);
+ Y1 = vec_mradds (Y1, lCY, lOY);
+ Y2 = vec_mradds (Y2, lCY, lOY);
+ Y3 = vec_mradds (Y3, lCY, lOY);
+
+ /* ux = (CBU*(u<<CSHIFT)+0x4000)>>15 */
+ ux = vec_sl (U, lCSHIFT);
+ ux = vec_mradds (ux, lCBU, (vector signed short)AVV(0));
+ ux0 = vec_mergeh (ux,ux);
+ ux1 = vec_mergel (ux,ux);
+
+ /* vx = (CRV*(v<<CSHIFT)+0x4000)>>15; */
+ vx = vec_sl (V, lCSHIFT);
+ vx = vec_mradds (vx, lCRV, (vector signed short)AVV(0));
+ vx0 = vec_mergeh (vx,vx);
+ vx1 = vec_mergel (vx,vx);
+ /* uvx = ((CGU*u) + (CGV*v))>>15 */
+ uvx = vec_mradds (U, lCGU, (vector signed short)AVV(0));
+ uvx = vec_mradds (V, lCGV, uvx);
+ uvx0 = vec_mergeh (uvx,uvx);
+ uvx1 = vec_mergel (uvx,uvx);
+ R0 = vec_add (Y0,vx0);
+ G0 = vec_add (Y0,uvx0);
+ B0 = vec_add (Y0,ux0);
+ R1 = vec_add (Y1,vx1);
+ G1 = vec_add (Y1,uvx1);
+ B1 = vec_add (Y1,ux1);
+ R = vec_packclp (R0,R1);
+ G = vec_packclp (G0,G1);
+ B = vec_packclp (B0,B1);
+
+ out_argb(R,G,B,oute);
+ R0 = vec_add (Y2,vx0);
+ G0 = vec_add (Y2,uvx0);
+ B0 = vec_add (Y2,ux0);
+ R1 = vec_add (Y3,vx1);
+ G1 = vec_add (Y3,uvx1);
+ B1 = vec_add (Y3,ux1);
+ R = vec_packclp (R0,R1);
+ G = vec_packclp (G0,G1);
+ B = vec_packclp (B0,B1);
+
+ out_argb(R,G,B,outo);
+ y1i += 16;
+ y2i += 16;
+ ui += 8;
+ vi += 8;
+
+ }
+
+ outo += (outstrides[0])>>4;
+ oute += (outstrides[0])>>4;
+
+ ui += instrides_scl[1];
+ vi += instrides_scl[2];
+ y1i += instrides_scl[0];
+ y2i += instrides_scl[0];
+ }
+ return srcSliceH;
+}
+
+#endif
+
+
+DEFCSP420_CVT (yuv2_rgba, out_rgba)
+DEFCSP420_CVT (yuv2_argb, out_argb)
+DEFCSP420_CVT (yuv2_rgb24, out_rgb24)
+DEFCSP420_CVT (yuv2_bgr24, out_bgr24)
+
+
+// uyvy|uyvy|uyvy|uyvy
+// 0123 4567 89ab cdef
+static
+const vector unsigned char
+ demux_u = (const vector unsigned char)AVV(0x10,0x00,0x10,0x00,
+ 0x10,0x04,0x10,0x04,
+ 0x10,0x08,0x10,0x08,
+ 0x10,0x0c,0x10,0x0c),
+ demux_v = (const vector unsigned char)AVV(0x10,0x02,0x10,0x02,
+ 0x10,0x06,0x10,0x06,
+ 0x10,0x0A,0x10,0x0A,
+ 0x10,0x0E,0x10,0x0E),
+ demux_y = (const vector unsigned char)AVV(0x10,0x01,0x10,0x03,
+ 0x10,0x05,0x10,0x07,
+ 0x10,0x09,0x10,0x0B,
+ 0x10,0x0D,0x10,0x0F);
+
+/*
+ this is so I can play live CCIR raw video
+*/
+static int altivec_uyvy_rgb32 (SwsContext *c,
+ unsigned char **in, int *instrides,
+ int srcSliceY, int srcSliceH,
+ unsigned char **oplanes, int *outstrides)
+{
+ int w = c->srcW;
+ int h = srcSliceH;
+ int i,j;
+ vector unsigned char uyvy;
+ vector signed short Y,U,V;
+ vector signed short R0,G0,B0,R1,G1,B1;
+ vector unsigned char R,G,B;
+ vector unsigned char *out;
+ ubyte *img;
+
+ img = in[0];
+ out = (vector unsigned char *)(oplanes[0]+srcSliceY*outstrides[0]);
+
+ for (i=0;i<h;i++) {
+ for (j=0;j<w/16;j++) {
+ uyvy = vec_ld (0, img);
+ U = (vector signed short)
+ vec_perm (uyvy, (vector unsigned char)AVV(0), demux_u);
+
+ V = (vector signed short)
+ vec_perm (uyvy, (vector unsigned char)AVV(0), demux_v);
+
+ Y = (vector signed short)
+ vec_perm (uyvy, (vector unsigned char)AVV(0), demux_y);
+
+ cvtyuvtoRGB (c, Y,U,V,&R0,&G0,&B0);
+
+ uyvy = vec_ld (16, img);
+ U = (vector signed short)
+ vec_perm (uyvy, (vector unsigned char)AVV(0), demux_u);
+
+ V = (vector signed short)
+ vec_perm (uyvy, (vector unsigned char)AVV(0), demux_v);
+
+ Y = (vector signed short)
+ vec_perm (uyvy, (vector unsigned char)AVV(0), demux_y);
+
+ cvtyuvtoRGB (c, Y,U,V,&R1,&G1,&B1);
+
+ R = vec_packclp (R0,R1);
+ G = vec_packclp (G0,G1);
+ B = vec_packclp (B0,B1);
+
+ // vec_mstbgr24 (R,G,B, out);
+ out_rgba (R,G,B,out);
+
+ img += 32;
+ }
+ }
+ return srcSliceH;
+}
+
+
+
+/* Ok currently the acceleration routine only supports
+ inputs of widths a multiple of 16
+ and heights a multiple 2
+
+ So we just fall back to the C codes for this.
+*/
+SwsFunc yuv2rgb_init_altivec (SwsContext *c)
+{
+ if (!(c->flags & SWS_CPU_CAPS_ALTIVEC))
+ return NULL;
+
+ /*
+ and this seems not to matter too much I tried a bunch of
+ videos with abnormal widths and mplayer crashes else where.
+ mplayer -vo x11 -rawvideo on:w=350:h=240 raw-350x240.eyuv
+ boom with X11 bad match.
+
+ */
+ if ((c->srcW & 0xf) != 0) return NULL;
+
+ switch (c->srcFormat) {
+ case PIX_FMT_YUV410P:
+ case PIX_FMT_YUV420P:
+ /*case IMGFMT_CLPL: ??? */
+ case PIX_FMT_GRAY8:
+ case PIX_FMT_NV12:
+ case PIX_FMT_NV21:
+ if ((c->srcH & 0x1) != 0)
+ return NULL;
+
+ switch(c->dstFormat){
+ case PIX_FMT_RGB24:
+ MSG_WARN("ALTIVEC: Color Space RGB24\n");
+ return altivec_yuv2_rgb24;
+ case PIX_FMT_BGR24:
+ MSG_WARN("ALTIVEC: Color Space BGR24\n");
+ return altivec_yuv2_bgr24;
+ case PIX_FMT_ARGB:
+ MSG_WARN("ALTIVEC: Color Space ARGB\n");
+ return altivec_yuv2_argb;
+ case PIX_FMT_ABGR:
+ MSG_WARN("ALTIVEC: Color Space ABGR\n");
+ return altivec_yuv2_abgr;
+ case PIX_FMT_RGBA:
+ MSG_WARN("ALTIVEC: Color Space RGBA\n");
+ return altivec_yuv2_rgba;
+ case PIX_FMT_BGRA:
+ MSG_WARN("ALTIVEC: Color Space BGRA\n");
+ return altivec_yuv2_bgra;
+ default: return NULL;
+ }
+ break;
+
+ case PIX_FMT_UYVY422:
+ switch(c->dstFormat){
+ case PIX_FMT_BGR32:
+ MSG_WARN("ALTIVEC: Color Space UYVY -> RGB32\n");
+ return altivec_uyvy_rgb32;
+ default: return NULL;
+ }
+ break;
+
+ }
+ return NULL;
+}
+
+static uint16_t roundToInt16(int64_t f){
+ int r= (f + (1<<15))>>16;
+ if(r<-0x7FFF) return 0x8000;
+ else if(r> 0x7FFF) return 0x7FFF;
+ else return r;
+}
+
+void yuv2rgb_altivec_init_tables (SwsContext *c, const int inv_table[4],int brightness,int contrast, int saturation)
+{
+ union {
+ signed short tmp[8] __attribute__ ((aligned(16)));
+ vector signed short vec;
+ } buf;
+
+ buf.tmp[0] = ( (0xffffLL) * contrast>>8 )>>9; //cy
+ buf.tmp[1] = -256*brightness; //oy
+ buf.tmp[2] = (inv_table[0]>>3) *(contrast>>16)*(saturation>>16); //crv
+ buf.tmp[3] = (inv_table[1]>>3) *(contrast>>16)*(saturation>>16); //cbu
+ buf.tmp[4] = -((inv_table[2]>>1)*(contrast>>16)*(saturation>>16)); //cgu
+ buf.tmp[5] = -((inv_table[3]>>1)*(contrast>>16)*(saturation>>16)); //cgv
+
+
+ c->CSHIFT = (vector unsigned short)vec_splat_u16(2);
+ c->CY = vec_splat ((vector signed short)buf.vec, 0);
+ c->OY = vec_splat ((vector signed short)buf.vec, 1);
+ c->CRV = vec_splat ((vector signed short)buf.vec, 2);
+ c->CBU = vec_splat ((vector signed short)buf.vec, 3);
+ c->CGU = vec_splat ((vector signed short)buf.vec, 4);
+ c->CGV = vec_splat ((vector signed short)buf.vec, 5);
+#if 0
+{
+int i;
+char *v[6]={"cy","oy","crv","cbu","cgu","cgv"};
+for (i=0; i<6;i++)
+ printf("%s %d ", v[i],buf.tmp[i] );
+ printf("\n");
+}
+#endif
+ return;
+}
+
+
+void
+altivec_yuv2packedX (SwsContext *c,
+ int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
+ int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
+ uint8_t *dest, int dstW, int dstY)
+{
+ int i,j;
+ vector signed short X,X0,X1,Y0,U0,V0,Y1,U1,V1,U,V;
+ vector signed short R0,G0,B0,R1,G1,B1;
+
+ vector unsigned char R,G,B;
+ vector unsigned char *out,*nout;
+
+ vector signed short RND = vec_splat_s16(1<<3);
+ vector unsigned short SCL = vec_splat_u16(4);
+ unsigned long scratch[16] __attribute__ ((aligned (16)));
+
+ vector signed short *YCoeffs, *CCoeffs;
+
+ YCoeffs = c->vYCoeffsBank+dstY*lumFilterSize;
+ CCoeffs = c->vCCoeffsBank+dstY*chrFilterSize;
+
+ out = (vector unsigned char *)dest;
+
+ for(i=0; i<dstW; i+=16){
+ Y0 = RND;
+ Y1 = RND;
+ /* extract 16 coeffs from lumSrc */
+ for(j=0; j<lumFilterSize; j++) {
+ X0 = vec_ld (0, &lumSrc[j][i]);
+ X1 = vec_ld (16, &lumSrc[j][i]);
+ Y0 = vec_mradds (X0, YCoeffs[j], Y0);
+ Y1 = vec_mradds (X1, YCoeffs[j], Y1);
+ }
+
+ U = RND;
+ V = RND;
+ /* extract 8 coeffs from U,V */
+ for(j=0; j<chrFilterSize; j++) {
+ X = vec_ld (0, &chrSrc[j][i/2]);
+ U = vec_mradds (X, CCoeffs[j], U);
+ X = vec_ld (0, &chrSrc[j][i/2+2048]);
+ V = vec_mradds (X, CCoeffs[j], V);
+ }
+
+ /* scale and clip signals */
+ Y0 = vec_sra (Y0, SCL);
+ Y1 = vec_sra (Y1, SCL);
+ U = vec_sra (U, SCL);
+ V = vec_sra (V, SCL);
+
+ Y0 = vec_clip_s16 (Y0);
+ Y1 = vec_clip_s16 (Y1);
+ U = vec_clip_s16 (U);
+ V = vec_clip_s16 (V);
+
+ /* now we have
+ Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15
+ U= u0 u1 u2 u3 u4 u5 u6 u7 V= v0 v1 v2 v3 v4 v5 v6 v7
+
+ Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15
+ U0= u0 u0 u1 u1 u2 u2 u3 u3 U1= u4 u4 u5 u5 u6 u6 u7 u7
+ V0= v0 v0 v1 v1 v2 v2 v3 v3 V1= v4 v4 v5 v5 v6 v6 v7 v7
+ */
+
+ U0 = vec_mergeh (U,U);
+ V0 = vec_mergeh (V,V);
+
+ U1 = vec_mergel (U,U);
+ V1 = vec_mergel (V,V);
+
+ cvtyuvtoRGB (c, Y0,U0,V0,&R0,&G0,&B0);
+ cvtyuvtoRGB (c, Y1,U1,V1,&R1,&G1,&B1);
+
+ R = vec_packclp (R0,R1);
+ G = vec_packclp (G0,G1);
+ B = vec_packclp (B0,B1);
+
+ switch(c->dstFormat) {
+ case PIX_FMT_ABGR: out_abgr (R,G,B,out); break;
+ case PIX_FMT_BGRA: out_bgra (R,G,B,out); break;
+ case PIX_FMT_RGBA: out_rgba (R,G,B,out); break;
+ case PIX_FMT_ARGB: out_argb (R,G,B,out); break;
+ case PIX_FMT_RGB24: out_rgb24 (R,G,B,out); break;
+ case PIX_FMT_BGR24: out_bgr24 (R,G,B,out); break;
+ default:
+ {
+ /* If this is reached, the caller should have called yuv2packedXinC
+ instead. */
+ static int printed_error_message;
+ if(!printed_error_message) {
+ MSG_ERR("altivec_yuv2packedX doesn't support %s output\n",
+ sws_format_name(c->dstFormat));
+ printed_error_message=1;
+ }
+ return;
+ }
+ }
+ }
+
+ if (i < dstW) {
+ i -= 16;
+
+ Y0 = RND;
+ Y1 = RND;
+ /* extract 16 coeffs from lumSrc */
+ for(j=0; j<lumFilterSize; j++) {
+ X0 = vec_ld (0, &lumSrc[j][i]);
+ X1 = vec_ld (16, &lumSrc[j][i]);
+ Y0 = vec_mradds (X0, YCoeffs[j], Y0);
+ Y1 = vec_mradds (X1, YCoeffs[j], Y1);
+ }
+
+ U = RND;
+ V = RND;
+ /* extract 8 coeffs from U,V */
+ for(j=0; j<chrFilterSize; j++) {
+ X = vec_ld (0, &chrSrc[j][i/2]);
+ U = vec_mradds (X, CCoeffs[j], U);
+ X = vec_ld (0, &chrSrc[j][i/2+2048]);
+ V = vec_mradds (X, CCoeffs[j], V);
+ }
+
+ /* scale and clip signals */
+ Y0 = vec_sra (Y0, SCL);
+ Y1 = vec_sra (Y1, SCL);
+ U = vec_sra (U, SCL);
+ V = vec_sra (V, SCL);
+
+ Y0 = vec_clip_s16 (Y0);
+ Y1 = vec_clip_s16 (Y1);
+ U = vec_clip_s16 (U);
+ V = vec_clip_s16 (V);
+
+ /* now we have
+ Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15
+ U= u0 u1 u2 u3 u4 u5 u6 u7 V= v0 v1 v2 v3 v4 v5 v6 v7
+
+ Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15
+ U0= u0 u0 u1 u1 u2 u2 u3 u3 U1= u4 u4 u5 u5 u6 u6 u7 u7
+ V0= v0 v0 v1 v1 v2 v2 v3 v3 V1= v4 v4 v5 v5 v6 v6 v7 v7
+ */
+
+ U0 = vec_mergeh (U,U);
+ V0 = vec_mergeh (V,V);
+
+ U1 = vec_mergel (U,U);
+ V1 = vec_mergel (V,V);
+
+ cvtyuvtoRGB (c, Y0,U0,V0,&R0,&G0,&B0);
+ cvtyuvtoRGB (c, Y1,U1,V1,&R1,&G1,&B1);
+
+ R = vec_packclp (R0,R1);
+ G = vec_packclp (G0,G1);
+ B = vec_packclp (B0,B1);
+
+ nout = (vector unsigned char *)scratch;
+ switch(c->dstFormat) {
+ case PIX_FMT_ABGR: out_abgr (R,G,B,nout); break;
+ case PIX_FMT_BGRA: out_bgra (R,G,B,nout); break;
+ case PIX_FMT_RGBA: out_rgba (R,G,B,nout); break;
+ case PIX_FMT_ARGB: out_argb (R,G,B,nout); break;
+ case PIX_FMT_RGB24: out_rgb24 (R,G,B,nout); break;
+ case PIX_FMT_BGR24: out_bgr24 (R,G,B,nout); break;
+ default:
+ /* Unreachable, I think. */
+ MSG_ERR("altivec_yuv2packedX doesn't support %s output\n",
+ sws_format_name(c->dstFormat));
+ return;
+ }
+
+ memcpy (&((uint32_t*)dest)[i], scratch, (dstW-i)/4);
+ }
+
+}
diff --git a/contrib/ffmpeg/libswscale/yuv2rgb_mlib.c b/contrib/ffmpeg/libswscale/yuv2rgb_mlib.c
new file mode 100644
index 000000000..824ee39d1
--- /dev/null
+++ b/contrib/ffmpeg/libswscale/yuv2rgb_mlib.c
@@ -0,0 +1,87 @@
+/*
+ * yuv2rgb_mlib.c, Software YUV to RGB coverter using mediaLib
+ *
+ * Copyright (C) 2000, Håkan Hjort <d95hjort@dtek.chalmers.se>
+ * All Rights Reserved.
+ *
+ * This file is part of mpeg2dec, a free MPEG-2 video decoder
+ *
+ * mpeg2dec 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; either version 2, or (at your option)
+ * any later version.
+ *
+ * mpeg2dec is distributed in the hope that 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 GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <mlib_types.h>
+#include <mlib_status.h>
+#include <mlib_sys.h>
+#include <mlib_video.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "swscale.h"
+
+static int mlib_YUV2ARGB420_32(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+ if(c->srcFormat == PIX_FMT_YUV422P){
+ srcStride[1] *= 2;
+ srcStride[2] *= 2;
+ }
+
+ assert(srcStride[1] == srcStride[2]);
+
+ mlib_VideoColorYUV2ARGB420(dst[0]+srcSliceY*dstStride[0], src[0], src[1], src[2], c->dstW,
+ srcSliceH, dstStride[0], srcStride[0], srcStride[1]);
+ return srcSliceH;
+}
+
+static int mlib_YUV2ABGR420_32(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+ if(c->srcFormat == PIX_FMT_YUV422P){
+ srcStride[1] *= 2;
+ srcStride[2] *= 2;
+ }
+
+ assert(srcStride[1] == srcStride[2]);
+
+ mlib_VideoColorYUV2ABGR420(dst[0]+srcSliceY*dstStride[0], src[0], src[1], src[2], c->dstW,
+ srcSliceH, dstStride[0], srcStride[0], srcStride[1]);
+ return srcSliceH;
+}
+
+static int mlib_YUV2RGB420_24(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+ if(c->srcFormat == PIX_FMT_YUV422P){
+ srcStride[1] *= 2;
+ srcStride[2] *= 2;
+ }
+
+ assert(srcStride[1] == srcStride[2]);
+
+ mlib_VideoColorYUV2RGB420(dst[0]+srcSliceY*dstStride[0], src[0], src[1], src[2], c->dstW,
+ srcSliceH, dstStride[0], srcStride[0], srcStride[1]);
+ return srcSliceH;
+}
+
+
+SwsFunc yuv2rgb_init_mlib(SwsContext *c)
+{
+ switch(c->dstFormat){
+ case PIX_FMT_RGB24: return mlib_YUV2RGB420_24;
+ case PIX_FMT_BGR32: return mlib_YUV2ARGB420_32;
+ case PIX_FMT_RGB32: return mlib_YUV2ABGR420_32;
+ default: return NULL;
+ }
+}
+
diff --git a/contrib/ffmpeg/libswscale/yuv2rgb_template.c b/contrib/ffmpeg/libswscale/yuv2rgb_template.c
new file mode 100644
index 000000000..fd222350e
--- /dev/null
+++ b/contrib/ffmpeg/libswscale/yuv2rgb_template.c
@@ -0,0 +1,540 @@
+
+/*
+ * yuv2rgb_mmx.c, Software YUV to RGB coverter with Intel MMX "technology"
+ *
+ * Copyright (C) 2000, Silicon Integrated System Corp.
+ * All Rights Reserved.
+ *
+ * Author: Olie Lho <ollie@sis.com.tw>
+ *
+ * This file is part of mpeg2dec, a free MPEG-2 video decoder
+ *
+ * mpeg2dec 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; either version 2, or (at your option)
+ * any later version.
+ *
+ * mpeg2dec is distributed in the hope that 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 GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * 15,24 bpp and dithering from Michael Niedermayer (michaelni@gmx.at)
+ * MMX/MMX2 Template stuff from Michael Niedermayer (needed for fast movntq support)
+ * context / deglobalize stuff by Michael Niedermayer
+ */
+
+#undef MOVNTQ
+#undef EMMS
+#undef SFENCE
+
+#ifdef HAVE_3DNOW
+/* On K6 femms is faster of emms. On K7 femms is directly mapped on emms. */
+#define EMMS "femms"
+#else
+#define EMMS "emms"
+#endif
+
+#ifdef HAVE_MMX2
+#define MOVNTQ "movntq"
+#define SFENCE "sfence"
+#else
+#define MOVNTQ "movq"
+#define SFENCE "/nop"
+#endif
+
+#define YUV2RGB \
+ /* Do the multiply part of the conversion for even and odd pixels,
+ register usage:
+ mm0 -> Cblue, mm1 -> Cred, mm2 -> Cgreen even pixels,
+ mm3 -> Cblue, mm4 -> Cred, mm5 -> Cgreen odd pixels,
+ mm6 -> Y even, mm7 -> Y odd */\
+ /* convert the chroma part */\
+ "punpcklbw %%mm4, %%mm0;" /* scatter 4 Cb 00 u3 00 u2 00 u1 00 u0 */ \
+ "punpcklbw %%mm4, %%mm1;" /* scatter 4 Cr 00 v3 00 v2 00 v1 00 v0 */ \
+\
+ "psllw $3, %%mm0;" /* Promote precision */ \
+ "psllw $3, %%mm1;" /* Promote precision */ \
+\
+ "psubsw "U_OFFSET"(%4), %%mm0;" /* Cb -= 128 */ \
+ "psubsw "V_OFFSET"(%4), %%mm1;" /* Cr -= 128 */ \
+\
+ "movq %%mm0, %%mm2;" /* Copy 4 Cb 00 u3 00 u2 00 u1 00 u0 */ \
+ "movq %%mm1, %%mm3;" /* Copy 4 Cr 00 v3 00 v2 00 v1 00 v0 */ \
+\
+ "pmulhw "UG_COEFF"(%4), %%mm2;" /* Mul Cb with green coeff -> Cb green */ \
+ "pmulhw "VG_COEFF"(%4), %%mm3;" /* Mul Cr with green coeff -> Cr green */ \
+\
+ "pmulhw "UB_COEFF"(%4), %%mm0;" /* Mul Cb -> Cblue 00 b3 00 b2 00 b1 00 b0 */\
+ "pmulhw "VR_COEFF"(%4), %%mm1;" /* Mul Cr -> Cred 00 r3 00 r2 00 r1 00 r0 */\
+\
+ "paddsw %%mm3, %%mm2;" /* Cb green + Cr green -> Cgreen */\
+\
+ /* convert the luma part */\
+ "movq %%mm6, %%mm7;" /* Copy 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */\
+ "pand "MANGLE(mmx_00ffw)", %%mm6;" /* get Y even 00 Y6 00 Y4 00 Y2 00 Y0 */\
+\
+ "psrlw $8, %%mm7;" /* get Y odd 00 Y7 00 Y5 00 Y3 00 Y1 */\
+\
+ "psllw $3, %%mm6;" /* Promote precision */\
+ "psllw $3, %%mm7;" /* Promote precision */\
+\
+ "psubw "Y_OFFSET"(%4), %%mm6;" /* Y -= 16 */\
+ "psubw "Y_OFFSET"(%4), %%mm7;" /* Y -= 16 */\
+\
+ "pmulhw "Y_COEFF"(%4), %%mm6;" /* Mul 4 Y even 00 y6 00 y4 00 y2 00 y0 */\
+ "pmulhw "Y_COEFF"(%4), %%mm7;" /* Mul 4 Y odd 00 y7 00 y5 00 y3 00 y1 */\
+\
+ /* Do the addition part of the conversion for even and odd pixels,
+ register usage:
+ mm0 -> Cblue, mm1 -> Cred, mm2 -> Cgreen even pixels,
+ mm3 -> Cblue, mm4 -> Cred, mm5 -> Cgreen odd pixels,
+ mm6 -> Y even, mm7 -> Y odd */\
+ "movq %%mm0, %%mm3;" /* Copy Cblue */\
+ "movq %%mm1, %%mm4;" /* Copy Cred */\
+ "movq %%mm2, %%mm5;" /* Copy Cgreen */\
+\
+ "paddsw %%mm6, %%mm0;" /* Y even + Cblue 00 B6 00 B4 00 B2 00 B0 */\
+ "paddsw %%mm7, %%mm3;" /* Y odd + Cblue 00 B7 00 B5 00 B3 00 B1 */\
+\
+ "paddsw %%mm6, %%mm1;" /* Y even + Cred 00 R6 00 R4 00 R2 00 R0 */\
+ "paddsw %%mm7, %%mm4;" /* Y odd + Cred 00 R7 00 R5 00 R3 00 R1 */\
+\
+ "paddsw %%mm6, %%mm2;" /* Y even + Cgreen 00 G6 00 G4 00 G2 00 G0 */\
+ "paddsw %%mm7, %%mm5;" /* Y odd + Cgreen 00 G7 00 G5 00 G3 00 G1 */\
+\
+ /* Limit RGB even to 0..255 */\
+ "packuswb %%mm0, %%mm0;" /* B6 B4 B2 B0 B6 B4 B2 B0 */\
+ "packuswb %%mm1, %%mm1;" /* R6 R4 R2 R0 R6 R4 R2 R0 */\
+ "packuswb %%mm2, %%mm2;" /* G6 G4 G2 G0 G6 G4 G2 G0 */\
+\
+ /* Limit RGB odd to 0..255 */\
+ "packuswb %%mm3, %%mm3;" /* B7 B5 B3 B1 B7 B5 B3 B1 */\
+ "packuswb %%mm4, %%mm4;" /* R7 R5 R3 R1 R7 R5 R3 R1 */\
+ "packuswb %%mm5, %%mm5;" /* G7 G5 G3 G1 G7 G5 G3 G1 */\
+\
+ /* Interleave RGB even and odd */\
+ "punpcklbw %%mm3, %%mm0;" /* B7 B6 B5 B4 B3 B2 B1 B0 */\
+ "punpcklbw %%mm4, %%mm1;" /* R7 R6 R5 R4 R3 R2 R1 R0 */\
+ "punpcklbw %%mm5, %%mm2;" /* G7 G6 G5 G4 G3 G2 G1 G0 */\
+
+
+static inline int RENAME(yuv420_rgb16)(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+ int y, h_size;
+
+ if(c->srcFormat == PIX_FMT_YUV422P){
+ srcStride[1] *= 2;
+ srcStride[2] *= 2;
+ }
+
+ h_size= (c->dstW+7)&~7;
+ if(h_size*2 > dstStride[0]) h_size-=8;
+
+ __asm__ __volatile__ ("pxor %mm4, %mm4;" /* zero mm4 */ );
+//printf("%X %X %X %X %X %X %X %X %X %X\n", (int)&c->redDither, (int)&b5Dither, (int)src[0], (int)src[1], (int)src[2], (int)dst[0],
+//srcStride[0],srcStride[1],srcStride[2],dstStride[0]);
+ for (y= 0; y<srcSliceH; y++ ) {
+ uint8_t *_image = dst[0] + (y+srcSliceY)*dstStride[0];
+ uint8_t *_py = src[0] + y*srcStride[0];
+ uint8_t *_pu = src[1] + (y>>1)*srcStride[1];
+ uint8_t *_pv = src[2] + (y>>1)*srcStride[2];
+ long index= -h_size/2;
+
+ b5Dither= dither8[y&1];
+ g6Dither= dither4[y&1];
+ g5Dither= dither8[y&1];
+ r5Dither= dither8[(y+1)&1];
+ /* this mmx assembly code deals with SINGLE scan line at a time, it convert 8
+ pixels in each iteration */
+ __asm__ __volatile__ (
+ /* load data for start of next scan line */
+ "movd (%2, %0), %%mm0;" /* Load 4 Cb 00 00 00 00 u3 u2 u1 u0 */
+ "movd (%3, %0), %%mm1;" /* Load 4 Cr 00 00 00 00 v3 v2 v1 v0 */
+ "movq (%5, %0, 2), %%mm6;" /* Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */
+// ".balign 16 \n\t"
+ "1: \n\t"
+/* no speed diference on my p3@500 with prefetch,
+ * if it is faster for anyone with -benchmark then tell me
+ PREFETCH" 64(%0) \n\t"
+ PREFETCH" 64(%1) \n\t"
+ PREFETCH" 64(%2) \n\t"
+*/
+YUV2RGB
+
+#ifdef DITHER1XBPP
+ "paddusb "MANGLE(b5Dither)", %%mm0;"
+ "paddusb "MANGLE(g6Dither)", %%mm2;"
+ "paddusb "MANGLE(r5Dither)", %%mm1;"
+#endif
+ /* mask unneeded bits off */
+ "pand "MANGLE(mmx_redmask)", %%mm0;" /* b7b6b5b4 b3_0_0_0 b7b6b5b4 b3_0_0_0 */
+ "pand "MANGLE(mmx_grnmask)", %%mm2;" /* g7g6g5g4 g3g2_0_0 g7g6g5g4 g3g2_0_0 */
+ "pand "MANGLE(mmx_redmask)", %%mm1;" /* r7r6r5r4 r3_0_0_0 r7r6r5r4 r3_0_0_0 */
+
+ "psrlw $3,%%mm0;" /* 0_0_0_b7 b6b5b4b3 0_0_0_b7 b6b5b4b3 */
+ "pxor %%mm4, %%mm4;" /* zero mm4 */
+
+ "movq %%mm0, %%mm5;" /* Copy B7-B0 */
+ "movq %%mm2, %%mm7;" /* Copy G7-G0 */
+
+ /* convert rgb24 plane to rgb16 pack for pixel 0-3 */
+ "punpcklbw %%mm4, %%mm2;" /* 0_0_0_0 0_0_0_0 g7g6g5g4 g3g2_0_0 */
+ "punpcklbw %%mm1, %%mm0;" /* r7r6r5r4 r3_0_0_0 0_0_0_b7 b6b5b4b3 */
+
+ "psllw $3, %%mm2;" /* 0_0_0_0 0_g7g6g5 g4g3g2_0 0_0_0_0 */
+ "por %%mm2, %%mm0;" /* r7r6r5r4 r3g7g6g5 g4g3g2b7 b6b5b4b3 */
+
+ "movq 8 (%5, %0, 2), %%mm6;" /* Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */
+ MOVNTQ " %%mm0, (%1);" /* store pixel 0-3 */
+
+ /* convert rgb24 plane to rgb16 pack for pixel 0-3 */
+ "punpckhbw %%mm4, %%mm7;" /* 0_0_0_0 0_0_0_0 g7g6g5g4 g3g2_0_0 */
+ "punpckhbw %%mm1, %%mm5;" /* r7r6r5r4 r3_0_0_0 0_0_0_b7 b6b5b4b3 */
+
+ "psllw $3, %%mm7;" /* 0_0_0_0 0_g7g6g5 g4g3g2_0 0_0_0_0 */
+ "movd 4 (%2, %0), %%mm0;" /* Load 4 Cb 00 00 00 00 u3 u2 u1 u0 */
+
+ "por %%mm7, %%mm5;" /* r7r6r5r4 r3g7g6g5 g4g3g2b7 b6b5b4b3 */
+ "movd 4 (%3, %0), %%mm1;" /* Load 4 Cr 00 00 00 00 v3 v2 v1 v0 */
+
+ MOVNTQ " %%mm5, 8 (%1);" /* store pixel 4-7 */
+
+ "add $16, %1 \n\t"
+ "add $4, %0 \n\t"
+ " js 1b \n\t"
+
+ : "+r" (index), "+r" (_image)
+ : "r" (_pu - index), "r" (_pv - index), "r"(&c->redDither), "r" (_py - 2*index)
+ );
+ }
+
+ __asm__ __volatile__ (EMMS);
+
+ return srcSliceH;
+}
+
+static inline int RENAME(yuv420_rgb15)(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+ int y, h_size;
+
+ if(c->srcFormat == PIX_FMT_YUV422P){
+ srcStride[1] *= 2;
+ srcStride[2] *= 2;
+ }
+
+ h_size= (c->dstW+7)&~7;
+ if(h_size*2 > dstStride[0]) h_size-=8;
+
+ __asm__ __volatile__ ("pxor %mm4, %mm4;" /* zero mm4 */ );
+//printf("%X %X %X %X %X %X %X %X %X %X\n", (int)&c->redDither, (int)&b5Dither, (int)src[0], (int)src[1], (int)src[2], (int)dst[0],
+//srcStride[0],srcStride[1],srcStride[2],dstStride[0]);
+ for (y= 0; y<srcSliceH; y++ ) {
+ uint8_t *_image = dst[0] + (y+srcSliceY)*dstStride[0];
+ uint8_t *_py = src[0] + y*srcStride[0];
+ uint8_t *_pu = src[1] + (y>>1)*srcStride[1];
+ uint8_t *_pv = src[2] + (y>>1)*srcStride[2];
+ long index= -h_size/2;
+
+ b5Dither= dither8[y&1];
+ g6Dither= dither4[y&1];
+ g5Dither= dither8[y&1];
+ r5Dither= dither8[(y+1)&1];
+ /* this mmx assembly code deals with SINGLE scan line at a time, it convert 8
+ pixels in each iteration */
+ __asm__ __volatile__ (
+ /* load data for start of next scan line */
+ "movd (%2, %0), %%mm0;" /* Load 4 Cb 00 00 00 00 u3 u2 u1 u0 */
+ "movd (%3, %0), %%mm1;" /* Load 4 Cr 00 00 00 00 v3 v2 v1 v0 */
+ "movq (%5, %0, 2), %%mm6;" /* Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */
+// ".balign 16 \n\t"
+ "1: \n\t"
+YUV2RGB
+
+#ifdef DITHER1XBPP
+ "paddusb "MANGLE(b5Dither)", %%mm0 \n\t"
+ "paddusb "MANGLE(g5Dither)", %%mm2 \n\t"
+ "paddusb "MANGLE(r5Dither)", %%mm1 \n\t"
+#endif
+
+ /* mask unneeded bits off */
+ "pand "MANGLE(mmx_redmask)", %%mm0;" /* b7b6b5b4 b3_0_0_0 b7b6b5b4 b3_0_0_0 */
+ "pand "MANGLE(mmx_redmask)", %%mm2;" /* g7g6g5g4 g3_0_0_0 g7g6g5g4 g3_0_0_0 */
+ "pand "MANGLE(mmx_redmask)", %%mm1;" /* r7r6r5r4 r3_0_0_0 r7r6r5r4 r3_0_0_0 */
+
+ "psrlw $3,%%mm0;" /* 0_0_0_b7 b6b5b4b3 0_0_0_b7 b6b5b4b3 */
+ "psrlw $1,%%mm1;" /* 0_r7r6r5 r4r3_0_0 0_r7r6r5 r4r3_0_0 */
+ "pxor %%mm4, %%mm4;" /* zero mm4 */
+
+ "movq %%mm0, %%mm5;" /* Copy B7-B0 */
+ "movq %%mm2, %%mm7;" /* Copy G7-G0 */
+
+ /* convert rgb24 plane to rgb16 pack for pixel 0-3 */
+ "punpcklbw %%mm4, %%mm2;" /* 0_0_0_0 0_0_0_0 g7g6g5g4 g3_0_0_0 */
+ "punpcklbw %%mm1, %%mm0;" /* r7r6r5r4 r3_0_0_0 0_0_0_b7 b6b5b4b3 */
+
+ "psllw $2, %%mm2;" /* 0_0_0_0 0_0_g7g6 g5g4g3_0 0_0_0_0 */
+ "por %%mm2, %%mm0;" /* 0_r7r6r5 r4r3g7g6 g5g4g3b7 b6b5b4b3 */
+
+ "movq 8 (%5, %0, 2), %%mm6;" /* Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */
+ MOVNTQ " %%mm0, (%1);" /* store pixel 0-3 */
+
+ /* convert rgb24 plane to rgb16 pack for pixel 0-3 */
+ "punpckhbw %%mm4, %%mm7;" /* 0_0_0_0 0_0_0_0 0_g7g6g5 g4g3_0_0 */
+ "punpckhbw %%mm1, %%mm5;" /* r7r6r5r4 r3_0_0_0 0_0_0_b7 b6b5b4b3 */
+
+ "psllw $2, %%mm7;" /* 0_0_0_0 0_0_g7g6 g5g4g3_0 0_0_0_0 */
+ "movd 4 (%2, %0), %%mm0;" /* Load 4 Cb 00 00 00 00 u3 u2 u1 u0 */
+
+ "por %%mm7, %%mm5;" /* 0_r7r6r5 r4r3g7g6 g5g4g3b7 b6b5b4b3 */
+ "movd 4 (%3, %0), %%mm1;" /* Load 4 Cr 00 00 00 00 v3 v2 v1 v0 */
+
+ MOVNTQ " %%mm5, 8 (%1);" /* store pixel 4-7 */
+
+ "add $16, %1 \n\t"
+ "add $4, %0 \n\t"
+ " js 1b \n\t"
+ : "+r" (index), "+r" (_image)
+ : "r" (_pu - index), "r" (_pv - index), "r"(&c->redDither), "r" (_py - 2*index)
+ );
+ }
+
+ __asm__ __volatile__ (EMMS);
+ return srcSliceH;
+}
+
+static inline int RENAME(yuv420_rgb24)(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+ int y, h_size;
+
+ if(c->srcFormat == PIX_FMT_YUV422P){
+ srcStride[1] *= 2;
+ srcStride[2] *= 2;
+ }
+
+ h_size= (c->dstW+7)&~7;
+ if(h_size*3 > dstStride[0]) h_size-=8;
+
+ __asm__ __volatile__ ("pxor %mm4, %mm4;" /* zero mm4 */ );
+
+ for (y= 0; y<srcSliceH; y++ ) {
+ uint8_t *_image = dst[0] + (y+srcSliceY)*dstStride[0];
+ uint8_t *_py = src[0] + y*srcStride[0];
+ uint8_t *_pu = src[1] + (y>>1)*srcStride[1];
+ uint8_t *_pv = src[2] + (y>>1)*srcStride[2];
+ long index= -h_size/2;
+
+ /* this mmx assembly code deals with SINGLE scan line at a time, it convert 8
+ pixels in each iteration */
+ __asm__ __volatile__ (
+ /* load data for start of next scan line */
+ "movd (%2, %0), %%mm0;" /* Load 4 Cb 00 00 00 00 u3 u2 u1 u0 */
+ "movd (%3, %0), %%mm1;" /* Load 4 Cr 00 00 00 00 v3 v2 v1 v0 */
+ "movq (%5, %0, 2), %%mm6;" /* Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */
+// ".balign 16 \n\t"
+ "1: \n\t"
+YUV2RGB
+ /* mm0=B, %%mm2=G, %%mm1=R */
+#ifdef HAVE_MMX2
+ "movq "MANGLE(M24A)", %%mm4 \n\t"
+ "movq "MANGLE(M24C)", %%mm7 \n\t"
+ "pshufw $0x50, %%mm0, %%mm5 \n\t" /* B3 B2 B3 B2 B1 B0 B1 B0 */
+ "pshufw $0x50, %%mm2, %%mm3 \n\t" /* G3 G2 G3 G2 G1 G0 G1 G0 */
+ "pshufw $0x00, %%mm1, %%mm6 \n\t" /* R1 R0 R1 R0 R1 R0 R1 R0 */
+
+ "pand %%mm4, %%mm5 \n\t" /* B2 B1 B0 */
+ "pand %%mm4, %%mm3 \n\t" /* G2 G1 G0 */
+ "pand %%mm7, %%mm6 \n\t" /* R1 R0 */
+
+ "psllq $8, %%mm3 \n\t" /* G2 G1 G0 */
+ "por %%mm5, %%mm6 \n\t"
+ "por %%mm3, %%mm6 \n\t"
+ MOVNTQ" %%mm6, (%1) \n\t"
+
+ "psrlq $8, %%mm2 \n\t" /* 00 G7 G6 G5 G4 G3 G2 G1 */
+ "pshufw $0xA5, %%mm0, %%mm5 \n\t" /* B5 B4 B5 B4 B3 B2 B3 B2 */
+ "pshufw $0x55, %%mm2, %%mm3 \n\t" /* G4 G3 G4 G3 G4 G3 G4 G3 */
+ "pshufw $0xA5, %%mm1, %%mm6 \n\t" /* R5 R4 R5 R4 R3 R2 R3 R2 */
+
+ "pand "MANGLE(M24B)", %%mm5 \n\t" /* B5 B4 B3 */
+ "pand %%mm7, %%mm3 \n\t" /* G4 G3 */
+ "pand %%mm4, %%mm6 \n\t" /* R4 R3 R2 */
+
+ "por %%mm5, %%mm3 \n\t" /* B5 G4 B4 G3 B3 */
+ "por %%mm3, %%mm6 \n\t"
+ MOVNTQ" %%mm6, 8(%1) \n\t"
+
+ "pshufw $0xFF, %%mm0, %%mm5 \n\t" /* B7 B6 B7 B6 B7 B6 B6 B7 */
+ "pshufw $0xFA, %%mm2, %%mm3 \n\t" /* 00 G7 00 G7 G6 G5 G6 G5 */
+ "pshufw $0xFA, %%mm1, %%mm6 \n\t" /* R7 R6 R7 R6 R5 R4 R5 R4 */
+ "movd 4 (%2, %0), %%mm0;" /* Load 4 Cb 00 00 00 00 u3 u2 u1 u0 */
+
+ "pand %%mm7, %%mm5 \n\t" /* B7 B6 */
+ "pand %%mm4, %%mm3 \n\t" /* G7 G6 G5 */
+ "pand "MANGLE(M24B)", %%mm6 \n\t" /* R7 R6 R5 */
+ "movd 4 (%3, %0), %%mm1;" /* Load 4 Cr 00 00 00 00 v3 v2 v1 v0 */
+\
+ "por %%mm5, %%mm3 \n\t"
+ "por %%mm3, %%mm6 \n\t"
+ MOVNTQ" %%mm6, 16(%1) \n\t"
+ "movq 8 (%5, %0, 2), %%mm6;" /* Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */
+ "pxor %%mm4, %%mm4 \n\t"
+
+#else
+
+ "pxor %%mm4, %%mm4 \n\t"
+ "movq %%mm0, %%mm5 \n\t" /* B */
+ "movq %%mm1, %%mm6 \n\t" /* R */
+ "punpcklbw %%mm2, %%mm0 \n\t" /* GBGBGBGB 0 */
+ "punpcklbw %%mm4, %%mm1 \n\t" /* 0R0R0R0R 0 */
+ "punpckhbw %%mm2, %%mm5 \n\t" /* GBGBGBGB 2 */
+ "punpckhbw %%mm4, %%mm6 \n\t" /* 0R0R0R0R 2 */
+ "movq %%mm0, %%mm7 \n\t" /* GBGBGBGB 0 */
+ "movq %%mm5, %%mm3 \n\t" /* GBGBGBGB 2 */
+ "punpcklwd %%mm1, %%mm7 \n\t" /* 0RGB0RGB 0 */
+ "punpckhwd %%mm1, %%mm0 \n\t" /* 0RGB0RGB 1 */
+ "punpcklwd %%mm6, %%mm5 \n\t" /* 0RGB0RGB 2 */
+ "punpckhwd %%mm6, %%mm3 \n\t" /* 0RGB0RGB 3 */
+
+ "movq %%mm7, %%mm2 \n\t" /* 0RGB0RGB 0 */
+ "movq %%mm0, %%mm6 \n\t" /* 0RGB0RGB 1 */
+ "movq %%mm5, %%mm1 \n\t" /* 0RGB0RGB 2 */
+ "movq %%mm3, %%mm4 \n\t" /* 0RGB0RGB 3 */
+
+ "psllq $40, %%mm7 \n\t" /* RGB00000 0 */
+ "psllq $40, %%mm0 \n\t" /* RGB00000 1 */
+ "psllq $40, %%mm5 \n\t" /* RGB00000 2 */
+ "psllq $40, %%mm3 \n\t" /* RGB00000 3 */
+
+ "punpckhdq %%mm2, %%mm7 \n\t" /* 0RGBRGB0 0 */
+ "punpckhdq %%mm6, %%mm0 \n\t" /* 0RGBRGB0 1 */
+ "punpckhdq %%mm1, %%mm5 \n\t" /* 0RGBRGB0 2 */
+ "punpckhdq %%mm4, %%mm3 \n\t" /* 0RGBRGB0 3 */
+
+ "psrlq $8, %%mm7 \n\t" /* 00RGBRGB 0 */
+ "movq %%mm0, %%mm6 \n\t" /* 0RGBRGB0 1 */
+ "psllq $40, %%mm0 \n\t" /* GB000000 1 */
+ "por %%mm0, %%mm7 \n\t" /* GBRGBRGB 0 */
+ MOVNTQ" %%mm7, (%1) \n\t"
+
+ "movd 4 (%2, %0), %%mm0;" /* Load 4 Cb 00 00 00 00 u3 u2 u1 u0 */
+
+ "psrlq $24, %%mm6 \n\t" /* 0000RGBR 1 */
+ "movq %%mm5, %%mm1 \n\t" /* 0RGBRGB0 2 */
+ "psllq $24, %%mm5 \n\t" /* BRGB0000 2 */
+ "por %%mm5, %%mm6 \n\t" /* BRGBRGBR 1 */
+ MOVNTQ" %%mm6, 8(%1) \n\t"
+
+ "movq 8 (%5, %0, 2), %%mm6;" /* Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */
+
+ "psrlq $40, %%mm1 \n\t" /* 000000RG 2 */
+ "psllq $8, %%mm3 \n\t" /* RGBRGB00 3 */
+ "por %%mm3, %%mm1 \n\t" /* RGBRGBRG 2 */
+ MOVNTQ" %%mm1, 16(%1) \n\t"
+
+ "movd 4 (%3, %0), %%mm1;" /* Load 4 Cr 00 00 00 00 v3 v2 v1 v0 */
+ "pxor %%mm4, %%mm4 \n\t"
+#endif
+
+ "add $24, %1 \n\t"
+ "add $4, %0 \n\t"
+ " js 1b \n\t"
+
+ : "+r" (index), "+r" (_image)
+ : "r" (_pu - index), "r" (_pv - index), "r"(&c->redDither), "r" (_py - 2*index)
+ );
+ }
+
+ __asm__ __volatile__ (EMMS);
+ return srcSliceH;
+}
+
+static inline int RENAME(yuv420_rgb32)(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+ int y, h_size;
+
+ if(c->srcFormat == PIX_FMT_YUV422P){
+ srcStride[1] *= 2;
+ srcStride[2] *= 2;
+ }
+
+ h_size= (c->dstW+7)&~7;
+ if(h_size*4 > dstStride[0]) h_size-=8;
+
+ __asm__ __volatile__ ("pxor %mm4, %mm4;" /* zero mm4 */ );
+
+ for (y= 0; y<srcSliceH; y++ ) {
+ uint8_t *_image = dst[0] + (y+srcSliceY)*dstStride[0];
+ uint8_t *_py = src[0] + y*srcStride[0];
+ uint8_t *_pu = src[1] + (y>>1)*srcStride[1];
+ uint8_t *_pv = src[2] + (y>>1)*srcStride[2];
+ long index= -h_size/2;
+
+ /* this mmx assembly code deals with SINGLE scan line at a time, it convert 8
+ pixels in each iteration */
+ __asm__ __volatile__ (
+ /* load data for start of next scan line */
+ "movd (%2, %0), %%mm0;" /* Load 4 Cb 00 00 00 00 u3 u2 u1 u0 */
+ "movd (%3, %0), %%mm1;" /* Load 4 Cr 00 00 00 00 v3 v2 v1 v0 */
+ "movq (%5, %0, 2), %%mm6;" /* Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */
+// ".balign 16 \n\t"
+ "1: \n\t"
+YUV2RGB
+ /* convert RGB plane to RGB packed format,
+ mm0 -> B, mm1 -> R, mm2 -> G, mm3 -> 0,
+ mm4 -> GB, mm5 -> AR pixel 4-7,
+ mm6 -> GB, mm7 -> AR pixel 0-3 */
+ "pxor %%mm3, %%mm3;" /* zero mm3 */
+
+ "movq %%mm0, %%mm6;" /* B7 B6 B5 B4 B3 B2 B1 B0 */
+ "movq %%mm1, %%mm7;" /* R7 R6 R5 R4 R3 R2 R1 R0 */
+
+ "movq %%mm0, %%mm4;" /* B7 B6 B5 B4 B3 B2 B1 B0 */
+ "movq %%mm1, %%mm5;" /* R7 R6 R5 R4 R3 R2 R1 R0 */
+
+ "punpcklbw %%mm2, %%mm6;" /* G3 B3 G2 B2 G1 B1 G0 B0 */
+ "punpcklbw %%mm3, %%mm7;" /* 00 R3 00 R2 00 R1 00 R0 */
+
+ "punpcklwd %%mm7, %%mm6;" /* 00 R1 B1 G1 00 R0 B0 G0 */
+ MOVNTQ " %%mm6, (%1);" /* Store ARGB1 ARGB0 */
+
+ "movq %%mm0, %%mm6;" /* B7 B6 B5 B4 B3 B2 B1 B0 */
+ "punpcklbw %%mm2, %%mm6;" /* G3 B3 G2 B2 G1 B1 G0 B0 */
+
+ "punpckhwd %%mm7, %%mm6;" /* 00 R3 G3 B3 00 R2 B3 G2 */
+ MOVNTQ " %%mm6, 8 (%1);" /* Store ARGB3 ARGB2 */
+
+ "punpckhbw %%mm2, %%mm4;" /* G7 B7 G6 B6 G5 B5 G4 B4 */
+ "punpckhbw %%mm3, %%mm5;" /* 00 R7 00 R6 00 R5 00 R4 */
+
+ "punpcklwd %%mm5, %%mm4;" /* 00 R5 B5 G5 00 R4 B4 G4 */
+ MOVNTQ " %%mm4, 16 (%1);" /* Store ARGB5 ARGB4 */
+
+ "movq %%mm0, %%mm4;" /* B7 B6 B5 B4 B3 B2 B1 B0 */
+ "punpckhbw %%mm2, %%mm4;" /* G7 B7 G6 B6 G5 B5 G4 B4 */
+
+ "punpckhwd %%mm5, %%mm4;" /* 00 R7 G7 B7 00 R6 B6 G6 */
+ MOVNTQ " %%mm4, 24 (%1);" /* Store ARGB7 ARGB6 */
+
+ "movd 4 (%2, %0), %%mm0;" /* Load 4 Cb 00 00 00 00 u3 u2 u1 u0 */
+ "movd 4 (%3, %0), %%mm1;" /* Load 4 Cr 00 00 00 00 v3 v2 v1 v0 */
+
+ "pxor %%mm4, %%mm4;" /* zero mm4 */
+ "movq 8 (%5, %0, 2), %%mm6;" /* Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */
+
+ "add $32, %1 \n\t"
+ "add $4, %0 \n\t"
+ " js 1b \n\t"
+
+ : "+r" (index), "+r" (_image)
+ : "r" (_pu - index), "r" (_pv - index), "r"(&c->redDither), "r" (_py - 2*index)
+ );
+ }
+
+ __asm__ __volatile__ (EMMS);
+ return srcSliceH;
+}
diff --git a/contrib/ffmpeg/makefile.xine.in b/contrib/ffmpeg/makefile.xine.in
new file mode 100644
index 000000000..3515c2aaa
--- /dev/null
+++ b/contrib/ffmpeg/makefile.xine.in
@@ -0,0 +1,30 @@
+srcdir = @srcdir@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+
+config.mak: $(srcdir)/configure makefile.xine
+ $(srcdir)/configure \
+ --disable-shared --enable-static \
+ --disable-encoders \
+ --disable-demuxers \
+ --disable-muxers \
+ --disable-strip \
+ --make="$(MAKE)" \
+ --cc="$(CC)" \
+ --extra-cflags="$(CFLAGS) -fPIC -DPIC" \
+ --extra-ldflags="$(LDFLAGS)" \
+ --enable-gpl \
+ --enable-pthreads \
+ --disable-ffmpeg \
+ --disable-ffserver \
+ --disable-ffplay
+
+libavutil/libavutil.a: config.mak
+ $(MAKE) -C libavutil libavutil.a
+
+libavcodec/libavcodec.a: config.mak
+ $(MAKE) -C libavcodec libavcodec.a
+
+libpostproc/libpostproc.a: config.mak
+ $(MAKE) -C libpostproc libpostproc.a
diff --git a/contrib/ffmpeg/output_example.c b/contrib/ffmpeg/output_example.c
new file mode 100644
index 000000000..7f75b76f2
--- /dev/null
+++ b/contrib/ffmpeg/output_example.c
@@ -0,0 +1,546 @@
+/*
+ * Libavformat API example: Output a media file in any supported
+ * libavformat format. The default codecs are used.
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#ifndef M_PI
+#define M_PI 3.1415926535897931
+#endif
+
+#include "avformat.h"
+#include "swscale.h"
+
+/* 5 seconds stream duration */
+#define STREAM_DURATION 5.0
+#define STREAM_FRAME_RATE 25 /* 25 images/s */
+#define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
+#define STREAM_PIX_FMT PIX_FMT_YUV420P /* default pix_fmt */
+
+static int sws_flags = SWS_BICUBIC;
+
+/**************************************************************/
+/* audio output */
+
+float t, tincr, tincr2;
+int16_t *samples;
+uint8_t *audio_outbuf;
+int audio_outbuf_size;
+int audio_input_frame_size;
+
+/*
+ * add an audio output stream
+ */
+static AVStream *add_audio_stream(AVFormatContext *oc, int codec_id)
+{
+ AVCodecContext *c;
+ AVStream *st;
+
+ st = av_new_stream(oc, 1);
+ if (!st) {
+ fprintf(stderr, "Could not alloc stream\n");
+ exit(1);
+ }
+
+ c = st->codec;
+ c->codec_id = codec_id;
+ c->codec_type = CODEC_TYPE_AUDIO;
+
+ /* put sample parameters */
+ c->bit_rate = 64000;
+ c->sample_rate = 44100;
+ c->channels = 2;
+ return st;
+}
+
+static void open_audio(AVFormatContext *oc, AVStream *st)
+{
+ AVCodecContext *c;
+ AVCodec *codec;
+
+ c = st->codec;
+
+ /* find the audio encoder */
+ codec = avcodec_find_encoder(c->codec_id);
+ if (!codec) {
+ fprintf(stderr, "codec not found\n");
+ exit(1);
+ }
+
+ /* open it */
+ if (avcodec_open(c, codec) < 0) {
+ fprintf(stderr, "could not open codec\n");
+ exit(1);
+ }
+
+ /* init signal generator */
+ t = 0;
+ tincr = 2 * M_PI * 110.0 / c->sample_rate;
+ /* increment frequency by 110 Hz per second */
+ tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;
+
+ audio_outbuf_size = 10000;
+ audio_outbuf = av_malloc(audio_outbuf_size);
+
+ /* ugly hack for PCM codecs (will be removed ASAP with new PCM
+ support to compute the input frame size in samples */
+ if (c->frame_size <= 1) {
+ audio_input_frame_size = audio_outbuf_size / c->channels;
+ switch(st->codec->codec_id) {
+ case CODEC_ID_PCM_S16LE:
+ case CODEC_ID_PCM_S16BE:
+ case CODEC_ID_PCM_U16LE:
+ case CODEC_ID_PCM_U16BE:
+ audio_input_frame_size >>= 1;
+ break;
+ default:
+ break;
+ }
+ } else {
+ audio_input_frame_size = c->frame_size;
+ }
+ samples = av_malloc(audio_input_frame_size * 2 * c->channels);
+}
+
+/* prepare a 16 bit dummy audio frame of 'frame_size' samples and
+ 'nb_channels' channels */
+static void get_audio_frame(int16_t *samples, int frame_size, int nb_channels)
+{
+ int j, i, v;
+ int16_t *q;
+
+ q = samples;
+ for(j=0;j<frame_size;j++) {
+ v = (int)(sin(t) * 10000);
+ for(i = 0; i < nb_channels; i++)
+ *q++ = v;
+ t += tincr;
+ tincr += tincr2;
+ }
+}
+
+static void write_audio_frame(AVFormatContext *oc, AVStream *st)
+{
+ AVCodecContext *c;
+ AVPacket pkt;
+ av_init_packet(&pkt);
+
+ c = st->codec;
+
+ get_audio_frame(samples, audio_input_frame_size, c->channels);
+
+ pkt.size= avcodec_encode_audio(c, audio_outbuf, audio_outbuf_size, samples);
+
+ pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
+ pkt.flags |= PKT_FLAG_KEY;
+ pkt.stream_index= st->index;
+ pkt.data= audio_outbuf;
+
+ /* write the compressed frame in the media file */
+ if (av_write_frame(oc, &pkt) != 0) {
+ fprintf(stderr, "Error while writing audio frame\n");
+ exit(1);
+ }
+}
+
+static void close_audio(AVFormatContext *oc, AVStream *st)
+{
+ avcodec_close(st->codec);
+
+ av_free(samples);
+ av_free(audio_outbuf);
+}
+
+/**************************************************************/
+/* video output */
+
+AVFrame *picture, *tmp_picture;
+uint8_t *video_outbuf;
+int frame_count, video_outbuf_size;
+
+/* add a video output stream */
+static AVStream *add_video_stream(AVFormatContext *oc, int codec_id)
+{
+ AVCodecContext *c;
+ AVStream *st;
+
+ st = av_new_stream(oc, 0);
+ if (!st) {
+ fprintf(stderr, "Could not alloc stream\n");
+ exit(1);
+ }
+
+ c = st->codec;
+ c->codec_id = codec_id;
+ c->codec_type = CODEC_TYPE_VIDEO;
+
+ /* put sample parameters */
+ c->bit_rate = 400000;
+ /* resolution must be a multiple of two */
+ c->width = 352;
+ c->height = 288;
+ /* time base: 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. */
+ c->time_base.den = STREAM_FRAME_RATE;
+ c->time_base.num = 1;
+ c->gop_size = 12; /* emit one intra frame every twelve frames at most */
+ c->pix_fmt = STREAM_PIX_FMT;
+ if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
+ /* just for testing, we also add B frames */
+ c->max_b_frames = 2;
+ }
+ if (c->codec_id == CODEC_ID_MPEG1VIDEO){
+ /* needed to avoid using macroblocks in which some coeffs overflow
+ this doesnt happen with normal video, it just happens here as the
+ motion of the chroma plane doesnt match the luma plane */
+ c->mb_decision=2;
+ }
+ // some formats want stream headers to be seperate
+ if(!strcmp(oc->oformat->name, "mp4") || !strcmp(oc->oformat->name, "mov") || !strcmp(oc->oformat->name, "3gp"))
+ c->flags |= CODEC_FLAG_GLOBAL_HEADER;
+
+ return st;
+}
+
+static AVFrame *alloc_picture(int pix_fmt, int width, int height)
+{
+ AVFrame *picture;
+ uint8_t *picture_buf;
+ int size;
+
+ picture = avcodec_alloc_frame();
+ if (!picture)
+ return NULL;
+ size = avpicture_get_size(pix_fmt, width, height);
+ picture_buf = av_malloc(size);
+ if (!picture_buf) {
+ av_free(picture);
+ return NULL;
+ }
+ avpicture_fill((AVPicture *)picture, picture_buf,
+ pix_fmt, width, height);
+ return picture;
+}
+
+static void open_video(AVFormatContext *oc, AVStream *st)
+{
+ AVCodec *codec;
+ AVCodecContext *c;
+
+ c = st->codec;
+
+ /* find the video encoder */
+ codec = avcodec_find_encoder(c->codec_id);
+ if (!codec) {
+ fprintf(stderr, "codec not found\n");
+ exit(1);
+ }
+
+ /* open the codec */
+ if (avcodec_open(c, codec) < 0) {
+ fprintf(stderr, "could not open codec\n");
+ exit(1);
+ }
+
+ video_outbuf = NULL;
+ if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
+ /* allocate output buffer */
+ /* XXX: API change will be done */
+ /* buffers passed into lav* can be allocated any way you prefer,
+ as long as they're aligned enough for the architecture, and
+ they're freed appropriately (such as using av_free for buffers
+ allocated with av_malloc) */
+ video_outbuf_size = 200000;
+ video_outbuf = av_malloc(video_outbuf_size);
+ }
+
+ /* allocate the encoded raw picture */
+ picture = alloc_picture(c->pix_fmt, c->width, c->height);
+ if (!picture) {
+ fprintf(stderr, "Could not allocate picture\n");
+ exit(1);
+ }
+
+ /* if the output format is not YUV420P, then a temporary YUV420P
+ picture is needed too. It is then converted to the required
+ output format */
+ tmp_picture = NULL;
+ if (c->pix_fmt != PIX_FMT_YUV420P) {
+ tmp_picture = alloc_picture(PIX_FMT_YUV420P, c->width, c->height);
+ if (!tmp_picture) {
+ fprintf(stderr, "Could not allocate temporary picture\n");
+ exit(1);
+ }
+ }
+}
+
+/* prepare a dummy image */
+static void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height)
+{
+ int x, y, i;
+
+ i = frame_index;
+
+ /* Y */
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;
+ }
+ }
+
+ /* Cb and Cr */
+ for(y=0;y<height/2;y++) {
+ for(x=0;x<width/2;x++) {
+ pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
+ pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
+ }
+ }
+}
+
+static void write_video_frame(AVFormatContext *oc, AVStream *st)
+{
+ int out_size, ret;
+ AVCodecContext *c;
+ static struct SwsContext *img_convert_ctx;
+
+ c = st->codec;
+
+ if (frame_count >= STREAM_NB_FRAMES) {
+ /* no more frame to compress. The codec has a latency of a few
+ frames if using B frames, so we get the last frames by
+ passing the same picture again */
+ } else {
+ if (c->pix_fmt != PIX_FMT_YUV420P) {
+ /* as we only generate a YUV420P picture, we must convert it
+ to the codec pixel format if needed */
+ if (img_convert_ctx == NULL) {
+ img_convert_ctx = sws_getContext(c->width, c->height,
+ PIX_FMT_YUV420P,
+ c->width, c->height,
+ c->pix_fmt,
+ sws_flags, NULL, NULL, NULL);
+ if (img_convert_ctx == NULL) {
+ fprintf(stderr, "Cannot initialize the conversion context\n");
+ exit(1);
+ }
+ }
+ fill_yuv_image(tmp_picture, frame_count, c->width, c->height);
+ sws_scale(img_convert_ctx, tmp_picture->data, tmp_picture->linesize,
+ 0, c->height, picture->data, picture->linesize);
+ } else {
+ fill_yuv_image(picture, frame_count, c->width, c->height);
+ }
+ }
+
+
+ if (oc->oformat->flags & AVFMT_RAWPICTURE) {
+ /* raw video case. The API will change slightly in the near
+ futur for that */
+ AVPacket pkt;
+ av_init_packet(&pkt);
+
+ pkt.flags |= PKT_FLAG_KEY;
+ pkt.stream_index= st->index;
+ pkt.data= (uint8_t *)picture;
+ pkt.size= sizeof(AVPicture);
+
+ ret = av_write_frame(oc, &pkt);
+ } else {
+ /* encode the image */
+ out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture);
+ /* if zero size, it means the image was buffered */
+ if (out_size > 0) {
+ AVPacket pkt;
+ av_init_packet(&pkt);
+
+ pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
+ if(c->coded_frame->key_frame)
+ pkt.flags |= PKT_FLAG_KEY;
+ pkt.stream_index= st->index;
+ pkt.data= video_outbuf;
+ pkt.size= out_size;
+
+ /* write the compressed frame in the media file */
+ ret = av_write_frame(oc, &pkt);
+ } else {
+ ret = 0;
+ }
+ }
+ if (ret != 0) {
+ fprintf(stderr, "Error while writing video frame\n");
+ exit(1);
+ }
+ frame_count++;
+}
+
+static void close_video(AVFormatContext *oc, AVStream *st)
+{
+ avcodec_close(st->codec);
+ av_free(picture->data[0]);
+ av_free(picture);
+ if (tmp_picture) {
+ av_free(tmp_picture->data[0]);
+ av_free(tmp_picture);
+ }
+ av_free(video_outbuf);
+}
+
+/**************************************************************/
+/* media file output */
+
+int main(int argc, char **argv)
+{
+ const char *filename;
+ AVOutputFormat *fmt;
+ AVFormatContext *oc;
+ AVStream *audio_st, *video_st;
+ double audio_pts, video_pts;
+ int i;
+
+ /* initialize libavcodec, and register all codecs and formats */
+ av_register_all();
+
+ if (argc != 2) {
+ printf("usage: %s output_file\n"
+ "API example program to output a media file with libavformat.\n"
+ "The output format is automatically guessed according to the file extension.\n"
+ "Raw images can also be output by using '%%d' in the filename\n"
+ "\n", argv[0]);
+ exit(1);
+ }
+
+ filename = argv[1];
+
+ /* auto detect the output format from the name. default is
+ mpeg. */
+ fmt = guess_format(NULL, filename, NULL);
+ if (!fmt) {
+ printf("Could not deduce output format from file extension: using MPEG.\n");
+ fmt = guess_format("mpeg", NULL, NULL);
+ }
+ if (!fmt) {
+ fprintf(stderr, "Could not find suitable output format\n");
+ exit(1);
+ }
+
+ /* allocate the output media context */
+ oc = av_alloc_format_context();
+ if (!oc) {
+ fprintf(stderr, "Memory error\n");
+ exit(1);
+ }
+ oc->oformat = fmt;
+ snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
+
+ /* add the audio and video streams using the default format codecs
+ and initialize the codecs */
+ video_st = NULL;
+ audio_st = NULL;
+ if (fmt->video_codec != CODEC_ID_NONE) {
+ video_st = add_video_stream(oc, fmt->video_codec);
+ }
+ if (fmt->audio_codec != CODEC_ID_NONE) {
+ audio_st = add_audio_stream(oc, fmt->audio_codec);
+ }
+
+ /* set the output parameters (must be done even if no
+ parameters). */
+ if (av_set_parameters(oc, NULL) < 0) {
+ fprintf(stderr, "Invalid output format parameters\n");
+ exit(1);
+ }
+
+ dump_format(oc, 0, filename, 1);
+
+ /* now that all the parameters are set, we can open the audio and
+ video codecs and allocate the necessary encode buffers */
+ if (video_st)
+ open_video(oc, video_st);
+ if (audio_st)
+ open_audio(oc, audio_st);
+
+ /* open the output file, if needed */
+ if (!(fmt->flags & AVFMT_NOFILE)) {
+ if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {
+ fprintf(stderr, "Could not open '%s'\n", filename);
+ exit(1);
+ }
+ }
+
+ /* write the stream header, if any */
+ av_write_header(oc);
+
+ for(;;) {
+ /* compute current audio and video time */
+ if (audio_st)
+ audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
+ else
+ audio_pts = 0.0;
+
+ if (video_st)
+ video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den;
+ else
+ video_pts = 0.0;
+
+ if ((!audio_st || audio_pts >= STREAM_DURATION) &&
+ (!video_st || video_pts >= STREAM_DURATION))
+ break;
+
+ /* write interleaved audio and video frames */
+ if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
+ write_audio_frame(oc, audio_st);
+ } else {
+ write_video_frame(oc, video_st);
+ }
+ }
+
+ /* close each codec */
+ if (video_st)
+ close_video(oc, video_st);
+ if (audio_st)
+ close_audio(oc, audio_st);
+
+ /* write the trailer, if any */
+ av_write_trailer(oc);
+
+ /* free the streams */
+ for(i = 0; i < oc->nb_streams; i++) {
+ av_freep(&oc->streams[i]->codec);
+ av_freep(&oc->streams[i]);
+ }
+
+ if (!(fmt->flags & AVFMT_NOFILE)) {
+ /* close the output file */
+ url_fclose(&oc->pb);
+ }
+
+ /* free the stream */
+ av_free(oc);
+
+ return 0;
+}
diff --git a/contrib/ffmpeg/pktdumper.c b/contrib/ffmpeg/pktdumper.c
new file mode 100644
index 000000000..3535fd03f
--- /dev/null
+++ b/contrib/ffmpeg/pktdumper.c
@@ -0,0 +1,97 @@
+#include <avformat.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define PKTFILESUFF "_%08"PRId64"_%02d_%010"PRId64"_%06d_%c.bin"
+
+static int usage(int ret)
+{
+ fprintf(stderr, "dump (up to maxpkts) AVPackets as they are demuxed by libavformat.\n");
+ fprintf(stderr, "each packet is dumped in its own file named like `basename file.ext`_$PKTNUM_$STREAMINDEX_$STAMP_$SIZE_$FLAGS.bin\n");
+ fprintf(stderr, "pktdumper [-nw] file [maxpkts]\n");
+ fprintf(stderr, "-n\twrite No file at all, only demux.\n");
+ fprintf(stderr, "-w\tWait at end of processing instead of quitting.\n");
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ char fntemplate[PATH_MAX];
+ char pktfilename[PATH_MAX];
+ AVFormatContext *fctx;
+ AVPacket pkt;
+ int64_t pktnum = 0;
+ int64_t maxpkts = 0;
+ int dontquit = 0;
+ int nowrite = 0;
+ int err;
+
+ if ((argc > 1) && !strncmp(argv[1], "-", 1)) {
+ if (strchr(argv[1], 'w'))
+ dontquit = 1;
+ if (strchr(argv[1], 'n'))
+ nowrite = 1;
+ argv++;
+ argc--;
+ }
+ if (argc < 2)
+ return usage(1);
+ if (argc > 2)
+ maxpkts = atoi(argv[2]);
+ strncpy(fntemplate, argv[1], PATH_MAX-1);
+ if (strrchr(argv[1], '/'))
+ strncpy(fntemplate, strrchr(argv[1], '/')+1, PATH_MAX-1);
+ if (strrchr(fntemplate, '.'))
+ *strrchr(fntemplate, '.') = '\0';
+ if (strchr(fntemplate, '%')) {
+ fprintf(stderr, "can't use filenames containing '%%'\n");
+ return usage(1);
+ }
+ if (strlen(fntemplate) + sizeof(PKTFILESUFF) >= PATH_MAX-1) {
+ fprintf(stderr, "filename too long\n");
+ return usage(1);
+ }
+ strcat(fntemplate, PKTFILESUFF);
+ printf("FNTEMPLATE: '%s'\n", fntemplate);
+
+ // register all file formats
+ av_register_all();
+
+ err = av_open_input_file(&fctx, argv[1], NULL, 0, NULL);
+ if (err < 0) {
+ fprintf(stderr, "av_open_input_file: error %d\n", err);
+ return 1;
+ }
+
+ err = av_find_stream_info(fctx);
+ if (err < 0) {
+ fprintf(stderr, "av_find_stream_info: error %d\n", err);
+ return 1;
+ }
+
+ av_init_packet(&pkt);
+
+ while ((err = av_read_frame(fctx, &pkt)) >= 0) {
+ int fd;
+ snprintf(pktfilename, PATH_MAX-1, fntemplate, pktnum, pkt.stream_index, pkt.pts, pkt.size, (pkt.flags & PKT_FLAG_KEY)?'K':'_');
+ printf(PKTFILESUFF"\n", pktnum, pkt.stream_index, pkt.pts, pkt.size, (pkt.flags & PKT_FLAG_KEY)?'K':'_');
+ //printf("open(\"%s\")\n", pktfilename);
+ if (!nowrite) {
+ fd = open(pktfilename, O_WRONLY|O_CREAT, 0644);
+ write(fd, pkt.data, pkt.size);
+ close(fd);
+ }
+ pktnum++;
+ if (maxpkts && (pktnum >= maxpkts))
+ break;
+ }
+
+ while (dontquit)
+ sleep(60);
+
+ return 0;
+}
diff --git a/contrib/ffmpeg/qt-faststart.c b/contrib/ffmpeg/qt-faststart.c
new file mode 100644
index 000000000..f9de43514
--- /dev/null
+++ b/contrib/ffmpeg/qt-faststart.c
@@ -0,0 +1,311 @@
+/*
+ * qt-faststart.c, v0.1
+ * by Mike Melanson (melanson@pcisys.net)
+ * This file is placed in the public domain. Use the program however you
+ * see fit.
+ *
+ * This utility rearranges a Quicktime file such that the moov atom
+ * is in front of the data, thus facilitating network streaming.
+ *
+ * Compile this program using:
+ * cc qt-faststart.c -o qt-faststart
+ * Invoke the program with:
+ * qt-faststart <infile.mov> <outfile.mov>
+ *
+ * Notes: Quicktime files can come in many configurations of top-level
+ * atoms. This utility stipulates that the very last atom in the file needs
+ * to be a moov atom. When given such a file, this utility will rearrange
+ * the top-level atoms by shifting the moov atom from the back of the file
+ * to the front, and patch the chunk offsets along the way. This utility
+ * presently only operates on uncompressed moov atoms.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#ifdef __MINGW32__
+#define fseeko(x,y,z) fseeko64(x,y,z)
+#define ftello(x) ftello64(x)
+#endif
+
+#define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
+#define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \
+ (((uint8_t*)(x))[1] << 16) | \
+ (((uint8_t*)(x))[2] << 8) | \
+ ((uint8_t*)(x))[3])
+#define BE_64(x) (((uint64_t)(((uint8_t*)(x))[0]) << 56) | \
+ ((uint64_t)(((uint8_t*)(x))[1]) << 48) | \
+ ((uint64_t)(((uint8_t*)(x))[2]) << 40) | \
+ ((uint64_t)(((uint8_t*)(x))[3]) << 32) | \
+ ((uint64_t)(((uint8_t*)(x))[4]) << 24) | \
+ ((uint64_t)(((uint8_t*)(x))[5]) << 16) | \
+ ((uint64_t)(((uint8_t*)(x))[6]) << 8) | \
+ ((uint64_t)((uint8_t*)(x))[7]))
+
+#define BE_FOURCC( ch0, ch1, ch2, ch3 ) \
+ ( (uint32_t)(unsigned char)(ch3) | \
+ ( (uint32_t)(unsigned char)(ch2) << 8 ) | \
+ ( (uint32_t)(unsigned char)(ch1) << 16 ) | \
+ ( (uint32_t)(unsigned char)(ch0) << 24 ) )
+
+#define QT_ATOM BE_FOURCC
+/* top level atoms */
+#define FREE_ATOM QT_ATOM('f', 'r', 'e', 'e')
+#define JUNK_ATOM QT_ATOM('j', 'u', 'n', 'k')
+#define MDAT_ATOM QT_ATOM('m', 'd', 'a', 't')
+#define MOOV_ATOM QT_ATOM('m', 'o', 'o', 'v')
+#define PNOT_ATOM QT_ATOM('p', 'n', 'o', 't')
+#define SKIP_ATOM QT_ATOM('s', 'k', 'i', 'p')
+#define WIDE_ATOM QT_ATOM('w', 'i', 'd', 'e')
+#define PICT_ATOM QT_ATOM('P', 'I', 'C', 'T')
+#define FTYP_ATOM QT_ATOM('f', 't', 'y', 'p')
+
+#define CMOV_ATOM QT_ATOM('c', 'm', 'o', 'v')
+#define STCO_ATOM QT_ATOM('s', 't', 'c', 'o')
+#define CO64_ATOM QT_ATOM('c', 'o', '6', '4')
+
+#define ATOM_PREAMBLE_SIZE 8
+#define COPY_BUFFER_SIZE 1024
+
+int main(int argc, char *argv[])
+{
+ FILE *infile;
+ FILE *outfile;
+ unsigned char atom_bytes[ATOM_PREAMBLE_SIZE];
+ uint32_t atom_type = 0;
+ uint64_t atom_size = 0;
+ uint64_t last_offset;
+ unsigned char *moov_atom;
+ unsigned char *ftyp_atom = 0;
+ uint64_t moov_atom_size;
+ uint64_t ftyp_atom_size = 0;
+ uint64_t i, j;
+ uint32_t offset_count;
+ uint64_t current_offset;
+ uint64_t start_offset = 0;
+ unsigned char copy_buffer[COPY_BUFFER_SIZE];
+ int bytes_to_copy;
+
+ if (argc != 3) {
+ printf ("Usage: qt-faststart <infile.mov> <outfile.mov>\n");
+ return 0;
+ }
+
+ infile = fopen(argv[1], "rb");
+ if (!infile) {
+ perror(argv[1]);
+ return 1;
+ }
+
+ /* traverse through the atoms in the file to make sure that 'moov' is
+ * at the end */
+ while (!feof(infile)) {
+ if (fread(atom_bytes, ATOM_PREAMBLE_SIZE, 1, infile) != 1) {
+ break;
+ }
+ atom_size = (uint32_t)BE_32(&atom_bytes[0]);
+ atom_type = BE_32(&atom_bytes[4]);
+
+ if ((atom_type != FREE_ATOM) &&
+ (atom_type != JUNK_ATOM) &&
+ (atom_type != MDAT_ATOM) &&
+ (atom_type != MOOV_ATOM) &&
+ (atom_type != PNOT_ATOM) &&
+ (atom_type != SKIP_ATOM) &&
+ (atom_type != WIDE_ATOM) &&
+ (atom_type != PICT_ATOM) &&
+ (atom_type != FTYP_ATOM)) {
+ printf ("encountered non-QT top-level atom (is this a Quicktime file?)\n");
+ break;
+ }
+
+ /* keep ftyp atom */
+ if (atom_type == FTYP_ATOM) {
+ ftyp_atom_size = atom_size;
+ ftyp_atom = malloc(ftyp_atom_size);
+ if (!ftyp_atom) {
+ printf ("could not allocate 0x%llX byte for ftyp atom\n",
+ atom_size);
+ fclose(infile);
+ return 1;
+ }
+ fseeko(infile, -ATOM_PREAMBLE_SIZE, SEEK_CUR);
+ if (fread(ftyp_atom, atom_size, 1, infile) != 1) {
+ perror(argv[1]);
+ free(ftyp_atom);
+ fclose(infile);
+ return 1;
+ }
+ start_offset = ftello(infile);
+ continue;
+ }
+
+ /* 64-bit special case */
+ if (atom_size == 1) {
+ if (fread(atom_bytes, ATOM_PREAMBLE_SIZE, 1, infile) != 1) {
+ break;
+ }
+ atom_size = BE_64(&atom_bytes[0]);
+ fseeko(infile, atom_size - ATOM_PREAMBLE_SIZE * 2, SEEK_CUR);
+ } else {
+ fseeko(infile, atom_size - ATOM_PREAMBLE_SIZE, SEEK_CUR);
+ }
+ }
+
+ if (atom_type != MOOV_ATOM) {
+ printf ("last atom in file was not a moov atom\n");
+ fclose(infile);
+ return 0;
+ }
+
+ /* moov atom was, in fact, the last atom in the chunk; load the whole
+ * moov atom */
+ fseeko(infile, -atom_size, SEEK_END);
+ last_offset = ftello(infile);
+ moov_atom_size = atom_size;
+ moov_atom = malloc(moov_atom_size);
+ if (!moov_atom) {
+ printf ("could not allocate 0x%llX byte for moov atom\n",
+ atom_size);
+ fclose(infile);
+ return 1;
+ }
+ if (fread(moov_atom, atom_size, 1, infile) != 1) {
+ perror(argv[1]);
+ free(moov_atom);
+ fclose(infile);
+ return 1;
+ }
+
+ /* this utility does not support compressed atoms yet, so disqualify
+ * files with compressed QT atoms */
+ if (BE_32(&moov_atom[12]) == CMOV_ATOM) {
+ printf ("this utility does not support compressed moov atoms yet\n");
+ free(moov_atom);
+ fclose(infile);
+ return 1;
+ }
+
+ /* close; will be re-opened later */
+ fclose(infile);
+
+ /* crawl through the moov chunk in search of stco or co64 atoms */
+ for (i = 4; i < moov_atom_size - 4; i++) {
+ atom_type = BE_32(&moov_atom[i]);
+ if (atom_type == STCO_ATOM) {
+ printf (" patching stco atom...\n");
+ atom_size = BE_32(&moov_atom[i - 4]);
+ if (i + atom_size - 4 > moov_atom_size) {
+ printf (" bad atom size\n");
+ free(moov_atom);
+ return 1;
+ }
+ offset_count = BE_32(&moov_atom[i + 8]);
+ for (j = 0; j < offset_count; j++) {
+ current_offset = BE_32(&moov_atom[i + 12 + j * 4]);
+ current_offset += moov_atom_size;
+ moov_atom[i + 12 + j * 4 + 0] = (current_offset >> 24) & 0xFF;
+ moov_atom[i + 12 + j * 4 + 1] = (current_offset >> 16) & 0xFF;
+ moov_atom[i + 12 + j * 4 + 2] = (current_offset >> 8) & 0xFF;
+ moov_atom[i + 12 + j * 4 + 3] = (current_offset >> 0) & 0xFF;
+ }
+ i += atom_size - 4;
+ } else if (atom_type == CO64_ATOM) {
+ printf (" patching co64 atom...\n");
+ atom_size = BE_32(&moov_atom[i - 4]);
+ if (i + atom_size - 4 > moov_atom_size) {
+ printf (" bad atom size\n");
+ free(moov_atom);
+ return 1;
+ }
+ offset_count = BE_32(&moov_atom[i + 8]);
+ for (j = 0; j < offset_count; j++) {
+ current_offset = BE_64(&moov_atom[i + 12 + j * 8]);
+ current_offset += moov_atom_size;
+ moov_atom[i + 12 + j * 8 + 0] = (current_offset >> 56) & 0xFF;
+ moov_atom[i + 12 + j * 8 + 1] = (current_offset >> 48) & 0xFF;
+ moov_atom[i + 12 + j * 8 + 2] = (current_offset >> 40) & 0xFF;
+ moov_atom[i + 12 + j * 8 + 3] = (current_offset >> 32) & 0xFF;
+ moov_atom[i + 12 + j * 8 + 4] = (current_offset >> 24) & 0xFF;
+ moov_atom[i + 12 + j * 8 + 5] = (current_offset >> 16) & 0xFF;
+ moov_atom[i + 12 + j * 8 + 6] = (current_offset >> 8) & 0xFF;
+ moov_atom[i + 12 + j * 8 + 7] = (current_offset >> 0) & 0xFF;
+ }
+ i += atom_size - 4;
+ }
+ }
+
+ /* re-open the input file and open the output file */
+ infile = fopen(argv[1], "rb");
+ if (!infile) {
+ perror(argv[1]);
+ free(moov_atom);
+ return 1;
+ }
+
+ if (start_offset > 0) { /* seek after ftyp atom */
+ fseeko(infile, start_offset, SEEK_SET);
+ last_offset -= start_offset;
+ }
+
+ outfile = fopen(argv[2], "wb");
+ if (!outfile) {
+ perror(argv[2]);
+ fclose(outfile);
+ free(moov_atom);
+ return 1;
+ }
+
+ /* dump the same ftyp atom */
+ if (ftyp_atom_size > 0) {
+ printf (" writing ftyp atom...\n");
+ if (fwrite(ftyp_atom, ftyp_atom_size, 1, outfile) != 1) {
+ perror(argv[2]);
+ goto error_out;
+ }
+ }
+
+ /* dump the new moov atom */
+ printf (" writing moov atom...\n");
+ if (fwrite(moov_atom, moov_atom_size, 1, outfile) != 1) {
+ perror(argv[2]);
+ goto error_out;
+ }
+
+ /* copy the remainder of the infile, from offset 0 -> last_offset - 1 */
+ printf (" copying rest of file...\n");
+ while (last_offset) {
+ if (last_offset > COPY_BUFFER_SIZE)
+ bytes_to_copy = COPY_BUFFER_SIZE;
+ else
+ bytes_to_copy = last_offset;
+
+ if (fread(copy_buffer, bytes_to_copy, 1, infile) != 1) {
+ perror(argv[1]);
+ goto error_out;
+ }
+ if (fwrite(copy_buffer, bytes_to_copy, 1, outfile) != 1) {
+ perror(argv[2]);
+ goto error_out;
+ }
+
+ last_offset -= bytes_to_copy;
+ }
+
+ fclose(infile);
+ fclose(outfile);
+ free(moov_atom);
+ if (ftyp_atom_size > 0)
+ free(ftyp_atom);
+
+ return 0;
+
+error_out:
+ fclose(infile);
+ fclose(outfile);
+ free(moov_atom);
+ if (ftyp_atom_size > 0)
+ free(ftyp_atom);
+ return 1;
+}
diff --git a/contrib/ffmpeg/tests/Makefile b/contrib/ffmpeg/tests/Makefile
new file mode 100644
index 000000000..c4c6925f8
--- /dev/null
+++ b/contrib/ffmpeg/tests/Makefile
@@ -0,0 +1,91 @@
+#
+# Makefile for tests
+# (c) 2002 Fabrice Bellard
+#
+include ../config.mak
+
+VPATH=$(SRC_PATH_BARE)/tests
+SRC_DIR=$(SRC_PATH)/tests
+CFLAGS=-O2 -Wall -g
+
+REFFILE1=$(SRC_DIR)/ffmpeg.regression.ref
+REFFILE2=$(SRC_DIR)/rotozoom.regression.ref
+
+SERVER_REFFILE=$(SRC_DIR)/ffserver.regression.ref
+
+LIBAV_REFFILE=$(SRC_DIR)/libav.regression.ref
+
+all fulltest test: codectest libavtest test-server
+
+test-server: vsynth1/00.pgm asynth1.sw
+ @$(SRC_DIR)/server-regression.sh $(SERVER_REFFILE) $(SRC_DIR)/test.conf
+
+# fast regression tests for all codecs
+codectest mpeg4 mpeg ac3 snow snowll: vsynth1/00.pgm vsynth2/00.pgm asynth1.sw tiny_psnr$(EXESUF)
+ @$(SRC_DIR)/regression.sh $@ $(REFFILE1) vsynth1
+ @$(SRC_DIR)/regression.sh $@ $(REFFILE2) vsynth2
+
+# fast regression for libav formats
+ifeq ($(CONFIG_GPL),yes)
+libavtest: vsynth1/00.pgm asynth1.sw
+ @$(SRC_DIR)/regression.sh $@ $(LIBAV_REFFILE) vsynth1
+else
+libavtest:
+ @echo
+ @echo "This test requires FFmpeg to be compiled with --enable-gpl."
+ @echo
+endif
+
+# video generation
+
+vsynth1/00.pgm: videogen$(EXESUF)
+ @mkdir -p vsynth1
+ ./videogen 'vsynth1/'
+
+vsynth2/00.pgm: rotozoom$(EXESUF)
+ @mkdir -p vsynth2
+ ./rotozoom 'vsynth2/' $(SRC_DIR)/lena.pnm
+
+videogen$(EXESUF): videogen.c
+ $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $<
+
+rotozoom$(EXESUF): rotozoom.c
+ $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $<
+
+# audio generation
+
+asynth1.sw: audiogen$(EXESUF)
+ ./audiogen $@
+
+audiogen$(EXESUF): audiogen.c
+ $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $<
+
+tiny_psnr$(EXESUF): tiny_psnr.c
+ $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $<
+
+DSPDEPS = $(SRC_PATH)/libavcodec/i386/dsputil_mmx.c \
+ $(SRC_PATH)/libavcodec/i386/dsputil_mmx_avg.h \
+ $(SRC_PATH)/libavcodec/i386/dsputil_mmx_rnd.h \
+ $(SRC_PATH)/libavcodec/i386/fdct_mmx.c \
+ $(SRC_PATH)/libavcodec/i386/idct_mmx.c \
+ $(SRC_PATH)/libavcodec/i386/motion_est_mmx.c \
+ $(SRC_PATH)/libavcodec/i386/simple_idct_mmx.c \
+ $(SRC_PATH)/libavcodec/dsputil.c \
+ $(SRC_PATH)/libavcodec/dsputil.h \
+ $(SRC_PATH)/libavcodec/simple_idct.c
+
+DSPCFLAGS = -O4 -fomit-frame-pointer -DHAVE_AV_CONFIG_H -I.. \
+ -I$(SRC_PATH)/libavutil/ -I$(SRC_PATH)/libavcodec/i386 \
+ -I$(SRC_PATH)/libavcodec/ -lm
+
+dsptestpic: dsptest.c $(DSPDEPS)
+ $(CC) -fPIC -DPIC $(DSPCFLAGS) -o $@ $<
+dsptest: dsptest.c $(DSPDEPS)
+ $(CC) $(DSPCFLAGS) -o $@ $<
+
+distclean clean:
+ rm -rf vsynth1 vsynth2 data
+ rm -f asynth1.sw *~ audiogen$(EXESUF) videogen$(EXESUF) rotozoom$(EXESUF) tiny_psnr$(EXESUF)
+
+.PHONY: all fulltest test codectest libavtest test-server
+.PHONY: mpeg4 mpeg ac3 snow snowll distclean clean
diff --git a/contrib/ffmpeg/tests/audiogen.c b/contrib/ffmpeg/tests/audiogen.c
new file mode 100644
index 000000000..31c437149
--- /dev/null
+++ b/contrib/ffmpeg/tests/audiogen.c
@@ -0,0 +1,168 @@
+/*
+ * Generates a synthetic stereo sound
+ * NOTE: no floats are used to guaranty a bit exact output.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+
+#define NB_CHANNELS 2
+#define FE 44100
+
+static unsigned int myrnd(unsigned int *seed_ptr, int n)
+{
+ unsigned int seed, val;
+
+ seed = *seed_ptr;
+ seed = (seed * 314159) + 1;
+ if (n == 256) {
+ val = seed >> 24;
+ } else {
+ val = seed % n;
+ }
+ *seed_ptr = seed;
+ return val;
+}
+
+#define FRAC_BITS 16
+#define FRAC_ONE (1 << FRAC_BITS)
+
+#define COS_TABLE_BITS 7
+
+/* integer cosinus */
+static const unsigned short cos_table[(1 << COS_TABLE_BITS) + 2] = {
+ 0x8000, 0x7ffe, 0x7ff6, 0x7fea, 0x7fd9, 0x7fc2, 0x7fa7, 0x7f87,
+ 0x7f62, 0x7f38, 0x7f0a, 0x7ed6, 0x7e9d, 0x7e60, 0x7e1e, 0x7dd6,
+ 0x7d8a, 0x7d3a, 0x7ce4, 0x7c89, 0x7c2a, 0x7bc6, 0x7b5d, 0x7aef,
+ 0x7a7d, 0x7a06, 0x798a, 0x790a, 0x7885, 0x77fb, 0x776c, 0x76d9,
+ 0x7642, 0x75a6, 0x7505, 0x7460, 0x73b6, 0x7308, 0x7255, 0x719e,
+ 0x70e3, 0x7023, 0x6f5f, 0x6e97, 0x6dca, 0x6cf9, 0x6c24, 0x6b4b,
+ 0x6a6e, 0x698c, 0x68a7, 0x67bd, 0x66d0, 0x65de, 0x64e9, 0x63ef,
+ 0x62f2, 0x61f1, 0x60ec, 0x5fe4, 0x5ed7, 0x5dc8, 0x5cb4, 0x5b9d,
+ 0x5a82, 0x5964, 0x5843, 0x571e, 0x55f6, 0x54ca, 0x539b, 0x5269,
+ 0x5134, 0x4ffb, 0x4ec0, 0x4d81, 0x4c40, 0x4afb, 0x49b4, 0x486a,
+ 0x471d, 0x45cd, 0x447b, 0x4326, 0x41ce, 0x4074, 0x3f17, 0x3db8,
+ 0x3c57, 0x3af3, 0x398d, 0x3825, 0x36ba, 0x354e, 0x33df, 0x326e,
+ 0x30fc, 0x2f87, 0x2e11, 0x2c99, 0x2b1f, 0x29a4, 0x2827, 0x26a8,
+ 0x2528, 0x23a7, 0x2224, 0x209f, 0x1f1a, 0x1d93, 0x1c0c, 0x1a83,
+ 0x18f9, 0x176e, 0x15e2, 0x1455, 0x12c8, 0x113a, 0x0fab, 0x0e1c,
+ 0x0c8c, 0x0afb, 0x096b, 0x07d9, 0x0648, 0x04b6, 0x0324, 0x0192,
+ 0x0000, 0x0000,
+};
+
+#define CSHIFT (FRAC_BITS - COS_TABLE_BITS - 2)
+
+static int int_cos(int a)
+{
+ int neg, v, f;
+ const unsigned short *p;
+
+ a = a & (FRAC_ONE - 1); /* modulo 2 * pi */
+ if (a >= (FRAC_ONE / 2))
+ a = FRAC_ONE - a;
+ neg = 0;
+ if (a > (FRAC_ONE / 4)) {
+ neg = -1;
+ a = (FRAC_ONE / 2) - a;
+ }
+ p = cos_table + (a >> CSHIFT);
+ /* linear interpolation */
+ f = a & ((1 << CSHIFT) - 1);
+ v = p[0] + (((p[1] - p[0]) * f + (1 << (CSHIFT - 1))) >> CSHIFT);
+ v = (v ^ neg) - neg;
+ v = v << (FRAC_BITS - 15);
+ return v;
+}
+
+FILE *outfile;
+
+void put_sample(int v)
+{
+ fputc(v & 0xff, outfile);
+ fputc((v >> 8) & 0xff, outfile);
+}
+
+int main(int argc, char **argv)
+{
+ int i, a, v, j, f, amp, ampa;
+ unsigned int seed = 1;
+ int tabf1[NB_CHANNELS], tabf2[NB_CHANNELS];
+ int taba[NB_CHANNELS];
+
+ if (argc != 2) {
+ printf("usage: %s file\n"
+ "generate a test raw 16 bit stereo audio stream\n", argv[0]);
+ exit(1);
+ }
+
+ outfile = fopen(argv[1], "wb");
+ if (!outfile) {
+ perror(argv[1]);
+ return 1;
+ }
+
+ /* 1 second of single freq sinus at 1000 Hz */
+ a = 0;
+ for(i=0;i<1 * FE;i++) {
+ v = (int_cos(a) * 10000) >> FRAC_BITS;
+ for(j=0;j<NB_CHANNELS;j++)
+ put_sample(v);
+ a += (1000 * FRAC_ONE) / FE;
+ }
+
+ /* 1 second of varing frequency between 100 and 10000 Hz */
+ a = 0;
+ for(i=0;i<1 * FE;i++) {
+ v = (int_cos(a) * 10000) >> FRAC_BITS;
+ for(j=0;j<NB_CHANNELS;j++)
+ put_sample(v);
+ f = 100 + (((10000 - 100) * i) / FE);
+ a += (f * FRAC_ONE) / FE;
+ }
+
+ /* 0.5 second of low amplitude white noise */
+ for(i=0;i<FE / 2;i++) {
+ v = myrnd(&seed, 20000) - 10000;
+ for(j=0;j<NB_CHANNELS;j++)
+ put_sample(v);
+ }
+
+ /* 0.5 second of high amplitude white noise */
+ for(i=0;i<FE / 2;i++) {
+ v = myrnd(&seed, 65535) - 32768;
+ for(j=0;j<NB_CHANNELS;j++)
+ put_sample(v);
+ }
+
+ /* stereo : 2 unrelated ramps */
+ for(j=0;j<NB_CHANNELS;j++) {
+ taba[j] = 0;
+ tabf1[j] = 100 + myrnd(&seed, 5000);
+ tabf2[j] = 100 + myrnd(&seed, 5000);
+ }
+ for(i=0;i<1 * FE;i++) {
+ for(j=0;j<NB_CHANNELS;j++) {
+ v = (int_cos(taba[j]) * 10000) >> FRAC_BITS;
+ put_sample(v);
+ f = tabf1[j] + (((tabf2[j] - tabf1[j]) * i) / FE);
+ taba[j] += (f * FRAC_ONE) / FE;
+ }
+ }
+
+ /* stereo 500 Hz with varying volume */
+ a = 0;
+ ampa = 0;
+ for(i=0;i<2 * FE;i++) {
+ for(j=0;j<NB_CHANNELS;j++) {
+ amp = ((FRAC_ONE + int_cos(ampa)) * 5000) >> FRAC_BITS;
+ if (j & 1)
+ amp = 10000 - amp;
+ v = (int_cos(a) * amp) >> FRAC_BITS;
+ put_sample(v);
+ a += (500 * FRAC_ONE) / FE;
+ ampa += (2 * FRAC_ONE) / FE;
+ }
+ }
+
+ fclose(outfile);
+ return 0;
+}
diff --git a/contrib/ffmpeg/tests/dsptest.c b/contrib/ffmpeg/tests/dsptest.c
new file mode 100644
index 000000000..06a185202
--- /dev/null
+++ b/contrib/ffmpeg/tests/dsptest.c
@@ -0,0 +1,178 @@
+/*
+ * MMX optimized DSP utils
+ * Copyright (c) 2000, 2001, 2002 Fabrice Bellard.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#define TESTCPU_MAIN
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+#include "mpeg12data.h"
+#include "mpeg4data.h"
+#include "../libavcodec/i386/cputest.c"
+#include "../libavcodec/i386/dsputil_mmx.c"
+
+#include "../libavcodec/i386/fdct_mmx.c"
+#include "../libavcodec/i386/idct_mmx.c"
+#include "../libavcodec/i386/motion_est_mmx.c"
+#include "../libavcodec/i386/simple_idct_mmx.c"
+#include "../libavcodec/dsputil.c"
+#include "../libavcodec/simple_idct.c"
+#include "../libavcodec/jfdctfst.c"
+
+#undef TESTCPU_MAIN
+
+#define PAD 0x10000
+/*
+ * for testing speed of various routine - should be probably extended
+ * for a general purpose regression test later
+ *
+ * currently only for i386 - FIXME
+ */
+
+#define PIX_FUNC_C(a) \
+ { #a "_c", a ## _c, 0 }, \
+ { #a "_mmx", a ## _mmx, MM_MMX }, \
+ { #a "_mmx2", a ## _mmx2, MM_MMXEXT | PAD }
+
+#define PIX_FUNC(a) \
+ { #a "_mmx", a ## _mmx, MM_MMX }, \
+ { #a "_3dnow", a ## _3dnow, MM_3DNOW }, \
+ { #a "_mmx2", a ## _mmx2, MM_MMXEXT | PAD }
+
+#define PIX_FUNC_MMX(a) \
+ { #a "_mmx", a ## _mmx, MM_MMX | PAD }
+
+/*
+ PIX_FUNC_C(pix_abs16x16),
+ PIX_FUNC_C(pix_abs16x16_x2),
+ PIX_FUNC_C(pix_abs16x16_y2),
+ PIX_FUNC_C(pix_abs16x16_xy2),
+ PIX_FUNC_C(pix_abs8x8),
+ PIX_FUNC_C(pix_abs8x8_x2),
+ PIX_FUNC_C(pix_abs8x8_y2),
+ PIX_FUNC_C(pix_abs8x8_xy2),
+*/
+
+static const struct pix_func {
+ char* name;
+ op_pixels_func func;
+ int mm_flags;
+} pix_func[] = {
+
+ PIX_FUNC_MMX(put_pixels),
+ //PIX_FUNC_MMX(get_pixels),
+ //PIX_FUNC_MMX(put_pixels_clamped),
+#if 1
+ PIX_FUNC(put_pixels_x2),
+ PIX_FUNC(put_pixels_y2),
+ PIX_FUNC_MMX(put_pixels_xy2),
+
+ PIX_FUNC(put_no_rnd_pixels_x2),
+ PIX_FUNC(put_no_rnd_pixels_y2),
+ PIX_FUNC_MMX(put_no_rnd_pixels_xy2),
+
+ PIX_FUNC(avg_pixels),
+ PIX_FUNC(avg_pixels_x2),
+ PIX_FUNC(avg_pixels_y2),
+ PIX_FUNC(avg_pixels_xy2),
+
+ PIX_FUNC_MMX(avg_no_rnd_pixels),
+ PIX_FUNC_MMX(avg_no_rnd_pixels_x2),
+ PIX_FUNC_MMX(avg_no_rnd_pixels_y2),
+ PIX_FUNC_MMX(avg_no_rnd_pixels_xy2),
+#endif
+ { 0, 0 }
+};
+
+static inline long long rdtsc()
+{
+ long long l;
+ asm volatile( "rdtsc\n\t"
+ : "=A" (l)
+ );
+ return l;
+}
+
+static test_speed(int step)
+{
+ const struct pix_func* pix = pix_func;
+ const int linesize = 720;
+ char empty[32768];
+ char* bu =(char*)(((long)empty + 32) & ~0xf);
+
+ int sum = 0;
+
+ while (pix->name)
+ {
+ int i;
+ uint64_t te, ts;
+ op_pixels_func func = pix->func;
+ char* im = bu;
+
+ if (pix->mm_flags & mm_flags)
+ {
+ printf("%30s... ", pix->name);
+ fflush(stdout);
+ ts = rdtsc();
+ for(i=0; i<100000; i++){
+ func(im, im + 1000, linesize, 16);
+ im += step;
+ if (im > bu + 20000)
+ im = bu;
+ }
+ te = rdtsc();
+ emms();
+ printf("% 9d\n", (int)(te - ts));
+ sum += (te - ts) / 100000;
+ if (pix->mm_flags & PAD)
+ puts("");
+ }
+ pix++;
+ }
+
+ printf("Total sum: %d\n", sum);
+}
+
+int main(int argc, char* argv[])
+{
+ int step = 16;
+
+ if (argc > 1)
+ {
+ // something simple for now
+ if (argc > 2 && (strcmp("-s", argv[1]) == 0
+ || strcmp("-step", argv[1]) == 0))
+ step = atoi(argv[2]);
+ }
+
+ mm_flags = mm_support();
+ printf("%s: detected CPU flags:", argv[0]);
+ if (mm_flags & MM_MMX)
+ printf(" mmx");
+ if (mm_flags & MM_MMXEXT)
+ printf(" mmxext");
+ if (mm_flags & MM_3DNOW)
+ printf(" 3dnow");
+ if (mm_flags & MM_SSE)
+ printf(" sse");
+ if (mm_flags & MM_SSE2)
+ printf(" sse2");
+ printf("\n");
+
+ printf("Using step: %d\n", step);
+ test_speed(step);
+}
diff --git a/contrib/ffmpeg/tests/ffmpeg.regression.ref b/contrib/ffmpeg/tests/ffmpeg.regression.ref
new file mode 100644
index 000000000..9db847a1f
--- /dev/null
+++ b/contrib/ffmpeg/tests/ffmpeg.regression.ref
@@ -0,0 +1,182 @@
+ffmpeg regression test
+dd4c189859399f7f251876be8e26e4f3 *./data/a-mpeg1.mpg
+722848 ./data/a-mpeg1.mpg
+78d202830e5ce5a67495ab14ebe6469e *./data/out.yuv
+stddev: 7.65 PSNR:30.44 bytes:7602176
+f3b008355f68394b6cad694f3488ea2b *./data/a-mpeg2.mpg
+736978 ./data/a-mpeg2.mpg
+9f364a477987c3b14412e303b94377ca *./data/out.yuv
+stddev: 7.68 PSNR:30.41 bytes:7602176
+1ed851cc079a7bc999e1cc2dc2aa146c *./data/a-mpeg2ivlc.mpg
+727637 ./data/a-mpeg2ivlc.mpg
+9f364a477987c3b14412e303b94377ca *./data/out.yuv
+stddev: 7.68 PSNR:30.41 bytes:7602176
+2566ea5760247a9485c8281cb52291a8 *./data/a-mpeg2.mpg
+735853 ./data/a-mpeg2.mpg
+55c22a09e4924977ee2cc4180078d3ae *./data/out.yuv
+stddev: 7.67 PSNR:30.42 bytes:7602176
+0093ab9141105dec8dc4452ba8f0ab6f *./data/a-mpeg2i.mpg
+749746 ./data/a-mpeg2i.mpg
+5189af71e6aa96cc2f6452e7f6b29287 *./data/out.yuv
+stddev: 7.68 PSNR:30.41 bytes:7602176
+f2067ddbe91a90ef12d606bba91cb900 *./data/a-mpeg2thread.mpg
+812667 ./data/a-mpeg2thread.mpg
+f101d3844ea2e12ac38001718c519232 *./data/out.yuv
+stddev: 7.63 PSNR:30.46 bytes:7602176
+fb900ca681fc054ed634ee4eadc9dc38 *./data/a-mpeg2threadivlc.mpg
+803035 ./data/a-mpeg2threadivlc.mpg
+f101d3844ea2e12ac38001718c519232 *./data/out.yuv
+stddev: 7.63 PSNR:30.46 bytes:7602176
+fd5f3e2a81558213bdfb8a7c86b3f541 *./data/a-mpeg2reuse.mpg
+2099878 ./data/a-mpeg2reuse.mpg
+e7f8692982e6d339a1f64bde4c297e59 *./data/out.yuv
+stddev: 7.67 PSNR:30.42 bytes:7602176
+c83ae8d8f3e2b4506df58e6a2f7e3b2a *./data/a-msmpeg4v2.avi
+636512 ./data/a-msmpeg4v2.avi
+279c33c2f6f58b7eb3d2daaa87160cb5 *./data/out.yuv
+stddev: 8.00 PSNR:30.06 bytes:7602176
+f546e8d0ada1917bc470584477f83e0e *./data/a-msmpeg4.avi
+639406 ./data/a-msmpeg4.avi
+8692a2e9ddb8081c4f00cb1557e2388e *./data/out.yuv
+stddev: 8.00 PSNR:30.05 bytes:7602176
+44c11ce4aa20af1aa609f68e544e5479 *./data/a-wmv1.avi
+641448 ./data/a-wmv1.avi
+69454f78ca636e83a600834e5a90660e *./data/out.yuv
+stddev: 8.01 PSNR:30.04 bytes:7602176
+044b1b5bd5899d54a8fe09eac2181d8b *./data/a-wmv2.avi
+675342 ./data/a-wmv2.avi
+69454f78ca636e83a600834e5a90660e *./data/out.yuv
+stddev: 8.01 PSNR:30.04 bytes:7602176
+12d215719748b4cf1adeaca4e519ba6c *./data/a-h261.avi
+727616 ./data/a-h261.avi
+bb2e71de01899ade4f850c180f9b0258 *./data/out.yuv
+stddev: 9.13 PSNR:28.90 bytes:7602176
+66d36048d15c3b04bd7bfc08ab977fae *./data/a-h263.avi
+673694 ./data/a-h263.avi
+d507be4253a9c8211a3738c58ba28118 *./data/out.yuv
+stddev: 8.06 PSNR:29.99 bytes:7602176
+e9e884a7c6b77d1aeeb4cb56ac150f92 *./data/a-h263p.avi
+2389564 ./data/a-h263p.avi
+0bb16a352798c997cb36e167f4fa8f3c *./data/out.yuv
+stddev: 2.07 PSNR:41.77 bytes:7602176
+3ee2dd25f141d520f61e5c01d08bdef1 *./data/a-odivx.mp4
+550787 ./data/a-odivx.mp4
+a1c691f3be526ecbf3be3152d5bab88c *./data/out.yuv
+stddev: 7.99 PSNR:30.06 bytes:7602176
+6c58e5707afe056b072d2ce21b3b8e4f *./data/a-huffyuv.avi
+7933744 ./data/a-huffyuv.avi
+799d3db687f6cdd7a837ec156efc171f *./data/out.yuv
+stddev: 0.00 PSNR:99.99 bytes:7602176
+5f35533ff4357e405971466ee06375db *./data/a-mpeg4-rc.avi
+814102 ./data/a-mpeg4-rc.avi
+2cc2a0b6699d861b4cffad28a704067b *./data/out.yuv
+stddev: 10.41 PSNR:27.76 bytes:7602176
+85e2456a673041d528b242d78318fb65 *./data/a-mpeg4-adv.avi
+600188 ./data/a-mpeg4-adv.avi
+60edc5a67271e425d0a2a52981895b81 *./data/out.yuv
+stddev: 10.25 PSNR:27.91 bytes:7602176
+c429ad61139904f03a211ba2bdf4cf01 *./data/a-mpeg4-thread.avi
+761308 ./data/a-mpeg4-thread.avi
+cd5bb5cbd9a7ea0953825482d2990f5a *./data/out.yuv
+stddev: 12.31 PSNR:26.31 bytes:7602176
+339c0dd9f30afa33a6f7134f84d5b60a *./data/a-mpeg4-Q.avi
+878910 ./data/a-mpeg4-Q.avi
+83b3cef07c91a397c63bc4bc45df667f *./data/out.yuv
+stddev: 5.61 PSNR:33.13 bytes:7602176
+c1dae02bddd79790266bc0a9f7d6eb0e *./data/a-mpeg4-PSP.mp4
+406449 ./data/a-mpeg4-PSP.mp4
+7315281e07830456208dff61337c982b *./data/a-error-mpeg4-adv.avi
+731526 ./data/a-error-mpeg4-adv.avi
+6ce2c82a0a9cf67a6991694473e9a306 *./data/out.yuv
+stddev: 18.23 PSNR:22.90 bytes:7602176
+b699b2fd005571dda3f8d34cb0ce7aec *./data/a-mpeg4-nr.avi
+688676 ./data/a-mpeg4-nr.avi
+2c16e13b1367022d52b0e75d93a734ba *./data/out.yuv
+stddev: 7.02 PSNR:31.18 bytes:7602176
+215cd567b5001181c24128e535cf77b0 *./data/a-mpeg1b.mpg
+1026948 ./data/a-mpeg1b.mpg
+1ee27511d22a4a553cac2ca64a79f2e1 *./data/out.yuv
+stddev: 6.34 PSNR:32.07 bytes:7602176
+2f9cb2ede35f7d12f6b518c50e20d81c *./data/a-mjpeg.avi
+1567580 ./data/a-mjpeg.avi
+18c3a76f984e717dd886d21fa04355f6 *./data/out.yuv
+stddev: 7.93 PSNR:30.13 bytes:7602176
+5a662e3833d900b56cca79ba5ed5ec06 *./data/a-ljpeg.avi
+6264498 ./data/a-ljpeg.avi
+799d3db687f6cdd7a837ec156efc171f *./data/out.yuv
+stddev: 0.00 PSNR:99.99 bytes:7602176
+8b9359781a7e87d09af1b1c9a536cb75 *./data/a-jpegls.avi
+9086694 ./data/a-jpegls.avi
+0f8637e9b861230aff9894825af83720 *./data/out.yuv
+stddev: 2.84 PSNR:39.04 bytes:7602176
+7eee6367442884321e27d15a26bc032a *./data/a-rv10.rm
+667915 ./data/a-rv10.rm
+d507be4253a9c8211a3738c58ba28118 *./data/out.yuv
+stddev: 8.06 PSNR:29.99 bytes:7602176
+55c73229105f35cbb06ee0dda215df2f *./data/a-rv20.rm
+640856 ./data/a-rv20.rm
+297dc46da1a256c0a97158c036c30c7f *./data/out.yuv
+stddev: 8.26 PSNR:29.77 bytes:7602176
+d13292f4583618d1b7b525a9ee010dff *./data/a-asv1.avi
+1488864 ./data/a-asv1.avi
+925320b74c7dfda5dc8378dd879ae2c3 *./data/out.yuv
+stddev: 20.00 PSNR:22.10 bytes:7602176
+2e50b590f32bf98bde82dbfaf180007a *./data/a-asv2.avi
+1454536 ./data/a-asv2.avi
+0b310840a6d3970595983491687669df *./data/out.yuv
+stddev: 18.82 PSNR:22.63 bytes:7602176
+4478bd22d09ae383b5cff05100437727 *./data/a-flv.flv
+649017 ./data/a-flv.flv
+40281942d6ee254f7d3027b8593b19be *./data/out.yuv
+stddev: 8.06 PSNR:29.99 bytes:7602176
+f8f51fa737add17f7fecaefa118b57ed *./data/a-ffv1.avi
+2654678 ./data/a-ffv1.avi
+799d3db687f6cdd7a837ec156efc171f *./data/out.yuv
+stddev: 0.00 PSNR:99.99 bytes:7602176
+b12ff53580cd8a9ce92ab7a0649e99f9 *./data/a-snow.avi
+155948 ./data/a-snow.avi
+b3feb1bf17bb4e720da1f1e8b4da4c03 *./data/out.yuv
+stddev: 23.19 PSNR:20.81 bytes:7602176
+265c4e0c45b2313817fa4d86dccbe6ba *./data/a-snow53.avi
+3519574 ./data/a-snow53.avi
+799d3db687f6cdd7a837ec156efc171f *./data/out.yuv
+stddev: 0.00 PSNR:99.99 bytes:7602176
+2fcbcdc63816e1321bf4b6b5380338d2 *./data/a-dv.dv
+7200000 ./data/a-dv.dv
+c2082cd8adf417c4ebc32654e446cba1 *./data/out.yuv
+stddev: 8.86 PSNR:29.17 bytes:7602176
+4f71942eb699bf3b12508a9e777a319f *./data/a-dv.dv
+14400000 ./data/a-dv.dv
+fc866b8879a34f5b440647e5135e4bfb *./data/out.yuv
+stddev: 8.45 PSNR:29.58 bytes:7602176
+6860534864cad0de4b1af9f987aaf9bf *./data/a-svq1.mov
+1365791 ./data/a-svq1.mov
+fb0a97094a89d6f379535f615783d00c *./data/out.yuv
+stddev: 10.98 PSNR:27.30 bytes:7602176
+21f8ff9f1daacd9133683bb4ea0f50a4 *./data/a-mp2.mp2
+95712 ./data/a-mp2.mp2
+83f8df5d5f84480566af548bb037fceb *./data/out.wav
+stddev:9330.70 PSNR:16.92 bytes:1054720
+stddev:4396.13 PSNR:23.46 bytes:1052672
+dd68110cb7e5388392f89d5160d3a825 *./data/a-ac3.rm
+98203 ./data/a-ac3.rm
+9e6e66847a568ef4f1f229b0939d2aae *./data/a-g726.wav
+24268 ./data/a-g726.wav
+a719ab6d47d8d601520edb13bf6136b4 *./data/out.wav
+stddev:8459.88 PSNR:17.77 bytes:96256
+ea2efb8ba20695a35ab0d71a7ee86f22 *./data/a-adpcm_ima.wav
+266288 ./data/a-adpcm_ima.wav
+60178d48204f5662d91776e36eddc82e *./data/out.wav
+stddev:11441.89 PSNR:15.15 bytes:1054720
+d2eee867856d2bdb6d08e936d4ceec0c *./data/a-adpcm_ms.wav
+267308 ./data/a-adpcm_ms.wav
+91a84bb4f319a3a0bf0c0441b3d3a529 *./data/out.wav
+stddev:1050.18 PSNR:35.89 bytes:1054720
+48ae9fcb043a44e316998b85043b61bc *./data/a-adpcm_yam.wav
+264236 ./data/a-adpcm_yam.wav
+e92cec8c07913ffb91ad2b11f79cdc00 *./data/out.wav
+stddev:18312.68 PSNR:11.06 bytes:1056768
+c3382f03ce2efb5d475240d288a33898 *./data/a-flac.flac
+353368 ./data/a-flac.flac
+c4228df189aad9567a037727d0e763e4 *./data/out.wav
+stddev: 33.31 PSNR:65.87 bytes:1040384
diff --git a/contrib/ffmpeg/tests/ffserver.regression.ref b/contrib/ffmpeg/tests/ffserver.regression.ref
new file mode 100644
index 000000000..7350fa481
--- /dev/null
+++ b/contrib/ffmpeg/tests/ffserver.regression.ref
@@ -0,0 +1,10 @@
+418d0c843a6605a7d48f285804a69df4 ff-test_h.avi
+ad4605187044d5e169f32a2ea205f937 ff-test_l.avi
+34f4f0c160efcdb37c0999680e07c41c ff-test.swf
+fe6de6234a8bb4ace52b86763741cecd ff-test_h.asf
+68e7c8a8ff64c4016a8d4e5ea27353f3 ff-test_l.asf
+cba8663681bf3ef89c95c09bb90204db ff-test_h.rm
+0a14086c708a7b8f4604e705a2bb7087 ff-test_l.rm
+353a9a8fb3d5bb2334ac991b5c60f6d3 ff-test.jpg
+7cbd46a6174d8203c26be333980595b5 ff-test_small.jpg
+aaa459e638cd1dc2c120760fa4e1e384 ff-test.mjpg
diff --git a/contrib/ffmpeg/tests/lena.pnm b/contrib/ffmpeg/tests/lena.pnm
new file mode 100644
index 000000000..9fa0c923f
--- /dev/null
+++ b/contrib/ffmpeg/tests/lena.pnm
@@ -0,0 +1,109 @@
+P6
+# CREATOR: The GIMP's PNM Filter Version 1.0
+256 256
+255
+â‰}߈‚â†väˆ|âŠ{â†|à†rÞ„uÝ„nÞŠvß‚kÞ„jÜ„pà€gÝ‚tÞsà‚jà„râŠvæŠrèŽrè’wì—zè—yî•vê”xévè†tàwfØvvÊZa´P_¨@Tœ>\œ=Y¤EX¦GXªJZ®IZ²J\²NW±JV¯LV°OZ²LX²LX´NX²LV²NZ°NZ®JS´JT´OV¸SY¼TZÂXZÂTXÂZYÄ^ZÄ[\Ê`\Ê^\Ë\ZÌf_Îb^ÎebÌabËbbËkhÍffÎd`Ìb]Îb`Ê`^Êg_Ëd^Ëd`Ëa^ÎhaÎhjÑb^ÐebÐfaÐgfÒebÔe`ÒddÒfbÒgdÎheÎf`Ïd^ÐffÐjfÌfeÎfbÎjfÐgbÓidÑibÐicÎhjÒheÊghÊknÎhlÌffËe_ÇddÌf^Îe]ÍcbÊcbÈjhÍibÍdaÎddÎdbÒb\Ðe`ÑhbÒf`Ðg`ÐjdÑd\ÏfdÎ``ÎjjÒplÍgcÌd_ÈbbÒe`Êd`ÎfgÌb^Çb`Îe`È`eÎieÈbcÈc^Êb`ÌcbÈccÎabËadÈbbÇbdÈ^^ÉbcÄbaÀ\`Â[dÀZ`»Za´X_°T[±PX¨HV¶LP¾V\È`]ÑlbÔqlÖzlÙtÜ„pÞˆnÞŠrÚŽvÝ‚nÜzgÜ~jÚ€jÜlÞ€nÜ€rÞ‚rÝ€pÞ†xÞ‚n߀hÞ€jÜ~j߀eÞ€lÞfà}fÝ‚jÞhÜ€eÞ„hÜ„m܆nÝ‚jÞ†q݈qÝ„pÜ‚hØ„nä”nï¹…ôÈøÎ–øÐžúÔ£üÔœúÔŸôÈ⪀Ärj§M\¥HX¨PZ®OZµX\¹Z\¶Za¼^`ºac¼X\¼^^¾ZZ½^b»dhº[cº\aÃZ[À[^ÃZZÃZ^¾^^Ã]`Â_^Á`cÄ`bÀ^_Å^]¼V\Á`cÂ`bÄbhÁ``Æ[[ÂbbÄa`¿[]¼V\¼V\ºVZ¾\bÚ{væ’€è”zÒrdâ‰}߈‚â†väˆ|âŠ{â†|à†rÞ„uÝ„nÞŠvß‚kÞ„jÜ„pà€gÝ‚tÞsà‚jà„râŠvæŠrèŽrè’wì—zè—yî•vê”xévè†tàwfØvvÊZa´P_¨@Tœ>\œ=Y¤EX¦GXªJZ®IZ²J\²NW±JV¯LV°OZ²LX²LX´NX²LV²NZ°NZ®JS´JT´OV¸SY¼TZÂXZÂTXÂZYÄ^ZÄ[\Ê`\Ê^\Ë\ZÌf_Îb^ÎebÌabËbbËkhÍffÎd`Ìb]Îb`Ê`^Êg_Ëd^Ëd`Ëa^ÎhaÎhjÑb^ÐebÐfaÐgfÒebÔe`ÒddÒfbÒgdÎheÎf`Ïd^ÐffÐjfÌfeÎfbÎjfÐgbÓidÑibÐicÎhjÒheÊghÊknÎhlÌffËe_ÇddÌf^Îe]ÍcbÊcbÈjhÍibÍdaÎddÎdbÒb\Ðe`ÑhbÒf`Ðg`ÐjdÑd\ÏfdÎ``ÎjjÒplÍgcÌd_ÈbbÒe`Êd`ÎfgÌb^Çb`Îe`È`eÎieÈbcÈc^Êb`ÌcbÈccÎabËadÈbbÇbdÈ^^ÉbcÄbaÀ\`Â[dÀZ`»Za´X_°T[±PX¨HV¶LP¾V\È`]ÑlbÔqlÖzlÙtÜ„pÞˆnÞŠrÚŽvÝ‚nÜzgÜ~jÚ€jÜlÞ€nÜ€rÞ‚rÝ€pÞ†xÞ‚n߀hÞ€jÜ~j߀eÞ€lÞfà}fÝ‚jÞhÜ€eÞ„hÜ„m܆nÝ‚jÞ†q݈qÝ„pÜ‚hØ„nä”nï¹…ôÈøÎ–øÐžúÔ£üÔœúÔŸôÈ⪀Ärj§M\¥HX¨PZ®OZµX\¹Z\¶Za¼^`ºac¼X\¼^^¾ZZ½^b»dhº[cº\aÃZ[À[^ÃZZÃZ^¾^^Ã]`Â_^Á`cÄ`bÀ^_Å^]¼V\Á`cÂ`bÄbhÁ``Æ[[ÂbbÄa`¿[]¼V\¼V\ºVZ¾\bÚ{væ’€è”zÒrdâŠ|à†yâ†vä†xâˆvâ„vàƒnà‚oß„m߆p߀hàhÞ„oà€gÝ€tÞ‚nß‚lÞnáˆtæ‹qçrè“yë—zë—yî–vì”vêuç„oßwh×omÈX_´O^§AW>Yž<V¤BV¦FZªFY®JZ°JZ²KV±JT®JT°LX³IS²JV³LW±JT²LX²LW¯JR³KU²PW¸QX¼U[ÂWYÃVZÂZXÄ\ZÆ\]Ê][Ê^^Ë[[Êa^Ïc^ÎdbËddËa^ÌheËccÎfbÍc^Ía`Ëa`ÊfcÌd`Íb`Ìb_ÏieÎgjÐd_ÐgdÐhdÒidÓfaÔeaÓfbÒfbÒfbÏidÐd`Ïc_ÐecÐgbÎdbÏfcÐhbÐgaÒhaÑfbÏhdÎhfÒgaËgjÍhiÍjjËebÌb`ÉbaÌe^Ðd]ÎcaÌb`ÈfdÍjaÊb_ÌddÍc_Ña\ÍfbÐfaÐfaÏf^ÐgbÐe^Ðd`Îb_ÌhhÒjiÎhdÌdaÇbaÐd_Ìc_ÌccÍd_Éa`ÍdaÉacËhiÈ^`Èa^ÉccÊdeÉa`ÎbcËceÈ`bÇbdÈ``Ë`aÄ`aÁ\_Â[bÀ\`ºY`µW^³TZ°OY¨JVµJP½TXÇ_^ÏjbÔpl×ylÙ}rÝ‚rÞ‡uߊrÛŠs݃mÜ|jÝhÜ~kÜmÜ}kÜ~oÞ‚pÜ€mÝ‚pÞƒoà€h߀hÝjÞ~fÞ~lÞ€hß~iÞ€hÞ„iÜdÞƒhÞ‚i܆o܃jÝ„qÞ†nÞ„pÜiÙlâ‘oôÅ÷ΘùМúÔ¡üÔúÖžö˔求Êzm¨NX¥HXªLV®Q\³X]¸Y\¹Y\½\^½``¼Z]»]]¾\[¼^b¼`eº]a¸[`¿[\¿Y\ÃZYÄ\]¿_`Ä^]Ä^^À_aÄa`Á`_Ä^\½WZÂ_aÁ^aÅbdÄ_`Ç]ZÂbbÄ`^À\\¾U\¾V\¼Z\À_bØtlÞ…vÚ}l¶WZâ†xà†qâ†vä‚nâ‡vâ†tâ€eà}lànà€ià€há~gÞ‚kà€fß|jÞ‚kß„nÞ€gä„næŒrévì’tì–|ì–xí–yì’sënæ„gÞxiÔfbÈZ\µL[¨<UŸ7S›;T¢<S§>T¬@T°KZ°LY°FS±FQ²EP±IV®FR°GS±JV²HOµFN²IT°GO³KV¶LRºOR¼VXÀTXÄWYÆ\\È_ZÊ\VÉ^ZÊZUÌZXÍ_\Ðb\Îa[ÌecÏ`\Îb_ËcbÐa^Ë`aÏbbÑf`Ðd_Íc]Ìc`Ïb]Òc`Ïb\Òc\ÐfgÐfdÑfbÒf`Òb^ÕebÔe`Ód^Ôa[Ñf^Òb^ÐabÎcdÎc_Ñc^ÑfcÎfdÎdaÏedÎfdÐc^Ïb`ÌdhËknÌdfËmjÊbbÍgbÊb`Îd`Î`ZËc`ËjfÌieËbbÊe`Í^XÎd\Îd^ÎgdÓd^Îh`Íb`Ðe`Ïa]ÐfbÐd^ÐffÍedÐd`Îa\Ë_\Ç`cÌ`^ÉfhÌ^]Ëb`Éa`Êa_Ê_^ÅbeÎa\ÎabËcaÌbaÌabÉ`^ÊbdÌ_\È^^Æ^`Æ[]ÁZ^¼\f¼W^¹T[¶RZ²LT«KX¬EPºUXÄ\^Èe`ÓlgÔvnØ{nÛrÛ†pÞˆt߈tÞ„mÞ‚oÞ~gÞ}gÜoÜ|gÞ€nÜ€nÜiÝ‚nß‚là€fßißfßeÞ~cà€ià‚hÝ€j߀fÞ}dÞeÞ‚gÝ‚iÜ‚lÝ„mÜ„rÞ‚kÝ‚jÚiÛhè¢xñ¾Š÷ÊøÐšúÒ›ûÔžüÖžûÒ•òÉߞs¸d_£HX¦JW«P]²V]¸V[¼[]½TWº[^»Z]½ZZ¼`^ÀZ^¾`a¿\^º^bº_d½]^¾^\Âa[Á__Æ_[À`_Á^]Ã]\Â\^Å\ZÀ^^¿[`Ä^^Æ``Ç]bÇ\[ÄbdÇ`\Ä_`Á[\Å[]Å`cÅb`¹VZœET~,KfEà‚ià…páƒrâ‚nâ…tâƒrà„kã€lâ€kà„nà‚jâiÞnß~mÝ~hà‚lÞ~iâƒjå‰mçŽré“rì“wì”sì–rî•ní‘pêŒlå€dÞtfÔjaÉWZ¸NX¨=Rž:Q¢8N¤:O¦@R­DT®DR²DPµHSµFP²DN³LW¯GR²KR²HR²GO²HN²HR°JT³LU³PY´OX»QY»VZÃUWÅZ]ÃYWÅ]]Ê^YÈ^]Ê]XÈa^Ì]]Í`^Ê_[Ðd]Ìc_Ìb`Íb^Íd_Íd`Îa^Îb]Îb^Ìd^Íb\Ðb^Îf_ÐbaÏc`ÏfaÐgbÒfaÓh^ÒhaÓd^Ñb_ÒgbÏhaÒdbÎb`ÐkhÑedÏdaÐfbÐdbÍa`ÑefÏcaÐd`ÏbfÌ`_Ë`bÒdbÎb^ËgfÌbaË`\Í^\Í`]ÉfbÌgdËhcÎedÎ^VÎ_[Ìb\Ëe_ÎdcÐb^Óa]Ðc`Ðb[Ïb_Òb\ÎcaÐd^ÐfbÌecÏ`\Ða^Êb`Í`\ËbbÊ]]Ëb]Ë`^Ì`]Ê\\È^`Í^^É]^ÈbaÎa_Ê_\Ì`[Ëb`Ç[[É^]Ç]]È_^Æ\^¼Y_¼Ya¹TX¸PX·QS³LU¬HT±JU¼SYÂ]^ÎffÑql×xpÚ{nÜ‚qÞ„tߊuß…rß‚nÝ‚pÞ€jÝ~jÞƒká„lß‚iàjÞ„mßiàjá„kàƒgâ‚eßjßg߀jà‚jß}eÞjß‚jÞƒjÜ‚lÜlÝnÛmÜlÜkÚhÚ~mÞ‰n쮀õÂŒöÌ™øÐšûÓžúÓ›üÔ™øÍ’ë·~Єl¬U[¨LY¬NU¯S\¸SZ¹XZºZ]¼\^¼Z_»Z\º]^¾[^¼]a¾\aÀ\]¾X[ÀZ`Á\^Â^^Â`^Ä[XÄ_^ÁZ\Ã_[Ã\_Ä^ZÆ]\Ä]^Ä`\Æ`cÆ``Å`]Ã`_Æa]ÈbbÆbdÉ_^Ä_\°NTŒ/Id@\B\Aàƒlà†nä‚iázká…oâƒká‚lâƒkä‚nàná„kâiß~hàhâ‚làbà‚hâ„jæŠjèŽnê’oë“qì–sì•oî”nìhèŽmå}eÞo^Õf]É\[µKT¨;OŸ8Q8P¥<P©@S¬BR®@P°HS´CN³GQ´FP±GT±IO´IR´DM±GP³IQ°DO°JR´KS¶OV¸OS½QT»VZÀW[Â[_Ä]`Æ\^È[VÊ^ZÎ[WÌb\Ï^ZËb_Í_ZÌa^Î`\Ïa^Í_ZÊfdÐd^Ïd`Ðe_Î`]Ïc\ÎaZÐ`]Ðe]Ð`[ÐdbÒfbÐfbÓb^Ôb[ÒdaÓd`ÒebÔd^ÐcaÐ_\ÑbbÐfbÓb^Òd`Ôd_Ñ`]Îc^ÐfaÎbbÑc\Ïc`ËcbÐa^ÐfdÍdbÎb`Ìb`ÍcbÏ`\Îa^Ìa^Ï`^ÈfcÏb^ÌcZÌc]ÍbaÎb\ÍdaÏcaÐhdÏc]Íd`Ïa]Îa_Î`_Î`[Ïb_Íd_Ðd_Ìc^ÌbbÑaZÌ`]Ì`]Êa^ÊbfÌb]Í``Èa_Ì_^ÊaaÊ^]Ì`dÌd`Ì`_Ìa]Èa`ÈbaÈ`]Ä^_À\`¼V\¿YbºTZ·U`´NV²NX¯LY®HV±NX¾X^ÈegÐjfÖsoÚzrÜ~tß„vàˆuà†rá„oßlÞ‚pßjßläƒiá†lá„mâ†oájâƒlá„jáƒlßj߀ià‚jà€hà†jàkà~fà€gßlÚ}aÝnÚlÚƒlÚhÛ€fÚ‚gÚ|iØkä—tð¹„öÆ’ùΘúМûÔšþÖœûÓ˜õÆŒä¤uÀlc¬JR¬IU«LU²RX³SZ¼VXÀ\]½ZZºY^»^a¾ZZ¾]^½Y\º\]¼Y_½ZZ½XZ¾\\¿\\Ã^^½]b¿]^Ä^\Ä\\Á^\Æ\\Â^^Ä^_È^\Í_\É\\Æ^`ÈdcÎfbËhbÃ_]®HO…,Fe@\@ZAZBäƒnâ‚pâ‚kâƒná„nâƒjâ€hâƒlâ‚jà‚qâ…lâkà€j߀iájáhãƒjä‹qèŒnè’rç”pé“tê’të“kínêŽhç‹hâ~gÝp\Ôh]ÉVT²JRª?Qœ7N :O¢=O¨<N¬BR°DQ±IV±GR³LX±KV°MV±NV³FN°DO±IP²CL±FO±DOµJR¸RVºNW¾RRÁWVÃVZÁVYÄZ^ÄX[È\ZË\YÍ\XÌ]YÐ]VÎ[XÍ^XÑb`Ì``Ðb_Îd_ÐebÑd`Òc`Îb^ÏbaÎb`Ía\Ñc\Îd`Ï`\ÏbcÏgcÐb\Ôb^Ód^ÓgdÔg]Öc^Ôb\Ðb\ÐfcÑddÐd`Óc`Ób]Ô_]Ñd_Î`aÐdcÎ`cÒc_Òb_ÑeaÒe`ÑdaÎdcÐd`Îb^Ï`^Îb_Ð_\Íb^ÏcaÍc`Òc`Ì_[Î`ZÎebÐb]ÐhdÒhdÒhaÑddÏfbÎb`ÎebÏb^Îb]Îd`Íb_Îb^ÐfbÌdfÎa\Èb`Î_ZÍcaÌb`ÉbaË^]Ìb`Ì__Ëc`Æ^\È]^Ì`^Ê`_É_^Ë`^ÌddÈ__Ã]bÅ\`À\`ÀZ^¹V`µPZ´PX±SZ²PZ®IT©HW·S\Â_hÏkiÔqnÚvlÛ}tàmá‡vâˆsâ‡sà„má„mß…lÞ‚oã†ná‡lâˆmåˆoä‰kä†pâ„pâ…jã‚fà‚là‚jà…gà‚ká‚fÞ€hàhÞ~dÜ‚jÜ€jÜ~jÜ‚oÜ€fÚ€jÚ‚mØ|hÖ~kÜ„lê©|óÀ‹øÊ’ùЛûÔžüÕœüÖžúјð»ˆÖr´WY¨LX¨M[¯T\±TZºTX¼X]¼Y_¼X\¼\_½\]ÂZZ¾\^¾[]ÀZ\ÁX[¼^c½[[¿^aÀ[ZÃ]\ÂZYÄ\]Ã\\Â\\Ã[\Æa^Ê`[Ç\[Æ`aÇ^`È^^ÌhcÏgcÇ]Y²OV†,Gb$HY@X=Z@\>ä„pâ„nâ‚jã‚eß„nâƒhâ‚lâjã‚mâ‚jâ€gá€jà€gÞ€jáiâ„iåˆpåŽpçqè“rç“vé“rê’nênêŽmæŒoç„fä~hÝr^×bVÊX\¶NW¦>Rœ<Qž<R£<M§?O­FT±CN³FSµIRµJU±KT²JU´JR³HO²CP°IP²KP±BK°DM´JQ¶MV¹OV¾PQ¾TWÁTZÆVUÄ[aÅ^\Ê^\É\YÉ]YÍb[Ì^XÎ^YÌb^Î^ZÍ^\Îb]Îd`Ìc`Ða^Ðd\Ïb^Ða`Ða^Ï_\Óc\Îd`Ðc]Ñc_Ðb^Òb^ÒaZÓheÖb`Ôc]Òb`Ñb[ÐcbÒd`ÑdbÒfeÖc^Ò`\Ñ``ÏfdÏdeÒfdÐcbÐecÒa`Ïc_ÏddÏdaÐc`Ñc\Îd_Ðb^Òb\Îc`Ïd]ÍdaÌb`Ïc`Ï_ZÎc]Îe_Ïb[Ðd^ÓhaÓd_ÒgfÎddÏb]ÐgdÏb]Î`^ÎddÎd`Îb_ÎaaÌcbÎc`ÉbcÍa^Í`\Ê`\Ë_]Ì`^Ê_`Î`bÊbcÊ`aÌ`_Îb^Ìa`Ë``Ìe_ËadÈ^cÄ^bÆ^`Â\aÁX^¼WY¶R]·T]±Vc±N[­KY«JX²NZ¼VaÊehÖpkØvrÜ|qÝsÞ…tâŠpâˆráŠvãˆnàˆtá…rä‡täˆnåŠpæ‰påŒoè‡jã…ká„kâƒgá€lâ‚hà‚hàhâ~fâ‚fá‚fà‚hÝ~hÜ|jÜ|hÙ€kÙ€pÜ€lÚ€oØ‚pØ~jØyhä“qñ¶€øÄú͘úÒœüÕŸüÖüÕŸ÷ʓ簀È{i¬MX­MY­MU´NW¶OUºZ[¸T\·VZ¼\^½Y[¾ZYÂ`]À[[¿YX½\]¾Z\À\`¿\b¿Z^Ã\\Á]`Ã^]Ä_`Æ_^Â]^Æ^^Å^^Å`ZÊcdÍdcÌecÎk`ÄZ\¨EQ&Ea?\HZBZ<\B\Bã‚pà‚máƒmágâƒlä‚gâ‚oâ‚hâ€gã‚kâ‚jãjà~fÞ~mâ€jãŠtæŠnætè’påqç‘pêpêlêŽmêŽnç‰mæ„gà|gÝo\Ôf\ÈWY¶HR¦<LŸ7L 6J¢=O¨:J­FR²GQ°@L·KR´HO´HRµMV±HT²GT°FQ´JT²DM´DN±DKµEN·MP¼NQÀQUÁRSÅTSÇXVÈZ[Æ\bÇ]ZË\YË]ZÎ^ZÏ`\Ï_\Í_[ÌeaÌ`\Ða[Ðd\Îb^Óa[Òb^Òc^Ñb^ÎfaÒa^Ð`ZÐc_Óc`Òf_ÐfdÑd^Òc^ÑgeÒfbÔe`ÓkhÒegÒfcÔa]Òd^Ôf\ÔefÑd^Õa_Ò``ÒfcÐecÑcbÌa_ÐedÑgdÑffÐhdÒecÒb^ÒffÑebÑ`\Í_\Ï`ZÎf]Ñd_Ïc`ÌbaÌ`]Ðb]Ðc^Óf]ÒifÒfcÕjfÓe^ÐcaÐd`Îb\ÎebÎc^Ðc`Òa_Ðd\Íc`Î_\Ì`\ÏbaÎ`[Ì`_Ê`]Î^ZÌ[^Î_^Ì_^ÎbbÎaaÉbcÎ``ËbdÎ`^ÎbcËb`Æ_`À`bÃY\ÃZ]¾TX¿QV¹T[¶Zc´MX²OWªJ\®HW¹S^Á^hÐooÖvpØwpÜ}qÜ„wà…pá‰tâŽsâŠsâ†tã†lå†påŠpäŒuã‰lãŠqä‰qä†mâ„nâ…oâŠnâ†jáƒnà‚láfâgá}bàhÞ„rÝ|eÚjÚ|lÛ€mÚ}lØ~mÚ~hØ}i×{iÞ~hé¥{ô¿ˆúÊ‘úÑžûÓœüÖ¢üÖ ûÒœóÃŽážvºb`¦JX­LV¬NZ¶PWºX\»TZ¼V[½Z_ÀY\¾[[Ä[ZÀZ[¾[]À_\½[\¿_a¾]_¿^^ÂabÂ_bÂ\\ÀceÅa^Ê`[Éb^Ìb`Îb\Ðd`ÒhbÏfeÃ\[¦@Ly!B^>W>X<ZBY>[9_@âlà‚là„sâhâ„jâiä„hä†kä†kâ†mâiàƒpà€màlá…pä‰påråoænè‘qæ‘pèŽpèsç‰jèŽuèˆoä‚dâ{jÝreÖjeÆ^a¶Q\¦@Sœ8MŸ9L¤?P©@M®DM²CN±BN¶FP´GR´LT±IW´FP³HT°JT´FO±DN¯JS±DL¶KS¹NR»QW¼UZÁSWÀY_ÅXXÂY\ÈWZÆ^[Ê\\ÊYVÌ`]Í`\Ï^`Ð`[Ða_Ñ^\Ða\Òd\ÎdbÐc_Ðc]ÏfdÒd`ÑfcÐa^Ïb_ÎdaÒa]Ñb`Òc`Ô`[ÑaaÑdbÒfbÔd_Òd_Òf`Òc_Ôb^Òb^ÒdaÔc\Òb\ÓcaÒ^[ÐbcÓjiÒdbÔb^ÐdbÑcbÑabÎaaÎdbÑdaÓgeÏa`ÎdfÌbeÎ`bÌfbÌgbÍf`Ì_]Í_^Ðb]Ðd]ÐgaÑgfÐigÒjfÐgdÑdcÐfbÎdaÌfcÐd`Ðb_ÎgfÓfbÌ`^Ìa^Î\[Ía`ÎcdÌcbÎdeÍ_ZÌ`^Ì^bÍ_`Ì`\ÎbbÐcaÍadÌabÊ\ZÏ__ÊaaÃ^dÀbgÂ^d¿Z`¾VZ¾TY»S\¶P[³NX³NX®HV­FX³Q^¼[gËfgÓol×xqÛ~uÜ‚uâ…tã‰râŒxãˆväŠwãŠoã†oäŠqã‹räŽuæˆmåŒmå‹qã…jã„má…jã†oä†ná‚pâ‚hàkà€dá‚jÝlÝ~lÜ~jÚlÝ}jÙ€pØlÙnØ~iØzeØxf߉jð°øÅŠúΕûÓ ûÔžüÖŸýÖøÌ“íµ„Ð…l«NXªISªM\°NVµTZ·V^ºTZ¼X_¾Z\Ä\ZÀ_`¾\`Ä_[À``¾\]À]`¼^`¾bbÀ]^Â__Â^^Äb^ÆbdÌ^]Ìb`ÐfbÐg^ÒgdÒiaÄZ[¤>Lu$CZ<V@YBZC^D\?\>`;â‚jà‚oâ‚nâláƒlæ‚jâ…mä„kä…lãƒlà~nâ‚nànà‚ná†oãŒqætæ‘oèŒpæ‘ränæoåpåŠkæ‰lç‰oç‚dä|fÞqbÕhbÈ^^´V\¤BRž=O9N¥=J¨>J®BPµFP²FO³OWµIRµFN´KQ°HP°IQ®CO°DL±KP°EL³EK³FR·OX¼OV¼RU¿QPÄUUÃVVÆWVÆZYË\YÈZWÌ\VÈ\\Ì\XÍ_^Ìa[Í`^Ïa`Ña[ÎcbÌ`_Ð_]ÎefÐ_[Ðc`Ñb`ÎdaÒb`ÍdcÐbZÏabÑc`Ñd\Ða`Ña]Òc`Ôd`Ôc^Ð`ZÑaZÔc`Ò`_ÐbaÒbaÒd_ÐcbÐaaÑeeÔc`Ò`]Ò`]Ô_\ÒecÓfgÎbbÏa`ÎacÏbbÎb`ÌjfÌbbÎe`Îc`ÌcaÍbbÎ^\Í`ZÌb`Îa]ÌcaÑedÒghÐkmÑooÑefÎdeÎb^ÏfdÐb_Ìb`ÍbaÑfcÌ`ZÌa`Ì]_Ðb[Ì_`Ë`]Î``Ð`\Ê\]ÌZ[Ê``Ë`^Î^\Ï`^Ì``Í_^Ì_\Ï_^Ê^ZÊ^`Â\`À]h¿\dÀelÂV\ºPX¶T\³LZ²JX°NY®FT´OY¸V^ÌecÑok×ztÜznÜsß„pàŠvâŒyäŠvåvä‰pä†oá‰täŠxä‰rãnäˆrä‰pâˆoäƒlà„nâ‚pâ„oâ„râ€fá‚sà‚jÞƒpÝ}kÜ~nÜ~lÛjÜ€jÚoÙlØ}oÚ|kØ}lÚ{kÙyeæœt󻇸ɒúÏšúÓ ûÖ üؤüÓ˜õÆŒä¦w»jbªLT°R[®NU¸T[µPW¹X^»X\»X\¾Z\¼\`À`aÀZ^½[]¼\_¼`e¼Z^¿^`¾aeÂhjÄabÈabÊb_ÊfeÍedÑhgÒigÒlfÆ\]£?Nx#D[AR@ZFXFX@\CZB]?aAâƒqà‚lâ~iâ‚lâ„mä‚iäƒnä„mã†râƒlâƒnà„màjâ€iã„mæŠtç‘nå“tçtä‹nåŽlæpäŒpäŠlå†jä‰ræ‚hâ{hÚwhÖheÉ`d´OZ¥@Rœ8N;N¥?O«AK°AL±DN°GP²QX³DM´FO²DN²EL²HN²GN±HN±EL±IP²GN¶HPµLQ¹PT½NQ¿UU¿SVÄZYÂWXÅWVÉZXÌZVÎ\WÈ\\Ë`\Ð_]Î`[Îc^Ñb[Ð`YÎc_Î`\ÎccÎc_Ðc`Î`\Î`bÍb[Ð`^Íb`Ò`ZÒc_ÐdbÐb]Îb]Òc]ÒdbÓa^ÑcfÐ`]Òc]Ñ`[Îb_Ï^ZÔc^Ñ_ZÑb^ÒecÐ^^Ób^Òd`Ò\XÒ_[Ðb`Ñ^]Í]]Î`\Ïb^Ìa^Ð``Ð\[Ïb^Ðc]Íb^Ì``Ëc`Í^\Ì`\Î_YÍbbÑfdÑbbÏedÏfdÎffÍbbÐc`ËbcÍa`Îb`ËdbÐb`Ðb]Ìe`ËaaÌa_Î`[ÌddÌ[YÊ\_Ë]\Ë\]Í^ZÌ`^Ì^ZÌ`ZÍ\]Ð^\ÎZ\Ï\ZÏa_Ê`\Ë]]Â\`Â[`À[b¿Y]¾X`¾RV¶QZ°PZ²S\¯JW«JZ®O[¶P[Æ`dÐjiÖxpÚzvÜ€xÝ„tàˆyâ‰vãŠwãŠxä‡näŠrã‡máˆpá‡sátä‡näˆkâŠoá‰qàƒgà€mâ‚jâ‚jâ€hàmÝhÝlÝ~jÛ€lÜ|kÛ€jÚ}jÛ~lÛ|iØ{kØ~k×~lØveÔvfÜ„jì¬|õÉøÌ’ùÒ›ûÔžüÕžû×¢úҗf֌i³TW¬JS°PU´PZ´RV¹V[»Y\ºVX¼V\¾UXÀ\\À_]¾[^¾\]ÀWZ¾\`ÀZ\ÁadÂbcÃfiÆdhÇddÌedÎgdÒhiÓldÊ\[ >OnA_IV@XEZA\ LZ?]>\>b<c@â‚hßlànâƒtä†qä…jå…mä„lã‡mãlàƒrâ„oà‚qâ†päŠsçtçvæsæ’oårã‹qåŠsä‹rá„kåˆlæ‡læ„jã}dÞtcÖh\ÊZZ¸LT¦@Nž6I5H¥>Mª<I°=J¯BN¯JR¶JR´HP²HR³CO±JR³JP±FL´FK°EL²EM´HN¸LP¹MP¸PU¾LR¾QSÃWXÅZYÆZWÈWUÈZXÈYTÌ`\Ë_\Ï_[Ð`^ÍZVÌ^\Ìc]Ïc_Ò`[Îc_Ð^_Ð_ZÐb^Òb_Ì]^Î``Ð`^Î`^Ñ_\Ñ`YÎb`Ò`ZÐ^YÓd_ÔfdÖe`Ô_\Òa\Ó`YÒ`ZÐ``Ð`\Òb`ÐfhÑgfÓdaÒa_Òa\Ó^\Õ^WÒ_ZÑ]XÒZVÐ^[Ï^[ÐZWÒ]WÍ]^Ì\^Î^]Î]YÎ^ZÍ`ZÌ^[Î^ZÌ`]Ð\WÌ][ÐaaÍ`_Ïb`ÍdiÎdbÒcbÒb`ÎcaÍbaÑc_ÏcbÐd_Ï_\Î`\Î^\Î\ZÎ^ZÎb^Î`XÍ\[Í_\Í\YÌ\[Ì^^Ê_\Î_\Î^[Î\ZÌ[\Í\XÎ``Î`_É\[Æ\aÂ^dÂZbÂ_fÀV]ºQ\µNW²N[°NW®JV®L\±T`·YhÆafÎjlÔtrÛ{tÜ~xß…yà‰|â‹vâ‹xâ‰xãŒtäŽuâ†pá†ràˆrâ‰nâ‡lâˆnáˆkâˆoã…ißjàlà„jájá‚ißoà‚lÞ~hÜlÞ~mÚ€kÛ}kÜ}jÛlÚ}lÙ|jØ|i×zmÖxkÖydã–qòº†øÇ’úКúÔžûÖ¢ûØ¡üÖ÷ÊŽç°~Çw`¨JU­KS°OX±TW¶X^¼]]¿ZYÁ\]½Z]Á\ZÄ^ZÀ[]À\Y¿Z]¿ZZ½Y\¼]cÄbfÃ]_ÅcbÉdfÐdhÒifÒjgÈ\_¤<Nr#Gf4XWDV>W=X<Z=X:`;_?f?f@â€fß‚pâ‚oäjä„næ…mæ…iäƒiä…mâ†râ‚nâ„má„nåŠpærètérç‘sçræoå‰iä‡pâˆnàˆqä‡jæˆpæ‡nã~gàt^Ùg[ÉTQ´FL¨7FŸ8Lš0Gž6I¨<L¯BM°DN°HN¶EN´GPµHQ²LV°JT°IT°DN¯FP²FQ´DL¶GN¸KO¸LP¹JN¼QW¿STÁX\ÆYXÄUUÈZ\ÊZVÇ^\ÌXYÈabÍ^[Îb_Í^\Ë]aÌ^YÏ^_Ð`ZÍbcÍ^aÏ^ZÎ`^Ð``Î`eÏbcÑb_ÎcbÐaaÐc_Ñ`\Ò^XÏ\ZÐaZÏ_`Ó`_Ó`]Ôb^Ò^ZÑ]ZÑ`\ÒdbÑcdÐdlÕhfÒgfÒebÒ`aÕ^ZÒXXÑYVÑ[WÎZZÏZZÎZWÎ]WÎ\XÎ`\Ì`bÐ^[Í`[Ì\_Ê\ZÍ_\Ê`]É^]Ê^[ÈbaÌZXÎ`bÌ]^ÌbbÏfeÏcdÐcbÐaaÏdbÒddÎcbÌfcÌ_ZÌ_]Í^ZÌ^\Ì^[Ì__Ì^`Ê][ËabË^_Î]WË_`Î`^Ë^]Î`XÍ\\Î]ZÎb`Í^_É^]È^`Ä]^ÀY`Ã\_Ã^a¾^dÀR\¶MX¸NW´LS±JQ±JY¶P^¹WbÃ[fÑfjÖolÖutÜ€xà†xâ…{â‡zâŠuâ‰uáŠwäˆtâ‡sá†mà†qá‡pâ…mà†lá‡hãˆhâ‡kÞƒlâƒlß„ná‚jâƒkÞ„mßjÞ€lÜ~lÝmÛmÜlÞhØ€mÛ|jÙ}mÚ~kÖwhÖzlÕvhÜ€dê«zö‹ù͘úÒ™ûÕŸúØ¥üÛ üÔ™ò‰ڜw´\Z¬JP²NT³RW´V[¶ST¾ac¼^cÀ`aÄY^Â]^Â^^¿Z]¿\\¿V\Àab½^cÃ\\Á_bÆbbÎd`ÒheÐhhÊ^X¢=MsAYA\FYDS:U7Z<\8_=c9h=j>c9äƒpã„oä„mã„jä„hæ„nå…lå„hå…oã†oä…jã†rãˆuçŽoètç”rç”tä‘ræpåŒsã‡hã‡kâ„oà†qåŠhæŠnç†låcàsZØgZÊXR·JN§<Kž6Hœ3H£;I¨CN®?M¯DO²HS±DNµHP³IR²HN²LV²FN¬KV°FN±HP°EP´HM·KT¸KO¸KR½SVÀSRÂTWÆXUÄZ\ÆYXÈYXÈ\[É]ZÊ`ZÊ`ZÌ^WÌ]ZÍ]ZÌa\Ì^[Î_[Î_[Î\]Ìb]ÍabÎa_Ña`ÌchÎ]]ÎbbÐbaÐacÑabÒc]ÎacÐ`]Ð`]ÒddÕ^^Ô`aÒ\]Ð^^Ï__Ô^ZÔ^^ÑedÓfeÒhhÒgaÒadÑ[\ÎZXÑ\ZÍ[XÊZWËVUÎWRÍZZÎVWÎ]\ÌbdÎ^[ÍZYÈ\`Ë\XÌZ[ÊYYÌ^\Ì^^Ì\ZÎa^Ða_Ìb`Ì^^ÎbdÐ`^ÎbeÌbfÐb^ÐdcÏhfÐbbÍb^Ê\\Ð_]Ê^\Ì_bÍa^Ê`aË`aÌ^[Î\ZÍ_]Ì\XÉ]\Ì\ZÏ]\ÍZ]ÈZ]Îa`Ì^aÎ_\Ë]\Æ\_Ä^bÃU]ÄX^¾V^ÀYb¸OW¹QX¸NVµLU²LX¶Pa½XcÆaiÎfjÔprØwtÚ~wÞƒyß„và†xãˆ{âŠtâŠxâˆtà‰vá‡tá‡o߇tâ‰oà‚mâˆjä†kâ…jã†jâ„iàmâƒmâ‚qá‚nâ€lÞƒrß‚oÝ‚sÜ„rÞ€nÜ~lÜ~nÚ~hÚ~qÙ{h×xkØxi×xdÖvgâlô¸€øÇ‘úÑ›úÔŸúÖ üؤüØ¢øÐ”Él°IN¬MU²OU´TY½UW¼VX½ZZ¾[^¾^]Â\ZÀ[]¾]]ÂZZ¾[`½]]Á^aÆb`Ä^^ÉfdÌfdÏjdÂZ_¢9Kt>W=V:ZCXA[BW;^?^<b=d=g@a>f'Lä„jã…qä„pâ…må†mç„kåˆpä‡iä‡qä†näˆqåŒnåvèrçwé“rè’tèrçŽrçŠlä†jâ†nà‚rá†tçˆkèŠnèŠmè€fÞs^ØgXÊXU¶KP¦=KŸ:Nž4K¦<Kª@M¯BR°BL²FR¶LV²LVµNV±DN±LU²GM°EP²FO²IR±DP²IQ¶IR·JO¸KQ½NR¾TUÅTVÇWVÂ\_Æ[ZÊ[XÆ\ZÉ\ZËZVÌ_[Ì\YÍ`^Ì_]Ë`_Ì`\Î`^Ì]ZÎ^^Ì\\Ï`\Î_aÍ``ËbfÍadÏ``Î_cÓd_Ð_^Ñb]Òc`Ð`\Î``ÏcbÓ^`Òa^Ð`]Ò`_Ð_^Î^^ÏbfÑebÐdeÒa`ÑbbÒdcÎ`cÎ_\ÎYVÌZZËUUÍXVÌZVÊYWÌ\[ÌZ\Î\ZÍ`]Ì^^Ì]`Î\\Î\XÈ]^È[\Î\[Ê]\Ñ[XÏcaÌdgÌacÎ`^Íb`ÌbdÌefÍfhÌa`ÌdhÎ^[Ëa`Ç]`ÌbbË\[É\_Ìb^Ë``Ë_^Ìb^Î]\ÎZXÊ^aÌ_^Ê[ZË^^Î]`Í\`ËbaÐ^\Ï``Ë`aÊbdÇX]ÀT_ÁV^ÀV\¼V`¿TYºLWºNX´NZ°KZ´Oaº[jÆclÎilÓkjÕwxÛ|tÞ€và„xá‚tâ†sâ‹xá‡wâ†tß…và‚qá‡và„oãˆpã†iâ†gä„hâ„mä„jáƒlà€eánàqá„rá€há~kÞƒp݃rÞ„pß‚nÞ‚lÝ~lÜ€oÚzlÛjÚyjÖwgÖxjÔtf×|gì¥xöÀ‰úÊ”ûÒœùÕ¡úÙ§üÙ¤üמ÷Ë’ã§v¹d]®JP²OT´PXºUV¹VV¾XX¾V[Á^`À]`¾Y\¿ZZ¿\^À^]¿`bÅ[]Å``ÈcdËgbÍgcÄZV¢=Ks<X9W@[@\@\BZ=]?^>b=e<e<b:bAcEä‚gä„pä„näiå…lä…hä†jä‡lå‡pä‰væ†pçŒrèsé”té”ré”rè’ræ‘tèpæŠeä‡fâ‡lâ…pã…iæˆoèˆièˆjåcâv^ÜhVÌ[VºHN§<JŸ9J¡9K¦?Q¥?P¬AN°BN²DN³GQ´HS´KT²KT°NV²FO´CL°CL²EP®ENµHO·GP¶JSºNU½PVÂPQÂTUÆUVÆYZÄZ]É\\ÆVVÊ[[É\\Ë_\Í^ZÎb]ÊZ]Ð`\Î^\Ía`Ê_aÌ^ZÊ]`Ð]ZÎ`aÌ`^Î`aÑ`^Ð`aÔ``Ò`_ÐaaÐb]ÑbbÒb]ÓbcÏ_`Ï_^ÐaeÓehÑ`^Ñ^]Ò_\Ñ``Ò``ÒcdÏbbÓddÑ\ZÔ\YÓ`_Ð[XÎXVÍZXÉZVÈXYÈVWÌ[XÈVDÌ[YÍ]ZÉ]^ÊZ[Ì^[Í\\Ì\XÌZZÉ\YÆ\YÊ[^Ë_]ÍabÌ_`ÎbeÌ`aÌ]`ËabÍheÎbeÍcbÎ_`Í__Ê^]Í__Ë^^ÌaJÎabÍ^`É^^Ëa_Ï^\ÎZXÌ`\É`cÊ\`Í]\Ì[^Ì^]Í[]Í`]Ê``Ç]`É^_É[_ÆW_ÅX_ÄT`¼RX¸QH¶L]¸N[´HX¶JX¶LY¼Y]Ç^bÏelÒjjÔqnÙwsÝ|rÞ€rÞƒvá†xá†wâ‡tâ‰vß„wÞ†t߆s߆sá‰rá‰mà…râ‡oá…là„Vâ„oà‚pâƒkà„qãƒoà€jß„nÞ‚p߆nà‚n߃TÞƒrÞ€mÝnÛoÛ~qÙ~oØ|nØvmÕrOÒqe܃iï®löÄdùÎúÓ‚úØ—úÚžüÛ¡üÖ õƘښ³\~«Nw®Ni´PZ¼VV½WU¼UZ¿XZ¾[YÀ_[Á^[¿^\ÀaaÂ^^Â_`Èd`ÇgeÍg]Â[]¨CUw#R[NXNTG_DZ2]B\:`Hb?eBe;b<`<d@d >ä‡sâ…lá…nâƒkä…mä‰läŠnæˆpå‡räŠtåŒrèŽqè’uêré’qèrêoèpèkå‡jä†mã†mâ„lã†lèˆiæ‹lè†gä~eàr[ØfVÉVP´HM¨>Kš6L;M¥;K¨BP®BR°@M´IR´GP´HP²HQ²JQ¯FM²FN°IS²EK°CM²BM´CMµEO¸LTºOW½OUÂRRÄSVÄSUÆXXÉWTË[ZÈZVÈ]YÆ\\Ê[ZÌ\YÍ`]Ð__Í^]Ð][Ò`]Ï_]Í_XÏ`^ÐZZÑ]\ÎYZÎ^`Óa_ÎceÕb^Ò^`Ñ^\ÒZXÒ``ÎbdÏ`bÎa`Ñ`^Î^eÐ`eÐ``Ð^^Ð`_Ð^]Ð`aÕcgÓdaÒ``Ñ^`Î][Ñ[XÏZYÏWUÍXYÉ[\ÈXZÆX[ÊXVÊX[ËZ[È\^Ê^^Ìb`ÈXVÄ[ZÉWWÌYWÉYXÈ]\Ê[XÎ_^ÌabÊafË_aÍefÌbcËbfÍejËgfÊfjÌaaÎ^\ËbdÍ`_Ì`aËbaÏa_Ë\`Ð][Î^^É]\Í]ZË]`Î]\Ì]\Ê\XÍ[]Î`]Í]]Î^]Ê_`Æ`dË]^Æ[_ÉW^ÅW^ÁRY¿T^µP[·P[¹RZ´JX¹LYºQ^½VaÈYcÏbfÕhkÕqnÙwqÝ}tÜ}tßuà‚tÞ†vá…tâˆuÞ„vá„qà†oß„ná†kà†mà„náƒnáƒnà‚iá†mÝ…pà€ná„pà„pá†lßoàn߃mÞ€pàƒmà‚rßpÜ~oÚpÝ~pÜ~pØxjØzjÕtcÔtcÖveçžsô¿ŠúË—ùÒ úרúÚ«ûÛ¦ýÚ¥úΘ賆ÂvfªLU«JS±NX¶PW»QTºVY¿VX¾\]À^^ÄZX¿[\Â^aÄdhÇbbÍdbÏhgÅ]\¤?Pu>Z9W;V=Z=Z@a"LaBfFdCf;iAd<b@d@f>e<ä„wä†mä„oãˆlâ‹väŽrå‰nä‰næ‹yæpæsè’tè’oêrépê‘péjèŽnçŠfç†jäiâ…mâ†nã†kå†jç‡lè†læ|eÞp[ÙdTÌ[R¶HP¤<Hš5Hž4I¢9Hª@P®@O±CN¯DQ´FN°DO®FL°FN­HP®HN°EQ®EQ°CO²JU²IS·FP·LTºNTºQX¼PU¿X[ÂRVÇY[ÆVTÄVXÇXXÈ^YÅZ\ÉVXË^XÌ_`Î^YÎ][Ï\ZÎcdÎ_\Ñ\WÐ\ZÏYYÌ^^ÉX\Í^\Ð\\Î``Ñ\]Ð[ZÔ`_Ñ\VÐ^\Ì\_Ê^bÎ`_Ð_aÐckÏgkÒbdÑ`^Ò`]Ð^^Ò\\Ñ_^Ò`^Ò^]Ï]^ÍZ\Ñ\ZÑ[[ÍZXÎ[WÎ[WËYVÇYZÉ^`ËXTÊ_aÊ]XÌ]XÌ]VÆXTÈXUÂ\XÃXZÉVWÈ]ZÈZZÊ]]Ì`bÌ`cÎabÌ`aÍdcÌaeËfjÌccÊejÌabÍ``Ê]`Ê^`Í^^Ï`_Ï`^Ë`^Í]^Ì^`Ì][ÐZXÌZXËZZÐ^_Ï_aÐ[XÎ][Í\ZÐ\\Ê]_Î_cËXZÉWZËY]ÄV\ÃQZÂY`¼T]¹T\ºPV¸JT´JZ¶M[¾UcÆ[fÌblÓklÔmpÔtrÙzqÛ~uÞ€uß‚tÜ€t߃sá„tà„tÞ†rÞmÞ…oá„là‡rá†lß‚p߃oàoá‡q߃lÞ€oá…ráƒnâ‚làƒoàkàƒoß‚jÞ€pÞp߃qß~lÚ{pÛ{nÜ{oØzlÙ{kÖviÕtfÖrcÝfî­~øÆŽùИùÖ¤úئùÚ©üÛ«üÖ£öÅÜžy·^Y¨DO¯FQ´OT¸RX½SX½TYÀZ\À^^Â]_ÂbbÂ_cÌecÊfdÏfeÀVWœ:Js?X:W>V<Y>YC^D`FdDdCe>d@d?^>d=cAa<^;äˆvãˆnäˆoã‡gä‡råˆjå‡qåŠpæŒsæuê‘rêrèŽoêséoéŠjèŒfè‹kè‰eæ‡nâ„kä„jã‰rä‡oçˆlç‰næ„gä}gÝq]Öi]ÊXQ¶FK£6Fž0C›3G 8J§?N©BN°CP²DJµGM±KT°CK¯GN°FN°DL®GP°HN¯HQ²GP®BNµEPµKR¸NS¼QTÀSUÂSUÃSXÅZ\ÄVXÄVXÃVYÅW]Ç^^È]YÈ\]É\\Ë_ZÈ[WË]\Ï_]Ê^^Î\YÈ\ZÌVVÌ]]É`cÎ`^Ð^_Ï`_ÑabÑ^^ÐabÐ^ZËZYÍ`^Î`bÌ_aÑ^]Ò`cÐ`bÒ_aÏ`cÐ`^Ï\\Ó^\ÐbcÏ\[Ò]]Ô\[ÒZ[Ò[YÏZZÌZZÍ\]ÈYZÌTTÌ\^ÊXYËVVÊXXÊ[XËZZÇTSÉVTÉTXÆVVÅTWÂZ[ÅY[È\^Ê\ZÊ\\Ì`bË]`Ë_dÈbhÊbeÎehÎacËabÐ``Ë^^Ê^^Ì^_Ë^`Ï^aÑ``Ï`^ÏZ\Î^aÌ`_Í\ZÊ]_Ë^\Ê[^ÌZ\Ð]XÍ_`Î[XÏ[\Î]\Ì]bÌY^ÉZcÇV\ÄUXÀV_¼Wa¿Wd¸U`¹NVµJX¶HY¹KY¾R`Å]fÌchÒhk×pnÔwsØzsÚzqÜ~oÝ€uÜ€uÝ„tà„vß…xÞ†sß‚o܆tàƒjà‚oáƒhàƒpà‚pß‚láƒmá‚oà~jà~kâ‚jã†rá„oà„là€oÞƒsà€nßnÞ~mÞ~lÚzkÛzjÜzlÙyiÚwf×ufÖqbÕpaÕrbæ–pô¼„øË”úÔžùÙªúÚªüÛ¬üÜ©ûÒ™ñ¾ƒÎƒhªJR¦DO¯OX³PV·PT»RYÀUZºW`¾Y[À_dÃacÈdfÌhe¾W[>Nn@Y<X@U>Y?V=\Cb"Od'Pe#Kj%Ld$GdDb>d@b>_?^<`CåŠwâŠpåŠnä†päˆjæ‹päˆqæŒvètè’uè“véoèpé‰oèˆièŒkçŒfçˆkçˆjæ†lä†næ†må‡qçˆjéˆhè‰lç‚gä}fàp[ÖbVÈUP¸AJ¦:I™0Fœ2G£<N¦:K«BP±HR²JT²FP±AP³BL´EP°EP®DN¯EQ²EO°DN¯EN°GPµEMºFN¼NT¾PTÂQSÄVWÁX\ÃVVÅZ\ÄYXÆ\YÁ\^ÄWZÉ][ÉVTÆYZÎ]ZÍ]YÈ]^È\`È^`Ì[ZËZZÎZWÍZ^ÏYZÍ[]Ñ^`Ð\ZÔ^`Ñ^^Ñ_aÒ^ZÐ\ZÐbaÎ`bÐ^]Îa_Ð\]Ð`dÐ\^Ða`Ñ^\Ð\`Ñ^aÔ^^Ñ^aÒ\^Ó^bÐ\\Ð\\Ð^^Ð[[Í]aÊ\[ÌXYÎ[WÏZUÌYTÈTPÇTTÆWVÈWSÆWYÅYUÆVVÉVQÃXZÄVVÈXXÉWWË^\É``Ê]aËabÊefÍafÌbdÊbfÌ_^Ë]`Í_eÎ^]ÌZ[È^cË^`Î_`Í_^Î^`Î][ÌYXÎ^`Î_`Ì^^Ë^bË^ZÎ]XÌ\ZÍ][Ò^^Î]\Ê\^È[`ÈY_ÇUZÂTZ½R[¿S\¾S\¼R\¼PZ»OZ¹L\»NYÄT_ÆZdÎbdÐflÕopÕrnÙwsÚwoÚ|tÝvÝ€uÜxÞ‚vÝ‚tÞ†sß…sÞ‚oà…káƒlß‚oá€iÞ‚tà€ià‚làjà}iß~i߀lá‚pá…nâ‚rál߀jàlÞ~mÜ}nÝ~jÛzjÛziÛ{iÚvjÚubØtbÖtbÕp_Ön_Üdî­y÷ÈŽùÑ—øÖ¥ùÚªûÛ©ûÞªüפøÈå©z¾f[§EP®LR¯OX·MS¸QYºRZ¶T\¼Z_À\`ÅddÊd_Ã\\¥?Lt?Z=V=X@X>\>Z@^@d@fAdAa>b<`@`<a:_>_9Z>\>å†mäˆpå‰oæˆpä†käˆpäˆpçsé’yè”réxçˆjç‡lç†hèƒfè†cç„få‚eç‡jèˆnå‡räƒhæ‡oæ†oè†jçˆkç†låzfÜp\ØgXÇYU´EM¤7Kœ1H4I£:N¥<O«DT®DO²EP²DJ±HS¶HO±HS¯GO´LR°AL±JP®DO¯DM²IO¶FJ¹IP¼MR¼NQ¼RXÄUXÈXTÇYWÆTTÆTTÅZ_Æ\[Æ\[Ì]ZÌYXÉXXÌZYÎZZÌ\bÎ`_ÉYZÍZZÍ\\ÐYXÒ_^Ñ^bÎ`aÑ^bÐ^bÒ][Î\_Ñ\YÐ\bÎZYÒ`^Ó[ZÐ`]Ñ_`Ð^^Ð_bÒ`^Ò``Ò]^Ñ^]Ð__Ñ``Ð]\Ï\^Ò^^ÐZZÑ\ZÔcaÒ^\ÓZXÐ[WÐZXÏ[UÊWVÌZVÌXTÃXVÈURÆXUÄUVÄWTÃSRÅXRÂTR¾XWÆVUÈVWÉ\[Ç\]Ë^_Ê\`Í_bË_dÈadÎbeÍ^aÍ\^É\aË_`Ë^_Ê`eÌZ\Î`gÍbdÍehÎ[^Î\_ÏbfÍ^bÌ][Ê_bÍ\XÐ\YÎZZÏ]YÐ^]Ë_aÉYZÄY[ÈZ\ÈXZÄRWÂX]¾RV½S]ºQ\¸R]¶NY¶KX¸MZ¿R]ÄXdÎ\`ÑjjÒlj×qnÖtrØxpÙypÜzpÛ~sÜ€wÞ~pÜ„w߃tà…tßjß‚lá€jànàƒnÝ€rÞ‚lÜ€qß~gá€kà‚lß~lâ€nà~jâ‚nâ€qßmà~lÞ|jÞzfÛwfÛxkØvfÚtgØvjÙtbØsbÔqdÖq^×o\Ös_ä“oòº‡ùÌ”ùÕ¢øØ¦úÚ¬úÛ§üܧüÔ›ð¾…ÑŠl®MRªGP®LU±MV±OV´RY¸SYºZ]À]bÉheÁYY¤>Hw"A^>V<V=X>Y>]A_BaHg"If&KdCb@_DaD`B]?^<^:]>\;ä‰pä…käŠläˆlãˆläˆrä‹qè’uê–ué’vèŠmæ„hæ€eæ‚gæ€hæ‚bå€eä‚iç†gè‹dç‡må‡hã…nä†læŠnçˆlè…nå|fÞub×bWÉVS±DM£=L˜/E3F£=M§=N®AM­CP°DQ´EN´EO±GR²EQ²BN²HR²HO°FL®FP±FO²FPµHPºLR»IR¾PTÁU\ÅRVÆVVÆVXÈVXÆXYË\ZÈ^[ÈZYÊ\YÊ][Ì[ZÎ\XÌ\YÊ^`ËZYË\[ÎZ[Ê\^Î^\Ï^bÑ]]Ð`bÑblÐ[^Ò^^Î\_Ë[]ÍZXÎ_bÐc`Ô^^Ð`_Ó^_ÑbcÒ\_ÒabÑ[ZÓ^`ÐZ_Ò[YÐbbÑbbÒZZÒ^ZÐXYÏZYÒ[\Ò_\Î[\ÎZ^ÎX[ËZ^ÈXcÆdqÄhrȇÇuzņ‘Ày~Àv~¾jp¾kr¼[`½X^ÁWVÅWVÆXWÉ[XÃXZÈWZÇ^^Ç\_ÇZ_Ë[_ÈX\Í^aÍ^^É^`Ï^`Ì^cÍ]`Ð^aÌaeÎbcÍ`dÎ\\Ñ]]Ï]^Í\`Ì`cÎb^Ñ[UÐ^ZÌ]ZÎ]`Î]^Ç\^ÊZ^É]\ÈY_ÃS\¾T^½Q\»R\¸VaºPX¶JT·JZºLY¼P\ÅT`Ê^cÐhgÔlkÕnfÖvqÙtiØwpÚzrÚ}sÚ|vÝ|nÝ€uÞ‚tÞ‚rÞƒqßoÞ€l߀mà€mÜqÞlß‚pßjá€jâ‚kâ€iâià~hàoáià}hßzlÝzgÜzjÚwjÕuj×qdØwhØqeÚrcØtbÖrcØsbØp_ÖrdÜ{dì©xöÅŒùΘùÖ¤úÚ¨úÚ©ûܪýÙ£÷Ìæ­}ÀhZ¨FR­JT°KS²PX¸U\¹RZ¼^bÁb`¼X\£@Nv@[>X?W=X@X>\A_AdCa FeFg"IgFaEa@dAb>^9^<`;_>]<æ‹xä‰qåŠså†nä…låŠtçŒnê’uìréˆhæ†hå€hä|cæ}cäz_ãz[ç|bä€cçˆlèŠjçŒpç‰lä†qå‹uèˆlé‰pêƒbå~lát_Ùj^È\[²GS¥;K™3Jœ2H <R¦=N­>O®CL²FQµFN³HSµKT´LU°GN²FR²GQ²FM¯EN°FP³HN¹GN¸PW¹NU¾RY¾QYÄUTÌXUÅWXÈZYËVXËZXÉZVËYUÍ[ZÊ[YË\ZÐ]\Í[\Ì\`Ì^cË[\ÑZXÎ]aÏ^]Òa\Ð\\Ñ[^Ð`bÒ^bÔ`bÒ]]ÎZ]Ð\]Ï\^ÒljÒ_aÐ``ÒbbÒdmÏ]`Ô\`Ð]_ÒYYÑ_`Ñ[[Ó^\ÒhfÍ_eÒY\Ï\`ÌZ\ÎbnÈ_fÍz‚ÈpuÅuÂs{¿x…Å„‰ÊžÏ”‰Î šÔœ•Ρ¡Ðš’Ѩ£Ô¤”ͤ¢É œÀ€†Áu}¾[]ÁVYÂRTÅTTÂVVÁVZÆXZÈ\aÌZZÌZ_ÍZ]Í\^ÎY]Ê_bË]aÏbfÎbfÎ`hÎacÍ_dÍ_cÉY_Í[]Ë]aË\\ÑZZÐYZÌ__Î\^Í[ZÌZ]ÌY_ÇYYÅV\ÂT_ÀR[¼Q\½S[ºR^¼LV¹KT¸HT¹NY¸UaÆU_Ì`eÒgdÕklÔqnÖsmÕup×toÚulÙxrÚ{uÛzrÛxÝ€tÞ€o݃rßlÞ‚pÞ~jÞ~mÜnÝ}oÞ€lÞ€náiâgâ€lâ€ià|hà~ià|iß|hÞyhÞvfÚxfÚvhØwlØvdØvjØrc×tg×udÕpaÕvdÖsdÕqaØqbãpó¶ŠøÈ’ùÓœúצúÛªûܪýÛ©üÔœóĈזt°RW­W_®OX³SZ¹U]¼Y^¼_a¼VV˜8Jq B\:V?ZBZAY<Z@]@^BbDgGh"Fe#IcDfAcE`=]<]>]=\<^?\<æŠuäˆnå‰kæˆlä…nèŠmè’yê”sê–pé‰læ‚eå}eäw]âw^âu\ßxdâw]âjèŠnæ‰hæˆnå‡mä†pä†réŒrçŠpé„hæ}dàs_Üe\Í]Z¶HO¦<Mœ6Lœ2J 9K¨<L¬=O°@L°BQ²FR²FUµFQ±JX®FP³EM´HO´FM³CN²DL´FL¿FL¹PS¿PVÀNQÂLPÄQVÈUSÇYYÇVWÇYXÊYZÌ\[ÌZYÊ^[Ì[VÌ\YÏ^ZÌ]^Ì^^Ð\^Î^]ÐZZÒ\\Ñ^\Ó\\Ð^`ÑcdÒ\aÏ]^Ð^_Ï[_Ð^`Ó]_Ï^^Ë]_Ð]\ÐabÐb`Ò`bÒ\^Ò^\Ò^]Õ_[ÒX[ÒZZÐ]^Î\bÐirÍivÇr€Æq}Æ~‰Â}ŠÃ}‚¾|ˆÀ~ŠÈ‰ŒÊ––Í’ˆÏ”ϥΡ›Î£›ÎŸœÓ­Ñ¥˜Ö´¦Ù¨˜Ö°§Ú³¢Ó¤šÊ§¥È˜™Àv|¿`h¿WZ¾UX¾VY¿X^ÄV]Ê\_ÈZ`ÈZZÊ\^È]_Ê`dÉehÈdlÉagÌdiÌcdÌ`bÌ\^ÏaeÏZXÍ^^Ð]^Ï[^Î`_É[^Í\^Î^`ÌZ\ÇY^ÉUVÃX^ÁV\ÁNV¼OZ½NZ¼P[¶LX·IV·LX¸P]ÂX`Ì\cÐed×kjÖqjØsnÖqmÕtlÖxpØtl×{xÛzrÜ~pÜ~vÞ€pÞpÞqàqÜ{mÞ~nÞ~ná~kà}mÞjà€lâjägâ€gß{eá|hßzjÞ}fÝzhÝxdØwfÙtfÖvj×tdØvh×rb×paÙr`ÖscÖrbÖsdÕobÖubÚxeë¡wöÀŒøÍ˜úÔ¤úبûÚ¨üÜ©ýÚ§üÏ—ì´Êxa¯NU«KT¶UZ¹U\Â_\¼TVŸ@Nq@X :V<V>X:W>Z:`@`Ae!Ga@f$Id: lena.pnm,v 1.1.2.1 2006/12/02 01:20:05 dgp85 Exp $Jb"Gd"FbE^>[:Z:\;a<^;`<`=æˆqæˆræ…nä†näˆtçŽqì”sì”uë‘qè†häbãt]ßt\Þp^ßn\ßqcáv`ä‚jç‹oèŽmå‹næ‰lçˆqæˆqèŠlè‹nê„iæhÞscÜgXÎZV´FL£:G™2Hœ6F£9I¨:G«>N¯?L°BR·FP²ER±IQ²DN¯DM¯EN³GP´HP¶HO´EN¸FK¾JO¾MNÁNVÁOTÂQVÇTVÈY]ÈWVÊXZÊVRÌWTÌ\YÌZTÎ`_ÍZTÌ\XÍ\YÊ[ZÊ_\Ì\ZÎ[\Ð\[ÑegÐ`bÑ_`Ò__Ò^`Ô^bÔ^^ÔacÒ\\Ò]aÑY^Î]`Ð^]Ò_`Ôa\Óf_Ô]\Ô\\Ó^\Ô\YÑZXÏZ\Ì[fÌivÄw†Ç{„É‚ˆÇ}€Æƒ‡Çƒ†ÀƒÂŠÂ‹Ê“Ò —̘͌”͘‘Ïž˜Õ¦šÔ­¨Ñ¨›Í£žÒ¦›Ò©ŸÐ§–Ѧ”Ò£˜Ö¯¢Û¶§Ú´£Ø³£Ï¥žÄ”—¼pz¼]f»U[¼NWÄWYÇUXÈZ[ÆY[ÆX^È^bÌ`dÈdjËahÌ_eÐ^bÎ`cÌ\_Ï^^ÍZ^ÎZYÎ\_Í\ZÏ\[Ñ[^Ë\^ÎXYËVWÅT_ÆVZÅS[¾W`½SX¾MW¼OZ¼MWµLY°J\·KV¸P\ÄV\Í_fÒfaÓmlÔrlÙtjØsjÖsj×umÕuqÙvlÜzmÚzrÜ{nÞ€sÜnÞ€q߀nÜ~nà€l߀p߀màkÞ|hà~oâ|gâ~gá€iàzfß|hàzhÝvfÞubÜwgÚudØrd×qg×sb×pfÖpfÖpaØpb×p^ÖpfÖn^Ön_×pbÖveß„nð°‚øÆ‘úКøÖ§úÚªüÜ­üàªþئøÉŽâ¡v¾c[²PXºX\¿]]ºXXœ=Lq>[;S:U<Y=Z<Z>Z?^?bDcCcBfCdBdEbA`EZ>X9Z:^8a8]7_=^;æ‡tæ„læ‡kçˆræŠmëpì’pê’lêŠmçhäx`àr\ÝlWÜiZÜm]ÝkYàw^ä‚gèŠlèŒhæoæ‡på‰lèŠoéŽsé‰iê†hå|dár\ÚfWÏWR¸EM¦8Gš2E˜3F 6K§<L©8L²BO°DN³GT´FQ±FL±IR­DR²KO³DM¶CLµGQ´GP·JP¾HN¼HPÁMTÃPRÅRVÉTSËVVÍXWÍZVÆUVÊWTÍZXÐZXÒ]YÐ]ZÏ\VÐYVÌYUÎZZÎ\]Î^\Ð_^Ò_\Ð]]Ô`]ÒZZÑ`aÖ__Ô^^Õ_\Ò`_Ð^aÐ]^Ñ^^Ï\[Ð]^Ò[ZÓ^XÓ]YÑ\`ÒZ\Ð[]Ð[aÌfrÆt‚Ãv€Æ~‚Æ}€Ê†ŠÃz‚¾s|Â|‚ÄzÃ|ƒÊŠŽÒ–ŽÎ™Ì›‘Θ’Ηϣ ÔªÕ§›Ô§˜Ð¥œÑ¬žÍš‘ʔ̟–ЪŸÕ¨”Ó©šÖ³¢×­œÝº©Þ¸¥Ø³¢Ð¥˜Â„ŠºdoºPWÀRXÂSZÃY_ÆX^È[^É\aÈ`dÉ\aÌ[`Ï]`Ð^`Ê\eÊ]cË]`É[]Î^_ÌW[ÎYYËZ^Î^^ÇX`ÆT[ÄVaÉUWÂSX¾T`ÀRX¾OX¸P^·QZ´JX²IV»IV¼MZ¿X`ÎbcÔgeÖnjØoiØxuØsnÕtqÕroØupÚwoÚwrÚxqÛ|wÜzsÝ‚rÞ}qÞ~nÞqß{lÞ{gÞ|là~jß{lß{ià|hÞzhá|hÞxjÝzfÞsdÝweÝscÜreÚtdØpeÖn`ØqeÖo`Öod×ocØp^ÔrdÔsc×scØn\ÕpcÔqdÖudç–qô»†úË’ùÓ¢úاûܬûß®þà®þÖžóÂÖrºYZ¾YZ½XY£GQuA\<R=U >X>V>X=[>Z>`@dDfDbCb>d@`>`@\@\@[>^<`9b:\8Z9]8è„hæˆoç†iêŒsèrìoì’rêŽnè‡håeàsXÞlYÛ`RÚ^RÚeZÛl]äu^ä…gèŠjê‹iç‹mèŠnè‰pé‰lìkèŠpê†eæ€jãrZÜjZÎVP¶FL¤6F—.Cš6I£5J§:K¨<L°?J¬AP±CPµFN²AM±BP¯FL±FN¯FP³EM¹IQ³CL¶EPºJN¼MT¿RZÄVZÃRUÊTWÌVTÌSUÍWVÉZXÌYYÍYXÐZ]Ð[\Ð\YÎ^ZÑZWÎZXÎZ[Ò^ZÏbaÑa`Ð`]Ñ\\Ñ\\Ñ\bÒ]\Ö^`ÔYYÔ\\ÑXYÓ^ZÏUVÑ\\Ð^^Ð^]Ñ^\Ô\\ÐY]Î[cÊanÉ_pÀfxÆy‚È}†¾qÀz„ƆɄŠÀz„½u~¾tyÇ‚…Æ‚ƒÈ‚„ÌŒŒÐ“ŠÉŒ†Ì””ИŒÐœ™Ô¢•УѮ¦Ð¦ Î¤ŸÎ¡šÌ¢Ð ’У™Ô° Ò¦“Ó¬ŸÖ±Ú³¤Ù°¤Ý¼ªß· à¸¢Òª¢Á|‚ºU^¿PVÃUZÂUZÈRWÅ\_Æ\bÈ^hÌZbÍ^dÌ\bËbjÊ[^Ë\cÈZ\Í^bÌ[aÆY`ÊZ\ÊW[ÉY`ÉSYÅX]ÅTYÀR^¿PX½R]ºO[¹QXºPX³JX¯IY·P\»NZÂZ`Ï``ÒhfÙlgÚshÛshÚtk×rlØsnØsnÚvnÜvnÙxtÚzsÛ~xÜ~uÞ~sÞq߀nà|lÛylÞ{nß}mÛ{lÜzfÜvfÝvfÝzfÞvdàxcÞubÜtcÜrbÜp`ÜvhÚsd×ndÖnbÙod×lbØn`ÖocÔse×od×pd×o`ÖnbÔrcÓkbØv`íªzøÄŒúИùبûÛ«ûܯþà¯þÞ¬ýҘÉuf¼\Z§DOz"D\@T?T>XAXD\D`@`DbCcFdEd Eb@b>d@^>W?X>\FbHb=`:_?^9\9`<é„mæ…lçˆpêŒqë“pí–qì‘lêŠhè€eäxZÜmUØcSÖXOÔ[RÕ`YÛo`â{bæƒfê‹léjèŽkê‹nç‹lêuëpëŒpé‡læ‚iâubÚfXÍZTµBI 6J–-F–.D¡4E£5Hª;H°?K¬>M®@L¯AM±DO²@L²DL²FO±ER°BN´FP´IRµIQ¸FO¼IS½MTÂTZÅOQÈTVÊSRËUVÈWVËYVÎUTÎ\\ÌXZÒ\]ÐWWÎZXÑYUÏ[YÎZYÍ`^ÎYZÒ[ZÒZZÒ^^ÑZ\Ï_`Ò]\Ò`cÏ\^Ó\[ÑXZÐYXÐXZÎ]]Ï^`ÊbnÍeoÍpÌpyÅjw¾`k¶dvÃtxË€Äv~¾zƒÅx~Å|~Év{ÇzxÆzzÅ‚ŠÈ‚Æx~Ç‚‡É…Ȇ…ƖʇƒÎ’ŒÍ“Ì•‘Ó Ò¤ŸÔ¨ Ñ¢™Ò¦–Ï¢šÒ©™ÕžÒª¡Ô¯š×§–Ó« ÚµžÝ´¤Ø´¥Ûº®âÀªá»¦Þ¶¦Ìžœ¹jr¼PYÀPU¾T\ÀX`Æ]gÉ[bÆ`iÉ`hÇ^fÌ\bÈZ_ÉZbÌ\`Ï\^ÈY`ÈZ^ÌVZÊX^ÆXZÆUXÂS[ÂRW¾NV½QZ½R\¼NU»R]¸JS´O[³HV·Q^»NVÆY_Ð^_Ôji×poÚndÚshÜvmÙukÙriØtmÙuoÛwoÚyqÙwqØ}xÙ{vÜ|uÝ|mÞ|qÞ}iÛylÝvjÞzgÜxhÜweÜvcÜubÝxcÛwfÜt`ÜthÛraÜrbÚtcÜp`ÙpeÙqcØk`ÖndØm`ÚkXØpbÖo]ÙpbÚp`Øo^Øo^ÖpbÕl^Ôl`á‰fó¶„úÌ•ùÖ®üÚ®ûܬýß®ÿà­ÿÝ©üÌ“ážy²MR~#CX<W@S>U=W;Z?Z@_CdBgCe?cEcAb@cAaBZ@Z?`F`B`B]:\>Z9Z;_<`:æˆoçŠmèpìoí–zì“mê‹mèƒlæzbàrXÚdTÐVKÍSOÎRN×dZÝvhâ~lä†gèŒlìŒléŽiêŽlè‹léŠlêŒnéŠné„hè}`ãvdÜh[ÌVPµCL¡4F—*B”/Fœ2EŸAX¨>M®@O©>M­>L°AN°BK°FS±@I¯CM²DL±?L³@JµJS´JPºFO¹JR¼OT¿NSÄQRÃTWÆTTÇTTÌVTÉXXÉX\ÊVWÊZ\ËZXÅZ\ÌXUÊW\ÇXTÍ]XÌ]^Ì\YÑ^\Î^^ÐZ\Ñ\_Ñ]^Ò]^Ò[ZÑZZÒX]ÍU]ÌalÉZkÍkxÎ~ŒÍ~ˆË~„¾rz¾fm¸Xe¼Ydºix¼hrÄnsÀpxÄrvÄx|ÅrwÈqwÅvzÈ‚ƒÊ}€É„‚ÉxzȂʆ†ÈŒÇˆŠÊ”ŽÎ˜–Ì™‘Ï”‘Í–Ò¤—ҜϗŽÑ¨œÖ§”ϜҬœÙ¨–Ó«¢Ú¸§Ø®žÖ²¦Üº¦Ý¶Ü¶¢Ü¼®Þ¼­à¼¦à¹¥Öµ¨¾~ˆ·T_¹NV¿V_½[dÃV_ÄY`Å^eÉ\dÇV\ÇV[ÆXcÉ[`ÉY^ÇX]ÍZ\ÌX\ÇW\ÃTZÀRX¿R\ÅQWÁNW¾MXÀOUºLV¶MYµGT²FT²IW¸MZ½OVÅR\Î]`ÓfdÖmlØrkÜvnÚulØulØtjØsmÚsmÝtpÙvpØzw×wuÙxsÝ|pÞ}rÝ}nß|nÞzhÝugÝwfÛtbÝxhÜxfÚsbÜr_ÜveÜteÞudÛucÚqdÛp^ÙrfÚpcØpbØpeØn`ØpfÖl\Ùm`Øl^Öl`ÚoaØo^Ùo`ÕsbÔmaÔl\Ùq\ìŸsùÄúÏŸûתûÜ­ýÞ±ÿß®ÿà¬ÿÚ ñ¼ˆ©HP\>RAV@U?XAZAZ?X>bAeDf>d@bBd@eBdD_C^D[@^>aD`>]=\A]?\:_:b9æ‡rèŠmë’xì”ní•vípê†jæ€fãzfÞiZÐXPÆJJ¾EJÇOLØ`XÞrbã|dæ†iêmê‘pêŒkìŽoèŠmémëˆkíŒjê†jèƒgät[Þk\Ð[PµDM¡6H–3G“.G˜5M;N 7J¦=L¨CSªFP­GT¬AL¬AK±AJ®DM­AL²DK±EM´FQ³IS³HR¸KSÁJUÀMSÂLQÆTZÅSTÇUUÆRUÆXZÈZ\ÌUTÉW[ËTXÎWUÌ\_ÎYWÊZZÌVUÍ\[Î[^ÏZXÒ]`ÐZ[Ò]^Ð^\Î[^ÐUXÒX\ÑTZÕelß›ŠÐy€Ñ„Ê}|Ãv{¾ow¾biÀbiÂ\c¾\i¹_n¸dlÀlwÀlvÀnsºfm¿kp¾jrËzxÇqwÅutÈ„È|{Ê…ˆË€~È„…ˆ‚Í“”Ò…Ï’’ÍžšÑ›Ê”ŽÌ˜—Ò¢‘Ô¤—Ò«¡Õ£‘Óž×´¥Ü®—Ö¬™Ø¸¨Ü±–ܰŸÚ·¨ßº¢âº¡Ý´¦Û»°ßÀ«ä¾¦ÝºªÇµguµR_¸Xc¼PXÂS[ÂR\ÀWZÂX_ÉYZÂV^ÅX^ÆX^ÇV\ÆV]ÆX^ÆX]ÄV]ÂT[ÂPTÁPXÂPVÀQWºNX´L\·LW³KU²DR°EQ´KX¼OXÉRWÎ`hÖedØpiÚriÜtnÜvnÚul×tiÙrjÚqjÚwjÜwmÛvnØsmÚvrÜ}qÜ|rÞzkÞ|nß~rÞzlÜtdÚqcÛtdÜqeÚpbÜrbÝr`ÜueÝtcÚvgÜqbÜr`ÜpbÙqeÙpb×pgÙo`Øl`ØpaÚp_Ûn_Øo_×pfÙrcÛo`Ørd×o_Õm^Õk^à}dò±‚ûÅ‘úÒ üبýݰþá³ÿä³ÿÞ£ò¾€‘.CM 8P>R=W?V@\@Z=\>dBhCc@bBbBdE`=]?Z=\B_@g#I_@^BW<^B`?_6d=f:çŠrèrë“pí˜vì’qêŠjç‚håx`ßp]Õ^OÄKM°@J´@JÈUPÖdXÞugä~fæ†dêtìlëŽmêŽjêmêŠlìŒmê‹oë†iè~hãvaÝf[ÎXS¶FO 6J”,D0F™2J›8LŸ6H£:L§=L¬=N©@Nª@Nª?K­AN¬AM¬BI²FM²CL°CL³FO¶EL¸JQ¹LV¼NXÁPVÄQVÄTVÄPRÅTYÆWYÃZ^ÆXZÅTSÍXXÊVUÌZZÏXVÉYZÎZVÐXXÎ[\Ñ[YÐZYÐZ\ÐXZÐXXÎY\ÐXXÎw‚Ïb`Í`dÇaeÈmqÆllÀgj½cj»^jÀbh½\g¼[j¼\h´`r¿gnÁnzÂlp¾nvºfr¹erÂhpÅw¼htÅrxÆy|Ê~}ʈˆÈ„ňŠÌŽŠÐ–ÍŽ†ÍŽ‡Ð˜É“Í ›Ðœ—Ц Ö¬Ñ–Ò²¤×²£Õ¬œÖ± Û¯”Ö¥–ײ¢Ý¸žÚ®™×±¥Ü¼­Þ¹£Ý¸ªÞ¼°àÁ±âÁªÞº¥Õ°¨½‚ˆ¯Xf¶NZ»NXÀPXÀV]ÄT\ÃSZÄT[Å[`ÆV]ÇW[ÆUXÇU_ÆWYÂV[ÀUZ¿TZÃOW¾MS¾PZ¶KW³JY´LW²FS²GU²@J·KW¾KUÇT^Ö^`ÖhfÜlbÜqhÞwjßvnÛtmÚthÙslÚsjÜtnØwrÚvoÚwrÚunÛvnÛ{uÝxkàylÞ}oß}qÜwhÚuiÛrbÚn`ÚnbÝraÝsbÜsbÛvfÚtcÜqaÛsgÚp`ÚrbÚufÚpeÙpcØodÙpbØpbØo^Úp_ØsbÚqaØthØqfÙl_×oaÕpfØsfè–sø¼ŠýОüتþÞ°þâ¶ÿâ¬ýÔÑ|_Z8P>Q=T>W>Z?\@_?bBfBeDdAdCeA`<[<Y>Z>`@d!Db?]<\=X;\9`;b:hAf=éŽmê”ví›sî—rëvê„då€dãw^ÚiXÌQK¶BF¤3C²9EÈRNÕbVÝsbä€fç‡hìŽnêŽhêmèŽléjëŒníŒnìŠmêŠnè}hãv\ÝfZÏWO¶CIž4G+BŽ-C–2F›0E¢4G¤:I¦?N¦?L¦@O¨=J¬CN¬AK¯DJ®CM­BL¯FS±FT·FN´HSµHN¸MV»FK»OVÁRYÇQRÄTWÄS[ÃVYÉSRÈUVÇRUÊZ[ÊWZÇ[]ÈZ\ËXWÊW[Í^_ËZ\ÑZZÎWYÎ[^ÏWUÐXYÎV\Ög_ìšrÊNMÀV[¾_d¿\d¼_c»`e¼X]»]g¼\e¹\f¾`n½^cºbl¾ms¼nvÁlp»ip¸doºhpÄptÀsxÂprÄpwÆtwÆ|~Â~…Át|Ë…†Ë„~Î’‹É…‚ĉŠÌ–’͌ӧ—Ó›ŒÐš–Õ¦˜Ù®ŸÙ± Ö²¥Ú°œÖ¥–Ô¯£Ú²˜Û²ŸÛµ¦Ú¶Þ°–Ú­¢Ú¸®à»¦àº¨Ü¸¬Ú»±Ü¾«â¾ªÛ·¢Ã–™´cm²LX³NX¸NW½NX¾T\ÁYd¼T]ÅU\ÄSXÃTYÅS[ÇSXÂTZ¾S]ÀTY¾Q\½NVÀOV»MX´P_·GT´LX±FS®FT¶FR¼LZÁS\Ï_aÖffÚnhÜtiàvjÞyoÜujÝtgÛsjÛsjÜqiØtnØrjØtnØsnÚupÙtnÚunÞ|kÞ|qÞyiÜxoÚpdÚpbØnaÚndÞo`Ûo^ÜpbÞqaÜvfÞp`ÜoaÙqdÚscÛrdÚpeÚo`Øk`ÛpbÙn^Øl_ØpaÚueÙrfÚse×tjÚrdÖpcÒqe×n`Üykï¤|ýÊ•þצÿß²ÿà­þÕ•ê¥p‚)AL :Q>Q 9U=X>YB^@dCgGfCcBdBhBb@[:Y<X<]@a@c@`BY=Y:\:]:c<g>c9\8ì’pë™xîœrî”mì‹kéƒiåxbßq`Õ`W¿JI¢:J–+B¯>FÇQOÖe\àtaæ~eèŒkéŽnìkêŽlëjçqè‰jì‰kêŠnê…hçzbãrYÞf[ÐVN¸FNœ2E-FŽ)C“.G™4HŸ8M¢>N¥;L«:Gª>L¨@K¯>K¬@M­CO«BQ¬EP®DO®EN²HT´BN¸GM·FR¸DNºNTÀNVÁPSÃQUÀRXÂVVÃQTÅPSÅTXÊ`cÊZ[ÈXXÌ\[ÉZ[ËZ^ÎZYÏVVÑZXÌZZÌZ[ÌXXÌQWÏXZåœ}Îo\ :T¶NY¼\cÀZbº`i¼X[À^e¸X`º`jº[eº\e¸Wb¾biÂjpÁflÃko¼eg¹fp¼jr¾lvÀnuÁkoÆs{Ànw¾x€ÄrtÅz‚Ɔ„ŃƒÄƒˆÈŒˆË‰‰Ò¥˜Ôž”Л•ΣšÔ¤™Ô¦šÖ°£Ø®šÕ£–Ø´¢Ú´£Ù¨”ر¤Û¸¤Þ®—תžØµ¤à¹ Ý¶£Üº­Þ¿°Þ¼¦à»­Ú»¬Ú¼®Úº¨Ýº¡Ô®¡¸t{­N[¯FT´IV´OZ¸U`ºPW¿NS¾RY¼RXÃR[ÁTZÂRXÀT\¾PYÁLV¼OY¸JU¹LY´LZ³KX¸HQ®FR°AQ³FVºNZÅW^Ñ_aÙjfÝmgÞtlâwlàxnàylÞxlÞtfØuqÙrmÖspØtlØqlØrm×pmÖpi×upÙunÞxpÞ{kÞ{nÚrbØphÚlbØn`ÝnaÜneÜp`ÞsdÞtbÛteÚpdØoaÚrfÚodØqaØpeÚo`ÚpbØohÙoaÚqeÙsgÙteÙp`ÚtdÙugÖrf×ufÖteØshâƒmù¾ˆÿÒžÿÛ¥ÿÒ–ï«xŸBHT=N>Q>T@T@V<\Bb?gCf Fd@f EgAhC`BX>Y=]?cBbA^@X:Z?[>`;d>k?d>T2I2ì“rî–wî•wìré…jæ}fâtdÚdVÊTR«<F—*B–*B¨;IÅRMÔbZÝo\ä|`èŒlêŒkì’jëqêŠlêjèŠmìŠlêŠlêƒiè|bâmYÝcUÏUQ¶CK4D)BŽ)B˜2F›6H :K =L¤@N¬<L©BPªCR«@N¬AO©DO«BP«DP¯GT°CL®DP´FN´HPµKT½LS»NU¾PUÁPSÄNP¿OUÅRTÄRRÄVZÄTVÆWYÇV[ÄVZËUWËZYÎZ^ÌVYÉ]_ÐZXÎZZÐZXÐXXÏ\\ÐXVâuXÂRT²IZ½PX¿V_ÄVYÃ^c»V`½Xb¾_iÁei½[h·Yd¸\dºdp¼dnÃilÀkr¸fq·fq½go¾jsÂouÆrvÁjnÄknÅpuÅxvÃx}ÄvyÆ€|ˆ‡Ì‰†Ð’†Ð“‹Ò¤ Ó¢Ó ›Õ¤˜Ö¤Ô¦šÔ¬ Ø¬˜ØªØ¯ Ø°šÞ°ŸÙª¢Ü¹§à´ŸÜ¯œÜ´§ß¸¡áº¢Þ¸¬Û¼²ß²ݼ¬Ú¶¦Ú½³Ü¾µâÁ¬Û¾¨Á–š¬Wc±DT´MX±JU¶GP¹JS·LW½QX¾OWÀQZ¾PXÀOXÂOU¼N[ºLU¶OZ´O]²HX¶JW´JV±HR­ET´GU¹NZÄP[Ò`eØjdßpiÞvnâzqâ{mÞzmßxqÞwlÚtjÙtnØrjÖro×mhÔtmÖnkÔokÔmfÚnhÛrlÝ{mÞzpÝsdÛtjÛpeÙndÜo`Þr`ÞraàsdÞugÜteÛpdÛr`ÛpfÜoaÜqaÛpd×nbØqhÚpgÙpdÚrjÛqhÝtfÚnbÛseÜtdÚukÚugÝxlÛxnßxjó¢~ÿÈ’ÿÌŒï§q£HNY?Q;T>V@U>V<[=\=dAa>d@cBfBgA`AZ@\A]@`BdA_AV=Z@[>\=bBi"Cg!DW9F3D3î•~î”pî“oìŒkç„hçx^ßlYÒZT¸FNš.>*C–0F¬?LÈRNÒc\Þp\ãyaç‰gìŽlì’jêrê‰nêŒiìqìŒné‹mæƒkæ{`álXÜfXÍVQ³EK›/D(CŽ(B“2J›8L¢4G¢;R¢@RªFW«HVªGY­HX©BP­GR¬COªAQ­EP¬DR¬IU³DR´KV·JT¸IT¼NRÁRXÄTY½JPÁMQÃSVÁSXÂUXÂUZÅVZÇUYÆUVÊUZËX[ÊXXÌ\[Ì[\ÐYXÎWZÑZ\ÒXYÏZVÐpg»NR»MU½RZ½KVÂV]ÂW_¿V]½V_½Za¾Z^¿_h¾\e¼\g¼\eÀdmÅlpÃnqÀks¾en¾ku¾jsÄovÆorÄirÃacºktÀt{¼krºjtÈ{Êyż…Њ…Í’ŠÓ—‰ÔšÓ¤—Ø¢ŽÑšÒ­ Ø¥‘Ï –Ó©£Û¯˜Ö£”Ô¦žØ¸«Þ¶£Ü±ŸÛ¸©ßº¥ß±žÛµªÞ¾¯á¾¥àº§Ý»¬ÛÀ²Ý¾¦Þ»ªÜ¼®ßúâóáÁ©Ë¡šªYg¦CUªBP¬HS¯HQ²JS¶JR¼MT¼PWÀRX»NX»PY¹NX¸NZ¶MV³K^´IVµJU³LX¯IY®AN²FTºJXÅR\ÑZ]Ùihßnfßwnâzräznãzjâynß|qÜyrÜwnÚrlØmiÔjlÕlkÔjhÓklÒgd×lhØoiÛwkÝylÝvhÝthÜpbÜpbÞp_ÞreÞofÜsfÞt`ÝtiÜpaÛo`ÙpiÚqbØpfÚpdØoeÛsiÜrcÛrgÜteÚpeßsdÝtgÛtjÜtjÜwiÚujÞznß}pà{nî’uù´}æŽi›<FX<W?WBW>V=X<Z>]>`<d<`@d@cCd?a@Y@ZBcFeDg@bB^EX<]A\@d>n(Jp,ObAI
+3?0R9î”zï”tïlì…eèfâr\×cWÄTS¨;H”.D(Aš3E°BJÃQSÕbXßp[ä|hé‡jênì’pë’têŽtêŽrê‹në‰lê†gé„jç{bàoZÙg\ÎTP²BI™-BŒ,BŒ(@”1E6JŸ:K¢>P¨?O©DV©DU§AR¨L^§DT®CNª>M­BN°@M¬EQ¬?N°EO²GR´KU·LXºKR¼PX¾NXÂTZ¾TZÀRUÃQYÂTWÆRTÈXYÆUXÄTTÍUVÊWWÌTXÌZZÐXXÑYXÍUVÎV[ÏSW×ppÕdWºMU»Q[ÂSVÀVX¾RW¼PW¶MVºSaÁU\¸Vb¿^dÁ\gÃbiÁ^bÀ`iÃjmÀ^a¾gn¿mpÁjrÆljÌmoÈnmÀeo¼enÁrzÈnrÉ|yÇrpÈ{€È~|Àw͆Ά‚ΖӘŠÐ‘ˆÔ£•Õ™ŽÓœÖ­¡Ø°Úª–Õ¨ ×´¦ß¸ŸÜ±¢Ú¶¨Ý¹¦Üµ¢Ûµ©ß»ªà¸¢à¹©Ü»®Ý¿®ß»¥Úº©Ù¹®ÚÀ´ÝÀ²àÁ³à·áõãÄ­Î¥š«bož>MŸBN¤>J¬BN®DNµIR³LW¸R[¹KR¹PW¸LX´JX°HW¶JV³L^¹PVµIU²ET±BR¯FV¸IXÁS\Ð^e×jjÞqnàvhã}nã|kã|mä~pàylßzoÞtlÚsjÙmfÔhdÑfdÍfiÎcfÐb_ÒbaÔieØpiÜxpÞymÞviÞrbÞobßp`ÞpeÝqeÞtgÞuiÞsdÞq_ÜpeÞpdÚp`ÛoeÝobÙrfÝqfÛshÛrcÛsgÜrdÞvfÞqbÜvhßxjÞyiÝxjÞwjãnålç„lÖo\’2C_AU?ZBVAV=Z@[?a?`=b@f>e>f@f;b>[<U;^Bg$JdC`>ZEV@Z>bEbCq)Ls.QfBT;D6K;E]ï•xî’rì‰nèƒlæxdÜl^ÏVS·DH1B“-D–*Bœ4F®BOÄVXÕdYÝn\æ€hè‰hìlî‘nèqìsêsê‹mî‹oêŠiè„iæxaâr\ÛbWÊVU°CK›,BŽ*D*@—2Gž6H¡:M¤@P¦=M¨BTªAO«DR¬GS¬CQ®GSªBR°DQ¬BQ«BO®DP±ER·HR´HR¶MV¸KT¼QY¾PWÂPVÂPZÁNTÀPUÂSWÆVUÌVZÈTVÇUVÊVUÈX[ËX\ÈZZÏXYÐYVÎWWÍW[Õf`é§~ÇPQ½MX¼SWÂPS¼OU¹MV¶KW»PW¼S]¾V]¼Y[¾ahÄfk¾[a¼`gÆhe¿_d¼]bÂgjÇlpÄjlÄopÆnp»jwÃkoÆuxÁmsÉppÄlsÂwzÃqxÀ{…˃„Åz|ȇʇɖ‘ÏŠÎŽŒÐŸš×¬™Ø ”Ö¨¡×°ŸÜ¨—Ú­¢Û³¤Ý¹¡Ý´£Û²§Üºªß¶¢Ýµ¨Þ¼±âÁ¯à·¢Þ¼¨Ü¼®Ûº¤Þ»©ß¼«Ü¾²Ü¾±Þ¶¢Ú´¨Ý¾µßƺҲ´¬~Œ©t¢Sbž<K¤@O«DQ´GR´O[·KV¸OX·JS¶JU²JX·HS³ETµJZ´DU¬DU¬BT¬CX¸KWÁN^Ñ^d×npßwsáznä|lå|lå‚sç€rã~oÞxpàwjÜxn×ohÕebÏbdÉ\`Å]dÈZ[Î\`Òbg×njÝrkÞzkÞvlßseÞpeÞn`ßrcâucâudàxjßwbÞl_ÜnbÜpbÜn^ÚodÜqfÛpfÜseÜtdÚshÜreÜtjÝzoÝtdÞvhÞxhàweàxjâzlã€pè€hØkb™7J`@X>V=V<Y=V:V9Y?aAg Ch!Cf?d<`=_:Z=X:^>dAgBdF\GZAYD]BfDh$Gr+Ng"EV:J5O;„:SËurîvìŒpê‡læ~fäq\Ù`TÃLN¦5G˜9M•2J“,D˜4H®CNÇUSÔdXÝq]æ{bèŠhëiìoìjì‘pënéŠrë‰kë‡iê„fæ|cát`ÚbUÉVR±@I›,DŽ*D*D˜1Fœ4F 3I¦@R§?L«GY¨@M¬>P¬@R¬@MªDR«CR­CO­DO®ER¯DO°FNµHPµJQ´LT³OTºMT¿NSÄSRÄT\ÀQTÁQVÃRVÆZ[ÄUVÆSVÄXZÈSXÊX\ÍVXËSVËWXÒ\\ÌYXÐTZßwpÜmUÁNUÂQP¾NSºIP¸JS·IP¸P]¿QV¾X`¾Y]¾T\Â]a¾X_¾ciÉbeÂ\aÀ_cÂflÂlnÂei¼hrÆchÌnnÍquÅpqÈprÃjl¿lxÃsz¾ekÇxzÌzÈ||Í~zÇ€|Í‘ˆË‚~Ëš’Ô¤”Ô™’Õ¦Ù­–تŸÚ©ŸÙ³ªÜ²œÚ¨Ú±¢Û¸¤á´œÛ°žÜ·¬ß¸§àºªÞ¸«Ý»°à¼§Þ¸¢Ö¶§Ø»¬Ú¸¥Ó¬¢Ñ°¯Ò½¼ØÅÇàÎÈæÔÍëÙÐæÛÐà×Ëξ¸«`hœ5H¦;M¬DQ±MZ¸IR±KW³LW³HP®DT±HTµGU±IV°FX«FXªBY³EV¸K\ÀS^ÒbdÖnmßsmá{på~nä€månæ€nâ~sá{nà|sÝxlØodÓd`Ì\_ÂV^¿PZÀTXÅT\Î`_ÖedÚpiÝulàxkßufßpdàrdßsgàrbâxgßvjßtdÞn^ÞneÝpcÝp`ÛpdÜpcÝrlÞrgÝrdÝqfÞreÞukÜqeÜrhÝuiàwiáxjâ{häoæoÞwh¸KPk@XAU@V?W=W<V:\>bDc?fBc@h@f<d:\>Y=^AeCe DfG]BXC\A\@`Dh!Fr2Sh$HS;J<N<y0Nºioà‰{êŒvê‡mèiäwdÜj\ÌVR´?G™.D˜3G›6I™1E/F¬AMÈTSÕbZßqbæ|cé…hëŽnìsì’pîpí‘uìnìŠhê†jè…dæ~dár]ÚfYÊTP°ENœ2F(D/F–2FŸ:L 5J¥?M§FT«H[¬BQ«@O«EQ«FQªBQ¬DT¬AP®FT°CO°DO°GR´GU·IPºNY»PX½TYÀU]ÁTWÂNTÀPRÂPV¿UXÀQXÊXYÈTUÆV]ÈV\ÉYZÎVZÊVXÌVXÒXXÒVXÒ\Väx^ÅUWÀSS¼LR¸JT·FO·LX¸KS»U_ÁW]¼X]½SX¼U\»PXÃbfÂZ\Âdl¾XbÀbgÅhm¾dlÃdh¿afÂgmËlnÁilÄnsÆln¾jrÉrpÂrxÂsxÇz|ÌzzÍywÍ€Ì|zË‹ˆÎ–Ò”ŽÒ—“׬–Ý©šØ¦›Ø´©Ý¶ Ü¬›×§œÛ·¢Ü±Û¨šÛ·§Üºªá·¦Ú®¤Ü¿³à¼¦Þ³¡Ú·©Ú·¨Ö­žÒ­©Ò¸¼ÚľäÎÃèÎÂêÐÃìÓÅìÓÇïÖÆòÝÏòàÑòàÉÒ´­ŸDV›4LŸ8J¨ER®FT®LV°HP®EP®CQ±CO°FU±GV¬FX¨FX©>T²GX³K\¼O`Ð_cØlhÞukâwlå{næ€pä~lç€pä|nãzkæ{lß|rÛriÕgbÌX^ÃPX´DN³JV¹IVÄTZÐ]^ØkjÛoiàwnàxnÞtißr`ÝrhàrcârdàteàsdÝpfÝn`ÝrhÞpcÜreÜpdÜodÞqfÝqeÝpdàobßtgßrbßvlàwkàwlãznâ~qæ€nä|gÂVVz'HXCU@X>X@V 8[AX<`@`>d@h@c=c<`8[:Z<]<d?jEb?_HVDX@^D^Bf$Kq.Py7Yf FO9Q@m'N¡YiÓ~täxë…fè†næycßn`Ô^W¿MO :K™.A˜2G˜3Hœ5Gž3H¬FRÉWTÖd^àtdå|fé‡gë‹iìlê‘nìŽnìpëŽmìŒjèŠmæ„læ|bàq]ÚaVÍRL°@K›5F*DŠ&B”2H4J¤8M¤<L§?Sª>Nª?P¬@O«?N­FR¬ER«@N®ER¯FR®DQ¯CO³ET³JPµLV¸MVºLSºNU¾QXÁRW¼PVÄPUÄV[ÄX\È[\ÊX_ÊVWÇ\bÊVZÆ\ZÈX^ÈTTËTWÐZ\ÐZ]ÔgbÐ[VÄQR¼KR¼HPºMXµKT¹NW½O[ÀT]À^^ºRX¼RX¼X_Æ]cÃ^dÃ\c½\d¿]bÂ^b¿em¼dl¼cjÀ[bÀjlÅdoÂlrÆhlÊqoÅjiÁisÃhlÂrv΂ÈllË|xÏ€}ËŠŠÎŒ‡É~‚ӟء֠”Ú°¢Þ²šÜ©žØ¦œÛ¶¨Û«šØ§œÙ²¨Ý¸¤Þ°žÝ´¤Û¸¬à¹¦Þ² Ù¯žÙ±£Øª›Ó°²Ô¿½àËÂåÏÃæÌÄè̾èÔÆæÎÅèÎÀçÑÆêÓÄîÖÆïÞÒôáÎïÚ¾»|’1Hš4K¡>M©CR¬GT®DQ®HV®CT¬FT¬FW­BS¬DT¥DV¤@V­DXµN\¾Q^Ï`cØgbÞsláwiå}nä~lä}kæ€kä}nå|nâ}qà|oÞrfÚg`ÌZY¼JP¬?J¤;M§;M³IXÅU^Óca×kmÞtpâxlàujàsdÝoaàpbào`àtcârdßpbÝpdÞncßqdÞodÞqhÞuiÝqgÜtiÜreÝrdÞrfàsbásháwháthâzlå€næzkÐ_Z.JZ>VET=X?X<\>^>`>c?f Da>e@f>b@]AX=Z=cBjBhC\AVAXBX=^B`Go-R|:[t5XdHW=o)K XhÅxzÛƒuä’wéˆvèhâtcÛdVÊQP­@K™.Fš0Hš4H™4Gš0Hž5H®CNÄTUÖd\àq`å|bê…fìŒkì’kênìqì‘rêjêtè‡pèƒkæz`Þm[ØaZÌOP³>Kœ0F+C+Fš2F 6I¤;L¨>Rª>L¬<O®GT­DT«DP­DP©CP«BP¬BN¬AO®DT®HQ²HS²ITµJRºNT¸OZÀOTÀNV¾RTÀRVÀPTÃRVÅSUÄXYÉVXÆTXÄZ`ÍWZÈWXÈTYÎYXÌXWÐ[\Ò\]Ñ]VÈQT»IN»LQ»NTºLU½NU¼T_¼U`ÀZbÀWa½RY¼[cÂ]`ÀX^¿[fÀ[^½Z`¾Z`¾_d¸T]Àcf¿`dÀhnÂckÆru¾bkÂlqÃbdÄnrÉhkÄlpÊrqÇprÉopÇimÐ~zÉzw͈„Ô•ˆÔ…Ó˜ŽÚ«—Ü® Ö¢œØ±žß³œÚª ×¬¢Þ¹«Þ­šÖ§žÚµ¨Ýº¢Û®™Ö§›Ò ˜Ò¨¡Ò´´ØÀ¼äÌÂçÏÂèÏĿɏåÌÀæÌ¿æÌºçÐÂçʼèͼéÒÃêÐÃîÙÉïÞÐðÞÈØÄ¸¤^l0Iš7J¢>N¨FS«BQ¬ES°ES­DP¦BS¨FVªDS¨BV£=U§BV´KZ»P\Î`dØjhÝrlâuhäzjåmä{iæ~lå|mâznä|oàzrÜskØljÏ_`¾NW¢8J•1H–2J¡6MºJXÊ[_ÒhiÜnjÝtkàvpßseÝrfàobâreàufár`ÝpbÛoaÝofÜrjÝpbÝndÞpfßqhÞvjÜrgÜshßshßsiâulâviãviåtæ€pÛmc¢<O`@T>T?U 8Z8Z8[;b>c>d@d@d@f=b>`@W<Y<b<i>i?`BU?ZBYB\AcFi(Or-Ts0Tn+P`?p&J›SdÀprÒ~wÙ‡vß‹uè|dãybßm^ÑZQ·EO 5J”.Dœ4K4I5H6J¢8H±DOÆTTÒbVßq_å|dè„fënì‘lì’lì‘pìŽnênëŒoéˆmédåz_àn[Ø`TÈMQ®MLž5J+E,F˜2HŸ6H¥8J¦?N§@N¬?QªBP¯@N¬BO¬CT¬@P®L[®HW«DR®FS®AN³HU²BO¶JRºNV¸OWÂQT¾TX¿QTÃQXÁRZÃVYÄSVÆX[ÊTXÊWVÆW]ÌVVÊZ[ÊVYÌ]XÌYYÏ[\ÖaXÉPRºHP¸MT¹IQ½KRºLT¼OTÂX`¿V`¾V`¹T`À]bÂ\cÀVZ¿Zb¿Zc¾]b·T^¿^]ºXb¼al¾`gÄfgÁgnÊjmÈlnÌroÈipÊvvÄcfÂprÇklÃqvÇrsÄjnËz|ÎvwÍ€Ò‹†Ï†…Õ™×›Ž×œŽÜ¯£ß®˜Ü©šÚ¬¡Þµ¦àº¥Ý°¤Ù²¦Ú´œÜ¦Ô¤–ΜšÏ¤¨Ñ²¶ÞÄ¿åÌÀæÎÂèʹæÌÀå˽äɾäÉ¿äÍÂäɼæÌºæÍÀäÅ»æÊµéÐÃéÓÈîÛÐïÛÍðßÄд­—BT”2F˜7LŸ<M¨>P¦>MªDR­@O¬@Q©DV©@Q¨AU¨?R­>T³KZ¿PYÍ]d×efÝnjàxläpä€mâ|kä{mãznã~pä|páxpÝqjÙleÍ_\¼NW™:J„%C€"AŒ(D¨@RÃTZÎceÕhiÛrlÞvjàujàtkàn`ârfàveàtiÞrgÛpdßqdÞrhÞn`ÝndÝrfàthàobÜpdÞqfÞsjàtjäxiâvmåylénßvi¹LPmCU=U9T :V 7[:]@b?d@f@fBc>f@c@`<X>W=_@d>iBbAZ=W@\?^B`Bg"Mq1Wv6[l)Pg%Jz1R˜Nc»mrÎxÏ}tÖ~uÕ†yèvaâr^ØaRÃLL¤7G›.Bœ6L¢5H¡:Lž9Jž1D¢;N®BLÅTVÔdXßo[ä{hçˆnëŽhîpìlìrëŽrëŒnêŽnêŠmè‚däzbàn[×bUÉTR°FMŸ6J‘-E2L˜3G:L¤8L¤:L¦<N©@Q®@M®CP®BN«BP¯FQ®JX°DQ°BQªAR®DQ²DN²HT¶JRµKR¼LS¾NUÀQTÁPQÆPOÅPUÇRTÃRVÄVZËVWÊUUÊVVËVWÊZ^ÌYXÌ\[ÌZ\Ð]YÇW\ºLT¸FP¶HR¸HNºPZ½RV¾T^¿X`¸MX½XaÂ`hÂY_¼X_¾[bÀZaºU\ºZa¼U]¸V^½^fÄbfÅghÄkoÄbbÆntÎttÆhnÌolËlnÇooÈilÄrvÉzyÇosÌwuÉkqÏ€|Ö†€Ò€€ÔŒƒÔ‘‹Ö˜‘Û£–ݪ™Øš”Ù®›Ýª“ܨšÚ¯ Þ·¢Ú­žÏŽ‡Ï–”Π¥Õ¸¹áÉÄäÌÃêÓÈèË»æÈ»åÃ®äÆµäɺå˾å̽ãǺäÈ»äÆ¹è̺æÏÂâÆ¹èʶéÓÇëÔÆîÛÎìÚÌêØ¿º”—”:N”-Fœ2F¡;L¢>O¥CU£@T§AS¦F[¢@R£?T¦:O©@T´IXÁPXÏ[_ÖfcÝokàznä~pä~mázmä|kä|lâ}oâ|qÞzsßqkÚlfÑbdºQWž7M~=q@x=ž4I·LWÊX\ÒfhØlmÞumàvmÞvgßriàocÞofáreßsiÜndÜmdßtlÝoeÞphÜpgàrhàpfÞnbÞodàpfäneæpfäxoê~lè|mÈc`†%@[:R 9U8X 6Y :Z:^=eBgCgChCdBgCaBY@T ;\Bd?hBa>\@Y@\B_Cf1Vh2Zm'Rr6Zp1Xn*Rx2T™Lc·lsÉ|xÐwÌzuÍzsÖ}râq^ÜfVÊTP°>Jœ2Iš2Eœ7K 8I¢8G¡4C2Dž7K®EOÃTVÖe[Ýscä{bæ†péŒnìŽlëoìŽqëŒlêqêqèŠkèeãy_Ýo\ÖbXÈRO°CMž5I‘,F’(C–2Gž3G¥:O¤;N§@P«;Q¬>M¬?R°FT«FR¯FS°HU­FU¯EO­CT°DO®ES¶KS¹KT¸LT¸KS»OVÁPVÀSUÄRUÁT[ÄQWÅVXÅW\ÈVVÌVXÊXXÍXXÈYYÈXXÍ\^Ò`\ÉRR»OXºJQ»JO¶LXºHP¼PUºS]ºNV½PXºU^ÆZ\ÁY_¹UZºQXÂ`g¼TX¼V`¶U_ºU`ÀW\ÃcgÅ^bÆgjÂ^gÂlpÊkmÊorËjiÇdjÌqsÊfjËnpÐtxÆmrÏrrËtvÎzÑwtÎ}wÒ†Ñ~|ד†Ø”†Õ“Ø£˜Þ©–Ù¡˜Ö¡”Ú³£Û¦ŽÒ•ŠÏ”’Ê•—Õ´´áÀ·æÍÄéÍÂèÌÁêʸåÈ¼ãÆºà¼áÅ´åʼãžãÈ»âÈ¿âÄ·âɼåǺèɹæÎ¼âƺå˹åÍÂêÐÃìßÒíÚÈäÓ»¸ˆ‹2G“0H›0FŸ9N <P£BS¢?T¢AT£@S BV¤>RªAS·GTÂPZÎZ\ØgdÜqnáznä~qå|lå~mç~kä{là|pâxnÜytßvkÚljÌaf¾V[ @R‚"Dh=p>Š$@¦;LÀQXÊ\aÖhgÜpiàuoàzoátjßpfàpfápdÞthÛqgÜogßpbÞqfÞpgÞqiÞrdàshÝn_àreàqfäqfæuiç{qé}jÜl_5FbAT8V?Y>Z;Z<`@dBjBgDdBfAf@`@\AU@Y>h Dj"Bd?\=X?YB^Aa#Je&Oh)Sl-Vt8az/Z~3Y–Pi³iuÈzxÍ~ЂzÈwsÇrqËulàfRÔ^N¼FJ¡7G˜2Hœ6HŸ8J¢6G¡:GŸ7E 6HŸ4E­EMÃQRÔ`ZÜq_äybèfêŠrëŽoënìŽnêpêŒlìŠnèŒlèƒbäycànZ×`UÊPL´DNž2G‘(B,E˜4Jœ;N¢<P¤?P¨ATª>Pª@S¬DV®GU©CN®HV±FPªDN­ER«CP­CR²HQ´IRºJP·JR¹LT»PUÀPSÀSUÂTXÃPTÄTXÇWVÈZ`ÈZZÉXZÈQTÌZ\ÈWZÉXYÐ^YÉXU¼JQ¶NX¸GN¼KQ¸OXµKWºQ[¾RY¶MZ¾[`Å\aÀRW»X_¸T_¼Z[¼W\²QZµQ^½Z`À^dÁ[\ÄdjÄc`¼X_ÇfjÆkoÇvsÆgfÂnpÍtrËlmÏrnÏqqÌuxÎvtÏrsÒ|xÏzzÌ|}ÌyvÏ|ÔŒ‰Ó†ˆÑ‰Ù¤–ܪ™ÚÙ¥–Û¬š×¡•Ì„~ƔϦ¯Ý¹±èȺæÈ¼ê˶åËÀãĵßļâ¼âȾäʸÞÀ¶æÈ´äÊÁâÈ¿ãǽáǺãµäȸàżãǹåÎÆãÐÇäÒÌèÔËíÝÑîßÔíØÂÜÆ¹¡[kŽ/E“1I—6Fš8Mœ7M>NCU¡?R¢@R <P¦?R®FU¼Q]Î]_×ddÛnláxoå~tå€tä€sæoå|jã{mãznà|sßxqÜolÓefÂV_¦AP„%Bd8^9y:˜1G³FSÃR[Ñ__ÚkhÞumÞuláwkàrcßpdàrfÞpeÜqfÛmcÞpgÞnhÞrjÜnfÞqnàrgÞpfÞuhàvpãwnçxnç~rÞscµBNk@VAb8\`0S^IZ<\=eCfAgAe@gBfBcB^@X@X>b@jBfB]AY>[@\?`=d$Lh%Nm+Vt4_u0\‚:`–Kh­fwÅvxÍ|zÐxÓƒwÂqn¾nl΂zØZNÈQN¬=H›1I›6I¡8L ?Nž8J¢:M5G9JŸ6G«>LÇTSÕ^XÞr`ã{gæ„hèŠrêŒpëoì’têŒnêŠlìŒnêŠgè…dåz`àlZÖ^SÈRR°@Hž6IŽ,G+F•8L›8L£<N¨?Q¨AQªAP©;N¬?L«DO¨@P­AM¯DQ«@P­@N¬BN®FS³HS´HN¶FQ¸IQ¸QY½PT¿PVÀSVÃRUÄRUÇTTÈUWÇUVÊTWÇ[\ÆVXÈWXÉYYÌZ^Î[S»MR¸JQºJO¹KR½MWÀRZ¼QZ¼PZ¼NX¾W_ÃW\¾V^½W`½V\¾U\·V^µN\¬M\µTb¿]eÆbcÂehÂaf¾ekÂhmÄhmËwtÌmnÌsrÌvrÆptÐwsËnpÎxxÔvuÏwvÐtkÈruÊsrÎqsÎvvÏ{vÓÖ’†ÛžŒÙ™‹Ú¡”Ü©—Õ–ŒÏŠƒÈƒ„Çž¦Ü¾¸âĸãĹæÀ±çŴ俵âÂ´ÞÆÁäÌÃæÐÄäȺâĺâIJ῰åïáĹâ¶àÁ·ßĻ߯ÂâÏÇäÎÄéÒÂèÐÊéÓÄêÔÈìÜÒïàÔìÜÒìÛÀͳ­—ASŠ-CŽ1G“0F˜6J–9L™8Mš;Pž;P¡<P¥@S®GXÃQ]Î]_×ihÞqlázmç~mæ€qä|lå}oå|lã}mã|qà|vàskÚppÑglÂZc¨BT‚$Ab9W;fB†,H¢DUµKVÈX`ÕgbÝojàtláwpàthÞpgàsjÞpgÝndÞqfÞocßncàrjÝohàrcàrjàqeâpdâulæukê}pærÍZV€ @Y@V@V;Z>Y;\>a<c>h>hAd>gBfA_>Z>X?a?n Bm$E]=Z@]D^D_@^Ab"Gh*Xl.Yv7b:_”Jg«at¼t|ÊywË~{ÐxÎ|xÀon΀wÔ‹ÌRP³DHŸ2F›2Fš7H¤>N¢>L£:I¢8H:Hž2Dž4H®AMÃQQÔc^Ýq\âxbæ€fåŠfëŒnì’sêqêŽsêuínêˆlçƒjä|dÜn`Õ`TÇOMµ@HŸ3GŽ+FŒ1J4O˜<P¢BR©AR§BP¯FS«AUªBN®BN¬AS¯DM®DSªCR±FR­CO®BQ³JT²HN·GN¸JP»MP¾QYÂPT¾RYÂUWÄRQÆTSÄUXÁTYÆVXÆV^ÈZ`ÎZ[ÍZZË]_¿TX¼TT¶KR·HQ¾NSÁSZºPZ·LW¼T`½R_¾W^»T^¼V]ÂTV¶JT´S\°HY³P\¹Ta¼Zc¼V_ÊehÂblÁfnÆabÇghÌlhËijÌrqÍgjÈtwÎvsÒrsÑwrÒ{zÎzvÍnlÀhoÎwtÈlmÍyyÓyvÏ{zׄ׈֒‡Ú©šÖ”„ÑŽ€Å€}½ŠÐ¤¨âÁ²åÇ¼æÆ¶åȹâ÷ửâÄ¸áÆ¿æË¼æÌÁæÅµãǽâÀ²ÞÁ¶Ý»²Ú¶¬Þ¼®àƾàùäʽèÒÆéÔÄçÎÂèɹåÌÀäɼå̾èÒÃêÔÅîÝÍîÚÆïÚÁ¸…†“@M†0F…,D3G3H˜7Kš8Lž7Kž6O¦?O¬HXÃRXÑ^[ØifÞphâxnå}pæ~pã}lä~täziâ~sâ€vá|rÞvnÚphÒb`ÀVZ¥<J‡%B_ 6P8`@v$F˜<U®GWÄV^Ñc`ÚjgÞpkávlávmàujàpeÞphÞldÞqfÞlbÞpißphßndÞqhàpjàqhâseåthèxiê|mÛmb£7F^;R:R :W?X<]@bAh@fAg@g?j!De@`:X<R 9^;fBpBfBV<[@^>aC_AaBfLi&Tr5b~8b•Pn¨bwÀv}É~|ÈÌzwÎ|sÂqrÊ{qÔ‹|Ø{¹CK¤9I™3Fš5N 6G¢:L¡:K¤;K¦9Lž6Fœ1DŸ8J¯=IÃPTÔbYÝnZâw`æƒièˆjéŒvêpësêuêŒrê‹nê‹uè‚lã~iÞn^Ôe`ÆRR²LT 2F)E4I–5K;O¤<M¨BQ¦?M«DP¬ET¨?O®AP¯AM¬@L®CQ®DP°BN¬HQ­FN²FS¯FM¶ER¸JRºPT¾OTÂQRÆX]ÂUWÀRTÃSVÉQVÆVXÈVXÈVZÈW\ÆZaÍbaÆYZ¼X_¼Q\¶PZ½U]¸IU¼RZ½NZºNX¼R\¾S\ÁX\¾U^¾SU¼OZ¹RV¶Xd¶V\¸Zg¿X\¼\iÂ`b¿\dÅklÁ_f¿hlÈeaÅotÊlhÄbdÊrsÎolÌtrÓtnÒyvÓzvÉloÄrxÊssÊosÌrrÐtwÏyyÖ‚{Ò€ƒÔ”ˆÚžŒÕ‘€ÈxzÀt|•ŸÙ¬£âøã¶ä´âµã÷ã¸àûäôæÉ»à½²åıßÀ¸à¸«Ý¼³Þ¼²áÈÀݸáúçʹäĸäÂ°åÆ±âÁ²à²ÝÅÀ߯ºàÊÂàÉ¿âÎÀäÐÆåÐÅèÔÈîÚÈÜÎŶŸª™`tŽ>O‰,B‹.BŽ0B™2Fž:G›4K¤:N®DQ¿RZÏ]^Øhbßoiâxkå}så~mä}qå~räylâ{pã~ràynßwnÞphÓdaÄY_¥<K†">c9UBWFg Gˆ3M¢BTºIUÊ\\ÖbbÚmhßtnâtnáufârbßnbÜndÝmbÜmfÞmeÝoiÞrlßqjãrhásjäxjèylêzläti¾NPq>Z?Q
+9V 8W;W=`BfDjEj"DfAe@dBb;^<Z<[?iBnBiA[=X=aE`BbDd Fj*Qf&Qg"Nu3]IjªdtºryÊ{|Ë~{Î{ÂxvÂutÊ~uЈyÖŽ}×’¨;Lš2F›6J›6J¡7H¤;K¢>P¤:G¢;N 9L 4Hž4G°DPÁOSÔ^UÚmZâyhæ‚féˆhë‹mêŽpéŒréŽtéŒrëˆlé†lç„käydÜj[Ö^VÄTS²DL7K*CŽ+B”+Eœ9L¡;Q¥@P©?R«BR©CRªBQ­DUª@O¬CNª@O¬BO°DO±AO³FPµFR±JO´JQµJS¹MU¾OZÅRVÄTYÀSUÃSVÄNQÆT[ÇVWÍXXÊV]ÊWYÌ_aÔe^ÂQV½NT¼LVÀQW¾TZ¼PV¸OWºLT¸RX½QW¾T[¸V^ÃT\ºOV¼Yc¾Xc½\d¾X`¼WdºZbÀYaÆeiÆfhÁbhÃjnÅ`fÀlrÎtrÇkoÌtrÌfmÂnsÒurÊjjÑvmÎnnÇsrÍnlÉinÎrrÐpmÎ|zÐxtÎvwÓƒÙ–‰ÔŠ|Ãpp·o~Ì¥¨ß²¢à»±å¹¦âÄ·àÀ¹ß¹«ãƺæÉ¼åȾ᾵⺬ßĻܾ»Û´¬Ú¿¼à¸¦ßøæÊºãŶིྶ޼±ÜÁºÞúàúà¸äÊ»ãÌÄäËÂåÎÂãÎÀæÎÀæÎÄèÒÅìÖÉðÚËîÞËÖÎÀ¬„“…4F‡-F‰)A’0F•3H–3H£:L®BOÁOZÐ\^ÖicÝolÞwkäpå~pã|lætä~lâ|nãzrß}vßztÜqlÔdaÃVX¥>M‡&Af:X=X@`<p82Hª?LÀTZÏ[]ÖgeÞoiâvlãtgâseàqdÞqdÞmcÜmfÞkaßnfßphàriárjátkæxlêzlèxhÑ^Z‰*FZ;S:T ;V ;W:\@gAl"HjDhAhBg>f?]<Z:W>d>qCjC`@W@[BbB`CcD`Ie"Jh$Rl(Sƒ;_¦[n¾rzÅzzÊ{z΀|΀vÁvxÅ|zÓŒ}Õ”€Õ}דš:N—4H7J <J¢8J£9J¢7H¢8J¤<Nž8NŸ5GŸ6H¬?MÂPOÐ^XÛpbâu`ç„jè†nëŒpèŽjéŒvèzèŒsìŒtèŠrè…mäzbÞpaÕbYÉRSµBMž5F’+C,D—0C7H¢9J¦=N¨@Q¨@R¬GS­CP«BN©DP¯EO­@M¬FP®AO°HV®IQ°DP²HN¹HO¸MS¼JS½MSÀPWÀTVÁRUÁSVÆV\ÆTVÆTZÇX[ÈTUÉW\×i`Í_\¼HT¼IR¼HR¼KTÁTZÂPT¸N\¸NU·NX¼NV¼QZ¼TZÁV\ºNX¿Xb¿W\ÄXZ¹XbÀX\»_hÃdmÆbcÁfnÆba¾`jÉnuÉfkÍorÐppÉfkÊnpÐpoÊt{ÏrpÍptÌllÌnmÀirÇlkÄlsÈrtÌoqÊxyÐ~{ÓŒˆÐ€{ÄimŒױ§á½®Ýµ¬â´ Ûº¶ß¶¨äƶ࿴弧æÄµå´àÀ¶Üº´à¼¯â¹ݼ´ãǶܶ¬Ý¼²Ý»±à¿­ßÄÀàļàļãŹæÈ»äƼâǼâȾäʾäËÄäʽäÍÂåÌÂçÍÂçÒÆèÔÈêÕÉñÚÈòÞÈàÖıŒ•¢FP$@‹)D/F”2Gž6K®BO¾MTÎX\×hdÞrkàznã~på~pã|nå~sã{mäykâ~sâu߃ÜlgÒdfÁRX¨@L‹'Dj<Z>U:W 9f9~;™4J²FVÈV]Óa`Úgeàthâtgàteârfán_ÝlbÛlbÞqgàpgàndáqiãtläulçxmê{kÝj`¦8Ib5T 8T 8T9Y<\<^<h@i@jDl HgBfBfA\?V;`?kDlA`>^?\D\=fFbCc I`Lb!Nm$R{9^Ri¼nxÆwxÆy|ÈxvÎyÈzxÄxzщ~×~Ö“€Ö‘€Ø‘~˜<Nš7Kž9L£<I¤<K¤:K¢<M£=K :L¡9Jœ6K 9L¬ANÁNMÐb\Úpbâvdæ‚jèˆpêrèŽxèŽté‘zéwêŒrèˆsèƒiäzdÜo`Õ_XÇTV´FN <O‘*DŽ(B–0FŸ2F£:K¦=M§<K®BP©@N®@N¬BS¬CQ­FR¬BO«DP­FQ±EO­@I±FR´EJ¸JN»LRÀLQÀNSÂTVÂTWÀVXÂWXÈTVÂVXÂUXÅUXÆWZÎd^ÔcYÁRU¸LT·PW²EQ·LW¿OTÃRW¼OXºRXºNV¾QU¶R\¼NW¸PY»TZ»U`¼RZÁWZ¿Yb½^fÈfgËhlÈgjÃ^dÅlsÍpoÌmpÐwwÐsrÈhqÏzwÏjlÌnnÌonÈkrÏpoÈfhÆlpÊhjÂbmÌrsÌprÌtnÇnnÀkqÄrp¿nxÉ’‘ܱ¨âº©â½®ß¼¬Ú¶²ã¼£Û½´à² á¸§Üº°ß·©Þ¹¬Þ»´Þ¼°ÞÀ¶äÁ®ß¼µßµ«Ü¾ºàÄ´âÈÁß¼±æÄ®åÌÃåǸáÈ¾äÆ»ãȾäʼãÊÁâȼäʺãÊÀäÌ»è̽åŰçϾèÏÀçÏÀêμíÔÃðàÊâÖ³}†}%A"=ˆ'@.Cœ6L¨?O½MVÌ`aÕfdÜocàxsä€rã}sä|oæ~pâzpâ|räzrå€pÞxrÞldÔb_ÀRWª@LŒ'Dl:^=W:W 4`;m:Ž)C¨<LºGSÌ`aØdcÞohàuiâtgàtfÝqeÜm`ÜlaÞkbàndßriâtjátkäyné|räsd¾PTr;Z>T:V<V<Z>`Af@j Bh@i@h=fBeDa<[@_AgAjBf H\>\>c"Gb@cBaD`I]Hb Nv3\˜Vn´lxÅyÇwxÃw|ÊzwÆxxÁxzÎ…~Ó}Ö”‚Ö”€×’ÕŽ}š4Jœ8H¡:L£<M£<N¤<K¢<K¡?JŸ<Jž;Pž6J >P¬BNÁUYÕaZÜo`âuaç‚næ†oè‰pèŽréŒuêŒvêŠrèŠpé‡oè‚jæzeÞpbØbXÅRT¯BM <R’*DŽ,H–/Fš8K <M¤?N¥?L¦AM¨>Q«>M®FU®IV´BL¯@M®BP¬BO®EM­DQ²DQ³EL·IPºLS·JQ½NV¿PVÂRXÂTWÄVZÆXYÁVY½RXÄPUÅ\_ÝŠuÊSTºHM±BP°EP®EP¶EPºNRÂRX¾V[¿RX¹KT¿SU¾OX¾TX¾U^»PV¹R\¼X_¸Vb¾X`Ã`_ÆhkÈadÁfrÈrrÎijÏuvÒwuÎnoÇrvÌljÌnpÏvwÌqyÅntÎurÉflÉmrÇlrÈlmÉhhÆmrËrlÆkn¼em½js¿|ˆÑš”ܦ–ᶡඦ࿴࿰ྰ߯¢ß¸¥Ü¸²Û±¦Þ¶£Ü¸°Ú´²àº®àº­Þ´§Ý¶²àÀµâÅ¾çÆ·á¾¶èÆ±äɾ߽¹èƲäÈÁåÊ¿ãÈ¾ãÆºâȼåʾáøãŸãÊ»ä̾ãʾâȼæÎ¾æÒÈäÏÄåÑÃæÎÁê×ÊðؼÜξ›Vjv:~"@Œ)A˜4H§>K»NVÎZYÓd`Ûngàyoãzlä~på|oäzmæ}päzrã|oã~uãwnÞnkÒdcÄTZªBNŒ-Hj<\8[9X6X5b 5v6+E°>JÆWZÒ][ÚfcÞnfàriàteÞndÝk_Ük`ÜjbßjaàtjárhãtlæznèygÑc\Œ(F^;V<V;\=Z>^<d=i>i>h@f@eBh"DcA^@[?dAh Fc<\;V:^?`Bc?h$IZB]H\Mp(T”NjµlxÇ{|Ê|ÆxvÃxyÂquÀsvÇ~xÒŠÖ”Ö”‚Õ“‚Õ’Ô~›6Kœ4J¡:K¢>P¢<L£;Kž>N¢@N¤=K :Lž:N ;L¬GSÀQWÒc\ÛlZávbä‚må†nè‹pæŠpæˆrèŠtéŽsè†hçŠrç„jå{fßp_×f`ÄRS°DOœ6L‘,G,F–/Fš5K¤:N¥<Nª>K¨<O«?L¬?L­CR¬FU®CPªDT¬@L¬@M¬BN®DO±FN´FN¶HPºKR»MT½PW¿MVÁPVÀV[ÂQVÄQU¿QUÀNVÂNWÞ„pèmÆNR´AMµDP·IU´DO·JQºNZ½MR½QY¾PT¼MT¼OU»QX¼QVºMW¶P\¹PZ¼W`Ä[^¿^hÄZ\Ã\fÄmuÌjmÇ`jËsrÒssÍsuÌrnÆ\`ÄnsÎqnÐptÌyzÏnqÐqsÊrrÂenÂioÀ^hºbnÅllº`j¾blºdrÍ•’Û²§Ú¨™Ú¢˜Þ­œá»°æ¼¤à¼¯Þ´¤Þº©Ý±¥ß¸¦Ø´²Ù°¨àº¦Ü³§Ú¦šÚ²ªÚ·²âÀ±âļåÄ·äÄºáÆ¼á¼´çÆ·ãÉÁÞÀ»æÆ²âõãÇ¿áÄ·ãʼå;ãȺæÈ¸åʼãÊ»äɼàÈÂáÆ¸çÒÅçÐÅèÑÃèÕÆéÚÒéÒÄîØ¸É®¨~*D~ ?‡#B”/D¤;H¹HRÌ[ZÔd]Üofàvlå{næ}nä}lä~oä~tä{rá}rá|wàvpÜomÓbdÄXY¨FRŠ,En=]<^<]>Z7[ 7f5~>›2F²DNËUSÖ`ZÚh`ÜobÞviÜraÞk^Ýj\Ük`àlbßreärhåwpæzmÜma¥>Ib:X>X<X=Z<X>`;iAj>hAgBi!EhAdC`@Z?^>gBfD`CY>^@dAfB`>_AVA_Kj%R…?a¬cwÇy}Î}È{|Ãrt»nv¿psÉ€ÒŒ}Ò€Ô’Õ‘~Õ”‚Ö“~Ö‘ <Jž8I¡:L£?L¢;L£>L¢9J 7I¢:JŸ9Jž7L 4F«CPÂSXÑ`WÜnbâzeå‚mä‡pç‹oêŽoèŠsè‹qè‰té‹tçŠræˆoå|iÝpcÔcbÆRS³EP<SŒ,I,G•3Jš5J¡8K£<L¢<LªAN¨DR«BO¬BP­CR«CN®FP¬CP®AO°BN®EM²DP¸FMµGO¶KR¹NSÀSYÃQTÄSX½RXÀPNÂTVÂORºPVÀTZê©„æƒbÂEL±=JºDN·KT³HV´NZºRZµLT»R[ºLVÁOT¾NWÀPXºMX¾T^¼U]ÄX^ÂV`Ã`fÆ^d¼YcÈbbÌ]cËjqÌjpÑotÒztÍgh¿ajÂlrÏleÅioÔurÌjsÍorÍloÃchÃmn¾`j¾`fÁ`bº`j´\f¿t~Ó–Ý ‹â¸§Ý¬¢Þ®žß°¤å´›à²¤ß¶ŸÜ±¦ß¶¨Þº«Ù­¬Þ¸ŸÛ²¨Ú¨›×°®Ù´¯à½±à¿µà½¶ä³âÄ»äÄ¹äÆºáÇÀãÀ±åÎÁàÃÀ⽫áÉÃåÉ¹áÆ½äȺäʼáǺáÈÀâȽßÄ·àĸÞĺÞĶàÊÂäÏÂæÔÈçÑÅéÚÎìÚÏëÞÊãÑ¿£ft˜;J„ BŽ*Bž8HµFOÊUVÔbZÝnfàvjä|lä~oã|mä€qä~qãztä~tàznßxoÜlgÓcdÇTV«CR+Er>^;\>^9\7[
+6^ 4m5‡"=Ÿ8F»IOÊVUÒ`XÕj`ÚqbÛpbÚj[Üj\Üh[ßn`ÞqdâtjåwlàvkÃRTt=V<V9U<Y=[=`Ed<j?f>h<gBfAf@cCZ>^BcBiDcBZA^DaCjBiF`@X@R=`Iƒ<d§`wÄy€Ð€€Ì}|ÈxzÁrqºnsÇ~|͆}ÔŒ{ÕÔ|ÖŽ|Ô~Ô“‚Ö‘}Ÿ>P¡<J¡:H¤<J¡<M 8L ;L¢>M¡<Jž6Hœ7Kœ7K§APÀOTÒaZÜpeâweå‚lç†néŠnæŒqèŽoêoéˆpéˆsé‹xçˆuä|iÞrdÔe`ÈVT²EQœ5MŽ,HŒ-K–1J˜7Mž4F¥;L¥<Lª?MªAO«AL¬BO¬FSªDS®FT°FS¬DQ®DO­DV²FR´LX¸NV¹NU¼KR¾PTÂMU½OVÀSX¼T\ºPX¸JU´K\Îmdô»ŠÚuY¸BK¯BL·EO´HU¯KW¶KV·JV¼LT¼NXºKU½PU¾RW¾PWÅZ\ÂZ^ÄVZÄY_ÃZ^ÀZbÅdeÇ^d¿alÇhlÍopÒppÓwnÈbcÃhpÆjiÈilÃhsÎtmÎjoÎqrÐmjÅflÆehÂahÄde¹Q`®Pd³ViÁ„ŽÖžšÝ™†Ü¯¤â°›àÀµà°¢á³¢Ü¦šÞ®—ܯ§ß¹£Ü¹¬Þ´¢Ý¯œÕ šÚ¶¬Ü¸µá»ªß¾·Ü¶¯à½­ãÀ³ß»°ãÁ±áżáÅ¼ãÆ´ßÀ»ä°ãÊÁÞÁ»äIJáŽáŸßżâĵàµàÀ¹ÞµÜÊÄÝÇÀáÊÀàǺåÌ»äÎÆæÒÆçÓÈèÔÄëÜÒîßÏëáÊÑĺžXft=Š'Cš2H¯HRÈZ^Ôd`Úmfßugãzlä|näzmä~rå}nâ~wä|rá|tÞxpÜniÔb`ÄSZ©DT.Jr?b>`<_:`:\ 5\ 5] 5l5‡$> :G³HNÂVXÌvyÒ“ÖŸ Ö£¤ÐŠÙi`ÛndÜ„}ãzjäwfÐcZŽ'D[=YAW;[@Z;`Bb@h?j$Ig?f=iEhDdB_C^Bd>fDeE\?\BbBhBi!Cb>X=P 9T@r*S›Ut¿t|Ñ}~Î}~Äx{Ápw¿prÈzuшÓŒ}Ռ֑|Ô‚ÔŽ|ÔŽ€ÕŽ|ÕŒ|¢<L¢@P ;L¢:H <Nž>O¢=J =Ož:Mž:Lš0Fœ4G§>P¿MPÒd_Üpdáxcähç‡nëŠmêŒrê‹oé‹séŠsêŠoéŠvçŠtä}iÞr`Ôc\ÇSV²FTš4N.JŽ+G”2Lœ6L¡7K¦>N¨>N¨:L©>K¬<J¬BP¬AO±FR°IV«BQ­DQ®ET¯GX²MZ²LY¶GQºLS¸PW½KRÁQZÂRVÀRV½LR¼LT¹IX¹Q]誊õ¯Íb`°?R²IU®HY²FSµFV¹GOºNWºHU¼PWºNTÀPTÂOR¾PUÅSVÄV]ÅYaÂR[¿[bÌaaÆ^gÄblÉioÊinÒsqÐhgÄfnÊklÌihÄhrÉnkÍlhÆlvÍruÍpuÅmrÈbg¶^lÂce²P`ªOd´`p̘”ݦ™Ü¨Ûª á¯•⯣㷜ޱ¨Þ¦œÛ¯¡Û¨œß¶žÝ°¤Þ¬™Ô ™Ó££Ü´¨à¾´ä¿²Þ¸²á¾®Þ¾¶Û·°à¶¦ß¿¸ÞÀ¸äĶãǾâÇ»âöÝÀ¸âÆ¹âÆ»àÄ»åÆ¶àÆºÞÁ¶Øµ¯ÚÀ·ßÄ½àÆ¼äÌ»äÎÁàÊÃâǸàɾâÍÄåÎÁäÐÅåÐÇêÖÆéÜÓîàÐîßÄ˰¬}"B~ C’0IªFTÈXXÐccÚldßxoäyhâxläyjâ}pà|qã{qä~tã}sà~wÜplÓ``ÄX[¨FUˆ+FpD`;]>a:_:[7\6X 5Z
+0g7+D¤UkÉ ¤àÀ¶æÏÄëÔÄîÒºàÄ´Ô žÜ¯²ã÷┌Ömd¢8Hb?V>U<Z>ZC]@^>fBh@g@gBdBg!Fi"Jf I^DcCf@b@^>ZAaDhEgAd?`=Y@T@h"LIj·n|Ì~|ÐzÈvvÄpt¼pxÄvvÌ„~ÔŒ„ÔŒyÕŽ~ÔŽ„ÓŒ}ÖŠzÔŠzÔŠ~ÖŒ{ž<NžAQ 9Kž:JŸ:Kœ8Mœ5G 9Jœ4Gœ4F3D3G§>M½OTÓ_ZÚnaàygæjç†oè‹nèŽsèˆpç‹sèˆoéˆqè‰tèˆräzcßpdØe`Æ\\²KVž8L,I-H˜0Hš2E¡:J¢<M¨<K§;K§>L°@L«BN¬CP¨@P«BP©BQ©>NªEV¯GX°N\³IT¸KS¸IP¸LS½JR¾OW¼NT¿NTÀLP¼KT¶FVÈ_^úÅ‘ïžwÏYW®>R²GT³HV±ER´GR¸HRºMX¹NXÀPX¾PX¾LSºJUµGV¹NZÄX^¾T_Å[_È\aÄ_cÍfaÊafËhlËfhÄejÉnnÍvsÐpoÉlkÎjeÇdkÅlpÏljÑqnÆ`c·P[º`j¿\b´Ve¯Pc¼u„Ô‘ÛŽÝ«¢Þ²¦àµ¢ß¤–⬔ڣœß«•ݳ©Ý³©Ü¹­Ù¡–וŒÖ—د¨ß² ßµ¬â·¦âº°à¾²Þº¶â»¬ßÁºÛ¸±â¼®âÁ¸ã¼¯ãƸà»ß¼ÞÀ¸ßÄ¿àÀ´à·޼´Ü½·ÞƹÝÇÁà¶áõáǼàÈ¿ãÈ»âÏÃàÊÂà²âÌ¿âÌÅå̾åÒÆæÓÇêÝÐìàÑï߯äÓ»CZy>‘2H­AQÄWXÔf`ÝndÝvpâyjâyjá{jä|nã|qä|mä}näxmá|tÞokÔcaÂZ_ªBPŠ0Jp?a<Z<_=\8Z:T
+2O 4N 8\Bœj~ؾºèÐÁîØÃìѹâÀªÞ»¯ÞºåÍÂíÑÂîÕÂæÖÀÄ–lBVARAVAX?\F[>cBi!DfAgBe?hBeDf$HbB^@fDdE^?_?^Ad@h Eb@\<V:\Fk$P‹Af²gzÈz~Ï~zÎzxÆvxÀpvÃxz΂Ò‰€Õ‚Ô~ÔŽ}ÓŠ~ÔŒ|ÓŠ~ÒyÒ‰zÖ‹{˜8J™<Lž:Jœ<Lž:Kœ;Lž9JŸ<J =Mœ9I›2Fš4F£>LºMPÏ\TØnháwhå€jçˆpéŒtèrçŠqé‹uç‹vç‰wç‰ré†mäzeào]×dXÈSS²CQ™9Nˆ$B‰(F–.G˜2H 7JŸ6K 8I¦;M§<L¨>Oª<M¨?O¦AM¤@R§>L¨DW©BS«DR¯HR°DP´HR¶GT¸LT¸LT½NU¼LT¼OTºJP¶BP°BXÛ“€ûÈ’é‹cÀPV¯>P²HX´ER´BRµJT¸JV¼LVÁRVÈTX»KVÁNVÀPX»MX¼R\¿X\ÂS\¿P_ÉaeÊajÈclÍhhÐnrÎknËgiÊdkÑssÌjiÇZ^ÃfnÎjhÐopÎkfÄ[^°Ub´\f»W]²Sc±\nÆz‚Ù›Ú¡–Ø™–୕㺪ᰜۨšÚš‹ØŽØ¢˜Þ±£Þ¸«Üª˜ÒžŸ×¨ Ü´¬à­™Ü²ªß²¢Ýº°à¸ªà»°âÀ³Þµ­á¼©ß½´àº®à¼«Ý¼´Þº¯â÷àļܽµÞ¼°Ù¹²Ø¼·àǽáǾãóæÊÀßȽ޽´áøàȼàÉÀâʾáÍÃÞÈÂáÊ¿äÍÂáËÄäÎÂåÐÄçÓÈìÞÔìÜÎêÛÀ²ˆx@Œ*C¥?NÂRVÑcaÚlißwnâzmâ{lå~lå~nã~lä~nä~qá|rà{sÝpnÑcb¾VZ¬ITŒ/Jn>\?\<\<W8U 8P 6L?XEŸ|ÝɼíÔÂìÒºæÀ¨Û²¥×¼¸àÊÃåÎÆìÖÈìØÏíÙÌîÓ¹Üijj,LLARDTBVB\C]AfAi"EfDbBh&Lg F`BbBbBcDfDdE_B]?`Dj"Fl(JaAW<P<^B~5Z¦_xÅxÏ€Ï~yÆv|ÂtzÃtv΂€Ò‰~Ô‘‚Ô•€Õ‹}ÕŒ~Ô}ÔŒ~Ó‰~Ò‰{Ô‰{ÔŠ{œCV›:Kœ:L;L8I6I¢6G 9H¤8Fž6H2Dœ4H¦:I½JOÒ`XÙh`âxfælæˆné‹téŠnê‹nè‹pæ‰xé‰mætè‡näzdàp`Öe\ÃTV®CRš/H†&BŽ)E“/H–3Jœ2Jž8J¢;L¦<O§<N¬AN§@N¨>L¨@L¨?N¦<Lª@P¬CO«DN¯HV±GV²HW´IR´HS·HQ¼NX¸KR»NR»FN°CV¸NYñ¼—ù¸~ã}eÄRV²BT¯@P´BO¸HR¸HU½KT¶M[½LQ½RXÂPTÀPYÆRVÀS\ÀU[ÂX^½YdÂZ\Æ]eËdcÌegÊ`dÏnmÐghÇclÇmkÉ\`Â]dÈjkÎljÐolÍhe¾[cµ]e¹X\­GXªI^¹j|ÏŒ‹Ø‘‹Ø–Þ¬ŸÞ¬žß¡Œà±£ÚœÙ¡”ؤšÖ ™Ú¤’Ù¢‘טפ¡Ý³¥ß²§ß®™Û®¦Ü¨˜Þ³¥ß¹¬àº°Þ¶¨à¸ªÝ»²Þ³ªâ¾¬Ú¸³Ü¸®à»°Ü¾¶Þ¼´ßº¬Ö´¯Øº¶Ý¾¹àÁ¸ãƺâȺáÄ»ä´âʾàǽÞÀ»áÄ´àȾßÊÃáȽâËÂàËÃßÈ¿ãÊ»áÌÄä;äÐÄêÖÊìßÒêßÊμ·…4N‡(C 9L¾OTÐ`\ÚjaÝtmßxlá|nå|læ~nå{jã{oåqâ|rß{rÛqjÔdb½RV§BNˆ(Dm=\;W9X8R 4M8J<f4Y°™¨à̽íÙÄèȰۮ˜Ö·±àÉÂåÑÈìÚÎïÞÐòßÎõâÑôäÕðàÐèÝÂi‚HBNBSAYBXAbBg"Hi@c?dAi Ff EbCbDaBb?f@a@[BaBbBh@dCaAV@V>p#NœQm¼t€Ï€„Ï}}ÊwyÇtwÄtxÈ~€Óˆ~Õ„Ö‘Ô’ÕŒ}Ñ€ÒŠ~Ô‹~ÓŠzÓˆ{ÔŒ|Ô‰xœ6I™:OŸ8Iž:L =M¤=L¢<L£>N¦=J ;Mž9KŸ1Fª<L½PTÎ`Z×j_àubäjè†méŒtêpëŒrêŠqêŠsê‰rèŠrç„læ|fÜqbÒ_XÇVU°BJ—.J‡&DŒ&E+E’0Gš4I :L¢:M¨=L¨BP­?J®@L®?M®BNª@RªAN¬CR¬@P­AP±FT°GS¶FR¸HRµJR¿KR¿NU»PUºJP¸KU²?UÈf^ûΚô©vænÊXY°DT®BR±HU²FV¸LU¾NV¶FS¶PWÂSZÄLPÂR\ÀQXÄWY¼SaÄ[_ÂR\ÄaiË`bÉ^dÎhiÎa]Æ\bÄhlÈc^¶O]¹`lÏmiÎiiÐkhÊbcÂZ_Æhg¿S\²L\®M^ÂnwØ“‡Ù›–Ûž•ޤ㯜ܗˆØ‰ÜžØ¢Öž˜Ø¤Ù«œÖ’‰Ñ“‘ל—Þ®›Ü¬¢à°žÙª Ý°žÜ´©Ú®¤ß¸¬à¸ªÜ´©Ý¼µà¸¬Üº±Ý²«ßº¬Ú´°Ü·¬Ú²£Ù°«×´²Ý¿¸âÅ¿âÁ¹à¹âÂ¸ãÆ»âźßÀ¸á¾¯âÇµßÆ»Ý¼²àÄ´àǼÞÈÀáȺßÈ¼ßÆ¼ÝúߟàÇ¿âËÄäÓÌêÜÒëÞÐáת‚‹‚&Cš4G½NQÒ^XØnhÚ|qßznâ~lä|hãnãpã~lä|mâ}qÞ|rÛskÑc_¾RT¤CMŠ,Eg:V:R9O8I9K?{Mm¬²æÏ¿ë־⼥ћ‘Òº¹åÏÂëÕÈìÙÉïÜÊïÛÊïÙÉòÚÌôßÍøæÒóæÌŬ­LFNDP@U@Y?^?bBfDgCiBh>`@^>^>b@c@bAX>[AcBh DfAfD[@ZAj$ODeµj|̃ӀyÍ||ÅuzÂvxÈ||І€Õ‹~ÔÖŽ€ÕŽÓŠ€ÕŽ|Ô‹‚ÒŒ€Ò‹~ÒŒ|Òˆ{Ò‰{Ÿ:Lœ:KŸ;K ;J£;G¢<L£<K¨>Q©?L¤8G ;K¡5F§?JÀOPÑ\XÚiXáveäfèˆréŠpêŽuêtéŽrépéŠqèˆpç„mæ~gÝpcØbYÊQQ­=I—2E‡&D‡'C(B’,Cš3G¡;L¦AL¦:Jª@M®@M«BP­BM­DR­BP°@M²@L®CQ¯@M°EO±HP´IS¹DN¼FNÀLPÀOS¾NU¹NW´GS´BXÓˆ|úÍ—ö©xáuaÄKR¯ER®?Q«BTµDP¶LVºDOµJVÀRVÆX`¼KTÀPUÂNZ½V\¿TZ·P`½`iË]bÎffÐhgÄXZ»VbÄda½PZªN]ÀdhÒigÒkiËghÉccÄadÄ]Y½QU´MZ¹P`È{}ØŽ‹ÙˆÞ¦–ݦœÞ¢–ݛؑ…Õ‹†×ˆ×š”Û´¨Û¡”Ô•’צ Ü¥—Û©œÜš‹Ù¨“ܪžÜ³¤Û¶®Þ­›Û·®ß³£Þ¸ªÚ­ªáµ¦Þº¸Þº¯Þ¹®Û²«Ü²¡Ö¬¦×®¥Ý¼·äÁ¶á¾¸äÁ³áÀ¶àÁ¶âÄ»âĻᾱàÀ´ÜÀ¶Þ»¯àÀ¯Û¾´Þ¾°ßǼâȾÞļÞĽàÈÀÝÈÂÜÈÂáÎÅáÉÂâËÁçÕÍéÞÕèÜËÖǼšQf˜.F¹HJÏ\X×jfÜnlà…zâ~uå~qç€jæ€oå~nä{nâzoßxnÜohÍcc½UY¤=K|=]5N8I 4I<RF“j†Ò¼èÐÀé̲֩•Ì•“ÚþåÒÄìÖÇíÕÅëÔÁìÓÃëÓÄëÒÅîØÈïÙËôàÎöèÌØÌÁ`(LLEOAV@^C`CcBeChCgDa?dA[@cAf@bC\>Z@\@dBf>fC_DZBdL„8\¬cxÆw€Ð€~Î~~ÇwzÁqvÆ{|І€ÔŠ€Ö‹€ÖŽ~Ö‹~Õ~Õ~ÓŒ~Ó‰zÓŠ~ÓŠ~Ò‰{ÔŠ|Óˆz >Rž:M¢=L <L¦:G¦<N¨;IªAN¨=N¦:H¢7H¤4E¬<J¸MSÎZUÚj_ávcåfèˆlëŽqêrìnéŽvêrërêŠpé„iå|fÞqaÕbXÆPO¯@L—.EŒ0HŠ-DŽ.E‘*B›5L:L¨>M¨@P¯BO°DOªBP®@J°DN°?J²BN²@M±DN®@N³DNµEP´GP·JS¸HO¿KQÀPU¼U[¸V_¶FQ´GXüÆŒñŸzÜo]¾HT¬=P¨BS¯FV³GS²FRºHO½LUÀOSÀVY¹FN¹LWÃ[`ÀJR¼VbÊ^_ËccÍfkÇaaÁXc¾`jÂY_¸Pc¸\gÅcgÐhkÏhbÊ`^À\fÆc`¾RT´PW³LX®I`ȂەˆÜœ‘Úš–ß§˜ÞŸ’Ø”ŽÚŠØ“ŽÔ’’Õ—–Ú¦”Ö…Õ’ŽÚ¦›á¯œÜ«ŸÛ¤’ל“Ùš”ßµ¨Þ²¬ß¹«Ø°«Ý¬˜Û°¤Ü¬£Ý¶¬Û¬«â¶¡Ú»³Þ´¤Ø¦¢×«¨Þ½µÞº´äº¨á½³á¿±Þ»´à¹§á¼°ä¶à¹޼µàÁ´à·޿´Ü¾¶Ü÷ÜÀ¼àźáÈ¿áÊÁ߯¾ßÌÄáÌÁàËÅâ˾áÈÀàÉÁåÐÇçÕÍèÙÌåÙÄÀ¢¦˜6L²CNÍ[VØiaÛtjàtã€ränçƒmæoæ‚oä~oá€rÞzpØlfÎc^¹NRœ<Jv:W 6H 6C<[(N¦‰ ÚƼéÒ¿äÄ­ÐœŠÆ›¡×¼éÓÅí×ÅìÒÁêпç;çÏÁéÓÃêÍ¿èÆ·ëÐÄòÛÈ÷æÑãÔÀxC`JDRCYA]B_@a@c>e@b@cA`<`<d<^:W:V=`Da@iGiDcC`I\Dv&PŸRnÂtÒƒ†ÑyÊzxÇvzÆwv̂ՊÔŠ}ÕŒ€Ö‹y׆{ÖŒ{Ô‹|ÕŒzÓ‹}ÔŠ€Ô‰xÒ‹{ÓŠyÖ‡x =P¢:N¢>L¤;K¥=L¨<L©?K¨>Iª>L©?K¦=L¤6Hª@L¼KRÎ]YÜiXãv`åfèŠlê’sêqêŽrê‘uërìŽnêsè‚jæ{dÜqdÖbYÄTT®EM—0F‹'@)B‘,D•0FŸ5H¢;N¤>N¬@L¬CP¯@M¬@M®CL²EN³BL±DM²BL°DJµDK²EP³EL·HP¼KTºOWÁLPÁNR¼NT¹Q]µHY¹OXô¾™ú¼…óžkÙoc¹AMª:L«@M¯FS®DS´JT¹JU¾PX¼PU´@L¬@P¿W[»MZ¿X^Ì\_ÊafÈ^`Ìb`À[bÀZ_¿OY¸VeÂ^fÑjmÍrpË^`ÂTZÃ`aÎfbÂU[¸PX¸LX´ViÎ~‚ÚŒƒÜš•ޟܧœÚ˜ˆØ…ÖŽ†×Õ–”Ü£šÚ–ŠÔ’Ú¥ŸÜ§Þž‘ܤ—ܦ’ئ›Ø£žÚ®¨à§•Þ¼´Ü®¡Þ¹«Ø®©Üª¢Ý§ Ú®£ß·¦Ù©©Ú¢–Ö£¤Û²ªâ¿¶ã¿µãÀµà¹²â¹¨Þ¼¶á½°Û´®Ý®£â»ªâøà´޾µà¶àúÝļÜĻ߯߯ÀãËÀàǼàŻ߯¶ÞŸÜüÞÅ¿ÝÇÁßÉ¿àÉÂâÍÆäÐÅèØÅÝμªev®BKÊYUÔhaÚulà|lã€mä~jç€oæ€jæ~læ€hß}oÞtcÖojÆZZ¶HJ—:Gg6J8F>o>a¶Ÿ¬ãÐÄìÒ¼Þº£Ê…Ê¢¨ÜÈÂéÓÆìÕÃëÓÀèϽçË»å̾è̾åɸáÅ¶áÆ½èÑÇïØÊöäÌçÛÅ„McKDP@ZAZB^Ab@b?fBbB`<`=`;b<\>V9]Ab?c>iAbB]EYCgHŽ@d¶j}Ђ„Ô‚~ÏzzËxxÆx{Ë~|ш׌‚ÖŠ|؇zÖˆyÔ‡|ÔŠ{ÕŠ}ÕˆzÓ‰~Ò†|Ô‰xÑŠ~ÒŠz׊y¤<J¤=L¥?N¨AN¦=LªAV¨BO¨?L¬@P¨?K¬BO¨=M¬@MÀQPÓ^VÝfYáu`ä‚hèˆkêpê’qêqê“xêrëqéŒnéˆiåmàt`Öe\ÃSS®EN˜4K*B.G‘-F›1F 8J¥:L£>N®>Mª>N®@O¯CO®CR²EM´AL²@L³@J²DP´ISµHS¸GP¹IO¼JQ¹JR¿MSÀOUÀPTµFR²@RÅ[YüМø¹†î•qà|aµHT¬:M­GT±DR´HW¸MW¸GS´HR¨>Q®GUÂNUÁU\ÄY`ÄX`Ê\_Í]`ÀT]Ä^fÃY`µN`»ZkÉ_cÈ`gÏhgÈdfÂ]gÈbfÏjdÂ`dºRWµGTºYeÔ‹‚ÞŠ…Ú‹†àžŠÜœÙ”ˆÖ“ŒÖŠ‚Ò„†Ù›’Û£˜×Œ†Ø—˜Ý¦žß§œÞªžÛ¡”Û›ŽÙŸ—ݪœß²ªß°œÚª¤Þ§˜×±¬Û©œÝ´­Û®¤Û´¨Ú¦žÚ ˜ÙÕ­¨Þ¸ªÝ³¬á¸¨â¾µà½´âÀ·à´¯à¶¦á¿´á¾®Üº´Ý²ªá¾®à¶ß¸߽°à¿µá³àÊÃàľ࿰޿±Ú¹«Ø¾·Ûľܯ¼ÝǾàŸÞÉÀàȾßÉÁàÊÂáÍÅäÒÉâÖÈ̶¶±htÇXXÖcXÝtfàyhã}hå~iæ‚læhä€jå~lâxeÛscÔhbÁRQªBIŒ-D]:]#JŽfʸ¸èÓÃèÌ´Û´¡È––ΰ´ßÈÁéÒÂêоêоèλèλäǹݻ­âŸáÄ·ãȺéÎÂêÔÈïÚÌõãÈèÜÄ‚K`JDR@\C\D`GdDdC`8\:\9]:d@`;[@]A_>eBfBd>Y<U>[F|*Rª\tÌ|‚Ñ„ˆÒ|Êz~Èt|Ê~шÔŒ‚׉׉|ÖŒ~Ö‡|Ô‹|Óˆ~Ò‹ÒˆyÔŠ~ч|Ô‡xÔ‡}ÓŠ~Ö‰y¨>M¨@N¦>Lª@K§BO«@J­DN®AK¯@L¬?K«>Kª=J­@L¼NRÑZXÚncát`å€jæŠnêŽnê’xêqê‘wépëlèlèˆpè‚gâveÙfYÆSW±FO4G0F’+E—0Fš4J¢8I¡>O§?L¬BO¯DN°AL­DP±BP±AL´CN´DN´BL±@L´EMºIPºFPºHM¹MS»MRÀMPÀPR¾MP¸JR³BUÑrhüΞøº‰ê’gÑ`V¼KS°@N²GR°@L´JT²GS²EN¤8Q­JXÀTb¾VZÄNYÆY\ÌabËTXÄZbÉ\]ÁR^»_jÀ^dÄR]Ä\fÎhgËdlÊrtÐnnÌghÆ`aºKR­DT¼ajÑxyÛ…wܛےŠÚŽ‚ÚˆzÔŠ†Ô‰„ؘ’ÖžžØ‡zÔ‡ƒØ–૜ݦकޣœÙ£œÕž™ÛªœÜªœß² Û¨£Þ¬œØ«¤Ú¤—دªÝ¦›Û²¦Ú£˜Ö˜‘ÒšžÚ¤ŸÞ¸¨Þ­¢ß±žÝ¶«ä»¬â¾¶â¼°Þ»°Üµ°à´¨ß¼²à¼¬Þ¼²Ý¶°â¿«â÷ÝÁµÜ¼¬Ý³¢Þº©Ö§˜Õ¶´Ú¾´Ûº´à´àÄ»áĹ߯»ÝÁ·àȼÞžàÈ»ßÉÂÞÈÁäÎÄãÒÏåÒÆÒÀ¾Éˆ‘ÖbYÞp\âzdå{bæ|aç€gæ~dä€já}fßwbÚugÒaW»PP 5D~&F†Ig¶œ§ÜÊÁêÒ¿â¾£Ôª™Î¢ØÀ½äÍÂìÔÃéÐÀè̽ç˼äÊ»äÆ¶ßÁ¶ÝºáÄ·áĶäË¿êÐÂì×ÊòÚÊõßÇåÙÁ€D]HBPB[C]EbHf"EfEa<_;`:`8]6Z8\=`>gBf<c<^:O 9M
+:fL–DcÃu‚Ò‚‚Ò€~Îx|Êw|ÈyxцԌ؎|֌։|Ö‰~ÕˆxÓŠ|Óˆ|ÒŠÒ‹ÓˆzІÓ„yÑ|Òˆ|Ô†|©@N§DO¬BL«>K¯@L°EP¯AL°?I°?G«<K®>Iª9G¯BJÂJOÒ`[ÜjXáufä€gçˆpêxëŒpêŽréxë’qëwípêŒtècâxhØh[ÆRRµCN¡3F’+E•.E™.D5G¤=K¦?L¨?N®CN¬CP´?J¶GN´EP³BMµDP·JO¶EO³AJ³DM¶HPºKS¾KR¹LR¾LRÀRTÃOT¾PV·FR³>Wà‘yûÊ÷½ˆâz`Ñ\T»IV«=L¨>L®@P¯DO²CR®@R·KWÀO]ÈVZÁMRÅ[^ÀOR¿TYÇa]ÆR[´HXÁZaÈW`ÅZeÄ_gÎ`bÍgnÌceÄZbÆ]`Ç`_¸HT¨<R¸eq؉|ØŒ„×€|ߌzÜœŠÔ}€ÓxvÒ}ÕššÚ “Ô„}ÒˆŠØ˜Ü•ÞšŒÞ¬›Ü¡œÜœ’Ü­ Ý®¦ÙŸ“Ú ™Ü¦œÞ°¤Û¨£Ú¦–ש¤Ü£šÚ°¥Ö˜’Ò”“Óšžß¦–ß´§Ü¶ªÜ®£Ü§ Þ¬›ß¶¬àµ¤Þº¯à¼´à»²Ýº²ßº¯Ýº³à¼¯Þ¾¸Ý·¬á¹âÅ·Û¹­Ñ–˓Դ´ß·Ý¶ÝÀ·Ý¿¹àÅ»ÝÁ¶ÝúݼÝÁ¶ÝļÞļÞøÜÃ¾ÞÆÂáÏÊãÏÊçÔÆÞÎÂÔŒÝjVâw^äydä{aå{eå}fã|eâydÝvbÕm^Ë[S°JUœD^¬y‰Ò¼»éÔÂæÄ®Û¶¢Ò¨ Ïª¦Û¾æÑÄèÏÂèξæÉ¹æÉ¶æÈ¹âĸÞĸ޿´à¶âĶäȼèÏÂêÒÆìÔËòÛÎôÞÅâÕ¿u9RLBTDZB\DbCgBe F_=d>`<b:`>]<bEcCjBhAc=T 8H8S@„5]³fxÏ{~ÓƒÎ}€Ëv|Èw{ÎÕŠƒ×‹~ØŒ€Ö‹~ÕˆÖ‡xÔ‡zÔ‡}Óˆ{Ó‡{Ô…xÔˆ{ÒŠzÔ†zφ{ІyÔ‡zªBPªAK®BP®DM®BL­BN­EP¬EOªBL°@L«<G¬>J°@HÄHKÒ\TÜjZáxiä€hæ‡tèrêqêsê‘tênísí‘pìŠlê€iâvdÕhcÆVT´CJ£2F‘*B”0E˜0Gœ5I 5F¤>Oª=K®@L­BN±BO³BL±BN¶CMµHR²HN´CN±AL³AH¶DM¸OV¹JM¾LP½OP¿LMÂPR¾QT¸ET¶CVꬖüÊ”ô²~Þq[ÊSO¹OT¬@M§=K©>O¬EN±GT¿LQÂNZ½IQ¾KVÂPV¹AJ±LY½][¿NW·IYÅ^bÎ\fÆXeÉ_dÎ]dÈ_cÈ[^¼R]»Y`Ä`^´MZ©F]¾fqÓ|wØ‚zÜŒ†ÙŽ€ÒvtÔyoÓƒƒÑxyш֒Í|ƒÔŽÞ ˜Üž–Ú˜‘ݘ“Üš’ܨګ§Ü¤˜Ý²¦Ø ˜Ø•ÚŸ’Ø£ Ú¬žØ¤¤Û§›Ú¦œ×“ŠÏ×¢žÛª¢Û¦šÜ¤“Ý´¥Û²«Ú°¦Ø§¢Þ²¢Ý´®à´§Þº¬ß»²Ý²«á¾°Þùܼ²à¼®ÞÀ¸àÀ´Þ·§Ôž”Ë’–Ò©¦Ý¶§Þ¼°ßÀ³ÝÁ»ÞÂ¹ßÆºÜÀºÞºàùÞúÝÀµÚ¾³Ø¼¶ÜÀ¶ÜÄ¾ÞÆÀàÌÄâÏÊçÒÁÞ¸Ü}nãv^äfädå|`ãyfâybßxbÚo[Òe]Ä^d¸sƒÎ¬°äÏÀèӻརմ¦×³¤Õ´²ÝÈÁåÐÂç;çͽæÊ¹âŶàĴ䯻ßÀµßÁ³á¸âÅ·äÇ»åȽæÎÄíÓÇìÖËñÙÍòÛÃÞͼf$DOET<ZB\@_?bB` Gd!He@b>_>^;^?eBb>h>f>_<P 4L
+:lL¤TrÄu~Ò„†Ò‚…Í|€ÈvÌ€€Ô‡|׋‚Ö‹ÖŒ|Ô‹‚Ô‡xÖŠ~Óˆ}І{Ó…|Òˆ}Ó†zÔ…|ц|Ô„zÒ„|Ð…{Ð…~«FRªDP©CM¬DM®FP±@J°BL­CN°BL®>G­@Q®;I´ALÅNOÖ\TÜk\ávdä€gè†lê‹rèŽrêpë”wê’mìŽtìnìŒkè‚jâydØi`ÊVTºIK 2F’)A”,E˜/C6J¢4H¥<Lª@N±EP­FR¯DR²DO²DO³EL²?L±HP´CK°?H¯@H¸BL¹HN¸GLºJP¸NT¾LO»PVºIQ°@Q±AQó¿“ýÉŒðžrÚfUÅSVÂRU¯ES¦<P±DQ°FUºHR»IP½HT²BP½LR¶BO³KUÄVYÁTZ¾V_ÆX^ÇT`ÈXbÎ]_ËbdÌafÊYZ»U^¿^c¿VZµNZ®M]ÄivØ|uÚ„×…Ù†|×…€ÓurÎpwÏusÖš”ÊzwÆlvÕŒ‚Ý˜àœ‘Ü›–Üœ“ß –Ú¦žØœ–Ü£ÖŸžÜ™Ú¦–Ø¡ŸÙš”Ú¨™Ú¡ŸÝ°¢Ø¦ Ó†ÍŒ’Ø’Þ²£Ü®¤ÛªŸÚ£šÜª Ý³¤Û´¤Û¬¤Þ¬¡ß¶§Ü²«ß°¢Þ·ªÜ°ªß¸­àÀ¸àºÞÀºàÀ²Þ¸ªÎŽˆÎ”‘ر¦Ú¹ªÙµ®Ù¸³Ü¾´ÞÁ·ß¾¶ÞÁ¸ßÁ´àºß·ÜÀ·ÝÀºÛ¿·Ø¾ºÚ¹°Û¾´ÚÁ»ÝùÞÈÂáÉÀäζܡšãu`æ~`å{bã{câu\ßyfÜveÖmdÒ„Ô¬®ßɽëÒ½æÁ¥Û² Ø´¤Öª ×»¶àÉÀçпæÍ¼å˺äɹãķ߸ãŸáÁ´ÝÁµá÷âÄ·âĸäÊ¿æÎÂèÑÈêÒÇíÕÌðÙËðܾӸ¨QDNCVF^E^C^B`B^@b@c@^7^9Z<[<b@f=e>`>Z<O
+9]BŽ9`ºfvЀӃ‚Ñ}|Éz}É|~ЃÖŒ€ØŽ~Ö‰|ÔŽ‚ÔŒyÕˆ}ׇ|Õˆ|Óˆ|Ô†zÑ‹|Ó‡~Òƒ|Ó†{Ò„zÑ…yÔ„yÒ„xªBTªCN°FQ°EO®CN­BO«CM¬AL°DO¬@N¯@N®BK¶GLËOLØ]SÞmXâwbâ{hæƒcèpéŽoì‘tì–sì”rí’vì“rí“tègâxgØf[ÈWT·FLž0D“.D˜-D›0Fš6H¤<L¥<K§>L°@M«AL±AN³FP²EM²EN¯@L³EL°DM°AN´@JµDK²DN¸HM½HLºJO¾MP¹KO³GQ®<R·LUö̦ù½ŒçŠfÖg^Ñb[ÀV[µFS®IU®AR´FRµIU¸>J®GX³AN¬<MºOSÄOSÀU`ÃTV»HU¾Q[Î^`Ë]fÍagÉXZ½KX¸TaÃZ^ÂS]¸T`´L\ÁkpÔpk×}Ü…xÙŠ€ÔspÐwvÔyxÓ…„Î|ÄgfËy|Öˆ‡ÚŠ…Ý”…ݘښ”Ü¢œÜ¢šÛŸ×˜‘Ô”•Ø”ˆÖš–Ø™˜Þ±¢Û®®Úž–Ú¥’Û“ˆÔ’‘Ò™›Ü§”Ú¥ Üž“ܬܮ¥Û¥žÛ©–Ú£›ÛžÝ²¡Û­¤Û œÝ§—Þ´¬Ü´°Ý¶²Ü¶°áÀ·â·áÀ¸Ù«¡Ò›”Ѧ¤Ö¬¤Ú´¨Ø²©Ý¹¬Û¼´Ü¾´Þ¼°Ü¼°Ü¼´Û¹­ß¿¸Ü½²Þ¾¶Ü¾·Ý¾·Û¾º×½·Ø¶­Ù¼¶Ö¼¹Ø¾¹ÝÈÂâʹ߾³ãxbå|bæ}dãxZßu_ÜpaÛvqØž¢àúêѾæÇ®Ü±–ض¦Ú´£Ô­¨ÚÃÀâÌ¿çξä˼ãȹâǶàõß¶à¶ßÀ²àĹàøâĸãÄ·âÊ¿æÍ½èÐÆêÐÃìÔÇìØÌðØÉðÚ¼À˜’KFPATA^F]B`B\=]@dAc>_<\=\>\:b>g=e>`@]>hA€.U¬YtÊz~ÒÒ€€Ï{{ÌwxÎ}Ö‡׋€ØŒ~ÖŠÕˆ~ÕŠ~Ôˆ|ÕˆwÔˆ~Ò…zÒˆ}Óˆ|ЇzЈ}Ò†zÒ…yσ{Ô…yÒ„x«CR¬FO¬BN¯?H®BL¯@L¬CP¬BL¬FT¬<J®BI±?G¼HJËNLÙ_Vßl^äxlá~lêˆfêpêlë“sî”rî–tí”tí”qípè†iãzgÛj\ÊXT´FL 3D•+@’*B™0Dœ9K¤?L¤9L¨@Q¬BOªDN­AN³EK°DN´@J²DO²EM²DP°BK²AI²EM´DM¸HNºIN»IN·GNºIO¯FRª<TÆb]üÒ ø¿‚àƒpÞr`Ð]VÈYY¶FR¶GR³HV³JZ°BP³DQ°?P©@R¶NX±>Q¼NV¼IR®@T¸R^ÆX^ÂT`ÆY^ÆRZºJX¼W`Æ\a¾S_ºR`ºUeÌsv×yrÕwvÚ{oØv×|sÏuuÐvvÔ‚Òˆ€ÀdiÈy~Õ‰ˆÚ…ٌՀژ‹Û¦¡Ú •ט֒ؓŽ×”Ô’•َܪœÛ¦ ß°œÙ¦£×‰…Òƒ„Ö™•ܬ¡Ü¡’Û’Ù¡›Úš’୘ܪ§Ü ”Û¤™Ø¤šØš’ݦ“ج¨Øž˜Û¦–߸®àº­ß´§ßª–ß°œØ¦ Ð˜•Ö¬¢Û³¨Þ¸©Ú² Ú²£Ø­œ×¯¦Û¸®Úµ¬ØºµÚ¼µÚ»¶Ý¶¨Ý¸°Û¶¬Ú´ªÛ¼´Ø¾¸Ø¼µÕµ³Ö²¤Õº²Ô´¯Ø¹±Û»Ýź݄yâz]âzbãxfÝxk؎ܲ®âʼæÍ¶á¶œÙ³žÚµ¢ÙªœØ·´áʼæÎ¾æÊ¸åǺáŹà´ßÁ¶ÞÀ¶àÀ´áÁ´àĹâÄ¸âÆºâÂ¶âÆºäÈ»çÌ¿èοêÏÂîÕÈîØÌðÚÅïܼ§v|KCRJX"I^H^E`AbAa@b>\:\<Y9Z<`?d?fBfFeEmJ~$M›HhÁn|Ñ|€Ñ€Ñz|Ïy|ÎzxÒ„Ö‰~׋ÖÖŒ€ÖŠ|Ö†Ôˆ}Õ†zÕŒzÔ‡{Õ‰yÓ†~Ò„{ц~І€Ò†}Ñ„zÐ…zÒ€z¬EN­BP¯BN³@J®@L¬@N«BO®BP±FO­@I®>I°@K»GJËNKÖ_WÞlZâ{hä„nè‹qëŒsì“mì–vî–rë”tî–}î–xì”vé‡jä{gÛiZÍXP²BL 2G’.F”.D—3I›;O¤<M¤<L«<K¯EO®@K¬@L¯DM¯BO±CN°CL²AL°;J±BI¯CN²FN²EK·JQ¼HO¹KO¶HN·FK®AO©7QÖ‚rüÑŸõ´~êkÝq\Ó_WÈ][´DN¸HP´HT²GU¹KX¼LW°HY¶ET´DU·LS¾PV´JYÀRYÈRXÉ[_ÃX_»O\¾Q\Ä^cÈ]dÅ\bÂU^¸PcÌsv×€€Ôwt×€{×stÕslÒrtÑvqÒˆÈoj¿bkËx~Ø‚ƒÙ†~Ùˆ†ÚˆÙ”‘Ö’ŽÙ™‰ÖœšÚ—Œ×—ŽÖ‘’Ù’‹Ù •×¢¤×Ž†Üª™ÛšŽÖ’‰Í€ˆÖ–ŽÛ¦™Û —Øœ—× šÙ›”Ù¤šÛŸšÞ¡Ø§¤Ú˜”Û­¢Ø£ ×˜’Ú©šÚ¯ªÚªžÜ´¥ÜŸ’֙ь֟›Ø¢œÚ¬£Ý´£Ø©–Ö¦Õ¤œÕ¬¨Ô®­Ö³ªØº²Øµ±Úº°Ý¾¸Ý»´Ø²°Ú®¥Úµ¬Ø´®Ù³¯×¸°×·´Ôµ²Ò¬¡Ô³­Ð²­Ó´®×¹²Ü²ۧ¦àqbßxd݆„Û°®à°èɴả޷¡à¼¨á´¤Ü±©ÚÁºå̾èÍ½åÆºâÆ¸á´ÜÁ¶ÞÀµß·ßµàµß·âŷ䯏âĸâĶãĸáÄ·äȹæÌÁèÐÅî×ÊîÙÍñÙÄìÚ¾‰RdOJRGXF^E`FbE`AaBb<Z<W 7^;`B`=eCc?dFp"Lz(P’8\±\tÎy‚Ò||ÒxyÎv{Ðx|Ï€~Ôˆ‚ք׈~׈€ÕŠ~Ô‹‚Õ~Ôˆ|Ôˆ{Ô†}Öˆ|Ö‰~ÒˆzІ|ц|уwÓ…xσ|Єzу{­BP¬FO¯BN³@J­CN¬DP®CN°AK¯EL±AI²@I²>J½CGÊPMÖ]VÝm]äzfå…lê‹nëŽmë’rï’pî–sì—wî•uî—~ï’rê‹pâ{fÜn^ÎUQµFL 6D‘+D“.C–3F?O¥@P¤8E©<K®@L¬DO«EP°BM¯@K±AJ±@L°BK±<I®@M­FR®BM²FN´FOºFOµFL¸GNµCJ¨;N¨:Oæœ~þΗ÷µémß~cÓh\Ê\X¾PU´BM²ES¬DS´IQ¶IX¸GRµFW¼R\µ@Q¹P\ÀLW¼ITÄY[ÄV\ºKX¿TbÈZbË_fÌ]bÀOX´K]ËjrÖxtÕxvÔ}~Ù‚zÖqoÏhhÒttÒ„ˆÎpg¿aiÍt~Ù~uÚŠ„ׄƒØ‚ƒØ“‹Ú™‹ÓƒƒÎ…ØŽ‚Ø”’Ø—Ú ”Ø™—ؗݦ•Ô›–Ó„wÓˆш†Ù¤“Ü –ÚšŒÚ ŒÙ£ Ú£™Ü¤šÚš”ÜžŽÚžÜšˆÙ¨ Ú–Û¨—ר©Ù¨¢Þ³ªÜ®¥Ý³¥Ô›•Ò™˜ØªŸÜ®£Û¬¥Û³§×¬¤ÏŸ Ö¤šÚ´­ÙµªÛº²Ø²®Ü½¶Ù¸²Ú¶¯ß¸§Ú¶«Ø¬£×ª¢Ù°¨Ù´¬Ù³°Ö¯¤Ö´°Ò±­Ð­«Ó®¦Ò¶´Ó¯ªÔ°±Ö·«Û¾ºÜ’Ûš˜à¿°èϹäªڪ‘Ú³žß±ß³ªãÀ·åǺæÉ¸æÉºäƸâŸàÄ·ÞÀ·ß¶àÀ³ß¸àÁ¶áÃ¹âÆ¼ãǼãŹáĸâ¶߿±ÞÁµæÊ¿æÍÂéÏÄîÖÌïÚÌòÜÄäÖ¿v6QKDVH\D`BbD^@`FbG^?]=X:^=c?c<dBdGjJt%Pƒ1W£PnÄrÓ}Ó|Íy}Êv}Í~|Є‚֊Ռ؋€×‰~ÓŠ€ÔŠ‚ÕˆÒ‡{Ôˆ~Ò…|ÒŠ}Ô†|Ô„xÐ…}Ñ…zÒ†xÒ‡xЂyц~Є{¯@N¬AL­CR³DN¯FP®AK«<I«CL®DP°?H±?J¶BHºHLÌQLÕ`UÜl\ä|dç‚fè‹nì‘qì•tî–oïští™vï—wî–zî’xê‡gäzdÞk\ÌWP¸HM¡4E‘,A+A–.Dœ5F¥6H§;H©?K®:H­AM®AN°FL°@J°BN²>I°?K¯>L¯DN®>L²AK³BL²DN¸FLµJP¸FL²BK©9O®<Pï¼™üΕö«vì˜jàxjÙhbÎZV¿LQ³HQ²ERºNS¶LSµFR­BR¶JVÀHQ½NXÅP[ÁT`¾S\ÇS\¿OYÁT\ÌY_Ì_jÈY[¿MW¶K^ÈktÖz|ÔrsÖ|zØ~xÔvqÒpnÐqnÑvrÊnjÀafÍpyÖ}xÔ{}Öxx؇ؖ“׊„Ò…ƒ×…Ôˆ‹Ô‹‹ÚŒˆÚ¢›Û¨¢Û¨œÖ”—Ø‘ˆØ–ŒÏ{Ô––Ú¢˜Üœ’Ý¡‘Øœ—Ö•’ÛœŠÚ¨žÜ¡”Ú›’Ø¡—ÜœŒÖ•–Üž‹Ù¨×œ˜Þ±£Üº³à²£Ü§™Ö¢Ø¥¡Ù§žØ¤›Ú¦›Ü«™Û´ªØ´­Ø³ªÖ¬©Ú°£Ø¶ªÚ·®Øµ®×²©Ú¸¯Ú±©Ú¦œØ¯¤Õª¨Øª§×­¨Ø°¬Ö°§Ôª¨Ô°§Ó­¤Ð«¨Î£ŸÒ¯«Ð¬¬Ô®©Ó±«Û¸¨Ý¹«ãÄ°çÆ­â¸¡Úµ¢Ü¹¦Ü·ªÛ»²âöæÉ¹çƶäÄ´ãÄ·âĶàÁµàÁ³ÞÀ´Þ¾®ß½²àÀ·àÀ¶ãÅ¸áÆ»äŹäµâĹ޼¬Ýº­àöæÌ½èËÀêÌÀî×ÊïÙÉòÝÁÛŲ\AL@V@Y<]?^>`Ad#EdD]@Y;Z8`>d>a?dIk$Pq$P1\–Imºf{Ñ{}Ö~~Òx{ÌwzÎy|Ï„‚Ò‰„ÖŒ}ØŒ~Ø~׊‚ÖŠÖŠÖŠ‚Ò‡‚Ó†~Óˆ€Ó†|ÔŠ|Ò†zцyÔ†xÒ†|Ò…{̆}ÒˆzÒ†}­FUªAM«BP­BN¬DPª:L«@M­BN­DP²AI³DK³BL·HMÅQRÐ^TÛl^äyaæ…gêŽlì’rî–mî•xî›vð˜rñ˜mî—rî’rìˆiä{gÜkZËRO·IOŸ5G“,B+@—0B4D¦8Fª=L«:H®=J¬<L®@M¬GQ­CR±@M®>J¬BL®@L­AM¯CM±@I²@L´DM¹IO¶DN¶BH²AL«8N¸FRöÍ©üÇó®xêŸ|ãx_ÞzcÏ\WÌ]XÀLUÅVR·KT´DPµFV°CR»JVÀKP¾JRÂPVÍRQÆOTÈX_ÇbdÉV_Ì]dÊ``¾P_²F[ÂhrÔuw×|wÔwwÔsqÒnnÒpnÔxvÒ|rÂad½_jÌpsÕxtÓuvÔ|Ô€ƒÓyÖ”ŒÎ|{Õ}yÖ…‚֊ْטؑڞ‘Ü¥˜Øž“Ôƒ‚Ò€ÖŽ‹à›‰Üª›Ü ”Ø“‹Üœ“Ûž“Ú˜–Ú—‹Û¤–Úœ”Ü –Ø›‘Ö˜’הڗۨܦ¤Ý¨›Ø¤ŸØ¥žÚ¨Ü©žÜª—Ü«œÜ­žÖ¤œÖ¦ŸÚ±©Ù²ªÚ¸²Ô¯©Ú²¥Ø¶¬Ù³¬Ø²®ÜªžÚ«œØ¨¦×›”Ô¤Ö«¤Ö¯«Õ°«Ô¤™Ò®ªÓªŸÔ­¥Î¤žÊš™ÈœšÎªªÒª¢×µ«à±俨߰’Þ­Þ½ªàºªÞ¸°áöåÊ»é̼æÈ·â³⽫àÀ¶à³ÞÁ¶ßÀ´à¿°ß¿±ß¾°à·àÃ·âÆ¸áøâÅ·äÆ¸àº®Û±£Ü¸®áúæÉ½æÊ¿êξïÖËñØÂïØ¸Â›L>O =X>[<_@]:cAb>[>\;Y<`Ab=f=gDdFbEn%RŠ:c¬[vÊt}Ö~Ò}|ÐwzÌvzÑ~~Ò‡Õ‰€ØŽ×€ÕŒÖŠÕŠÖˆ~Ô†Óˆ€Ó†Ô‡}Ó‰€Ô†{ш€Ñ‡|Ò†€Ñ†~Ò†}Ò…{Ò‡{Ó…z°FW«AOª>N¬CPªDQ°AN¬>Hª@M¬>J¬=I¯@L³?G·ENÂQNÍ\VÙn`äxcæ‚hèŽsí”sî–mï™sî›sî–yï–rî™zï‘qê‰näydÜhZÎUR¶INŸ3E“'@’)C˜.Ež6F¢8H¥=LªAL°?I²@M°=J¯AK«@M°>K¯AL¯BN®@M­>I°@J´CL³BJ·EM¾IN´FN·BH®FR¨6NºLQøÐ£þʼnô¨qñ¡nä|cÞqcØj^Ò`ZË\UÌVTÂNQ¼RX¸GR´HXºGR¸GV¼MU¼KV®>N¼QWÊTWÂTZÄ\cÈY\¼Va¶N[Ã`nÒqsÖvrÔz|ÕytÍlpËhlÒwwÔ‹„Ã_aÄhoÒuvÕÒzyÒzyÔ~|ÕŠˆÆsuÌpnÕ†}Òz~ØŒƒÙœÚžœÜš’דԉֆ{Ö‡„Ô…ˆÚŸ™Ü¡”ڈݘ„ÜœŽÜ–ŽÜ™ŽÞœÜ¦˜Ú›”چܢ—Ûž˜Úœ‘ØŸ—Ö–’Øœ™Ú”Ú¢—Õ œÙŸ˜Þ®¡Û°¨Ùª¢Ø£Ø¦šÖ¨¤×ž™×¦œÙ®¦Ø®¦Û¸°Õ´°Ô®¨Ú°¤Ø²¬Ø© Øª¤Õ¡£×œ’Ô  Ôœ™Õ¨£Ö­©Ö­©Ô©¨Ð¡•Ï ¢Ñ¢™É–—ÊÇ™›Ô±¥ßòäêݬ–×¥˜Ó¦žÛº¬à¼°Ý¼²âŹæÊ¼è̸æÇ¸äIJ۸¬Ü¼²àÀµÞ¿µàÀ±ßÁ¶ß»°Þ¾´à¿³âøß¸âÅ»ãĹ寏äÀ±Ù¨ž× “ܲ¥ß¾²äƼçȽêʽîÑÄîÔÀéÕº–^fKCR ;Z=[<]=^Db>dD\BX=Y=]<c<hAfB]<Z?u)TžMj¿o}Ó|Ö}{Ðy|ÐuxÌy|Ò€~ÕŠ‚Ö‹ƒ×ŽÖŒ}ÔŠ€Ö‹€Õ‰|׋‚֌Ԇ€Õ‡ÔŠ‚Óˆ‚ÕŠ€Ô‡|Ò‡ÔŠ}Ò†}Ó…~Ò‰~ÔŠzÔ†{§AQª=Kª@NªDPªDQ¬CP«?M©AL¬@M¯AJ­?J¬=H²CLÀMLÐ\RÛn\âwaå…eêŒnëpî˜qî•rî˜uî”rð—wï–vî’oê‰räv`ÝjZÌ[U·JM 4H”,C“+C™.FŸ3F¦;G¨?Iª@K®<K°AL´>J¯BN­?L°BJ²BN®@K­?L°CK°?J³@K²FN¶DN³CM´HN´DJ®BM¨7N¿TXùÔ­û¿…ô¬wéštÞs\Þzc×h_ÖjbÈQSÌjbÆTSÂMN¶CN¼HP¶CP½P[¸FR°HZ¶J\ÁSXÃYdÀT\ÄPTºP`´L`Âck×rxÓjlÖwyÕzuÎlqÒnpÌvwÑ€w¾Y^ºZfÐprÙ|tÖ|yØyvÔ‚~Ô†€ÒztÊgkÐprÒprÔ‡‚ÕØÜ¥ Ù™˜Ø”ˆÖ‹†ÎptÖŠ†Ý¤—Þ —Þ ”ÜšŠÕŠÛŒ{ÞŸ‘Üœ”ÜšÞ¢•ݧšÙ›–Û–’Ü ‘Úž•×›˜Ø™’ׄטŽÚ—•Ü›ŽÙ§žÝ¦šÛ¦˜Û£™ÚžÖ¨¡Ü¬¢Ùª¦×Ÿ›Ú¨–Ø®¨Ùµ­Ú¶­×²¬×¨¢Ù¢™Ù¦¢Ø©¤Ö®ªÓ¢£Ô›”Ó£ Ö˜•Ö«£Õ©¦Õ¨£Ï–Ì ŸÉŠ…Å‘”Í¢ Ý¿³ä®޳œÕž’Õ£˜Þ¹®Þº®à¾²àĹãǸçÇ¶åÆ¸ãÆ¶ã²ܺ±Ü¼³ÞÀ´àÀ¶àÁ´Þ¿´ß¿´à¾´ßÀ³á÷àÃºáÆ¼äÃ·åÆ¶äÆ¹×¥˜Ò–ŒÒ•ŽÛ¥”Úµ«æÆºäÄ¶æÆ¸îÑÁíѺáÉ´o,HQ@T<X:Z:\<`Ba>c$L_&LV;`>a;eDhDcDY@ZA„3\®cyÏ|~ÔƒÑz|Ìv|Ïz|Ѓ‚ÑŠ‚ÖŒ€×Š|ÖŒƒ×~Ö‰€×‹ƒÖŒ×‹~ÖŒ€ÕŠ‚Ô‡}Óˆ‚ÔŠ~Ô‹xÓ‰Ô‰|Ó‰|Ôˆ}Ò†}ÔŠzÕŒ{Ô†z¬<J¬DQªFT«?M«=Jª@M®?N¬@M¬@L­DP©?Lª@L³DLÄQPÏ\TÜn[âw_è…gìjî’nì—rî–uí™rí–uî–ví˜{ì‘tê‡kåzaÜl^ËXW´JS 7J˜,D’.G˜4J <O£:H¦=K¨:I®=J°CM²BL±DN±@J¬>G°BN°CJ®>I°DJ²>H°?L´FO¶DJ³GNµIO´DN¯@I¨7PÅ\Tù׫ü€ô¨zí•jâ•zÜoØpeÝr`ÓaX×]VÑZS»HN»HQ´JV¶DO³ET¶IYÂRXºGVÀ[bË\Y¹GR«AWµHXÈlsÔxuÖhjÔtpÖurÑkjÓsuÑrpЀr²T_»\hÐnlÖyvÔtrÓzvÕ€Õ|ЄÏopÍktÒxzÔ~ƒÑxyØŒzц‹Õ‡~Ùœ”Ò‚€Ñ}‚ÔŠŒÛ™’ߚݡڜ”Û”ˆÛ”ŠÕ݂ݞڞ˜Üœ’ޜߢ“Ú˜”ØŒˆÖ‚€Ö”ˆÙ£–֕ֈܖ‰Û ”ÚœŽÜ ”Ò֜ץ Ù¢˜ÜªžÚ¯¨Ø­¤ÚŸ–Ú« Ú±¬Ø¯¦×«¡×¥ ØŸš× žØ¦¢Ø¤¡Ù­¨×§¤Ö˜ŽÔ¡¢Õ˜ŒÔ¦žÔŸ˜ÌŽÆŽÇ––Û»°æÄ®á¹žÖª—׫žÙ¶ªÜ³«ßº±àÁ´æÆ¶æÆµäöä±ã±àÀ®Þ½±Ý¼±Þ¾±ÞÀ¶ÞÀ¶ß¿´ß½³ßÀµàÀ·à´ãĸáźâĹ䯹ãŶܰžÔ”ÑŠ‚ÓŒˆØ›ŽÝ¸©à¶¢Þ°Ÿä¼®íʼêήƕŒT<P>U@Z@]>`@_?^;]AZ?\>_;`9_=`C_H_Hn!LœJjÀn}Ô€Õ~}Ïy|Îv|ÎÒˆ„ÔŒ„ÖŒ~Ö‚Ö€Ù€Ö‹‚Öˆ׊‚ÔŒ…Ô‹Õ†yÔˆ|Ô‡|Ó‰|Ôˆ~Óˆ{Ò‡|Õ‡{ÓŒ{Òˆ{Óˆ}Ô†}Ô†z¬@L¨AJ¨AJ¨BQª>NªANª>L¬@M¬=I¯@K¬>I¬?H´GPÄNOÐ`XÞo`ãzbæ…nëlî–oì—uí–ví˜zí˜xì“tì–vî‘xê‡iä|jÞjZÎXW°FP 2H”.F”*E˜3IŸ9H¥>N«?L¨?L®@L°?M¬HS®BN¯BO­@L²?K°BJ®@J®AN±>H°CN¯BL´DM³AJµEK¶BI±AM£5Q½VTùÔ®ù¶~ô¦uî™lî‰géŠhàwaàr^ÞmXØj]ÌZ[ÁQTÆPO»IP¨2F¬BS¼MSµDP¿UZÇXYÄRXµHT°FXÆdjÕtsÔspÒmnÒfdÎnvÑmnÔ€tÆrr²P^»XfÐrpÕvuÙ{xÖz|ÑzwÓ‚|ÏvxÕ|{ÒryÒ|×…‡ÔŠ‚ÌrxÌnsÖ’ˆÎƒŠÑtpÎ}„Ú‘Œßž–Ýž’Û“ŽÙ‹ÚˆÚšŽÙ•ŒÛ”Ž×’‹ØŠ†Ü–ˆÚ –Ù–Ú‹€ØŽ‰×”ŽÖ‰ÓŠÚ€Ø˜ŽØœ•ؘÕ҈ГšÕ ™Ö™Øœ”Ø¤šØŸ™Û®£Ü®¦Úª¦Ö¡ž×§š×§Ÿ×¡šØ¢˜ÖžžÕ–“Ù§¤×¨¦Ö§¨Ø¥›Ò–šÔš‘ЉˆÐš–Ì’”È“’Ôªžä®æÀ¤Ú§Ù¬œÛ·¨Ý´¦Ýº¯à¸âĶä°å²âÀ²à¼®Þ¸¦Üº«Ý¹ªÜ½³Ý½°à¼°áÀ´ß¿µÞÀµÞ½²áõâ¸áÀ¶âÅ¸ãÆ»âȾä²âÀ±Õ›ŒÒ‹„͈ˆÐ‹‹Ö¤—Ø£–΀zØž–ḭêÄ®æÏ¸‹LWQ@T@]"J]C`A`@aB`A^@W=\8`<^9Z<^Cn&Vz0\Œ:_²cyÐy|Ó}ÒzxÏwzÏy|ЂƒÒˆ~Ö‹„׋،‚ØŒ‚ÕŠ׋|ØŠÔˆÔ†Ô‰}Ô‡~ÓŒ€Ñˆ}ÓŒ~ш~ÒŠ{Ôˆ|ӌҌӆ|Ó‡tÒ‰€Õ†x¬@JªBNª>JªES¥<K§@O¦BN©@J©@Jª>K¬?L±BL³BN¿NSÏa\Ýoaä€lç†hëlí•rë”uí“vì™pë•sí’vì•yìŽléˆkæz`Þk\Ì[V±GOœ6J’0F’.D˜.FŸ6H§>P¨>Oª>P®ER®DPª@Nª@N°BL°@L°@K®AL°@K¯@K°@L°EO°BJµBL´HP²@K²BL«?M¢7V¾`WúÔ¬úµpò®{ìfæ‰må€dÜ|jßpYØogÛdZØg]Ò\VÆNS±@NªBR¯<L¬:M»NTÃRV¾OW¿MV³GXÄjnÒjnÖnjÔnmÔnlÌdjÏjpÐwwÊzu¶R`¸VfÏjlÖpnÖyvÙxt×€{ÎwuËrrÍr{ÒttÕ„Ô…†ÎrrÌx}ÍzÑtÕ~zÕ~xÏvÚˆzÜ”à˜Þ›‘Ü•ŒØŽØ‰ÜŒ‡Û˜Ü”ŒÛ™’Ø–Ž×†„Ü€Ùœ‹Ø•Ù‹ƒÛ”‰Ù‹Ø•‰Ò–‘ØŽ†ÕˆÑ‚‚Ì…ˆÓÙ––Øž–Øž“Ùœ–Ø’Úš˜Ø˜Ú¯§Ù«¦Ô¥ Óž›ÕŸ˜Ö¢œÖž™Õœ™Ò–˜Ô”’×£ŸØ¬¢Ô žÏ™™Ê…~ʈɋŠÕ¢”ݺ¨ã½¢Ü¨ŽØª—Û²ŸÛ´¥Ü¹°Þ¾³âÇ·çÅ´ãÁ°á¾°á½¬Þ»ªÛµ¬Úµ«Ú´ªÛ¸°Ü»°Üº°àÀ´Þ¿³àÀµàÀ³Þ¿²à·âÀµâĹâùäÈ¼ãÆ¸äǺؤ”Ћ„ÍƒÑ’ŽØ¤—ؤ’ÀjhÆz€Ùž—೤æÃ¦Öµ¥^=TDR 8\C_"J` D`?b<_:Z:Z;b9d>\;\Bb Oy.Zˆ8d¦XrÈt€Ö|{Ó|}ÐvzÌvyÍ€‚Òˆ…Ò‹„Ô‹€×Œ€ÔŒ€ÖŠ€Ö„}֋׊ƒÖ‹‚ÖŠÓ‰ÒŠ€Òˆ{Ò‰‚ÒˆÒˆÒŠÔ‰|Ò‰€ÒŒ|Ô‡|Ò†yÔˆ}Ôˆ¬@L¨@K§;J¦>H£>L¨:L¥<I¥@J§>L§>Iª?L°@N°BOÅQRÓbZÜrbä{cè†fëŽpì’rë”uê“wì”té”sì“rê”vìoì†jæzcÝl\ÎXR±HPŸ8H”)D/H˜.Fž5J¥<K¦;Lª@N«?L«DQ®BN°@K¬@L¯BN¬>J®BM®AJ¬>H­@I±AH´DH´AJ³EN³AI°@Iª>MŸ4PÆl\úÌœõ±|ó¥lì–qëŽgç†héeÞobÛj\ØpfÛm_ÍXU¾FN³FS®@M¥8N²HQ¼LS»HP·EO²@TÇmrÔtqÒmjÎioÓifÐegÏlnÐppÊqo´P\¸ZjÈjnÓllÔllÖxt×€}ÐtsÐsrËloÑtrÔÎvpË~Ìx~ÖŠˆÖ…‚Õ{yÍjpÔ}{Û–Ö‚‰Ùˆ€Ü‰Ú‰‰ÝŠ‡Ü˜‘Û–˜ÙŒŠÚ’†Ø–ŒÜ’‡Ø“ŠØ‹…Ö†‡Ø‚|ß ’Ø”’ÙŒ†Ý‘‚Ù—ÕƒÊ~‚Ï‹ˆÑ•”Ô“Ö™’Ö•‘Ø””ÛŸ”ܞו”Ø—’Ô“”Ø¡–Û¬£Ø£œ×ž˜Ö“‘Ô™‘ÕÔžšÓ‘ÓšœÔ•–Õ££Òš˜ÅŽÅƒÎ”’Ù±¥åÀ«ÞªÖ¥–Ù­ŸÚª Þ²¨ÞÀ¶âȼæÄ´æÃ²ãÀ°äÀ­Ý¹­Ü¯¤Ú¸­Ýº­Ü¶ªÚµ¬Ýº°à»²Þ¾²àÁµàÁ¶áÁµßµàÀ¸âøâÀ¶ãȾäȽäǺäǵ⽭̇ˈˆÑŽ‰Ø£”Ø¥ÀkjÀnqÓ‹ŒÛ œß´¦èÑ´©v}P<P<U:X:]@d(K`$C^<[9X7^=h>c<\>_Fl#R~1\žIj¼o}Óz|Ô{Ôz{ÎvzËz}Є€×‰‚ÔŒƒÕŽÕŒ„ҀЎ‚Ö‡~ÔŒ€Õ‡}ÓˆÒŠ|ÔŠ~ҌՋ҆~ІÔˆzÒ‡yÒˆ}ÓÒ‹}ÔŠyІ{ÏŠ~Ò‡~«<G¬JT§=J¨@N¦>J¨BK©@L¨=J©>I©>L©@J­?L´DPÃSXÓ`[ßn^æ|dè†ièŽlërì–vë–rë–yë–tì–ví•xì’qêˆmæ|dßr`ÎYT¶FN 6H”*D“,F™0H¡8L¥>M¨=L¨BO©BP®BQ­AN¯@K­BN«;G¬>L®AJ¬@M®AN¯AJ°BJ±FQ°@I°AK¬@Jª?H¥8Kž2NÎziúΞú®jð xîškçŠoæ‚_Ýrfæ{^Ùm`ÜfYÖpfÑ[R¼JO¸GT­CT¶JU½JPºLWºET®EYÆdlÖrqÑpqÔkjÏjiÊY`ÍinÏtuÁaa±ZhºXeÆ`iÓqqÔwuÑqrÒrpÓtoÎrtÐnqÔvqÉryÈqjÂgrÐ|xØ„…ׂ~Ö‚ÎosÏ{ƒÔzzÜŠÙ‘ŠÒ‡ŒÓ{ׂz؇ŒÜŒƒÝ£”ے؆ƒÙŠ„Ø†€ØŠ‚Ù‘†ÚŠÖŽ‹Û†€Ý˜†Ù–ÒvqÌÑ‹‡Ò›–Ó‹ÖŠˆÖ”Ž×ŒƒÛ–ŽÖ—Ú”ŒÚœšÚ”ŒÙŒŠØš”ؔۘכ•Õ–˜ÖœšÓ’•ؘԜžÎ’Ҕˌ‘ΈÎȔبžã¼¦â±‘ÚšˆÕžÜ¯™Ü°¢Þ¾²áÁ²æÈ¸æÅ²å¯ßÀ¯Üº¬Ü¶ªÙ¹«Ü¸¬Üº¬Û¸¬Ü·«Üº®Ý¼±à¾´ßÀ´â³ßµ߿¶à¸àĸßøÞļâȼæÉ»æËºäɸ՘‰Ë†ƒÒ’ŒÚ¢–× ŽÂpnÀw}ʆˆØ™”ÜŸšã¶¤æÒ¼‚BTN <R<X;[<]AaA^A\=W<[<`@e@`<\AcLv.ZŠ7a¯_wË{~Ö„ÔyyÍvyÎx{Í€|Ó‰‚ÔŠÒ‹€ÖŽƒÔŠƒÕ‹†ÕŽ€Ôˆ~Óˆ€ÒˆÒ‰„ÒŠ€Ó‹Ћ„Ó‹}Ò‰}Òˆ~ш~Òˆ|Ñ…}ÒŠ~ÔˆxÒ†€Ðˆ€ÐŠ{Ô‰|¨>Kª@M¨?L¦=J¥>L¨>L¨>K§<I¦<J©>L®<Hª@Q³DPÆPRÒd\ân\æ|fç†jèlì”që–vì–tì“yí”rï”oî”tí”pêˆjäzcÞn`Ì]Y±GSŸ;P”-H“/I™2J¡7J¤:L¨=LªAN­@N¯>M®@K®@L®@K°<H°BN°@I®@M°BL³FN°DK²BK²@J°DK¬BK©<G¥8K¢1MÜ’súÄ‹óªzó©në™tëœmÜtjæˆdÚvoÜl\Î`\ÚpcÏ]YÊQUÂRW·MVµCR¸HQ¶BPºHWËilÔtvÔppÓnnÒhiÊfjÉehÌmkÂgj³O^ÃajÉcnÓtuÔsrÖpmÔ~}ÐkkÐjmÐppÐytÈhmÅimÉrvÒ~~ÑyzÓ~zÒpoÎhoÔ}~Ú‰…׌Ø€Úƒ~؆„Ó†ŠÔ€„Ú…~ÕŒŽÚŠÙ†Ï‚ˆÒ†”Õˆ‹ØŒÚŒ‡Ý’…ܘَ„ÒxÍyzÄw€Ôƒ×œ˜ÙŽ‚Ú’‡Ø”Ø™Öׇ„Û˜‘Ù”–Üœ‘Ù“’Ø““؈֕‘Ö‹ÔˆˆÖ‘ŒÖœ˜Ó—˜Ò‹Ô•ŽÒ“‘Ê€„ÉŠŽÇ‚ˆÔ”Žá´¢ä¶ŸÞ¤‹Ø ŽÜ©“Þ­Ÿà¹©äÀ­åİçª㿪ཨ๤۸ªÜ·¬Ú´¨Ú¹°Ü¸®Þº®Ü»°ß»­ß½¯ß¿µàÀ´à¸á¹áÁ¶à·âÄ·á·âÄ»âǼäÊÀçʼæÊºà¶¤Ì†ƒÌ†…Ôž–ØžŽÇwrÇ‚ԌՖ‘ÒŠŠÜ£œçֹ̳§V@P@T?Z@\<^?_@^=^&MU<[<aAcB]@^Gj#Sy+Z NoÀo~Ò‚„Õ~}ÐxzÌx}ÑyzЂӇƒÕ‰Ö~׌|ÔŒ‚Ô‰~Ôˆ~Óˆ}Ò†zÓ†{Ó†~Òˆ€Ó‹{Ó‰€Ò‡|Òˆ~Òˆ{Ї{ÒŒ|Ò‰{Ó‰|Ї|Óˆ}ІyÒ‡zÓ‡z¦BUªBM¨DS©=L¦8F©=J¨?J©@L¥<Mª>K«<I²BN¼JRÌUTÚaXánYä|dç‡kénì”pé”sê–ní“xì”tì˜rí’tí’uëˆnæzgÞqbÐ[V´JR¢4H’,CŽ.Fš1EŸ:K¤:L¨<Kª@O°AN«BL¬@O¬?M¬AM²@L¬AL­@J­<H«?L¬@G±@K¯@G°<I°BL®BL«:F¥5Fž/Lâž…ø¾…ø¶zñ¤{ô¯pëoéjÞv`éˆfÜtbßq\Ûj^Ûj\ÍUUÐZT¼LS¶JR°?O®DWÈegÊ`jÕjiÑlqÎfhÌglÊjpÎtt¿X^°TfÀUfÆ^dÒtpÕtrÔssÖuvÖwvÎnlÑmoÍvrÀ`gÁbnÌkqÔzyÕ~xЄÏpsÊgoÑ||Ù€؇€Ú„Ûˆ†Ô{~Ôx|ÚŒ‚Ø‘–Ñ~ƒÔ~ÐÎv‡Àsă™Ôˆ‘ØŽ”Ø“ƒÜƒØˆÐ€Å~‰ÑŽ×Ž‡×Š†Û‘„Ö’Ö‡†ÛŒ„Ø“ŽÚ’ŽØŽØŠˆØ”Œ×Š‰×“ÙŽŽÖ”˜Ô†ˆÕŽˆÑŽ’ҋҊҔЈŠÐ‹ŒËŒŽÅ‹ÌÚ¬œâ¸¢à®‘ÙŸÚ¡ˆÛ¨—Þ·¬ãÀ­ã¼©ã¼¦á¸Ÿá·žß²™Ù¬™Ø¬žÚ¶¦Ü´¨Û¶¬Þ»®ß»­Þ¼®Þ»­Ý¼¯ßÁ³à´âøâ÷âĸá¸à·á÷âĺâǺäË¿åʽæÌºãŶ΃ȅ…Ò–Ò˜ŽÇuyʇŠÔ—Ó‰~ÉvwÌ€†á´¥îÙ½¨tvLBO?V@XD^A^?_>]EU:^$KaBeBdB^E_Jk+X†8b³dtÏ}Ò€€Ò}|ÍuxÊvyЀщ„Ó‰‚ÔŒƒÕŒÕ‹€ÔˆÑŠ€Ò†~Ó„|Óˆ‚Ôˆ~Ôˆ|Ò‹„Ò‰}шÒ‡}Ò‹}Љ|ц}ÑŠyω|Ò†|ч|щ~χ}Ò‰Óˆx¨=K¦?J¨BR®BP­AN¬<J¨@N¨?M«@L¬@H³@M´@J¾GPÉTTÖbZàpaåzeæ…léŽpì“oì–uì—rì˜xë™xì˜pì˜tínëˆpæ|fÞshÐ]\¶NT¤:N“)B‘.C˜-C6J :K¥>L§>L©<M­BL­=L®=J¬@N¯9G®?J°@L²AJ®BN¬AN®?H°>I°BN±AM«>I©:D£2Gž0Iì°†ûÅŽö¸…ö¹yíœzð©|èpæ“pâ‚jä~_ÜdTáycÙo]Òf^ÅLN¼HP´<L©<NÈgf×mkÑhjÇXaÐjhÈfrËdjÍrrÂ_b´WeÀZfÄ]lÓtuÐlqÒllÓutÖzvÐhiÐuwÌipº[g½]lÌhqÓz}Ô€|ÐssÒ{uÈdmØyz׈ˆØˆ„Ö„Ú|ׄ‰Ö|Ð~ÐwŠÓ‹šÎ‰¢ÅŒ«¼…œ²ž¨v–¨j†¬by¯gx«Uh¹^aˆˆÔŠŠ×Š„ÚŽŠÛˆØŒ„ØØˆ„Ø‘ˆÖˆ‡Ô†…Û†Û–ŽØˆ×…Ö”“ÕŠˆ×’×ÔÒ„ŒÔ‘ŠÑ’—Í{΋ŽÊ„ŒÅˆÊ…ˆÖ¤™Þ³›ä¶ŸÛ˜†Ù “Þ²žÞ¬¤ß¸¤çñå¬ỨܴœÛ± Ø­žÔ­ŸÕ°£Ù±¨Üµ¨Þ¸¬ÝºªÜº­Þ»¬Þ½°à¾³ßÀ´à÷àĸãøâĹâøá¸ß¸áŹáÅ»ãɽæÊÀåÌ¿çк֪¡Æ‚‚Ñ–Ñ’†ÇzzÎŒ‡Íˆw¾ed²Ud¿mvÙ˜éÌ·åÒ½t0HJ<R@WAZA`FaB`D`"LZEc!Hi,PgDc@aH`Gt&X›JjÆqyÕ€~Ö~|Ñy~ÎwyÎ|yÓ…Òˆ~ÕŠ€×ˆ~Õ‰|Õˆ~Ó‰|Ó‡|Ôˆ}Ô†|ш{Ô…zÓ†|Óˆ~ÔŠ~Ô‰}Ó‡~Ò†{ш}чyÒˆzЊ{Ò‰~Òˆ}ÒŠÒˆ|Ó†|Ò…x¬>Kª@M¨@N¬BP¨AP©AM¦>P¨>J¯@J­BMµDL¸HRÄHNÏTTÚ`Xàm^åzcèˆiëŒrì”tì˜tì•vî–rì—vî“tì•pìmîˆlæ|fßqcÎa]°DKŸ5E‘*C'?–.Fœ4H ;L¤>O¨AQª<P«BO­BN«>M©>L¨<K«BO®BK®>J¬>J®CL°@I®@K¯>H°@H¬<H§:FŸ.Ež-Jé«úÆ’ü¾‚ò«xõ½†î”kí›pèŠiæißq\Ü~kánVâmÞhVÍb\¾DK¬3JÂSVÏbhÖjiÐhkÈenÄ[fÉjuÌom½\e³VfÁcjÄZfÓutÕqmÑkjÐllÒqrÒjgÎnrÉgi¿[lÅipÇfsËjrÔ€{Ð|ƒÎrpÀ_kÐkr×yxÛ‚€Ù„Ú‡…ÓyÈs~³^~´d}¯i‡®h„¸rŠÅx‡Æ‚ŽÈ|ˆ°b~½zÃxz±v†•U|+VÍ~€ÚŽ‚×ˆ„ÛŠ€ÚŒ…Ö†ƒÖ†Ò…‡Ó‹–ÛŠŒØŒÖˆ‰Ú‹ÖŽÔ„‚Ø…~Ò‰‹Ð„ŒÐ‹ŠÓ‹’ÔŒŒÏ„ˆÑŒÈ‚ŒÈyy˃̊‹Þ¬–羦ߠ‡ÙŒØžÛ­¥á¹§à¸­åº¢èÀ«á¼©Ü³ Ù²¤Ù³¤Ùµ¦Û²¢Úµ©Ü¸¬Ûº°Þ»°Ýº°Ü½­Þ¿²ß¾°àÀ´âÁ¶á¶âöâºâ¶ãĹáżàÃ¹ãÆ¹âÆ¼æË½æË¾æÌ¾åƸɈ„Ì“’Ћ€Æ€Æ|r³TS¢MXš>W°XfÅ{„â¶¬îØ¼Ì¬žT?K<P :X@ZDaDcD^A\DZ>bBl)LcDbFcNj!Q…2\²`vÏ}Ö‚~ÑxxÐyzÍz|Ђ~Óˆ~Ó‹ØŒ~׊Ԋ~Ôˆ€Õ‰~ÓˆÔ†{Ô†}Ò†|Ð…~ш€Ôˆ~Ô…{ч~Ó†{Ò‡yшzÓ†uш}ЉzχzЈ~Ð…|φ~цzÎ…}¬DQª>N¬BO¨@N¨<J¬@KªEP©AM®AL±@M·HL¸FPÂHNÌSUØbXào\åzaç†lêŽnì–rí”sì—rí˜tì–xî”pí—nî’pîŒmå~gÞo^Ï[S´DL¢6H‘'A(C•0F™4J¢7K¡<M¨DR«BP©=L¬?K¯<Gª;J®<HªBM®>J®?L°AM±<J±=J°CL´@G¯BL®<H§8Eœ/Gš+KꬂúÌ™÷¹…÷ÀŠò¡wðª~êŠhè˜lè€\åjä‚[à|mèzVÝzkÕZQ¶ES¸HVÇ]dÌ`aÇ^hË`fÌbfÇ`hÌqrÄag­N_¾\gÄ\fÏopØvrÔstÑkjÒnsÐloÑspÆfg¶VgÊdkËjmÍsyÌntÑmoÎwrÈ\jÓ{ÔzÖvyØ{yÓw}¿dvžDfŸP{¤\§Wv Ji—Eh”Ab¡Nm»gvÈm|¨QsÈ|…Ëx…Ð„Š·wƒ”Nzª^lËyÎÕŠŠÚŠ†Ø‡ÖŒ‹½u€²uŠÂzÍz€Î~„ØŽÖˆŽØŒÌyŒ¶i§ZxŒ7XłІ̇’Æv{Æ‹Är}Җഢ䰖ݠŠÖ—ŠÚ©¢Þ¶®á¹¬ä½­æ¾ªäº§ã¼©Ý¶¦Û±£Ú´¤Ú¸§Û·¬Ú·«Ú¸ªÛº°Ü¼±Ü¿µà¾³ÞÀ±à´߾³à³â·áÂ¸âÆ¸âĺàÄ·ãŸâÄ·âùäǺäȽçÍÀèÏÁæÊº× –ΌΈ€È‚v²ZW”:G”1IAT¢H^Áv†Ö¢£ìϾíÚ»—_bM
+8J
+6Q
+7Y;\?_<\@\<\?]@f@lB_@`I`Mr&TšLjÂny×|×|ÐvyÌv~Ï}ЄÓ‰‚Ԍ։€Ø‹Ö‰|ÖŠ~Õ‰|Ò†|Ò†zш|Ò‡|Ô…|ц}Ôˆ|Ò†|ц|ц}Ò‡{Є}ч~Ð…yÑŠ}Ј€Ð‰|Є}Ð…zÐ…uÍ…{¨BQªDR®?L¬CR¨>N«BP¨AS«AN¯BP¯BP¸CL½DNÃHPÊSV×d[àq^å{_è…fìoì”së”sì˜rì—sì–sî˜tî˜nï‘sîŒnäƒpßpaÓ]T¶HL6D‘+@Œ$?–+@œ9K£8L¥=JªBN®AL­?L«BP¬AK­DN±?I¬>J°DJ®@K°?K±<H¯CN²AG±>J°:Dª>J©<F0Dœ,I檈øÉüÆŒøªyö”ïšlæ˜tè‡`äŽnæ~WÞvhèƒ^à{dê{XÐ_`ÆPUÊZ_ÄU^Ç[aÉ^bÅ^iÊ]dÊns¼]`¬N]¼XdÀ\hÏjlÔptÒklÓpqÐhkÐehÐtr¾Z^¼XcÊhnÆamÊksÍrrÐ~‚ÇclÃ`lÐsvÕz~×€ƒÖ~…Ðq|·To”Cmª\{Ä~ŽÆn~ÅizºXp±[r§PnœKnˆ6^“>d–Oză”Ù’“ÛÔŒ¼wŒ›_”T‰’S…ŸZ~©Wx¶`sшڈӆŒÇŽ˜°z’žV~»pˆ¹kˆÆxЏŒ±—^¢pw5pf O°mʆ’ÂvŠÌxؤ–㳚঎؀ؖ‰Û¦žâ¶¡æÆ´æÂ²æÀªâ¸¥à¶¢àº¨Ü¹ªÜ¹ªÚ¶¬Û¸¨Ú·©Ù¹«Ú»±Üº¬Ü½µàÁµàÀµßÁ¶áÀ´à·áÁ·âøãĹâŸâ¶áĺâĸâĺãÄ·åȺæÊÁèοêоܮҕ‰Ì‡|¸h`œ;H‹3J–<Mœ<O¨L^¹anÖ›šçÆ»ñÖ¸Ùº¢f:M :P8T 9[:a@^<]?Y?\;c>f>h D_G^Kh N€3\®_vÉz‚Ó}|Ô}zÎx|ÐwyÑ‚~Ó‹„Ò‚Óˆ}Ô‰ÕŠ€Òˆ~ÕŒ|Ô‡|Ò‡Ôˆш‚ш€Ñ‡€Ñ†~ш~ц|Ї}Ñ„zЈ|цzшzЇ~Ï…yΆ}І}Є|Í‚zΈ|΃zªDN¨BP«>MªDQ©DQ©@O¨?M¬BM±BP­>N¶AJ»CHÆJPÑTQÜdXäpZæ{bé†kìlí–vë–uï–qîpí—vî–ní—vï’pí‹lè€fáp^Ó\R¶HNŸ4D'>,E•0D˜0Dž8H¢<J©>LªAQ©@O¬=M±@L®AN±>K°AK³BK±=KµBP²@J²@L¶@F²=H´>F«<F¨4?ž-C+Iå{ùÒ¢ö¶ˆøÃŽöªzòµ…ðžfç›uéƒ^Ûvdä}XÚpfè…bàp[ÜhYÊTWÀQYÂ\aÂT\¿P\Æ\fÈflÃ`d¬M`¶]h¼XdÎmr×rlÒniÒjhÎefÎnpËfj¼[b¸XdÄbjÊdiÈhnËjqÍnrÎmkÁ`lÎnrÔutÑzÓw~Ó{~Áh€«Rvºn‰Èo|Ín~¾]s¶Yu°Tq¢Ll›Ff—Df‹?ks&\N|À‰¤Ö” ÙŒ˜Ø–»l’¤hš¦lš f™œiš™e™†J8^–Jh®a{°b·p‰¡Vv“Lq‹Cjl$Nw6]h$WŠFd„FpQIw4VÅ…•̈‘ۦ㮛׎€Ô‰€×’ŽÙ§ Ü¶«á± ä¼¦ã¾¬â¼«Þ¶¦Ý¸¬à¼¬Üº®Úº®Üº¬Úº­Ø¶ªÚ¹°Ü»°Ü½°ÞÀ´ßÀµàÀ´ßÀ¶áÁ´á´á³á´ãÇ¼ãÆ·ãÁµâøãÅ·âøäźçÇ»éοæÇ°Þ©Î‚Ànc©QRŽ2E“:M—?NžBS¤BVµ\kцŠâ¶¬îѸéÔ¹LOO:N 9X?\=_>\;`<]9Y9Y:c?iCbA[B\In%R˜LjÁp~Ó}~Ñ~|Ðx{Ív|Ì|Ó†‚Ô‹‚ÖÔŒ‚Õ‹Ôˆ€ÕŒ~Õ‰~ԌԊ|Ô†|Ñ…|Óˆч~Ј‚Ñ…|ц~І~Ј~Є{ЄxЃ|φ€Î…|Ï„{Ά}Ð…z̓xЈxÏw®@N«DP®BMªBQ¨@N¨JV§@P¬CR®FS°GP¶FL¾HOÈOQÔYVÝf\âq^æ~fè…hìkí•tìšví–qî˜vî—tî—vî˜uï“tîŠféião[Ñ\V³HQž7J*E$?–,Cœ2F¡6H§=K¥>Mª<Jª?M¬>I¯FQ²FM°=M°?L®FS°>J²@J±AM±?I²?K¸?E²@F¬<G§9D /Cœ,Páš~÷ƘúÌšù°võ¾‘ù¯uòžhå‹nátOÑaVáw[Ül`ë”bÖbT¹KX»KVÀSZÁ^bÀT`ÄcfÂ_a§FX²RbÁXeÊhmÓplÔllÐhkÎjlÍlmÊfj¼V`¼[fÈflÌ`fÊflËjoÈfkÃflÅ^hÍltÒz}ÐjnÒtwÓz‚Áaw¬PrÂx‡Íz…Çlz¹\w›Fl›KnœMm‹<\0Sy(Ps&Qo"\Iz©¦Ìƒ–шš¼~§¢n¡¤r  \Š”R|V}@vr;tx=y†Wu9il.dn2`t0`n(Uq+W^NUHXLQAUDJH]"Q¾‡”㸪ܞ‘Ï‚{Õ‹‚Ô˜œÜ´¤ã¿¬ç¿¬ä¹¦ã¼­â¼ªÞ¶ªÛµ©Ý¹ªà½®Þ½­Û·©Ü¸ªÙ¸¬Ù·©Û¹®Ý½®ßº¯ßÀ´àÀ³ÞÀ·àÁ´áÀ³àÀ´âÀ²ãÅ·ãÆ¹âĶäŹâÅ½ãÆ½äĺåÈ»æÆ°ß¯–Ïw¼po¬NQ˜;G“6G”7Hœ8Gœ<N¥FZ°TfÈ‚Šà®¥êƲêÓ·¾‚T:L 9T:X<_B_=]<^BX8[8`8c>h@^?TD^Hƒ<a­_rÏy|Ò€Îx~Ëv|Ëvwу‚ÖŠÔŽ„Ô‹‚ÔŠ€×ŽƒÕ‰~ÓŒ‚ÕŠ|ÖŒ€Ó‡~Ò‡~Ò…|Ò†Òˆ€Òˆ}Ò‡Ò…~І~Ñ„zІ}ЇzІzÌ…~Є|ЈxÏ…|·{Î…{Ð…zÒ‚v°BQ¬BNªET®FPªEQ©BN¨DNªAN®BP´FPÀFJÄFNËKNÔTOÝh\äsYè~dé†iì“lí˜qî–qí—qíšwí–xñ—tì˜uï’rìkæ~gâp`Õ^VµLN4FŽ.FŒ&A•.F™1E 7K¨?L¤>K«@M©?N«BN°BP°BL°?J®BO±FP°=H°=J²?L°?J³BJ¸<F³=G®?H±:C¦3Eœ*KÕy]øÕ¬û¹€ø¿‹÷°xô¼—ø³nî›qìˆXÔlVÛeSËSPâ€`ÝhRºNY´JU¹LX¾R[Å\`Æ\`À[_¦BU®Nb½YgÈfqÒqnÎhjÐhhÏfeÒkjÊmn¸ZgÂdnÊ`dÀhqÈdnÎllÌkpÄcm¾ZbÌjsÐptÕutÐnuÊlyÁ^q§Rp´i„Ên}Ìq~¯\|˜Ah Nu¨UqœBe–Bg¤Pq P{ˆ;t„C†Ž^–œb“²lŽ©l•¤x¤h–P~v0gh*bd$Xh'et8tŽd–€N~b Xp6kk+b^LZEYER?SGSGK>JH\"Všn‹Ö®£Ù–ŠÉ}€Ï’•ذ±ß¼²ä¾­å½¨ã»ªâ¸¦á½­Þ¸§Þ¸¬ß¸©Þ¼©á¼ªÝ¹©ÜºªÚ´¦Ø¶ªÙ»°Üº­Þ»®ßÀ°ß¾²áÀ²àÀ²à´ྰྮ⽭åÇºåÆ¸äÅ¹æÆ½æÆ»åǺãÁ¬Úª’Çvd®XTžDM—>L™@O˜9J™:G›9H¢@P BW±Xd̃‰Ý§è·¤î̳ßìv/BY$IR=X=[Aa?a@\@\?V@a@h@g@aAX@O@bJ–IfÀoxÏ~Íz}ËvwÊsxÐ|{Óˆ„ÔŒ…ÔŽ‚ÓŽ…ÓƒÓŒ‚Ô‹€ÔŠ~ÔŠӌҋ~ÔŠ‚ъЇ‚цω‚Ò|̃|υΆ€Ï†~Ї~·}͆}Í„{Ì„|Î…{І|φ|Ò†zÒƒvª?P¬EP¬EQ®HQ­FP¬AO©DP©AP²DN³@KºHOÅIOÉJNÒVRÛf\àr^é~`êŠfì“pì“píšrï–rî•tï˜vî”tîšuî“qíŠlæ‚lârcÖ^R¹KQž0F&B‹)A”1Fš4Hž8N¢=N¥@P¦>L«CR¯AM¬>J®<J°BN°AP²BM²=J°BK³@L°@K´CMµAH²DK­>G­=E¥5Cž,IÀZNöΟúÉ–üµzô¾˜ü¾~ô³Œò¢jæ„eÛeVÊPLÑbTÒ^QÍc^¾UW¹T`»R]¸NZ¿U]Ädg«FR®Rc¹Q^Â_kÔjnÏhmÐhmÏfjÌhkÊfh¸U`Â^dÍdjÊflÎjqÂeoÊdkÉjqÆ`hÄdpÓnrÒrrÒlvÒntÆdt£Io±ZvËo|Ìn|´`€˜Rv®ZyÀhz²Qh¦Jx´fжj’¡^Žƒ8m|1i~Bt„D}‚>pšh—^…€9qv6kr4ke#Xh"`‡R†…X„k,Xi+bj,hm0dr5hWKRCN?K
+:RQONNQŒ`‘µ†ŒÛª“ÏŠ}¿xЗ޼µäðæÄ±åÀªä»ªà»®Þµ¦Þº¦Ü¶¨Þ¶©ß·§Þ¹¨Ü¹¬ß»«Ý¹¨Ù¶§Ú¸ªÛ¹©Ü¼¯Üº¯Þ¾±ß¾²Þ¾²âÀ°à½´àÁ´ß¸©â¿±çÉ»åÄ·æÇ¸çɼྤЕ{¯\VœEN™;J;I–<NCS˜<Lœ>Kž<M¢DR®Ta¸dqΉŠá©œæµ¢êÀ¥á¼ž“PTR;UBV:]@b@dC`=]B\DZ@^<hAf?\>SDQBr*S¨XnËwzÑ{xÍx{Èw~Ëx~ÒƒÔ‡Ö‘ˆÔ‹ÒŒ€ÔŽ„Ô‹~ÖŠƒÓŒƒÕŒ~ÔŒƒÒ‰ÒˆÓ‰~ÑŠ†Ï‰…χІ~Î…Í…€Ï…~΃~Ї~Ά{Ï…}ψ{І}Ï…|΂xÏ‚xÎ…xÑ„y¬CP®DN®ER¯HP°FN±BK¬BL¬=J®AM¶JR½HNÄFKÌLLÕWOÝcTàr`ç|`çŠnì•lì–rì”tí”tí—vî˜qð–pî—sî•sîŠlè€iãp^Ô`X¯GN 4F.D(B–2G›3F¡<J¦>L¥DQ­>J­?M«DK°BJ¯BJ®?I°DM²AL±@M­@K°BP¶?I²BK°<G±?L­<F­;E¨4Bž,F«9Kô˨ûÇøÅ“ü¾€÷·‹ýº{ð¦ví‘aÑ]WÌQR¿INÌqlÓk`ÄdlÄS[Ä[c¸S_»Z`°NX®MZ¾S_Æ[dÔlkÒkpÒhiÐgqÌhkÈdf¸Ze¼WaÆ\`ÉdnÎilÌjqËkqÄelÁXcÆ`kÒlmÒqtÏjoÑhoÉm{ªIl²a|ÂizÆewÀ[r¢Px¨Vy¿a¯V}¨W†œO€œXxƒ=h}7il"Vt*\u-\t+eƒFyXŒ†N†ŠTŽ~<y{2p€B‚ŠV‹y<ir2hyAxm.cb$Uk>fn1h\!MVDM>C 9B
+:HD{Dlͤ›Ü ŠÈurÃv|Íš¤Ý¬œâ¼¬æ½¤â¾­áº«â»¬ßºªß¹¨Ý·©Üº©Ý¸¦Ý¶©ß»«à»©Ý¸¨Ý¹­Ú¸ªØ·©Ü¹«Ü¶«Üº¯ß¾¯Ýº°Ü¼±àÀ´à÷ãŵãÂ°æÆ¹éʺèÊ·äéƋr£MNšBO“9L˜9L™9J–7Jœ<L AOœ=M¤BR¥I^®XjÄ|ً榖캜꿠¸s`s):V9V ;V9Z>bAb@c@_=^?[>_Dd=j?eCX@PBXEŒ?dºj|Ð}Ï|{ÍxzÉv|΀~Ó‰‚׎„Ø‘„ÖŽ€×Ž€Ó‹†ÔŒÔ…Ô‹ÔŒ‚Ô‹‚ÒŒΊъ€Ñ‡ƒÑ‡~Έ„ψш‚Ј€Ï‡‚΄~Ѓ{Ї}І|χ~΄{Î…~Ï…|΄|΄{уz°BR­DS°FR°GR®FQ®DP¬?K«>I®@M·FP¼DNÄFLÈMPÔXTÜeYàp`å~gèˆgì“lì–tê˜sì–pî•qî™qð–rí–víoìŒnèƒgãoWÐ_ZµGN 3F)CŒ,B—0H›/Dª:G«<K¨=M«<H®@N°BM¬@M®BN¬=J°DP´BM°AN°>I¯DR´>J²@J²=H®>G®<Hª:B¤:E ,E¤/Gíµ€ùÌ¢üÁöÀ”ü¼ö½’ò¥ræ‚dÚn[ÆKWÈY`݉zÒlnÚ{fÆW`Ê^_ÀY[¬N`§DT·UeÀZdÎgfÏfjÔnmÐjpËlpÃfl¶Yc¿\iÈ^bÈbhÌdhÇhpÇhpÆdjÄ_dÆ^fÎjmÐmrÕjnÐjtÄ[l­Ji®[yÂhyÄhxÈfx´T|N|®fޤ_˜T‚Ksv-Zk%RgNf RePhSlTx2m‹NŒ†O†’r£„EyR†Hz–iš~;nZ‹ŠX„]Lg(d\Vo@mwDyNCJ;OJD BMJŠ_|É¡™Ø–€º\d¾jvÓ¨¤á¼¨à°žà°šß°šÝµ¢Ü¸«à»­Ý¹¬Ü¶¦ß·¥Ý¶£Û²£Ýµ¤Û´¨Û¸¬Ý¸¦Ü¶ªÛ·¥Ø·¨Ø¹«Úº­Úº¯Ü»¯Ü¼±ÞÀ´â¾°â¸äÀ¯äÀ³æÇ¶æÆ²Ü´›³ji˜DT˜>NžBRš=N›>Oš9L—9I >M¥HW¬Vg±^o¿oyÒ†…à簤뾣èħ°tmZ7V>W<\<\>_BcAa>`=^<]AX8b>f=j AbEXDUJl&S¢SnÅt~Ó}xÐ|zÇu|Êy~Є„ÓŽ„׈ւՎ؎€ÓŽ‚Ò‡ƒÔ‹‚ÓŒ„ÔŒ‚Ò‹ƒÒŒ‚ÑŠ‚ÒŒ„҈ъ‡Î‡Òˆ‚ІƒÐ†€Ð…|Ï„}Ά}І~Ï„xÊ…~̆~Î…|Í„|χ€Ì…~Î…~³JT°IR°GQ³FN®HQ®BN¯>J­AK¯?L´DN¼FLÂHNÈJJÒWQÚdTás`äzbç†iètì•nî”rì”rì–rìšsï”tî—oî“rìŒlè‚gâp^ÖaX´FM¢6F1F,E–,Fš4E¢9J©=H§;K«=J¬>M°?I®@J®>J®BJ°@L¯DP°AL­;H°@H´BN±BI²;F¯<F¬<H°@H¦=Iœ6F™/MÚvúÉœøº‹û„ö¸‡üÆ~ñ§|ê…X×^XÔ`XÛwgØmjÖ|uÐ^^ÐspÄ^f²GV¬HXµM^¿T`ÍdhÐddÎlpÐhoÐhjÆfu¹P^¼]lÉ`mÆZ^ÊgnÍenÆhnÄgqÅ_hÅZfÒnrÓkmÐjlÓluÊap§Ffª\€»dzÃfyÌjwÄa~¦P|’KzˆHtu1^s.`~3ly0hv.`lQdLh"TjSt,dŒT’ˆJ{•pŸ‚Bs|>uj"T:lˆAv†O†’Xx0ev<{v=xXRlAer@tF >C
+<@@d,fn„Ö®—Ô†v´[fµfuÔ¢žâ¹ å¹œß®˜Ûª›Ù¬ Ø­ Ú¶¬Ý¸¨ÜµªÛ³¥Üµ¤Þ·¦Ù«œ×±¤Û·¨Ü¶§Ù´¨Û¶¨Ø³¨Ù»«Ú¸«Úº°Ü¼¶Û»°Ü»°ß¾±Ü¿¶Þ¿²à½²áÀ¯Ô«–º€x®p€§cxž@V >L¤APœ:L˜<Lš<M ATªMb¹hsÊvwÙ‡Þ‰|㙇訔鴖è¨͇g<VA]>[<_>`>eEd?fA^:^<X:]<dFj Cj'F`(PXL\N„;a·duÍz|Ò|xÍ|zÇtxÐ|Ò„Õ”†×’†Õ’†Ó„ÖÔ†ÔŒ~ÔŽ„ÑŒ…ÒŒ‚Ӏόъы€ÏˆÐ‰€ÎŠ…Ð‰‚͇ϊ€Ñˆ}Έ‚щ|ц{φy͇~ψ€Î†}Ά̓~͆‚Í€x²HX²IVµKX³DP¯GW®<K¯BN°BN²BJ²AR¸BJ¼FPÃIMÒYUÜbUàr^æzcç†nêrë”uê™vê—té–rì”rì˜pë•sî“pìŒnè‚gãr]Ô]T¶HN 8JŒ*DŒ(B“-D™4H¢<N¤<Nª>K«=I©AL©?J¬BJ¯>I­@K±DP°BM®BL®AJ­@L®DL°?N²<I²@H®AL°BH¨<G¤4Dš'G¿_NøÐ¬ûĆõ¸ú»ö²…õ®rä†jâ~\Ö\SÌdkÖwuÚvgÔ€{Ðe_Â[g¦DU³PcºO_È_dÒjnÏfgÍbfÍloÆbf¾YbºZfÆ`iÈ]fÆ^hÊckÌjnÅdk¿ZgÃUaÎnsÑuxÍhnÎkmÐbjÅ`t™7`¾i€Èj|Éhx¾TnžDo†7lp(^n&Zz3l…F}~;qq0^e MaHbJcNm Z‹L‚™b–X‹‰R€s2b]D`Sj(X‡Tt5h|6jIƒx=m^"RM EiDnb)ZB?< <YN©yˆÙ¡Ð~m·^n½v‚ר ã°–䶠߬“Ù¤”צ›Ö©ŸØ±¤ÛµªÛ³§Û³¢Ýµ§Ý´ŸÚ®ŸÚ²¡Û³¢Û²£Ü´©Ü´¨Ûµ§Ú¸«Ú·¬Ú¸¬Ù¹­Úº²Ý¼°Ý¼²à½²âÁ¶à¯ذ˜µ|u˜NhRm«vŠ®k|¬Vg¤BP¨BS¡>T£J^´ao¾ksЂ|܉|ß‹z唿—柎ꬔçÀ¤Ã“|m#>T <Z?^?^?`=fCeCiAb?^;[;Y=]8f?j"GbD`(T\%Tk(TŸRnÈt|Ò}{Ð}{Èz|Éx}Ò…€Õ„Ö“†Ø‚ÔƒÔŽ„ÖƒÔ†ÔŽƒÔ‹‚ÔŽ‚ÕŒ€ÒŒ€Ñ|ӌЌ„ÎŒˆÐŒ‡Ð‹„Ή‚Ά€Î‡‚Òˆ~Ï…|Ï…|Ð…~Έ}̆χ{ІzΆ~Í{Ì‚zÎ|±LZ´FPµJV°HU¯EP²FP³GS±BQ±BL±BN¸BI¼ELÆLNÒVQØf]àtaå|cç…dêŽpê”sê”mê”uì“së”oî”sì•qî’píŠlèeãs\ÕbX¸LSœ8IŽ,DŽ+F•0Cš2H 6D§:G¦<K§=J¨=L®?L¯?L®@M­<J®AK­@K°BK«@J¯CO®@K±FM¶>F¶BK®BK°BI¬>G¢:E›-E¨8Kñ‘ùƘú½€ó¯ˆø½ƒñ¬|ò¤mß}cÊmjÇ\ZÚ€uÓheÞyeÂhn¯HY®EVÀVbÆ_kÍnrÐfhÑhnÎjkÉen°O`´WhÄ\hÇboÄ^hÌ]eÉ`fÇfnÃ`h¼ZiÍ_hÒjqÐgjÒkmÒjlÏirÆhz>dÀh€Èfv©Mo‹>lv,`fRg!XŠJ‚‰Lzl'SdL_LbL\DfQ]L„;užj›œ]ˆ’Z~v2`]FX F`N‡[Fyl,eI|€LzXFJEHB|WŒqAƒHHg/Y®~†Üž‡Érl¼foɆŒÝ³®â·¢ãµžÞ¯œØ©›Ö¦ŸØ©œÙ±¥Ù±¦Ú±¡Ú°¢Ù²¢Ù±¢Ú±ŸÙ¯žÚ®šÙ¯ Ø³¢Ü´©Û¸©Ú²£Û¶©Ø¶¬Üº¬Üº®Üº¬à¾°ßÀ³Þ½¬Þº¢¿ŠzŽFX‚B_”Xv˜Vv«uвxŠ»ly´`o¾hoÉmjÒzà‹zâtæ‘wå“vá|æz蛄馒ìÀ¤Æ‘~g6T>X<^<^=_<fCdAc@h@d?\C[<W8`7j@l!Bg!HZH^I€3Z²duÎx{Ï|xÎ{|ÊsuÏzxԀד„Ö‘€Ö“‚Ö‚Ó“…ד€Ô’…ÖƒÔŽ…Ó„ÒˆÓ€ÒŒ‚ÑŒƒÐŠ‚Î‡‚ÓŠƒÐŒÍ†‚φ€Í†ƒÑˆ|̇€Ìˆ€Î†~͈€Ï‰~Ј€Î‡‚Ά}̃΂{Ê‚|¶LX²GS±FU¯DQ°JU°DT²ER¯@L±BM°AM·CKÀAIÉKNÐTP×b\Þq`ä}hæ„lëŽqì’ré–së–qê”tì˜pì’sî•pî”rìŒrçhâr`Ô`X¶JP8I*C)D‘.F™2H 4H¦<J¨<I¨@P¬?M­<K²AL®CM°BM±@K­BL¯AM®AK¬BN®>I¬<H®=J²@H²BL³DL¬BJ¥;H/Eœ,JÞlùÌ¡ö»Žûº}ò®‚ú¼ƒî vçœxà„iÌqp×i[Ú€sÍ\XÄ\^³LUºPbÆTaÔhkÒihÐilÐceÂ`j¸LY´L]Â]iÄ_jÉcgÉcmÊfj½ZhÅ]e¼Yd²UoÈnÈiuÊdrÑelÔhoÕr~Ên|§Fi»`v®Sl{0Zj$WdTw2i‹M|v6_^FXEZDdN`F\D`N\L‘Wˆ–W‡›Pt{2]^HdPbR‰W‘\Šo*`y;tz@q]IJ >RNI?€[f3g|<k½‡Ú–€Élh¶_jÌŠß²¨ä¼«á¶¡Þ®™Ø°£×¨šÔ¦ Õª Ø° Ø¬¡Ø¬›Ø«Ô©›Ø± Ú¬›ÙªŸÚ°£Ú±¢Ú°£Þ´£Ý´¢Ûµ¥Ü¶¦Ú¸®Ü¹¬Ý½³Þ¾´ãÀ®Ü¾¦ÀŽv‚>H|<\‰Hk†=`•Uq”Nk¦j†´xЀ„ÝŠ€åˆuæŠrèxæŽwæxå|蕂Ⓜ蚋쪔îĤԣŒj!<P;W;[;`>cAf Cj Db?dAe>_:aA]=a>d;j?a9W<VFdL—PmÀpzÑ|zÌzxÉ{€ÉsxÑ€|Õ’Ù’„ÕƒÖ’†Ö”ƒ×”Ö”†Õ’€ÔŽ‚ÕƒÖŽ€ÓŒ„ӈςы‚ÑŽ„ÑŠ€ÐŠ…Ð‰Ðˆ‚ψ€Í…Ή~·‚Í…|χχ~ÌŠ|͇~Î…z͈˃z΂|Ë{µLX°MX±IT°FS°FQ²HU²HT­AM°CP³EK¸BI¾FKÁKMÐTQØ`Xâp\æzdéˆgìŽjì˜tì–pë•së”sê–rì–vî–nï”níŒpébáp\×`V¸LPž8F)DŽ)D•/Fœ7I¢6J¦:N¦?N§=L©?M©=K®@L®BN®BL±DN°BJ®DP®BM®@J¯AL¬AK°=I°CL²BL²CN±CM§<H¢3Gœ.MÊq[÷Ò°úÀ€ö´ŠúÁ‰ô®~ú¼‡ê˜p߇|å™t×rhâŽsÇ^]«AL¶P_Ã`gËdkÑknÎfmÔljÈen°JV«F\ÀWdÉ[cÈ`hÅ_jÆ[kÇ`iÃ_l¼Vd¼Wb»ly´dpœMhB_ªF]ÉasÖpxÊjv¤Dd’Bbv*Uh0^g$Zx8h„Ami"Pb$R[IWAh#Ph"OU :]FaPz;qšlšx.Z~4_dH\Gh X‰W‘”g“‡D|@{R‰TEO>i4vF @QJ„XŒƒKoÆ‹†ÚsÂdf¼hqÌ’–Þ­–廤⼨ܮ™ÙªœÖ¦›Ö¤žÔ©¤Ö®¤Ø­¢×«šÕ¨šÒ§žÔªšÔ§šÖ¨š×­œÖ¬¢Ù¯¤Ú±¤Þ¶©Þ¸§Ü´§Þ¶¨Üº­Ý»°ß¼ªá¼¢Ì¤ŠŒIG‚<YaI};X l‡”Sx—Tp˜Rvaz²|Ó‡†à„æŠwåxçtç‘vçvå{阃è¡î³•ðÄ Ó£Šv(=R;V<V 8Z8b?b>d<jCdBdAfE`:^;]:^<e?g@^EVB^Os*T¬]qÎ{~ÑzxÌwzÉxzÎ{yÓŠ€×’Ø’„Õ”Ö’€Ô‚Ö”ƒÕ“„Ö‚ÔÕ‚ÕŽ‚҆ӂЊ€Ð‹‚ЊЉӋЋ‚ЊЈ‚͊ψΆ€ÌˆÎ‰‚̇͆̆€É„Î…~΄|Í„Ìz²JW´JR´IR²IR²FQ³FP®EQ®EP³DK³EL³AJ¼BIÁILÐVTÚbWáo_æybç†lênë–pê–tì–ví–xì–rï•qî”pî”pìˆlégâr_ÖbYºNR 8IŽ(@+F’-Fœ7L¢;L¢<M¤?O¨=Jª=Qª>J¯@K¯@L«?K¯BM¬@K¬>K¬=I¬>J®BM¬AL±@G¶CH³DL·EK°FP«@I§9Ež/I´FKîÁ’öÆŸüÇö²ùÄ‹ò¢tã‡p袄ærߌuØmUÄ^\¬ATÂZcÊ\cÎ`fÐinÐkmÎce¿Xb°Rbº_lÄ[dÊ^gÈafÀZh¸ZhÁblÂ\g¾U`ÎhoÕlpÖjlÍhp¸[sJl<c¦Eb¸VkšFeq(Tg%Xl-`{;ky0bm*[f"Xb ReLj%Su/^X<R ;\Fp)`†IvˆH{cGiMdOcP€FˆP€y4m]–Š^Šf&ZMGnF|nC{:>b6lª|¢Ë™”Ïzm¼_f¼cnÑ””߸­à²¢äº¥ß¹©Ö® Ö¦œÑ¤ Ø¨œØªžÔª¢Ù¬œÖ©šÖªšÔ¦—Ô§™Ó¨›ÒžÓ¨ž×±¥×´¦Û´¦Ý²¢Û±¤Ü³¡Ý¸ªÝº¬Þ¹£Ù¸ ¶‚jf;fD‘Mfˆ?jy,R­wƒ¢k†˜Tp¡d™Rr±t‡Ì†’Ú‰†âˆ}è’{è”|ê“vê—|êšï¦’î²–ð¿œÙ©Šv)BR9V?Y;^=^<a?f>c?e?c?c?d?`<[7_>`=g>d@]E^IdKA`¸juÍy}ÌyyÊtxËvzÒ‚|Ö„Ø’€×’…Ø•€Ö“„Ô‘€Ö”וƒÕ‘Ô‘ÕŽ‚ÕÓƒÔ‘ÓŽÓŽ‚ÎŒ„ÒŒƒÒŠÑ‰ƒÎ†„̈€Î‰€ÏŠω~Έ|ψ€Ìˆ‚Ά̆Ê„€Íˆ‚Í„{Í…|É‚´FP°JR³GS±IT°HU²DQ®DP¯BN´BO²AL°DMµFG¾FIÍOO×]Qân\æzcê‡hê’në•rëšqì’sí–zë“qî”uî–rî•uìŽsç‚nâr`Öe^¾KPž6H&BŠ$@’,F˜0HŸ:M¢8H¤;J¦>Lª?N¬;H¬=I­>Lª>L¯CL®CL­=L­>J¬>H¯@K¬>K°>K´EL¹EK¼FN¶DH±DN­>H¢9LŸ6NÎv[÷زùÂúÍ—õ´|ê âˆlì~å „äkÀ_]¨8H¶NYÏddÉdlÄ[fÌ`bÊfm½R_­CV»boÅ`kÄ]fÉbfÀVbºYf¼UfÅ[f¾WeÊckÑflÖnqÕlsÇjt¦Hf-N˜Fb‰6_x,X{:ft8kn+^y3i„?|p1el*^f S^Lm'VŠNƒ^CQ
+<R >bR~>vx;bx4b^DbGbJh$R‰N~t*b€Cy‡No1gP Go>x‹xªQLEHiÆ“ŸÊ{s®ZeºftИšá¸¦ç½§ä¸¥á³¡Ý´¥Ø¯¢Ôª¢Ó¦™Ô© Ö©œÓ¥›Ö«žÔ©›Ñ¥•Ò¡–Ò£šÓ¤˜Ñ¦œÐ¤˜Ö¯¡Ø´©Ø´«Ü¹­Ú¶§ß³¢à¶¥Ü¶Ÿ×©’´fY€.ElEf?FbžWn8a’Ld­}“š[x£m‚ž\{¦gz¾‚’Ð{àˆ{è“yê“xì˜yìž„í¢ˆò²”ê½–»rXo&:U6S 5X7]:a:a=f?d@d@hDf Dc Ba?_@\=`8b=e;b?Z@_Jp(QŸPl¼pzÊwxÉx|ÆpvÌyzÖˆ}ؔؔוƒÕ‘€×—‚Ö‚Ö‘‚ב€Ö“…Õ’„ÕƒÓԂ҃уԊьЉƒÑŠÐ‹ÎŠÍ‰†ÒŠƒÏŠ€Ð‰~І̊ƒÎˆ~Έ€Ì‡|Ë„‚͈Ë}Ì„{Ë‚~»NZ¶KT³KU³KZ³IU³HR®IT®BN±AL®AL­EN´AI¼DJÌPQÕ]VÞm[æzbéŠmëpí–që”vì’wí•sì˜uï•xî˜mî”uìˆhè‚jäp_ÚbY¿MNž4FŒ(CŠ&C‘/H›5H 6I¤:L¤>L¥>M«;I¬?K®<L®>H®<K¯<I¬:G°@HµBK®<H°?J°AJ±@J·FN·DK¸ELºIJ²FN²DJª>F¢3H¯BMì¶„úÔ¯ú„öƓ짆à„mè˜zìŸxä~Íe_®BTÇ^aÐgjÌdkËbhÆ^fÃ[d´N\¶TgÈ\eÊ^fÄ`lÀ\lÂYh½WjÂ[jÂZmÌ\lÓltÍclÈ]fÀUe¬Nd”@bt'Vm"Pv"S{4dq6dm(Z?q|;ko0`e&Xb PTD\IŒR…<iS<S@UAl(Y‹Hzq1_cFX@cHs'Xs)Vv,^aLm-]‚P‚ZNSKŽ«€bŽG Ej0lµˆ¡ª^r«\t¿lzÕ£ â´¨æº§ãº©à·¦Ý´¤Ú³¦×²¦Ö«ŸÔ¬ ÖªžÓ¨£Ñ«£Õ¬ŸÒ£›Ô£”Ñœ’У˜Ô¨žÔ©œÐ¦š×¯¢ÙµªØ·©Úµ©Ý´£Ü²¤Ý­žÚ¦œÕ“Œ±YfŽ2OŒ8Vˆ<^}.OJd–SlŠDlš_rªvŽœ\s¤iƒ˜Rq»|‰Ë€ˆÞ‚zæŽzë’|ë—‚î Šòºšç´ŠžTN\6W:V<T
+6Y:`9b;b<h<i Eg!Gh"Ci$Dc@`<^<\8_9e<e>aC\Fi"N‚4Xª^oÀrvÁnuÁpv¿ltÐ~|ׂ֓„Ø•†Ù”Õ”‚×”€×”ƒÔ•ƒÔ‘‚Ô€ÔƒÔ‘‚Õ’„Ó„ÓÔ€ÔŒÓЋ„Ò‹€ÏŠ€Ò‰€Ð‹ƒÎ‡„΋€ÏŠ~Έ~Έ€Í‰€Î‡ƒÌ…΃xÌ…€ËƒzÌ‚|΄}²HS´JT´JW±NX²MVµIR±GR­ES­@L¯AI²>H±>H¸CIÉPNÕ^SÝm^å{dè…lëpì•vê˜tí”yï–qì˜uíšuì—sï”qí‰lçiâubÖ`X¾JMž4G+D(B”0H—5G 0F¤8J¦<J¥<Mª>M¬AP®AO­@K°@L®>J°=I°>J°?N®<I²>I®@L°AL¶EO·FM¸HOµHL¶HN´CK¯DJ¨;H 2JÄaPöÆ”øÐ¥úÆŽó®€ç¦‰ç˜{쨂è¥{Ãg`¼cfÎ`aËagÈdlÌdoÃZg´Rb²TfÄ\fÌbgÍflÇalÃ`o¿Zq¾\r»UlÀ]xÎjxÍar¶Sp­Ss®Tr°Xr¨KlžHn‘<fˆ9gp&Xk$Y}6j‚Aoe%RYITBSC\Sz3l˜f‘t2\R :S ?YDo+]ŠIxr0^]?`BjLdDgNaNYIt?k~IO IX UŽ~®l6fˆKz–i˜Ro Oh§iŒÕ«ªå¸žä»¦â·¨Þ¶¨Ý¸¬Ú°¢×¯¥Õ¬¡Ó«žÐ§›Ñ¤šÕª¡Õ«žÔ­ Ñ¤˜Î˜ŽÎš“Ó§šÖ«¢Ó¨žÑ«¡Ô±¨×²§Õ°¦Ø²¦ØªÚ¥žå°§ê±¨è¢›Ø‚¬BUŒ-OŽ9P•Pt„<^ŒDb‹GeŠCgªt„¡f€ b}›Lm°l„ËŒÝè•‚í ˆð­”ñº’ᣉ8CX<W;Z;Y=[ 5_;c;i>f=c=jBfAk Dg=\<Z<Z<^=]:f>dD_Gj$Qt(S’Hd´hr¼ox¹ls¸jtÁptц‚Ø–‚×—…Ù’Ú”Õ’‚Ö’„Ô~Ô‚Ö‚ÓŽ€ÕŽÖƒÖ€Ô‘„Õ†ÖŽ€ÔÓ€ÒÒŒ…ÑŒ†ÑŽ†ÐŒ…Ћ‚ÑŠ‚ÐŒ~ЉЉ€ÎŠ~̈~ˈˆ‚Ά|Ì„}È~Ë‚|´N\´MR³LV´KU±EO±FR®HR°EO²CL®CP¯>H°>H·@EÇLLÔ\SÞjZãzhè…jëŽtìtì—xì–zî˜xî™vï˜vì—rî“rîoéhâs`ÖbXÀMQœ3HŒ)Cˆ(B.F™/Bœ5H¡:J£<M¦8I«BO©>OªBN®?L«?I®>L°BN°AN±?M®>J¯>N±BL¶DO¸DL·GL¸JP¹FL¹HL·FM±DN«?I£8L 5Rß•lúÒ¦øÄ’ò²ƒö·„彩ð®~Ú}o´=FÙybË^[ÆVZÈaiÆbp¾[g·ViÀXeÃ_hÈdq¿]w¿n‡»gŒ¼_ˆ·a‘¶V†°\†¼^Æb~Èa}Æ^oÃUg¡B[•=X›<b4^~.^t.d‚:nŠIt|@mb QUFQCS C_O‚<q˜h’dGQ<YCaMn*\v.Zq.[bHcFr$QbEbHaOUGzFz{;zTLuI†Œl£›`Žº”œlœ„6[®b~»‘¦â± äµ¢á¶¥Þµ¥Þ·§Û´ªÙ¬ Ö¬¡ÔªœÒ¤šÑ¨žÔ¨˜Ô¨›Öª Ô¥˜Ïž’Π™Ð¡œÑ«£Ô¯¦Ô¬¡Ñ«¢Õ±©Ô®¤Õª Û§žâ¦¢ç®ªé°ªé³¨æ«Ÿà‘ŠÉ]e¥>Pˆ2]‚4Tžb€–Rt“Lr–Sw `v¬z¥f~¤d‚¯k€Ç€ŒÜ‰‹î¤ò¶–ð¶‹Èv]€*>Z:X?X:X;^<a:e>i@h?f<d:gBe>h>f@^=]=`?^8b>e>dD`Hi$O4XŸWjºpu¼ns¯fr¯dpÄv|ÒŽ‚ו„Ø–†×—„Ö•‚Ó’„Ô‚ÔŽ„Õ‘~Ô‘€ÔŽƒÖƒØ‚×’Õ‘‚ÕŽÓ‘‚ÓŽ„ЌЃЂϊ‚ЈƒÐ‹Ï„ÑŽƒÐŒ~Јщ€Ì‰„ÍŠ‚˅̉€Î†~Ë…}ˇ€Î„~µKV´JT´LV²KW°FR²HT°EQ­CN®?N¯DM¬>G®<Jµ?FÃILÑ\UÜk\ät`èˆoì’pì•wë–tî–zí–yî•rîštðœtð”sïlè€hâtb×`T¿JR 6H*F‰(B’,D˜0D›4FŸ7J¤=L¨:L¨CR¨@N§?O¬>K¬<L¬?M°@L®<J®BK³CO®BO¬CO±EO¶EO·FL¼INÀHP¾LRºJP³JP²FJ¨8EŸ4N¼ONóÈž÷¾•ô·ˆó´‚ó°‚ñ¶ŠÍf`ÇghÙoaÆU[ÂPWÁ\d¾WaµNb½`lÇ`qÊ`jÈev¹]v¼^qºXl²Rl´^|²e†³^†¥U‚ŸQ{¦_ˆªR~ Bl~1]r%V‰6f{,[ˆ:j†:hŽDu‰H|p,\aN\KZFTFbOˆN€ŽU\CVCeH~Ev^A`HcHgRm!V€9m„>z€>z€>}p%c†XŽw8sk)lƒR‰†P¡_ƒ©l•˜]Ÿ`†Ê¦ËžªÞ°œâ°œÜ®¢Ý¯ Û´§Õ°¤Ø¬žÔ©žÓ§›Ò¦žÓ§žÑ¥žÔ§˜Ò¢•Ò •Ò¢–Ò¢šÔŸ•Ò¬¥Õ¬¤Õ¬¢Ñª¥Õ¬§Úª¥æ®¤éª ê¯¨ë´ªë¹®ê¹¬æ®¢â “×qr¼HUœ:N7^ˆ<T¢l„“Kf†?`€:Z¬pƒ©rˆ«pŠ®jƒÆ|Þ•’꧉ߑq§JIi9];Z>Y>Z>]<[8f>j>f>j!Fh@eAf@f>k?b<\;Z:b=`:f<f?^Ec"Lo)U?^­dp¸qr´iq®dn´kxÊ€}Ô“ŒÖ–ˆØ˜„Ö˜‡Ô”„ÔÖ€Ô’Ô’‚Ô’„ÔƒÖ‘ƒÖ’‚ÔŽÕŽƒÓŽÔÒŽ€ÐŽƒÐ‚ÑŒ„ЂҌ‚҃ы‚Ћ€ÏˆÏŠ‚Îˆ€Ê‹~ˈ€Ìˆ‚Ë…}̈Ì„zÌ„zÌ|¶LR´LX´NW´KS¯FT´CP¶FL±GP°DP¬@Kª>M«;E°:H¿JMÐ]YÝl[âzgç‡nêŒoë–xê˜tî”ví—vëšxï—vð˜wð–pðŽmè€hâvb×f[»LN 5FŒ&AŒ$?’+F—2Ež4F¡8H£9I¦;Lª>L©=J«?N¬@L¬<J®>J¯?I­BL­@M°>K°?L®@K¶EP¸EPºHQÀJRºLPºPT¼JP¶KO¸EK­BJ¤8K¤6Qè©„öز÷Á˜ôµ„ô´€ò»ŽÖxhÛu^Ì\[ÅY`¾S_½V]°IY°L_½YeÆajÄcqÂ^n¶Oe´Rb°I`Â]rÍbrÏ`pË\sÊbvÂj~§Xq’Fop%Yp%V|/dr&X„0aƒ0`‚9gŒFt|;km.Zd"PdLXJVGj$X|7j€Ani"Tf Rn(Sp2^[?^>aB^@` EaCi"Lf$N^FbJ|Auj)Zn,dyAt}A€†L‡¤z¨š^ŒÄš£ÆœÒ¢ Ûª–ܦ”ؤ˜Ö¬ŸØ°¢Ô¬ Ô¤šÑ”ÒžŽÒŸ˜Ñ¥Òž’Ñž“Ó¡“Ò¤šÓ¢šÒ¢™Ñ¡šÑ¤Ï¥ Ò¦¢Úª¤ä²¬è±ªê°¦ê±¨ì´©ë´­ï¶¯ï¼¯í¶¨ë°¡ãŒ„Ô^b²;J’7Ox-Xn,Hœa€„:[~8b€Aa®vŒªq‰¯p‰¾}ŽÖЉÐqn¶XX€)F[ :Z =X;ZAY>]>a>f9g=h>j@h>j@i Bj@h A^9Z9[;`=b=g>bA^Cf Ly/VšOg¶jq¸ow°fs®hsºmtΈ€Ö–†Ö™…Ô”„Õ—„Ô•†Ô”ƒÕƒÔ”†Ó‘€Ô€Ô“Ö’Ö‚Ô~ÓŽ€Ó‚Ó’ƒÒƒÒƒÒŽ„Ò„Ñ€ÓŽ€ÐƒÏŒ„Ί~Ћ‚Ћ|щ‚ω͈}΋€Í„~Ά{Ì„zÊ}É…‚µHT¶MVµLV³GS³FR´HP±DP°CL¯BP¬@K¨>J§<H®;E»JMÎ[XÚjZà{hå‚fèrê’uë—vìšqê—xì–yïšwî˜zð•sîqé‚kârbØcWÂOQ¢6FŒ&A‡%A‘+C•1D–2F :L¡6H¨?L­=L¯?K­>L«>N¬?L¬>L®:H¬>J­@N¯@K°@M²BL²BPºDM»HP½GN¾JR¾PV¼MVºJQ·HO²BI¥;N¤5Pá—zúÑ™úÒ¤öÀŒöº†ö´‹æ›rÐibÂXbÆ^dÂ^jµJ^¬DX¶Rh¿`pÈ^kÁ]l¹Wj·Sj¸QeÆfnÑfnÑboÄ[q®FgªH`Ìgs¾\sžDjw*So,Zo*]dPi!Un!Vz1d…Ap~7gq*\g!VZFXO`Pp-bl$Zx4k‚?v>rh#NZB]@^<]=^>_C_C\>Z=T=R@l-ar*ZˆFtz;nm/nzK„”]‹™l–±~¾Š‘Ô¡˜Ú¥œÖž•Õ¥žÕ¨žÕ«žÒ¢—Ξ”Λ”Í–’Ò¦žÑ —Ï ™Ò¢›Ô£›Ó¡•Ò ™Ï¢šÏ¤—Ìš“Ϥ¡á°¨ê¶©í·¬ë°¨ê²©ì°ªíµ«ìµ¬ì´ªî¶­ï¶©î´žèœŽÝnj¿FO£6K-LkOr0JNo‹@ct'R f}¬nˆ´x޼}É€„Âhm´QSŠ(BY<X 9X>V;Z=^<gAh@h>jAl DjCg@jBe?a=^:Z8Z6`<l<f>_@`Hp'S‰=_«dr»qt·lp­an±doÁtw͈‚Ö”„וƒÔ”ƒÕ˜„Õ”‚Ö“Õ’ƒÑ˜ƒÑ‚Ô’€Ò‘‚Ô’‚Ô“…Ó’€Õ€ÔŽ„Ô€Ô‚Ò„ÒŽƒÓƒÓŽƒÔ€ÒŽ€Ð‹ƒÑŠ~Ј}ЉЊ‚ψЈ|·~͆|ω{Ì‚{ʃ΄z¶IV²JR´HU´HO±HW´FP®FR°BN°BK®BMª=I¦7F¨;J¸IMÎXSÚj[ávcæ€héŽoì’uë–wí’tî”wê—xîšví˜xî˜tðnèmãtcÙbXÂNM4GŒ(BŠ&@”0G“,Dœ1F£<N¢:N¨:K­BO°AL­AM¬BP®BO­BPª@P¯?M°AMª>K¯@O¶CK²DN·HP´DN¼MTÁQS¼NT¼KQ¸LO¼KJ´DL£:N¦2Nß–€ùÓ®üΖøÈšø¼Žôµzä†`ÆX\ÄZ]ÄZcÆ\d¸Td´RkÄ\g¿\e½Ta¶Tj·RgÉ`pÐlpØhjÒafË\hÆ\m«He¡Og²Sc£?Z•5X.Wt,dh#PcL[K^Ln+Z{4gx.dq(^y4hp)\d!U^Jw4m^Ot8pT†ŒM~k$UW:[=^BZ>]>^B^HZ@T<SATBx6hœQx Liˆ:gx9}Žo¦£~œ¸“£Ì™“×›ŒØ£›Ö¤œÖ¦ Ö¯¤×­¡Ò¦œÐ–ҙ͗”ÏŸ–Ñ¡šÒ£œÓ¦œÔ¦šÑ–Ïš‘Ò£šÍ¡›Ë—˜Ô Ÿç­¨ì°¥ìµ«îº¯ë´¨ì¶­ìµ©ì¹®îµ®ì¶¬î¸¨ðº¦ï±¢ìžàvrÈMU°<JŒ.Kl!HTCu4RŽGe|.]ˆA`©pŒ³p‡¾‚’Ë…ŠÊps²NVv>`>T;X :X:]=b<hAlCi@h<lEl An&Gl$Hf@`<^=Y;[7\7e;b<ZDcLv*S˜Nhµgtºpt²jq²bk¸ktÈ~}Љ‚Ó’Õ”„Ö–‚Ö”„Ö“‚Õ•‚Ô–…Ô‘‚ÓƒÔ‘ÓÔ‘€Õ„Ô’Õ“}Ó„ÒŽ‚Ò‚Ó‘ƒÒ‰€ÒŒ†ÑŒ‡ÔŽ…Ñ…Ñ‹ƒÐŽ}ЈЊ~Ñ‹~ÑŠ~Ћ~ωΈ}Ά|Ά|̆~Ì‚~²L\²HR°HW´HT°FS°JS±HP®>I±@I®?K©:E¥7F¦<N¸LQÌZVÛh]âvbã‚qèŒjì•xë˜vì–vì™xîšzï˜xî˜yï˜xíoèläudØf^ÀPP¡4H(FŠ%E’-H–4I7M¢>N¢8K§BQ«>N¬@P¬?N®DR­EP®AN¬AN®?M²?L¬<L¯<K¯@NµAN¸FRºHO¿LTÃMU¿MT½PV¼MP¼FK²DM¬=M©3Nà’zûÔ¢ýÌ›ûПúÈŽñ¨sÊRNºFPÀX_Ä^i¸Vf»VfÃ\fÆ\d¶We¬E^¸NbÉanÔjqÔejÒdjÒcgÄap¸QdŸ;X’1L•7P|Ht"M‡Btq-[^EXBUBWFaKz7lu,\q/a{:f>qa QXHu3d^Kd$YŠRŠ™g”|:kV<\@]>^BZ@V9XBS<M 7P@l'U”Np®_tŽ/R˜Bg˜_š¬ˆ¬·{Õ¦Û¨˜Ú£–ب›Øª¢Ù°§Ù±¤ÖªŸÒ£˜Î˜ŽÍ‹Í˜”Κ’Òœ—Ó¦ Ó§žÑ ”ÊŠÊ’‰Í›–ј–á¤šê®¤ì¶§ìµ§ìº¯í¾¯ì¶«ë¶ªë´¨ì·¯ì·°ð»°î¶¨î¶«ï± ëž‘å‡|ÒX\´9G’,Ir C^AZ>ŠHb€4Z~5\§l„¯nˆ»u…΃Êtw¬HRl@\>X<\<Z>^=d;d;j Af@k!Ej>iAl#DiBd>_<`A[9\:b<g>_>ZAbJ‚=`©aq¼rv¼pv³kp¯fn¸tvȇ€ÑŒ€Ó€Ó‘‚Ö”€Ö“€Ö’Õ}Ô“‚Ó‘Õ“|Ó€Ò|Ö~ÔÔ‘Ô~Ö“ƒÔ’€Ô~Ó€Ô€ÓŽ‚ІЂы҆ҊƒÒŠ€ÑŽ‚Ò‹‚Òˆ}Њш}χ€Í‡Ì‚zÍzË€}¯KV²LV±ES±KX°JV´JS¯GQ­FS¬BL«BN¨;F£;G¨8H¶EMË[[Øhbãu`ç‚mèŒtê’vê“wê˜vì—wíšvï—vî˜xð–qîŒnè€låtfÙ`V¾MQ¤2F*D*E'B™4Hž7N£=P¦<MªAQ®BN®>N®AN°CQ®@N¯@O°CR¯@K±?M´AL³@M³BL¶FP·FQ¸HP¿MRÄRVÀSV¾PY½NS½LO¶JR¯<Mª4NߌrûÒ¨üТýÊŠ÷Ì›á}Z¶EN¹CMÂVZ¾V_ºT`¾YeÆ\d»\m²K^´NdÆ\kÒflÐdmÎelÐdhÁTfÂWdº^oƒ*Jd:mD\Bn.Yy4]dDWAZCWCYHYJx7f~>jl$Yv2b‚Bs^ NVJu4icRUKv=w’b“šil'Z^G[@Y?Y=V;P :N 6L?h!M¨c|¥ZtšKo›?b¼€šµˆ¤ª‚¤¾Š£Ø¬¡Ù§–Û§›Ø¬šÚ²§Ú³¨×°£Ô¨šÐ—’Ê’ŠÍŽ‡Ì”Ì™”ÏŸšÓ«£Ò¤žË——LjˆÏ’“Þ›ç£™è©œê®¡ì´¬ì¶¨î¸¨ï¼¯ï¹¬ì¹­íµ«í·¬ð¸«ð¼®ï½¯ò»­ï¸¨í¨œçŠ‚ÒZZ¸;Jž2JtA]>YBn!F†9\y.W›\r¶x‘»‚•Ê‚‰Çy‚.IeA^E]B^>]>_;e;j?l?k!DlEj Gp,Mm#Hl&Hc@^<]9_:`;f:c;Y<[Hk!L“Id¶jrÃvu·qs°fp¹kpÅ|}͆̅€Ð†|ÒÕ”€Ö”„Ö“‚Õ“€Ö•„Ö”‚Ó’Ò‘€ÐŽÒŽ€ÓŽ€Ô‚ÒƒÔ‚ÔÖ€Ô’ÒŽÒ‚ÐŒ„Ô‹‚ÒŽ‚ÒŠ„ЉЊ‚ÑŠ‚щ€ÐŠ‚ÑŒ€Ñˆ~·€Ò†zЇw΄~Ê€®HX±JV°KU¯LZ®JV®EP­FT®CP®AN­AK§?H¤;Hª:H¸JOËZZÙi^áwfæiè‹vê“|ì”tì—wì˜yí˜{î–yí”wî•yíŒpè„nâtcÙe[¾OP¡;I-H&@”*B—1E›5F¤@V¥<N«>N¬@N®CP°AQ°BR²DP°CR­@R°@L­>L°BN°BP±EQµHUºFN¹JR½JSÁLS¿NTÀNWÂNP¾JR»KN´@M¬8TÒr]úÖ³þÑ™ûÍ”ø¹‚ÉXN´DN¹FMºKS¼RX»P[»S^¾Te·J[ºRaÌ]cÌ\iÉZgÂOYËelÊVc¼Rf¾\n¶\n<^V@Z@hJ}=llI]@ZB[>X>\HXFd$R~9jx.ho%Xz9fr.bWIq:gh VQ B\RyCv¢wª‹Iƒ…Bx‚ExdQN
+8N:I
+8H ?^F¬lzÐ}z FfœJkÄ‚–ÙÀ…“škšºŽ¦Û°£Ö£–Ùª›Ù´§Ü¶«Þ¸¤Ø¨žÒ›’ϔʑŽÎ‰Ì“’КҨ ÔªžÒž”цێˆæ•è˜ê¦ê¨é°¢ì¶§ì²¢ì¶¨ð½®í»®îºªïº«ð¼°ñ¾±ò¿³ñ¿³ñÀ±ñ½®î°œê”ŠÙmj»ALŸ7JzBT=ZC^<…:Xx)TGf¼„˜Â‘Ï”Áuy&Fa@[>X@]:^>`?d:j<k>i@jAn%Fl"Dm#DkB^8^;]:]8b7d?_=\DbJ|2T£\m¼uvÀut·nq¶jpÁzyÉ‚|ʆzÉzÈ‚x͆ΊÒ~Õ‘ƒÔ•Õ•„Ô”„Ô”ƒÓ’„Ò€Ò’}ÓÒŽÕŽ€ÔŒ‚Ô’Ö’‚Õ’„Ô„Ôуҋ~Ò‹ϊЉ‚Ò‹~Ñ~΋€Ð‰~Ï‹~Έ€Íˆ€Ðˆz΄xЄ{Ì~z®DQ®HV²IU°FR®HR¬DO®DR°BN¯EN«ERª@K¨7F¨=HºIPÍ[X×i]àxhã‚pèxì’tì™wë–ví”sí›xî—xî˜wï”wívè‚jâ{nÚc\¼PY <M*EŽ">—/E˜1F5G¢<O¦:Kª>O®?N«BN²BN²AK²@N´EO°BP®@O°BO°AO²BPµEN¶EP·EMºKQ¹IRÀLTÂSXÇTXÃMP¾LR¿JQ¸DL±>RÀOTöÈœþÑžüÔœè›s¼FM¸KRºKQ²KWµLV»U\¶R[ºVd¹XgÉ`iÌ\aÍaiÊbg©BX¶Rg¸Od¶Pc®G_£C\‚7V[A^D7b„@i]>X<X<aE`?_EZFYHf"L|9np)Zo*Zn,\d"Vs<ml'[^O^Xk._ž~¨o)VbDd FZ?O:G 6G:X@§n|Ôx¾Td²Tkƈ–ܦšÚŽ‡ÎŒœm›ª‚¦Ð«¬Õ£¡ØœÝ¶«Ú¯ŸÜ¬ŸÒ¢›Ð˜–Ì’“É‘‘ÉÊ—”ЧžÖ®¡Ò™ŠÕ„€àˆ„å’‹è–æŸ•ê¨›ì­¤ì±¥ì¶¨ì´©í¹ªï¾²í½±îºªð¼°ð¿±òÀ²ôǹòǺôÅ´ôĶð¶£î á{xÆKP¬8IŠ&A^ :T?[Bu%H0^‚2Y»”‡–Жœ¼q}x D_<`>Y:b@_=b<e@f@i@h?j CiDp'Fo&Je=\:\8]7]8d9e>\=ZEj!PB\²iuÂxv¾qp·jq»ptÇ‚€Î‡~Ë…~Ê‚yÊyÌ„{ǃ}͆€Ï‰~ÑŠ€Ò‚Ô’ÐŽ€Ò€Ó€Õ|ÖŽ~Ó€ÒŽ€ÓŽ~Ô~Ô€Õ“€Ó€ÔŒ„ть€ÑŒƒÎŒ†ÑˆÐ‰Њ„ÑŠ~Ћ~ÒŒ{ψ~ψzЇ}Єy΃|Ìy®EP®HT°FT°IU®HT²GS°FQ®EQ«@K©DP©@N¨:I¤<NµJRÊ[\Ùj]áwbäƒmé‹sêtì–vì–wí–{ì˜zî›vì—yï™qî‘pæ„hãveÚf`ÃRV¢:OŽ,H‹(B’.H˜.DŸ4G¢?M¤=L¨>N­BO¬DQ®CO®CP³DR²DR²AM°EN°DP¯CR²BU¶DNµCOµ?M¹GRÄmuÂRUÁPUÄRUÀNTÆPRÄLQºIM²>O¶>Qì¬þÖ«üÓœÞj»PZ½LPÂSX¿S[¹OZ¼PX²FU´L`ÐhjÌbdÆXdÆT^¸T_’7Wƒ0QŒ9\‰0T}$L‚/Q‚3VkJ_G†Do{1^X<V=X>k!P_Aj"N\A\E\Bl)Ts/`h"Qg#Wm(^{<nj$Yf,^]Vc$V˜u›s.`V>S 8M 8K 5E5O>šZiÖŽxÀSa»SgΉ“߬žÛ”ˆÚ†ÕŽŒ©v™¥„©¸›«Ä–£Ôœ›Û´©Ô¤™Õ¨¢Ò›—Ñ›šÐœ•Ì–“Í••Ïœ˜Õ¦˜ÒŠÖ{zãˆäŽ„æ˜Šèè¦›ê¨œì²¦ì²¥î»°ì¶§ì¼¯ï¼¬î¼¯í¼¬ð»­ð¾±óöõôóÆ·ôdzõÇ´ò¾«ï¬šæ…{ÏV[´<H˜*Ai9P ;X<hAz.Rt&T©fzÆŠ—Øœ™¿z†v"HbCh@_?h>n?j"EeAfCh?hDl Do)Jl%Dl @b>^9]>_<c>g=c@W>\Fr(PVh¼u{Æzt¼np´dpÂ{v̈ЎΆʆ€Èƒ|Í„~Æ‚~É~È‚€Ì„€Î…~χ΋‚ÑŽ}ÐŒ€ÐŒ|Ô~ÒÓŒ€ÓŽ€Ó~Ó’‚Ò…Ó’†ÒŒ‚ÐЂԌ‚ушЋ€Ñ‰€Ðˆ~щ|Òˆ|Ї{Ñ…{І|Ï‚|΂|Í|µBQ°IT°IT±CN°HT°GS°DN®DL­DN«ANª>L§<I¦=JµHNÌXVÛjaávdä†qæ‹sê•tì–uì—wì˜tì™~í›vì˜zï—vð’nè‚nãvf×d\ÀPW¤<N-F*D’+B˜0F¢0E¡9I¢<Lª?Q«CQ¯FT²DR±ET±IX²DS±GR´AN±@R®CP°@N°@Lµ?P¶HXÈvpÞ„hÄJO¿MTÃSXÆOPÆONÀLP¾JM·FS²DZÔu^üܶûÓ Ùn[ÃOR½NVÃXYÄW\¸Q^°@R´L`ÊgiÎahÈ]gÎgp·Ul™Fh—Bb€2Y€5SŠ2Rh<u!Ez!F[D`FŽT„l$MVAU@^Jr*VaIgKYB_DfL\FbKi&UaQdSCw„C|‚J~aR]PVv„L}R;N 9L
+6I <M>NgÒ‰yÂaj³QeЃ’Ý¢–ÜšŽØ”‹Ø‘‰Ó”•­{˜³¤Ì¦¡¿— Ò©¨×¶¬×³¨Ö¦ŸÐ—”И˜Òœ–Μ˜Ò“Л”Ó…|Ùyzá‰†ä‡æ’‡å˜‘èŸ•ê¬žê¦šî²£í²¡î·©î¶§î»¬ðº®í¼®î»®ð¿°ñÄ´óĸóõóǺõÅ´öɸôÀ¬ñ°žê“ŠÙbd¾AJž,Dr?V@T:] :jE}+\ŠC`À„–Ò•˜ÃƒŠ†7Y`HdDZ>`Af>h=fBi BkEl"Jl"Fp(In'HiAaAZ<\8b<d?iAbAU@XCy2V¨cqÄxvÄspºlp¼otÈ‚~ÔŽ€ÒŽΉ~Ì„}Ê„{É„~Ê|Ê}È€~ÉzÈ‚~È€|Ê‚}Ë…|Ì„~ÎŒ|Ò‹}ÐŒ€ÓŒÒŒ‚ÐŽ‚Ò}ÑŽÐŽƒÑ‚ЅЋƒÐŒ‚Љ€ÑƒÐˆ~χ€Ò‰|Ò†zΈ{φц}Ò†‚Ά~̓΀|²HP´MR±IS¯LS®FS¯EP®EP«FQªBO§EQª>J¥:I©;H¶JPÌYVÙj`âtfäƒkèŽsê•vê–zì–xí™zí˜yí˜uì™uí–wí’pæ„kàtbØd]·QX¤?S,IŠ*F–.F™2F£6H¨<N¨AQ­DV®BR²CS°GS°IW´JTµDQ°FS²DN°@N°BN°@Q°BR¶@OÆZYÕo\ÂPTÄNRÄSXÀOTÄQWÆNQÂSXÃRX¼LQ·JW¾T`ñº‡ù×®Ù~nÄMPÄQSÃQVÅQS¾T`¸MZÆ]dÈX^Ë_cË^kÖetÑco¾R_³J`£Fb‘8ZkG^BbCX?V?eI‹P~dCU<ZCt0\j MbKdKYB`IhMYC^Fk&VaLbRt3f’R†—b’v2nbVl5\‘g”VCF4D
+9J?ˆE^ЊvÎgk½XgÎ}ˆÝ¨›Ý™ŠÝ¨žØœ•Ö’‘Ô™°š¹Œ¢ÕÑ —Ö¬¥Û¶«Ù¶«Ó¢šÐ˜’К–М’ΗŽÐ‘Õ}zÞzwâ~yæ‹„æˆæ’‹æœ•é¦šê°¢ê®£ì¯¢í´­îº¬îº©î¸¬ï¾°ï½°î¼®ð¾¯òŵòŹôÆ·õŸõɸöÇ·ôÀ±ô¶¦íœŽÞmmÆDLŸ.D:Z;M6V :aA€4`z-SÃŒ Ð“”Ä‚„‘@[bH`B^&M^@f@g@hBjCj#Eg Dm#Hq*Jn$Eh>c>Z9]:`:f;j=[=WAaFŒCa¸lqÅyvÀtx»hjÄzxω€Ò•€ÏΌ͉z̈~̆É…}ɆȃÈ…€È€zÈzÉ|ʆ€È‚|Ʉ˄}Ë„yË„|ψÐŒ€ÑŒ{ҎҀЄЂцЀϊƒÒ‰ÍŠ„Ïˆ|Љ{ψ~ІzÏ…|Ï…~Ï…z΂yÐÎ|t¶FR³HT±IS¯FR®EQ°>N°BL®BNªBL¨AP¦:H¤9K©BN¹HMÌXQØh[àtbäjèŒvë”vê”uìšvíšyìšvî—vìšwî›wîræ‚nâu`Öh^»TZ¢>TŒ1PŽ-L˜3O˜4NŸ7O¦?R¨AT²ET±CR°CQ³CP²FP²AQ²DP±BN²BN²@N±@L²DPµDN¸HQÃPSÁPWÂNV¿RYÄPWÈTVÅRVÅUZÂQVÄRTÃRV¼KT¶GZÜ|bùÜ®æ›ÇTSÃST¾OS¹FQÄV\Ñ\\Ê\aÅ_hÆV_ÍhrÊ^pÄU^®DX¨B]€!IkD`Ij$PeGP<VAZA…JtcHZDaJcH\Bj&S^C]FeHaLZFh#TdNVDj%U‚>x‚?zw3c„F€~:€‚C~¢Ž°r2^D6E ;{5UÇ€xÌi`»WjÅsޫᖇ࢔ި—Ù¦¡Ù¡šÖ¥¢±† ²ˆ Ï“ŒÔš’Û°¦Þ¾µÚ¸ªÒš–ј“њ̌΋Ø|zß{zâƒä†‚æ†å“‰æ’ˆèœ“ê¥™ë¬ í°¦î²¨ì²§íµ¨ï¹¨ï»­ð¾®ðÀ¯ð¾¬ñ½­ñòòŸôƵôƺöȶõȹõÅ´ôºªî£–âyqÅHP§4Fˆ!@`:J 8S ;YAz0Wu&T‰šÐ“•€ˆ™AXl H`F^DbDl FeAhBl$Hl En#Fq$Iq(Hl%DfA]<^=]=b:d<b>V>YDt*TŸ\pÀvwÆxu½pr¿knÈ}}ÒÖ”€Ô”‚ӀЌΊ}͈zÌ„|ǃ|ȃ|Æ‚|È‚}Å~}Â|Æ€|Æ‚{ƃyÆzÃ~{Ã|yÆ‚}È‚}Ê„|ω€ÎŒƒÐ„ÎŒ„ΌΉ‚Έ‚ψ|Ί~Έ}φ|φ}Í„|χ~΄|Ë‚{Ð~wÒ€yÑ}t´HR²JS±HS²HR®DP­>N¯AO¯EP©?J¦=K¦<J¦:J¨<HµHNÆXYÖdYàtcâiéwê‘zê–xì˜zìœyëœvì™yë˜uî—zî‘tæƒqâug×f^»RY¢<Q0M/N–4Pš<PŸ>P¤?P¦<OªAS­AN«FR¯DS°CR±DOµDN°DR±CO´DO²EQ³CQ´FT¹EPÂMRÂ\eÂMQ½NVÂQVÈXXÆTWÊSVÆTWÉRRÆR[ÄPQÂKTÉV\ñ½ˆì¬ÎXTÆXWÂNN¿GRÎdbÍ\aÈ\cÐdhÌctÉZdÅ\hª<R¡>R…(IdMaNq/`€<lU<P:RAWFw6ez8lr)Tj"TZDf$Pg"R\C`IfLaG`Hr0]dNU C^F‡K‰o._u-`n*^VH^F™|›m+`B:n&LÀvsÎqn»UbÀevס”ß—„ß—Œß£ŽÞ±¦Ü®£Ø¥¢Õ§¤°ƒ ®|’Í“˜Óž–ܵ­Ý¼²Ó¦›Ð”ώΓŽÑ‘ŒÛ{zá€}á~ãŠ†æˆæ”‰ç•蔎霎ë¦ëªœì³¦î´¤ìµ©í¶ªî¹­îºªð¿°ï¾°ïÀ°òÁ±ò´òĶôÅ·ôȶõȹöɺöȶôÁ«ï¬žä€{ÏTX´<J–$?j:P;Q<UAfE|,Z°j~Ж˜Æ…Ž¢Ldp#JZA[@dBlCh DeEf!Fj$FiCq#Fq(Fj!DfC_>^<c=d@e>aAX@`EŒC_´l{È{zÂut¹nr¿qsË„{Ñ”„Õ”ƒÒ’~Ò“ƒÑ’Ï’‚ÏÍŠ}ɉlj~Ȇ|ʈ{Ç…€È„~È„|Å„}Ã}€zÃ~}À~€}ÀzÂ|zÈ~{Æ„€Ê„~Ɇʇ„ÍŠ‚ΊƒÎ„~Ά}ʃ|ˆ{Í…{͆zÌ…z̈ЃzуzÑ{Ð}z¯EQ±IT±FQ¯FR«ES®CR°AL®CQª=J§<L¦;H¨6F¦3H´FKÆZ[Üf[àvfå‚lèŽvë”|êšwê™vìšxêœ|íšwí™zî–oìŽoæ„nàtgÕic½OT¤<PŽ+L.J”.L›<R :O¤>Q§>P«@R¬BP°ES²BO±ES³CO¶FO´FT±FT±FR²FQ´BP´EP·GQºIRÌ^\ÃMTÃUZÄPVËUXÉUXËUYÇWZÅYZÇTZÅPUÆQWÈT\à}`í¡vÐZRÅTX¼ERÐ_cÔb`ÔfkË`nÍbrÍhyÀex¶M_™6Qm@bI`Ra!P‚Jzw6gV ?T?ZDWDbH…Hrk NVD]Fz<ifL_DbEbIZEk*Zl&Sk$VZF`Jl.\YEz6j`JL =N
+@wQpŠRŽbF³nrÒvl¾U_ÃenÓ—›ÛŒ|݇ތܢ’ß²¤Ú­¤Ø°§Ï¨£®†œ¤l€ÍŸž×­¦Ü·­Öª Îš–ÍŒ†ÊŠŠ×†ß|zâ€ä†…ᆅäŽç“‘æ–é˜ŒèšŽèšŽê¢”ê¦ší²¢ì±¤î±¦ï¶©îºªí¸©ðÁ®ð¾°ð¿¯ò¾­ñ´òŵóƸóĶô˽ö˼öË»öÄ²ð³¤æ‰‚×ac·<K /DvBXBRAT<aD…5c—NcÒ——Ó––žK^n@\>`@bBhDgDh&Hj$IhBg!Dk#DmCg@c@^?]<`<g?d>X;XBiH™NhÀtwÇ{tÄtrºnpÂ{{΂֖€Ô–‚Ð’€Ò’Ñ’‚ÒŽ|Ђ̎~̃΄ˌ…̉€Ë‡ˇ€Ì†|ˇ~ɇ~Ç‚{Ä{¼€}Á~~¾x¾‚zÀ~¾~Á}~Â~Ç€~É~zÌ‚|Í„{̓|̆€Ì‚|Ë…{Í‚z͆Ï…{ЂwЂwÑ€wÐ}t²CP®GR±FP­BP«EP®DR«BN¬>M­BK¨@L¥<J¨6D¤:H·HPÊYTÚj^àvfæ|oèŒwë”|ê—uì™xë›sì™|î›tî˜wí–ríuå…pázmØg_ºOT¢8LŽ/I*J–0Jœ8P :P§@Q¥>O©ET®DR±CO°BR³FS±ER²JS´ES´BS²DR³DQ¶BR¸FR¹IU½IRÀQ[ÀSX¿QWÆNPÇPTÆRRÆPQÃQSÄSQÃORÆRSÊ\YÐc_È[MÔq]ÃMPÄTTÊUYÖa_ÔkuÓftÂi‰µc‰±_¨Sp’8ZpE`Gr.cXBS ?xExh"SVBj-aZA^HU =bFz2d`J{:kz2^\B[=bG]FWAv8hbEx4d^GYEVEf YIz`OH 8F<XHU…¨c€Õ‚m¾Yc¾ZgÎ’Þ’zÝŒ€ÚŠÛ‘ƒÜ¦”ܲ¥Ø¬¦Ù°§Ô¬§À”ž¦k†ÊŸ¤Ú´§×¬ Ð™”ËÍ……Øzà€‚à€„ãƒ„â‡„âŠˆæ’Žè•æ“è˜Œê™‘èž•ë –ê¦˜ì®¢í²¥íµªï¶ªð»ªë¸®ï¸©ï¼«ï½­ð¾­ñÁ²òôôƶòÆ·öɸöȸöÊ»öDzðº©ê–‹Ûji¾DO§:Iƒ'FZCTAS<Z@‚<bŽ>\ΕœÖ˜˜œFZm!Ep$I]>cCh"Gi Al"Cl"Dn&Jl%Hk)Ii"Eb>`?`@b@e@f@`<V=aLƒ>_¨dwÂxrÅtoÄop½pwÈ}yÐ’‚Ô”€Ò‘Ò҂уϒ‚ÐŽ΀Ж€Ó”Ñ~ЂЂΎ€ÌŒƒÎ†{ˈ}ʉ|Å„}¾€€¾}~¾}y¼{ă}¾}|À~~½{~À|~Á|ÁztÇ|xÊxË~yÊ…‚ÊzÊ…|Ά|ψ{Ï„|ЂxÏ€xÑ€v²CM²GT°BO°IU®FN¬DO¬EN®=I­@J©DR¨=N¦7G¥;K³EOÉYYØh\Þvjãpèxê—{ê˜|ì™zë›xëš{îžsívï˜uíqè„jäudØf\ºNP¤;L“,G,H—0H—4Kž6K¥=R£ARªFV¬BR±ET¬CS°HU²FT³HV¶GRµFQ³BP³BR·FS¶IRºGR¼KR¿NTÈRXÊRTÂSVÂPV¼PYÀNS¹LR·LV¶KTÀPTÔn\ÂVHž8H±MPÁTV¿FLÔcbÑYdÐdz¾eŽ«_Œ®g‡­^|›Ib†.RZBl2`o)\M @L <€R†m(Z`Mj,[T>aHXBVFi SƒJ~…FphI[>W9fMZB\AFxS@f Or/ddPaT[Ge‘h&TG5F6M=†De¸o{¸T`¸TaʓܞˆÚ†|ۊ׊ԎŠÖ›’Û°¤Ø±¬×­¦Ø®¤Î£¤º†’Ч¤Ô¨¡Ò”‘Д’ч„Ý~€á†…⌌ↆᅆâ‹äŒŠç’è–è–Žé˜’êšŽê ”êœ”ì£˜ë­ í¯ î´©î·ªðµ¤ì´§î¶£í·¨î»¬ð¼®ïÀ°ð¾®ó´óŵõƶöȼöȸóÁ´ð¼ªî¥–ßtpÂHQ­9H&D^?P 9R>Z@|.U‰2UÉ‹”×›˜§Ziw&LgF_>aDjBfDhFh"Gn(Ip(Hn%Fh F]>]:b?b<e?e>\?XDdN’Ni²kyÀxwÀqp½nrÆsp΃{Ô‘Ö‘~Ô’ƒÓŽÒŽ€ÒŽ€ÎŽÎ€Î~Ï‘€Ò”‚Ó“‚Ò‘„Ó“…Ò”„Ï~Ί|·͉~Ȇ„€Á€|Àz¿‚yÁƒ}Á~|¾}}¼~z¾}~Àzy¿y{Àyz¿zxÀ}zÃ|zÆ}zÊ„̇~É{Ë|ÐxÍxÏ€y°DR°HQ¯EO³EN¬CS®@P­CL«=J¬?L©BN¨>L¤6F¤:I²DMÈYYÚibÝzqâ†qæxè”|é”zë™|ëœxìšzí›~ìš{í—uî’rè„màtbÚb[ÀKN¥;M’.KŽ(E–.G›6MŸ5N¤<R¨?Q­BPªFT®FV®@P°FU±CQ´ERµEQ³DO´GS´DQ¸DQ´HR¸KR¾LQ¿KPÆQRÊQPËTUÌVWËSTÌWXÊRSÌVTÌSWÐ\XÊwtž9R¶V^΄oÒ„ÃLWËVdÂ^ƒ°`³m޲]t¾T`Æ]b¨F[wL^R…S„d RI
+@NB‚WŠz9ldQV@\O]En)^o$\ˆM}=fs*ZbEU :X?hPVD`A|@nT C_N…JƒfTZGo>nk0TR>RGH <t2V¶rx K\FaÉ€‡Û¡’ÛŒ€Ú‡Ø“„Ö‰ÓŒ‡ÓœÜ²§Ø´«Õ¬¢×±ªÓ§£Î¢Òª£Ð —Ï”ŠÔ„~Ü~‚á††ãŠŠãŒŠäŠŽâ‹ŠäŒææ”Žêœ“è™’ê˜’éœê›‘ë˜ëž–ì¨šî«ší°¤í·¦î¶©ë´¥î³£î·¨îº®ð¼ªî½¬ð¿²òÁ²óijôƶõȺ÷ǸöÆ´ô¯ð©•ázvÈKQ¬8IŽ$Ca<S :S>XCt*O€.VÀ|ŠÙžœ¯dv~,Pk&JeFi$Kp*Nh"Fm&Ji!Fl'Jn(Ik&Hf@]@_BbBa>e@a<Y@ZEr+SŸ[p¾uwÂtvºmn¸hnÆ{vщ~ÔzÔ~Õ’€Ñ’€Ò‘„ÐŽ‚σЎ|Б|Ò€Ó“‚Ó•„Ó–„Ó“„Ò–ŠÐ”†Ð„ÏŒ€ÎŒ~ʈ}Ç„~Â}À„}Ä€x‚~À~|¿|v¼}¼z|¼||¾{{½{|Â{~½xyÀ{{Á{yÄ}}È~zÇ€~Í~yÐv΂|Ì„}®?N±HQ°BK®AL©CS¯@L®CK°?J¬<I¬@L©<L¥8J¢:N²FRÊVYØlfÞwmãlçzé“xë–vì—xìšzí›xìœ{îœzï›xí’ræ„iáwdÚfYÁNO¢:K‘0LŒ)H•-H™3J :L£=P§?R¬ER­BR®BP­EU°IX°EV²DT°BP°DN´FR±BN·@N²HPºHPÃLQÂOUÄNSÄTTÆORÊTUÌTSÊUTÈWXËUSÍZbÒ[Vâ–rÀ\NÍZOàjRíœhÐff»Wuª^Œµg…Æbs¾TaÈ\d»Udz"G\Lk,f…XˆZ@K BSFX†ƒJ~V?R:[DZHr,\†Ft‚<gt0\g"JZ>V>Z@dL[Ig(Mp2[S >\F†U‡`LY>|FvWF]VRLaE¶rxÅ_a¥;S¿w€Ý«šÜ‘~ݘˆÜ Ø™ŽÔ†ÔŠƒÖ˜Û±¥×³ªÖ±©Ø²¬Òª¨Ó© Ñ¤˜Å|kÀTZÍ`iÔqwÛxyß~€á†‰â‹â‰ææ••癒Ꙓ꜔ꞔëœê›‘ëœì¢”죕쮞봤ﳡﶦ︦ð¼ªñ¾«ó¾«ñÀ°ôŲöȸôƸõÁ²ó¿«ð¬—â‚|ÆNVž,F}Bc9U :R:V?kGw"P¶xˆÙ£ ºq{…+N{,LdHn,Nm*Ne Ef Hk$Eo%Ho*GjCb>^>bBa@d?f!E^?TBe K†@d«bsÂrwÁrsºlqºnsÈ€|ÒŒ€Ò~Ó‘€ÒÒ‘Ò~Ò‘€Ð~ЀÎБzÑ’€Ò’‚Ó’Ó˜†Ò•†Ò‘‚Ò‘ÏŽÏŠÌ‹~ËŒ}Ȉ~Æ|ƒÀ„yÀ}½~¿}{¾||¿~|¾{}Áy{¾{|Â{{¾y}ºwy¼z|Á{~ÂyxÆwrÉ|wÊ{xÌ}v±GR¯CO¯FR¯DO«@M«BN®@L®@M±>L¬AM©=J¨;I¤8H¯EPÊUTÖjfÞqfäƒoæŒxç”|ê˜yì™|ìš|ìœzî›zî›vì—vìqè†qâvdÚdY¿NR¤:L’.L‹*H–0K›6PŸ8N <O¤@S«BQ°FR±FR°FT°DR¬>R°ER²CP¯DP®BQ³BNµGT¸HQºJRÀLSÂQTÇPPÇTWÉTRÈSZËUTÊSWÈR\Õ†‡ã®‰Ö„dÀbPb:n6t:(=¼Zn²j•³d„ÇcmÅV]»LUÂRVž9TdJm.lu;g|KxL
+=NHb"XŒcv8iP :Y@`Dk"Pp&OdDaDeJZ;V ;X@]A^DaHf'N_GT Bh.`‚Oƒ^Kg&Zw7id$YQCQ>¢\hÍ}n¨DY¸]lݰ¢àš„Ý“‚ܢܪ—Ô—‰Ð„~ÒÕ›—Û³«Ú¶²Ü¹´Ü´¬×³¡ÌŸ„¦PJ•*>¢:PµJ^ºQ`Å_lÍhsÐjp×ruÝ€âŒå“’藒뜕렕ë’ꙑ階똌ëšì¡‘î¢–ìªžî´£î¶¦ë´¢î°¡í®¢ì´¦ï¶¤ïº¥ð»¨ðºªñ¾©ôðôôôðò¾­ð³—ꛉÚvqºDL…@p=a<W 7T ;T?lFw'W¤f{Û¦Á|…Š2Rp Dk Im&Jf"Jh)Pi$Jl*Ns1Rr0Ph!@d?]=a@`@e?fCY@XFk"Q•Nk¹ntÀtu¿ps·hpÀrrÌ…|ÔŽ{Ó‚Ò~ÓŠ}ÑŽ~ÑŽÑ‹}ÑŽ}ÏŽxÎŽ~Ћ|Ð}ЀтВ‚Ð’€Ò“ƒÐ‘‚΋͉ÍŠ{ÌŠ~ʈ€ÉŠƆ}ąÆ~¾ƒ}À|¿€ƒÄ€~Á€À€~À}~¾{z¼yy¹z|º{¿{|ºy{¿xxÀuuÁuxÃvv¯@P²CN®BN®BP­DP­CQ±AN°BN°DN¬@M¬<J¥;I¦<J²DLÉXVØf_Þwoæ‚nèsê‘yí™xîš‚ìœ{îœ|ïš|îœxí–sì”pæ…láxfÙdXÀQS¤:MŽ0L‹-K”2M˜6OŸ3J :M£?R«AR¬@R°FU²GV­HU±HU°ES°DT°DQ®CT´FUµCN¶FN¹HRÀJQÂORÆSVÈSTÆSXÉVXÉVVËT[ÎY_õ¾›Þ‰i¦<A|;Q 9Q <S Ar&Q¼x”Р°×§©ÍVZ¶BQ«FT4LkEeR~?s{N‚g%UOFPKu7n–ršn0^Q 6`EZ<_DaF`G`Hf"OYAX?bJZD\Ah$Vt._k#VbOp.jy<ldRl0`XEL >H 9…D[Í}q¯LZ¯N^Ôœ“ࠆߖƒÝ¡ß®–Þ´ ÒŽ†Î…€ÎŠˆØ¨§Ü³ªÜº²Þº±Ú¸§Ê€¬HP¨BW«K^°KZ¯EW©@NªBV›6I¦?U³K_ÃVfÒmrÛ‚ƒãŠèš“ꢘ뜔ëšêš‘ìš’ê•Šëš‰ì£’ì¨—î° í²Ÿê²£ëªœí­ë°žî²£íµ£ð»ªòºªð¾©ô®ôÀ¬ð»¦î®˜ã’Övn¾RX3Jx@j:a8X 6S;V ?iD{.^’Jeݪ¦Æ€…žLedIhCv,Qj$Ii"HiEm'Hr-Jm%De=_>]>b?dCb@fGXBZFx/W Wq¾ptÁvx¹pv¸gpÆz{Њ|Õ~Õ|Ñ}ÓŒ|Њ}ЋxÒŒ~Ñ{Ï‹z΋|ÎŒ{ÏŒzÌŠ~ÐŽ~Òςю~Ñ’Ò‘~ÍŠzˆzʇ~ÍŒ|̉{ÊŠ~ljlj{LJ~Â…~ă€Â††Ä€À‚‡¿~|¸z}¼{|½zy¾x{¼wz»w|ºx¸x|¶sz»rr¯BO®FR­ET®BR®EP®CQ°ES°@L®BL®AOª<L¢=N¢6J²BLÈWZÙj_Þyjå‚oè‹të’xì˜xï™~íìœxïxíœ~ðš~îsç‡mã|gÙh[¾NS¢6K-KŒ+L’0M—6Nž4M¥BT§<O«@R­ES°HV°DR«BS±CQ°IT²GT²DPµEOµCL´ANµGP¸FQ¼KRÁUWÃPUÇQVÊRWÈW]É[_ÈZ`Ñccð¤~Ò†r’6KtBe>T =gE Lk¾™ì•uâ‹fÂRX•+Hˆ-Mƒ+NhSj*c{Bm‡^‘RCQJb#^€D~pq6`M7W?R<g"Um3]b*R\Fl/Yc LV>dGX=V@XAr,\†H€dKt<vd(Ti%[f)_OAJ@n*LÂyp¾`d¤G[ÌŒ’ÞœƒÜ™„Þ¢Þª˜àº¦Û®œÐ‡Ï…‚Ò•™Ú®¨Ù´®Úº°Ú¶¤ÌƒxÈ[bÎdjØtyØrv×rwÌhsÂ]j´Q^œ<S‡">‚$@†$>š4H±FXÍjo݂斋ê˜é™Šé•陎疉ꗌì›ìª›í¯žî²¢ê²£í¨œì«Ÿë­ î¯žî² òº¡ñ¸¤ð¸¢ð¸Ÿê­”߀Ìrm¸X]®JX£<LŽ(D~=w:d 4[ 8T<TBdEr$U„=ZÚ¥¢Ì‰‹«YkgH`Bj"Fu(Ho*Kj#Eo(Il#FeB` EaE]?_?e<g"CeA\C^C„:\¬dsÄts¾px¸kq¶luÌ|Ô~Ù’~ÖxÓ‰|ÓŒ{Њ~Њ|ÑŠ~Ћ}ÒˆyÐŒz͈}Ή€ÎŠ~ÎŒ}Ë‹‚̀Ύ‚ÐŽÍ̈}Ɇ}ɇ|ʇ~ÊŠzʈ|Ȉ~ȆzɉƇ‚ÇŠ…ņ„Ĉ„‚„ă¾}}¼|}½{|¾{z¸~¸wz»w|µrx²py¶pt¶GQ¯HV²DS°DQ±HP®DO®CN¬EQ²DO®@Jª>J¦<M¥9J°ANÉTT×g^àujãlèyì–xë™vî•vî›}î™{í}ïœ~î™ví‘xè„mâvcÛi\ÂRT¡9L-H0O–1N™8Pž9N¤:J¬=Pª@P¬DR²JV²ER±EQ°AN®@N¯@N®BP²@N´EP²ALµEN¼IR½IP½MSÁRV¿QVÉRTÈTYÊ`cÑnhØibÙlbß„m³XRvB`:N ;RF˜LoÆovÆ\a£:I¤CV€ GŒ8T*SgTz?w|BugOVL\PyB|:{xMp|GtM ;QAXKr8cl%U\"Kh6_m.Xt0^Z@`BS 8T;Q
+:VBt6f|>s~Q‰U<y9t[HJ?TBªclÒx°KZćஙܑ~݌ਛ߷¦Þ¼«Ò›ŒË€ÐŒÓ¦¢×¶®Û¼±Ö²¡ÉqhÊT\ÔfjÛsuà{xÝuzÛpnâ‚€à~€ØlpÇXcµJY6L“-E†$>‚ ;Ž)A«CUÒpr㊀摆瑇é‡è’Šé˜ëœŽí§•î­î® í®Ÿì©œíª í´¢î°¡í¬›ð²í¦ä˜Ðvg¶UT¥EN”4KŠ1M˜8S¦FX¨BVª?L¡1Dt:f;W=U>^?p%S~<Xؤ¦Î…Š´eto&KeIaBu1Rs-Kt&Gs+Ln$Cd?Y;`?^>_?d@h"GdD^DfL’Fb´p|Ãtv¸lu·hrÁtt΄|Ö|׎|ÖŽ|Ô‹~Ô‹|ÑŠ|щ|Њ€Ï‹|ЊzΊ|ψvψ|̈~΋~ÌŒ~ÍŒ‚ÎŒ€Î|Î}͈|ÌŠ€Ëˆyˆ~Ɉ|ˉ}Ȉ|Ê‹zȈ‚ʈ~ËŠƒÊ‹…lj†Å‡„Ä„ƒ¿‚€À‚‚»|€¼|~¼{·x|ºu}³ry³tz³nt²BM­BR°GP¯CS¬JV±KV­FQ®FP±BL¯@JªAP£5H¡8J°BMÈTWØbYàwhã{méˆsì”yî›xî”sî›|ì™xï›|ðœzðœzî”xç…läxeØh\ÁQR¢:N‘,I1N˜1Mš8NŸ:P¤BQ¨>Q¬AR°JX±GS²BQ²DQ²BP³CO¯AP­:I°BO²?I´GR³DM¶DM¹JRºGN¿JPÀOUÂO[ÐfiÚ{vátÜojÝneÚ}j§VemE‚:Vp0SJB’Pv¿cqÂbo›1QŒ6RŒ7Ty"IhMp-b„M„t7p]R\Uv@w„Mƒ^Qh3Z”hšV@TDV@p)XcHSBWGn1`ˆKxk#OV8T 6X8X:Z?_"Qm7VˆY‡YDh*UL7G6†>V΄vÊb`¿lxÜ« Þ—Ü—†Ü¤’ݲ ß¾­Ù³£ÐŒ„·†ÔŸœÚµ®Ü½®Ö¬”¾^YÄRWÐ\cÏ]`×kk×ijÑjqºH\×vtãƒ|ÝuuÍZbÎaa³?P®?P¦8J›2H•/Iš2KµGYÔhn㊄抆猆ê†éˆì–‹ì£˜í©œí°Ÿî°¡í«¢î©Ÿí¬ží¨™ë¢’ê¡Ö{t¹TV 8Mž=T¦Jb¦I\±UiºVcÍdjÂLN¸CJ¢4Bv=o=Y;T?[<t&V}/R֞ˇŒ°ar}.OdBbCu2PgDo"Jr(Kp(IeB\@`A`=dAfAfDdFdIp#PRn¾rx¿ts¶kp¹jnÇ}{ÔŠ|Õ{Ö~Ô‹~Ô‹|ÕŒ|Ò‰|ш~ÓˆzЊzЊ{ψ~ІzΉ{·{φxΊ|ÏŠ~ЋÐŒ{ÏŠ{ΉxΈẅxȇ}ʆyˉ~ˇ{Ê‹zËŠ€Çˆ‚ȉ€ÉŠ†È†…ȇ„Ç„‚Ã…„Ä„}¾‚…»€º~~¸x~¸uy²r{²qz°nz®AO­FT¯FT°FT°JV®FV®HR®BK°CM¬>G§:J¤6E¢4C¯CMÉVXØg\àv`ã€pêŠtì–xìšzï˜}ï˜wìšyïšwðzñ~í”tæ‡oâ|iØl`ÂTY§;L‘,H‹)G•2Kœ4J 8M¥>P¨AS°DS°DR±DQ®BQ²ER±AN³EO²BO²>K´FP²AK²AJ²CN¸DK¾JN¹GQ¸KU½LUÇTZÚxnÞuÞ€yÞzpßvlæ…lØ …¯nqÅ|~¿lz–Fd¦bƒ¾U`Ôjf¢=Rp(Il"D[Kk$_{7o`™x0hp&fp0h‡X†n1fK@ZH‹[ƒe%TVEYD}=n\BP=RCh(VŒR}t-[T:U 6Z 5`>\:V:Z?` Fr4fN
+8J:f!BÂ~y¾[`¶ZfÚ¦ Ý ‰Ü–‚Þ¡ß²žâºªà¾­Ù¦šÒ“ŒÓ–”Ú®¤ÝÀ­Îžˆ­JL¸BHÂJN¾FPºHM¾OPÁPNµKQ†<¬CKÔthÂP[¬=L¯BRµDYÂXi¸DT¼LZ¸AT¸EV¼DVÏ[bÞtvà~‚æz剃牂둉죗î¬ð²¢ï³¦ï¯ î«Ÿî®¡ì¥™æ“‡Ø~|ÂZd´Wf²N`¶U]¶R\ 8IŸ9G²HN±AI™0B–/CŽ(Bz =y'HZAU>[Cw,Xv,PÑšœÎŠŽ°_jB[a<b@r/Ph Dm(Hp)Gl"Bb?]>b?d>b@f?a@_Af J‚3YªbvÁsw¼ru¹gm¼kmÌ€zÔ‹|Ô|ÕŠ~Õ‰~Ôˆ{Ô†yÓŠzÒ†|ÒˆzшxÒˆv·χxЇxχ{ΉzΈ|ÏŒxÐŒ}ÑŒzÏŠwΉẅÿ|̆wˆ{ˆzʆ~Æ„~Ȉ€ÈŠ~ÌŒ€Í‹ÉŠ…ÉŒ‰Å†‚Ä‚~ƃ€Ä†Â…ƒ¿¸}~¸vzµu}³u~°oy°@T¬FR­ER®HW¯FR¯DS®BM¬AM®DNª<I¤<I 3G¢2D°?LÈXUØe`áugå€kèŒrí–xîœuîœxð™tð›zïœuîœvìš{ìvçˆvã~gÚndÅQU§<K’,EŽ(H–0G›3H 3I£@P¦?S­AN­BR²BR´EQ²BL±?K²BL°BK³@J´?H®;I³?J´BL³@K¶ET²N_¶Zt¾o{ÎpuÛtjÜ€rÞ‚xÞ€xÞ|pæhî–pãŠgá}à‰€¿Wa‡/Mƒ$D} @`A^2[]#Qh)f~;t^‘}>sdT|7vv3j‰[ˆg&XG>RCs<bv:lY@ZH€BrZ>R=R ?[L{AkˆP~YBV<Y=\8a:]<Y<S:V<XLL
+5¢YcÏxr®JXÐ⩌ږ…Þ›ˆà©˜âº¨äÁ³Ýº®ÖªžÖœ•Ú© Þ¾­É‘}œ7B¤6E§7B 3B¤;H‰$=†"=„#:~6o5z6”/:w9m6w;š4G¾Va²AVÐ\eËU\ÍQ\ÌR^ÑYaÙfmÞtwâ|æ‚~ç}êˆîŸ“ï°¢ñ¯œïµ¥ð²¤î®¡ï¬žë§–߆‚Ñno½`h·X\›5B…(=z8r7r:}>{@~"@‹'?‡ =ƒ,Dk8\;R :\B|1Yw&NÒ—˜Ë–¬Xh•G]hCaBt3Ol"Gp(Ll"Ef?a<`?`=`>`>d@^?U=eJ’Ib¸pw¿wzºquµhoÀvvÎ…zÕŽ~ÕzÕŒ~ÕŠzÒŠyÒ…zЇ}ц{ÓŠzÓ‰vÓ‡wІyЄyЄyЇ|Ј|ЈzΊzЉwΊzΊxІzˆyÎ…vÌ…zʆẍ}ÊŠ{dž€Ì‰|ȉɈ€Í‰È‰‚Ȇ„Å‚€Â€}Â~|ÀÁ€¾~º}¾z€¸v~¶w{±r~®@N«HR°DN¬DQ¯AP®DQ­@M¬DN®>H§AO¤8E¡8G›0E°>IÌVT×f^Þuhä|jéŒrê”wì™tïwîœvîŸyïœxí|í˜zì’tè†nâxdÚhZÆRS¦;J3L*D–*Bš2F 3I§9J¢=K±@O´DN²BL·DMµBJ´AJ´BL´<G°>L²?H²BL®<H²;G®=P´QdÂ{ŒÊŽÔ‹zÔqjÜwfàzhàrß|sâ{mâpÙxk·N^ÀT`Ãmu”<^^:T<K ;QHk8kt8s|:|ŠR‡–jšp&ak$]„G‰x4hŒ`d#VNDWDr4fq2a^MXB‚N~X?S ;P ;RH`RŽ_…M„`MS:X9b:_8V 5P 6G>L9w3Qˇ€¾Yc¿lvÞ³¦Ý—‚݋ޣ’â³£ãÀ±ß¾®Û²§Ú® Ûª™ß¼¦Ã…o+<”*B’&<ˆ <r:v:o:o:l:j8j8l<h8f<a5]
+3k7€;»UbÔjuÔ\fÖ[aÕXaÕ]dÙhpÝnpâvuä}zæ‚}ìŒ‡í “ð®¡ð²¥ð¶¬ñº©ð·¥ì®™ä–†Êkf;H'Br<m7p8l8k8j8l=n?p<v?$Ay"A`6]=Q <X<2ZsIГ’Ó˜š¬^n–F[z/NbAq,Nn(Jn#Gl%Df@`:`>c@^@d>fCYBR <bGžTi¿txÂtq¹mp¿klÇzuЈ|ÔŠ|ÔŒxÒŠ}Ò‹|Ó‰vÓ‡vЈzІ{Ñ‚vшwÓˆxч|Ò†xÒˆvχ{Їyω}ΉxЊ|ЋyЋxÎ…x̆vË…{ˈ|Ê„{ʇzɆ}Ç…{Ȇ~LJ€É†‚ʈ„ƈƒÇ…€Ã…€¾€À€¾|{¼z»}€»|€·z~¶wzµuz±s|¨>N¬DNªBN§>O¥DQ¨@Q«<K¨<M§<J¤=Kž4E™0F˜0G©8FÄOPÖdZÞtfäkèrì’uíšyðšvïžyìžxð|î›|ð™xìŽuèƒiäwdÚnaÃRR¤<L/J‹&A“-Dš2Hœ6E¤6H¢4F«@N¬>L²HQ¶BM´@H²>J®>J°@L­>K®@L®;I¬5Hª4N¯F^Å‚–ØšöLjáz^×l_Þvfàvfá{pâ~rá|rÙzwÀfr“B\lF‡<X€.PR <G @RMzG‚ŽXŽz3kz:pb—t1_€B€t1i~@~|By“oc"UMCUCu3fXAq/h[I‰W†[@TAR :O
+;R Dj,Z_ŽZŽm,_P
+5Y 5`9\;J9F <U=³opÅnf¹VdÚ© à ƒß”€Ü †Þ¨™á´¨â¶ݺªÝ²©Þ³¢Ý¶ŸÆwŽ*=† =†<w6n:n<k:l=i:g5c9d=k&KŠCY„9Rm?Z7Y9_ 6ƒ>¾KXÓfkÕ`eÔZbÖ\dÛdiÝklàrxãxuåë†í¢˜ð°Ÿó»­ó¼¯ó¿­ðº¥á ‹»[Z†(BjDd@eCk>~(F|(Do=h<j=oAl Bp>z<l8d8_7U:Y?v)SqFÌŠŽÕ˜ž­[n”H`v,Lo#Lp*Ln&Jl$DkAb<[<`=c<b?eAbCZATBr$Jª^lÄy{ÀspºntÅstΆ~ÕŽÔŒ|ÓŒxÒˆyÒˆzÒ†yÏ‚yчxЄzÏ„zÏ„vц{уvчyÒ‰y΄yÒƒzІyψzЇ|·|ψsÎ…{̇xÉ…y̆{̈zÊ„zȆ~È„~Ƀ|Ȇ†È…€È…€Ä„~Á~Á~}Á|¾||½~|¼{~½z|ºy}¶x{¸x}µv{´s{¨>L§=L¨AN¦<J¥>J¨@N¦:H¦;K¦:HŸ8Iœ6D•,B’+E¤5H½PTÕbWàrcä~féŽsì˜wí›xîštîšrîžvï›~îœtîšvìnè„häxbÙe\ÅRT§8JŽ(CŒ&C—(B2F¡6J¤:J¦:J¨?J«=J°>H±BN¯<I¯<I°>L­;H¯>Jª9G¥8G¦0H¡.NÏ„~í¸šòµˆøºtÒZQÙnbÞraàveâlälÈadÁox°^o‚-Mz-Sm@X@J DLEU‹^l'X^I†YŒd)SXOx<pBwz5vŠ_Ž”l”XJJ <XFn0`TFd$Ti&W‰^ˆf!KXE[>T:T=TCm4_V†Gty:pgOZ6U
+5J ;H
+:H]Í‚z«HWÎŒŽã²™Ý–‚à›ˆÜ¢“Þª–ྰàÀ´ß»®Þ³§Ü¼¦È{Ž*@”)B‡!>u7g9f;i7k:h:i;]=hCtJŽFf¿– Á–§ Xpt$E[ 7Z 6a:*GÊXXÕbdÔYbÙZ\ÜbjÞejánoâuwç}zꊄð²©õÀ­õµôŭ篖®PVj=aD\C^Lp!K2dœWv®k~—?Vk<^ 5f8m>p?n>c7h:a=V;^@{.WpFȆŠÙ¡ž­`rŽAYt'Jo Hv.Ps-Km"Eg@a<^<`>b<b=cC^>[E_Gˆ;Y¹jsËxvÄvu¾orÈ{{Ί|ÕŽyÔˆzÒŒ{Љ}Ò†xÒ‡zÒ„wÏ„yЃvÏ‚zцyЂyÏ„vЃuщЃzσyЈzЊ|Ά|΄|ΆzÏ…zÎ…yÍ„tΈ~Ά|Ì„|É…{Ç…|‚|Ń€Ä„Æ…€~À~Á||½||»z|ºy|´u}¶u{¹vz¸w|²t|µt|²qx§>M©EP¨BQ¦<L¨;J¦?O£:M¥:J¡:Hž5F˜0D“1E”)B£5DÀMNÖe[Þsbä€iéŽví™sî›{ï™xïxîœ|ïœ|ð|ïšvëtæ„lâvcÚfZÆSP§:HŽ*D‘(D˜,F¡4H¦5J¤<N¬>K­AN¯?K°?K²?M³=H°CL°<J°BK«;I¬8F¨5D¦3J¢0Oáv誘õ¹…à€hÌ^\×lcÞteâzfähØrk¢C_Êjpº]l|+Ox$KO >RIXNp>pˆVzk#VVF{Izs9aJ BNHv6lŽ_—‡F}‰YƒDpVHP>WG`FT>XHWF{Onx<h\D\AW:\>[AZ?bBW>b)Ls7abHT
+:K=a@Áxw¼]`³\n೥ܘ€ÞšÞ¦“Û¤—Ù¯§ãĸ࿳໧àÀ©Èš‚˜7E4D”*B|9g8a 7k?†2IvAs"BpDT 8d@0W…8TÖ®¯á¼ÀѨ®²~ƒ+Ns=˜;Z‘(GÀOTÐXbÎR[ÔV[Ü`gÝejànrßplå~{銃ð–ô¹ª÷Ǻö̵ðèÂoc|AbB`CZF\Jx*NªxŸŸ[sÈ¡¶fv‰*Id9b7j8n9jAd;d;_<T 6`@~-TgDÇ‚…Øž™°^t–BY‚8]q(My4Rp%Ho&EfBa;`<`;d @bB^>\@WBl"OPfÁryÊztÂtt¿pqË{ÓŠ|Ô‹zÕ‰|ÓˆzÓ‰zшyщw΂wЇzÒ…|уtÏ„zЂtЃxÏ…zΆ~ЄwЄwΆ~Ï‚x΄yІuΆ|ˆ~͆vÍ„vÌ„xˆ|Í„{ɃzÅ‚}Æ|Ä‚}Æ…€Â‚€»}€»|y¼zy¼yx¸vzµtz´w{µpv²t|¯t|®q{¬s|«px¬DNªBN©AO¥?P¦?L¨@O¦=N¥;K¢6Kœ4E™2E’,B‘'@¡8IÄPQÖf^Þr`ã‚kéŽrî›rîžxížxí™yîžvðŸxî wéšä„nâxbÚdZÆRP¥:L‘(C“)Aœ0E 2E¨;J©BP«>L°@K²BJ°BL¬@M­>L­BN²EL¯BK®?L­9H¨9D£4G!F¶[]ࡔݦ{Þ¨”ׂÖvpÝtlâxjàxiÐkmº[hÜ{hœ8Rc@dALE^TFzDr\FXGo2hp0Yd"XPKYRx:n”d™|;s†[ˆ~>o^KUBV@U>V=ZCSEk1S‹Y‡e"M`DT 9X>Z=^E\=U7YAVFR@^Rr(g–NfËvm¬EW֤㬒ܖ…Ý¢ŒÝ¬™Ù¯¤à¾²â·àÀ±âÀªÕ¬”¢FN¬AM 6F‰"?s;g8k:#B¡IY‹1P|/N‹>`lEt(HCeo(PÒ®½ä¿Ä潾ܰ°¿n~•&H¸LU¶@T¹@IÊRXÆLVÌT^×ZcÚdkÞghájpç{vìŠð§›õ½®úлôвۘ†¢>K‚(HgDz0NbCdCx+OŽ?d™TrÔ›¥Ë|…¢9Jv>a8g<g6i<b;b:bDX@d@~3\gDÀ„ŽÖœ¶n’4N‹Dfs*L;Wl"Fj!Dc>b:`>a>a;`=Z>Y@]I}0Rª^pÆvvÈttÁssÂstÏ„zԌ҉~Ó‰xÒ‡{Ôˆ|Ô‰yΆ€Í„|Í‚xÒ‚vÑ‚vσxÐ…vσyЀvÒ‚sÑ‚yЄyÏ‚vÍ‚w΂xÏ„|Ï€vÎ…{Ì„zÌ„wË„~Ì„zÈ€{ÆzÁ~Á~|Ä|Â{À~~¼}€¼z|¼y}¶z~¶v|±s{²ov²rx¯oxªovªlxªo{°vz°ANªAQªGT©=L¨CP«>J¦?M¡<K 8K›;K˜2B•,D&?¢4F¾OQÕbXßrcãnêŽtî˜vì›|ìžzíž|í yð¤ð {ïœ|ì”vè†rãu^ÙfYÈTR©>K–+B”*C›1G 2Fª>K®AN®AK¶DL¶CK³BLµFN±DN³GN°EP²@L±FP®@Lª<GŽ(BiB—MRÆ•›Š2O«^Tê°’ç­œâŠ|à€qÛzk´Q\‹,D‰/E^BP=RGWP~Gz‡HtfQSCm2ip-a`Pt8nZNaYzEz’^˜|9t•v |=mXCSBZD[BZCW<PAcL’dŽp(U[?Y?X:Z;`D\8X 5W9R7L@L >j(N¤^{™@Z¸l€Ú¥˜Ò‡‚É€ƒÍ’“צ¢Üº®á¶ÝÀ´Ü¼©×±š°Z^°GWÂR^³HV¤8L•2H{<l6‘&F¨HS«Xlz'J‚6V‹;V‡7WwJšbŽÜÇÏçÇÆêÅ¿éÀ·Û”®AZ¨6IÉR\¸:HÄHTÄJXÉP_ÓT`Ö^`Üdmßqt惀쒋ðªžöóøÎ¸îŬÊpn£<P§Rj|&KE`Ž=]‰6RŽA^{$N°r•Ú–Òzƒ«AN~ <h3`3b 2f8^:`9^9W=fB~3ZcFÀ|…×¢œÀx‚„2QGbz.Q„@\hDm$F`>\8a<bAeBc?^@ZBbEŒ?[´joÃxvÅtp¾npÃyzÍ„|ÏŒЉ|ÓŠzщ|Ї~ÒŠy΃zЄxÍ„v΄vÏ„uË‚wÏ€uÌ‚|уvÑ„zÒ„yІzσxÌ„vψzÏ„zЃtЂvÌ„xÍ€yÊ€vÃ~xÊ{Æ„|Ã~{Â|Ã~zÀ~{¾zz½{}»vxºx~¸uv´ps®nv°os®jrªmv¯py²z~»‚„ÆŒƒ¯FQ©CP©BQª@JªBN«@P¥BR¢8JŸ=Mœ8G”0B‘*BŒ%@ž4F¼MRÔb[Þsdãmèrì—xîžvïyîœwñ¢zî ðzí—xç‰oãv`ØdZÈSQ­?J–2H˜+Eš4F¢6Iª:J°@K°BL¸DL»FL³DK¸EK³JW³?M¸FSºJQ»YU—1B}9q:^?l@Ƭc{˜šç©”úÉ¢õҾꮎ°TTbGR>TCSAO BXKx<n~:hi Pe"\cWq0fi*bd!Up/am+gs0nˆ\”b™‚=y™zš€H~RDVA_H[Bd#MXBSA^D}BghF\=bEZ<X:a>^<W9P 6Q<PHVFœZnªUb˜H`Àš¦ÆŠƒÍ”’Ô ’ܰ¢à»­ßÀ³Þ¼±Ü¼©Ø²š²\_µN\ÂT\Í_dÈ\hÇYdºQX <Ov8=®EZ¹V^¡Rl}.RrHy*Xš^ŒË±ÅçÁÄíÁÀ첦áˆ~Í_kÂBTÐWVÆKVÈKSÎV`ËNZÑTcØ^fÙgnàpp傀씌ð¶©ö̾÷Һ輪½S`´M^Àlv¦Wyƒ4RB\‹B`€.X›Y…Π±Ü”Òq~ª;L€=m5j6j4h6\7^7Z;Y?o)Jz2ZeJ¹u„Ù š¾{ˆ€0T‡@b‚6Uƒ<ZhCfA`<bBb@`>i$Fc=\:Z>dC—Nd¼ryÅytÂut¾tyÊvÑŠyÒŒ|ÑŠ{ЈxÒ†yІ{Έ|Ì‚wÏ…vÌ€xÎ…z̓vÍ„{΄|΃wÏyЄw΀yÐ…xÐ…xÎx̓zÏ‚yÏ„xÏ‚vÌ‚w΄uÈ€zÅ}xÄ€zÆxÃ}yÁ€¾{{À~z¾x|¹sw¹t|´tx´r|±mt®oz­lt°rw²y}À„{ÈŠ‚Д…Øž‡®@N¬FQªCP­BNª@LªBN§@N¢9J¢;J›:K–2F‘*CŠ$@ž6F»LSÔ`Yàubã~nèŒrî–yížvïŸzð xðŸ{òŸ~ðž~îŸî•zè‡oâxfÚdZÊRP²>M›0Gš1H 4I¥8I¯>JµCL²EM¶GN¶JP½HO»IP»HNµEL±?Fž3<„)<l<2[z$P‡<_§_|И”Ë‚šç”ˆî¸£ùïÑôݯ´r`h!Lm0jM>R@M?TJs4nŠK„|;tq5nh(aZKl0jv7ny<s|:r€Dys/hŠb•ˆU’s0h–tžˆX_L_K[BV=cFZ<X;_=f#H]DbEfFY=\:\<`>Q8N :J 8RL„D\Âwx¢BVÀ†Ú¨šÕ‚zÜŸÚ¨•Þ·¬ß¼²Ü¿´Û»¨Ôª’¶ZV¾R_ÉVaËR\ÐVdÔhmÖjoÑcj¼Tf6R—2N³@TÀQgÂez´a¨Z„³u’Χ¯á¸ºå¿½îļæžÜmpÞsoÓ\gÌNWÒ_cÎPVÍNXÒU[Ó[dÖ[dÙ_hÝinä~똒ò¾´÷ÔÅõһ⮞¼P\¬<Pµ\hÂp‚¦`•Hv•M~¦lœÊ¢¶Ø «×’˜Îgp¦:L€>m9n;n6o=c>Y<`C_Br,Lu+RdL­cvÚ£Ÿ¿„‹‡8\†>`‚>^€;Vl&G`>`>_>];^=k>f>\>Z?n(M£Zf¾uxÂssÀqrÂtt˃ÒŽ~ЉzщzÒ‡wЇzцv΄|Î…w΄vË‚wЂx΂wÍ„z΃̅|ʃsÏ…x̃|Ï…x·{·wÊ…z̓y΃zÎxÊ‚zÌ‚sÉ€wÅ{Ç€xÆ|wÂ|y¼yy¼yzºxw¼wvºyx¶qv±qx²nv®lw¯tz»~{Ň|Ê€Ô–ƒØž„Û¢ˆà«‹¯DQ«EP®FPªAN¨BN©BN©@M¤8L¤8K:J•6G)@&A 2GÁPQÕcYàsbä€lêŒsë–uíœ|î uî¢yï¤|ð ñ ~ì—vê‰qã{jÚg[ÊWT°@N4I™5J¢3D¨8I­<J³AMºEN¿HP¾LT¼IRÀJR¿MP³]bp8^7b;tHžSl²k‹ÇØ~„䔊߫­áŸ’óɤʔk|<CXKYKH€SMVQh)l„P’šo¥ŒZ†{ApP>OCPDuB_L‚Byw6mr2lt8x‹j˜’g¦k(dœƒ°b|>rh"Ke$VR=[>T
+4V 8]A^@^Ag GdB`A^=^#C\>R6J 7K <e C¼ru´MX²]qÞ·¯Ûš‰Ú•ˆÜ¥—ܰ¡Þ¿´ÞÁ¶Û¾ªÑª”¬OQ½LVÊX^ÍZdÏ`eÒ[bÙkmÚrxØnsÕhlÅ^k·HX¯B[²D^ËSdÐdnÑt€Ø€‰Û‹‡Üœ›ã¤¡é¤Ÿæžœàž¥Ú…–Úq€Ð_rÒ_hÖ_bÔV\ÎQ\ÏQZÖZbÔ]eÙXbÞovå~€ìš•ò¹­øÕÇóÒÄડÅj|´Nm°LoÄXpÌs‡ÃtÉz”щבžÑ†Îpr¾HP‘*@n4{#@{">t<r?d?[Bc"K`Fw2Ks*RcK©dzÜž—Ę—Gb†;[ŒHcs$Fm"JcDZ:^AZ8b;h>b>Z8dC†8V®gtÀxwÀsuºnrÆ{ẍЌ‚χ|ΆyÒŠx͆x̓tÎ…yÌ„v̓xÆ~z̃z΃vΆ|ÏŒ‚ΓˆÌƒzÑ…w΂xЄzΆzˆ{ÌỹwÌ€vÌ€vÉ€wÊ~tÅ~yÃ|vÄyvÂ|x¿zx¼yz¸t{ºvy¼xxµst¶qx²nt´tx¼}}Æ{Г֘ۤˆÝ§‰àª„䮇粌°JV®IQ®DR­DR­IT¬FN¨>K¢9H 8Jœ1F˜0D”-D$>2D¿MPÔb\àsbä‚mèŽtê–wî™zðž{ï yñ¡€ñ¢|ò¢ñ {ðšwê‹pä{hÜk\ÈUR¯@M2F›1F£7H¬<I±>I´FP¶GQ»NR¾LR½OY¿KSË^P«XY\8\ 8ƒ*P¡JfÆ…ŒÍ‚ˆÃwŒÏyˆÌr‚Ίۥ¡¬ifb CY RTNVP{G|‡PŽˆPŠˆW„}Erl/Y|Gx_MJ @MC[N„X’UJ|H}v6pl,kv8x‡Y‹v«…G‰¡‡¯‡R~~Bwn1ar9hSAY@S:U<Y=]@^?a@]=`<`A[?Y 9O
+4J
+8N
+6—O]Érl¨>UË•–ଛړ„ÛŸŽÝ®Þ¹¬àöݿ«Ò®š¯LN·DNÊP\Ï_iÒ^hÔdmÕcnÙjqÜnuÝosÙpvÖkqÊ\hÊcrÎ[fºGXÆRd²>QÅ[lÒgpÈfiÊnlÄdkÒ~ˆØ‘œÛ—£Ü›œÞˆØnqÒW`ÒV_ÎVbÒZhÖXbØ\dÚ\fÜkqãzzé—’ð¶¯öÕÊôÖÊæ°ªÞ˜ÖŽÎ€ŒÌp~ÖvÍdpÈ]gÌnrÆpr¬JTŸ4F“&>€<t<—8JŠ-Av<t@eB\=e"HdEv0Mq#J^K¤\uØ•‘Ì“—žVn}3TD`u,Jp$F\>\>`?\<e<l#G`BbBy<X˜LcµjtÀux¾mnÁopÇ|wÑŠ{ЊχxшzчzΆ{Í‚yÍ„z΃xÊ€xÄz΂zÍ‚zΆzÏŒ„Ê’‹È„{̓ỹ}Í„zÌ…{̇zφz̃uÌ‚zÊ~tÄ}xÇ~uÇ|s¾wv½utÁyv¿xv¹tx¸pw´uz¶uy³tzµrw¹{|ȆwÓ“~מܥ„⨆⬅䯈它氆贉´CP®DP°HW®HU«BN¬DQ¥<N¢9I¤4Gœ4F–.B’(@$?œ0B½HLÕc\às_äqèŽoê˜xì›}ï}î¢|ï¦|ò¨|ó£~ñ¥}ð—yêtå~mÜhYÌXT±BL™/Fœ0F¡6F©>K°DL´DN»EKÀLR»KVÁKOÂFPÊXJ´hciA+K¶bvÊlyÚˆÌnƒ²j†®jŒ®cÀ~}ŸS`j&Vn-`e QZF\RaRf–^–n,d`\„V}IyRFRDTJ]I‚R‰`$ZwCtJTSn2nˆY]“‘[–™sŸDˆVŠŽrŸZCR<\AW?ZBX;\<_@^>[9_C`>V5T 4J
+5H <p)IÂwv¹JSµXcÚ®¢×‚Úœ‹Û¨—೥ྰÝÁ¯Õ²š¨IN¯<LÅJXÐZdÔblÕdtÚnrÙhpØnsÛpzÛptÛnvÚqzÙqvÚquÓcmÄTbÌZfµF^È`nËjvÀcyºYl¸\xÉ|‡ÒxÜ‚„ÞƒƒÚvxÒfsÌVdÐT`Ñ\jÔ`mÖX^ÖYfØXeÚjrãvyêï°ª÷ÓÈôØÊæ¶°Þ‘‘Þ~×tvØlnÑjm½Uh³Rj´Tl²Qa˜8X‰*H†&E—6N™3G4F”)?x7v:e:]7eBdD7Tp)O`P¤VrÖ””Мœ«d{~/TŽH`x+Ig>`@^>_?Z9h@hA]?dB„8S©]m¾tx¾rr¾mqÁvwË„|ÑÔŒ{ω~ΆyÏ…{ІyÏ„t΄{ʆ{΃xÆ„€ÈxÍsÍ‚wË„yË‚yÌ‚vÍ…zÈ€zË€x˃vÌ…|Ë‚{Ê‚zÊ€yÈ~xÂ{vÅ|tÄzvÀxr¼xzºts¹rs·sx´tt²q{¸rwºz}Ɉ~Ï’€Öž~Ü¥„à«â¬‡æ³†æ²†ç³ˆæ±†æ±Œç±ˆ³DR¯HR®GP®CN¤CQ©BP¢;Lž9L1Eš5G•0D)BŠ%>˜+@¼JNÓaXÞrdä€léŽpë•{ìœ|ðŸxï xñ¤|ñ¤ñ¤ó¤€ñš|ëŽxå|hßjZÎWP²CJœ.Dœ.E¡2D¥9F°>K´CM¸FL¼KQÀPS¿JPÀFP¾JWÊypªap´pÊr†¾d‰»tŠŒª^k‡8Xp,Sy4^…Gmv2^_JW>PAWLONh5g—{©•l­‰X˜šs§‡KŽ~KŒd"W^ TO FxCsg'bn2e†Xj,lh6l‚Nˆ„Pˆ–l¥™n©”k¢•|£d*NP>\H^JV<]AaBZ:`B`@]>_D^>X8N
+6D4S>¬foÉqk®FTË‚†Ö™„Ú•ŠÚ£•ڨݻ°àò׶§NM¢0B¿ANÊPYÔ\dÔbmÙguÜrzÜoxÚs|ßtzßx~ÛquÜlpÜppÝwwÚkrÖjqÚhkÑ_jÓcnÔjrÓkxÌjxÔx„Ø~†Ü‹Ú|‡ÚvØz‚Ôw}ÎYhÓVfÖ`j×bkÖ\dÖZcØVcÚ_nãx€êŠí²¬ôÏÅöÙËé¾´Þœ›ÚˆˆØ}€ÖoxÓdpÐ^jÏcpÈ\iÊ^i¾Qa¤>K¢4K¥>L©@J¢=I˜/?|8y8_ 6`8c<fBy-Ln(P_LžVrÕŽŒÖ¤£³m€€2V‡?\r$F^<d@\9[:\8q(Dd<Y<a>‹>[²jtÁrs½mn¸hpÇyu΋|ÑÒ‰zω|Í„yφz̓zÏ„zË€x̓wÌxȅʃyË„|Ì„xÌ€sÌ‚xÌ‚vÈ‚|É„vÊ‚{É‚|É‚vȃzÉ€uÇxÇxÀzvÂ~x¾yy»vu¼xy¸vw·ss¶tw¹ptµpy¾~}ÎŽ~Öš€Ü¦‚஄氄洂贅鵇泆贇賅氄粂®CQ©GTªDP¨CT¤@O¢>Ož9Iš5Iš2E–6F‘.C‹%A„:™.C¼FJÓ^WÜqfâ€rçwì–zí~îyï¢xñ¢|ô¢‚ñ¥€óžzñœ}ìnä~jÝm^ÏZS´AJž,D™,B 4H¦<H®=H²CJºFL¾HM¿HLÀGLÀFN¼DTÔ`U΀‡×w€Þ‘ÚÉpyªRm‚4^l3_j+X}8d„@dj'TRDRB^#YZJYN^Wn6h›}®šv°”hžŽhšS€d!Q\NMFh+[u6nf&aO…ŒS”{E}p4ir3k‹X’‹W…›{¬„R}|>tm-]h#RX<\<[<]>\:\;cB\?\;X<P6P <I :}8OÍ~r¾RW¿\bÛª›Ø”†Üž‹Û¬ Ü¶ªáıÛÀ¨¦TNž/G¸:JÅJVÏS[Ò[gØfoÛoyÞu|àz}ßz}Þwxáz}à{~ß|~ÞyzÞttÚnrÜrxÜouÜlpÚoxÛq{Üz~Ý}†à‚‹àˆà‰ŽÞ…݆މŽÖovÒ_iÖ_l×dnÙdmØ\gØWeØXdÛZhâr|èî°²óɼô×Ìëĺતޛœß‰ŠÞ€„ÙszÙlsÙhnÒ^gÏ[cÇV^ºHT¹FT¯HTµIO­BL 2@~8{ =_9b<f>hFs*Fn$N`PšRkÔŽŽÕ¡¤¶p„2T}2Rp$DeBg@`F[@_;o(A`;V;c@–I_ºpuÁqrºnp¼lmÉ~{щ~шxЊz·~Ë‚zχ~Їy˃|Ë€xÌ€z˃y̆zÌ‚w΀vËzÊyÇxÊ‚vÉ‚yÉxÌ‚xɃ|È„|È~zÇ{xÉ~uÇ{tÂyvÀxv¾zt½z|¾ttºrs¶rt²mx¸tz‚‚Ó—„Û¦„ᮈ䲅趈귃뵆궆洆泉貇賅籄鲇°DRªBP¦@N§<J =M8Iœ6F–4Fš2E’0CŒ)A„;w8%<µEKÒ`ZÜqdã~nçŠtê’vìšxí yð¢yð¢~ñ¤ñ¤‚ò¤„ñšyêŒpä~fÞmZÐZP²>Gœ.Dš/B¢6G¦8Fª<H´BL·DL¾HMÂJNÁGLÂGM¾ISÁNZÕkg׋ˆÏyƒºXo¯Xo–Iik'Tf"R}:iŠJxp/\^NNETKq8pdTn-fq2n‚I„„NvGxuCr‚Pk/^XDTBPDb Vp1fh&d^"YˆZ’a£ƒPŽ‹U“‚I…yDv…W„j0[M~`F`BZ@X>X;Y9[;Z<aB[BZCWDP>J @Z@¶opÉe^°FSÌ~†Þ¡Þ¥”ܫߵªâóÞÅ®­hX“&>°:GÀHRÈLVÐTYÔbl×blÚlsàv|àz|à|€Þ}ƒâ„ˆä…ˆå„‚ㄈâ…ßy„Þ|€ÞŠß|€Þƒˆá‡ˆàŠâŽã‘”ጎâ–ᆊàŽÝ„‡×ktÕ]kØckÛjrÜchÚXb×ZhÙYbÛYjáqx劌訪ñÉÂôØÌëĺ⮧⤡ߎ߄†Ü‚Ûx|ÚqwÕ`lÓ^fÏ^hÎVZÅPZ¼R^¾PY´JS¤8G„<|=c9h:f>p"Dv,Jn&N\M–NiÓ’×§¨´w„„7]~6Sr(Jb>f=Z<Y7c;f:Z9ZAl C¢We½tvÀqs¼nt¼qrÊ€zÏŠ~ÑŠ{φ~Έ{Љ{Í‚zÌ„xÌ‚zÍ‚xÊ‚yË„{ʃ{̓vÌ‚zʃxÌ„yÊyÉ€wÊ‚xÈ‚{ÉzÆyÄ‚}ÆxÆ|xÄ|tÄ{xÀxtÂyv¾wx¸yz·rv´nr³mpµqtƈ„Öœ‚᫊消鸈까빂븄鶄궂鵂貅貄è³è´†è³ƒªDT©=K¦9J£8Jž<N›6L™2F–-G–1F”/CŠ&<†;€:Ž$>®AKÑ_ZÝqdâ}hçŒvè•|뜀îŸ|ð¢ƒð¢|ò£€ò£~ð¤ð›wêŽsä}fàkZÎYP¯@Iž4Eœ*A¤2D¨9G²=G´@K¹HN½LT¼LP¼KP¿KT¾JX¾Vf¾]w¸^z¨Op®Ri¡Efy-bz?{ˆKQr1_\H_NUJ^MzBzq+f„J‰Ž[–a~@u\Wq5i‡R…f#TI ?ND^Tb[w@q|Aw\ \W V•r¥†²Œan,dt@zyAx—Œºn9_QBX@_B\>]AZ?Y:Z@\D^HZHUGNFPEŒEVÎzk²ETµXfÖœ•Þ Þ¬Ÿß²¢â¾¬àʰ´o‚!>§.Bº?LÆMSÍQ\ÓV^Ö^dÖfsÛiràuxâw{á~‚ä…懇厌懆勉甊䔑⌋䊈⌊㌌䖓◓ã”ã‘⌌ä’⊊áˆÞ||ØjrÙflÜopÛkpÙchÙ\dØ[aÚZfÚYgßov厎騪òÇ»óÖÌíÊÀä±§á¥ß˜—Þ‰ŠÜ€Ü|€ÚxyÖjsÖdlÔ^hÒY`ÊRbÃRa½L[´HU¦<M†:x>g:h>h>s#Dx&DkEXF’FdÑŽ—Þ¤ Á‚Ž„3Yv/Jp"Fb<g>X<Y9f:b:X8[:|+M­`h½qr½nl¹nsÄww͈~΋φ|Ј{ÒˆzÎ…{Í„z̃x΂vÌ‚zÈ{Ë‚{Æ€y̆xÈ„}˃yÉ‚xÇ~uÈxÌ‚yÈ€xÈ~xÄ~vÀ|Ã}yÇ}|Ä{wÀyvÁ{u¾zv»xt¶ss´pr°ovµrtƌؠ‚⫇赊꼌컈빇붃鴃êµê³‚沅贆贂粅괇¦<N¤;K¢:M 8Jœ5Lš4H–5I”.F”.F‘.EŠ"<„;:+C°?GÒ^XÜl`ã|kç‹tê’xìš|ïž~ðžyð |ó¥xò¢~ð¢‚ð˜vêŒpçeÝm\ÎZT±CK0D—-A 1A¦:H®<F²@L·DL¼HMºKT¾JR¼NZÀN_ÀVm¬P|¤L}¼n˜¾w  d¤žw´¨ˆ¸¡v¢„Jye$Ud S_QcXn*_ŠTŒv2jeœŒXŒŒSˆz7wt5r“g™{@pN>J@QFZKe&_ƒJ„•dšz@{l2nl4jwDvŽd Hb¡š¹Žfƒf$Rh&Mh!G`D^B^@]AX=X;ZDWFXHRDNGeD¾xsÃ_Z²JZË‹‘ÜŸŽà¨•ß´¢à¸ªßÁªÄš‡w=&B¬5E¿FRÈLSÑV]ÒW`ÔZbØhsÜgqßprâx~ä}}å慄摎懆æ‰è”Œè˜‘ä”äæŽŒå攎ç”㑎掓䔓â“⎎àƒÞyvÚltÛhoÜntÙfnÚ`bÙYdÖ\fÚY`ÙU^Þfr倅訨ðÁ»óÖËðÍÄæ±ªà¤šàž™ß܃†ÝzzÝtxÚknØdhØbhÒ]fÒW_ÈVcÆS[ºNU¨<L‰#=t<b=h<p Br>z-HoCW FŒ?`ÒŽ”Ü¥œÇˆŽˆ<]r&Fm A[6jB[A\:d=_<[<c@’?X·fk¾vt¾npºntÈ|xЊ„ÐvЊzφ|ψx΄x΃~Ë€vÌ€y˃{Ê„{É‚~ȃzʃzÊ‚zÊxÌ€xÇ€wȃyË~sÈ€{Æ~vÆ~xÃ|w¾|wÂxxÄyuÀyv¼uq¼us¶tr¶st±puµtvÆ‹|Ùž‚ã®‡éµ‰ì¼‰ì¾Šî¼Œí»‡ë¸†ê¶ê¶‚ê´è±„簀鲅鴂絆赌¢:I¢=L¡DQ:L™7J˜6L–5J’3F.C,C…#<:{>Ž(?­>JÐYVÙncâ€oèoì•|ëœzîwïžð ò£zñ¡xò ~ñ™uìŒoæ€iÜlZÊTP¯@Hž0C™,B¡3E¢;J¬;G³>F²>KºCT¿HX¼Qq¾\Œ¹n »x«°}´º‰ºÃ‰­»’¯žy˜Œ^~ƒVvz?ki)Yd!Rf%Tl-`e Ux;n„M„u6n‹_‘‹W€A{ŒX”’b„Fu[HL?R@O:ZJUN_T{Dt‡NŒ‰X’Œ\˜€MŒ~>x˜|¥œ°ˆ\‡n.Xš\}™Hc‹9Pƒ3TR<WB_BY;WAX@VDRCLBNF”RbÐ}p­EW¸XcØ¥£ÜŸ’ß´¢Ü´¨âĮҵ›t/B{:˜(B°:IÁKXÉO[ÐS\ÔYaÖ[b×alÜipßouãy~äxwåƒç„†çŽˆè‘Œç„è–ꙓ甋蜖Ꙕ旒甑å呑處晓æ—âŒà€€àxyÝruÛkqÞnuÚksÚcj×ZeÚ`iÚU]ÚV`ßbkä}‚袠ïÀ¼ôÕÌðÐÅé¸­à¡˜àš‘á˜ŽÞ‡†ÛxyÞptØjqÚfiÖen×_lÔXdÏXbÌU\ÂQR«DOˆ#BvAb?f@nBt!B~-Hh?U
+Bˆ:WÒŠÜž—È‹Ž’Fan!?e9V 2o#CV8_<h<_;\=f? Pa¼qwÂrsºnnÂnn̆|ÒŒ|Ћ}Јz͇{ˈ~̃|ΆyÍ„zÌ…€Î„Ê‚xÇ‚}̇zɃ}Ì‚zʆzǃ{Æ‚xÄxÀ|€|Ä|wÄ~|Ä}zÀ|yÀywÂwr¼vw½wsºrt¸rw´rv´rxƈÖœã­Šè¶‡í¼‹ð¾Œî½†ð¼‹î¹ˆë¸…ì·…ê´ê³‚鲄糅궈괅趉鸌ž7Lœ:MBU™7I•4H˜0H”0E”/F,D'?†$>}<w8Œ'>²HRÐ\XÚpbßjçŠoê”|ê›xîyðŸ|ð zò¢|ò¢€ò |ðš{ê‰næ~iÜkZÌYU°@Lš,Cœ*@ 1B 7Gª7H³?N°Dc¸Nt¿h’È„œÊzŽÅšºpŽÁpŽÈu´p‚|:V^!Sb'Zv=ph)X` Rh&Yi&Zh$Wm&Z~G€€B|x;sˆ^—z@zfŸ™nž„Ith*VWGYHT?P?XASEUKd*Yr3ot8l’_“˜kž•k•l6\NARJx2V´u€±huœPc„4UWFYE[>X?VBWDSBSFNF_ J¾}z½ba°P`Ç|†Ü¨“ட߷¨áÁ¬ÜǬ„GL]8<š.B¶<HÉMUÍOTÒT^ÕX^Ø[bÙdnÛilàptâwtâvxä~€ç„„挄蓊锎蕑ꞕç—è‘Žéœ•çš”è–æ›’痑阒皓敌äŠâ…ƒàxyÝsvÝv|ÞpuÜlrÜdoÜ^eÛ^fÜY^Û[dÜbnãw|皘ï¼ôÔÉðÎÆë»°á¡šà’Œá‹‰à‰†ß‚‚áutÜirÚbhÙ_n×ZiÕ\iÒ\hÌTZÄRY­?O‚DuBa>l Bt$Ds"C€0Hd>YG|-RЊۜšÌˆ¢\sm"AcCY8k>\;b<d<\8^;x)G¬[d¿vuÂqp¾mnÄvtц{Ð~Ћ~ψ}ΈyÊ„|̆y͈zÊ‚zÊ~È‚zÈ‚~Ê„zÇ€{È€{ɈȃyÊuÄ|xÆ~xÄ~xÁ}wÀ~xÆ~{À|xÄzuÁzxºvw»tt¹sv·pp´qvµptÂ{Öš~à¬‚èµˆê¹ˆî¼‹î¼„í»‰íº†í¹„ì¹†ì·ƒé¶ƒê´‡è³èµ„ë·Šê·Žé¸è»“™6K˜5N˜:P–6L“0G”,D•6N-F*C‰&?„'D{=x<‹'C­CMÍ\ZÙthß~lçrì•xëš}îœ{ïŸyðœzð zð¦€ð¢~ð–zêŒqä€iÜn`ËXQª>Hœ/C˜,Až0B¤6G«9L¶ET·atÂhtÇ\bÄQ^ÁXkµdˆ¬aаeLx†6hk$\m)a|:nv7hg#Ug'Yb Rf']j)b|?xu<ru7p‹Z—ŒX”–u«–l–’f‘aQXG]J\DZCWBYCVBUFYNl/Xx?v_Jh-H„CWT<D >[D‹<\¶ot·nu P_v*N\DTAY>Y@V@V@SBNDRIŽM`ÌzpµT]¸\dӟޢⴢ຤â̲¥zhO9g9‚<¢:J»DLÆQVÐUXÒV\ÔY`×^`Û_gÜfnàpxâorâyvä~~胂挈éŠè”Œê–꜔ꜘ隒階雔è˜çšç›êœ’薌玆懄ã€|â~|ßuxÞqsÞnsÞlrÜglÚ^aØ^dÙ[dØXbÛ`iãwæ™™ïÀ¶ôÒÊïÔÊëÀ´ä¢™Þ“ŠÞŒ‡ß‡„á‚‚ßwyÛkrÚepÚ`kÙZhÖZjÒZdÍX[ÄRW¬@M|?v@^Ao?nCu'Fƒ3Nd?VDy*NΆŒÔ”™Ì„„´sl=`8Z 4`6^7e:b<Y7[=…5Q¶djÄsrÂsqÀnpÈzvЊÒŽЉ~Љ}ψ}͇}̇~ψzÌ„zȃ|Ë„ˆ~ÉzÈ‚|Ë‚zÊ‚xÈzÉvÆ€|ÄxÃ}xÃ}wÂwÀ|{ÀzyÀ}z¾||¾xt·tv¶tx®nt²qu½xvÔ”âª€ç³…ë¸†í¹ƒíº‡îº„ì»…î¼…ì¹ì»ˆì¸ê¸êµ€ç¶‡è·ëºê½–êÀ–êÁœ–4J”3I’0H’0H0FŽ)C”.E‘/G‹*F†(D‚"=x;t?‡ @¯@HÎ^XÜndâ~mæŽpê–yîœ|î›zîž}ðŸ{ð¥~î }ðž|ï˜}êŒræzdßl_ËTS°DIž/D–*@š6G¥5H«=J±GV´MY¹HU¼MV¾N\ÃVeÂd|©Po•Fh>mˆH|‚>uƒAt~?rr1]s)ZiN_Vp-g‚H…WŒ_ \r6n—k¦™v¢‘bk)Xi1]n1f\I_HZ@Y@XDXCXB[HXIWEr.Rv:ncCˆ6IX<H <T<–E\´ep¼qwžRf”Lf^AUAT=T>R;XCN=J @j&JÀ}|¾ef¹TdÉ€ˆâ²¥á°Ÿß°œà¿§Â¡ŒX<Z<p<„!@¦8IÀGRÉRXÐR[ÒW^ÔV]ÕWZÚ_eÝikÞksãtsâyzãzyä~}凂针閎阉윓ꛓꞙꡚ蜒蚒界蚋ê•甈率åˆâ„}àywàtvàtvßttÞpqÜjnÚbgÙ`dÚVaØ^bÜ`gãwzçí¾¶ôÖÎñØÎëø⠚ޒ‹Þˆˆß††ß„€ßxyÜqvÚkqÜ`lÚ^m×ZfÖ\aÑY[ÆMR¦8Iu?tA[=p?hBv$@Š9Nc@Y At IȈ֔˜Àox¼…Œp?\:W 7^:n"Be<`8]<d:–EV¾mmÈynÅtpÀpqÍ„{ÑŽ~Ó~ÍŠxψxÌ„ẇzˈ̈zÊ„zË€xÊ‚~É‚zÉ€zÉ€zÊyËzÇ~yÅ|€|Ç€xÈ|xÄ}xÅ|yÀ~¾||Àzv¼z|ºuv¶rq³puµlr¹rtÌ€Þ¤€è±ƒë¸†î¸ƒí¸~ì¹„í¸„ì¹‚íº„ìºƒì·„ë¹†ê¹†è·ŠêºŠê»ì¿–ëÀ–ìœê ”2J0I1J‘.HŽ.FŽ,D*D‰*Bˆ+D†)B~#@x Aw@ˆ#@²?HÍ\XÙmdã{kæpè’vêš}îœyì ~î |ïŸ~ðŸ|ò€ï—}éŠpæxfßl^ËZU¯@Jš0F”.Dž4F¢8K¨@P¬@N°LW·KV¹LU¿N]ÆS]Ä_nž=`Š<jx4my6o…I‚ˆMˆy0`“Lz}1bdVr-h‡N„†^Žc*\\^zCš~±†Q†‚VŠd*cl8go2\`JV?Z@[A^J^FZE]FZFX@d&HZD_@ˆ8Mb:F9T?“CY±bq¸eu´€‚R^\BQ7P<R;O 6U>K ;K 8˜M]Étj·P]º\fÚ°®â°˜â¶§Ý´ ÖÀ§r9FM>Z@l>Š'B©<J¿KRÊNVÏRYÔXbØ[`×\cÙ`iÜ_cÞfkáqpârrârrä{yå…ƒé†è…ꔎì˜éœ–윔ꡒ顕è–瓊疌蓊蔅戀äƒ|â}zàxvßqràoqßtsÜlmÛfjÚ`cÖY]ØY`Ù_gÛblàpwå’’í¸®óÐËñÖÊìÈ½à¢˜ÞŠàŒ‹ß‰‡ß~ÞyxÛrtÜkrÝ`pÚ`qÖ[dÔ]bÏZ\ÀJPž2Fx@n@]<oAdBz#D‹9N`:X <sFÆ€ŠÖ“—ÂqzÊŒ†z&HZ8^=\:r&Dc:`<^6o>£PZÀnjÅspÂqnÇxvЈ{Ò€ÓŒ{Έzχu˃y·{Ì…|Ì…yˆ~Í‚zÊ€xÈvÌxÈ‚xÆzÄ~|Æ~zÈwÁ}yÇ€vÆ~uÂ}zÄzvÅ~w¾{{¼x{¼xx¼ut·rq±mp²hnÅ€yØœ{æ¯츄ðºƒí·„í·‚î¶„ì¹€íº‚ì¹„ì¹†í¹‰êºŠë»‹ì¿”ëÀ’íÅœìÄžéÅ ëÄ¢’2J2JŒ,F‹*CŠ(B‹*Eˆ'D†(C„'E„$@}>w?u:ˆ%C¯:DÏ\WÙojà~låˆxë”{ê–vì›{êŸ{ë›xïœ|îœ|ïšxð•zê‰oç~hàk\Í\X²AJš,A”.D›2DŸ8L¤9J¬ET²FRºFP¾GNÂMSÄMV¿P`Ž*Z‚=|™dœ˜n¤‘av/cŒ<l¡Rz4iz4jX„P}^(UVP][j.g‰j™a¢€Lzx?xc'Pe'U]HUDZ@dJ\E]FZ@ZFZEZEZ F^IX@y,Bj=J
+;t FœDY¬^pžJlȉÀwv‚7TL6N<L ;L
+5N :K9fBÀxj»^^·TbÆw}ß´¥à³¤â¼¬ÜȲžpmODSCdCo?ˆ#?ª:H¾GPÌTWÍRXÑSZØ\dÚ`fÚ^dÜafßioãnrânpâtuäzxå{vè€x艂ꌃ쓊êšêœ’êš“é¡é˜é•Žè—Šç’ˆæ‚åˆ|æ„uá{wßmpÝmpÜhlÞppÛhkÛfeØ]cÔUTÔ\aÙ\cÚdmÞt{䉌쭨óÎÆñ×ÍîËÀᣚޑ†àˆÞ„‚Þ‚Ýz~ÚrwÛmqÚdmØ^jØZgÓZbÌV]½LT‘+EzBa=a=i;d>{"B‰8Nb8Z
+=jEÄ‚†ÙœšÄv}Ì…Š?ZT:X
+6Z:t*Dd>]>b@€*F²adÅtkÆtnÂppʈ„Õ™ŒÓ“‚ÓŒyωzΈ|χy·zˉ|̃xÊ„}ËxÌ‚xÇ‚yÇ€wÅ~zÉ}|Å|zÃ{Ä€}Á|vÄ}wÂ~vÀyuÁ|xÀyw¼zw¼xuºtw¶op¶np´ko»tuÔ‘{⪂괂ﺂì¹î·‚ìº€ì¹ƒìºƒì¹‡í¼‰ëÀìÁ‘íÄ™ìÅœîÆœìÆ›êÆžêÅ¢Š-G‹,H‡.L‡,G†/Hˆ.H‡.I†(G~%D€&Cx>t:q:Š">¯:FÍ[[Ùroà|lå†té‘xê”|ì›xìšyë˜xí›|îœzíœxí•ué‹wç|dàlZÎZS¬?M˜*B’,I›3J¢>T©Hi¨?N°CN´FO¹JQÁJSÁK`°M{’J¥‡¶ŸyšX|w1f;ošU…ˆGzs-_]“‚Nzc%Y^&\e&^d&bXWqBt’v¨|Cv†UŽ\Pf'RgO]J`Dj$MYBXAY@V=ZBWC\#F€PvX;^5o =R>\=—CZ¢Zvš>a®PQÖ—Šºxyx2QO>H 8J9N 7Y=DPËre¶JR¾ZaÖ¤¤à±£å¾®äʶƫ”XBJ :UBlCr:‰#D¤8I»FRËNUÐUXÔX^×Y^Ú]cÜ_aÞgkághânpâtvåtwåzxäzv䀀戂猄êê—閎Ꙏ뚌ꗒèˆê’†êƒçŒ„æ‡{ä|âxtàsqÝknÚgnÝhjÜijÙbdÙZYÔVa×VYØ\cÚ`làruよêœñÈÁòØÎðÍÀá¥ ÞƒàˆƒÞ†ƒÛ||ÞuxÜzÚmtØfpØ_lÕ^iÒZ]ÈV\·DNŠ&Bp>X=e@i<iCx)Bˆ8L]8V
+?a>»x€Øš˜Æw‚Ë„‚ Vl^ER 9V:n$@eD[@h>“8N¼ihÂsjÃqnÀopÍ„~Õš†Ô•‚ÒˆxÒˆ{Їz͇y͆}Ì„y̆xÍ‚xˆ}Ê€tÉyÉ€|Ä~{Å~zÆxÄ{Ä}zÃ|wÁ{tÁyvÂ|xÅ{xÂ|x½{y¼xx¸sp¶pt´mp´oṗxÞ¢é°†í¸ƒï»ƒïº‚ï¶î¸îµ}íµì¸…í¸ƒìºˆì¼ìÀ‘ëÄ—ìÆ›ìÇžìÆîÆžíÅžìÄžêß-Hˆ/J†-L†,J‡*H‡.L†1O„'G~(H|'Hv Bo>l=„ =­>KÍYVÚpjá~mç†oé”têš|ìšyê˜{é—zì›|ìœxðxïnê…næxdàm]ÐYP«?L–,B'C–.L¦Jb¶iЬ@S®>N·GT¸F\ºTyÀq µ‡¨¦w’ƒLfn*XdUƒ>s¨qššT†s2dg˜€JqZOZQzH…l,fq0p_ a‚Yššz°‰P‡”qh(Z`!Nd"Pb"RcGl(QXBWDT<T>YET >^"Hr5LhCkAn<`@vKHc­r‚¸`dŽ)G°QUÒŒv¼|}`?J;P:R =^;¶ji½a_´LXÃnt⿵㾳æÄ²àʳCJI 9M <^>{%Ds='B¤5F¹AOÆJSÌPVÔX^Ø[`Ù[`Ý_`Übdàjnágoârtäxzåxxä~~æ}{悀狄쎅ꘊë”떎ꕌ閌鎉钉錆èŠå†zä|táxtßkiÚbhÙcgØbeØhjØ`dÕX^ÕX[ÕT[ØY^ÛckàjsညéœñļóÖÊñÒÄ㪧݇‚à†‚Ý„‚Ü~ÝsxÜszÛhrÛfmÖ`hÕ^hÑ\dÈTZ®@N‚ AdBX@h@jDnA|*DŠ:NY6T:a <´lvÖ’‘Èt}Ã~«^nj"FP :\<k>`BXBj< P`ÂohÆtlÃrnÅxpÐ~ÔzÓ{ÒŠwЉxÏŠuÏ…{Ì…zʈzÌ„xÊ‚}É{Ê€vÊ€wÈ€wÄ€|Ä}tÆ}vÃ|xÅ~zÃ{vÁ{uÀ|ÀzvÀxwÀ|w¼wyºuu¹tu´no°opÀ{sÖ–u䬂췂ﺀï¹}ï¸î¶}í¸î¶î·í¸‚캃뽎íÀ”îÄ–íÇ›îÊ¥íÊ£íÈ îÆìÚêÄžë Ž5Jˆ-Jˆ.Jˆ.Lˆ0L„0L,J€+J|'G{$Ev@l;l8„&D°CKÌZXØnhß|läˆrèŽyê–ì˜yê˜xé–zìŸîž|ðžwïqêˆnåyfÞk]ÎVV®@M–(B‘*G“'H«Pb°h‹ =X¬:Z¶Qx¿u£Å§»y¹l€Œ:bTBaUw2m¢e•º ŽEvˆ\yBj]SXVZ$]…^˜l<qi,th4n˜†»”qŸ‘\™„Z€€E|_JeOf.Vc Lj"NX@Q;O<O<SBX?r$C9Qˆ.Cˆ1Kf=€.Q4]œW~Í͆–7Rw"F½`\̃j{(LF4J
+9H<~8NÆxo¶U^´VaÔššæÀ¯æÅ³âȱ¯ƒnO:N :N
+;c@‚*Fs;‹<¦2E·@LÂJRËNVÒT\×]`×[`Ú`dÛ`dàcfàlnânoässäxxã~~å|惂ç‚}éˆçŽŠê”‹ê‹„è’‰ê”Šé‘‡è’‰é‚舀æ‡|â€yàxrÝhfÙabØbhØbfÙ`cØ^`Ö\`ÔRVÕRXÕX\Ù\fÜcoà‚‰éœ ð·óÓÉòÖÉè·´Þ‹ƒßŒ‰ß€}à{~ársÜpyÙjrØbjÖ`hÖ_hÒX\ÆSU¤5JxBZ=VAfDt$DmA€)A;R^ 8T >_Bª_lÑ“’Às~Æ„‡°gxn(HK
+7b>e@^=X>w*J­YaÄujÇrkÄpoÈ|uÑzÔŽzÔŽxÕŽ}ÒˆvÒŠyψz̈wΆz̆|΄{Ë„zÈ‚|Ç€}Æ‚|Æ~yÆxÄ~xÀ~|Ä}xÃzu¿zwÂ}wÀxu¿vu¾zw»uw»vx´su¶knºpr΋uà§{è¶íº‚ð»€îºð·|ï¶zî·~î·|ì·z뼃î¾íÂîÆ–îÇœïË îÌ¡îË¢ìÉ ìÆ˜ë–éšêÂ0JŒ1L‰/K†0N†5P…/N„1P‚(Hz"Fy#FsBl<h:€$B¬9FÌZZØofàziæ‡tê’yë–|ê˜zê–yë–yì™vîœ|ïœsî‘pèˆoçyeÜn^ÍXS­9H•)?‘*C”&F©>QÀwŠ«P³TwƆ¢ÅrŠ®Sx®d±f{&XbTz,e a¤l–ŠBjŒS‚z>ie#Z`"`\ Zt@€{H„ežq6u|T’‘qª‡Y•o¬u>l˜r¦d#Pd$Rd)P`Ff NV=P 8M8H 7V>jH=N«Zg:K‚&@b@7[’Hw¸qƒâ£˜ß¥‘®WdYD’7F¬jpkBC4@4S:²ii¾ib²Xd¾dhݯ¨åÁ°ãƮģŽZ4K
+6P 8N
+6i!A†0Hx:Œ!;¡1D¹DNÇFNÌOYÒX_ÖZbØ]`Û[cÜ]`àdjàdjàlqârxæwzå|~æ{vç~憃æ}熀掇æˆè„ꎂèˆèŽ„èˆè†å‚wä{tßvvÜihÚdd×^dØ_dÙadÔ[cÕY]ÓTZÒSZÔVZ×X`Üjmá~„蘒ﴮòÑÆôÛÎìźۂ{ß„Ý|ÝzzÞttÚpvÚmtØbo×]jÖ^fÐZ\¾HR›/Iq@T@Y@`Av"Cs'Gƒ-G<L]6P :^@£Ndё‚ŽÈ…ˆ´pwm%HH3`:]=[<Z:Š5P¸fhÇvoÈqlÂpnÍ„{ÔŒ{ÒŒxÒŽxшwчvÎ…xÏ„vÏ…x·yΆxÊ‚xÈ„zʃ{È‚xÆ‚zÄzÄ€zÁ€}ÄzÄ~x¿}yÁ|vÂ|v¿yv½vs»vt¹ww¸qr±pq¶lpÇ|tÚ˜|æ°~ì¸‚í¼ƒð¹‚î¸|í¶î¶}í¶„í¸íº…쿎îÂ—îÆ˜îÈ™ðÊ îË¢îË îÌ¢ìÇŸíÆ¡êÜêÃìàŽ1J‹1JŠ2J„-H„.L‚+K‚+H€(Fz&Dz @s=l;c7<ª<HÌ]ZØlbà~læ‰ré“ê”|ì—}ë˜|ë–wí˜vîœzî›xï”sêŠnèzfÝl\ÍWO¬<G’+@’(B’'Bš1L¹R_Æx„ºk‹´Z€§Lt§Rz¶_}°Zw‰/ep \Aj¨hŠOp9k€Kzv<l|T`!Yn4sIˆv@vŠhžj(eƒaœ‡^š‰\’žˆº{<q‘ršf#PYCZDb!Kc HX>S 8T>O:n FfP|*E©QY >PwB2`Fi¬^r³FU؞᪚½nr^<s:…8JO5D2D6v*CÄugºTXºXcË„äÁ´æÆ°Õ¾©p1BJ:R 9O
+9P =j<’9Rz:$> .B¶?KÈHLÊNVÔ\`ÖT\×Z_Ú\bÛbdÞdißdmàjmärväpqãzzävwå}ç…|æ€}æ|èƒ~æ†|挄è‰çŒ„åˆ€èŠæŠå‚|âyvßpoÚhf×b`Ö^cÖ]dÖ]`Õ[bÔV\ÐSYÒRXÔTZÖXcÛflày~æŒìª¨óÒÉöÞÒðÍÀÛ‰†Þ‡„Ú~|Ü{zÞsrÜrwÜhpØen×_kÔ\aËTW³FP-I^AV@`G_<v#Ev$Dƒ.E‡6K` 3R5]@™DZÑŠ‹Ì‹’É~€¶v{s+KI 6b@T:[?c@˜EV¿nlÈtmÈpjÄtpÑ„yÕŽzÒŒxÒwÒŠ{цtÐ{pφt·vΆtÌ„yË…{Ê‚wÌ„yÉ…{ÉzÄ~xÆ€xÄ‚}ÀxÆ|xÃ~zÂ|vÂyv½wuºvu¾zx½tt¶st²nrºrrÒŠxá§~ê´}ðºƒîºð¸‚î·î¸~칆켈îÓïÈ™ïÉìÊîÊœîËžîÉ¢îË ìÈ¡ìÈ¡íÆžëÄŸíÆ¥’0J2L4Jˆ,Lƒ0N‚(H„+H,J|'Dt=m;i9c9~7«9EËXZÙlaâ}måˆxç‘zé”yí™}íšxíœ}îšyîœyñšwï•sé‰lè~bßm[ÐTK­;H–*@“(@“+B˜1F¢?N®E\µPj®Y‡¥c“§c–¶g޹d„‡6fdR|9p’T…>qF€>x~F„c!Yt:xzB‚r3pŠh¢O‚p4t~Z—zC€fš¢·x4prJrg*\N<RAV@`E]?X>U?TA`El4d€>b6R‘8S†*Q²w~¶a`µSX+GŒ9B­h_’JW^:W4dDN 5K9R 8 S[Æl^ºWb¿clÞµ®èÆ®ÞĤ][K 7P<S9S
+:R 9n(F–AT€;Œ(@§2C³<IÂGLÌPUÐSZÔZ`Ú]`Ü\aÜ_dÞahàeiàjnälqãqvâutäwwäwuäzwæ~yå~{å|{åƒæˆçŠæ…å…€è†~ä€{â|uàrrÜmnØddÒZ\ÑY]ÔVZ×^bØdjÖU^ÖT\ÓV[ÑNV×ZbÚclàx}抌좞òÐÆöàÔñϿޒŠÝ‚~ÚÞy|ÞxyÚqyÙgoÖfnÔ^gÓ]cÃUZ§>L~AT<SB_>cCw(Gx'D„+Aƒ/Dd:Q4Y ;“9T̆‡ÍÈ||¼xx€8UV;\>R9Z<v&I¢S\ÃtoÉtlÆqmÊvlÒŠ~ÒzÒŠuЋxЇz͈x΂sÎ…t˃t΄vÌ‚ẋ|Ljzʆ€Ç‚wÇ€xÇ‚vÄxÆ‚xÂzÆ|tÂ~y¾}xÂ}x¾{v¼usºzvºss¸mo´mrÅ~vÛŸ|氄ñ¼ïºð¸|ï¶î¶~ï¸ƒì¸„í¾ŒíÃîÆœðÊžîÌžîÊîÈ›îÉžíÈœìÈ¢ìÉ¡íɤìÉ¦íÆ£íÇ¡’2OŽ2K‹0IŒ0JŠ.J‡0J‡0I‚.K| Bw@r<g:` 5y8¨8DÊXSÙj\à{måˆxêzê•í˜zí›|í™î›zðŸyò~ð•wëkç~bânZÐVP°@K”,D&B’,Eœ2G¤;T©Hj¶\|´Tt§Ot¸`}·f¦Xr'Yt*^‚@q}4j|:nŽWŽ‚Ho0et:u|D}n.rn2iq¢c%[e'_~X˜p3s‹g𣑷€>~d0T‚P†N?SA[FU>^FdF\ET?Y =e"F7as&H…/TŸG\Æwt¾HOž3Fy H‹Oi†C_aEP5W;]@F2Z<ŒBU»d_¶QV»ZaÍ‚„äÀ¨Òš~¼†{Y9J5K 5V 8U8T 9s*EšJ^:”%<£/B²;HÀENÊOSÌRZÔW]×[\Ú]`Û`bÜdfÝ^fàekâlqäqvãsråxyãxxâxväxzã{z倿‚|僂艂æ„~戅èƒ}â€zàxtÞssÛpn×`bÐRYÍNVØY`Ù`fÜdfÙ]`ØX_ÔW\ÓTZÖ^cÛdlàrwçŠêž™òËÄöáÖòÓ¾Þ—’ÜvrÜvuÞxxÞzzÛnpÖhnÖbjÒ[cÎZ^»T\›:Nd>Q>UB`A]@v"C}*Eƒ.G~(>j<U4\ <…-NÁ|†Î•Æ|€Å€˜Qf\<T:L:U9…2M³_bËxmÌwkÆsmÊ{vÒ|ÒzÑŠ|ψzΆx̆{ΆxÌ‚tË„tÌ‚yÌ~tÊtÊ‚{É‚{Ê‚uÉyÆ‚yÂ~ÆxÅvÅxÈ}rÂ}xÁzvÂxw¿vs½us¸pq¸mq·suÐxâ©ë·‚ñ¼„ñº‚ð¹~ðº€î¸|ðÃŽðÆ—ðË ðÊïÊïÊ™îÆ˜íÆ˜ìÈœìÈ¢ìÉ¢ìÊ¢ìÉ¢íÉ¥ìȨ“4I1JŽ2K.L‰0HŠ/Jˆ,E‚&B~=w;t:f6`
+2{7¨6BÊWTÙi]à}oèŠpê‘xë–yîš~ì˜~îšzîšyð~ñ |ò•víŒtæ~fßl[ÐWR¯AJ*AŒ"?–-L¥@^²\„¾d†¶Tm³G^ªMmµRq¹Ri™<ht%]-b†Asv,fƒI}–fšz7js6nt6ln-nc"a„]‘†XˆURh-nŽl¤q1s…_™žˆ¬ŽUŽ^ NŒf•WDQAZLb!Sl/X_CT9J 7^Bn&I~7a—O_™Slœ<TÆnYÈ„s¯dlBX‡=Po'FV:N 7X>K
+;Q>œh¼u|·fm¦P\ŸPfÀ|wʈ|À‹Œ°xn%JS 8O 6Z8W6W@u*BK]%<&=ž0C­:FÄKQÊORÑTZÔY]ÖYZÙX\Ú_bÞ`eággáhnánqämnáoqåxsãxväuuåzvã{zæ}~å~xä‚~ç|æ„~æ„~惀â|{àvsÞmlØmlÑSYÈFRÐQYÚ_eÜgiÜelÝgmÜhnØ`g×X]ÖY_ÙblÞlp芊ôÈ»ùáÓóÓ¿ß•ØtsÜuqÞvwÞtw×lr×djÔ^fÑ]cÈW^³N]…&CY@V@Z?aB\A{%B.H€+E€+Bf;T3[ ;r>»v~Í“•Ê…‡Ì„}¤\mg=R;K 9X<•GZ¼ikÏ{qËzpÊtlÏ€tÒzщw͈zÎ…xÍ…{Í…tÌ‚vÊvÈx̆wÊ€sÉũwÊ‚wÈ‚{ȇ|Æ‚xÄ‚~Ç€vÇwÄzÁ~vÀ…~Ã|v¾wv½vr¼rq³ll¶npÄzwÙ˜z鲂ò¾‚ðº€ð¸ð¸|ð¹€î¸‚(ïÀŽðÄ•ðÈîÊšîÊ îÈ™îÈ–îÅ”ìÆ›ìÇžìÈ êÈ¥ì̧ëʨêÈ¥ìȨ”6N’9O’2L1H‹0H‹.F‡,F†(@‚%@};v;f8` 4|9¦<HÍXVÚjaázmæ‹vê’|ë–~ì˜|ë›}횀ï{îž|òzñ–tìŒpædàmZÐVR²<J“,K”-V¦Fq»f‹Áe{´KZ°EZ¶IV®Pq¸Sr¹Pk‹8hz,`i'T†Ay‚;y”b“ŽZ‰z2hx;nh,^o3pZ Ut¥t;nPQe*bŽp£x8€vH{ ®“b–\Q|Y€j'^[Ll+[g%PX<^<l$IN
+4U=iH…6Nªj_ KMf=q%K’@T¥Sin"DT:P 3K
+2R 4T 9D:‚LfΔ‹Ø‡Ï‰Ä†‚·w„¸~ˆÌ§šÒœ…žKP[
+4O5R9\7T 7U <u.H Na’0CŒ!< 2E¶>HÃJSÌPWÑX^ÕSZÖ]bÚY^Ü\bÞ`càacàhlâlnâmpàmpãppäwvãwtäxuä€|ä~{ä€zä€yæzå…ã‚å‚~â~|ÞvoÞrwØpoÐV]ÉDMÔR[ÜchÞjkÞejßjjÞkjÞjmØZ\ÔQXØWXßlo熀ó¿°÷Ô»òζۇÚtqÜwuÛuxÝnrØipØdiÓ\eÑY`ÆX]¤BPfDR<T>X<_?a?u$A{)G~+D~&Be:Z 6^=f?´mxÒ”“Í…ŠÇ}~¨bln$CS:H 8Z<ŸPbÄrkÓyhÏyhÇsoÒ‡zÒŒxÎŒ}Έ}ψzψ|ΆwÌ‚vË‚yÊ‚uÈ‚wÊvÊ‚sÇxÈ€xÅ~yÆuă€Å~zÇ€vÆ‚xÄ~vÃ|tÂ|uÀ|xÀzyºss»sq´kq¼otΈxߢ|ì¶ð»„ò»~ð»‚ð¹zð¸…﹂jïÑðÈ—ðÉžïÈšîÉ›íÈšîÆšìÆ™ëÈšìÇíÊ¢ëÊ¥ëɧìË¥êÊ¦ëÆ§–=N’4K1H7L‹0F‹3H‡*B‡(A‚$?€ ;z ?k7e 6†"@©?JÍZVØj_àzlæŠré‘zê–zë–zꘀë–{ï™zîž|òŸyð—xìyämÞj[ÏZY´FX¢?a§Ol«Pj®HW¦?R©>P°AS¶DX°Tu¼Xt­Pv†6gq&Zf&[ŠC|‹N†Ž\ŒŒM}8ll-cXNh(f~T‘Œen.eXXUTˆb˜€C‡p3qœ¤¢°`ZvPsŽb‘SD`EZBY@g=‚4PN
+9L<WAl-TcFX8R<^FCf—Rh0LV8N8N5X:G8D3®„ŠÐ”’ØšŒ×•ڜघߨ“֠Ц[al:P
+6P
+4T6_5Y=X
+:x.JœL\’.D’#:¨4C¸<DÆKRÊOVÓWVÖY^ØZ_ÚW_Ü[dÞ^hàbfáklâflânrâkpärtävvãuwäuvâtwäz{ä~xã{}ä|æ~å‚|ä€zá~{ßvrÝrtÚmlÑT_ËFP×W`ÞccÝa^Ù^WÔVN×abÚ`]×\bÓP[ØOTÜagävsì˜ï¸¨ô®콬րvÚuuÜuuÜruÜprØmtÓirÒ_aÊ[[»QX‚&FX?V@RAXE`Ff@v@‚/Hv"?&Ab5b;\:Z >¦_pГ”Î’“Ãxz¨dpt$FU<H 9gA¨W`ÊzpÐ|fÍunÈztÓ‹~Ñ|΋|͈}̆vÍ„z̆xË„xÊ€vʆuÌ„zȃzÈ‚xdžyÆ„zÄ„~Æ€yÂvÈ„xÈwÆ€wÃ~wÁ~xÂ|w¾wx¼wv¾tp¸pr´mr¿tqÖ•€äª„î·|ð¼‡ñºð¸~ð¶~ð¶ðº‚ð¾ˆïÃïÄ”ðÆ˜ïÆ™íÈœîÇ îÆœìÉŸìÈŸëÈŸìȤëȤë̪ë˧ë˦êɨëȧ’2J’5L’/G‘0J/HŽ,CŽ-Eˆ*B„"?~!?{?t<n8Ž&A°ENÏ\]Úoià{læŠuéxê’|ë˜{ê˜~ì˜}îš~ðž~óœ~ò˜xìŽpç|dÞnbÐ\_´Jbž<\*L“,Hš3K¤9J«=P°DU¶DV´Mj¸UxŸPwˆ5a„*`v,b‡D}„D|›l”˜V†}6hi(`J
+Ej6l Š¶†Hj)]l/qVVW…N~>Š—v ² Âv3uh5]ž~§ZGXGZDu-Tj"@€4NN 4M;N<Z@g#Od![^M h‚¨w–c;P
+6Q8R<V9M 7E<\DȤ–Ö¡˜Ý¯Û¦›Þ®¤Ú¬œËž”UVb9S4Q1T
+4X5b=Z 8[ ;t+EœK]”5Nœ)>®8D´=HÅJLÊPQÓSTÖRT×WYÚZ\ÛZXÝ^aàfhàdhâfjâlpâlnæwsäqråvxäxuâ{xãyuäz|ä}zä€~ä€{ä‚zä€{â‚€àysàsrÛljÓblÐPYÜ^^ßbXÏWQˆ6t6š%9½>BÄCEÐRRÖTW×VZÞbdèŠ‡î¬¡ï»­à˜‰Ú}zÛvxÜuvÜttÜnrÙhoÕ^hÒ\`ÆZ^¦APe?T?WBT@ZGcFi>}%C…0Dt>(De8f8\ :X
+<œVpÓŒŒÎ’”Ânqµnvz0MS>VB|,J¸dgÌ~oÒ|nÌyjÊvÓŒ|Ò‹|Ήz͇|̇|̈{Ì„yÈwÈ‚xÈ‚{Ì€vÌ€vÉ‚xÈ€zÈ‚xÆ}wÄ{zÃ~z‚|Ç~tÂ|tÂzrÃ{sÂ}t»yx¾yx¼rpµpt²kpÈ}tÜ™~é¯ñ·ñ¼ò»~ð¹~ﻀñ¹ð½…ðÂðÆ•ïǘðÇ—îÅ™ìÆžîÇœìÈžíË ìÊ¡ìʤì̤ì̧ê˧ëÍ©ë˦ìÉ¥êÈ©“0J’0I‘/G-G.F‘.G’1GŠ)B†#>€"?€$>y:{;—/DºNVÒbaÝtlà~tæˆvévé–€ê˜|ì˜zíš~î™yï|ò}ï”{ìqç~hÞn`Ð]d¶FT—.G%A•.E5E¢:J«>M´BM¸DS¶Md§Qy˜?h…1\•6gz0d„Bx†H{±p‰”Iwv1hVHLM\’•m”l&`j2f|@‚Z'\vH}„Q~B’j ªš¶ŒOŒ`%S›„¬\KTDW?y5Nt$Du(Da?L
+7J 8L <T@n-^z1j¬wŒ®dldDV<YB^@R9E
+;F9ˆRi˄ז‹à¯˜ß®Ÿá·©Ú¶¨¨hnV2R
+4T4S 5V7]:c:_;Z
+9w*H¢Wdš9P¤+=°=JºAHÅFLÎMNÎSVÖRUØVXÛZ]Ü[`Ü\`àbdàdhájnápsãopåpoâxvävtåtvâuyäwwä~{ä€|æ€|ä{å€yä€}ã‚€àytâvqÞspÛflÓQZÖWZÜ\ZÉQV¨7P™.K°BT¶CR°7J¯6DÈHKÑRWÛ\\ávt袘謟àŠÞ‰ƒÜuwÜsvÚpuÙknÖinÒcjÒ`bÃVZ…(H\BVCYCTC`C`@mA‚(B‚(Du'A‚)Af8f7d:T;@ZІϔ’µgnºz€€2NQ:o F“;PÂniÐ}oÔykËvgÎvÔ‰|Њ{ΈzË…yÉ„wÊ„|É‚yË‚vÈ‚zÆ€zÊ€xÈ€xÉ„|Ç}È€vÆ€zÈwÃ~vÂ}xÆ{sÃ{tÆ}vÄsÀ{wÁxt¾xw¸ru¸pr¸psÑ„wá¢}í³|ñº‚ð¼ò»}ñ»ïº„ñ¼†ð¿ŽïÆ”ñǘïÇœïÉ›îÇìÈ¢îȤíʤìË¢íͧí̦í̦į̀ìͨíͪìˤëÈ£ìÉ¥/F‘5K’.F“-F’,D“.D‘*BŒ'A†&A†(B„&A‚$>‡#@¡7IÀSZÐhhÜyoá€rç‹uè‘zê•ë˜|ê”zì™ïœ}ðž€òñ˜{ìŽuèkák[Ò[Wµ@Hš.F’&B—2Iž9K¦<M¯BL³DPºJZ¸Mn°X~Ÿ>fŽ=fŠ3c{6g€>pw1g…Cnv1bj'`M Jq@{™w „P„i$`uF||G\ZxJ}‹`™yG|aœ›~¡Ÿv­l,dœ†¢j*YF
+8K 8^>aAYg®e`f>LAH<J>O@†T‘b€jFR :f Hf@j Ha Fl%F‚6Z©^d¿qtЄzØŽ€ß™„ߦŒ½yr)BP
+8W :Z<Y=]<_5c:[:\B|.J£Zh¡:Oœ*=´?JÂCHÌNQÎKPÔTY×UYÙTXÙZ\Û[`Ü]_àbhàbjâiiâmpâpráooãtsâuráooäxxãw{äzxä{xåzwæ€|äƒ|ãyäƒ~á}váusÞvtÝpsÔ]gÓRZÙUZØYZÚ[\Ø[^Ø^dÛ\[ÐPWÃKWÃFQÌR`ÖYhÜ|ˆæ©¢äŸ‘â„Þ„}Û{|ÛtyØnrÙipÓfpÔ^fË`d®FUiBZBYDWEQBbEbBo B…,Dƒ.Hv&B‚,Be5i8h<S=|-Nʈ‰Ò”‘¹px¾~~ˆ@WT?n#E§OZÊwmÑ|iÑ|iÊ{tÏ„zÒŒ|΋|Ίy͇v͆wʃwÌ‚wÍ‚xÌ‚tÈ‚}È‚zÆ…}È„|ÈwÂzÄ€xÈ€xÄzÄ~uÃvÀ|vÅ}rÁytÂytÀyt¼vt¸tt¶mq½tpÖŽwå¥{î·|ñ»ð»€ñºƒñº‚ðº‚ñ¿ŠñÃòÉ—òÇïÉœïÉœîÉ£ìÊ îÉŸîÈží̧ïΨî̧î̦į̂íÌ£îʤíÈ£ëȤìÈ©”,E4G,D”0D+B(AŽ+FŠ*E…!;‚"?†)Cˆ)C/Gª<OÃW^ÒlnÝwqâ‚tçŠvèŽxé’zé’{ê”{ì–zî˜|ïò¡‚òœyëvè}gÞqeÐ^V¶EMš.IŽ&A–0F8J¤:Fª@P±BQºI^º[x¸Sjœ@d2YjNv/_„Bwt1bw4`d"RN Gh,d˜l™†N{l*_y=wu:rq4mj(ltFx‹`•t5w‡^œ^Žª’¼„Hƒ–xš‚K}G9K;hG^>¼ijÜ‹t˜HVX6? 9E @WNŽ^„€@h\LH :€<\‡:\ PižOf¥Yp±q€§NR³[^½\`¶fnÏ­ªÈ°¥f$<P8P 9Z<d.Qj>^e&J`6b6[6^Hw-Jª`m£EY.@²:GÂHPÌJOÎPSÔRXÕVZØV[ÚYUÙ^eÞZ\ß_eÞbgßdjãlnánoâmnátràptâqsávuättä}~âuxå{xå€}å€|å€~ä€|äyâyvàxvàtpÝlnØfjÙ`k×UYÞX[àYZÝ^^Þ``×QXÔQ^ÔfxÕ…—ܨ嫤欞晎⋅܀Ý{{Úuy×nvÕhpÒbkÑcfÄX\ˆ/L\@XCZEVEVE`CdDnFŒ9L„2N|(B€*Df8k9`7V
+>qHŃˆÒ˜¼ls¿{~”G]^Dl$B·`fÑxiÒ{pÓwhÊ{oÒŠzÒ‹zΊzцtφzΆzÌ„{ɃwɃwËvÈ€yË€vÆ‚zÆ‚{ÈzÉ€yÆyÅvÀ||ÁxÂ{¿|sÁys¾{wÀzt¾|x»tq¸po¹nnÂztÚ”{讀ï¸~òºï»}ñº€ñ»‚ð¾‡ñÃñÄ–ñÊ›òÉŸðÈðÈžîÉ íÈŸîÈœîÊ îΣðͦíÍ©íË£íÍ£íÌ îÈ¡ìÉ¥ëÈ¥ìË­‘,FŒ3HŽ.D’,BŽ&>‘0C”.D*E‡#B‚&B†)B+B”5MªBRÅ\aÔopÜ|tà„yä‹vè’zèwê’xê’vë–zîš~ðšzð {ðš{ëvçfÞp`Ò[T¸BJ™1F“'A–1Fž5I¢:I«?M¯?P¸K]ºRfÄQcªRyjNRDj$X?sv4bn']`U\ Vf–„Ho` O`Uu:os2pn4m{G„|Qˆ†V|Bl¢B€œ~§”[”™y¤”i”RCN9fD^B­ZfØŒnÄ|f]:@
+:E 9uJql#Gr&Et*Sz3V”D[¢Ph¬Zr¼€ŽË¡™¶mbªNR¦DU°ZeÅ‹‘äв›[ZN>R?S:^:c@g$DbDf;b:Z9Z<{2K«ao BQž-C³:FÅHNËMQÐPVÒTW×TU×VZÙYXØZbÚXZÝ^dß`dàadâhjäklânoàmmàosâqrãtvärqåz|ãzxæ|{âzzã€zæ€yä‚å}xä}}á~|ÞzxßtvànpÝlqÚajÛ`lÜagÞkmß{xÚtyØoz㊌벩踭赥嫟旑⌇Ü{|ÜyxÙtx×pvÔhnÏejÍ_b²LXdBXDX>ZFVETCdGh Hp$F’?N.E4J€%@n9t$@^:\ >hA¼v}Ó™ºjt¸u}‘CYlE€.IÂllÎ{oÐykÓ|pÌ€pÑŒxЉz·x͈z͈|Ë„zÌw̃wË„yÈ‚zÆ‚{Ê€vÄ€{Â|Æ‚xƃzÅyÈ~vÄ€vÅ€uÁ|vÁ~yÃ~wÀzx¾xt¿vr·sr´rqµpmÈ}rÞ›zë²€òº€ñ¸}ðº„ò»~ñ¼†ñÁòÅ”ðÇ›ñÊœðÈšîÇœîÉ¢îÈŸìÈ›ïÉŸîÊ¡ïÌ¢îˤí̦ì̤íÏ¥ìÊ¥ìÊ£ìʧêˬìÌ®‘.H4KŽ.HŠ.E4K”0F‘0HŽ+A†)Bƒ&E‚$?Œ,F˜;R¬HZÆ^eÕrrß~vá„xæ‹zè{æ‘të“xë–{ì˜zð—~ï~òœ~ñš|îtè‚jápeÔ`Z·DO–1H,F”1IŸ5G¢:K¨<K±AQ´CV»MfÌh€Åqˆy$WUHe&U~=up&Zo,jh#bŠf›^‚f'VSL[Tt2lq1oh1j~K„‡a—„QˆŠZ‰ašr3vŠf‘œn¤™y¢œzžu8kUEgHfD‘D\¼hrªAJmFLC_,S`$LNGw0T›\v¡Um¥\{¯f€À†•Õ¦ŸÄ€žDV¢LZ°\r¼v‚ܼ¬¼•€ZEVG[HZH`AbFg$EhAfBd>\A^Dz1O¨`q¡GZŸ0F°>KÀHQÊLVÎTXÔT[ÖUX×XZÙSVÚYZÛ]bÞ`bÞbhàfiàhlâlmâljàloàpsàlpâosäwuäyzä{zä}|å€僂æ€~ã€}ã€|ã}zá|áyvàvvÞvtÝqtßklÝimßnpâ|zæœäž™à}}ç‹ê´¤é¶ªè³¦ä®¡æšŽà†Ü}|Úuz×ptÕkpÑblÌblÄ^e9SZH[IXBXET@WIaFr&Jo E˜FSz&A…:O{$@o<x(B`<\ <\ >¬ivÔ™¸kr¸u~>S(K˜ATÄrmÒzlÒxeÒwi΄qÒŒxшv͆y̆|̇z̈zË‚wÌ„zÍ„yÌxÈ€uÈzÉwÄ€xÆ€zÅ|ÅxÅ|wÈ}uÆ|xÆ€v¾|yÀ|v¿|uÀzt»xyµpn¶pp¹pnΆvâž|í±~òº~òºð¹~ñº~ð¼ˆðÂòÆ”ðÊ›ñÊñÊœîÊ ðÆ›ïÆšíÉžîÊžðÊžîÌžïͤí̤íÍ¥îÌ¥ì̦î̦ìͪíήîͲŽ3AŒ0Fˆ(@Œ*C.E‘.D‹*F)?†&@~;~=‹)?˜@T²JXÇ`iÓqsÞ{tá„våŠxèxé‘vê”xì”vî˜|ðœ}ðŸ‚ó ðšuêvékßs`Ñ`Z¶FN˜0D*D/H™8N¤>O¨@P­DV¶J`Æe„ÑyµWpz,`]Pj&]~Bzo*d€B‚Ž\’•lj.Z]RTOZSl,`q3hf+ep9pQ‰y?tŠXŠe˜{DŠ}S~œw«‡Y‰œ{¢ŽYŠn-ap*Yƒ5aƒ:]›F]’;\n'Sl(Pj&LG>TL{;d¶t„¶n†½~Í”™Ò¢˜Ò«žžHPDRš9W¼hlÓ¬¢Ë¯—l.EVDZF_!N`"JbHd$Jh%Iq'Hj"HfA`B\Gw0O¢Zl¢M`¤8L´@N¾ITÊPXÎW^ÔV\ÔW_×[^Ø\^Ú]`Û]`Þahágkàglâikâhgâfißlnßkrânrâsväyxäyzãzzãz|ä{zã~z倀ä€{ã~~ázxàyvß{zÝxxßurÞutÝppÞpoâ|wèˆê²¤ç´¨âŽç˜ê´¦è·®è´¦ç±¦ä—Žà…Üv~ÛqwÚsw×jvÔgkÌfl¸U`fBYEWHVGYHXFYFk*Kt&Mt%D˜@Pw&Bƒ1F{"Cp >u#DgD\?ZD VeÒ˜Œ¼w~¾x~‹>UŒ8R­W^ÊvlÒ|jÏuhÌ|nЂtÒŒ|φzΉ~͇zˇzʃvÊ‚yÆ‚{Ê‚zÌ‚vÄvÈ‚xÈ€zÈ‚zÆzÄ{wÄ~yÆ~xÆ€yÄ{ÄxÂ~vÀ~u¾wrÀvq½xs¶rsµnm»qpÒŠwä¤wïµ€ò»}ñ¹|ð¹‚ñ½‚ñÁŒïÆ’òÊ›ñÊœñËšðÈšïȘðÆ—ðǘîÈ›ðÉœïÊ ïÊžîË¢ì̤îΨî̧ìϨį́íαëÍ­îÌ®Š*Bˆ.BŠ&@Š+BŒ(BŽ'@Ž+CŒ*B„!={8=‰(B–8O°N^ÉdlÔrvÝ~tâ†{æŠyè‘|ê’yê”tì“}í•wðš~ð ~òž{ð˜zì‘rèjßq^Ï]W·DL˜3H*B”0Fš2F¤6J¬<P°<R¿ZtÐv‘·Zw P|{/_h&Yo)av2j„H›oœ†Ptl)Ta(UWFYRZNp0en0bm0ck.ft<un/f…V‹€R…}Iq6p“lœ„P„¢„¯˜cŽw4ju2c“KxŒ@m†<`„7Z]>Z@g HMCp*X³ŽÄ‰’Æ„ŒÍ•–С¢Õ°§º€w™=Mž?Pž@XµjnÔ»£v9@U9Y=[>]>b:d<c:h=w(Bn%Bb?`8\?mB¡Yj¢N`¨:N±@IÃIOÈKTÑTVÕSVÖYYØXYÚX[ÚWYÛ]`Ý_^ÞefßegàkkàlnàhmÞfißikãgjállårrävvãvwäxxâxxàvsäzyãyzâ~yà{zÝutÞxwÝwuÜtsÞttÞupßywâ€|皎캯柘ç—츮뻮긨賡㓈߂€Ùx}×ouÚsvØgrÔflÊaf’7NYCZHXHWAXCUBXDq(Ho#I|,F“:N{$?…1G~"Bx >w;d6V 8X <‘AYÌ’‰À‚‡»v|Œ;QžNaµ]^ÐxgÕ{hÒr\Î~qщwÑŠwχx̆yʇyÌ„|˃yÈ‚{È‚xÇ‚zÈ€zÇ‚xÇvÄ€xÃ~yÂ|tÂ|yÂ|tÀ}Â~xÂ~uÂ|xÀv¾|tÀxs¾zv¾xq¹sp¶onÀtnÖwè¦{î¸~ñº€ñ»|ð»€ñ¿‰ñÄðÈšòÊ™òÌŸñÉ™ñÈšðɘïÇ›ðÈ—îÉ›ðËŸîÊœîÊœî̦į̀îάîͨìΨîͪîίîÍ®íͰŠ,Dˆ,CŒ&@*B†)@ˆ(@Ž+@ˆ$>†;€=>‹'B—=Q®N\ÉbjÒptÝ|vá†xæŒvëwé”xê’uë’xì˜|îšyñ ò ð›zì’tæ„làr\Ñ`Y¸FJ˜1EŒ&?*?œ4G£5I¨<R¸PjÊy“·Xr²Ui¥Rtq Rp"Zr,d‚;vŸl“YƒVAZFkBf[Na"X\Np/id(Wv1lh(\w:vp.i|Bn‹a—g*at:|ˆb‘—fœŸ€ª™iŽƒ@vm$O©nˆŒ=Zh Gm@Z;O 6p E‡5VPk¼zÆ€ˆÉˆ‘Ò šØ¸«Ò®˜¤IK§IRœ;P¥P\ɤœ’]TO>U;Z=j>]<a9f6c7i;}-Fo?_;f<Y
+8o ?œQežK^¥GY®<JÀFLÈKQÏPUÔRVØVZÙXZÚ_^Ù\\ÜWZàacádeàccâhmâeeãhlàhkàloáiißlnâljãqqâtrâtuâvvâsuäytáy{ä€zàzvÜurÞstÜxvÚ{zÝwyÞzuá||刄飖îŶêÀ´æ§¢æ™ì»¬ì¿³ê¶¦ç­Ÿã•‹Þƒ‚ÖrwØrx×pvÔioÐhn¸ZdiCWBYD\EZC]CU@_Fu)Gp%I…/F’7J&A‚/E|=}'@o7f8Y 6V >ˆ=Zʇ~½}ƒ¹mtŽ>T¨Vf½c^ÔveÔ{gÔvaÏ~lЉxцwΆv̈zʇ|È„~É‚xÊuÇxÉ€vÆzÄ~zÇ€wŃyÄ|ÄxÂztÂ|vÂvÁxtÃ~wÂ}x¿}zÁ~v¾zpÀxq½wl¹rq¶lnÂsmØ’vè­xð¸zòºòº~ò¼„òÂŒñÈ–ðÌžòËœòÊ›ñÉ›ðÇ—ðÉðÉœðÊžîÉðËžîÈžíÊ í˦ìÍ­íΪìͨí̪îΪí̪ì̱îΰ‰+B‡(Bˆ(@‡(Bˆ%?†!<‰%<…&@‚"@}"A€$?Œ.F’4J«JYÃ]hÏpqÛ|và‚xæ‹séŽxç“wê•vì–tìš}ì˜~ïœyñžzòœzísè…kàtdÒ\T»CH™.FŒ%>”.Dš4J£0MªB^ÀmŒ¶\v°JbÀap¢NznUr"Z…>y“Uˆ—l”x;kTGbRd,Wp5li+_c(Wm.f]L}Brn,[h.bo.kq/d‹^c#`n3q‰]Žœl›b”bœdšŠFeÊŠt8aFV 7p#Dz+T<ZžMb¡I`¬dxƒŒÌ˜Ó¬¤Ö¹©°b^DQš:O BW¼ˆŒ®lVAR<`>e?n?fC`:l;c8n @~,Cz(Ed<c:\<j>˜L_HZ¦Qe¢1E¹GTÆJPÎPVÕTZÙV[Ú[`ÜYYÚ\aÜZ^à^`ßehàagâfjällãdhàfiàkkácdàjhâhjâikáppâssàstáqqârqàtqâ|xàrpÝxvÝrvÝvuÛxxÛ~}Þ~yâ‚~䎈馜ðǺìÂ´æ§æ”쯥íÀ¶ê¸¬ç®›ä”ŒÛz|×ntØqvÔkwÑktÊek›?XYDYBXCZDXAZAYEbFs&Lj$IŠ4IŽ4J€*E‚/Fr8y%Bq=e=Z9S ?ˆ@]Æ€zÄˆŠ´js’=VµcjÉj_ÓueÓwbÏznÎwΉxÌ„xΊ|ʇ|Ì‚yʇ|Ì…x̆uÉxÉ€vÉ„~Æ~xÆ€|ÄzÅ€zÄ}xÂ~yÆ}vÂ~yÃ}vÁ€wÂ~yÄ}vÂxnÂzp»tp³pr´ml´moÃwmÚ—xë®vñ¹‚ò»}ò»ñ¿‰òÆ‘òÈ”ñÌœóÊ—òÊ™òÉ™ñÈ›ðÊœðÊ¡ðÊžîÈœðÊíÉœìÊ£ì̪ìЭíÏ­ïͬį̂îͪíίìÍ­îα†*D„&C…&A…$B†$@‡%?„%?%A€>z <ƒ&>Œ+E‘7L¥G\À\jÎmtÙ|yàƒyæŠzèvé“{ë“uê—}í™zîœ}ìž„ñ }òžyî“pé„làtcÕ^S¸GI”,A#>’-D™1M¥;V¼g½h«H^¸FV¿dr›Hvk V5o„<p‡N€‹\†j'X^M`Qa#Vp2ff(\l2jh+^h.bt8fx7gd*Zh-bj.b}Ju{C|[V`$^Œ\Œžx«Ž[›t°x‘²\\R0U@X ?|1O®at¦`zœLf Pe¶p~ÈŽ˜ÎœœÖ»¬¾„tœDQœ:LŸ@WµkoÄ ŠX8N:R;o#@€*GdAb=]8n9f>n<{-F~,Fp?c:\ 7h:›O`›DS¤Lbž0Dµ<FÄJRÏJNÔVYÙTWØX[ÚZXÛ[_Û]`ß`_àdeàdháhlâlkãgfãiiàehàdeàfhàflßjnàioàkiÞosàppÞqrÞmnÞtsÞnlÜprÝqrÜrsÛttÞzzÞ||á‚€æŽé¨›íÁ±ìÇÁ毳騫îĽîÀ®ì¸¨è°£ä–“ÙtyÖjqÖjuÒjvÓkqÂ`jlEU@Y>XDb&JYFXDXAe"En$Gx)H…1IŠ2L€%?.Fs >v"?v!<b9Y 9U
+>~7U¾wzËŠŒ·kn—E_¶`gËmaÑsbÑwdÌ}qΆrΊyΆvІu͈xΈzÌ‚v̆xÉ€yÇsÆwÇwÀ{Æ~zÅ‚}Å~zÆ~yÈ€xÅ}xÄ}xÁ~|À}xÂ|yÄ|uÄ{pÀxtºup»rm²or³ljÆzpÞ˜vê°xñº€óº‚ô½‰òÄ‘óÈ”óËšòËšóËšñÉšðʘñʘðËžðËžðÊœîɘîÈšìÊžíΧíΩíЭíΫîÏ­íΫîήîέîϯîΰƒ,B| @{ >€ <#?‚)D…'B$D‚!B~ >„#Aˆ&@‘5M¦DWÂ]lÏntÚ~z߃xåŒ{è‘xè”yê–|ì—|îšî{î¡~ñ¢|ðœ{ì–vè‚iàs`Ó^VºJO”*DŽ%B’(G™/O´ZsÀn†¥CZ²ASºHV¹]t”>mp&Yr*_]H‰YŠ„Hy_Lc"T_Nn5fc&X_&Xn9rh,b{Fxw:p~@st5kh.do6kp7m|Ftz@~YWh,d”l’”c—–r¢„¤p0[@@IB}0V¶`rËsË–£¿•ª¸–È•£Û³¤Ø¸¨Ë‹œ>H¥JU CW²^gƤŸx?KPDO@R?„3F•:Pd@a@Z8l>e=l=x(E‡8Nr"@b6`<h:”G]™>P¢L^œ5J²8FÁEPÌJPÕOSÖVZÚY\ÜZZÚ][Ü[[ß\_ÞggâcaÞfjáffáhjáheÞekÞcdÞehàihÞlnÝlhÝefÜjlÜnlÞhjÚglÜonÛroÚprÝkrÝoqÜzzàxá…zä‚zæƒtå„tê“虇쳘뛎苋ꈈæšâ’ÒfnÏ_lÑdsÔlsÐjq¡DYZHVAV>[Ea&LXBZA_BbAu)Hz)H†4KŠ8P~&Bˆ0F€-Fx">€(>e7T
+5X>n)L»w|Г’²dj£Pc¼ieÎqaÔu_Òx`Ëzh΄sÏŠwЈv͈{̇zÌ…yÊ‚wÌ„zÊ„{Æ‚yÇ}xÆ€wƃzÈ…wÄ€}Ä€wÆ€xÄ€zÂysÆ}vÂ}xÅ}yÃ|uÂzsÃypÀwr¼wq»tr´nk³kpÈ{lÞœxì­|ðºò¾óŠòÅ’òÊœòΞòËœóÌ™òÉšñɘñËžðË ðÌ ðËžíÊ¡ïÊŸí˦ìͦîͬíÒ°îЭïϯíάïͪîϬîΪîά€(Ex?x>{:~"@‚#=‚&C‚$A‚$B~=„ ?‹,C’2I¦FWÃ`lÐpqÚ~{à‰xä‹zè’}ê•{ê–}ì•~ë˜zî›~ð¢ð €ñ{ì”wé…hàueÕZRºCK•-E‰&H‘*L¥B\Âs‰¨Ic§:M¯>S¸J]¼l„?ifO[L_#W‰Z„“a’d"Mb$T^ Qf*[f$XZSd+cg(dq;k‰T’€Au†J~z>wu<rp4li*aˆZ‡w;q]Sh0c|B~d™˜s›‘h—TTMA§Td¥Bd¬^~И¦â¾´ß¾¾ç°⼩Ҥ’ FI¦JRœ8P«OXÈ“¢qfO 9Q=S:V;„+B˜AJ^:b:Y6n<m:p>-D|,Fx"?`@b :l<–J^8IœIU•/D©3B¼?KÉKQÓTTØT[ÛZXÝ\ZÚ^[ÛYVÞ^\à^^Þ`_àbdáeeâjmàjnàfeàfgßffâjiÝccÚ`^Ú\ZÚ[ZÚ_\ÚdfÚgcÙopÚifÚomÜkgÜolÞjbßhfÞefÜ`aÜ^eÜ[bãjpâhpävxæz}ãoxãeuãhrÞtuÐjh¿L[Æ[fÒkvÒotÆenrCYFWCXA^D\D^D]FcBdDy-Jo(F‚0J‰6J„,B‰4L'Bv>}(Bg9T 5Y <hFºv̬Za®ZhÆkbÒudÖzfÔvcÍznφ{ΊyφyΉyˇzË„wÊvÈxÈzÄ}vÈ€tÄ|yÄ€xÇ„xÃ~|ÄyÄ‚z€xÀ}|Â}z¾~~¿||ÃzqÄzrÂxq¾wt¼to¹rq´lm²hkÊ~qßšzí±€ðº‚ñÁŠóÅ‘ñÈ™òÌŸòÌŸñËœñÊœñÈšðÊšóËðÊ ñÌ¡ðÌ îÊ¢ï̦îÍ£ìÏ«îΫíЬîЭîЮíЯîάîЭíÏ­ïÏ«s?r>v=t<v<z=&A‚$A~ :}<‚ <Š*A’4H¢DVÁ_jÓqsÚ€yß‹|åzꔀê˜}門뜀ïš}ðž~ð €ñž€ðž~ì’qèƒjàraÔ[Q¶DK)F‰!E›6X¹i„±Xq 6Oª8O±H^ÂbzÃsЉ4a^L[Ir4lb!M|Gsl)[b&Xa&Vj-]f*[^!TTT`!^s@v’k£‚E|‹Qƒ†Ny?rp4kh+hl1d‹\Žz;|j5m~PŒL€Žg †N‚‹V—_˜Öˆ¬k–¡hÌ¢ªÞ¶´êɾèűִ¤©ST©LT¤CR¢DY»{}Ħ˜Z<P?R;\=V<l8ˆ4F_;]9a:f;j<v%Ax%C|(A…+E^6^:g:šRd3H˜D[’,C¡1Fº<HÆGLÏNPÖRYÚ\\Û^_ÚXVÚXYÝYXÝ[Yß`]ß^_àcbâhlâloâliájiâldßrgØ[T·9@®6>ÀGHÊSMÑYSÕ]Z×`YÕ\YÔ[VÕWXÕQQÒOOÓPOÑPMÐKMÐLNÎHRÝRVßWXßf`ÙbaÀ>D´3@ÆDMÂNSµ>L¸FUÍadÙrtÏov¦J\]CVDXA[@dDXB\BZ>fAf@‚3JlBˆ2Fƒ,D€*@8K{%>k8z&@p=U 5\ 8cD°hvÍŒ¬Yj¹jsËodÔzg×xaÔ|iÊvnφxΈvΉv̈zÊ‚uÌ„zË…xÇ‚xÈ‚vǃzÇ€wÃ~zƃv€{Ä‚|€yÆ‚vÂzÄ{¾}wÀ~yÀ|uÃ|rÄ{rÃ|uÀzu½usµrq±kn´hhÍ‚uá tï°|ò½…ôÅŽóÈ•òÌŸò΢òËŸñÌ òÌðÌ¢ðÌžñÊ›ðÈšðÌ ðÊžïË¡îͤïͨíЬîЪìЮîѰîЯîÏ­îÏ®îϯîЭîÒ­pAp>s>vAv"?}#A‚&@€=}>=†%AŽ.F”:S¨K\ÂblÒvwÛ~|à†yåŽxê˜~ëš|ëœ}íœ~ðž~ï {îŸðœuì“vè„mào_ÑZR´DM”-K&O¹m‹½g~¡:T£0Lª:TÃe~ÑyŠ¿l‚ƒ0`bQo)\|<iVE\HbPg*Zb(Xl1cm-`d&[YZ]^wJ—{¦‘a“ŠTŒ‚J€ŒVŒ}@xs=va'`o6j^‘gšNƒf)^xM{n3jy0]µj‚³pˆ¯^uÉŠŠÜ²ºÞ»½ê˼ÞÁ®´xxœ=L«KT¢AX³clе¨…JPP =ZB^@cAT8c<.>kA] 5d9b8h:r @q ?|+Dˆ3Jc 3Z 6f8”H\ƒ(F•ER‘3H–*@´<FÂFMÌRRÓQRÔ][Ù_[ÙZWØ[[ÚXTÚ\^Ý^_âd`àgeãfhájiâlläojânhßneÑTR±:N®;K¨.>¥*=®0<³6>¼:@Á:BÄ@HÉHLÂ>F»;D·8C¬4A°/=¸4BÄ?HÕGO×LRÖRXÈER·?T²6TºDXÇWfÆQ^É\bÖlpÖuxÇinv$FW@UDY>`BeCZ>Z@bBfAt*Gz*Jm CŠ8L€*B‚0E‹6Hz">e 5€0Az)D[8]@^D£ZlÊŒ´htÄvzÐoaÔ|hØxbÖ|jÌ}qЊẏyÍ’€Ì†vÊ…wË…uʆwÊ„wʃvȃ{ÇxÄ€{Å€u‚|¿{À}xÄ~yÃwÃ~zÀ}w¾{xÃ|sÀ~yÃ|uÅ{s¼xu¸tpµnm®jl¸khÒ„qã¦xï³|ò¾ŠôÆôËœñΤóÍ òÍ ñÌœñÌžòËœðÊ›ñÉ›ïÊœðË¡ïÌ îÌ¢ð̦ïͧíάíάíÏ­îÒ¯îÓ­íЮïЮïѰïЮïάl@l?p>q?v?|>€&A~!A~=€ B„$@8O•:U¯L]Ä`jÑvvÜ~uâˆxåyì˜~ë™zì›~îœ{ññ¢zð¢|ïœ{ìqæ‚lÞnbÏ[Z³BU˜/T°\€Är†£BW.J£2L²LhÎrŒÈm„¯_z~,\bKu2ch#O[HR?d&Rh-Zc,Wl5ff$Yj0bh*j^ bwH€˜v¦–k„L…€H…†K‡‡O„ŒT€Dv;y…L}Ÿ|ž„I~e'\j3n]"\ƒ>n·h{ÎmkÚb`Þbfä¼¶ìØÑæÌ¾Ó¬›¢LR¦ESœ8Q´\hΩŸª~oSAXA`<b<^9T;`6s$>s >]=b<j<k=o ?n@v(Cƒ5Jj=a=d<’G\„*E‘=O6K“.C°6D¼@IÊNSÒRRÔUSÕ\Y×VTÙUUØXVÙ\]Ü]bàbeÞdbàadàejáspâppâqmànhÙ\^ÔV]ÖW^ÏR[ÈFVÅ>LÄ<LÊ@OÐDOÒLWÕN\ÔNXÐO]ÐP^ÌK_ÊN\ÌObÒLbÚUmß`vÚe|ÞjƒÚb}ÕVrÒ]nÔjqÒfhÙilÜrqÔnn¤DRZDVBRC\@aB^DU@W@f?gA|.HpBr?Œ6Jƒ0I‚+DŒ8Hz"Ah;{.F€1K[9\<\BšLaЈ„¹muÍ~|Ôq_Õ~rØxaÑ~mÍ}rщxЉxЈw·xÊ„wË…yÊ„zÈ…|ʃxÈ‚yȆ{€zÄ€v‚Â~yÁzÁƒ~‚|ÁyÀ{¾|xÄ}tÂ~vÂ}xÁ|u¼vs¸uq´on°kn¹nlÕ‹pæ§~ñ¸‚ôÄŽôʘôÍžòΡòΠñÌ ñÍŸòÌžñÊðÌ ðÊœðÌ ñÍ£ðΤîÍ¡ðΦî̦îÏ©ïÏ®îЬïÑ«ðÒ°îЫðϬðЬïϬðάh@kAp?q>v>y?} =|>|=z"B†,EŽ>U•AZ­QeÂeoÓsrÞ}sâˆxævé™zê›~í›}ìœ}îž{ð¢|ð£ð¡ïšzêqælÝqgÍVb³C`µgˆÇ|Œ¦B\“,Eš.L¨<X¿bÈqжYv§Rp‚7bj(Wj&Rs/^^K^MXA]NVJn7ig%]d(Ws8xY^uQ„¦–¼˜g™n0jzE€Lˆ~KŠ…P‚‰P‚‚Gw‚Hxn2a{Do~D~l:vL„¥`ŽÜ}{ån[Ýa_ÓVaÛŽƒïÚËÛ¼«´pq GT¨FX²WeГŒÉ¦’`$FQE^DdAd@Z>U=`:p"Br <^9a;j?r"Ao!BpBr"@€2Hm?^@e>‹CYz)FŠ6JŠ6L’1H§7I¶@JÇMQÏOOÎSUÔYUÕTRÖTWÖXXÖZ\ØZZÞ_aÜabÞffÞghßpoàsnàqnáonánnÞfdÞZZÚVWÛVXßU[ÞRbàNWáKVäSZäZiã_pæZpèm…åw”æ{šå„œè„¡ë“¬ì µë¤±ìž«èwÞ_{ÚbvÒrsÚtvÜnnÖpoÂ__mAV?XCVBb@fB[AXAZAgAh Dy%CjBw&C‹:L-E†.G5K}(Gh>z*@„6O_=_<\B’B[ÊŒŠÀw|Ð}yÕs`×qØwdÒnÌ€rÑ‹tʉyˈwÌ„wʃwʆ{ʇzÉ„wɆzʃxÌ„{ÅxÀwÃyÁ~vÂ~vÀ€x€vÀwÀ|xÁzÄ~vÁzyÂ~vÂzv¾vr¹vu³no°gi»mf׋vçª~ò¼‰óÅ’ôΞóΞñУòΠòÌŸðÌ ñÍ ðΡðÍ ðËžïΠíÍ£ïΧîÏ©îЪîÑ©íЮðЭîѯîЬïϬíΪîΪðΩïϨñͤj>iBp@r@u@z!A#B"@z={?‰*F8L™@V«K\ÁalÐsqÞ}vá…væ‹tê˜~ëšzìzìž{î î¡yð¤î¢}îœvèzäƒzÚpwÉWrÂh‡Æ|Œ¢EZŽ)D—,Eš0N®KhÊuµVtµOh¦JlŠ9fm)\f"P‰S‰k(U_ LN>XKSHvBzp*^b!S~J‡V\xX‡®œ¼“e’d+cd(d{I€†W’Š]•D€z<p|Cq[%_i-\VŒ‚PŒ’fž¥h•Õy‰äocÚb\ËP`ÎyâÌ„x¤FQ¬NVÁgiÚš€Ö®˜„FPSGZM]EbAb@Z<X;\8g:n6k=^8c<p >k:t!Bt">~+Ht@]<g?„:O|$A8Kˆ6I‡&@˜.A¬:HÀIMÉLPÌKRÐTVÐPRÔRVÓWZÔXYÖZ`ÚY[Ü\`Ü`aÜglánláppánnänlåtláhhÞ``Û\_ÙVUÜWZÞTWàVZàLWâNZæP\åZmçetêy„錎휘뚘ðŸ˜ï©¦ï°«í žænÜ`wÕhwÕvyÜxwØllÈjl5JX@WAT@ZDd>g?X<V:_;j=l=f<j@~-D‘@Sƒ(@‹0DŽ/Lv=o:~)A‰<Ob>`<]D>\ˌƆÐ|uÔxb×r×xdÑ€r̃sÌŠzÌŠz̉{ΊwÆ…yɉ|Ê…xÌ„wÌ…vʆ{È„xƃxÅ„wÃzăwÄ€vƒxÂyÄ~x½}zÂzÄvÁ|vÂ~v½zwºzv¶qn²oq­fn¾ojØŽtë®|ôÀõËšõΞôУñÎòΞòΠðÌœòΞñÍ¡ðΤðÍ¥ïΧðϧðÎ¥ïÏ­ñШîЬïѬðЫîШîÏ©ïϦîΤðͤðͤðÍŸñÊœhCkAl>r<s>y>z<| =w<w>‡/J“:Oš@U¬HXÁ^hÒrpÞ}t߇xäŒwé“{êšzì}ì }ì{ï¡zî¢ðŸ}î˜|é€â”Í|¡ÁlÃpˆ B[Š$B‹$B‘+Kœ:[¹`ÄxެIf±Ib–Dkw,V|2ks2`šzžp*WT<S@UI^%X‚N‡m+^f!YwFzf"ff”¬š¼•f–n1p] Zv=vt=w|Mfž„P‰z?wn6hg-b€@rJ‚žx¬ªp˜É|˜âkiÔU`ÊhsÔ¯²Ï°¦˜?P°W`Æjfä˜{Ø•~]TVCXJXB_DbDcB_<Z<^7^:k<k<_=`:j>p@r At#B},Dx(D`<c={+Cz"@Ž8Nˆ6L"?3J®<H»BKÄHKÉMPÎQUÊPVÎPRÐVXÐTYÖTYØYXØ\bÙY\ÚadÚlhàjjâmiätpäplánfßhfÝbdØY[×W\ØRUÚVZßU^âYaæR\çP\ê\nìjxên|îu‚í|…ìxƒîn€ípì{ŒçxŠÜ`vØk{ÖrvÜxyÜttÒnp¹W\d>U=V<V@Y>h?d<Y;W8`8g8w(Ba:h=€,A–BV„,F‘8JŠ5Jz$Bw$Bx$@‹@Rg:_>\FŠ>^É‹ŠÉ„‡ÏzwØ~hÖ†yØzaÑ€rËrÍŠvÌ‹w΋xÌŠxÊŠzÌŒzʈyȇzÊ…xÈ„wȆxɈyÄ‚wÄ{ăzÆ…yÄ€xÂ|wÀ~tÁ~yÂzÂ|wÁzwÂ~v¾ztºvt¹rn²kl­hk½mlÛ’x첄õÄõÌšöÒ¤ôПòУòΜóΠñË¢òΠò΢ñ΢ñШðЦðϨñϦðЦñѬðѨðШðϦïϤïËŸðËžîÍ¡ïÉšðÉ™îɘñÈ—m Dg?l>n>v:x9v9v:s:w<†,G“8L™?S¨DTÁ\cÒppÜ~vã†væxè•yé™}ì }íž}í |î¢}î¢|욈瑊匉à”Înx°NW'D…>Ž$F”/Q¬RtɘµRl­C`°OiŒ=dfOl&Z„U~”fŠf KZFZHRJd/`L…g"WA‚l8mt6u˜ƒ²¡„¬]Œ‘bž` \q9nzF…_%_xNw•j¥‡TŠŠSŠ~LŠŠZ–†Pˆ§‚°Ä„¢¼w–×t…ÉJ]Õå˸´pw®SaÐtkå‘r躓¬ihZHYKZG[F`Ed!Fg CbBZ>^<aBe@f>f@b@f>t)BlAn"By*Fw(Ec>cC}6Q„.JŒ9Kƒ0Hz!=‡*D 6I³BL»HRÂKOÇLPÉMMÊMRÐQTÏTVÓZZÖXYÔ_dØZaØ_fÛfgÞhiÞjhàloâpmâmlàieÜcbÛ`fÛ^[ØWVÖTWÕVZÚXZàYZâVYäT`è^pébxêbyëk‚êiìdzébzçcxâ`vØfzÔt|ÛvtÙ|xÒlnÈfhŽ4KXBXBVCSAZCdA^@`>]>h>f8r"Ad<k<‰.B’9T~&DŒ8M‰1J(C}'Ds>ŽDWe<b=^F‡>_ʈŠÎ‰‡Õ~tØ~n؆x×{fÍ‚tˆỷzÊŠw͉xˈxÈ…xȆxʉ{Ɇy̆wÊ…xɇxÆ„zĆxÄzÄ‚wĆ{Äz€xÀ}yÂ{¾|½~y¿~{Á|tÂ}uºvt²rr°nn¬dn¼njÜ’w÷Ê”öРöÒ£öѤóРóÏŸóΠñÍ òΠòШòÑ©òШïÒ¬ñЩñÑ©ðÒ¯ñÓ¬ñѨðΡðÌžîÌŸîÊ›îÈ™îÈ”ïÇ”ðÆ’îÆ–ðÇ”e>d:j:m9l:s<v:q:r=x;‹/F˜8K˜EZ¥@PÁZ`ÒnlÜypàƒrä‰sè’{ì~ë |îžî¡|ð¡{ï }ð¤€í›‚葃â‚|ÚtqËY[¬@J(@ˆ"E(M;\Âz“¿g¥Da°H^®Xx„:`cR`O•t˜’]€X?XDZMSOwF|xDwXPv:qv8xv<r§šÆ–hš{D}”zªEˆ|D€‹c–n3ne+duFo˜n¨ŒN‚’x­™pš‘T˜eŽÎªÁ€Çp“ÄJaÍ~ƒÖ¼»»iqÏwvärí¸—À{fn,NVL]"LXI[G^Gg"IdDb*L\D_FbEcH_Be!DhDe!Dj Du&En#Cw,Fz+Hh Ed>v-H‚0L3F2Hy"@…,D˜-A¬;H¸BJ»DLÂDIÇLOÈOTÊRYÌTUÏX\ÓXXÖabÖadÚbdÜddÜfkÚfjÞhlàijâkfàmjÜddÜbdÜ^_Ú_`ØYZÖ[`ÔXYØQTØQWÜQZáXZáZcá]hådvä]gã\jáWfÜVbØdsØuvÙxwÛsrÖttÌjj¦DMx#DT<XCVBX?_Cb?`Ah@`Bh=j@p"@e=m:ˆ4F‹8M'FŒ8H‡/E…0Gy >x:’FVi;d@`G‚;_Ȇ„ÏŽ‰Ð}m×€p؆tÔjÍ„sʉvËŠvÈ‹z̈u͉xȇzɆzˉ|Ë‹ÿwÈ…yÇ…zÇ„wÅ„xÄ…{ÃxÀƒzÄ‚v¿z½€x¾~x¼~yº|x¼yw¼vs¾zrµtt²qm°lm¨co¾liÝ•{îºõÊ”õÒ¦öÓ¨öÒ¢òÑ¢óΞòФòÏ¡òТñϦñÒ¬ôÓ«ñÓ®ñÒªòÒ¨ðѧñТðΠðÊ™ïȘîÈ–ïÆ”îÆ—ìÅ–îÇ—íÈ–îÆ–îÆšf&Lc<f<g<j:r=p;n;o>w;Ž3FžAM˜8L£=NÀV]ÒjfÚvoÞtä‡uè•xëœ}í¢~ìŸ}îŸð}ï¢|ð¡~ïœé’|ä€oÜqfÍ[T®@K’)D"H†$N©TnÄ€—¥Fi¨C\°Lb Nil"NcUo&Y~™‹TyQ =^HSHRKP‚j1^XP\!Vx=‚~F±¯Îœv§o1n|R„–q¨ˆVŽ’lœw=tg,bb$czP€–€³“r£ŒMv§oŽ|?k­xœ²_~¶z¥ÁUoŜ޽܂pì—xì¥Ø¦{v*KXNXJ\H\ L` LdDhAj!Ca@Z?`Bg!B`?_@`Bq!Cp$DhBt(Bn"@t(Bx&Ek?a@o$C3P|,C‡6Ls >|(DŒ'@¡1A°<F¸GO¾DN¾BFÂKSÇLQÉRVÍQXÏTXÕ[\Ø\]Ø\`ÚdfÚaeÚflÝfkÞjoßkmßgiÞimÜdfÜ`eÛ`_Û\\Ü^aÖZWÕXZÎTXÐQTÑMSÒNRÓQTÒOZÑLTÐP\ÒT`ÔhsÝ~Úz|ÜptÚrqÏqm¶MP…)AiBVBT>R<W>^?]>hBeDn"Cc<i;h;j;n<”DS‹2JŠ0H‹5H‡3D….Cw=x"@<Jq:d?`F€8[ÉÒŽÑ{lÙrØ‚vÒ}mʃwʉxÊŠxȈuȈẅzɆ|ʈ}ʇ|ɆẍzɇzɆzÌŠxɈzÄ…yÁƒ}À…|ƒyÀ„zÂxÁy¼}z½}v¼{xº|y¼xqµvt±on«ik§agºjiÙ–xöÍöÔ¨öÔ«öÒ¤ôУòУòТñТòЦòÒ¨òÔ¯ôÔ­ñÔ®òÓ«òЦðͤñÌœíɘîÈ–îÈ•íÈ—îÇ–îÈœíÉšîÈžîÊŸïË¡ðÊž`?b>f>k@h;h8j8f6k;z"@”<OžBPš>O¦>N¾V^ÐhbÚrnÜ|râƒté’|ëœìž{ì {ðž{ð¡{ñ¢~ð¤{ðš{èwå„pàqdÍ[Y±BL*E‚DŒ'P®Xrºu’ @^ªF`£Rj{7]\L^Ty2ct”€=bXAXFOJ\'X€I~g&X\TNPa&df²¨Èž€ª‚Gˆg5n™‚´b›‘nŸG‚q<zr6w~Z™mœ™x¥–cš–Ms}7j˜f”–Mx©d¾QgÔ©ªÛ­¬Úzræ›å®~ƒ8GVFVG[J\F[C^BeCj Al BdAW?]<k@]@bAa!GfCm BqBj@l @o?s#@l?dAjB|-Kv$C†:Rt#Cv#B‹,Ež,@¤6D±<Eº@F¹CH¾GL¿ELÈNSÌOTÐUXÔXZÖ\^Ø\_Ø_fØaiÚhmÝfjÜjlÝllÜhlÚgnÙbhÛdiÚ`dÙ^dÙ`dØ\cØbf×dgÖ^cÏ[bÌW`ÎZfÑ^jÔbgØirÛu|ß{zÝ|}Úp{ØhrÖpnÄlm€ >…*Cc@V>UBT?Z>aBcDdCl+Im$Cd @e>j>i>k>•GW3K‹.IŒ8HŽ<P€)Ex<z%BŽ<Ls=o"EgHz4WăˆÕ—ŽÓ}nÚ…zÕ€pÎ{n̆vʈxÌŠ{ËŒyȇ|ÌŒ|ɇzˉ~ˈ{Ȉ̈~ʈ{ÊŠ~ÌŠ{È‹LJ~ņzÀ†€Âƒ{À‚{¾z¾€w»~x½~wº{x»zv¼ztµro°onªhj£_e³hhÜ•vð¾÷ÏžõÖ«öÔ¨öÒ¤óТóÒ£óÑ¢òÑ£óѨòÓ¬òÓ¬ôÓ­óÓªóЧñΤïÌ›ðÊœíÉ–îɘïÊ›îËœïËžðÌ îË¡ðË¢ðÍ£ðÍ£òË¥bD`=f>h>f=i<h9f<j:„,FŸL\§GR¢FR­J\ÂX[ÐedÖqjÜznâ…tè’vêš|ìœ{î~ížzð|ð €ð¢‚îš~ê’xæ„pàtbÒ_X´CL)D‚EŒ#N®Xt¶p”¤<Z¥Bc:`y2Zi(WcUt4]b†h L\HUFGC`-\y@p^Kf)\WUR[˜¬«—½–{«™p¢t<„f“š{°–p ‰TŽ‚SŒlžLtBvl Ÿj–Dlh-b–mœ˜e˜—`–§V„Ö ¢Û¸½î¦ñ¿¡QTVIWJXEZF[BZD^Ah!FgAl Be BZB_Ah"EbDgD^DbDf"Fk BlDl Bp!@t"Br'Ch@d=x%CpB€3Jt'Cl?‚,B“+Až5C¥6D®<G¸CI»EN¾IOÆJTËRWÏU]Õ[cÕY^Ö\aØajÙ`cÚdjÛikÛflÛfkÞfnÚfiÙgiÚcjÚejÙglÙbjÙefÞmnÞqpÞrpßtyÝx|ßx|ãvxâw{ãzyá|Û|Þx|ÙhvÙqsÑol«JUc8€,E^DXAR>UBX@`B`BhBg Bj#D`?f;d8g=j<˜DTŽ4J1HŽ7FŒ7L‚)Az"<{">Ž:Fw%Dk8fGt,N„†Ô“ŠÖ~oØŠyÔ|oÌ|nË‹yÉ…xÍŠxÊ‹|ʉwʈ|ƇzȆzÉŠzɈ{ʈÊ„ż|ȇ}Ƈ|Ć|ÁƒÁ…zÁ‚|À‚|½€|¼x¼~{¹|v¸}zºzv¸xw´sq®kl¨gj¥bi²gjÛ—vðÀŽöÒ¡õÖªöÖªöÖ¥ôÒ£ôÑ£óѤòÔªôÔ¬òÒªôÓ¨ôÒ©ñФñÏ¢ðÌ ðËžîËœîÌ¡ðÌ¡ñÌ ïËžðÍ¡ðË¢ðͦðÍ£òΣòÌ£òÌ¡bBb@d<e<c;e:d6a:i<Ž5F©ITªLU¨FR²JWÅ[`ÎhfÖpkÝvkã‚tévë˜}ìœyìœ~ìž|î~ïž‚ð ~îš}èzå‡rÞtcÐ`Z¹CH’+G… DŠ$K¤Ff´hŽ«HgHmŒCf5\l&U~8gu3X}Ck^H\EPHLEh4ay=nWKi*[] ZY!_Žlª“¶‘q§ƒO‚—m¢|M€¡’½–q¢ˆWŠaŠ[Šh1guFƒ‡b”¨n–§Dbo&WŽbQw¡g”·e~྾ïÊ¿ö¾“Ât_m#HSETEYF\I\B\A]@hBlChBg@U>\@h Da=c@c@\@aChAm"Cl@p @t#Aq$@h<`<n <r?t$Ax+DhAv$@ˆ&@Ž%;¢4C§6D²AH¹DL¿FLÄIPÈKTÍU[ÕZ[ØVWÕ]aØbf×cfØikÚdkÚfjÛgmÜimÚimÚjpÞjmÜhpÜpqÜnrÜpsàvwà{}â€ç…‡çŒ†æˆ„æzå|å~{à‚ß|zÜu}ØrwØspÈnhy=a<„.FXCR=UAZBXB^B^Bm'Fh@o&G`<k>a9d@n>›LX5Jˆ-DŒ7JŽ7EŠ/C€(A„.D6F|'Bf<pLp"JăƒØš‹×†sØŽ~ÐxfÉqÌŠxËŠvÊŒzÊŒzÉŽyËŠ|Ĉ~Ć€ÆŠ€Ä†ȇ{Å„zǃzƇ}〯ˆ|¿„{Á…Á‚zÀ…€¾€y¾|»z¹||·|z¶xxµwt°qr¨jp¦inŸbl¬djÛ~ñÑöТõÖ¬õתöרôÔ¥ôÓ¤ôÒ¦óÓªôѤòÐ¥óСôУñЧñΤðÍ¡ïÌ£ð΢ðϦðÏ¥ò΢ñÌ¡òÍŸòÌ ðÌžòË òËœòÊœóÉb<^>^=d>c@c>a>b@rC˜;KªFP§HT©FS´JSÅ^eÑdbÖqhÛwjä„pê’xë˜|ì›îì›zîœ|ðž}ðž‚î—{ìwåqàsbÒ^V¸DO˜1Jˆ"Dˆ&L”;Z¨\€¬Qt¡Nl†3`v.\s-]ŒKt€>ev8b`JVELDNHr:fx;lQH`Pf"^Z[}W€œy£‚ZŽ€TŽŠ_–‰Srœ}°Œ\ŒŒ^’€N‡v;wp:tsBuœpœÀPv¾Eh k–r:d’Y„¤JiÓ–„êȱÀŠjh$G\IUGZI[J`!J^ H]G`De?l Dm Dd?W@`Aj"@_@f<l@^>\<`;j Bi>n<t!>t&Ai=b;l>v$Dn ?{,Bh=q;†+@€:!8˜0>¦<G®<D´CO¾FNÅJPÌNSÓWZÕ\_Õ]e×`b×cfØhfÚfnØgnÚglÛkkÚmpÛnpßoqßtwá|}ây{Þvxãvv䃃拉猆蒋鑎劂æƒ~â~}ß‚€Ý|~Üu~ØuvÔyq®RZ\ 7b:v#BVBVBVBVDVDbEi$Il"Bt,JfAf:j<a>gAo? S_‘7LŠ0F‘>QŠ1F…-G&@‡.F8N{(Ep>mKp H„†ÖšÖ‡zÚÌuiʆxʆyÊyÌ‹|ÉŒzÉŠ~ÉŒ€ÄŠȈ~ÇŠÃ…Æ„dž~Â…}ņ}Ċƈ|‚yÁƒ|Ä|¾‚º~z¸€¸}v¸{w¸|y´zx´wv±rr©lp¤ek£`l®imÞ¢ðÄ•öÓ§õ׬õÕ§öÖ¦ôÔ£ôУôТôТôÐ¥ò΢ò΢ôΠò΢ñΤòΤñϤò΢òΣòϧñÌ¥ñÊŸñÊšòÊñɘòÈœòÈ›ñÆ–ôÆš^:`;b:a<c@b@`>`Ft>•6H¨JT¬JS¦DR´LVÉ^_Ñd`×neÝ|tâ…qèvêœ{êšyꚀëžzížyîœ}ðžƒîœzêŽxæ„oÞraÐ[U·CJ—.F†BŽ*Hš7R¡LhHl¢Ji‡8fw/Zu5a€;aˆGmr2\`"OXJNFMFu@mx6gPIZNf"Vj)j~Pv˜qœQuB}„YŽŽdž‰]–•t¢’h¡’m Œ_˜†Tn9vl6n¡y¡°R~ÒLd±p˜r7bKx™Pv¶u†Ð¹¶t:RXJf FUDZB[E\A\CZC_;i$Eo'Fn<`AX<bAn"@`?b?l=c>]<`<f=n>l=n;r ?lAf<g<t"?o@s"=k=m>‡.A€";r6ƒ7ž-=¡2>®:B¶@HºBIÅJNÌRVÔVWØ`d×`cØacÖbfÙfjÛfkÚinÜorÚmtÜnpßtxàxxää…„á‚âƒæ„„å‰è”Œè‘‰çŽ…èŒå‡†äŠˆßˆ†Þ}~Üv|Ú||Ïun‹/IX>kAw$CTAUAXDTBbHb!Dm$FhAo%Ca;q$Bo!@b:l;x A O\“8P‹3I’@V:M€'C€'?ˆ.DŒ3Hv$B~&GkEr$LÂ…‰Ô•ÖˆtØ‚ÊtiÆ‚tLJxÍ‘|ÌŒxÉŽzȆ|ÊŒ~Ň|ȉ€Å‡|Ć{È„{Ć~Ń}Ȉ|Çzˆ~Ã…{‡}¾†|½‚~»€|·||¶}z·|vµ{y³xx´uv®tt©lp¤hpž`j²prଋòËžöÖ§öجöת÷Ö¦õÒ¢ôÑ¢óСòΡòϤòΠòÏ£ôЦòÒ¨óШóФòÏ£òΞòÍ ñËœòÊžðË òÉœñÈœðÈžñÈœóÇœñÆœóÔ_:]>]>`>_>]@]A\@t @—;L¦IQ­JR¨GT°GRÆ\^ÑhdØneÞxoã‡xé{꜂êžvì›|ìžwîî›|ïž}îšxëtè…qÞs_Ï\T´CL”+G‚B,H–4Q¢Nf–GhKiw&Rj)So*]h#R\ƒm0YZLa OUIOHr<ft2fQF]"T\Ts2r„M€dŽ‚XŠ`#Xb&`i3eˆa–h¨™{­—t°j‘fšQ’p8yžz¡£b–ÁHjÆ€žˆBfn5a•Ut£X`Ǭ¤i)Pw:U_LUIZH\H^G[D^H`@p-Lp$DnBb?X9d?m"B]?\<f>f@Y>`=`?f;k<p>k?r<j=h@q!Al>t%?t"Ah9€-Dƒ,Ao6p4€6&:ž0>¦<C²=B¼BHÇMPÍUZÔZ[ÓYdÖ^cÖbhÙdjØejÚlqÝsxÜsxÜqvàzyá}€ã†ƒåŽŒäŽŒæ‰ˆæ†ç‹ˆèˆæŠˆäˆ‡èŽäŽçŽ‹Þˆ„ÜxÜvxÖ}xÅgfj9W?v'BgBSBZFZEUF^F`Fn'Fk#@m @^<s*Ee<e>jAy$FŸVb•?P2L’DWŠ6G„(B…0G….Cˆ*Bv$@….JbBlI‰Œ×™Ö†~Ö‹€ÉykÈ„~ʇxËŽ~ÊŒ|ÈŒzÇŠzÆ…ă~ƆĆ~Ä|„À„}Àƒ~Ä|Æ{Ɔ{Áƒ{„zÁ{¿‚}¼|x¸}z¶{z¶zy´{x³vt³ss®qp©np hjŸ_m¹wvç´òÌŸöצõÙ®ö×§÷Ô¢ôÏšóΜóΠòΟóϤòΦòÒ¦ôѧóѤôÒ¥ôÏ¢òΠòËòÉ™ðÉšñǘñÇšñÆ™ñÇœðǘòÅžòÆšòÄ–ñÀ‘^=^<aBb@\<[<`B`Dt#D‘5H›<K BQ£CP¶HPÉ\[Òh`×leÞ|lã†qè“yì™ë›vëœwëšzîžyîžxï¡~ï›|ëpè†nár^Ò^X´EL’+D†"CŠ,J“7R G]¢Pp€0Vk"Nh#Rb!Tb&R—kŒj*XY!N`#OWLTNk4^t2cRJ^!RWQj,i^Š”j˜…X‹f&^Z S] \l5p„Z–u¨–s§†Z•”s¦’s«„X˜”h•ªnœºf“Âx–¯G`Fv…I`…@[l1Lh)Nz6QTLWI]Gl$F^D[D[F`Dq#Dr"Dr"CaBZ?dBq&D^>_E`>n>_;^<d=`>k @m?n>l:k?k@p$Bl<s"?t(Ch>z(Bƒ,Ar<d7g5u3†";š.<©0<°8DÁEJÊOTÎT\ÐZbÓ^aÒaiØcjÙfnÜhnÝmpÚrvØstßvzâyyä~}æä’åŽŠåŒŠè‹æŠŠåŠçŠˆè‘‘ç˜å”ŽÞ†„Ùv}ØzzÑzx´JQa?\>v%D^FWK^!JVJXJ_ J^Gn$Cr(Ef:`=j!<e<b>l=x#AžT_•=R5O’GZˆ2G…*D‹9H†0Fˆ.Hv&@‡/Kp"HjHƉٜ’؈|Ö†ÈxoÆ€wɉxÊ‹xʋɌ~ÈŠ{Ljz‚zÁ‚~Ć}Ć¿‡Á‡À…€¿ƒ}¾†~¿„Â…{Á…|½„}º‚€¶{º|z¶|{µzxµxx³zy¯vtªqq§nq¢ckŸcn½€x긎ôСöÚ©õÛ°öÖ¥÷ÒžóΙôÍ™ôΛòÎóФòТôÑ¥ôÒ¨ñѦóѧôΟò̘òÊ™òÆ–ñÅ–òÈ–ðÅ•ðÄ’òÓñÔôÁŒð¼‘í¶ˆêª‚^B\>`D`C[B\AY@[>mA‚.E˜:L¡BPªGRºPXÌabÔiaÙngß|nå†tç“xè™zêœ|뚀ìzížzîž|î |î›|ì’té†nâr`Ð^X²@K‘*F€ D‡(H’4N G^¤PbcG^GbLYRe.Z•_~€<dVJd$Pi)XVJo2`l*]RGZNSOTU]’œt¤’st2hZPl*jl8p{I„ˆYŽ‹d™’j£—z®–x­†Z“Œ_š›c–´tŸ´~“Lv–Dk‡Ia’N`^%No+N[#JX!KUE\FaD\EYBXDa@r @t@u$B^@V>eAx(C_@`B`Ai$FaA[@d@]:b>k Bn!Bh<l!>d=lAn#Ep =t'Df@r#?~+D„+Bh<a:a5s5‚9’(>¡0A²>HÂJLÈRVÌSZÎTZÐ\aÕ`i×bf×cmÛkkÜrtÛqvÜvtÞv|àvyä‚‚â‰„æ‰ˆææ’ç’‘æ‹åŒˆçŽŠäŽ‹â‹‡Ý€…Ørz×yvÆmlª@IY;[<s#HZHW"M^$LX$OX L]J_!Jo%At.Id;f?e>i@i<l@„,E¡Wb“>LŽ/G”CT„.Fƒ)@Ž6J‰/D0Gx"@ˆ3LjFgHȆ„Ö–ŠØ‡wׄÆ|tÅyÄ„uĆzÈŠyŇ|ň}Â…€Â‚}Á‡Ä„€Å…~†ƒÀ‡½…~ƒ|†~À…¾„|¿‚z¸~}»~y·|z´||²yw³xw¶xv±xt­rv¨nq§jk bl£dkÉŠzî¾óÒ¢öÛ­õÛ®öÕ¦÷ОôÍ›ô̘ôÏœòОôСôÒ£ôÒ¨ôÒ©ñЦôΡóËòÉšñÆ™òÆ“òÇ™óÔðÃ’ï¾Ží¹ˆìµ„ê«|äœz؇eÃgOa?\?]=\=[<Y=Z<\Bf@y$B“5FžDPªHTºTZËcdÒd^Úqià{ræ†tè’zê˜ë—xë–{ëœ|î›|ð~ð›~î’tç†ràuaÐ^Y¬ALˆ)Ex D{&GŽ3N¦[t€3Ub F\DWIj)[v>j€<]4^YKd&Sl(Vd"Rp.\h,ZSHUKUQJPR‚ ƒ²’sš‡P…_Vs9ro5q{D|‡WŽ€K†Žf Ša”œ†¶˜‚¶˜}°Ž^– s¢¸‚¦¾Ž¨x4cyAfŽMeŠIdZ"LRKT"LTJZJ\J\H\JYHd Jr&Hw+H~,HcAWBc>v(D]@^Dd CgBe D[@b@bA`?f?l!@j Bn%Ck%Dh>nBn!Co#DgBo"D‚.F†+By"Aj<e9f9n:|:Œ,Bœ.@«8@­<I²@KÀJMÅV\ÇU]È\fÉ\hÓbiÕgkÜjkÜprÝrxßvzâ}€à|~åˆ‰æŒˆæŒ‰è’Œä‡„ã†‚ä†‚à…„ß„„Ûz|Ör{ÐsrÆgd©@NZD\Ej$LY%OZ$N[&PW$O\$L_"L_ Is+Hr*HbDm'Ga@fBgChA„.JžQ]’?S‘;NARŠ5I†0F;NŒ8M3H~,HŠ8NmJl#LĈŒØ’…Ø‚xÒˆ}Äxp¼tp¸ur»|tÂ}sÀzÃ~wÃx‚{†‚¿~À†‚À„€Â„~Á„|Á€¿‚|„|Àƒ~¼|½€|µ}~¸}zµzw°yz´zx²uv³vw®ux¨no¦hlŸcl¤foÔ˜zïÃ’öÓ¢öÚ©öجõÕ¤÷ПôÍœôÍšôРóÐôÏŸõÑžôѤöТôΞôÍžôÉœñÈšòÆ—ôÅ•óÃ’ò¿”ﻋꯆäœpÙ†cÄfP¢FF€-@h;X<[@ZB^@^?X=W;YC`?p@Ž1FŸDP¦FR²IRÇ\_ÑfbÙukàvãŠxéxè˜|ê–{è˜~ꘀízî|îž{ï˜zì‘rè„pßq^Î[T®AK„&DiEƒ/T¬f„¦^„ˆ9a“V~WHNIp-ZŒJro,Tv0Xf"Mg%Se&Tk(Sl,Wc$RTFTHYRKRlDt¢Œ»˜w£^g(\n4er6pf*d€Dx`‘hž{F‡^ˆ™{«„TŽ’nª›t¨¯¸¾‡ª›gŸ£x¦¤iˆ¨n„h1VLHNFSFXJZF\H^F\DmB{&B.Fz&DX=X=g!Bx,E_A]A_>hAjA^@_=c>[<a?f>h@o"An BjCq(Fs&Er(FiDl D~+G‚+Dˆ,E|!>u>q>n:x<{7";† :„":‹&<–0@¡;I¨@KªMX¶TbÀZaË\cÏdjÕjnÔnwÚwzÞxyÞtzá~|㇆䉆劄ჂÞ{zßzxÞ|xÜ|zÕpuÐppÊkhÉ^S—0BX@ZB_FXJ\"MZLX$N`#Na!L]Jn,Jl!DcCiBbBa<gBo$H„.J O_“CZ’>R=S‹8M„/FŽ=P‘:N7I&@‹6Lo Kt)OÈׂֈ~΂x¹roµhf°ff¸lk¼rl»vn»uwÀzw¾z¾|{¼~¾„‚À„~„ˆƒÂ„~À…~¿‚~¾‚}½€|¾€y¶¶~~¸||´}|°yx°ux¯vw­su§nq¡dp `k­ouÞ¨ƒñÇ—õÔ¤÷Ù©öÖ¦öÓ£öÏžôÌ™õΜõÎôÎôÏŸöΞôΠõËŸõÌ›ôȘõÈšòÇ“òÂ’ð¼Šî´ˆëªâštÒ~h³ULˆ0?i8^<X@U>Y@[>`A]>Z<X:X>V>];q B†-DšBPœAO¤ANÁTVÑe_Úpc߀rã†rè’yé–|è˜~é—|ì˜xìš|ëœzðŸ„ð˜~êŒtã„lÚn_ÈTP¤<Iz H†7`ºšÓ°°¥Lm Ut±t‡UEOGc M~8`q0YfJl'Ph#Qa Np/Z]H\LWFSHWLMPa4e Œ¹~©Ÿ­ƒJ†€L‚z?ub$`p6m”h˜’w¢J„q;o…c–}S“o¢Ÿƒ³®’¶¢y¤ q¢­†¦·™·±«•fŠX)SQNRKUKXJ[JZG[Il E‡2L0Ix)EZAT>e<{-D_?`A\A_?hA^?`?d>]>c=dBf@n!Aq%Bo"Cp$Dr%Ds%Bo!Bh=p!@‚&A”6G‹-D~"=z@~#?Š/J.MŽ6O”5OŸ>[§H^®H`¯Lc²Kb³Qc¾UlÄ\lÌXhÑ_jÖdtÔdzÚuÜu~Ý|…ßz‚á‡â‹âŠŠà‚Šà~†à}‰Ý|ƒÖp|ÈhrÆipËlb½VUˆ4KYF\F[L\#NY'OY(SY La%M^"L^Go,Nj$Ff Dd@a@_@d=r$D€,HœN`“BV‘<P‘CR‰<R„4Lˆ4L8L6H}&DŠ0Kw*Px*PÌŽ‹×Ž{؉Èyr¯ff®`b«Z\¬\`´c`µjn´nn»ml·tu¼rr¶tx¸wx»~z¾~~¿|zÂ~z½‚¿…‚¼‚¸€‚¼€|º€}·|x´zz±yz¯uw®tvªuvªlp¤jqžcj `l¹xt䲋òʘõÖ§÷×£öÒ¢öÏœöÌ›ôÌšôÎõÍšôÍôÌ›õÌœôÊ™öÊšõÉ›ôÇ’óÂ’î¼î·‰æ¨~Þ’nÎvZªMJ€-Bc;Z<T 7U:Y;^>^@`=`A^>X>V<X9T<Z;q;‡-A—=G˜;Ož9J¼IRÎa\Ùqeß~oä‡yæxè–|ëš{é–véšwë™wêš}î™zî—{ê‹päjÚlbÃRP¢7S˜Agتܾ¬–JT|$XšRmŸc~TGMCUG~>gv4]aKj$Pj(Rf#Pm*S\H`JTFSETHNOb0`™|¨–n¢¥ˆ¨—jœt8dy9kf&b`!]~Hs—w›zC|n6t‹o¥o®t>x˜{§§Œµ ~¥‰Tˆq2[“Nm§†®‘´“ah0YNBM@RDVBZGZDlCŠ0H…4Hu(GT<R=h Cu$B^B_@]?^Be@c?\?b>c?_=e@`?g?m$Cj#Ei?o!Al!Am Ag=j<€'=‰,A‘-B0E˜1H¤?NµLZ·OZ¾Q`Æ\gÌajÒbkÐenÒptÐpvÏjmÌinÊlnÎpzÒnr×uyØuz܇܃Þ‰‚Þ„}ß„~Þ‰‚ß„Þ‹à“Šá•Žß”ˆÛ”Ž×•–ÕšžØœÃ–£av{A_e.MW#HY'PZ(NZ#NY$L[!H^"N^Gl#Dh"Fe D`>^BaA`=t%D|*F›LZ–HYŽ8M“FVŠ:T…2L‰8N‘:N0I}(B‚,H{+S~5WЖ‘ׇtÕˆÁmh¦X[¬bb¦RX¨V^¯ZX¯`f³ae°bb®fi¶on±hl²nt¶st¶tuµwx¹vu¾~xÃ|¾‚~»‚€º~yº}z¸}|´yx°x|®xv­svªqp¨mp hp`i¡_kƉ{ê¼õÏöÕ§øÕžöÏ™öË’öÌ–ó̘ð˘ôÌœóÊšöÊšõÊ–ôÈ”öÇ‘õÇ“óÁŽí¸ç¬†á~Ñ…o¶ZQ‹/@e;X;T:O:R<`<n<p>eCf DfBfA\=W=T:R<X;o<‚)=3CŒ0D’1E¶OTËdcØobÞ|sã…wæ“|è—|ê˜}ê˜|ê˜|ê–xé˜|î™}î™zèŽrã{eÖh`½Qb±UxР¯â¿¢GLˆNmr%TžftŒLaX KT MPD|<d{8an*Vi&Tl&Tt2`_H^Iq1]VIXIXJVQu>s™v¨’fŸ’hŸ€¬„N„u8fj.d[Ob%XwFswAƒZ˜žŽ·“qšv>|R‹žˆ³¨’ºšw£x@xb"Tu6`´”¨¾¢»¦ƒ¨f1aGCNFSFUE`Dn@.HŠ8Ks @T>T=o*Fy(B^@]@`>^>cCh?\>a>b>\<aAb>d Dg An"Bj<u&?j>f<f8c8t$=†,D’3D“6I¦AO¶KX»O^ÄZfÊ]`Ð`dÐ_fÓ``ÔcfÔlhÔihÓheÑjkÍljÔpn×jk×mrÜtwÜzwÝ}yÛ|Þ|{Ü{zÚ€€Û€xÚ‚~Û‚|Ý„‚Ýˆà“‰ä›‘æ§œè²é¸£á·¥Ð­¤²˜‡\{j9]R#IW$MUJY$M[E^EfBf BaAX@XCi!F`?s(F{(G—KY”G\‰7O‘FX:S…2LŒ5J;P’8L‡-F†,Hy&N‡:WÓ•Õ€jÖ†}¸ff¨QX´\\­Y\¨O\ªSW¨U]¯Z_®Z^­^c¬_hª[c¬bi©bg®fk¯jn®ln²ps·ss¸zzºzwºwv¶yz´z{´z{°xz±y}®ts¨or¥jq¢gnœaj¤dlÔ—ïÀ”öПøÔ¢÷ÒžõÊ”öÈ’öÊ—ôÊ•ò˘ôΜòÊ›ôÉ™òÈ”ôÈ”õÄ”òÂí¼Žç®Šß›|ÒŠu´e_Š8Hf:W>S@P:Z>e8w"=ƒ.F€*Di>i"Dl$Fd!Ed@^?Z>U:V 8l=z!=†/A…/F/E¯KQÌcb×lbÜ{må…vèzè–{ê–ê•~é˜|ê—|ìšì~î—{èŠrâzjÕklÊj€Û«®Ü°Œ’BH}0Ru&Pc K[xj*PL?MDNFw8^„Bhp,VdNl)Rn)R` M`Q~Dmd!Q] M[LXPp4j“k™•m Z’šxœœ~©|Fv^&UNK]#]‚WfŸ“x§Ÿ´€PwD|RˆŒe’ž¦”T|”iŠƒFzd P–_vÓ µ–«¢‚¬a0`MKSFVFbEs#Gƒ-GŽ:KmBXDXBt.Hx-I]C]CbF]B_@fB`@_=`>_>_@bBbBjBo#CkAl?r#Ce?d;f@m>‰-C”2GŸ:JµFSÀQXÊV^Ð`fÐ_dÐ^gÌY^Ë_cÏ`aÐbcÒfeÑedÌglÏihÓjoØmpØpqÛvuÜvtÚzyÙ|zÛwwÙyvØvtÙut×xtÙzwÛÛˆ‚ß”‡âŸŒâ¨–çµ¡è·¥ìº¤í½¦ì¾¨à¼¬À¢¥“k†n?aX,QW(PYH^HeEc E^BVBXB^DdEv.N‚1L—GU–Ja†2KŠ;PŒAZ†3M„0L:OŽ6N‹1H/Mw,U‹>[×™”Ö€n΀y¸bc©Zb°]e¶cd¬Zb¬V\ªYa¬R]®\bªX`¬V`ªYc¬Z`£Yd¨\b¦\g§ah©di¯hl­jp¯mp±pr¯pw°tv±uy¬sv°ux¬rs©or¤ktžfrœ`m¨dnØž€òÄ“öÏšöÒøÍ˜ôÆöÈ‘÷ÇòÇ–ôËœôÊšôÉšöÉ™õÈ—ôÃŽóÀ굌⦋ה|¿rj—DLoB\BS:W;a>k @})DŒ1GŠ4H‡/Hx,Hu*Jp(Hm%IhCfA`CV@W@f>{#?‚)A‚%=ˆ,B¦BLÄWXÔf^Üthå‚sæŽxè”}ê”|è–zè’|ê•|ê–}í™wì‘wè‰tâ~vÚ~Šß­¬Ó’u4Hx$H‡8[f"T|<_¯xˆVDLELCLDn*VˆDjv*TdLg&Ri'S^NeT|Ej~<he"S\M[Nf&`q>n‘j˜šr£†S…“m——w¨p7w`*fq9tƒP†˜w¤¡’¸k’h1jwJzF‚|FŠf”—p¤~Dn}@lt8v„Ii¬ˆ ¢jƒ¨Œ ¡‚¬T"MODVFf Es)P,H‘:LhEWCXDj%Fy/NfH\Fb D\CZ?cCh"G`B`>bCbDfD`@eAm#Fm&FjBl Ce@i Af<m>‰2G–7K¢:K·J\ÂT^Ê[`Ð]`Í_dÎZaÌ[`Ê]cË`gÎfjÒbcÏejÐhlÓknÖilÖgmÙnsÜqqÛvtÛvwØsrÚrtÔqqÔtuÖqxØrtØvuÝ{ÞŒ‡â™‹âŸŒãª˜æ´žçº¤èº£é¼¤ê¾¨íÀ¬î«⿭Ȫ¨œu‰sDg[,NV!G]G[H` HUCTCZCdFp(GŒ>W•IW˜Ob†5Pˆ=Sˆ<U/L†2I’=NŽ4N„+G…8Wx,V”H^Øž”×iËvr´be²bfºmoºhf·jj²[_°ag¯[^°Y]¬V\©U`¨T^¨T^¥P]¢T`ŸS^ V`¡W^¥T\¦^f¨^e§^g¤bm¨bi¬hm¨joªlo¨kp¤ip£fmžfnœ^j§dqÚ ~òÂŽöΘöКöÊõÅôÄõÈ‘ôÉ—õËœôÈ™óÊ›öʘôɘðÀŽí¸‹ê°‡ä¨†Ý–Èzj LTr=]9Z:_>gCr B+C0G’8MŽ5J†3I™NdBZ‚5L{,Ft%Dj>f>_@a?q>}$>{$>t<~"<–4F¾NRÐ`XÚtjãƒtèŽwé–zè”xê’{ê“|ê•wì“xí›yí“|玅䌎贞ٌr£EP€#Dx$I~0^t+V´‡šWaMBJ>J@K
+>\ H€;dy.YW@d%N_H^J`P~GkNys*[l)Zf%Sb$YUQm8fœx¦’a˜|Axm˜fŸ”o«˜t²˜w­¤”¶š†¨l3du>}s<x†Z€Jˆ~N‚”q—‹Vm.kh›£rž¸”¯£f‰w6]«šªh”RKTBcGnB~(EŠ0HaBRCUCr,H~1J`B\@bD[A\>^>i DaA_@bB_Ad=aB`>l"?l#Bk Cp@hChAf>k:*C’8N¨=K¾LVÂP[ËYZËX^Î\_ÐZ]ËZ^ÊZbÎZ_Ð^cÑbhÓdkÑjlÖhn×ijØklÚknÛpnÙrsÚqpÖkjÖrpÕllÖpp×rrØroÛ{xÞ€zà’„á–‰â¢ã¬•洞湣黢꾦뾤뾥êÀ¨ì¿¨ïÀ¨è¿ªÏ²©¤|u@\Z BR?Z>O:N>P;`=p!D‰=U‰8LšPb‚/J‡:T†8O‚/Kƒ.K’=P4K~&E~3Pr#JžQbÙšÔ~lÈtmµfi´lkÀqmºljÂql½ni¸ed¶fd³bh±^c°\`«U`¦Vb£PY£P[¥OW¢OWœLWšL[¡Q[¢Ua£X\ [hžX`œX` [b \d \i\e]j—Xc˜Uf§agÛ¡„òÀöË–öÌ’öÅŠôËóÄöÇ–ôɘôÊšôÊ›òÉ™õÊšóÈ›ðÀ’ë´Šä§„Ú“v¾fX–=Fq<Z7[5f=n>t"B€*E‹1G”8H’7L‘5J”?N¢kz cv›RdCW†5M}.Gv$Dj@jAz"@x:t<n6p8‰(@­BKÌWRÚoeâ‚pèxè“zè“yê–ë’tê”x薀ꗈꡞ갢朄à€lÆ[Z¤APˆ'I€,R˜Ko§rНnsi$ILBRBO?NBXCg$S:bn)Ux;fM :SB^Lr0[’R{|6fs1dj%Pr>lKENLˆd…qœ`Œs8ja)UtAiƒM|‘l’Ÿ®uFqo7vxF~‚P†x?x‰b—ˆ^–†YŠ[†P‰”f˜²ŒŸÅ–¢•Tn|7hvB^ª”¤o8cVAgBmB€)DŠ5K`@RBVCx-C‚1L_?^BbA\>\@Z<jCf>`>a@]?^?a?dGl$Hp&Ci Bs BkBj?g>f:~(DŒ5J¢<K¼MVÄY`ÁX_ÆV\ÏZ]ÎZ]Ì\^Í\aÏ[dÌ[fÐ`jÔjlÑhhÔfkÖgjØglÜjmÙlsØln×jr×moÙklÔnsÖpmØpoÚtqÚ|wÞ„}á’ƒâ˜Œä§æ®›è²œç¸¢é¸¡ê¼¤ê½¢ê¾¨ìÀ§íÀ«î¾¦ïÁªñĪîĭ̲¨ wf5TQ<L8K<M 6`:n@‡1Jˆ:O˜P`€(F‡;Pˆ8Qƒ1J‚,H9H‡*D€*Dz%Er$N¦XgÙ’Ò}pÈtrºlnºsn¾trºqnÁrlÄvrºke½jh¶hh³eh³dk®^e«Xb©Xb¦S^¢MW¢KUžJT IZœJU˜DTJVšOY•KX•LY–N^šLX U_žX^—R]GXŽDYžUbØ•yﻆöÉöÉ’öňõ‹öÅõȘóǘõÈ›ôɘôɘöÈ•óÆ–ï¾å¬ˆÚ–t¹f\„,A`<^<c>m>z&Ax&B~(D†*B‘8J”4G‘4J“9L–<N¦q€¦q€§k{ _n“I]Œ=P‚4Lv'Dv$B„,Fy<s9j8n9…&?¨>GÉTTÚncâ~næŒ{ê’zê’~ì”}ê˜zë–z蔂ç ð§Œìš|æˆtÛtgÌ^YªBTŠ,PMwª`lЩ£w(DT?M>L>L=O=VARFr-WŒPw‚ItG7L=[Nm&W“`ˆ†Drw2ew8exCrJ @J C^"TbŒx§•g›|JzCvv:pƒW‘p™^#Z€UŒƒVL††T‹ƒLŠg˜fŸŠ^’‹Y•a–f}°’­„Cj~:ct/e|Dež|Ÿe"MiChB€'D…/I`?T?U=y+C~-Ca>`@a@Z@\BY>iBg Bd@_B[A\?bBh BfAm$Dl"B{0Ip!Bl@g=b<q!>‰0F¤?JµHPÀPUÃRXÌXYÌY]ÊY\ÊV\Ì\dÐ[`Ñ_eÏ]dÐhkÑfgÚddØdiÙhjÚjlÙlnØinØouÖkn×km×om×rnØvvÛxuÞ}àˆ~ß•ˆâ Šä«æ¯—粖洜跚鶜ê»í¼¥ë¾¦í¿¦îÁ¨í¿¨ð¬òëóƯéȱÀ©ªWvR#CH<J <[<q&D€-IŠ<O–Ob},L†7L3L}.I~(D5H‚,Eƒ,Hy)Kr$O¬^kØŽƒÒzqÃvxÀvzÀzu½xt¾vpÀunÁzt¼rl¼qr·ooºlo¸jj´hn³fi°bkªYa¨Vc§U_£P\ LYHT›FT˜DR–JVHUAV‘HXšJW§W[§XZžRU?Q„0J–DVÑ‹töÈ’öÈŽöÄŒõÃŽôÇ”õËœôÊšôǘôÈ–òÆ”ò•걈ޗ|ÀufŠ5D]6`;pA€*D~,Bƒ+F€,E…0G3F“8I‘7J–8J•8L“7L©|„§u„¨t‡¦r} bpTf’AZˆ7N‚1Lˆ4K~(Dr=f>h;€(D¦>HÉTRÚncâ‚qç‹tè{é’wê’zì”yì”|ë|ìš~í•zë’rè…rßtbÊ\]¨C[˜Dd³gˆ»w}ÆŠ‚W?RCNAQAQ?TDR?WNi(V‡QuƒHpE 9H<PFh%Tp–‡Fsv2b†R}w@iTIOETHo4b[ƒa‡›v¨ˆTŽRˆ˜|¤„Th.mc-e‡b’ˆ[”ˆ[ŠY“v@nœ‡¶‘j¢’hšw¡£b‚¢iz¨ˆªu-X^JŽR„ vƒWbCgD‚(Ax(D^@R;Q;|5Ix-GbC`Cd!E[?\CW>f!IdDj'Ib!F`B]B`BgBdCi Eq%H|,Hz(Fo BjBc@r B‡4KŸDV²HR»NW¿NUÅQZÇY_ÌX\Î[_Î]dÓ`dÐ^`Æ_hÎaf×fgÚehÚkhÙjjÜnkÙjlØlmØmnÖjj×mnÙrrØppÛvtÝ}yÞ„yà‚á—‡ã‰ä§Žå®•尖沚篖粖è·ê¸Ÿê¹›ì½¤ï¾£ð¿¦ðÀ¥òÁ¦ñƬôȲòɮ׿®œ~”\-PJ:V<n"Br@†:K—NZx$F‚0J4N{*F~*D1G„(D‚0Ju Ep#M¶lwÖÐyq¿pnÀ|zÀ~zÁ~|¿xuÀzwÅyr¾wvºsr¸su¶rtºqr·noºmn´jl¯fk¯ah®^e¨Zb§Wb¡P\ŸL[˜FZ”JXBR?S“FV¤T^´ca±`XªWZ“CQ0L’>PÓsð½ŒöÈ’õÈŽöÆŒôÆöÊ™õÌ ôÉšôǘõÈ–òŕç¦zÜ’jÀhYŽ8Gg<b;s$B‚,F‹4J†2J…/H†6JŠ4L”7I”<L˜<K”6H”>P”9M¨zˆ¨v‡¨}‰¦y‡¦s¥hvŸWj—L\Ž@U@N…3F{#@d8e4€(@¤>HÈRR×ncâ‚qæ‹{èzç’yê’xë”wì”{ë–zë•|ì—{êŽwè„lÞrfÆZ^¹dºuŒ¯^u¿zzŒH]RFP?QBR<N>Q?ODv;r•U”Y†DsSIGDXU‰UˆŸvšu0`y7hHra%PXKQHi,`‡N|u2cd"XzJyŽ^–yŸ~Kpd(]k2iq6xh2fŒfšf–_“ˆH„”o¤Œ¸”hœ›tšœY‚”Lb™oyœ|¦ZN^ MŽLp¬†žm,UeD|&EnCYBS?W@‚1G~.Gd?cF_BbD^BXC\CfFh&Gh,L_A^C^BcAhDi"Do"E|,H‰4Jn"DfBbAo Bˆ6J•BU®HUÀRXÄQXÆRXÆVZÍY\Î\bÏ[`Ð^dÃZaÊahÕdhØhkÜikÚnpÚlnÜlnØkmØhhÙjnØde×mrÙstØttÜxvÞyÞ‡~à’„áš‹ã ‹ä¦’ä«”ç²šæ°•æ®™è±™è¸œé¶ éµœë»¤ì¾¤ï¾¤ð£ò©ðĬòÆ®òȰò˳åʱ°š¤m:ZQAfBeBx1M‘K\u(J}2N4Ny(F„0GŽ9L'D,GlDs%MÀ{€Ö†zÎwjÀqtÊ~yÈtÄ|wÁ~|Á~uÁzvÀxt»vu¼uvºtvºtw¹sv»rv¹or´jm°go®bj¬elª_f¨Ze¢R_¢T]›Tb”HV‘@TŸOY®XZ¾k`¿eYµSN”DR‚+I›FTÚ–wñ½ŠöÊ–öÊ•öÈ•õÉ”öΞ÷ΞöÌ›öÉšôÈ•ðđ窀؄e´UQ|$>_7a:u$Bˆ0EŽ6LŒ0F‰1I‹3H:O–;Lœ?Pš@N˜AM’7I•2G–7N¦x†¥t„¨}Šª‚’¬„ªy‡¦lw \l™K[–EUŠ7H}&@f8e9z=§<HÉVUØplá€tçŒ}ê{ë”xê•zè”zì–xì˜zî™~ï”zêŽqä€lÝmdÈ_eÒ‡–Ü¥¢šC]¨^tv.RPBPBQ?R>L9N 8H
+<VF‡Ip›d’p¢šb W’›lžiŒ|8`r.fn,^k.Zs:rPLf+c’a‹€Ald!Th(`ƒ^hr;bn5l^$[h2ft?up;uq@ra–”jŸ–e𣅲ž~«š­–ršžvœm'RaLˆg{ˆ`ŽMLm/a¡m{˜l_Ew"Fj!KXJUFTF6O|.JfFfHaHbE^BWD] He Hh$If$Ha"GaD^Ba>r%Fi%Hx%Gw$A‹5Hy%Df?hDmA‹9Lš?S­LYÂRTÃRZÊTYÈT[Ï[aÐ\aÍ[`ÆZ\ÆajÔad×diÛikÚnqÙpoÜmmÚlm×nmÚddÙfk×fgØoqÛrmÜvlÝxÞƒyàŠ~à‚á”ƒâ˜‰ä£‘ä¨’å®“å«–æ®æ²˜è²–é²–é´—ë¸›í» ï¾¤ïÀ¦ñÀ¤ñħòƬñÆ®óȰôʶìÌ®½¦¦t@^\>WAl$D‹BTp"Ft(Dy,Ht"B~(A‹4J(C„(DfAr#JÄ…†ÖnÊunÀuŏxÈzÆ}vÂ~xÄ~zÄ}vÀ|w¾xy¾yz¼wxºxwºux¸qu¸tv¹op´op³kp±in®cfª_h¨`i¤Zb WešSa™GW¢OV·\YÈjTÄk\µXP›BN‘2N¶^Zà£~òÄ‘öʘö̘÷˘õÌ›öΙøÎœô˘öÈ•ôÆ•ï¿Ý›r´\Wz$>\@Z9t!B;K”:H‘7F‹0FŒ0GŽ1H–;M?O CRŸDQš>L‘8K”2D˜8N¢n‚¤v†¨‹¬ˆ“°Š’®„¬|‡§m|¢`h›P^;K‚(@j=^ 7w @¤=IÈYV×njâ‚tè‘zê–}ëšyê–{ê–|ê•uë˜víœ{í˜vêŽnä€nÛkjÔ{ˆéƸԕ„=]‘@Z1Yd"RTBP>V>P7T?P@VCk)Ta!Jc%J|;`VvLlu1\n.[v8hc!Vb([k0fx@|”fŽŽTu^HTHo2b”y¢m-X^"Vf.ba$[]"\r>r€N†r<t€R†Œb’—n¢žx¤šw©šz¨Ÿ€­£«ƒDuH JvB_¶¢°|H{\Jƒ?f·›ªl(OlD`CRBRBRDz0G~,IhDfA`Cd H^FSD^Dh Cl)Jj&F`EbD^E`Dt&Hl!Fz&H},H˜:K’6FiAe=h>Œ8P–9N²P[ÃPSÆQWÍWZÍ^`ÐZ\ËZ^ÄTXÊZbÔgk×ik×gkÛdfÛikÙnlÙllÚlnÚlmØffÙhlØjmÚljÜtnÞzvß{à…{àŠ€áŽ€á‘†ã–†â ‹ä¢å©’娓檒谓殑貔級긜캞ì¸ð¿ ñÀ¢ðħóÄ«òȰóɱõʳô̵îδŭ¦DdT?j Dˆ:NjBo!?t%Bn C.Dˆ/H+By#D_?t#FÌ„„ÖuÇvq½toʃxÆxÆ‚xÂ}yÂ~xÂ|v¾{tÀzy¿|x»z|¼|z¹vvºsu¶su·su¶rr²ln°ko¯gm­ho§clªal¤`k¢_kŸR`¥X\ºbVÆkXÈjUµXQ¤DQ <PÎxeè³…ôÆ–öÎöΜöÍœöÍžôÎ÷ÏŸöÊšóÄŽòÁé±Î‚jœBP^=Z<p!D9Mœ>L–>N–8L“8K2I•9NŸDQ¤FR¨JUžCPš?N“:L’6Hž@O l~¢t‡©~Œ¬„”­Ž™®‰•¯ˆ“«|‰§nz¢`j”HV.Fl @\8y#B¤<HÄTW×nfãƒuçyé™|ì˜yêš|ê—}ë˜zì˜yíyî–zèŽrå~lÞnnæ“”öо¸nzTr;\`FdJ_J[EbJXCWF\Ei$Rv8_XGLEh'Rw5_n(Rk&Sb!N^Kf$Ss4gzDozChx;]e#PN BUP‹]‹™{¤XR\$Vd(\n6me)dd*c}L€‚PˆxA{zD|‹[v¦œv¦˜r ¥“¼ž‚šŸ{¢SQSJ´†º£½m*X‡F{žvPwh@Z@Q?TDSFv-Lw,HeDhB]E`E`GXG^GcDl(Ir(H^B`A`E]Gv.Jr*Hv Aˆ1K£?I©BKt#C`;_;†0H’4H¶S^ÄQVÉPWÎVXÏa]ÇU]ºO]ÆW_ÖadØfkØmlÙhjØdgÚflÚjkØihÛmjÚjhÙklÜjmØouÜqrÝwsÝ}xá€xà…~àŠ€â‹â‚ã•…ãœŒäžŒä£Žæ£æ§’ç¬æ¬—鯔貒굘춗췞ð¼¢ñ¾¢ð¤óèóÅ®óÆ®ôÊ´ô˶õιñϲĪ¥s;ZeE€4Ll#Fm"Fm#Fu'G…6M‡2H-Iy*J\G|.QÔŽ‡Õ|mÄxr»wxÇ€yÅ‚zƃÀ}z¿~|À}z½|w¿‚}¾zx¿}z¾yw»wx¼x|¹ww·tx¼vy¹ss±nr±lr°orªjt©jp¦hr¤ai¢\e«_Z¹gZÂhVÄjS¹[O«NR²NTÙqﺉöÈ•öΛöΘ÷Í™öΛöΛøÍôÈ”ðŠë¶á¡s¿n^ƒ*C\;k@ˆ0H›;L˜=L—?Q—:J”7M˜6JCS¨JR«LR«HRžAM˜<N–=P˜<P£FXœl€h|£r„¬‚¬‹–¬Ž˜®Œ–ª‚¬x‚©tz XaŒ<Ls ?a7z#@¢7FÆVX×ohâƒrçŽvéš|íœ~êšuì˜|ì—xìšyí{ì•vèŒpänßqs蜒îʬXr¼o}±xŽJ :S@P8\Bf Hh"KfJh$Nn(Sx3Xf#QPDr/Vx6\j#L^Hf$Qh(Tf&S`!JXDVCVI`!PRNXRV~ŽgŠm2jPH`(`p:kn6lj0jk7j‡ZŽK~xAuK›pœŸ«œs¢œ ŽbŒšwšˆVŒm-n–VrÌš”¡r”€Et@V°Œ¥c JXHTFVJWL|4Qv.Ok!Hh#Lc Jb$L^$KZ L^!Jd%Km(Lt.M_"Ib"M`$Nc!J€5Sy/Ls"J‰6R©FW­HU…0MbF]B~-J’9P¸ZfÈW\ÈT[ÊSZÅW^¶N\ÃW]ÔfmØafØceÚjnØfjØgmÚimÛmlÛnmÛhiÙhjÛifÛlhÛroÞvqÝxtÞ~váƒ{áŠ|߈|á€á‘‚┆⑃㜇垇ä¤ä Šå¤‹æ¯Žè®é®é´—쳕췘ð½ ðÀ¤òĦòƪñǰôɶóɵóλõѺîг¿ž p-Nl!<n=c>l;p!@-Dx"D„/H},LYE†4NÖ”‡ÒufÄwrÂwrÆ~xÅ‚{Æ‚s€xÀ€x¿}v½xrÀ~zÂzs¿zx¿{x¼y{½vv»wxºuw¸vv¹sv´rx±nr°mp¯lpªitªjq¥dl¥cj¬``µdYÃjVÇiUÄdP¶TPÂ_SáŸyð‘õÌ›öΙõКøÍœøÎšøÎœøÎóÈ’í¼‡æªxÕ‰e¯XSwAf@~(Dš>Pž=Lš<NžAQœ@Qš;K<N«LV¯TW°V]¨JVDR–=N•4J›@O¢AQ‰JdSjŸl~¦yˆª‚’°Š–°’°Œ˜´Š•°‚‡¥fm@Rr >b8| ; @LÅWZØneá€rè‘xê›zïš~íšìœ{ì{ìšzî }ìšyêpè„nàphÞ€zᵪ˜Ah˜HT¤fjJ=M>S@T;ZA[CX?^Ao2Xl%Ko+R]D]BZ!LXDZKw:h}>lf(P_ IS@PBQCp5^^"NPFZ SuBoˆV…b&[VLh*`d)\p6nk/ltBtŒ^–€F‚z<t—n›¡~«œt™s¡`”“j” x¡ŠMz–Y‰“Rl¦„žr8l]J¸£­v4ZRESHQERC€5Nt(Ij%Fl&HaA^@]DUDaBb"Hj#Fx,K^HbDa@`@s#Bz*Ew$F’6N´MR¹LPš8Hh;^<|(F‘6K´YdËXYÊPV¿M[¸T]É`cÖ^aØadØbiÚhkÝhiÙhiØlkÛjfÜijÜojÜhgÙnlÚllÛllÛqlßvrÞytá}râƒxâ‰}à‡zà‹€áŒ}ã‚㖆✊㚄äŠä‰å¦Žæ£Œé¦è§‹ê®‘쵕븚ð¼ ð¿ óèòìòÆ®ôɳôʶôͺõνôÒ¼îÒ²²ˆ•c?j;^5e:t;‚-Dt!B}%@r"D\C”@RÖ“„ÑrdÂtpÄ|tÆ‚{È„uÄxÀ€x¾~xÀ}u½ztÀ{wÀxt¾zvÀ{v¾xt½zx¼xx¹wz¹txµqt²rx·qs°nt±ot¨jr§mt©flªgl®fd½h^Är\ÇlSÅcO¿[RÐw_ꯂóÅöОöΜöÏøÏš÷М÷МøÍ™ðœ鵅à›tÉrXžDPx Dz(H9N CRœ>Q™8Lž>Nœ=Oš?R§HT´PY´TY°MT¢HTœCR˜=Nœ@Q¥GU¤JYm*L~:\—\rŸp…¦}Œ­Š˜¶™¢¶˜˜¼–˜µ…‰©pu—P^u!@`9v=£;GÆVXÚsjä„qè{ìœzîœ}ìœ~ëš}ëš{îž~ï¢|î˜yétékârhÚ‡Ê~‚¢Xx{/Qf AL=Q>V@Q;T>]@UA^Dr3\\@e#HeHTCUBQC\K…JxˆK}d!Mk-W\KKCQFr<_v8gLDNKf1c‡T‚GvYQ^$Tl2jo3fh,fn5s|Q‚ˆYy>v–k˜¡¨šn—˜pž|¯˜n›¦†ªŠEodƒq%Ux|ª…ª\O¾”“še‚L<N<OCR=€3Fr%Dn@p"Ad@`A^@TCb@aCq&Ht.K_D_=Z>\;r#@{*Dz$E™>P¾QUÂSV§EPr<b<r"D“9M²PbÊTVºER¾O[Ìbf×fdÖ^_×\\ÚfhÚhfÛhgÛilØheÙljÛghÚhiÜikÚghÛmpÜqpÜnlßtnÞxqÞzqâ~rá‡{â‡zâ…}àŠ~ã~ã‘䚆â‡âš„㜈枎ä§ç¦‹æ§Žè¬’ì´–ë¶˜í¸›ï¼›ï¾žñÁ§òĦòŬôȰôȲôÍ·õмõÑÀõÔ¾çͶ—dwi@Z8a8n8{'@n>r%Ch=[A¢J[ד†Îq`ÂvmÇ~vÅ€vÀtÅrÁ~uÀ€uÂ~w¿|uÃ}zÂxt¾xvÁ|v¼xz¼||¼wv¼yy¾ut·tt²rvµqt´rv¯mq«luªjt¬il®in´hfÄmZÌsXÌqUÆhSÄ`SØ„f﹄óÉ™÷Ñ öКöΜ÷К÷Θ÷Í›õÊšðĎ讀ւd¸XPŽ1J{(HŠ4MœAN¡CQ™:Mž=NŸ@NžBU¢FV¬PX²QY¯RX«LS£DTž@Oœ:P¡AQ HX¥KYZ<n'KˆKfšf|¤wˆ­Ž˜·œ¢»šž½š˜´‹¬xzž\dz.G] :t>Ÿ9HÆXYÜphäƒrèyìž~ðœîš|ëœ~ìž|î {ïž|홀ëwæ€jàvtâwÍš¥ª_p‚2Tk"LO>O=R>R>T;\AUCu<bh%LUD\#J^A^GTBSHf%UŒS~…EyXBx=dj$QOBNCd)RTWOPH_(Zz>tt;f}Cy_"Zh-bw:ps6ni4ih2f‚[‘€D|“i–ŽZƒ[Šb’Ÿ‚²x§² ¾¬yžª[r[Ie*J¿¨¯:p°€„º›L>N 8M:Q>{,Bn$Fm Ar%Ff?eB_@V@aCcCl$Fo$Ea"HbH]@Z:q#>x(B|$Bª@LÃUXÄRT°EJ|!:`:q$B’6G§L_¾GTÁMZÒ[aÚcbØcdÖ^aÖ^`ÛcfØefÛfmÚliÙkkÚlkÛgcÛkkÞhfÛjmÝnlÜllÝrnÞpnÞxrÞzsàzràuáˆxâ†yà‰|áŒ|äŽä“‚ãš„ãšˆãž‡æ¤ŠæŸŠè¥Žç®Žè¬Žê±–ê²“í¶™í¸–îº ñÀ¤ñÀ¨òìôưòǵó̶õ̺ôÑ¿öÔÂô׺պ²†<TX;_:m9u=h:r @iAaB´\eÖˆzÌl^¾wpÄxpÆ€vÄ~tÄ€vÆtÂ~qÃ|u¾|rÄ€uÁ~w½|vÀ{u¾{x¾{v½xwºxz¸xzºvy´rtµxy®ru®ns®kt¬ip®os®gj·jcÈpXÍpSÌrVÈpSÇjWà”mò½‡öΜøÔ¤öÑžöΞöМöΙ÷ИõȒâ¢zÉnX =K†,K‡/M”<N DS™>Rœ?R EV¡BR¦FW®OZ¶U\´W\­LVž@Pž@Pœ@R BT¥L\£J^ L\P 8\?z9[Zqžs…²”š·˜ ½ž¡¿œ·Ž®{ fm€1I[ 6n<˜7LÉXXÚvlå„té’|ëš~î|îŸ}îž|훀íž|î {íšzésè„fâsgât`Üž¥Wy‡@`v8]K;M<UBR<VAXAZEƒFl\DUFSDZ*Q]F\EVIm(X—aŒ…FuUBl2Vi#NQ7O @RD‚Jnt4iQJUK}J~h$Yw@l~Bf$^~L}~Gxq:t`(an<qI€h™|@t”_Ž˜k›d”{©´ž¹¬«LtN@HC‚Q`–^Ž£tɬ´M=J 8H 6R :x(An&Dk@z)Dd=d>\>V>]A_Gt3Ts+J`B`Be(L^9p>t<†$@²DNÅTVÈUTµJK‚%>` 7j=‰0J£H[ÃTZÎUUÖY[ÙacØedÕadÖchÚ]`ÙdhÜegÜfiÚljÜlfÛmlÜlhÝmhÛjjÚllÜmkÝmlßvtÞxsÞ|uà}và‚và„}à‡zà‰~âŠyãŽ~┃㔃㘄䙈䟉䢋ç¦åªŒè«ê±•ê²–ì¶–î¹Ÿí¼ ò¾¤ñÀ¦ðªòưñůòʶö͸õϼöÔÃõØÃïÖ¶½‘”\<X:d:r1Kb6q!?]>b@¾kkÌ‚vÆmbÁwqÄ}tÄ‚{Ä€tÄ}tÄ}uÃ}vÂ|r¾uÀvÀ{t½xrÀ|x½wt½xu¼yyºvu½vv¹ux¸tu¶uy³qs²ps®lt¯no¯ls°ge¹eaÅlZÍoXÎvXÐv[Ðw[ä¤uòÁŽõЛøÓ¡õΜøÏ›øÐö͘öË•õÈ“ì¼~Û”r´TNŽ.D‹.H”6L›=N@Q”:N FT£FU¥DS­JU¶TYµRZ®JTBPš<Ož>NžBR¨GU¨JW¦M`ŸJ_N 5V8fGBašk‚®Žœ¹ž£¾¢£Á¢¡º”–±†ˆ£ot6P[4d7“2FÄV[Úulå‚rè’yì›ìš~욀ì›|í |ì €íž{î™yítè†jàxfÔdb·Y\Ä“ ‘JYw0MG <R?VCSAXAZDo3[l)LWATAXFYJVBXB\Im)Y–g‹…K{PCg,Vp*RV?S@L @`LƒAns.fQDwDug#Zd*[†M€z>yw@s†Q‰…W‰Lˆj2lq=r‰\‘z>v™oœs£‰Xz¬°›¸§ˆ£ŒRz_"UD Cd&U£z®¨yˆØÃÂY@MEF?P<w*Cv&Cp>~/I`>b=_=Z=bB^Cq(Gx/L\BcF_C^:n?s=•2H¸LUÁRUÇSR±DJ"<^ 8d@Ž4N¨K^ÊPTÐRT×][Úbb×^\ÖaeØahÛcgÚb`ÛdbÝgcÛjeÛmkÛigÜkhÞlhÝmiÚmlÜprÞrlÞrqàvnàuqáyqà}ràuàˆ{à†zàŽ€âŽâ}㒄☄⛆䟌堊è§ä¤Žæ¬ç³˜é²‘뵘츙ð¾¤ñªòìòůñŰñ˸ó˸ôͺ÷ÒÀöÖÄõ×»äÊ´ˆE]X>b8j9a7n<W
+8f;ÅrpЀuÃk_ÄvpɃyÈtÆ~sÇ€sÃ}sÅ}rÃzo¿zpÃt¼zt¼wu½wv¼xvºwvºxv·uw»vuºvw¸ss¶tt´sv®os®ps®jm°gl±ed²a]Ãi\Ñ}fÚˆbÞ–là t곈òÄŽöРöÒžöМøÑžøÐœöÌ–öÊ•õƉé²|Ð}^¦DL‹/J•6Jœ;L >P˜9N™@T¦GR¦KZ®OW²RW²SX¬FR BP˜:N›8L =L£JY©IW¦J\ H\œLeJ5K 4^Bx6Y˜mƒ®Œ—ºŸ¤¼ £ÀŸž¼–š¶ˆŠ¤ov8NU
+4\ 3,@Ã[XØrdâƒrè}ëš{íŸyìŸxê™{ì™xîžð ~ñ{í’vë‡käxfÕdZ·P\Ì“z2R^CLAVDT@R<[!N^!Jj&O]EU?WBZGVBT>TA[Go,W›m”~BrQCf'Pz8^^EN 9M <QF_K„Dq|;qt?qn.dZOq2dz@yw<w‚R‡Š\ŒŒ^Š~Ji0fzDyt:te’£y¨Ÿ‚µœušª‘ª’d…bCh)VRFr&Z³Ž°¾‘¡ÖÄÂ` GI?G>P9€0Et!>w!>ƒ2GaAb@\BXA^D^ Gr)Ep"E\A_?_A_:l<p<š:H´CJ¾INÀRS³AHŒ)?`>i=–:P­FRÊTWÐRT×\YØ``ÖXXØ^`ÚfeÚcbØ__Ý`^ßgfÛdfÛlkÜlfÜmjÝlhÜlfÝlhÞtsÞuqàyvÝxtÞunàztàuß~tâ„xà†yá‰{àŠâ㔅㗆♇䜊䢎å£å¤åª’讔箘괕캠캜ᄂð¿©ðîòƱñÈ´òȵô˸ôνöÒ¿õÔÂõÖ¾óطÕ™[8\9f8^ 3a7R
+<t>ÎzqÒˆÁmgÄxmʃrÈ‚wÅ~rÈ|pÄ}pÆrÀ|qÀ{sÃ~s¾|x¼yw¼zw¾xwºyx¼us¶st·svºxu¶st´ss³ru«np«jn«hk°hg²_a¸hfÌxhÜŠqäžuê«xì´òÁŽõÉ—÷МöÒ øÒšøÐ›øÎ–øÌ–ôÆŒñ¿†ážlÄgP›:H—5Lž9N¢BPž@R8O¦BQªHU­KW²QX·TW´NV§DNž=O”8K›;M¡?N§JX¨KY¢LašJbL`L 6M<[Dq-T–ay®‹–¼Ÿ£¾£§À££Àž˜·Œ¦rtt(BP 4\9.@ÇWTÜtfâ„nçvꞀí¢zìŸzì{ìœ|í zðŸðš€í•têŠiæ{fÕc[ªKd¢Ub¨s‡TAM@YFUAR=ZCf(N_D^AYAYDUBUGYESCUK|<j ¢w;hQA]C|=^\CM:R?[LVJd&Vz>i‚Ftv:nYJr5mf-\Hƒ}FxŠ\Œ‚R‚~J}r9pvC{s6q…T…¦‡®¨´£~­¨Œ©¢„¨^KRCz8meR­†¦È¨¶Ìµ¸T:I ;B ;N <.DnBw&BŽAT\?c>[@[>`@b@q&Ai!B[A]@c#FfBp@~(D¤AN¾NN½JL¶>G²DH–0Ag7o;—<N¬HTËTXÑVYÚ]\×`]×XZ×[^ÚbdÚecÚedÝgdÜhdÜfdÛjkÛibÛigÝldÛlhÜnkÝsrÞvqàsmßphÞxràwqÞzqáuà€xÞ„wàˆ|áˆ{áŒ⒃䘊䘇䜉äŸåž‰ä©’æ©æ°–毕貕꺠컟ðªïÄ®òƱñDzòÍ·ò˹ò̺ôÐÁöÔÃôÖÄöØÀäʵ„<UY 8`9W
+4_4K4?Ñ€tÖ†s¿lhÇ|rÊ„rƃtÆrÉ€vÅ}sÄtÂzvÄ~uÂ}w¾}u¾xs¿xv¼vrºwtºro¹rr¹rs¸st±tx´pt²ru®lo¬fj¬hk²b^ºb`ÍshÞŽtê¢zí³„ð¸†ñ½ŠóÅ÷Ì™÷ÒžøÓŸøÒœ÷ÑœùΘõÈ•ôÆë³~׊a³ML›:Kœ=L¢>M¦BPž=P¡AN­GU¬IR²MT´SX´OTªJQœCT–=N˜>Nž?O§EO¨LW¥JWžF]™K`NbH
+6R@XBl(RŽYtª‡“º› Â£¤Â¤£½œ˜·ŽŸipo+HN :]9“2DÄWWÚteà‚së‘xì|ð¡€ì |ìŸ{îŸ}î¡zð ‚îŸvì–uë‹kå|hØha¸e~¬_p«hjPHWLZHRDUE`&N`"IXE_EXBX@VCZH[BRKXRW„¤¢x8cNAQ>}8\j(NN 9bKaMUA`(P\K[Eb%SVIu;mf&\{H}‚E~ƒR„~J|xE|n4kwB{r:uˆVŠ£|¤¥Š²w¡£‚¡¨ŽŸx>qK?_J^P¦~™Æ³½¶•ŸJ?K=KDTA‰8Jv&Fu$C’CU_EgA\D^HaAcDt(FfEY<Z<_>i;r=1H°FL»HK­?HºHN¾PS›0@f:l>š>O¨CRÊPVÕ[[ØaaØ_[Ù]^×\`ÛcdÜhbÚgdÞhdÞidÛfbÜf`ÜhaÜjdÜkeÜmgÛolÜliÝpnÞtnÝplÞsoßyrà~sà‚tà€x߃xá„zà†{á€â€â–‡â–‚âŒâšŽã¡å«“媓媒殕籖궛뻠ᆭðÁ«ñíòǰðŲñ̺òʸðÌ»óϽõÒÂõÔÆøÖÁò×·¼…ŠZ
+4\ 4S.\
+3O6ˆ.EÐ{lׄrÁqnÅ~vÈ‚sÈ‚tÆ„uÆ„uÄ|rÅ~pÈ€tÂ~rÃ{tÂ|r¾|x¾|r»utºyv¸ts¶ts¶tt¸tr²tr°np²nj¬lm®gi°ffµd^ÆofÜŽqé§òµ‡ô¼‡õ½‡öÁ’øÈ“ùМøÓ¢ùÒŸøÒžøÑ›ùÍ–öÈŒñ½‚ä¢oÊjR§@Jž8M >M¡?LŸ<M AM©ER­LV°LU¶RVºUV²LU¦DN™>P™;M>P¢DT¨GR¨M[¡HVšCZ›NbœPdI2L
+5V@j,WŽVo«‚¶”žÀ ¥Ä£¢¼œœ°Š‡ kpt-HL5[
+4’+@ÃXUØr_å„qê“uìž|ížzêžzëž}îœ{í¡xï¤}ñ €í–yêˆlåyhÛg^Ø”“¯epz?]NEa GR?Q@a#Od%QZDX:`BU>T>[F\DUBRIa%Zšsžœu˜v2XL>O=l+Mm(OR<i)Qf#KUDb.XWLO?ZO\Ph.[r4jj8j‚N†R‚‹^’|L~s?um4rg2nˆZ‘¢~¥žy©^‘¬Ž²Ÿt–_†YGNFZNŸwŽ¿°»†VhREI
+;I<]>Ž:Hr Bz'C†5I`<j D^A`<a@e>p*Hf(K[B\<b:n?u:–:H­>F²@J¼GPÈZZÅST6Fg<o;™BU¬HVÊRTØ]^Ø`_×\\Ú]\Ú``ÜhdÜfdÜdbàhdÝheÛhdÛb^ÜfaÛhbÝibÚieÝjgÜmjÜtpßqkÝroÞtlÞxrß{qà}tà~wà‚zà‚wâ‹}àŽˆâá“à—„ã—…ãœŒå¡‹ä¢ä¨–殗宗泖鵜깢Eð¾ªï«òÅ®ðIJðɸñ̹ð̼ñͼòÐÀóÓÂ÷ÖÃöØ»àÀ®u @X:P2X 4N8”?OÏzgÑ|lÄysÅsŃuÅrÄpƃxÄqÄ€pÄ~pÅ~pÀyoÀxt¹|x¼xt»xv¸tr³no¶pq·roµqs¯ru¯np®lqªhj¬ef®ef¹baÔ€q殃ò¾öÅ•ôÄ“ö¾‹÷ÂŽöÈøÒŸöÕ¤÷Ò øÒžúÑ›úÍ”öÅŠì±sÚ‹a¼VN¡<N¢<J >K£;IŸ:K§DN®JW°MV´RV¹UX¸UW«HS?N—@Sœ:MœAR¥JS¨IR¦JXžH\šI_žSgšQeI1K3O
+7bJŠRmª‚³¼ž¤Á¢¡¾Ÿœ±ˆŸmqv0JQ2^7Ž)>ÁTTÚrbå„lé‘vëœ{ì¢xíž|ì {êžxí ï£|ðŸzî—tìŠhæzcÝf]ØŽˆ¤^jn9ZN?bJTC]Gh)O^DWAV@Z?XBT<_IM 9L @NIyJ‡žp–œjŽu.ZNCQBYDa$LT>r4\cJYJZJ[$PTCXKWHZLt3ji0bw=v„Q„c’~H{l6ik4n`%f‡Sƒª³—nš•j›¦²’m”ž|¤“_’j)hd TªŒ¬««v;`’s¡J=H <b@Œ7It$F|,H~*DaAg>c=d?b>bBg?bG^$J_De>t"@"<™5GÀFNÄNQÊWZÌWVÇSR 8He 8w"BŸ?N´JUÌOPØ]\Ø`dÚ`cÛaaÛ`]ÜgdÝdeÜc`ÝhdÝedÝfeßd_ÜeeÛebÞfcÚfdÞlfÛsqÛrjÝrmÜtnÝrjÝwoÞ{rß|tÝ}vß‚xáƒwá‡}âŠ{ãàŽ‚à“†â˜‡âœˆåžŒä Žä¤Žæ­•å­˜æ±—ê·žê¸ î»¦îÀ­ðÄ®òűðɲðÈ·ñȶîͼð;òÑÁôÐÁöÕÄ÷Ö¾îÕµ¥fpP 6N5U3P5§LXÒwdÐvnÈ{qÄpÆ‚uÇ€tÄtÁxÄtÁ~tÄpÄ|p¿|vÀ|qºtq½zr¼wr¸tn¶tr¸qn´rp±or­ln­kp®moªln°kl°`bÃjbáž}ñ¾’÷ÌœøÏ ÷ÌšöÄ“öÄ‹õÉ”øÐöÔ ùÔžùÒŸ÷Ϙ÷Êò½€çŸjÏsX¬JI¡<I¢>J¡=L >M¡?O®DN°GPºSV¹TW¼TX·TZ¥ESš=P˜:N>N ER©NX¦MX L[šJ`šHZ™Mb•H^G0I 2L6^D„Jl¦{г‘¼ ¢Å£¤ÂŸœ¸Œ¤rvx1KP0\ 6†&?¾VWÛr\å†pì”vìž{ï {ëž}ì {ìž~î¤xï¦zòšwî’qì‰dçyaÛh\Î}u’HdR>PAdH\Id"N]BZAV:W<X?W@ZBXAJ =J D`*`œz§›f‡—f„q0XL>NAR=` H\Dr-S^AbJS=ZJVCa"QWHTHl,\b)Wj4ju@o˜pšˆZˆ^ R^![a&e…X‹¤ˆ®žz©¦„©¨­B|€Ll¢~¥I~™k¤¶¤Â¡w« |¥À±»\GK?d>„,Dk?x(Cr"Dj Bg@j"Di@`?c>h@b@^DdGhAu?’0E±GTÊRSÌXZÍY\ÎZWÆTR¢:Hg9~,G›<L³LTÐRTÖ`]Ø`_Ø`bÛhfÙdaØgiÞe_Üfdàe`Þd`ÛcbÜhfÛhfÜf`Ûf_Üh`ÛnhÜomÜpjÜqmÞphÝtnÞslàymÞ{tà}uÝ€vàƒ{à‹}áˆ{áŠàŽ€áŽ€ä™…âž‰ãœˆâ¢Žä¥‘æ­‘æ¬—å±–êµœé¶ í¼¥î«ðªðűðÉ´ðȵñʶðͼòͽñÎÀóοõÓÃø×Ãôض̜”T
+2D-M2R 3´Y\ÎreÐ{jÄzpÆŠ|ÈsÆ‚uÄ~vÂ~tÁ~tÁztÃtÄ{u¾{q¿yu½vq¾wo¹xtºxr¹sp¶qn´rt´qr®kn®jm­mu«ik¬ei´aeÊp`ê°ˆòÉœøÒ¥øÔ¦ùОøÈ•öÈ”÷Ì™úÒœøÕ¦ùÔ¢ùÓœøÐ–öÆŠí²tߊ`Â\O«BIªAJ¦;F :H 8H¥<L¬EP´KS·PU¼QSºRW­JTŸCS›<O˜9O AO¦JV¥KZ¨O]žJ^›Lb™Mb˜PcŽDZG 4I3N7[B‚@b¢t‡´”¾¡£Å¤¢ÁŸš¶¥tx9MT 2[ 3Œ"<ÀVXÜoYä†të’uî ~î¡{ìŸzì|î¢~î¡{ï¤zð xî˜qìŠhå|eÚh^ÊrlF_VF\Je"Lf$N`HR :YBS;[<X>XAYBO@MEd&XŽ_’Z‚‚Fg…IlbINAM?QD[Fj)Pp,TU9b HO 8O=VEh*T`"PP>k/^d&V]&\`$[‹d’g”g(df.htE‡‹c– z¦Ÿ{¦§‰²®’³ z¦ˆDq¦r—x5h¦ˆ²®•±lˆ’qz†_jQ@V>n"@}(Da?r!Bm!As'DeBf!Bl!Bd@h"Dd<c=`?f@z&F(F¡:HÄTRËSXÏZZÍZ\ÎWVÅTV›-Dk;†6LŸ@O¶LVÑTV×WR×][Ú]`ÜdcÚhdÛgaÝefÝicÞfbÞf`Üd^Þd\ÜecÜgbÜhdÜidÝhdÞljÜlhÞnjÜrkÝrpÞxtÞvoÞzsà€xà‚{á…zàƒxÞ‹}àˆߎ€â„㘇ãœä—‰ä¡ä¦äªå­˜æ¯šç´œç¶¡ë¹¥î¾ªí¾¬ðƳïIJðǵðȶð̼ñ̽ðÎÀñÏÃöÑÀ÷ÔÄöÙºãİr)EE9H4X 6¼_[ÍndÎwkÃxsÌŠ{Ä}pÆ‚y€sÃrÂzpÃ|pÃ{sÁ}u¼xtÁzr¾wp¼zs¼vp¹xs´ql²on¶sn´pn­mo¬kn­gh«de¯bd¶^_Ñ}iôÍ øÖ¨øÔ¦ùΚùÊ”öÌ™÷ΛøÓŸ÷Ô¤ùÔžùÑšøÌõ¿‚è nÖvU¼NI­DL°?F¤=H¡:H 7F§AN«DO´NV¶TWºTU²MT¦BP @R›>Nœ>R¡FQ¥NZ¥L\¡L\šMa˜Pf˜K_“J\‡:RH.J4M
+:\CDc t„´’›Á¢¤Æ¨¤Â¡œµ‘¥xy‡BTU 4\
+4†#;¾QRÜp_älë”vî›yíž{íŸ|îœ~îŸ|î¡î¡xð ~ì˜nëŠjå}iÙjfÃbbŒCdbOh%Rj&RZEXGS>X>X@Z<[>Y@VDRH^L’d‹|Fj^LƒNz~Bdg.XTEPCSF\!Kv4]k&LR8`GR<Q:[De(P`#RK
+=a)Rl.`a [j:p‡cœŒZŽŠ[’~L†TŽ‘f–¡x¢¢|¡¤z‚Knœw ¤z¦¨²²Ž´Ç®¶¡}[BG9K6f&Kk"@y(Bs @]@u"Bj>n$Bb?f Bf?a?l$Ad@b@bAoA€(B-F­DKÎWSÒZXÒ[ZÌXZÌTTÀLO&>g:‹<P >M¸KTÓXVÖXVØ\]Ú`_Úb[ÚebÜgdÞj`ßf^àgdÞh^ÜgcÜf_ÚheÚjgÝjdÝjhÜhcÝnlÞphßpjÝrlÜpjÜvpÜxnÞvmà~rà~uàwß…à„|á‰~âŒâŒ€â‘„㚌ä‹ã¡Œã¤å¦‘䮘沚浘踣뺦뽩íÀ®ïƱîÄ´ïÆ´ðÇ·ïʺðÉ»ï̼ñÏÀôοõÒÂöÕ¿ïвšYhA1H5a:ÀlgÎl]ËzjÄytÈŠ|ÄrÂ|rÂ~rÀ~vÀ~sÀ~t¿|tÀ{r¸xu»xvºxt»yrºzv¹us·wr²rs±rr²qq¯mm¬jm¬fg®fe²`a»b`ÖŒrñ¾ŒõΞ÷Õ¦ùÒžöÍ’öÈ“÷É‘øÏž÷Ô¢÷Ô¥øÑøÎ—öÇ‹ï²záŽ_ÌiT¹NP´IM°HO­BN¦@J¨?Jª@K°GP»RR½XT´MR®IU¢CR=N<O CS§KZ¦O]¤N\žL_˜IZ–DZ”E[ˆ<Qˆ=XF0J6H5[A|Ddžvˆ°˜¼Ÿ¢Â¥¥ÀŸž¶¦yy‰JY]8\ 3…$?¸PTÜqdæ„pê“vìŸxìœ{ìœzëžxêžsèwëxîwè‘vä‡rà~rÖplºZm”Lsl'Xg%Ne"PTAS?T>Y@W<X=Z>WGZLi*Zn2[j.PQHYJ”b†~<bn2XVBTARB`!Lw7[h#JT@XAU@P@YDf&Rf(WL A_(QAq_OTIf/`n4f‰]Ž”kž•s©–jœrŸ¦‡¨—i|6p‚Kršm›v¢²‘´º•«¦€¨†YŒ^&Z`'IBXX<x,BjBdBz&DfAn$Dk"Dk$BeCd<o"B`=c<e<}!@‡)@–4G¹GMÍXSÑ\ZÏZXÎXZÍ[[ÂPN…!<h8;N¢@QºKSÓZXØ_`Ú`\ÚbbÚ^\ÚdgÜgfÞfaßlfàkfßebÜdcßf`ÜfcÛe`ÜffÜhcÜieÝidÜjfÞjbÛliÚpmÞupÜumÝtlß|tß~và‚zßy߆~áˆ~àŒ€â‘„á”„ä•ˆä›Šâžä å¦”䭘江粚綞꺥뺨ëÀ¬îIJî²îÅ´ðƶðʹñ˽ð̺ñÍÀòϽôÑÃöÓ¾ô×µÇG0D5g9ÃigÐn^ÊwkÅ|vÈ„wƃv¾|vÀ~tÄ~p¾~t¾{p¼{s¾xm¼yv¾znºwp½zs¹xt·xr¶tq´st²st±pp¬ovªjl®lo¯fe´c`¾jhÛ’wñÀ÷М÷Ò øÍ“öÆŒ÷ÆŠö˘øÐŸúÕ¦øÔ¢ùÒøÍ’óÁê¢nØy[ÄaT¼RR·KL³EJ®GOªAIªCL«BM°HP»PQ¼RU¶QU­IR¢DRœ>Ož@P BR¥JX¥LZ¡L]žJ^–JZ•CV‘@Tˆ9R„5RH3F0L4W?w@b tˆ¯š¼¡Â¤¢¾  ¸”§z|Uac:^2„ =·NPÛodæ‚në’ví›|뜀痂æ˜~ä˜|ß”}â—‚åšä’{à…uÝ|rÒki¸fy§kk(UXFYJTCVDW@X>W@`HZFWHm3\€Fp]EUFTGbM…Ai~<d~>bVCWHTDc*Pd"Kf(QXCU>VFTC]Jj1ZXFZQi+V}Bpe%VTFUJZXm:njœœ®špž”d“Ÿ~¦–l—ŒU~}>hs:_zQp’s•’b°ŽŸ¾˜«£x¡ªv “Rz>nŽGfo&Hf Cj Bk F}0L‚9Pm>e@hAi>d;`<f<†(AŒ)@Ÿ5DÀIKÌZXÏZ[ÐYYÐW\ÏZX¾NR?j<•<N¨GTÃRRÖWR×[WÙb^Ùb]Ú_\ÚefÚjiàidßojájbÝhdÞe`ÞjcÛbYÜ`]Üb]ÜfbÝg`ÜjbÛlfÞndÜpgÛmhÞqjÞulßvrÞypÞ}uàxàƒxÞˆ~à†yÞ†zâŠ~áŽâ•„à”‡á–Žâ¢Œäª’ä«“å³˜æ²˜ç³Ÿêº¤ê½«êÀ­í³î²îųðƸðÉ·ð̺ò˺òÏ¿ò;óÏÃöÒÀöÔ¸Û¸©`<D6w:Æh^Îs`ÇzpÂ|sÆ„vĉ{¿|t½ztÁ|pÀ|t¼yo¿yr»zpºzt¸vt½xn¼wr¹wp¸zs¶ur´ts³ut¯lqªoq¬kp®gg°fe¹c_Æmcà–zòÃöÐ÷Óœ÷Ê–õÄöÄ÷Ê”ùÑ›ùÔ¦øÔ ùИöƈð¶yâŒ^ÎhUÂZTÄXTºLN²GOª=G¬AI§CMªIT¬FL¶PV·QR±PT¨DOž>Nœ;K>NŸHV¨MY¡I[¢Pc™EZ”JZ’BZŒ<T‰>Y…6RF/D2J:U>v9^šj}²—Àž¡Ã¤¤À¡º•¬~~U]]7[ 0‚#<·JNÚl]çƒlí’wîœ{ï~êœ|æ›~曀ãšå †èœ€è“qè†nâygÕlmÆr„®bl&Rd&MRBVBX?W@X>T<`B]DXBe*Ma#GUA]HZKYH‚Bk}?dv2W^HRD_#Lc&OWC`$J^EYHZEZHZGd*S^R^P|Bk}@qYJTHF BQNi5nf˜£„¬“f•™r§˜qš˜pœ†Fl†JuM
+7O :i0Kp1XX:h#A†?QŒG[†Rp o“¦lž\Œ¢sŸ˜_‰”Y{†>Vj@n @c>c;k>a;e>o>†(B™4I¨@NÇOQÐ\ZÏWYÒ[\Ò]bÒXV¶HM%FtA›?P«HTÆTZ×[V×]^Úc`Úd`Ûa`ÛabÜfeÞicÞljàjeÝhbÝidßgcÛdaÛc_Üb\Úc]ßf_ÞjeÛheÞohÝneÜmfÞnjßwrÞzsàymÞ~yà~và}xß„y߇{߆~⌀⒂┇ãˆà˜ˆá¡ã¨Žä©”存氚泠鸦軨꼫ìÀ¯íòî±ðÄ´ðƶñÊ·ð˼ñνðÍ¿ñÐÀõÑ¿öÒºè̯‡=WF:*DÇh]ÌtgÄ|sÀ{sÄ€rÄŠ|Ä~sÀ~v¾|r»{x½~t¿}tºws½xo¸wr½xs½xr»yr»zr·xt²sr¶ts®mn¬jnªgh­ge´hdºgdËnbå¡|õÄ“öϘøÑš÷ÈŽöÉöÄöÊ“øÒžøÕ¦úÒ¢ùÎ’ôˆé¥jÙyYÇ]TÄTPÅXV¹KN²JP¯BL¬CM§?K±DN³JNµPS²NR¬DL >Oš<K9HžBQ¢KY¤N\ L^šFY˜DX˜F[‘<SŠ>WD[‰AXJ 4H2G6R>n1U–dx°Ž•»šžÃ¥¥Ä¢Ÿ¿œ™®„„ŒS`c8\9‚"@¹NQÛk]æ…kê’yìš{ï›yìžyìž{럀ì|í¡|îœzë•tèŒkäzfÕwuÆm~˜Fjd"ObFXG[DW@] FX>ZA^BY>U@YBVD] Jc#LXEXFw7\r5^j)PbFYGg*S[HUC`$Gc"H[BY>S@Q@d&R^ RXH†Ott8fL<e,eLE\ Zo4s‡Z‡–lœ}Jvœ‚ª…P‡bŠœlœY~r0cN =`=|FmP>W<x1DI 8N;w/Ir/Jl%Kžcf–[o‘JaOsy/Qk Bd=f!FhA^=f=}'C.Ež6E´CLÎUTÏXZÐZ^Ð`bÎ_cÑ\^­;ItB~(Ež@R¯ESÎX\Øa`Ù]\Ûb\ØdfÚcbÚgfÜjfÞigÞkdßggßgbÞd`ÞjfÜfcÚbZÛc^Ûc]Üe`ÚgbÛgfÝkeÜohÛplÝohßsnÞtnÝzrÜzvÞzwà‚yà„vß‚xß„yáˆ{à€à“‚㑅ᙊࠊ⢌ã¤äª˜ç²›æ´¢è¶ èº¨é»«ì¿¯í³î¶ðĶðÆ´ñȹðɼï̾ñÍ¿ò̾óпõлñÒ®´pzF5‘8JÉi\ÍvbÃ|r¾|rÃqÆ‚s„xÀ|pÀ~rÂ{u½|u»zt¹xnºwrºzo¸xr¼xo»yt¸xt¶wt¶vrµur³rqªloªnm®lm²ki¼hbÌn`䤂ôÁ‹÷͘øÒöÈöÁ†öÄŽöÊ—øÖ£úÖ¤ùÑ™øÈŽñ¹|ä•bÔlUÆVSÀPRÀVX¸KP°HN¯HM£=HªCM±GL¶HJ¶KN­FP¥BL8I˜8Fœ9J¤FS¦LZ¤N^žO_–>T”CX”FY=RŽAYŽA[B]I5H2I
+8R?f%L’_uªˆ“¹šžÂ¤£Ã¤Ÿ»œ”«…†Ubf<_4‚%BºLPØl`ãnë’wì˜zîž|íìžvì |ì¡zí¢}íŸxë–qç‹oâzbÓoqÀsƒ—EhbH[A[@d"LZ=V@W=X>\HZCUBYH^"Le(PZFTFc Nq2Yj.Uc!KYD^"L\FXGXGg+Nh-TX@S;N=T>g%SOD\NƒPvr9kMJX$Pv@k,dt@zƒLhš‡[”dŽl …Q‹˜n›žtš–f“\E];„TvR7g>b;H?]@w,HfCYDp1Ja"Ht$GŒ?Mœ]fo&Hh>b;`<_>o@†*A–5F¢<J¼IMÍVXÌXYÎ\`Ð^aÐ`bÎ^[ <In?Ž4M¥FU´MUÔ``Ùb]Ú`[ÚbcÛcbÜggÜggÛlhßhdÞgbÞhdßlhÞjdÝifÜcaÛdbÜdaÜd`ÜfdÛkeÛieÛlhÛigÜlißmjÝrkÜupÜtqÝxsß|tÞ„{Þ„{Ý„z݇{Þ‹}à~á‘„â“áš†à™ˆâžˆä¦’å¬“ç²•ä³ç¶Ÿè¸¦èºªê¾®ìÀ³ïÆ·ïÅ´îÆ·ïȶðɺð̽ñÌ»ñÌ¿ò̼õоóҲРšM 6š>LÇbWÍxgÄ|uÁ€vÄ‚w‚sÁƒ{¼zwÂ|t¿zvÂ~tÀzsºxo»xrºzrºwq¹ytºwu¹xt·xu´vr²rr°oo­no­kl±lm¸lgÀeXÌobà˜sò¹„öÈ’øÍ÷ÇŠöÀ…øÃ‰÷Ì—ùÔ¢ûÔ ùÏ•õĈî²x܆bÐ\NÅWVÀTQ¼RS¸OU¶HN¬DN¢>J¦:G¬EP®EM°IP¤?L—6Jš8L˜<J¢CP©HU¨OZ¢M`›J^–BV˜I_”DW@XAXF^“H`P9L9L ;T>f$K[sª„‘µ’˜À ¤À¢œ¶š”¬†ƒ”Ydf<^:…'F¶LQØk`ãhê’tëšsëžzë yìŸyìž|ì xíŸzî yì™tê‹sàxeÖy|Äv†¦KkgHbEZAdHU=WBS@V@^HUAVFd$Pq/Vg)PVCXKXGj*Wd(Lf(Ng&M^ LR?UDTD]Hu<aUAQ=RB]Fa"NMBl2gt:jk5^s>yTPs@q|Bu?kL|}JvŒg”‰`”„XŠ}Iz‡Zœt¦€¢„Hy[>‡Y|T9d=P<Q>p&Bp<e%H[>u)Dh@m ?a?|-@r&D^@^;[9b:z$AŒ2Cœ6F¯BNÂJOÍVVÐ[ZÐ\^ÎbdÏ_]ÄTV”/DjB“:L¨LZ¼RXÖ_^Ø`aØ`^ÛggÜhfÞhfÝheÝfdÞleßlfàlhàngßmdÞhfÛfcÛdZÛfdÚc^ÛgdÝhbÜjbÝh_ÜmbÜndÝpfÞpmÜsnÝvrÞxoß}uÞ~wÞ€xà‚yÞ‡Þ‹àŽ}áâ‘‚à“€ßš‡âžŠä¦Žä¨‘å­’äµè´¢è·¥é»ªì¼­ê¾­î´îòíŵðÆ´ïȺïÊ¿òͼòÍ¿ðÌÀôξóжßÀ¬o E BLÉfZÌxiÆxÀ€vÂ…|¿‚yÀ€t¾}wÀ|pÀ|t½|vÂ~vºzr½{t½{v»xt»zv¼zx¸xqµwu²tr³sq®nm«mp°pp¶rn»leÄl]Êl`Ú†dê¨xñ¾ƒöÀ‚ö¿„õ¿€öÃŒøÎšúÖ¤úÔžöΕóˆë¨mÚ|XÊWSÂTRÂQT½NR´JN³LV§DM @M¤>J¬DL®JP <H•2E‘.Bš9M¡IW©KX¦L^ GXžJ\•BV”BZ—F\”E[•C\@Y‘Ea“H_L
+4L
+5K 8Q >b L‹Ul§Œµ”˜¾£ ½¡¹˜•¬‡†–_jm$Cd<„#B¶HNØj^âiéŽuê˜xìŸyëžxìœzìž{êž|ìŸzíœyì—rè‰gàtfÛ€}Ðz„´`ufEo&PV>`FQ>R>P ;VG]HUIu7b…@ek'L^CTBTDZIh*Sb#Md$Kb#G[F^JZFVJSGd)O`PO<UA^I^$TPF~Huj+``&V}Myn2jQFyT„NyM‡zH‰‹lœ–u¢ˆb“u<nd&]{Fq˜j }§}8bKp\ CdHL <T?r$@j @`;`;o$Dr(Dg>^>d>i#C_?]<^8j:€$=‘3G¤8H»HNÀJRÉW]ÍVVÍ^_Î^`Î]\¹NS#CnD™:N©IVÄUWÖ`]Øc`ÚbaÞjgÜkhÞifÜjiÝgißkeÝjgákfßkgÞhbÞiiÚecÜfbÜgfÙedÛfbÝkeÞg\Þf`ÝibÜlbÞlgÞtoÞtlÞupÛuoàwqà€tßtà‚uÞƒzà‰~ß‚à~â€ß‚à–†â›†â¥ä¦ä­”氚涢浢漪꽬齭ìÁ®îÂ³îÆ´ïŲðȸîɼñ̼ïʾð̾ò̽òϺìÌ®žVjªGOÍj]ÊzfÀ|t¾xmÀ„x¾z¼|x¼~t¿}w¿~t¼}y¾zuÀ€s¾~w¼|u¼|t½{u»zvºyt¶zv³vu³vt²rr®np´rl¶nm¿peÉo`Ëm\ÐsZ܇`è¤nê­rí®vî¶xõÃøÏúÖ¢ùÒš÷Ê‹ôÀ‚è i×rUÆTR¾PR¿LO»LO´FO®DK¦<I¢<J¥AN«HPªAJ˜6HŠ&@1FŸBR§LYªLY£HUŸJX™BTŽ@S“BV–BW”BX”D[‘Ha‘JaŽCXR<R>N:M 9[F„Jf¥}ˆ´”𽡤À¢ž¼š—®……šdlx0Jj>ˆ)DµFN×i_ã|dëuìš}ízìœzí~é|êŸ{ì }îž|ì”qê‰káxhØvvÚ‡„±WmkFˆ>d\BZAL>NBN@_Im&R~=ey:]c!CX>TAPDTGb(Tk(Qf*S^FYFVHh&R_$LZ#PRJZ$It8hRBbLXG`(\e.\m2[b%Wd$Zs:b‚R‚LLII‡pœœ–ÈŠb’—|±‡d’ˆ^ˆL~i.gd+dŒdž’f”˜n “_šzFp˜}¤N <[Dn AeD\Dh Bj Ap"B`>b@`>c>_>Z8a:p >‹1B–5D¨;E¿LPÅPTÊVXÌ[^Ð\ZÏZXÊVW®DNnC~,JBTªLXÌ\^Ø^]ØffÚgfßhfÞkiÞjgÝhfÝmiÞqpßifág`ßgbÞf^ßgaßf^ÜhdÜc`ÛibÚfaÙe`Þe]Ýf\ÝjdÞldÞnhÝpjÞupÞvpÞ{ußzsÞ}rÞ|tà‚xàƒx݆zàˆ|à‹~ጀâ’ᘄ☄➊㢎䬒䫖洠泠纩黨輮ëÀ±ïóîÄ·ðĵðʸðɼò˺ð̽ðË»òÌ¿ñλðΰ̌‘¸LNÐpcÊxf¹tj¬he¸rp¼wn¼wr¼zu¾{u¾~z¾w‚tÀ~x¼zº|x¼|t½|w»{vº|v´yw´wt´us°op±sqºrm¼tpÄthÈtfÌr\Ît_Ît\ÖZÞŽbà“fê­zöÆŽ÷ÑšùØ¢úЗ÷ÉŠò»}è—`ÒiVÆRP¾MN¸KQ´EM¯DM§>Lž9L£ALªHT¦@N>M’1GŠ.H”9N¤GTªT\¨LXŸHVžGY”?SŽ;T‘AS”F[”H\”BZ”H[H^†8OR:M 7M 9J
+9WB~Ddžuƒ°’˜ºŸ¾¢ž¼›–®‰‰žnu~:Pn?†&C²FLÖi\â€hé{ë˜tîœíšzê›}éžzéž{ìž~îžxì”pçˆnßxfÖprÜŽ‚²Zrs&MŒBb^JXCO?OD^ Nw8^{;^h$K[HSBSBTARDVHj-Zd Om-X^I\I`$Nk)Tm,Uc)RWIPCk,W`$N\HQJd*V‚R‚^GUD]Mc$R‚Zm4fOMS IoBdq?oˆbŽˆh–‹e“p8d\R]TxK|g£©Œµ¡v­¤Ž±ŒfN:^@k@^=T<n?c=d=]8b<`=[8]=_:f:z >Ž,D¢>H¶FPÄORÉTVÎVWÌ^^ÎYXÌY\ÄTZ—3Gh?Œ4J¤BQ½U\Ô]\ØadÙedÚfeÛgiÝnjÞmhÞjkßleàqmâmhàldÞhaÝjfÞieÞh_ÚhdÜc^ÙfdÚd\ÞdaÝf_Üd[ÝmeÜpjÞlkÞpkÝslÞsiÜwnÞxlÝ|sß}tà}sßuÞ„{Þ„vß‹|߉z߂ߖ‚àœˆáž‰â¨ã©ä¬”è°ç´¤è¸¦é»¨è¼®ê¾±î±îÅ·ðƸðɺðÌ¿ñʼð̼ïʼò̼ñÌ¿òϸ䶫ÂWXÒw^Åxa°e`¢Z[©cf«ff®ij´nj¹pk¸snÀxs¿~t¾~wÀy¿€w¹}wºxº~uº~v¸|y´{u·zt´tr¶ztÀsnÅxoÈxnÎykÏvfÐt\Éq^ÊiRÎsZÙ„dë®xøÈúÖ¢ûןûÒ“øÆ‰ð³qâŠ\ÎaRÁPPºNPµJO°>H¦BP¡9LŸ<N§BP©@L¢=L•4GŒ,D6J?R¨LX¨PX¥HZšCV”AV>RŽ>V@T•EX“F]’DY“Nb‰@R0JN:M 6L
+5NAR@zA`žx†°š¸œœµš·™–¬ˆ†žlr€;Pn>†&>µBJÖfYâ{bè‹të–vìšzë›vêœwêžwì{ìŸxíœ~ë–xèsâ{jÓfeÚ†z´ats'K‰?`b I[CUBUC\C`E_CWEWEXEV@ZHTF\ Jd"Nk+Xj+P_ LYIh,Ue#P_Ic"Ld!La!Ij*N]APCLDk6]}Fq\FPEYNl0c‡`ŽBzi/bUKWKVKWNtHr–}¡„X„[K\Rn0lrBs˜o—¶¥¼¨˜§_$JY<d<j?V>X;r!>e!C`>]<b<]8Z9`;e8j:ƒ(A‘.C§>J¿LPÂOTÊPRÍXXÎ^`ËYYÍXVºIM}@lD˜=R¨EQËZZØ_XÜdbÚbbÛghÞhgÜgfÞjfßkhàidápkàsnálfàhhÞhdâkbßldßlaÜhbÛfcÜdaÞgcÞkbÝfaÜlhÛmfÜllÜphÜsoÞwqÞwmÞxpÝysÞ{oß|rßuÝ‚wÝ…{݇~ߊ|àƒâ“€à›„áˆâ¢‰â¦ã¨ä°œæ´ å¸¤è¸¦è½ªê¿­îÀ±îĶðȸðȺðȼðÉ»ð̽ð;ñ̾ð̾òϺïÊ·ÒspÓv^¾iX¢OR–DQŸTZOU¡Y^¢\_ªfj®gf´nl¶qt»xu¾zv½|s¾{»z»€x¸|y¸}z¶|tµyu¸vs¼wpÄ|uÉ~rÌoÐ}hÐwfÐt^ÊtdÅk\ËviÖ†kì·„øÌ–úÙ£ûÖžûÏöÆì¦gÜ|ZÉ[NÄNL¹MP²HN«DP¤<Lž7L¤@NªFR£AO•1F1F1G˜<M CT¨LZ£IX H\™FV“A[<R‘@W”CZ–H[’DXŽDYCW„9Nv'?P:N6J5L;TA‚Fd¡x‡­•¶˜š¸œ£º™—®ˆŠns€<Ps#@†&@±BJÕdXß{iè‹pê–vì›zêxìœzëžxìyíŸ{îœyë•tìŠnå|bÔd_Ðtr®_vx,N5Xl%PZCS@R=X@]B[CZDVDT?TD[JXEk,X_Jl)S[L\!P`'Pz>ag*PRCYE\@c#I]AS@OAP?wBjb J`IUJXNx@ui˜Žg—i0^o6jZHX HLFSO‚`z•mœ[P\"RJ~€Gxr4^˜wŽˆVuO 9a=j>e>R7]8h<a:^8^;]5X8Y8e9g;o>‰*?˜6D±FKÂKNÅPTÊRRÊUXÌ\^ËY[ÉXX£9LiIx&F<L¼PVÓ`\Øa[ÚgcØfaÚigÜgfÝiiÝifÞhdßmhàniáncàpjájdàjbâlbàldàkbßjdÞe\Üg`ÜhbÜg^ÝldÝhaÛoiÞojÝojÞqjßxmÜvrßvjßypß{qà~uÝ|qÞ‚wà‡zàˆ}àŒzá}ß”á˜„á˜‡âž‡â¤Žäª’æ®šå²æ¶¡è¸¦è¼¬êÀ®ìÁ±ì´ïÅ·ðȼîÈ»òʼñÊ»ðͼñ̼ñ˽óϾóÑ´Ý—ÊlX§LN”@J†4H˜HS‘;F–DI˜KRžOT¤Y]©`d«ef®jh²ll·vv³trºyv·xs¶xt¶zx·~z¸|wºzrÁvmÆ{o΄tÒ„jÔ}gÑx_ÐvYËq[Éo\Ðt]Ýmñ¾ŽøÎšúØ¢üÕ™û̉ó¼|ç˜^ÖmTÅRL½KMµEN¨>Hœ:Jš6I<J©BL¦CN—8MŒ,BŠ-F–9MŸFX¤L]¢JY CT›DT–CW:P’@W–EW›Lb˜J]‘DVF\†:R},Em>N 5L 2M
+8M :WB|<]šk|®Œ–¼ ¡Å¦¢Á¢µ– qt€:Or$@ˆ(@´?GÒe\ß|fçŠrê˜zê–xìœzêœxìœ{ëž~ì¡zï yì–wëŠmè~bÖf]Èbd¤Vn~4V„>^p(PT>N?SA]Fa"IYDYGXCTBTC]Ja&Qe&Lb&Pj(SVIWLd,Ur5Xl+PVDT@S<ZF[CTAR@XDr9bTA^ Kj+^\Tj+`Œd•’g’‘h–\"Ki)TZNJ>VLf1To<Z_#WYM†V†[††G~Œ\y}BbU 7g9l@^9U>b<^8^9^@^6T 4X 6]7i=u&C~(C‘,@¦>HºNOÂORÇSSÈSTÊZXÌ]]ÎZT¾PO‡&@c>ˆ/I¢ANÊZ\×fdÚd`Úb[ÙcdÚfdÜhfÞkfÞkfÞnjàlfánlßmjÞpnàlhàjfàjcßngßgdàhbÝd\ÛhfÜhbÜcbÚgbÛicÚjbÝkfÜrkÞrhÜulÞxpßumà{pß|qß~rÞ|tÞxÞˆx݉|ߊzâ|ß’~à•‡à•„á˜‚ã¡ˆâ§Žä°—ä¯œæ²¢ç¶¢å¸¦é¾¯ìÁ´íŵðÆ·ðÈ·ïɼð;ð˽ñÎÁòÎÀñÎÂôÏ¿ôԺ亩·ZV‘6FŒ2D€'?Ž6C„,=‹8EŽ7G“DN˜DR›FPžOUŸR\¤^_§ad§bf¯jj°nn®pq°pr³ut¸ywº~{Ä‚w΂oчtщkÎz`ÈtXÇiQÈiTËnWÔ~bå¥zôÅúÒœüØ¡ûÒ’øÆ‚í²râŠXÏbSÀQM³FJ¤=I–1G“0F–5J¢>L¨DMž>KŽ.F‡(BŽ2H•:N¤N[¤IXœDTšDV™FZ”CT>X•BWšN`œOb•EZŽEZ‰>T€6Mt%@j @L 4L7J 2L
+6Y@o,P•f}¸˜œÂ¤¤Â§¥Á¥¡¸—–¦z|‹G[n!?~ ?®>GÓaUÞveä‡nç”sè—vèœ~êšyìž|êž}ì |ð |î˜uìkçcÛk^Æ`eŸPn€4Z„;^{3[N>N@ZAj%LZ@WAT@RDVGXHj(Qj*RVDd+Tb&PUKWJg(Oh&Jr.V]EXCXAT>R8]DQ>ZFYBWHa,ii0a…X–„NŽƒN„˜pžŸ†©m;p[Lj0\l0hVCe#L`!N\Jd%U‰b•r/Z‰Jt—b‹d CX;b<f8R :Z<c>Y<Y:Z7Y8U4Z6b:l;+DŠ,B˜6G´FNÄQQÇRPÇRSÈPTÌVTÉVSÇVT¤9Dd;r$G’:N®ITÔ`ZÖa^Øb\ÙebØffÚfdÜhgÞnlàmhÞohànjátiÝkgàgeàjeàndándàlbÞlgàiaÞe^ÜdYÜhbÛd\Üf`Üh_ÜlcÛieÞpdÝpfÞrhÞrgßvpÞypÞynÞ|sÞvÞuÞ„v߆x߉váŽzà’á”‚à–‚àš†âœŠâ¤Žå¯˜ä®—ä²æ³¢æ·©é¾¬ëÁ±ëĵïÅ¶íÆ¸ïʹñ̼ðʼò˼óÌ»ñÐÁôпöÓ¼ëʶ±UZ…,D4F…0J‹:L€)B‚+B„,@‹0@Š8J9F“@M“CN–DP˜MU˜JZœR\Ÿ[`Ÿ^d¤`j¨gj¯rs¹tpÄ|t͈vÒzÓŒpÎjÃv]¼eXÂjYÈlW؈eöË•üÕ¡ý× ûÎó¿~éžbÚuVÈYR´FL¥:F˜4EŽ,C2G˜8H¤BP¤@L—6H…&@Œ0F™>N¡HV£NcBT—BV˜CW”CY“AV’BX”D\›PbšOc”F]EY‚8Pz-Fl<n;L3H2H
+6L 8Q=h#O–j|µ”˜À žÄª¤Ä¦¡»›‘¨~~”Wcn<&@­=FÑ`WÞviå†pé“wê˜xê˜xêž{ëž|ì›zïž{ïžvî—xìŒnç~aÞodÃX^¤Uu†6[ƒ<^|6ZP>O>`FdAV@V@VBUCTFZHo0V\HSHl,V^MQJXNk,Vj(Mj)OaF`DY?R@WF\B_G\FSF_'LnErFDpBlˆZŒ|E|‘h¡‘jޡޏx>ua&Vf(Sj(br2az8fv2fEl „šZBf#Br4KbB`=d9]6R 5b@]:W8Z>\=W;W9]5i @q;ˆ0C‘1D£<H¾MNÆRRÊXUÆTRÈSUÉTTÇVT¸LPx;Z=„0NžCQÀVXÖ`]Ùd`Ú_ZÜhbÛa_ÙcdÜf_ÜjgÞjhàlfàleáoiàlfâgbÞjcàofájbßf_ßjeßgbÞe^Þh`Þg]Úe\Üf[ÜfaÜg[ÜleÜofÞmgßofÞrjßrjßvlÝvjß{lÞ|tÞ€tà‚uÞ†xà‡yàŒà‘€á”€ß˜†ä—†â˜†ä¢Žä¬’㬘属洢湪辯꾮ì´íÄ¸íÆºîÈ»ðʺïÊ¿ð;óÌÀñÏÂôÐÁöÒ»ñÒ¸¸rwˆ/G’;HŒ8H’>N‹2IŒ5J†3I†2H†6J„/E‰1D†5D†2E‡4D‰:HŠ>K‹COETIX–P]\f«fjºrlÆ~pЊpÓŠlÎ|bÍ‚hч]Ð`Í|_Ûjðº†øÐ›üÖ¤üÔ˜úÈ…í°và…XÐdN¸JK£<G–1D*A‹,B’4FžANŸ>M›9H.C‡,E”:N¡IY¤J] K]˜BT–AX•FV“@T’?S–GVšLbšRg–I`“H^ŠAW}0Lt*Cg=l:O:J7G 6F1L 9g"Ošl|´’À ¢Æ§ È§¢½œ—ªˆ…œblu">€&@¨>HÏ]WÜvdãˆpæ’tè—zêšvêœ{ìŸzêš|í¢|ð¡{íš{ëŒpè‚cÙk^¨?P¦b}‹:`ŠBcx3ZK <Q>bFX;RAV@R?RB\Km.Vi'OTFUGo0U\KRGXHi(Ri(On,Sc!Lh(ObFP=U@[D\D`K\JZCZHF ARHxF{v:vˆ[‹ašššŸ©Š_–] Rn5h…K€”^‡•[ƒj%Do#>U?X<X=f?h#CcBV6X;`;X:X9X9Y8W8Z=`8o;w <3Eš4DµDJÃRUÆVUÈWVÈRWÈYXÈTTÂPMŽ*@Y:e=”;LªO\Í^ZÛbZÚd`Úd]Úb`ÚdbÞegÝegÝjfÝlfàjdàieápiàjdÞhhÞjhßniànhàjbÞjaáhdßf`Ýg\ÜhaÚdZÛaXÛfaÚd\ÝkdÜmcÜkcÞrhÞmdßqgÝwkÞwlßynßzmÞ|nßt݆zÞ†wß‹zàŽyâ’à”á”â—„ã Šã¨ãª–实岤温軫꾯êÁ²ìÅ·ìĸîȺðɸïÊ»ð˼ñË¿òÌ¿õÑÀõмôԴЖ”†,FŽ9J–>M–BN˜DS“>N’6I6HŒ:L…0F„*A€,Av&By(Ax+Dz)Ay,Cv.Fx.Fz.FŠAP”NV©``¼l^Ær^Î|fÔŒgÝœpÝ–f؃^Õ„câ¢uôÃŽúÒýÖüЕöÀxèšdØuWÀSJ¦:B.B‚;};Œ'?–2Fš8F•2G3FŒ.H3IžFV¤N\¢JX“<P•>T”BV–EW’>T“>T˜DWLb˜Nd‘D[‘F[‡?V~2Hm!>k=k@W9R7P
+4R5R :f"K—hv²’™ÂžŸÇª¤Èª¤¾˜±‡žjtv&?|$>¦<HÎ_UÜwlä‰pæ’wé—vëyë›yêž{êœ{ì¢}ð¡íš|ì’oæ„jÌ[WŒ1N¥bxŒ>`„:[t-WN?\G\AS=V>S=R@YGv6`b!G` LTCTFr4]\LSH[Ln+Tf"Km-Tf'Qf'QaG[ET=d LVA^"K^!HVDN@OFXMQFzJ†€L†’gš‘q¨•ošŸ‚¨‹SŒg‰IxƒBpSu€Ft`FO<V;Z?e=h@\9S8\=]9T7U 6X6V5Z8X:d9r @‚'=š;D©=G»GJÄRQÇPLÉTPÇSRÆUSÆUN¦5<a6Z:,F¢CRÂV[ØbXÛb\Ûg]Üg`Ýb^ÚfdÜhdÜijÞigßjeßieàhfàkeàjbàljáofâneÞniÞjdàk_âf^áicÞjbÝgcÜf^ÝdZÛhbÚibÞj`Ük`ÜhbÜqlÝrlÞphÝslÞxpßwlÞyjà{oà~sÞvÞ„vÞ†zߌ|â~à“„à“…âœ‡âŸŽã¤Žä«—ä®˜ä¯æ¶£è¾«ê¼­é¿°ìŵìôìÇ»îÆ¹îÊ»ïÌ¿òʾñÌÁôÐÁõÏÂõԹ⺭“6M9JšBM˜GTœFSšDN™BQ˜BO–:J8J8J….D-Ew%An Am=h;d6`7c8j <w,B?JŸOR´VTÒ„nä®|çµ|áªp׉dÚŽdê­zøÆúÒ˜ýÔ–úˈð¸qãŽ`ÊaP«?E”/D}"@v>| <‘2J”6I’2F‹,D0H’:OšDS¤Qc¤P_›FY“AT’=S’=S’?V’@T“@TšHZ›Lb—Ob”I^DW„7Rs$?n ?i:h;`<^;b;hAhCp(Lšft²’–¿¡¢È«ªÉ¬¤Ä£·˜”Ÿkpy+E}'A¦@KÎ`[Ûwhãˆsæ’xè™xèzéxèœzéžxì¥}ï£zïš~î’pæ„fÀWY’9T¨i~…6Xp&LeKL>\ IT@R=XBS@[Hf$Lh&KXEb$OYDUDe*P[IQD_$Lo0Tc"Je%Mb#Kc"L\De$Jb"HXBP>R@^$Ib"KVG[HUENBUNxG|ˆV™}¢›„¹‰[šv‘\‰…Fz}Axp0^ŠSxt5bT;R:^<e?]8Z<X@aFXFU<]:T7T 6Z8Z6h9{&@‹-BŸ;I´DHÁKOÇPRÆPQÈUSÉTRÈVO¶AFt6V :k?–;N¶RXÓ^YÖ`YÙd_Ûg_ÚgaÝd`ÛfbÛhfÞhhÝkcÞhbÞhdßfbßjiÞjeßnlàkhàqkáicànhànfàj_ßk`ßi]ÝgcÜgbÞg^Ûd]Ûh`Ýj]Üh\Üg]ÜkdÜngÞocÜukÜ{nÞyoÞ{n߀pà€rÞ€rà„rÞ‡yÞˆ|à|á}à”⚃â ãŸŠâ¦‘⪓䭚峤繧軦꾮ìÁ²ëöìÄ¸íÆºîȸï̾ð˾ðÌÀòÏÃõоõзîͲª]h6H–DQ›IS¡NY¢LTžKTGSšAM•?O•<L‹4G‡,D(Cu'Bo@d<^<X9X:U7]<k ?:Q»ldá¦}î½„íº€æ®rÝ”cÝ’jïµ€øÉüЕüÐøÆ‚ìªfØzS²KH•/@†(@s<} B…(A0D’5HŠ2F†*DŽ6L›AQžHZ¤Sb P^™FV“>P“>R8PŒ=R’>T•BXœJZœPh•LbH[ˆ<Ry2Il"=p <h8g:i8~,C.B~,Dy(F|4Q˜]p³ŠŒÄ¤¡È¬§Ë°ªÈ«¢º›’žin~4I(D¨BLÍ\SÜviã„qæ“xê˜xéŸvêžvæšvèž|î£vð¢zîœzípã„h´MZ™@W¶t„=^j$KbJR>dHR?TEYDf$OdFWAYCWCc#LW>SEZHh&TTBh(Ti+Qc%Mc"Nc Ic"Lb"NZD]ER=SAN <R<l-P_EXAe&QVEXCRJp<oŽ`”£Ž±˜³‘qž“lœu8p†Nˆ˜`ˆ¡n‹~:fP<T;e>a<S7W7Y4X7U7U8T6P6X8Y9d=}$@‡*@•3Dª@J¼HKÈNNÆONÊSRËPNËXT¼LL:W;]<ˆ0H®JRÎ\ZÖ_VÖ`^Ûf_Ûf_ÛgbÝe`ÛhcÛeeÝfaÜhdÞifÝhcÝgeÞllßleàrlßlhâpjànháldàjaáifàj^àjdÝgaÜe]ßh_Üd]ÜhaÛngÛg`ÝjbÜjbÚnhÞjcÞpeÛujÝthÜxlß|nà|pÞvàƒqÞ‚x߆vÞŠzß|ᓀ㜄䞌⟊⨔⫖å®ä´¤æ¹¤ç¹«è¼ªêÁ°ëÃµìÆ·íÇºìÆºïʺð̽ð̽òÎÀôξôкòбĈ‰Ž9J”BQšKT R\¢NV£OU¢MVžKU˜GW–@P>P8J‡2F~1Ht <h@`<Z?R:L 5N:Y?<RÕŒp컇ôĆïÄ‚æ¤dÛ„[à™pô¾†úÍ’ýÒ’ý̈ô¼zã•^À[M˜5C€!?u@vA…&BŒ/F5FŽ2H‚&D„(G”:QžH\¦Rb¢N^—FY‘=SŒ8R‹8QŠ<Tˆ5LAW˜H]ŸSfžSh—MbDY…8Pu(Es'Bj<f=n;Š6IŽ>NŽ:Lˆ6N†9RˆB]—^r­„ˆÂŸœË®¤Ï²¤ÊªŸº™•¤rv…@R-C¨@IÌ\PÚteã‡ræ”uìœzèxéŸwêš|èž|ì¦yï§~í™vê”pß|b¹L]¡D[·p‚’Ffj"LZBWB]DVF^Jq2Zh%IY@VBT?XDa!I[IUHYFd$N^Il,V^ Kb'Mj(Sd&Pf(Nd LVBUESBS?YBR=T:f"P[Bv6`c JVBPDMFq9f”nž“q ›²˜|±†Rˆ‹Xˆ„>q—Rh›_ŠR?W?c?W:X<V:V7S8V7U9S;V>\8^:p<Œ0DŽ.Dž<I¶FJÄQRÆTSÇPRÆWXÈVN¿OO(;a7W9u>¤@NÉVUÔ`^Ö]S×e`Üe_Úc[Úc^Ýf_ÚmhÝgeÜjhÞhcÞjgàhaßjdàjfáicâohálfàplàngàojàldápfÞmdßh]Ýg_ÝiaÞi`ÜhbÜh`ÝicÜi^ÝjbÝj`Ýi^ÚkdÜpfÜrhÞtjÞrfßxjà€nÝs߃vÝ€xÞƒyàˆzàŒ|á‘~â—ƒã˜äš‰ä¤‘㤎䫘峢赦繩缮辭ëÀ´ëõìźíɽîǹîɼðË¿ñÎÀóÌ¿ôÏ¿õÓ¶Ú®¤”=M’>O˜JTŸJS¤P]¥PX¥RX¡PXLVœFS”FV>PŒ=P8O~.Fq"Ai D^8X<N=I :Q;š<Là›nóÀ‰÷ȃóÂzÞ—[܆^çªxô†üËŒü΋ùÄ€é¨nÎoP’0>€!:q>p>z#@…*DŒ/FŠ0D„,Hƒ+IŽ6O™DV¦N_¦Vf˜JZŒ:Q‰6N‡9R‰8OŠ8OŠ8M’>U›NbŸXmžVk•J`ˆ@W‚8Q|2Jx,Gp%Dj>l!A’BR‘DV‘?PŽ?QE\‘I`dw¬„Œ¾ž›Ê¬¤Ì°¨È¬žºŸª|yŽIW„4I¥COÌ\VÚvdâ†rå’uêšxèŸ|êž{ëœwéŸyð¦|ò§}ìžuê“rÜzf¸U_ Lb®ezCct,TQ>SAXBd#J`Ca DYBW@XBZA[DXB\DWE[G]H`%Li)OZFh+Um,Xi*Te&Lf$MR@UDR@P>ZG^GL>b"Gn+Uh*Rd K\KVHXLf,^p:eŒa“ ~¤«—³—t¦|D~€G{’j•Ž_X?^@[<V8V7V9U<T9U5R5Q 1Y6^6h6(>.A“.@¨>G¾LMÅRPÅTSÉRPÈWQÂOK%;[ 7Z=v%D9JÂPQÐ]VÖ^UØ^ZÙg_Úd[ÙdbÜd`ÞhaÝlaÝleÞidÜg`ÞhaßkháhcàieÝhgàpjàleÞlhßmgànhàmfàngÞj`àh_àjaÞnfÝh^Ýf^Þe\ÜiaÜi\ÜmbÜjaÚg_ÜkcÛpkÛpjßugÜsiÞxlÞ|pÝ~oÞ‚t߀tà‚zÞˆzàŠxâ“€à•ƒâ“‚â™…äžŠã¥Žå®šæ°žæ´¤çºªçºªç¾°ê³êÄ¶ìÆµëÅ·ìÈ»îȽï˾ñ̾òÌ¿óϾöѶèDZ£LX8N•CRœOW¢T\¢PX§RW¤PV MUFR™GV=NAR‰9Pƒ2J|1Kq&Ah"@]<T;O<X?<JÞ’iðº|øÄ~ð¾xâ›fã˜jì²zõÁƒùÆ…öÀ~í­qÑzV¢:Cv9t<l>y#B‚&@‹0F„&?'?‚)BŒ3MœCT¡Na¥Sa›L\>Tˆ:N†6N„1Jˆ5NŠ8N@V—G^ Ui¡]pœNd‘K_Œ@Vƒ6Q€5Pz)Fn#?k!@s'DŒ:PBP?PCX”K`—Vj¡n~®ŠŒ½Ÿ¡Åª¦É°«Ê®¢Â¢•ª‚€’Ta†0D«DNÊXQÛtcã†qç”xëœyêž|ì¡zëžzêž|ï¥~ð§ví pè—nÚzc¦L^¦Nh¬`s†@`u*SXB[GX=XCX?ZB[DX?VAX?]Ja%L` HXFWEV@XAZDYGi-Tm.X^!JZIf&Od)STBVBRDVBh&Na#NP=e$Lj,Ud&P\Mb"Rm/^b$Np0\j.\m8]ŠZ‚—xš’f˜Šaf3O[A\@_AYAT<Y@T;V<V8O 4N 5X7`@d8t =†+@”4Gž4C¸HJÁMOÉ[WÆTTÈQP½KEŠ#7T 3T
+4p >š9I¼JPÏ\WÒ\YÖ]ZØ_[×b\Úf]ÚfeÝb[ßhbÜhhÚjfÞhfÝjaÞheÝlgàjcàheÞhfßngßnfàlißkfàlcàohàpiàh]àkaàmfÞhbÞg^ÞedÛd]ÝjdÜiaÝmdÜndÙkdÜibÜmcÛsfßrgÞrgßziÜ|pÝ{nÞ|qß‚tÞ†yÞŠ|ÞŠzà~à‹xß’€ã˜…✌â¨ä§•䫚沢洣湧迭龴ê¶ìÄ¹ìÆ»íǺðÇ»ð˾ò̾òǶó˼öϼðβºtxŠ3D“BP›JTŸR\¤SY¨RW¥SZ¢OUŸKU˜DS–GU”CR8L‹9M…5Jx,Bt'Bf>`:^@jE˜:LÖ‚bí²zõÀ„ó¿î¶yí±xð¶uö¼~ò¸zê¥iÔ{Tž@Cx;j<g<o<|$B‚*Aˆ,D$Aƒ(CŠ1J”<P KY¤Pb›JW’AX†4N€0J‚2L…2K†2KŒ8R”FZMd XmžXr”OgG^‡;T…:T‚8Os*Go"Bk$Ar)Fˆ;RŽ@V“DW—K^—Sgž_p¦v„®‹Ž¼¢£Ã¬¦É¯§Ê¬£Ä£–­„ƒ–Zd‡3F¨CLËZOÙrbá‰zç’téšyêzêŸzìŸvë¢|î§yñ¤zïxì–mÚn—7O®\qªYl„@`d FR>_GT?YDYDX@ZD[@ZCX@ZCb%JbIWGZGYEUCTDc%Pd%Le'QVJVHp4\|>fVBZHVFL@g&Q|@j`LTDf%Js5f\LXLs>gu;raQw@svAp€Oq<l’fŽž„©v@gZ?\<[>U>T>\@T;V8U=N=R 7[:`5n9†,@ˆ,@—3B®BJ¶FOÅQPÈWRÇOK¶DHv9S
+7W<v#@Ÿ6F·FLÊVVÒYTÒZZÕ^XØa\×^YÚf_Úf_Ýd[ßjhÝgdÞlbßh`ÜhaÛebÜmfÞgfßhbÞgdßlgàqhàohàkdÞkfÞolàpkßmfálcàlgßneßiaàg_ÛfbÜlfÛibÜngÜjbÛohÝj`ÜleÝrfÝrjÜrjÜtfÞvjÞxpß|nßrÞ‚wá‰xàŠ~àà‰{àŽã—ƒäŠâ ˆâ£ä¨–䱠峥浦绫農ê²ëÄ·ìÄ·íɹîʾîʾð̾ðȹò̾õιóдա–’7G<H”BPœKT¢QV§V[¤TXŸPWŸNX™EM™HT–ET?RŽ?R†7J~1H}2Kv,Et"?v$C{'C“6LÐweê²€ôˆôÊõ†òº{î®jê¤jä’_ÎsY¤JM‚)Dl<g>k>u"A€)B*A"?~$B‰3K—?QJY¢L]žL`“BXŒ>R‚6L2L…/H„6L‰6O’@Y˜Lb Uj \qšPg’E`ŒH\†=U€4Nx.Jm$Cp"Dt0Lu.Kx-JŠ>P–L\œXhœ\m dv§t€¯†‹À¡¡Æ¨¤Ç«¥Å§ž¾ ˜­„€—\dˆ6G¢FPÉZWØsgà‡tår蚀êxéžzêŸzí¤~î§ð¦víœzë”sß‚i–6R°bv¥Un†;_ZBQB`HRAXGW@\FXAaJbJVB]Df$J_FS@VDTFUF`'Su5bj/Zj1]TD^!Ox>d|Ad[FSAZHKAf(Y~Ei|>g^L]LzBmZH`&\a0X}Jyf'`v>o—l˜”ld&Pp1]p@X‚Jud?Z@U?T>W;\<X:R9P7O 4V8b@c<z)HŒ0F4I¯CH·FK¶GIÀOJ´FFŠ&7]6N7`6‰-B¨>HµHNÅONÍXUÐZXÔ^Z×^XÙ`\Ùa[Ûe`Úh^Ûd^áj`Üj`ÞibÝh_ÝjcßjcÞhbÞieÞjdÞkgßldâniâkbâjbÞlgÞngáohßoeàlbàldàkdàmdÞhaÛjjÞk_ÚifÝndÚh^Üh`ÜfZÚl`ÜpfÝphÜreÜujÞwjÝvhÝ~qÞrÞ~uÞˆzàŠxà‹|à}à’‚â”‚á’„àœ†âžã¦–㭚䱣䲧座漮迲ëÂ´ëÆ¸íÆºïÇ»îʼï̼ïÊ»ðËÀõμôж侬žCRŠ:K“CRšJUžKQ£PX£PT¡PX¢LVšHV•FQ—MX”DT”FSŠ;P„8O…8J2J‚3J†6IŠ3N£GUÏ|lè´‚öÇ”øÌ–÷È’ò¸zæ iÙ|TÂbQ¢BJ‚*Du"@n;n@v&E‚.F„,B)B|"B†/F‘8OšFX Qb¢O_˜MZŽ?U„2M2M€.J…2L†4MŒ>VšNbŸTh£[nœRh–MeŽBZŒHZ‡=R~4Mt*Hr&Et,Gq*Jm Ak">„?W’J[Znœ^oœ^oœj{«„¼ ¿¥¥Å©¨Ä§ ½Ÿ”¬„€˜^iŒ<L£GPÇXRØrdà…oå–xèšyèšzêž|ëŸ{ì zî¦zî§{îyì“o߃hž:T£Wl YpˆBfR>N?YCTB`"N]Cd&NT?f&N_IWC^Db%Hg'NWEQ=SCTFb'P}8duAnk6`SJe&UvAf~Djr4\N@R@VG] I|Cnk,Sj,V_#Te+MwAu[ Jj+\`!Rw:nl0i‰T~¥‡©€Mzv4jTAwAhn'OU>Q;S<Y=\?S8P 4Q:M 3U 4^3n:ˆ1A–1?£=E²AH¯BGœ6@„6b6R:Z:x$B 9GµBL»JPÆQQÉSUÎ\WÓXRÔ]VØ`ZØaXØc^ÜdZÙfaÙf]Üg`ÚicÝf\ÞhdÞljànaÝleÞießifàjfâldàngßnfánbßtlàngàrjßpkàmhámfßofàofÝndÜlhÝliÜj`ßmcÞj`Üi_Ýk_Üi^ÜmeÞndÜqgÞwiÝuiÜvmÞylÞ|tÞoà‡{Þ‡zߊzá‹~â’â‘â’‡à›ŒâŠâ¢—㪘㮠Ⲣ涧湬農êÀ³ê¶ìŶîȾîʾïËÀî˽ï;óÏÀôϸêʯ¬^i‰7F’AO–HQšMYžMUNVŸNS¡T[›JU™IQ™JV’GZ–HV>P‹<Qˆ;TŒAR@P”=P–8K­KTÓ€pé°„÷È•ùÌ‘õÂ…è¤pÑyS±PK‘4D(@|">r<t@{&B|*C‚.E€&B'A‡,H’=RœGZ Q`ŸNa˜J]EW‡5L|-Iy*H~,G„5PŠ<Q“BZœPb¢Zl£ZkœNf–QdŽG]ŽFZ€6Ly1Jl @t%Fz0Kv1Ml$Bb<€4LŒG]—Vf–Vi‘Si”^t¢y…µ–š¿¤¡Äª¤Åª ¼ š¬‚˜Zf>L¦GRÅVP×rdá„mã“wèšzëž|êŸ|í }ì¡€ï¤ï£|ëžxî’kàˆn >X˜If˜Tny2TN@N>XCTD]"KX@b!JZBk'O`FT@XG]Fq2\b&OSAXFVDl.Yv0^yLuv7cTHb$Tu@j‚Lt~Aj`LRA]JV@€Fli)TQ>WJ]%Oh‘b%Vd&Y^Rq:it9u|Ax¡¡ŽaŽq5d\Ih.Vj.YR<N8WA[<T9R9R8Z=U:\5j4)?Ž1<”1?‰,=|<h6V@W9`:$@œ0A­@IµBG½KNÆSTËWXÎTTÐYYÒ\VÐecÖ`\Ö_\Öa\Ûh]Ùe^Ûd\Üg_Ûh`Üb^Þf`àleßkbÞheÝidàgcÞpiámdâlbàngápcàqdßtjàtfßrjáqißrjàphándÞmbßleÜljÛjdÞjbÞiaÜj^ÝlbÝi`Ýj]ÝpfÝpdÝugÝvhÛxlÞxlÝ~qÜ€uÞtÞ…x߈|áˆ|á’┃◈⚈⛌â£ã¦–䫚㲤䵧幭缰辯êĹëŸíÇ»ìË¿îËÂðʽïË¿òÎÂñνïί‡„†3E:G“HR•JT›LWšLTœPVŸNU™NW™HTšOZ”K]—MX“ETŽCVEV•FX˜HV™CQ—>Q«HUÒxf樄ñ¿Œð¿ˆèª{Ö^¨HJŽ4Gˆ4K~.F|(Fw!A€,Dƒ.E‡2H„.D‚*D….H”:QžK^¤Tc¤WjšN\‘CU†:L€2Hx(Fu(Gz&B‡4M‘BW—F\¢Vh YlŸVgšQg“MaŽH]„>Vy.Gl"Bq&Bz,Hx-Ht,Gh!BZ6o'C~9PˆDZ‰F[ŠKe“\t u„°“–À¤¢Ç«¦Èª¡¿¢™°ˆ„Ÿdn>I¢ENÅXQØp`ß‚nã’wêœvìœì |î£|í£xï¦zî§vëì”lä‰m±P`Œ7XD`n(OQ@TAU>YE] I[H_GT>m+Vf"JZBZHX@v<gTBVCYFVDj*Sn)TvLoq3\KAd&Vz:hŒZŽ„Lu€@n[JWFQGh,Q„KtK>THc&ZsHa`•b#QY Td(_uBx‰W––dŽ«—´‘_Œ\E^Fd+SS;P8U9Y>T=ZAX8[8^8f3i8i8e8^>S7W9[>j!D‚,Fœ;OªBPµDN¼HLÀNSÉTUÍUTÎ]^ÎXTÐXXÒZVÒ^ZÖ_YÖa\Ö^ZÚcaÚgaÙfeÜhaÛebÜjfàg^ÞjaÞjcÜfbÛfdÝkhßmfßlhÞldÞngàpdÞpjÞtràphásfàtlàsmÞnhßlhÝnfÝphßodÚjeÜhbÝldÞpfÞnbÜnfÛlbÞodÛphÜrgÞtfÜxlÝynÝzrÞ~sàuÞ„w߇{á†}á€â“ƒá–†âžŠâ‰â¡“⤔䬘䮜䳦䵥漯龰éÀ´ëÄ·ìȾìļîËÀíÊÀî̾ñÎÀò̹òήܮ¢9GŒ;HŽ@O’FO•JU˜LVšOXŸSZžR\›LW™R\›PZ–MZ’FZ“JY™M^ P\¤P`¤NX¢GU¨GTÈc\ÛuâpÞšnÌyZ§JJŒ8N‰8Nˆ:K†0Iƒ,D†0Fˆ/DŒ2Jˆ/F„*E…/J‘8P™FZŸRa¢[jMY“AQ‰9L‚2J~5Pz(Ct'F|-FŽ;O™M`Qf¥^m Zož\n˜Pg•NcŒFZ€7Mr(Dp&Fr,Fw*Ft(Fj!CgAW:f >p*H€<T‡D[‰HdVpžo°•¼¤ŸÄ¨£Æ¨ Á ˜±Š‡ kr–FS¦FRÄVRÙnaß‚mäŽvê™xìœzí ~ð¤zî¢~ñ¦ð¨~ïŸzî•sæŠn¼\fv'K}6\]BUDSBR>U>X?YE\J^Jk'Pg K\I\H\F|GsVEVDZHWId!Nd#PzNxk*XMG`$S‚E€Œ_ŠY†ŒT€j'TV"QTL^LŠUz`(VLHSEb$W‹a‚t7fn2f_!Ut>pb”^™šr‘¤z ‚Ft`L`&NR<P:V9S:T8\>]?\8^5[2U 5T6^<d:t(B†(@“/Bž6C¬9D¯<JºGNÂPTÊTVÎVZÎ^[ÐZWÑ\\Ñ_^Ò`_Ò]YÓ^ZÔ\V×`XÔb]Ød[ÖdbØ`ZÚjcÙgbÜf\àj`Þh`Þf]ÞfaÝjbÞiaÞifÞjeàidßlcàsißmgánfàqjßrlárißsoßojßnfÞnbàneÞmbÝodÜhbÜjcÝj_àp`ÞnbÜm`ÞndÛogÝrgÜtkÝvjÝzqß{nÜsà„wÞ†|߆~àˆxáŒ€â‘€à”…âž†â Žá¡‘â§—äªšâ¬œã²¢ä´¦æº¨è¼¬èÀ²éôíŶíɾí˾îÊ¿íÌÀðÎÀñξñз嬜HX†7HŠ<LŽ@N’IV•KX–MRRXŸR^žS\ V^›Q\˜K\–P]˜R^ Ra¨W]¬V\ªRZªLU®LV¼VWËl`Êp^ÀeZ¨JS’:LŠ4K‡2F‹.E4H’4G”:K‘4FŽ1B,Dƒ,G‰8N•DYL^žQbžT`“ET‰<J€,C{(Bx(Ft!@v(F†4PšK] RežYj¤]n¤^pžZn•MeNd†?X|0Hr)Dr(Cn"@r#@q$BhB_;Y@e>j @u1L€;T‚A\ˆJg›gx¬Š¸œÃ¦ Â¦Ÿ½ š³‰„¢lqšRW£KTÁXS×kZá€læ’xê™zê€í ~î¡|î¡€ñ¢ñ§ì€ëtç‰rÆddr!Ev5ZT@XFRCV@\)M\ATAZDb"Lh*Tb!L` Pd"O`K}Mub LVBYFZKd*Wn,Y~Nvc MOCZL|@v‡Tƒ_ŠZ†j0]PGKBt<rƒHiŠ[…L@G <j+`k.Z‹X„g*Xn.nd(X“i™Ž_‡yDt}KqZ‚zAm\EOBSDWJV IYHW:S3U4X4a3m:v"=…$9‘);›4@§4@«;E®;G»HQÀLRÆTTÊWXÏWSÎTUÑVUÐWVÓZYÒ^WÓ\UÓ^ZÒ\\Ö^VÔ_XÖ[T×c]Øe^Ø`ZÜc[ÚfcÝh^Üe_Üf`Þe]ÜgbßlgßkdàlfájeálcàmfàmfÝqlßrlàtpàtjátlÞnjßnhÞtmÞndÝsißnbÞrfÜldÞkbÜpfàlaÝodÞl`ÞncÚqhÜngÝshÝyhÞ{nÞxlÝ|qßuàƒu߃wà„xà‚â‹~áà˜ˆãŽâ¢ã§’䫘䮛ä°ä³£å¶¨åº«è¿²é¿²ì¶ìÄ·î˽î̾íÊ¿î̽ðÌÀòθì̯´muƒ4E†9JŠBPŒDR“KY•KQšNZ¡U^¡TZ W_œXfšP_šRažTa¥[f«^a¯ZZ²VW±SX´RX²OT´TV²TZ¦NW›CR’:O’=O“<N”:LšBRš<K—:I–6GŒ-A†*C‰.I“<R™H\œPb˜R_DVˆ=Qƒ0F.D},Cu$Bs#D|0K’ATŸQ` Vl Vh£`r¡^qœXo•UiŽIc„9T{0Is(Ep"Bm"An$Ck @c<aC^ Ad"Ae?m(Hz6T~=[‚Ab•by«†»Ÿ Æª¡Æ¬¥Ã¤š²‘‡¦stžW_¤LY¿WV×jZà€kåuê™zí}졀ñ¤€ñ¤~ì}é’tã‰p»[_t"Iu1W[H^HVFV>[F\FR=YAb Kk*Te%Qb%Qb"N_Mn:Zq5fTDQBVHc M{BdzCkXFPGSGv<h„Pˆ|Ht”j’zBrPCF Cb%WˆNx•jŒn-YC <MFr2ey@\ƒL}^$Nh,fS‚ŒX‡’c˜j4j†S|~Di]"KP?P<V"BT8P4R4W6`7k=t;…'@’/B›8H¢6E©CL¶HL¸FIÂMNÆPPÈTXÉVYÌVWÎWUÏXVÐZYÐZXÒZZÓ][Ôb\Ô`YÐ\WÖ^UÖYSÖ^ZØ^\Ød\Úd\ÚhaÜd^ÞfZÜc\Üb_ÝfbÛohÞofàj`ài`âldànfßibÞkhÜliÞqjßrlÞqjàpfÞrnÝnfàsjàpiÝqgßpdÞvjÞndßneÜocßl^ÞleÝldßrlÛohÝqdÞthÜviÝviÞvlßznàqÞƒsÞtÞ‡y߉~à€à‘ƒá’†á›‰àœŠá£â¥‘㪚㰜㰢䴤縩湮述ë·êÅ·îÊ»îʼìʼî˼ï̾ðκïÎ±É”Žƒ4K‚3H‡@OŒBS‘JT’KV˜OZžS]ŸV^ \bžWcœV`¡Xa§[f«^b°\]µVV²TX¶TW¼TW´NS¬LUªJR¢FSœAQ™>Qš@R¡HV£FR¦HTŸ>O–:M5I‹2G‹6J7P—BVœPe™J^H[ˆ8L„6N‚6Mƒ2H{*Fw,Fv&Fˆ;T˜J^¢Xl¢Zm¥bw£fxœYj–Tf‘Nb‡CZ|/Kv+Fo$Ck @l"Do"?gAb <bA\@f%Dh*Li%Cn,Mt3T{:Z’]t¯ˆ‘Á¦¤Ð´¬Ô¸®Î´¬Á¤–®} \e¥JSÀYX×l^â‚kæ’vìšyí ~ì î£~ð¨ò¦í¡|ç•tÐ|a”<PlIp.Ta.PY#MSAWDZ@ZDV@_"MaHh'R] J` Ne$Nb$T\ I}FxZGQARF]NyDjt4aQBQFQJv:k‹Y–g'X“j’’f’\MNERL„Hz•g‡„HmVF><XF‚Bpaˆh(\SJo8jˆV‰’a„T€p7cg+Ka"KM;R>U?T:W=]9h9l3t58•*: 5B©:F²BH¾OLÄNNÄOKÄPOÆNNÈTSÊXVÎYWÐZXÒ^\ÒZXÔ^\Ô][Õ^UÖ\VÕ\WÓ_W×]WÖ[YÖ`XÚgbÚb\Úd`ÞhhÜfZÞd^ÜdaÝf]Þf_Üjeßibàgbàh`àkeànfßjhÞnfßleßmhárißpjáskápiàpiàsjÞtlàpkßqlßwqÞrfÞpfßodÞreÞriÜncßphÛtlÝvkßvhÜxhÞvjÞ|rÝzpß}sÞ€rà‚uÞ…zߊ{âŒ⎀ᑄ╆♊á¢ã ’⣔⫝̸ᮛⰣ乨巪绮èÁ´ê¶íȸìÊ»ëÉ»ìǹî̽ð̸ñͱװ¡Œ3H€0D†=L‹CS’IT•MWšQZU]žY`Xb [d£]e§^hª_d¬]a¸`^»XV·TU¸VVºQT´NR¬IT¬KT¨HT¥FP¤DR¦GU¯NR°NX¯IR£BO—:LŽ2HŒ3J8O˜@TšF\•JZˆ7N„6L~2G}+B‚0C‚.C}2L|.H2K‘@TžN`¦\l£`l¨ap£`s˜Tf–TeŒFZ‚6Ox+El Bj @n>f>e:d:b8f6^=b BdBbAj(Jj)Nn-S”Yp´Ž“ж°ÜµßóÝÀ®Ö¹¦»•Ž£_f§T[ÀZXØn\á„lçríœ{îž|îŸ~ð¤‚ñ§ô§€ðŸâŒpªS^z,QdDh%N^C_JV@\ I[DUBVE_Hc%Pf%N\Jb Md$Mf(TXIoAao3cP@VH]K‹aŒ|@mTLUNTLzApŒ^“hY‚R}šwž}GxZ"PPEqGoŠVz„Oyr/^H?J>v0`zC_”h•VNPEr3e}Ju‘bl.dR>b$MP?T;ZAV@\>c8k8q0€!6”0?¥9A²?IºCG½NOÅMJÊPKÊRPÇNKÉQPÊSRÎWUÐ[VÐZUÑZYÓ\XÕ^XÖ_WÒZTÔa\×\SÖ^TÙaX×^XÖ^ZÚd\Ø`YÚf_Úc[Üe\ÜdZÜh`ÞfZÞg`Üi`Þiaßg]àf\ámdàj`àlcßlfÞmdàqkáphàpiàniàrqßrkàulÞqlÞskàqhßulßrhàrlßrdàncÞriÝpfÞwlÝrfÝthàvhàxgßxjßwkÝzpÞznÞpÞ…vÞ…zߌ{àŒ~㑀ᓃᖆàá ”â¤à¦âªšâ­žà® äµ¦æº¯ç½¯è¿±èÁ³ëÄ·ëÆºêɺëȽêǼì̼ñ͵âîšKZ|.G…;K‡BVŽDOšQYœR\žRYžXbVb [f¤`fªaf¬af´`^·YZºUU¹VU¸VV¸UX·QT´QV°JT«JR©DT¬FRµQV¼TV¸QU®HR£@Nš:N“6N˜=R•DV˜I`–I\ŒAZ†:L~,Dz*A|,D~.G~)>~6N4NŽ;NœPd¥\h§aq§s¤^nžZo–PeŒEY†?Uy1Hn)Gh$Ah @i>h"@f>f;f<v:Z>d"@bA_@h"Eg%Jo.W”av½•—Û¾¯áóâijß°޾¤Î©“­po§RZÁZVØjZà‚næpìšxìŸ{ïœ~ð¢€î¢€ð¤ð¤~ìž|â“y¼lpOlx'Pc KVCbFf&NZAZDQBYB`#PbHfKb"Ld"Nj(Qi-UZL\&IzGvL@TGb'T˜uz8bVEWOVH~EtŽbo'_w8hŸ}¢•j”b#LOBRFy@h‡T€_"J`#SI @j'Ou/^ˆXs€FxOBq0dn1cŠ[‰yJum6po4\T=P:V 7S6_6l6s2‚!7—0;¤7>°<@¹EG¾GGÀMHÃPNÊQJÊTLÈTNËRNÉSMÐWSÒXSÒ]UÐZVÒXPÓ^YÕZRÒXVÖ^XÕ^ZÕ`YÚcZØ`Y×^YÚ^XØaZÛaTÝd[ÜaXÝhaÜh`Þh`Þf]ÝdaÝh`ÞfZÞjgàhcáießkdàjaÞhgáogßqjàleápnárkàrsãtiàtkàpjàtfÞxoápjàvpßsjßreÞxqÞvlßtnÞtiÝtkÞznÞxjàylà|qß~kÞzpß}mà„và„táŠxâ|à‘‚à—…à“…á™‹à â¤“ᡎᩜ⬜ᮟ䴦漬溬龲èÀ´ëõêĶêÈ»ëÈ»ëʽìͺñ͹êʱ¯ox{.J„8H‰>JŒGUŒGPŒHT˜T]˜Tb›T`ŸZb¨bi­bf°ae´``¸ZYº[Y¼VQ¼TT¹UV¸RT·OU¸JP³LT²NV¸VYÁWXÀVV¶RY­LT¦AR@Q—=T™DZ˜F\—H^’K_„>Vƒ6J~.C}-F‚.I}0F}/H0I‹=SœM^£Wd«bn«du¨bpž\p˜VjŽJ`ŠBU4Lr)Fh#Cd>h">k%Cf:h;i<r >Œ2HY<`=`@`>d&GcHk*P˜bz̤œÛ½±ß³ãijàòݼ§Ó°’»ƒw¨PWÀ\\Õm`á€järìœvìœxìxï¡|îž{î£~ñ£|îŸ~é‘sÈnn³do‚3VcJYE\D`DXD_KPA_"Jb-Sf&PfMd Pi"Nn)Um+Tf"RTFzJpb PVLg-W˜r—s2^[JVJ\NˆQ|e•eR}4q„Uv ¦s4dPBSJh*WŠ\‚g,ac&Pe"TZA€:dn.T†NucTi)[p,`„T€G€†V„_‹ZDL 6N 2X 1c3u4ƒ#;’.<¥5=¬9?·DI¹HJÀGGÃNKÂJJÊPNÊTOÌSPÍVQËRPÐVOÑZUÔ`YÒ\UÐ\XÐ]VÔYRÑ[VÖ]V×a^Ø`XÚ_XÚb\Ø`[Ú^RØ_YÜ_VÜd\ÛaZÞd[Ýf^Ýf_Üb[Ûg_Þmfáj^Þhdàh`àkdàg^àlbàlhßplànjàniásnàoeàqiâulßriâtkàthàqkávjàwmÞthâujßxmßsjàslÞtfÞtgÞwlÞzlâyná~sà|sà{pßzoáƒzâ‡{á‹yâà‘€ß‘à’ᚆ⠊ឈ࢒䨖⭜à¯ä²¡ä¶¨äº­ç¾°çÀ´êĶêÄ·êȺìȺìʼìÊ»ñ˹îαʓ’}/J{4Lˆ>LHR’R[–MY—P\”NZ›Vc¡\b«^c¯ad²]`¶\^º][À[WÂXV¼UV¼UVºOQ¸OU½RS¼QS¿WYÈ[VÊ_XÂXWºOQ¬GR ?Pœ@U›DXœNb”F]ˆBZˆ@Y‚<Xˆ;Qƒ8Rƒ4J‚;P€-G†2H‹:P˜H\§Vh­cq¬hs¬fv¤cp›Uf•RiˆD]€;Rt*Fh @c;`6f9i<j)Fl<}+Fˆ0C™8IZ>[=b?`@d"EaEj'P˜\rΦœÚ¼¯ÜÀ°àñßÁ®Þ»¦Õ²˜Áˆ~¥R\¾ZXÖnbà‚kåŽuìœvìžwê xí¢|î {ï£|ñ¥€íšxß“xºYbžNbv-QbF^DWAX>ZAc JUH^H`#LdLk%Rh"Nr*Vz6\z5]r2\[Jd$Ms0`\OsDnŒ\‚q,XcJ[Nj"W„Fq`TB~?ut0dšz˜–d‘[KRIk/b_„‹X†XJe&Pf&Tr0T}<gf*Oh+XVGn/`~@k€I}s9q”fŠ^‰^!KT 4\ 4o3€7&9œ+;¨6>¯9B¸FHºDEÁGFÆPQÈPNÌOLÊWTÍUQÎUPÌWTÐXQÐXOÒ_WÒ]VÐZWÐ\XÔ^TÓ`[×`UØbXÖ]ZÙ`XÙb\ØbYÜ\TÛ^TÚh_Üd[ÝjdÝf`ÞeXÝc]Ý`XÜf`ÞjhÞjbÝgeÞmkÞkfßgdàicàngánjâpdârgâtjárgàsjàkiàrfásháqjßrhârfázpàwnâxiátgÞxlávhÞrfßuhÞxoÝzjà{lâ~lá}oà€rà~rà„wã…và‹}áŒ~à‹|ÝŠá’‚á–‡àžŽàšŠá£’ã©—ã¬á®ã²žæµ¨å¹§ç¼±è¾±êÁ´ëÂ·éÆ·ìÆ¸íʽíʺðʺïͲڲ¦‹:N4I„<KŠ?IBN”FO’NZ”O[šR\ž[b¨\`®^a´[\¸^^ÄaXÃa^Ã\VÀTRÀTS¿SPÁYWÇXTËUTÐ`WÐ`XÌ_XÃVS¸KR£GTž?Oš@V™DT–E\Š<X‚<V6Pƒ9OŠ<U„:P†:P†5K„2GŒ<Q˜H]£Xj¬bl¯mx¬kx«htž\m—Uh‹EZ€<Tt)Ei<f!A^8a>e>g=p&By(CŒ5HŸ?J¢<KU<\<^>^:c D^Fc&O‰OmË¢šÚ»²Þ¾²ÞÀ³Ý¿²Ú¸¦Ò®—À‡y§NXÀ\XØn_ß„nåtìšwëž{ì î |좀î£ñ¤}íŸvÞ‘w¤JWŠA^j"Gf$NdHR@P<_Bh%LP?g*V[Hh)Rn(Rg#Pp-Vs*Tx5Zx6b\JbMp0fj.^o’†HpbLg!T` QiR†Lub‹P@w8fv3fu<h“jŠ€FzXMf'U˜p—‹XzXDRCTDl(Q<^s0\f(SWIWFaL~Kym,b}?g—f…X|j$Ki<‚$<–->œ4B¢1?©7@®?F½GHÁHIÆMJÊQNÊSRÊPPÎTTÎXSÏXSÐWUÑ\SÓZRÐZXÑZXÐ^[Ò]TÖ]TÓ]TÕ^X×_TØ\UØ\XØaZ×`ZÛ^XÚ^VÛcXÜa\Üe[àe[Þi`Þf_à^WÞdZÝc[Þd\Þhhàh_àhdÞlfàjcÞnhàrgárfâpfßphßrjßrjÞkfàrlâsjàtoßsmârgáwlàxlàuhàtlàvhßyoßymàtgßxjÜ{pàwkßyoá€rá€tá€pá‚sâ…yáˆ|áŽ€àŽ„àŽá~ß“†á˜ŠàšŒàžŒâ¤•⪕⯟䱠崦帨帬翰꿰êÁ´éÄ¶íÆ¼íÈÀìÇ»ïʼðηæÄ®¥Vl„>Z‡?PˆDS‘HNŽ@JBM”JV™W`œW_¦Y`«X[´^_Âe_Ìg\É`VÆ[VÅ\WÆZTÆXTÄZWÎb[Ñh[ÖkXÑdYË]UÀTR±IR¡>NžBQ—>O’:P‡7Q{4Q4R‚6SŒBY>XŠ@Tˆ:Q†:P…4M”DUžK^©Zk²gp¯n|¬ktªguœ]kŽH^:Qv/Hg >a<_6`:`8c;j?u+F†4Jš@R¬FRªANR9^>`=\=` C[>`H†HfÄ™ŽÚ¼®Þ¾±Ü¾°Ü¾®Øº¦Ñ¬·zq¡S^Â`\Øl\á„mæŒnë–xì„ì¢zì¢|ð¤‚잀á–{¢JWFdh&Nj%LY>Q>P:d"Gi*PH8g(RV@r0Yr2[k"Mq*Vm&Nt-Xx4^f%ObS|@t|;h ˆ«r4Y`Fq.`VBd R‚Gm^ˆTHi(Tt4`p+d|Fk˜nœs2l\!N x|EhN=YFSJZDo*Xy:`e-Se"PTD_L}Lso.a`F‚Lzz7NR€z8’/D—1A›2>¨:D¨8@²@DºDF¾HKÃJJÆLNÈQRÏSRËWTÌVQÎXQÑZPÐXQÒZTÑbZÑa[ÐZWÒ]TÕ\TÔ\VÔ]WÖ\T×`\×b^Ùb\Öd]Û`TÛ^XÜ^Wß`YÞe^ÞibÞe_Üe]ß`XÞc\Ýd\ßb^ÞfdâhfàhdÞnháihàhbàojândârlÞnfÞpfÞnnâmcàrkárhàqhßrjàrhàvjàxiáypàwlßvhßxlÞxqáyißxlÞ{oÞztà{pà„rà„tà‚xâ€tà„tàˆ~ጂà†ßŒ„ß€à”ˆá”Šâ˜Œàœâ¦”᪘ᬘ峢䳤䷤䶨溰辰èÀ´ê´ìŹìÇÀîļðÊ»ð˵êÈ·Ân‚žR€’IhˆEZŽDRŽBPHT“HRšPWœRZœPY°bf½f^Çj]Ñh\Ïc\Ì`VÈ\XÎ]TÊ[TÈ`\Ðj^×l[ØkZÑfZÊXP¸RS¨BK˜<J˜<L6Lƒ/H1Lx2P|2P‰>ZŽ@]AXŽBZ†<V‡6QŒ<R—DV¤P_¬cn²fp®mvªjx¥dr–Vg†D[v+Fh#@f"D_<Z2_7`:k>v,N~8P–BV¨GT²DN·HQ \ No newline at end of file
diff --git a/contrib/ffmpeg/tests/libav.regression.ref b/contrib/ffmpeg/tests/libav.regression.ref
new file mode 100644
index 000000000..a5ea5f15d
--- /dev/null
+++ b/contrib/ffmpeg/tests/libav.regression.ref
@@ -0,0 +1,106 @@
+ffmpeg regression test
+8a0536ccfe36f4fff408b3327d33e1dd *./data/b-libav.avi
+340344 ./data/b-libav.avi
+./data/b-libav.avi CRC=0x400c29e9
+85caa242a36abeab85a27c82ba73cc28 *./data/b-libav.asf
+339767 ./data/b-libav.asf
+./data/b-libav.asf CRC=0x74113749
+1ad618e9fd318eb3483270cf9b9b3f43 *./data/b-libav.rm
+355405 ./data/b-libav.rm
+bdb7484c68db722f66ba1630cf79844c *./data/b-libav.mpg
+378880 ./data/b-libav.mpg
+./data/b-libav.mpg CRC=0x2b71a386
+0bf8fb3b4d7bb70ed89356e94cd8ffa2 *./data/b-libav.ts
+471316 ./data/b-libav.ts
+./data/b-libav.ts CRC=0xcc4948e1
+16cf1c37c123f8d3c4a31d192d9b0cc6 *./data/b-libav.swf
+41836 ./data/b-libav.swf
+./data/b-libav.swf CRC=0xcdec36a1
+87a8c8be5db2513356b28f29dff5769e *./data/b-libav.ffm
+380928 ./data/b-libav.ffm
+./data/b-libav.ffm CRC=0x01522b4a
+5e8aa303a877cfac6569ed11cf20e92b *./data/b-libav.flv
+335810 ./data/b-libav.flv
+./data/b-libav.flv CRC=0xe14e8847
+16518706f425cb537362bfc1c58b8de5 *./data/b-libav.mov
+366923 ./data/b-libav.mov
+./data/b-libav.mov CRC=0x45079dca
+26c41db318d9aacfd6b9e734c0ea4d94 *./data/b-libav.dv
+3600000 ./data/b-libav.dv
+./data/b-libav.dv CRC=0xa6b8b635
+2b3f921fb7a01bb126cab5ee21ae3f8d *./data/b-libav.gxf
+815700 ./data/b-libav.gxf
+./data/b-libav.gxf CRC=0x238a01b0
+9a9da315747599f7718cc9a9a09c21ff *./data/b-libav.pbm
+ 317075 ./data/b-libav.pbm
+./data/b-libav.pbm CRC=0xb92906cb
+6ea0e1faf08f6fcdb44db4a104361b57 *./data/b-libav.pgm
+2534775 ./data/b-libav.pgm
+./data/b-libav.pgm CRC=0xf4aa7c47
+0c5fe86621b7377705837f304d4ba1e9 *./data/b-libav.ppm
+7603575 ./data/b-libav.ppm
+./data/b-libav.ppm CRC=0xb2bb8e92
+88a98269295fbfce7816558ad84e1259 *./data/b-libav.gif
+2906382 ./data/b-libav.gif
+b977a4fedff90a79baf70c8e02986820 *./data/b-libav.y4m
+3801810 ./data/b-libav.y4m
+./data/b-libav%02d.pgm CRC=0x84c09106
+./data/b-libav%02d.ppm CRC=0x25c06ecf
+./data/b-libav%02d.jpg CRC=0x62328baa
+b0a8c8063d81921db5d7c8f50a1cc454 *./data/b-libav.wav
+ 89132 ./data/b-libav.wav
+./data/b-libav.wav CRC=0x2a09519c
+e2a6d6fae17394dfe87cb5bb8ae11837 *./data/b-libav.al
+ 44544 ./data/b-libav.al
+./data/b-libav.al CRC=0xefdf94c3
+4574d7e2c09e1e13663e61bd2889f12d *./data/b-libav.ul
+ 44544 ./data/b-libav.ul
+./data/b-libav.ul CRC=0x6064b2f8
+7a21ff174e3cca1702e0826c4ca0eccf *./data/b-libav.au
+ 89112 ./data/b-libav.au
+./data/b-libav.au CRC=0x2a09519c
+272b91d8fc31ed43b08246d182719751 *./data/b-libav.mmf
+ 22609 ./data/b-libav.mmf
+./data/b-libav.mmf CRC=0x03633476
+c8cf5bac13fb7862bcbce76977328f92 *./data/b-libav.aif
+89160 ./data/b-libav.aif
+./data/b-libav.aif CRC=0x2a09519c
+8d117c49d6b210abe783d1b0b897cec7 *./data/b-libav.voc
+ 32768 ./data/b-libav.voc
+./data/b-libav.voc CRC=0x49972c8c
+ce356ce2708cb6033ab5d762da93cfd4 *./data/b-libav-yuv420p.yuv
+ 304128 ./data/b-libav-yuv420p.yuv
+ce356ce2708cb6033ab5d762da93cfd4 *./data/b-libav-yuv422p.yuv
+ 304128 ./data/b-libav-yuv422p.yuv
+ce356ce2708cb6033ab5d762da93cfd4 *./data/b-libav-yuv444p.yuv
+ 304128 ./data/b-libav-yuv444p.yuv
+ce356ce2708cb6033ab5d762da93cfd4 *./data/b-libav-yuv422.yuv
+ 304128 ./data/b-libav-yuv422.yuv
+545f61c353a8b4419808785cb4f0069d *./data/b-libav-yuv410p.yuv
+ 304128 ./data/b-libav-yuv410p.yuv
+d6c03f930018ff859bd43f52b92e9321 *./data/b-libav-yuv411p.yuv
+ 304128 ./data/b-libav-yuv411p.yuv
+14117c4d7956775a7bbceabfc38da808 *./data/b-libav-yuvj420p.yuv
+ 304128 ./data/b-libav-yuvj420p.yuv
+14117c4d7956775a7bbceabfc38da808 *./data/b-libav-yuvj422p.yuv
+ 304128 ./data/b-libav-yuvj422p.yuv
+14117c4d7956775a7bbceabfc38da808 *./data/b-libav-yuvj444p.yuv
+ 304128 ./data/b-libav-yuvj444p.yuv
+deb2f7ebe297df2c1fe264d19b34d2fb *./data/b-libav-rgb24.yuv
+ 304128 ./data/b-libav-rgb24.yuv
+deb2f7ebe297df2c1fe264d19b34d2fb *./data/b-libav-bgr24.yuv
+ 304128 ./data/b-libav-bgr24.yuv
+deb2f7ebe297df2c1fe264d19b34d2fb *./data/b-libav-rgba32.yuv
+ 304128 ./data/b-libav-rgba32.yuv
+5d395f62bff8ac475f743268c772ca3a *./data/b-libav-rgb565.yuv
+ 304128 ./data/b-libav-rgb565.yuv
+2ffd6871fcbfe9570454e8703ac8ea01 *./data/b-libav-rgb555.yuv
+ 304128 ./data/b-libav-rgb555.yuv
+0b62dcf9b57b294dbaa5d9e99b1ee192 *./data/b-libav-gray.yuv
+ 304128 ./data/b-libav-gray.yuv
+e197450dae2feba9e757b551e1e9145c *./data/b-libav-monow.yuv
+ 304128 ./data/b-libav-monow.yuv
+e197450dae2feba9e757b551e1e9145c *./data/b-libav-monob.yuv
+ 304128 ./data/b-libav-monob.yuv
+7a319375916cae4e691ecb74295e5d2a *./data/b-libav-pal8.yuv
+ 304128 ./data/b-libav-pal8.yuv
diff --git a/contrib/ffmpeg/tests/regression.sh b/contrib/ffmpeg/tests/regression.sh
new file mode 100755
index 000000000..70f4eba12
--- /dev/null
+++ b/contrib/ffmpeg/tests/regression.sh
@@ -0,0 +1,785 @@
+#!/bin/sh
+#
+# automatic regression test for ffmpeg
+#
+#
+#set -x
+# Even in the 21st century some diffs are not supporting -u.
+diff -u "$0" "$0" > /dev/null 2>&1
+if [ $? -eq 0 ]; then
+ diff_cmd="diff -u"
+else
+ diff_cmd="diff"
+fi
+
+diff -w "$0" "$0" > /dev/null 2>&1
+if [ $? -eq 0 ]; then
+ diff_cmd="$diff_cmd -w"
+fi
+
+set -e
+
+datadir="./data"
+
+logfile="$datadir/ffmpeg.regression"
+outfile="$datadir/a-"
+
+# tests to do
+if [ "$1" = "mpeg4" ] ; then
+ do_mpeg4=y
+elif [ "$1" = "mpeg" ] ; then
+ do_mpeg=y
+ do_mpeg2=y
+elif [ "$1" = "ac3" ] ; then
+ do_ac3=y
+elif [ "$1" = "huffyuv" ] ; then
+ do_huffyuv=y
+elif [ "$1" = "mpeg2thread" ] ; then
+ do_mpeg2thread=y
+elif [ "$1" = "snow" ] ; then
+ do_snow=y
+elif [ "$1" = "snowll" ] ; then
+ do_snowll=y
+elif [ "$1" = "libavtest" ] ; then
+ do_libav=y
+ logfile="$datadir/libav.regression"
+ outfile="$datadir/b-"
+else
+ do_mpeg=y
+ do_mpeg2=y
+ do_mpeg2thread=y
+ do_msmpeg4v2=y
+ do_msmpeg4=y
+ do_wmv1=y
+ do_wmv2=y
+ do_h261=y
+ do_h263=y
+ do_h263p=y
+ do_mpeg4=y
+ do_mp4psp=y
+ do_huffyuv=y
+ do_mjpeg=y
+ do_ljpeg=y
+ do_jpegls=y
+ do_rv10=y
+ do_rv20=y
+ do_mp2=y
+ do_ac3=y
+ do_g726=y
+ do_adpcm_ima_wav=y
+ do_adpcm_ms=y
+ do_flac=y
+ do_rc=y
+ do_mpeg4adv=y
+ do_mpeg4thread=y
+ do_mpeg4nr=y
+ do_mpeg1b=y
+ do_asv1=y
+ do_asv2=y
+ do_flv=y
+ do_ffv1=y
+ do_error=y
+ do_svq1=y
+ do_snow=y
+ do_snowll=y
+ do_adpcm_yam=y
+ do_dv=y
+ do_dv50=y
+fi
+
+
+# various files
+ffmpeg="../ffmpeg_g"
+tiny_psnr="./tiny_psnr"
+reffile="$2"
+benchfile="$datadir/ffmpeg.bench"
+raw_src="$3/%02d.pgm"
+raw_dst="$datadir/out.yuv"
+raw_ref="$datadir/ref.yuv"
+pcm_src="asynth1.sw"
+pcm_dst="$datadir/out.wav"
+pcm_ref="$datadir/ref.wav"
+if [ X"`echo | md5sum 2> /dev/null`" != X ]; then
+ do_md5sum() { md5sum -b $1; }
+elif [ -x /sbin/md5 ]; then
+ do_md5sum() { /sbin/md5 -r $1 | sed 's# \**\./# *./#'; }
+else
+ do_md5sum() { echo No md5sum program found; }
+fi
+
+# create the data directory if it does not exists
+mkdir -p $datadir
+
+FFMPEG_OPTS="-y -flags +bitexact -dct fastint -idct simple"
+
+do_ffmpeg()
+{
+ f="$1"
+ shift
+ echo $ffmpeg $FFMPEG_OPTS $*
+ $ffmpeg $FFMPEG_OPTS -benchmark $* > $datadir/bench.tmp 2> /tmp/ffmpeg$$
+ egrep -v "^(Stream|Press|Input|Output|frame| Stream| Duration|video:)" /tmp/ffmpeg$$ || true
+ rm -f /tmp/ffmpeg$$
+ do_md5sum $f >> $logfile
+ if [ $f = $raw_dst ] ; then
+ $tiny_psnr $f $raw_ref >> $logfile
+ elif [ $f = $pcm_dst ] ; then
+ $tiny_psnr $f $pcm_ref 2 >> $logfile
+ else
+ wc -c $f >> $logfile
+ fi
+ expr "`cat $datadir/bench.tmp`" : '.*utime=\(.*s\)' > $datadir/bench2.tmp
+ echo `cat $datadir/bench2.tmp` $f >> $benchfile
+}
+
+do_ffmpeg_crc()
+{
+ f="$1"
+ shift
+ echo $ffmpeg $FFMPEG_OPTS $* -f crc $datadir/ffmpeg.crc
+ $ffmpeg $FFMPEG_OPTS $* -f crc $datadir/ffmpeg.crc > /tmp/ffmpeg$$ 2>&1
+ egrep -v "^(Stream|Press|Input|Output|frame| Stream| Duration|video:|ffmpeg version| configuration| built)" /tmp/ffmpeg$$ || true
+ rm -f /tmp/ffmpeg$$
+ echo "$f `cat $datadir/ffmpeg.crc`" >> $logfile
+}
+
+do_ffmpeg_nocheck()
+{
+ f="$1"
+ shift
+ echo $ffmpeg $FFMPEG_OPTS $*
+ $ffmpeg $FFMPEG_OPTS -benchmark $* > $datadir/bench.tmp 2> /tmp/ffmpeg$$
+ egrep -v "^(Stream|Press|Input|Output|frame| Stream| Duration|video:)" /tmp/ffmpeg$$ || true
+ rm -f /tmp/ffmpeg$$
+ expr "`cat $datadir/bench.tmp`" : '.*utime=\(.*s\)' > $datadir/bench2.tmp
+ echo `cat $datadir/bench2.tmp` $f >> $benchfile
+}
+
+do_video_decoding()
+{
+ do_ffmpeg $raw_dst -y -i $file -f rawvideo $@ $raw_dst
+}
+
+do_video_encoding()
+{
+ do_ffmpeg $file -y $1 -f pgmyuv -i $raw_src $2 $file
+}
+
+do_audio_encoding()
+{
+ file=${outfile}$1
+ do_ffmpeg $file -y -ab 128 -ac 2 -f s16le -i $pcm_src $3 $file
+}
+
+do_audio_decoding()
+{
+ do_ffmpeg $pcm_dst -y -i $file -f wav $pcm_dst
+}
+
+do_libav()
+{
+ file=${outfile}libav.$1
+ do_ffmpeg $file -t 1 -y -qscale 10 -f pgmyuv -i $raw_src -f s16le -i $pcm_src $2 $file
+ do_ffmpeg_crc $file -i $file $3
+
+}
+
+do_streamed_images()
+{
+ file=${outfile}libav.$1
+ do_ffmpeg $file -t 1 -y -qscale 10 -f pgmyuv -i $raw_src -f image2pipe $file
+ do_ffmpeg_crc $file -f image2pipe -i $file
+}
+
+do_image_formats()
+{
+ file=${outfile}libav%02d.$1
+ $ffmpeg -t 0.5 -y -qscale 10 -f pgmyuv -i $raw_src $2 $3 $file
+ do_ffmpeg_crc $file $3 -i $file
+
+}
+
+do_audio_only()
+{
+ file=${outfile}libav.$1
+ do_ffmpeg $file -t 1 -y -qscale 10 -f s16le -i $pcm_src $file
+ do_ffmpeg_crc $file -i $file
+}
+
+echo "ffmpeg regression test" > $logfile
+echo "ffmpeg benchmarks" > $benchfile
+
+###################################
+# generate reference for quality check
+do_ffmpeg_nocheck $raw_ref -y -f pgmyuv -i $raw_src -an -f rawvideo $raw_ref
+do_ffmpeg_nocheck $pcm_ref -y -ab 128 -ac 2 -ar 44100 -f s16le -i $pcm_src -f wav $pcm_ref
+
+###################################
+if [ -n "$do_mpeg" ] ; then
+# mpeg1 encoding
+file=${outfile}mpeg1.mpg
+do_video_encoding "-qscale 10" "-f mpeg1video"
+
+# mpeg1 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_mpeg2" ] ; then
+# mpeg2 encoding
+file=${outfile}mpeg2.mpg
+do_video_encoding "-qscale 10" "-vcodec mpeg2video -f mpeg1video"
+
+# mpeg2 decoding
+do_video_decoding
+
+# mpeg2 encoding using intra vlc
+file=${outfile}mpeg2ivlc.mpg
+do_video_encoding "-qscale 10" "-vcodec mpeg2video -f mpeg1video -flags2 +ivlc"
+
+# mpeg2 decoding
+do_video_decoding
+
+# mpeg2 encoding
+file=${outfile}mpeg2.mpg
+do_video_encoding "-qscale 10" "-vcodec mpeg2video -idct int -dct int -f mpeg1video"
+
+# mpeg2 decoding
+do_ffmpeg $raw_dst -y -idct int -i $file -f rawvideo $raw_dst
+
+# mpeg2 encoding interlaced
+file=${outfile}mpeg2i.mpg
+do_video_encoding "-qscale 10" "-vcodec mpeg2video -f mpeg1video -flags +ildct+ilme"
+
+# mpeg2 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_mpeg2thread" ] ; then
+# mpeg2 encoding interlaced
+file=${outfile}mpeg2thread.mpg
+do_video_encoding "-qscale 10" "-vcodec mpeg2video -f mpeg1video -bf 2 -flags +ildct+ilme -threads 2"
+
+# mpeg2 decoding
+do_video_decoding
+
+# mpeg2 encoding interlaced using intra vlc
+file=${outfile}mpeg2threadivlc.mpg
+do_video_encoding "-qscale 10" "-vcodec mpeg2video -f mpeg1video -bf 2 -flags +ildct+ilme -flags2 +ivlc -threads 2"
+
+# mpeg2 decoding
+do_video_decoding
+
+# mpeg2 encoding interlaced
+file=${outfile}mpeg2reuse.mpg
+do_ffmpeg $file -y -sameq -me_threshold 256 -mb_threshold 1024 -i ${outfile}mpeg2thread.mpg -vcodec mpeg2video -f mpeg1video -bf 2 -flags +ildct+ilme -threads 4 $file
+
+# mpeg2 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_msmpeg4v2" ] ; then
+# msmpeg4 encoding
+file=${outfile}msmpeg4v2.avi
+do_video_encoding "-qscale 10" "-an -vcodec msmpeg4v2"
+
+# msmpeg4v2 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_msmpeg4" ] ; then
+# msmpeg4 encoding
+file=${outfile}msmpeg4.avi
+do_video_encoding "-qscale 10" "-an -vcodec msmpeg4"
+
+# msmpeg4 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_wmv1" ] ; then
+# wmv1 encoding
+file=${outfile}wmv1.avi
+do_video_encoding "-qscale 10" "-an -vcodec wmv1"
+
+# wmv1 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_wmv2" ] ; then
+# wmv2 encoding
+file=${outfile}wmv2.avi
+do_video_encoding "-qscale 10" "-an -vcodec wmv2"
+
+# wmv2 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_h261" ] ; then
+# h261 encoding
+file=${outfile}h261.avi
+do_video_encoding "-qscale 11" "-s 352x288 -an -vcodec h261"
+
+# h261 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_h263" ] ; then
+# h263 encoding
+file=${outfile}h263.avi
+do_video_encoding "-qscale 10" "-s 352x288 -an -vcodec h263"
+
+# h263 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_h263p" ] ; then
+# h263p encoding
+file=${outfile}h263p.avi
+do_video_encoding "-qscale 2 -flags +umv+aiv+aic" "-s 352x288 -an -vcodec h263p -ps 300"
+
+# h263p decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_mpeg4" ] ; then
+# mpeg4
+file=${outfile}odivx.mp4
+do_video_encoding "-flags +mv4 -mbd bits -qscale 10" "-an -vcodec mpeg4"
+
+# mpeg4 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_huffyuv" ] ; then
+# huffyuv
+file=${outfile}huffyuv.avi
+do_video_encoding "" "-an -vcodec huffyuv -pix_fmt yuv422p"
+
+# huffyuv decoding
+do_video_decoding -strict -2 -pix_fmt yuv420p
+fi
+
+###################################
+if [ -n "$do_rc" ] ; then
+# mpeg4 rate control
+file=${outfile}mpeg4-rc.avi
+do_video_encoding "-b 400k -bf 2" "-an -vcodec mpeg4"
+
+# mpeg4 rate control decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_mpeg4adv" ] ; then
+# mpeg4
+file=${outfile}mpeg4-adv.avi
+do_video_encoding "-qscale 9 -flags +mv4+part+aic+trell -mbd bits -ps 200" "-an -vcodec mpeg4"
+
+# mpeg4 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_mpeg4thread" ] ; then
+# mpeg4
+file=${outfile}mpeg4-thread.avi
+do_video_encoding "-b 500k -flags +mv4+part+aic+trell -mbd bits -ps 200 -bf 2" "-an -vcodec mpeg4 -threads 2"
+
+# mpeg4 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_mpeg4adv" ] ; then
+# mpeg4
+file=${outfile}mpeg4-Q.avi
+do_video_encoding "-qscale 7 -flags +mv4+qpel -mbd 2 -bf 2 -cmp 1 -subcmp 2" "-an -vcodec mpeg4"
+
+# mpeg4 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_mp4psp" ] ; then
+# mp4 PSP style
+file=${outfile}mpeg4-PSP.mp4
+do_ffmpeg $file -y -b 768k -s 320x240 -f psp -ar 24000 -ab 32 -i $raw_src $file
+fi
+
+###################################
+if [ -n "$do_error" ] ; then
+# damaged mpeg4
+file=${outfile}error-mpeg4-adv.avi
+do_video_encoding "-qscale 7 -flags +mv4+part+aic -mbd rd -ps 250 -error 10" "-an -vcodec mpeg4"
+
+# damaged mpeg4 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_mpeg4nr" ] ; then
+# noise reduction
+file=${outfile}mpeg4-nr.avi
+do_video_encoding "-qscale 8 -flags +mv4 -mbd rd -nr 200" "-an -vcodec mpeg4"
+
+# mpeg4 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_mpeg1b" ] ; then
+# mpeg1
+file=${outfile}mpeg1b.mpg
+do_video_encoding "-qscale 8 -bf 3 -ps 200" "-an -vcodec mpeg1video -f mpeg1video"
+
+# mpeg1 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_mjpeg" ] ; then
+# mjpeg
+file=${outfile}mjpeg.avi
+do_video_encoding "-qscale 10" "-an -vcodec mjpeg -pix_fmt yuvj420p"
+
+# mjpeg decoding
+do_video_decoding -pix_fmt yuv420p
+fi
+
+###################################
+if [ -n "$do_ljpeg" ] ; then
+# ljpeg
+file=${outfile}ljpeg.avi
+do_video_encoding "" "-an -vcodec ljpeg -strict -1"
+
+# ljpeg decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_jpegls" ] ; then
+# jpeg ls
+file=${outfile}jpegls.avi
+do_video_encoding "" "-an -vcodec jpegls -vtag MJPG"
+
+# jpeg ls decoding
+do_video_decoding -pix_fmt yuv420p
+fi
+
+###################################
+if [ -n "$do_rv10" ] ; then
+# rv10 encoding
+file=${outfile}rv10.rm
+do_video_encoding "-qscale 10" "-an"
+
+# rv10 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_rv20" ] ; then
+# rv20 encoding
+file=${outfile}rv20.rm
+do_video_encoding "-qscale 10" "-vcodec rv20 -an"
+
+# rv20 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_asv1" ] ; then
+# asv1 encoding
+file=${outfile}asv1.avi
+do_video_encoding "-qscale 10" "-an -vcodec asv1"
+
+# asv1 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_asv2" ] ; then
+# asv2 encoding
+file=${outfile}asv2.avi
+do_video_encoding "-qscale 10" "-an -vcodec asv2"
+
+# asv2 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_flv" ] ; then
+# flv encoding
+file=${outfile}flv.flv
+do_video_encoding "-qscale 10" "-an -vcodec flv"
+
+# flv decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_ffv1" ] ; then
+# ffv1 encoding
+file=${outfile}ffv1.avi
+do_video_encoding "-strict -2" "-an -vcodec ffv1"
+
+# ffv1 decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_snow" ] ; then
+# snow encoding
+file=${outfile}snow.avi
+do_video_encoding "-strict -2" "-an -vcodec snow -qscale 2 -flags +qpel -me iter -dia_size 2 -cmp 12 -subcmp 12 -s 128x64"
+
+# snow decoding
+do_video_decoding -s 352x288
+fi
+
+###################################
+if [ -n "$do_snowll" ] ; then
+# snow encoding
+file=${outfile}snow53.avi
+do_video_encoding "-strict -2" "-an -vcodec snow -qscale .001 -pred 1 -flags +mv4+qpel"
+
+# snow decoding
+do_video_decoding
+fi
+
+###################################
+if [ -n "$do_dv" ] ; then
+# dv encoding
+file=${outfile}dv.dv
+do_video_encoding "-dct int" "-s pal -an"
+
+# dv decoding
+do_video_decoding -s cif
+fi
+
+###################################
+if [ -n "$do_dv50" ] ; then
+# dv50 encoding
+file=${outfile}dv.dv
+do_video_encoding "-dct int" "-s pal -pix_fmt yuv422p -an"
+
+# dv50 decoding
+do_video_decoding -s cif -pix_fmt yuv420p
+fi
+
+
+###################################
+if [ -n "$do_svq1" ] ; then
+# svq1 encoding
+file=${outfile}svq1.mov
+do_video_encoding "" "-an -vcodec svq1 -qscale 3 -pix_fmt yuv410p"
+
+# svq1 decoding
+do_video_decoding -pix_fmt yuv420p
+fi
+
+###################################
+if [ -n "$do_mp2" ] ; then
+# mp2 encoding
+do_audio_encoding mp2.mp2 "-ar 44100"
+
+# mp2 decoding
+do_audio_decoding
+$tiny_psnr $pcm_dst $pcm_ref 2 1924 >> $logfile
+fi
+
+###################################
+if [ -n "$do_ac3" ] ; then
+# ac3 encoding
+do_audio_encoding ac3.rm "" -vn
+
+# ac3 decoding
+#do_audio_decoding
+fi
+
+###################################
+if [ -n "$do_g726" ] ; then
+# g726 encoding
+do_audio_encoding g726.wav "-ar 44100" "-ab 32 -ac 1 -ar 8000 -acodec g726"
+
+# g726 decoding
+do_audio_decoding
+fi
+
+###################################
+if [ -n "$do_adpcm_ima_wav" ] ; then
+# encoding
+do_audio_encoding adpcm_ima.wav "-ar 44100" "-acodec adpcm_ima_wav"
+
+# decoding
+do_audio_decoding
+fi
+
+###################################
+if [ -n "$do_adpcm_ms" ] ; then
+# encoding
+do_audio_encoding adpcm_ms.wav "-ar 44100" "-acodec adpcm_ms"
+
+# decoding
+do_audio_decoding
+fi
+
+###################################
+if [ -n "$do_adpcm_yam" ] ; then
+# encoding
+do_audio_encoding adpcm_yam.wav "-ar 44100" "-acodec adpcm_yamaha"
+
+# decoding
+do_audio_decoding
+fi
+
+###################################
+if [ -n "$do_flac" ] ; then
+# encoding
+do_audio_encoding flac.flac "-ar 44100" "-acodec flac -compression_level 2"
+
+# decoding
+do_audio_decoding
+fi
+
+###################################
+# libav testing
+###################################
+
+if [ -n "$do_libav" ] ; then
+
+# avi
+do_libav avi
+
+# asf
+do_libav asf "-acodec mp2" "-r 25"
+
+# rm
+file=${outfile}libav.rm
+do_ffmpeg $file -t 1 -y -qscale 10 -f pgmyuv -i $raw_src -f s16le -i $pcm_src $file
+# broken
+#do_ffmpeg_crc $file -i $file
+
+# mpegps
+do_libav mpg
+
+# mpegts
+do_libav ts
+
+# swf (decode audio only)
+do_libav swf "-acodec mp2"
+
+# ffm
+do_libav ffm
+
+# flv
+do_libav flv -an
+
+# mov
+do_libav mov "-acodec pcm_alaw"
+
+# nut
+#do_libav nut "-acodec mp2"
+
+# dv
+do_libav dv "-ar 48000 -r 25 -s pal -ac 2"
+
+# gxf
+do_libav gxf "-ar 48000 -r 25 -s pal -ac 1"
+
+####################
+# streamed images
+# mjpeg
+#file=${outfile}libav.mjpeg
+#do_ffmpeg $file -t 1 -y -qscale 10 -f pgmyuv -i $raw_src $file
+#do_ffmpeg_crc $file -i $file
+
+# pbmpipe
+do_streamed_images pbm
+
+# pgmpipe
+do_streamed_images pgm
+
+# ppmpipe
+do_streamed_images ppm
+
+# gif
+file=${outfile}libav.gif
+do_ffmpeg $file -t 1 -y -qscale 10 -f pgmyuv -i $raw_src -pix_fmt rgb24 $file
+#do_ffmpeg_crc $file -i $file
+
+# yuv4mpeg
+file=${outfile}libav.y4m
+do_ffmpeg $file -t 1 -y -qscale 10 -f pgmyuv -i $raw_src $file
+#do_ffmpeg_crc $file -i $file
+
+####################
+# image formats
+# pgm (we do not do md5 on image files yet)
+do_image_formats pgm
+
+# ppm (we do not do md5 on image files yet)
+do_image_formats ppm
+
+# jpeg (we do not do md5 on image files yet)
+do_image_formats jpg "-flags +bitexact -dct fastint -idct simple -pix_fmt yuvj420p" "-f image2"
+
+####################
+# audio only
+
+# wav
+do_audio_only wav
+
+# alaw
+do_audio_only al
+
+# mulaw
+do_audio_only ul
+
+# au
+do_audio_only au
+
+# mmf
+do_audio_only mmf
+
+# aiff
+do_audio_only aif
+
+# voc
+do_audio_only voc
+
+####################
+# pix_fmt conversions
+conversions="yuv420p yuv422p yuv444p yuv422 yuv410p yuv411p yuvj420p \
+ yuvj422p yuvj444p rgb24 bgr24 rgba32 rgb565 rgb555 gray monow \
+ monob pal8"
+for pix_fmt in $conversions ; do
+ file=${outfile}libav-${pix_fmt}.yuv
+ do_ffmpeg_nocheck $file -r 1 -t 1 -y -f pgmyuv -i $raw_src \
+ -f rawvideo -s 352x288 -pix_fmt $pix_fmt $raw_dst
+ do_ffmpeg $file -f rawvideo -s 352x288 -pix_fmt $pix_fmt -i $raw_dst \
+ -f rawvideo -s 352x288 -pix_fmt yuv444p $file
+done
+
+fi
+
+
+
+if $diff_cmd "$logfile" "$reffile" ; then
+ echo
+ echo Regression test succeeded.
+ exit 0
+else
+ echo
+ echo Regression test: Error.
+ exit 1
+fi
diff --git a/contrib/ffmpeg/tests/rotozoom.c b/contrib/ffmpeg/tests/rotozoom.c
new file mode 100644
index 000000000..5549d6ec2
--- /dev/null
+++ b/contrib/ffmpeg/tests/rotozoom.c
@@ -0,0 +1,289 @@
+/*
+ * Generates a synthetic YUV video sequence suitable for codec testing.
+ * GPLv2
+ * rotozoom.c -> s.bechet@av7.net
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+#define FIXP (1<<16)
+#define MY_PI 205887 //(M_PI*FIX)
+
+static int64_t int_pow(int64_t a, int p){
+ int64_t v= FIXP;
+
+ for(; p; p--){
+ v*= a;
+ v/= FIXP;
+ }
+
+ return v;
+}
+
+static int64_t int_sin(int64_t a){
+ if(a<0) a= MY_PI-a; // 0..inf
+ a %= 2*MY_PI; // 0..2PI
+
+ if(a>=MY_PI*3/2) a -= 2*MY_PI; // -PI/2 .. 3PI/2
+ if(a>=MY_PI/2 ) a = MY_PI - a; // -PI/2 .. PI/2
+
+ return a - int_pow(a, 3)/6 + int_pow(a, 5)/120 - int_pow(a, 7)/5040;
+}
+
+#define SCALEBITS 8
+#define ONE_HALF (1 << (SCALEBITS - 1))
+#define FIX(x) ((int) ((x) * (1L<<SCALEBITS) + 0.5))
+typedef unsigned char UINT8;
+
+static void rgb24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
+ UINT8 *src, int width, int height)
+{
+ int wrap, wrap3, x, y;
+ int r, g, b, r1, g1, b1;
+ UINT8 *p;
+
+ wrap = width;
+ wrap3 = width * 3;
+ p = src;
+ for(y=0;y<height;y+=2) {
+ for(x=0;x<width;x+=2) {
+ r = p[0];
+ g = p[1];
+ b = p[2];
+ r1 = r;
+ g1 = g;
+ b1 = b;
+ lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
+ FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
+ r = p[3];
+ g = p[4];
+ b = p[5];
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
+ FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
+ p += wrap3;
+ lum += wrap;
+
+ r = p[0];
+ g = p[1];
+ b = p[2];
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
+ FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
+ r = p[3];
+ g = p[4];
+ b = p[5];
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
+ FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
+
+ cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
+ FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
+ cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
+ FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
+
+ cb++;
+ cr++;
+ p += -wrap3 + 2 * 3;
+ lum += -wrap + 2;
+ }
+ p += wrap3;
+ lum += wrap;
+ }
+}
+
+/* cif format */
+#define DEFAULT_WIDTH 352
+#define DEFAULT_HEIGHT 288
+#define DEFAULT_NB_PICT 50
+
+void pgmyuv_save(const char *filename, int w, int h,
+ unsigned char *rgb_tab)
+{
+ FILE *f;
+ int i, h2, w2;
+ unsigned char *cb, *cr;
+ unsigned char *lum_tab, *cb_tab, *cr_tab;
+
+ lum_tab = malloc(w * h);
+ cb_tab = malloc((w * h) / 4);
+ cr_tab = malloc((w * h) / 4);
+
+ rgb24_to_yuv420p(lum_tab, cb_tab, cr_tab, rgb_tab, w, h);
+
+ f = fopen(filename,"wb");
+ fprintf(f, "P5\n%d %d\n%d\n", w, (h * 3) / 2, 255);
+ fwrite(lum_tab, 1, w * h, f);
+ h2 = h / 2;
+ w2 = w / 2;
+ cb = cb_tab;
+ cr = cr_tab;
+ for(i=0;i<h2;i++) {
+ fwrite(cb, 1, w2, f);
+ fwrite(cr, 1, w2, f);
+ cb += w2;
+ cr += w2;
+ }
+ fclose(f);
+
+ free(lum_tab);
+ free(cb_tab);
+ free(cr_tab);
+}
+
+unsigned char *rgb_tab;
+int width, height, wrap;
+
+void put_pixel(int x, int y, int r, int g, int b)
+{
+ unsigned char *p;
+
+ if (x < 0 || x >= width ||
+ y < 0 || y >= height)
+ return;
+
+ p = rgb_tab + y * wrap + x * 3;
+ p[0] = r;
+ p[1] = g;
+ p[2] = b;
+}
+
+unsigned char tab_r[256*256];
+unsigned char tab_g[256*256];
+unsigned char tab_b[256*256];
+
+int teta = 0;
+int h_cos [360];
+int h_sin [360];
+
+static int ipol(uint8_t *src, int x, int y){
+ int int_x= x>>16;
+ int int_y= y>>16;
+ int frac_x= x&0xFFFF;
+ int frac_y= y&0xFFFF;
+ int s00= src[ ( int_x &255) + 256*( int_y &255) ];
+ int s01= src[ ((int_x+1)&255) + 256*( int_y &255) ];
+ int s10= src[ ( int_x &255) + 256*((int_y+1)&255) ];
+ int s11= src[ ((int_x+1)&255) + 256*((int_y+1)&255) ];
+ int s0= (((1<<16) - frac_x)*s00 + frac_x*s01)>>8;
+ int s1= (((1<<16) - frac_x)*s10 + frac_x*s11)>>8;
+
+ return (((1<<16) - frac_y)*s0 + frac_y*s1)>>24;
+}
+
+void gen_image(int num, int w, int h)
+{
+ const int c = h_cos [teta];
+ const int s = h_sin [teta];
+
+ const int xi = -(w/2) * c;
+ const int yi = (w/2) * s;
+
+ const int xj = -(h/2) * s;
+ const int yj = -(h/2) * c;
+ int i,j;
+
+ int x,y;
+ int xprime = xj;
+ int yprime = yj;
+
+
+ for (j=0;j<h;j++) {
+
+ x = xprime + xi + FIXP*w/2;
+ xprime += s;
+
+ y = yprime + yi + FIXP*h/2;
+ yprime += c;
+
+ for ( i=0 ; i<w ; i++ ) {
+ x += c;
+ y -= s;
+#if 1
+ put_pixel(i, j, ipol(tab_r, x, y), ipol(tab_g, x, y), ipol(tab_b, x, y));
+#else
+ {
+ unsigned dep;
+ dep = ((x>>16)&255) + (((y>>16)&255)<<8);
+ put_pixel(i, j, tab_r[dep], tab_g[dep], tab_b[dep]);
+ }
+#endif
+ }
+ }
+ teta = (teta+1) % 360;
+}
+
+#define W 256
+#define H 256
+
+void init_demo(const char *filename) {
+ int i,j;
+ int h;
+ int radian;
+ char line[3 * W];
+
+ FILE *fichier;
+
+ fichier = fopen(filename,"rb");
+ if (!fichier) {
+ perror(filename);
+ exit(1);
+ }
+
+ fread(line, 1, 15, fichier);
+ for (i=0;i<H;i++) {
+ fread(line,1,3*W,fichier);
+ for (j=0;j<W;j++) {
+ tab_r[W*i+j] = line[3*j ];
+ tab_g[W*i+j] = line[3*j + 1];
+ tab_b[W*i+j] = line[3*j + 2];
+ }
+ }
+ fclose(fichier);
+
+ /* tables sin/cos */
+ for (i=0;i<360;i++) {
+ radian = 2*i*MY_PI/360;
+ h = 2*FIXP + int_sin (radian);
+ h_cos[i] = ( h * int_sin (radian + MY_PI/2) )/2/FIXP;
+ h_sin[i] = ( h * int_sin (radian ) )/2/FIXP;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int w, h, i;
+ char buf[1024];
+
+ if (argc != 3) {
+ printf("usage: %s directory/ image.pnm\n"
+ "generate a test video stream\n", argv[0]);
+ exit(1);
+ }
+
+ w = DEFAULT_WIDTH;
+ h = DEFAULT_HEIGHT;
+
+ rgb_tab = malloc(w * h * 3);
+ wrap = w * 3;
+ width = w;
+ height = h;
+
+ init_demo(argv[2]);
+
+ for(i=0;i<DEFAULT_NB_PICT;i++) {
+ snprintf(buf, sizeof(buf), "%s%02d.pgm", argv[1], i);
+ gen_image(i, w, h);
+ pgmyuv_save(buf, w, h, rgb_tab);
+ }
+
+ free(rgb_tab);
+ return 0;
+}
diff --git a/contrib/ffmpeg/tests/rotozoom.regression.ref b/contrib/ffmpeg/tests/rotozoom.regression.ref
new file mode 100644
index 000000000..91dbe27d9
--- /dev/null
+++ b/contrib/ffmpeg/tests/rotozoom.regression.ref
@@ -0,0 +1,182 @@
+ffmpeg regression test
+73ca6f1deab02d1d67a0e8495c026a9e *./data/a-mpeg1.mpg
+192783 ./data/a-mpeg1.mpg
+56147e94b12f08df7213e610e177823d *./data/out.yuv
+stddev: 4.95 PSNR:34.21 bytes:7602176
+2d55ce623a7be4e8136f80266e487678 *./data/a-mpeg2.mpg
+198667 ./data/a-mpeg2.mpg
+b7cae8a1f751b821cddcbe4d5dbc518c *./data/out.yuv
+stddev: 4.96 PSNR:34.19 bytes:7602176
+6dc412b7972918b0c3be5b448c76cdbb *./data/a-mpeg2ivlc.mpg
+197869 ./data/a-mpeg2ivlc.mpg
+b7cae8a1f751b821cddcbe4d5dbc518c *./data/out.yuv
+stddev: 4.96 PSNR:34.19 bytes:7602176
+f979bcca866e6e4cad5dc6cb06e56cfb *./data/a-mpeg2.mpg
+198041 ./data/a-mpeg2.mpg
+f6d9bf24ff8676a7f6076c05cd2c81a3 *./data/out.yuv
+stddev: 4.97 PSNR:34.18 bytes:7602176
+f90197a8b6e62ae25f82625337f27240 *./data/a-mpeg2i.mpg
+204579 ./data/a-mpeg2i.mpg
+ea5057b60146c06d40449cdfc686bf13 *./data/out.yuv
+stddev: 4.98 PSNR:34.17 bytes:7602176
+dc359097986fc04df7541f720fa5da14 *./data/a-mpeg2thread.mpg
+183314 ./data/a-mpeg2thread.mpg
+354eb621a217e50252dbed937f9eab18 *./data/out.yuv
+stddev: 4.76 PSNR:34.57 bytes:7602176
+fb02afb5a0c79c7e99a32e60e19a86bc *./data/a-mpeg2threadivlc.mpg
+182460 ./data/a-mpeg2threadivlc.mpg
+354eb621a217e50252dbed937f9eab18 *./data/out.yuv
+stddev: 4.76 PSNR:34.57 bytes:7602176
+b567ce695c24fb1e08ff1c137a805e1a *./data/a-mpeg2reuse.mpg
+394759 ./data/a-mpeg2reuse.mpg
+c3a86762e97a8869ed3c969ee2e084b8 *./data/out.yuv
+stddev: 4.76 PSNR:34.56 bytes:7602176
+c09815e40a9d260628e1ebad8b2b3774 *./data/a-msmpeg4v2.avi
+129918 ./data/a-msmpeg4v2.avi
+8920194f8bf8f9cdd6c65b3df9e1a292 *./data/out.yuv
+stddev: 5.33 PSNR:33.58 bytes:7602176
+3069f95f2ffca1f20c8ea36e2625fabc *./data/a-msmpeg4.avi
+127680 ./data/a-msmpeg4.avi
+0e1c6e25c71c6a8fa8e506e3d97ca4c9 *./data/out.yuv
+stddev: 5.33 PSNR:33.58 bytes:7602176
+6896c9bdf765953d272c25e34795b934 *./data/a-wmv1.avi
+129548 ./data/a-wmv1.avi
+81eee429b665254d19a06607463c0b5e *./data/out.yuv
+stddev: 5.33 PSNR:33.59 bytes:7602176
+34b40c67036c8e09740f7acfe3d43df6 *./data/a-wmv2.avi
+129864 ./data/a-wmv2.avi
+81eee429b665254d19a06607463c0b5e *./data/out.yuv
+stddev: 5.33 PSNR:33.59 bytes:7602176
+dfd005d4c9030a0dc889c828a6408b9c *./data/a-h261.avi
+191086 ./data/a-h261.avi
+db7ceff174823b98834faa2320ca89ac *./data/out.yuv
+stddev: 6.38 PSNR:32.02 bytes:7602176
+9a368687ab34c48079f11a202839a6bc *./data/a-h263.avi
+160106 ./data/a-h263.avi
+61213b91b359697ebcefb9e0a53ac54a *./data/out.yuv
+stddev: 5.43 PSNR:33.41 bytes:7602176
+c7644d40e9f40bbd98e5a978f9f94bb4 *./data/a-h263p.avi
+868018 ./data/a-h263p.avi
+4b0ee791f280029dc03c528f76f195d4 *./data/out.yuv
+stddev: 1.91 PSNR:42.49 bytes:7602176
+f15f07988bfdb2851f88ebe3036b72d3 *./data/a-odivx.mp4
+119797 ./data/a-odivx.mp4
+90a3577850239083a9042bef33c50e85 *./data/out.yuv
+stddev: 5.34 PSNR:33.56 bytes:7602176
+a1323da0c8b437cd6961f8c90451880b *./data/a-huffyuv.avi
+6455232 ./data/a-huffyuv.avi
+dde5895817ad9d219f79a52d0bdfb001 *./data/out.yuv
+stddev: 0.00 PSNR:99.99 bytes:7602176
+a418db8cc1410a50a154e8418d78e3d7 *./data/a-mpeg4-rc.avi
+227918 ./data/a-mpeg4-rc.avi
+56b327651c526538576fbc104f696dde *./data/out.yuv
+stddev: 4.24 PSNR:35.55 bytes:7602176
+9001cf571eb7f26fa5592bdec6538583 *./data/a-mpeg4-adv.avi
+173590 ./data/a-mpeg4-adv.avi
+699edf05648fdc42196b7bebef9be269 *./data/out.yuv
+stddev: 4.84 PSNR:34.41 bytes:7602176
+5d94ca237bd1ba1a6cdab6796485c6dc *./data/a-mpeg4-thread.avi
+254248 ./data/a-mpeg4-thread.avi
+1cb815783ab9dc787add51cdbc97e156 *./data/out.yuv
+stddev: 4.03 PSNR:36.01 bytes:7602176
+59e682efe457070d21170fdb117c1961 *./data/a-mpeg4-Q.avi
+165840 ./data/a-mpeg4-Q.avi
+f5838ffcf1dd6c538e27dbe906e5eadd *./data/out.yuv
+stddev: 4.00 PSNR:36.08 bytes:7602176
+5b5b88ce610114e346a5df4f46995bb9 *./data/a-mpeg4-PSP.mp4
+325006 ./data/a-mpeg4-PSP.mp4
+90e65096aa9ebafa3fe3f44a5a47cdc4 *./data/a-error-mpeg4-adv.avi
+176588 ./data/a-error-mpeg4-adv.avi
+113defd3f8daf878e0b3fc03fafb4c09 *./data/out.yuv
+stddev: 9.02 PSNR:29.01 bytes:7602176
+c41187c99588fb7229ad330b2f80d28b *./data/a-mpeg4-nr.avi
+155044 ./data/a-mpeg4-nr.avi
+f7fc191308679f709405e62271f5c65f *./data/out.yuv
+stddev: 4.73 PSNR:34.62 bytes:7602176
+1244f602a39b255ca676ca1e47617afd *./data/a-mpeg1b.mpg
+230033 ./data/a-mpeg1b.mpg
+df02ed235141aa229b47b91b28f71da5 *./data/out.yuv
+stddev: 4.13 PSNR:35.79 bytes:7602176
+b179402bba391073b5f5f9324a834061 *./data/a-mjpeg.avi
+703564 ./data/a-mjpeg.avi
+b1aa72cfb6f9cc3f525b27abc86a8f51 *./data/out.yuv
+stddev: 4.38 PSNR:35.28 bytes:7602176
+bc0d8c868c1a05db0ff03f41768f6c5e *./data/a-ljpeg.avi
+4766558 ./data/a-ljpeg.avi
+dde5895817ad9d219f79a52d0bdfb001 *./data/out.yuv
+stddev: 0.00 PSNR:99.99 bytes:7602176
+8a2f3984a27a7513545cf98bc05fd066 *./data/a-jpegls.avi
+8334508 ./data/a-jpegls.avi
+a63d4e3ea1f0b0c0d44821da9e09b8f4 *./data/out.yuv
+stddev: 0.67 PSNR:51.57 bytes:7602176
+989a42671603dc1a7e6b156dccf0e820 *./data/a-rv10.rm
+154330 ./data/a-rv10.rm
+61213b91b359697ebcefb9e0a53ac54a *./data/out.yuv
+stddev: 5.43 PSNR:33.41 bytes:7602176
+1b1cbff8e78602de498b4314cb991e72 *./data/a-rv20.rm
+132754 ./data/a-rv20.rm
+c66afdcc0daac2f1b4167b9811968877 *./data/out.yuv
+stddev: 5.42 PSNR:33.44 bytes:7602176
+4eb34d2de25f67a2706456e999338fe9 *./data/a-asv1.avi
+832512 ./data/a-asv1.avi
+c96ff7fd17c52f99ddb7922a4cb9168f *./data/out.yuv
+stddev: 10.47 PSNR:27.72 bytes:7602176
+9649a4b68fb1107bad13e8a7574cc72d *./data/a-asv2.avi
+789072 ./data/a-asv2.avi
+74a78015b64b2cf8cb9da2e44f508a69 *./data/out.yuv
+stddev: 10.28 PSNR:27.88 bytes:7602176
+bd76377d9e167caff10ebaf381f01a82 *./data/a-flv.flv
+131337 ./data/a-flv.flv
+8999c8264fb0941561f64c4a736e9d88 *./data/out.yuv
+stddev: 5.33 PSNR:33.58 bytes:7602176
+d72b0960e162d4998b9acbabb07e99ab *./data/a-ffv1.avi
+3525804 ./data/a-ffv1.avi
+dde5895817ad9d219f79a52d0bdfb001 *./data/out.yuv
+stddev: 0.00 PSNR:99.99 bytes:7602176
+4b306a67e21771eba4c61b1cf0f56141 *./data/a-snow.avi
+68526 ./data/a-snow.avi
+d2914543504345fad6e5593f66f072bc *./data/out.yuv
+stddev: 10.93 PSNR:27.34 bytes:7602176
+892221ef4c1debf694a481a5e23e1136 *./data/a-snow53.avi
+2722066 ./data/a-snow53.avi
+dde5895817ad9d219f79a52d0bdfb001 *./data/out.yuv
+stddev: 0.00 PSNR:99.99 bytes:7602176
+af9f474238c9c68cb32e389659ee25ab *./data/a-dv.dv
+7200000 ./data/a-dv.dv
+bb69dda7a84a5b166434e28e1243d3d1 *./data/out.yuv
+stddev: 2.99 PSNR:38.59 bytes:7602176
+91dc1c1dc4a8cca72f27d85db6d7636f *./data/a-dv.dv
+14400000 ./data/a-dv.dv
+74b01209bb5e096d570dd4df112bb82d *./data/out.yuv
+stddev: 2.98 PSNR:38.61 bytes:7602176
+7ba9292d663819a9a1d1cdecc6f1b079 *./data/a-svq1.mov
+768407 ./data/a-svq1.mov
+6bc10518bc387c3bdf117997713ee69a *./data/out.yuv
+stddev: 3.44 PSNR:37.39 bytes:7602176
+21f8ff9f1daacd9133683bb4ea0f50a4 *./data/a-mp2.mp2
+95712 ./data/a-mp2.mp2
+83f8df5d5f84480566af548bb037fceb *./data/out.wav
+stddev:9330.70 PSNR:16.92 bytes:1054720
+stddev:4396.13 PSNR:23.46 bytes:1052672
+dd68110cb7e5388392f89d5160d3a825 *./data/a-ac3.rm
+98203 ./data/a-ac3.rm
+9e6e66847a568ef4f1f229b0939d2aae *./data/a-g726.wav
+24268 ./data/a-g726.wav
+a719ab6d47d8d601520edb13bf6136b4 *./data/out.wav
+stddev:8459.88 PSNR:17.77 bytes:96256
+ea2efb8ba20695a35ab0d71a7ee86f22 *./data/a-adpcm_ima.wav
+266288 ./data/a-adpcm_ima.wav
+60178d48204f5662d91776e36eddc82e *./data/out.wav
+stddev:11441.89 PSNR:15.15 bytes:1054720
+d2eee867856d2bdb6d08e936d4ceec0c *./data/a-adpcm_ms.wav
+267308 ./data/a-adpcm_ms.wav
+91a84bb4f319a3a0bf0c0441b3d3a529 *./data/out.wav
+stddev:1050.18 PSNR:35.89 bytes:1054720
+48ae9fcb043a44e316998b85043b61bc *./data/a-adpcm_yam.wav
+264236 ./data/a-adpcm_yam.wav
+e92cec8c07913ffb91ad2b11f79cdc00 *./data/out.wav
+stddev:18312.68 PSNR:11.06 bytes:1056768
+c3382f03ce2efb5d475240d288a33898 *./data/a-flac.flac
+353368 ./data/a-flac.flac
+c4228df189aad9567a037727d0e763e4 *./data/out.wav
+stddev: 33.31 PSNR:65.87 bytes:1040384
diff --git a/contrib/ffmpeg/tests/server-regression.sh b/contrib/ffmpeg/tests/server-regression.sh
new file mode 100755
index 000000000..fb28fbae8
--- /dev/null
+++ b/contrib/ffmpeg/tests/server-regression.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# Even in the 21st century some diffs are not supporting -u.
+diff -u $0 $0 > /dev/null 2>&1
+if [ $? -eq 0 ]; then
+ diff_cmd="diff -u"
+else
+ diff_cmd="diff"
+fi
+
+# Make sure that the data directory exists
+mkdir -p data
+
+cp "$2" data/test.conf
+#perl -e 'chomp($wd = `pwd`); print map { s!data/!!; "<Stream $_>\nFile $wd/data/$_\n</Stream>\n\n" } @ARGV' data/a* >> data/test.conf
+#perl -e 'chomp($wd = `pwd`); print map { s!data/!!; "<Stream $_.asf>\nFile $wd/data/$_\n</Stream>\n\n" } @ARGV' data/a* >> data/test.conf
+
+FILES=`sed -n 's/^[^#]*<Stream \(.*\)>.*/\1/p' data/test.conf | grep -v html`
+
+rm -f /tmp/feed.ffm
+../ffserver -d -f data/test.conf 2> /dev/null &
+FFSERVER_PID=$!
+echo "Waiting for feeds to startup..."
+sleep 2
+(
+ cd data || exit $?
+ rm -f ff-*;
+ WGET_OPTIONS="--user-agent=NSPlayer -q --proxy=off -e verbose=off -e server_response=off"
+ for file in $FILES; do
+ if [ `expr $file : "a-*"` != 0 ]; then
+ wget $WGET_OPTIONS --output-document=- http://localhost:9999/$file > ff-$file &
+ else
+ wget $WGET_OPTIONS --output-document=- http://localhost:9999/$file?date=19700101T000000Z | dd bs=1 count=100000 > ff-$file 2>/dev/null &
+ fi
+ MDFILES="$MDFILES ff-$file"
+ done
+ wait
+ # the status page is always different
+ md5sum $MDFILES > ffserver.regression
+)
+kill $FFSERVER_PID
+wait > /dev/null 2>&1
+if $diff_cmd data/ffserver.regression "$1" ; then
+ echo
+ echo Server regression test succeeded.
+ exit 0
+else
+ echo
+ echo Server regression test: Error.
+ exit 1
+fi
diff --git a/contrib/ffmpeg/tests/test.conf b/contrib/ffmpeg/tests/test.conf
new file mode 100644
index 000000000..cc2038a60
--- /dev/null
+++ b/contrib/ffmpeg/tests/test.conf
@@ -0,0 +1,306 @@
+#
+# This is a test configuration file. You can invoke it with
+# ../ffserver -f test.conf
+# when in the tests directory and once the vsynth1 subdirectory
+# has been populated. Then point your browser at http://whatever:9999/teststat.html
+# and you can look at the streams
+#
+
+#
+# Port on which the server is listening. You must select a different
+# port from your standard http web server if it is running on the same
+# computer.
+
+Port 9999
+RTSPPort 9990
+
+# Address on which the server is bound. Only useful if you have
+# several network interfaces.
+
+BindAddress 0.0.0.0
+
+# Number of simultaneous requests that can be handled. Since FFServer
+# is very fast, this limit is determined mainly by your Internet
+# connection speed.
+
+MaxClients 1000
+
+MaxBandwidth 100000
+
+# Access Log file (uses standard Apache log file format)
+# '-' is the standard output
+
+CustomLog -
+
+##################################################################
+# Definition of the live feeds. Each live feed contains one video
+# and/or audio sequence coming from an ffmpeg encoder or another
+# ffserver. This sequence may be encoded simultaneously with several
+# codecs at several resolutions.
+
+<Feed feed1.ffm>
+
+# You must use 'ffmpeg' to send a live feed to ffserver. In this
+# example, you can type:
+#
+# ffmpeg http://localhost:8090/feed1.ffm
+
+# ffserver can also do time shifting. It means that it can stream any
+# previously recorded live stream. The request should contain:
+# "http://xxxx?date=[YYYY-MM-DDT][[HH:]MM:]SS[.m...]".You must specify
+# a path where the feed is stored on disk. You also specify the
+# maximum size of the feed (100M bytes here). Default:
+# File=/tmp/feed_name.ffm FileMaxSize=5M
+
+File /tmp/feed.ffm
+FileMaxSize 100M
+
+# Fire up ffmpeg pointing at this stream
+
+Launch ../ffmpeg -loop_input -flags +bitexact -dct fastint -idct simple -y -f pgmyuv -i vsynth1/%02d.pgm
+acl allow localhost
+</Feed>
+
+##################################################################
+# Now you can define each stream which will be generated from the
+# original audio and video stream. Each format has a filename (here
+# 'test128.mpg'). FFServer will send this stream when answering a
+# request containing this filename.
+
+<Stream test_h.avi>
+Feed feed1.ffm
+Format avi
+#
+BitExact
+DctFastint
+IdctSimple
+VideoFrameRate 10
+VideoSize 352x288
+VideoBitRate 100
+VideoGopSize 30
+NoAudio
+
+PreRoll 10
+StartSendOnKey
+MaxTime 100
+
+</Stream>
+
+<Stream test_l.avi>
+Feed feed1.ffm
+Format avi
+#
+BitExact
+DctFastint
+IdctSimple
+VideoFrameRate 2
+VideoSize 320x240
+VideoBitRate 40
+VideoGopSize 20
+NoAudio
+
+PreRoll 20
+StartSendOnKey
+MaxTime 100
+
+</Stream>
+
+#<Stream test_h.mpg>
+#Feed feed1.ffm
+#
+#VideoFrameRate 10
+#VideoSize 352x288
+#VideoBitRate 100
+#VideoGopSize 30
+#NoAudio
+
+#PreRoll 10
+#StartSendOnKey
+#MaxTime 100
+#
+#</Stream>
+#
+#<Stream test_l.mpg>
+#Feed feed1.ffm
+##
+#VideoFrameRate 2
+#VideoSize 320x240
+#VideoBitRate 40
+#VideoGopSize 20
+#NoAudio
+#
+#PreRoll 20
+#StartSendOnKey
+#MaxTime 100
+#
+#</Stream>
+#
+<Stream test.swf>
+Feed feed1.ffm
+#
+BitExact
+DctFastint
+IdctSimple
+Qscale 10
+VideoFrameRate 10
+VideoSize 352x288
+VideoBitRate 100
+VideoGopSize 30
+NoAudio
+
+PreRoll 10
+StartSendOnKey
+MaxTime 100
+
+</Stream>
+
+<Stream test_h.asf>
+Feed feed1.ffm
+Format asf
+#
+BitExact
+DctFastint
+IdctSimple
+Qscale 10
+VideoFrameRate 10
+VideoSize 320x240
+VideoBitRate 100
+VideoGopSize 30
+NoAudio
+
+PreRoll 10
+StartSendOnKey
+MaxTime 100
+
+Title "Test data stream"
+
+</Stream>
+
+<Stream test_l.asf>
+Feed feed1.ffm
+Format asf
+#
+BitExact
+DctFastint
+IdctSimple
+Qscale 10
+VideoFrameRate 2
+VideoSize 320x240
+VideoBitRate 40
+VideoGopSize 20
+NoAudio
+
+PreRoll 20
+StartSendOnKey
+MaxTime 100
+
+Title "Test data stream"
+
+</Stream>
+
+<Stream test_h.rm>
+
+Feed feed1.ffm
+Format rm
+
+BitExact
+DctFastint
+IdctSimple
+Qscale 10
+VideoBitRate 100
+VideoFrameRate 10
+VideoGopSize 30
+VideoSize 320x240
+NoAudio
+
+PreRoll 10
+StartSendOnKey
+MaxTime 100
+
+</Stream>
+
+<Stream test_l.rm>
+
+Feed feed1.ffm
+Format rm
+
+BitExact
+DctFastint
+IdctSimple
+Qscale 10
+VideoBitRate 40
+VideoFrameRate 2
+VideoGopSize 20
+VideoSize 320x240
+NoAudio
+
+PreRoll 20
+StartSendOnKey
+MaxTime 100
+
+</Stream>
+
+
+<Stream test.jpg>
+
+Feed feed1.ffm
+Format jpeg
+Strict -1
+
+BitExact
+DctFastint
+IdctSimple
+VideoFrameRate 1
+VideoSize 352x288
+NoAudio
+
+PreRoll 2
+
+</Stream>
+
+<Stream test_small.jpg>
+
+Feed feed1.ffm
+Format jpeg
+Strict -1
+
+BitExact
+DctFastint
+IdctSimple
+VideoFrameRate 1
+VideoSize 160x128
+NoAudio
+
+PreRoll 2
+
+</Stream>
+
+<Stream test.mjpg>
+
+Feed feed1.ffm
+Format mpjpeg
+Strict -1
+
+BitExact
+DctFastint
+IdctSimple
+VideoFrameRate 1
+VideoSize 320x240
+NoAudio
+StartSendOnKey
+
+PreRoll 1
+MaxTime 100
+
+</Stream>
+
+
+##################################################################
+# Special stream : server status
+
+<Stream teststat.html>
+
+Format status
+
+</Stream>
+
diff --git a/contrib/ffmpeg/tests/tiny_psnr.c b/contrib/ffmpeg/tests/tiny_psnr.c
new file mode 100644
index 000000000..d8bce2b7b
--- /dev/null
+++ b/contrib/ffmpeg/tests/tiny_psnr.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#define F 100
+#define SIZE 2048
+
+uint64_t exp16_table[21]={
+ 65537,
+ 65538,
+ 65540,
+ 65544,
+ 65552,
+ 65568,
+ 65600,
+ 65664,
+ 65793,
+ 66050,
+ 66568,
+ 67616,
+ 69763,
+ 74262,
+ 84150,
+ 108051,
+ 178145,
+ 484249,
+ 3578144,
+ 195360063,
+ 582360139072LL,
+};
+#if 1
+// 16.16 fixpoint exp()
+static unsigned int exp16(unsigned int a){
+ int i;
+ int out= 1<<16;
+
+ for(i=19;i>=0;i--){
+ if(a&(1<<i))
+ out= (out*exp16_table[i] + (1<<15))>>16;
+ }
+
+ return out;
+}
+// 16.16 fixpoint log()
+static int64_t log16(uint64_t a){
+ int i;
+ int out=0;
+
+ if(a < 1<<16)
+ return -log16((1LL<<32) / a);
+ a<<=16;
+
+ for(i=20;i>=0;i--){
+ int64_t b= exp16_table[i];
+ if(a<(b<<16)) continue;
+ out |= 1<<i;
+ a = ((a/b)<<16) + (((a%b)<<16) + b/2)/b;
+ }
+ return out;
+}
+
+#endif
+static uint64_t int_sqrt(uint64_t a)
+{
+ uint64_t ret=0;
+ int s;
+ uint64_t ret_sq=0;
+
+ for(s=31; s>=0; s--){
+ uint64_t b= ret_sq + (1ULL<<(s*2)) + (ret<<s)*2;
+ if(b<=a){
+ ret_sq=b;
+ ret+= 1ULL<<s;
+ }
+ }
+ return ret;
+}
+
+int main(int argc,char* argv[]){
+ int i, j;
+ uint64_t sse=0;
+ uint64_t dev;
+ FILE *f[2];
+ uint8_t buf[2][SIZE];
+ uint64_t psnr;
+ int len= argc<4 ? 1 : atoi(argv[3]);
+ int64_t max= (1<<(8*len))-1;
+ int shift= argc<5 ? 0 : atoi(argv[4]);
+ int skip_bytes = argc<6 ? 0 : atoi(argv[5]);
+
+ if(argc<3){
+ printf("tiny_psnr <file1> <file2> [<elem size> [<shift> [<skip bytes>]]]\n");
+ printf("for wav files use the following:\n");
+ printf("./tiny_psnr file1.wav file2.wav 2 0 44 to skip the header.\n");
+ return -1;
+ }
+
+ f[0]= fopen(argv[1], "rb");
+ f[1]= fopen(argv[2], "rb");
+ fseek(f[shift<0], shift < 0 ? -shift : shift, SEEK_SET);
+
+ fseek(f[0],skip_bytes,SEEK_CUR);
+ fseek(f[1],skip_bytes,SEEK_CUR);
+
+ for(i=0;;){
+ if( fread(buf[0], SIZE, 1, f[0]) != 1) break;
+ if( fread(buf[1], SIZE, 1, f[1]) != 1) break;
+
+ for(j=0; j<SIZE; i++,j++){
+ int64_t a= buf[0][j];
+ int64_t b= buf[1][j];
+ if(len==2){
+ a= (int16_t)(a | (buf[0][++j]<<8));
+ b= (int16_t)(b | (buf[1][ j]<<8));
+ }
+ sse += (a-b) * (a-b);
+ }
+ }
+
+ if(!i) i=1;
+ dev= int_sqrt( ((sse/i)*F*F) + (((sse%i)*F*F) + i/2)/i );
+ if(sse)
+ psnr= ((2*log16(max<<16) + log16(i) - log16(sse))*284619LL*F + (1<<31)) / (1LL<<32);
+ else
+ psnr= 100*F-1; //floating point free infinity :)
+
+ printf("stddev:%3d.%02d PSNR:%2d.%02d bytes:%d\n",
+ (int)(dev/F), (int)(dev%F),
+ (int)(psnr/F), (int)(psnr%F),
+ i*len);
+ return 0;
+}
+
+
diff --git a/contrib/ffmpeg/tests/videogen.c b/contrib/ffmpeg/tests/videogen.c
new file mode 100644
index 000000000..a6b8ce167
--- /dev/null
+++ b/contrib/ffmpeg/tests/videogen.c
@@ -0,0 +1,278 @@
+/*
+ * Generates a synthetic YUV video sequence suitable for codec testing.
+ * NOTE: no floats are used to guaranty a bit exact output.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+
+#define SCALEBITS 8
+#define ONE_HALF (1 << (SCALEBITS - 1))
+#define FIX(x) ((int) ((x) * (1L<<SCALEBITS) + 0.5))
+typedef unsigned char uint8_t;
+
+static void rgb24_to_yuv420p(uint8_t *lum, uint8_t *cb, uint8_t *cr,
+ uint8_t *src, int width, int height)
+{
+ int wrap, wrap3, x, y;
+ int r, g, b, r1, g1, b1;
+ uint8_t *p;
+
+ wrap = width;
+ wrap3 = width * 3;
+ p = src;
+ for(y=0;y<height;y+=2) {
+ for(x=0;x<width;x+=2) {
+ r = p[0];
+ g = p[1];
+ b = p[2];
+ r1 = r;
+ g1 = g;
+ b1 = b;
+ lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
+ FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
+ r = p[3];
+ g = p[4];
+ b = p[5];
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
+ FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
+ p += wrap3;
+ lum += wrap;
+
+ r = p[0];
+ g = p[1];
+ b = p[2];
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
+ FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
+ r = p[3];
+ g = p[4];
+ b = p[5];
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
+ FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
+
+ cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
+ FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
+ cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
+ FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
+
+ cb++;
+ cr++;
+ p += -wrap3 + 2 * 3;
+ lum += -wrap + 2;
+ }
+ p += wrap3;
+ lum += wrap;
+ }
+}
+
+/* cif format */
+#define DEFAULT_WIDTH 352
+#define DEFAULT_HEIGHT 288
+#define DEFAULT_NB_PICT 50 /* 2 seconds */
+
+void pgmyuv_save(const char *filename, int w, int h,
+ unsigned char *rgb_tab)
+{
+ FILE *f;
+ int i, h2, w2;
+ unsigned char *cb, *cr;
+ unsigned char *lum_tab, *cb_tab, *cr_tab;
+
+ lum_tab = malloc(w * h);
+ cb_tab = malloc((w * h) / 4);
+ cr_tab = malloc((w * h) / 4);
+
+ rgb24_to_yuv420p(lum_tab, cb_tab, cr_tab, rgb_tab, w, h);
+
+ f = fopen(filename,"wb");
+ fprintf(f, "P5\n%d %d\n%d\n", w, (h * 3) / 2, 255);
+ fwrite(lum_tab, 1, w * h, f);
+ h2 = h / 2;
+ w2 = w / 2;
+ cb = cb_tab;
+ cr = cr_tab;
+ for(i=0;i<h2;i++) {
+ fwrite(cb, 1, w2, f);
+ fwrite(cr, 1, w2, f);
+ cb += w2;
+ cr += w2;
+ }
+ fclose(f);
+
+ free(lum_tab);
+ free(cb_tab);
+ free(cr_tab);
+}
+
+unsigned char *rgb_tab;
+int width, height, wrap;
+
+void put_pixel(int x, int y, int r, int g, int b)
+{
+ unsigned char *p;
+
+ if (x < 0 || x >= width ||
+ y < 0 || y >= height)
+ return;
+
+ p = rgb_tab + y * wrap + x * 3;
+ p[0] = r;
+ p[1] = g;
+ p[2] = b;
+}
+
+static unsigned int myrnd(unsigned int *seed_ptr, int n)
+{
+ unsigned int seed, val;
+
+ seed = *seed_ptr;
+ seed = (seed * 314159) + 1;
+ if (n == 256) {
+ val = seed >> 24;
+ } else {
+ val = seed % n;
+ }
+ *seed_ptr = seed;
+ return val;
+}
+
+#define NOISE_X 10
+#define NOISE_Y 30
+#define NOISE_W 26
+
+#define FRAC_BITS 8
+#define FRAC_ONE (1 << FRAC_BITS)
+
+/* cosine approximate with 1-x^2 */
+int int_cos(int a)
+{
+ int v, neg;
+ a = a & (FRAC_ONE - 1);
+ if (a >= (FRAC_ONE / 2))
+ a = FRAC_ONE - a;
+ neg = 0;
+ if (a > (FRAC_ONE / 4)) {
+ neg = -1;
+ a = (FRAC_ONE / 2) - a;
+ }
+ v = FRAC_ONE - ((a * a) >> 4);
+ v = (v ^ neg) - neg;
+ return v;
+}
+
+#define NB_OBJS 10
+
+typedef struct VObj {
+ int x, y, w, h;
+ int r, g, b;
+} VObj;
+
+VObj objs[NB_OBJS];
+
+unsigned int seed = 1;
+
+void gen_image(int num, int w, int h)
+{
+ int r, g, b, x, y, i, dx, dy, x1, y1;
+ unsigned int seed1;
+
+ if (num == 0) {
+ for(i=0;i<NB_OBJS;i++) {
+ objs[i].x = myrnd(&seed, w);
+ objs[i].y = myrnd(&seed, h);
+ objs[i].w = myrnd(&seed, w / 4) + 10;
+ objs[i].h = myrnd(&seed, h / 4) + 10;
+ objs[i].r = myrnd(&seed, 256);
+ objs[i].g = myrnd(&seed, 256);
+ objs[i].b = myrnd(&seed, 256);
+ }
+ }
+
+ /* first a moving background with gradients */
+ /* test motion estimation */
+ dx = int_cos(num * FRAC_ONE / 50) * 35;
+ dy = int_cos(num * FRAC_ONE / 50 + FRAC_ONE / 10) * 30;
+ for(y=0;y<h;y++) {
+ for(x=0;x<w;x++) {
+ x1 = (x << FRAC_BITS) + dx;
+ y1 = (y << FRAC_BITS) + dx;
+ r = ((y1 * 7) >> FRAC_BITS) & 0xff;
+ g = (((x1 + y1) * 9) >> FRAC_BITS) & 0xff;
+ b = ((x1 * 5) >> FRAC_BITS) & 0xff;
+ put_pixel(x, y, r, g, b);
+ }
+ }
+
+ /* then some noise with very high intensity to test saturation */
+ seed1 = num;
+ for(y=0;y<NOISE_W;y++) {
+ for(x=0;x<NOISE_W;x++) {
+ r = myrnd(&seed1, 256);
+ g = myrnd(&seed1, 256);
+ b = myrnd(&seed1, 256);
+ put_pixel(x + NOISE_X, y + NOISE_Y, r, g, b);
+ }
+ }
+
+ /* then moving objects */
+ for(i=0;i<NB_OBJS;i++) {
+ VObj *p = &objs[i];
+ seed1 = i;
+ for(y=0;y<p->h;y++) {
+ for(x=0;x<p->w;x++) {
+ r = p->r;
+ g = p->g;
+ b = p->b;
+ /* add a per object noise */
+ r += myrnd(&seed1, 50);
+ g += myrnd(&seed1, 50);
+ b += myrnd(&seed1, 50);
+ put_pixel(x + p->x, y + p->y, r, g, b);
+ }
+ }
+ p->x += myrnd(&seed, 21) - 10;
+ p->y += myrnd(&seed, 21) - 10;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int w, h, i;
+ char buf[1024];
+
+ if (argc != 2) {
+ printf("usage: %s file\n"
+ "generate a test video stream\n", argv[0]);
+ exit(1);
+ }
+
+#if 0
+ for(i=0;i<256;i++)
+ printf("cos(%d)=%d\n", i, int_cos(i));
+#endif
+
+ w = DEFAULT_WIDTH;
+ h = DEFAULT_HEIGHT;
+
+ rgb_tab = malloc(w * h * 3);
+ wrap = w * 3;
+ width = w;
+ height = h;
+
+ for(i=0;i<DEFAULT_NB_PICT;i++) {
+ snprintf(buf, sizeof(buf), "%s%02d.pgm", argv[1], i);
+ gen_image(i, w, h);
+ pgmyuv_save(buf, w, h, rgb_tab);
+ }
+
+ free(rgb_tab);
+ return 0;
+}
diff --git a/contrib/ffmpeg/unwrap-diff b/contrib/ffmpeg/unwrap-diff
new file mode 100755
index 000000000..ccea99b7b
--- /dev/null
+++ b/contrib/ffmpeg/unwrap-diff
@@ -0,0 +1,2 @@
+#!/bin/sh
+tr '\n' '\001' | sed 's/\x01\x01/\x01 \x01/g' | sed 's/\x01\([^-+ @]\)/ \1/g' | tr '\001' '\n'
diff --git a/contrib/ffmpeg/version.sh b/contrib/ffmpeg/version.sh
new file mode 100755
index 000000000..c04822f46
--- /dev/null
+++ b/contrib/ffmpeg/version.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+svn_revision=`cd "$1" && LC_ALL=C svn info 2> /dev/null | grep Revision | cut -d' ' -f2`
+test $svn_revision || svn_revision=`cd "$1" && grep revision .svn/entries | \
+ cut -d '"' -f2 2> /dev/null`
+test $svn_revision || svn_revision=UNKNOWN
+
+NEW_REVISION="#define FFMPEG_VERSION \"SVN-r$svn_revision\""
+OLD_REVISION=`cat version.h 2> /dev/null`
+
+# Update version.h only on revision changes to avoid spurious rebuilds
+if test "$NEW_REVISION" != "$OLD_REVISION"; then
+ echo "$NEW_REVISION" > version.h
+fi
diff --git a/contrib/ffmpeg/vhook/Makefile b/contrib/ffmpeg/vhook/Makefile
new file mode 100644
index 000000000..06b48935e
--- /dev/null
+++ b/contrib/ffmpeg/vhook/Makefile
@@ -0,0 +1,51 @@
+include ../config.mak
+
+VPATH=$(SRC_PATH_BARE)/vhook
+
+CFLAGS=-I$(BUILD_ROOT) -I$(SRC_PATH) -I$(SRC_PATH)/libavutil -I$(SRC_PATH)/libavcodec \
+ -I$(SRC_PATH)/libavformat -I$(SRC_PATH)/libswscale $(VHOOKCFLAGS) -DHAVE_AV_CONFIG_H
+LDFLAGS+= -g
+
+HOOKS=null$(SLIBSUF) fish$(SLIBSUF) ppm$(SLIBSUF) watermark$(SLIBSUF)
+ALLHOOKS=$(HOOKS) imlib2$(SLIBSUF) drawtext$(SLIBSUF)
+
+ifeq ($(HAVE_IMLIB2),yes)
+ HOOKS += imlib2$(SLIBSUF)
+ LIBS_imlib2$(SLIBSUF) = -lImlib2
+endif
+
+ifeq ($(HAVE_FREETYPE2),yes)
+ HOOKS += drawtext$(SLIBSUF)
+ CFLAGS += `freetype-config --cflags`
+ LIBS_drawtext$(SLIBSUF) = `freetype-config --libs`
+endif
+
+SRCS := $(HOOKS:$(SLIBSUF)=.c)
+
+all: $(HOOKS)
+
+depend dep: $(SRCS)
+ $(CC) -MM $(CFLAGS) $^ 1>.depend
+
+install: $(HOOKS)
+ install -d "$(shlibdir)/vhook"
+ install -m 755 $(HOOKS) "$(shlibdir)/vhook"
+
+uninstall:
+ rm -f $(addprefix $(shlibdir)/vhook/,$(ALLHOOKS))
+ -rmdir "$(shlibdir)/vhook/"
+
+%$(SLIBSUF): %.o
+ $(CC) $(LDFLAGS) -o $@ $(VHOOKSHFLAGS) $< $(VHOOKLIBS) $(LIBS_$@)
+
+clean:
+ rm -f *.o *.d *~ *.a *.lib *.so *.dylib *.dll
+
+distclean: clean
+ rm -f .depend
+
+.PHONY: all depend dep clean distclean install* uninstall*
+
+ifneq ($(wildcard .depend),)
+include .depend
+endif
diff --git a/contrib/ffmpeg/vhook/drawtext.c b/contrib/ffmpeg/vhook/drawtext.c
new file mode 100644
index 000000000..081847620
--- /dev/null
+++ b/contrib/ffmpeg/vhook/drawtext.c
@@ -0,0 +1,531 @@
+/*
+ * drawtext.c: print text over the screen
+ ******************************************************************************
+ * Options:
+ * -f <filename> font filename (MANDATORY!!!)
+ * -s <pixel_size> font size in pixels [default 16]
+ * -b print background
+ * -o outline glyphs (use the bg color)
+ * -x <pos> x position ( >= 0) [default 0]
+ * -y <pos> y position ( >= 0) [default 0]
+ * -t <text> text to print (will be passed to strftime())
+ * MANDATORY: will be used even when -T is used.
+ * in this case, -t will be used if some error
+ * occurs
+ * -T <filename> file with the text (re-read every frame)
+ * -c <#RRGGBB> foreground color ('internet' way) [default #ffffff]
+ * -C <#RRGGBB> background color ('internet' way) [default #000000]
+ *
+ ******************************************************************************
+ * Features:
+ * - True Type, Type1 and others via FreeType2 library
+ * - Font kerning (better output)
+ * - Line Wrap (if the text doesn't fit, the next char go to the next line)
+ * - Background box
+ * - Outline
+ ******************************************************************************
+ * Author: Gustavo Sverzut Barbieri <gsbarbieri@yahoo.com.br>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General 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 MAXSIZE_TEXT 1024
+
+#include "framehook.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#undef time
+#include <sys/time.h>
+#include <time.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+
+#define SCALEBITS 10
+#define ONE_HALF (1 << (SCALEBITS - 1))
+#define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
+
+#define RGB_TO_YUV(rgb_color, yuv_color) do { \
+ yuv_color[0] = (FIX(0.29900) * rgb_color[0] + FIX(0.58700) * rgb_color[1] + FIX(0.11400) * rgb_color[2] + ONE_HALF) >> SCALEBITS; \
+ yuv_color[2] = ((FIX(0.50000) * rgb_color[0] - FIX(0.41869) * rgb_color[1] - FIX(0.08131) * rgb_color[2] + ONE_HALF - 1) >> SCALEBITS) + 128; \
+ yuv_color[1] = ((- FIX(0.16874) * rgb_color[0] - FIX(0.33126) * rgb_color[1] + FIX(0.50000) * rgb_color[2] + ONE_HALF - 1) >> SCALEBITS) + 128; \
+} while (0)
+
+#define COPY_3(dst,src) { \
+ dst[0]=src[0]; \
+ dst[1]=src[1]; \
+ dst[2]=src[2]; \
+}
+
+
+
+#define SET_PIXEL(picture, yuv_color, x, y) { \
+ picture->data[0][ (x) + (y)*picture->linesize[0] ] = yuv_color[0]; \
+ picture->data[1][ ((x/2) + (y/2)*picture->linesize[1]) ] = yuv_color[1]; \
+ picture->data[2][ ((x/2) + (y/2)*picture->linesize[2]) ] = yuv_color[2]; \
+}
+
+#define GET_PIXEL(picture, yuv_color, x, y) { \
+ yuv_color[0] = picture->data[0][ (x) + (y)*picture->linesize[0] ]; \
+ yuv_color[1] = picture->data[1][ (x/2) + (y/2)*picture->linesize[1] ]; \
+ yuv_color[2] = picture->data[2][ (x/2) + (y/2)*picture->linesize[2] ]; \
+}
+
+
+typedef struct {
+ unsigned char *text;
+ char *file;
+ unsigned int x;
+ unsigned int y;
+ int bg;
+ int outline;
+ unsigned char bgcolor[3]; /* YUV */
+ unsigned char fgcolor[3]; /* YUV */
+ FT_Library library;
+ FT_Face face;
+ FT_Glyph glyphs[ 255 ];
+ FT_Bitmap bitmaps[ 255 ];
+ int advance[ 255 ];
+ int bitmap_left[ 255 ];
+ int bitmap_top[ 255 ];
+ unsigned int glyphs_index[ 255 ];
+ int text_height;
+ int baseline;
+ int use_kerning;
+} ContextInfo;
+
+
+void Release(void *ctx)
+{
+ if (ctx)
+ av_free(ctx);
+}
+
+
+static int ParseColor(char *text, unsigned char yuv_color[3])
+{
+ char tmp[3];
+ unsigned char rgb_color[3];
+ int i;
+
+ tmp[2] = '\0';
+
+ if ((!text) || (strlen(text) != 7) || (text[0] != '#') )
+ return -1;
+
+ for (i=0; i < 3; i++)
+ {
+ tmp[0] = text[i*2+1];
+ tmp[1] = text[i*2+2];
+
+ rgb_color[i] = strtol(tmp, NULL, 16);
+ }
+
+ RGB_TO_YUV(rgb_color, yuv_color);
+
+ return 0;
+}
+
+int Configure(void **ctxp, int argc, char *argv[])
+{
+ int c;
+ int error;
+ ContextInfo *ci=NULL;
+ char *font=NULL;
+ unsigned int size=16;
+ FT_BBox bbox;
+ int yMax, yMin;
+ *ctxp = av_mallocz(sizeof(ContextInfo));
+ ci = (ContextInfo *) *ctxp;
+
+ /* configure Context Info */
+ ci->text = NULL;
+ ci->file = NULL;
+ ci->x = ci->y = 0;
+ ci->fgcolor[0]=255;
+ ci->fgcolor[1]=128;
+ ci->fgcolor[2]=128;
+ ci->bgcolor[0]=0;
+ ci->fgcolor[1]=128;
+ ci->fgcolor[2]=128;
+ ci->bg = 0;
+ ci->outline = 0;
+ ci->text_height = 0;
+
+ optind = 0;
+ while ((c = getopt(argc, argv, "f:t:T:x:y:s:c:C:bo")) > 0) {
+ switch (c) {
+ case 'f':
+ font = optarg;
+ break;
+ case 't':
+ ci->text = av_strdup(optarg);
+ break;
+ case 'T':
+ ci->file = av_strdup(optarg);
+ break;
+ case 'x':
+ ci->x = (unsigned int) atoi(optarg);
+ break;
+ case 'y':
+ ci->y = (unsigned int) atoi(optarg);
+ break;
+ case 's':
+ size = (unsigned int) atoi(optarg);
+ break;
+ case 'c':
+ if (ParseColor(optarg, ci->fgcolor) == -1)
+ {
+ av_log(NULL, AV_LOG_ERROR, "Invalid foreground color: '%s'. You must specify the color in the internet way(packaged hex): #RRGGBB, ie: -c #ffffff (for white foreground)\n", optarg);
+ return -1;
+ }
+ break;
+ case 'C':
+ if (ParseColor(optarg, ci->bgcolor) == -1)
+ {
+ av_log(NULL, AV_LOG_ERROR, "Invalid foreground color: '%s'. You must specify the color in the internet way(packaged hex): #RRGGBB, ie: -c #ffffff (for white foreground)\n", optarg);
+ return -1;
+ }
+ break;
+ case 'b':
+ ci->bg=1;
+ break;
+ case 'o':
+ ci->outline=1;
+ break;
+ case '?':
+ av_log(NULL, AV_LOG_ERROR, "Unrecognized argument '%s'\n", argv[optind]);
+ return -1;
+ }
+ }
+
+ if (!ci->text)
+ {
+ av_log(NULL, AV_LOG_ERROR, "No text provided (-t text)\n");
+ return -1;
+ }
+
+ if (ci->file)
+ {
+ FILE *fp;
+ if ((fp=fopen(ci->file, "r")) == NULL)
+ {
+ av_log(NULL, AV_LOG_INFO, "WARNING: The file could not be opened. Using text provided with -t switch: %s", strerror(errno));
+ }
+ else
+ {
+ fclose(fp);
+ }
+ }
+
+ if (!font)
+ {
+ av_log(NULL, AV_LOG_ERROR, "No font file provided! (-f filename)\n");
+ return -1;
+ }
+
+ if ((error = FT_Init_FreeType(&(ci->library))) != 0)
+ {
+ av_log(NULL, AV_LOG_ERROR, "Could not load FreeType (error# %d).\n", error);
+ return -1;
+ }
+
+ if ((error = FT_New_Face( ci->library, font, 0, &(ci->face) )) != 0)
+ {
+ av_log(NULL, AV_LOG_ERROR, "Could not load face: %s (error# %d).\n", font, error);
+ return -1;
+ }
+
+ if ((error = FT_Set_Pixel_Sizes( ci->face, 0, size)) != 0)
+ {
+ av_log(NULL, AV_LOG_ERROR, "Could not set font size to %d pixels (error# %d).\n", size, error);
+ return -1;
+ }
+
+ ci->use_kerning = FT_HAS_KERNING(ci->face);
+
+ /* load and cache glyphs */
+ yMax = -32000;
+ yMin = 32000;
+ for (c=0; c < 256; c++)
+ {
+ /* Load char */
+ error = FT_Load_Char( ci->face, (unsigned char) c, FT_LOAD_RENDER | FT_LOAD_MONOCHROME );
+ if (error) continue; /* ignore errors */
+
+ /* Save bitmap */
+ ci->bitmaps[c] = ci->face->glyph->bitmap;
+ /* Save bitmap left */
+ ci->bitmap_left[c] = ci->face->glyph->bitmap_left;
+ /* Save bitmap top */
+ ci->bitmap_top[c] = ci->face->glyph->bitmap_top;
+
+ /* Save advance */
+ ci->advance[c] = ci->face->glyph->advance.x >> 6;
+
+ /* Save glyph */
+ error = FT_Get_Glyph( ci->face->glyph, &(ci->glyphs[c]) );
+ /* Save glyph index */
+ ci->glyphs_index[c] = FT_Get_Char_Index( ci->face, (unsigned char) c );
+
+ /* Measure text height to calculate text_height (or the maximum text height) */
+ FT_Glyph_Get_CBox( ci->glyphs[ c ], ft_glyph_bbox_pixels, &bbox );
+ if (bbox.yMax > yMax)
+ yMax = bbox.yMax;
+ if (bbox.yMin < yMin)
+ yMin = bbox.yMin;
+
+ }
+
+ ci->text_height = yMax - yMin;
+ ci->baseline = yMax;
+
+ return 0;
+}
+
+
+
+
+static inline void draw_glyph(AVPicture *picture, FT_Bitmap *bitmap, unsigned int x, unsigned int y, unsigned int width, unsigned int height, unsigned char yuv_fgcolor[3], unsigned char yuv_bgcolor[3], int outline)
+{
+ int r, c;
+ int spixel, dpixel[3], in_glyph=0;
+
+ if (bitmap->pixel_mode == ft_pixel_mode_mono)
+ {
+ in_glyph = 0;
+ for (r=0; (r < bitmap->rows) && (r+y < height); r++)
+ {
+ for (c=0; (c < bitmap->width) && (c+x < width); c++)
+ {
+ /* pixel in the picture (destination) */
+ GET_PIXEL(picture, dpixel, (c+x), (y+r));
+
+ /* pixel in the glyph bitmap (source) */
+ spixel = bitmap->buffer[r*bitmap->pitch +c/8] & (0x80>>(c%8));
+
+ if (spixel)
+ COPY_3(dpixel, yuv_fgcolor);
+
+ if (outline)
+ {
+ /* border detection: */
+ if ( (!in_glyph) && (spixel) )
+ /* left border detected */
+ {
+ in_glyph = 1;
+ /* draw left pixel border */
+ if (c-1 >= 0)
+ SET_PIXEL(picture, yuv_bgcolor, (c+x-1), (y+r));
+ }
+ else if ( (in_glyph) && (!spixel) )
+ /* right border detected */
+ {
+ in_glyph = 0;
+ /* 'draw' right pixel border */
+ COPY_3(dpixel, yuv_bgcolor);
+ }
+
+ if (in_glyph)
+ /* see if we have a top/bottom border */
+ {
+ /* top */
+ if ( (r-1 >= 0) && (! bitmap->buffer[(r-1)*bitmap->pitch +c/8] & (0x80>>(c%8))) )
+ /* we have a top border */
+ SET_PIXEL(picture, yuv_bgcolor, (c+x), (y+r-1));
+
+ /* bottom */
+ if ( (r+1 < height) && (! bitmap->buffer[(r+1)*bitmap->pitch +c/8] & (0x80>>(c%8))) )
+ /* we have a bottom border */
+ SET_PIXEL(picture, yuv_bgcolor, (c+x), (y+r+1));
+
+ }
+ }
+
+ SET_PIXEL(picture, dpixel, (c+x), (y+r));
+ }
+ }
+ }
+}
+
+
+static inline void draw_box(AVPicture *picture, unsigned int x, unsigned int y, unsigned int width, unsigned int height, unsigned char yuv_color[3])
+{
+ int i, j;
+
+ for (j = 0; (j < height); j++)
+ for (i = 0; (i < width); i++)
+ {
+ SET_PIXEL(picture, yuv_color, (i+x), (y+j));
+ }
+
+}
+
+
+
+
+void Process(void *ctx, AVPicture *picture, enum PixelFormat pix_fmt, int width, int height, int64_t pts)
+{
+ ContextInfo *ci = (ContextInfo *) ctx;
+ FT_Face face = ci->face;
+ FT_GlyphSlot slot = face->glyph;
+ unsigned char *text = ci->text;
+ unsigned char c;
+ int x = 0, y = 0, i=0, size=0;
+ unsigned char buff[MAXSIZE_TEXT];
+ unsigned char tbuff[MAXSIZE_TEXT];
+ time_t now = time(0);
+ int str_w, str_w_max;
+ FT_Vector pos[MAXSIZE_TEXT];
+ FT_Vector delta;
+
+ if (ci->file)
+ {
+ int fd = open(ci->file, O_RDONLY);
+
+ if (fd < 0)
+ {
+ text = ci->text;
+ av_log(NULL, AV_LOG_INFO, "WARNING: The file could not be opened. Using text provided with -t switch: %s", strerror(errno));
+ }
+ else
+ {
+ int l = read(fd, tbuff, sizeof(tbuff) - 1);
+
+ if (l >= 0)
+ {
+ tbuff[l] = 0;
+ text = tbuff;
+ }
+ else
+ {
+ text = ci->text;
+ av_log(NULL, AV_LOG_INFO, "WARNING: The file could not be read. Using text provided with -t switch: %s", strerror(errno));
+ }
+ close(fd);
+ }
+ }
+ else
+ {
+ text = ci->text;
+ }
+
+ strftime(buff, sizeof(buff), text, localtime(&now));
+
+ text = buff;
+
+ size = strlen(text);
+
+
+
+
+ /* measure string size and save glyphs position*/
+ str_w = str_w_max = 0;
+ x = ci->x;
+ y = ci->y;
+ for (i=0; i < size; i++)
+ {
+ c = text[i];
+
+ /* kerning */
+ if ( (ci->use_kerning) && (i > 0) && (ci->glyphs_index[c]) )
+ {
+ FT_Get_Kerning( ci->face,
+ ci->glyphs_index[ text[i-1] ],
+ ci->glyphs_index[c],
+ ft_kerning_default,
+ &delta );
+
+ x += delta.x >> 6;
+ }
+
+ if (( (x + ci->advance[ c ]) >= width ) || ( c == '\n' ))
+ {
+ str_w = width - ci->x - 1;
+
+ y += ci->text_height;
+ x = ci->x;
+ }
+
+
+ /* save position */
+ pos[i].x = x + ci->bitmap_left[c];
+ pos[i].y = y - ci->bitmap_top[c] + ci->baseline;
+
+
+ x += ci->advance[c];
+
+
+ if (str_w > str_w_max)
+ str_w_max = str_w;
+
+ }
+
+
+
+
+ if (ci->bg)
+ {
+ /* Check if it doesn't pass the limits */
+ if ( str_w_max + ci->x >= width )
+ str_w_max = width - ci->x - 1;
+ if ( y >= height )
+ y = height - 1 - 2*ci->y;
+
+ /* Draw Background */
+ draw_box( picture, ci->x, ci->y, str_w_max, y - ci->y, ci->bgcolor );
+ }
+
+
+
+ /* Draw Glyphs */
+ for (i=0; i < size; i++)
+ {
+ c = text[i];
+
+ if (
+ ( (c == '_') && (text == ci->text) ) || /* skip '_' (consider as space)
+ IF text was specified in cmd line
+ (which doesn't like neasted quotes) */
+ ( c == '\n' ) /* Skip new line char, just go to new line */
+ )
+ continue;
+
+ /* now, draw to our target surface */
+ draw_glyph( picture,
+ &(ci->bitmaps[ c ]),
+ pos[i].x,
+ pos[i].y,
+ width,
+ height,
+ ci->fgcolor,
+ ci->bgcolor,
+ ci->outline );
+
+ /* increment pen position */
+ x += slot->advance.x >> 6;
+ }
+
+
+}
+
diff --git a/contrib/ffmpeg/vhook/fish.c b/contrib/ffmpeg/vhook/fish.c
new file mode 100644
index 000000000..2a30d2847
--- /dev/null
+++ b/contrib/ffmpeg/vhook/fish.c
@@ -0,0 +1,380 @@
+/*
+ * Fish Detector Hook
+ * Copyright (c) 2002 Philip Gladstone
+ *
+ * This file implements a fish detector. It is used to see when a
+ * goldfish passes in front of the camera. It does this by counting
+ * the number of input pixels that fall within a particular HSV
+ * range.
+ *
+ * It takes a multitude of arguments:
+ *
+ * -h <num>-<num> the range of H values that are fish
+ * -s <num>-<num> the range of S values that are fish
+ * -v <num>-<num> the range of V values that are fish
+ * -z zap all non-fish values to black
+ * -l <num> limit the number of saved files to <num>
+ * -i <num> only check frames every <num> seconds
+ * -t <num> the threshold for the amount of fish pixels (range 0-1)
+ * -d turn debugging on
+ * -D <directory> where to put the fish images
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <dirent.h>
+
+#include "framehook.h"
+#include "dsputil.h"
+#include "avformat.h"
+#include "swscale.h"
+
+static int sws_flags = SWS_BICUBIC;
+
+#define SCALEBITS 10
+#define ONE_HALF (1 << (SCALEBITS - 1))
+#define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
+
+#define YUV_TO_RGB1_CCIR(cb1, cr1)\
+{\
+ cb = (cb1) - 128;\
+ cr = (cr1) - 128;\
+ r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;\
+ g_add = - FIX(0.34414*255.0/224.0) * cb - FIX(0.71414*255.0/224.0) * cr + \
+ ONE_HALF;\
+ b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;\
+}
+
+#define YUV_TO_RGB2_CCIR(r, g, b, y1)\
+{\
+ yt = ((y1) - 16) * FIX(255.0/219.0);\
+ r = cm[(yt + r_add) >> SCALEBITS];\
+ g = cm[(yt + g_add) >> SCALEBITS];\
+ b = cm[(yt + b_add) >> SCALEBITS];\
+}
+
+
+
+
+typedef struct {
+ int h; /* 0 .. 360 */
+ int s; /* 0 .. 255 */
+ int v; /* 0 .. 255 */
+} HSV;
+
+typedef struct {
+ int zapping;
+ int threshold;
+ HSV dark, bright;
+ char *dir;
+ int file_limit;
+ int debug;
+ int min_interval;
+ int64_t next_pts;
+ int inset;
+ int min_width;
+ struct SwsContext *toRGB_convert_ctx;
+} ContextInfo;
+
+static void dorange(const char *s, int *first, int *second, int maxval)
+{
+ sscanf(s, "%d-%d", first, second);
+ if (*first > maxval)
+ *first = maxval;
+ if (*second > maxval)
+ *second = maxval;
+}
+
+void Release(void *ctx)
+{
+ ContextInfo *ci;
+ ci = (ContextInfo *) ctx;
+
+ if (ctx) {
+ sws_freeContext(ci->toRGB_convert_ctx);
+ av_free(ctx);
+ }
+}
+
+int Configure(void **ctxp, int argc, char *argv[])
+{
+ ContextInfo *ci;
+ int c;
+
+ *ctxp = av_mallocz(sizeof(ContextInfo));
+ ci = (ContextInfo *) *ctxp;
+
+ optind = 0;
+
+ ci->dir = "/tmp";
+ ci->threshold = 100;
+ ci->file_limit = 100;
+ ci->min_interval = 1000000;
+ ci->inset = 10; /* Percent */
+
+ while ((c = getopt(argc, argv, "w:i:dh:s:v:zl:t:D:")) > 0) {
+ switch (c) {
+ case 'h':
+ dorange(optarg, &ci->dark.h, &ci->bright.h, 360);
+ break;
+ case 's':
+ dorange(optarg, &ci->dark.s, &ci->bright.s, 255);
+ break;
+ case 'v':
+ dorange(optarg, &ci->dark.v, &ci->bright.v, 255);
+ break;
+ case 'z':
+ ci->zapping = 1;
+ break;
+ case 'l':
+ ci->file_limit = atoi(optarg);
+ break;
+ case 'i':
+ ci->min_interval = 1000000 * atof(optarg);
+ break;
+ case 't':
+ ci->threshold = atof(optarg) * 1000;
+ if (ci->threshold > 1000 || ci->threshold < 0) {
+ fprintf(stderr, "Invalid threshold value '%s' (range is 0-1)\n", optarg);
+ return -1;
+ }
+ break;
+ case 'w':
+ ci->min_width = atoi(optarg);
+ break;
+ case 'd':
+ ci->debug++;
+ break;
+ case 'D':
+ ci->dir = av_strdup(optarg);
+ break;
+ default:
+ fprintf(stderr, "Unrecognized argument '%s'\n", argv[optind]);
+ return -1;
+ }
+ }
+
+ fprintf(stderr, "Fish detector configured:\n");
+ fprintf(stderr, " HSV range: %d,%d,%d - %d,%d,%d\n",
+ ci->dark.h,
+ ci->dark.s,
+ ci->dark.v,
+ ci->bright.h,
+ ci->bright.s,
+ ci->bright.v);
+ fprintf(stderr, " Threshold is %d%% pixels\n", ci->threshold / 10);
+
+
+ return 0;
+}
+
+static void get_hsv(HSV *hsv, int r, int g, int b)
+{
+ int i, v, x, f;
+
+ x = (r < g) ? r : g;
+ if (b < x)
+ x = b;
+ v = (r > g) ? r : g;
+ if (b > v)
+ v = b;
+
+ if (v == x) {
+ hsv->h = 0;
+ hsv->s = 0;
+ hsv->v = v;
+ return;
+ }
+
+ if (r == v) {
+ f = g - b;
+ i = 0;
+ } else if (g == v) {
+ f = b - r;
+ i = 2 * 60;
+ } else {
+ f = r - g;
+ i = 4 * 60;
+ }
+
+ hsv->h = i + (60 * f) / (v - x);
+ if (hsv->h < 0)
+ hsv->h += 360;
+
+ hsv->s = (255 * (v - x)) / v;
+ hsv->v = v;
+
+ return;
+}
+
+void Process(void *ctx, AVPicture *picture, enum PixelFormat pix_fmt, int width, int height, int64_t pts)
+{
+ ContextInfo *ci = (ContextInfo *) ctx;
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+ int rowsize = picture->linesize[0];
+
+#if 0
+ printf("pix_fmt = %d, width = %d, pts = %lld, ci->next_pts = %lld\n",
+ pix_fmt, width, pts, ci->next_pts);
+#endif
+
+ if (pts < ci->next_pts)
+ return;
+
+ if (width < ci->min_width)
+ return;
+
+ ci->next_pts = pts + 1000000;
+
+ if (pix_fmt == PIX_FMT_YUV420P) {
+ uint8_t *y, *u, *v;
+ int width2 = width >> 1;
+ int inrange = 0;
+ int pixcnt;
+ int h;
+ int h_start, h_end;
+ int w_start, w_end;
+
+ h_end = 2 * ((ci->inset * height) / 200);
+ h_start = height - h_end;
+
+ w_end = (ci->inset * width2) / 100;
+ w_start = width2 - w_end;
+
+ pixcnt = ((h_start - h_end) >> 1) * (w_start - w_end);
+
+ y = picture->data[0] + h_end * picture->linesize[0] + w_end * 2;
+ u = picture->data[1] + h_end * picture->linesize[1] / 2 + w_end;
+ v = picture->data[2] + h_end * picture->linesize[2] / 2 + w_end;
+
+ for (h = h_start; h > h_end; h -= 2) {
+ int w;
+
+ for (w = w_start; w > w_end; w--) {
+ unsigned int r,g,b;
+ HSV hsv;
+ int cb, cr, yt, r_add, g_add, b_add;
+
+ YUV_TO_RGB1_CCIR(u[0], v[0]);
+ YUV_TO_RGB2_CCIR(r, g, b, y[0]);
+
+ get_hsv(&hsv, r, g, b);
+
+ if (ci->debug > 1)
+ fprintf(stderr, "(%d,%d,%d) -> (%d,%d,%d)\n",
+ r,g,b,hsv.h,hsv.s,hsv.v);
+
+
+ if (hsv.h >= ci->dark.h && hsv.h <= ci->bright.h &&
+ hsv.s >= ci->dark.s && hsv.s <= ci->bright.s &&
+ hsv.v >= ci->dark.v && hsv.v <= ci->bright.v) {
+ inrange++;
+ } else if (ci->zapping) {
+ y[0] = y[1] = y[rowsize] = y[rowsize + 1] = 16;
+ u[0] = 128;
+ v[0] = 128;
+ }
+
+ y+= 2;
+ u++;
+ v++;
+ }
+
+ y += picture->linesize[0] * 2 - (w_start - w_end) * 2;
+ u += picture->linesize[1] - (w_start - w_end);
+ v += picture->linesize[2] - (w_start - w_end);
+ }
+
+ if (ci->debug)
+ fprintf(stderr, "Fish: Inrange=%d of %d = %d threshold\n", inrange, pixcnt, 1000 * inrange / pixcnt);
+
+ if (inrange * 1000 / pixcnt >= ci->threshold) {
+ /* Save to file */
+ int size;
+ char *buf;
+ AVPicture picture1;
+ static int frame_counter;
+ static int foundfile;
+
+ if ((frame_counter++ % 20) == 0) {
+ /* Check how many files we have */
+ DIR *d;
+
+ foundfile = 0;
+
+ d = opendir(ci->dir);
+ if (d) {
+ struct dirent *dent;
+
+ while ((dent = readdir(d))) {
+ if (strncmp("fishimg", dent->d_name, 7) == 0) {
+ if (strcmp(".ppm", dent->d_name + strlen(dent->d_name) - 4) == 0) {
+ foundfile++;
+ }
+ }
+ }
+ closedir(d);
+ }
+ }
+
+ if (foundfile < ci->file_limit) {
+ FILE *f;
+ char fname[256];
+
+ size = avpicture_get_size(PIX_FMT_RGB24, width, height);
+ buf = av_malloc(size);
+
+ avpicture_fill(&picture1, buf, PIX_FMT_RGB24, width, height);
+
+ // if we already got a SWS context, let's realloc if is not re-useable
+ ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx,
+ width, height, pix_fmt,
+ width, height, PIX_FMT_RGB24,
+ sws_flags, NULL, NULL, NULL);
+ if (ci->toRGB_convert_ctx == NULL) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Cannot initialize the toRGB conversion context\n");
+ exit(1);
+ }
+ // img_convert parameters are 2 first destination, then 4 source
+ // sws_scale parameters are context, 4 first source, then 2 destination
+ sws_scale(ci->toRGB_convert_ctx,
+ picture->data, picture->linesize, 0, height,
+ picture1.data, picture1.linesize);
+
+ /* Write out the PPM file */
+ snprintf(fname, sizeof(fname), "%s/fishimg%ld_%"PRId64".ppm", ci->dir, (long)(av_gettime() / 1000000), pts);
+ f = fopen(fname, "w");
+ if (f) {
+ fprintf(f, "P6 %d %d 255\n", width, height);
+ fwrite(buf, width * height * 3, 1, f);
+ fclose(f);
+ }
+
+ av_free(buf);
+ ci->next_pts = pts + ci->min_interval;
+ }
+ }
+ }
+}
+
diff --git a/contrib/ffmpeg/vhook/imlib2.c b/contrib/ffmpeg/vhook/imlib2.c
new file mode 100644
index 000000000..87c54cf0b
--- /dev/null
+++ b/contrib/ffmpeg/vhook/imlib2.c
@@ -0,0 +1,450 @@
+/*
+ * imlib2 based hook
+ * Copyright (c) 2002 Philip Gladstone
+ *
+ * This module implements a text overlay for a video image. Currently it
+ * supports a fixed overlay or reading the text from a file. The string
+ * is passed through strftime so that it is easy to imprint the date and
+ * time onto the image.
+ *
+ * You may also overlay an image (even semi-transparent) like TV stations do.
+ * You may move either the text or the image around your video to create
+ * scrolling credits, for example.
+ *
+ * Text fonts are being looked for in FONTPATH
+ *
+ * Options:
+ *
+ * -c <color> The color of the text
+ * -F <fontname> The font face and size
+ * -t <text> The text
+ * -f <filename> The filename to read text from
+ * -x <expresion> X coordinate of text or image
+ * -y <expresion> Y coordinate of text or image
+ * -i <filename> The filename to read a image from
+ *
+ * Expresions are functions of:
+ * N // frame number (starting at zero)
+ * H // frame height
+ * W // frame width
+ * h // image height
+ * w // image width
+ * X // previous x
+ * Y // previous y
+ *
+
+ Examples:
+
+ FONTPATH="/cygdrive/c/WINDOWS/Fonts/"
+ FONTPATH="$FONTPATH:/usr/share/imlib2/data/fonts/"
+ FONTPATH="$FONTPATH:/usr/X11R6/lib/X11/fonts/TTF/"
+ export FONTPATH
+
+ ffmpeg -i input.avi -vhook \
+ 'vhook/imlib2.dll -x W*(0.5+0.25*sin(N/47*PI))-w/2 -y H*(0.5+0.50*cos(N/97*PI))-h/2 -i /usr/share/imlib2/data/images/bulb.png'
+ -acodec copy -sameq output.avi
+
+ ffmpeg -i input.avi -vhook \
+ 'vhook/imlib2.dll -c red -F Vera.ttf/20 -x 150+0.5*N -y 70+0.25*N -t Hello'
+ -acodec copy -sameq output.avi
+
+ * This module is very much intended as an example of what could be done.
+ *
+ * One caution is that this is an expensive process -- in particular the
+ * conversion of the image into RGB and back is time consuming. For some
+ * special cases -- e.g. painting black text -- it would be faster to paint
+ * the text into a bitmap and then combine it directly into the YUV
+ * image. However, this code is fast enough to handle 10 fps of 320x240 on a
+ * 900MHz Duron in maybe 15% of the CPU.
+
+ * See further statistics on Pentium4, 3GHz, FFMpeg is SVN-r6798
+ * Input movie is 20.2 seconds of PAL DV on AVI
+ * Output movie is DVD compliant VOB.
+ *
+ ffmpeg -i input.avi -target pal-dvd out.vob
+ # 13.516s just transcode
+ ffmpeg -i input.avi -vhook /usr/local/bin/vhook/null.dll -target pal-dvd out.vob
+ # 23.546s transcode and img_convert
+ ffmpeg -i input.avi -vhook \
+ 'vhook/imlib2.dll -c red -F Vera/20 -x 150-0.5*N -y 70+0.25*N -t Hello_person' \
+ -target pal-dvd out.vob
+ # 21.454s transcode, img_convert and move text around
+ ffmpeg -i input.avi -vhook \
+ 'vhook/imlib2.dll -x 150-0.5*N -y 70+0.25*N -i /usr/share/imlib2/data/images/bulb.png' \
+ -target pal-dvd out.vob
+ # 20.828s transcode, img_convert and move image around
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "framehook.h"
+#include "swscale.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#undef time
+#include <sys/time.h>
+#include <time.h>
+#include <X11/Xlib.h>
+#include <Imlib2.h>
+#include "eval.h"
+
+const char *const_names[]={
+ "PI",
+ "E",
+ "N", // frame number (starting at zero)
+ "H", // frame height
+ "W", // frame width
+ "h", // image height
+ "w", // image width
+ "X", // previous x
+ "Y", // previous y
+ NULL
+};
+
+static int sws_flags = SWS_BICUBIC;
+
+typedef struct {
+ int dummy;
+ Imlib_Font fn;
+ char *text;
+ char *file;
+ int r, g, b;
+ double x, y;
+ char *fileImage;
+ struct _CachedImage *cache;
+ Imlib_Image imageOverlaid;
+ AVEvalExpr *eval_x, *eval_y;
+ char *expr_x, *expr_y;
+ int frame_number;
+ int imageOverlaid_width, imageOverlaid_height;
+
+ // This vhook first converts frame to RGB ...
+ struct SwsContext *toRGB_convert_ctx;
+ // ... and then converts back frame from RGB to initial format
+ struct SwsContext *fromRGB_convert_ctx;
+} ContextInfo;
+
+typedef struct _CachedImage {
+ struct _CachedImage *next;
+ Imlib_Image image;
+ int width;
+ int height;
+} CachedImage;
+
+void Release(void *ctx)
+{
+ ContextInfo *ci;
+ ci = (ContextInfo *) ctx;
+
+ if (ci->cache) {
+ imlib_context_set_image(ci->cache->image);
+ imlib_free_image();
+ av_free(ci->cache);
+ }
+ if (ctx) {
+ if (ci->imageOverlaid) {
+ imlib_context_set_image(ci->imageOverlaid);
+ imlib_free_image();
+ }
+ ff_eval_free(ci->expr_x);
+ ff_eval_free(ci->expr_y);
+ sws_freeContext(ci->toRGB_convert_ctx);
+ sws_freeContext(ci->fromRGB_convert_ctx);
+ av_free(ctx);
+ }
+}
+
+int Configure(void **ctxp, int argc, char *argv[])
+{
+ int c;
+ ContextInfo *ci;
+ char *font = "LucidaSansDemiBold/16";
+ char *fp = getenv("FONTPATH");
+ char *color = 0;
+ FILE *f;
+ char *p;
+
+ *ctxp = av_mallocz(sizeof(ContextInfo));
+ ci = (ContextInfo *) *ctxp;
+
+ ci->x = 0.0;
+ ci->y = 0.0;
+ ci->expr_x = "0.0";
+ ci->expr_y = "0.0";
+
+ optind = 0;
+
+ /* Use ':' to split FONTPATH */
+ if (fp)
+ while (p = strchr(fp, ':')) {
+ *p = 0;
+ imlib_add_path_to_font_path(fp);
+ fp = p + 1;
+ }
+ if ((fp) && (*fp))
+ imlib_add_path_to_font_path(fp);
+
+
+ while ((c = getopt(argc, argv, "c:f:F:t:x:y:i:")) > 0) {
+ switch (c) {
+ case 'c':
+ color = optarg;
+ break;
+ case 'F':
+ font = optarg;
+ break;
+ case 't':
+ ci->text = av_strdup(optarg);
+ break;
+ case 'f':
+ ci->file = av_strdup(optarg);
+ break;
+ case 'x':
+ ci->expr_x = av_strdup(optarg);
+ break;
+ case 'y':
+ ci->expr_y = av_strdup(optarg);
+ break;
+ case 'i':
+ ci->fileImage = av_strdup(optarg);
+ break;
+ case '?':
+ fprintf(stderr, "Unrecognized argument '%s'\n", argv[optind]);
+ return -1;
+ }
+ }
+
+ if (ci->text || ci->file) {
+ ci->fn = imlib_load_font(font);
+ if (!ci->fn) {
+ fprintf(stderr, "Failed to load font '%s'\n", font);
+ return -1;
+ }
+ imlib_context_set_font(ci->fn);
+ imlib_context_set_direction(IMLIB_TEXT_TO_RIGHT);
+ }
+
+ if (color) {
+ char buff[256];
+ int done = 0;
+
+ f = fopen("/usr/share/X11/rgb.txt", "r");
+ if (!f)
+ f = fopen("/usr/lib/X11/rgb.txt", "r");
+ if (!f) {
+ fprintf(stderr, "Failed to find rgb.txt\n");
+ return -1;
+ }
+ while (fgets(buff, sizeof(buff), f)) {
+ int r, g, b;
+ char colname[80];
+
+ if (sscanf(buff, "%d %d %d %64s", &r, &g, &b, colname) == 4 &&
+ strcasecmp(colname, color) == 0) {
+ ci->r = r;
+ ci->g = g;
+ ci->b = b;
+ /* fprintf(stderr, "%s -> %d,%d,%d\n", colname, r, g, b); */
+ done = 1;
+ break;
+ }
+ }
+ fclose(f);
+ if (!done) {
+ fprintf(stderr, "Unable to find color '%s' in rgb.txt\n", color);
+ return -1;
+ }
+ }
+ imlib_context_set_color(ci->r, ci->g, ci->b, 255);
+
+ /* load the image (for example, credits for a movie) */
+ if (ci->fileImage) {
+ ci->imageOverlaid = imlib_load_image_immediately(ci->fileImage);
+ if (!(ci->imageOverlaid)){
+ av_log(NULL, AV_LOG_ERROR, "Couldn't load image '%s'\n", ci->fileImage);
+ return -1;
+ }
+ imlib_context_set_image(ci->imageOverlaid);
+ ci->imageOverlaid_width = imlib_image_get_width();
+ ci->imageOverlaid_height = imlib_image_get_height();
+ }
+
+ if (!(ci->eval_x = ff_parse(ci->expr_x, const_names, NULL, NULL, NULL, NULL, NULL))){
+ av_log(NULL, AV_LOG_ERROR, "Couldn't parse x expression '%s'\n", ci->expr_x);
+ return -1;
+ }
+
+ if (!(ci->eval_y = ff_parse(ci->expr_y, const_names, NULL, NULL, NULL, NULL, NULL))){
+ av_log(NULL, AV_LOG_ERROR, "Couldn't parse y expression '%s'\n", ci->expr_y);
+ return -1;
+ }
+
+ return 0;
+}
+
+static Imlib_Image get_cached_image(ContextInfo *ci, int width, int height)
+{
+ CachedImage *cache;
+
+ for (cache = ci->cache; cache; cache = cache->next) {
+ if (width == cache->width && height == cache->height)
+ return cache->image;
+ }
+
+ return NULL;
+}
+
+static void put_cached_image(ContextInfo *ci, Imlib_Image image, int width, int height)
+{
+ CachedImage *cache = av_mallocz(sizeof(*cache));
+
+ cache->image = image;
+ cache->width = width;
+ cache->height = height;
+ cache->next = ci->cache;
+ ci->cache = cache;
+}
+
+void Process(void *ctx, AVPicture *picture, enum PixelFormat pix_fmt, int width, int height, int64_t pts)
+{
+ ContextInfo *ci = (ContextInfo *) ctx;
+ AVPicture picture1;
+ Imlib_Image image;
+ DATA32 *data;
+
+ image = get_cached_image(ci, width, height);
+
+ if (!image) {
+ image = imlib_create_image(width, height);
+ put_cached_image(ci, image, width, height);
+ }
+
+ imlib_context_set_image(image);
+ data = imlib_image_get_data();
+
+ avpicture_fill(&picture1, (uint8_t *) data, PIX_FMT_RGBA32, width, height);
+
+ // if we already got a SWS context, let's realloc if is not re-useable
+ ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx,
+ width, height, pix_fmt,
+ width, height, PIX_FMT_RGBA32,
+ sws_flags, NULL, NULL, NULL);
+ if (ci->toRGB_convert_ctx == NULL) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Cannot initialize the toRGB conversion context\n");
+ exit(1);
+ }
+
+// img_convert parameters are 2 first destination, then 4 source
+// sws_scale parameters are context, 4 first source, then 2 destination
+ sws_scale(ci->toRGB_convert_ctx,
+ picture->data, picture->linesize, 0, height,
+ picture1.data, picture1.linesize);
+
+ imlib_image_set_has_alpha(0);
+
+ {
+ int wid, hig, h_a, v_a;
+ char buff[1000];
+ char tbuff[1000];
+ char *tbp = ci->text;
+ time_t now = time(0);
+ char *p, *q;
+ int y;
+
+ double const_values[]={
+ M_PI,
+ M_E,
+ ci->frame_number, // frame number (starting at zero)
+ height, // frame height
+ width, // frame width
+ ci->imageOverlaid_height, // image height
+ ci->imageOverlaid_width, // image width
+ ci->x, // previous x
+ ci->y, // previous y
+ 0
+ };
+
+ if (ci->file) {
+ int fd = open(ci->file, O_RDONLY);
+
+ if (fd < 0) {
+ tbp = "[File not found]";
+ } else {
+ int l = read(fd, tbuff, sizeof(tbuff) - 1);
+
+ if (l >= 0) {
+ tbuff[l] = 0;
+ tbp = tbuff;
+ } else {
+ tbp = "[I/O Error]";
+ }
+ close(fd);
+ }
+ }
+
+ if (tbp)
+ strftime(buff, sizeof(buff), tbp, localtime(&now));
+ else if (!(ci->imageOverlaid))
+ strftime(buff, sizeof(buff), "[No data]", localtime(&now));
+
+ ci->x = ff_parse_eval(ci->eval_x, const_values, ci);
+ ci->y = ff_parse_eval(ci->eval_y, const_values, ci);
+ y = ci->y;
+
+ if (!(ci->imageOverlaid))
+ for (p = buff; p; p = q) {
+ q = strchr(p, '\n');
+ if (q)
+ *q++ = 0;
+
+ imlib_text_draw_with_return_metrics(ci->x, y, p, &wid, &hig, &h_a, &v_a);
+ y += v_a;
+ }
+
+ if (ci->imageOverlaid) {
+ imlib_context_set_image(image);
+ imlib_blend_image_onto_image(ci->imageOverlaid, 0,
+ 0, 0, ci->imageOverlaid_width, ci->imageOverlaid_height,
+ ci->x, ci->y, ci->imageOverlaid_width, ci->imageOverlaid_height);
+ }
+
+ }
+
+ ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx,
+ width, height, PIX_FMT_RGBA32,
+ width, height, pix_fmt,
+ sws_flags, NULL, NULL, NULL);
+ if (ci->fromRGB_convert_ctx == NULL) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Cannot initialize the fromRGB conversion context\n");
+ exit(1);
+ }
+// img_convert parameters are 2 first destination, then 4 source
+// sws_scale parameters are context, 4 first source, then 2 destination
+ sws_scale(ci->fromRGB_convert_ctx,
+ picture1.data, picture1.linesize, 0, height,
+ picture->data, picture->linesize);
+
+ ci->frame_number++;
+}
+
diff --git a/contrib/ffmpeg/vhook/null.c b/contrib/ffmpeg/vhook/null.c
new file mode 100644
index 000000000..041e5abda
--- /dev/null
+++ b/contrib/ffmpeg/vhook/null.c
@@ -0,0 +1,116 @@
+/*
+ * Null Video Hook
+ * Copyright (c) 2002 Philip Gladstone
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <stdio.h>
+
+#include "framehook.h"
+#include "swscale.h"
+
+static int sws_flags = SWS_BICUBIC;
+
+typedef struct {
+ int dummy;
+
+ // This vhook first converts frame to RGB ...
+ struct SwsContext *toRGB_convert_ctx;
+
+ // ... and later converts back frame from RGB to initial format
+ struct SwsContext *fromRGB_convert_ctx;
+
+} ContextInfo;
+
+void Release(void *ctx)
+{
+ ContextInfo *ci;
+ ci = (ContextInfo *) ctx;
+
+ if (ctx) {
+ sws_freeContext(ci->toRGB_convert_ctx);
+ sws_freeContext(ci->fromRGB_convert_ctx);
+ av_free(ctx);
+ }
+}
+
+int Configure(void **ctxp, int argc, char *argv[])
+{
+ fprintf(stderr, "Called with argc=%d\n", argc);
+
+ *ctxp = av_mallocz(sizeof(ContextInfo));
+ return 0;
+}
+
+void Process(void *ctx, AVPicture *picture, enum PixelFormat pix_fmt, int width, int height, int64_t pts)
+{
+ ContextInfo *ci = (ContextInfo *) ctx;
+ char *buf = 0;
+ AVPicture picture1;
+ AVPicture *pict = picture;
+
+ (void) ci;
+
+ if (pix_fmt != PIX_FMT_RGB24) {
+ int size;
+
+ size = avpicture_get_size(PIX_FMT_RGB24, width, height);
+ buf = av_malloc(size);
+
+ avpicture_fill(&picture1, buf, PIX_FMT_RGB24, width, height);
+
+ // if we already got a SWS context, let's realloc if is not re-useable
+ ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx,
+ width, height, pix_fmt,
+ width, height, PIX_FMT_RGB24,
+ sws_flags, NULL, NULL, NULL);
+ if (ci->toRGB_convert_ctx == NULL) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Cannot initialize the toRGB conversion context\n");
+ exit(1);
+ }
+// img_convert parameters are 2 first destination, then 4 source
+// sws_scale parameters are context, 4 first source, then 2 destination
+ sws_scale(ci->toRGB_convert_ctx,
+ picture->data, picture->linesize, 0, height,
+ picture1.data, picture1.linesize);
+
+ pict = &picture1;
+ }
+
+ /* Insert filter code here */
+
+ if (pix_fmt != PIX_FMT_RGB24) {
+ ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx,
+ width, height, PIX_FMT_RGB24,
+ width, height, pix_fmt,
+ sws_flags, NULL, NULL, NULL);
+ if (ci->fromRGB_convert_ctx == NULL) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Cannot initialize the fromRGB conversion context\n");
+ exit(1);
+ }
+// img_convert parameters are 2 first destination, then 4 source
+// sws_scale parameters are context, 4 first source, then 2 destination
+ sws_scale(ci->fromRGB_convert_ctx,
+ picture1.data, picture1.linesize, 0, height,
+ picture->data, picture->linesize);
+ }
+
+ av_free(buf);
+}
+
diff --git a/contrib/ffmpeg/vhook/ppm.c b/contrib/ffmpeg/vhook/ppm.c
new file mode 100644
index 000000000..51badd58d
--- /dev/null
+++ b/contrib/ffmpeg/vhook/ppm.c
@@ -0,0 +1,367 @@
+/*
+ * PPM Video Hook
+ * Copyright (c) 2003 Charles Yates
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include "framehook.h"
+#include "avformat.h"
+#include "swscale.h"
+
+static int sws_flags = SWS_BICUBIC;
+
+/** Bi-directional pipe structure.
+*/
+
+typedef struct rwpipe
+{
+ int pid;
+ FILE *reader;
+ FILE *writer;
+}
+rwpipe;
+
+/** Create a bidirectional pipe for the given command.
+*/
+
+static rwpipe *rwpipe_open( int argc, char *argv[] )
+{
+ rwpipe *this = av_mallocz( sizeof( rwpipe ) );
+
+ if ( this != NULL )
+ {
+ int input[ 2 ];
+ int output[ 2 ];
+
+ pipe( input );
+ pipe( output );
+
+ this->pid = fork();
+
+ if ( this->pid == 0 )
+ {
+#define COMMAND_SIZE 10240
+ char *command = av_mallocz( COMMAND_SIZE );
+ int i;
+
+ strcpy( command, "" );
+ for ( i = 0; i < argc; i ++ )
+ {
+ pstrcat( command, COMMAND_SIZE, argv[ i ] );
+ pstrcat( command, COMMAND_SIZE, " " );
+ }
+
+ dup2( output[ 0 ], STDIN_FILENO );
+ dup2( input[ 1 ], STDOUT_FILENO );
+
+ close( input[ 0 ] );
+ close( input[ 1 ] );
+ close( output[ 0 ] );
+ close( output[ 1 ] );
+
+ execl("/bin/sh", "sh", "-c", command, (char*)NULL );
+ exit( 255 );
+ }
+ else
+ {
+ close( input[ 1 ] );
+ close( output[ 0 ] );
+
+ this->reader = fdopen( input[ 0 ], "r" );
+ this->writer = fdopen( output[ 1 ], "w" );
+ }
+ }
+
+ return this;
+}
+
+/** Read data from the pipe.
+*/
+
+static FILE *rwpipe_reader( rwpipe *this )
+{
+ if ( this != NULL )
+ return this->reader;
+ else
+ return NULL;
+}
+
+/** Write data to the pipe.
+*/
+
+static FILE *rwpipe_writer( rwpipe *this )
+{
+ if ( this != NULL )
+ return this->writer;
+ else
+ return NULL;
+}
+
+/* Read a number from the pipe - assumes PNM style headers.
+*/
+
+static int rwpipe_read_number( rwpipe *rw )
+{
+ int value = 0;
+ int c = 0;
+ FILE *in = rwpipe_reader( rw );
+
+ do
+ {
+ c = fgetc( in );
+
+ while( c != EOF && !isdigit( c ) && c != '#' )
+ c = fgetc( in );
+
+ if ( c == '#' )
+ while( c != EOF && c != '\n' )
+ c = fgetc( in );
+ }
+ while ( c != EOF && !isdigit( c ) );
+
+ while( c != EOF && isdigit( c ) )
+ {
+ value = value * 10 + ( c - '0' );
+ c = fgetc( in );
+ }
+
+ return value;
+}
+
+/** Read a PPM P6 header.
+*/
+
+static int rwpipe_read_ppm_header( rwpipe *rw, int *width, int *height )
+{
+ char line[ 3 ];
+ FILE *in = rwpipe_reader( rw );
+ int max;
+
+ fgets( line, 3, in );
+ if ( !strncmp( line, "P6", 2 ) )
+ {
+ *width = rwpipe_read_number( rw );
+ *height = rwpipe_read_number( rw );
+ max = rwpipe_read_number( rw );
+ return max != 255 || *width <= 0 || *height <= 0;
+ }
+ return 1;
+}
+
+/** Close the pipe and process.
+*/
+
+static void rwpipe_close( rwpipe *this )
+{
+ if ( this != NULL )
+ {
+ fclose( this->reader );
+ fclose( this->writer );
+ waitpid( this->pid, NULL, 0 );
+ av_free( this );
+ }
+}
+
+/** Context info for this vhook - stores the pipe and image buffers.
+*/
+
+typedef struct
+{
+ rwpipe *rw;
+ int size1;
+ char *buf1;
+ int size2;
+ char *buf2;
+
+ // This vhook first converts frame to RGB ...
+ struct SwsContext *toRGB_convert_ctx;
+ // ... then processes it via a PPM command pipe ...
+ // ... and finally converts back frame from RGB to initial format
+ struct SwsContext *fromRGB_convert_ctx;
+}
+ContextInfo;
+
+/** Initialise the context info for this vhook.
+*/
+
+int Configure(void **ctxp, int argc, char *argv[])
+{
+ if ( argc > 1 )
+ {
+ *ctxp = av_mallocz(sizeof(ContextInfo));
+ if ( ctxp != NULL && argc > 1 )
+ {
+ ContextInfo *info = (ContextInfo *)*ctxp;
+ info->rw = rwpipe_open( argc - 1, &argv[ 1 ] );
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/** Process a frame.
+*/
+
+void Process(void *ctx, AVPicture *picture, enum PixelFormat pix_fmt, int width, int height, int64_t pts)
+{
+ int err = 0;
+ ContextInfo *ci = (ContextInfo *) ctx;
+ AVPicture picture1;
+ AVPicture picture2;
+ AVPicture *pict = picture;
+ int out_width;
+ int out_height;
+ int i;
+ uint8_t *ptr = NULL;
+ FILE *in = rwpipe_reader( ci->rw );
+ FILE *out = rwpipe_writer( ci->rw );
+
+ /* Check that we have a pipe to talk to. */
+ if ( in == NULL || out == NULL )
+ err = 1;
+
+ /* Convert to RGB24 if necessary */
+ if ( !err && pix_fmt != PIX_FMT_RGB24 )
+ {
+ int size = avpicture_get_size(PIX_FMT_RGB24, width, height);
+
+ if ( size != ci->size1 )
+ {
+ av_free( ci->buf1 );
+ ci->buf1 = av_malloc(size);
+ ci->size1 = size;
+ err = ci->buf1 == NULL;
+ }
+
+ if ( !err )
+ {
+ avpicture_fill(&picture1, ci->buf1, PIX_FMT_RGB24, width, height);
+
+ // if we already got a SWS context, let's realloc if is not re-useable
+ ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx,
+ width, height, pix_fmt,
+ width, height, PIX_FMT_RGB24,
+ sws_flags, NULL, NULL, NULL);
+ if (ci->toRGB_convert_ctx == NULL) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Cannot initialize the toRGB conversion context\n");
+ exit(1);
+ }
+
+// img_convert parameters are 2 first destination, then 4 source
+// sws_scale parameters are context, 4 first source, then 2 destination
+ sws_scale(ci->toRGB_convert_ctx,
+ picture->data, picture->linesize, 0, height,
+ picture1.data, picture1.linesize);
+
+ pict = &picture1;
+ }
+ }
+
+ /* Write out the PPM */
+ if ( !err )
+ {
+ ptr = pict->data[ 0 ];
+ fprintf( out, "P6\n%d %d\n255\n", width, height );
+ for ( i = 0; !err && i < height; i ++ )
+ {
+ err = !fwrite( ptr, width * 3, 1, out );
+ ptr += pict->linesize[ 0 ];
+ }
+ if ( !err )
+ err = fflush( out );
+ }
+
+ /* Read the PPM returned. */
+ if ( !err && !rwpipe_read_ppm_header( ci->rw, &out_width, &out_height ) )
+ {
+ int size = avpicture_get_size(PIX_FMT_RGB24, out_width, out_height);
+
+ if ( size != ci->size2 )
+ {
+ av_free( ci->buf2 );
+ ci->buf2 = av_malloc(size);
+ ci->size2 = size;
+ err = ci->buf2 == NULL;
+ }
+
+ if ( !err )
+ {
+ avpicture_fill(&picture2, ci->buf2, PIX_FMT_RGB24, out_width, out_height);
+ ptr = picture2.data[ 0 ];
+ for ( i = 0; !err && i < out_height; i ++ )
+ {
+ err = !fread( ptr, out_width * 3, 1, in );
+ ptr += picture2.linesize[ 0 ];
+ }
+ }
+ }
+
+ /* Convert the returned PPM back to the input format */
+ if ( !err )
+ {
+ /* The out_width/out_height returned from the PPM
+ * filter won't necessarily be the same as width and height
+ * but it will be scaled anyway to width/height.
+ */
+ av_log(NULL, AV_LOG_DEBUG,
+ "PPM vhook: Input dimensions: %d x %d Output dimensions: %d x %d\n",
+ width, height, out_width, out_height);
+ ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx,
+ out_width, out_height, PIX_FMT_RGB24,
+ width, height, pix_fmt,
+ sws_flags, NULL, NULL, NULL);
+ if (ci->fromRGB_convert_ctx == NULL) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Cannot initialize the fromRGB conversion context\n");
+ exit(1);
+ }
+
+// img_convert parameters are 2 first destination, then 4 source
+// sws_scale parameters are context, 4 first source, then 2 destination
+ sws_scale(ci->fromRGB_convert_ctx,
+ picture2.data, picture2.linesize, 0, out_height,
+ picture->data, picture->linesize);
+ }
+}
+
+/** Clean up the effect.
+*/
+
+void Release(void *ctx)
+{
+ ContextInfo *ci;
+ ci = (ContextInfo *) ctx;
+
+ if (ctx)
+ {
+ rwpipe_close( ci->rw );
+ av_free( ci->buf1 );
+ av_free( ci->buf2 );
+ sws_freeContext(ci->toRGB_convert_ctx);
+ sws_freeContext(ci->fromRGB_convert_ctx);
+ av_free(ctx);
+ }
+}
+
diff --git a/contrib/ffmpeg/vhook/watermark.c b/contrib/ffmpeg/vhook/watermark.c
new file mode 100644
index 000000000..4d2acd2aa
--- /dev/null
+++ b/contrib/ffmpeg/vhook/watermark.c
@@ -0,0 +1,661 @@
+/*
+ * Watermark Hook
+ * Copyright (c) 2005 Marcus Engene myfirstname(at)mylastname.se
+ *
+ * parameters for watermark:
+ * -m nbr = nbr is 0..1. 0 is the default mode, see below.
+ * -t nbr = nbr is six digit hex. Threshold.
+ * -f file = file is the watermark image filename. You must specify this!
+ *
+ * MODE 0:
+ * The watermark picture works like this (assuming color intensities 0..0xff):
+ * Per color do this:
+ * If mask color is 0x80, no change to the original frame.
+ * If mask color is < 0x80 the abs difference is subtracted from the frame. If
+ * result < 0, result = 0
+ * If mask color is > 0x80 the abs difference is added to the frame. If result
+ * > 0xff, result = 0xff
+ *
+ * You can override the 0x80 level with the -t flag. E.g. if threshold is
+ * 000000 the color value of watermark is added to the destination.
+ *
+ * This way a mask that is visible both in light pictures and in dark can be
+ * made (fex by using a picture generated by Gimp and the bump map tool).
+ *
+ * An example watermark file is at
+ * http://engene.se/ffmpeg_watermark.gif
+ *
+ * MODE 1:
+ * Per color do this:
+ * If mask color > threshold color then the watermark pixel is used.
+ *
+ * Example usage:
+ * ffmpeg -i infile -vhook '/path/watermark.so -f wm.gif' -an out.mov
+ * ffmpeg -i infile -vhook '/path/watermark.so -f wm.gif -m 1 -t 222222' -an out.mov
+ *
+ * Note that the entire vhook argument is encapsulated in ''. This
+ * way, arguments to the vhook won't be mixed up with those for ffmpeg.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+//#include <fcntl.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include "common.h"
+#include "avformat.h"
+
+#include "framehook.h"
+#include "cmdutils.h"
+#include "swscale.h"
+
+static int sws_flags = SWS_BICUBIC;
+
+typedef struct {
+ char filename[2000];
+ int x_size;
+ int y_size;
+
+ /* get_watermark_picture() variables */
+ AVFormatContext *pFormatCtx;
+ const char *p_ext;
+ int videoStream;
+ int frameFinished;
+ AVCodecContext *pCodecCtx;
+ AVCodec *pCodec;
+ AVFrame *pFrame;
+ AVPacket packet;
+ int numBytes;
+ uint8_t *buffer;
+ int i;
+ AVInputFormat *file_iformat;
+ AVStream *st;
+ int is_done;
+ AVFrame *pFrameRGB;
+ int thrR;
+ int thrG;
+ int thrB;
+ int mode;
+
+ // This vhook first converts frame to RGB ...
+ struct SwsContext *toRGB_convert_ctx;
+ // ... then converts a watermark and applies it to the RGB frame ...
+ struct SwsContext *watermark_convert_ctx;
+ // ... and finally converts back frame from RGB to initial format
+ struct SwsContext *fromRGB_convert_ctx;
+} ContextInfo;
+
+int get_watermark_picture(ContextInfo *ci, int cleanup);
+
+
+/****************************************************************************
+ *
+ ****************************************************************************/
+void Release(void *ctx)
+{
+ ContextInfo *ci;
+ ci = (ContextInfo *) ctx;
+
+ if (ci) {
+ get_watermark_picture(ci, 1);
+ sws_freeContext(ci->toRGB_convert_ctx);
+ sws_freeContext(ci->watermark_convert_ctx);
+ sws_freeContext(ci->fromRGB_convert_ctx);
+ }
+ av_free(ctx);
+}
+
+
+/****************************************************************************
+ *
+ ****************************************************************************/
+int Configure(void **ctxp, int argc, char *argv[])
+{
+ ContextInfo *ci;
+ int c;
+ int tmp = 0;
+
+ if (0 == (*ctxp = av_mallocz(sizeof(ContextInfo)))) return -1;
+ ci = (ContextInfo *) *ctxp;
+
+ optind = 1;
+
+ // Struct is mallocz:ed so no need to reset.
+ ci->thrR = 0x80;
+ ci->thrG = 0x80;
+ ci->thrB = 0x80;
+
+ while ((c = getopt(argc, argv, "f:m:t:")) > 0) {
+ switch (c) {
+ case 'f':
+ strncpy(ci->filename, optarg, 1999);
+ ci->filename[1999] = 0;
+ break;
+ case 'm':
+ ci->mode = atoi(optarg);
+ break;
+ case 't':
+ if (1 != sscanf(optarg, "%x", &tmp)) {
+ av_log(NULL, AV_LOG_ERROR, "Watermark: argument to -t must be a 6 digit hex number\n");
+ return -1;
+ }
+ ci->thrR = (tmp >> 16) & 0xff;
+ ci->thrG = (tmp >> 8) & 0xff;
+ ci->thrB = (tmp >> 0) & 0xff;
+ break;
+ default:
+ av_log(NULL, AV_LOG_ERROR, "Watermark: Unrecognized argument '%s'\n", argv[optind]);
+ return -1;
+ }
+ }
+
+ //
+ if (0 == ci->filename[0]) {
+ av_log(NULL, AV_LOG_ERROR, "Watermark: There is no filename specified.\n");
+ return -1;
+ }
+
+ av_register_all();
+ return get_watermark_picture(ci, 0);
+}
+
+
+/****************************************************************************
+ * For mode 0 (the original one)
+ ****************************************************************************/
+static void Process0(void *ctx,
+ AVPicture *picture,
+ enum PixelFormat pix_fmt,
+ int src_width,
+ int src_height,
+ int64_t pts)
+{
+ ContextInfo *ci = (ContextInfo *) ctx;
+ char *buf = 0;
+ AVPicture picture1;
+ AVPicture *pict = picture;
+
+ AVFrame *pFrameRGB;
+ int xm_size;
+ int ym_size;
+
+ int x;
+ int y;
+ int offs, offsm;
+ int mpoffs;
+ uint32_t *p_pixel = 0;
+ uint32_t pixel_meck;
+ uint32_t pixel;
+ uint32_t pixelm;
+ int tmp;
+ int thrR = ci->thrR;
+ int thrG = ci->thrG;
+ int thrB = ci->thrB;
+
+ if (pix_fmt != PIX_FMT_RGBA32) {
+ int size;
+
+ size = avpicture_get_size(PIX_FMT_RGBA32, src_width, src_height);
+ buf = av_malloc(size);
+
+ avpicture_fill(&picture1, buf, PIX_FMT_RGBA32, src_width, src_height);
+
+ // if we already got a SWS context, let's realloc if is not re-useable
+ ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx,
+ src_width, src_height, pix_fmt,
+ src_width, src_height, PIX_FMT_RGBA32,
+ sws_flags, NULL, NULL, NULL);
+ if (ci->toRGB_convert_ctx == NULL) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Cannot initialize the toRGB conversion context\n");
+ exit(1);
+ }
+
+// img_convert parameters are 2 first destination, then 4 source
+// sws_scale parameters are context, 4 first source, then 2 destination
+ sws_scale(ci->toRGB_convert_ctx,
+ picture->data, picture->linesize, 0, src_height,
+ picture1.data, picture1.linesize);
+
+ pict = &picture1;
+ }
+
+ /* Insert filter code here */ /* ok */
+
+ // Get me next frame
+ if (0 > get_watermark_picture(ci, 0)) {
+ return;
+ }
+ // These are the three original static variables in the ffmpeg hack.
+ pFrameRGB = ci->pFrameRGB;
+ xm_size = ci->x_size;
+ ym_size = ci->y_size;
+
+ // I'll do the *4 => <<2 crap later. Most compilers understand that anyway.
+ // According to avcodec.h PIX_FMT_RGBA32 is handled in endian specific manner.
+ for (y=0; y<src_height; y++) {
+ offs = y * (src_width * 4);
+ offsm = (((y * ym_size) / src_height) * 4) * xm_size; // offsm first in maskline. byteoffs!
+ for (x=0; x<src_width; x++) {
+ mpoffs = offsm + (((x * xm_size) / src_width) * 4);
+ p_pixel = (uint32_t *)&((pFrameRGB->data[0])[mpoffs]);
+ pixelm = *p_pixel;
+ p_pixel = (uint32_t *)&((pict->data[0])[offs]);
+ pixel = *p_pixel;
+// pixelm = *((uint32_t *)&(pFrameRGB->data[mpoffs]));
+ pixel_meck = pixel & 0xff000000;
+
+ // R
+ tmp = (int)((pixel >> 16) & 0xff) + (int)((pixelm >> 16) & 0xff) - thrR;
+ if (tmp > 255) tmp = 255;
+ if (tmp < 0) tmp = 0;
+ pixel_meck |= (tmp << 16) & 0xff0000;
+ // G
+ tmp = (int)((pixel >> 8) & 0xff) + (int)((pixelm >> 8) & 0xff) - thrG;
+ if (tmp > 255) tmp = 255;
+ if (tmp < 0) tmp = 0;
+ pixel_meck |= (tmp << 8) & 0xff00;
+ // B
+ tmp = (int)((pixel >> 0) & 0xff) + (int)((pixelm >> 0) & 0xff) - thrB;
+ if (tmp > 255) tmp = 255;
+ if (tmp < 0) tmp = 0;
+ pixel_meck |= (tmp << 0) & 0xff;
+
+
+ // test:
+ //pixel_meck = pixel & 0xff000000;
+ //pixel_meck |= (pixelm & 0x00ffffff);
+
+ *p_pixel = pixel_meck;
+
+ offs += 4;
+ } // foreach X
+ } // foreach Y
+
+
+
+
+ if (pix_fmt != PIX_FMT_RGBA32) {
+ ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx,
+ src_width, src_height, PIX_FMT_RGBA32,
+ src_width, src_height, pix_fmt,
+ sws_flags, NULL, NULL, NULL);
+ if (ci->fromRGB_convert_ctx == NULL) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Cannot initialize the fromRGB conversion context\n");
+ exit(1);
+ }
+// img_convert parameters are 2 first destination, then 4 source
+// sws_scale parameters are context, 4 first source, then 2 destination
+ sws_scale(ci->fromRGB_convert_ctx,
+ picture1.data, picture1.linesize, 0, src_height,
+ picture->data, picture->linesize);
+ }
+
+ av_free(buf);
+}
+
+
+/****************************************************************************
+ * For mode 1 (the original one)
+ ****************************************************************************/
+static void Process1(void *ctx,
+ AVPicture *picture,
+ enum PixelFormat pix_fmt,
+ int src_width,
+ int src_height,
+ int64_t pts)
+{
+ ContextInfo *ci = (ContextInfo *) ctx;
+ char *buf = 0;
+ AVPicture picture1;
+ AVPicture *pict = picture;
+
+ AVFrame *pFrameRGB;
+ int xm_size;
+ int ym_size;
+
+ int x;
+ int y;
+ int offs, offsm;
+ int mpoffs;
+ uint32_t *p_pixel = 0;
+ uint32_t pixel;
+ uint32_t pixelm;
+
+ if (pix_fmt != PIX_FMT_RGBA32) {
+ int size;
+
+ size = avpicture_get_size(PIX_FMT_RGBA32, src_width, src_height);
+ buf = av_malloc(size);
+
+ avpicture_fill(&picture1, buf, PIX_FMT_RGBA32, src_width, src_height);
+
+ // if we already got a SWS context, let's realloc if is not re-useable
+ ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx,
+ src_width, src_height, pix_fmt,
+ src_width, src_height, PIX_FMT_RGBA32,
+ sws_flags, NULL, NULL, NULL);
+ if (ci->toRGB_convert_ctx == NULL) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Cannot initialize the toRGB conversion context\n");
+ exit(1);
+ }
+
+// img_convert parameters are 2 first destination, then 4 source
+// sws_scale parameters are context, 4 first source, then 2 destination
+ sws_scale(ci->toRGB_convert_ctx,
+ picture->data, picture->linesize, 0, src_height,
+ picture1.data, picture1.linesize);
+
+ pict = &picture1;
+ }
+
+ /* Insert filter code here */ /* ok */
+
+ // Get me next frame
+ if (0 > get_watermark_picture(ci, 0)) {
+ return;
+ }
+ // These are the three original static variables in the ffmpeg hack.
+ pFrameRGB = ci->pFrameRGB;
+ xm_size = ci->x_size;
+ ym_size = ci->y_size;
+
+ // I'll do the *4 => <<2 crap later. Most compilers understand that anyway.
+ // According to avcodec.h PIX_FMT_RGBA32 is handled in endian specific manner.
+ for (y=0; y<src_height; y++) {
+ offs = y * (src_width * 4);
+ offsm = (((y * ym_size) / src_height) * 4) * xm_size; // offsm first in maskline. byteoffs!
+ for (x=0; x<src_width; x++) {
+ mpoffs = offsm + (((x * xm_size) / src_width) * 4);
+ p_pixel = (uint32_t *)&((pFrameRGB->data[0])[mpoffs]);
+ pixelm = *p_pixel; /* watermark pixel */
+ p_pixel = (uint32_t *)&((pict->data[0])[offs]);
+ pixel = *p_pixel;
+
+ if (((pixelm >> 16) & 0xff) > ci->thrR ||
+ ((pixelm >> 8) & 0xff) > ci->thrG ||
+ ((pixelm >> 0) & 0xff) > ci->thrB)
+ {
+ *p_pixel = pixelm;
+ } else {
+ *p_pixel = pixel;
+ }
+ offs += 4;
+ } // foreach X
+ } // foreach Y
+
+ if (pix_fmt != PIX_FMT_RGBA32) {
+ ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx,
+ src_width, src_height, PIX_FMT_RGBA32,
+ src_width, src_height, pix_fmt,
+ sws_flags, NULL, NULL, NULL);
+ if (ci->fromRGB_convert_ctx == NULL) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Cannot initialize the fromRGB conversion context\n");
+ exit(1);
+ }
+// img_convert parameters are 2 first destination, then 4 source
+// sws_scale parameters are context, 4 first source, then 2 destination
+ sws_scale(ci->fromRGB_convert_ctx,
+ picture1.data, picture1.linesize, 0, src_height,
+ picture->data, picture->linesize);
+ }
+
+ av_free(buf);
+}
+
+
+/****************************************************************************
+ * This is the function ffmpeg.c callbacks.
+ ****************************************************************************/
+void Process(void *ctx,
+ AVPicture *picture,
+ enum PixelFormat pix_fmt,
+ int src_width,
+ int src_height,
+ int64_t pts)
+{
+ ContextInfo *ci = (ContextInfo *) ctx;
+ if (1 == ci->mode) {
+ return Process1(ctx, picture, pix_fmt, src_width, src_height, pts);
+ } else {
+ return Process0(ctx, picture, pix_fmt, src_width, src_height, pts);
+ }
+}
+
+
+/****************************************************************************
+ * When cleanup == 0, we try to get the next frame. If no next frame, nothing
+ * is done.
+ *
+ * This code follows the example on
+ * http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html
+ *
+ * 0 = ok, -1 = error
+ ****************************************************************************/
+int get_watermark_picture(ContextInfo *ci, int cleanup)
+{
+ if (1 == ci->is_done && 0 == cleanup) return 0;
+
+ // Yes, *pFrameRGB arguments must be null the first time otherwise it's not good..
+ // This block is only executed the first time we enter this function.
+ if (0 == ci->pFrameRGB &&
+ 0 == cleanup)
+ {
+
+ /*
+ * The last three parameters specify the file format, buffer size and format
+ * parameters; by simply specifying NULL or 0 we ask libavformat to auto-detect
+ * the format and use a default buffer size. (Didn't work!)
+ */
+ if (av_open_input_file(&ci->pFormatCtx, ci->filename, NULL, 0, NULL) != 0) {
+
+ // Martin says this should not be necessary but it failed for me sending in
+ // NULL instead of file_iformat to av_open_input_file()
+ ci->i = strlen(ci->filename);
+ if (0 == ci->i) {
+ av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() No filename to watermark vhook\n");
+ return -1;
+ }
+ while (ci->i > 0) {
+ if (ci->filename[ci->i] == '.') {
+ ci->i++;
+ break;
+ }
+ ci->i--;
+ }
+ ci->p_ext = &(ci->filename[ci->i]);
+ ci->file_iformat = av_find_input_format (ci->p_ext);
+ if (0 == ci->file_iformat) {
+ av_log(NULL, AV_LOG_INFO, "get_watermark_picture() attempt to use image2 for [%s]\n", ci->p_ext);
+ ci->file_iformat = av_find_input_format ("image2");
+ }
+ if (0 == ci->file_iformat) {
+ av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Really failed to find iformat [%s]\n", ci->p_ext);
+ return -1;
+ }
+ // now continues the Martin template.
+
+ if (av_open_input_file(&ci->pFormatCtx, ci->filename, ci->file_iformat, 0, NULL)!=0) {
+ av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to open input file [%s]\n", ci->filename);
+ return -1;
+ }
+ }
+
+ /*
+ * This fills the streams field of the AVFormatContext with valid information.
+ */
+ if(av_find_stream_info(ci->pFormatCtx)<0) {
+ av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to find stream info\n");
+ return -1;
+ }
+
+ /*
+ * As mentioned in the introduction, we'll handle only video streams, not audio
+ * streams. To make things nice and easy, we simply use the first video stream we
+ * find.
+ */
+ ci->videoStream=-1;
+ for(ci->i = 0; ci->i < ci->pFormatCtx->nb_streams; ci->i++)
+ if(ci->pFormatCtx->streams[ci->i]->codec->codec_type==CODEC_TYPE_VIDEO)
+ {
+ ci->videoStream = ci->i;
+ break;
+ }
+ if(ci->videoStream == -1) {
+ av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to find any video stream\n");
+ return -1;
+ }
+
+ ci->st = ci->pFormatCtx->streams[ci->videoStream];
+ ci->x_size = ci->st->codec->width;
+ ci->y_size = ci->st->codec->height;
+
+ // Get a pointer to the codec context for the video stream
+ ci->pCodecCtx = ci->pFormatCtx->streams[ci->videoStream]->codec;
+
+
+ /*
+ * OK, so now we've got a pointer to the so-called codec context for our video
+ * stream, but we still have to find the actual codec and open it.
+ */
+ // Find the decoder for the video stream
+ ci->pCodec = avcodec_find_decoder(ci->pCodecCtx->codec_id);
+ if(ci->pCodec == NULL) {
+ av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to find any codec\n");
+ return -1;
+ }
+
+ // Inform the codec that we can handle truncated bitstreams -- i.e.,
+ // bitstreams where frame boundaries can fall in the middle of packets
+ if (ci->pCodec->capabilities & CODEC_CAP_TRUNCATED)
+ ci->pCodecCtx->flags|=CODEC_FLAG_TRUNCATED;
+
+ // Open codec
+ if(avcodec_open(ci->pCodecCtx, ci->pCodec)<0) {
+ av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to open codec\n");
+ return -1;
+ }
+
+ // Hack to correct wrong frame rates that seem to be generated by some
+ // codecs
+ if (ci->pCodecCtx->time_base.den>1000 && ci->pCodecCtx->time_base.num==1)
+ ci->pCodecCtx->time_base.num=1000;
+
+ /*
+ * Allocate a video frame to store the decoded images in.
+ */
+ ci->pFrame = avcodec_alloc_frame();
+
+
+ /*
+ * The RGB image pFrameRGB (of type AVFrame *) is allocated like this:
+ */
+ // Allocate an AVFrame structure
+ ci->pFrameRGB=avcodec_alloc_frame();
+ if(ci->pFrameRGB==NULL) {
+ av_log(NULL, AV_LOG_ERROR, "get_watermark_picture() Failed to alloc pFrameRGB\n");
+ return -1;
+ }
+
+ // Determine required buffer size and allocate buffer
+ ci->numBytes = avpicture_get_size(PIX_FMT_RGBA32, ci->pCodecCtx->width,
+ ci->pCodecCtx->height);
+ ci->buffer = av_malloc(ci->numBytes);
+
+ // Assign appropriate parts of buffer to image planes in pFrameRGB
+ avpicture_fill((AVPicture *)ci->pFrameRGB, ci->buffer, PIX_FMT_RGBA32,
+ ci->pCodecCtx->width, ci->pCodecCtx->height);
+ }
+ // TODO loop, pingpong etc?
+ if (0 == cleanup)
+ {
+// av_log(NULL, AV_LOG_DEBUG, "get_watermark_picture() Get a frame\n");
+ while(av_read_frame(ci->pFormatCtx, &ci->packet)>=0)
+ {
+ // Is this a packet from the video stream?
+ if(ci->packet.stream_index == ci->videoStream)
+ {
+ // Decode video frame
+ avcodec_decode_video(ci->pCodecCtx, ci->pFrame, &ci->frameFinished,
+ ci->packet.data, ci->packet.size);
+
+ // Did we get a video frame?
+ if(ci->frameFinished)
+ {
+ // Convert the image from its native format to RGBA32
+ ci->watermark_convert_ctx =
+ sws_getCachedContext(ci->watermark_convert_ctx,
+ ci->pCodecCtx->width, ci->pCodecCtx->height, ci->pCodecCtx->pix_fmt,
+ ci->pCodecCtx->width, ci->pCodecCtx->height, PIX_FMT_RGBA32,
+ sws_flags, NULL, NULL, NULL);
+ if (ci->watermark_convert_ctx == NULL) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Cannot initialize the watermark conversion context\n");
+ exit(1);
+ }
+// img_convert parameters are 2 first destination, then 4 source
+// sws_scale parameters are context, 4 first source, then 2 destination
+ sws_scale(ci->watermark_convert_ctx,
+ ci->pFrame->data, ci->pFrame->linesize, 0, ci->pCodecCtx->height,
+ ci->pFrameRGB->data, ci->pFrameRGB->linesize);
+
+ // Process the video frame (save to disk etc.)
+ //fprintf(stderr,"banan() New frame!\n");
+ //DoSomethingWithTheImage(ci->pFrameRGB);
+ return 0;
+ }
+ }
+
+ // Free the packet that was allocated by av_read_frame
+ av_free_packet(&ci->packet);
+ }
+ ci->is_done = 1;
+ return 0;
+ } // if 0 != cleanup
+
+ if (0 != cleanup)
+ {
+ // Free the RGB image
+ av_freep(&ci->buffer);
+ av_freep(&ci->pFrameRGB);
+
+ // Close the codec
+ if (0 != ci->pCodecCtx) {
+ avcodec_close(ci->pCodecCtx);
+ ci->pCodecCtx = 0;
+ }
+
+ // Close the video file
+ if (0 != ci->pFormatCtx) {
+ av_close_input_file(ci->pFormatCtx);
+ ci->pFormatCtx = 0;
+ }
+
+ ci->is_done = 0;
+ }
+ return 0;
+}
+
+
+void parse_arg_file(const char *filename)
+{
+}
diff --git a/contrib/ffmpeg/xvmc_render.h b/contrib/ffmpeg/xvmc_render.h
new file mode 100644
index 000000000..82dfeb0b8
--- /dev/null
+++ b/contrib/ffmpeg/xvmc_render.h
@@ -0,0 +1,47 @@
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/XvMClib.h>
+
+
+//the surface should be shown, video driver manipulate this
+#define MP_XVMC_STATE_DISPLAY_PENDING 1
+//the surface is needed for prediction, codec manipulate this
+#define MP_XVMC_STATE_PREDICTION 2
+// 1337 IDCT MCo
+#define MP_XVMC_RENDER_MAGIC 0x1DC711C0
+
+typedef struct{
+//these are not changed by decoder!
+ int magic;
+
+ short * data_blocks;
+ XvMCMacroBlock * mv_blocks;
+ int total_number_of_mv_blocks;
+ int total_number_of_data_blocks;
+ int mc_type;//XVMC_MPEG1/2/4,XVMC_H263 without XVMC_IDCT
+ int idct;//does we use IDCT acceleration?
+ int chroma_format;//420,422,444
+ int unsigned_intra;//+-128 for intra pictures after clip
+ int reserved1[13];//future extenstions (e.g. gmc,qpel)
+ XvMCSurface* p_surface;//pointer to rendered surface, never changed
+
+//these are changed by decoder
+//used by XvMCRenderSurface function
+ XvMCSurface* p_past_surface;//pointer to the past surface
+ XvMCSurface* p_future_surface;//pointer to the future prediction surface
+
+ unsigned int picture_structure;//top/bottom fields or frame !
+ unsigned int flags;//XVMC_SECOND_FIELD - 1'st or 2'd field in the sequence
+ unsigned int display_flags; //1,2 or 1+2 fields for XvMCPutSurface,
+
+//these are internal communication one
+ int state;//0-free,1 Waiting to Display,2 Waiting for prediction
+ int start_mv_blocks_num;//offset in the array for the current slice,updated by vo
+ int filled_mv_blocks_num;//processed mv block in this slice,change by decoder
+
+ int next_free_data_block_num;//used in add_mv_block, pointer to next free block
+
+} xvmc_render_state_t;